This commit is contained in:
bluesea 2024-06-14 17:40:26 +08:00
parent a4773a19e4
commit c8d7993a2f
8795 changed files with 0 additions and 2798663 deletions

View File

@ -1,28 +0,0 @@
Pod::Spec.new do |spec|
spec.name = "DSDeltaCore"
spec.version = "0.1"
spec.summary = "Nintendo DS plug-in for Delta emulator."
spec.description = "iOS framework that wraps DeSmuME to allow playing Nintendo DS games with Delta emulator."
spec.homepage = "https://github.com/rileytestut/DSDeltaCore"
spec.platform = :ios, "14.0"
spec.source = { :git => "https://github.com/rileytestut/DSDeltaCore.git" }
spec.author = { "Riley Testut" => "riley@rileytestut.com" }
spec.social_media_url = "https://twitter.com/rileytestut"
spec.source_files = "DSDeltaCore/**/*.{swift}", "DSDeltaCore/Bridge/DSEmulatorBridge.mm", "DSDeltaCore/Types/DSTypes.{h,m}", "desmume/desmume/src/*.{h,hpp}", "desmume/desmume/src/libretro-common/include/*.{h,hpp}", "desmume/desmume/src/libretro-common/include/math/*.{h,hpp}", "desmume/desmume/src/metaspu/**/*.{h,hpp}", "libDeSmuME/*.{h,hpp}"
spec.public_header_files = "DSDeltaCore/Types/DSTypes.h", "DSDeltaCore/Bridge/DSEmulatorBridge.h"
spec.header_mappings_dir = ""
spec.resource_bundles = {
"DSDeltaCore" => ["DSDeltaCore/**/*.deltamapping", "DSDeltaCore/**/*.deltaskin"]
}
spec.dependency 'DeltaCore'
spec.xcconfig = {
"HEADER_SEARCH_PATHS" => '"${PODS_CONFIGURATION_BUILD_DIR}" "$(PODS_ROOT)/Headers/Private/DSDeltaCore/desmume/desmume/src/libretro-common/include"',
"USER_HEADER_SEARCH_PATHS" => '"${PODS_CONFIGURATION_BUILD_DIR}/DeltaCore/Swift Compatibility Header"',
"OTHER_CFLAGS" => "-DHOST_DARWIN -DDESMUME_COCOA -DHAVE_OPENGL -DHAVE_LIBZ -DANDROID -fexceptions -ftree-vectorize -DCOMPRESS_MT -DIOS -DOBJ_C -marm -fvisibility=hidden -DSTATIC_LIBRARY=1"
}
end

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:DSDeltaCore.xcodeproj">
</FileRef>
</Workspace>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,80 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "BFAEFD2422F4C40300F21EC9"
BuildableName = "DSDeltaCore.framework"
BlueprintName = "DSDeltaCore"
ReferencedContainer = "container:DSDeltaCore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "BFAEFD2422F4C40300F21EC9"
BuildableName = "DSDeltaCore.framework"
BlueprintName = "DSDeltaCore"
ReferencedContainer = "container:DSDeltaCore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "BFAEFD2422F4C40300F21EC9"
BuildableName = "DSDeltaCore.framework"
BlueprintName = "DSDeltaCore"
ReferencedContainer = "container:DSDeltaCore.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,80 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "BFAEFD3322F4C82800F21EC9"
BuildableName = "liblibDeSmuME.a"
BlueprintName = "libDeSmuME"
ReferencedContainer = "container:DSDeltaCore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "BFAEFD3322F4C82800F21EC9"
BuildableName = "liblibDeSmuME.a"
BlueprintName = "libDeSmuME"
ReferencedContainer = "container:DSDeltaCore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "BFAEFD3322F4C82800F21EC9"
BuildableName = "liblibDeSmuME.a"
BlueprintName = "libDeSmuME"
ReferencedContainer = "container:DSDeltaCore.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>DSDeltaCore.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>libDeSmuME.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>39</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>BFAEFD3322F4C82800F21EC9</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

View File

@ -1,24 +0,0 @@
//
// DSEmulatorBridge.h
// DSDeltaCore
//
// Created by Riley Testut on 8/2/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol DLTAEmulatorBridging;
NS_ASSUME_NONNULL_BEGIN
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Weverything" // Silence "Cannot find protocol definition" warning due to forward declaration.
@interface DSEmulatorBridge : NSObject <DLTAEmulatorBridging>
#pragma clang diagnostic pop
@property (class, nonatomic, readonly) DSEmulatorBridge *sharedBridge;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,359 +0,0 @@
//
// DSEmulatorBridge.m
// DSDeltaCore
//
// Created by Riley Testut on 8/2/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
#import "DSEmulatorBridge.h"
#import <UIKit/UIKit.h>
#import <DeltaCore/DeltaCore.h>
#import <DeltaCore/DeltaCore-Swift.h>
#if STATIC_LIBRARY
#import "DSDeltaCore-Swift.h"
#else
#import <DSDeltaCore/DSDeltaCore-Swift.h>
#endif
// DeSmuME
#include "types.h"
#include "render3D.h"
#include "rasterize.h"
#include "SPU.h"
#include "debug.h"
#include "NDSSystem.h"
#include "path.h"
#include "slot1.h"
#include "saves.h"
#include "cheatSystem.h"
#include "slot1.h"
#include "version.h"
#include "metaspu.h"
#include "GPU.h"
#undef BOOL
#define SNDCORE_DELTA 1
void DLTAUpdateAudio(s16 *buffer, u32 num_samples);
u32 DLTAGetAudioSpace();
SoundInterface_struct DeltaAudio = {
SNDCORE_DELTA,
"CoreAudio Sound Interface",
SNDDummy.Init,
SNDDummy.DeInit,
DLTAUpdateAudio,
DLTAGetAudioSpace,
SNDDummy.MuteAudio,
SNDDummy.UnMuteAudio,
SNDDummy.SetVolume,
};
volatile bool execute = true;
GPU3DInterface *core3DList[] = {
&gpu3DNull,
&gpu3DRasterize,
NULL
};
SoundInterface_struct *SNDCoreList[] = {
&SNDDummy,
&DeltaAudio,
NULL
};
@interface DSEmulatorBridge () <DLTAEmulatorBridging>
{
BOOL _isPrepared;
}
@property (nonatomic, copy, nullable, readwrite) NSURL *gameURL;
@property (nonatomic) uint32_t activatedInputs;
@property (nonatomic) CGPoint touchScreenPoint;
@end
@implementation DSEmulatorBridge
@synthesize audioRenderer = _audioRenderer;
@synthesize videoRenderer = _videoRenderer;
@synthesize saveUpdateHandler = _saveUpdateHandler;
+ (instancetype)sharedBridge
{
static DSEmulatorBridge *_emulatorBridge = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_emulatorBridge = [[self alloc] init];
});
return _emulatorBridge;
}
#pragma mark - Emulation State -
- (void)startWithGameURL:(NSURL *)gameURL
{
self.gameURL = gameURL;
path.ReadPathSettings();
// General
CommonSettings.num_cores = (int)sysconf( _SC_NPROCESSORS_ONLN );
CommonSettings.advanced_timing = false;
CommonSettings.cheatsDisable = true;
CommonSettings.autodetectBackupMethod = 1;
CommonSettings.use_jit = false;
CommonSettings.micMode = TCommonSettings::Physical;
CommonSettings.showGpu.main = 1;
CommonSettings.showGpu.sub = 1;
// HUD
CommonSettings.hud.FpsDisplay = false;
CommonSettings.hud.FrameCounterDisplay = false;
CommonSettings.hud.ShowInputDisplay = false;
CommonSettings.hud.ShowGraphicalInputDisplay = false;
CommonSettings.hud.ShowLagFrameCounter = false;
CommonSettings.hud.ShowMicrophone = false;
CommonSettings.hud.ShowRTC = false;
// Graphics
CommonSettings.GFX3D_HighResolutionInterpolateColor = 0;
CommonSettings.GFX3D_EdgeMark = 0;
CommonSettings.GFX3D_Fog = 1;
CommonSettings.GFX3D_Texture = 1;
CommonSettings.GFX3D_LineHack = 0;
// Sound
CommonSettings.spuInterpolationMode = SPUInterpolation_Cosine;
CommonSettings.spu_advanced = false;
// Firmware
CommonSettings.fwConfig.language = NDS_FW_LANG_ENG;
CommonSettings.fwConfig.favoriteColor = 15;
CommonSettings.fwConfig.birthdayMonth = 10;
CommonSettings.fwConfig.birthdayDay = 7;
CommonSettings.fwConfig.consoleType = NDS_CONSOLE_TYPE_LITE;
static const char *nickname = "Delta";
CommonSettings.fwConfig.nicknameLength = strlen(nickname);
for(int i = 0 ; i < CommonSettings.fwConfig.nicknameLength ; ++i)
{
CommonSettings.fwConfig.nickname[i] = nickname[i];
}
static const char *message = "Delta is the best!";
CommonSettings.fwConfig.messageLength = strlen(message);
for(int i = 0 ; i < CommonSettings.fwConfig.messageLength ; ++i)
{
CommonSettings.fwConfig.message[i] = message[i];
}
if (!_isPrepared)
{
Desmume_InitOnce();
NDS_Init();
cur3DCore = 1;
GPU->Change3DRendererByID(1);
GPU->SetColorFormat(NDSColorFormat_BGR888_Rev);
SPU_ChangeSoundCore(SNDCORE_DELTA, DESMUME_SAMPLE_RATE * 8/60);
_isPrepared = true;
}
NSURL *gameDirectory = [NSURL URLWithString:@"/dev/null"];
path.setpath(PathInfo::BATTERY, gameDirectory.fileSystemRepresentation);
if (!NDS_LoadROM(gameURL.relativePath.UTF8String))
{
NSLog(@"Error loading ROM: %@", gameURL);
}
}
- (void)stop
{
NDS_FreeROM();
}
- (void)pause
{
}
- (void)resume
{
}
#pragma mark - Game Loop -
- (void)runFrameAndProcessVideo:(BOOL)processVideo
{
// Inputs
NDS_setPad(self.activatedInputs & DSGameInputRight,
self.activatedInputs & DSGameInputLeft,
self.activatedInputs & DSGameInputDown,
self.activatedInputs & DSGameInputUp,
self.activatedInputs & DSGameInputSelect,
self.activatedInputs & DSGameInputStart,
self.activatedInputs & DSGameInputB,
self.activatedInputs & DSGameInputA,
self.activatedInputs & DSGameInputY,
self.activatedInputs & DSGameInputX,
self.activatedInputs & DSGameInputL,
self.activatedInputs & DSGameInputR,
false,
false);
if (self.activatedInputs & DSGameInputTouchScreenX || self.activatedInputs & DSGameInputTouchScreenY)
{
NDS_setTouchPos(self.touchScreenPoint.x, self.touchScreenPoint.y);
}
else
{
NDS_releaseTouch();
}
NDS_beginProcessingInput();
NDS_endProcessingInput();
if (!processVideo)
{
NDS_SkipNextFrame();
}
NDS_exec<false>();
if (processVideo)
{
memcpy(self.videoRenderer.videoBuffer, GPU->GetDisplayInfo().masterNativeBuffer, 256 * 384 * 4);
[self.videoRenderer processFrame];
}
SPU_Emulate_user();
}
#pragma mark - Inputs -
- (void)activateInput:(NSInteger)input value:(double)value playerIndex:(NSInteger)playerIndex
{
self.activatedInputs |= (uint32_t)input;
CGPoint touchPoint = self.touchScreenPoint;
switch ((DSGameInput)input)
{
case DSGameInputTouchScreenX:
touchPoint.x = value * 256;
break;
case DSGameInputTouchScreenY:
touchPoint.y = value * 192;
break;
default: break;
}
self.touchScreenPoint = touchPoint;
}
- (void)deactivateInput:(NSInteger)input playerIndex:(NSInteger)playerIndex
{
self.activatedInputs &= ~((uint32_t)input);
CGPoint touchPoint = self.touchScreenPoint;
switch ((DSGameInput)input)
{
case DSGameInputTouchScreenX:
touchPoint.x = 0;
break;
case DSGameInputTouchScreenY:
touchPoint.y = 0;
break;
default: break;
}
self.touchScreenPoint = touchPoint;
}
- (void)resetInputs
{
self.activatedInputs = 0;
self.touchScreenPoint = CGPointZero;
}
#pragma mark - Game Saves -
- (void)saveGameSaveToURL:(NSURL *)URL
{
MMU_new.backupDevice.export_raw(URL.fileSystemRepresentation);
}
- (void)loadGameSaveFromURL:(NSURL *)URL
{
if ([[NSFileManager defaultManager] fileExistsAtPath:URL.path])
{
MMU_new.backupDevice.import_raw(URL.fileSystemRepresentation);
}
}
#pragma mark - Save States -
- (void)saveSaveStateToURL:(NSURL *)URL
{
savestate_save(URL.fileSystemRepresentation);
}
- (void)loadSaveStateFromURL:(NSURL *)URL
{
savestate_load(URL.fileSystemRepresentation);
}
#pragma mark - Cheats -
- (BOOL)addCheatCode:(NSString *)cheatCode type:(NSString *)type
{
return NO;
}
- (void)resetCheats
{
}
- (void)updateCheats
{
}
#pragma mark - Audio -
void DLTAUpdateAudio(s16 *buffer, u32 num_samples)
{
[DSEmulatorBridge.sharedBridge.audioRenderer.audioBuffer writeBuffer:(uint8_t *)buffer size:num_samples * 4];
}
u32 DLTAGetAudioSpace()
{
NSInteger availableBytes = DSEmulatorBridge.sharedBridge.audioRenderer.audioBuffer.availableBytesForWriting;
u32 availableFrames = (u32)availableBytes / 4;
return availableFrames;
}
#pragma mark - Getters/Setters -
- (NSTimeInterval)frameDuration
{
return (1.0 / 60.0);
}
@end

View File

@ -1,19 +0,0 @@
//
// texcache.cpp
// DSDeltaCore
//
// Created by Riley Testut on 2/3/20.
// Copyright © 2020 Riley Testut. All rights reserved.
//
// Rename TextureCache to prevent static library collision with N64's TextureCache.
#define TextureCache TextureCacheDS
#include "../../desmume/desmume/src/texcache.cpp"
// Include files that reference texcache.h.
#include "../../desmume/desmume/src/driver.cpp"
#include "../../desmume/desmume/src/render3D.cpp"
#include "../../desmume/desmume/src/rasterize.cpp"
#undef TextureCache

View File

@ -1,920 +0,0 @@
{
"name" : "Standard DS",
"identifier" : "com.delta.ds.standard",
"gameTypeIdentifier" : "com.rileytestut.delta.game.ds",
"debug" : false,
"representations" : {
"iphone" : {
"standard" : {
"portrait" : {
"assets" : {
"resizable" : "iphone_portrait.pdf"
},
"items": [
{
"inputs": {
"up": "up",
"down": "down",
"left": "left",
"right": "right"
},
"frame": {
"x": 15,
"y": 500,
"width": 128,
"height": 128
},
"extendedEdges": {
"top": 15,
"bottom": 15,
"left": 17,
"right": 10
}
},
{
"inputs": [
"a"
],
"frame": {
"x": 313,
"y": 540,
"width": 47,
"height": 47
},
"extendedEdges": {
"top": 0,
"bottom": 0,
"left": 0,
"right": 16
}
},
{
"inputs": [
"b"
],
"frame": {
"x": 267,
"y": 586,
"width": 47,
"height": 47
},
"extendedEdges": {
"top": 0,
"left": 0,
"right": 0
}
},
{
"inputs": [
"l"
],
"frame": {
"x": 18,
"y": 366,
"width": 32,
"height": 112
},
"extendedEdges": {
"right": 0,
"left": 18
}
},
{
"inputs": [
"r"
],
"frame": {
"x": 325,
"y": 366,
"width": 32,
"height": 112
},
"extendedEdges": {
"left": 0,
"right": 18
}
},
{
"inputs": [
"start"
],
"frame": {
"x": 154,
"y": 600,
"width": 18,
"height": 18
},
"extendedEdges": {
"top": 15,
"bottom": 0,
"left": 0,
"right": 45
}
},
{
"inputs": [
"select"
],
"frame": {
"x": 154,
"y": 631,
"width": 18,
"height": 18
},
"extendedEdges": {
"top": 0,
"bottom": 15,
"left": 0,
"right": 45
}
},
{
"inputs": [
"menu"
],
"frame": {
"x": 154,
"y": 498,
"width": 18,
"height": 18
},
"extendedEdges": {
"left": 0,
"right": 45
}
},
{
"inputs": [
"y"
],
"frame": {
"x": 221,
"y": 540,
"width": 47,
"height": 47
},
"extendedEdges": {
"top": 0,
"bottom": 0,
"right": 0
}
},
{
"inputs": [
"x"
],
"frame": {
"x": 267,
"y": 494,
"width": 47,
"height": 47
},
"extendedEdges": {
"bottom": 0,
"left": 0,
"right": 0
}
},
{
"inputs": {
"x": "touchScreenX",
"y": "touchScreenY"
},
"frame": {
"x": 50,
"y": 252,
"width": 275,
"height": 206
},
"extendedEdges": {
"top": 0,
"bottom": 0,
"left": 0,
"right": 0
}
}
],
"screens": [
{
"inputFrame": {
"x": 0,
"y": 0,
"width": 256,
"height": 192
},
"outputFrame": {
"x": 50,
"y": 18,
"width": 275,
"height": 206
}
},
{
"inputFrame": {
"x": 0,
"y": 192,
"width": 256,
"height": 192
},
"outputFrame": {
"x": 50,
"y": 252,
"width": 275,
"height": 206
}
}
],
"mappingSize" : {
"width" : 375,
"height" : 667
},
"extendedEdges" : {
"top" : 7,
"bottom" : 7,
"left" : 7,
"right" : 7
}
},
"landscape" : {
"assets" : {
"resizable" : "iphone_landscape.pdf"
},
"items": [
{
"inputs": {
"up": "up",
"down": "down",
"left": "left",
"right": "right"
},
"frame": {
"x": 15,
"y": 235,
"width": 123,
"height": 123
},
"extendedEdges": {
"top": 15,
"bottom": 20,
"left": 20,
"right": 20
}
},
{
"inputs": [
"a"
],
"frame": {
"x": 606,
"y": 273,
"width": 47,
"height": 47
},
"extendedEdges": {
"top": 0,
"bottom": 0,
"left": 0,
"right": 30
}
},
{
"inputs": [
"b"
],
"frame": {
"x": 562,
"y": 318,
"width": 47,
"height": 47
},
"extendedEdges": {
"top": 0,
"left": 0,
"right": 0
}
},
{
"inputs": [
"l"
],
"frame": {
"x": 173,
"y": 219,
"width": 135,
"height": 33
},
"extendedEdges": {
"top": 0
}
},
{
"inputs": [
"r"
],
"frame": {
"x": 359,
"y": 219,
"width": 135,
"height": 33
},
"extendedEdges": {
"top": 0
}
},
{
"inputs": [
"start"
],
"frame": {
"x": 304,
"y": 287,
"width": 18,
"height": 18
},
"extendedEdges": {
"right": 50
}
},
{
"inputs": [
"select"
],
"frame": {
"x": 410,
"y": 288,
"width": 18,
"height": 18
},
"extendedEdges": {
"right": 50
}
},
{
"inputs": [
"menu"
],
"frame": {
"x": 195,
"y": 288,
"width": 18,
"height": 18
},
"extendedEdges": {
"right": 50
}
},
{
"inputs": [
"x"
],
"frame": {
"x": 562,
"y": 229,
"width": 47,
"height": 47
},
"extendedEdges": {
"top": 8,
"bottom": 0,
"left": 0,
"right": 0
}
},
{
"inputs": [
"y"
],
"frame": {
"x": 517,
"y": 273,
"width": 47,
"height": 47
},
"extendedEdges": {
"top": 0,
"bottom": 0,
"right": 0
}
},
{
"inputs": {
"x": "touchScreenX",
"y": "touchScreenY"
},
"frame": {
"x": 361,
"y": 24,
"width": 259,
"height": 194
},
"extendedEdges": {
"top": 0,
"bottom": 0,
"left": 0,
"right": 0
}
}
],
"mappingSize" : {
"width" : 667,
"height" : 375
},
"screens": [
{
"inputFrame": {
"x": 0,
"y": 0,
"width": 256,
"height": 192
},
"outputFrame": {
"x": 47,
"y": 24,
"width": 259,
"height": 194
}
},
{
"inputFrame": {
"x": 0,
"y": 192,
"width": 256,
"height": 192
},
"outputFrame": {
"x": 361,
"y": 24,
"width": 259,
"height": 194
}
}
],
"extendedEdges" : {
"top" : 15,
"bottom" : 15,
"left" : 15,
"right" : 15
}
}
},
"edgeToEdge" : {
"portrait" : {
"assets" : {
"resizable" : "iphone_edgetoedge_portrait.pdf"
},
"items" : [
{
"inputs" : {
"up" : "up",
"down" : "down",
"left" : "left",
"right" : "right"
},
"frame" : {
"x" : 18,
"y" : 650,
"width" : 165,
"height" : 165
},
"extendedEdges" : {
"top" : 15,
"bottom" : 15,
"left" : 18,
"right" : 10
}
},
{
"inputs" : [
"a"
],
"frame" : {
"x" : 336,
"y" : 703,
"width" : 60,
"height" : 60
},
"extendedEdges" : {
"top" : 0,
"bottom" : 0,
"left" : 0,
"right" : 18
}
},
{
"inputs" : [
"b"
],
"frame" : {
"x" : 280,
"y" : 759,
"width" : 60,
"height" : 60
},
"extendedEdges" : {
"top" : 0,
"left" : 0,
"right" : 0
}
},
{
"inputs" : [
"l"
],
"frame" : {
"x" : 29,
"y" : 590,
"width" : 136,
"height" : 35
}
,
"extendedEdges": {
"top": 0,
"left": 29
}
},
{
"inputs" : [
"r"
],
"frame" : {
"x" : 249,
"y" : 590,
"width" : 136,
"height" : 35
}
,
"extendedEdges": {
"top": 0,
"right": 29
}
},
{
"inputs" : [
"start"
],
"frame" : {
"x" : 174,
"y" : 844,
"width" : 20,
"height" : 20
},
"extendedEdges" : {
"bottom": 32,
"left": 15,
"right" : 75
}
},
{
"inputs" : [
"select"
],
"frame" : {
"x" : 369,
"y" : 844,
"width" : 20,
"height" : 20
},
"extendedEdges": {
"bottom": 32,
"left": 75,
"right": 25
}
},
{
"inputs" : [
"menu"
],
"frame" : {
"x" : 25,
"y" : 844,
"width" : 20,
"height" : 20
},
"extendedEdges": {
"bottom": 32,
"left": 25,
"right": 75
}
},
{
"inputs" : [
"y"
],
"frame" : {
"x" : 224,
"y" : 703,
"width" : 60,
"height" : 60
},
"extendedEdges" : {
"top" : 0,
"bottom" : 0,
"right" : 0
}
},
{
"inputs" : [
"x"
],
"frame" : {
"x" : 280,
"y" : 647,
"width" : 60,
"height" : 60
},
"extendedEdges" : {
"bottom" : 0,
"left" : 0,
"right" : 0
}
},
{
"inputs": {
"x": "touchScreenX",
"y": "touchScreenY"
},
"frame": {
"x": 30,
"y": 324,
"width": 354,
"height": 265
}
,
"extendedEdges": {
"top": 0,
"bottom": 0,
"left": 0,
"right": 0
}
}
],
"screens": [
{
"inputFrame": {
"x": 0,
"y": 0,
"width": 256,
"height": 192
},
"outputFrame": {
"x": 30,
"y": 43,
"width": 354,
"height": 265
}
},
{
"inputFrame": {
"x": 0,
"y": 192,
"width": 256,
"height": 192
},
"outputFrame": {
"x": 30,
"y": 324,
"width": 354,
"height": 265
}
}
],
"mappingSize" : {
"width" : 414,
"height" : 896
},
"extendedEdges" : {
"top" : 7,
"bottom" : 7,
"left" : 7,
"right" : 7
}
},
"landscape" : {
"assets" : {
"resizable" : "iphone_edgetoedge_landscape.pdf"
},
"items" : [
{
"inputs" : {
"up" : "up",
"down" : "down",
"left" : "left",
"right" : "right"
},
"frame" : {
"x" : 69,
"y" : 260,
"width" : 136,
"height" : 136
},
"extendedEdges" : {
"left" : 30,
"top" : 20,
"right" : 20,
"bottom" : 20
}
},
{
"inputs" : [
"a"
],
"frame" : {
"x" : 777,
"y" : 302,
"width" : 51,
"height" : 51
},
"extendedEdges" : {
"top" : 0,
"bottom" : 0,
"left" : 0,
"right" : 30
}
},
{
"inputs" : [
"b"
],
"frame" : {
"x" : 728,
"y" : 351,
"width" : 51,
"height" : 51
},
"extendedEdges" : {
"top" : 0,
"left" : 0,
"right" : 0
}
},
{
"inputs" : [
"l"
],
"frame" : {
"x" : 69,
"y" : 65,
"width" : 40,
"height" : 148
}
,
"extendedEdges": {
"left": 50,
"right": 0
}
},
{
"inputs" : [
"r"
],
"frame" : {
"x" : 788,
"y" : 65,
"width" : 40,
"height" : 148
}
,
"extendedEdges": {
"left": 0,
"right": 50
}
},
{
"inputs" : [
"start"
],
"frame" : {
"x" : 415,
"y" : 315,
"width" : 20,
"height" : 20
},
"extendedEdges": {
"right": 50
}
},
{
"inputs" : [
"select"
],
"frame" : {
"x" : 533,
"y" : 315,
"width" : 20,
"height" : 20
},
"extendedEdges" : {
"right" : 50
}
},
{
"inputs" : [
"menu"
],
"frame" : {
"x" : 295,
"y" : 315,
"width" : 20,
"height" : 20
},
"extendedEdges": {
"right": 50
}
},
{
"inputs" : [
"x"
],
"frame" : {
"x" : 728,
"y" : 253,
"width" : 51,
"height" : 51
},
"extendedEdges" : {
"bottom" : 0,
"left" : 0,
"right" : 0
}
},
{
"inputs" : [
"y"
],
"frame" : {
"x" : 679,
"y" : 302,
"width" : 51,
"height" : 51
},
"extendedEdges" : {
"top" : 0,
"bottom" : 0,
"right" : 0
}
},
{
"inputs": {
"x": "touchScreenX",
"y": "touchScreenY"
},
"frame": {
"x": 500,
"y": 27,
"width": 286,
"height": 214
}
,
"extendedEdges": {
"top": 0,
"bottom": 0,
"left": 0,
"right": 0
}
}
],
"mappingSize" : {
"width" : 896,
"height" : 414
},
"screens": [
{
"inputFrame": {
"x": 0,
"y": 0,
"width": 256,
"height": 192
},
"outputFrame": {
"x": 110,
"y": 27,
"width": 286,
"height": 214
}
},
{
"inputFrame": {
"x": 0,
"y": 192,
"width": 256,
"height": 192
},
"outputFrame": {
"x": 500,
"y": 27,
"width": 286,
"height": 214
}
}
],
"extendedEdges" : {
"top" : 15,
"bottom" : 15,
"left" : 15,
"right" : 15
}
}
}
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,68 +0,0 @@
//
// DSDeltaCore.swift
// DSDeltaCore
//
// Created by Riley Testut on 8/2/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
import Foundation
import AVFoundation
import DeltaCore
@objc public enum DSGameInput: Int, Input
{
case up = 1
case down = 2
case left = 4
case right = 8
case a = 16
case b = 32
case x = 64
case y = 128
case l = 256
case r = 512
case start = 1024
case select = 2048
case touchScreenX = 4096
case touchScreenY = 8192
public var type: InputType {
return .game(.ds)
}
public var isContinuous: Bool {
switch self
{
case .touchScreenX, .touchScreenY: return true
default: return false
}
}
}
public struct DS: DeltaCoreProtocol
{
public static let core = DS()
public var name: String { "DSDeltaCore" }
public var identifier: String { "com.rileytestut.DSDeltaCore" }
public var gameType: GameType { GameType.ds }
public var gameInputType: Input.Type { DSGameInput.self }
public var gameSaveFileExtension: String { "dsv" }
public let audioFormat = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: 44100, channels: 2, interleaved: true)!
public let videoFormat = VideoFormat(format: .bitmap(.rgba8), dimensions: CGSize(width: 256, height: 384))
public var supportedCheatFormats: Set<CheatFormat> {
return []
}
public var emulatorBridge: EmulatorBridging { DSEmulatorBridge.shared }
private init()
{
}
}

View File

@ -1,20 +0,0 @@
//
// DSDeltaCore.h
// DSDeltaCore
//
// Created by Riley Testut on 8/2/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
#import <UIKit/UIKit.h>
//! Project version number for DSDeltaCore.
FOUNDATION_EXPORT double DSDeltaCoreVersionNumber;
//! Project version string for DSDeltaCore.
FOUNDATION_EXPORT const unsigned char DSDeltaCoreVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <DSDeltaCore/PublicHeader.h>
#import <DSDeltaCore/DSTypes.h>
#import <DSDeltaCore/DSEmulatorBridge.h>

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
</plist>

View File

@ -1,12 +0,0 @@
//
// DSTypes.h
// DSDeltaCore
//
// Created by Riley Testut on 2/1/20.
// Copyright © 2020 Riley Testut. All rights reserved.
//
#import <DeltaCore/DeltaTypes.h>
// Extensible Enums
FOUNDATION_EXPORT GameType const GameTypeDS NS_SWIFT_NAME(ds);

View File

@ -1,11 +0,0 @@
//
// DSTypes.m
// DSDeltaCore
//
// Created by Riley Testut on 2/1/20.
// Copyright © 2020 Riley Testut. All rights reserved.
//
#import "DSTypes.h"
GameType const GameTypeDS = @"com.rileytestut.delta.game.ds";

View File

@ -1,6 +0,0 @@
# DeSmuME
[![AppVeyor CI Build Status](https://ci.appveyor.com/api/projects/status/abfd7jm09wnmxyvu?svg=true)](https://ci.appveyor.com/project/zeromus/desmume)
DeSmuME is a Nintendo DS emulator.
http://desmume.org

View File

@ -1,50 +0,0 @@
Original author
---------------
yopyop
Current team
------------
Guillaume Duhamel
Normmatt
zeromus
rogerman
Contributors
------------
Bernat Muñoz (shash)
Allustar
amponzi
Anthony Molinaro
ape
Damien Nozay (damdoum)
delfare
Romain Vallet
snkmad
Theo Berkau
thoduv
Tim Seidel (Mighty Max)
Pascal Giard (evilynux)
Ben Jaques (masscat)
Jeff Bland
Bernat Muñoz (shash)
matusz
nitsuja
gocha
pa__
adelikat
hi-coder
WinterMute
pengvado
dormito
ldesnogue
mtheall
thelemonman
nash679
pokefan999
dottorleo
yki
Luigi__
CrazyMax
Riccardo Magliocchetti
CyberWarriorX
mic

View File

@ -1,339 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -1,877 +0,0 @@
0.9.11 -> 0.9.12 (r5146-r????)
0.9.10 -> 0.9.11 (r4908-r5146)
In this version, we have focused on the Cocoa frontend, but there have been some good core fixes over so long.
Notably, the save-related issues resulting in the advice "dont use 0.9.10" have been resolved.
General/Core:
bug: fix large numbers of games not being able to save anymore
bug: fix some missing sound effects due to wrong volumes in some boot scenarios and other things
bug: fix freezes due to tiny looping sounds
bug: fix many big endian issues
bug: fix some apparently rarely-used CPU instructions, no known consequences
bug: fix (block) reading of some GPU registers
bug: fix action replay code type 0xE
bug: fix reading of last 4 bytes of rom
bug: large improvements to stability of GDB stub
bug: support w-buffer support in OpenGL renderers
bug: fix unpredictable crashes in some 3d scenes from w=0
enh: better loading of roms (bad patches) with wrong size info in header
enh: warn user sometimes when 'stream rom from disk' will create malfunctions
enh: add xBRZ filters
enh: add "TXT Hack" for software rasterizer to improve text rendering in some games
Windows:
bug: fix 5x filters
enh: support import of action replay save files (.dss)
enh: add antialiasing option for OpenGL renderers
enh: don't malfunction if saveram is unavailable or read-only
Cocoa:
bug: 16-bit to 32-bit color space conversions no longer darken video or images
bug: fix intermittent issues with loading user defaults on app startup
bug: fix rendering inaccuracies of the video preview in the app display preferences
bug: fix various UI font rendering and text alignment issues on OS X Yosemite
bug: fix crackly sound from N-sync and Z-sync methods
enh: make N-sync method the default sound sync method since it has much lower latency than P-sync method
enh: add support for gdbstub (Tools > Show GDB Stub Control) (only available on custom builds using the dev+ build target)
enh: optimize input handling to use less CPU
enh: add support for App Nap when the app is in an idle state (only supported on OS X Mavericks and later)
enh: add Execution Control panel (Emulation > Show Execution Control), now with frame advance and frame jump controls
enh: auto frame skip is now smoother
enh: further improve execution timing accuracy
enh: improve overall video performance
enh: render video through a 3-stage filtering pipeline, (Video Source)-->(Pixel Scaler)-->(Video Output)
enh: add the following video source filters - Deposterize
enh: add the following video output filters - Bicubic B-Spline, Bicubic Mitchell-Netravali, Lanczos2, Lanczos3
enh: add ability to run all existing pixel scalers on either the CPU or the GPU
enh: add ability to toggle the main and touch display positions (View > Toggle All Displays)
enh: add preliminary support for replay playback and recording
enh: add support for turbo and autohold
enh: add support for the entire suite of slot-2 devices (Emulation > Show SLOT-2 Manager)
enh: add support for using the host machine's audio input device for emulating the NDS microphone (Emulation > Show Microphone Settings)
enh: change the sine wave tone generator's range from 100Hz-5000Hz to 40Hz-4000Hz
enh: reorganize the menu options to more logical locations
enh: greatly improve the File Migration Assistant (now renamed Game Data Migration Assistant) and ROM Info panel with a more modern and space efficient look and feel
enh: miscellaneous user interface improvements
Linux:
bug: fix screen gap bug
bug: workaround for std::bad_alloc exceptions compiler bugs
enh: add experimental AV recording
enh: generally improve main loop throttling and skipping
enh: massive improvements to HUD and menu layout
enh: add window sizing options and sound interpolation options
enh: add Lid button; disallow U+D, L+R; manual option saving
0.9.9 -> 0.9.10 (r4623-r4908)
In this version, we have focused on trying to clean up some complexities in the user experience and emulator internals. Pretty unglamorous stuff, but some games are newly compatible.
General/Core:
enh: break savestate back-compatibility
bug: improve save size autodetection for some games
bug: cpu: fix many basic jit cpu bugs
bug: 3d: tweak softrasterizer edge marking
bug: 3d: fix stale 4x4 texture palettes
bug: fix some GPU sprite blending scenarios
bug: fix bios HLE BitUnPack, UnCompHuffman
enh: modular slot-1 device system, emulate GC bus more faithfully
enh: support NAND slot-1 device
enh: auto-detect appropriate slot-1 and slot-2 device
enh: many revisions to firmware boot process for more authenticity. iQue and FlashME versions function, .dfc rewritten.
enh: support streaming NDS file from disk (like an ISO, to avoid long initial load time)
enh: run .dsv directly on disk, to save long flushing times. should speed backup operations.
enh: spu synch mode and method on commandline
Windows:
bug: fixes to advanscene DB import
bug: save opengl display method filter option
bug: general bugfixes to various screen layout modes
enh: add option to stop non-integer scaling during fullscreen or maximize
enh: improvements to save import dialog
enh: improved memory viewer tool
enh: operate better when run, against our advice, from a zipfile
enh: add slot-1 Nitro Filesystem viewer tool
Cocoa:
bug: fix slot1-R4 path saving
bug: fix bug with mic samples < 16khz
bug: fix bugs and enhancements in multi display windows
bug: fix handling of some joystick analog inputs
enh: save display windows configuration and emulation speed on app exit
0.9.8 -> 0.9.9 (r4228-r4623)
Yes, it's been a while since the last release, but we haven't been completely idle. There's a brand new jit cpu core which yields some impressive speedups!
General/Core:
!!!: add optional arm cpu jit (functioning on x86 and x64 hosts only)
bug: we're not going to list 70% of the emulation fixes, as is traditional.
bug: savestate reliability fixes related to halt states, gxstat, firmware
bug: lua: fix readbyterange, gdscreenshot functions
bug: commandline slot-1 handling straightened out
enh: fixes and additions to resize filter options
Graphics:
enh: opengl 3d driver compatibility improvements
bug: fix giant regression from 0.9.7 that left garbage from previous frames on the screen in some games
bug: 3d: fix some single poly pixels
bug: 3d: fix some polygon and texture coloring bugs on big-endian systems
Windows:
bug: fix some full screen stretching bugs
enh: add xaudio2 output driver
enh: add opengl display method (as opposed to directdraw), with controllable bilinear filter
enh: upgrade archive handling system, lzma2 supported
enh: reorganize main menu quite a bit
enh: add rotation hotkeys, and hotkey to control mouse cursor visibility
enh: memory viewer improvements and fixes
enh: improve interface for rom eject to prevent accidents and improve usefulness (hide in slot-1 config screen)
Cocoa:
bug: fix missing display when running on OS X v10.8 Mountain Lion
bug: fix possible sound crash when using Dual SPU Synch/Asynch
bug: fix File menu items being disabled after the file migration sheet is used
bug: fix window resizing issues
bug: fix text rendering in About box
enh: show the icon and name of the loaded ROM
enh: add Support Request and Bug Report forms to the Help menu
enh: add more detailed info to the About box
enh: add OpenGL as a 3D rendering option
enh: add support for MSAA when using OpenGL as the 3D rendering engine
enh: add V-Sync option
enh: add Display Orientation, Display Order, and Display Separation options for Combo Display mode
enh: add HQ4xS filter
enh: completely revamp the user interface for Input Preferences
enh: many emulator commands may now be mapped
enh: add ability to map an input to user-defined touch screen coordinates
enh: add support for saving and applying input profiles
enh: add support for using an audio file for the microphone input
enh: add sine wave tone generator for microphone input
enh: add support for multiple display windows (File > New Display Window)
enh: add support for SLOT-1 devices (Emulation > Show SLOT-1 Manager)
enh: overall performance and stability improvements
enh: miscellaneous user interface improvements
0.9.7 -> 0.9.8 (r3812-r4228)
Yes, it's been a while since the last release, but we haven't been completely idle. There's a brand new top shelf Cocoa frontend to make life far more pleasant for OSX users, and a host of compatibility fixes.
General/Core:
bug: fix more IPC FIFO errors
bug: import more save files correctly
bug: don't autopatch already-patched roms
bug: fix bugs in piano and guitar grip
bug: fix ARM7's VRAMSTAT register
bug: fix memory leaks on compact flash emulation
bug: fix reading of rom from low header area
bug: spu: fix some poppy interpolation audio quality issues
bug: improve timing of dma operations by running through normal mem cycle accounting; fixes an annoying number of games and graphical glitches
bug: fix opcode MRC and fake bios CRC16
enh: jitter some related register and irq events to simulate pipeline effects and stimulate some race conditions to other outcomes
enh: fake (deterministic) some tiny jitter from human's hand holding stylus; some games were accidentally depending on this
enh: support nocash-style prints from arm
enh: add lua apis for accessing vram
enh: platforms other than windows receive threading optimizations
enh: provide diagnostics when system powers off (useful for homebrewers returning from main())
enh: clarify handling of different console types within the family (ds,dslite,debug)
enh: vfat support for slot-1 devices
enh: emulate temperature register
enh: add paddle emulation
Graphics:
bug: fix occasional crash from uninitialized blending table
bug: fix some 2d alpha blending cases resulting in white screens
bug: fix VRAM_I B_OBJ mirroring and fix sprites rendering across the end of vram
bug: fix rotoscaled sprites wrapping around screen
bug: dont fix rotscaled bitmap sprites with alpha==0
bug: opengl: fix degradation of toon rendering during loadstate
bug: opengl: alpha blending fixes
bug: many refinements to opengl renderer
bug: opengl: support rear-plane/ClearImage emulation (fixes many graphics)
bug: rasterizer: fix some rare alpha blending cases
bug: fix bug in environment mapping introduced after 0.9.6
bug: fix totally glitched out 3d graphics with several improvements involving matrix stack
bug: fix memory overflows in epx filter
bug: prevent backdrop from blending with ???
enh: opengl: better depth buffering emulation
enh: better support for line segment "polys" by detection and special rendering logic
enh: opengl: support quad primitives directly
enh: add hq4x filter
Windows:
bug: fix a long-standing loadstate crash
bug: fix lag frame accounting
bug: fix glitches in cheat entry menu
bug: stop compact flash emulation from accidentally scanning c:\ sometimes
enh: add support for game database for improved save type detection
enh: hotkey for limit framerate toggle
enh: remove stop and reset toolbar buttons which were accidentally getting used
enh: additional complexification to desmume's behaviour run from a console prompt. whether it's better is uncertain.
enh: add support for cheats databases
enh: improvements to ram search tool
enh: preliminary support for varying stylus pressure
enh: add [Display] Show Console=1 to ini file
enh: more graceful cheat parsing and add some hotkeys
enh: add 5x window size
enh: add big endian and 20.12 toggle to memview and ramwatch
enh: improve FPS throttle feedback and granularity
enh: add lua menu API
enh: hud font switching
enh: add optional file association for .nds to path config dialog
Cocoa:
enh: Big update to cocoa frontend. Pretty much entirely new. (rogerman)
Linux:
bug: gtk: glitches in rom and recent rom loading
bug: glade: normalize savestate slot to hotkey mapping
enh: support soundtouch for use by metaspu
enh: gtk: add SPU mode selection (Tobias Jakobi)
enh: cli: better fps limiting (Thomas Jones)
Wx:
bug: some small fixes here and there (Jan Bücken)
enh: lot of code cleanup (Jan Bücken)
0.9.6 -> 0.9.7 (r3493-r3812)
General/Core:
bug: fix a ton of old, broken cpu opcodes and CP15 logic
bug: return Z1 and Z2 from TSC (fixes some touch logic)
bug: gba slot save type detection improved
bug: handle unusual rom headers more correctly
bug: dont confuse motion pack commands with save memory commands
bug: make cheat system a little less flaky and add AR 1.54 support
bug: fix nondeterministic backup memory behaviour while rerecording
bug: correct emulation of register accesses of wrong size and during powerdown
bug: rewrite --cflash-path emulation
bug: rewrite IPC/GX FIFO, IRQ flag generation, and wait-for-IRQ logics
bug: rewrite RTC calendar handling; now supports years > 2038
enh: auto-DLDI patching for homebrew
enh: --gbaslot-rom=self mounts self.nds in slot2
enh: more realistic exception handling
enh: piano controller emulation
enh: modular slot-1 system for exact emulation of homebrew cards
Graphics:
bug: edge marking colors were wrong
bug: handle some "invalid" vram configurations correctly
bug: convert half of geometry engine to fixed point
bug: fix sprite blend+fadein/fadeout
bug: improve rasterizer shadows
bug: fix main memory display DMA
bug: fix some raster fx timing bugs
enh: add a hack for improving some non-stencil shadows
Windows:
bug: misc fixes and improvements to gpu viewer tools
bug: sub screen layer display toggling fixed
bug: fixes and improvements to ram watch, ram search, cheats list
bug: fix start-paused commandline
bug: fix memory leaks when sound disabled
bug: improve load average calculators and add arm7 load average
enh: background input support
enh: add vsync option
enh: support more knobs on joysticks
enh: import cheats from R4 database
enh: add xinput rumble for 360 pads
Linux/OSX:
bug: crash less in recent roms list
enh: Add horizontal screen layout and swap screen ability to gtk frontend (noodlebox)
enh: Big improvement to joystick support, support complex configurations and multiple devices (noodlebox)
0.9.5 -> 0.9.6 (r3075-r3493)
Users of gtk, cli and gtk-glade frontends please note that now we
have a common directory in ~/.config/desmume for config file,
saves and savestates. The old .desmume.ini will be moved
automatically with the name config but you have to move your saves
manually.
Some save files may be invalidated due to use of broken crc logic.
Back up your DSV files before using this version of the emulator or else
the game might wipe it.
General/Core:
bug: emulate keypad interrupt
bug: spu overhaul, add capture support
bug: fix dma address reloading
bug: fix rom close memory corruption
bug: fix div and sqrt busy flag bug
bug: fix vectest
bug: fix lid savestate desync
bug: fix texcache memory GB explosion when games use tons of tiny 3d sprites
bug: fix huge rerecording movie file handle leak
bug: fix EXXXXXXX cheat codes and some add/edit/save/load bugs
bug: add 8MBit - 512MBit flash emulation
bug: fix firmware booted-from-card flag
bug: fix some failures to wake
bug: fix some rtc calendar logic
bug: op_bkpt emulation
bug: correctly emulate POWCNT1 and POWCNT2 and SPI power device
bug: corrections to bootup stack configuration
bug: protect bios from being overwritten
bug: initialize save data to 0xFF instead of 0x00
bug: handle relocated irq vectors
bug: support patched firmwares
bug: handle 8bit auxspidata, 32bit BLDY, 32bit div regs
bug: fix some divide by zero cases
bug: don't print \n in ideas debug message
bug: don't let games read off end of cart and crash emulator
bug: fix SWI 0x0E crc16 ; some save files using wrong crc may be invalidated
bug: fix many big endian bugs
bug: fix CPSR.I idle wakeup
bug: fix loadstate crashes, mostly when sound is enabled
enh: support devkitpro argv
enh: add gbaslot-rom commandline
enh: add no$gba debug message
enh: add rtc start to dsm header
Graphics:
bug: fix a mistakenly rendered OBJ window and 3d blend effects
bug: fixes to matrix stacks, fixing lots of garbled geometry
bug: fix fog density registers
bug: fix hblank dma to run also on scanline 262
bug: fix w/z depth flags for broken GUIs in dual screen 3d games
bug: fixes to poly sorting
bug: block 8bit vram writes
enh: improve accuracy of opengl shaders
Windows:
bug: fix 16bpp display
bug: more fixes to multi-gamepads
bug: cheat windows robustification
bug: fix that sticky pause state when resetting and loading roms
bug: dont crash when no sound device is available
bug: change F10 to be save slot 0
bug: fix --start-paused
enh: try not to screensave while using gamepad
enh: add EPX and EPX1.5X resize filters
enh: add a japanese translation which will soon be stale like the others
enh: add fancy ctrl+printscreen with emulator info on it
enh: add "lockdown" window mode to keep window safe from fast stylus action
enh: add alt+enter fullscreen command
enh: add card eject command
enh: add ddraw software mode forcer
enh: improve oam viewer
enh: default 3d to rasterizer so we dont have to suggest it 1000 times a day
enh: add dump-all-memory tool
enh: add reload rom menu/hotkey
Linux/OSX:
bug: fix building for nosse2 systems
bug: fix --num-cores
bug: fix occasional touchscreen failures
bug: fix crash starting dsm record
enh: add --nojoy=1 to fix laptops with accelerometers
enh: add simple auto frameskip mode in the gtk frontend
enh: add gui for configuring joystick in the gtk frontend
enh: make the cli frontend read the ini config file too
enh: additional OpenAL microphone backend (ncalexan)
enh: common place for config and saves (Jan Steffens)
enh: libagg is now optional if you don't need the hud
0.9.4 -> 0.9.5 (r2437-r3075)
0.9.5 introduces an entirely rewritten main emulation loop
This totally changes the timing, and totally breaks old savestates.
The OSX build is now based on the GTK port which is more up-to-date.
Assorted Highlights:
* synchronous SPU mode to fix streaming sounds
* win32: lua engine, path configuration, 7z dearchiving support
General/Core:
bug: rewrite main emulation loop and cycle accounting, fixes a lot of timings
bug: add more detailed timing emulation, removes much bogus lag
bug: rewrite DMA,gxfifo,gxstat; fix many games and no more alternate flush mode
bug: fix cflash directory support for non-windows and sector-writing
bug: fix freeze in cart irq
bug: correctly emulate dma to/from tcm
bug: fix in thumb LSR carryflag
bug: fix thumb BX PC switch to arm state
bug: fix adpcm looping, remove adpcm caching (no longer necessary)
bug: fixes to swi 3,4,5,8,0x10
bug: fixes to exmemstat and ipc sync registers
bug: support new backup commands
bug: improve bootup bios/firmware emulation steps
enh: gbaslot: add guitar grip, gbagame flash support, expansion memory pak
enh: add more powerful antigrain-based drawing library and rewrite OSD system
enh: ideas-style debugging prints
enh: most optimizations now SSE instead of SSE2
enh: more improvements to frameskipping and frame advance/speed controls
Graphics:
bug: fix backdrop blending with garbage
bug: fix 256B granularity sprite addressing for sub gpu
bug: fix obj blending, bmp obj rendering, and some obj window cases
bug: fix 128-wide captures
bug: fix 16color BG line buffer overflow
bug: fix color overflow in capture blending
bug: fix disp fifo capture
bug: fix simultaneous vram display and capture via same bank
bug: fix 3d overflow acknowledge registers
bug: fix 32bit toon table writes
bug: change 3d cores to use 18bit color
bug: fix boxtest (addition overflow!), move clipper to main graphics engine
bug: fix failure in some cases of polygon clipping
bug: fix disp3dcnt emulations
bug: fixes to poly sorting
bug: fix ogl renderer wireframe support
bug: swrast: fix backface culling of nonconvex polys
bug: swrast: add clear image and scroll emulation
bug: swrast: add fog emulation
bug: swrast: fixes to shadow rendering
bug: swrast: preliminary edge marking, works decent
enh: swrast: multicore optimization for a few fps speedup
Windows:
bug: fix support for multiple gamepads and gamepad hotkeys
bug: fix mic noise code and load wav instead of raw; effective in more cases
bug: fix for several sticky and broken hotkeys, and f10 hotkeys
bug: fixes in ram search, add DTCM and ITCM searching, ...
bug: fix sound settings vol slider
bug: recover from missing window -32000 problem
bug: don't turn on mic unless mic input is enabled
enh: x64 build type now supported
enh: side-by-side and single screen view modes, many fixes to window resizing
enh: choose any gap size by dragging bottom window edge (must be enabled)
enh: choose a gap color
enh: import/export no$GBA savefiles directly
enh: multicore optimization for filters, rotation, OSD
enh: soundview can now mute channels
enh: new ioregview
enh: common commandline system, many arguments shared with linux
enh: improve map view tool to support more modes
enh: add "FORCE AS CURRENT" recovery tool for mis-sized savefiles
enh: add some kind of very small savestate rewinding buffer
enh: autoframeskip works better
enh: add Italian translation
enh: added 2x resizing filters (hq2x, hq2xs, lq2x, lq2xs, 2xsai, supereagle)
(scanlines, nearest2x, bilinear)
Linux:
enh: alsa microphone support
enh: hud and osd notification for gtk and cli frontends
enh: add support for the SSE optimizations
0.9.2 -> 0.9.4 (r1844->r2352->r2437)
0.9.3 was skipped due to emu news sites sneaking it out of our staging area and
releasing it prematurely while it still had bugs. I was going to curse them
individually, but then I decided that they would just like the publicity.
Highlights:
* New save autodetection and save file format
* Full rerecording support
General/Core:
bug: fix many 64 bit and endian issues
bug: fix mic input, which was nearly useless before
bug: fix failures of large dmas
bug: fix in ipc sync which broke devkitpro touch
bug: screenshots now exclude hud and rotation
bug: rewritten vram mapping (fixes corrupted or missing BG)
enh: add universal commandline system (same commandline options on every port)
enh: cheats: added Action Replay code parser
enh: more reliable and useful frameskipping
enh: SPU: speedup: add adpcm caching
enh: SPU: speedup: interpolation is now optional
enh: print svn build number so we can identify people's svn builds from screenshots
Graphics:
bug: add polygon y-sorting (fixes 3d guis)
bug: fix texcoordgen mode 3; fixes some ortho sprites and some entirely broken games
bug: display capture fixes
bug: fix a number of OBJ modes
bug: fixes to affine BG modes
bug: better emulate some translucent OBJ
bug: more correct handling of color effect windows and backdrop colors
bug: fix matrix stack overrun which crashed emulator
bug: swrast: add clear depth image emulation and other fixes to depth buffering
bug: swrast: fix some toon and highlight cases
bug: fix bug in matrix stack, fixes some broken models
enh: add alternate flush mode HACK 3d config toggle, fixes some entirely broken 3d games
Windows:
bug: more robust cheats engine and dialog
enh: more solid avi and wav recording
enh: improved tools: memory viewer
enh: added tools: spu viewer, ram watch, ram search
enh: change build configuration system
enh: speedup: add gpu core disabling to hide useless screens
enh: add background pause feature (for when emulator loses focus)
enh: add missing autohold for L and R
enh: add chinese translation
Gtk frontend:
enh: switch all of menu/toolbar system to GtkAction + GtkUIManager
enh: remove the gtglext 3d code
enh: improve/speedup screen resize and final presentation logic in gtk frontend
enh: minimal rerecording hookups
Cli frontend:
enh: hooked the frameskip (szigor)
enh: misc usability improvements: auto pause switch for pausing when focus is lost and exit on escape pressing (szigor)
enh: hook the fake noise mic; use m to toggle
0.9.1 -> 0.9.2
General/Core:
bug: fix error in SBCS/RSCS flags; fixes many odd behaviors and crashes [zeromus]
bug: add support for sleep mode and power registers [luigi__]
bug: important fixes to RTC so correct time is actually told [luigi__]
bug: fix card reads below 0x8000; fixes some game freezes [normatt]
bug: fix 4 mbit save type; fix non-autodetect savefile dumping [zeromus, matusz]
enh: add sram to GBA game addon emulation for importing savefiles [zeromus]
enh: many improvements and feature hookups in linux ports [matusz, luigi__]
Graphics:
bug: fix specular texture mapping mode [luigi__]
bug: repairs to some capture modes and vram mapping [zeromus, CrazyMax]
bug: viewports finally correctly handled [zeromus]
enh: add software rasterizer. quirky, but on par with opengl [zeromus]
Windows:
bug: mitigate bad frameskipper; default to old frameskipping mode [zeromus]
bug: fixes with recent roms and zipfile loading [zeromus]
bug: fix window position memory [zeromus]
enh: bios and firmware may now be used and booted [luigi__]
enh: many display, OSD, and input enhancements [luigi__]
enh: brand new hotkey and controls binding system [zeromus]
enh: configurable screen separation [luigi__]
enh: fast forward key [pa__]
enh: improvements to mic [luigi__]
enh: faster updates in debug tools, up to once per frame [pa__]
Mac OS X Port:
enh: added Italian translation thanks to Paolo Bernini [jeff]
enh: resurrection of GDB stub [sigmaris]
0.9 -> 0.9.1
General/Core:
enh: GBA slot emulation [CrazyMax]
- Rumble support (windows only)
- GBA game
enh: Mic support (windows only?) [luigi__]
enh: Preliminary cheats system [CrazyMax]
enh: Savestates invalidated, as more variables have been added.
bug: Added PSG white noise [luigi__]
bug: fix arm/thumb ROR [zeromus]
bug: [ 2550645 ] Super Princess Peach: crash when starting a puzzle [zeromus]
bug: win32: fix spu wav file writer (regression from 0.8) [zeromus,luigi__]
bug: Much work on FIFOs, still not finished [CrazyMax]
bug: Many fixes to dma [zeromus, CrazyMax]
bug: bios WaitForVblank and WaitForInterrupt fixed [luigi__]
Graphics:
bug: Added sprite blending [luigi__]
bug: more correct mosaic effects, still imperfect [zeromus]
bug: Many fixes to tile rendering; all graphics tests now pass [luigi__]
bug: fix crashes in some affine BG [zeromus]
bug: Implement some pos test function [luigi__]
bug: fix texture mapping across texture and palette banks and to unmapped banks [zeromus]
bug: fix texture handling for texels with MSB set (fixes some texture corruption) [zeromus]
bug: fix texture coordinate generation, including environment mapping [zeromus]
bug: texture cache invalidates when palettes change, prevents some texture corruption [zeromus]
bug: fix display capturing from 2d+3d source when display mode is display-vram [zeromus]
bug: [ 2488334 ].1 fixes to layer compositing [luigi__]
bug: [ 2488334 ].3 fix bug in support for hdma affine bg parameters [zeromus]
bug: Improvements to 3d h-scrolling [luigi__]
bug: Fix some errors in rendering 512 tall BG [zeromus,CrazyMax] (still not fully resolved)
bug: Add optional fragment shading pipeline (more precision) [luigi__]
bug: Fix bug where some sprites got cut of on x=255 [zeromus]
bug: Implement GXSTAT register [CrazyMax]
Windows:
bug: resizing and rotating work in vista [luigi__]
enh: 0 frameskip now lets emulator run at excess speed [zeromus]
Mac OS X Port:
bug: left key setting no longer gets confused with the right key [jeff]
enh: more keys can be mapped
0.8 -> 0.9
There have been so many changes that this list can hardly be considered complete.
For this release, we have formatted the list into a high level overview of big changes and bad bugs relative to the previous release. Hopefully what you're interested in.
This list does not include items which are solely performance boosts, for let us just say that virtually every system has been speeded up.
* The savestate system is totally changed and incompatible with old savestates.
* The 3d system should be considered rewritten.
General/Core:
enh: Convert to c++
enh: Add functions for a lid open/close. Holding key (default "Backspace" in Windows port) while game is freeze/non freeze. [CrazyMax]
enh: Add secure area decryption from ndstool [zeromus]
enh: Change savestate code to support loosely bound chunks and more easily other parts of the emu (GE, GPU).
The savestate format is changed, but from now on it is in principle more resilient
(though it will continue to break as we tinker with the internals) [zeromus]
enh: Added SSE2 optimizations for matrices. Since we now make an SSE2 build, more optimizations can be made. [CrazyMax]
enh: Add a preliminary GUI hud system [CrazyMax,zeromus]
CPU/MMU:
bug: Many fixes in IPC and GE FIFOs. Fixes freezes in NSMB, dsracing, and others. [CrazyMax,luigi__,shash]
bug: Fix ARM instructions SBC and RSC (likewise SBC in thumb) [normatt]
bug: Fixed Thumb LDMIA (fixes ingame Dead'n'Furious) [shash]
bug: Fix repeating DMA (fixes NSMB parallax BG) [zeromus]
bug: Proper handling for unaligned CPU accesses [luigi__]
bug: Proper handling for undefined instruction exceptions [Salva Peiró]
bug: correctly return vram control register values (fixes homebrew 3d games) [zeromus]
enh: Remove 16MB of WRAM at 0x01****** from arm9. Mapped to unused instead. Nobody knows what this was. [zeromus]
enh: Changed instruction execution to 16 at a time blocks (tested and stable) [shash]
Hardware:
bug: Newer and better sqrt and div emulation; makes SM64DS playable [luigi__,shash,zeromus]
bug: Add preliminary RTC implementations [CrazyMax]
enh: Add cosine interpolation in the SPU (conditionally compiled) [zeromus,luigi__]
enh: Experimental: always one silent non-mixing SPU core at 44.1khz synched with emu, for more precision.
The audible core runs with the host, causing music to slow down but not tear or pitch bend. [zeromus]
Graphics:
- Overhaul 3d:
. Move entire GE to core emu.
. Move OpenGL renderer to emu core for optional use by platforms, removing ogl_collector. Now every platform shares the same 3d code.
. Reorganize 3d code to defer rendering to after 3d vblank. Eliminates tearing, and texturing artifacts. [zeromus]
. Add optional fragment shading pipeline (more precision) [luigi__]
. Move lighting model to software instead of using opengl's fixed function model [zeromus]
. Render shadow volumes; toon shading and highlight table [zeromus, luigi__]
. Added texture caching! big speed up. [CrazyMax]
bug: Many assorted tweaks and improvements to 3d and 2d precision [zeromus,CrazyMax,luigi__]
bug: Fixes to GE: command unpacking, projection and pos-vector mode matrix handling, mult and load commands [zeromus]
bug: Fix a bug in texture transformation mode 1 [zeromus]
bug: Fixed GPU rendering bugs in sprites and BG [CrazyMax]
bug: Fixes to texture conversion [CrazyMax,zeromus]
bug: Fixes in capture display (no blinking in many games with dual 3D) [CrazyMax]
bug: Fixes in master brightness (this fixes some games with black screens) [CrazyMax]
bug: Fixes in screen, backdrop, and sprite blending [luigi__]
bug: Changed clear depths and how depth initial values are calculated (fixes SM64DS skybox, Castlevania) [shash,lugi__]
bug: Add 3d layer h-scrolling [zeromus]
bug: Added transparency and fixed material alpha support and alpha testing on the 3D core [shash]
bug: Rewrite VRAM mapping control and rendering (more accurate) [CrazyMax,luigi__]
bug: convert colors to opengl better to prevent alpha=31 polys from being ever so slightly transparent [zeromus]
enh: Add MMU->GPU signal for when vram mappings change to function as a texture cache invalidate signal [zeromus]
enh: Make matrix 4x4 multiply routines use W-coordinate; carry w coord through pipeline [zeromus]
Mac OS X port:
bug: Fixed: Filenames and paths with unicode characters now work. [Jeff]
bug: Fixed: Load state from file button works again. [Jeff]
enh: Save State panel now pauses emulation while the file selection box is open. [Jeff]
bug: Fixed: Frozen video output (and/or messed 3d emulation) after loading a state. [Jeff]
bug: Added option to load the most recent file upon launching the program. [Jeff]
enh: Added French translation (thanks to Pierre Rudloff). [Jeff]
enh: Added basic key mapping configuration to application preferences (thanks to Julio GorgŽ). [Jeff]
enh: Added keyboard shortcuts for Execute, Pause and Reset command (thanks to Julio GorgŽ). [Jeff]
enh: Default key mappings are no longer case sensitive. [Jeff]
enh: Added ability to limit speed. [Jeff]
enh: Fixed: Video output should work on software-only 3D renderers. [Jeff]
Windows port:
bug: Fix a race condition in NDS_3D_Reset and NDS_glInit [zeromus]
bug: Fix the buggy auto frameskip logic which made the emu slow to a crawl. Now it runs fast! [zeromus]
bug: Fix resizing, rotate & aspect ration of main window. [CrazyMax,_zeromus]
bug: Remove multithreading from user interface after finding several synchronization issues [zeromus]
enh: recent roms menu [luigi_]
enh: Changed graphics render core to DirectDraw (work faster) [CrazyMax]
enh: Add an arm9 cpu load average calculator similar to no$. but I dont think it works right. [zeromus]
enh: Rewrite all debug tools (autoupdate works now) [CrazyMax]
enh: Rewrite input core & replace config input dialog [CrazyMax]
enh: Add AVI output [zeromus]
enh: Add pause toggle and frame advance hotkeys [adelikat]
enh: Add frame counter display and hud messages framework [adelikat]
enh: Main window remembers position, size, and a few other emu preferences [adelikat]
enh: Removed directx sdk dependency for easier building. [zeromus]
enh: Savestate doesnt unpause emu if it is already paused [adelikat]
0.7.3 -> 0.8
Cocoa:
- Save State As function now works. [Jeff B]
- Recent Items menu now works. [Jeff B]
- Opening NDS files from Finder now works. [Jeff B]
- Added screenshot feature. [Jeff B]
- Added preferences. [Jeff B]
- Many more strings are translatable now. [Jeff B]
- Default screen color is black (better represents being "off" and easier on eyes at night). [Jeff B]
- Added sound. [Jeff B]
- Now is a universal binary. [Jeff B]
- Leopard resolution icon added. [Jeff B]
- Added a Japanese translation. [Jeff B]
- Added an optional status bar (resize handle no longer overlaps screen). [Jeff B]
- New ROM Info and About DeSmuME windows have been added. [Jeff B]
- Fixed several bugs in window resizing. [Jeff B]
- Added FAT image support for homebrew games (thanks to TypeError). [Jeff B]
- Key config can be changed on the command line. Save/load hotkeys changed (so expose doesn't override). [Jeff B]
- Key bindings may work better on non-US keyboards now (needs testing). [Jeff B]
general:
- Encapsulate GDB debug stub to avoid certain problems [shash]
- Fixed CPU LD*/ST* bugs [shash]
- Fixed New SMB mini-games freeze [shash]
- Fixed possible segfault in ROMReader on ia64 and amd64. [evilynux]
- Fixed a crash bug with 2D background corrupting memory [shash]
- Flag check optimization [carlo_bramini]
- Applied some endian fixes in GPU (thanks to Phazz) [Jeff B]
gtk-glade:
- Added DeSmuME version in about dialog. [evilynux]
- Updated website url in about dialog. [evilynux]
- Added Brazilian Portuguese translation by Dreampeppers99. [evilynux]
- Better desktop menu entry following FreeDesktop specifications. [evilynux]
gtk:
- Updated website url in about dialog. [evilynux]
- Better desktop menu entry following FreeDesktop specifications. [evilynux]
windows port:
- Added an "about" box [shash]
- DirectInput control interface with joystick support [CrazyMax]
- Matrix and Light viewer [Acid Burn]
0.7.2 -> 0.7.3
gtk-glade:
- Full localization using intltool/gettext. [evilynux]
general:
- Added a README.TRANSLATION documenting the localization process. [evilynux]
MacOS X:
- Initial version of the Mac interface added. [Jeff B]
0.7.1 -> 0.7.2
spu:
- big endian fixes. [cyberwarriorx]
gpu:
- big endian fixes. [marcus_c]
gtk-glade:
- opengl improvements. [masscat]
general:
- Added support for setting NDS firmware language value. [masscat]
- Function added for setting firmware language. [masscat]
- Mac/msys compilation fixes. [cyberwarriorx]
- Fix compilation when pkg-config macros are not available [evilynux]
0.7.0 -> 0.7.1
general:
- Added GDB debugger stub [masscat]
- Added new/different GBAMP CFlash image reader/writer [masscat]
gpu:
- Major speedup to the 2D core [shash]
gtk-glade:
- Added command line options. [masscat]
- Added FPS limiter [masscat]
cli:
- Added command line options. [masscat]
- Added FPS limiter [masscat]
- Added option to use OpenGl to render window (allows resizing). [masscat]
windows port:
- Added command line options. [masscat]
- Added multiple language support [cyberwarriorx]
- Added Danish language translation [thomas-2007]
0.6.0 -> 0.7.0
general:
- Added support for *.duc files [cyberwarriorx]
gpu:
- Added support for sprite rotation/scaling [shash]
- Added support for the 3D core (openGL and null plugins) [shash]
windows port:
- A bunch of fixes [Dmitry Krutskih]
- Fixed a bug in sound that was causing it to still not work for some
people [cyberwarriorx]
gtk:
- Added 3D emulation
- Added command line options.
- Added option to use OpenGL to render window (allows resizing).
gtk-glade:
- Added 3D emulation
0.5.0 -> 0.6.0
general:
- Added zipped (based on zziplib) and gzipped (based on zlib) rom support.
arm:
- Added relocation interrupt vector.
- Added region access right checks.
- Enabled LDC/STC instructions.
- Fixed powersave (cp15) IRQ wait.
- Fixed MOV instructions
gpu:
- Added special color effects.
- Added windowing feature.
- Fixed transparent direct color backgrounds.
- Fixed disabled sprites showing.
- Fixed 8/32 bit access to gpu registers.
- Fixed missing backgrounds
- Support for master brightness
wifi:
- Added RF chip interface.
- Added BB chip interface.
windows port:
- Fixed address calculation in disassembler.
- Added Force Maintain Ratio option for window stretching
linux port (cli, gtk and gtk-glade):
all:
- Added joystick support.
- Fixed X and Y buttons.
gtk-glade:
- Added joystick configuration.
- Improved I/O registers viewer tool.
- Added save and load states support.
0.3.3 -> 0.5.0
arm:
- Fixed MSR with immediate value opcode.
- Fixed LSR_0 thumb opcode (C flag is correctly set now).
- Fixed LDR*/STR* opcodes.
- Fixed unaligned memory access on THUMB Core.
- Added relocating SWI routines.
bios:
- Added decompression functions.
- Added GetPitchTable function.
- Added GetVolumeTable function.
- Added GetCRC16 function.
- Added experimental SoundBias function.
- Added GetSineTable function.
cart:
- Added CompactFlash/FAT emulation.
- Added Get ROM chip ID Cartridge command.
gpu:
- Added framebuffer emulation.
- Fixed a bug in GPU (xfin could be greater than LG causing a segfault).
- Added support for Display Mode 0(Display Off).
- Added the basic framework for Display Mode 3(Display from Main RAM).
spu:
- Added sound emulation.
- Added sound core system.
- Added WAV write core.
- Added dummy core.
- Added Direct Sound core.
linux port:
- Added GTK+ GUI.
- Added command line interface.
- Added stylus and arm9 keypad support in CLI version.
- Added FPS display.
- Added basic frameskip.
windows port:
- Fixed a bug when displaying a ROM's information.
- Added key configuration.
- Removed the debug key.
- Added new experimental auto frameskip/frame limit code.
- Added sound settings dialog.
- Added a few menu options for accessing the website, forums, and for
submitting bugs.
general:
- Rewrote code in C.
- Fixed warnings.
- Used defines and typedef's to make things more portable and easier to
read.
- Added autotools stuff.
- Changes to logging system.
- Added screenshot function.
- Translated most french to english.
- Added savestate support.
- Added firmware reading support(needs work).
- Added Backup Memory support with autodetection.
- Fixed some endianess issues.
- Fixed things so Visual C++ can compile code.
- Added bsd support.
- Reworked ROM loading so you can load a different rom without any problems.
- Finished NDS_Reset. Now the emulation can be reset even while running.

View File

@ -1,97 +0,0 @@
DeSmuME
_________________________________________
Copyright (C) 2006 yopyop
Copyright (C) 2006-2015 DeSmuME team
Last Updated: March 28, 2015
Contents:
1) About ................................................................... 14
2) Credits ................................................................. 59
3) Contact Information ..................................................... 72
4) License ................................................................. 82
1) About ______________________________________________________________________
DeSmuME is software that allows you to emulate a Nintendo DS system. Think of
it as a Swiss-Army knife for Nintendo DS emulation, giving you access to many
powerful tools for testing DS features, from viewing ROM properties to managing
Action Replay cheats. And best of all, this software is completely free and
open-source.
For information on how to install or operate DeSmuME for your operating system,
please see the README file that should be present with your installation.
Port-specific README files:
* README.LIN for the Linux port
* README.WIN for the Windows port
* README.MAC for the Macintosh port
Note that each DeSmuME port may have a different feature set from another port.
You may see more feature parity between ports over time as we continue
developing DeSmuME.
You can find our documentation on our online Wiki page. The major pages of
interest are:
* Official Documentation: http://wiki.desmume.org/index.php?title=Main_Page
This is the main Wiki page that contains all of our official documentation.
* Manuals: http://wiki.desmume.org/index.php?title=Manual
The manuals contain detailed information about how to operate DeSmuME for each
port.
* FAQ: http://wiki.desmume.org/index.php?title=Faq
The Frequently Asked Questions (FAQ) page has a lot of useful general
information about DeSmuME. Do note that some of the information may be platform
specific, and may not directly apply to your version of DeSmuME.
* Build Instructions:
http://wiki.desmume.org/index.php?title=Installing_DeSmuME_from_source
This page contains detailed port-specific instructions about how to make your
own build of DeSmuME directly from the source code.
2) Credits ____________________________________________________________________
See the AUTHORS file for list of DeSmuME team members.
Special thanks go to:
* yopyop (original author of DeSmuME),
for releasing the source code of this great emulator.
* Martin Korth (author of GBATEK),
for his well-written Gameboy Advance and Nintendo DS documentation.
3) Contact Information ________________________________________________________
Official Website: http://desmume.org
Public Forum: http://forums.desmume.org
Developer Chat: irc://irc.freenode.net/desmume
Bug Reports: http://sourceforge.net/p/desmume/bugs
Please don't ask for ROMs, BIOS files, or any other copyrighted stuff.
4) License ____________________________________________________________________
This file is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 2 of the License, or (at your option) any later
version.
This file is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this software. If not, see <http://www.gnu.org/licenses/>.
* See the GNU General Public License details in COPYING.

View File

@ -1,65 +0,0 @@
DeSmuME
DeSmuME is written in C++ using the GTK+ and SDL libraries.
* http://www.gtk.org
* http://www.libsdl.org/
DeSmuME provides another interface based on libglade, to use
, you'll need glade:
* http://glade.gnome.org/
To build, first cd to src/frontend/posix and then run `./autogen.sh`
This will create the file `configure`.
It does this using the packages `autoconf` and `automake`.
It also requires `libglib2.0-dev` to generate correctly.
(`glib` from the AUR if building on Arch)
Run this using `./configure`
Then build the program by running `make`
It will generate three programs:
1) "desmume" in the "gtk" directory;
2) "desmume-cli" in the "cli" directory.
If glade is installed on your system, you'll get a third
binary:
3) "desmume-glade" in the "gtk-glade" directory.
You can even type "make install" to install those programs on
your system (in /usr/local/ by default); then uninstalling is
done by typing "make uninstall".
For more information on the available commandline options,
check the other README files which will be more up to date.
The following options specially are available on these posix ports:
--disable-limiter Disables the 60 fps limiter
--soft-convert Use software colour conversion during OpenGL
screen rendering. May produce better or worse
frame rates depending on hardware.
The following options specially are available on the Gtk+ port:
--opengl-2d Enables using OpenGL for screen rendering
--disable-sound Disables the sound emulation
--disable-3d Disables the 3D emulation
The following options specially are available on the CLI port:
--opengl-2d Enables using OpenGL for screen rendering
--disable-sound Disables the sound emulation
NOTE:
The Gtk+ and Glade builds use gtkGLext to handle the OpenGL
rendering and contexts. You may get improved performance by
also passing the argument --gdk-gl-force-indirect. This has
been seen to improve things for Nvidia based graphics cards
under Linux.
Visit us on the web at http://www.desmume.org

View File

@ -1,348 +0,0 @@
DeSmuME
_________________________________________
Copyright (C) 2006 yopyop
Copyright (C) 2006-2015 DeSmuME team
Last Updated: March 28, 2015
Contents:
1) System Requirements ..................................................... 15
2) Quick Start Guide for Using DeSmuME for OS X ............................ 36
3) Additional Documentation ............................................... 201
4) Contact Information .................................................... 231
5) License ................................................................ 333
1) System Requirements ________________________________________________________
DeSmuME is a very demanding app, especially for CPU usage. Before you begin,
make sure that your Mac meets the listed system requirements.
If your Mac meets only the minimum requirements, then you should expect to run
most simple 2D-only games with some frameskip, but you will be unable to run
complex 2D games or any 3D-heavy games. However, if your Mac meets the
recommended requirements, then you should expect to run almost every game,
including very complex 3D-heavy games, with minimal to no frameskip.
Operating System: OS X v10.5 (Leopard) or later
CPU: Can run on any PowerPC G4, G5, or Intel processor
2.1 GHz Intel Core 2 Duo (minimum)
3.0 GHz Intel Core 2 Duo or faster (recommended)
RAM: 512 MB (minimum)
2 GB (recommended)
2) Quick Start Guide for Using DeSmuME for OS X _______________________________
Installing DeSmuME is as easy as copying DeSmuME.app to your Applications
folder (or other folder of your choice). Double-click the app to start DeSmuME.
Note that DeSmuME for OS X may have a different feature set than DeSmuME for
Windows and DeSmuME for Linux. As of this writing, some features that are
present in DeSmuME for Windows are not present in DeSmuME for OS X.
The rest of this section will be a guide to help you quickly get started using
DeSmuME for OS X.
Loading a ROM and Starting the Emulator:
Simply double-click the desired ROM from the Finder to play the game. By
default, DeSmuME will load the ROM and start emulation. Also, there are
additional ROM loading options that you can change in DeSmuME > Preferences if
you need them.
Using the NDS Controller:
Each NDS controller button can be mapped to a button of your choice on your
keyboard, gamepad, or joystick. You can view the mappings by clicking on Input
in DeSmuME > Preferences. To change a mapping, click on the NDS control that you
want to change, then press the button on your input device to map it.
By default, the NDS controller is mapped to the following keys on your keyboard:
Up - Up Arrow
Down - Down Arrow
Left - Left Arrow
Right - Right Arrow
A Button - X
B Button - Z
X Button - S
Y Button - A
L Trigger - Q
R Trigger - W
Start - Return
Select - Tab
Lid - Delete (Backspace)
Microphone (Internal Noise Samples) - ` (Accent)
The NDS can support a variety of SLOT-2 devices. Some devices, such as the
Guitar Grip, EasyPiano, and Taito Paddle have inputs, which are mapped to your
keyboard using these defaults:
Guitar Grip:
Green - E
Red - R
Yellow - T
Blue - Y
EasyPiano:
C - C
C# - F
D - V
D# - G
E - B
F - N
F# - J
G - M
G# - K
A - , (Comma)
A# - L
B - . (Period)
High C - / (Forward Slash)
Paddle:
Paddle Adjust -5 - O
Paddle Adjust +5 - P
In addition, the following emulator functions are mapped to your keyboard by
default:
Execute/Pause - Forward Delete
Reset - Page Down
Rotate Display Left - [ (Left Bracket)
Rotate Display Right - ] (Right Bracket)
Set Speed to Half - - (Dash)
Set Speed to Double - = (Equal)
Using the NDS Touch Pad:
Touch pad input is emulated using the left mouse button by default. Simply
click in the touch pad area of the NDS display window to use the NDS touch pad.
Using the NDS Microphone:
Some games make use of the NDS microphone. DeSmuME emulates the NDS microphone
by using the default input device selected in your System Preferences. You can
choose Emulation > Show Microphone Settings to view the input device that
DeSmuME is currently using, as well as setting its gain.
DeSmuME will track the input level on the meter as the NDS reads the
microphone. The meter reflects the input level as seen by the NDS. Note that
some games ignore the microphone, and therefore will not register on the meter.
If you need to view the input level from the host machine's perspective, you
can view the host's input level in your System Preferences.
Finally, you can generate audio samples in software by using one of DeSmuME's
audio generators, and send those audio samples to the NDS. This is what the
Microphone command in your Input Preferences does. As long as the Microphone
command is engaged, the host input device will be ignored. When you disengage
the Microphone command, DeSmuME will automatically return to reading the host
input device.
The microphone icon serves to indicate the current status of the NDS
microphone, and will change color for each status:
Black - The microphone is inactive.
Dark Green - The microphone is active. However, the input level is too
low to be meaningful, or the game is ignoring the microphone.
Bright Green - The microphone is active and the game is reading a
meaningful input level.
Bright Red - The microphone is active and the game is reading a clipped
input level. Depending on the situation, this may or may not
be desirable. Use the gain slider to influence the input
level if needed.
Gray - The host input device is being temporarily ignored because a
Microphone command is currently engaged.
Rotating the NDS Display:
Some games require that the NDS display be at a certain rotation in order to
look correct. Rotation options can be found by choosing
View > Display Rotation. You can also use the toolbar buttons Rotate Left and
Rotate Right to rotate the display by 90 degrees counterclockwise or clockwise,
respectively. Finally, you can assign inputs to Rotate Left and Rotate Right in
your Input Preferences.
Freezing and Restoring the Emulation State:
Save states are a powerful feature that allows you to freeze the emulation
state and restore it later. However, note that save states are only a
temporary means of saving -- more permanent saves must be done using the
in-game save (or ROM save).
- To freeze the emulation state, choose File > Save State File.
- To restore the emulation state, choose File > Open State File.
You can also freeze/restore emulation states without having to manage the
Open/Save dialogs. There are ten available save state "slots" that you can
use to quickly freeze/restore the emulation state.
- To quick freeze the emulation state, choose File > Save State Slot > Slot #.
The default hotkey for this is (Shift-#).
- To quick restore the emulation state, choose File > Load State Slot > Slot #.
The default hotkey for this is (#).
Improving Emulation Performance:
There are many settings you can change in order to improve DeSmuME's emulation
performance. All of the settings listed below affect performance the most. Use
the settings as shown for the best possible performance. All of these settings
may be found in DeSmuME > Preferences.
- WARNING: Changing any Emulation setting may cause emulation glitches in
certain ROMs. Do not change these settings unless you are willing to
accept reduced ROM compatibility.
Display:
Video Output:
Use Vertical Sync - Off
Video Filter - None
3D Rendering:
3D Rendering Engine - SoftRasterizer
Rendering Threads - Automatic
Emulation:
Advanced Bus Level Timing - Off (May cause glitches)
Rigourous 3D Rendering Timing - On (May cause graphical glitches)
3D Rendering Engine - Dynamic Recompiler (May reduce ROM compatibility)
Dynamic Recompiler Block Size - 100 (May cause glitches)
Use External BIOS Images - Off (May reduce ROM compatibility)
3) Additional Documentation ___________________________________________________
The quick start guide in this Read Me is by no means a complete reference to
everything that DeSmuME can do! If you need any additional information about
DeSmuME, then you can reference our online Wiki pages for up-to-date
information.
* Official Documentation: http://wiki.desmume.org/index.php?title=Main_Page
This is the main Wiki page that contains all of our official documentation.
* FAQ: http://wiki.desmume.org/index.php?title=Faq
The Frequently Asked Questions (FAQ) page has a lot of useful general
information about DeSmuME. Do note that some of the information may be platform
specific, and may not directly apply to the OS X version of DeSmuME.
* DeSmuME Manual for OS X:
http://wiki.desmume.org/index.php?title=DeSmuME_Manual_for_the_Macintosh_port
This page contains complete and detailed information about how to operate
DeSmuME for OS X.
* DeSmuME Build Instructions for OS X:
http://wiki.desmume.org/index.php?title=Installing_DeSmuME_from_source_on_OS_X
This page contains complete and detailed instructions about how to make your
own build of DeSmuME for OS X directly from the source code.
4) Contact Information ________________________________________________________
Thank you for you interest in DeSmuME! If you want to tell us how useful
DeSmuME is in your life, your love (or hate) of certain NDS games, your passion
for NDS homebrew development, or anything else related to DeSmuME or NDS
emulation, then there are various ways for you to contact us!
However, keep in mind that there are a few of rules that you need to follow:
- Do not ask us to provide ROMs, BIOS files, or any other copyrighted stuff.
We don't want to have to deal with any legal issues that could get us in
trouble, or worse, completely shut down.
- When contacting us, please use the appropriate means to do it. For example,
if you simply want to tell us how much you love or hate us, then use the
comments on the official webpage. Another example: If you want to post on the
forum, be sure to keep the topic focused on DeSmuME; questions that ask for
things like us providing you the latest Pokemon cheats are not DeSmuME
related, and we will instead refer you to a Pokemon cheaters forum. Finally,
our developer chat channel is intended for furthering the development work of
DeSmuME; questions about how to use DeSmuME should not come here, but instead
go to the Support forum. In short, use the appropriate contact method. That's
why the different methods exist!
* Official Website: http://desmume.org
Our official website has the latest news on DeSmuME releases, and also has a
lot of other useful information about DeSmuME. You can comment on different
posts telling us how you feel about DeSmuME. Is DeSmuME the best thing in your
life? Is it making you cry? Or is it a bunch of blah? Let us know here!
* Public Forum: http://forums.desmume.org
If you have a question about DeSmuME, then this is the place to ask it. But
before you ask it, be aware that your question may have already been answered
before, so try the following things first:
- Read the manual and the FAQ. A lot of questions people have are usually
already answered in our documentation.
- Do a forum search about your question.
If you still need to ask a question, choose Help > Submit a Support Request in
the DeSmuME application. Follow the onscreen instructions on the Support
Request Form.
* Live Developer Chat Channel: irc://irc.freenode.net/desmume
We have a live developer chatline on Freenode IRC at #desmume. This channel
is meant for discussing the development of DeSmuME, and shows the real work
that goes on behind the scenes. If you are interested in doing any sort of
software programming, software testing, documentation, or graphics work, then
please join our chat channel! We would love for you to join us!
* Bug Reports:
If you believe that you have found a bug, you may submit a bug report by
choosing Help > Submit a Bug Report in the DeSmuME application. Follow the
onscreen instructions on the Bug Report Form.
When you click Go To Bug Report Webpage, you will be taken to our bug tracker
on SourceForge. Do note that you will need a SourceForge account in order to
submit a bug report.
Bug submissions are very welcome and encouraged. However, when you submit a bug
to us, you MUST provide the following information, or else your bug submission
may be rejected:
- DeSmuME app version
- Your operating system and OS version
- Your Mac model identifier
- The name of the running ROM when the bug was observed (or "None", if no ROM
was running)
- The serial code of the running ROM when the bug was observed (or "None", if
no ROM was running)
- A description of the exact behavior you observed
- A description of the behavior you expected
All of this information will be prepared for you if you use the Bug Report Form
from Help > Submit a Bug Report.
When you write your description, make sure that they are as detailed as
possible. The better your descriptions are, the faster we can test and fix
bugs. For example, if you observed a bug in the game Golden Sun: Dark Dawn, then
the bug report could look something like this:
App Version: v0.9.11
Operating System: OS X v10.10.2 (14C1510)
Mac Model Identifier: iMac11,2
ROM Name: GOLDENSUN_DD
ROM Serial: NTR-BO5E-USA
Observed Behavior: I tried to load a save state using the
File > Load State > Slot 3 menu option, but the game froze. If I reset, I
can get the game working again.
Expected Behavior: The game should continue running from the point where I
made the save state.
We will try to get your bug tested as soon as possible, but any fixes may take
longer, depending on the complexity of the bug. Also, some bugs may require us
to ask you for certain files, such as your ROM saves, save states, or console
logs. For the above example, we would probably ask you for your save states to
help us track down the bug.
5) License ____________________________________________________________________
This file is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 2 of the License, or (at your option) any later
version.
This file is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this software. If not, see <http://www.gnu.org/licenses/>.
* See the GNU General Public License details in COPYING.

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +0,0 @@
DSM is ascii plain text. It is derived from the FCEUX FM2 format.
It consists of several key-value pairs followed by an inputlog section.
The inputlog section can be identified by its starting with a | (pipe).
The inputlog section terminates at eof.
Newlines may be \r\n or \n
Key-value pairs consist of a key identifier, followed by a space separator, followed by the value text.
Value text is always terminated by a newline, which the value text will not include.
The value text is parsed differently depending on the type of the key.
The key-value pairs may be in any order, except that the first key must be version.
Integer keys (also used for booleans, with a 1 or 0) will have a value that is a simple integer not to exceed 32bits
- version (required) - the version of the movie file format; for now it is always 3
- emuVersion (required) - the version of the emulator used to produce the movie
- rerecordCount (optional) - the rerecord count
- romChecksum (optional) - the CRC32 of the rom used to make the movie. should match values specified on advanscene.com
- romSerial (optional) - a concatenation of other uniquely identifying information about the rom (name,gamecode,makercode)
- useExtBios (optional) - were bios files was used? defaults to false.
- swiFromBios (optional) - were swi emulated by ExtBios? (alternative is internal HLE bios). defaults to false.
The rom identification information may be used at a later point to warn about mismatches between movies and roms, but is not right now.
String keys have values that consist of the remainder of the key-value pair line. As a consequence, string values cannot contain newlines.
- romFilename (required) - the name of the file used to record the movie
- comment (optional) - simply a memo.
by convention, the first token in the comment value is the subject of the comment.
by convention, subsequent comments with the same subject will have their ordering preserved and may be used to approximate multiline comments.
by convention, the author of the movie should be stored in comment(s) with a subject of: author
Hex string keys (used for binary blobs) will have a value that is like 0x0123456789ABCDEF...
- romChecksum (required) - this is currently unused.
GUID keys have a value which is in the standard guid format: 452DE2C3-EF43-2FA9-77AC-0677FC51543B
- guid (required) a unique identifier for a movie, generated when the movie is created, which is used when loading a savestate to make sure it belongs to the current movie.
The inputlog section consists of lines beginning and ending with a | (pipe).
The fields are as follows, except as noted in note C.
|c|.............XXX YYY Z|
'R','L','D','U','T','S','B','A','Y','X','W','E','G'
field c is a variable length decimal integer which is a bitfield corresponding to miscellaneous input states which are valid at the start of the frame.
Therefore, no miscellaneous commands is represented by a value of 0.
Here are the currently defined bit values:
0x01 - Microphone Noise (hardcoded noise sample; to be held through duration of frame)
0x02 - Reset
0x04 - Lid
the format of the main section is as follows:
the field begins with 13 characters which constitute a bitfield.
any character other than ' ' or '.' means that the button was pressed.
by convention, the following mnemonics will be used in a column to remind us of which button corresponds to which column:
RLDUTSBAYXWEG (Right,Left,Down,Up,sTart,Select,B,A,Y,X,lshoulder,rshoulder,debuG)
This ordering is based on FCEUX to a certain extent, and arbitrary after that.
W and E were chosen for shoulders to suggest West and East for Left and Right.
While the emulator supports a 'lid' button, and to some extent a 'blow' button, these are not supported in the movies.
XXX: %03d, the x position of the stylus (0,0 topleft, 255,191 bottomright)
YYY: %03d, the y position of the stylus
Z: %1d, 1 if the stylus is pressed pressed; 0 if not
Additional fields after this main section may be added later without breaking the file format.
* Notes *
A. There is no key-value pair that indicates the length of the movie. This must be read by scanning the inputlog and counting the number of lines.
B. All movies start from power-on.
C. The emulator uses these framerate constants
arm7_cycles_per_frame = 560190
frames_per_second = 59.8261

View File

@ -1,39 +0,0 @@
The desmume save file format is merely a raw save file with a FOOTER.
This was chosen in order to maximize compatibility with other emulators,
which tend load the savefile as-is and let the game read out of whatever range
it is expecting. To assist with this, before writing the save file, desmume
will pad the raw save file out to the next highest known length. Note that this
may sometimes be incorrect if the savefile hasnt been written through to the end
during initialization. This could cause other emulators to fail to recognize the
save file.
Additionally, the footer makes it easier to analyze save files, because the
game's data will be at the correct addresses starting at offset 0x0000.
The footer format can be identified by locating the 16Byte ascii string
"|-DESMUME SAVE-|"
at the end of the file. This corresponds with the following save structure:
struct Footer {
u32 actually_written_size;
u32 padded_size;
u32 save_type; //(not currently used)
u32 address_size; //address bus size
u32 save_size; //size parameter of the save type (not currently used)
u32 version_number; //should be 0
char cookie[16];
};
note that padded_size should be where you see the end of the raw save data
and the beginning of desmume-specific information, including some junk before
the actual footer.
actually_written_size is the highest address (plus one) written to by the game.
The new desmume savefile system tries to make as few decisions as possible,
which is the reason for the behavior of actually_written_size and the disuse
of save_type and save_size. If few decisions are made, then few mistakes can
be made. That is the idea, anyway. We'll make decisions later if we need to.
save_type and save_size are reserved in case we do.

View File

@ -1,4 +0,0 @@
root = true
[*]
indent_style = tab

View File

@ -1,392 +0,0 @@
/*
Copyright (C) 2008-2016 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "types.h"
#include "Database.h"
#include "retro_miscellaneous.h"
//------------------------------------------------------------
//large databases are first. scroll down to ENDLARGE to find the code
struct MAKER
{
u16 code;
const char* name;
};
static const char regions_index[] = "JPFSEODIRKHXVWUC";
static const char *regions[] = {
"JPN", // J
"EUR", // P
"FRA", // F
"ESP", // S
"USA", // E
"INT", // O
"NOE", // D
"ITA", // I
"RUS", // R
"KOR", // K
"HOL", // H
"EUU", // X
"EUU", // V
"EUU", // W
"AUS", // U
"CHN", // C
};
static MAKER makerCodes[] = {
{ 0x3130, "Nintendo" },
{ 0x3230, "Rocket Games, Ajinomoto" },
{ 0x3330, "Imagineer-Zoom" },
{ 0x3430, "Gray Matter?" },
{ 0x3530, "Zamuse" },
{ 0x3630, "Falcom" },
{ 0x3730, "Enix?" },
{ 0x3830, "Capcom" },
{ 0x3930, "Hot B Co." },
{ 0x4130, "Jaleco" },
{ 0x4230, "Coconuts Japan" },
{ 0x4330, "Coconuts Japan/G.X.Media" },
{ 0x4430, "Micronet?" },
{ 0x4530, "Technos" },
{ 0x4630, "Mebio Software" },
{ 0x4730, "Shouei System" },
{ 0x4830, "Starfish" },
{ 0x4A30, "Mitsui Fudosan/Dentsu" },
{ 0x4C30, "Warashi Inc." },
{ 0x4E30, "Nowpro" },
{ 0x5030, "Game Village" },
{ 0x3031, "?????????????" },
{ 0x3231, "Infocom" },
{ 0x3331, "Electronic Arts Japan" },
{ 0x3531, "Cobra Team" },
{ 0x3631, "Human/Field" },
{ 0x3731, "KOEI" },
{ 0x3831, "Hudson Soft" },
{ 0x3931, "S.C.P." },
{ 0x4131, "Yanoman" },
{ 0x4331, "Tecmo Products" },
{ 0x4431, "Japan Glary Business" },
{ 0x4531, "Forum/OpenSystem" },
{ 0x4631, "Virgin Games" },
{ 0x4731, "SMDE" },
{ 0x4A31, "Daikokudenki" },
{ 0x5031, "Creatures Inc." },
{ 0x5131, "TDK Deep Impresion" },
{ 0x3032, "Destination Software, KSS" },
{ 0x3132, "Sunsoft/Tokai Engineering??" },
{ 0x3232, "POW, VR 1 Japan??" },
{ 0x3332, "Micro World" },
{ 0x3532, "San-X" },
{ 0x3632, "Enix" },
{ 0x3732, "Loriciel/Electro Brain" },
{ 0x3832, "Kemco Japan" },
{ 0x3932, "Seta" },
{ 0x4132, "Culture Brain" },
{ 0x4332, "Palsoft" },
{ 0x4432, "Visit Co.,Ltd." },
{ 0x4532, "Intec" },
{ 0x4632, "System Sacom" },
{ 0x4732, "Poppo" },
{ 0x4832, "Ubisoft Japan" },
{ 0x4A32, "Media Works" },
{ 0x4B32, "NEC InterChannel" },
{ 0x4C32, "Tam" },
{ 0x4D32, "Jordan" },
{ 0x4E32, "Smilesoft ???, Rocket ???" },
{ 0x5132, "Mediakite" },
{ 0x3033, "Viacom" },
{ 0x3133, "Carrozzeria" },
{ 0x3233, "Dynamic" },
{ 0x3433, "Magifact" },
{ 0x3533, "Hect" },
{ 0x3633, "Codemasters" },
{ 0x3733, "Taito/GAGA Communications" },
{ 0x3833, "Laguna" },
{ 0x3933, "Telstar Fun & Games, Event/Taito" },
{ 0x4233, "Arcade Zone Ltd" },
{ 0x4333, "Entertainment International/Empire Software?" },
{ 0x4433, "Loriciel" },
{ 0x4533, "Gremlin Graphics" },
{ 0x4633, "K.Amusement Leasing Co." },
{ 0x3034, "Seika Corp." },
{ 0x3134, "Ubi Soft Entertainment" },
{ 0x3234, "Sunsoft US?" },
{ 0x3434, "Life Fitness" },
{ 0x3634, "System 3" },
{ 0x3734, "Spectrum Holobyte" },
{ 0x3934, "IREM" },
{ 0x4234, "Raya Systems" },
{ 0x4334, "Renovation Products" },
{ 0x4434, "Malibu Games" },
{ 0x4634, "Eidos (was U.S. Gold <=1995)" },
{ 0x4734, "Playmates Interactive?" },
{ 0x4A34, "Fox Interactive" },
{ 0x4B34, "Time Warner Interactive" },
{ 0x5134, "Disney Interactive" },
{ 0x5334, "Black Pearl" },
{ 0x5534, "Advanced Productions" },
{ 0x5834, "GT Interactive" },
{ 0x5934, "RARE?" },
{ 0x5A34, "Crave Entertainment" },
{ 0x3035, "Absolute Entertainment" },
{ 0x3135, "Acclaim" },
{ 0x3235, "Activision" },
{ 0x3335, "American Sammy" },
{ 0x3435, "Take 2 Interactive (before it was GameTek)" },
{ 0x3535, "Hi Tech" },
{ 0x3635, "LJN LTD." },
{ 0x3835, "Mattel" },
{ 0x4135, "Mindscape, Red Orb Entertainment?" },
{ 0x4235, "Romstar" },
{ 0x4335, "Taxan" },
{ 0x4435, "Midway (before it was Tradewest)" },
{ 0x4635, "American Softworks" },
{ 0x4735, "Majesco Sales Inc" },
{ 0x4835, "3DO" },
{ 0x4B35, "Hasbro" },
{ 0x4C35, "NewKidCo" },
{ 0x4D35, "Telegames" },
{ 0x4E35, "Metro3D" },
{ 0x5035, "Vatical Entertainment" },
{ 0x5135, "LEGO Media" },
{ 0x5335, "Xicat Interactive" },
{ 0x5435, "Cryo Interactive" },
{ 0x5735, "Red Storm Entertainment" },
{ 0x5835, "Microids" },
{ 0x5A35, "Conspiracy/Swing" },
{ 0x3036, "Titus" },
{ 0x3136, "Virgin Interactive" },
{ 0x3236, "Maxis" },
{ 0x3436, "LucasArts Entertainment" },
{ 0x3736, "Ocean" },
{ 0x3936, "Electronic Arts" },
{ 0x4236, "Laser Beam" },
{ 0x4536, "Elite Systems" },
{ 0x4636, "Electro Brain" },
{ 0x4736, "The Learning Company" },
{ 0x4836, "BBC" },
{ 0x4A36, "Software 2000" },
{ 0x4C36, "BAM! Entertainment" },
{ 0x4D36, "Studio 3" },
{ 0x5136, "Classified Games" },
{ 0x5336, "TDK Mediactive" },
{ 0x5536, "DreamCatcher" },
{ 0x5636, "JoWood Produtions" },
{ 0x5736, "SEGA" },
{ 0x5836, "Wannado Edition" },
{ 0x5936, "LSP" },
{ 0x5A36, "ITE Media" },
{ 0x3037, "Infogrames" },
{ 0x3137, "Interplay" },
{ 0x3237, "JVC" },
{ 0x3337, "Parker Brothers" },
{ 0x3537, "Sales Curve" },
{ 0x3837, "THQ" },
{ 0x3937, "Accolade" },
{ 0x4137, "Triffix Entertainment" },
{ 0x4337, "Microprose Software" },
{ 0x4437, "Universal Interactive, Sierra, Simon & Schuster?" },
{ 0x4637, "Kemco" },
{ 0x4737, "Rage Software" },
{ 0x4837, "Encore" },
{ 0x4A37, "Zoo" },
{ 0x4B37, "BVM" },
{ 0x4C37, "Simon & Schuster Interactive" },
{ 0x4D37, "Asmik Ace Entertainment Inc./AIA" },
{ 0x4E37, "Empire Interactive?" },
{ 0x5137, "Jester Interactive" },
{ 0x5437, "Scholastic" },
{ 0x5537, "Ignition Entertainment" },
{ 0x5737, "Stadlbauer" },
{ 0x3038, "Misawa" },
{ 0x3138, "Teichiku" },
{ 0x3238, "Namco Ltd." },
{ 0x3338, "LOZC" },
{ 0x3438, "KOEI" },
{ 0x3638, "Tokuma Shoten Intermedia" },
{ 0x3738, "Tsukuda Original" },
{ 0x3838, "DATAM-Polystar" },
{ 0x4238, "Bulletproof Software" },
{ 0x4338, "Vic Tokai Inc." },
{ 0x4538, "Character Soft" },
{ 0x4638, "I'Max" },
{ 0x4738, "Saurus" },
{ 0x4A38, "General Entertainment" },
{ 0x4E38, "Success" },
{ 0x5038, "SEGA Japan" },
{ 0x3039, "Takara Amusement" },
{ 0x3139, "Chun Soft" },
{ 0x3239, "Video System, McO'River???" },
{ 0x3339, "BEC" },
{ 0x3539, "Varie" },
{ 0x3639, "Yonezawa/S'pal" },
{ 0x3739, "Kaneko" },
{ 0x3939, "Victor Interactive Software, Pack in Video" },
{ 0x4139, "Nichibutsu/Nihon Bussan" },
{ 0x4239, "Tecmo" },
{ 0x4339, "Imagineer" },
{ 0x4639, "Nova" },
{ 0x4739, "Den'Z" },
{ 0x4839, "Bottom Up" },
{ 0x4A39, "TGL" },
{ 0x4C39, "Hasbro Japan?" },
{ 0x4E39, "Marvelous Entertainment" },
{ 0x5039, "Keynet Inc." },
{ 0x5139, "Hands-On Entertainment" },
{ 0x3041, "Telenet" },
{ 0x3141, "Hori" },
{ 0x3441, "Konami" },
{ 0x3541, "K.Amusement Leasing Co." },
{ 0x3641, "Kawada" },
{ 0x3741, "Takara" },
{ 0x3941, "Technos Japan Corp." },
{ 0x4141, "JVC, Victor Musical Indutries" },
{ 0x4341, "Toei Animation" },
{ 0x4441, "Toho" },
{ 0x4641, "Namco" },
{ 0x4741, "Media Rings Corporation" },
{ 0x4841, "J-Wing" },
{ 0x4A41, "Pioneer LDC" },
{ 0x4B41, "KID" },
{ 0x4C41, "Mediafactory" },
{ 0x5041, "Infogrames Hudson" },
{ 0x5141, "Kiratto. Ludic Inc" },
{ 0x3042, "Acclaim Japan" },
{ 0x3142, "ASCII (was Nexoft?)" },
{ 0x3242, "Bandai" },
{ 0x3442, "Enix" },
{ 0x3642, "HAL Laboratory" },
{ 0x3742, "SNK" },
{ 0x3942, "Pony Canyon" },
{ 0x4142, "Culture Brain" },
{ 0x4242, "Sunsoft" },
{ 0x4342, "Toshiba EMI" },
{ 0x4442, "Sony Imagesoft" },
{ 0x4642, "Sammy" },
{ 0x4742, "Magical" },
{ 0x4842, "Visco" },
{ 0x4A42, "Compile " },
{ 0x4C42, "MTO Inc." },
{ 0x4E42, "Sunrise Interactive" },
{ 0x5042, "Global A Entertainment" },
{ 0x5142, "Fuuki" },
{ 0x3043, "Taito" },
{ 0x3243, "Kemco" },
{ 0x3343, "Square" },
{ 0x3443, "Tokuma Shoten" },
{ 0x3543, "Data East" },
{ 0x3643, "Tonkin House (was Tokyo Shoseki)" },
{ 0x3843, "Koei" },
{ 0x4143, "Konami/Ultra/Palcom" },
{ 0x4243, "NTVIC/VAP" },
{ 0x4343, "Use Co.,Ltd." },
{ 0x4443, "Meldac" },
{ 0x4543, "Pony Canyon" },
{ 0x4643, "Angel, Sotsu Agency/Sunrise" },
{ 0x4A43, "Boss" },
{ 0x4743, "Yumedia/Aroma Co., Ltd" },
{ 0x4B43, "Axela/Crea-Tech?" },
{ 0x4C43, "Sekaibunka-Sha, Sumire kobo?, Marigul Management Inc.?" },
{ 0x4D43, "Konami Computer Entertainment Osaka" },
{ 0x5043, "Enterbrain" },
{ 0x3044, "Taito/Disco" },
{ 0x3144, "Sofel" },
{ 0x3244, "Quest, Bothtec" },
{ 0x3344, "Sigma, ?????" },
{ 0x3444, "Ask Kodansha" },
{ 0x3644, "Naxat" },
{ 0x3744, "Copya System" },
{ 0x3844, "Capcom Co., Ltd." },
{ 0x3944, "Banpresto" },
{ 0x4144, "TOMY" },
{ 0x4244, "LJN Japan" },
{ 0x4444, "NCS" },
{ 0x4544, "Human Entertainment" },
{ 0x4644, "Altron" },
{ 0x4744, "Jaleco???" },
{ 0x4844, "Gaps Inc." },
{ 0x4C44, "????" },
{ 0x4E44, "Elf" },
{ 0x3045, "Jaleco" },
{ 0x3145, "????" },
{ 0x3245, "Yutaka" },
{ 0x3345, "Varie" },
{ 0x3445, "T&ESoft" },
{ 0x3545, "Epoch" },
{ 0x3745, "Athena" },
{ 0x3845, "Asmik" },
{ 0x3945, "Natsume" },
{ 0x4145, "King Records" },
{ 0x4245, "Atlus" },
{ 0x4345, "Epic/Sony Records" },
{ 0x4545, "IGS" },
{ 0x4745, "Chatnoir" },
{ 0x4845, "Right Stuff" },
{ 0x4C45, "Spike" },
{ 0x4D45, "Konami Computer Entertainment Tokyo" },
{ 0x4E45, "Alphadream Corporation" },
{ 0x3046, "A Wave" },
{ 0x3146, "Motown Software" },
{ 0x3246, "Left Field Entertainment" },
{ 0x3346, "Extreme Ent. Grp." },
{ 0x3446, "TecMagik" },
{ 0x3946, "Cybersoft" },
{ 0x4246, "Psygnosis" },
{ 0x4546, "Davidson/Western Tech." },
{ 0x3147, "PCCW Japan" },
{ 0x3447, "KiKi Co Ltd" },
{ 0x3547, "Open Sesame Inc???" },
{ 0x3647, "Sims" },
{ 0x3747, "Broccoli" },
{ 0x3847, "Avex" },
{ 0x3947, "D3 Publisher" },
{ 0x4247, "Konami Computer Entertainment Japan" },
{ 0x4447, "Square-Enix" },
{ 0x4849, "Yojigen" },
};
//------------------------------------------------------------
//ENDLARGE
//------------------------------------------------------------
namespace Database
{
const char* RegionXXXForCode(char code, bool unknownAsString)
{
size_t regions_num = ARRAY_SIZE(regions);
const char* found = strchr(regions_index,code);
if(found) return regions[found-regions_index];
else return unknownAsString ? "???" : NULL;
}
const char *MakerNameForMakerCode(u16 id, bool unknownAsString)
{
//too bad these aren't sorted
for (int i = 0; i < ARRAY_SIZE(makerCodes); i++)
{
if (makerCodes[i].code == id)
return makerCodes[i].name;
}
return unknownAsString ? "Unknown" : NULL;
}
}

View File

@ -1,10 +0,0 @@
#ifndef DESMUME_DATABASE_H_
#define DESMUME_DATABASE_H_
namespace Database
{
const char* RegionXXXForCode(char code, bool unknownAsString);
const char* MakerNameForMakerCode(u16 id, bool unknownAsString);
};
#endif

View File

@ -1,343 +0,0 @@
/*
Copyright 2006 yopyop
Copyright 2007 shash
Copyright 2007-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FIFO.h"
#include <string.h>
#include "armcpu.h"
#include "debug.h"
#include "mem.h"
#include "MMU.h"
#include "registers.h"
#include "NDSSystem.h"
#include "gfx3d.h"
// ========================================================= IPC FIFO
IPC_FIFO ipc_fifo[2];
void IPC_FIFOinit(u8 proc)
{
memset(&ipc_fifo[proc], 0, sizeof(IPC_FIFO));
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, 0x00000101);
}
void IPC_FIFOsend(u8 proc, u32 val)
{
u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
if (!(cnt_l & IPCFIFOCNT_FIFOENABLE)) return; // FIFO disabled
u8 proc_remote = proc ^ 1;
if (ipc_fifo[proc].size > 15)
{
cnt_l |= IPCFIFOCNT_FIFOERROR;
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
return;
}
u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc_remote][0x40], 0x184);
//LOG("IPC%s send FIFO 0x%08X size %03i (l 0x%X, tail %02i) (r 0x%X, tail %02i)\n",
// proc?"7":"9", val, ipc_fifo[proc].size, cnt_l, ipc_fifo[proc].tail, cnt_r, ipc_fifo[proc^1].tail);
cnt_l &= 0xBFFC; // clear send empty bit & full
cnt_r &= 0xBCFF; // set recv empty bit & full
ipc_fifo[proc].buf[ipc_fifo[proc].tail] = val;
ipc_fifo[proc].tail++;
ipc_fifo[proc].size++;
if (ipc_fifo[proc].tail > 15) ipc_fifo[proc].tail = 0;
if (ipc_fifo[proc].size > 15)
{
cnt_l |= IPCFIFOCNT_SENDFULL; // set send full bit
cnt_r |= IPCFIFOCNT_RECVFULL; // set recv full bit
}
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r);
if(cnt_r&IPCFIFOCNT_RECVIRQEN)
NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_RECVNONEMPTY);
NDS_Reschedule();
}
u32 IPC_FIFOrecv(u8 proc)
{
u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
if (!(cnt_l & IPCFIFOCNT_FIFOENABLE)) return (0); // FIFO disabled
u8 proc_remote = proc ^ 1;
u32 val = 0;
if ( ipc_fifo[proc_remote].size == 0 ) // remote FIFO error
{
cnt_l |= IPCFIFOCNT_FIFOERROR;
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
return (0);
}
u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc_remote][0x40], 0x184);
cnt_l &= 0xBCFF; // clear send full bit & empty
cnt_r &= 0xBFFC; // set recv full bit & empty
val = ipc_fifo[proc_remote].buf[ipc_fifo[proc_remote].head];
ipc_fifo[proc_remote].head++;
ipc_fifo[proc_remote].size--;
if (ipc_fifo[proc_remote].head > 15) ipc_fifo[proc_remote].head = 0;
//LOG("IPC%s recv FIFO 0x%08X size %03i (l 0x%X, tail %02i) (r 0x%X, tail %02i)\n",
// proc?"7":"9", val, ipc_fifo[proc].size, cnt_l, ipc_fifo[proc].tail, cnt_r, ipc_fifo[proc^1].tail);
if ( ipc_fifo[proc_remote].size == 0 ) // FIFO empty
{
cnt_l |= IPCFIFOCNT_RECVEMPTY;
cnt_r |= IPCFIFOCNT_SENDEMPTY;
if(cnt_r&IPCFIFOCNT_SENDIRQEN)
NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_SENDEMPTY);
}
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r);
NDS_Reschedule();
return (val);
}
void IPC_FIFOcnt(u8 proc, u16 val)
{
u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184);
if (val & IPCFIFOCNT_FIFOERROR)
{
//at least SPP uses this, maybe every retail game
cnt_l &= ~IPCFIFOCNT_FIFOERROR;
}
if (val & IPCFIFOCNT_SENDCLEAR)
{
ipc_fifo[proc].head = 0; ipc_fifo[proc].tail = 0; ipc_fifo[proc].size = 0;
cnt_l |= IPCFIFOCNT_SENDEMPTY;
cnt_r |= IPCFIFOCNT_RECVEMPTY;
cnt_l &= ~IPCFIFOCNT_SENDFULL;
cnt_r &= ~IPCFIFOCNT_RECVFULL;
}
cnt_l &= ~IPCFIFOCNT_WRITEABLE;
cnt_l |= val & IPCFIFOCNT_WRITEABLE;
//IPCFIFOCNT_SENDIRQEN may have been set (and/or the fifo may have been cleared) so we may need to trigger this irq
//(this approach is used by libnds fifo system on occasion in fifoInternalSend, and began happening frequently for value32 with r4326)
if(cnt_l&IPCFIFOCNT_SENDIRQEN) if(cnt_l & IPCFIFOCNT_SENDEMPTY)
NDS_makeIrq(proc, IRQ_BIT_IPCFIFO_SENDEMPTY);
//IPCFIFOCNT_RECVIRQEN may have been set so we may need to trigger this irq
if(cnt_l&IPCFIFOCNT_RECVIRQEN) if(!(cnt_l & IPCFIFOCNT_RECVEMPTY))
NDS_makeIrq(proc, IRQ_BIT_IPCFIFO_RECVNONEMPTY);
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, cnt_r);
NDS_Reschedule();
}
// ========================================================= GFX FIFO
GFX_PIPE gxPIPE;
GFX_FIFO gxFIFO;
void GFX_PIPEclear()
{
gxPIPE.head = 0;
gxPIPE.tail = 0;
gxPIPE.size = 0;
gxFIFO.matrix_stack_op_size = 0;
}
void GFX_FIFOclear()
{
gxFIFO.head = 0;
gxFIFO.tail = 0;
gxFIFO.size = 0;
gxFIFO.matrix_stack_op_size = 0;
}
static void GXF_FIFO_handleEvents()
{
bool low = gxFIFO.size <= 127;
bool lowchange = MMU_new.gxstat.fifo_low ^ low;
MMU_new.gxstat.fifo_low = low;
if(low) triggerDma(EDMAMode_GXFifo);
bool empty = gxFIFO.size == 0;
bool emptychange = MMU_new.gxstat.fifo_empty ^ empty;
MMU_new.gxstat.fifo_empty = empty;
MMU_new.gxstat.sb = gxFIFO.matrix_stack_op_size != 0;
if(emptychange||lowchange) NDS_Reschedule();
}
static bool IsMatrixStackCommand(u8 cmd)
{
return cmd == 0x11 || cmd == 0x12;
}
void GFX_FIFOsend(u8 cmd, u32 param)
{
//INFO("gxFIFO: send 0x%02X = 0x%08X (size %03i/0x%02X) gxstat 0x%08X\n", cmd, param, gxFIFO.size, gxFIFO.size, gxstat);
//printf("fifo recv: %02X: %08X upto:%d\n",cmd,param,gxFIFO.size+1);
//TODO - WOAH ! NOT HANDLING A TOO-BIG FIFO RIGHT NOW!
//if (gxFIFO.size > 255)
//{
// GXF_FIFO_handleEvents();
// //NEED TO HANDLE THIS!!!!!!!!!!!!!!!!!!!!!!!!!!
// //gxstat |= 0x08000000; // busy
// NDS_RescheduleGXFIFO(1);
// //INFO("ERROR: gxFIFO is full (cmd 0x%02X = 0x%08X) (prev cmd 0x%02X = 0x%08X)\n", cmd, param, gxFIFO.cmd[255], gxFIFO.param[255]);
// return;
//}
gxFIFO.cmd[gxFIFO.tail] = cmd;
gxFIFO.param[gxFIFO.tail] = param;
gxFIFO.tail++;
gxFIFO.size++;
if (gxFIFO.tail > HACK_GXIFO_SIZE-1) gxFIFO.tail = 0;
//if a matrix op is entering the pipeline, do accounting for it
//(this is tested by wild west, which will jam a few ops in the fifo and then wait for the matrix stack to be
//un-busy so it can read back the current matrix stack position).
//it is definitely only pushes and pops which set this flag.
//seems like it would be less work in the HW to make a counter than do cmps on all the command bytes, so maybe we're even doing it right.
if(IsMatrixStackCommand(cmd))
gxFIFO.matrix_stack_op_size++;
//along the same lines:
//american girls julie finds a way will put a bunch of stuff and then a box test into the fifo and then immediately test the busy flag
//so we need to set the busy flag here.
//does it expect the fifo to be running then? well, it's definitely jammed -- making it unjammed at one point did fix this bug.
//it's still not clear whether we're handling the immediate vs fifo commands properly at all :(
//anyway, here we go, similar treatment. consider this a hack.
if(cmd == 0x70) MMU_new.gxstat.tb = 1; //just set the flag--youre insane if you queue more than one of these anyway
if(cmd == 0x71) MMU_new.gxstat.tb = 1;
if(gxFIFO.size>=HACK_GXIFO_SIZE) {
printf("--FIFO FULL-- : %d\n",gxFIFO.size);
}
//gxstat |= 0x08000000; // set busy flag
GXF_FIFO_handleEvents();
NDS_RescheduleGXFIFO(1);
}
// this function used ONLY in gxFIFO
BOOL GFX_PIPErecv(u8 *cmd, u32 *param)
{
//gxstat &= 0xF7FFFFFF; // clear busy flag
if (gxFIFO.size == 0)
{
GXF_FIFO_handleEvents();
return FALSE;
}
*cmd = gxFIFO.cmd[gxFIFO.head];
*param = gxFIFO.param[gxFIFO.head];
//see the associated increment in another function
if(IsMatrixStackCommand(*cmd))
{
gxFIFO.matrix_stack_op_size--;
if(gxFIFO.matrix_stack_op_size>0x10000000)
printf("bad news disaster in matrix_stack_op_size\n");
}
gxFIFO.head++;
gxFIFO.size--;
if (gxFIFO.head > HACK_GXIFO_SIZE-1) gxFIFO.head = 0;
GXF_FIFO_handleEvents();
return (TRUE);
}
void GFX_FIFOcnt(u32 val)
{
////INFO("gxFIFO: write cnt 0x%08X (prev 0x%08X) FIFO size %03i PIPE size %03i\n", val, gxstat, gxFIFO.size, gxPIPE.size);
if (val & (1<<29)) // clear? (only in homebrew?)
{
GFX_PIPEclear();
GFX_FIFOclear();
return;
}
//zeromus says: what happened to clear stack?
//if (val & (1<<15)) // projection stack pointer reset
//{
// gfx3d_ClearStack();
// val &= 0xFFFF5FFF; // clear reset (bit15) & stack level (bit13)
//}
T1WriteLong(MMU.ARM9_REG, 0x600, val);
}
// ========================================================= DISP FIFO
DISP_FIFO disp_fifo;
void DISP_FIFOinit()
{
memset(&disp_fifo, 0, sizeof(DISP_FIFO));
}
void DISP_FIFOsend(u32 val)
{
//INFO("DISP_FIFO send value 0x%08X (head 0x%06X, tail 0x%06X)\n", val, disp_fifo.head, disp_fifo.tail);
disp_fifo.buf[disp_fifo.tail] = val;
disp_fifo.tail++;
if (disp_fifo.tail > 0x5FFF)
disp_fifo.tail = 0;
}
u32 DISP_FIFOrecv()
{
//if (disp_fifo.tail == disp_fifo.head) return (0); // FIFO is empty
u32 val = disp_fifo.buf[disp_fifo.head];
disp_fifo.head++;
if (disp_fifo.head > 0x5FFF)
disp_fifo.head = 0;
return (val);
}
void DISP_FIFOreset()
{
disp_fifo.head = 0;
disp_fifo.tail = 0;
}

View File

@ -1,92 +0,0 @@
/*
Copyright 2006 yopyop
Copyright 2007 shash
Copyright 2007-2011 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FIFO_H
#define FIFO_H
#include "types.h"
//=================================================== IPC FIFO
typedef struct
{
u32 buf[16];
u8 head;
u8 tail;
u8 size;
} IPC_FIFO;
extern IPC_FIFO ipc_fifo[2];
extern void IPC_FIFOinit(u8 proc);
extern void IPC_FIFOsend(u8 proc, u32 val);
extern u32 IPC_FIFOrecv(u8 proc);
extern void IPC_FIFOcnt(u8 proc, u16 val);
//=================================================== GFX FIFO
//yeah, its oversize for now. thats a simpler solution
//moon seems to overdrive the fifo with immediate dmas
//i think this might be nintendo code too
#define HACK_GXIFO_SIZE 200000
typedef struct
{
u8 cmd[HACK_GXIFO_SIZE];
u32 param[HACK_GXIFO_SIZE];
u32 head; // start position
u32 tail; // tail
u32 size; // size FIFO buffer
u32 matrix_stack_op_size; //number of matrix stack items in the fifo (stack is busy when this is nonzero)
} GFX_FIFO;
typedef struct
{
u8 cmd[4];
u32 param[4];
u8 head;
u8 tail;
u8 size;
} GFX_PIPE;
extern GFX_PIPE gxPIPE;
extern GFX_FIFO gxFIFO;
void GFX_PIPEclear();
void GFX_FIFOclear();
void GFX_FIFOsend(u8 cmd, u32 param);
BOOL GFX_PIPErecv(u8 *cmd, u32 *param);
void GFX_FIFOcnt(u32 val);
//=================================================== Display memory FIFO
typedef struct
{
u32 buf[0x6000]; // 256x192 32K color
u32 head; // head
u32 tail; // tail
} DISP_FIFO;
extern DISP_FIFO disp_fifo;
void DISP_FIFOinit();
void DISP_FIFOsend(u32 val);
u32 DISP_FIFOrecv();
void DISP_FIFOreset();
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,460 +0,0 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2007 shash
Copyright (C) 2007-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
// this file is split from MMU.h for the purpose of avoiding ridiculous recompile times
// when changing it, because practically everything includes MMU.h.
#ifndef MMUTIMING_H
#define MMUTIMING_H
#include <algorithm>
#include "MMU.h"
#include "cp15.h"
#include "readwrite.h"
#include "debug.h"
#include "NDSSystem.h"
#include "emufile.h"
////////////////////////////////////////////////////////////////
// MEMORY TIMING ACCURACY CONFIGURATION
//
// the more of these are enabled,
// the more accurate memory access timing _should_ become.
// they should be listed roughly in order of most to least important.
// it's reasonable to disable some of these as a speed hack.
// obviously, these defines don't cover all the variables or features needed,
// and in particular, DMA or code+data access bus contention is still missing.
//disable this to prevent the advanced timing logic from ever running at all
#define ENABLE_ADVANCED_TIMING
#ifdef ENABLE_ADVANCED_TIMING
// makes non-sequential accesses slower than sequential ones.
#define ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS
//(SOMETIMES THIS IS A BIG SPEED HIT!)
// enables emulation of code fetch waits.
#define ACCOUNT_FOR_CODE_FETCH_CYCLES
// makes access to DTCM (arm9 only) fast.
#define ACCOUNT_FOR_DATA_TCM_SPEED
// enables simulation of cache hits and cache misses.
#define ENABLE_CACHE_CONTROLLER_EMULATION
#endif //ENABLE_ADVANCED_TIMING
//
////////////////////////////////////////////////////////////////
FORCEINLINE bool USE_TIMING() {
#ifdef ENABLE_ADVANCED_TIMING
return CommonSettings.advanced_timing;
#else
return false;
#endif
}
enum MMU_ACCESS_DIRECTION
{
MMU_AD_READ, MMU_AD_WRITE
};
// note that we don't actually emulate the cache contents here,
// only enough to guess what would be a cache hit or a cache miss.
// this doesn't really get used unless ENABLE_CACHE_CONTROLLER_EMULATION is defined.
template<int SIZESHIFT, int ASSOCIATIVESHIFT, int BLOCKSIZESHIFT>
class CacheController
{
public:
template<MMU_ACCESS_DIRECTION DIR>
FORCEINLINE bool Cached(u32 addr)
{
u32 blockMasked = addr & BLOCKMASK;
if(blockMasked == m_cacheCache)
return true;
else
return this->CachedInternal<DIR>(addr, blockMasked);
}
void Reset()
{
for(int blockIndex = 0; blockIndex < NUMBLOCKS; blockIndex++)
m_blocks[blockIndex].Reset();
m_cacheCache = ~0;
}
CacheController()
{
Reset();
}
void savestate(EMUFILE &os, int version)
{
os.write_32LE(m_cacheCache);
for (int i = 0; i < NUMBLOCKS; i++)
{
for (int j = 0; j < ASSOCIATIVITY; j++)
os.write_32LE(m_blocks[i].tag[j]);
os.write_32LE(m_blocks[i].nextWay);
}
}
bool loadstate(EMUFILE &is, int version)
{
is.read_32LE(m_cacheCache);
for (int i = 0; i < NUMBLOCKS; i++)
{
for (int j = 0; j < ASSOCIATIVITY; j++)
is.read_32LE(m_blocks[i].tag[j]);
is.read_32LE(m_blocks[i].nextWay);
}
return true;
}
private:
template<MMU_ACCESS_DIRECTION DIR>
bool CachedInternal(u32 addr, u32 blockMasked)
{
u32 blockIndex = blockMasked >> BLOCKSIZESHIFT;
CacheBlock& block = m_blocks[blockIndex];
addr &= TAGMASK;
for(int way = 0; way < ASSOCIATIVITY; way++)
if(addr == block.tag[way])
{
// found it, already allocated
m_cacheCache = blockMasked;
return true;
}
if(DIR == MMU_AD_READ)
{
// TODO: support other allocation orders?
block.tag[block.nextWay++] = addr;
block.nextWay %= ASSOCIATIVITY;
m_cacheCache = blockMasked;
}
return false;
}
enum { SIZE = 1 << SIZESHIFT };
enum { ASSOCIATIVITY = 1 << ASSOCIATIVESHIFT };
enum { BLOCKSIZE = 1 << BLOCKSIZESHIFT };
enum { TAGSHIFT = SIZESHIFT - ASSOCIATIVESHIFT };
enum { TAGMASK = (u32)(~0U << TAGSHIFT) };
enum { BLOCKMASK = ((u32)~0U >> (32 - TAGSHIFT)) & (u32)(~0U << BLOCKSIZESHIFT) };
enum { WORDSIZE = sizeof(u32) };
enum { WORDSPERBLOCK = (1 << BLOCKSIZESHIFT) / WORDSIZE };
enum { DATAPERWORD = WORDSIZE * ASSOCIATIVITY };
enum { DATAPERBLOCK = DATAPERWORD * WORDSPERBLOCK };
enum { NUMBLOCKS = SIZE / DATAPERBLOCK };
struct CacheBlock
{
u32 tag [ASSOCIATIVITY];
u32 nextWay;
void Reset()
{
nextWay = 0;
for(int way = 0; way < ASSOCIATIVITY; way++)
tag[way] = 0;
}
};
u32 m_cacheCache; // optimization
CacheBlock m_blocks [NUMBLOCKS];
};
template<int PROCNUM, MMU_ACCESS_TYPE AT, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION, bool TIMING>
FORCEINLINE u32 _MMU_accesstime(u32 addr, bool sequential);
template<int PROCNUM, MMU_ACCESS_TYPE AT>
class FetchAccessUnit
{
public:
template<int READSIZE, MMU_ACCESS_DIRECTION DIRECTION, bool TIMING>
FORCEINLINE u32 Fetch(u32 address)
{
#ifdef ACCOUNT_FOR_CODE_FETCH_CYCLES
const bool prohibit = TIMING;
#else
const bool prohibit = false;
#endif
if(AT == MMU_AT_CODE && !prohibit)
{
return 1;
}
u32 time = _MMU_accesstime<PROCNUM, AT, READSIZE, DIRECTION,TIMING>(address,
#ifdef ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS
(TIMING?
(address == (m_lastAddress + (READSIZE>>3)))
:true
)
#else
true
#endif
);
#ifdef ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS
m_lastAddress = address;
#endif
return time;
}
void Reset()
{
m_lastAddress = ~0;
}
FetchAccessUnit() { this->Reset(); }
void savestate(EMUFILE &os, int version)
{
os.write_32LE(m_lastAddress);
}
bool loadstate(EMUFILE &is, int version)
{
is.read_32LE(m_lastAddress);
return true;
}
private:
u32 m_lastAddress;
};
struct MMU_struct_timing
{
// technically part of the cp15, but I didn't want the dereferencing penalty.
// these template values correspond with the value of armcp15->cacheType.
CacheController<13,2,5> arm9codeCache; // 8192 bytes, 4-way associative, 32-byte blocks
CacheController<12,2,5> arm9dataCache; // 4096 bytes, 4-way associative, 32-byte blocks
// technically part of armcpu_t, but that struct isn't templated on PROCNUM
FetchAccessUnit<0,MMU_AT_CODE> arm9codeFetch;
FetchAccessUnit<0,MMU_AT_DATA> arm9dataFetch;
FetchAccessUnit<1,MMU_AT_CODE> arm7codeFetch;
FetchAccessUnit<1,MMU_AT_DATA> arm7dataFetch;
template<int PROCNUM> FORCEINLINE FetchAccessUnit<PROCNUM,MMU_AT_CODE>& armCodeFetch();
template<int PROCNUM> FORCEINLINE FetchAccessUnit<PROCNUM,MMU_AT_DATA>& armDataFetch();
};
template<> FORCEINLINE FetchAccessUnit<0,MMU_AT_CODE>& MMU_struct_timing::armCodeFetch<0>() { return this->arm9codeFetch; }
template<> FORCEINLINE FetchAccessUnit<1,MMU_AT_CODE>& MMU_struct_timing::armCodeFetch<1>() { return this->arm7codeFetch; }
template<> FORCEINLINE FetchAccessUnit<0,MMU_AT_DATA>& MMU_struct_timing::armDataFetch<0>() { return this->arm9dataFetch; }
template<> FORCEINLINE FetchAccessUnit<1,MMU_AT_DATA>& MMU_struct_timing::armDataFetch<1>() { return this->arm7dataFetch; }
extern MMU_struct_timing MMU_timing;
// calculates the time a single memory access takes,
// in units of cycles of the current processor.
// this function replaces what used to be MMU_WAIT16 and MMU_WAIT32.
// this may have side effects, so don't call it more than necessary.
template<int PROCNUM, MMU_ACCESS_TYPE AT, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION, bool TIMING>
FORCEINLINE u32 _MMU_accesstime(u32 addr, bool sequential)
{
static const int MC = 1; // cached or tcm memory speed
static const int M32 = (PROCNUM==ARMCPU_ARM9) ? 2 : 1; // access through 32-bit bus
static const int M16 = M32 * ((READSIZE>16) ? 2 : 1); // access through 16-bit bus
static const int MSLW = M16 * 8; // this needs tuning
if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_CODE && addr < 0x02000000)
return MC; // ITCM
#ifdef ACCOUNT_FOR_DATA_TCM_SPEED
if(TIMING && PROCNUM==ARMCPU_ARM9 && AT==MMU_AT_DATA && (addr&(~0x3FFF)) == MMU.DTCMRegion)
return MC; // DTCM
#endif
// for now, assume the cache is always enabled for all of main memory
if(AT != MMU_AT_DMA && TIMING && PROCNUM==ARMCPU_ARM9 && (addr & 0x0F000000) == 0x02000000)
{
#ifdef ENABLE_CACHE_CONTROLLER_EMULATION
bool cached = false;
if(AT==MMU_AT_CODE)
cached = MMU_timing.arm9codeCache.Cached<DIRECTION>(addr);
if(AT==MMU_AT_DATA)
cached = MMU_timing.arm9dataCache.Cached<DIRECTION>(addr);
if(cached)
return MC;
u32 c;
if(sequential && AT==MMU_AT_DATA)
c = M16; // bonus for sequential data access
else if(DIRECTION == MMU_AD_READ)
c = M16 * 5;
else
c = M16 * 2; // should be 4, but write buffer isn't emulated yet.
if(DIRECTION == MMU_AD_READ)
{
// cache miss while reading means it has to fill a whole cache line
// by reading 32 bytes...
c += 8 * M32*2;
}
if(CheckDebugEvent(DEBUG_EVENT_CACHE_MISS))
{
DebugEventData.addr = addr;
DebugEventData.size = READSIZE;
HandleDebugEvent(DEBUG_EVENT_CACHE_MISS);
}
return c;
#elif defined(ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS)
// this is the closest approximation I could find
// to the with-cache-controller timing
// that doesn't do any actual caching logic.
return sequential ? MC : M16;
#endif
}
static const TWaitState MMU_WAIT[16*16] = {
// ITCM, ITCM, MAIN, SWI, REG, VMEM, LCD, OAM, ROM, ROM, RAM, U, U, U, U, BIOS
#define X MC, MC, M16, M32, M32, M16, M16, M32, MSLW, MSLW, MSLW, M32,M32,M32,M32, M32,
// duplicate it 16 times (this was somehow faster than using a mask of 0xF)
X X X X X X X X X X X X X X X X
#undef X
};
u32 c = MMU_WAIT[(addr >> 24)];
#ifdef ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS
if(TIMING && !sequential)
{
//if(c != MC || PROCNUM==ARMCPU_ARM7) // check not needed anymore because ITCM/DTCM return earlier
{
c += (PROCNUM==ARMCPU_ARM9) ? 3*2 : 1;
}
}
#endif
return c;
}
// calculates the cycle time of a single memory access in the MEM stage.
// to be used to calculate the memCycles argument for MMU_aluMemCycles.
// this may have side effects, so don't call it more than necessary.
template<int PROCNUM, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION, bool TIMING>
FORCEINLINE u32 MMU_memAccessCycles(u32 addr)
{
if(TIMING)
return MMU_timing.armDataFetch<PROCNUM>().template Fetch<READSIZE,DIRECTION,true>((addr)&(~((READSIZE>>3)-1)));
else
return MMU_timing.armDataFetch<PROCNUM>().template Fetch<READSIZE,DIRECTION,false>((addr)&(~((READSIZE>>3)-1)));
}
template<int PROCNUM, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION>
FORCEINLINE u32 MMU_memAccessCycles(u32 addr)
{
if(USE_TIMING())
return MMU_memAccessCycles<PROCNUM,READSIZE,DIRECTION,true>(addr);
else
return MMU_memAccessCycles<PROCNUM,READSIZE,DIRECTION,false>(addr);
}
// calculates the cycle time of a single code fetch in the FETCH stage
// to be used to calculate the fetchCycles argument for MMU_fetchExecuteCycles.
// this may have side effects, so don't call it more than necessary.
template<int PROCNUM, int READSIZE>
FORCEINLINE u32 MMU_codeFetchCycles(u32 addr)
{
if(USE_TIMING())
return MMU_timing.armCodeFetch<PROCNUM>().template Fetch<READSIZE,MMU_AD_READ,true>((addr)&(~((READSIZE>>3)-1)));
else
return MMU_timing.armCodeFetch<PROCNUM>().template Fetch<READSIZE,MMU_AD_READ,false>((addr)&(~((READSIZE>>3)-1)));
}
// calculates the cycle contribution of ALU + MEM stages (= EXECUTE)
// given ALU cycle time and the summation of multiple memory access cycle times.
// this function might belong more in armcpu, but I don't think it matters.
template<int PROCNUM>
FORCEINLINE u32 MMU_aluMemCycles(u32 aluCycles, u32 memCycles)
{
if(PROCNUM==ARMCPU_ARM9)
{
// ALU and MEM are different stages of the 5-stage pipeline.
// we approximate the pipeline throughput using max,
// since simply adding the cycles of each instruction together
// fails to take into account the parallelism of the arm pipeline
// and would make the emulated system unnaturally slow.
return std::max(aluCycles, memCycles);
}
else
{
// ALU and MEM are part of the same stage of the 3-stage pipeline,
// thus they occur in sequence and we can simply add the counts together.
return aluCycles + memCycles;
}
}
// calculates the cycle contribution of ALU + MEM stages (= EXECUTE)
// given ALU cycle time and the description of a single memory access.
// this may have side effects, so don't call it more than necessary.
template<int PROCNUM, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION>
FORCEINLINE u32 MMU_aluMemAccessCycles(u32 aluCycles, u32 addr)
{
u32 memCycles;
if(USE_TIMING())
memCycles = MMU_memAccessCycles<PROCNUM,READSIZE,DIRECTION,true>(addr);
else memCycles = MMU_memAccessCycles<PROCNUM,READSIZE,DIRECTION,false>(addr);
return MMU_aluMemCycles<PROCNUM>(aluCycles, memCycles);
}
// calculates the cycle contribution of FETCH + EXECUTE stages
// given executeCycles = the combined ALU+MEM cycles
// and fetchCycles = the cycle time of the FETCH stage
// this function might belong more in armcpu, but I don't think it matters.
template<int PROCNUM>
FORCEINLINE u32 MMU_fetchExecuteCycles(u32 executeCycles, u32 fetchCycles)
{
#ifdef ACCOUNT_FOR_CODE_FETCH_CYCLES
const bool allow = true;
#else
const bool allow = false;
#endif
if(USE_TIMING() && allow)
{
// execute and fetch are different stages of the pipeline for both arm7 and arm9.
// again, we approximate the pipeline throughput using max.
return std::max(executeCycles, fetchCycles);
// TODO: add an option to support conflict between MEM and FETCH cycles
// if they're both using the same data bus.
// in the case of a conflict this should be:
// return std::max(aluCycles, memCycles + fetchCycles);
}
return executeCycles;
}
#endif //MMUTIMING_H

View File

@ -1,258 +0,0 @@
include desmume.mk
AM_CPPFLAGS += $(SDL_CFLAGS) $(GTHREAD_CFLAGS) $(X_CFLAGS) $(ALSA_CFLAGS) $(LIBAGG_CFLAGS) $(LIBSOUNDTOUCH_CFLAGS)
EXTRA_DIST = instruction_tabdef.inc thumb_tabdef.inc cocoa
if HAVE_GDB_STUB
SUBDIRS = . gdbstub $(UI_DIR)
else
SUBDIRS = . $(UI_DIR)
endif
#DIST_SUBDIRS = . gdbstub cli gtk gtk-glade
noinst_LIBRARIES = libdesmume.a
libdesmume_a_SOURCES = \
armcpu.cpp armcpu.h \
arm_instructions.cpp \
agg2d.h agg2d.inl \
bios.cpp bios.h bits.h cp15.cpp cp15.h \
commandline.h commandline.cpp \
common.cpp common.h \
debug.cpp debug.h \
Database.cpp Database.h Disassembler.cpp Disassembler.h \
emufile.h emufile.cpp encrypt.h encrypt.cpp FIFO.cpp FIFO.h \
firmware.cpp firmware.h GPU.cpp GPU.h \
GPU_osd.h \
instructions.h \
mem.h mc.cpp mc.h \
path.cpp path.h \
readwrite.cpp readwrite.h \
wifi.cpp wifi.h \
mic.h \
MMU.cpp MMU.h MMU_timing.h NDSSystem.cpp NDSSystem.h registers.h \
OGLRender.h OGLRender_3_2.h \
ROMReader.cpp ROMReader.h \
render3D.cpp render3D.h \
rtc.cpp rtc.h \
saves.cpp saves.h \
slot1.cpp slot1.h \
slot2.cpp slot2.h \
SPU.cpp SPU.h \
matrix.cpp matrix.h \
gfx3d.cpp gfx3d.h \
thumb_instructions.cpp types.h \
movie.cpp movie.h \
PACKED.h PACKED_END.h \
utils/advanscene.cpp utils/advanscene.h \
utils/datetime.cpp utils/datetime.h \
utils/ConvertUTF.c utils/ConvertUTF.h utils/guid.cpp utils/guid.h \
utils/emufat.cpp utils/emufat.h utils/emufat_types.h \
utils/fsnitro.cpp utils/fsnitro.h \
utils/md5.cpp utils/md5.h utils/valuearray.h utils/xstring.cpp utils/xstring.h \
utils/decrypt/crc.cpp utils/decrypt/crc.h utils/decrypt/decrypt.cpp \
utils/decrypt/decrypt.h utils/decrypt/header.cpp utils/decrypt/header.h \
utils/task.cpp utils/task.h \
utils/vfat.h utils/vfat.cpp \
utils/colorspacehandler/colorspacehandler.cpp \
utils/dlditool.cpp \
utils/libfat/bit_ops.h \
utils/libfat/cache.cpp \
utils/libfat/cache.h \
utils/libfat/common.h \
utils/libfat/directory.cpp \
utils/libfat/directory.h \
utils/libfat/disc.cpp \
utils/libfat/disc.h \
utils/libfat/disc_io.h \
utils/libfat/fat.h \
utils/libfat/fatdir.cpp \
utils/libfat/fatdir.h \
utils/libfat/fatfile.cpp \
utils/libfat/fatfile.h \
utils/libfat/filetime.cpp \
utils/libfat/filetime.h \
utils/libfat/file_allocation_table.cpp \
utils/libfat/file_allocation_table.h \
utils/libfat/libfat.cpp \
utils/libfat/libfat_pc.h \
utils/libfat/libfat_public_api.cpp \
utils/libfat/libfat_public_api.h \
utils/libfat/lock.cpp \
utils/libfat/lock.h \
utils/libfat/mem_allocate.h \
utils/libfat/partition.cpp \
utils/libfat/partition.h \
utils/tinyxml/tinystr.cpp \
utils/tinyxml/tinystr.h \
utils/tinyxml/tinyxml.cpp \
utils/tinyxml/tinyxml.h \
utils/tinyxml/tinyxmlerror.cpp \
utils/tinyxml/tinyxmlparser.cpp \
utils/glcorearb.h \
addons/slot2_auto.cpp \
addons/slot2_mpcf.cpp \
addons/slot2_paddle.cpp \
addons/slot2_gbagame.cpp \
addons/slot2_none.cpp \
addons/slot2_rumblepak.cpp \
addons/slot2_guitarGrip.cpp \
addons/slot2_expMemory.cpp \
addons/slot2_piano.cpp \
addons/slot2_passme.cpp \
addons/slot1_none.cpp \
addons/slot1_r4.cpp \
addons/slot1_retail_nand.cpp \
addons/slot1_retail_auto.cpp \
addons/slot1_retail_mcrom.cpp \
addons/slot1_retail_mcrom_debug.cpp \
addons/slot1comp_mc.cpp \
addons/slot1comp_mc.h \
addons/slot1comp_rom.h \
addons/slot1comp_rom.cpp \
addons/slot1comp_protocol.h \
addons/slot1comp_protocol.cpp \
cheatSystem.cpp cheatSystem.h \
texcache.cpp texcache.h rasterize.cpp rasterize.h \
metaspu/metaspu.cpp metaspu/metaspu.h \
filter/2xsai.cpp \
filter/bilinear.cpp \
filter/deposterize.cpp \
filter/epx.cpp \
filter/filter.h \
filter/hq2x.cpp \
filter/hq2x.h \
filter/hq3x.cpp \
filter/hq3x.dat \
filter/hq4x.cpp \
filter/hq4x.dat \
filter/interp.h \
filter/lq2x.cpp filter/lq2x.h \
filter/scanline.cpp \
filter/videofilter.cpp filter/videofilter.h \
filter/xbrz.cpp filter/xbrz.h \
version.cpp version.h \
desmume_config.cpp desmume_config.h \
libretro-common/compat/compat_getopt.c \
libretro-common/file/file_path.c \
libretro-common/compat/compat_strl.c \
libretro-common/features/features_cpu.c \
libretro-common/file/retro_dirent.c \
libretro-common/file/retro_stat.c \
libretro-common/rthreads/async_job.c \
libretro-common/rthreads/rsemaphore.c \
libretro-common/rthreads/rthreads.c
if SUPPORT_SSE2
libdesmume_a_SOURCES += \
utils/colorspacehandler/colorspacehandler_SSE2.cpp
endif
if SUPPORT_AVX2
libdesmume_a_SOURCES += \
utils/colorspacehandler/colorspacehandler_AVX2.cpp
endif
if SUPPORT_ALTIVEC
libdesmume_a_SOURCES += \
utils/colorspacehandler/colorspacehandler_AltiVec.cpp
endif
if HAVE_JIT
libdesmume_a_SOURCES += \
arm_jit.cpp arm_jit.h instruction_attributes.h \
utils/AsmJit/AsmJit.h \
utils/AsmJit/Config.h \
utils/AsmJit/core.h \
utils/AsmJit/x86.h \
utils/AsmJit/core/apibegin.h \
utils/AsmJit/core/apiend.h \
utils/AsmJit/core/assembler.cpp \
utils/AsmJit/core/assembler.h \
utils/AsmJit/core/assert.cpp \
utils/AsmJit/core/assert.h \
utils/AsmJit/core/buffer.cpp \
utils/AsmJit/core/buffer.h \
utils/AsmJit/core/build.h \
utils/AsmJit/core/compiler.cpp \
utils/AsmJit/core/compiler.h \
utils/AsmJit/core/compilercontext.cpp \
utils/AsmJit/core/compilercontext.h \
utils/AsmJit/core/compilerfunc.cpp \
utils/AsmJit/core/compilerfunc.h \
utils/AsmJit/core/compileritem.cpp \
utils/AsmJit/core/compileritem.h \
utils/AsmJit/core/context.cpp \
utils/AsmJit/core/context.h \
utils/AsmJit/core/cpuinfo.cpp \
utils/AsmJit/core/cpuinfo.h \
utils/AsmJit/core/defs.cpp \
utils/AsmJit/core/defs.h \
utils/AsmJit/core/func.cpp \
utils/AsmJit/core/func.h \
utils/AsmJit/core/intutil.h \
utils/AsmJit/core/lock.h \
utils/AsmJit/core/logger.cpp \
utils/AsmJit/core/logger.h \
utils/AsmJit/core/memorymanager.cpp \
utils/AsmJit/core/memorymanager.h \
utils/AsmJit/core/memorymarker.cpp \
utils/AsmJit/core/memorymarker.h \
utils/AsmJit/core/operand.cpp \
utils/AsmJit/core/operand.h \
utils/AsmJit/core/podvector.h \
utils/AsmJit/core/stringbuilder.cpp \
utils/AsmJit/core/stringbuilder.h \
utils/AsmJit/core/stringutil.cpp \
utils/AsmJit/core/stringutil.h \
utils/AsmJit/core/virtualmemory.cpp \
utils/AsmJit/core/virtualmemory.h \
utils/AsmJit/core/zonememory.cpp \
utils/AsmJit/core/zonememory.h \
utils/AsmJit/x86/x86assembler.cpp \
utils/AsmJit/x86/x86assembler.h \
utils/AsmJit/x86/x86compiler.cpp \
utils/AsmJit/x86/x86compiler.h \
utils/AsmJit/x86/x86compilercontext.cpp \
utils/AsmJit/x86/x86compilercontext.h \
utils/AsmJit/x86/x86compilerfunc.cpp \
utils/AsmJit/x86/x86compilerfunc.h \
utils/AsmJit/x86/x86compileritem.cpp \
utils/AsmJit/x86/x86compileritem.h \
utils/AsmJit/x86/x86cpuinfo.cpp \
utils/AsmJit/x86/x86cpuinfo.h \
utils/AsmJit/x86/x86defs.cpp \
utils/AsmJit/x86/x86defs.h \
utils/AsmJit/x86/x86func.cpp \
utils/AsmJit/x86/x86func.h \
utils/AsmJit/x86/x86operand.cpp \
utils/AsmJit/x86/x86operand.h \
utils/AsmJit/x86/x86util.cpp \
utils/AsmJit/x86/x86util.h
endif
if HAVE_GL
libdesmume_a_SOURCES += OGLRender.cpp OGLRender_3_2.cpp
endif
if HAVE_OPENAL
libdesmume_a_SOURCES += mic_openal.cpp
else
if HAVE_ALSA
libdesmume_a_SOURCES += mic_alsa.cpp
else
libdesmume_a_SOURCES += mic.cpp
endif
endif
if HAVE_LIBSOUNDTOUCH
libdesmume_a_SOURCES += metaspu/SndOut.cpp metaspu/SndOut.h metaspu/Timestretcher.cpp
endif
if HAVE_LIBAGG
libdesmume_a_SOURCES += aggdraw.cpp aggdraw.h GPU_osd.cpp
else
libdesmume_a_SOURCES += GPU_osd_stub.cpp
endif
if HAVE_LUA
AM_CPPFLAGS += $(LUA_CFLAGS)
libdesmume_a_SOURCES += lua-engine.cpp
endif

File diff suppressed because it is too large Load Diff

View File

@ -1,701 +0,0 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2008-2019 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NDSSYSTEM_H
#define NDSSYSTEM_H
#include <string.h>
#include <string>
#include <vector>
#include "types.h"
#include "ROMReader.h"
#include "firmware.h"
#include "render3D.h"
#include "wifi.h"
class CFIRMWARE;
class EMUFILE;
template<typename Type>
struct buttonstruct {
union {
struct {
// changing the order of these fields would break stuff
//fRLDUTSBAYXWEg
Type G; // debug
Type E; // right shoulder
Type W; // left shoulder
Type X;
Type Y;
Type A;
Type B;
Type S; // start
Type T; // select
Type U; // up
Type D; // down
Type L; // left
Type R; // right
Type F; // lid
};
Type array[14];
};
};
extern buttonstruct<bool> Turbo;
extern buttonstruct<u32> TurboTime;
extern buttonstruct<bool> AutoHold;
extern volatile bool execute;
extern BOOL click;
/*
* The firmware language values
*/
#define NDS_FW_LANG_JAP 0
#define NDS_FW_LANG_ENG 1
#define NDS_FW_LANG_FRE 2
#define NDS_FW_LANG_GER 3
#define NDS_FW_LANG_ITA 4
#define NDS_FW_LANG_SPA 5
#define NDS_FW_LANG_CHI 6
#define NDS_FW_LANG_RES 7
extern CFIRMWARE *extFirmwareObj;
#define DSGBA_LOADER_SIZE 512
enum
{
ROM_NDS = 0,
ROM_DSGBA
};
enum EmuHaltReasonCode
{
EMUHALT_REASON_USER_REQUESTED_HALT = 0,
EMUHALT_REASON_SYSTEM_POWERED_OFF = 1000,
EMUHALT_REASON_JIT_UNMAPPED_ADDRESS_EXCEPTION = 2000,
EMUHALT_REASON_ARM_RESERVED_0X14_EXCEPTION,
EMUHALT_REASON_ARM_UNDEFINED_INSTRUCTION_EXCEPTION,
EMUHALT_REASON_UNKNOWN = 10000
};
enum NDSErrorCode
{
NDSError_NoError = 0,
NDSError_SystemPoweredOff = 1000,
NDSError_JITUnmappedAddressException = 2000,
NDSError_ARMUndefinedInstructionException,
NDSError_UnknownError = 10000
};
enum NDSErrorTag
{
NDSErrorTag_None = 0,
NDSErrorTag_ARM9 = 1,
NDSErrorTag_ARM7 = 2,
NDSErrorTag_BothCPUs = 3,
};
struct NDSError
{
NDSErrorCode code;
NDSErrorTag tag;
u32 programCounterARM9;
u32 instructionARM9;
u32 instructionAddrARM9;
u32 programCounterARM7;
u32 instructionARM7;
u32 instructionAddrARM7;
};
typedef struct NDSError NDSError;
//#define LOG_ARM9
//#define LOG_ARM7
#include "PACKED.h"
struct NDS_header
{
char gameTile[12]; // 000 - Game Title (uppercase ASCII, padded with 00h)
char gameCode[4]; // 00C - Gamecode (uppercase ASCII, NTR-<code>, 0=homebrew)
u16 makerCode; // 010 - Makercode (uppercase ASCII, 0=homebrew)
u8 unitCode; // 012 - Unitcode (00h=Nintendo DS)
u8 deviceCode; // 013 - Encryption Seed Select (00..07h, usually 00h)
u8 cardSize; // 014 - Devicecapacity (Chipsize = 128KB SHL nn) (eg. 7 = 16MB)
u8 reserved1[8]; // 015 - Must be set to 0x00
u8 region; // 01D - Specific region: 0x80 - China, 0x40 - Korea, 0x00 - Other
u8 romversion; // 01E - ROM Version (usually 00h)
u8 autostart; // 01F - Autostart (Bit2: Skip "Press Button" after Health and Safety)
// (Also skips bootmenu, even in Manual mode & even Start pressed)
u32 ARM9src; // 020 - ARM9 rom_offset (4000h and up, align 1000h)
u32 ARM9exe; // 024 - ARM9 entry_address (2000000h..23BFE00h)
u32 ARM9cpy; // 028 - ARM9 ram_address (2000000h..23BFE00h)
u32 ARM9binSize; // 02C - ARM9 size (max 3BFE00h) (3839.5KB)
u32 ARM7src; // 030 - ARM7 rom_offset (8000h and up)
u32 ARM7exe; // 034 - ARM7 entry_address (2000000h..23BFE00h, or 37F8000h..3807E00h)
u32 ARM7cpy; // 038 - ARM7 ram_address (2000000h..23BFE00h, or 37F8000h..3807E00h)
u32 ARM7binSize; // 03C - ARM7 size (max 3BFE00h, or FE00h) (3839.5KB, 63.5KB)
u32 FNameTblOff; // 040 - File Name Table (FNT) offset
u32 FNameTblSize; // 044 - File Name Table (FNT) size
u32 FATOff; // 048 - File Allocation Table (FAT) offset
u32 FATSize; // 04C - File Allocation Table (FAT) size
u32 ARM9OverlayOff; // 050 - File ARM9 overlay_offset
u32 ARM9OverlaySize; // 054 - File ARM9 overlay_size
u32 ARM7OverlayOff; // 058 - File ARM7 overlay_offset
u32 ARM7OverlaySize; // 05C - File ARM7 overlay_size
u32 normalCmd; // 060 - Port 40001A4h setting for normal commands (usually 00586000h)
u32 Key1Cmd; // 064 - Port 40001A4h setting for KEY1 commands (usually 001808F8h)
u32 IconOff; // 068 - Icon_title_offset (0=None) (8000h and up)
u16 CRC16; // 06C - Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] - Calculations with this algorithm use 0xffff as the initial value
u16 ROMtimeout; // 06E - Secure Area Loading Timeout (usually 051Eh)
u32 ARM9autoload; // 070 - ARM9 Auto Load List RAM Address
u32 ARM7autoload; // 074 - ARM7 Auto Load List RAM Address
u8 infoResevedRegion[8]; // 078 - ROM Information Reserved Region (must be set to 0x00)
u32 endROMoffset; // 080 - Total Used ROM size (remaining/unused bytes usually FFh-padded)
u32 HeaderSize; // 084 - ROM Header Size (4000h)
u32 ARM9module; // 088 - ARM9 Module Parameter Address (auto-load parameters)
u32 ARM7module; // 08C - ARM7 Module Parameter Address (auto-load parameters)
u8 reserved2[48]; // 090 - Must be set to 0x00 - "PASS" is contained within here?
u8 logo[156]; // 0C0 - Nintendo Logo (compressed bitmap, same as in GBA Headers)
u16 logoCRC16; // 15C - Nintendo Logo Checksum, CRC-16 of [0C0h-15Bh], fixed CF56h
u16 headerCRC16; // 15E - Header Checksum, CRC-16 of [000h-15Dh]
u8 reserved[160]; // Must be set to 0x00
};
#include "PACKED_END.h"
extern void debug();
NDSError NDS_GetLastError();
static void NDS_CurrentCPUInfoToNDSError(NDSError &ndsError);
void emu_halt(EmuHaltReasonCode reasonCode, NDSErrorTag errorTag);
extern u64 nds_timer;
void NDS_Reschedule();
void NDS_RescheduleGXFIFO(u32 cost);
void NDS_RescheduleDMA();
void NDS_RescheduleReadSlot1(int procnum, int size);
void NDS_RescheduleTimers();
enum ENSATA_HANDSHAKE
{
ENSATA_HANDSHAKE_none = 0,
ENSATA_HANDSHAKE_query = 1,
ENSATA_HANDSHAKE_ack = 2,
ENSATA_HANDSHAKE_confirm = 3,
ENSATA_HANDSHAKE_complete = 4
};
enum NDS_CONSOLE_TYPE
{
NDS_CONSOLE_TYPE_FAT = 0xFF,
NDS_CONSOLE_TYPE_LITE = 0x20,
NDS_CONSOLE_TYPE_IQUE = 0x43,
NDS_CONSOLE_TYPE_IQUE_LITE = 0x63,
NDS_CONSOLE_TYPE_DSI = 0xFE
};
struct NDSSystem
{
s32 wifiCycle;
s32 cycles;
u64 timerCycle[2][4];
u32 VCount;
u32 old;
u8 overclock;
//raw adc touch coords for old NDS
u16 adc_touchX;
u16 adc_touchY;
s32 adc_jitterctr;
//the DSI returns calibrated touch coords from its TSC (?), so we need to save these separately
u16 scr_touchX;
u16 scr_touchY;
//whether the console is using our faked-bootup process
BOOL isFakeBooted;
BOOL isTouch;
u16 paddle;
u8 *FW_ARM9BootCode;
u8 *FW_ARM7BootCode;
u32 FW_ARM9BootCodeAddr;
u32 FW_ARM7BootCodeAddr;
u32 FW_ARM9BootCodeSize;
u32 FW_ARM7BootCodeSize;
BOOL sleeping;
BOOL cardEjected;
u32 freezeBus;
//this is not essential NDS runtime state.
//it was perhaps a mistake to put it here.
//it is far less important than the above.
//maybe I should move it.
s32 idleCycles[2];
s32 runCycleCollector[2][16];
s32 idleFrameCounter;
s32 cpuloopIterationCount; //counts the number of times during a frame that a reschedule happened
//console type must be copied in when the system boots. it can't be changed on the fly.
int ConsoleType;
bool Is_DSI() { return ConsoleType == NDS_CONSOLE_TYPE_DSI; }
bool Is_DebugConsole() { return _DebugConsole!=0; }
BOOL _DebugConsole;
//set if the user requests ensata emulation
BOOL ensataEmulation;
//there is a hack in the ipc sync for ensata. this tracks its state
u32 ensataIpcSyncCounter;
//maintains the state of the ensata handshaking protocol
u32 ensataHandshake;
struct {
u8 lcd, gpuMain, gfx3d_render, gfx3d_geometry, gpuSub, dispswap;
} power1; //POWCNT1
struct {
u8 speakers, wifi /*(initial value=0)*/;
} power2; //POWCNT2
BOOL power_render, power_geometry;
bool isInVblank() const { return VCount >= 192; }
bool isIn3dVblank() const { return VCount >= 192 && VCount<215; }
};
extern NDSSystem nds;
int NDS_Init();
void Desmume_InitOnce();
void NDS_DeInit(void);
BOOL NDS_SetROM(u8 * rom, u32 mask);
NDS_header * NDS_getROMHeader(void);
struct RomBanner
{
RomBanner(bool defaultInit = true);
u16 version; //Version (0001h)
u16 crc16; //CRC16 across entries 020h..83Fh
u8 reserved[0x1C]; //Reserved (zero-filled)
u8 bitmap[0x200]; //Icon Bitmap (32x32 pix) (4x4 tiles, each 4x8 bytes, 4bit depth)
u16 palette[0x10]; //Icon Palette (16 colors, 16bit, range 0000h-7FFFh) (Color 0 is transparent, so the 1st palette entry is ignored)
enum { NUM_TITLES = 6 };
union {
struct {
u16 title_jp[0x80]; //Title 0 Japanese (128 characters, 16bit Unicode)
u16 title_en[0x80]; //Title 1 English ("")
u16 title_fr[0x80]; //Title 2 French ("")
u16 title_de[0x80]; //Title 3 German ("")
u16 title_it[0x80]; //Title 4 Italian ("")
u16 title_es[0x80]; //Title 5 Spanish ("")
};
u16 titles[NUM_TITLES][0x80];
};
u8 end0xFF[0x1C0];
//840h ? (Maybe newer/chinese firmware do also support chinese title?)
//840h - End of Icon/Title structure (next 1C0h bytes usually FFh-filled)
};
struct GameInfo
{
void *fROM;
ROMReader_struct *reader;
u8 *romdataForReader;
u32 romsize;
u32 cardSize;
u32 mask;
u32 crc;
u32 chipID;
u32 romType;
u32 headerOffset;
char ROMserial[20];
char ROMname[13];
bool _isDSiEnhanced;
NDS_header header;
//a copy of the pristine secure area from the rom
u8 secureArea[0x4000];
RomBanner banner;
const RomBanner& getRomBanner();
GameInfo() : fROM(NULL),
romdataForReader(NULL),
crc(0),
chipID(0x00000FC2),
romsize(0),
cardSize(0),
mask(0),
romType(ROM_NDS),
headerOffset(0),
_isDSiEnhanced(false)
{
memset(&header, 0, sizeof(header));
memset(&ROMserial[0], 0, sizeof(ROMserial));
memset(&ROMname[0], 0, sizeof(ROMname));
}
~GameInfo() { closeROM(); }
bool IsCode(const char* code) const;
bool loadROM(std::string fname, u32 type = ROM_NDS);
void closeROM();
u32 readROM(u32 pos);
bool ValidateHeader();
void populate();
bool isDSiEnhanced();
bool isHomebrew();
bool hasRomBanner();
};
typedef struct TSCalInfo
{
struct
{
u16 x1, x2;
u16 y1, y2;
u16 width;
u16 height;
} adc;
struct
{
u8 x1, x2;
u8 y1, y2;
u16 width;
u16 height;
} scr;
} TSCalInfo;
extern GameInfo gameInfo;
struct UserButtons : buttonstruct<bool>
{
};
struct UserTouch
{
u16 touchX;
u16 touchY;
bool isTouch;
};
struct UserMicrophone
{
u32 micButtonPressed;
u8 micSample;
};
struct UserInput
{
UserButtons buttons;
UserTouch touch;
UserMicrophone mic;
};
// set physical user input
// these functions merely request the input to be changed.
// the actual change happens later at a specific time during the frame.
// this is to minimize the risk of desyncs.
void NDS_setTouchPos(u16 x, u16 y);
void NDS_releaseTouch(void);
void NDS_setPad(bool right,bool left,bool down,bool up,bool select,bool start,bool B,bool A,bool Y,bool X,bool leftShoulder,bool rightShoulder,bool debug, bool lid);
void NDS_setMic(bool pressed);
// get physical user input
// not including the results of autofire/etc.
// the effects of calls to "set physical user input" functions will be immediately reflected here though.
const UserInput& NDS_getRawUserInput();
const UserInput& NDS_getPrevRawUserInput();
// get final (fully processed) user input
// this should match whatever was or would be sent to the game
const UserInput& NDS_getFinalUserInput();
// set/get to-be-processed or in-the-middle-of-being-processed user input
// to process input, simply call this function and edit the return value.
// (applying autofire is one example of processing the input.)
// (movie playback is another example.)
// this must be done after the raw user input is set
// and before that input is sent to the game's memory.
UserInput& NDS_getProcessingUserInput();
bool NDS_isProcessingUserInput();
// call once per frame to prepare input for processing
void NDS_beginProcessingInput();
// call once per frame to copy the processed input to the final input
void NDS_endProcessingInput();
// this is in case something needs reentrancy while processing input
void NDS_suspendProcessingInput(bool suspend);
int NDS_LoadROM(const char *filename, const char* physicalFilename=0, const char* logicalFilename=0);
void NDS_FreeROM(void);
void NDS_Reset();
bool NDS_LegitBoot();
bool NDS_FakeBoot();
void nds_savestate(EMUFILE &os);
bool nds_loadstate(EMUFILE &is, int size);
void NDS_Sleep();
void NDS_TriggerCardEjectIRQ();
void NDS_SkipNextFrame();
#define NDS_SkipFrame(s) if(s) NDS_SkipNext2DFrame();
void NDS_OmitFrameSkip(int force=0);
void NDS_debug_break();
void NDS_debug_continue();
void NDS_debug_step();
int NDS_GetCPUCoreCount();
void NDS_GetCPULoadAverage(u32 &outLoadAvgARM9, u32 &outLoadAvgARM7);
void NDS_SetupDefaultFirmware();
//void execHardware_doAllDma(EDMAMode modeNum);
template<bool FORCE> void NDS_exec(s32 nb = 560190<<1);
extern int lagframecounter;
extern struct TCommonSettings
{
TCommonSettings()
: GFX3D_HighResolutionInterpolateColor(true)
, GFX3D_EdgeMark(true)
, GFX3D_Fog(true)
, GFX3D_Texture(true)
, GFX3D_LineHack(true)
, GFX3D_Renderer_MultisampleSize(0)
, GFX3D_Renderer_TextureScalingFactor(1) // Possible values: 1, 2, 4
, GFX3D_Renderer_TextureDeposterize(false)
, GFX3D_Renderer_TextureSmoothing(false)
, GFX3D_TXTHack(false)
, OpenGL_Emulation_ShadowPolygon(true)
, OpenGL_Emulation_SpecialZeroAlphaBlending(true)
, OpenGL_Emulation_NDSDepthCalculation(true)
, OpenGL_Emulation_DepthLEqualPolygonFacing(false)
, jit_max_block_size(12)
, loadToMemory(false)
, UseExtBIOS(false)
, SWIFromBIOS(false)
, PatchSWI3(false)
, UseExtFirmware(false)
, UseExtFirmwareSettings(false)
, RetailCardProtection8000(true)
, BootFromFirmware(false)
, DebugConsole(false)
, EnsataEmulation(false)
, cheatsDisable(false)
, rigorous_timing(false)
, advanced_timing(true)
, micMode(InternalNoise)
, spuInterpolationMode(2)
, manualBackupType(0)
, autodetectBackupMethod(0)
, spu_captureMuted(false)
, spu_advanced(true)
, StylusPressure(50)
, ConsoleType(NDS_CONSOLE_TYPE_FAT)
, backupSave(false)
, SPU_sync_mode(1)
, SPU_sync_method(0)
, WifiBridgeDeviceID(0)
{
strcpy(ARM9BIOS, "biosnds9.bin");
strcpy(ARM7BIOS, "biosnds7.bin");
strcpy(ExtFirmwarePath, "firmware.bin");
for(int i=0;i<16;i++)
spu_muteChannels[i] = false;
for(int g=0;g<2;g++)
for(int x=0;x<5;x++)
dispLayers[g][x]=true;
#ifdef HAVE_JIT
//zero 06-sep-2012 - shouldnt be defaulting this to true for now, since the jit is buggy.
//id rather have people discover a bonus speedhack than discover new bugs in a new version
use_jit = false;
#else
use_jit = false;
#endif
num_cores = NDS_GetCPUCoreCount();
NDS_SetupDefaultFirmware();
}
bool GFX3D_HighResolutionInterpolateColor;
bool GFX3D_EdgeMark;
bool GFX3D_Fog;
bool GFX3D_Texture;
bool GFX3D_LineHack;
int GFX3D_Renderer_MultisampleSize;
int GFX3D_Renderer_TextureScalingFactor; //must be one of {1,2,4}
bool GFX3D_Renderer_TextureDeposterize;
bool GFX3D_Renderer_TextureSmoothing;
bool GFX3D_TXTHack;
bool OpenGL_Emulation_ShadowPolygon;
bool OpenGL_Emulation_SpecialZeroAlphaBlending;
bool OpenGL_Emulation_NDSDepthCalculation;
bool OpenGL_Emulation_DepthLEqualPolygonFacing;
bool loadToMemory;
bool UseExtBIOS;
char ARM9BIOS[MAX_PATH];
char ARM7BIOS[MAX_PATH];
bool SWIFromBIOS;
bool PatchSWI3;
bool RetailCardProtection8000;
bool UseExtFirmware;
bool UseExtFirmwareSettings;
char ExtFirmwarePath[MAX_PATH];
char ExtFirmwareUserSettingsPath[MAX_PATH];
bool BootFromFirmware;
FirmwareConfig fwConfig;
NDS_CONSOLE_TYPE ConsoleType;
bool DebugConsole;
bool EnsataEmulation;
bool cheatsDisable;
int num_cores;
bool single_core() { return num_cores==1; }
bool rigorous_timing;
struct GameHacks {
GameHacks()
: en(true)
{
clear();
}
bool en;
struct {
bool overclock;
bool stylusjitter;
} flags;
void apply();
void clear();
} gamehacks;
int StylusPressure;
bool dispLayers[2][5];
FAST_ALIGN bool advanced_timing;
bool use_jit;
u32 jit_max_block_size;
int WifiBridgeDeviceID;
enum MicMode
{
InternalNoise = 0,
Sample = 1,
Random = 2,
Physical = 3
} micMode;
int spuInterpolationMode;
//this is a temporary hack until we straighten out the flushing logic and/or gxfifo
//int gfx3d_flushMode;
int autodetectBackupMethod;
//this is the user's choice of manual backup type, for cases when the autodetection can't be trusted
int manualBackupType;
bool backupSave;
int SPU_sync_mode;
int SPU_sync_method;
bool spu_muteChannels[16];
bool spu_captureMuted;
bool spu_advanced;
struct _ShowGpu {
_ShowGpu() : main(true), sub(true) {}
union {
struct { bool main,sub; };
bool screens[2];
};
} showGpu;
struct _Hud {
_Hud()
: ShowInputDisplay(false)
, ShowGraphicalInputDisplay(false)
, FpsDisplay(false)
, FrameCounterDisplay(false)
, ShowLagFrameCounter(false)
, ShowMicrophone(false)
, ShowRTC(false)
{}
bool ShowInputDisplay, ShowGraphicalInputDisplay, FpsDisplay, FrameCounterDisplay, ShowLagFrameCounter, ShowMicrophone, ShowRTC;
} hud;
std::string run_advanscene_import;
} CommonSettings;
void NDS_RunAdvansceneAutoImport();
extern std::string InputDisplayString;
extern int LagFrameFlag;
extern int lastLag, TotalLagFrames;
extern u8 MicSampleSelection;
extern std::vector< std::vector<u8> > micSamples;
void MovieSRAM();
void ClearAutoHold(void);
bool ValidateSlot2Access(u32 procnum, u32 demandSRAMSpeed, u32 demand1stROMSpeed, u32 demand2ndROMSpeed, int clockbits);
//MUSTANG
//extern ADVANsCEne advsc;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,919 +0,0 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2019 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OGLRENDER_H
#define OGLRENDER_H
#include <map>
#include <queue>
#include <set>
#include <string>
#include "render3D.h"
#include "types.h"
#ifndef OGLRENDER_3_2_H
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/gl.h>
#include <GL/glext.h>
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)wglGetProcAddress(#func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#elif defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
// Ignore dynamic linking on Apple OS
#define OGLEXT(procPtr, func)
#define INITOGLEXT(procPtr, func)
#define EXTERNOGLEXT(procPtr, func)
// We're not exactly committing to OpenGL 3.2 Core Profile just yet, so redefine APPLE
// extensions as a temporary measure.
#if defined(GL_APPLE_vertex_array_object) && !defined(GL_ARB_vertex_array_object)
#define glGenVertexArrays(n, ids) glGenVertexArraysAPPLE(n, ids)
#define glBindVertexArray(id) glBindVertexArrayAPPLE(id)
#define glDeleteVertexArrays(n, ids) glDeleteVertexArraysAPPLE(n, ids)
#endif
#else
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glx.h>
/* This is a workaround needed to compile against nvidia GL headers */
#ifndef GL_ALPHA_BLEND_EQUATION_ATI
#undef GL_VERSION_1_3
#endif
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)glXGetProcAddress((const GLubyte *) #func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#endif
// Check minimum OpenGL header version
#if !defined(GL_VERSION_2_1)
#if defined(GL_VERSION_2_0)
#warning Using OpenGL v2.0 headers with v2.1 overrides. Some features will be disabled.
#if !defined(GL_ARB_framebuffer_object)
// Overrides for GL_EXT_framebuffer_blit
#if !defined(GL_EXT_framebuffer_blit)
#define GL_READ_FRAMEBUFFER_EXT GL_FRAMEBUFFER_EXT
#define GL_DRAW_FRAMEBUFFER_EXT GL_FRAMEBUFFER_EXT
#define glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter)
#endif
// Overrides for GL_EXT_framebuffer_multisample
#if !defined(GL_EXT_framebuffer_multisample)
#define GL_MAX_SAMPLES_EXT 0
#define glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height)
#endif
// Overrides for GL_ARB_pixel_buffer_object
#if !defined(GL_PIXEL_PACK_BUFFER) && defined(GL_PIXEL_PACK_BUFFER_ARB)
#define GL_PIXEL_PACK_BUFFER GL_PIXEL_PACK_BUFFER_ARB
#endif
#endif
#else
#error OpenGL requires v2.1 headers or later.
#endif
#endif
// Textures
#if !defined(GLX_H)
EXTERNOGLEXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) // Core in v1.3
EXTERNOGLEXT(PFNGLACTIVETEXTUREARBPROC, glActiveTextureARB)
#endif
// Blending
#if !defined(GLX_H)
EXTERNOGLEXT(PFNGLBLENDEQUATIONPROC, glBlendEquation) // Core in v1.2
#endif
EXTERNOGLEXT(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate) // Core in v1.4
EXTERNOGLEXT(PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate) // Core in v2.0
EXTERNOGLEXT(PFNGLBLENDFUNCSEPARATEEXTPROC, glBlendFuncSeparateEXT)
EXTERNOGLEXT(PFNGLBLENDEQUATIONSEPARATEEXTPROC, glBlendEquationSeparateEXT)
// Shaders
EXTERNOGLEXT(PFNGLCREATESHADERPROC, glCreateShader) // Core in v2.0
EXTERNOGLEXT(PFNGLSHADERSOURCEPROC, glShaderSource) // Core in v2.0
EXTERNOGLEXT(PFNGLCOMPILESHADERPROC, glCompileShader) // Core in v2.0
EXTERNOGLEXT(PFNGLCREATEPROGRAMPROC, glCreateProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLATTACHSHADERPROC, glAttachShader) // Core in v2.0
EXTERNOGLEXT(PFNGLDETACHSHADERPROC, glDetachShader) // Core in v2.0
EXTERNOGLEXT(PFNGLLINKPROGRAMPROC, glLinkProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLUSEPROGRAMPROC, glUseProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETSHADERIVPROC, glGetShaderiv) // Core in v2.0
EXTERNOGLEXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) // Core in v2.0
EXTERNOGLEXT(PFNGLDELETESHADERPROC, glDeleteShader) // Core in v2.0
EXTERNOGLEXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv) // Core in v2.0
EXTERNOGLEXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) // Core in v2.0
EXTERNOGLEXT(PFNGLVALIDATEPROGRAMPROC, glValidateProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1IPROC, glUniform1i) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1IVPROC, glUniform1iv) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1FPROC, glUniform1f) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1FVPROC, glUniform1fv) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM2FPROC, glUniform2f) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM4FPROC, glUniform4f) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM4FVPROC, glUniform4fv) // Core in v2.0
EXTERNOGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0
// Generic vertex attributes
EXTERNOGLEXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) // Core in v2.0
EXTERNOGLEXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) // Core in v2.0
EXTERNOGLEXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) // Core in v2.0
EXTERNOGLEXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) // Core in v2.0
// VAO
EXTERNOGLEXT(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays)
EXTERNOGLEXT(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays)
EXTERNOGLEXT(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray)
// VBO and PBO
EXTERNOGLEXT(PFNGLGENBUFFERSARBPROC, glGenBuffersARB)
EXTERNOGLEXT(PFNGLDELETEBUFFERSARBPROC, glDeleteBuffersARB)
EXTERNOGLEXT(PFNGLBINDBUFFERARBPROC, glBindBufferARB)
EXTERNOGLEXT(PFNGLBUFFERDATAARBPROC, glBufferDataARB)
EXTERNOGLEXT(PFNGLBUFFERSUBDATAARBPROC, glBufferSubDataARB)
EXTERNOGLEXT(PFNGLMAPBUFFERARBPROC, glMapBufferARB)
EXTERNOGLEXT(PFNGLUNMAPBUFFERARBPROC, glUnmapBufferARB)
EXTERNOGLEXT(PFNGLGENBUFFERSPROC, glGenBuffers) // Core in v1.5
EXTERNOGLEXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) // Core in v1.5
EXTERNOGLEXT(PFNGLBINDBUFFERPROC, glBindBuffer) // Core in v1.5
EXTERNOGLEXT(PFNGLBUFFERDATAPROC, glBufferData) // Core in v1.5
EXTERNOGLEXT(PFNGLBUFFERSUBDATAPROC, glBufferSubData) // Core in v1.5
EXTERNOGLEXT(PFNGLMAPBUFFERPROC, glMapBuffer) // Core in v1.5
EXTERNOGLEXT(PFNGLUNMAPBUFFERPROC, glUnmapBuffer) // Core in v1.5
// FBO
EXTERNOGLEXT(PFNGLGENFRAMEBUFFERSEXTPROC, glGenFramebuffersEXT)
EXTERNOGLEXT(PFNGLBINDFRAMEBUFFEREXTPROC, glBindFramebufferEXT)
EXTERNOGLEXT(PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC, glFramebufferRenderbufferEXT)
EXTERNOGLEXT(PFNGLFRAMEBUFFERTEXTURE2DEXTPROC, glFramebufferTexture2DEXT)
EXTERNOGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC, glCheckFramebufferStatusEXT)
EXTERNOGLEXT(PFNGLDELETEFRAMEBUFFERSEXTPROC, glDeleteFramebuffersEXT)
EXTERNOGLEXT(PFNGLBLITFRAMEBUFFEREXTPROC, glBlitFramebufferEXT)
// Multisampled FBO
EXTERNOGLEXT(PFNGLGENRENDERBUFFERSEXTPROC, glGenRenderbuffersEXT)
EXTERNOGLEXT(PFNGLBINDRENDERBUFFEREXTPROC, glBindRenderbufferEXT)
EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEEXTPROC, glRenderbufferStorageEXT)
EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC, glRenderbufferStorageMultisampleEXT)
EXTERNOGLEXT(PFNGLDELETERENDERBUFFERSEXTPROC, glDeleteRenderbuffersEXT)
#else // OGLRENDER_3_2_H
// Basic Functions
EXTERNOGLEXT(PFNGLGETSTRINGIPROC, glGetStringi) // Core in v3.0
EXTERNOGLEXT(PFNGLCLEARBUFFERFVPROC, glClearBufferfv) // Core in v3.0
EXTERNOGLEXT(PFNGLCLEARBUFFERFIPROC, glClearBufferfi) // Core in v3.0
// Textures
#if !defined(GLX_H)
EXTERNOGLEXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) // Core in v1.3
#endif
// Blending
#if !defined(GLX_H)
EXTERNOGLEXT(PFNGLBLENDEQUATIONPROC, glBlendEquation) // Core in v1.2
#endif
EXTERNOGLEXT(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate) // Core in v1.4
EXTERNOGLEXT(PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate) // Core in v2.0
// Shaders
EXTERNOGLEXT(PFNGLCREATESHADERPROC, glCreateShader) // Core in v2.0
EXTERNOGLEXT(PFNGLSHADERSOURCEPROC, glShaderSource) // Core in v2.0
EXTERNOGLEXT(PFNGLCOMPILESHADERPROC, glCompileShader) // Core in v2.0
EXTERNOGLEXT(PFNGLCREATEPROGRAMPROC, glCreateProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLATTACHSHADERPROC, glAttachShader) // Core in v2.0
EXTERNOGLEXT(PFNGLDETACHSHADERPROC, glDetachShader) // Core in v2.0
EXTERNOGLEXT(PFNGLLINKPROGRAMPROC, glLinkProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLUSEPROGRAMPROC, glUseProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETSHADERIVPROC, glGetShaderiv) // Core in v2.0
EXTERNOGLEXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) // Core in v2.0
EXTERNOGLEXT(PFNGLDELETESHADERPROC, glDeleteShader) // Core in v2.0
EXTERNOGLEXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv) // Core in v2.0
EXTERNOGLEXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) // Core in v2.0
EXTERNOGLEXT(PFNGLVALIDATEPROGRAMPROC, glValidateProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1IPROC, glUniform1i) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1IVPROC, glUniform1iv) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1FPROC, glUniform1f) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1FVPROC, glUniform1fv) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM2FPROC, glUniform2f) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM4FPROC, glUniform4f) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM4FVPROC, glUniform4fv) // Core in v2.0
EXTERNOGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0
// Generic vertex attributes
EXTERNOGLEXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) // Core in v2.0
EXTERNOGLEXT(PFNGLBINDFRAGDATALOCATIONPROC, glBindFragDataLocation) // Core in v3.0
EXTERNOGLEXT(PFNGLBINDFRAGDATALOCATIONINDEXEDPROC, glBindFragDataLocationIndexed) // Core in v3.3
EXTERNOGLEXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) // Core in v2.0
EXTERNOGLEXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) // Core in v2.0
EXTERNOGLEXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) // Core in v2.0
// VAO
EXTERNOGLEXT(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays) // Core in v3.0
EXTERNOGLEXT(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays) // Core in v3.0
EXTERNOGLEXT(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray) // Core in v3.0
// VBO and PBO
EXTERNOGLEXT(PFNGLGENBUFFERSPROC, glGenBuffers) // Core in v1.5
EXTERNOGLEXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) // Core in v1.5
EXTERNOGLEXT(PFNGLBINDBUFFERPROC, glBindBuffer) // Core in v1.5
EXTERNOGLEXT(PFNGLBUFFERDATAPROC, glBufferData) // Core in v1.5
EXTERNOGLEXT(PFNGLBUFFERSUBDATAPROC, glBufferSubData) // Core in v1.5
EXTERNOGLEXT(PFNGLMAPBUFFERPROC, glMapBuffer) // Core in v1.5
EXTERNOGLEXT(PFNGLUNMAPBUFFERPROC, glUnmapBuffer) // Core in v1.5
// Buffer Objects
EXTERNOGLEXT(PFNGLMAPBUFFERRANGEPROC, glMapBufferRange) // Core in v3.0
// FBO
EXTERNOGLEXT(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) // Core in v3.0
EXTERNOGLEXT(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) // Core in v3.0
EXTERNOGLEXT(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer) // Core in v3.0
EXTERNOGLEXT(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D) // Core in v3.0
EXTERNOGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) // Core in v3.0
EXTERNOGLEXT(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers) // Core in v3.0
EXTERNOGLEXT(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer) // Core in v3.0
EXTERNOGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0
// Multisampled FBO
EXTERNOGLEXT(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers) // Core in v3.0
EXTERNOGLEXT(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer) // Core in v3.0
EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) // Core in v3.0
EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample) // Core in v3.0
EXTERNOGLEXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) // Core in v3.0
EXTERNOGLEXT(PFNGLTEXIMAGE2DMULTISAMPLEPROC, glTexImage2DMultisample) // Core in v3.2
// UBO
EXTERNOGLEXT(PFNGLGETUNIFORMBLOCKINDEXPROC, glGetUniformBlockIndex) // Core in v3.1
EXTERNOGLEXT(PFNGLUNIFORMBLOCKBINDINGPROC, glUniformBlockBinding) // Core in v3.1
EXTERNOGLEXT(PFNGLBINDBUFFERBASEPROC, glBindBufferBase) // Core in v3.0
EXTERNOGLEXT(PFNGLGETACTIVEUNIFORMBLOCKIVPROC, glGetActiveUniformBlockiv) // Core in v3.1
// TBO
EXTERNOGLEXT(PFNGLTEXBUFFERPROC, glTexBuffer) // Core in v3.1
// Sync Objects
EXTERNOGLEXT(PFNGLFENCESYNCPROC, glFenceSync) // Core in v3.2
EXTERNOGLEXT(PFNGLWAITSYNCPROC, glWaitSync) // Core in v3.2
EXTERNOGLEXT(PFNGLDELETESYNCPROC, glDeleteSync) // Core in v3.2
#endif // OGLRENDER_3_2_H
// Define the minimum required OpenGL version for the driver to support
#define OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MAJOR 1
#define OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MINOR 2
#define OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_REVISION 0
#define OGLRENDER_VERT_INDEX_BUFFER_COUNT (POLYLIST_SIZE * 6)
// Assign the FBO attachments for the main geometry render
#ifdef OGLRENDER_3_2_H
#define GL_COLOROUT_ATTACHMENT_ID GL_COLOR_ATTACHMENT0
#define GL_WORKING_ATTACHMENT_ID GL_COLOR_ATTACHMENT3
#define GL_POLYID_ATTACHMENT_ID GL_COLOR_ATTACHMENT1
#define GL_FOGATTRIBUTES_ATTACHMENT_ID GL_COLOR_ATTACHMENT2
#else
#define GL_COLOROUT_ATTACHMENT_ID GL_COLOR_ATTACHMENT0_EXT
#define GL_WORKING_ATTACHMENT_ID GL_COLOR_ATTACHMENT3_EXT
#define GL_POLYID_ATTACHMENT_ID GL_COLOR_ATTACHMENT1_EXT
#define GL_FOGATTRIBUTES_ATTACHMENT_ID GL_COLOR_ATTACHMENT2_EXT
#endif
enum OGLVertexAttributeID
{
OGLVertexAttributeID_Position = 0,
OGLVertexAttributeID_TexCoord0 = 8,
OGLVertexAttributeID_Color = 3
};
enum OGLTextureUnitID
{
// Main textures will always be on texture unit 0.
OGLTextureUnitID_FinalColor = 1,
OGLTextureUnitID_GColor,
OGLTextureUnitID_DepthStencil,
OGLTextureUnitID_GPolyID,
OGLTextureUnitID_FogAttr,
OGLTextureUnitID_PolyStates
};
enum OGLBindingPointID
{
OGLBindingPointID_RenderStates = 0,
OGLBindingPointID_PolyStates = 1
};
enum OGLErrorCode
{
OGLERROR_NOERR = RENDER3DERROR_NOERR,
OGLERROR_DRIVER_VERSION_TOO_OLD,
OGLERROR_BEGINGL_FAILED,
OGLERROR_CLIENT_RESIZE_ERROR,
OGLERROR_FEATURE_UNSUPPORTED,
OGLERROR_VBO_UNSUPPORTED,
OGLERROR_PBO_UNSUPPORTED,
OGLERROR_SHADER_UNSUPPORTED,
OGLERROR_VAO_UNSUPPORTED,
OGLERROR_FBO_UNSUPPORTED,
OGLERROR_MULTISAMPLED_FBO_UNSUPPORTED,
OGLERROR_VERTEX_SHADER_PROGRAM_LOAD_ERROR,
OGLERROR_FRAGMENT_SHADER_PROGRAM_LOAD_ERROR,
OGLERROR_SHADER_CREATE_ERROR,
OGLERROR_FBO_CREATE_ERROR
};
enum OGLPolyDrawMode
{
OGLPolyDrawMode_DrawOpaquePolys = 0,
OGLPolyDrawMode_DrawTranslucentPolys = 1,
OGLPolyDrawMode_ZeroAlphaPass = 2
};
union GLvec2
{
struct { GLfloat x, y; };
GLfloat v[2];
};
union GLvec3
{
struct { GLfloat r, g, b; };
struct { GLfloat x, y, z; };
GLfloat v[3];
};
union GLvec4
{
struct { GLfloat r, g, b, a; };
struct { GLfloat x, y, z, w; };
GLfloat v[4];
};
struct OGLVertex
{
GLvec4 position;
GLvec2 texCoord;
GLvec3 color;
};
struct OGLRenderStates
{
GLuint enableAntialiasing;
GLuint enableFogAlphaOnly;
GLuint clearPolyID;
GLfloat clearDepth;
GLfloat alphaTestRef;
GLfloat fogOffset;
GLfloat fogStep;
GLfloat pad_0; // This needs to be here to preserve alignment
GLfloat fogDensity[32];
GLvec4 fogColor;
GLvec4 edgeColor[8];
GLvec4 toonColor[32];
};
union OGLPolyStates
{
u32 packedState;
struct
{
u8 PolygonID:6;
u8 PolygonMode:2;
u8 PolygonAlpha:5;
u8 IsWireframe:1;
u8 EnableFog:1;
u8 SetNewDepthForTranslucent:1;
u8 EnableTexture:1;
u8 TexSingleBitAlpha:1;
u8 TexSizeShiftS:3;
u8 TexSizeShiftT:3;
u8 :8;
};
};
union OGLGeometryFlags
{
u8 value;
struct
{
#ifndef MSB_FIRST
u8 EnableWDepth:1;
u8 EnableAlphaTest:1;
u8 EnableTextureSampling:1;
u8 ToonShadingMode:1;
u8 NeedsDepthEqualsTest:1;
u8 EnableFog:1;
u8 EnableEdgeMark:1;
u8 OpaqueDrawMode:1;
#else
u8 OpaqueDrawMode:1;
u8 EnableEdgeMark:1;
u8 EnableFog:1;
u8 NeedsDepthEqualsTest:1;
u8 ToonShadingMode:1;
u8 EnableTextureSampling:1;
u8 EnableAlphaTest:1;
u8 EnableWDepth:1;
#endif
};
struct
{
u8 :5;
u8 DrawBuffersMode:3;
};
};
typedef OGLGeometryFlags OGLGeometryFlags;
union OGLFogProgramKey
{
u32 key;
struct
{
u16 offset;
u8 shift;
u8 :8;
};
};
typedef OGLFogProgramKey OGLFogProgramKey;
struct OGLFogShaderID
{
GLuint program;
GLuint fragShader;
};
typedef OGLFogShaderID OGLFogShaderID;
struct OGLRenderRef
{
// OpenGL Feature Support
GLint stateTexMirroredRepeat;
// VBO
GLuint vboGeometryVtxID;
GLuint iboGeometryIndexID;
GLuint vboPostprocessVtxID;
// PBO
GLuint pboRenderDataID;
// UBO / TBO
GLuint uboRenderStatesID;
GLuint uboPolyStatesID;
GLuint tboPolyStatesID;
GLuint texPolyStatesID;
// FBO
GLuint texCIColorID;
GLuint texCIFogAttrID;
GLuint texCIDepthStencilID;
GLuint texGColorID;
GLuint texGFogAttrID;
GLuint texGPolyID;
GLuint texGDepthStencilID;
GLuint texFinalColorID;
GLuint texMSGColorID;
GLuint texMSGWorkingID;
GLuint rboMSGColorID;
GLuint rboMSGWorkingID;
GLuint rboMSGPolyID;
GLuint rboMSGFogAttrID;
GLuint rboMSGDepthStencilID;
GLuint fboClearImageID;
GLuint fboRenderID;
GLuint fboMSIntermediateRenderID;
GLuint selectedRenderingFBO;
// Shader states
GLuint vertexGeometryShaderID;
GLuint fragmentGeometryShaderID[256];
GLuint programGeometryID[256];
GLuint vtxShaderGeometryZeroDstAlphaID;
GLuint fragShaderGeometryZeroDstAlphaID;
GLuint programGeometryZeroDstAlphaID;
GLuint vtxShaderMSGeometryZeroDstAlphaID;
GLuint fragShaderMSGeometryZeroDstAlphaID;
GLuint programMSGeometryZeroDstAlphaID;
GLuint vertexEdgeMarkShaderID;
GLuint vertexFogShaderID;
GLuint vertexFramebufferOutput6665ShaderID;
GLuint vertexFramebufferOutput8888ShaderID;
GLuint fragmentEdgeMarkShaderID;
GLuint fragmentFramebufferRGBA6665OutputShaderID;
GLuint fragmentFramebufferRGBA8888OutputShaderID;
GLuint programEdgeMarkID;
GLuint programFramebufferRGBA6665OutputID[2];
GLuint programFramebufferRGBA8888OutputID[2];
GLint uniformStateEnableFogAlphaOnly;
GLint uniformStateClearPolyID;
GLint uniformStateClearDepth;
GLint uniformStateEdgeColor;
GLint uniformStateFogColor;
GLint uniformStateFogDensity;
GLint uniformStateAlphaTestRef[256];
GLint uniformStateToonColor[256];
GLint uniformPolyTexScale[256];
GLint uniformPolyMode[256];
GLint uniformPolyIsWireframe[256];
GLint uniformPolySetNewDepthForTranslucent[256];
GLint uniformPolyAlpha[256];
GLint uniformPolyID[256];
GLint uniformPolyEnableTexture[256];
GLint uniformPolyEnableFog[256];
GLint uniformTexSingleBitAlpha[256];
GLint uniformTexDrawOpaque[256];
GLint uniformDrawModeDepthEqualsTest[256];
GLint uniformPolyStateIndex[256];
GLint uniformPolyDepthOffsetMode[256];
GLint uniformPolyDrawShadow[256];
// VAO
GLuint vaoGeometryStatesID;
GLuint vaoPostprocessStatesID;
// Client-side Buffers
GLfloat *color4fBuffer;
CACHE_ALIGN GLushort vertIndexBuffer[OGLRENDER_VERT_INDEX_BUFFER_COUNT];
CACHE_ALIGN GLushort workingCIColorBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
CACHE_ALIGN GLuint workingCIDepthStencilBuffer[2][GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
CACHE_ALIGN GLuint workingCIFogAttributesBuffer[2][GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
// Vertex Attributes Pointers
GLvoid *vtxPtrPosition;
GLvoid *vtxPtrTexCoord;
GLvoid *vtxPtrColor;
};
struct GFX3D_State;
struct POLYLIST;
struct INDEXLIST;
struct POLY;
class OpenGLRenderer;
extern GPU3DInterface gpu3Dgl;
extern GPU3DInterface gpu3DglOld;
extern GPU3DInterface gpu3Dgl_3_2;
extern const GLenum GeometryDrawBuffersEnum[8][4];
extern const GLint GeometryAttachmentWorkingBuffer[8];
extern const GLint GeometryAttachmentPolyID[8];
extern const GLint GeometryAttachmentFogAttributes[8];
extern CACHE_ALIGN const GLfloat divide5bitBy31_LUT[32];
extern CACHE_ALIGN const GLfloat divide6bitBy63_LUT[64];
extern const GLfloat PostprocessVtxBuffer[16];
extern const GLubyte PostprocessElementBuffer[6];
//This is called by OGLRender whenever it initializes.
//Platforms, please be sure to set this up.
//return true if you successfully init.
extern bool (*oglrender_init)();
//This is called by OGLRender before it uses opengl.
//return true if youre OK with using opengl
extern bool (*oglrender_beginOpenGL)();
//This is called by OGLRender after it is done using opengl.
extern void (*oglrender_endOpenGL)();
//This is called by OGLRender whenever the framebuffer is resized.
extern bool (*oglrender_framebufferDidResizeCallback)(const bool isFBOSupported, size_t w, size_t h);
// Helper functions for calling the above function pointers at the
// beginning and ending of OpenGL commands.
bool BEGINGL();
void ENDGL();
// These functions need to be assigned by ports that support using an
// OpenGL 3.2 Core Profile context. The OGLRender_3_2.cpp file includes
// the corresponding functions to assign to each function pointer.
//
// If any of these functions are unassigned, then one of the legacy OpenGL
// renderers will be used instead.
extern void (*OGLLoadEntryPoints_3_2_Func)();
extern void (*OGLCreateRenderer_3_2_Func)(OpenGLRenderer **rendererPtr);
bool IsOpenGLDriverVersionSupported(unsigned int checkVersionMajor, unsigned int checkVersionMinor, unsigned int checkVersionRevision);
class OpenGLTexture : public Render3DTexture
{
protected:
GLuint _texID;
GLfloat _invSizeS;
GLfloat _invSizeT;
bool _isTexInited;
u32 *_upscaleBuffer;
public:
OpenGLTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes);
virtual ~OpenGLTexture();
virtual void Load(bool forceTextureInit);
GLuint GetID() const;
GLfloat GetInvWidth() const;
GLfloat GetInvHeight() const;
void SetUnpackBuffer(void *unpackBuffer);
void SetDeposterizeBuffer(void *dstBuffer, void *workingBuffer);
void SetUpscalingBuffer(void *upscaleBuffer);
};
#if defined(ENABLE_AVX)
class OpenGLRenderer : public Render3D_AVX
#elif defined(ENABLE_SSE2)
class OpenGLRenderer : public Render3D_SSE2
#elif defined(ENABLE_ALTIVEC)
class OpenGLRenderer : public Render3D_Altivec
#else
class OpenGLRenderer : public Render3D
#endif
{
private:
// Driver's OpenGL Version
unsigned int versionMajor;
unsigned int versionMinor;
unsigned int versionRevision;
private:
Render3DError _FlushFramebufferFlipAndConvertOnCPU(const FragmentColor *__restrict srcFramebuffer,
FragmentColor *__restrict dstFramebufferMain, u16 *__restrict dstFramebuffer16,
bool doFramebufferFlip, bool doFramebufferConvert);
protected:
// OpenGL-specific References
OGLRenderRef *ref;
// OpenGL Feature Support
bool isVBOSupported;
bool isPBOSupported;
bool isFBOSupported;
bool isMultisampledFBOSupported;
bool isShaderSupported;
bool isVAOSupported;
bool willFlipOnlyFramebufferOnGPU;
bool willFlipAndConvertFramebufferOnGPU;
bool willUsePerSampleZeroDstPass;
bool _emulateShadowPolygon;
bool _emulateSpecialZeroAlphaBlending;
bool _emulateNDSDepthCalculation;
bool _emulateDepthLEqualPolygonFacing;
FragmentColor *_mappedFramebuffer;
FragmentColor *_workingTextureUnpackBuffer;
bool _pixelReadNeedsFinish;
bool _needsZeroDstAlphaPass;
size_t _currentPolyIndex;
bool _enableAlphaBlending;
OGLTextureUnitID _lastTextureDrawTarget;
OGLGeometryFlags _geometryProgramFlags;
OGLFogProgramKey _fogProgramKey;
std::map<u32, OGLFogShaderID> _fogProgramMap;
CACHE_ALIGN OGLRenderStates _pendingRenderStates;
bool _enableMultisampledRendering;
int _selectedMultisampleSize;
bool _isPolyFrontFacing[POLYLIST_SIZE];
size_t _clearImageIndex;
Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebufferMain, u16 *__restrict dstFramebuffer16);
OpenGLTexture* GetLoadedTextureFromPolygon(const POLY &thePoly, bool enableTexturing);
template<OGLPolyDrawMode DRAWMODE> size_t DrawPolygonsForIndexRange(const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template<OGLPolyDrawMode DRAWMODE> Render3DError DrawAlphaTexturePolygon(const GLenum polyPrimitive,
const GLsizei vertIndexCount,
const GLushort *indexBufferPtr,
const bool performDepthEqualTest,
const bool enableAlphaDepthWrite,
const bool canHaveOpaqueFragments,
const u8 opaquePolyID,
const bool isPolyFrontFacing);
template<OGLPolyDrawMode DRAWMODE> Render3DError DrawOtherPolygon(const GLenum polyPrimitive,
const GLsizei vertIndexCount,
const GLushort *indexBufferPtr,
const bool performDepthEqualTest,
const bool enableAlphaDepthWrite,
const u8 opaquePolyID,
const bool isPolyFrontFacing);
// OpenGL-specific methods
virtual Render3DError CreateVBOs() = 0;
virtual void DestroyVBOs() = 0;
virtual Render3DError CreatePBOs() = 0;
virtual void DestroyPBOs() = 0;
virtual Render3DError CreateFBOs() = 0;
virtual void DestroyFBOs() = 0;
virtual Render3DError CreateMultisampledFBO(GLsizei numSamples) = 0;
virtual void DestroyMultisampledFBO() = 0;
virtual void ResizeMultisampledFBOs(GLsizei numSamples) = 0;
virtual Render3DError CreateVAOs() = 0;
virtual void DestroyVAOs() = 0;
virtual Render3DError CreateGeometryPrograms() = 0;
virtual void DestroyGeometryPrograms() = 0;
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString) = 0;
virtual void DestroyGeometryZeroDstAlphaProgram() = 0;
virtual Render3DError CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString) = 0;
virtual void DestroyEdgeMarkProgram() = 0;
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString) = 0;
virtual void DestroyFogProgram(const OGLFogProgramKey fogProgramKey) = 0;
virtual void DestroyFogPrograms() = 0;
virtual Render3DError CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString) = 0;
virtual void DestroyFramebufferOutput6665Programs() = 0;
virtual Render3DError CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString) = 0;
virtual void DestroyFramebufferOutput8888Programs() = 0;
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet) = 0;
virtual Render3DError InitPostprocessingPrograms(const char *edgeMarkVtxShader,
const char *edgeMarkFragShader,
const char *framebufferOutputVtxShader,
const char *framebufferOutputRGBA6665FragShader,
const char *framebufferOutputRGBA8888FragShader) = 0;
virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID) = 0;
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet) = 0;
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags) = 0;
virtual Render3DError EnableVertexAttributes() = 0;
virtual Render3DError DisableVertexAttributes() = 0;
virtual void _ResolveWorkingBackFacing() = 0;
virtual void _ResolveGeometry() = 0;
virtual Render3DError ReadBackPixels() = 0;
virtual Render3DError DrawShadowPolygon(const GLenum polyPrimitive, const GLsizei vertIndexCount, const GLushort *indexBufferPtr, const bool performDepthEqualTest, const bool enableAlphaDepthWrite, const bool isTranslucent, const u8 opaquePolyID) = 0;
virtual void SetPolygonIndex(const size_t index) = 0;
virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer) = 0;
public:
OpenGLRenderer();
virtual ~OpenGLRenderer();
virtual Render3DError InitExtensions() = 0;
bool IsExtensionPresent(const std::set<std::string> *oglExtensionSet, const std::string extensionName) const;
Render3DError ShaderProgramCreate(GLuint &vtxShaderID,
GLuint &fragShaderID,
GLuint &programID,
const char *vtxShaderCString,
const char *fragShaderCString);
bool ValidateShaderCompile(GLenum shaderType, GLuint theShader) const;
bool ValidateShaderProgramLink(GLuint theProgram) const;
void GetVersion(unsigned int *major, unsigned int *minor, unsigned int *revision) const;
void SetVersion(unsigned int major, unsigned int minor, unsigned int revision);
bool IsVersionSupported(unsigned int checkVersionMajor, unsigned int checkVersionMinor, unsigned int checkVersionRevision) const;
virtual FragmentColor* GetFramebuffer();
virtual GLsizei GetLimitedMultisampleSize() const;
Render3DError ApplyRenderingSettings(const GFX3D_State &renderState);
};
class OpenGLRenderer_1_2 : public OpenGLRenderer
{
protected:
// OpenGL-specific methods
virtual Render3DError CreateVBOs();
virtual void DestroyVBOs();
virtual Render3DError CreatePBOs();
virtual void DestroyPBOs();
virtual Render3DError CreateFBOs();
virtual void DestroyFBOs();
virtual Render3DError CreateMultisampledFBO(GLsizei numSamples);
virtual void DestroyMultisampledFBO();
virtual void ResizeMultisampledFBOs(GLsizei numSamples);
virtual Render3DError CreateVAOs();
virtual void DestroyVAOs();
virtual Render3DError CreateGeometryPrograms();
virtual void DestroyGeometryPrograms();
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual void DestroyGeometryZeroDstAlphaProgram();
virtual Render3DError CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual void DestroyEdgeMarkProgram();
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString);
virtual void DestroyFogProgram(const OGLFogProgramKey fogProgramKey);
virtual void DestroyFogPrograms();
virtual Render3DError CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString);
virtual void DestroyFramebufferOutput6665Programs();
virtual Render3DError CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString);
virtual void DestroyFramebufferOutput8888Programs();
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
virtual Render3DError InitPostprocessingPrograms(const char *edgeMarkVtxShader,
const char *edgeMarkFragShader,
const char *framebufferOutputVtxShader,
const char *framebufferOutputRGBA6665FragShader,
const char *framebufferOutputRGBA8888FragShader);
virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual void _ResolveWorkingBackFacing();
virtual void _ResolveGeometry();
virtual Render3DError ReadBackPixels();
// Base rendering methods
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError RenderGeometry();
virtual Render3DError PostprocessFramebuffer();
virtual Render3DError EndRender();
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes);
virtual void SetPolygonIndex(const size_t index);
virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer);
virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex);
virtual Render3DError SetupViewport(const u32 viewportValue);
virtual Render3DError DrawShadowPolygon(const GLenum polyPrimitive, const GLsizei vertIndexCount, const GLushort *indexBufferPtr, const bool performDepthEqualTest, const bool enableAlphaDepthWrite, const bool isTranslucent, const u8 opaquePolyID);
public:
~OpenGLRenderer_1_2();
virtual Render3DError InitExtensions();
virtual Render3DError Reset();
virtual Render3DError RenderPowerOff();
virtual Render3DError RenderFinish();
virtual Render3DError RenderFlush(bool willFlushBuffer32, bool willFlushBuffer16);
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
};
class OpenGLRenderer_2_0 : public OpenGLRenderer_1_2
{
protected:
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex);
};
class OpenGLRenderer_2_1 : public OpenGLRenderer_2_0
{
public:
virtual Render3DError RenderFinish();
virtual Render3DError RenderFlush(bool willFlushBuffer32, bool willFlushBuffer16);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,123 +0,0 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2019 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OGLRENDER_3_2_H
#define OGLRENDER_3_2_H
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glcorearb.h>
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)wglGetProcAddress(#func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#elif defined(__APPLE__)
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
// Ignore dynamic linking on Apple OS
#define OGLEXT(procPtr, func)
#define INITOGLEXT(procPtr, func)
#define EXTERNOGLEXT(procPtr, func)
#else
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glx.h>
#include "utils/glcorearb.h"
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)glXGetProcAddress((const GLubyte *) #func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#endif
// Check minimum OpenGL header version
#if !defined(GL_VERSION_3_2)
#error OpenGL requires v3.2 headers or later.
#endif
#include "OGLRender.h"
#define MAX_CLIPPED_POLY_COUNT_FOR_UBO 16384
void OGLLoadEntryPoints_3_2();
void OGLCreateRenderer_3_2(OpenGLRenderer **rendererPtr);
class OpenGLRenderer_3_2 : public OpenGLRenderer_2_1
{
protected:
bool _is64kUBOSupported;
bool _isDualSourceBlendingSupported;
bool _isSampleShadingSupported;
bool _isConservativeDepthSupported;
bool _isConservativeDepthAMDSupported;
GLsync _syncBufferSetup;
CACHE_ALIGN OGLPolyStates _pendingPolyStates[POLYLIST_SIZE];
virtual Render3DError InitExtensions();
virtual Render3DError CreateFBOs();
virtual void DestroyFBOs();
virtual Render3DError CreateMultisampledFBO(GLsizei numSamples);
virtual void DestroyMultisampledFBO();
virtual void ResizeMultisampledFBOs(GLsizei numSamples);
virtual Render3DError CreateVAOs();
virtual void DestroyVAOs();
virtual Render3DError CreateGeometryPrograms();
virtual void DestroyGeometryPrograms();
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateMSGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual void DestroyMSGeometryZeroDstAlphaProgram();
virtual Render3DError CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString);
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual void _ResolveWorkingBackFacing();
virtual void _ResolveGeometry();
virtual Render3DError ReadBackPixels();
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError PostprocessFramebuffer();
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes);
virtual void SetPolygonIndex(const size_t index);
virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer);
virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex);
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
public:
OpenGLRenderer_3_2();
~OpenGLRenderer_3_2();
virtual Render3DError RenderPowerOff();
};
#endif

View File

@ -1,12 +0,0 @@
#ifndef __GNUC__
#pragma pack(push, 1)
#pragma warning(disable : 4103)
#endif
#ifndef __PACKED
#ifdef __GNUC__
#define __PACKED __attribute__((__packed__))
#else
#define __PACKED
#endif
#endif

View File

@ -1,3 +0,0 @@
#ifndef __GNUC__
#pragma pack(pop)
#endif

View File

@ -1,375 +0,0 @@
/*
Copyright 2007 Guillaume Duhamel
Copyright 2007-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ROMReader.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#ifdef HAVE_LIBZZIP
#include <zzip/zzip.h>
#endif
#include "utils/xstring.h"
#ifdef WIN32
#define stat(...) _stat(__VA_ARGS__)
#define S_IFMT _S_IFMT
#define S_IFREG _S_IFREG
#endif
ROMReader_struct * ROMReaderInit(char ** filename)
{
#ifdef HAVE_LIBZ
if(!strcasecmp(".gz", *filename + (strlen(*filename) - 3)))
{
(*filename)[strlen(*filename) - 3] = '\0';
return &GZIPROMReader;
}
#endif
#ifdef HAVE_LIBZZIP
if (!strcasecmp(".zip", *filename + (strlen(*filename) - 4)))
{
(*filename)[strlen(*filename) - 4] = '\0';
return &ZIPROMReader;
}
#endif
return &STDROMReader;
}
void * STDROMReaderInit(const char * filename);
void STDROMReaderDeInit(void *);
u32 STDROMReaderSize(void *);
int STDROMReaderSeek(void *, int, int);
int STDROMReaderRead(void *, void *, u32);
int STDROMReaderWrite(void *, void *, u32);
ROMReader_struct STDROMReader =
{
ROMREADER_STD,
"Standard ROM Reader",
STDROMReaderInit,
STDROMReaderDeInit,
STDROMReaderSize,
STDROMReaderSeek,
STDROMReaderRead,
STDROMReaderWrite
};
struct STDROMReaderData
{
FILE* file;
long pos;
};
void* STDROMReaderInit(const char* filename)
{
#ifndef _MSC_VER
struct stat sb;
if (stat(filename, &sb) == -1)
return 0;
if ((sb.st_mode & S_IFMT) != S_IFREG)
return 0;
#endif
#ifdef WIN32
FILE* inf = _wfopen(mbstowcs((std::string)filename).c_str(),L"rb");
#else
FILE* inf = fopen(filename, "rb");
#endif
if(!inf) return NULL;
STDROMReaderData* ret = new STDROMReaderData();
ret->file = inf;
ret->pos = 0;
return (void*)ret;
}
void STDROMReaderDeInit(void * file)
{
if (!file) return ;
fclose(((STDROMReaderData*)file)->file);
delete ((STDROMReaderData*)file);
}
u32 STDROMReaderSize(void * file)
{
u32 size;
if (!file) return 0;
FILE* inf = ((STDROMReaderData*)file)->file;
fseek(inf, 0, SEEK_END);
size = ftell(inf);
fseek(inf, ((STDROMReaderData*)file)->pos, SEEK_SET);
return size;
}
int STDROMReaderSeek(void * file, int offset, int whence)
{
//not normal fseek return value meanings. awesome.
if (!file) return 0;
if(whence == SEEK_SET && offset == ((STDROMReaderData*)file)->pos)
return 1;
fseek(((STDROMReaderData*)file)->file, offset, whence);
((STDROMReaderData*)file)->pos = ftell(((STDROMReaderData*)file)->file);
return 1;
}
int STDROMReaderRead(void * file, void * buffer, u32 size)
{
if (!file) return 0;
int read = fread(buffer, 1, size, ((STDROMReaderData*)file)->file);
((STDROMReaderData*)file)->pos += read;
return read;
}
int STDROMReaderWrite(void *, void *, u32)
{
//not supported, for now
return 0;
}
#ifdef HAVE_LIBZ
void * GZIPROMReaderInit(const char * filename);
void GZIPROMReaderDeInit(void *);
u32 GZIPROMReaderSize(void *);
int GZIPROMReaderSeek(void *, int, int);
int GZIPROMReaderRead(void *, void *, u32);
int GZIPROMReaderWrite(void *, void *, u32);
ROMReader_struct GZIPROMReader =
{
ROMREADER_GZIP,
"Gzip ROM Reader",
GZIPROMReaderInit,
GZIPROMReaderDeInit,
GZIPROMReaderSize,
GZIPROMReaderSeek,
GZIPROMReaderRead,
GZIPROMReaderWrite
};
void * GZIPROMReaderInit(const char * filename)
{
return (void*)gzopen(filename, "rb");
}
void GZIPROMReaderDeInit(void * file)
{
gzclose((gzFile)file);
}
u32 GZIPROMReaderSize(void * file)
{
char useless[1024];
u32 size = 0;
/* FIXME this function should first save the current
* position and restore it after size calculation */
gzrewind((gzFile)file);
while (gzeof ((gzFile)file) == 0)
size += gzread((gzFile)file, useless, 1024);
gzrewind((gzFile)file);
return size;
}
int GZIPROMReaderSeek(void * file, int offset, int whence)
{
return gzseek((gzFile)file, offset, whence);
}
int GZIPROMReaderRead(void * file, void * buffer, u32 size)
{
return gzread((gzFile)file, buffer, size);
}
int GZIPROMReaderWrite(void *, void *, u32)
{
//not supported, ever
return 0;
}
#endif
#ifdef HAVE_LIBZZIP
void * ZIPROMReaderInit(const char * filename);
void ZIPROMReaderDeInit(void *);
u32 ZIPROMReaderSize(void *);
int ZIPROMReaderSeek(void *, int, int);
int ZIPROMReaderRead(void *, void *, u32);
int ZIPROMReaderWrite(void *, void *, u32);
ROMReader_struct ZIPROMReader =
{
ROMREADER_ZIP,
"Zip ROM Reader",
ZIPROMReaderInit,
ZIPROMReaderDeInit,
ZIPROMReaderSize,
ZIPROMReaderSeek,
ZIPROMReaderRead,
ZIPROMReaderWrite
};
void * ZIPROMReaderInit(const char * filename)
{
ZZIP_DIR * dir = zzip_opendir(filename);
ZZIP_DIRENT * dirent = zzip_readdir(dir);
if (dir != NULL)
{
char *tmp1;
char tmp2[1024];
memset(tmp2,0,sizeof(tmp2));
tmp1 = strndup(filename, strlen(filename) - 4);
sprintf(tmp2, "%s/%s", tmp1, dirent->d_name);
free(tmp1);
return zzip_fopen(tmp2, "rb");
}
return NULL;
}
void ZIPROMReaderDeInit(void * file)
{
zzip_close((ZZIP_FILE*)file);
}
u32 ZIPROMReaderSize(void * file)
{
u32 size;
zzip_seek((ZZIP_FILE*)file, 0, SEEK_END);
size = zzip_tell((ZZIP_FILE*)file);
zzip_seek((ZZIP_FILE*)file, 0, SEEK_SET);
return size;
}
int ZIPROMReaderSeek(void * file, int offset, int whence)
{
return zzip_seek((ZZIP_FILE*)file, offset, whence);
}
int ZIPROMReaderRead(void * file, void * buffer, u32 size)
{
#ifdef ZZIP_OLD_READ
return zzip_read((ZZIP_FILE*)file, (char *) buffer, size);
#else
return zzip_read((ZZIP_FILE*)file, buffer, size);
#endif
}
int ZIPROMReaderWrite(void *, void *, u32)
{
//not supported ever
return 0;
}
#endif
struct {
void* buf;
int len;
int pos;
} mem;
void * MemROMReaderInit(const char * filename)
{
return NULL; //dummy
}
void MemROMReaderDeInit(void *)
{
//nothing to do
}
u32 MemROMReaderSize(void *)
{
return (u32)mem.len;
}
int MemROMReaderSeek(void * file, int offset, int whence)
{
switch(whence) {
case SEEK_SET:
mem.pos = offset;
break;
case SEEK_CUR:
mem.pos += offset;
break;
case SEEK_END:
mem.pos = mem.len + offset;
break;
}
return mem.pos;
}
int MemROMReaderRead(void * file, void * buffer, u32 size)
{
if(mem.pos<0) return 0;
int todo = (int)size;
int remain = mem.len - mem.pos;
if(remain<todo)
todo = remain;
if(todo<=0)
return 0;
else if(todo==1) *(u8*)buffer = ((u8*)mem.buf)[mem.pos];
else memcpy(buffer,(u8*)mem.buf + mem.pos, todo);
mem.pos += todo;
return todo;
}
int MemROMReaderWrite(void * file, void * buffer, u32 size)
{
if(mem.pos<0) return 0;
int todo = (int)size;
int remain = mem.len - mem.pos;
if(remain<todo)
todo = remain;
if(todo==1) *(u8*)buffer = ((u8*)mem.buf)[mem.pos];
else memcpy((u8*)mem.buf + mem.pos,buffer, todo);
mem.pos += todo;
return todo;
}
static ROMReader_struct MemROMReader =
{
ROMREADER_MEM,
"Memory ROM Reader",
MemROMReaderInit,
MemROMReaderDeInit,
MemROMReaderSize,
MemROMReaderSeek,
MemROMReaderRead,
MemROMReaderWrite,
};
ROMReader_struct * MemROMReaderRead_TrueInit(void* buf, int length)
{
mem.buf = buf;
mem.len = length;
mem.pos = 0;
return &MemROMReader;
}

View File

@ -1,53 +0,0 @@
/*
Copyright (C) 2007 Guillaume Duhamel
Copyright (C) 2007-20017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
#include <string.h>
#include "types.h"
#define ROMREADER_DEFAULT -1
#define ROMREADER_STD 0
#define ROMREADER_GZIP 1
#define ROMREADER_ZIP 2
#define ROMREADER_MEM 3
typedef struct
{
int id;
const char * Name;
void * (*Init)(const char * filename);
void (*DeInit)(void * file);
u32 (*Size)(void * file);
int (*Seek)(void * file, int offset, int whence);
int (*Read)(void * file, void * buffer, u32 size);
int (*Write)(void * file, void * buffer, u32 size);
} ROMReader_struct;
extern ROMReader_struct STDROMReader;
#ifdef HAVE_LIBZ
extern ROMReader_struct GZIPROMReader;
#endif
#ifdef HAVE_LIBZZIP
extern ROMReader_struct ZIPROMReader;
#endif
ROMReader_struct * ROMReaderInit(char ** filename);
ROMReader_struct * MemROMReaderRead_TrueInit(void* buf, int length);

File diff suppressed because it is too large Load Diff

View File

@ -1,303 +0,0 @@
/*
Copyright 2006 Theo Berkau
Copyright (C) 2006-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SPU_H
#define SPU_H
#include <iosfwd>
#include <string>
#include <assert.h>
#include <stdio.h>
#include "types.h"
#include "matrix.h"
#include "metaspu/metaspu.h"
class EMUFILE;
#define SNDCORE_DEFAULT -1
#define SNDCORE_DUMMY 0
#define CHANSTAT_STOPPED 0
#define CHANSTAT_PLAY 1
//who made these static? theyre used in multiple places.
FORCEINLINE u32 sputrunc(float f) { return u32floor(f); }
FORCEINLINE u32 sputrunc(double d) { return u32floor(d); }
FORCEINLINE s32 spumuldiv7(s32 val, u8 multiplier) {
assert(multiplier <= 127);
return (multiplier == 127) ? val : ((val * multiplier) >> 7);
}
enum SPUInterpolationMode
{
SPUInterpolation_None = 0,
SPUInterpolation_Linear = 1,
SPUInterpolation_Cosine = 2
};
struct SoundInterface_struct
{
int id;
const char *Name;
int (*Init)(int buffersize);
void (*DeInit)();
void (*UpdateAudio)(s16 *buffer, u32 num_samples);
u32 (*GetAudioSpace)();
void (*MuteAudio)();
void (*UnMuteAudio)();
void (*SetVolume)(int volume);
void (*ClearBuffer)();
void (*FetchSamples)(s16 *sampleBuffer, size_t sampleCount, ESynchMode synchMode, ISynchronizingAudioBuffer *theSynchronizer);
size_t (*PostProcessSamples)(s16 *postProcessBuffer, size_t requestedSampleCount, ESynchMode synchMode, ISynchronizingAudioBuffer *theSynchronizer);
};
extern SoundInterface_struct SNDDummy;
extern SoundInterface_struct SNDFile;
extern int SPU_currentCoreNum;
struct channel_struct
{
channel_struct() : num(0),
vol(0),
volumeDiv(0),
hold(0),
pan(0),
waveduty(0),
repeat(0),
format(0),
keyon(0),
status(0),
addr(0),
timer(0),
loopstart(0),
length(0),
totlength(0),
double_totlength_shifted(0.0),
sampcnt(0.0),
sampinc(0.0),
lastsampcnt(0),
pcm16b(0),
pcm16b_last(0),
loop_pcm16b(0),
index(0),
loop_index(0),
x(0),
psgnoise_last(0)
{}
u32 num;
u8 vol;
u8 volumeDiv;
u8 hold;
u8 pan;
u8 waveduty;
u8 repeat;
u8 format;
u8 keyon;
u8 status;
u32 addr;
u16 timer;
u16 loopstart;
u32 length;
u32 totlength;
double double_totlength_shifted;
double sampcnt;
double sampinc;
// ADPCM specific
u32 lastsampcnt;
s16 pcm16b, pcm16b_last;
s16 loop_pcm16b;
s32 index;
int loop_index;
u16 x;
s16 psgnoise_last;
};
class SPUFifo
{
public:
SPUFifo();
void enqueue(s16 val);
s16 dequeue();
s16 buffer[16];
s32 head,tail,size;
void save(EMUFILE &fp);
bool load(EMUFILE &fp);
void reset();
};
class SPU_struct
{
public:
SPU_struct(int buffersize);
u32 bufpos;
u32 buflength;
s32 *sndbuf;
s32 lastdata; //the last sample that a channel generated
s16 *outbuf;
u32 bufsize;
channel_struct channels[16];
//registers
struct REGS {
REGS()
: mastervol(0)
, ctl_left(0)
, ctl_right(0)
, ctl_ch1bypass(0)
, ctl_ch3bypass(0)
, masteren(0)
, soundbias(0)
{}
u8 mastervol;
u8 ctl_left, ctl_right;
u8 ctl_ch1bypass, ctl_ch3bypass;
u8 masteren;
u16 soundbias;
enum LeftOutputMode
{
LOM_LEFT_MIXER=0, LOM_CH1=1, LOM_CH3=2, LOM_CH1_PLUS_CH3=3
};
enum RightOutputMode
{
ROM_RIGHT_MIXER=0, ROM_CH1=1, ROM_CH3=2, ROM_CH1_PLUS_CH3=3
};
struct CAP {
CAP()
: add(0), source(0), oneshot(0), bits8(0), active(0), dad(0), len(0)
{}
u8 add, source, oneshot, bits8, active;
u32 dad;
u16 len;
struct Runtime {
Runtime()
: running(0), curdad(0), maxdad(0)
{}
u8 running;
u32 curdad;
u32 maxdad;
double sampcnt;
SPUFifo fifo;
} runtime;
} cap[2];
} regs;
void reset();
~SPU_struct();
void KeyOff(int channel);
void KeyOn(int channel);
void KeyProbe(int channel);
void ProbeCapture(int which);
void WriteByte(u32 addr, u8 val);
void WriteWord(u32 addr, u16 val);
void WriteLong(u32 addr, u32 val);
u8 ReadByte(u32 addr);
u16 ReadWord(u32 addr);
u32 ReadLong(u32 addr);
bool isSPU(u32 addr) { return ((addr >= 0x04000400) && (addr < 0x04000520)); }
//kills all channels but leaves SPU otherwise running normally
void ShutUp();
};
extern SPU_struct *SPU_core, *SPU_user;
extern int spu_core_samples;
int SPU_ChangeSoundCore(int coreid, int buffersize);
SoundInterface_struct *SPU_SoundCore();
void SPU_ReInit(bool fakeBoot = false);
int SPU_Init(int coreid, int buffersize);
void SPU_Pause(int pause);
void SPU_SetVolume(int volume);
void SPU_SetSynchMode(int mode, int method);
void SPU_ClearOutputBuffer(void);
void SPU_Reset(void);
void SPU_DeInit(void);
void SPU_KeyOn(int channel);
static FORCEINLINE void SPU_WriteByte(u32 addr, u8 val)
{
addr &= 0xFFF;
SPU_core->WriteByte(addr,val);
if(SPU_user)
SPU_user->WriteByte(addr,val);
}
static FORCEINLINE void SPU_WriteWord(u32 addr, u16 val)
{
addr &= 0xFFF;
SPU_core->WriteWord(addr,val);
if(SPU_user)
SPU_user->WriteWord(addr,val);
}
static FORCEINLINE void SPU_WriteLong(u32 addr, u32 val)
{
addr &= 0xFFF;
SPU_core->WriteLong(addr,val);
if(SPU_user)
SPU_user->WriteLong(addr,val);
}
static FORCEINLINE u8 SPU_ReadByte(u32 addr) { return SPU_core->ReadByte(addr & 0x0FFF); }
static FORCEINLINE u16 SPU_ReadWord(u32 addr) { return SPU_core->ReadWord(addr & 0x0FFF); }
static FORCEINLINE u32 SPU_ReadLong(u32 addr) { return SPU_core->ReadLong(addr & 0x0FFF); }
void SPU_Emulate_core(void);
void SPU_Emulate_user(bool mix = true);
void SPU_DefaultFetchSamples(s16 *sampleBuffer, size_t sampleCount, ESynchMode synchMode, ISynchronizingAudioBuffer *theSynchronizer);
size_t SPU_DefaultPostProcessSamples(s16 *postProcessBuffer, size_t requestedSampleCount, ESynchMode synchMode, ISynchronizingAudioBuffer *theSynchronizer);
void spu_savestate(EMUFILE &os);
bool spu_loadstate(EMUFILE &is, int size);
enum WAVMode
{
WAVMODE_ANY = -1,
WAVMODE_CORE = 0,
WAVMODE_USER = 1
};
class WavWriter
{
public:
WavWriter();
bool open(const std::string & fname);
void close();
void update(void* soundData, int numSamples);
bool isRecording() const;
WAVMode mode;
private:
FILE *spufp;
};
void WAV_End();
bool WAV_Begin(const char* fname, WAVMode mode=WAVMODE_CORE);
bool WAV_IsRecording(WAVMode mode=WAVMODE_ANY);
void WAV_WavSoundUpdate(void* soundData, int numSamples, WAVMode mode=WAVMODE_CORE);
// we should make this configurable eventually
// but at least defining it somewhere is probably a step in the right direction
#define DESMUME_SAMPLE_RATE 44100
//#define DESMUME_SAMPLE_RATE 48000
#endif

View File

@ -1,35 +0,0 @@
/*
Copyright (C) 2010-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../slot1.h"
class Slot1_None : public ISlot1Interface
{
public:
virtual Slot1Info const* info()
{
static Slot1InfoSimple info("None","Slot1 no-card emulation", 0xFF);
return &info;
}
//pretty much every access to the card should just be ignored and reading HIGH-Z off the GC bus.
//so, nothing really to do here
//(notably, it results in a 0xFFFFFFFF card ID)
};
ISlot1Interface* construct_Slot1_None() { return new Slot1_None(); }

View File

@ -1,244 +0,0 @@
/*
Copyright (C) 2010-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "slot1comp_protocol.h"
#include <time.h>
#include "../slot1.h"
#include "../NDSSystem.h"
#include "../emufile.h"
class Slot1_R4 : public ISlot1Interface, public ISlot1Comp_Protocol_Client
{
private:
EMUFILE *img;
Slot1Comp_Protocol protocol;
u32 write_count;
u32 write_enabled;
public:
Slot1_R4()
: img(NULL)
, write_count(0)
, write_enabled(0)
{
}
virtual Slot1Info const* info()
{
static Slot1InfoSimple info("R4", "Slot1 R4 emulation", 0x03);
return &info;
}
//called once when the emulator starts up, or when the device springs into existence
virtual bool init()
{
//strange to do this here but we need to make sure its done at some point
srand(time(NULL));
return true;
}
virtual void connect()
{
img = slot1_GetFatImage();
if(!img)
INFO("slot1 fat not successfully mounted\n");
protocol.reset(this);
protocol.chipId = 0xFC2;
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
}
//called when the emulator disconnects the device
virtual void disconnect()
{
img = NULL;
}
//called when the emulator shuts down, or when the device disappears from existence
virtual void shutdown()
{
}
virtual void write_command(u8 PROCNUM, GC_Command command)
{
protocol.write_command(command);
}
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
{
protocol.write_GCDATAIN(PROCNUM, val);
}
virtual u32 read_GCDATAIN(u8 PROCNUM)
{
return protocol.read_GCDATAIN(PROCNUM);
}
virtual void slot1client_startOperation(eSlot1Operation operation)
{
if(operation != eSlot1Operation_Unknown)
return;
u32 address;
int cmd = protocol.command.bytes[0];
switch(cmd)
{
case 0xB0:
break;
case 0xB9:
case 0xBA:
address = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4];
img->fseek(address,SEEK_SET);
break;
case 0xBB:
write_enabled = 1;
write_count = 0x80;
//passthrough on purpose?
case 0xBC:
address = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4];
img->fseek(address,SEEK_SET);
break;
}
}
virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation)
{
if (operation != eSlot1Operation_Unknown)
return 0;
u32 val = 0;
int cmd = protocol.command.bytes[0];
switch (cmd)
{
case 0xB0:
val = (img != NULL) ? 0x1F4 : 0x1F2;
break;
case 0xB9:
val = (rand() % 100) ? (img) ? 0x1F4 : 0x1F2 : 0;
break;
case 0xBB:
case 0xBC:
val = 0;
break;
case 0xBA:
//INFO("Read from sd at sector %08X at adr %08X ",card.address/512,ftell(img));
img->read_32LE(val);
//INFO("val %08X\n",val);
break;
default:
val = 0;
break;
}
return val;
}
void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val)
{
if (operation != eSlot1Operation_Unknown)
return;
int cmd = protocol.command.bytes[0];
switch (cmd)
{
case 0xBB:
{
if (write_count && write_enabled)
{
img->write_32LE(val);
img->fflush();
write_count--;
}
break;
}
default:
break;
}
}
virtual void post_fakeboot(int PROCNUM)
{
// The BIOS leaves the card in NORMAL mode
protocol.mode = eCardMode_NORMAL;
}
void write32_GCDATAIN(u32 val)
{
//bool log = false;
//last_write_count = write_count;
//can someone tell me ... what the hell is this doing, anyway?
//seems odd to use card.command[4] for this... isnt it part of the address?
if (protocol.command.bytes[4])
{
// transfer is done
//are you SURE this is logical? there doesnt seem to be any way for the card to signal that
T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF);
MMU_GC_endTransfer(0);
return;
}
int cmd = protocol.command.bytes[0];
switch (cmd)
{
case 0xBB:
{
if (write_count && write_enabled)
{
img->write_32LE(val);
img->fflush();
write_count--;
}
break;
}
default:
break;
}
if (write_count == 0)
{
write_enabled = 0;
//transfer is done
//are you SURE this is logical? there doesnt seem to be any way for the card to signal that
T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF);
//but isnt this a different IRQ? IREQ_MC perhaps
MMU_GC_endTransfer(0);
}
/*if(log)
{
INFO("WRITE CARD command: %02X%02X%02X%02X%02X%02X%02X%02X\t",
card.command[0], card.command[1], card.command[2], card.command[3],
card.command[4], card.command[5], card.command[6], card.command[7]);
INFO("FROM: %08X\t", NDS_ARM9.instruct_adr);
INFO("VAL: %08X\n", val);
}*/
}
};
ISlot1Interface* construct_Slot1_R4() { return new Slot1_R4(); }

View File

@ -1,104 +0,0 @@
/*
Copyright (C) 2013-2105 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../slot1.h"
#include "../NDSSystem.h"
class Slot1_Retail_Auto : public ISlot1Interface
{
private:
ISlot1Interface *mSelectedImplementation;
public:
Slot1_Retail_Auto()
: mSelectedImplementation(NULL)
{
}
virtual Slot1Info const* info()
{
static Slot1InfoSimple info("Retail (Auto)","Slot1 Retail (auto-selection) card emulation", 0xFE);
return &info;
}
virtual void connect()
{
NDS_SLOT1_TYPE selection = NDS_SLOT1_RETAIL_MCROM;
//check game ID in core emulator and select right implementation
//gamehack: definitely not a game hack, just a lazy way of selecting the right equipment for the game
if(gameInfo.IsCode("UOR") || // WarioWare - D.I.Y. (U)(E)(EUR) / Made in Ore (J)
gameInfo.IsCode("UXBP") || // Jam with the Band (EUR)
gameInfo.IsCode("AXBJ") // Daigassou! Band-Brothers DX (J)
)
selection = NDS_SLOT1_RETAIL_NAND;
slot1_selected_type = selection;
mSelectedImplementation = slot1_List[selection];
mSelectedImplementation->connect();
printf("Slot1 auto-selected device type: %s\n",mSelectedImplementation->info()->name());
}
virtual void disconnect()
{
if(mSelectedImplementation) mSelectedImplementation->disconnect();
mSelectedImplementation = NULL;
}
virtual void write_command(u8 PROCNUM, GC_Command command)
{
mSelectedImplementation->write_command(PROCNUM, command);
}
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
{
mSelectedImplementation->write_GCDATAIN(PROCNUM, val);
}
virtual u32 read_GCDATAIN(u8 PROCNUM)
{
return mSelectedImplementation->read_GCDATAIN(PROCNUM);
}
virtual u8 auxspi_transaction(int PROCNUM, u8 value)
{
return mSelectedImplementation->auxspi_transaction(PROCNUM, value);
}
virtual void auxspi_reset(int PROCNUM)
{
mSelectedImplementation->auxspi_reset(PROCNUM);
}
virtual void post_fakeboot(int PROCNUM)
{
mSelectedImplementation->post_fakeboot(PROCNUM);
}
virtual void savestate(EMUFILE &os)
{
mSelectedImplementation->savestate(os);
}
virtual void loadstate(EMUFILE &is)
{
mSelectedImplementation->loadstate(is);
}
};
ISlot1Interface* construct_Slot1_Retail_Auto() { return new Slot1_Retail_Auto(); }

View File

@ -1,107 +0,0 @@
/*
Copyright (C) 2010-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "slot1comp_mc.h"
#include "slot1comp_rom.h"
#include "slot1comp_protocol.h"
#include "../slot1.h"
#include "../NDSSystem.h"
//quick architecture overview:
//MCROM receives GC bus commands from MMU.cpp
//those are passed on to the protocol component for parsing
//protocol calls back into MCROM via ISlot1Comp_Protocol_Client interface for things the protocol doesnt know about (the contents of the rom, chiefly)
//MCROM utilizes the rom component for address logic and delivering data
class Slot1_Retail_MCROM : public ISlot1Interface, public ISlot1Comp_Protocol_Client
{
private:
Slot1Comp_Protocol protocol;
Slot1Comp_Rom rom;
public:
virtual Slot1Info const* info()
{
static Slot1InfoSimple info("Retail MC+ROM", "Slot1 Retail MC+ROM (standard) card emulation", 0x01);
return &info;
}
virtual void connect()
{
protocol.reset(this);
protocol.chipId = gameInfo.chipID;
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
g_Slot1Comp_MC.connect();
}
virtual u8 auxspi_transaction(int PROCNUM, u8 value)
{
return g_Slot1Comp_MC.auxspi_transaction(PROCNUM,value);
}
virtual void auxspi_reset(int PROCNUM)
{
g_Slot1Comp_MC.auxspi_reset(PROCNUM);
}
virtual void write_command(u8 PROCNUM, GC_Command command)
{
protocol.write_command(command);
}
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
{
protocol.write_GCDATAIN(PROCNUM, val);
}
virtual u32 read_GCDATAIN(u8 PROCNUM)
{
return protocol.read_GCDATAIN(PROCNUM);
}
virtual void slot1client_startOperation(eSlot1Operation operation)
{
rom.start(operation,protocol.address);
}
virtual void post_fakeboot(int PROCNUM)
{
// The BIOS leaves the card in NORMAL mode
protocol.mode = eCardMode_NORMAL;
}
virtual void savestate(EMUFILE &os)
{
protocol.savestate(os);
rom.savestate(os);
}
virtual void loadstate(EMUFILE &is)
{
protocol.loadstate(is);
rom.loadstate(is);
}
private:
u32 slot1client_read_GCDATAIN(eSlot1Operation operation)
{
return rom.read();
}
};
ISlot1Interface* construct_Slot1_Retail_MCROM() { return new Slot1_Retail_MCROM(); }

View File

@ -1,214 +0,0 @@
/*
Copyright (C) 2013-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
//This module implements a device which is capable of building a nitro FS on the fly
//(and REBUILDING it! -- Q: under what conditions?)
//so that you can test your homebrew games and patches without having to rebuild the ROM and restart it.
//Q. can it handle resized files?
#include "slot1comp_mc.h"
#include "slot1comp_rom.h"
#include "slot1comp_protocol.h"
#include <stdio.h>
#include <string>
#include "../slot1.h"
#include "../path.h"
#include "../NDSSystem.h"
#include "../utils/fsnitro.h"
class Slot1_Retail_DEBUG : public ISlot1Interface, public ISlot1Comp_Protocol_Client
{
private:
Slot1Comp_Protocol protocol;
Slot1Comp_Rom rom;
FILE *fpROM;
FS_NITRO *fs;
u16 curr_file_id;
std::string pathData;
public:
virtual Slot1Info const* info()
{
static Slot1InfoSimple info("Retail DEBUG","Slot1 Retail (standard) card emulation + FS Nitro DEBUG", 0x04);
return &info;
}
virtual void connect()
{
protocol.reset(this);
protocol.chipId = gameInfo.chipID;
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
curr_file_id = 0xFFFF;
fpROM = NULL;
fs = NULL;
pathData = path.getpath(path.SLOT1D) + path.GetRomNameWithoutExtension();
printf("Path to Slot1 data: %s\n", pathData.c_str());
fs = new FS_NITRO();
fs->rebuildFAT(pathData);
}
virtual u8 auxspi_transaction(int PROCNUM, u8 value)
{
return g_Slot1Comp_MC.auxspi_transaction(PROCNUM,value);
}
virtual void auxspi_reset(int PROCNUM)
{
g_Slot1Comp_MC.auxspi_reset(PROCNUM);
}
virtual void write_command(u8 PROCNUM, GC_Command command)
{
protocol.write_command(command);
}
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
{
protocol.write_GCDATAIN(PROCNUM, val);
}
virtual u32 read_GCDATAIN(u8 PROCNUM)
{
return protocol.read_GCDATAIN(PROCNUM);
}
virtual void post_fakeboot(int PROCNUM)
{
// The BIOS leaves the card in NORMAL mode
protocol.mode = eCardMode_NORMAL;
}
virtual void savestate(EMUFILE &os)
{
protocol.savestate(os);
rom.savestate(os);
}
virtual void loadstate(EMUFILE &is)
{
protocol.loadstate(is);
rom.loadstate(is);
}
virtual void slot1client_startOperation(eSlot1Operation operation)
{
if (protocol.operation == eSlot1Operation_B7_Read)
{
u16 file_id = 0xFFFF; u32 offset = 0;
bool bFromFile = false;
if (fs && fs->isFAT(protocol.address))
{
fs->rebuildFAT(protocol.address, protocol.length, pathData);
}
else
{
if (fs && fs->getFileIdByAddr(protocol.address, file_id, offset))
{
if (file_id != curr_file_id)
{
std::string tmp = fs->getFullPathByFileID(file_id);
printf("%04X:[%08X, ofs %08X] %s\n", file_id, protocol.address, offset, tmp.c_str());
if (fpROM)
{
fclose(fpROM);
fpROM = NULL;
}
tmp = pathData + tmp;
fpROM = fopen(tmp.c_str(), "rb");
if (fpROM)
{
bFromFile = true;
printf("\t * found at disk, offset %08X\n", offset);
if (fseek(fpROM, offset, SEEK_SET) != 0)
{
printf("\t\t - ERROR seek file position\n");
}
}
}
else
{
if (fpROM)
{
bFromFile = true;
if (ftell(fpROM) != offset)
{
printf("\t * new file seek %08Xh\n", offset);
fseek(fpROM, offset, SEEK_SET);
}
}
}
}
}
if (!bFromFile && fpROM)
{
fclose(fpROM);
fpROM = NULL;
}
curr_file_id = file_id;
}
rom.start(operation, protocol.address);
}
private:
u32 slot1client_read_GCDATAIN(eSlot1Operation operation)
{
if (protocol.operation == eSlot1Operation_B7_Read)
{
u32 address = rom.getAddress();
if (fs && fs->isFAT(address))
{
u32 res = fs->getFATRecord(address);
if (res != 0xFFFFFFFF)
{
rom.incAddress();
return res;
}
}
else
if (fpROM)
{
u32 data = 0;
u32 readed = fread(&data, 1, 4, fpROM);
if (readed)
{
rom.incAddress();
if (readed < 4)
data |= ((u32)0xFFFFFFFF << (readed * 8));
return data;
}
fclose(fpROM);
fpROM = NULL;
}
}
return rom.read();
}
};
ISlot1Interface* construct_Slot1_Retail_DEBUG() { return new Slot1_Retail_DEBUG(); }

View File

@ -1,321 +0,0 @@
/*
Copyright (C) 2010-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
// Games with NAND Flash:
// Ore/WarioWare D.I.Y. - chip: SAMSUNG 004
// KLC2811ANB-P204
// NTR-UORE-0
// - 128Mbit
#include "slot1comp_rom.h"
#include "slot1comp_protocol.h"
#include "../slot1.h"
#include "../NDSSystem.h"
#include "../emufile.h"
//quick architecture overview:
//NAND receives GC bus commands from MMU.cpp
//those are passed on to the protocol component for parsing
//protocol calls back into NAND via ISlot1Comp_Protocol_Client interface for things the protocol doesn't know about (the contents of the rom, chiefly)
//NAND utilizes the rom component for address logic and delivering data.
//it also processes some commands itself which aren't rom-related (the NANDy stuff)
class Slot1_Retail_NAND : public ISlot1Interface, public ISlot1Comp_Protocol_Client
{
private:
u32 subAdr;
Slot1Comp_Protocol protocol;
Slot1Comp_Rom rom;
u32 mode;
u32 handle_save;
//current NAND read/write start position
//when this is changed, the read/write cursor will be reset to it
//when it is set to the same value, the read/write cursor will NOT be reset
//(this is since some value must necessarily come in on the protocol address, so the 'current save_start' is used as a special 'dont change' value
u32 save_start;
//current NAND read/write cursor
u32 save_adr;
public:
virtual Slot1Info const* info()
{
static Slot1InfoSimple info("Retail NAND","Slot1 retail NAND card emulation", 0x02);
return &info;
}
virtual void connect()
{
protocol.reset(this);
protocol.chipId = gameInfo.chipID;
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
save_adr = 0;
handle_save = 0;
mode = 0;
subAdr = T1ReadWord(gameInfo.header.reserved2, 0x6) << 17;
}
virtual void write_command(u8 PROCNUM, GC_Command command)
{
protocol.write_command(command);
}
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
{
protocol.write_GCDATAIN(PROCNUM, val);
}
virtual u32 read_GCDATAIN(u8 PROCNUM)
{
return protocol.read_GCDATAIN(PROCNUM);
}
virtual void slot1client_startOperation(eSlot1Operation operation)
{
//INFO("Start command: %02X%02X%02X%02X%02X%02X%02X%02X\t",
// protocol.command.bytes[0], protocol.command.bytes[1], protocol.command.bytes[2], protocol.command.bytes[3],
// protocol.command.bytes[4], protocol.command.bytes[5], protocol.command.bytes[6], protocol.command.bytes[7]);
//INFO("FROM: %08X\n", NDS_ARM9.instruct_adr);
u32 addressFromProtocol = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4];
//pass the normal rom operations along to the rom component
switch(operation)
{
case eSlot1Operation_00_ReadHeader_Unencrypted:
rom.start(operation,addressFromProtocol);
return;
case eSlot1Operation_2x_SecureAreaLoad:
rom.start(operation,protocol.address);
return;
default:
break;
}
//handle special commands ourselves
int cmd = protocol.command.bytes[0];
switch(cmd)
{
// Nand Init
case 0x94:
mode = cmd;
break;
// Nand Error?
case 0xD6:
break;
//Nand Write Page
case 0x81:
mode = cmd;
if(addressFromProtocol != save_start)
{
save_start = addressFromProtocol;
save_adr = (addressFromProtocol & gameInfo.mask) - subAdr;
}
handle_save = 1;
break;
case 0x84: //Write disable
case 0x85: //Write enable
mode = cmd;
break;
case 0x8B:
mode = cmd;
handle_save = 0;
MMU_new.backupDevice.flushBackup();
break;
//Start read mode
case 0xB7:
if (handle_save)
{
mode = cmd;
if(addressFromProtocol != save_start)
{
save_start = addressFromProtocol;
save_adr = (addressFromProtocol & gameInfo.mask) - subAdr;
}
}
else
{
rom.start(operation, addressFromProtocol);
}
break;
case 0xB2: //Set save position
mode = cmd;
save_start = addressFromProtocol;
//cursor resets regardless of whether save_start changed, that's what makes this special.
//the cursor could be reset to the beginning of the previous save_start region
save_adr = (addressFromProtocol & gameInfo.mask) - subAdr;
handle_save = 1;
break;
}
}
virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation)
{
//pass the normal rom operations along to the rom component
switch(operation)
{
case eSlot1Operation_00_ReadHeader_Unencrypted:
case eSlot1Operation_2x_SecureAreaLoad:
//case eSlot1Operation_B7_Read:
return rom.read();
}
//handle special commands ourselves
int cmd = protocol.command.bytes[0];
int val = 0;
switch(cmd)
{
// Nand Init?
case 0x94:
val = 0;
mode = 0;
break;
//Rom/Save Read
case 0xB7:
{
if(handle_save)
{
MMU_new.backupDevice.ensure(save_adr+4, (u8)0);
val = MMU_new.backupDevice.readLong(save_adr, 0);
save_adr += 4;
}
else
{
val = rom.read();
}
}
break;
// Nand Status?
case 0xD6:
//0x80 == busy
//0x40 == ??
//0x20 == ready?
//0x10 == write enabled?
switch (mode)
{
case 0x84: //Write disable
val = 0x20202020;
break;
case 0x85: //Write enable
val = 0x20202020 | 0x10101010;
break;
case 0x8B:
val = 0x60606060 | 0x10101010;
break;
case 0xB2: //Set save position
val = 0x20202020;
break;
default:
val = 0x60606060; //0x20 == ready
break;
}
break;
}
return val;
}
virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val)
{
//pass the normal rom operations along to the rom component
switch(operation)
{
case eSlot1Operation_00_ReadHeader_Unencrypted:
case eSlot1Operation_B7_Read:
case eSlot1Operation_2x_SecureAreaLoad:
return;
}
//handle special commands ourselves
int cmd = protocol.command.bytes[0];
u32 value = val;
u32 adr = save_adr;
switch(cmd)
{
case 0x81: //Nand Write
MMU_new.backupDevice.ensure(adr+4, (u8)0);
MMU_new.backupDevice.writeLong(adr, val);
save_adr += 4;
break;
}
}
virtual void post_fakeboot(int PROCNUM)
{
// The BIOS leaves the card in NORMAL mode
protocol.mode = eCardMode_NORMAL;
}
virtual void savestate(EMUFILE &os)
{
s32 version = 0;
protocol.savestate(os);
rom.savestate(os);
os.write_32LE(version);
os.write_32LE(mode);
os.write_32LE(handle_save);
os.write_32LE(save_adr);
os.write_32LE(save_start);
os.write_32LE(subAdr);
}
virtual void loadstate(EMUFILE &is)
{
s32 version = 0;
protocol.loadstate(is);
rom.loadstate(is);
is.read_32LE(version);
// version 0
if (version >= 0)
{
is.read_32LE(mode);
is.read_32LE(handle_save);
is.read_32LE(save_adr);
is.read_32LE(save_start);
is.read_32LE(subAdr);
}
}
};
ISlot1Interface* construct_Slot1_Retail_NAND() { return new Slot1_Retail_NAND(); }

View File

@ -1,43 +0,0 @@
/*
Copyright (C) 2013-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
//this file contains the components used for emulating standard gamecard "MC" devices (eeprom, fram, flash)
//this is largely done by accessing the BackupDevice resources in the core emulator
#include "slot1comp_mc.h"
#include "../MMU.h"
#include "../NDSSystem.h"
Slot1Comp_MC g_Slot1Comp_MC;
u8 Slot1Comp_MC::auxspi_transaction(int PROCNUM, u8 value)
{
return MMU_new.backupDevice.data_command(value, PROCNUM);
}
void Slot1Comp_MC::auxspi_reset(int PROCNUM)
{
MMU_new.backupDevice.reset_command();
}
void Slot1Comp_MC::connect()
{
//gamehack: not really a game hack
if(gameInfo.IsCode("AXBJ"))
MMU_new.backupDevice.uninitializedValue = 0x00; // Daigassou! Band Brothers DX (JP)
}

View File

@ -1,35 +0,0 @@
/*
Copyright (C) 2013-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
//this file contains the components used for emulating standard gamecard "MC" devices (eeprom, fram, flash)
#ifndef _SLOT1COMP_MC_H
#define _SLOT1COMP_MC_H
#include "../types.h"
class Slot1Comp_MC
{
public:
u8 auxspi_transaction(int PROCNUM, u8 value);
void auxspi_reset(int PROCNUM);
void connect();
};
extern Slot1Comp_MC g_Slot1Comp_MC;
#endif

View File

@ -1,256 +0,0 @@
/*
Copyright (C) 2012-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "slot1comp_protocol.h"
#include <string.h>
#include "../armcpu.h"
#include "../encrypt.h"
#include "../emufile.h"
#include "../utils/decrypt/decrypt.h"
static _KEY1 key1((const u8*)arm7_key);
void Slot1Comp_Protocol::reset(ISlot1Comp_Protocol_Client* client)
{
this->client = client;
//we have to initialize this to something.. lets use dummy.
//(need to clean this up...)
memcpy(&command,"\x9F\0\0\0\0\0\0\0",8);
operation = eSlot1Operation_9F_Dummy;
length = 0;
delay = 0;
mode = eCardMode_RAW;
}
void Slot1Comp_Protocol::write_command_RAW(GC_Command command)
{
int cmd = command.bytes[0];
if(cmd == 0x9F)
{
operation = eSlot1Operation_9F_Dummy;
length = 0x2000;
}
if(cmd == 0x90)
{
operation = eSlot1Operation_90_ChipID;
length = 4;
//we handle this operation ourselves
}
if(cmd == 0x3C)
{
//switch to KEY1
length = 0;
mode = eCardMode_KEY1;
//defer initialization of KEY1 until we know we need it, just to save some CPU time.
//TODO - some information about these parameters
//level == 2
//modulo == 8
key1.init(gameCode, 2, 0x08);
GCLOG("[GC] KEY1 ACTIVATED\n");
}
if(cmd == 0x00)
{
operation = eSlot1Operation_00_ReadHeader_Unencrypted;
client->slot1client_startOperation(operation);
}
}
void Slot1Comp_Protocol::write_command_KEY1(GC_Command command)
{
//decrypt the KEY1-format command
u32 temp[2];
command.toCryptoBuffer(temp);
key1.decrypt(temp);
command.fromCryptoBuffer(temp);
GCLOG("[GC] (key1-decrypted):"); command.print();
//and process it:
int cmd = command.bytes[0];
switch(cmd&0xF0)
{
case 0x10:
operation = eSlot1Operation_1x_ChipID;
delay = 0x910, length = 4;
//we handle this operation ourselves
break;
case 0x20:
operation = eSlot1Operation_2x_SecureAreaLoad;
delay = 0x910, length = 0x11A8;
//TODO - more endian-safe way of doing this (theres examples in R4)
{
#ifdef MSB_FIRST
u64 cmd64 = *(u64*)command.bytes;
#else
u64 cmd64 = bswap64(*(u64*)command.bytes);
#endif
//todo - parse into blocknumber
u32 blocknumber = (cmd64>>44)&0xFFFF;
if(blocknumber<4||blocknumber>7)
printf("SLOT1 WARNING: INVALID BLOCKNUMBER FOR \"Get Secure Area Block\": 0x%04X\n",blocknumber);
address = blocknumber*0x1000;
}
client->slot1client_startOperation(operation);
break;
case 0x40:
//switch to KEY2
delay = 0x910, length = 0;
//well.. not really... yet.
GCLOG("[GC] KEY2 ACTIVATED\n");
break;
case 0x60:
//KEY2 disable? any info?
break;
case 0xA0:
delay = 0x910, length = 0;
mode = eCardMode_NORMAL;
GCLOG("[GC] NORMAL MODE ACTIVATED\n");
break;
}
}
void Slot1Comp_Protocol::write_command_NORMAL(GC_Command command)
{
switch(command.bytes[0])
{
case 0xB7:
{
operation = eSlot1Operation_B7_Read;
//TODO - more endian-safe way of doing this (theres examples in R4)
#ifdef MSB_FIRST
u64 cmd64 = *(u64*)command.bytes;
#else
u64 cmd64 = bswap64(*(u64*)command.bytes);
#endif
address = (u32)((cmd64 >> 24));
length = 0x200;
client->slot1client_startOperation(operation);
}
break;
case 0xB8:
operation = eSlot1Operation_B8_ChipID;
delay = 0, length = 4;
//we handle this operation ourselves
break;
default:
operation = eSlot1Operation_Unknown;
client->slot1client_startOperation(operation);
break;
}
}
void Slot1Comp_Protocol::write_command(GC_Command command)
{
this->command = command;
//unrecognized commands will do something depending on the current state of the card
delay = 0;
length = 0;
address = 0;
switch(mode)
{
case eCardMode_RAW:
write_command_RAW(command);
break;
case eCardMode_KEY1:
write_command_KEY1(command);
break;
case eCardMode_NORMAL:
write_command_NORMAL(command);
break;
}
}
void Slot1Comp_Protocol::write_GCDATAIN(u8 PROCNUM, u32 val)
{
switch(operation)
{
case eSlot1Operation_Unknown:
client->slot1client_write_GCDATAIN(operation,val);
break;
}
}
u32 Slot1Comp_Protocol::read_GCDATAIN(u8 PROCNUM)
{
switch(operation)
{
default:
return client->slot1client_read_GCDATAIN(operation);
case eSlot1Operation_9F_Dummy:
return 0xFFFFFFFF;
case eSlot1Operation_1x_ChipID:
return chipId;
case eSlot1Operation_90_ChipID:
case eSlot1Operation_B8_ChipID:
//Most games continuously compare the current chipId with the value in
//stored in memory at boot-up, probably to know if the card was removed.
//staff of kings verifies this (it also uses the arm7 IRQ 20 to detect card ejects)
return chipId;
}
return 0xFFFFFFFF;
}
void Slot1Comp_Protocol::savestate(EMUFILE &os)
{
s32 version = 0;
os.write_32LE(version);
os.write_32LE((s32)mode);
os.write_32LE((s32)operation);
os.fwrite(command.bytes,8);
os.write_32LE(address);
os.write_32LE(length);
os.write_32LE(delay);
os.write_32LE(chipId);
os.write_32LE(gameCode);
}
void Slot1Comp_Protocol::loadstate(EMUFILE &is)
{
s32 version = is.read_s32LE();
mode = (eCardMode)is.read_s32LE();
operation = (eSlot1Operation)is.read_s32LE();
is.fread(command.bytes,8);
is.read_32LE(address);
is.read_32LE(length);
is.read_32LE(delay);
is.read_32LE(chipId);
is.read_32LE(gameCode);
}

View File

@ -1,114 +0,0 @@
/*
Copyright (C) 2013-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
//this file contains the components used for emulating standard gamecard protocol.
//this largely means the complex boot-up process.
//i think there's no reason why proprietary cards couldn't speak any protocol they wish, as long as they didn't mind being unbootable.
//TODO - could this be refactored into a base class? that's probably more reasonable. but we've gone with this modular mix-in architecture so... not yet.
#ifndef _SLOT1COMP_PROTOCOL_H
#define _SLOT1COMP_PROTOCOL_H
#include "../types.h"
#include "../MMU.h"
class EMUFILE;
enum eSlot1Operation
{
//----------
//RAW mode operations
//before encrypted communications can be established, some values from the rom header must be read.
//this is the only way to read the header, actually, since the only reading commands available to games (after KEY2 mode is set) are
eSlot1Operation_00_ReadHeader_Unencrypted,
//it's not clear why this exists
eSlot1Operation_9F_Dummy,
eSlot1Operation_90_ChipID,
//----------
//----------
//KEY1 mode operations
eSlot1Operation_1x_ChipID,
eSlot1Operation_2x_SecureAreaLoad,
//----------
//----------
//NORMAL mode operations
//the main rom data reading command
eSlot1Operation_B7_Read,
eSlot1Operation_B8_ChipID,
//----------
eSlot1Operation_Unknown
};
class ISlot1Comp_Protocol_Client
{
public:
virtual void slot1client_startOperation(eSlot1Operation operation) {}
virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation) = 0;
virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val) {}
};
class Slot1Comp_Protocol
{
public:
void savestate(EMUFILE &os);
void loadstate(EMUFILE &is);
//set some kind of protocol/hardware reset state
void reset(ISlot1Comp_Protocol_Client* client);
//signals from the GC bus
void write_command(GC_Command command);
void write_GCDATAIN(u8 PROCNUM, u32 val);
u32 read_GCDATAIN(u8 PROCNUM);
//helpers for write_command()
void write_command_RAW(GC_Command command);
void write_command_KEY1(GC_Command command);
void write_command_NORMAL(GC_Command command);
//operations not related to obscurities of the protocol or otherwise unknown are passed through to the client here
ISlot1Comp_Protocol_Client* client;
//--state--
//the major operational mode. the protocol shifts modes and interprets commands into operations differently depending on the mode
eCardMode mode;
//the current operational state
eSlot1Operation operation;
//the command we're currently crunching on
GC_Command command;
//most operations are defined in terms of returning a series of bytes
//the meaning of these varies by operation. they are provided publicly as a service to clients
u32 address;
s32 length, delay; //the expected length and delay of this state
//chipId which should be returned by the various chipId commands
u32 chipId;
//gameCode used by the protocol KEY1 crypto
u32 gameCode;
};
#endif //_SLOT1COMP_PROTOCOL_H

View File

@ -1,123 +0,0 @@
/*
Copyright (C) 2010-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "slot1comp_rom.h"
#include "../NDSSystem.h"
#include "../emufile.h"
void Slot1Comp_Rom::start(eSlot1Operation operation, u32 addr)
{
this->operation = operation;
this->address = addr;
}
u32 Slot1Comp_Rom::read()
{
switch(operation)
{
case eSlot1Operation_00_ReadHeader_Unencrypted:
{
u32 ret = gameInfo.readROM(address);
address = (address + 4) & 0xFFF;
return ret;
}
break;
case eSlot1Operation_2x_SecureAreaLoad:
{
//see B7 for details
//zero 15-sep-2014 - this is meaningless. newer mask is actually reasonable
//address &= gameInfo.mask; //sanity check
u32 secureAreaAddress = (address - 0x4000);
secureAreaAddress &= 0x3FFF; //memory safe sanity test
u32 ret = LE_TO_LOCAL_32(*(u32*)(gameInfo.secureArea + secureAreaAddress));
address = (address&~0xFFF) + ((address+4)&0xFFF);
return ret;
}
case eSlot1Operation_B7_Read:
{
//TODO - check about non-4-byte aligned addresses
//it seems that etrian odyssey 3 doesnt work unless we mask this to cart size.
//but, a thought: does the internal rom address counter register wrap around? we may be making a mistake by keeping the extra precision
//but there is no test case yet
address &= gameInfo.mask;
//feature of retail carts:
//B7 "Can be used only for addresses 8000h and up, smaller addresses will be silently redirected to address `8000h+(addr AND 1FFh)`"
if(CommonSettings.RetailCardProtection8000)
if(address < 0x8000)
address = (0x8000 + (address & 0x1FF));
//1. as a sanity measure for funny-sized roms (homebrew and perhaps truncated retail roms) we need to protect ourselves by returning 0xFF for things still out of range.
//2. this isnt right, unless someone documents otherwise:
//if (address > gameInfo.header.endROMoffset)
// ... the cart hardware doesnt know anything about the rom header. if it has a totally bogus endROMoffset, the cart will probably work just fine. and, the +4 is missing anyway:
//3. this is better: it just allows us to read 0xFF anywhere we dont have rom data. forget what the header says
//note: we allow the reading to proceed anyway, because the readROM method is built to allow jaggedy reads off the end of the rom to support trimmed roms
if(address+4 > gameInfo.romsize)
{
DEBUG_Notify.ReadBeyondEndOfCart(address,gameInfo.romsize);
}
//actually read from the ROM provider
u32 ret = gameInfo.readROM(address);
//"However, the datastream wraps to the begin of the current 4K block when address+length crosses a 4K boundary (1000h bytes)"
address = (address&~0xFFF) + ((address+4)&0xFFF);
return ret;
}
break;
default:
return 0;
} //switch(operation)
} //Slot1Comp_Rom::read()
u32 Slot1Comp_Rom::getAddress()
{
return address & gameInfo.mask;
} //Slot1Comp_Rom::getAddress()
u32 Slot1Comp_Rom::incAddress()
{
address &= gameInfo.mask;
address = (address&~0xFFF) + ((address+4)&0xFFF);
return address;
}
void Slot1Comp_Rom::savestate(EMUFILE &os)
{
s32 version = 0;
os.write_32LE(version);
os.write_32LE((s32)operation);
os.write_32LE(address);
}
void Slot1Comp_Rom::loadstate(EMUFILE &is)
{
s32 version = is.read_s32LE();
operation = (eSlot1Operation)is.read_s32LE();
address = is.read_u32LE();
}

View File

@ -1,45 +0,0 @@
/*
Copyright (C) 2010-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
//this file contains the components used for emulating standard gamecard ROMs
//this is largely done by accessing the rom provided in the core emulator
#ifndef _SLOT1COMP_ROM_H
#define _SLOT1COMP_ROM_H
#include "slot1comp_protocol.h"
#include "../types.h"
class EMUFILE;
class Slot1Comp_Rom
{
public:
void start(eSlot1Operation operation, u32 addr);
u32 read();
u32 getAddress();
u32 incAddress();
void savestate(EMUFILE &os);
void loadstate(EMUFILE &is);
private:
u32 address;
eSlot1Operation operation;
};
#endif

View File

@ -1,72 +0,0 @@
/*
Copyright (C) 2013-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "../slot2.h"
class Slot2_Auto : public ISlot2Interface
{
private:
ISlot2Interface *mSelectedImplementation;
public:
Slot2_Auto()
: mSelectedImplementation(NULL)
{
}
virtual Slot2Info const* info()
{
static Slot2InfoSimple info("Auto","Slot2 (auto-selection) device emulation", 0xFE);
return &info;
}
virtual void connect()
{
slot2_selected_type = slot2_DetermineType();
mSelectedImplementation = slot2_List[slot2_selected_type];
mSelectedImplementation->connect();
printf("Slot2 auto-selected device type: %s (0x%02X)\n", mSelectedImplementation->info()->name(), mSelectedImplementation->info()->id());
}
virtual void disconnect()
{
if(mSelectedImplementation) mSelectedImplementation->disconnect();
mSelectedImplementation = NULL;
}
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val) { mSelectedImplementation->writeByte(PROCNUM, addr, val); }
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val) { mSelectedImplementation->writeWord(PROCNUM, addr, val); }
virtual void writeLong(u8 PROCNUM, u32 addr, u32 val) { mSelectedImplementation->writeLong(PROCNUM, addr, val); }
virtual u8 readByte(u8 PROCNUM, u32 addr) { return mSelectedImplementation->readByte(PROCNUM, addr); }
virtual u16 readWord(u8 PROCNUM, u32 addr) { return mSelectedImplementation->readWord(PROCNUM, addr); }
virtual u32 readLong(u8 PROCNUM, u32 addr) { return mSelectedImplementation->readLong(PROCNUM, addr); }
virtual void savestate(EMUFILE &os)
{
mSelectedImplementation->savestate(os);
}
virtual void loadstate(EMUFILE &is)
{
mSelectedImplementation->loadstate(is);
}
};
ISlot2Interface* construct_Slot2_Auto() { return new Slot2_Auto(); }

View File

@ -1,196 +0,0 @@
/*
Copyright (C) 2009 CrazyMax
Copyright (C) 2009-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../slot2.h"
#include "../emufile.h"
#include "../mem.h"
#if 0
#define EXPINFO(...) INFO(__VA_ARGS__)
#else
#define EXPINFO(...)
#endif
#define EXPANSION_MEMORY_SIZE (8 * 1024 * 1024)
static u8 header_0x00B0[] =
{ 0xFF, 0xFF, 0x96, 0x00, //this 0x96 is strange. it can't be read from the pak when it boots, it must appear later
0x00, 0x24, 0x24, 0x24,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x7F
};
class Slot2_ExpansionPak : public ISlot2Interface
{
private:
u8 *expMemory;
bool ext_ram_lock;
public:
Slot2_ExpansionPak()
{
expMemory = NULL;
ext_ram_lock = true;
}
virtual Slot2Info const* info()
{
static Slot2InfoSimple info("Memory Expansion Pak", "Official RAM expansion for Opera browser", 0x05);
return &info;
}
virtual void connect()
{
if (expMemory == NULL)
{
expMemory = new u8[EXPANSION_MEMORY_SIZE];
}
memset(expMemory, 0xFF, EXPANSION_MEMORY_SIZE);
ext_ram_lock = true;
}
virtual void disconnect()
{
delete[] expMemory;
expMemory = NULL;
}
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
{
if (ext_ram_lock) return;
if (addr >= 0x09000000)
{
u32 offs = (addr - 0x09000000);
if (offs >= EXPANSION_MEMORY_SIZE) return;
T1WriteByte(expMemory, offs, val);
}
EXPINFO("ExpMemory: write 08 at 0x%08X = 0x%02X\n", addr, val);
}
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
{
if (addr == 0x08240000)
{
if (val == 0)
ext_ram_lock = true;
else
if (val == 1)
ext_ram_lock = false;
return;
}
if (ext_ram_lock) return;
if (addr >= 0x09000000)
{
u32 offs = (addr - 0x09000000);
if (offs >= EXPANSION_MEMORY_SIZE) return;
T1WriteWord(expMemory, offs, val);
}
EXPINFO("ExpMemory: write 16 at 0x%08X = 0x%04X\n", addr, val);
}
virtual void writeLong(u8 PROCNUM, u32 addr, u32 val)
{
if (ext_ram_lock) return;
if (addr >= 0x09000000)
{
u32 offs = (addr - 0x09000000);
if (offs >= EXPANSION_MEMORY_SIZE) return;
T1WriteLong(expMemory, offs, val);
}
EXPINFO("ExpMemory: write 32 at 0x%08X = 0x%08X\n", addr, val);
}
virtual u8 readByte(u8 PROCNUM, u32 addr)
{
EXPINFO("ExpMemory: read 08 at 0x%08X\n", addr);
if ((addr >= 0x080000B0) && (addr < 0x080000C0))
return T1ReadByte(header_0x00B0, (addr - 0x080000B0));
if (addr >= 0x09000000)
{
u32 offs = (addr - 0x09000000);
if (offs >= EXPANSION_MEMORY_SIZE) return (0xFF);
return T1ReadByte(expMemory, offs);
}
return 0xFF;
}
virtual u16 readWord(u8 PROCNUM, u32 addr)
{
EXPINFO("ExpMemory: read 16 at 0x%08X\n", addr);
if ((addr >= 0x080000B0) && (addr < 0x080000C0))
return T1ReadWord(header_0x00B0, (addr - 0x080000B0));
if (addr == 0x0801FFFC) return 0x7FFF;
if (addr == 0x08240002) return 0; //this can't be 0xFFFF. dunno why, we just guessed 0
if (addr >= 0x09000000)
{
u32 offs = (addr - 0x09000000);
if (offs >= EXPANSION_MEMORY_SIZE) return (0xFFFF);
return T1ReadWord(expMemory, offs);
}
return 0xFFFF;
}
virtual u32 readLong(u8 PROCNUM, u32 addr)
{
EXPINFO("ExpMemory: read 32 at 0x%08X\n", addr);
if((addr >= 0x080000B0) && (addr < 0x080000C0))
return T1ReadLong(header_0x00B0, (addr - 0x080000B0));
if (addr >= 0x09000000)
{
u32 offs = (addr - 0x09000000);
if (offs >= EXPANSION_MEMORY_SIZE) return 0xFFFFFFFF;
return T1ReadLong(expMemory, offs);
}
return 0xFFFFFFFF;
}
virtual void savestate(EMUFILE &os)
{
s32 version = 0;
EMUFILE_MEMORY ram = EMUFILE_MEMORY(expMemory, EXPANSION_MEMORY_SIZE);
os.write_32LE(version);
os.write_bool32(ext_ram_lock);
os.write_MemoryStream(ram);
}
virtual void loadstate(EMUFILE &is)
{
EMUFILE_MEMORY ram = EMUFILE_MEMORY();
s32 version = is.read_s32LE();
if (version >= 0)
{
is.read_bool32(ext_ram_lock);
is.read_MemoryStream(ram);
memcpy(expMemory, ram.buf(), std::min(EXPANSION_MEMORY_SIZE, ram.size()));
}
}
};
ISlot2Interface* construct_Slot2_ExpansionPak() { return new Slot2_ExpansionPak(); }

View File

@ -1,463 +0,0 @@
/*
Copyright (C) 2009 CrazyMax
Copyright (C) 2009-2016 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../slot2.h"
#include <string.h>
#include "../debug.h"
#include "../NDSSystem.h"
#include "../path.h"
#include "../emufile.h"
#define EEPROM 0x52504545
#define SRAM_ 0x4D415253
#define FLASH 0x53414C46
#define FLASH1M_ 0x5F4D3148
#define SIIRTC_V 0x52494953
static const char *saveTypes[] = {
"EEPROM",
"SRAM",
"FLASH",
"FLASH1M",
"SIIRTC_V",
};
class Slot2_GbaCart : public ISlot2Interface
{
private:
EMUFILE* fROM;
EMUFILE* fSRAM;
u32 romSize;
u32 sramSize;
u32 saveType;
struct
{
u32 size;
u8 state;
u8 cmd;
u8 idDevice;
u8 idManufacturer;
u8 bank;
} gbaFlash;
u32 readRom(const u32 pos, const u8 size)
{
if (!fROM) return 0xFFFFFFFF;
fROM->fseek(pos, SEEK_SET);
u32 data = 0xFFFFFFFF;
u32 readed = fROM->fread(&data, size);
return data;
}
u32 readSRAM(const u32 pos, const u8 size)
{
if (!fSRAM)
return 0xFFFFFFFF;
fSRAM->fseek(pos, SEEK_SET);
u32 data = 0xFFFFFFFF;
u32 readed = fSRAM->fread(&data, size);
return data;
}
void writeSRAM(const u32 pos, const u8 *data, u32 size)
{
if (!fSRAM)
return;
fSRAM->fseek(pos, SEEK_SET);
u32 writed = size;
fSRAM->fwrite(data, size);
fSRAM->fflush();
}
u32 scanSaveTypeGBA()
{
if (!fROM) return 0xFF;
fROM->fseek(0, SEEK_SET);
int size = fROM->size();
int lastpct=1;
int len = fROM->size();
for(;;)
{
u32 tmp;
u32 readed = fROM->fread(&tmp, 4);
int pos = fROM->ftell();
int currPct = pos*100/(size-1);
for(int i=lastpct;i<currPct;i++)
{
if(i%10==0)
printf(" %d%%\n",i/10*10);
else printf(".");
lastpct = currPct;
}
if (readed < 4)
break;
if(pos >= len)
break;
switch (tmp)
{
case EEPROM:
return 1;
case SRAM_:
return 2;
case FLASH:
{
u32 tmp = fROM->read_u32LE();
return ((tmp == FLASH1M_)?3:5);
}
case SIIRTC_V:
return 4;
}
}
return 0xFF;
}
void gbaWriteFlash(u32 adr, u8 val)
{
if (!fSRAM) return;
switch (gbaFlash.state)
{
case 0:
if (adr == 0x0A005555)
{
if (val == 0xF0)
{
//INFO("GBAgame: Flash: reset\n");
gbaFlash.state = 0;
gbaFlash.cmd = 0;
return;
}
if (val == 0xAA)
{
gbaFlash.state = 1;
return;
}
}
if (adr == 0x0A000000)
{
if (gbaFlash.cmd == 0xB0)
{
gbaFlash.bank = val;
gbaFlash.cmd = 0;
//INFO("GBAgame: Flash: change bank %i\n", val);
return;
}
}
break;
case 1:
if ( (adr == 0x0A002AAA) && (val == 0x55) )
{
gbaFlash.state = 2;
return;
}
gbaFlash.state = 0;
break;
case 2:
if (adr == 0x0A005555)
{
//INFO("GBAgame: Flash: send command flash 0x%02X\n", val);
switch (val)
{
case 0x80: // Erase
gbaFlash.state = 0x80;
break;
case 0x90: // Chip Identification
gbaFlash.state = 0x90;
break;
case 0xA0: // Write
gbaFlash.state = 0;
break;
default:
gbaFlash.state = 0;
break;
}
gbaFlash.cmd = val;
return;
}
gbaFlash.state = 0;
break;
// erase
case 0x80:
if ( (adr == 0x0A005555) && (val == 0xAA) )
{
gbaFlash.state = 0x81;
return;
}
gbaFlash.state = 0;
break;
case 0x81:
if ( (adr == 0x0A002AAA) && (val == 0x55) )
{
gbaFlash.state = 0x82;
return;
}
gbaFlash.state = 0;
break;
case 0x82:
if (val == 0x30)
{
u32 ofs = (adr & 0x0000F000) + (0x10000 * gbaFlash.bank);
//INFO("GBAgame: Flash: erase from 0x%08X to 0x%08X\n", ofs + 0x0A000000, ofs + 0x0A001000);
u8 *tmp = new u8[0x1000];
memset(tmp, 0xFF, 0x1000);
writeSRAM(ofs, tmp, 0x1000);
delete [] tmp;
}
gbaFlash.state = 0;
gbaFlash.cmd = 0;
return;
// Chip Identification
case 0x90:
if ( (adr == 0x0A005555) && (val == 0xAA) )
{
gbaFlash.state = 0x91;
return;
}
gbaFlash.state = 0;
break;
case 0x91:
if ( (adr == 0x0A002AAA) && (val == 0x55) )
{
gbaFlash.state = 0x92;
return;
}
gbaFlash.state = 0;
break;
case 0x92:
gbaFlash.state = 0;
gbaFlash.cmd = 0;
return;
}
if (gbaFlash.cmd == 0xA0) // write
{
writeSRAM((adr & 0x1FFFF) + (0x10000 * gbaFlash.bank), &val, 1);
gbaFlash.state = 0;
gbaFlash.cmd = 0;
return;
}
INFO("GBAgame: Flash: write unknown atn 0x%08X = 0x%02X\n", adr, val);
}
u8 gbaReadFlash(u32 adr)
{
if (!fSRAM) return 0xFF;
if (gbaFlash.cmd == 0)
return readSRAM((adr & 0x1FFFF) + (0x10000 * gbaFlash.bank), 1);
//INFO("GBAgame: flash read at 0x%08X\n", adr);
switch (gbaFlash.cmd)
{
case 0x90: // Chip Identification
if (adr == 0x0A000000) return gbaFlash.idManufacturer;
if (adr == 0x0A000001) return gbaFlash.idDevice;
break;
case 0xF0: //
gbaFlash.state = 0;
gbaFlash.cmd = 0;
break;
case 0xB0: // Bank switching
break;
default:
INFO("GBAgame: Flash: read - unknown command at 0x%08X = 0x%02X\n", adr, gbaFlash.cmd);
break;
}
return 0xFF;
}
void Close()
{
delete fROM; fROM = NULL;
delete fSRAM; fSRAM = NULL;
romSize = 0;
sramSize = 0;
}
public:
Slot2_GbaCart()
: fROM(NULL)
, fSRAM(NULL)
{
Close();
}
virtual Slot2Info const* info()
{
static Slot2InfoSimple info("GBA Cartridge", "GBA cartridge in slot", 0x03);
return &info;
}
virtual void connect()
{
Close();
romSize = 0;
sramSize = 0;
if (gameInfo.romsize == 0)
{
return;
}
if (GBACartridge_RomPath.empty())
{
return;
}
if (!strcasecmp(GBACartridge_RomPath.c_str(), "self"))
{
GBACartridge_RomPath = path.path;
GBACartridge_SRAMPath = Path::GetFileNameWithoutExt(GBACartridge_RomPath) + "." + GBA_SRAM_FILE_EXT;
}
printf("GBASlot opening ROM: %s\n", GBACartridge_RomPath.c_str());
EMUFILE_FILE *inf = new EMUFILE_FILE(GBACartridge_RomPath, "rb");
fROM = inf;
if (fROM->fail())
{
printf(" - Failed\n");
Close();
return;
}
inf->EnablePositionCache();
romSize = fROM->size();
printf(" - Success (%u bytes)\n", romSize);
// Load the GBA cartridge SRAM.
inf = new EMUFILE_FILE(GBACartridge_SRAMPath, "rb+");
fSRAM = inf;
if(fSRAM->fail())
{
delete fSRAM;
fSRAM = NULL;
printf("GBASlot did not load associated SRAM.\n");
}
else
{
inf->EnablePositionCache();
sramSize = fSRAM->size();
printf("Scanning GBA rom to ID save type\n");
saveType = scanSaveTypeGBA();
printf("\nGBASlot found SRAM (%s - %u bytes) at:\n%s\n", (saveType == 0xFF)?"Unknown":saveTypes[saveType], sramSize, GBACartridge_SRAMPath.c_str());
gbaFlash.size = sramSize;
if (gbaFlash.size <= (64 * 1024))
{
gbaFlash.idDevice = 0x1B;
gbaFlash.idManufacturer = 0x32;
}
else
{
gbaFlash.idDevice = 0x09;
gbaFlash.idManufacturer = 0xC2;
}
gbaFlash.state = 0;
}
}
virtual void disconnect()
{
Close();
}
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
{
if ((addr >= 0x0A000000) && (addr < 0x0A010000))
{
switch (saveType)
{
case 3: // Flash
case 5:
gbaWriteFlash(addr, val);
break;
default: break;
}
}
}
virtual u8 readByte(u8 PROCNUM, u32 addr)
{
if (addr < 0x0A000000)
return (u8)readRom(addr - 0x08000000, 1);
if (addr < 0x0A010000)
{
if ((saveType == 3) || (saveType == 5))
return gbaReadFlash(addr);
return (u8)readSRAM(addr - 0x0A000000, 1);
}
return 0xFF;
}
virtual u16 readWord(u8 PROCNUM, u32 addr)
{
if (addr < 0x0A000000)
return (u16)readRom(addr - 0x08000000, 2);
if (addr < 0x0A010000)
return (u16)readSRAM(addr - 0x0A000000, 2);
return 0xFFFF;
}
virtual u32 readLong(u8 PROCNUM, u32 addr)
{
if (addr < 0x0A000000)
return (u32)readRom(addr - 0x08000000, 4);
if (addr < 0x0A010000)
return (u32)readSRAM(addr - 0x0A000000, 4);
return 0xFFFFFFFF;
}
};
ISlot2Interface* construct_Slot2_GbaCart() { return new Slot2_GbaCart(); }

View File

@ -1,65 +0,0 @@
/*
Copyright (C) 2009 CrazyMax
Copyright (C) 2009-2013 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../slot2.h"
static u8 guitarKeyStatus;
class Slot2_GuitarGrip : public ISlot2Interface
{
private:
public:
virtual Slot2Info const* info()
{
static Slot2InfoSimple info("Guitar Grip", "Guitar Grip for Guitar Hero games", 0x04);
return &info;
}
virtual void connect()
{
guitarKeyStatus = 0xFF;
}
virtual u8 readByte(u8 PROCNUM, u32 addr)
{
if (addr == 0x0A000000)
return guitarKeyStatus;
return (addr & 1) ? 0xF9 : 0xFF;
}
virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xF9FF; }
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xF9FFF9FF; }
};
ISlot2Interface* construct_Slot2_GuitarGrip() { return new Slot2_GuitarGrip(); }
void guitarGrip_setKey(bool green, bool red, bool yellow, bool blue)
{
const u8 g = (green) ? (1 << 6) : 0;
const u8 r = (red) ? (1 << 5) : 0;
const u8 y = (yellow) ? (1 << 4) : 0;
const u8 b = (blue) ? (1 << 3) : 0;
guitarKeyStatus = ~(g | r | y | b);
}
void guitarGrip_setKey(u8 theKeys)
{
guitarKeyStatus = theKeys;
}

View File

@ -1,301 +0,0 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006 Mic
Copyright (C) 2009-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "../slot2.h"
#include "../debug.h"
#include "../emufile.h"
#include "../path.h"
#include "../utils/vfat.h"
// Set up addresses for GBAMP
#define CF_REG_DATA 0x9000000
#define CF_REG_ERR 0x9020000
#define CF_REG_SEC 0x9040000
#define CF_REG_LBA1 0x9060000
#define CF_REG_LBA2 0x9080000
#define CF_REG_LBA3 0x90A0000
#define CF_REG_LBA4 0x90C0000
#define CF_REG_CMD 0x90E0000
#define CF_REG_STS 0x98C0000
// CF Card commands
#define CF_CMD_LBA 0xE0
#define CF_CMD_READ 0x20
#define CF_CMD_WRITE 0x30
static u16 cf_reg_sts,
cf_reg_lba1,
cf_reg_lba2,
cf_reg_lba3,
cf_reg_lba4,
cf_reg_cmd;
static off_t currLBA;
static const int lfnPos[13] = {1,3,5,7,9,14,16,18,20,22,24,28,30};
static u32 fileStartLBA,fileEndLBA;
static std::string sFlashPath;
static BOOL cflashDeviceEnabled = FALSE;
static EMUFILE* file = NULL;
// ===========================
BOOL inited;
enum EListCallbackArg {
EListCallbackArg_Item, EListCallbackArg_Pop
};
static BOOL cflash_init()
{
if (inited) return FALSE;
BOOL init_good = FALSE;
CFLASHLOG("CFlash_Mode: %d\n",CFlash_Mode);
if (CFlash_Mode == ADDON_CFLASH_MODE_RomPath)
{
sFlashPath = path.RomDirectory;
INFO("Using CFlash directory of rom: %s\n", sFlashPath.c_str());
}
else if(CFlash_Mode == ADDON_CFLASH_MODE_Path)
{
sFlashPath = CFlash_Path;
INFO("Using CFlash directory: %s\n", sFlashPath.c_str());
}
else if(CFlash_Mode == ADDON_CFLASH_MODE_File)
{
sFlashPath = CFlash_Path;
INFO("Using CFlash disk image file %s\n", sFlashPath.c_str());
}
else
{
return FALSE;
}
if (sFlashPath == "") return FALSE;
if(CFlash_IsUsingPath())
{
cflashDeviceEnabled = FALSE;
currLBA = 0;
fileStartLBA = fileEndLBA = 0xFFFFFFFF;
VFAT vfat;
bool ret = vfat.build(sFlashPath.c_str(),16); //allocate 16MB extra for writing. this is probably enough for anyone, but maybe it should be configurable.
//we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded)
if(!ret)
{
CFLASHLOG("FAILED cflash_build_fat\n");
return FALSE;
}
file = vfat.detach();
cf_reg_sts = 0x58; // READY
cflashDeviceEnabled = TRUE;
init_good = TRUE;
}
else
{
file = new EMUFILE_FILE(sFlashPath.c_str(),"rb+");
if(file->fail())
{
INFO("Failed to open file %s\n", sFlashPath.c_str());
delete file;
file = NULL;
}
}
// READY
cf_reg_sts = 0x58;
currLBA = 0;
cf_reg_lba1 = cf_reg_lba2 =
cf_reg_lba3 = cf_reg_lba4 = 0;
inited = TRUE;
return init_good;
}
static unsigned int cflash_read(unsigned int address)
{
unsigned int ret_value = 0;
size_t elems_read = 0;
switch (address)
{
case CF_REG_STS:
ret_value = cf_reg_sts;
break;
case CF_REG_DATA:
if (cf_reg_cmd == CF_CMD_READ)
{
if(file)
{
u8 data[2] = {0,0};
file->fseek(currLBA, SEEK_SET);
elems_read += file->fread(data,2);
ret_value = data[1] << 8 | data[0];
}
currLBA += 2;
}
break;
case CF_REG_CMD:
break;
case CF_REG_LBA1:
ret_value = cf_reg_lba1;
break;
}
return ret_value;
}
static void cflash_write(unsigned int address,unsigned int data)
{
static u8 sector_data[512];
static u32 sector_write_index = 0;
switch (address)
{
case CF_REG_STS:
cf_reg_sts = data&0xFFFF;
break;
case CF_REG_DATA:
if (cf_reg_cmd == CF_CMD_WRITE)
{
{
sector_data[sector_write_index] = (data >> 0) & 0xff;
sector_data[sector_write_index + 1] = (data >> 8) & 0xff;
sector_write_index += 2;
if (sector_write_index == 512)
{
CFLASHLOG( "Write sector to %ld\n", currLBA);
size_t written = 0;
if(file)
if(currLBA + 512 < file->size())
{
file->fseek(currLBA,SEEK_SET);
while(written < 512)
{
size_t todo = 512-written;
file->fwrite(&sector_data[written], todo);
size_t cur_write = todo;
written += cur_write;
if ( cur_write == (size_t)-1) break;
}
}
CFLASHLOG("Wrote %u bytes\n", written);
currLBA += 512;
sector_write_index = 0;
}
}
}
break;
case CF_REG_CMD:
cf_reg_cmd = data&0xFF;
cf_reg_sts = 0x58; // READY
break;
case CF_REG_LBA1:
cf_reg_lba1 = data&0xFF;
currLBA = (currLBA&0xFFFFFF00)| cf_reg_lba1;
break;
case CF_REG_LBA2:
cf_reg_lba2 = data&0xFF;
currLBA = (currLBA&0xFFFF00FF)|(cf_reg_lba2<<8);
break;
case CF_REG_LBA3:
cf_reg_lba3 = data&0xFF;
currLBA = (currLBA&0xFF00FFFF)|(cf_reg_lba3<<16);
break;
case CF_REG_LBA4:
cf_reg_lba4 = data&0xFF;
if ((cf_reg_lba4 & 0xf0) == CF_CMD_LBA)
{
currLBA = (currLBA&0x00FFFFFF)|((cf_reg_lba4&0x0F)<<24);
currLBA *= 512;
sector_write_index = 0;
}
break;
}
}
static void cflash_close( void)
{
if (!inited) return;
if(file) delete file;
cflashDeviceEnabled = FALSE;
file = NULL;
inited = FALSE;
}
class Slot2_CFlash : public ISlot2Interface
{
public:
virtual Slot2Info const* info()
{
static Slot2InfoSimple info("MPCF Flash Card Device", "MPCF Flash Card Device", 0x01);
return &info;
}
virtual void connect()
{
cflash_close();
cflash_init();
}
virtual void disconnect()
{
cflash_close();
}
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val) { cflash_write(addr, val); }
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val) { cflash_write(addr, val); }
virtual void writeLong(u8 PROCNUM, u32 addr, u32 val) { cflash_write(addr, val); }
virtual u8 readByte(u8 PROCNUM, u32 addr) { return (cflash_read(addr)); }
virtual u16 readWord(u8 PROCNUM, u32 addr) { return (cflash_read(addr)); }
virtual u32 readLong(u8 PROCNUM, u32 addr) { return (cflash_read(addr)); }
};
ISlot2Interface* construct_Slot2_CFlash() { return new Slot2_CFlash(); }

View File

@ -1,31 +0,0 @@
/*
Copyright (C) 2009 CrazyMax
Copyright (C) 2009-2013 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../slot2.h"
class Slot2_None : public ISlot2Interface
{
public:
virtual Slot2Info const* info()
{
static Slot2InfoSimple info("None", "Slot2 no-device emulation", 0xFF);
return &info;
}
};
ISlot2Interface* construct_Slot2_None() { return new Slot2_None(); }

View File

@ -1,143 +0,0 @@
/*
Copyright (C) 2011-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
/*
this device seems to have a 12bit value (like 20.12 fixed point.. get it?) located at 0x0A000000
clockwise = right = increases.
it returns the correct little endian bytes through byte reads.
through halfword reads, it returns the LSB twice
through full word reads, it returns the LSB four times.
after that everything is 0x00.
if the slot2 timings are wrong, then this device will return glitchy or 0xFF output.
so this emulation code will attempt to validate that.
arkanoid was setting REG_EXMEMCNT = 0x082F
the rom returns 0xEFFF for all addresses and should be used to detect this device
writing any byte to SRAM or writing any halfword/word to rom results in a reset or some kind of recalibrate
the resulting value may be 0x000,0x001, or 0xFFF. seems mostly random, though once it is reset, resetting again won't change it.
you must wait until the paddle has been moved.
conclusion:
The emulation in all the handling of erroneous cases is not perfect, and some other users of the paddle (do any other games use it?)
maybe legally configure the paddle differently, which could be rejected here; in which case this code will need finetuning
*/
#include <string.h>
#include "../slot2.h"
#include "../NDSSystem.h"
class Slot2_Paddle : public ISlot2Interface
{
private:
void calibrate() { nds.paddle = 0; }
bool Validate(u32 procnum, bool rom)
{
if(rom)
return ValidateSlot2Access(procnum, 0, 0, 0, -1);
else
return ValidateSlot2Access(procnum, 18, 0, 0, 1);
}
public:
virtual Slot2Info const* info()
{
static Slot2InfoSimple info("Paddle Controller", "Taito Paddle Controller", 0x07);
return &info;
}
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
{
if (addr < 0x0A000000)
calibrate();
}
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
{
if (addr < 0x0A000000)
calibrate();
}
virtual void writeLong(u8 PROCNUM, u32 addr, u32 val)
{
if (addr < 0x0A000000)
calibrate();
}
virtual u8 readByte(u8 PROCNUM, u32 addr)
{
//printf("paddle: read 08 at 0x%08X\n", addr);
if (!Validate(PROCNUM, (addr < 0x0A000000)))
return 0xFF;
if (addr < 0x0A000000)
return (addr & 1)?0xFF:0xEF;
if (addr == 0x0A000000)
return (nds.paddle & 0xFF);
if (addr == 0x0A000001)
return ((nds.paddle >> 8) & 0x0F);
return 0x00;
}
virtual u16 readWord(u8 PROCNUM, u32 addr)
{
//printf("paddle: read 16 at 0x%08X\n", addr);
if (!Validate(PROCNUM, (addr < 0x0A000000)))
return 0xFFFF;
if (addr < 0x0A000000)
return 0xEFFF;
if (addr == 0x0A000000)
{
u8 val = (nds.paddle & 0xFF);
return (val | (val << 8));
}
return 0x0000;
}
virtual u32 readLong(u8 PROCNUM, u32 addr)
{
//printf("paddle: read 32 at 0x%08X\n", addr);
if (!Validate(PROCNUM, (addr < 0x0A000000)))
return 0xFFFFFFFF;
if (addr < 0x0A000000)
return 0xEFFFEFFF;
if (addr == 0x0A000000)
{
u8 val = (nds.paddle & 0xFF);
return (val | (val << 8) | (val << 16) | (val << 24));
}
return 0x00000000;
}
};
u16 Paddle_GetValue()
{
return nds.paddle;
}
void Paddle_SetValue(u16 theValue)
{
nds.paddle = theValue;
}
ISlot2Interface* construct_Slot2_Paddle() { return new Slot2_Paddle(); }

View File

@ -1,56 +0,0 @@
/*
Copyright (C) 2013-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../slot2.h"
#include "../NDSSystem.h"
class Slot2_PassME : public ISlot2Interface
{
public:
virtual Slot2Info const* info()
{
static Slot2InfoSimple info("PassME", "PassME in GBA slot", 0x08);
return &info;
}
virtual u8 readByte(u8 PROCNUM, u32 addr)
{
u32 tmp_addr = (addr & 0x07FFFFFF);
if (tmp_addr < gameInfo.romsize)
return (u8)gameInfo.readROM(tmp_addr);
return (0xFF);
}
virtual u16 readWord(u8 PROCNUM, u32 addr)
{
u32 tmp_addr = (addr & 0x07FFFFFF);
if (tmp_addr < gameInfo.romsize)
return (u16)gameInfo.readROM(tmp_addr);
return (0xFFFF);
}
virtual u32 readLong(u8 PROCNUM, u32 addr)
{
u32 tmp_addr = (addr & 0x07FFFFFF);
if (tmp_addr < gameInfo.romsize)
return (u32)gameInfo.readROM(tmp_addr);
return (0xFFFFFFFF);
}
};
ISlot2Interface* construct_Slot2_PassME() { return new Slot2_PassME(); }

View File

@ -1,122 +0,0 @@
/*
Copyright (C) 2010-2013 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../slot2.h"
static u16 pianoKeyStatus = 0;
class Slot2_EasyPiano : public ISlot2Interface
{
public:
virtual Slot2Info const* info()
{
static Slot2InfoSimple info("Piano", "Piano for EasyPiano", 0x06);
return &info;
}
virtual void connect()
{
pianoKeyStatus = 0xE7FF;
}
virtual u8 readByte(u8 PROCNUM, u32 addr)
{
//printf("piano: read 08 at 0x%08X\n", adr);
//the actual keyboard output
//byte:bit
//0x09FFFFFE:0 = C
//0x09FFFFFE:1 = C#
//0x09FFFFFE:2 = D
//0x09FFFFFE:3 = D#
//0x09FFFFFE:4 = E
//0x09FFFFFE:5 = F
//0x09FFFFFE:6 = F#
//0x09FFFFFE:7 = G
//0x09FFFFFF:0 = G#
//0x09FFFFFF:1 = A
//0x09FFFFFF:2 = A#
//0x09FFFFFF:3 = ?
//0x09FFFFFF:4 = ?
//0x09FFFFFF:5 = B
//0x09FFFFFF:6 = hiC
//0x09FFFFFF:7 = ?
//deassert bit if key is pressed
//LOG("PIANO: %04X\n",pianoKeyStatus);
if (addr == 0x09FFFFFE) return ((pianoKeyStatus >> 0) & 0xFF);
if (addr == 0x09FFFFFF) return ((pianoKeyStatus >> 8) & 0xFF) & ~(0x18);
return (addr & 1) ? 0xE7 : 0xFF;
}
virtual u16 readWord(u8 PROCNUM, u32 addr)
{
if (addr != 0x09FFFFFE)
return 0xE7FF;
return readByte(PROCNUM, 0x09FFFFFE) | (readByte(PROCNUM,0x09FFFFFF) << 8);
}
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xE7FFE7FF; }
};
ISlot2Interface* construct_Slot2_EasyPiano() { return new Slot2_EasyPiano(); }
void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool fs, bool g, bool gs, bool a, bool as, bool b, bool hic)
{
//0x09FFFFFE:0 = C
//0x09FFFFFE:1 = C#
//0x09FFFFFE:2 = D
//0x09FFFFFE:3 = D#
//0x09FFFFFE:4 = E
//0x09FFFFFE:5 = F
//0x09FFFFFE:6 = F#
//0x09FFFFFE:7 = G
//0x09FFFFFE:0 = G#
//0x09FFFFFE:1 = A
//0x09FFFFFF:2 = A#
//0x09FFFFFF:3 = ?
//0x09FFFFFF:4 = ?
//0x09FFFFFF:5 = B
//0x09FFFFFF:6 = hiC
//0x09FFFFFF:7 = ?
#define BIT_P(N,v) ((v)?(1<<(N)):0)
pianoKeyStatus = ~(
BIT_P(0,c) |
BIT_P(1,cs) |
BIT_P(2,d) |
BIT_P(3,ds) |
BIT_P(4,e) |
BIT_P(5,f) |
BIT_P(6,fs) |
BIT_P(7,g) |
BIT_P(8,gs) |
BIT_P(9,a) |
BIT_P(10,as) |
BIT_P(13,b) |
BIT_P(14,hic)
);
}
void piano_setKey(u16 theKeys)
{
pianoKeyStatus = theKeys;
}

View File

@ -1,62 +0,0 @@
/*
Copyright (C) 2009 CrazyMax
Copyright (C) 2009-2013 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../slot2.h"
void (*FeedbackON)(bool enable) = NULL;
class Slot2_RumblePak : public ISlot2Interface
{
private:
u16 old_val_rumble;
public:
virtual Slot2Info const* info()
{
static Slot2InfoSimple info("Rumble Pak", "NDS Rumble Pak (need joystick with Feedback)", 0x02);
return &info;
}
virtual void connect()
{
old_val_rumble = 0;
if (!FeedbackON) return;
FeedbackON(false);
}
virtual void disconnect()
{
FeedbackON(false);
}
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
{
if (!FeedbackON) return;
if (old_val_rumble == val) return;
old_val_rumble = val;
if ((addr == 0x08000000) || (addr == 0x08001000))
FeedbackON(val);
}
virtual u8 readByte(u8 PROCNUM, u32 addr) { return (addr & 1)?0xFF:0xFD; };
virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xFFFD; };
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xFFFDFFFD; };
};
ISlot2Interface* construct_Slot2_RumblePak() { return new Slot2_RumblePak(); }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,82 +0,0 @@
/* Copyright (C) 2006 yopyop
Copyright (C) 2011 Loren Merritt
Copyright (C) 2012-2013 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ARM_JIT
#define ARM_JIT
#include "types.h"
#ifndef _MSC_VER
#include <stdint.h>
#endif
typedef u32 (FASTCALL* ArmOpCompiled)();
void arm_jit_reset(bool enable, bool suppress_msg = false);
void arm_jit_close();
void arm_jit_sync();
template<int PROCNUM> u32 arm_jit_compile();
//#define MAPPED_JIT_FUNCS: to define or not to define?
//* x86 windows seems faster with NON-DEFINED
//* x64 windows seems faster with DEFINED
//* x86 windows seems to have problems without DEFINED when desmume is built as a dll due to the
// ~300 MB .bss section created by the 256MB non-mapped compiled_funcs table
// (when loaded as a dll into a busy process, that much contiguous address space is hard to find. No big deal when starting up a process)
//In principle, mapped compiled_funcs should be faster because it avoids some bit shifting logic to look it up from the memory map, right,
//but I guess it doesn't always work out that way.
//
//So here's my proposed policy. NON-DEFINED is dangerous due to the huge .bss section, so it should be the default
//The build system should #define JIT_FUNCS_FLAT to make the flat array
#ifndef JIT_FUNCS_FLAT
#define MAPPED_JIT_FUNCS
#endif
#ifdef MAPPED_JIT_FUNCS
struct JIT_struct
{
// only include the memory types that code can execute from
uintptr_t MAIN_MEM[16*1024*1024/2];
uintptr_t SWIRAM[0x8000/2];
uintptr_t ARM9_ITCM[0x8000/2];
uintptr_t ARM9_LCDC[0xA4000/2];
uintptr_t ARM9_BIOS[0x8000/2];
uintptr_t ARM7_BIOS[0x4000/2];
uintptr_t ARM7_ERAM[0x10000/2];
uintptr_t ARM7_WIRAM[0x10000/2];
uintptr_t ARM7_WRAM[0x40000/2];
static uintptr_t *JIT_MEM[2][0x4000];
};
extern CACHE_ALIGN JIT_struct JIT;
#define JIT_COMPILED_FUNC(adr, PROCNUM) JIT.JIT_MEM[PROCNUM][((adr)&0x0FFFC000)>>14][((adr)&0x00003FFE)>>1]
#define JIT_COMPILED_FUNC_PREMASKED(adr, PROCNUM, ofs) JIT.JIT_MEM[PROCNUM][(adr)>>14][(((adr)&0x00003FFE)>>1)+ofs]
#define JIT_COMPILED_FUNC_KNOWNBANK(adr, bank, mask, ofs) JIT.bank[(((adr)&(mask))>>1)+ofs]
#define JIT_MAPPED(adr, PROCNUM) JIT.JIT_MEM[PROCNUM][(adr)>>14]
#else
// actually an array of function pointers, but they fit in 32bit address space, so might as well save memory
extern uintptr_t compiled_funcs[];
// there isn't anything mapped between 07000000 and 0EFFFFFF, so we can mask off bit 27 and get away with a smaller array
#define JIT_COMPILED_FUNC(adr, PROCNUM) compiled_funcs[((adr) & 0x07FFFFFE) >> 1]
#define JIT_COMPILED_FUNC_PREMASKED(adr, PROCNUM, ofs) JIT_COMPILED_FUNC(adr+(ofs<<1), PROCNUM)
#define JIT_COMPILED_FUNC_KNOWNBANK(adr, bank, mask, ofs) JIT_COMPILED_FUNC(adr+(ofs<<1), PROCNUM)
#define JIT_MAPPED(adr, PROCNUM) true
#endif
extern u32 saveBlockSizeJIT;
#endif

View File

@ -1,765 +0,0 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2009-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <algorithm>
#include "armcpu.h"
#include "instructions.h"
#include "cp15.h"
#include "bios.h"
#include "debug.h"
#include "NDSSystem.h"
#include "MMU_timing.h"
#include "utils/bits.h"
#ifdef HAVE_LUA
#include "lua-engine.h"
#endif
#ifdef HAVE_JIT
#include "arm_jit.h"
#endif
template<u32> static u32 armcpu_prefetch();
FORCEINLINE u32 armcpu_prefetch(armcpu_t *armcpu) {
if(armcpu->proc_ID==0) return armcpu_prefetch<0>();
else return armcpu_prefetch<1>();
}
armcpu_t NDS_ARM7;
armcpu_t NDS_ARM9;
#define SWAP(a, b, c) do \
{ \
c=a; \
a=b; \
b=c; \
} \
while(0)
#define STALLED_CYCLE_COUNT 10
static void
stall_cpu( void *instance) {
armcpu_t *armcpu = (armcpu_t *)instance;
printf("STALL\n");
armcpu->stalled = 1;
}
static void
unstall_cpu( void *instance) {
armcpu_t *armcpu = (armcpu_t *)instance;
printf("UNSTALL\n");
armcpu->stalled = 0;
}
static void
install_post_exec_fn( void *instance,
void (*ex_fn)( void *, u32 adr, int thumb),
void *fn_data) {
armcpu_t *armcpu = (armcpu_t *)instance;
armcpu->post_ex_fn = ex_fn;
armcpu->post_ex_fn_data = fn_data;
}
static void
remove_post_exec_fn( void *instance) {
armcpu_t *armcpu = (armcpu_t *)instance;
armcpu->post_ex_fn = NULL;
}
static u32 read_cpu_reg( void *instance, u32 reg_num)
{
armcpu_t *armcpu = (armcpu_t *)instance;
if ( reg_num <= 14) {
return armcpu->R[reg_num];
}
else if ( reg_num == 15) {
return armcpu->instruct_adr;
}
else if ( reg_num == 16) {
//CPSR
return armcpu->CPSR.val;
}
return 0;
}
static void
set_cpu_reg( void *instance, u32 reg_num, u32 value) {
armcpu_t *armcpu = (armcpu_t *)instance;
if ( reg_num <= 14) {
armcpu->R[reg_num] = value;
}
else if ( reg_num == 15) {
armcpu->next_instruction = value;
}
else if ( reg_num == 16) {
/* FIXME: setting the CPSR */
}
}
int armcpu_new( armcpu_t *armcpu, u32 id)
{
armcpu->proc_ID = id;
armcpu->stalled = 0;
armcpu->base_mem_if.prefetch32 = NULL;
armcpu->base_mem_if.prefetch16 = NULL;
armcpu->base_mem_if.read8 = NULL;
armcpu->base_mem_if.read16 = NULL;
armcpu->base_mem_if.read32 = NULL;
armcpu->base_mem_if.write8 = NULL;
armcpu->base_mem_if.write16 = NULL;
armcpu->base_mem_if.write32 = NULL;
armcpu->base_mem_if.data = NULL;
armcpu->SetControlInterface(&arm_default_ctrl_iface);
armcpu->SetControlInterfaceData(armcpu);
armcpu->SetCurrentMemoryInterface(NULL);
armcpu->SetCurrentMemoryInterfaceData(NULL);
armcpu->post_ex_fn = NULL;
armcpu->post_ex_fn_data = NULL;
armcpu_init(armcpu, 0);
return 0;
}
void armcpu_t::SetControlInterface(const armcpu_ctrl_iface *theControlInterface)
{
this->ctrl_iface = *theControlInterface;
}
armcpu_ctrl_iface* armcpu_t::GetControlInterface()
{
return &this->ctrl_iface;
}
void armcpu_t::SetControlInterfaceData(void *theData)
{
this->ctrl_iface.data = theData;
}
void* armcpu_t::GetControlInterfaceData()
{
return this->ctrl_iface.data;
}
void armcpu_t::SetCurrentMemoryInterface(armcpu_memory_iface *theMemoryInterface)
{
this->mem_if = theMemoryInterface;
}
armcpu_memory_iface* armcpu_t::GetCurrentMemoryInterface()
{
return this->mem_if;
}
void armcpu_t::SetCurrentMemoryInterfaceData(void *theData)
{
if (this->mem_if != NULL)
{
this->mem_if->data = theData;
}
}
void* armcpu_t::GetCurrentMemoryInterfaceData()
{
return (this->mem_if != NULL) ? this->mem_if->data : NULL;
}
void armcpu_t::SetBaseMemoryInterface(const armcpu_memory_iface *theMemInterface)
{
this->base_mem_if = *theMemInterface;
}
armcpu_memory_iface* armcpu_t::GetBaseMemoryInterface()
{
return &this->base_mem_if;
}
void armcpu_t::SetBaseMemoryInterfaceData(void *theData)
{
this->base_mem_if.data = theData;
}
void* armcpu_t::GetBaseMemoryInterfaceData()
{
return this->base_mem_if.data;
}
void armcpu_t::ResetMemoryInterfaceToBase()
{
this->SetCurrentMemoryInterface(this->GetBaseMemoryInterface());
this->SetCurrentMemoryInterfaceData(this->GetBaseMemoryInterfaceData());
}
//call this whenever CPSR is changed (other than CNVZQ or T flags); interrupts may need to be unleashed
void armcpu_t::changeCPSR()
{
//but all it does is give them a chance to unleash by forcing an immediate reschedule
//TODO - we could actually set CPSR through here and look for a change in the I bit
//that would be a little optimization as well as a safety measure if we prevented setting CPSR directly
NDS_Reschedule();
}
void armcpu_init(armcpu_t *armcpu, u32 adr)
{
#if defined(_M_X64) || defined(__x86_64__)
memcpy(&armcpu->cond_table[0], &arm_cond_table[0], sizeof(arm_cond_table));
#endif
armcpu->LDTBit = (armcpu->proc_ID==0); //set ARMv5 style bit--different for each processor
armcpu->intVector = 0xFFFF0000 * (armcpu->proc_ID==0);
armcpu->freeze = CPU_FREEZE_NONE;
armcpu->intrWaitARM_state = 0;
//#ifdef GDB_STUB
// armcpu->irq_flag = 0;
//#endif
for(int i = 0; i < 16; ++i)
armcpu->R[i] = 0;
armcpu->CPSR.val = armcpu->SPSR.val = SYS;
armcpu->R13_usr = armcpu->R14_usr = 0;
armcpu->R13_svc = armcpu->R14_svc = 0;
armcpu->R13_abt = armcpu->R14_abt = 0;
armcpu->R13_und = armcpu->R14_und = 0;
armcpu->R13_irq = armcpu->R14_irq = 0;
armcpu->R8_fiq = armcpu->R9_fiq = armcpu->R10_fiq = armcpu->R11_fiq = armcpu->R12_fiq = armcpu->R13_fiq = armcpu->R14_fiq = 0;
armcpu->SPSR_svc.val = armcpu->SPSR_abt.val = armcpu->SPSR_und.val = armcpu->SPSR_irq.val = armcpu->SPSR_fiq.val = 0;
//#ifdef GDB_STUB
// armcpu->instruct_adr = adr;
// armcpu->R[15] = adr + 8;
//#else
//armcpu->R[15] = adr;
//#endif
//do something sensible when booting up to a thumb address
armcpu->next_instruction = adr & ~1;
armcpu->CPSR.bits.T = BIT0(adr);
//#ifndef GDB_STUB
armcpu_prefetch(armcpu);
//#endif
}
u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode)
{
u32 oldmode = armcpu->CPSR.bits.mode;
switch(oldmode)
{
case USR :
case SYS :
armcpu->R13_usr = armcpu->R[13];
armcpu->R14_usr = armcpu->R[14];
break;
case FIQ :
{
u32 tmp;
SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
armcpu->R13_fiq = armcpu->R[13];
armcpu->R14_fiq = armcpu->R[14];
armcpu->SPSR_fiq = armcpu->SPSR;
break;
}
case IRQ :
armcpu->R13_irq = armcpu->R[13];
armcpu->R14_irq = armcpu->R[14];
armcpu->SPSR_irq = armcpu->SPSR;
break;
case SVC :
armcpu->R13_svc = armcpu->R[13];
armcpu->R14_svc = armcpu->R[14];
armcpu->SPSR_svc = armcpu->SPSR;
break;
case ABT :
armcpu->R13_abt = armcpu->R[13];
armcpu->R14_abt = armcpu->R[14];
armcpu->SPSR_abt = armcpu->SPSR;
break;
case UND :
armcpu->R13_und = armcpu->R[13];
armcpu->R14_und = armcpu->R[14];
armcpu->SPSR_und = armcpu->SPSR;
break;
default :
break;
}
switch(mode)
{
case USR :
case SYS :
armcpu->R[13] = armcpu->R13_usr;
armcpu->R[14] = armcpu->R14_usr;
//SPSR = CPSR;
break;
case FIQ :
{
u32 tmp;
SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
armcpu->R[13] = armcpu->R13_fiq;
armcpu->R[14] = armcpu->R14_fiq;
armcpu->SPSR = armcpu->SPSR_fiq;
break;
}
case IRQ :
armcpu->R[13] = armcpu->R13_irq;
armcpu->R[14] = armcpu->R14_irq;
armcpu->SPSR = armcpu->SPSR_irq;
break;
case SVC :
armcpu->R[13] = armcpu->R13_svc;
armcpu->R[14] = armcpu->R14_svc;
armcpu->SPSR = armcpu->SPSR_svc;
break;
case ABT :
armcpu->R[13] = armcpu->R13_abt;
armcpu->R[14] = armcpu->R14_abt;
armcpu->SPSR = armcpu->SPSR_abt;
break;
case UND :
armcpu->R[13] = armcpu->R13_und;
armcpu->R[14] = armcpu->R14_und;
armcpu->SPSR = armcpu->SPSR_und;
break;
default :
printf("switchMode: WRONG mode %02X\n",mode);
break;
}
armcpu->CPSR.bits.mode = mode & 0x1F;
armcpu->changeCPSR();
return oldmode;
}
u32 armcpu_Wait4IRQ(armcpu_t *cpu)
{
cpu->freeze = (CPU_FREEZE_WAIT_IRQ | CPU_FREEZE_IE_IF);
return 1;
}
template<u32 PROCNUM>
FORCEINLINE static u32 armcpu_prefetch()
{
armcpu_t* const armcpu = &ARMPROC;
//#ifdef GDB_STUB
// u32 temp_instruction;
//#endif
u32 curInstruction = armcpu->next_instruction;
if(armcpu->CPSR.bits.T == 0)
{
//#ifdef GDB_STUB
// temp_instruction =
// armcpu->mem_if->prefetch32( armcpu->mem_if->data,
// armcpu->next_instruction);
//
// if ( !armcpu->stalled) {
// armcpu->instruction = temp_instruction;
// armcpu->instruct_adr = armcpu->next_instruction;
// armcpu->next_instruction += 4;
// armcpu->R[15] = armcpu->next_instruction + 4;
// }
//#else
curInstruction &= 0xFFFFFFFC; //please don't change this to 0x0FFFFFFC -- the NDS will happily run on 0xF******* addresses all day long
//please note that we must setup R[15] before reading the instruction since there is a protection
//which prevents PC > 0x3FFF from reading the bios region
armcpu->instruct_adr = curInstruction;
armcpu->next_instruction = curInstruction + 4;
armcpu->R[15] = curInstruction + 8;
armcpu->instruction = _MMU_read32<PROCNUM, MMU_AT_CODE>(curInstruction);
//#endif
return MMU_codeFetchCycles<PROCNUM,32>(curInstruction);
}
//#ifdef GDB_STUB
// temp_instruction =
// armcpu->mem_if->prefetch16( armcpu->mem_if->data,
// armcpu->next_instruction);
//
// if ( !armcpu->stalled) {
// armcpu->instruction = temp_instruction;
// armcpu->instruct_adr = armcpu->next_instruction;
// armcpu->next_instruction = armcpu->next_instruction + 2;
// armcpu->R[15] = armcpu->next_instruction + 2;
// }
//#else
curInstruction &= 0xFFFFFFFE; //please don't change this to 0x0FFFFFFE -- the NDS will happily run on 0xF******* addresses all day long
//please note that we must setup R[15] before reading the instruction since there is a protection
//which prevents PC > 0x3FFF from reading the bios region
armcpu->instruct_adr = curInstruction;
armcpu->next_instruction = curInstruction + 2;
armcpu->R[15] = curInstruction + 4;
armcpu->instruction = _MMU_read16<PROCNUM, MMU_AT_CODE>(curInstruction);
//#endif
if(PROCNUM==0)
{
// arm9 fetches 2 instructions at a time in thumb mode
if(!(curInstruction == armcpu->instruct_adr + 2 && (curInstruction & 2)))
return MMU_codeFetchCycles<PROCNUM,32>(curInstruction);
else
return 0;
}
return MMU_codeFetchCycles<PROCNUM,16>(curInstruction);
}
#if 0 /* not used */
static BOOL FASTCALL test_EQ(Status_Reg CPSR) { return ( CPSR.bits.Z); }
static BOOL FASTCALL test_NE(Status_Reg CPSR) { return (!CPSR.bits.Z); }
static BOOL FASTCALL test_CS(Status_Reg CPSR) { return ( CPSR.bits.C); }
static BOOL FASTCALL test_CC(Status_Reg CPSR) { return (!CPSR.bits.C); }
static BOOL FASTCALL test_MI(Status_Reg CPSR) { return ( CPSR.bits.N); }
static BOOL FASTCALL test_PL(Status_Reg CPSR) { return (!CPSR.bits.N); }
static BOOL FASTCALL test_VS(Status_Reg CPSR) { return ( CPSR.bits.V); }
static BOOL FASTCALL test_VC(Status_Reg CPSR) { return (!CPSR.bits.V); }
static BOOL FASTCALL test_HI(Status_Reg CPSR) { return (CPSR.bits.C) && (!CPSR.bits.Z); }
static BOOL FASTCALL test_LS(Status_Reg CPSR) { return (CPSR.bits.Z) || (!CPSR.bits.C); }
static BOOL FASTCALL test_GE(Status_Reg CPSR) { return (CPSR.bits.N==CPSR.bits.V); }
static BOOL FASTCALL test_LT(Status_Reg CPSR) { return (CPSR.bits.N!=CPSR.bits.V); }
static BOOL FASTCALL test_GT(Status_Reg CPSR) { return (!CPSR.bits.Z) && (CPSR.bits.N==CPSR.bits.V); }
static BOOL FASTCALL test_LE(Status_Reg CPSR) { return ( CPSR.bits.Z) || (CPSR.bits.N!=CPSR.bits.V); }
static BOOL FASTCALL test_AL(Status_Reg CPSR) { return 1; }
static BOOL (FASTCALL* test_conditions[])(Status_Reg CPSR)= {
test_EQ , test_NE ,
test_CS , test_CC ,
test_MI , test_PL ,
test_VS , test_VC ,
test_HI , test_LS ,
test_GE , test_LT ,
test_GT , test_LE ,
test_AL
};
#define TEST_COND2(cond, CPSR) \
(cond<15&&test_conditions[cond](CPSR))
#endif
//TODO - merge with armcpu_irqException?
//http://www.ethernut.de/en/documents/arm-exceptions.html
//http://docs.google.com/viewer?a=v&q=cache:V4ht1YkxprMJ:www.cs.nctu.edu.tw/~wjtsai/EmbeddedSystemDesign/Ch3-1.pdf+arm+exception+handling&hl=en&gl=us&pid=bl&srcid=ADGEEShx9VTHbUhWdDOrTVRzLkcCsVfJiijncNDkkgkrlJkLa7D0LCpO8fQ_hhU3DTcgZh9rcZWWQq4TYhhCovJ625h41M0ZUX3WGasyzWQFxYzDCB-VS6bsUmpoJnRxAc-bdkD0qmsu&sig=AHIEtbR9VHvDOCRmZFQDUVwy53iJDjoSPQ
void armcpu_exception(armcpu_t *cpu, u32 number)
{
Mode cpumode = USR;
switch(number)
{
case EXCEPTION_RESET: cpumode = SVC; break;
case EXCEPTION_UNDEFINED_INSTRUCTION: cpumode = UND; break;
case EXCEPTION_SWI: cpumode = SVC; break;
case EXCEPTION_PREFETCH_ABORT: cpumode = ABT; break;
case EXCEPTION_DATA_ABORT: cpumode = ABT; break;
case EXCEPTION_RESERVED_0x14: emu_halt(EMUHALT_REASON_ARM_RESERVED_0X14_EXCEPTION, (cpu->proc_ID == ARMCPU_ARM9) ? NDSErrorTag_ARM9 : NDSErrorTag_ARM7); break;
case EXCEPTION_IRQ: cpumode = IRQ; break;
case EXCEPTION_FAST_IRQ: cpumode = FIQ; break;
}
Status_Reg tmp = cpu->CPSR;
armcpu_switchMode(cpu, cpumode); //enter new mode
cpu->R[14] = cpu->next_instruction;
cpu->SPSR = tmp; //save old CPSR as new SPSR
cpu->CPSR.bits.T = 0; //handle as ARM32 code
cpu->CPSR.bits.I = 1;
cpu->changeCPSR();
cpu->R[15] = cpu->intVector + number;
cpu->next_instruction = cpu->R[15];
printf("armcpu_exception!\n");
//extern bool dolog;
//dolog=true;
//HOW DOES THIS WORTK WITHOUT A PREFETCH, LIKE IRQ BELOW?
//I REALLY WISH WE DIDNT PREFETCH BEFORE EXECUTING
}
BOOL armcpu_irqException(armcpu_t *armcpu)
{
Status_Reg tmp;
//TODO - remove GDB specific code
//#ifdef GDB_STUB
// armcpu->irq_flag = 0;
//#endif
tmp = armcpu->CPSR;
armcpu_switchMode(armcpu, IRQ);
//TODO - remove GDB specific code
//#ifdef GDB_STUB
// armcpu->R[14] = armcpu->next_instruction + 4;
//#else
armcpu->R[14] = armcpu->instruct_adr + 4;
//#endif
armcpu->SPSR = tmp;
armcpu->CPSR.bits.T = 0;
armcpu->CPSR.bits.I = 1;
armcpu->next_instruction = armcpu->intVector + 0x18;
armcpu->freeze &= ~CPU_FREEZE_IRQ_IE_IF;
//must retain invariant of having next instruction to be executed prefetched
//(yucky)
armcpu_prefetch(armcpu);
return TRUE;
}
//TODO - remove GDB specific code
//BOOL
//armcpu_flagIrq( armcpu_t *armcpu) {
// if(armcpu->CPSR.bits.I) return FALSE;
//
// armcpu->waitIRQ = 0;
//
//#ifdef GDB_STUB
// armcpu->irq_flag = 1;
//#endif
//
// return TRUE;
//}
u32 TRAPUNDEF(armcpu_t* cpu)
{
INFO("ARM%c: Undefined instruction: 0x%08X PC=0x%08X\n", cpu->proc_ID?'7':'9', cpu->instruction, cpu->instruct_adr);
if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9)))
{
armcpu_exception(&NDS_ARM9,EXCEPTION_UNDEFINED_INSTRUCTION);
return 4;
}
else
{
emu_halt(EMUHALT_REASON_ARM_UNDEFINED_INSTRUCTION_EXCEPTION, (cpu->proc_ID == ARMCPU_ARM9) ? NDSErrorTag_ARM9 : NDSErrorTag_ARM7);
return 4;
}
}
//BOOL
//armcpu_flagIrq( armcpu_t *armcpu) {
// if(armcpu->CPSR.bits.I) return FALSE;
//
// armcpu->waitIRQ = 0;
//
//#ifdef GDB_STUB
// armcpu->irq_flag = 1;
//#endif
//
// return TRUE;
//}
template<int PROCNUM>
u32 armcpu_exec()
{
// Usually, fetching and executing are processed parallelly.
// So this function stores the cycles of each process to
// the variables below, and returns appropriate cycle count.
u32 cFetch = 0;
u32 cExecute = 0;
//this assert is annoying. but sometimes it is handy.
//assert(ARMPROC.instruct_adr!=0x00000000);
//#ifdef DEVELOPER
#if 0
if ((((ARMPROC.instruct_adr & 0x0F000000) == 0x0F000000) && (PROCNUM == 0)) ||
(((ARMPROC.instruct_adr & 0x0F000000) == 0x00000000) && (PROCNUM == 1)))
{
switch (ARMPROC.instruct_adr & 0xFFFF)
{
case 0x00000000:
printf("BIOS%c: Reset!!!\n", PROCNUM?'7':'9');
emu_halt();
break;
case 0x00000004:
printf("BIOS%c: Undefined instruction\n", PROCNUM?'7':'9');
//emu_halt();
break;
case 0x00000008:
//printf("BIOS%c: SWI\n", PROCNUM?'7':'9');
break;
case 0x0000000C:
printf("BIOS%c: Prefetch Abort!!!\n", PROCNUM?'7':'9');
//emu_halt();
break;
case 0x00000010:
//printf("BIOS%c: Data Abort!!!\n", PROCNUM?'7':'9');
//emu_halt();
break;
case 0x00000014:
printf("BIOS%c: Reserved!!!\n", PROCNUM?'7':'9');
break;
case 0x00000018:
//printf("BIOS%c: IRQ\n", PROCNUM?'7':'9');
break;
case 0x0000001C:
printf("BIOS%c: Fast IRQ\n", PROCNUM?'7':'9');
break;
}
}
#endif
#if 0 //#ifdef GDB_STUB
if (ARMPROC.stalled) {
return STALLED_CYCLE_COUNT;
}
/* check for interrupts */
if (ARMPROC.irq_flag) {
armcpu_irqException(&ARMPROC);
}
cFetch = armcpu_prefetch(&ARMPROC);
if (ARMPROC.stalled) {
return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch);
}
#endif
//cFetch = armcpu_prefetch(&ARMPROC);
//printf("%d: %08X\n",PROCNUM,ARMPROC.instruct_adr);
if(ARMPROC.CPSR.bits.T == 0)
{
if(
CONDITION(ARMPROC.instruction) == 0x0E //fast path for unconditional instructions
|| (TEST_COND(CONDITION(ARMPROC.instruction), CODE(ARMPROC.instruction), ARMPROC.CPSR)) //handles any condition
)
{
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 4, ARMPROC.instruction, LUAMEMHOOK_EXEC); // should report even if condition=false?
#endif
#ifdef DEVELOPER
DEBUG_statistics.instructionHits[PROCNUM].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++;
#endif
cExecute = arm_instructions_set[PROCNUM][INSTRUCTION_INDEX(ARMPROC.instruction)](ARMPROC.instruction);
}
else
cExecute = 1; // If condition=false: 1S cycle
#ifdef GDB_STUB
if ( ARMPROC.post_ex_fn != NULL) {
/* call the external post execute function */
ARMPROC.post_ex_fn(ARMPROC.post_ex_fn_data, ARMPROC.instruct_adr, 0);
}
ARMPROC.mem_if->prefetch32( ARMPROC.mem_if->data, ARMPROC.next_instruction);
#endif
cFetch = armcpu_prefetch<PROCNUM>();
return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch);
}
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 2, ARMPROC.instruction, LUAMEMHOOK_EXEC);
#endif
#ifdef DEVELOPER
DEBUG_statistics.instructionHits[PROCNUM].thumb[ARMPROC.instruction>>6]++;
#endif
cExecute = thumb_instructions_set[PROCNUM][ARMPROC.instruction>>6](ARMPROC.instruction);
#ifdef GDB_STUB
if ( ARMPROC.post_ex_fn != NULL) {
/* call the external post execute function */
ARMPROC.post_ex_fn( ARMPROC.post_ex_fn_data, ARMPROC.instruct_adr, 1);
}
ARMPROC.mem_if->prefetch32( ARMPROC.mem_if->data, ARMPROC.next_instruction);
#endif
cFetch = armcpu_prefetch<PROCNUM>();
return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch);
}
//these templates needed to be instantiated manually
template u32 armcpu_exec<0>();
template u32 armcpu_exec<1>();
#ifdef HAVE_JIT
void arm_jit_sync()
{
NDS_ARM7.next_instruction = NDS_ARM7.instruct_adr;
NDS_ARM9.next_instruction = NDS_ARM9.instruct_adr;
armcpu_prefetch<0>();
armcpu_prefetch<1>();
}
template<int PROCNUM, bool jit>
u32 armcpu_exec()
{
if (jit)
{
ARMPROC.instruct_adr &= ARMPROC.CPSR.bits.T?0xFFFFFFFE:0xFFFFFFFC;
ArmOpCompiled f = (ArmOpCompiled)JIT_COMPILED_FUNC(ARMPROC.instruct_adr, PROCNUM);
return f ? f() : arm_jit_compile<PROCNUM>();
}
return armcpu_exec<PROCNUM>();
}
template u32 armcpu_exec<0,false>();
template u32 armcpu_exec<0,true>();
template u32 armcpu_exec<1,false>();
template u32 armcpu_exec<1,true>();
#endif
void setIF(int PROCNUM, u32 flag)
{
//don't set generated bits!!!
assert(!(flag&0x00200000));
MMU.reg_IF_bits[PROCNUM] |= flag;
NDS_Reschedule();
}
const armcpu_ctrl_iface arm_default_ctrl_iface = {
stall_cpu,
unstall_cpu,
read_cpu_reg,
set_cpu_reg,
install_post_exec_fn,
remove_post_exec_fn,
NULL
};

View File

@ -1,359 +0,0 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DESMUME_ARMCPU_H
#define DESMUME_ARMCPU_H
//half of this stuff is arm cpu internals
//half is public API
//really a mess
#include "types.h"
#include "MMU.h"
#define CONDITION(i) ((i)>>28)
#define REG_POS(i,n) (((i)>>n)&0xF)
#define CODE(i) (((i)>>25)&0x7)
#define OPCODE(i) (((i)>>21)&0xF)
#define SIGNEBIT(i) (((i)>>20)&1)
#define EXCEPTION_RESET 0x00
#define EXCEPTION_UNDEFINED_INSTRUCTION 0x04
#define EXCEPTION_SWI 0x08
#define EXCEPTION_PREFETCH_ABORT 0x0C
#define EXCEPTION_DATA_ABORT 0x10
#define EXCEPTION_RESERVED_0x14 0x14
#define EXCEPTION_IRQ 0x18
#define EXCEPTION_FAST_IRQ 0x1C
#define CPU_FREEZE_NONE 0x00
#define CPU_FREEZE_WAIT_IRQ 0x01 //waiting for some IRQ to happen, any IRQ
#define CPU_FREEZE_IE_IF 0x02 //waiting for IE&IF to signal something (probably edge triggered on IRQ too)
#define CPU_FREEZE_IRQ_IE_IF (CPU_FREEZE_WAIT_IRQ|CPU_FREEZE_IE_IF)
#define CPU_FREEZE_OVERCLOCK_HACK 0x04
#define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
inline u32 ROR(u32 i, u32 j) { return ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j)))); }
template<typename T>
inline T UNSIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)) | (((a)|(b))&(~c))); }
template<typename T>
inline T UNSIGNED_UNDERFLOW(T a,T b,T c) { return BIT31(((~a)&(b)) | (((~a)|(b))&(c))); }
template<typename T>
inline T SIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)&(~c)) | ((~a)&(~(b))&(c))); }
template<typename T>
inline T SIGNED_UNDERFLOW(T a,T b,T c) { return BIT31(((a)&(~(b))&(~c)) | ((~a)&(b)&(c))); }
#if !defined(bswap32)
#define bswap32(val) \
( (val << 24) & 0xFF000000) | \
( (val << 8) & 0x00FF0000) | \
( (val >> 8) & 0x0000FF00) | \
( (val >> 24) & 0x000000FF)
#endif
#if !defined(bswap64)
#define bswap64(x) \
( (x << 56) & 0xff00000000000000ULL ) | \
( (x << 40) & 0x00ff000000000000ULL ) | \
( (x << 24) & 0x0000ff0000000000ULL ) | \
( (x << 8) & 0x000000ff00000000ULL ) | \
( (x >> 8) & 0x00000000ff000000ULL ) | \
( (x >> 24) & 0x0000000000ff0000ULL ) | \
( (x >> 40) & 0x000000000000ff00ULL ) | \
( (x >> 56) & 0x00000000000000ffULL )
#endif
// ============================= CPRS flags funcs
inline bool CarryFrom(s32 left, s32 right)
{
u32 res = (0xFFFFFFFFU - (u32)left);
return ((u32)right > res);
}
inline bool BorrowFrom(s32 left, s32 right)
{
return ((u32)right > (u32)left);
}
inline bool OverflowFromADD(s32 alu_out, s32 left, s32 right)
{
return ((left >= 0 && right >= 0) || (left < 0 && right < 0))
&& ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
}
inline bool OverflowFromSUB(s32 alu_out, s32 left, s32 right)
{
return ((left < 0 && right >= 0) || (left >= 0 && right < 0))
&& ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
}
//zero 15-feb-2009 - these werent getting used and they were getting in my way
//#define EQ 0x0
//#define NE 0x1
//#define CS 0x2
//#define CC 0x3
//#define MI 0x4
//#define PL 0x5
//#define VS 0x6
//#define VC 0x7
//#define HI 0x8
//#define LS 0x9
//#define GE 0xA
//#define LT 0xB
//#define GT 0xC
//#define LE 0xD
//#define AL 0xE
static const u8 arm_cond_table[16*16] = {
// N=0, Z=0, C=0, V=0
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF, // 0x00
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20, // 0x00
// N=0, Z=0, C=0, V=1
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00, // 0x10
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=0, Z=0, C=1, V=0
0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF, // 0x20
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
// N=0, Z=0, C=1, V=1
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00, // 0x30
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=0, Z=1, C=0, V=0
0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF, // 0x40
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
// N=0, Z=1, C=0, V=1
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00, // 0x50
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=0, Z=1, C=1, V=0
0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF, // 0x60
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
// N=0, Z=1, C=1, V=1
0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00, // 0x70
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=1, Z=0, C=0, V=0
0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF, // 0x80
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=1, Z=0, C=0, V=1
0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00, // 0x90
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
// N=1, Z=0, C=1, V=0
0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF, // 0xA0
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=1, Z=0, C=1, V=1
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00, // 0xB0
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
// N=1, Z=1, C=0, V=0
0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF, // 0xC0
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=1, Z=1, C=0, V=1
0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00, // 0xD0
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
// N=1, Z=1, C=1, V=0
0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF, // 0xE0
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=1, Z=1, C=1, V=1
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00, // 0xF0
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20
};
#define TEST_COND(cond, inst, CPSR) ((arm_cond_table[((CPSR.val >> 24) & 0xf0)|(cond)]) & (1 << (inst)))
enum Mode
{
USR = 0x10,
FIQ = 0x11,
IRQ = 0x12,
SVC = 0x13,
ABT = 0x17,
UND = 0x1B,
SYS = 0x1F
};
typedef union
{
struct
{
#ifdef MSB_FIRST
u32 N : 1,
Z : 1,
C : 1,
V : 1,
Q : 1,
RAZ : 19,
I : 1,
F : 1,
T : 1,
mode : 5;
#else
u32 mode : 5,
T : 1,
F : 1,
I : 1,
RAZ : 19,
Q : 1,
V : 1,
C : 1,
Z : 1,
N : 1;
#endif
} bits;
u32 val;
} Status_Reg;
/**
* The control interface to a CPU
*/
struct armcpu_ctrl_iface
{
/** stall the processor */
void (*stall)( void *instance);
/** unstall the processor */
void (*unstall)( void *instance);
/** read a register value */
u32 (*read_reg)( void *instance, u32 reg_num);
/** set a register value */
void (*set_reg)( void *instance, u32 reg_num, u32 value);
/** install the post execute function */
void (*install_post_ex_fn)( void *instance,
void (*fn)( void *, u32 adr, int thumb),
void *fn_data);
/** remove the post execute function */
void (*remove_post_ex_fn)( void *instance);
/** the private data passed to all interface functions */
void *data;
};
typedef void* armcp_t;
struct armcpu_t
{
u32 proc_ID;
u32 instruction; //4
u32 instruct_adr; //8
u32 next_instruction; //12
u32 R[16]; //16
Status_Reg CPSR; //80
Status_Reg SPSR;
void SetControlInterface(const armcpu_ctrl_iface *theCtrlInterface);
armcpu_ctrl_iface* GetControlInterface();
void SetControlInterfaceData(void *theData);
void* GetControlInterfaceData();
void SetCurrentMemoryInterface(armcpu_memory_iface *theMemInterface);
armcpu_memory_iface* GetCurrentMemoryInterface();
void SetCurrentMemoryInterfaceData(void *theData);
void* GetCurrentMemoryInterfaceData();
void SetBaseMemoryInterface(const armcpu_memory_iface *theMemInterface);
armcpu_memory_iface* GetBaseMemoryInterface();
void SetBaseMemoryInterfaceData(void *theData);
void* GetBaseMemoryInterfaceData();
void ResetMemoryInterfaceToBase();
void changeCPSR();
u32 R13_usr, R14_usr;
u32 R13_svc, R14_svc;
u32 R13_abt, R14_abt;
u32 R13_und, R14_und;
u32 R13_irq, R14_irq;
u32 R8_fiq, R9_fiq, R10_fiq, R11_fiq, R12_fiq, R13_fiq, R14_fiq;
Status_Reg SPSR_svc, SPSR_abt, SPSR_und, SPSR_irq, SPSR_fiq;
u32 intVector;
u8 LDTBit; //1 : ARMv5 style 0 : non ARMv5 (earlier)
u32 freeze;
//BOOL waitIRQ;
//BOOL halt_IE_and_IF;
u8 intrWaitARM_state;
BOOL BIOS_loaded;
u32 (* *swi_tab)();
// flag indicating if the processor is stalled (for debugging)
int stalled;
#if defined(_M_X64) || defined(__x86_64__)
u8 cond_table[16*16];
#endif
/** there is a pending irq for the cpu */
int irq_flag;
/** the post executed function (if installed) */
void (*post_ex_fn)( void *, u32 adr, int thumb);
/** data for the post executed function */
void *post_ex_fn_data;
/** the memory interface */
armcpu_memory_iface *mem_if; // This is the memory interface currently in use.
armcpu_memory_iface base_mem_if; // This is the CPU's base memory interface.
/** the ctrl interface */
armcpu_ctrl_iface ctrl_iface;
};
int armcpu_new( armcpu_t *armcpu, u32 id);
void armcpu_init(armcpu_t *armcpu, u32 adr);
u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode);
BOOL armcpu_irqException(armcpu_t *armcpu);
BOOL armcpu_flagIrq( armcpu_t *armcpu);
void armcpu_exception(armcpu_t *cpu, u32 number);
u32 TRAPUNDEF(armcpu_t* cpu);
u32 armcpu_Wait4IRQ(armcpu_t *cpu);
extern armcpu_t NDS_ARM7;
extern armcpu_t NDS_ARM9;
extern const armcpu_ctrl_iface arm_default_ctrl_iface;
template<int PROCNUM> u32 armcpu_exec();
#ifdef HAVE_JIT
template<int PROCNUM, bool jit> u32 armcpu_exec();
#endif
void setIF(int PROCNUM, u32 flag);
static INLINE void NDS_makeIrq(int PROCNUM, u32 num)
{
setIF(PROCNUM,1<<num);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +0,0 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BIOS_H
#define BIOS_H
#include "types.h"
extern u32 (* ARM_swi_tab[2][32])();
extern const char* ARM_swi_names[2][32];
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,202 +0,0 @@
/*
Copyright (C) 2009-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <vector>
#include "types.h"
#define CHEAT_VERSION_MAJOR 2
#define CHEAT_VERSION_MINOR 0
#define MAX_CHEAT_LIST 100
#define MAX_XX_CODE 1024
#define CHEAT_FILE_MIN_FGETS_BUFFER 32768
#define CHEAT_DB_GAME_TITLE_SIZE 256
#define CHEAT_TYPE_EMPTY 0xFF
#define CHEAT_TYPE_INTERNAL 0
#define CHEAT_TYPE_AR 1
#define CHEAT_TYPE_CODEBREAKER 2
struct CHEATS_LIST
{
CHEATS_LIST()
{
memset(this,0,sizeof(*this));
type = 0xFF;
}
u8 type;
BOOL enabled;
// TODO
u8 freezeType; // 0 - normal freeze
// 1 - can decrease
// 2 - can increase
u32 code[MAX_XX_CODE][2];
char description[1024];
int num;
u8 size;
};
class CHEATS
{
private:
std::vector<CHEATS_LIST> list;
u8 filename[MAX_PATH];
u32 currentGet;
void clear();
void ARparser(CHEATS_LIST& cheat);
char *clearCode(char *s);
public:
CHEATS()
: currentGet(0)
{
memset(filename, 0, sizeof(filename));
}
~CHEATS() {}
void init(char *path);
BOOL add(u8 size, u32 address, u32 val, char *description, BOOL enabled);
BOOL update(u8 size, u32 address, u32 val, char *description, BOOL enabled, u32 pos);
BOOL move(u32 srcPos, u32 dstPos);
BOOL add_AR(char *code, char *description, BOOL enabled);
BOOL update_AR(char *code, char *description, BOOL enabled, u32 pos);
BOOL add_AR_Direct(CHEATS_LIST cheat);
BOOL add_CB(char *code, char *description, BOOL enabled);
BOOL update_CB(char *code, char *description, BOOL enabled, u32 pos);
BOOL remove(u32 pos);
void getListReset();
BOOL getList(CHEATS_LIST *cheat);
CHEATS_LIST* getListPtr();
BOOL get(CHEATS_LIST *cheat, u32 pos);
CHEATS_LIST* getItemByIndex(const u32 pos);
u32 getSize();
size_t getActiveCount();
void setDescription(const char *description, u32 pos);
BOOL save();
BOOL load();
void process(int targetType);
void getXXcodeString(CHEATS_LIST cheat, char *res_buf);
static BOOL XXCodeFromString(CHEATS_LIST *cheatItem, const std::string codeString);
static BOOL XXCodeFromString(CHEATS_LIST *cheatItem, const char *codeString);
};
class CHEATSEARCH
{
private:
u8 *statMem;
u8 *mem;
u32 amount;
u32 lastRecord;
u32 _type;
u32 _size;
u32 _sign;
public:
CHEATSEARCH()
: statMem(0), mem(0), amount(0), lastRecord(0), _type(0), _size(0), _sign(0)
{}
~CHEATSEARCH() { close(); }
BOOL start(u8 type, u8 size, u8 sign);
BOOL close();
u32 search(u32 val);
u32 search(u8 comp);
u32 getAmount();
BOOL getList(u32 *address, u32 *curVal);
void getListReset();
};
enum CHEATS_DB_TYPE
{
CHEATS_DB_R4 = 0
};
#pragma pack(push)
#pragma pack(1)
typedef struct FAT_R4
{
u8 serial[4];
u32 CRC;
u64 addr;
} FAT_R4;
#pragma pack(pop)
class CHEATSEXPORT
{
private:
CHEATS_DB_TYPE type;
bool encrypted;
FILE *fp;
u32 fsize;
u32 dataSize;
u32 encOffset;
FAT_R4 fat;
bool search();
bool getCodes();
void R4decrypt(u8 *buf, u32 len, u32 n);
u32 numCheats;
CHEATS_LIST *cheats;
u8 error; // 0 - no errors
// 1 - open failed/file not found
// 2 - file format is wrong (no valid header ID)
// 3 - cheat not found in database
// 4 - export error from database
public:
CHEATSEXPORT() :
fp(NULL),
fsize(0),
dataSize(0),
encOffset(0),
type(CHEATS_DB_R4),
encrypted(false),
numCheats(0),
cheats(0),
CRC(0),
error(0)
{
memset(date, 0, sizeof(date));
gametitle = (u8 *)malloc(CHEAT_DB_GAME_TITLE_SIZE);
memset(gametitle, 0, CHEAT_DB_GAME_TITLE_SIZE);
}
~CHEATSEXPORT()
{
free(gametitle);
gametitle = NULL;
}
u8 *gametitle;
u8 date[17];
u32 CRC;
bool load(char *path);
void close();
CHEATS_LIST *getCheats();
u32 getCheatsNum();
u8 getErrorCode() { return error; }
};
extern CHEATS *cheats;
extern CHEATSEARCH *cheatSearch;

View File

@ -1,618 +0,0 @@
/*
Copyright (C) 2009-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
//windows note: make sure this file gets compiled with _cdecl
#include <algorithm>
#include <stdio.h>
#include "commandline.h"
#include "types.h"
#include "movie.h"
#include "rtc.h"
#include "slot1.h"
#include "slot2.h"
#include "NDSSystem.h"
#include "utils/datetime.h"
#include "utils/xstring.h"
#include <compat/getopt.h>
//#include "frontend/modules/mGetOpt.h" //to test with this, make sure global `optind` is initialized to 1
#define printerror(...) fprintf(stderr, __VA_ARGS__)
int _scanline_filter_a = 0, _scanline_filter_b = 2, _scanline_filter_c = 2, _scanline_filter_d = 4;
int _commandline_linux_nojoy = 0;
CommandLine::CommandLine()
: is_cflash_configured(false)
, _load_to_memory(-1)
, _play_movie_file(0)
, _record_movie_file(0)
, _cflash_image(0)
, _cflash_path(0)
, _gbaslot_rom(0)
, _bios_arm9(NULL)
, _bios_arm7(NULL)
, _bios_swi(0)
, _fw_path(NULL)
, _fw_boot(0)
, _spu_sync_mode(-1)
, _spu_sync_method(-1)
, _spu_advanced(0)
, _num_cores(-1)
, _rigorous_timing(0)
, _advanced_timing(-1)
, _gamehacks(-1)
, _texture_deposterize(-1)
, _texture_smooth(-1)
, _slot1(NULL)
, _slot1_fat_dir(NULL)
, _slot1_fat_dir_type(false)
, _slot1_no8000prot(0)
#ifdef HAVE_JIT
, _cpu_mode(-1)
, _jit_size(-1)
#endif
, _console_type(NULL)
, _advanscene_import(NULL)
, load_slot(-1)
, arm9_gdb_port(0)
, arm7_gdb_port(0)
, start_paused(FALSE)
, autodetect_method(-1)
, render3d(COMMANDLINE_RENDER3D_DEFAULT)
, texture_upscale(-1)
, gpu_resolution_multiplier(-1)
, language(1) //english by default
, disable_sound(0)
, disable_limiter(0)
, windowed_fullscreen(0)
, _rtc_day(-1)
, _rtc_hour(-1)
{
}
CommandLine::~CommandLine()
{
}
static char mytoupper(char c) { return ::toupper(c); }
static std::string strtoupper(const std::string& str)
{
std::string ret = str;
std::transform(ret.begin(), ret.end(), ret.begin(), ::mytoupper);
return ret;
}
#define ENDL "\n"
static const char* help_string = \
"Arguments affecting overall emulator behaviour: (`user settings`):" ENDL
" --num-cores N Override numcores detection and use this many" ENDL
" --spu-synch Use SPU synch (crackles; helps streams; default ON)" ENDL
" --spu-method N Select SPU synch method: 0:N, 1:Z, 2:P; default 0" ENDL
" --3d-render [SW|AUTOGL|GL|OLDGL]" ENDL
" Select 3d renderer; default SW" ENDL
" --3d-texture-deposterize-enable" ENDL
" Enables texture deposterization." ENDL
" --3d-texture-upscale [1|2|4]" ENDL
" Automatically upscales textures by the specified" ENDL
" amount; 1:No scaling (default), 2:2x upscaling," ENDL
" 4:4x upscaling" ENDL
" --3d-texture-smoothing-enable" ENDL
" Enables smooth texture sampling while rendering." ENDL
#ifdef HOST_WINDOWS
" --gpu-resolution-multiplier N" ENDL
" Increases the resolution of GPU rendering by this" ENDL
" multipler; 1:256x192 (default), 2:512x384," ENDL
" 3:768x576, 4:1024x768, 5:1280x960" ENDL
" --windowed-fullscreen" ENDL
" Launches in windowed fullscreen (same as alt+enter)" ENDL
#else
" --nojoy Disables joystick support" ENDL
#endif
" --disable-sound Disables the sound output" ENDL
" --disable-limiter Disables the 60fps limiter" ENDL
" --rtc-day D Override RTC day, 0=Sunday, 6=Saturday" ENDL
" --rtc-hour H Override RTC hour, 0=midnight, 23=an hour before" ENDL
ENDL
"Arguments affecting overall emulation parameters (`sync settings`): " ENDL
#ifdef HAVE_JIT
" --jit-enable Formerly --cpu-mode; default OFF" ENDL
" --jit-size N JIT block size 1-100; 1:accurate 100:fast (default)" ENDL
#endif
" --advanced-timing Use advanced bus-level timing; default ON" ENDL
" --rigorous-timing Use more realistic component timings; default OFF" ENDL
" --gamehacks Use game-specific hacks; default ON" ENDL
" --spu-advanced Enable advanced SPU capture functions (reverb)" ENDL
" --backupmem-db Use DB for autodetecting backup memory type" ENDL
ENDL
"Arguments affecting the emulated requipment:" ENDL
" --console-type [FAT|LITE|IQUE|DEBUG|DSI]" ENDL
" Select basic console type; default FAT" ENDL
" --bios-arm9 BIN_FILE Uses the ARM9 BIOS provided at the specified path" ENDL
" --bios-arm7 BIN_FILE Uses the ARM7 BIOS provided at the specified path" ENDL
" --firmware-path BIN_FILE Uses the firmware provided at the specified path" ENDL
" --firmware-boot 0|1 Boot from firmware" ENDL
" --bios-swi Uses SWI from the provided bios files (else HLE)" ENDL
" --lang N Firmware language (can affect game translations)" ENDL
" 0 = Japanese, 1 = English (default), 2 = French" ENDL
" 3 = German, 4 = Italian, 5 = Spanish" ENDL
ENDL
"Arguments affecting contents of SLOT-1:" ENDL
" --slot1 [RETAIL|RETAILAUTO|R4|RETAILNAND|RETAILMCDROM|RETAILDEBUG]" ENDL
" Device type to be used SLOT-1; default RETAILAUTO" ENDL
" --preload-rom precache ROM to RAM instead of streaming from disk" ENDL
" --slot1-fat-dir DIR Directory to mount for SLOT-1 flash cards" ENDL
" --slot1_no8000prot Disables retail card copy protection <8000 feature" ENDL
ENDL
"Arguments affecting contents of SLOT-2:" ENDL
" --cflash-image IMG_FILE Mounts cflash in SLOT-2 with specified image file" ENDL
" --cflash-path DIR Mounts cflash in SLOT-2 with FS rooted at DIR" ENDL
" --gbaslot-rom GBA_FILE Mounts GBA specified rom in SLOT-2" ENDL
ENDL
"Commands taking place after ROM is loaded: (be sure to specify a ROM!)" ENDL
" --start-paused emulation should start paused" ENDL
" --load-slot N loads savestate from slot N (0-9)" ENDL
" --play-movie DSM_FILE automatically plays movie" ENDL
" --record-movie DSM_FILE begin recording a movie" ENDL
ENDL
"Arguments affecting video filters:" ENDL
" --scanline-filter-a N Fadeout intensity (N/16) (topleft) (default 0)" ENDL
" --scanline-filter-b N Fadeout intensity (N/16) (topright) (default 2)" ENDL
" --scanline-filter-c N Fadeout intensity (N/16) (bottomleft) (default 2)" ENDL
" --scanline-filter-d N Fadeout intensity (N/16) (bottomright) (default 4)" ENDL
ENDL
#ifdef GDB_STUB
"Arguments affecting debugging features:" ENDL
" --arm9gdb PORTNUM Enable the ARM9 GDB stub on the given port" ENDL
" --arm7gdb PORTNUM Enable the ARM7 GDB stub on the given port" ENDL
ENDL
#endif
"Utility commands which occur in place of emulation:" ENDL
" --advanscene-import PATH Import advanscene, dump .ddb, and exit" ENDL
ENDL
"These arguments may be reorganized/renamed in the future." ENDL ENDL
;
//https://github.com/mono/mono/blob/b7a308f660de8174b64697a422abfc7315d07b8c/eglib/test/driver.c
#define OPT_NUMCORES 1
#define OPT_SPU_METHOD 2
#define OPT_3D_RENDER 3
#define OPT_3D_TEXTURE_UPSCALE 81
#define OPT_GPU_RESOLUTION_MULTIPLIER 82
#define OPT_JIT_SIZE 100
#define OPT_CONSOLE_TYPE 200
#define OPT_ARM9 201
#define OPT_ARM7 202
#define OPT_LANGUAGE 203
#define OPT_FIRMPATH 204
#define OPT_FIRMBOOT 205
#define OPT_SLOT1 300
#define OPT_SLOT1_FAT_DIR 301
#define OPT_LOAD_SLOT 400
#define OPT_PLAY_MOVIE 410
#define OPT_RECORD_MOVIE 411
#define OPT_SLOT2_CFLASH_IMAGE 500
#define OPT_SLOT2_CFLASH_DIR 501
#define OPT_SLOT2_GBAGAME 502
#define OPT_SCANLINES_A 600
#define OPT_SCANLINES_B 601
#define OPT_SCANLINES_C 602
#define OPT_SCANLINES_D 603
#define OPT_ARM9GDB 700
#define OPT_ARM7GDB 701
#define OPT_RTC_DAY 800
#define OPT_RTC_HOUR 801
#define OPT_ADVANSCENE 900
bool CommandLine::parse(int argc,char **argv)
{
std::string _render3d;
int opt_help = 0;
int option_index = 0;
for(;;)
{
//libretro-common's optional argument is not supported presently
static struct option long_options[] =
{
//stuff
{ "help", no_argument, &opt_help, 1 },
//user settings
{ "num-cores", required_argument, NULL, OPT_NUMCORES },
{ "spu-synch", no_argument, &_spu_sync_mode, 1 },
{ "spu-method", required_argument, NULL, OPT_SPU_METHOD },
{ "3d-render", required_argument, NULL, OPT_3D_RENDER },
{ "3d-texture-deposterize-enable", no_argument, &_texture_deposterize, 1 },
{ "3d-texture-upscale", required_argument, NULL, OPT_3D_TEXTURE_UPSCALE },
{ "3d-texture-smoothing-enable", no_argument, &_texture_smooth, 1 },
#ifdef HOST_WINDOWS
{ "gpu-resolution-multiplier", required_argument, NULL, OPT_GPU_RESOLUTION_MULTIPLIER },
{ "windowed-fullscreen", no_argument, &windowed_fullscreen, 1 },
#else
{ "nojoy", no_argument, &_commandline_linux_nojoy, 1},
#endif
{ "disable-sound", no_argument, &disable_sound, 1},
{ "disable-limiter", no_argument, &disable_limiter, 1},
{ "rtc-day", required_argument, NULL, OPT_RTC_DAY},
{ "rtc-hour", required_argument, NULL, OPT_RTC_HOUR},
//sync settings
#ifdef HAVE_JIT
{ "jit-enable", no_argument, &_cpu_mode, 1},
{ "jit-size", required_argument, NULL, OPT_JIT_SIZE },
#endif
{ "rigorous-timing", no_argument, &_rigorous_timing, 1},
{ "advanced-timing", no_argument, &_advanced_timing, 1},
{ "gamehacks", no_argument, &_gamehacks, 1},
{ "spu-advanced", no_argument, &_spu_advanced, 1},
{ "backupmem-db", no_argument, &autodetect_method, 1},
//system equipment
{ "console-type", required_argument, NULL, OPT_CONSOLE_TYPE },
{ "bios-arm9", required_argument, NULL, OPT_ARM9},
{ "bios-arm7", required_argument, NULL, OPT_ARM7},
{ "bios-swi", no_argument, &_bios_swi, 1},
{ "firmware-path", required_argument, NULL, OPT_FIRMPATH},
{ "firmware-boot", required_argument, NULL, OPT_FIRMBOOT},
{ "lang", required_argument, NULL, OPT_LANGUAGE},
//slot-1 contents
{ "slot1", required_argument, NULL, OPT_SLOT1},
{ "preload-rom", no_argument, &_load_to_memory, 1},
{ "slot1-fat-dir", required_argument, NULL, OPT_SLOT1_FAT_DIR},
//and other slot-1 option
{ "slot1-no8000prot", no_argument, &_slot1_no8000prot, 1},
//slot-2 contents
{ "cflash-image", required_argument, NULL, OPT_SLOT2_CFLASH_IMAGE},
{ "cflash-path", required_argument, NULL, OPT_SLOT2_CFLASH_DIR},
{ "gbaslot-rom", required_argument, NULL, OPT_SLOT2_GBAGAME},
//commands
{ "start-paused", no_argument, &start_paused, 1},
{ "load-slot", required_argument, NULL, OPT_LOAD_SLOT},
{ "play-movie", required_argument, NULL, OPT_PLAY_MOVIE},
{ "record-movie", required_argument, NULL, OPT_RECORD_MOVIE},
//video filters
{ "scanline-filter-a", required_argument, NULL, OPT_SCANLINES_A},
{ "scanline-filter-b", required_argument, NULL, OPT_SCANLINES_B},
{ "scanline-filter-c", required_argument, NULL, OPT_SCANLINES_C},
{ "scanline-filter-d", required_argument, NULL, OPT_SCANLINES_D},
//debugging
#ifdef GDB_STUB
{ "arm9gdb", required_argument, NULL, OPT_ARM9GDB},
{ "arm7gdb", required_argument, NULL, OPT_ARM7GDB},
#endif
//utilities
{ "advanscene-import", required_argument, NULL, OPT_ADVANSCENE},
{0,0,0,0}
};
int c = getopt_long(argc,argv,"",long_options,&option_index);
if(c == -1) break;
if(c == '?')
break;
switch(c)
{
case 0: break;
//user settings
case OPT_NUMCORES: _num_cores = atoi(optarg); break;
case OPT_SPU_METHOD: _spu_sync_method = atoi(optarg); break;
case OPT_3D_RENDER: _render3d = optarg; break;
case OPT_3D_TEXTURE_UPSCALE: texture_upscale = atoi(optarg); break;
case OPT_GPU_RESOLUTION_MULTIPLIER: gpu_resolution_multiplier = atoi(optarg); break;
//RTC settings
case OPT_RTC_DAY: _rtc_day = atoi(optarg); break;
case OPT_RTC_HOUR: _rtc_hour = atoi(optarg); break;
//sync settings
#ifdef HAVE_JIT
case OPT_JIT_SIZE: _jit_size = atoi(optarg); break;
#endif
//system equipment
case OPT_CONSOLE_TYPE: console_type = optarg; break;
case OPT_ARM9: _bios_arm9 = strdup(optarg); break;
case OPT_ARM7: _bios_arm7 = strdup(optarg); break;
case OPT_FIRMPATH: _fw_path = strdup(optarg); break;
case OPT_FIRMBOOT: _fw_boot = atoi(optarg); break;
//slot-1 contents
case OPT_SLOT1: slot1 = strtoupper(optarg); break;
case OPT_SLOT1_FAT_DIR: slot1_fat_dir = optarg; break;
//slot-2 contents
case OPT_SLOT2_CFLASH_IMAGE: cflash_image = optarg; break;
case OPT_SLOT2_CFLASH_DIR: _cflash_path = optarg; break;
case OPT_SLOT2_GBAGAME: _gbaslot_rom = optarg; break;
//commands
case OPT_LOAD_SLOT: load_slot = atoi(optarg); break;
case OPT_PLAY_MOVIE: play_movie_file = optarg; break;
case OPT_RECORD_MOVIE: record_movie_file = optarg; break;
//video filters
case OPT_SCANLINES_A: _scanline_filter_a = atoi(optarg); break;
case OPT_SCANLINES_B: _scanline_filter_b = atoi(optarg); break;
case OPT_SCANLINES_C: _scanline_filter_c = atoi(optarg); break;
case OPT_SCANLINES_D: _scanline_filter_d = atoi(optarg); break;
//debugging
case OPT_ARM9GDB: arm9_gdb_port = atoi(optarg); break;
case OPT_ARM7GDB: arm7_gdb_port = atoi(optarg); break;
//utilities
case OPT_ADVANSCENE: CommonSettings.run_advanscene_import = optarg; break;
case OPT_LANGUAGE: language = atoi(optarg); break;
}
} //arg parsing loop
if(opt_help)
{
printf(help_string);
exit(1);
}
if(_load_to_memory != -1) CommonSettings.loadToMemory = (_load_to_memory == 1)?true:false;
if(_num_cores != -1) CommonSettings.num_cores = _num_cores;
if(_rigorous_timing) CommonSettings.rigorous_timing = true;
if(_advanced_timing != -1) CommonSettings.advanced_timing = _advanced_timing==1;
if(_gamehacks != -1) CommonSettings.gamehacks.en = _gamehacks==1;
#ifdef HAVE_JIT
if(_cpu_mode != -1) CommonSettings.use_jit = (_cpu_mode==1);
if(_jit_size != -1)
{
if ((_jit_size < 1) || (_jit_size > 100))
CommonSettings.jit_max_block_size = 100;
else
CommonSettings.jit_max_block_size = _jit_size;
}
#endif
//process console type
CommonSettings.DebugConsole = false;
CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT;
console_type = strtoupper(console_type);
if(console_type == "") {}
else if(console_type == "FAT") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT;
else if(console_type == "LITE") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_LITE;
else if(console_type == "IQUE") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_IQUE;
else if(console_type == "DSI") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_DSI;
else if(console_type == "DEBUG")
{
CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT;
CommonSettings.DebugConsole = true;
}
//process 3d renderer
_render3d = strtoupper(_render3d);
if(_render3d == "NONE") render3d = COMMANDLINE_RENDER3D_NONE;
else if(_render3d == "SW") render3d = COMMANDLINE_RENDER3D_SW;
else if(_render3d == "OLDGL") render3d = COMMANDLINE_RENDER3D_OLDGL;
else if(_render3d == "AUTOGL") render3d = COMMANDLINE_RENDER3D_AUTOGL;
else if(_render3d == "GL") render3d = COMMANDLINE_RENDER3D_GL;
if (_texture_deposterize != -1) CommonSettings.GFX3D_Renderer_TextureDeposterize = (_texture_deposterize == 1);
if (_texture_smooth != -1) CommonSettings.GFX3D_Renderer_TextureSmoothing = (_texture_smooth == 1);
if (autodetect_method != -1)
CommonSettings.autodetectBackupMethod = autodetect_method;
//TODO NOT MAX PRIORITY! change ARM9BIOS etc to be a std::string
if(_bios_arm9) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM9BIOS,_bios_arm9); }
if(_bios_arm7) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM7BIOS,_bios_arm7); }
#ifndef HOST_WINDOWS
if(_fw_path) { CommonSettings.UseExtFirmware = true; CommonSettings.UseExtFirmwareSettings = true; strcpy(CommonSettings.ExtFirmwarePath,_fw_path); }
#endif
if(_fw_boot) CommonSettings.BootFromFirmware = true;
if(_bios_swi) CommonSettings.SWIFromBIOS = true;
if(_slot1_no8000prot) CommonSettings.RetailCardProtection8000 = false;
if(_spu_sync_mode != -1) CommonSettings.SPU_sync_mode = _spu_sync_mode;
if(_spu_sync_method != -1) CommonSettings.SPU_sync_method = _spu_sync_method;
if(_spu_advanced) CommonSettings.spu_advanced = true;
free(_bios_arm9);
free(_bios_arm7);
_bios_arm9 = _bios_arm7 = NULL;
//remaining argument should be an NDS file, and nothing more
int remain = argc-optind;
if(remain==1)
nds_file = argv[optind];
else if(remain>1) return false;
return true;
}
bool CommandLine::validate()
{
if(slot1 != "")
{
if(slot1 != "R4" && slot1 != "RETAIL" && slot1 != "NONE" && slot1 != "RETAILNAND") {
printerror("Invalid slot1 device specified.\n");
return false;
}
}
if (_load_to_memory < -1 || _load_to_memory > 1) {
printerror("Invalid parameter (0 - stream from disk, 1 - from RAM)\n");
return false;
}
if (_spu_sync_mode < -1 || _spu_sync_mode > 1) {
printerror("Invalid parameter\n");
return false;
}
if (_spu_sync_method < -1 || _spu_sync_method > 2) {
printerror("Invalid parameter\n");
return false;
}
if (load_slot < -1 || load_slot > 10) {
printerror("I only know how to load from slots 0-10; -1 means 'do not load savegame' and is default\n");
return false;
}
if(play_movie_file != "" && record_movie_file != "") {
printerror("Cannot both play and record a movie.\n");
return false;
}
if(record_movie_file != "" && load_slot != -1) {
printerror("Cannot both record a movie and load a savestate.\n");
return false;
}
if(cflash_path != "" && cflash_image != "") {
printerror("Cannot specify both cflash-image and cflash-path.\n");
return false;
}
if((_bios_arm9 && !_bios_arm7) || (_bios_arm7 && !_bios_arm9)) {
printerror("If either bios-arm7 or bios-arm9 are specified, both must be.\n");
return false;
}
if(_bios_swi && (!_bios_arm7 || !_bios_arm9)) {
printerror("If either bios-swi is used, bios-arm9 and bios-arm7 must be specified.\n");
}
if(_fw_boot && (!_fw_path)) {
printerror("If either firmware boot is used, firmware path must be specified.\n");
}
if((_cflash_image && _gbaslot_rom) || (_cflash_path && _gbaslot_rom)) {
printerror("Cannot specify both cflash and gbaslot rom (both occupy SLOT-2)\n");
}
if (autodetect_method < -1 || autodetect_method > 1) {
printerror("Invalid autodetect save method (0 - internal, 1 - from database)\n");
}
if ( (texture_upscale != -1) && (texture_upscale != 1) && (texture_upscale != 2) && (texture_upscale != 4) ) {
printerror("Invalid texture upscaling value [1|2|4]. Ignoring command line setting.\n");
texture_upscale = -1;
}
if ( (gpu_resolution_multiplier != -1) && ((gpu_resolution_multiplier < 1) || (gpu_resolution_multiplier > 5)) ) {
printerror("Invalid GPU resolution multiplier [1..5]. Ignoring command line setting.\n");
gpu_resolution_multiplier = -1;
}
#ifdef HAVE_JIT
if (_cpu_mode < -1 || _cpu_mode > 1) {
printerror("Invalid cpu mode emulation (0 - interpreter, 1 - dynarec)\n");
}
if (_jit_size < -1 && (_jit_size == 0 || _jit_size > 100)) {
printerror("Invalid jit block size [1..100]. set to 100\n");
}
#endif
if (_rtc_day < -1 || _rtc_day > 6) {
printerror("Invalid rtc day override, valid values are from 0 to 6");
return false;
}
if (_rtc_hour < -1 || _rtc_hour > 23) {
printerror("Invalid rtc day override, valid values are from 0 to 23");
return false;
}
return true;
}
void CommandLine::errorHelp(const char* binName)
{
printerror(help_string);
}
void CommandLine::process_movieCommands()
{
if(play_movie_file != "")
{
FCEUI_LoadMovie(play_movie_file.c_str(),true,false,-1);
}
else if(record_movie_file != "")
{
FCEUI_SaveMovie(record_movie_file.c_str(), L"", START_BLANK, NULL, FCEUI_MovieGetRTCDefault());
}
}
void CommandLine::process_addonCommands()
{
if (cflash_image != "")
{
CFlash_Mode = ADDON_CFLASH_MODE_File;
CFlash_Path = cflash_image;
is_cflash_configured = true;
}
if (cflash_path != "")
{
CFlash_Mode = ADDON_CFLASH_MODE_Path;
CFlash_Path = cflash_path;
is_cflash_configured = true;
}
if(slot1_fat_dir != "")
slot1_SetFatDir(slot1_fat_dir);
if(slot1 == "RETAIL")
slot1_Change(NDS_SLOT1_RETAIL_AUTO);
else if(slot1 == "RETAILAUTO")
slot1_Change(NDS_SLOT1_RETAIL_AUTO);
else if(slot1 == "R4")
slot1_Change(NDS_SLOT1_R4);
else if(slot1 == "RETAILNAND")
slot1_Change(NDS_SLOT1_RETAIL_NAND);
else if(slot1 == "RETAILMCROM")
slot1_Change(NDS_SLOT1_RETAIL_MCROM);
else if(slot1 == "RETAILDEBUG")
slot1_Change(NDS_SLOT1_RETAIL_DEBUG);
if (_rtc_day != -1 || _rtc_hour != -1) {
DateTime now = DateTime::get_Now();
int cur_day = now.get_DayOfWeek();
int cur_hour = now.get_Hour();
int cur_total = cur_day * 24 + cur_hour;
int day = (_rtc_day != -1 ? _rtc_day : cur_day);
int hour = (_rtc_hour != -1 ? _rtc_hour : cur_hour);
int total = day * 24 + hour;
int diff = total - cur_total;
if (diff < 0)
diff += 24 * 7;
rtcHourOverride = diff;
}
}

View File

@ -1,118 +0,0 @@
/*
Copyright (C) 2009-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _COMMANDLINE_H_
#define _COMMANDLINE_H_
#include <string>
#include "types.h"
//hacky commandline options that i didnt want to route through commonoptions
extern int _commandline_linux_nojoy;
#define COMMANDLINE_RENDER3D_DEFAULT 0
#define COMMANDLINE_RENDER3D_NONE 1
#define COMMANDLINE_RENDER3D_SW 2
#define COMMANDLINE_RENDER3D_OLDGL 3
#define COMMANDLINE_RENDER3D_GL 4
#define COMMANDLINE_RENDER3D_AUTOGL 5
//this class will also eventually try to take over the responsibility of using the args that it handles
//for example: preparing the emulator run by loading the rom, savestate, and/or movie in the correct pattern.
//it should also populate CommonSettings with its initial values
//EDIT: not really. combining this with what a frontend wants to do is complicated.
//you might design the API so that the frontend sets all those up, but I'm not sure I like that
//Really, this should be a passive structure that just collects the results provided by the shared command line processing, to be used later as appropriate
//(and the CommonSettings setup REMOVED or at least refactored into a separate method)
class CommandLine
{
public:
//actual options: these may move to another struct
int load_slot;
int autodetect_method;
int render3d;
int texture_upscale;
int gpu_resolution_multiplier;
int language;
std::string nds_file;
std::string play_movie_file;
std::string record_movie_file;
int arm9_gdb_port, arm7_gdb_port;
int start_paused;
std::string cflash_image;
std::string cflash_path;
std::string gbaslot_rom;
std::string slot1;
std::string console_type;
std::string slot1_fat_dir;
bool _slot1_fat_dir_type;
int _slot1_no8000prot;
int disable_sound;
int disable_limiter;
int windowed_fullscreen;
bool parse(int argc,char **argv);
//validate the common commandline options
bool validate();
//process movie play/record commands
void process_movieCommands();
//etc.
void process_addonCommands();
bool is_cflash_configured;
//print a little help message for cases when erroneous commandlines are entered
void errorHelp(const char* binName);
CommandLine();
~CommandLine();
int _spu_sync_mode;
int _spu_sync_method;
private:
char* _play_movie_file;
char* _record_movie_file;
char* _cflash_image;
char* _cflash_path;
char* _gbaslot_rom;
char* _bios_arm9, *_bios_arm7;
char* _fw_path;
int _fw_boot;
int _load_to_memory;
int _bios_swi;
int _spu_advanced;
int _num_cores;
int _rigorous_timing;
int _advanced_timing;
int _gamehacks;
int _texture_deposterize;
int _texture_smooth;
#ifdef HAVE_JIT
int _cpu_mode;
int _jit_size;
#endif
char* _slot1;
char *_slot1_fat_dir;
char* _console_type;
char* _advanscene_import;
int _rtc_day;
int _rtc_hour;
};
#endif

View File

@ -1,144 +0,0 @@
/*
Copyright (C) 2008-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
//TODO - move this into ndssystem where it belongs probably
#include "common.h"
#ifndef _MSC_VER
#include <stdint.h>
#endif
#include <string.h>
#include <string>
#include <stdarg.h>
#include <zlib.h>
#include <stdlib.h>
#include <map>
static std::map<void *, void *> _alignedPtrList; // Key: Aligned pointer / Value: Original pointer
// ===============================================================================
// Message dialogs
// ===============================================================================
#define MSG_PRINT { \
va_list args; \
va_start (args, fmt); \
vprintf (fmt, args); \
va_end (args); \
}
void msgFakeInfo(const char *fmt, ...)
{
MSG_PRINT;
}
bool msgFakeConfirm(const char *fmt, ...)
{
MSG_PRINT;
return true;
}
void msgFakeError(const char *fmt, ...)
{
MSG_PRINT;
}
void msgFakeWarn(const char *fmt, ...)
{
MSG_PRINT;
}
msgBoxInterface msgBoxFake = {
msgFakeInfo,
msgFakeConfirm,
msgFakeError,
msgFakeWarn,
};
msgBoxInterface *msgbox = &msgBoxFake;
void* malloc_aligned(size_t length, size_t alignment)
{
const uintptr_t ptrOffset = alignment; // This value must be a power of 2, or this function will fail.
const uintptr_t ptrOffsetMask = ~(ptrOffset - 1);
void *originalPtr = malloc(length + ptrOffset);
if (originalPtr == NULL)
{
return originalPtr;
}
void *alignedPtr = (void *)(((uintptr_t)originalPtr + ptrOffset) & ptrOffsetMask);
_alignedPtrList[alignedPtr] = originalPtr;
return alignedPtr;
}
void* malloc_aligned16(size_t length)
{
return malloc_aligned(length, 16);
}
void* malloc_aligned32(size_t length)
{
return malloc_aligned(length, 32);
}
void* malloc_aligned64(size_t length)
{
return malloc_aligned(length, 64);
}
void* malloc_alignedCacheLine(size_t length)
{
#if defined(HOST_32)
return malloc_aligned32(length);
#elif defined(HOST_64)
return malloc_aligned64(length);
#else
return malloc_aligned16(length);
#endif
}
void* malloc_alignedPage(size_t length)
{
// WARNING!
//
// This may fail for SPARC users, which have a page size
// of 8KB instead of the more typical 4KB.
return malloc_aligned(length, 4096);
}
void free_aligned(void *ptr)
{
if (ptr == NULL)
{
return;
}
// If the input pointer is aligned through malloc_aligned(),
// then retrieve the original pointer first. Otherwise, this
// function behaves like the usual free().
void *originalPtr = ptr;
if (_alignedPtrList.find(ptr) != _alignedPtrList.end())
{
originalPtr = _alignedPtrList[ptr];
_alignedPtrList.erase(ptr);
}
free(originalPtr);
}

View File

@ -1,55 +0,0 @@
/*
Copyright (C) 2008-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
//TODO - dismantle this file
#ifndef _COMMON_H_
#define _COMMON_H_
#include <stdio.h>
#include <string.h>
#include <string>
#include "types.h"
// ===============================================================================
// Message dialogs
// ===============================================================================
#define CALL_CONVENTION
typedef struct
{
void (CALL_CONVENTION* info) (const char *fmt, ...);
bool (CALL_CONVENTION* confirm)(const char *fmt, ...);
void (CALL_CONVENTION* error) (const char *fmt, ...);
void (CALL_CONVENTION* warn) (const char *fmt, ...);
} msgBoxInterface;
extern msgBoxInterface *msgbox;
// ===============================================================================
// Maker codes
// ===============================================================================
//
void* malloc_aligned(size_t length, size_t alignment);
void* malloc_aligned16(size_t length);
void* malloc_aligned32(size_t length);
void* malloc_aligned64(size_t length);
void* malloc_alignedCacheLine(size_t length);
void* malloc_alignedPage(size_t length);
void free_aligned(void *ptr);
#endif

View File

@ -1,530 +0,0 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "armcpu.h"
#include "cp15.h"
#include "debug.h"
#include "MMU.h"
#include "emufile.h"
#include "readwrite.h"
#include "utils/bits.h"
armcp15_t cp15;
#define CP15_ACCESSTYPE(val, n) (((val) >> (4*n)) & 0x0F)
/* sets the precalculated regions to mask,set for the affected accesstypes */
void armcp15_t::setSingleRegionAccess(u8 num, u32 mask, u32 set) {
switch (CP15_ACCESSTYPE(DaccessPerm, num)) {
case 4: /* UNP */
case 7: /* UNP */
case 8: /* UNP */
case 9: /* UNP */
case 10: /* UNP */
case 11: /* UNP */
case 12: /* UNP */
case 13: /* UNP */
case 14: /* UNP */
case 15: /* UNP */
case 0: /* no access at all */
regionWriteMask_USR[num] = 0 ;
regionWriteSet_USR[num] = 0xFFFFFFFF ;
regionReadMask_USR[num] = 0 ;
regionReadSet_USR[num] = 0xFFFFFFFF ;
regionWriteMask_SYS[num] = 0 ;
regionWriteSet_SYS[num] = 0xFFFFFFFF ;
regionReadMask_SYS[num] = 0 ;
regionReadSet_SYS[num] = 0xFFFFFFFF ;
break ;
case 1: /* no access at USR, all to sys */
regionWriteMask_USR[num] = 0 ;
regionWriteSet_USR[num] = 0xFFFFFFFF ;
regionReadMask_USR[num] = 0 ;
regionReadSet_USR[num] = 0xFFFFFFFF ;
regionWriteMask_SYS[num] = mask ;
regionWriteSet_SYS[num] = set ;
regionReadMask_SYS[num] = mask ;
regionReadSet_SYS[num] = set ;
break ;
case 2: /* read at USR, all to sys */
regionWriteMask_USR[num] = 0 ;
regionWriteSet_USR[num] = 0xFFFFFFFF ;
regionReadMask_USR[num] = mask ;
regionReadSet_USR[num] = set ;
regionWriteMask_SYS[num] = mask ;
regionWriteSet_SYS[num] = set ;
regionReadMask_SYS[num] = mask ;
regionReadSet_SYS[num] = set ;
break ;
case 3: /* all to USR, all to sys */
regionWriteMask_USR[num] = mask ;
regionWriteSet_USR[num] = set ;
regionReadMask_USR[num] = mask ;
regionReadSet_USR[num] = set ;
regionWriteMask_SYS[num] = mask ;
regionWriteSet_SYS[num] = set ;
regionReadMask_SYS[num] = mask ;
regionReadSet_SYS[num] = set ;
break ;
case 5: /* no access at USR, read to sys */
regionWriteMask_USR[num] = 0 ;
regionWriteSet_USR[num] = 0xFFFFFFFF ;
regionReadMask_USR[num] = 0 ;
regionReadSet_USR[num] = 0xFFFFFFFF ;
regionWriteMask_SYS[num] = 0 ;
regionWriteSet_SYS[num] = 0xFFFFFFFF ;
regionReadMask_SYS[num] = mask ;
regionReadSet_SYS[num] = set ;
break ;
case 6: /* read at USR, read to sys */
regionWriteMask_USR[num] = 0 ;
regionWriteSet_USR[num] = 0xFFFFFFFF ;
regionReadMask_USR[num] = mask ;
regionReadSet_USR[num] = set ;
regionWriteMask_SYS[num] = 0 ;
regionWriteSet_SYS[num] = 0xFFFFFFFF ;
regionReadMask_SYS[num] = mask ;
regionReadSet_SYS[num] = set ;
break ;
}
switch (CP15_ACCESSTYPE(IaccessPerm, num)) {
case 4: /* UNP */
case 7: /* UNP */
case 8: /* UNP */
case 9: /* UNP */
case 10: /* UNP */
case 11: /* UNP */
case 12: /* UNP */
case 13: /* UNP */
case 14: /* UNP */
case 15: /* UNP */
case 0: /* no access at all */
regionExecuteMask_USR[num] = 0 ;
regionExecuteSet_USR[num] = 0xFFFFFFFF ;
regionExecuteMask_SYS[num] = 0 ;
regionExecuteSet_SYS[num] = 0xFFFFFFFF ;
break ;
case 1:
regionExecuteMask_USR[num] = 0 ;
regionExecuteSet_USR[num] = 0xFFFFFFFF ;
regionExecuteMask_SYS[num] = mask ;
regionExecuteSet_SYS[num] = set ;
break ;
case 2:
case 3:
case 6:
regionExecuteMask_USR[num] = mask ;
regionExecuteSet_USR[num] = set ;
regionExecuteMask_SYS[num] = mask ;
regionExecuteSet_SYS[num] = set ;
break ;
}
} ;
/* precalculate region masks/sets from cp15 register */
void armcp15_t::maskPrecalc()
{
#define precalc(num) { \
u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */ \
if (BIT_N(protectBaseSize[num],0)) /* if region is enabled */ \
{ /* reason for this define: naming includes var */ \
mask = CP15_MASKFROMREG(protectBaseSize[num]) ; \
set = CP15_SETFROMREG(protectBaseSize[num]) ; \
if (CP15_SIZEIDENTIFIER(protectBaseSize[num])==0x1F) \
{ /* for the 4GB region, u32 suffers wraparound */ \
mask = 0 ; set = 0 ; /* (x & 0) == 0 is allways true (enabled) */ \
} \
} \
setSingleRegionAccess(num, mask, set) ; \
}
precalc(0) ;
precalc(1) ;
precalc(2) ;
precalc(3) ;
precalc(4) ;
precalc(5) ;
precalc(6) ;
precalc(7) ;
#undef precalc
}
BOOL armcp15_t::isAccessAllowed(u32 address,u32 access)
{
int i ;
if (!(ctrl & 1)) return TRUE ; /* protection checking is not enabled */
for (i=0;i<8;i++) {
switch (access) {
case CP15_ACCESS_WRITEUSR:
if ((address & regionWriteMask_USR[i]) == regionWriteSet_USR[i]) return TRUE ;
break ;
case CP15_ACCESS_WRITESYS:
if ((address & regionWriteMask_SYS[i]) == regionWriteSet_SYS[i]) return TRUE ;
break ;
case CP15_ACCESS_READUSR:
if ((address & regionReadMask_USR[i]) == regionReadSet_USR[i]) return TRUE ;
break ;
case CP15_ACCESS_READSYS:
if ((address & regionReadMask_SYS[i]) == regionReadSet_SYS[i]) return TRUE ;
break ;
case CP15_ACCESS_EXECUSR:
if ((address & regionExecuteMask_USR[i]) == regionExecuteSet_USR[i]) return TRUE ;
break ;
case CP15_ACCESS_EXECSYS:
if ((address & regionExecuteMask_SYS[i]) == regionExecuteSet_SYS[i]) return TRUE ;
break ;
}
}
/* when protections are enabled, but no region allows access, deny access */
return FALSE ;
}
BOOL armcp15_t::dataProcess(u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
{
LOG("Unsupported CP15 operation : DataProcess\n");
return FALSE;
}
BOOL armcp15_t::load(u8 CRd, u8 adr)
{
LOG("Unsupported CP15 operation : Load\n");
return FALSE;
}
BOOL armcp15_t::store(u8 CRd, u8 adr)
{
LOG("Unsupported CP15 operation : Store\n");
return FALSE;
}
BOOL armcp15_t::moveCP2ARM(u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
{
if(NDS_ARM9.CPSR.bits.mode == USR) return FALSE;
switch(CRn)
{
case 0:
if((opcode1 == 0)&&(CRm==0))
{
switch(opcode2)
{
case 1:
*R = cacheType;
return TRUE;
case 2:
*R = TCMSize;
return TRUE;
default:
*R = IDCode;
return TRUE;
}
}
return FALSE;
case 1:
if((opcode1==0) && (opcode2==0) && (CRm==0))
{
*R = ctrl;
//LOG("CP15: CPtoARM ctrl %08X\n", ctrl);
return TRUE;
}
return FALSE;
case 2:
if((opcode1==0) && (CRm==0))
{
switch(opcode2)
{
case 0:
*R = DCConfig;
return TRUE;
case 1:
*R = ICConfig;
return TRUE;
default:
return FALSE;
}
}
return FALSE;
case 3:
if((opcode1==0) && (opcode2==0) && (CRm==0))
{
*R = writeBuffCtrl;
//LOG("CP15: CPtoARM writeBuffer ctrl %08X\n", writeBuffCtrl);
return TRUE;
}
return FALSE;
case 5:
if((opcode1==0) && (CRm==0))
{
switch(opcode2)
{
case 2:
*R = DaccessPerm;
return TRUE;
case 3:
*R = IaccessPerm;
return TRUE;
default:
return FALSE;
}
}
return FALSE;
case 6:
if((opcode1==0) && (opcode2==0))
{
if (CRm < 8)
{
*R = protectBaseSize[CRm];
return TRUE;
}
}
return FALSE;
case 9:
if(opcode1==0)
{
switch(CRm)
{
case 0:
switch(opcode2)
{
case 0:
*R = DcacheLock;
return TRUE;
case 1:
*R = IcacheLock;
return TRUE;
default:
return FALSE;
}
case 1:
switch(opcode2)
{
case 0:
*R = DTCMRegion;
return TRUE;
case 1:
*R = ITCMRegion;
return TRUE;
default:
return FALSE;
}
}
}
return FALSE;
default:
LOG("Unsupported CP15 operation : MRC\n");
return FALSE;
}
}
BOOL armcp15_t::moveARM2CP(u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
{
if(NDS_ARM9.CPSR.bits.mode == USR) return FALSE;
switch(CRn)
{
case 1:
if((opcode1==0) && (opcode2==0) && (CRm==0))
{
//On the NDS bit0,2,7,12..19 are R/W, Bit3..6 are always set, all other bits are always zero.
ctrl = (val & 0x000FF085) | 0x00000078;
MMU.ARM9_RW_MODE = BIT7(val);
//zero 31-jan-2010: change from 0x0FFF0000 to 0xFFFF0000 per gbatek
NDS_ARM9.intVector = 0xFFFF0000 * (BIT13(val));
NDS_ARM9.LDTBit = !BIT15(val); //TBit
//LOG("CP15: ARMtoCP ctrl %08X (val %08X)\n", ctrl, val);
return TRUE;
}
return FALSE;
case 2:
if((opcode1==0) && (CRm==0))
{
switch(opcode2)
{
case 0:
DCConfig = val;
return TRUE;
case 1:
ICConfig = val;
return TRUE;
default:
return FALSE;
}
}
return FALSE;
case 3:
if((opcode1==0) && (opcode2==0) && (CRm==0))
{
writeBuffCtrl = val;
//LOG("CP15: ARMtoCP writeBuffer ctrl %08X\n", writeBuffCtrl);
return TRUE;
}
return FALSE;
case 5:
if((opcode1==0) && (CRm==0))
{
switch(opcode2)
{
case 2:
DaccessPerm = val;
maskPrecalc();
return TRUE;
case 3:
IaccessPerm = val;
maskPrecalc();
return TRUE;
default:
return FALSE;
}
}
return FALSE;
case 6:
if((opcode1==0) && (opcode2==0))
{
if (CRm < 8)
{
protectBaseSize[CRm] = val;
maskPrecalc();
return TRUE;
}
}
return FALSE;
case 7:
if((CRm==0)&&(opcode1==0)&&((opcode2==4)))
{
//CP15wait4IRQ;
NDS_ARM9.freeze = CPU_FREEZE_IRQ_IE_IF;
//IME set deliberately omitted: only SWI sets IME to 1
return TRUE;
}
return FALSE;
case 9:
if(opcode1 == 0)
{
switch(CRm)
{
case 0:
switch(opcode2)
{
case 0:
DcacheLock = val;
return TRUE;
case 1:
IcacheLock = val;
return TRUE;
default:
return FALSE;
}
case 1:
switch(opcode2)
{
case 0:
MMU.DTCMRegion = DTCMRegion = val & 0x0FFFF000;
return TRUE;
case 1:
ITCMRegion = val;
//ITCM base is not writeable!
MMU.ITCMRegion = 0;
return TRUE;
default:
return FALSE;
}
}
}
return FALSE;
default:
return FALSE;
}
}
// Save state
void armcp15_t::saveone(EMUFILE &os)
{
os.write_32LE(IDCode);
os.write_32LE(cacheType);
os.write_32LE(TCMSize);
os.write_32LE(ctrl);
os.write_32LE(DCConfig);
os.write_32LE(ICConfig);
os.write_32LE(writeBuffCtrl);
os.write_32LE(und);
os.write_32LE(DaccessPerm);
os.write_32LE(IaccessPerm);
for (int i=0;i<8;i++) os.write_32LE(protectBaseSize[i]);
os.write_32LE(cacheOp);
os.write_32LE(DcacheLock);
os.write_32LE(IcacheLock);
os.write_32LE(ITCMRegion);
os.write_32LE(DTCMRegion);
os.write_32LE(processID);
os.write_32LE(RAM_TAG);
os.write_32LE(testState);
os.write_32LE(cacheDbg);
for (int i=0;i<8;i++) os.write_32LE(regionWriteMask_USR[i]);
for (int i=0;i<8;i++) os.write_32LE(regionWriteMask_SYS[i]);
for (int i=0;i<8;i++) os.write_32LE(regionReadMask_USR[i]);
for (int i=0;i<8;i++) os.write_32LE(regionReadMask_SYS[i]);
for (int i=0;i<8;i++) os.write_32LE(regionExecuteMask_USR[i]);
for (int i=0;i<8;i++) os.write_32LE(regionExecuteMask_SYS[i]);
for (int i=0;i<8;i++) os.write_32LE(regionWriteSet_USR[i]);
for (int i=0;i<8;i++) os.write_32LE(regionWriteSet_SYS[i]);
for (int i=0;i<8;i++) os.write_32LE(regionReadSet_USR[i]);
for (int i=0;i<8;i++) os.write_32LE(regionReadSet_SYS[i]);
for (int i=0;i<8;i++) os.write_32LE(regionExecuteSet_USR[i]);
for (int i=0;i<8;i++) os.write_32LE(regionExecuteSet_SYS[i]);
}
bool armcp15_t::loadone(EMUFILE &is)
{
if (!is.read_32LE(IDCode)) return false;
if (!is.read_32LE(cacheType)) return false;
if (!is.read_32LE(TCMSize)) return false;
if (!is.read_32LE(ctrl)) return false;
if (!is.read_32LE(DCConfig)) return false;
if (!is.read_32LE(ICConfig)) return false;
if (!is.read_32LE(writeBuffCtrl)) return false;
if (!is.read_32LE(und)) return false;
if (!is.read_32LE(DaccessPerm)) return false;
if (!is.read_32LE(IaccessPerm)) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(protectBaseSize[i])) return false;
if (!is.read_32LE(cacheOp)) return false;
if (!is.read_32LE(DcacheLock)) return false;
if (!is.read_32LE(IcacheLock)) return false;
if (!is.read_32LE(ITCMRegion)) return false;
if (!is.read_32LE(DTCMRegion)) return false;
if (!is.read_32LE(processID)) return false;
if (!is.read_32LE(RAM_TAG)) return false;
if (!is.read_32LE(testState)) return false;
if (!is.read_32LE(cacheDbg)) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(regionWriteMask_USR[i])) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(regionWriteMask_SYS[i])) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(regionReadMask_USR[i])) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(regionReadMask_SYS[i])) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(regionExecuteMask_USR[i])) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(regionExecuteMask_SYS[i])) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(regionWriteSet_USR[i])) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(regionWriteSet_SYS[i])) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(regionReadSet_USR[i])) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(regionReadSet_SYS[i])) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(regionExecuteSet_USR[i])) return false;
for (int i=0;i<8;i++) if (!is.read_32LE(regionExecuteSet_SYS[i])) return false;
return true;
}

View File

@ -1,131 +0,0 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CP15_H__
#define __CP15_H__
#include <string.h>
#include "types.h"
class EMUFILE;
#define CP15_ACCESS_WRITE 0
#define CP15_ACCESS_READ 2
#define CP15_ACCESS_EXECUTE 4
#define CP15_ACCESS_WRITEUSR CP15_ACCESS_WRITE
#define CP15_ACCESS_WRITESYS 1
#define CP15_ACCESS_READUSR CP15_ACCESS_READ
#define CP15_ACCESS_READSYS 3
#define CP15_ACCESS_EXECUSR CP15_ACCESS_EXECUTE
#define CP15_ACCESS_EXECSYS 5
#define CP15_SIZEBINARY(val) (1 << (CP15_SIZEIDENTIFIER(val)+1))
#define CP15_SIZEIDENTIFIER(val) ((((val) >> 1) & 0x1F))
#define CP15_MASKFROMREG(val) (~((CP15_SIZEBINARY(val)-1) | 0x3F))
#define CP15_SETFROMREG(val) ((val) & CP15_MASKFROMREG(val))
struct armcp15_t
{
public:
u32 IDCode;
u32 cacheType;
u32 TCMSize;
u32 ctrl;
u32 DCConfig;
u32 ICConfig;
u32 writeBuffCtrl;
u32 und;
u32 DaccessPerm;
u32 IaccessPerm;
u32 protectBaseSize[8];
u32 cacheOp;
u32 DcacheLock;
u32 IcacheLock;
u32 ITCMRegion;
u32 DTCMRegion;
u32 processID;
u32 RAM_TAG;
u32 testState;
u32 cacheDbg;
/* calculated bitmasks for the regions to decide rights uppon */
/* calculation is done in the MCR instead of on mem access for performance */
u32 regionWriteMask_USR[8] ;
u32 regionWriteMask_SYS[8] ;
u32 regionReadMask_USR[8] ;
u32 regionReadMask_SYS[8] ;
u32 regionExecuteMask_USR[8] ;
u32 regionExecuteMask_SYS[8] ;
u32 regionWriteSet_USR[8] ;
u32 regionWriteSet_SYS[8] ;
u32 regionReadSet_USR[8] ;
u32 regionReadSet_SYS[8] ;
u32 regionExecuteSet_USR[8] ;
u32 regionExecuteSet_SYS[8] ;
void setSingleRegionAccess(u8 num, u32 mask, u32 set);
void maskPrecalc();
public:
armcp15_t() : IDCode(0x41059461),
cacheType(0x0F0D2112),
TCMSize(0x00140180),
ctrl(0x00012078),
DCConfig(0),
ICConfig(0),
writeBuffCtrl(0),
und(0),
DaccessPerm(0x22222222),
IaccessPerm(0x22222222),
cacheOp(0),
DcacheLock(0),
IcacheLock(0),
ITCMRegion(0x0C),
DTCMRegion(0x0080000A),
processID(0),
RAM_TAG(0),
testState(0),
cacheDbg(0)
{
//printf("CP15 Reset\n");
memset(&protectBaseSize[0], 0, sizeof(protectBaseSize));
memset(&regionWriteMask_USR[0], 0, sizeof(regionWriteMask_USR));
memset(&regionWriteMask_SYS[0], 0, sizeof(regionWriteMask_SYS));
memset(&regionReadMask_USR[0], 0, sizeof(regionReadMask_USR));
memset(&regionReadMask_SYS[0], 0, sizeof(regionReadMask_SYS));
memset(&regionExecuteMask_USR[0], 0, sizeof(regionExecuteMask_USR));
memset(&regionExecuteMask_SYS[0], 0, sizeof(regionExecuteMask_SYS));
memset(&regionWriteSet_USR[0], 0, sizeof(regionWriteSet_USR));
memset(&regionWriteSet_SYS[0], 0, sizeof(regionWriteSet_SYS));
memset(&regionReadSet_USR[0], 0, sizeof(regionReadSet_USR));
memset(&regionReadSet_SYS[0], 0, sizeof(regionReadSet_SYS));
memset(&regionExecuteSet_USR[0], 0, sizeof(regionExecuteSet_USR));
memset(&regionExecuteSet_SYS[0], 0, sizeof(regionExecuteSet_SYS));
}
BOOL dataProcess(u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
BOOL load(u8 CRd, u8 adr);
BOOL store(u8 CRd, u8 adr);
BOOL moveCP2ARM(u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
BOOL moveARM2CP(u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
BOOL isAccessAllowed(u32 address,u32 access);
// savestate
void saveone(EMUFILE &os);
bool loadone(EMUFILE &is);
};
extern armcp15_t cp15;
#endif /* __CP15_H__*/

View File

@ -1,473 +0,0 @@
/*
Copyright (C) 2006 Guillaume Duhamel
Copyright (C) 2006-2016 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "debug.h"
#include <algorithm>
#include <stdarg.h>
#include <stdio.h>
#include "MMU.h"
#include "armcpu.h"
#include "instructions.h"
#include "cp15.h"
#include "NDSSystem.h"
#include "utils/xstring.h"
#include "movie.h"
#ifdef HAVE_LUA
#include "lua-engine.h"
#endif
armcpu_t* TDebugEventData::cpu() { return procnum==0?&NDS_ARM9:&NDS_ARM7; }
TDebugEventData DebugEventData;
u32 debugFlag;
// PACKET HACK VARS
FILE *log_ptr; // File to store the dumped data
const u32 rc4_addr[2] = { 0x020986A8, 0x02098710 };
//DEBUG CONFIGURATION
const bool debug_acl = false;
const bool debug_cacheMiss = false;
static bool acl_check_access(u32 adr, u32 access) {
//non-user modes get separate access handling, so check that here
if(NDS_ARM9.CPSR.bits.mode != USR)
access |= 1;
if (cp15.isAccessAllowed(adr,access)==FALSE) {
HandleDebugEvent(DEBUG_EVENT_ACL_EXCEPTION);
}
return true;
}
void HandleDebugEvent_ACL_Exception()
{
printf("ACL EXCEPTION!\n");
if(DebugEventData.memAccessType == MMU_AT_CODE)
armcpu_exception(DebugEventData.cpu(),EXCEPTION_PREFETCH_ABORT);
else if(DebugEventData.memAccessType == MMU_AT_DATA)
armcpu_exception(DebugEventData.cpu(),EXCEPTION_DATA_ABORT);
}
static bool CheckRange(u32 adr, u32 min, u32 len)
{
return (adr>=min && adr<min+len);
}
void HandleDebugEvent_Read()
{
if(!debug_acl) return;
if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9
acl_check_access(DebugEventData.addr,CP15_ACCESS_READ);
}
void HandleDebugEvent_Write()
{
// Disabled by default.
// If you want to enable first you must know and update the address of the
// RC4 algoritm function.
return;
// This method is called twice, so ommit one call.
extern bool nds_debug_continuing[2];
if (nds_debug_continuing[DebugEventData.procnum]) {
nds_debug_continuing[DebugEventData.procnum] = false;
return;
}
// RC4 encrypt / decrypt function
// R1: Pointer to data to operate (to decrypt or encrypt)
// R2: Size of this data
if (DebugEventData.addr == rc4_addr[0] || DebugEventData.addr == rc4_addr[1]) {
nds_debug_continuing[DebugEventData.procnum] = true;
u32 addr = DebugEventData.addr;
printf("WIFI: Call to RC4_ALGORITM\n");
// Write log. Append current data
// TODO: It needs to open the file each time, it could be slow.
// An improvement could be opening the file at the start of the function
// and closing at the end of the function.
log_ptr = fopen("wifi_log.txt", "a");
if (log_ptr != NULL)
{
// Create header
time_t ti;
time(&ti);
tm* t = localtime(&ti);
fprintf(log_ptr, "\n[%02d-%02d-%02d-%02d-%02d] %s of RC4_ALGORITM -----------\n",
t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,
(addr == rc4_addr[0]) ? "Start" : "End"
);
// Dump data
int length = DebugEventData.cpu()->R[2];
int position = DebugEventData.cpu()->R[1] - 0x02000000; // Relative to memory array
fwrite(MMU.MAIN_MEM + position, sizeof(char), length, log_ptr);
// End
fprintf(log_ptr, "\n- THE END -----------------------------------------------\n");
// Flush and close by the moment
fflush(log_ptr);
fclose(log_ptr);
}
else {
printf("Error opening log file\n");
}
}
}
void HandleDebugEvent_Execute()
{
//HACKY BREAKPOINTS!
//extern bool nds_debug_continuing[2];
//if(!nds_debug_continuing[DebugEventData.procnum]) //dont keep hitting the same breakpoint
//{
// if((DebugEventData.addr & 0xFFFFFFF0) == 0x02000000)
// {
// void NDS_debug_break();
// NDS_debug_break();
// }
//}
if(!debug_acl) return;
if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9
acl_check_access(DebugEventData.addr,CP15_ACCESS_EXECUTE);
}
void HandleDebugEvent_CacheMiss()
{
if(!debug_cacheMiss) return;
extern int currFrameCounter;
if(currFrameCounter<200) return;
static FILE* outf = NULL;
if(!outf) outf = fopen("c:\\miss.txt","wb");
fprintf(outf,"%05d,%08X,%d\n",currFrameCounter,DebugEventData.addr,DebugEventData.size);
}
//------------------------------------------------
DebugStatistics DEBUG_statistics;
DebugStatistics::DebugStatistics()
{
}
DebugStatistics::InstructionHits::InstructionHits()
{
memset(&arm,0,sizeof(arm));
memset(&thumb,0,sizeof(thumb));
}
static DebugStatistics::InstructionHits combinedHits[2];
template<int proc, int which>
static bool debugStatsSort(int num1, int num2) {
if(which==0) {
if(combinedHits[proc].arm[num2] == combinedHits[proc].arm[num1]) return false;
if(combinedHits[proc].arm[num1] == 0xFFFFFFFF) return false;
if(combinedHits[proc].arm[num2] == 0xFFFFFFFF) return true;
return combinedHits[proc].arm[num2] < combinedHits[proc].arm[num1];
}
else {
if(combinedHits[proc].thumb[num2] == combinedHits[proc].thumb[num1]) return false;
if(combinedHits[proc].thumb[num1] == 0xFFFFFFFF) return false;
if(combinedHits[proc].thumb[num2] == 0xFFFFFFFF) return true;
return combinedHits[proc].thumb[num2] < combinedHits[proc].thumb[num1];
}
}
void DebugStatistics::print()
{
//consolidate opcodes with the same names
for(int i=0;i<2;i++) {
combinedHits[i] = DEBUG_statistics.instructionHits[i];
for(int j=0;j<4096;j++) {
if(combinedHits[i].arm[j] == 0xFFFFFFFF)
continue;
std::string name = arm_instruction_names[j];
for(int k=j+1;k<4096;k++) {
if(combinedHits[i].arm[k] == 0xFFFFFFFF)
continue;
if(name == arm_instruction_names[k]) {
//printf("combining %s with %d and %d\n",name.c_str(),combinedHits[i].arm[j],combinedHits[i].arm[k]);
combinedHits[i].arm[j] += combinedHits[i].arm[k];
combinedHits[i].arm[k] = 0xFFFFFFFF;
}
}
}
for(int j=0;j<1024;j++) {
if(combinedHits[i].thumb[j] == 0xFFFFFFFF)
continue;
std::string name = thumb_instruction_names[j];
for(int k=j+1;k<1024;k++) {
if(combinedHits[i].thumb[k] == 0xFFFFFFFF)
continue;
if(name == thumb_instruction_names[k]) {
//printf("combining %s with %d and %d\n",name.c_str(),combinedHits[i].arm[j],combinedHits[i].arm[k]);
combinedHits[i].thumb[j] += combinedHits[i].thumb[k];
combinedHits[i].thumb[k] = 0xFFFFFFFF;
}
}
}
}
InstructionHits sorts[2];
for(int i=0;i<2;i++) {
for(int j=0;j<4096;j++) sorts[i].arm[j] = j;
for(int j=0;j<1024;j++) sorts[i].thumb[j] = j;
}
std::sort(sorts[0].arm, sorts[0].arm+4096, debugStatsSort<0,0>);
std::sort(sorts[0].thumb, sorts[0].thumb+1024, debugStatsSort<0,1>);
std::sort(sorts[1].arm, sorts[1].arm+4096, debugStatsSort<1,0>);
std::sort(sorts[1].thumb, sorts[1].thumb+1024, debugStatsSort<1,1>);
for(int i=0;i<2;i++) {
printf("Top arm instructions for ARM%d:\n",7+i*2);
for(int j=0;j<10;j++) {
int val = sorts[i].arm[j];
printf("%08d: %s\n", combinedHits[i].arm[val], arm_instruction_names[val]);
}
printf("Top thumb instructions for ARM%d:\n",7+i*2);
for(int j=0;j<10;j++) {
int val = sorts[i].thumb[j];
printf("%08d: %s\n", combinedHits[i].thumb[val], thumb_instruction_names[val]);
}
}
}
void DebugStatistics::printSequencerExecutionCounters()
{
for(int i=0;i<21;i++) printf("%06d ",sequencerExecutionCounters[i]);
printf("\n");
}
void DEBUG_reset()
{
//for now, just enable all debugging in developer builds
#ifdef DEVELOPER
debugFlag = 1;
#endif
DEBUG_Notify = DebugNotify();
DEBUG_statistics = DebugStatistics();
printf("DEBUG_reset: %p\n",&DebugStatistics::print); //force a reference to this function
}
static void DEBUG_dumpMemory_fill(EMUFILE &fp, u32 size)
{
static std::vector<u8> buf;
buf.resize(size);
memset(&buf[0],0,size);
fp.fwrite(&buf[0],size);
}
void DEBUG_dumpMemory(EMUFILE &fp)
{
fp.fseek(0x000000,SEEK_SET); fp.fwrite(MMU.MAIN_MEM,0x800000); //arm9 main mem (8192K)
fp.fseek(0x900000,SEEK_SET); fp.fwrite(MMU.ARM9_DTCM,0x4000); //arm9 DTCM (16K)
fp.fseek(0xA00000,SEEK_SET); fp.fwrite(MMU.ARM9_ITCM,0x8000); //arm9 ITCM (32K)
fp.fseek(0xB00000,SEEK_SET); fp.fwrite(MMU.ARM9_LCD,0xA4000); //LCD mem 656K
fp.fseek(0xC00000,SEEK_SET); fp.fwrite(MMU.ARM9_VMEM,0x800); //OAM
fp.fseek(0xD00000,SEEK_SET); fp.fwrite(MMU.ARM7_ERAM,0x10000); //arm7 WRAM (64K)
fp.fseek(0xE00000,SEEK_SET); fp.fwrite(MMU.ARM7_WIRAM,0x10000); //arm7 wifi RAM ?
fp.fseek(0xF00000,SEEK_SET); fp.fwrite(MMU.SWIRAM,0x8000); //arm9/arm7 shared WRAM (32KB)
}
//----------------------------------------------------
std::vector<Logger *> Logger::channels;
static void defaultCallback(const Logger& logger, const char * message) {
logger.getOutput() << message;
}
Logger::Logger() {
out = &std::cout;
callback = defaultCallback;
flags = 0;
}
Logger::~Logger() {
for(int i=0;i<(int)channels.size();i++)
delete channels[i];
}
void Logger::vprintf(const char * format, va_list l, const char * file, unsigned int line) {
char buffer[1024];
char * cur = buffer;
if (flags & Logger::FILE) cur += sprintf(cur, "%s:", file);
if (flags & Logger::LINE) cur += sprintf(cur, "%d:", line);
if (flags) cur += sprintf(cur, " ");
::vsnprintf(cur, 1024, format, l);
callback(*this, buffer);
}
void Logger::setOutput(std::ostream * o) {
out = o;
}
void Logger::setCallback(void (*cback)(const Logger& logger, const char * message)) {
callback = cback;
}
void Logger::setFlag(unsigned int flag) {
this->flags = flag;
}
void Logger::fixSize(unsigned int channel) {
while(channel >= channels.size()) {
channels.push_back(new Logger());
}
}
std::ostream& Logger::getOutput() const {
return *out;
}
void Logger::log(unsigned int channel, const char * file, unsigned int line, const char * format, ...) {
fixSize(channel);
va_list l;
va_start(l, format);
channels[channel]->vprintf(format, l, file, line);
va_end(l);
}
void Logger::log(unsigned int channel, const char * file, unsigned int line, std::ostream& os) {
fixSize(channel);
channels[channel]->setOutput(&os);
}
void Logger::log(unsigned int channel, const char * file, unsigned int line, unsigned int flag) {
fixSize(channel);
channels[channel]->setFlag(flag);
}
void Logger::log(unsigned int channel, const char * file, unsigned int line, void (*callback)(const Logger& logger, const char * message)) {
fixSize(channel);
channels[channel]->setCallback(callback);
}
void IdeasLog(armcpu_t* cpu)
{
u32 adr = cpu->R[0];
for(;;) {
u8 c = _MMU_read08(cpu->proc_ID, MMU_AT_DEBUG, adr);
adr++;
if(!c) break;
printf("%c",c);
}
//don't emit a newline. that is a pain in the butt.
}
void NocashMessage(armcpu_t* cpu, int offset)
{
u32 adr = cpu->instruct_adr + offset;
std::string todo;
for(;;) {
u8 c = _MMU_read08(cpu->proc_ID, MMU_AT_DEBUG, adr);
adr++;
if(!c) break;
todo.push_back(c);
}
//r0,r1,r2,...,r15 show register content (displayed as 32bit Hex number)
//sp,lr,pc alias for r13,r14,r15
//scanline show current scanline number
//frame show total number of frames since coldboot
//totalclks show total number of clock cycles since coldboot
//lastclks show number of cycles since previous lastclks (or zeroclks)
//zeroclks resets the 'lastclks' counter
//this is very inefficiently coded!
char tmp[100];
todo = mass_replace(todo,"%sp%","%r13%");
todo = mass_replace(todo,"%lr%","%r14%");
todo = mass_replace(todo,"%pc%","%r15%");
sprintf(tmp,"%08X",cpu->R[0]); todo = mass_replace(todo,"%r0%",tmp);
sprintf(tmp,"%08X",cpu->R[1]); todo = mass_replace(todo,"%r1%",tmp);
sprintf(tmp,"%08X",cpu->R[2]); todo = mass_replace(todo,"%r2%",tmp);
sprintf(tmp,"%08X",cpu->R[3]); todo = mass_replace(todo,"%r3%",tmp);
sprintf(tmp,"%08X",cpu->R[4]); todo = mass_replace(todo,"%r4%",tmp);
sprintf(tmp,"%08X",cpu->R[5]); todo = mass_replace(todo,"%r5%",tmp);
sprintf(tmp,"%08X",cpu->R[6]); todo = mass_replace(todo,"%r6%",tmp);
sprintf(tmp,"%08X",cpu->R[7]); todo = mass_replace(todo,"%r7%",tmp);
sprintf(tmp,"%08X",cpu->R[8]); todo = mass_replace(todo,"%r8%",tmp);
sprintf(tmp,"%08X",cpu->R[9]); todo = mass_replace(todo,"%r9%",tmp);
sprintf(tmp,"%08X",cpu->R[10]); todo = mass_replace(todo,"%r10%",tmp);
sprintf(tmp,"%08X",cpu->R[11]); todo = mass_replace(todo,"%r11%",tmp);
sprintf(tmp,"%08X",cpu->R[12]); todo = mass_replace(todo,"%r12%",tmp);
sprintf(tmp,"%08X",cpu->R[13]); todo = mass_replace(todo,"%r13%",tmp);
sprintf(tmp,"%08X",cpu->R[14]); todo = mass_replace(todo,"%r14%",tmp);
sprintf(tmp,"%08X",cpu->R[15]); todo = mass_replace(todo,"%r15%",tmp);
sprintf(tmp,"%d",nds.VCount); todo = mass_replace(todo,"%scanline%",tmp);
sprintf(tmp,"%d",currFrameCounter); todo = mass_replace(todo,"%frame%",tmp);
sprintf(tmp,"%lld",nds_timer); todo = mass_replace(todo,"%totalclks%",tmp);
printf("%s",todo.c_str());
}
//-------
DebugNotify DEBUG_Notify;
//enable bits arent being used right now.
//if you want exhaustive logging, move the print before the early return (or comment the early return)
//the intent of this system is to provide a compact dialog box showing which debug notifies have been
//triggered in this frame (with a glowing LED!) and which debug notifies have been triggered EVER
//which can be cleared, like a clip indicator in an audio tool.
//obviously all this isnt implemented yet.
void DebugNotify::NextFrame()
{
#ifdef DEVELOPER
pingBits.reset();
#endif
}
void DebugNotify::ReadBeyondEndOfCart(u32 addr, u32 romsize)
{
#ifdef DEVELOPER
if(!ping(DEBUG_NOTIFY_READ_BEYOND_END_OF_CART)) return;
INFO("Reading beyond end of cart! ... %08X >= %08X\n",addr,romsize);
#endif
}
bool DebugNotify::ping(EDEBUG_NOTIFY which)
{
bool wasPinged = pingBits[(int)which];
pingBits[(int)which] = true;
return !wasPinged;
}

View File

@ -1,219 +0,0 @@
/*
Copyright (C) 2006 Guillaume Duhamel
Copyright (C) 2006-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DEBUG_H
#define DEBUG_H
#include <vector>
#include <iostream>
#include <cstdarg>
#include <bitset>
#include "types.h"
#include "mem.h"
struct armcpu_t;
class EMUFILE;
struct DebugStatistics
{
DebugStatistics();
struct InstructionHits {
InstructionHits();
u32 thumb[1024];
u32 arm[4096];
} instructionHits[2]; //one for each cpu
s32 sequencerExecutionCounters[32];
void print();
void printSequencerExecutionCounters();
};
extern DebugStatistics DEBUG_statistics;
void DEBUG_reset();
void DEBUG_dumpMemory(EMUFILE &fp);
struct armcpu_t;
class Logger {
protected:
void (*callback)(const Logger& logger, const char * format);
std::ostream * out;
unsigned int flags;
static std::vector<Logger *> channels;
static void fixSize(unsigned int channel);
public:
Logger();
~Logger();
void vprintf(const char * format, va_list l, const char * filename, unsigned int line);
void setOutput(std::ostream * o);
void setCallback(void (*cback)(const Logger& logger, const char * message));
void setFlag(unsigned int flag);
std::ostream& getOutput() const;
static const int LINE = 1;
static const int FILE = 2;
static void log(unsigned int channel, const char * file, unsigned int line, const char * format, ...);
static void log(unsigned int channel, const char * file, unsigned int line, std::ostream& os);
static void log(unsigned int channel, const char * file, unsigned int line, unsigned int flag);
static void log(unsigned int channel, const char * file, unsigned int line, void (*callback)(const Logger& logger, const char * message));
};
#if defined(DEBUG) || defined(GPUDEBUG) || defined(DIVDEBUG) || defined(SQRTDEBUG) || defined(DMADEBUG) || defined(DEVELOPER)
#define LOGC(channel, ...) Logger::log(channel, __FILE__, __LINE__, __VA_ARGS__)
#else
#define LOGC(...) {}
#endif
#ifdef DEBUG
#define LOG(...) LOGC(0, __VA_ARGS__)
#else
#define LOG(...) {}
#endif
#ifdef GPUDEBUG
#define GPULOG(...) LOGC(1, __VA_ARGS__)
#else
#define GPULOG(...) {}
#endif
#ifdef DIVDEBUG
#define DIVLOG(...) LOGC(2, __VA_ARGS__)
#else
#define DIVLOG(...) {}
#endif
#ifdef SQRTDEBUG
#define SQRTLOG(...) LOGC(3, __VA_ARGS__)
#else
#define SQRTLOG(...) {}
#endif
#ifdef DMADEBUG
#define DMALOG(...) LOGC(4, __VA_ARGS__)
#else
#define DMALOG(...) {}
#endif
#ifdef CFLASHDEBUG
#define CFLASHLOG(...) LOGC(5, __VA_ARGS__)
#else
#define CFLASHLOG(...) {}
#endif
#ifdef UNTESTEDOPCODEDEBUG
#define UNTESTEDOPCODELOG(...) LOGC(6, __VA_ARGS__)
#else
#define UNTESTEDOPCODELOG(...) {}
#endif
#ifdef DEVELOPER
#define PROGINFO(...) LOGC(7, __VA_ARGS__)
#else
#define PROGINFO(...) {}
#endif
#define INFOC(channel, ...) Logger::log(channel, __FILE__, __LINE__, __VA_ARGS__)
#define INFO(...) INFOC(10, __VA_ARGS__)
void IdeasLog(armcpu_t* cpu);
void NocashMessage(armcpu_t* cpu, int offset);
enum EDEBUG_EVENT
{
DEBUG_EVENT_READ=1, //read from arm9 or arm7 bus, including cpu prefetch
DEBUG_EVENT_WRITE=2, //write on arm9 or arm7 bus
DEBUG_EVENT_EXECUTE=3, //prefetch on arm9 or arm7, triggered after the read event
DEBUG_EVENT_ACL_EXCEPTION=4, //acl exception on arm9
DEBUG_EVENT_CACHE_MISS=5, //cache miss on arm9
};
enum EDEBUG_NOTIFY
{
DEBUG_NOTIFY_READ_BEYOND_END_OF_CART,
DEBUG_NOTIFY_MAX
};
class DebugNotify
{
public:
void NextFrame();
void ReadBeyondEndOfCart(u32 addr, u32 romsize);
private:
std::bitset<DEBUG_NOTIFY_MAX> pingBits;
std::bitset<DEBUG_NOTIFY_MAX> enableBits;
bool ping(EDEBUG_NOTIFY which);
};
extern DebugNotify DEBUG_Notify;
//information about a debug event will be stuffed into here by the generator
struct TDebugEventData
{
MMU_ACCESS_TYPE memAccessType;
u32 procnum, addr, size, val;
armcpu_t* cpu();
};
extern TDebugEventData DebugEventData;
//bits in here are set according to what debug handlers are installed?
//for now it is just a single bit
extern u32 debugFlag;
FORCEINLINE bool CheckDebugEvent(EDEBUG_EVENT event)
{
//for now, debug events are only handled in dev+ builds
#ifndef DEVELOPER
return false;
#endif
if(!debugFlag) return false;
return true;
}
void HandleDebugEvent_Read();
void HandleDebugEvent_Write();
void HandleDebugEvent_Execute();
void HandleDebugEvent_ACL_Exception();
void HandleDebugEvent_CacheMiss();
inline void HandleDebugEvent(EDEBUG_EVENT event)
{
switch(event)
{
case DEBUG_EVENT_READ: HandleDebugEvent_Read(); return;
case DEBUG_EVENT_WRITE: HandleDebugEvent_Write(); return;
case DEBUG_EVENT_EXECUTE: HandleDebugEvent_Execute(); return;
case DEBUG_EVENT_ACL_EXCEPTION: HandleDebugEvent_ACL_Exception(); return;
case DEBUG_EVENT_CACHE_MISS: HandleDebugEvent_CacheMiss(); return;
}
}
#endif

View File

@ -1,68 +0,0 @@
/*
Copyright (C) 2009-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "driver.h"
#include "debug.h"
#include "rasterize.h"
#include "gfx3d.h"
#include "texcache.h"
#if HAVE_LIBAGG
#include "frontend/modules/osd/agg/agg_osd.h"
#endif
static VIEW3D_Driver nullView3d;
BaseDriver::BaseDriver()
: view3d(NULL)
{
VIEW3D_Shutdown();
}
void BaseDriver::VIEW3D_Shutdown()
{
if(view3d != &nullView3d) delete view3d;
view3d = &nullView3d;
}
void BaseDriver::VIEW3D_Init()
{
VIEW3D_Shutdown();
}
BaseDriver::~BaseDriver()
{
}
void BaseDriver::AddLine(const char *fmt, ...)
{
#if HAVE_LIBAGG
if(!osd) return;
va_list list;
va_start(list,fmt);
osd->addLine(fmt,list);
va_end(list);
#endif
}
void BaseDriver::SetLineColor(u8 r, u8 b, u8 g)
{
#if HAVE_LIBAGG
if(!osd) return;
osd->setLineColor(r,b,g);
#endif
}

View File

@ -1,81 +0,0 @@
/*
Copyright (C) 2009-2018 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DRIVER_H_
#define _DRIVER_H_
#include <stdio.h>
#include "types.h"
#include "debug.h"
class VIEW3D_Driver
{
public:
virtual void Launch() {}
virtual void NewFrame() {}
virtual bool IsRunning() { return false; }
};
//each platform needs to implement this, although it doesnt need to implement any functions
class BaseDriver {
public:
BaseDriver();
~BaseDriver();
virtual void AVI_SoundUpdate(void* soundData, int soundLen) {}
virtual bool AVI_IsRecording() { return FALSE; }
virtual bool WAV_IsRecording() { return FALSE; }
virtual void USR_InfoMessage(const char *message) { LOG("%s\n", message); }
virtual void USR_RefreshScreen() {}
virtual void USR_SetDisplayPostpone(int milliseconds, bool drawNextFrame) {} // -1 == indefinitely, 0 == don't pospone, 500 == don't draw for 0.5 seconds
enum eStepMainLoopResult
{
ESTEP_NOT_IMPLEMENTED = -1,
ESTEP_CALL_AGAIN = 0,
ESTEP_DONE = 1
};
virtual eStepMainLoopResult EMU_StepMainLoop(bool allowSleep, bool allowPause, int frameSkip, bool disableUser, bool disableCore) { return ESTEP_NOT_IMPLEMENTED; } // -1 frameSkip == useCurrentDefault
virtual void EMU_PauseEmulation(bool pause) {}
virtual bool EMU_IsEmulationPaused() { return false; }
virtual bool EMU_IsFastForwarding() { return false; }
virtual bool EMU_HasEmulationStarted() { return true; }
virtual bool EMU_IsAtFrameBoundary() { return true; }
virtual void EMU_DebugIdleEnter() {}
virtual void EMU_DebugIdleUpdate() {}
virtual void EMU_DebugIdleWakeUp() {}
enum eDebug_IOReg
{
EDEBUG_IOREG_DMA
};
virtual void DEBUG_UpdateIORegView(eDebug_IOReg category) { }
VIEW3D_Driver* view3d;
void VIEW3D_Shutdown();
void VIEW3D_Init();
virtual void AddLine(const char *fmt, ...);
virtual void SetLineColor(u8 r, u8 b, u8 g);
};
extern BaseDriver* driver;
#endif //_DRIVER_H_

View File

@ -1,511 +0,0 @@
/*
The MIT License
Copyright (C) 2009-2019 DeSmuME team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "emufile.h"
#include <vector>
inline u64 double_to_u64(double d)
{
union
{
u64 a;
double b;
} fuxor;
fuxor.b = d;
return fuxor.a;
}
inline double u64_to_double(u64 u)
{
union
{
u64 a;
double b;
} fuxor;
fuxor.a = u;
return fuxor.b;
}
inline u32 float_to_u32(float f)
{
union
{
u32 a;
float b;
} fuxor;
fuxor.b = f;
return fuxor.a;
}
inline float u32_to_float(u32 u)
{
union
{
u32 a;
float b;
} fuxor;
fuxor.a = u;
return fuxor.b;
}
bool EMUFILE::readAllBytes(std::vector<u8>* dstbuf, const std::string& fname)
{
EMUFILE_FILE file(fname.c_str(),"rb");
if(file.fail()) return false;
int size = file.size();
dstbuf->resize(size);
file.fread(&dstbuf->at(0),size);
return true;
}
size_t EMUFILE_MEMORY::_fread(const void *ptr, size_t bytes){
u32 remain = len-pos;
u32 todo = std::min<u32>(remain,(u32)bytes);
if(len==0)
{
failbit = true;
return 0;
}
if(todo<=4)
{
u8* src = buf()+pos;
u8* dst = (u8*)ptr;
for(size_t i=0;i<todo;i++)
*dst++ = *src++;
}
else
{
memcpy((void*)ptr,buf()+pos,todo);
}
pos += todo;
if(todo<bytes)
failbit = true;
return todo;
}
void EMUFILE_FILE::truncate(s32 length)
{
::fflush(fp);
#ifdef HOST_WINDOWS
_chsize(_fileno(fp),length);
#else
ftruncate(fileno(fp),length);
#endif
fclose(fp);
fp = NULL;
open(fname.c_str(),mode);
}
int EMUFILE_FILE::fseek(int offset, int origin)
{
//if the position cache is enabled, and the seek offset matches the known current position, then early exit.
if(mPositionCacheEnabled)
{
if(origin == SEEK_SET)
{
if(mFilePosition == offset)
{
return 0;
}
}
}
mCondition = eCondition_Clean;
int ret = ::fseek(fp, offset, origin);
if(mPositionCacheEnabled)
mFilePosition = ::ftell(fp);
return ret;
}
int EMUFILE_FILE::ftell()
{
if(mPositionCacheEnabled)
return (int)mFilePosition;
return (u32)::ftell(fp);
}
void EMUFILE_FILE::DemandCondition(eCondition cond)
{
//allows switching between reading and writing; an fseek is required, under the circumstances
if(mCondition == eCondition_Clean)
goto CONCLUDE;
if(mCondition == eCondition_Unknown)
goto RESET;
if(mCondition != cond)
goto RESET;
return;
RESET:
::fseek(fp,::ftell(fp),SEEK_SET);
CONCLUDE:
mCondition = cond;
}
size_t EMUFILE_FILE::_fread(const void *ptr, size_t bytes)
{
DemandCondition(eCondition_Read);
size_t ret = ::fread((void*)ptr, 1, bytes, fp);
mFilePosition += ret;
if(ret < bytes)
failbit = true;
return ret;
}
void EMUFILE_FILE::EnablePositionCache()
{
mPositionCacheEnabled = true;
mFilePosition = ::ftell(fp);
}
size_t EMUFILE_FILE::fwrite(const void *ptr, size_t bytes)
{
DemandCondition(eCondition_Write);
size_t ret = ::fwrite((void*)ptr, 1, bytes, fp);
mFilePosition += ret;
if(ret < bytes)
failbit = true;
return ret;
}
EMUFILE* EMUFILE_FILE::memwrap()
{
EMUFILE_MEMORY* mem = new EMUFILE_MEMORY(size());
if(size()==0) return mem;
fread(mem->buf(),size());
return mem;
}
EMUFILE* EMUFILE_MEMORY::memwrap()
{
return this;
}
size_t EMUFILE::write_64LE(s64 s64valueIn)
{
return write_64LE(*(u64 *)&s64valueIn);
}
size_t EMUFILE::write_64LE(u64 u64valueIn)
{
u64valueIn = LOCAL_TO_LE_64(u64valueIn);
fwrite(&u64valueIn,8);
return 8;
}
size_t EMUFILE::read_64LE(s64 &s64valueOut)
{
return read_64LE(*(u64 *)&s64valueOut);
}
size_t EMUFILE::read_64LE(u64 &u64valueOut)
{
u64 temp = 0;
if (fread(&temp,8) != 8)
return 0;
u64valueOut = LE_TO_LOCAL_64(temp);
return 1;
}
s64 EMUFILE::read_s64LE()
{
s64 value = 0;
read_64LE(value);
return value;
}
u64 EMUFILE::read_u64LE()
{
u64 value = 0;
read_64LE(value);
return value;
}
size_t EMUFILE::write_32LE(s32 s32valueIn)
{
return write_32LE(*(u32 *)&s32valueIn);
}
size_t EMUFILE::write_32LE(u32 u32valueIn)
{
u32valueIn = LOCAL_TO_LE_32(u32valueIn);
fwrite(&u32valueIn,4);
return 4;
}
size_t EMUFILE::read_32LE(s32 &s32valueOut)
{
return read_32LE(*(u32 *)&s32valueOut);
}
size_t EMUFILE::read_32LE(u32 &u32valueOut)
{
u32 temp = 0;
if (fread(&temp,4) != 4)
return 0;
u32valueOut = LE_TO_LOCAL_32(temp);
return 1;
}
s32 EMUFILE::read_s32LE()
{
s32 value = 0;
read_32LE(value);
return value;
}
u32 EMUFILE::read_u32LE()
{
u32 value = 0;
read_32LE(value);
return value;
}
size_t EMUFILE::write_16LE(s16 s16valueIn)
{
return write_16LE(*(u16 *)&s16valueIn);
}
size_t EMUFILE::write_16LE(u16 u16valueIn)
{
u16valueIn = LOCAL_TO_LE_16(u16valueIn);
fwrite(&u16valueIn,2);
return 2;
}
size_t EMUFILE::read_16LE(s16 &s16valueOut)
{
return read_16LE(*(u16 *)&s16valueOut);
}
size_t EMUFILE::read_16LE(u16 &u16valueOut)
{
u32 temp = 0;
if (fread(&temp,2) != 2)
return 0;
u16valueOut = LE_TO_LOCAL_16(temp);
return 1;
}
s16 EMUFILE::read_s16LE()
{
s16 value = 0;
read_16LE(value);
return value;
}
u16 EMUFILE::read_u16LE()
{
u16 value = 0;
read_16LE(value);
return value;
}
size_t EMUFILE::write_u8(u8 u8valueIn)
{
fwrite(&u8valueIn,1);
return 1;
}
size_t EMUFILE::read_u8(u8 &u8valueOut)
{
return fread(&u8valueOut,1);
}
u8 EMUFILE::read_u8()
{
u8 value = 0;
fread(&value,1);
return value;
}
size_t EMUFILE::write_doubleLE(double doubleValueIn)
{
return write_64LE(double_to_u64(doubleValueIn));
}
size_t EMUFILE::read_doubleLE(double &doubleValueOut)
{
u64 temp = 0;
size_t ret = read_64LE(temp);
doubleValueOut = u64_to_double(temp);
return ret;
}
double EMUFILE::read_doubleLE()
{
double value = 0.0;
read_doubleLE(value);
return value;
}
size_t EMUFILE::write_floatLE(float floatValueIn)
{
return write_32LE(float_to_u32(floatValueIn));
}
size_t EMUFILE::read_floatLE(float &floatValueOut)
{
u32 temp = 0;
size_t ret = read_32LE(temp);
floatValueOut = u32_to_float(temp);
return ret;
}
float EMUFILE::read_floatLE()
{
float value = 0.0f;
read_floatLE(value);
return value;
}
size_t EMUFILE::write_bool32(bool boolValueIn)
{
return write_32LE((boolValueIn) ? 1 : 0);
}
size_t EMUFILE::read_bool32(bool &boolValueOut)
{
u32 temp = 0;
size_t ret = read_32LE(temp);
if (ret != 0)
boolValueOut = (temp != 0);
return ret;
}
bool EMUFILE::read_bool32()
{
bool value = false;
read_bool32(value);
return value;
}
size_t EMUFILE::write_bool8(bool boolValueIn)
{
return write_u8((boolValueIn) ? 1 : 0);
}
size_t EMUFILE::read_bool8(bool &boolValueOut)
{
u8 temp = 0;
size_t ret = read_u8(temp);
if (ret != 0)
boolValueOut = (temp != 0);
return ret;
}
bool EMUFILE::read_bool8()
{
bool value = false;
read_bool8(value);
return value;
}
size_t EMUFILE::write_buffer(std::vector<u8> &vec)
{
u32 size = (u32)vec.size();
write_32LE(size);
if (size > 0)
fwrite(&vec[0],size);
return (size + 4);
}
size_t EMUFILE::read_buffer(std::vector<u8> &vec)
{
u32 size = 0;
if (read_32LE(size) != 1)
return 0;
vec.resize(size);
if (size > 0)
{
size_t ret = fread(&vec[0],size);
if (ret != size)
return 0;
}
return 1;
}
size_t EMUFILE::write_MemoryStream(EMUFILE_MEMORY &ms)
{
u32 size = (u32)ms.size();
write_32LE(size);
if (size > 0)
{
std::vector<u8> *vec = ms.get_vec();
fwrite(&vec->at(0),size);
}
return (size + 4);
}
size_t EMUFILE::read_MemoryStream(EMUFILE_MEMORY &ms)
{
u32 size = 0;
if (read_32LE(size) != 1)
return 0;
if (size > 0)
{
std::vector<u8> vec(size);
size_t ret = fread(&vec[0],size);
if (ret != size)
return 0;
ms.fwrite(&vec[0],size);
}
return 1;
}

View File

@ -1,369 +0,0 @@
/*
The MIT License
Copyright (C) 2009-2017 DeSmuME team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
//don't use emufile for files bigger than 2GB! you have been warned! some day this will be fixed.
#ifndef EMUFILE_H
#define EMUFILE_H
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
#include <string>
#include <stdarg.h>
#include "types.h"
#ifdef HOST_WINDOWS
#include <io.h>
#else
#include <unistd.h>
#endif
class EMUFILE_MEMORY;
class EMUFILE {
protected:
bool failbit;
public:
EMUFILE()
: failbit(false)
{}
//returns a new EMUFILE which is guranteed to be in memory. the EMUFILE you call this on may be deleted. use the returned EMUFILE in its place
virtual EMUFILE* memwrap() = 0;
virtual ~EMUFILE() {}
static bool readAllBytes(std::vector<u8>* buf, const std::string& fname);
bool fail(bool unset=false) { bool ret = failbit; if(unset) unfail(); return ret; }
void unfail() { failbit=false; }
bool eof() { return size()==ftell(); }
size_t fread(const void *ptr, size_t bytes){
return _fread(ptr,bytes);
}
void unget() { fseek(-1,SEEK_CUR); }
//virtuals
public:
virtual FILE *get_fp() = 0;
virtual int fprintf(const char *format, ...) = 0;
virtual int fgetc() = 0;
virtual int fputc(int c) = 0;
virtual size_t _fread(const void *ptr, size_t bytes) = 0;
virtual size_t fwrite(const void *ptr, size_t bytes) = 0;
size_t write_64LE(s64 s64valueIn);
size_t write_64LE(u64 u64valueIn);
size_t read_64LE(s64 &s64valueOut);
size_t read_64LE(u64 &u64valueOut);
s64 read_s64LE();
u64 read_u64LE();
size_t write_32LE(s32 s32valueIn);
size_t write_32LE(u32 u32valueIn);
size_t read_32LE(s32 &s32valueOut);
size_t read_32LE(u32 &u32valueOut);
s32 read_s32LE();
u32 read_u32LE();
size_t write_16LE(s16 s16valueIn);
size_t write_16LE(u16 u16valueIn);
size_t read_16LE(s16 &s16valueOut);
size_t read_16LE(u16 &u16valueOut);
s16 read_s16LE();
u16 read_u16LE();
size_t write_u8(u8 u8valueIn);
size_t read_u8(u8 &u8valueOut);
u8 read_u8();
size_t write_bool32(bool boolValueIn);
size_t read_bool32(bool &boolValueOut);
bool read_bool32();
size_t write_bool8(bool boolValueIn);
size_t read_bool8(bool &boolValueOut);
bool read_bool8();
size_t write_doubleLE(double doubleValueIn);
size_t read_doubleLE(double &doubleValueOut);
double read_doubleLE();
size_t write_floatLE(float floatValueIn);
size_t read_floatLE(float &floatValueOut);
float read_floatLE();
size_t write_buffer(std::vector<u8> &vec);
size_t read_buffer(std::vector<u8> &vec);
size_t write_MemoryStream(EMUFILE_MEMORY &ms);
size_t read_MemoryStream(EMUFILE_MEMORY &ms);
virtual int fseek(int offset, int origin) = 0;
virtual int ftell() = 0;
virtual int size() = 0;
virtual void fflush() = 0;
virtual void truncate(s32 length) = 0;
};
//todo - handle read-only specially?
class EMUFILE_MEMORY : public EMUFILE {
protected:
std::vector<u8> *vec;
bool ownvec;
s32 pos, len;
void reserve(u32 amt) {
if(vec->size() < amt)
vec->resize(amt);
}
public:
EMUFILE_MEMORY(std::vector<u8> *underlying) : vec(underlying), ownvec(false), pos(0), len((s32)underlying->size()) { }
EMUFILE_MEMORY(u32 preallocate) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) {
vec->resize(preallocate);
len = preallocate;
}
EMUFILE_MEMORY() : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) { vec->reserve(1024); }
EMUFILE_MEMORY(void* buf, s32 size) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(size) {
vec->resize(size);
if(size != 0)
memcpy(&vec->front(),buf,size);
}
~EMUFILE_MEMORY() {
if(ownvec) delete vec;
}
virtual EMUFILE* memwrap();
virtual void truncate(s32 length)
{
vec->resize(length);
len = length;
if(pos>length) pos=length;
}
u8* buf() {
if(size()==0) reserve(1);
return &(*vec)[0];
}
std::vector<u8>* get_vec() const { return vec; };
virtual FILE *get_fp() { return NULL; }
virtual int fprintf(const char *format, ...) {
va_list argptr;
va_start(argptr, format);
//we dont generate straight into the buffer because it will null terminate (one more byte than we want)
int amt = vsnprintf(0,0,format,argptr);
char* tempbuf = new char[amt+1];
va_end(argptr);
va_start(argptr, format);
vsprintf(tempbuf,format,argptr);
fwrite(tempbuf,amt);
delete[] tempbuf;
va_end(argptr);
return amt;
};
virtual int fgetc() {
u8 temp;
//need an optimized codepath
//if(_fread(&temp,1) != 1)
// return EOF;
//else return temp;
u32 remain = len-pos;
if(remain<1) {
failbit = true;
return -1;
}
temp = buf()[pos];
pos++;
return temp;
}
virtual int fputc(int c) {
u8 temp = (u8)c;
//TODO
//if(fwrite(&temp,1)!=1) return EOF;
fwrite(&temp,1);
return 0;
}
virtual size_t _fread(const void *ptr, size_t bytes);
virtual size_t fwrite(const void *ptr, size_t bytes){
reserve(pos+(s32)bytes);
memcpy(buf()+pos,ptr,bytes);
pos += (s32)bytes;
len = std::max(pos,len);
return bytes;
}
virtual int fseek(int offset, int origin){
//work differently for read-only...?
switch(origin) {
case SEEK_SET:
pos = offset;
break;
case SEEK_CUR:
pos += offset;
break;
case SEEK_END:
pos = size()+offset;
break;
default:
assert(false);
}
reserve(pos);
return 0;
}
virtual int ftell() {
return pos;
}
virtual void fflush() {}
void trim()
{
vec->resize(len);
}
virtual int size() { return (int)len; }
};
class EMUFILE_FILE : public EMUFILE {
protected:
FILE* fp;
std::string fname;
char mode[16];
long mFilePosition;
bool mPositionCacheEnabled;
enum eCondition
{
eCondition_Clean,
eCondition_Unknown,
eCondition_Read,
eCondition_Write
} mCondition;
private:
void open(const char* fname, const char* mode)
{
mPositionCacheEnabled = false;
mCondition = eCondition_Clean;
mFilePosition = 0;
fp = fopen(fname,mode);
if(!fp)
failbit = true;
this->fname = fname;
strcpy(this->mode,mode);
}
public:
EMUFILE_FILE(const std::string& fname, const char* mode) { open(fname.c_str(),mode); }
EMUFILE_FILE(const char* fname, const char* mode) { open(fname,mode); }
void EnablePositionCache();
virtual ~EMUFILE_FILE() {
if(NULL != fp)
fclose(fp);
}
virtual FILE *get_fp() {
return fp;
}
virtual EMUFILE* memwrap();
bool is_open() { return fp != NULL; }
void DemandCondition(eCondition cond);
virtual void truncate(s32 length);
virtual int fprintf(const char *format, ...) {
va_list argptr;
va_start(argptr, format);
int ret = ::vfprintf(fp, format, argptr);
va_end(argptr);
return ret;
};
virtual int fgetc() {
return ::fgetc(fp);
}
virtual int fputc(int c) {
return ::fputc(c, fp);
}
virtual size_t _fread(const void *ptr, size_t bytes);
virtual size_t fwrite(const void *ptr, size_t bytes);
virtual int fseek(int offset, int origin);
virtual int ftell();
virtual int size() {
int oldpos = ftell();
fseek(0,SEEK_END);
int len = ftell();
fseek(oldpos,SEEK_SET);
return len;
}
virtual void fflush() {
::fflush(fp);
}
};
#endif

View File

@ -1,133 +0,0 @@
/*
Copyright (C) 2009-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "encrypt.h"
#include "armcpu.h"
#include "MMU.h"
#include "registers.h"
//TODO - a lot of redundant code (maybe?) with utils/decrypt.cpp
//we should try unifying all that.
//TODO - endian unsafeness in here... dont like the way these take u32. maybe it makes sense and the user is genuinely supposed to present data in units of u32
//================================================================================== KEY1
#define DWNUM(i) ((i) >> 2)
void _KEY1::init(u32 idcode, u8 level, u8 modulo)
{
memcpy(keyBuf, keyBufPtr, 0x1048);
keyCode[0] = idcode;
keyCode[1] = idcode >> 1;
keyCode[2] = idcode << 1;
if (level >= 1) // first apply (always)
applyKeycode(modulo);
if (level >= 2) // second apply (optional)
applyKeycode(modulo);
keyCode[1] <<= 1;
keyCode[2] >>= 1;
if (level >= 3) // third apply (optional)
applyKeycode(modulo);
}
void _KEY1::applyKeycode(u8 modulo)
{
encrypt(&keyCode[1]);
encrypt(&keyCode[0]);
u32 scratch[2] = {0};
for (u32 i = 0; i <= 0x44; i += 4) // xor with reversed byte-order (bswap)
keyBuf[DWNUM(i)] ^= bswap32(keyCode[DWNUM(i % modulo)]);
for (u32 i = 0; i <= 0x1040; i += 8)
{
encrypt(scratch); // encrypt S (64bit) by keybuf
keyBuf[DWNUM(i)] = scratch[1]; // write S to keybuf (first upper 32bit)
keyBuf[DWNUM(i+4)] = scratch[0]; // write S to keybuf (then lower 32bit)
}
}
void _KEY1::decrypt(u32 *ptr)
{
u32 y = ptr[0];
u32 x = ptr[1];
for (u32 i = 0x11; i >= 0x02; i--)
{
u32 z = keyBuf[i] ^ x;
x = keyBuf[DWNUM(0x048 + (((z >> 24) & 0xFF) << 2))];
x = keyBuf[DWNUM(0x448 + (((z >> 16) & 0xFF) << 2))] + x;
x = keyBuf[DWNUM(0x848 + (((z >> 8) & 0xFF) << 2))] ^ x;
x = keyBuf[DWNUM(0xC48 + (((z >> 0) & 0xFF) << 2))] + x;
x = y ^ x;
y = z;
}
ptr[0] = x ^ keyBuf[DWNUM(0x04)];
ptr[1] = y ^ keyBuf[DWNUM(0x00)];
}
void _KEY1::encrypt(u32 *ptr)
{
u32 y = ptr[0];
u32 x = ptr[1];
for (u32 i = 0x00; i <= 0x0F; i++)
{
u32 z = keyBuf[i] ^ x;
x = keyBuf[DWNUM(0x048 + (((z >> 24) & 0xFF) << 2))];
x = keyBuf[DWNUM(0x448 + (((z >> 16) & 0xFF) << 2))] + x;
x = keyBuf[DWNUM(0x848 + (((z >> 8) & 0xFF) << 2))] ^ x;
x = keyBuf[DWNUM(0xC48 + (((z >> 0) & 0xFF) << 2))] + x;
x = y ^ x;
y = z;
}
ptr[0] = x ^ keyBuf[DWNUM(0x40)];
ptr[1] = y ^ keyBuf[DWNUM(0x44)];
}
#undef DWNUM
//================================================================================== KEY2
u64 _KEY2::bitsReverse39(u64 key)
{
u64 tmp = 0;
for (u32 i = 0; i < 39; i++)
tmp |= ((key >> i) & 1) << (38 - i);
return tmp;
}
void _KEY2::applySeed(u8 PROCNUM)
{
u64 tmp = (MMU_read8(PROCNUM, REG_ENCSEED0H) & 0xFF);
seed0 = MMU_read32(PROCNUM, REG_ENCSEED0L) | (tmp << 32);
tmp = (MMU_read8(PROCNUM, REG_ENCSEED1H) & 0xFF);
seed1 = MMU_read32(PROCNUM, REG_ENCSEED1L) | (tmp << 32);
x = bitsReverse39(seed0);
y = bitsReverse39(seed1);
//printf("ARM%c: set KEY2 seed0 to %010llX (reverse %010llX)\n", PROCNUM?'7':'9', seed0, x);
//printf("ARM%c: set KEY2 seed1 to %010llX (reverse %010llX)\n", PROCNUM?'7':'9', seed1, y);
}
u8 _KEY2::apply(u8 data)
{
x = (((x >> 5) ^ (x >> 17) ^ (x >> 18) ^ (x >> 31)) & 0xFF) + (x << 8);
y = (((y >> 5) ^ (y >> 23) ^ (y >> 18) ^ (y >> 31)) & 0xFF) + (y << 8);
return ((data ^ x ^ y) & 0xFF);
}

Some files were not shown because too many files have changed in this diff Show More