s
This commit is contained in:
parent
a4773a19e4
commit
c8d7993a2f
Binary file not shown.
@ -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
@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:DSDeltaCore.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
Binary file not shown.
@ -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
@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
Binary file not shown.
@ -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);
|
||||
@ -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";
|
||||
@ -1,6 +0,0 @@
|
||||
# DeSmuME
|
||||
[](https://ci.appveyor.com/project/zeromus/desmume)
|
||||
|
||||
DeSmuME is a Nintendo DS emulator.
|
||||
|
||||
http://desmume.org
|
||||
@ -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
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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
|
||||
@ -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
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
@ -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
|
||||
@ -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
@ -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
@ -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
@ -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
|
||||
@ -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
|
||||
@ -1,3 +0,0 @@
|
||||
#ifndef __GNUC__
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
@ -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;
|
||||
}
|
||||
@ -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
@ -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
|
||||
@ -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(); }
|
||||
@ -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(); }
|
||||
@ -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(); }
|
||||
@ -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(); }
|
||||
@ -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(); }
|
||||
@ -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(); }
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -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();
|
||||
}
|
||||
@ -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
|
||||
@ -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(); }
|
||||
@ -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(); }
|
||||
@ -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(); }
|
||||
@ -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;
|
||||
}
|
||||
@ -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(§or_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(); }
|
||||
@ -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(); }
|
||||
@ -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(); }
|
||||
@ -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(); }
|
||||
@ -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;
|
||||
}
|
||||
@ -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
@ -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
|
||||
@ -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
|
||||
};
|
||||
@ -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
@ -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
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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(®ionWriteMask_USR[0], 0, sizeof(regionWriteMask_USR));
|
||||
memset(®ionWriteMask_SYS[0], 0, sizeof(regionWriteMask_SYS));
|
||||
memset(®ionReadMask_USR[0], 0, sizeof(regionReadMask_USR));
|
||||
memset(®ionReadMask_SYS[0], 0, sizeof(regionReadMask_SYS));
|
||||
memset(®ionExecuteMask_USR[0], 0, sizeof(regionExecuteMask_USR));
|
||||
memset(®ionExecuteMask_SYS[0], 0, sizeof(regionExecuteMask_SYS));
|
||||
memset(®ionWriteSet_USR[0], 0, sizeof(regionWriteSet_USR));
|
||||
memset(®ionWriteSet_SYS[0], 0, sizeof(regionWriteSet_SYS));
|
||||
memset(®ionReadSet_USR[0], 0, sizeof(regionReadSet_USR));
|
||||
memset(®ionReadSet_SYS[0], 0, sizeof(regionReadSet_SYS));
|
||||
memset(®ionExecuteSet_USR[0], 0, sizeof(regionExecuteSet_USR));
|
||||
memset(®ionExecuteSet_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__*/
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
@ -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_
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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
Loading…
Reference in New Issue
Block a user