Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b1495d48b | |||
| c0e0b5580c | |||
| d2dc097eff | |||
| 4fad1f3005 | |||
| b10c052626 | |||
| 652dd3ec0a | |||
| f31480c0be | |||
| 61284bed2b | |||
| 869c2f6680 | |||
| 7b86e8c494 | |||
| 1f4dce126a |
Binary file not shown.
+3
-3
@@ -3,7 +3,7 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
@@ -19,7 +19,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.60</string>
|
||||
<string>1.62.3</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>OEGameCoreController</string>
|
||||
<key>OEGameCoreClass</key>
|
||||
@@ -70,7 +70,7 @@
|
||||
<key>OEGameCorePlayerCount</key>
|
||||
<string>8</string>
|
||||
<key>OEProjectURL</key>
|
||||
<string>http://www.snes9x.com/</string>
|
||||
<string>https://github.com/snes9xgit/snes9x</string>
|
||||
<key>OESystemIdentifiers</key>
|
||||
<array>
|
||||
<string>openemu.system.snes</string>
|
||||
|
||||
@@ -32,8 +32,12 @@
|
||||
87431C061B02F20700F82158 /* stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 87431C041B02F20700F82158 /* stream.cpp */; };
|
||||
8769DC9D20D19CDC005ABC18 /* bml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8769DC9C20D19CDB005ABC18 /* bml.cpp */; };
|
||||
8769DCA020D19D1C005ABC18 /* sha256.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8769DC9E20D19D1C005ABC18 /* sha256.cpp */; };
|
||||
87709EEC294EDD590084AEE0 /* tileimpl-n1x1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 87709EE9294EDD580084AEE0 /* tileimpl-n1x1.cpp */; };
|
||||
87709EED294EDD590084AEE0 /* tileimpl-h2x1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 87709EEA294EDD580084AEE0 /* tileimpl-h2x1.cpp */; };
|
||||
87709EEE294EDD590084AEE0 /* tileimpl-n2x1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 87709EEB294EDD580084AEE0 /* tileimpl-n2x1.cpp */; };
|
||||
8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
|
||||
8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
|
||||
8F6CC7A029FD51E2006C7D59 /* fscompat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F6CC79E29FD51E2006C7D59 /* fscompat.cpp */; };
|
||||
94790D7A14C0C46900B30798 /* apu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94790CDC14C0C46900B30798 /* apu.cpp */; };
|
||||
94790D8114C0C46900B30798 /* bsx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94790CF014C0C46900B30798 /* bsx.cpp */; };
|
||||
94790D8214C0C46900B30798 /* c4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94790CF214C0C46900B30798 /* c4.cpp */; };
|
||||
@@ -105,10 +109,10 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
|
||||
089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
|
||||
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||
089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
089C167EFE841241C02AAC07 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
3DA5C31714DCF0180029660B /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
|
||||
8233FF2814C1E1B100FC4547 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; };
|
||||
8233FF2A14C1E1C100FC4547 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
|
||||
@@ -149,9 +153,14 @@
|
||||
8769DC9C20D19CDB005ABC18 /* bml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bml.cpp; path = src/bml.cpp; sourceTree = "<group>"; };
|
||||
8769DC9E20D19D1C005ABC18 /* sha256.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sha256.cpp; path = src/sha256.cpp; sourceTree = "<group>"; };
|
||||
8769DC9F20D19D1C005ABC18 /* sha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sha256.h; path = src/sha256.h; sourceTree = "<group>"; };
|
||||
87709EE8294EDD580084AEE0 /* tileimpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tileimpl.h; path = src/tileimpl.h; sourceTree = "<group>"; };
|
||||
87709EE9294EDD580084AEE0 /* tileimpl-n1x1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "tileimpl-n1x1.cpp"; path = "src/tileimpl-n1x1.cpp"; sourceTree = "<group>"; };
|
||||
87709EEA294EDD580084AEE0 /* tileimpl-h2x1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "tileimpl-h2x1.cpp"; path = "src/tileimpl-h2x1.cpp"; sourceTree = "<group>"; };
|
||||
87709EEB294EDD580084AEE0 /* tileimpl-n2x1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "tileimpl-n2x1.cpp"; path = "src/tileimpl-n2x1.cpp"; sourceTree = "<group>"; };
|
||||
8D5B49B6048680CD000E48DA /* SNES9x.oecoreplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SNES9x.oecoreplugin; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
942597D5151470C00074E3A3 /* OpenEmuBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenEmuBase.framework; path = ../OpenEmu/build/Release/OpenEmuBase.framework; sourceTree = "<group>"; };
|
||||
8F6CC79E29FD51E2006C7D59 /* fscompat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fscompat.cpp; path = src/fscompat.cpp; sourceTree = "<group>"; };
|
||||
8F6CC79F29FD51E2006C7D59 /* fscompat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fscompat.h; path = src/fscompat.h; sourceTree = "<group>"; };
|
||||
94790CDA14C0C46900B30798 /* 65c816.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = 65c816.h; path = src/65c816.h; sourceTree = "<group>"; };
|
||||
94790CDC14C0C46900B30798 /* apu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apu.cpp; sourceTree = "<group>"; };
|
||||
94790CDD14C0C46900B30798 /* apu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apu.h; sourceTree = "<group>"; };
|
||||
@@ -248,9 +257,9 @@
|
||||
94790D6914C0C46900B30798 /* srtcemu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = srtcemu.h; path = src/srtcemu.h; sourceTree = "<group>"; };
|
||||
94790D6A14C0C46900B30798 /* tile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tile.cpp; path = src/tile.cpp; sourceTree = "<group>"; };
|
||||
94790D6B14C0C46900B30798 /* tile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tile.h; path = src/tile.h; sourceTree = "<group>"; };
|
||||
C6480FFA1364B1CF0094FA33 /* OESNESSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OESNESSystemResponderClient.h; path = ../OpenEmu/SuperNES/OESNESSystemResponderClient.h; sourceTree = "<group>"; };
|
||||
C6480FFA1364B1CF0094FA33 /* OESNESSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OESNESSystemResponderClient.h; path = ../OpenEmu/SystemPlugins/SuperNES/OESNESSystemResponderClient.h; sourceTree = "<group>"; };
|
||||
C6D120FA1711314D00E868A8 /* OpenEmuBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OpenEmuBase.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
|
||||
D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -317,7 +326,6 @@
|
||||
1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
942597D5151470C00074E3A3 /* OpenEmuBase.framework */,
|
||||
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */,
|
||||
);
|
||||
name = "Linked Frameworks";
|
||||
@@ -389,6 +397,8 @@
|
||||
94790D0F14C0C46900B30798 /* dsp3.cpp */,
|
||||
94790D1014C0C46900B30798 /* dsp4.cpp */,
|
||||
94790D1114C0C46900B30798 /* font.h */,
|
||||
8F6CC79E29FD51E2006C7D59 /* fscompat.cpp */,
|
||||
8F6CC79F29FD51E2006C7D59 /* fscompat.h */,
|
||||
94790D1214C0C46900B30798 /* fxdbg.cpp */,
|
||||
94790D1314C0C46900B30798 /* fxemu.cpp */,
|
||||
94790D1414C0C46900B30798 /* fxemu.h */,
|
||||
@@ -454,6 +464,10 @@
|
||||
87431C051B02F20700F82158 /* stream.h */,
|
||||
94790D6A14C0C46900B30798 /* tile.cpp */,
|
||||
94790D6B14C0C46900B30798 /* tile.h */,
|
||||
87709EEA294EDD580084AEE0 /* tileimpl-h2x1.cpp */,
|
||||
87709EE9294EDD580084AEE0 /* tileimpl-n1x1.cpp */,
|
||||
87709EEB294EDD580084AEE0 /* tileimpl-n2x1.cpp */,
|
||||
87709EE8294EDD580084AEE0 /* tileimpl.h */,
|
||||
);
|
||||
name = core;
|
||||
sourceTree = "<group>";
|
||||
@@ -570,15 +584,13 @@
|
||||
089C1669FE841209C02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 0830;
|
||||
};
|
||||
buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "SNES9x" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
English,
|
||||
en,
|
||||
);
|
||||
mainGroup = 089C166AFE841209C02AAC07 /* SNES9x */;
|
||||
@@ -661,6 +673,7 @@
|
||||
94790DA714C0C46900B30798 /* netplay.cpp in Sources */,
|
||||
94790DA814C0C46900B30798 /* obc1.cpp in Sources */,
|
||||
94790DA914C0C46900B30798 /* ppu.cpp in Sources */,
|
||||
8F6CC7A029FD51E2006C7D59 /* fscompat.cpp in Sources */,
|
||||
87431C061B02F20700F82158 /* stream.cpp in Sources */,
|
||||
94790DAB14C0C46900B30798 /* sa1.cpp in Sources */,
|
||||
94790DAC14C0C46900B30798 /* sa1cpu.cpp in Sources */,
|
||||
@@ -677,6 +690,9 @@
|
||||
94790DB714C0C46900B30798 /* spc7110.cpp in Sources */,
|
||||
94790DBA14C0C46900B30798 /* srtc.cpp in Sources */,
|
||||
94790DBC14C0C46900B30798 /* tile.cpp in Sources */,
|
||||
87709EED294EDD590084AEE0 /* tileimpl-h2x1.cpp in Sources */,
|
||||
87709EEC294EDD590084AEE0 /* tileimpl-n1x1.cpp in Sources */,
|
||||
87709EEE294EDD590084AEE0 /* tileimpl-n2x1.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -694,7 +710,7 @@
|
||||
089C167DFE841241C02AAC07 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
089C167EFE841241C02AAC07 /* English */,
|
||||
089C167EFE841241C02AAC07 /* en */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
@@ -706,6 +722,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
@@ -735,6 +752,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GCC_STRICT_ALIASING = YES;
|
||||
@@ -792,8 +810,8 @@
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
LLVM_LTO = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
VALID_ARCHS = x86_64;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -827,7 +845,6 @@
|
||||
LLVM_LTO = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
SDKROOT = macosx;
|
||||
VALID_ARCHS = x86_64;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
+17
-73
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2018, OpenEmu Team
|
||||
Copyright (c) 2022, OpenEmu Team
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -54,6 +54,7 @@
|
||||
{
|
||||
uint16_t *_indirectVideoBuffer;
|
||||
uint16_t *_soundBuffer;
|
||||
uint16_t *_soundBufferCurrent;
|
||||
NSURL *_romURL;
|
||||
NSMutableDictionary<NSString *, NSNumber *> *_cheatList;
|
||||
}
|
||||
@@ -100,9 +101,8 @@ static __weak SNESGameCore *_current;
|
||||
Settings.SoundInputRate = 32040;
|
||||
Settings.DynamicRateControl = false;
|
||||
Settings.DynamicRateLimit = 5;
|
||||
Settings.SupportHiRes = true;
|
||||
Settings.Transparency = true;
|
||||
GFX.InfoString = NULL;
|
||||
GFX.InfoString.clear();
|
||||
GFX.InfoStringTimeout = 0;
|
||||
Settings.DontSaveOopsSnapshot = true;
|
||||
Settings.NoPatch = true;
|
||||
@@ -122,7 +122,6 @@ static __weak SNESGameCore *_current;
|
||||
|
||||
_indirectVideoBuffer = (uint16_t *)malloc(MAX_SNES_WIDTH * MAX_SNES_HEIGHT * sizeof(uint16_t));
|
||||
|
||||
GFX.Pitch = 512 * 2;
|
||||
GFX.Screen = _indirectVideoBuffer;
|
||||
|
||||
S9xUnmapAllControls();
|
||||
@@ -168,7 +167,9 @@ static __weak SNESGameCore *_current;
|
||||
NSLocalizedRecoverySuggestionErrorKey : @"To run this Satellaview game you need: \"BS-X.bin\"\n\nObtain this file, drag and drop onto the game library window and try again.\n\nFor more information visit: https://github.com/OpenEmu/OpenEmu/wiki/User-guide:-BIOS-files"
|
||||
}];
|
||||
|
||||
*error = outErr;
|
||||
if (error) {
|
||||
*error = outErr;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
@@ -641,7 +642,10 @@ static __weak SNESGameCore *_current;
|
||||
- (void)executeFrame
|
||||
{
|
||||
IPPU.RenderThisFrame = true;
|
||||
_soundBufferCurrent = _soundBuffer;
|
||||
S9xMainLoop();
|
||||
NSUInteger samples = _soundBufferCurrent - _soundBuffer;
|
||||
[[self audioBufferAtIndex:0] write:_soundBuffer maxLength:samples * 2];
|
||||
}
|
||||
|
||||
- (void)setupEmulation
|
||||
@@ -660,7 +664,7 @@ static __weak SNESGameCore *_current;
|
||||
- (void)stopEmulation
|
||||
{
|
||||
// Save SRAM
|
||||
NSURL *url = [NSURL fileURLWithPath:@(Memory.ROMFilename)];
|
||||
NSURL *url = [NSURL fileURLWithPath:@(Memory.ROMFilename.c_str())];
|
||||
NSString *extensionlessFilename = url.lastPathComponent.stringByDeletingPathExtension;
|
||||
NSURL *batterySavesDirectory = [NSURL fileURLWithPath:self.batterySavesDirectoryPath];
|
||||
NSURL *saveFileURL = [batterySavesDirectory URLByAppendingPathComponent:[extensionlessFilename stringByAppendingPathExtension:@"sav"]];
|
||||
@@ -718,8 +722,8 @@ static void FinalizeSamplesAudioCallback(void *context)
|
||||
- (void)finalizeAudioSamples
|
||||
{
|
||||
int samples = S9xGetSampleCount();
|
||||
S9xMixSamples((uint8_t *)_soundBuffer, samples);
|
||||
[[self ringBufferAtIndex:0] write:_soundBuffer maxLength:samples * 2];
|
||||
S9xMixSamples((uint8_t *)_soundBufferCurrent, samples);
|
||||
_soundBufferCurrent += samples;
|
||||
}
|
||||
|
||||
- (double)audioSampleRate
|
||||
@@ -901,7 +905,7 @@ NSString *SNESEmulatorKeys[] = { @"Up", @"Down", @"Left", @"Right", @"A", @"B",
|
||||
const char *cheatCode = [singleCode stringByReplacingOccurrencesOfString:@":" withString:@""].UTF8String;
|
||||
|
||||
S9xAddCheatGroup("OpenEmu", cheatCode);
|
||||
S9xEnableCheatGroup(Cheat.g.size () - 1);
|
||||
S9xEnableCheatGroup(Cheat.group.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -929,42 +933,7 @@ void S9xMessage(int type, int number, const char *message)
|
||||
NSLog(@"[Snes9x] %s", message);
|
||||
}
|
||||
|
||||
void _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext)
|
||||
{
|
||||
// This function is mostly used for various Snes9x generated snapshots (functionality that belongs in the frontend instead), but defined anyway
|
||||
NSString *nsPath = @(path);
|
||||
|
||||
drive[0] = '\0';
|
||||
|
||||
NSString *extension = nsPath.pathExtension;
|
||||
NSArray *components = nsPath.pathComponents;
|
||||
NSArray *dirComponents = [nsPath.pathComponents subarrayWithRange:NSMakeRange(0, components.count - 1)];
|
||||
NSString *fileName = [nsPath.lastPathComponent stringByDeletingPathExtension];
|
||||
NSString *directory = [NSString pathWithComponents:dirComponents];
|
||||
|
||||
strcpy(dir, directory.UTF8String);
|
||||
strcpy(fname, fileName.UTF8String);
|
||||
strcpy(ext, extension.UTF8String);
|
||||
}
|
||||
|
||||
void _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext)
|
||||
{
|
||||
// This function is mostly used for Snes9x internal soft patching, but defined anyway
|
||||
#pragma unused (drive)
|
||||
|
||||
NSString *directory = @(dir);
|
||||
NSString *fileName = @(fname);
|
||||
NSString *extension = @(ext);
|
||||
|
||||
fileName = [fileName stringByAppendingPathExtension:extension];
|
||||
|
||||
NSString *fullPath = [directory stringByAppendingPathComponent:fileName];
|
||||
NSURL *fullURL = [NSURL fileURLWithPath:fullPath];
|
||||
|
||||
strcpy(path, fullURL.fileSystemRepresentation);
|
||||
}
|
||||
|
||||
const char *S9xGetDirectory(enum s9x_getdirtype dirtype)
|
||||
std::string S9xGetDirectory(enum s9x_getdirtype dirtype)
|
||||
{
|
||||
// We don't seem to use this function, but defined anyway
|
||||
NSURL *batterySavesDirectory = [NSURL fileURLWithPath:_current.batterySavesDirectoryPath];
|
||||
@@ -976,7 +945,7 @@ const char *S9xGetDirectory(enum s9x_getdirtype dirtype)
|
||||
case SRAM_DIR: return batterySavesDirectory.fileSystemRepresentation; break;
|
||||
case BIOS_DIR: return biosDirectoryURL.fileSystemRepresentation; break;
|
||||
case SAT_DIR: return biosDirectoryURL.fileSystemRepresentation; break;
|
||||
default: return NULL; break;
|
||||
default: return ""; break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1013,35 +982,14 @@ unsigned char S9xContinueUpdate(int width, int height)
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *S9xBasename(const char *filename)
|
||||
{
|
||||
// Called by S9xFreezeGame/S9xUnfreezeGame -- useless for us
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *S9xStringInput(const char *message)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *S9xChooseMovieFilename(bool8 read_only)
|
||||
std::string S9xGetFilenameInc(std::string, enum s9x_getdirtype)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *S9xChooseFilename(bool8 read_only)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *S9xGetFilename(const char *extension, enum s9x_getdirtype dirtype)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *S9xGetFilenameInc(const char *, enum s9x_getdirtype)
|
||||
{
|
||||
return NULL;
|
||||
return "";
|
||||
}
|
||||
|
||||
bool S9xPollButton(uint32 id, bool *pressed)
|
||||
@@ -1079,10 +1027,6 @@ void S9xHandlePortCommand(s9xcommand_t cmd, int16 data1, int16 data2)
|
||||
{
|
||||
}
|
||||
|
||||
void S9xSetPalette()
|
||||
{
|
||||
}
|
||||
|
||||
void S9xExtraUsage()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
Executable → Regular
Executable → Regular
+6
-4
@@ -21,7 +21,7 @@
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2019 BearOso,
|
||||
(c) Copyright 2009 - 2023 BearOso,
|
||||
OV2
|
||||
|
||||
(c) Copyright 2017 qwertymodo
|
||||
@@ -139,7 +139,7 @@
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2019 BearOso
|
||||
(c) Copyright 2004 - 2023 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@@ -147,11 +147,13 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2019 OV2
|
||||
(c) Copyright 2009 - 2023 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
Original Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2011 zones
|
||||
New MacOS GUI code
|
||||
(c) Copyright 2022 - 2023 Michael Donald Buckley
|
||||
|
||||
Libretro port
|
||||
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
|
||||
|
||||
Executable → Regular
+54
-91
@@ -5,6 +5,7 @@
|
||||
\*****************************************************************************/
|
||||
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include "../snes9x.h"
|
||||
#include "apu.h"
|
||||
#include "../msu1.h"
|
||||
@@ -36,10 +37,10 @@ namespace spc {
|
||||
static apu_callback callback = NULL;
|
||||
static void *callback_data = NULL;
|
||||
|
||||
static bool8 sound_in_sync = TRUE;
|
||||
static bool8 sound_enabled = FALSE;
|
||||
static bool8 sound_in_sync = true;
|
||||
static bool8 sound_enabled = false;
|
||||
|
||||
static Resampler *resampler = NULL;
|
||||
static Resampler resampler;
|
||||
|
||||
static int32 reference_time;
|
||||
static uint32 remainder;
|
||||
@@ -56,9 +57,8 @@ static double dynamic_rate_multiplier = 1.0;
|
||||
|
||||
namespace msu {
|
||||
// Always 16-bit, Stereo; 1.5x dsp buffer to never overflow
|
||||
static Resampler *resampler = NULL;
|
||||
static int16 *resample_buffer = NULL;
|
||||
static int resample_buffer_size = 0;
|
||||
static Resampler resampler;
|
||||
static std::vector<int16_t> resampler_buffer;
|
||||
} // namespace msu
|
||||
|
||||
static void UpdatePlaybackRate(void);
|
||||
@@ -74,44 +74,32 @@ bool8 S9xMixSamples(uint8 *dest, int sample_count)
|
||||
{
|
||||
memset(out, 0, sample_count << 1);
|
||||
S9xClearSamples();
|
||||
spc::sound_in_sync = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
if (spc::resampler.avail() < sample_count)
|
||||
{
|
||||
if (spc::resampler->avail() >= sample_count)
|
||||
{
|
||||
spc::resampler->read((short *)out, sample_count);
|
||||
memset(out, 0, sample_count << 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Settings.MSU1)
|
||||
{
|
||||
if (msu::resampler->avail() >= sample_count)
|
||||
{
|
||||
if (msu::resample_buffer_size < sample_count)
|
||||
{
|
||||
if (msu::resample_buffer)
|
||||
delete[] msu::resample_buffer;
|
||||
msu::resample_buffer = new int16[sample_count];
|
||||
msu::resample_buffer_size = sample_count;
|
||||
}
|
||||
msu::resampler->read(msu::resample_buffer,
|
||||
sample_count);
|
||||
for (int i = 0; i < sample_count; ++i)
|
||||
{
|
||||
int32 mixed = (int32)out[i] + msu::resample_buffer[i];
|
||||
out[i] = ((int16)mixed != mixed) ? (mixed >> 31) ^ 0x7fff : mixed;
|
||||
}
|
||||
}
|
||||
else // should never occur
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
spc::resampler.read((short *)out, sample_count);
|
||||
|
||||
if (Settings.MSU1)
|
||||
{
|
||||
if ((int)msu::resampler_buffer.size() < sample_count)
|
||||
msu::resampler_buffer.resize(sample_count);
|
||||
|
||||
msu::resampler.read(msu::resampler_buffer.data(), sample_count);
|
||||
for (int i = 0; i < sample_count; ++i)
|
||||
{
|
||||
memset(out, 0, sample_count << 1);
|
||||
return false;
|
||||
int32 mixed = (int32)out[i] + msu::resampler_buffer[i];
|
||||
out[i] = ((int16)mixed != mixed) ? (mixed >> 31) ^ 0x7fff : mixed;
|
||||
}
|
||||
}
|
||||
|
||||
if (spc::resampler->space_empty() >= 535 * 2 || !Settings.SoundSync ||
|
||||
if (spc::resampler.space_empty() >= 535 * 2 || !Settings.SoundSync ||
|
||||
Settings.TurboMode || Settings.Mute)
|
||||
spc::sound_in_sync = true;
|
||||
else
|
||||
@@ -122,7 +110,10 @@ bool8 S9xMixSamples(uint8 *dest, int sample_count)
|
||||
|
||||
int S9xGetSampleCount(void)
|
||||
{
|
||||
return spc::resampler->avail();
|
||||
int avail = spc::resampler.avail();
|
||||
if (Settings.MSU1) // return minimum available samples, otherwise we can run into the assert above due to partial sample generation in msu1
|
||||
avail = Resampler::min(avail, msu::resampler.avail());
|
||||
return avail;
|
||||
}
|
||||
|
||||
void S9xLandSamples(void)
|
||||
@@ -130,7 +121,7 @@ void S9xLandSamples(void)
|
||||
if (spc::callback != NULL)
|
||||
spc::callback(spc::callback_data);
|
||||
|
||||
if (spc::resampler->space_empty() >= 535 * 2 || !Settings.SoundSync ||
|
||||
if (spc::resampler.space_empty() >= 535 * 2 || !Settings.SoundSync ||
|
||||
Settings.TurboMode || Settings.Mute)
|
||||
spc::sound_in_sync = true;
|
||||
else
|
||||
@@ -139,15 +130,15 @@ void S9xLandSamples(void)
|
||||
|
||||
void S9xClearSamples(void)
|
||||
{
|
||||
spc::resampler->clear();
|
||||
spc::resampler.clear();
|
||||
if (Settings.MSU1)
|
||||
msu::resampler->clear();
|
||||
msu::resampler.clear();
|
||||
}
|
||||
|
||||
bool8 S9xSyncSound(void)
|
||||
{
|
||||
if (!Settings.SoundSync || spc::sound_in_sync)
|
||||
return (TRUE);
|
||||
return true;
|
||||
|
||||
S9xLandSamples();
|
||||
|
||||
@@ -180,12 +171,12 @@ static void UpdatePlaybackRate(void)
|
||||
time_ratio *= spc::dynamic_rate_multiplier;
|
||||
}
|
||||
|
||||
spc::resampler->time_ratio(time_ratio);
|
||||
spc::resampler.time_ratio(time_ratio);
|
||||
|
||||
if (Settings.MSU1)
|
||||
{
|
||||
time_ratio = (44100.0 / Settings.SoundPlaybackRate) * (Settings.SoundInputRate / 32040.0);
|
||||
msu::resampler->time_ratio(time_ratio);
|
||||
time_ratio = time_ratio * 44100 / 32040;
|
||||
msu::resampler.time_ratio(time_ratio);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,27 +189,11 @@ bool8 S9xInitSound(int buffer_ms)
|
||||
if (requested_buffer_size_samples > buffer_size_samples)
|
||||
buffer_size_samples = requested_buffer_size_samples;
|
||||
|
||||
if (!spc::resampler)
|
||||
{
|
||||
spc::resampler = new Resampler(buffer_size_samples);
|
||||
if (!spc::resampler)
|
||||
return (FALSE);
|
||||
}
|
||||
else
|
||||
spc::resampler->resize(buffer_size_samples);
|
||||
spc::resampler.resize(buffer_size_samples);
|
||||
msu::resampler.resize(buffer_size_samples * 3 / 2);
|
||||
|
||||
|
||||
if (!msu::resampler)
|
||||
{
|
||||
msu::resampler = new Resampler(buffer_size_samples * 3 / 2);
|
||||
if (!msu::resampler)
|
||||
return (FALSE);
|
||||
}
|
||||
else
|
||||
msu::resampler->resize(buffer_size_samples * 3 / 2);
|
||||
|
||||
SNES::dsp.spc_dsp.set_output(spc::resampler);
|
||||
S9xMSU1SetOutput(msu::resampler);
|
||||
SNES::dsp.spc_dsp.set_output(&spc::resampler);
|
||||
S9xMSU1SetOutput(&msu::resampler);
|
||||
|
||||
UpdatePlaybackRate();
|
||||
|
||||
@@ -236,7 +211,7 @@ void S9xSetSoundMute(bool8 mute)
|
||||
{
|
||||
Settings.Mute = mute;
|
||||
if (!spc::sound_enabled)
|
||||
Settings.Mute = TRUE;
|
||||
Settings.Mute = true;
|
||||
}
|
||||
|
||||
void S9xDumpSPCSnapshot(void)
|
||||
@@ -246,33 +221,22 @@ void S9xDumpSPCSnapshot(void)
|
||||
|
||||
static void SPCSnapshotCallback(void)
|
||||
{
|
||||
S9xSPCDump(S9xGetFilenameInc((".spc"), SPC_DIR));
|
||||
S9xSPCDump(S9xGetFilenameInc((".spc"), SPC_DIR).c_str());
|
||||
printf("Dumped key-on triggered spc snapshot.\n");
|
||||
}
|
||||
|
||||
bool8 S9xInitAPU(void)
|
||||
{
|
||||
spc::resampler = NULL;
|
||||
msu::resampler = NULL;
|
||||
spc::resampler.clear();
|
||||
msu::resampler.clear();
|
||||
|
||||
return (TRUE);
|
||||
return true;
|
||||
}
|
||||
|
||||
void S9xDeinitAPU(void)
|
||||
{
|
||||
if (spc::resampler)
|
||||
{
|
||||
delete spc::resampler;
|
||||
spc::resampler = NULL;
|
||||
}
|
||||
|
||||
if (msu::resampler)
|
||||
{
|
||||
delete msu::resampler;
|
||||
msu::resampler = NULL;
|
||||
}
|
||||
|
||||
S9xMSU1DeInit();
|
||||
msu::resampler_buffer.clear();
|
||||
}
|
||||
|
||||
static inline int S9xAPUGetClock(int32 cpucycles)
|
||||
@@ -306,10 +270,10 @@ void S9xAPUSetReferenceTime(int32 cpucycles)
|
||||
|
||||
void S9xAPUExecute(void)
|
||||
{
|
||||
SNES::smp.clock -= S9xAPUGetClock(CPU.Cycles);
|
||||
SNES::smp.enter();
|
||||
|
||||
int cycles = S9xAPUGetClock(CPU.Cycles);
|
||||
spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles);
|
||||
SNES::smp.clock -= cycles;
|
||||
SNES::smp.enter();
|
||||
|
||||
S9xAPUSetReferenceTime(CPU.Cycles);
|
||||
}
|
||||
@@ -319,7 +283,7 @@ void S9xAPUEndScanline(void)
|
||||
S9xAPUExecute();
|
||||
SNES::dsp.synchronize();
|
||||
|
||||
if (spc::resampler->space_filled() >= APU_SAMPLE_BLOCK || !spc::sound_in_sync)
|
||||
if (spc::resampler.space_filled() >= APU_SAMPLE_BLOCK)
|
||||
S9xLandSamples();
|
||||
}
|
||||
|
||||
@@ -386,7 +350,6 @@ void S9xAPULoadState(uint8 *block)
|
||||
|
||||
SNES::smp.load_state(&ptr);
|
||||
SNES::dsp.load_state(&ptr);
|
||||
|
||||
spc::reference_time = SNES::get_le32(ptr);
|
||||
ptr += sizeof(int32);
|
||||
spc::remainder = SNES::get_le32(ptr);
|
||||
@@ -515,9 +478,9 @@ bool8 S9xSPCDump(const char *filename)
|
||||
|
||||
fs = fopen(filename, "wb");
|
||||
if (!fs)
|
||||
return (FALSE);
|
||||
return false;
|
||||
|
||||
S9xSetSoundMute(TRUE);
|
||||
S9xSetSoundMute(true);
|
||||
|
||||
SNES::smp.save_spc(buf);
|
||||
|
||||
@@ -530,7 +493,7 @@ bool8 S9xSPCDump(const char *filename)
|
||||
|
||||
fclose(fs);
|
||||
|
||||
S9xSetSoundMute(FALSE);
|
||||
S9xSetSoundMute(false);
|
||||
|
||||
return (TRUE);
|
||||
return true;
|
||||
}
|
||||
|
||||
Executable → Regular
Executable → Regular
+10
-2
@@ -55,9 +55,11 @@ static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] =
|
||||
|
||||
// Access global DSP register
|
||||
#define REG(n) m.regs [r_##n]
|
||||
#define XREG(n) m.external_regs [r_##n]
|
||||
|
||||
// Access voice DSP register
|
||||
#define VREG(r,n) r [v_##n]
|
||||
#define XVREG(r,n) (m.external_regs + (r - m.regs))[v_##n]
|
||||
|
||||
#define WRITE_SAMPLES( l, r, out ) \
|
||||
{\
|
||||
@@ -751,7 +753,7 @@ MISC_CLOCK( 30 )
|
||||
|
||||
inline VOICE_CLOCK( V1 )
|
||||
{
|
||||
m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4;
|
||||
m.t_dir_addr = (m.t_dir * 0x100 + m.t_srcn * 4) & 0xffff;
|
||||
m.t_srcn = VREG(v->regs,srcn);
|
||||
}
|
||||
inline VOICE_CLOCK( V2 )
|
||||
@@ -927,6 +929,7 @@ inline VOICE_CLOCK( V7 )
|
||||
{
|
||||
// Update ENDX
|
||||
REG(endx) = m.endx_buf;
|
||||
XREG(endx) = m.endx_buf;
|
||||
|
||||
m.envx_buf = v->t_envx_out;
|
||||
}
|
||||
@@ -934,11 +937,13 @@ inline VOICE_CLOCK( V8 )
|
||||
{
|
||||
// Update OUTX
|
||||
VREG(v->regs,outx) = m.outx_buf;
|
||||
XVREG(v->regs,outx) = m.outx_buf;
|
||||
}
|
||||
inline VOICE_CLOCK( V9 )
|
||||
{
|
||||
// Update ENVX
|
||||
VREG(v->regs,envx) = m.envx_buf;
|
||||
XVREG(v->regs,envx) = m.envx_buf;
|
||||
}
|
||||
|
||||
// Most voices do all these in one clock, so make a handy composite
|
||||
@@ -1237,7 +1242,9 @@ void SPC_DSP::soft_reset()
|
||||
|
||||
void SPC_DSP::load( uint8_t const regs [register_count] )
|
||||
{
|
||||
memcpy( m.regs, regs, sizeof m.regs );
|
||||
memcpy( m.external_regs, regs, sizeof m.regs );
|
||||
memset( m.regs, 0, sizeof m.regs);
|
||||
m.regs[r_flg] = 0xE0;
|
||||
memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count );
|
||||
|
||||
// Internal state
|
||||
@@ -1398,6 +1405,7 @@ void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy )
|
||||
SPC_COPY( uint16_t, m.t_echo_ptr );
|
||||
SPC_COPY( uint8_t, m.t_looped );
|
||||
|
||||
copier.copy(m.external_regs, register_count);
|
||||
copier.extra();
|
||||
}
|
||||
#endif
|
||||
|
||||
Executable → Regular
+4
-1
@@ -204,6 +204,8 @@ private:
|
||||
sample_t extra [extra_size];
|
||||
|
||||
uint8_t separate_echo_buffer [0x10000];
|
||||
uint8_t external_regs [register_count];
|
||||
|
||||
};
|
||||
state_t m;
|
||||
|
||||
@@ -260,7 +262,7 @@ inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; }
|
||||
inline int SPC_DSP::read( int addr ) const
|
||||
{
|
||||
assert( (unsigned) addr < register_count );
|
||||
return m.regs [addr];
|
||||
return m.external_regs [addr];
|
||||
}
|
||||
|
||||
inline void SPC_DSP::write( int addr, int data )
|
||||
@@ -268,6 +270,7 @@ inline void SPC_DSP::write( int addr, int data )
|
||||
assert( (unsigned) addr < register_count );
|
||||
|
||||
m.regs [addr] = (uint8_t) data;
|
||||
m.external_regs [addr] = (uint8_t) data;
|
||||
switch ( addr & 0x0F )
|
||||
{
|
||||
case v_envx:
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
-11
@@ -5,17 +5,6 @@
|
||||
#include "../../resampler.h"
|
||||
#include "../../../msu1.h"
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define inline inline
|
||||
#define alwaysinline inline __attribute__((always_inline))
|
||||
#elif defined(_MSC_VER)
|
||||
#define inline inline
|
||||
#define alwaysinline inline __forceinline
|
||||
#else
|
||||
#define inline inline
|
||||
#define alwaysinline inline
|
||||
#endif
|
||||
|
||||
#define debugvirtual
|
||||
|
||||
namespace SNES
|
||||
|
||||
Executable → Regular
+15
-3
@@ -56,12 +56,18 @@ class Resampler
|
||||
return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
|
||||
}
|
||||
|
||||
Resampler()
|
||||
{
|
||||
this->buffer_size = 0;
|
||||
buffer = NULL;
|
||||
r_step = 1.0;
|
||||
}
|
||||
|
||||
Resampler(int num_samples)
|
||||
{
|
||||
this->buffer_size = num_samples;
|
||||
buffer = new int16_t[this->buffer_size];
|
||||
buffer = NULL;
|
||||
resize(num_samples);
|
||||
r_step = 1.0;
|
||||
clear();
|
||||
}
|
||||
|
||||
~Resampler()
|
||||
@@ -77,6 +83,9 @@ class Resampler
|
||||
|
||||
inline void clear(void)
|
||||
{
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
start = 0;
|
||||
size = 0;
|
||||
memset(buffer, 0, buffer_size * 2);
|
||||
@@ -210,6 +219,9 @@ class Resampler
|
||||
{
|
||||
if (buffer)
|
||||
delete[] buffer;
|
||||
// Only allow even buffer sizes
|
||||
if (num_samples & 1)
|
||||
num_samples++;
|
||||
buffer_size = num_samples;
|
||||
buffer = new int16_t[buffer_size];
|
||||
clear();
|
||||
|
||||
Executable → Regular
+137
-234
@@ -1,35 +1,16 @@
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <stack>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "port.h"
|
||||
#include "bml.h"
|
||||
|
||||
static char *strndup_p(char *str, int len)
|
||||
bml_node::bml_node()
|
||||
{
|
||||
char *buffer;
|
||||
int n;
|
||||
|
||||
buffer = (char *) malloc (len + 1);
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
for (n = 0; ((n < len) && (str[n] != 0)); n++) buffer[n] = str[n];
|
||||
buffer[n] = '\0';
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static inline bml_node *bml_node_new (void)
|
||||
{
|
||||
bml_node *node = new bml_node;
|
||||
|
||||
node->data = NULL;
|
||||
node->name = NULL;
|
||||
node->depth = -1;
|
||||
|
||||
return node;
|
||||
type = CHILD;
|
||||
depth = -1;
|
||||
}
|
||||
|
||||
static inline int islf(char c)
|
||||
@@ -42,6 +23,11 @@ static inline int isblank(char c)
|
||||
return (c == ' ' || c == '\t');
|
||||
}
|
||||
|
||||
static inline int isblankorlf(char c)
|
||||
{
|
||||
return (islf(c) || isblank(c));
|
||||
}
|
||||
|
||||
static inline int isalnum(char c)
|
||||
{
|
||||
return ((c >= 'a' && c <= 'z') ||
|
||||
@@ -49,340 +35,257 @@ static inline int isalnum(char c)
|
||||
(c >= '0' && c <= '9'));
|
||||
}
|
||||
|
||||
static inline int bml_valid (char c)
|
||||
static inline int bml_valid(char c)
|
||||
{
|
||||
return (isalnum (c) || c == '-');
|
||||
return (isalnum(c) || c == '-');
|
||||
}
|
||||
|
||||
static char *strndup_trim (char *str, int len)
|
||||
static std::string trim(std::string str)
|
||||
{
|
||||
int start;
|
||||
int end;
|
||||
|
||||
for (start = 0; str[start] && start != len && isblank (str[start]); start++) {}
|
||||
if (!str[start] || start >= len)
|
||||
return strdup ("");
|
||||
|
||||
for (end = len - 1; isblank (str[end]) || str[end] == '\n' || str[end] == '\r'; end--) {}
|
||||
|
||||
return strndup_p (str + start, end - start + 1);
|
||||
for (start = 0; str[start] && start != (int)str.length() && isblank(str[start]); start++) {}
|
||||
if (start >= (int)str.length())
|
||||
return std::string("");
|
||||
for (end = str.length() - 1; isblankorlf(str[end]); end--) {}
|
||||
return str.substr(start, end - start + 1);
|
||||
}
|
||||
|
||||
static inline unsigned int bml_read_depth (char *data)
|
||||
static std::string trimcomments(std::string str)
|
||||
{
|
||||
unsigned int depth;
|
||||
for (depth = 0; isblank (data[depth]); depth++) {}
|
||||
return depth;
|
||||
int end = str.length();
|
||||
size_t comment = str.find("//");
|
||||
if (comment != std::string::npos)
|
||||
end = comment;
|
||||
|
||||
for (int i = end - 1; i >= 0; i--)
|
||||
{
|
||||
if (!isblankorlf(str[i]))
|
||||
{
|
||||
end = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return str.substr(0, end);
|
||||
}
|
||||
|
||||
static void bml_parse_depth (bml_node *node, char **data)
|
||||
static inline int bml_read_depth(std::string &data)
|
||||
{
|
||||
unsigned int depth = bml_read_depth (*data);
|
||||
*data += depth;
|
||||
node->depth = depth;
|
||||
size_t depth;
|
||||
for (depth = 0; isblank(data[depth]) && depth < data.length(); depth++) {}
|
||||
return depth == data.length() ? -1 : depth;
|
||||
}
|
||||
|
||||
static void bml_parse_name (bml_node *node, char **data)
|
||||
static void bml_parse_depth(bml_node &node, std::string &line)
|
||||
{
|
||||
unsigned int depth = bml_read_depth(line);
|
||||
line.erase(0, depth);
|
||||
node.depth = depth;
|
||||
}
|
||||
|
||||
static void bml_parse_name(bml_node &node, std::string &line)
|
||||
{
|
||||
int len;
|
||||
|
||||
for (len = 0; bml_valid(*(*data + len)); len++) {};
|
||||
for (len = 0; bml_valid(line[len]); len++) {};
|
||||
|
||||
node->name = strndup_trim (*data, len);
|
||||
*data += len;
|
||||
node.name = trim(line.substr(0, len));
|
||||
line.erase(0, len);
|
||||
}
|
||||
|
||||
static void bml_parse_data (bml_node *node, char **data)
|
||||
static void bml_parse_data(bml_node &node, std::string &line)
|
||||
{
|
||||
char *p = *data;
|
||||
int len;
|
||||
|
||||
if (p[0] == '=' && p[1] == '\"')
|
||||
if (line[0] == '=' && line[1] == '\"')
|
||||
{
|
||||
len = 2;
|
||||
while (p[len] && p[len] != '\"' && !islf (p[len]))
|
||||
while (line[len] && line[len] != '\"' && !islf(line[len]))
|
||||
len++;
|
||||
if (p[len] != '\"')
|
||||
if (line[len] != '\"')
|
||||
return;
|
||||
|
||||
node->data = strndup_p (p + 2, len - 2);
|
||||
*data += len + 1;
|
||||
node.data = line.substr(2, len - 2);
|
||||
line.erase(0, len + 1);
|
||||
}
|
||||
else if (*p == '=')
|
||||
else if (line[0] == '=')
|
||||
{
|
||||
len = 1;
|
||||
while (p[len] && !islf (p[len]) && p[len] != '"' && p[len] != ' ')
|
||||
while (line[len] && !islf(line[len]) && line[len] != '"' && line[len] != ' ')
|
||||
len++;
|
||||
if (p[len] == '\"')
|
||||
if (line[len] == '\"')
|
||||
return;
|
||||
node->data = strndup_trim (p + 1, len - 1);
|
||||
*data += len;
|
||||
node.data = line.substr(1, len - 1);
|
||||
line.erase(0, len);
|
||||
}
|
||||
else if (*p == ':')
|
||||
else if (line[0] == ':')
|
||||
{
|
||||
len = 1;
|
||||
while (p[len] && !islf (p[len]))
|
||||
while (line[len] && !islf(line[len]))
|
||||
len++;
|
||||
node->data = strndup_trim (p + 1, len - 1);
|
||||
*data += len;
|
||||
node.data = trim(line.substr(1, len - 1));
|
||||
line.erase(0, len);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void bml_skip_empty (char **data)
|
||||
static std::string bml_read_line(std::ifstream &fd)
|
||||
{
|
||||
char *p = *data;
|
||||
std::string line;
|
||||
|
||||
while (*p)
|
||||
while (fd)
|
||||
{
|
||||
for (; *p && isblank (*p) ; p++) {}
|
||||
|
||||
if (!islf(p[0]) && (p[0] != '/' && p[1] != '/'))
|
||||
return;
|
||||
|
||||
/* Skip comment data */
|
||||
while (*p && *p != '\r' && *p != '\n')
|
||||
p++;
|
||||
|
||||
/* If we found new-line, try to skip more */
|
||||
if (*p)
|
||||
std::getline(fd, line);
|
||||
line = trimcomments(line);
|
||||
if (!line.empty())
|
||||
{
|
||||
p++;
|
||||
*data = p;
|
||||
return line;
|
||||
}
|
||||
}
|
||||
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
static char *bml_read_line (char **data)
|
||||
static void bml_parse_attr(bml_node &node, std::string &line)
|
||||
{
|
||||
char *line;
|
||||
char *p;
|
||||
|
||||
bml_skip_empty (data);
|
||||
|
||||
line = *data;
|
||||
|
||||
if (line == NULL || *line == '\0')
|
||||
return NULL;
|
||||
|
||||
p = strpbrk (line, "\r\n\0");
|
||||
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
if (islf (*p))
|
||||
{
|
||||
*p = '\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
*data = p;
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
static void bml_parse_attr (bml_node *node, char **data)
|
||||
{
|
||||
char *p = *data;
|
||||
bml_node *n;
|
||||
int len;
|
||||
|
||||
while (*p && !islf (*p))
|
||||
while (line.length() > 0)
|
||||
{
|
||||
if (*p != ' ')
|
||||
if (!isblank(line[0]))
|
||||
return;
|
||||
|
||||
while (isblank (*p))
|
||||
p++;
|
||||
if (p[0] == '/' && p[1] == '/')
|
||||
break;
|
||||
while (isblank(line[0]))
|
||||
line.erase(0, 1);
|
||||
|
||||
n = bml_node_new ();
|
||||
bml_node n;
|
||||
len = 0;
|
||||
while (bml_valid (p[len]))
|
||||
len++;
|
||||
while (bml_valid(line[len]))
|
||||
len++;
|
||||
if (len == 0)
|
||||
return;
|
||||
n->name = strndup_trim (p, len);
|
||||
p += len;
|
||||
bml_parse_data (n, &p);
|
||||
n->depth = bml_attr_type;
|
||||
node->child.push_back (n);
|
||||
n.name = trim(line.substr(0, len));
|
||||
line.erase(0, len);
|
||||
bml_parse_data(n, line);
|
||||
n.depth = node.depth + 1;
|
||||
n.type = bml_node::ATTRIBUTE;
|
||||
node.child.push_back(n);
|
||||
}
|
||||
|
||||
*data = p;
|
||||
}
|
||||
|
||||
static int contains_space (char *str)
|
||||
static int contains_space(const char *str)
|
||||
{
|
||||
for (int i = 0; str[i]; i++)
|
||||
{
|
||||
if (isblank (str[i]))
|
||||
if (isblank(str[i]))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bml_print_node (bml_node *node, int depth)
|
||||
static void bml_print_node(bml_node &node, int depth)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
for (i = 0; i < depth * 2; i++)
|
||||
{
|
||||
printf (" ");
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
if (node->name)
|
||||
printf ("%s", node->name);
|
||||
if (!node.name.empty())
|
||||
printf("%s", node.name.c_str());
|
||||
|
||||
if (node->data)
|
||||
if (!node.data.empty())
|
||||
{
|
||||
if (contains_space (node->data))
|
||||
printf ("=\"%s\"", node->data);
|
||||
if (contains_space(node.data.c_str()))
|
||||
printf("=\"%s\"", node.data.c_str());
|
||||
else
|
||||
printf (": %s", node->data);
|
||||
printf(": %s", node.data.c_str());
|
||||
}
|
||||
for (i = 0; i < (int) node->child.size () && node->child[i]->depth == bml_attr_type; i++)
|
||||
for (i = 0; i < (int)node.child.size() && node.child[i].type == bml_node::ATTRIBUTE; i++)
|
||||
{
|
||||
if (node->child[i]->name)
|
||||
if (!node.child[i].name.empty())
|
||||
{
|
||||
printf (" %s", node->child[i]->name);
|
||||
if (node->child[i]->data)
|
||||
printf(" %s", node.child[i].name.c_str());
|
||||
if (!node.child[i].data.empty())
|
||||
{
|
||||
if (contains_space (node->child[i]->data))
|
||||
printf ("=\"%s\"", node->child[i]->data);
|
||||
if (contains_space(node.child[i].data.c_str()))
|
||||
printf("=\"%s\"", node.child[i].data.c_str());
|
||||
else
|
||||
printf ("=%s", node->child[i]->data);
|
||||
printf("=%s", node.child[i].data.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (depth >= 0)
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
|
||||
for (; i < (int) node->child.size(); i++)
|
||||
for (; i < (int)node.child.size(); i++)
|
||||
{
|
||||
bml_print_node (node->child[i], depth + 1);
|
||||
bml_print_node(node.child[i], depth + 1);
|
||||
}
|
||||
|
||||
if (depth == 0)
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void bml_print_node (bml_node *node)
|
||||
void bml_node::print()
|
||||
{
|
||||
bml_print_node (node, -1);
|
||||
bml_print_node(*this, -1);
|
||||
}
|
||||
|
||||
static bml_node *bml_parse_node (char **doc)
|
||||
void bml_node::parse(std::ifstream &fd)
|
||||
{
|
||||
char *line;
|
||||
bml_node *node = NULL;
|
||||
std::stack<bml_node *> nodestack;
|
||||
nodestack.push(this);
|
||||
|
||||
if ((line = bml_read_line (doc)))
|
||||
while (fd)
|
||||
{
|
||||
node = bml_node_new ();
|
||||
bml_node newnode;
|
||||
std::string line = bml_read_line(fd);
|
||||
if (line.empty())
|
||||
return;
|
||||
|
||||
bml_parse_depth (node, &line);
|
||||
bml_parse_name (node, &line);
|
||||
bml_parse_data (node, &line);
|
||||
bml_parse_attr (node, &line);
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
int line_depth = bml_read_depth(line);
|
||||
while (line_depth <= nodestack.top()->depth && nodestack.size() > 1)
|
||||
nodestack.pop();
|
||||
|
||||
bml_skip_empty (doc);
|
||||
while (*doc && (int) bml_read_depth (*doc) > node->depth)
|
||||
{
|
||||
bml_node *child = bml_parse_node (doc);
|
||||
bml_parse_depth(newnode, line);
|
||||
bml_parse_name(newnode, line);
|
||||
bml_parse_data(newnode, line);
|
||||
bml_parse_attr(newnode, line);
|
||||
|
||||
if (child)
|
||||
node->child.push_back (child);
|
||||
|
||||
bml_skip_empty (doc);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void bml_free_node (bml_node *node)
|
||||
{
|
||||
delete[] (node->name);
|
||||
delete[] (node->data);
|
||||
|
||||
for (unsigned int i = 0; i < node->child.size(); i++)
|
||||
{
|
||||
bml_free_node (node->child[i]);
|
||||
delete node->child[i];
|
||||
nodestack.top()->child.push_back(newnode);
|
||||
nodestack.push(&nodestack.top()->child.back());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bml_node *bml_parse (char **doc)
|
||||
{
|
||||
bml_node *root = NULL;
|
||||
bml_node *node = NULL;
|
||||
char *ptr = *doc;
|
||||
|
||||
root = bml_node_new ();
|
||||
|
||||
while ((node = bml_parse_node (&ptr)))
|
||||
{
|
||||
root->child.push_back (node);
|
||||
}
|
||||
|
||||
if (!root->child.size())
|
||||
{
|
||||
delete root;
|
||||
root = NULL;
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
bml_node *bml_find_sub (bml_node *n, const char *name)
|
||||
bml_node *bml_node::find_subnode(std::string name)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < n->child.size (); i++)
|
||||
for (i = 0; i < child.size(); i++)
|
||||
{
|
||||
if (!strcasecmp (n->child[i]->name, name))
|
||||
return n->child[i];
|
||||
if (name.compare(child[i].name) == 0)
|
||||
return &child[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bml_node *bml_parse_file (const char *filename)
|
||||
bool bml_node::parse_file(std::string filename)
|
||||
{
|
||||
FILE *file = NULL;
|
||||
char *buffer = NULL;
|
||||
int file_size = 0;
|
||||
bml_node *node = NULL;
|
||||
|
||||
file = fopen (filename, "rb");
|
||||
std::ifstream file(filename.c_str(), std::ios_base::binary);
|
||||
|
||||
if (!file)
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
fseek (file, 0, SEEK_END);
|
||||
file_size = ftell (file);
|
||||
fseek (file, 0, SEEK_SET);
|
||||
parse(file);
|
||||
|
||||
buffer = new char[file_size + 1];
|
||||
fread (buffer, file_size, 1, file);
|
||||
buffer[file_size] = '\0';
|
||||
|
||||
fclose (file);
|
||||
|
||||
node = bml_parse (&buffer);
|
||||
delete[] buffer;
|
||||
|
||||
return node;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,31 +1,27 @@
|
||||
#ifndef __BML_H
|
||||
#define __BML_H
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
const int bml_attr_type = -2;
|
||||
|
||||
typedef struct bml_node
|
||||
struct bml_node
|
||||
{
|
||||
char *name;
|
||||
char *data;
|
||||
enum node_type {
|
||||
CHILD,
|
||||
ATTRIBUTE
|
||||
};
|
||||
|
||||
bml_node();
|
||||
bool parse_file(std::string filename);
|
||||
void parse(std::ifstream &fd);
|
||||
bml_node *find_subnode(std::string name);
|
||||
void print();
|
||||
|
||||
std::string name;
|
||||
std::string data;
|
||||
int depth;
|
||||
|
||||
std::vector<bml_node *> child;
|
||||
|
||||
} bml_node;
|
||||
|
||||
bml_node *bml_find_sub (bml_node *node, const char *name);
|
||||
|
||||
bml_node *bml_parse_file (const char *filename);
|
||||
|
||||
/* Parse character array into BML tree. Destructive to input. */
|
||||
bml_node *bml_parse (char **buffer);
|
||||
|
||||
/* Recursively free bml_node and substructures */
|
||||
void bml_free_node (bml_node *);
|
||||
|
||||
/* Print node structure to stdout */
|
||||
void bml_print_node (bml_node *);
|
||||
std::vector<bml_node> child;
|
||||
node_type type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Executable → Regular
+15
-23
@@ -738,16 +738,14 @@ void S9xBSXSetStream1 (uint8 count)
|
||||
if (BSX.sat_stream1.is_open())
|
||||
BSX.sat_stream1.close(); //If Stream already opened for one file: Close it.
|
||||
|
||||
char path[PATH_MAX + 1], name[PATH_MAX + 1];
|
||||
std::string path = S9xGetDirectory(SAT_DIR) + SLASH_STR;
|
||||
|
||||
strcpy(path, S9xGetDirectory(SAT_DIR));
|
||||
strcat(path, SLASH_STR);
|
||||
|
||||
snprintf(name, PATH_MAX + 1, "BSX%04X-%d.bin", (BSX.PPU[0x2188 - BSXPPUBASE] | (BSX.PPU[0x2189 - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin
|
||||
strcat(path, name);
|
||||
char name[PATH_MAX];
|
||||
snprintf(name, PATH_MAX, "BSX%04X-%d.bin", (BSX.PPU[0x2188 - BSXPPUBASE] | (BSX.PPU[0x2189 - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin
|
||||
path += name;
|
||||
|
||||
BSX.sat_stream1.clear();
|
||||
BSX.sat_stream1.open(path, std::ios::in | std::ios::binary);
|
||||
BSX.sat_stream1.open(path.c_str(), std::ios::in | std::ios::binary);
|
||||
if (BSX.sat_stream1.good())
|
||||
{
|
||||
BSX.sat_stream1.seekg(0, BSX.sat_stream1.end);
|
||||
@@ -770,16 +768,15 @@ void S9xBSXSetStream2 (uint8 count)
|
||||
if (BSX.sat_stream2.is_open())
|
||||
BSX.sat_stream2.close(); //If Stream already opened for one file: Close it.
|
||||
|
||||
char path[PATH_MAX + 1], name[PATH_MAX + 1];
|
||||
|
||||
strcpy(path, S9xGetDirectory(SAT_DIR));
|
||||
strcat(path, SLASH_STR);
|
||||
std::string path = S9xGetDirectory(SAT_DIR) + SLASH_STR;
|
||||
|
||||
snprintf(name, PATH_MAX + 1, "BSX%04X-%d.bin", (BSX.PPU[0x218E - BSXPPUBASE] | (BSX.PPU[0x218F - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin
|
||||
strcat(path, name);
|
||||
char name[PATH_MAX];
|
||||
snprintf(name, PATH_MAX, "BSX%04X-%d.bin", (BSX.PPU[0x218E - BSXPPUBASE] | (BSX.PPU[0x218F - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin
|
||||
path += name;
|
||||
|
||||
BSX.sat_stream2.clear();
|
||||
BSX.sat_stream2.open(path, std::ios::in | std::ios::binary);
|
||||
BSX.sat_stream2.open(path.c_str(), std::ios::in | std::ios::binary);
|
||||
if (BSX.sat_stream2.good())
|
||||
{
|
||||
BSX.sat_stream2.seekg(0, BSX.sat_stream2.end);
|
||||
@@ -1207,20 +1204,15 @@ uint8 * S9xGetBasePointerBSX (uint32 address)
|
||||
static bool8 BSX_LoadBIOS (void)
|
||||
{
|
||||
FILE *fp;
|
||||
char path[PATH_MAX + 1], name[PATH_MAX + 1];
|
||||
bool8 r = FALSE;
|
||||
|
||||
strcpy(path, S9xGetDirectory(BIOS_DIR));
|
||||
strcat(path, SLASH_STR);
|
||||
strcpy(name, path);
|
||||
strcat(name, "BS-X.bin");
|
||||
std::string name = S9xGetDirectory(BIOS_DIR) + SLASH_STR + "BS-X.bin";
|
||||
|
||||
fp = fopen(name, "rb");
|
||||
fp = fopen(name.c_str(), "rb");
|
||||
if (!fp)
|
||||
{
|
||||
strcpy(name, path);
|
||||
strcat(name, "BS-X.bios");
|
||||
fp = fopen(name, "rb");
|
||||
name = S9xGetDirectory(BIOS_DIR) + SLASH_STR + "BS-X.bios";
|
||||
fp = fopen(name.c_str(), "rb");
|
||||
}
|
||||
|
||||
if (fp)
|
||||
@@ -1255,7 +1247,7 @@ void S9xInitBSX (void)
|
||||
{
|
||||
Settings.BS = FALSE;
|
||||
|
||||
if (is_BSX_BIOS(Memory.ROM,Memory.CalculatedSize))
|
||||
if (is_BSX_BIOS(Memory.ROM,Memory.CalculatedSize))
|
||||
{
|
||||
// BS-X itself
|
||||
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
+1
-107
@@ -37,116 +37,10 @@
|
||||
(s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \
|
||||
((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24))))
|
||||
|
||||
static bool8 S9xAllHex (const char *, int);
|
||||
|
||||
|
||||
static bool8 S9xAllHex (const char *code, int len)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
if ((code[i] < '0' || code[i] > '9') && (code[i] < 'a' || code[i] > 'f') && (code[i] < 'A' || code[i] > 'F'))
|
||||
return (FALSE);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
const char * S9xProActionReplayToRaw (const char *code, uint32 &address, uint8 &byte)
|
||||
{
|
||||
uint32 data = 0;
|
||||
|
||||
if (strlen(code) != 8 || !S9xAllHex(code, 8) || sscanf(code, "%x", &data) != 1)
|
||||
return ("Invalid Pro Action Replay code - should be 8 hex digits in length.");
|
||||
|
||||
address = data >> 8;
|
||||
byte = (uint8) data;
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
const char * S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram, uint8 &num_bytes, uint8 bytes[3])
|
||||
{
|
||||
char tmp[15];
|
||||
int i;
|
||||
|
||||
if (strlen(code) != 14)
|
||||
return ("Invalid Gold Finger code - should be 14 hex digits in length.");
|
||||
|
||||
strncpy(tmp, code, 5);
|
||||
tmp[5] = 0;
|
||||
if (sscanf(tmp, "%x", &address) != 1)
|
||||
return ("Invalid Gold Finger code.");
|
||||
|
||||
// Correct GoldFinger Address
|
||||
address = (address & 0x7FFF) | ((address & 0x7F8000) << 1) | 0x8000;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
unsigned int byte;
|
||||
|
||||
strncpy(tmp, code + 5 + i * 2, 2);
|
||||
tmp[2] = 0;
|
||||
if (sscanf(tmp, "%x", &byte) != 1)
|
||||
break;
|
||||
bytes[i] = (uint8) byte;
|
||||
}
|
||||
|
||||
num_bytes = i;
|
||||
sram = code[13] == '1';
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
const char * S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte)
|
||||
{
|
||||
char new_code[12];
|
||||
|
||||
if (strlen(code) != 9 || *(code + 4) != '-' || !S9xAllHex(code, 4) || !S9xAllHex(code + 5, 4))
|
||||
return ("Invalid Game Genie(tm) code - should be 'xxxx-xxxx'.");
|
||||
|
||||
strcpy(new_code, "0x");
|
||||
strncpy(new_code + 2, code, 4);
|
||||
strcpy(new_code + 6, code + 5);
|
||||
|
||||
static const char *real_hex = "0123456789ABCDEF";
|
||||
static const char *genie_hex = "DF4709156BC8A23E";
|
||||
|
||||
for (int i = 2; i < 10; i++)
|
||||
{
|
||||
if (islower(new_code[i]))
|
||||
new_code[i] = toupper(new_code[i]);
|
||||
|
||||
int j;
|
||||
for (j = 0; j < 16; j++)
|
||||
{
|
||||
if (new_code[i] == genie_hex[j])
|
||||
{
|
||||
new_code[i] = real_hex[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == 16)
|
||||
return ("Invalid hex-character in Game Genie(tm) code.");
|
||||
}
|
||||
|
||||
uint32 data = 0;
|
||||
sscanf(new_code, "%x", &data);
|
||||
byte = (uint8) (data >> 24);
|
||||
address = data & 0xffffff;
|
||||
address = ((address & 0x003c00) << 10) +
|
||||
((address & 0x00003c) << 14) +
|
||||
((address & 0xf00000) >> 8) +
|
||||
((address & 0x000003) << 10) +
|
||||
((address & 0x00c000) >> 6) +
|
||||
((address & 0x0f0000) >> 12) +
|
||||
((address & 0x0003c0) >> 6);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void S9xStartCheatSearch (SCheatData *d)
|
||||
{
|
||||
memmove(d->CWRAM, d->RAM, 0x20000);
|
||||
memmove(d->CSRAM, d->SRAM, 0x10000);
|
||||
memmove(d->CSRAM, d->SRAM, 0x80000);
|
||||
memmove(d->CIRAM, &d->FillRAM[0x3000], 0x2000);
|
||||
memset((char *) d->ALL_BITS, 0xff, 0x32000 >> 3);
|
||||
}
|
||||
|
||||
Executable → Regular
+18
-22
@@ -23,17 +23,17 @@ struct SCheat
|
||||
|
||||
struct SCheatGroup
|
||||
{
|
||||
char *name;
|
||||
std::string name;
|
||||
bool8 enabled;
|
||||
std::vector<struct SCheat> c;
|
||||
std::vector<struct SCheat> cheat;
|
||||
};
|
||||
|
||||
struct SCheatData
|
||||
{
|
||||
std::vector<struct SCheatGroup> g;
|
||||
std::vector<struct SCheatGroup> group;
|
||||
bool8 enabled;
|
||||
uint8 CWRAM[0x20000];
|
||||
uint8 CSRAM[0x10000];
|
||||
uint8 CSRAM[0x80000];
|
||||
uint8 CIRAM[0x2000];
|
||||
uint8 *RAM;
|
||||
uint8 *FillRAM;
|
||||
@@ -73,20 +73,20 @@ typedef enum
|
||||
extern SCheatData Cheat;
|
||||
extern Watch watches[16];
|
||||
|
||||
int S9xAddCheatGroup (const char *name, const char *cheat);
|
||||
int S9xModifyCheatGroup (uint32 index, const char *name, const char *cheat);
|
||||
void S9xEnableCheatGroup (uint32 index);
|
||||
void S9xDisableCheatGroup (uint32 index);
|
||||
void S9xDeleteCheats (void);
|
||||
char *S9xCheatGroupToText (uint32 index);
|
||||
void S9xDeleteCheatGroup (uint32 index);
|
||||
bool8 S9xLoadCheatFile (const char *filename);
|
||||
bool8 S9xSaveCheatFile (const char *filename);
|
||||
void S9xUpdateCheatsInMemory (void);
|
||||
int S9xImportCheatsFromDatabase(const char *filename);
|
||||
void S9xCheatsDisable (void);
|
||||
void S9xCheatsEnable (void);
|
||||
char *S9xCheatValidate (char *cheat);
|
||||
int S9xAddCheatGroup(const std::string &name, const std::string &cheat);
|
||||
int S9xModifyCheatGroup(uint32 index, const std::string &name, const std::string &cheat);
|
||||
void S9xEnableCheatGroup(uint32 index);
|
||||
void S9xDisableCheatGroup(uint32 index);
|
||||
void S9xDeleteCheats(void);
|
||||
std::string S9xCheatGroupToText(uint32 index);
|
||||
void S9xDeleteCheatGroup(uint32 index);
|
||||
bool8 S9xLoadCheatFile(const std::string &filename);
|
||||
bool8 S9xSaveCheatFile(const std::string &filename);
|
||||
void S9xUpdateCheatsInMemory(void);
|
||||
int S9xImportCheatsFromDatabase(const std::string &filename);
|
||||
void S9xCheatsDisable(void);
|
||||
void S9xCheatsEnable(void);
|
||||
std::string S9xCheatValidate(const std::string &cheat);
|
||||
|
||||
void S9xInitCheatData (void);
|
||||
void S9xInitWatchedAddress (void);
|
||||
@@ -96,8 +96,4 @@ void S9xSearchForValue (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize,
|
||||
void S9xSearchForAddress (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8);
|
||||
void S9xOutputCheatSearchResults (SCheatData *);
|
||||
|
||||
const char * S9xGameGenieToRaw (const char *, uint32 &, uint8 &);
|
||||
const char * S9xProActionReplayToRaw (const char *, uint32 &, uint8 &);
|
||||
const char * S9xGoldFingerToRaw (const char *, uint32 &, bool8 &, uint8 &, uint8 bytes[3]);
|
||||
|
||||
#endif
|
||||
|
||||
Executable → Regular
+307
-301
@@ -4,37 +4,24 @@
|
||||
For further information, consult the LICENSE file in the root directory.
|
||||
\*****************************************************************************/
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "bml.h"
|
||||
#include "cheats.h"
|
||||
#include "snes9x.h"
|
||||
#include "memmap.h"
|
||||
#include "cheats.h"
|
||||
#include "bml.h"
|
||||
|
||||
static inline char *trim (char *string)
|
||||
static inline uint8 S9xGetByteFree(uint32 Address)
|
||||
{
|
||||
int start;
|
||||
int end;
|
||||
|
||||
for (start = 0; string[start] && isspace (string[start]); start++) {}
|
||||
for (end = start; string[end] && !isspace (string[end]); end++) {}
|
||||
string[end] = '\0';
|
||||
return &string[start];
|
||||
}
|
||||
|
||||
static inline uint8 S9xGetByteFree (uint32 Address)
|
||||
{
|
||||
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
|
||||
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
|
||||
uint8 *GetAddress = Memory.Map[block];
|
||||
uint8 byte;
|
||||
|
||||
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
|
||||
if (GetAddress >= (uint8 *)CMemory::MAP_LAST)
|
||||
{
|
||||
byte = *(GetAddress + (Address & 0xffff));
|
||||
return (byte);
|
||||
}
|
||||
|
||||
switch ((pint) GetAddress)
|
||||
switch ((pint)GetAddress)
|
||||
{
|
||||
case CMemory::MAP_CPU:
|
||||
byte = S9xGetCPU(Address & 0xffff);
|
||||
@@ -62,7 +49,7 @@ static inline uint8 S9xGetByteFree (uint32 Address)
|
||||
|
||||
case CMemory::MAP_HIROM_SRAM:
|
||||
case CMemory::MAP_RONLY_SRAM:
|
||||
byte = *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));
|
||||
byte = *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0x1f0000) >> 3)) & Memory.SRAMMask));
|
||||
return (byte);
|
||||
|
||||
case CMemory::MAP_BWRAM:
|
||||
@@ -108,18 +95,18 @@ static inline uint8 S9xGetByteFree (uint32 Address)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void S9xSetByteFree (uint8 Byte, uint32 Address)
|
||||
static inline void S9xSetByteFree(uint8 Byte, uint32 Address)
|
||||
{
|
||||
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
|
||||
uint8 *SetAddress = Memory.Map[block];
|
||||
|
||||
if (SetAddress >= (uint8 *) CMemory::MAP_LAST)
|
||||
if (SetAddress >= (uint8 *)CMemory::MAP_LAST)
|
||||
{
|
||||
*(SetAddress + (Address & 0xffff)) = Byte;
|
||||
return;
|
||||
}
|
||||
|
||||
switch ((pint) SetAddress)
|
||||
switch ((pint)SetAddress)
|
||||
{
|
||||
case CMemory::MAP_CPU:
|
||||
S9xSetCPU(Byte, Address & 0xffff);
|
||||
@@ -153,7 +140,7 @@ static inline void S9xSetByteFree (uint8 Byte, uint32 Address)
|
||||
case CMemory::MAP_HIROM_SRAM:
|
||||
if (Memory.SRAMMask)
|
||||
{
|
||||
*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = Byte;
|
||||
*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0x1f0000) >> 3)) & Memory.SRAMMask)) = Byte;
|
||||
CPU.SRAMModified = TRUE;
|
||||
}
|
||||
return;
|
||||
@@ -197,165 +184,229 @@ static inline void S9xSetByteFree (uint8 Byte, uint32 Address)
|
||||
}
|
||||
}
|
||||
|
||||
void S9xInitWatchedAddress (void)
|
||||
void S9xInitWatchedAddress(void)
|
||||
{
|
||||
for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++)
|
||||
watches[i].on = false;
|
||||
}
|
||||
|
||||
void S9xInitCheatData (void)
|
||||
void S9xInitCheatData(void)
|
||||
{
|
||||
Cheat.RAM = Memory.RAM;
|
||||
Cheat.SRAM = Memory.SRAM;
|
||||
Cheat.FillRAM = Memory.FillRAM;
|
||||
}
|
||||
|
||||
static inline std::string trim(const std::string &&string)
|
||||
{
|
||||
auto start = string.find_first_not_of(" \t\n\r");
|
||||
auto end = string.find_last_not_of(" \t\n\r");
|
||||
if (start != std::string::npos && end != std::string::npos)
|
||||
return string.substr(start, end - start + 1);
|
||||
return "";
|
||||
}
|
||||
|
||||
void S9xUpdateCheatInMemory (SCheat *c)
|
||||
void S9xUpdateCheatInMemory(SCheat &c)
|
||||
{
|
||||
uint8 byte;
|
||||
|
||||
if (!c->enabled)
|
||||
if (!c.enabled)
|
||||
return;
|
||||
|
||||
byte = S9xGetByteFree (c->address);
|
||||
byte = S9xGetByteFree(c.address);
|
||||
|
||||
if (byte != c->byte)
|
||||
if (byte != c.byte)
|
||||
{
|
||||
/* The game wrote a different byte to the address, update saved_byte */
|
||||
c->saved_byte = byte;
|
||||
c.saved_byte = byte;
|
||||
|
||||
if (c->conditional)
|
||||
if (c.conditional)
|
||||
{
|
||||
if (c->saved_byte != c->cond_byte && c->cond_true)
|
||||
if (c.saved_byte != c.cond_byte && c.cond_true)
|
||||
{
|
||||
/* Condition is now false, let the byte stand */
|
||||
c->cond_true = false;
|
||||
c.cond_true = false;
|
||||
}
|
||||
else if (c->saved_byte == c->cond_byte && !c->cond_true)
|
||||
else if (c.saved_byte == c.cond_byte && !c.cond_true)
|
||||
{
|
||||
c->cond_true = true;
|
||||
S9xSetByteFree (c->byte, c->address);
|
||||
c.cond_true = true;
|
||||
S9xSetByteFree(c.byte, c.address);
|
||||
}
|
||||
}
|
||||
else
|
||||
S9xSetByteFree (c->byte, c->address);
|
||||
S9xSetByteFree(c.byte, c.address);
|
||||
}
|
||||
else if (c->conditional)
|
||||
else if (c.conditional)
|
||||
{
|
||||
if (byte == c->cond_byte)
|
||||
if (byte == c.cond_byte)
|
||||
{
|
||||
c->cond_true = true;
|
||||
c->saved_byte = byte;
|
||||
S9xSetByteFree (c->byte, c->address);
|
||||
c.cond_true = true;
|
||||
c.saved_byte = byte;
|
||||
S9xSetByteFree(c.byte, c.address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void S9xDisableCheat (SCheat *c)
|
||||
void S9xDisableCheat(SCheat &c)
|
||||
{
|
||||
if (!c->enabled)
|
||||
if (!c.enabled)
|
||||
return;
|
||||
|
||||
if (!Cheat.enabled)
|
||||
{
|
||||
c->enabled = false;
|
||||
c.enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure we restore the up-to-date written byte */
|
||||
S9xUpdateCheatInMemory (c);
|
||||
c->enabled = false;
|
||||
S9xUpdateCheatInMemory(c);
|
||||
c.enabled = false;
|
||||
|
||||
if (c->conditional && !c->cond_true)
|
||||
if (c.conditional && !c.cond_true)
|
||||
return;
|
||||
|
||||
S9xSetByteFree (c->saved_byte, c->address);
|
||||
c->cond_true = false;
|
||||
S9xSetByteFree (c.saved_byte, c.address);
|
||||
c.cond_true = false;
|
||||
}
|
||||
|
||||
void S9xDeleteCheatGroup (uint32 g)
|
||||
void S9xDeleteCheatGroup(uint32 g)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (g >= Cheat.g.size ())
|
||||
if (g >= Cheat.group.size())
|
||||
return;
|
||||
|
||||
for (i = 0; i < Cheat.g[g].c.size (); i++)
|
||||
for (i = 0; i < Cheat.group[g].cheat.size(); i++)
|
||||
{
|
||||
S9xDisableCheat (&Cheat.g[g].c[i]);
|
||||
S9xDisableCheat(Cheat.group[g].cheat[i]);
|
||||
}
|
||||
|
||||
delete[] Cheat.g[g].name;
|
||||
|
||||
Cheat.g.erase (Cheat.g.begin () + g);
|
||||
Cheat.group.erase(Cheat.group.begin() + g);
|
||||
}
|
||||
|
||||
void S9xDeleteCheats (void)
|
||||
void S9xDeleteCheats(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < Cheat.g.size (); i++)
|
||||
for (size_t i = 0; i < Cheat.group.size(); i++)
|
||||
{
|
||||
S9xDisableCheatGroup (i);
|
||||
|
||||
delete[] Cheat.g[i].name;
|
||||
S9xDisableCheatGroup(i);
|
||||
}
|
||||
|
||||
Cheat.g.clear ();
|
||||
Cheat.group.clear();
|
||||
}
|
||||
|
||||
void S9xEnableCheat (SCheat *c)
|
||||
void S9xEnableCheat(SCheat &c)
|
||||
{
|
||||
uint8 byte;
|
||||
|
||||
if (c->enabled)
|
||||
if (c.enabled)
|
||||
return;
|
||||
|
||||
c->enabled = true;
|
||||
c.enabled = true;
|
||||
|
||||
if (!Cheat.enabled)
|
||||
return;
|
||||
|
||||
byte = S9xGetByteFree(c->address);
|
||||
byte = S9xGetByteFree(c.address);
|
||||
|
||||
if (c->conditional)
|
||||
if (c.conditional)
|
||||
{
|
||||
if (byte != c->cond_byte)
|
||||
if (byte != c.cond_byte)
|
||||
return;
|
||||
|
||||
c->cond_true = true;
|
||||
c.cond_true = true;
|
||||
}
|
||||
|
||||
c->saved_byte = byte;
|
||||
S9xSetByteFree (c->byte, c->address);
|
||||
c.saved_byte = byte;
|
||||
S9xSetByteFree(c.byte, c.address);
|
||||
}
|
||||
|
||||
void S9xEnableCheatGroup (uint32 num)
|
||||
void S9xEnableCheatGroup(uint32 num)
|
||||
{
|
||||
unsigned int i;
|
||||
for (auto &c : Cheat.group[num].cheat)
|
||||
S9xEnableCheat(c);
|
||||
|
||||
for (i = 0; i < Cheat.g[num].c.size (); i++)
|
||||
{
|
||||
S9xEnableCheat (&Cheat.g[num].c[i]);
|
||||
}
|
||||
|
||||
Cheat.g[num].enabled = true;
|
||||
Cheat.group[num].enabled = true;
|
||||
}
|
||||
|
||||
void S9xDisableCheatGroup (uint32 num)
|
||||
void S9xDisableCheatGroup(uint32 num)
|
||||
{
|
||||
unsigned int i;
|
||||
for (auto &c : Cheat.group[num].cheat)
|
||||
S9xDisableCheat(c);
|
||||
|
||||
for (i = 0; i < Cheat.g[num].c.size (); i++)
|
||||
{
|
||||
S9xDisableCheat (&Cheat.g[num].c[i]);
|
||||
}
|
||||
|
||||
Cheat.g[num].enabled = false;
|
||||
Cheat.group[num].enabled = false;
|
||||
}
|
||||
|
||||
SCheat S9xTextToCheat (char *text)
|
||||
static bool is_all_hex(const std::string &code)
|
||||
{
|
||||
for (const auto &c : code)
|
||||
{
|
||||
if ((c < '0' || c > '9') &&
|
||||
(c < 'a' || c > 'f') &&
|
||||
(c < 'A' || c > 'F'))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S9xProActionReplayToRaw(const std::string &code, uint32 &address, uint8 &byte)
|
||||
{
|
||||
if (code.length() != 8 || !is_all_hex(code))
|
||||
return false;
|
||||
|
||||
uint32 data = std::strtoul(code.c_str(), nullptr, 16);
|
||||
|
||||
address = data >> 8;
|
||||
byte = (uint8)data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S9xGameGenieToRaw(const std::string &code, uint32 &address, uint8 &byte)
|
||||
{
|
||||
if (code.length() != 9)
|
||||
return false;
|
||||
if (code[4] != '-')
|
||||
return false;
|
||||
if (!is_all_hex(code.substr(0, 4)))
|
||||
return false;
|
||||
if (!is_all_hex(code.substr(5, 4)))
|
||||
return false;
|
||||
|
||||
auto new_code = code.substr(0, 4) + code.substr(5, 4);
|
||||
|
||||
static const char *real_hex = "0123456789ABCDEF";
|
||||
static const char *genie_hex = "DF4709156BC8A23E";
|
||||
|
||||
for (auto &c : new_code)
|
||||
{
|
||||
c = toupper(c);
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (genie_hex[i] == c)
|
||||
{
|
||||
c = real_hex[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 data = strtoul(new_code.c_str(), nullptr, 16);
|
||||
byte = (uint8)(data >> 24);
|
||||
address = data & 0xffffff;
|
||||
address = ((address & 0x003c00) << 10) +
|
||||
((address & 0x00003c) << 14) +
|
||||
((address & 0xf00000) >> 8) +
|
||||
((address & 0x000003) << 10) +
|
||||
((address & 0x00c000) >> 6) +
|
||||
((address & 0x0f0000) >> 12) +
|
||||
((address & 0x0003c0) >> 6);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SCheat S9xTextToCheat(const std::string &text)
|
||||
{
|
||||
SCheat c;
|
||||
unsigned int byte = 0;
|
||||
@@ -364,34 +415,28 @@ SCheat S9xTextToCheat (char *text)
|
||||
c.enabled = false;
|
||||
c.conditional = false;
|
||||
|
||||
if (!S9xGameGenieToRaw (text, c.address, c.byte))
|
||||
if (S9xGameGenieToRaw(text, c.address, c.byte))
|
||||
{
|
||||
byte = c.byte;
|
||||
}
|
||||
|
||||
else if (!S9xProActionReplayToRaw (text, c.address, c.byte))
|
||||
else if (S9xProActionReplayToRaw(text, c.address, c.byte))
|
||||
{
|
||||
byte = c.byte;
|
||||
}
|
||||
|
||||
else if (sscanf (text, "%x = %x ? %x", &c.address, &cond_byte, &byte) == 3)
|
||||
else if (sscanf(text.c_str(), "%x = %x ? %x", &c.address, &cond_byte, &byte) == 3)
|
||||
{
|
||||
c.conditional = true;
|
||||
}
|
||||
|
||||
else if (sscanf (text, "%x = %x", &c.address, &byte) == 2)
|
||||
else if (sscanf(text.c_str(), "%x = %x", &c.address, &byte) == 2)
|
||||
{
|
||||
}
|
||||
|
||||
else if (sscanf (text, "%x / %x / %x", &c.address, &cond_byte, &byte) == 3)
|
||||
else if (sscanf(text.c_str(), "%x / %x / %x", &c.address, &cond_byte, &byte) == 3)
|
||||
{
|
||||
c.conditional = true;
|
||||
}
|
||||
|
||||
else if (sscanf (text, "%x / %x", &c.address, &byte) == 2)
|
||||
else if (sscanf(text.c_str(), "%x / %x", &c.address, &byte) == 2)
|
||||
{
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
c.address = 0;
|
||||
@@ -404,318 +449,287 @@ SCheat S9xTextToCheat (char *text)
|
||||
return c;
|
||||
}
|
||||
|
||||
SCheatGroup S9xCreateCheatGroup (const char *name, const char *cheat)
|
||||
std::vector<std::string> split_string(const std::string &str, unsigned char delim)
|
||||
{
|
||||
SCheatGroup g;
|
||||
char *code_string = strdup (cheat);
|
||||
char *code_ptr = code_string;
|
||||
int len;
|
||||
std::vector<std::string> tokens;
|
||||
size_t pos = 0;
|
||||
size_t index;
|
||||
|
||||
g.name = strdup (name);
|
||||
g.enabled = false;
|
||||
|
||||
for (len = strcspn (code_ptr, "+"); len; len = strcspn (code_ptr, "+"))
|
||||
while (pos < str.length())
|
||||
{
|
||||
char *code = code_ptr;
|
||||
code_ptr += len + (code_ptr[len] == '\0' ? 0 : 1);
|
||||
code[len] = '\0';
|
||||
code = trim (code);
|
||||
index = str.find(delim, pos);
|
||||
if (index == std::string::npos)
|
||||
{
|
||||
if (pos < str.length())
|
||||
{
|
||||
tokens.push_back(trim(str.substr(pos)));
|
||||
}
|
||||
|
||||
SCheat c = S9xTextToCheat (code);
|
||||
if (c.address)
|
||||
g.c.push_back (c);
|
||||
break;
|
||||
}
|
||||
else if (index > pos)
|
||||
{
|
||||
tokens.push_back(trim(str.substr(pos, index - pos)));
|
||||
}
|
||||
|
||||
pos = index + 1;
|
||||
}
|
||||
|
||||
delete[] code_string;
|
||||
return tokens;
|
||||
}
|
||||
|
||||
SCheatGroup S9xCreateCheatGroup(const std::string &name, const std::string &cheat)
|
||||
{
|
||||
SCheatGroup g;
|
||||
|
||||
g.name = name;
|
||||
g.enabled = false;
|
||||
|
||||
auto cheats = split_string(cheat, '+');
|
||||
for (const auto &c : cheats)
|
||||
{
|
||||
SCheat new_cheat = S9xTextToCheat(c);
|
||||
if (new_cheat.address)
|
||||
g.cheat.push_back(new_cheat);
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
int S9xAddCheatGroup (const char *name, const char *cheat)
|
||||
int S9xAddCheatGroup(const std::string &name, const std::string &cheat)
|
||||
{
|
||||
SCheatGroup g = S9xCreateCheatGroup (name, cheat);
|
||||
if (g.c.size () == 0)
|
||||
SCheatGroup g = S9xCreateCheatGroup(name, cheat);
|
||||
if (g.cheat.size() == 0)
|
||||
return -1;
|
||||
|
||||
Cheat.g.push_back (g);
|
||||
Cheat.group.push_back(g);
|
||||
|
||||
return Cheat.g.size () - 1;
|
||||
return Cheat.group.size() - 1;
|
||||
}
|
||||
|
||||
int S9xModifyCheatGroup (uint32 num, const char *name, const char *cheat)
|
||||
int S9xModifyCheatGroup(uint32 num, const std::string &name, const std::string &cheat)
|
||||
{
|
||||
if (num >= Cheat.g.size())
|
||||
if (num >= Cheat.group.size())
|
||||
return -1;
|
||||
|
||||
S9xDisableCheatGroup (num);
|
||||
delete[] Cheat.g[num].name;
|
||||
S9xDisableCheatGroup(num);
|
||||
|
||||
Cheat.g[num] = S9xCreateCheatGroup (name, cheat);
|
||||
Cheat.group[num] = S9xCreateCheatGroup(name, cheat);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
char *S9xCheatToText (SCheat *c)
|
||||
std::string S9xCheatToText(const SCheat &c)
|
||||
{
|
||||
int size = 10; /* 6 address, 1 =, 2 byte, 1 NUL */
|
||||
char *text;
|
||||
char output[256]{};
|
||||
|
||||
if (c->conditional)
|
||||
size += 3; /* additional 2 byte, 1 ? */
|
||||
|
||||
text = new char[size];
|
||||
|
||||
if (c->conditional)
|
||||
snprintf (text, size, "%06x=%02x?%02x", c->address, c->cond_byte, c->byte);
|
||||
if (c.conditional)
|
||||
sprintf(output, "%06x=%02x?%02x", c.address, c.cond_byte, c.byte);
|
||||
else
|
||||
snprintf (text, size, "%06x=%02x", c->address, c->byte);
|
||||
sprintf(output, "%06x=%02x", c.address, c.byte);
|
||||
|
||||
return std::string(output);
|
||||
}
|
||||
|
||||
std::string S9xCheatGroupToText(SCheatGroup &g)
|
||||
{
|
||||
std::string text = "";
|
||||
|
||||
for (size_t i = 0; i < g.cheat.size(); i++)
|
||||
{
|
||||
text += S9xCheatToText(g.cheat[i]);
|
||||
if (i != g.cheat.size() - 1)
|
||||
text += "+";
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
char *S9xCheatGroupToText (SCheatGroup *g)
|
||||
std::string S9xCheatValidate(const std::string &code_string)
|
||||
{
|
||||
std::string text = "";
|
||||
unsigned int i;
|
||||
SCheatGroup g = S9xCreateCheatGroup("temp", code_string);
|
||||
|
||||
if (g->c.size () == 0)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < g->c.size (); i++)
|
||||
if (g.cheat.size() > 0)
|
||||
{
|
||||
char *tmp = S9xCheatToText (&g->c[i]);
|
||||
if (i != 0)
|
||||
text += " + ";
|
||||
text += tmp;
|
||||
delete[] tmp;
|
||||
return S9xCheatGroupToText(g);
|
||||
}
|
||||
|
||||
return strdup (text.c_str ());
|
||||
return "";
|
||||
}
|
||||
|
||||
char *S9xCheatValidate (char *code_string)
|
||||
std::string S9xCheatGroupToText(uint32 num)
|
||||
{
|
||||
SCheatGroup g = S9xCreateCheatGroup ("temp", code_string);
|
||||
if (num >= Cheat.group.size())
|
||||
return "";
|
||||
|
||||
delete[] g.name;
|
||||
|
||||
if (g.c.size() > 0)
|
||||
{
|
||||
return S9xCheatGroupToText (&g);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return S9xCheatGroupToText(Cheat.group[num]);
|
||||
}
|
||||
|
||||
char *S9xCheatGroupToText (uint32 num)
|
||||
void S9xUpdateCheatsInMemory(void)
|
||||
{
|
||||
if (num >= Cheat.g.size ())
|
||||
return NULL;
|
||||
|
||||
return S9xCheatGroupToText (&Cheat.g[num]);
|
||||
}
|
||||
|
||||
void S9xUpdateCheatsInMemory (void)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
|
||||
if (!Cheat.enabled)
|
||||
return;
|
||||
|
||||
for (i = 0; i < Cheat.g.size (); i++)
|
||||
{
|
||||
for (j = 0; j < Cheat.g[i].c.size (); j++)
|
||||
{
|
||||
S9xUpdateCheatInMemory (&Cheat.g[i].c[j]);
|
||||
}
|
||||
}
|
||||
for (auto &group : Cheat.group)
|
||||
for (auto &cheat : group.cheat)
|
||||
S9xUpdateCheatInMemory(cheat);
|
||||
}
|
||||
|
||||
static int S9xCheatIsDuplicate (char *name, char *code)
|
||||
static bool S9xCheatIsDuplicate(const std::string &name, const std::string &code)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < Cheat.g.size(); i++)
|
||||
for (size_t i = 0; i < Cheat.group.size(); i++)
|
||||
{
|
||||
if (!strcmp (name, Cheat.g[i].name))
|
||||
if (Cheat.group[i].name == name)
|
||||
{
|
||||
char *code_string = S9xCheatGroupToText (i);
|
||||
char *validated = S9xCheatValidate (code);
|
||||
auto code_string = S9xCheatGroupToText(i);
|
||||
auto validated_string = S9xCheatValidate(code);
|
||||
|
||||
if (validated && !strcmp (code_string, validated))
|
||||
{
|
||||
free (code_string);
|
||||
free (validated);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
free (code_string);
|
||||
free (validated);
|
||||
if (validated_string == code_string)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void S9xLoadCheatsFromBMLNode (bml_node *n)
|
||||
static void S9xLoadCheatsFromBMLNode(bml_node &n)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < n->child.size (); i++)
|
||||
for (auto &c : n.child)
|
||||
{
|
||||
if (!strcasecmp (n->child[i]->name, "cheat"))
|
||||
{
|
||||
char *desc = NULL;
|
||||
char *code = NULL;
|
||||
bool8 enabled = false;
|
||||
if (strcasecmp(c.name.c_str(), "cheat"))
|
||||
continue;
|
||||
|
||||
bml_node *c = n->child[i];
|
||||
bml_node *tmp = NULL;
|
||||
auto subnode = c.find_subnode("code");
|
||||
if (!subnode)
|
||||
continue;
|
||||
std::string code = subnode->data;
|
||||
|
||||
tmp = bml_find_sub(c, "name");
|
||||
if (!tmp)
|
||||
desc = (char *) "";
|
||||
else
|
||||
desc = tmp->data;
|
||||
std::string name;
|
||||
subnode = c.find_subnode("name");
|
||||
if (subnode)
|
||||
name = subnode->data;
|
||||
|
||||
tmp = bml_find_sub(c, "code");
|
||||
if (tmp)
|
||||
code = tmp->data;
|
||||
bool enable = false;
|
||||
if (c.find_subnode("enable"))
|
||||
enable = true;
|
||||
|
||||
if (bml_find_sub(c, "enable"))
|
||||
enabled = true;
|
||||
if (S9xCheatIsDuplicate(name, code))
|
||||
continue;
|
||||
|
||||
if (code && !S9xCheatIsDuplicate (desc, code))
|
||||
{
|
||||
int index = S9xAddCheatGroup (desc, code);
|
||||
|
||||
if (enabled)
|
||||
S9xEnableCheatGroup (index);
|
||||
}
|
||||
}
|
||||
auto index = S9xAddCheatGroup(name, code);
|
||||
if (enable)
|
||||
S9xEnableCheatGroup(index);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static bool8 S9xLoadCheatFileClassic (const char *filename)
|
||||
static bool8 S9xLoadCheatFileClassic(const std::string &filename)
|
||||
{
|
||||
FILE *fs;
|
||||
uint8 data[28];
|
||||
|
||||
fs = fopen(filename, "rb");
|
||||
fs = fopen(filename.c_str(), "rb");
|
||||
if (!fs)
|
||||
return (FALSE);
|
||||
|
||||
while (fread ((void *) data, 1, 28, fs) == 28)
|
||||
while (fread(data, 1, 28, fs) == 28)
|
||||
{
|
||||
SCheat c;
|
||||
char name[21];
|
||||
char cheat[10];
|
||||
c.enabled = (data[0] & 4) == 0;
|
||||
c.byte = data[1];
|
||||
c.address = data[2] | (data[3] << 8) | (data[4] << 16);
|
||||
memcpy (name, &data[8], 20);
|
||||
name[20] = 0;
|
||||
c.address = data[2] | (data[3] << 8) | (data[4] << 16);
|
||||
|
||||
snprintf (cheat, 10, "%x=%x", c.address, c.byte);
|
||||
S9xAddCheatGroup (name, cheat);
|
||||
std::string name((const char *)&data[8], 20);
|
||||
char code[32]{};
|
||||
sprintf(code, "%x=%x", c.address, c.byte);
|
||||
std::string cheat(code);
|
||||
S9xAddCheatGroup(name, cheat);
|
||||
|
||||
if (c.enabled)
|
||||
S9xEnableCheatGroup (Cheat.g.size () - 1);
|
||||
S9xEnableCheatGroup(Cheat.group.size() - 1);
|
||||
}
|
||||
|
||||
fclose(fs);
|
||||
|
||||
return (TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool8 S9xLoadCheatFile (const char *filename)
|
||||
bool8 S9xLoadCheatFile(const std::string &filename)
|
||||
{
|
||||
bml_node *bml = NULL;
|
||||
bml_node *n = NULL;
|
||||
|
||||
bml = bml_parse_file (filename);
|
||||
if (!bml)
|
||||
bml_node bml;
|
||||
if (!bml.parse_file(filename))
|
||||
{
|
||||
return S9xLoadCheatFileClassic (filename);
|
||||
return S9xLoadCheatFileClassic(filename);
|
||||
}
|
||||
|
||||
n = bml_find_sub (bml, "cheat");
|
||||
bml_node *n = bml.find_subnode("cheat");
|
||||
if (n)
|
||||
{
|
||||
S9xLoadCheatsFromBMLNode (bml);
|
||||
S9xLoadCheatsFromBMLNode(bml);
|
||||
}
|
||||
|
||||
bml_free_node (bml);
|
||||
|
||||
if (!n)
|
||||
{
|
||||
return S9xLoadCheatFileClassic (filename);
|
||||
return S9xLoadCheatFileClassic(filename);
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
bool8 S9xSaveCheatFile (const char *filename)
|
||||
bool8 S9xSaveCheatFile(const std::string &filename)
|
||||
{
|
||||
unsigned int i;
|
||||
FILE *file = NULL;
|
||||
|
||||
if (Cheat.g.size () == 0)
|
||||
if (Cheat.group.size() == 0)
|
||||
{
|
||||
remove (filename);
|
||||
remove(filename.c_str());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
file = fopen (filename, "w");
|
||||
file = fopen(filename.c_str(), "w");
|
||||
|
||||
if (!file)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < Cheat.g.size (); i++)
|
||||
for (i = 0; i < Cheat.group.size(); i++)
|
||||
{
|
||||
char *txt = S9xCheatGroupToText (i);
|
||||
|
||||
fprintf (file,
|
||||
"cheat\n"
|
||||
" name: %s\n"
|
||||
" code: %s\n"
|
||||
"%s\n",
|
||||
Cheat.g[i].name ? Cheat.g[i].name : "",
|
||||
txt,
|
||||
Cheat.g[i].enabled ? " enable\n" : ""
|
||||
);
|
||||
|
||||
delete[] txt;
|
||||
fprintf(file,
|
||||
"cheat\n"
|
||||
" name: %s\n"
|
||||
" code: %s\n"
|
||||
"%s\n",
|
||||
Cheat.group[i].name.c_str(),
|
||||
S9xCheatGroupToText(i).c_str(),
|
||||
Cheat.group[i].enabled ? " enable\n" : "");
|
||||
}
|
||||
|
||||
fclose (file);
|
||||
fclose(file);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void S9xCheatsDisable (void)
|
||||
void S9xCheatsDisable(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!Cheat.enabled)
|
||||
return;
|
||||
|
||||
for (i = 0; i < Cheat.g.size (); i++)
|
||||
for (i = 0; i < Cheat.group.size(); i++)
|
||||
{
|
||||
if (Cheat.g[i].enabled)
|
||||
if (Cheat.group[i].enabled)
|
||||
{
|
||||
S9xDisableCheatGroup (i);
|
||||
Cheat.g[i].enabled = TRUE;
|
||||
S9xDisableCheatGroup(i);
|
||||
Cheat.group[i].enabled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
Cheat.enabled = FALSE;
|
||||
}
|
||||
|
||||
void S9xCheatsEnable (void)
|
||||
void S9xCheatsEnable(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -724,27 +738,25 @@ void S9xCheatsEnable (void)
|
||||
|
||||
Cheat.enabled = TRUE;
|
||||
|
||||
for (i = 0; i < Cheat.g.size (); i++)
|
||||
for (i = 0; i < Cheat.group.size(); i++)
|
||||
{
|
||||
if (Cheat.g[i].enabled)
|
||||
if (Cheat.group[i].enabled)
|
||||
{
|
||||
Cheat.g[i].enabled = FALSE;
|
||||
S9xEnableCheatGroup (i);
|
||||
Cheat.group[i].enabled = FALSE;
|
||||
S9xEnableCheatGroup(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int S9xImportCheatsFromDatabase (const char *filename)
|
||||
int S9xImportCheatsFromDatabase(const std::string &filename)
|
||||
{
|
||||
bml_node *bml;
|
||||
char sha256_txt[65];
|
||||
char hextable[] = "0123456789abcdef";
|
||||
unsigned int i;
|
||||
|
||||
bml = bml_parse_file (filename);
|
||||
|
||||
if (!bml)
|
||||
return -1; /* No file */
|
||||
bml_node bml;
|
||||
if (!bml.parse_file(filename))
|
||||
return -1; // No file
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
@@ -753,25 +765,19 @@ int S9xImportCheatsFromDatabase (const char *filename)
|
||||
}
|
||||
sha256_txt[64] = '\0';
|
||||
|
||||
for (i = 0; i < bml->child.size (); i++)
|
||||
for (auto &c : bml.child)
|
||||
{
|
||||
if (!strcasecmp (bml->child[i]->name, "cartridge"))
|
||||
if (!strcasecmp(c.name.c_str(), "cartridge"))
|
||||
{
|
||||
bml_node *n;
|
||||
auto n = c.find_subnode("sha256");
|
||||
|
||||
if ((n = bml_find_sub (bml->child[i], "sha256")))
|
||||
if (n && !strcasecmp(n->data.c_str(), sha256_txt))
|
||||
{
|
||||
if (!strcasecmp (n->data, sha256_txt))
|
||||
{
|
||||
S9xLoadCheatsFromBMLNode (bml->child[i]);
|
||||
bml_free_node (bml);
|
||||
return 0;
|
||||
}
|
||||
S9xLoadCheatsFromBMLNode(c);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bml_free_node (bml);
|
||||
|
||||
return -2; /* No codes */
|
||||
}
|
||||
|
||||
Executable → Regular
@@ -0,0 +1,67 @@
|
||||
#include <cstring>
|
||||
#include "port.h"
|
||||
|
||||
void _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext)
|
||||
{
|
||||
char *slash = strrchr((char *)path, SLASH_CHAR);
|
||||
char *dot = strrchr((char *)path, '.');
|
||||
|
||||
*drive = '\0';
|
||||
|
||||
if (dot && slash && dot < slash)
|
||||
{
|
||||
dot = 0;
|
||||
}
|
||||
|
||||
if (!slash)
|
||||
{
|
||||
*dir = '\0';
|
||||
strcpy(fname, path);
|
||||
|
||||
if (dot)
|
||||
{
|
||||
fname[dot - path] = '\0';
|
||||
strcpy(ext, dot + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ext = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(dir, path);
|
||||
dir[slash - path] = '\0';
|
||||
strcpy(fname, slash + 1);
|
||||
|
||||
if (dot)
|
||||
{
|
||||
fname[(dot - slash) - 1] = '\0';
|
||||
strcpy(ext, dot + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ext = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext)
|
||||
{
|
||||
if (dir && *dir)
|
||||
{
|
||||
strcpy(path, dir);
|
||||
strcat(path, "/");
|
||||
}
|
||||
else
|
||||
*path = '\0';
|
||||
|
||||
strcat(path, fname);
|
||||
|
||||
if (ext && *ext)
|
||||
{
|
||||
if (*ext != '.')
|
||||
strcat(path, ".");
|
||||
strcat(path, ext);
|
||||
}
|
||||
}
|
||||
Executable → Regular
+1
-1
@@ -452,7 +452,7 @@ void ConfigFile::ClearLines()
|
||||
}
|
||||
}
|
||||
|
||||
bool ConfigFile::ConfigEntry::section_then_key_less::operator()(const ConfigEntry &a, const ConfigEntry &b) {
|
||||
bool ConfigFile::ConfigEntry::section_then_key_less::operator()(const ConfigEntry &a, const ConfigEntry &b) const{
|
||||
if(curConfigFile && a.section!=b.section){
|
||||
const int sva = curConfigFile->GetSectionSize(a.section);
|
||||
const int svb = curConfigFile->GetSectionSize(b.section);
|
||||
|
||||
Executable → Regular
+3
-3
@@ -90,7 +90,7 @@ class ConfigFile {
|
||||
mutable bool used;
|
||||
|
||||
struct section_then_key_less {
|
||||
bool operator()(const ConfigEntry &a, const ConfigEntry &b);
|
||||
bool operator()(const ConfigEntry &a, const ConfigEntry &b) const;
|
||||
};
|
||||
|
||||
struct key_less {
|
||||
@@ -101,8 +101,8 @@ class ConfigFile {
|
||||
};
|
||||
|
||||
struct line_less {
|
||||
bool operator()(const ConfigEntry &a, const ConfigEntry &b){
|
||||
if(a.line==b.line) return (b.val.empty() && !a.val.empty()) || a.key<b.key;
|
||||
bool operator()(const ConfigEntry &a, const ConfigEntry &b) const{
|
||||
if(a.line==b.line) return (b.val.empty() && !a.val.empty()) || a.key<b.key;
|
||||
if(b.line<0) return true;
|
||||
if(a.line<0) return false;
|
||||
return a.line<b.line;
|
||||
|
||||
Executable → Regular
+57
-76
@@ -328,14 +328,12 @@ static void DoGunLatch (int x, int y)
|
||||
|
||||
if (x > 295)
|
||||
x = 295;
|
||||
else
|
||||
if (x < 40)
|
||||
else if (x < 40)
|
||||
x = 40;
|
||||
|
||||
if (y > PPU.ScreenHeight - 1)
|
||||
y = PPU.ScreenHeight - 1;
|
||||
else
|
||||
if (y < 0)
|
||||
else if (y < 0)
|
||||
y = 0;
|
||||
|
||||
PPU.GunVLatch = (uint16) (y + 1);
|
||||
@@ -1164,8 +1162,7 @@ s9xcommand_t S9xGetCommandT (const char *name)
|
||||
|
||||
if (!strcmp(name, "None"))
|
||||
cmd.type = S9xNoMapping;
|
||||
else
|
||||
if (!strncmp(name, "Joypad", 6))
|
||||
else if (!strncmp(name, "Joypad", 6))
|
||||
{
|
||||
if (name[6] < '1' || name[6] > '8' || name[7] != ' ')
|
||||
return (cmd);
|
||||
@@ -1176,24 +1173,15 @@ s9xcommand_t S9xGetCommandT (const char *name)
|
||||
s = name + 13;
|
||||
|
||||
if (!strncmp(s, "Left/Right ", 11)) { j = 0; i = 0; s += 11; }
|
||||
else
|
||||
if (!strncmp(s, "Right/Left ", 11)) { j = 0; i = 1; s += 11; }
|
||||
else
|
||||
if (!strncmp(s, "Up/Down ", 8)) { j = 1; i = 0; s += 8; }
|
||||
else
|
||||
if (!strncmp(s, "Down/Up ", 8)) { j = 1; i = 1; s += 8; }
|
||||
else
|
||||
if (!strncmp(s, "Y/A ", 4)) { j = 2; i = 0; s += 4; }
|
||||
else
|
||||
if (!strncmp(s, "A/Y ", 4)) { j = 2; i = 1; s += 4; }
|
||||
else
|
||||
if (!strncmp(s, "X/B ", 4)) { j = 3; i = 0; s += 4; }
|
||||
else
|
||||
if (!strncmp(s, "B/X ", 4)) { j = 3; i = 1; s += 4; }
|
||||
else
|
||||
if (!strncmp(s, "L/R ", 4)) { j = 4; i = 0; s += 4; }
|
||||
else
|
||||
if (!strncmp(s, "R/L ", 4)) { j = 4; i = 1; s += 4; }
|
||||
else if (!strncmp(s, "Right/Left ", 11)) { j = 0; i = 1; s += 11; }
|
||||
else if (!strncmp(s, "Up/Down ", 8)) { j = 1; i = 0; s += 8; }
|
||||
else if (!strncmp(s, "Down/Up ", 8)) { j = 1; i = 1; s += 8; }
|
||||
else if (!strncmp(s, "Y/A ", 4)) { j = 2; i = 0; s += 4; }
|
||||
else if (!strncmp(s, "A/Y ", 4)) { j = 2; i = 1; s += 4; }
|
||||
else if (!strncmp(s, "X/B ", 4)) { j = 3; i = 0; s += 4; }
|
||||
else if (!strncmp(s, "B/X ", 4)) { j = 3; i = 1; s += 4; }
|
||||
else if (!strncmp(s, "L/R ", 4)) { j = 4; i = 0; s += 4; }
|
||||
else if (!strncmp(s, "R/L ", 4)) { j = 4; i = 1; s += 4; }
|
||||
else
|
||||
return (cmd);
|
||||
|
||||
@@ -1374,8 +1362,7 @@ s9xcommand_t S9xGetCommandT (const char *name)
|
||||
|
||||
if (*s == 'h')
|
||||
cmd.axis.pointer.HV = 0;
|
||||
else
|
||||
if (*s == 'v')
|
||||
else if (*s == 'v')
|
||||
cmd.axis.pointer.HV = 1;
|
||||
else
|
||||
return (cmd);
|
||||
@@ -1523,8 +1510,7 @@ s9xcommand_t S9xGetCommandT (const char *name)
|
||||
|
||||
j = i;
|
||||
}
|
||||
else
|
||||
if (name[i] == ',')
|
||||
else if (name[i] == ',')
|
||||
{
|
||||
free(c);
|
||||
return (cmd);
|
||||
@@ -1537,8 +1523,7 @@ s9xcommand_t S9xGetCommandT (const char *name)
|
||||
{
|
||||
if (name[i] == '+')
|
||||
press = 1;
|
||||
else
|
||||
if (name[i] == '-')
|
||||
else if (name[i] == '-')
|
||||
press = 2;
|
||||
else
|
||||
{
|
||||
@@ -2007,14 +1992,12 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
|
||||
uint16 x = r; r = st; st = x;
|
||||
x = s; s = t; t = x;
|
||||
}
|
||||
else
|
||||
if (cmd.button.joypad.turbo)
|
||||
else if (cmd.button.joypad.turbo)
|
||||
{
|
||||
uint16 x = r; r = t; t = x;
|
||||
x = s; s = st; st = x;
|
||||
}
|
||||
else
|
||||
if (cmd.button.joypad.sticky)
|
||||
else if (cmd.button.joypad.sticky)
|
||||
{
|
||||
uint16 x = r; r = s; s = x;
|
||||
x = t; t = st; st = x;
|
||||
@@ -2269,25 +2252,19 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
|
||||
break;
|
||||
|
||||
case LoadFreezeFile:
|
||||
S9xUnfreezeGame(S9xChooseFilename(TRUE));
|
||||
break;
|
||||
|
||||
case SaveFreezeFile:
|
||||
S9xFreezeGame(S9xChooseFilename(FALSE));
|
||||
break;
|
||||
|
||||
case LoadOopsFile:
|
||||
{
|
||||
char filename[PATH_MAX + 1];
|
||||
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
|
||||
std::string filename = S9xGetFilename("oops", SNAPSHOT_DIR);
|
||||
|
||||
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
|
||||
snprintf(filename, PATH_MAX + 1, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, _MAX_EXT - 1, "oops");
|
||||
|
||||
if (S9xUnfreezeGame(filename))
|
||||
if (S9xUnfreezeGame(filename.c_str()))
|
||||
{
|
||||
snprintf(buf, 256, "%s.%.*s loaded", def, _MAX_EXT - 1, "oops");
|
||||
S9xSetInfoString (buf);
|
||||
snprintf(buf, 256, "%.240s.oops loaded", S9xBasename(Memory.ROMFilename).c_str());
|
||||
S9xSetInfoString(buf);
|
||||
}
|
||||
else
|
||||
S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, "Oops file not found");
|
||||
@@ -2315,15 +2292,15 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
|
||||
case QuickLoad009:
|
||||
case QuickLoad010:
|
||||
{
|
||||
char filename[PATH_MAX + 1];
|
||||
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
|
||||
std::string ext = std::to_string(i - QuickLoad000);
|
||||
while (ext.length() < 3)
|
||||
ext = '0' + ext;
|
||||
|
||||
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
|
||||
snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickLoad000);
|
||||
auto filename = S9xGetFilename(ext, SNAPSHOT_DIR);
|
||||
|
||||
if (S9xUnfreezeGame(filename))
|
||||
if (S9xUnfreezeGame(filename.c_str()))
|
||||
{
|
||||
snprintf(buf, 256, "%s.%03d loaded", def, i - QuickLoad000);
|
||||
snprintf(buf, 256, "Quick save-state %s loaded", ext.c_str());
|
||||
S9xSetInfoString(buf);
|
||||
}
|
||||
else
|
||||
@@ -2344,16 +2321,16 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
|
||||
case QuickSave009:
|
||||
case QuickSave010:
|
||||
{
|
||||
char filename[PATH_MAX + 1];
|
||||
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
|
||||
std::string ext = std::to_string(i - QuickLoad000);
|
||||
while (ext.length() < 3)
|
||||
ext = '0' + ext;
|
||||
|
||||
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
|
||||
snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickSave000);
|
||||
auto filename = S9xGetFilename(ext, SNAPSHOT_DIR);
|
||||
|
||||
snprintf(buf, 256, "%s.%03d saved", def, i - QuickSave000);
|
||||
snprintf(buf, 256, "Quick save-state %s saved", ext.c_str());
|
||||
S9xSetInfoString(buf);
|
||||
|
||||
S9xFreezeGame(filename);
|
||||
S9xFreezeGame(filename.c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2414,15 +2391,15 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
|
||||
break;
|
||||
|
||||
case BeginRecordingMovie:
|
||||
if (S9xMovieActive())
|
||||
S9xMovieStop(FALSE);
|
||||
S9xMovieCreate(S9xChooseMovieFilename(FALSE), 0xFF, MOVIE_OPT_FROM_RESET, NULL, 0);
|
||||
// if (S9xMovieActive())
|
||||
// S9xMovieStop(FALSE);
|
||||
// S9xMovieCreate(S9xChooseMovieFilename(FALSE), 0xFF, MOVIE_OPT_FROM_RESET, NULL, 0);
|
||||
break;
|
||||
|
||||
case LoadMovie:
|
||||
if (S9xMovieActive())
|
||||
S9xMovieStop(FALSE);
|
||||
S9xMovieOpen(S9xChooseMovieFilename(TRUE), FALSE);
|
||||
// if (S9xMovieActive())
|
||||
// S9xMovieStop(FALSE);
|
||||
// S9xMovieOpen(S9xChooseMovieFilename(TRUE), FALSE);
|
||||
break;
|
||||
|
||||
case EndRecordingMovie:
|
||||
@@ -2773,14 +2750,12 @@ static void UpdatePolledMouse (int i)
|
||||
mouse[i - MOUSE0].delta_x = 0xff;
|
||||
mouse[i - MOUSE0].old_x -= 127;
|
||||
}
|
||||
else
|
||||
if (j < 0)
|
||||
else if (j < 0)
|
||||
{
|
||||
mouse[i - MOUSE0].delta_x = 0x80 | -j;
|
||||
mouse[i - MOUSE0].old_x = mouse[i - MOUSE0].cur_x;
|
||||
}
|
||||
else
|
||||
if (j > 127)
|
||||
else if (j > 127)
|
||||
{
|
||||
mouse[i - MOUSE0].delta_x = 0x7f;
|
||||
mouse[i - MOUSE0].old_x += 127;
|
||||
@@ -2798,14 +2773,12 @@ static void UpdatePolledMouse (int i)
|
||||
mouse[i - MOUSE0].delta_y = 0xff;
|
||||
mouse[i - MOUSE0].old_y -= 127;
|
||||
}
|
||||
else
|
||||
if (j < 0)
|
||||
else if (j < 0)
|
||||
{
|
||||
mouse[i - MOUSE0].delta_y = 0x80 | -j;
|
||||
mouse[i - MOUSE0].old_y = mouse[i - MOUSE0].cur_y;
|
||||
}
|
||||
else
|
||||
if (j > 127)
|
||||
else if (j > 127)
|
||||
{
|
||||
mouse[i - MOUSE0].delta_y = 0x7f;
|
||||
mouse[i - MOUSE0].old_y += 127;
|
||||
@@ -3267,8 +3240,7 @@ void S9xControlEOF (void)
|
||||
pseudopointer[n].x += pseudopointer[n].H_adj;
|
||||
if (pseudopointer[n].x < 0)
|
||||
pseudopointer[n].x = 0;
|
||||
else
|
||||
if (pseudopointer[n].x > 255)
|
||||
else if (pseudopointer[n].x > 255)
|
||||
pseudopointer[n].x = 255;
|
||||
|
||||
if (pseudopointer[n].H_var)
|
||||
@@ -3291,8 +3263,7 @@ void S9xControlEOF (void)
|
||||
pseudopointer[n].y += pseudopointer[n].V_adj;
|
||||
if (pseudopointer[n].y < 0)
|
||||
pseudopointer[n].y = 0;
|
||||
else
|
||||
if (pseudopointer[n].y > PPU.ScreenHeight - 1)
|
||||
else if (pseudopointer[n].y > PPU.ScreenHeight - 1)
|
||||
pseudopointer[n].y = PPU.ScreenHeight - 1;
|
||||
|
||||
if (pseudopointer[n].V_var)
|
||||
@@ -3515,11 +3486,17 @@ void S9xControlPreSaveState (struct SControlSnapshot *s)
|
||||
for (int k = 0; k < 2; k++)
|
||||
COPY(mp5[j].pads[k]);
|
||||
|
||||
assert(i == sizeof(s->internal));
|
||||
|
||||
#undef COPY
|
||||
#define COPY(x) { memcpy((char *) s->internal_macs + i, &(x), sizeof(x)); i += sizeof(x); }
|
||||
i = 0;
|
||||
|
||||
COPY(macsrifle.x);
|
||||
COPY(macsrifle.y);
|
||||
COPY(macsrifle.buttons);
|
||||
|
||||
assert(i == sizeof(s->internal) + sizeof(s->internal_macs));
|
||||
assert(i == sizeof(s->internal_macs));
|
||||
|
||||
#undef COPY
|
||||
|
||||
@@ -3594,11 +3571,15 @@ void S9xControlPostLoadState (struct SControlSnapshot *s)
|
||||
|
||||
if (s->ver > 3)
|
||||
{
|
||||
#undef COPY
|
||||
#define COPY(x) { memcpy(&(x), (char *) s->internal_macs + i, sizeof(x)); i += sizeof(x); }
|
||||
i = 0;
|
||||
|
||||
COPY(macsrifle.x);
|
||||
COPY(macsrifle.y);
|
||||
COPY(macsrifle.buttons);
|
||||
|
||||
assert(i == sizeof(s->internal) + sizeof(s->internal_macs));
|
||||
assert(i == sizeof(s->internal_macs));
|
||||
}
|
||||
|
||||
#undef COPY
|
||||
|
||||
Executable → Regular
Executable → Regular
+2
-5
@@ -13,7 +13,6 @@
|
||||
#include "srtc.h"
|
||||
#include "snapshot.h"
|
||||
#include "cheats.h"
|
||||
#include "logger.h"
|
||||
#ifdef DEBUGGER
|
||||
#include "debug.h"
|
||||
#endif
|
||||
@@ -76,7 +75,6 @@ static void S9xSoftResetCPU (void)
|
||||
SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation);
|
||||
ClearFlags(Decimal);
|
||||
|
||||
Timings.InterlaceField = FALSE;
|
||||
Timings.H_Max = Timings.H_Max_Master;
|
||||
Timings.V_Max = Timings.V_Max_Master;
|
||||
Timings.NMITriggerPos = 0xffff;
|
||||
@@ -99,10 +97,9 @@ static void S9xSoftResetCPU (void)
|
||||
void S9xReset (void)
|
||||
{
|
||||
S9xResetSaveTimer(FALSE);
|
||||
S9xResetLogger();
|
||||
|
||||
memset(Memory.RAM, 0x55, 0x20000);
|
||||
memset(Memory.VRAM, 0x00, 0x10000);
|
||||
memset(Memory.RAM, 0x55, sizeof(Memory.RAM));
|
||||
memset(Memory.VRAM, 0x00, sizeof(Memory.VRAM));
|
||||
memset(Memory.FillRAM, 0, 0x8000);
|
||||
|
||||
S9xResetBSX();
|
||||
|
||||
Executable → Regular
-1
@@ -513,7 +513,6 @@ static inline uint32 StackRelativeIndirectIndexed (AccessMode a) // (d,S),Y
|
||||
if (a & READ)
|
||||
OpenBus = (uint8) (addr >> 8);
|
||||
addr = (addr + Registers.Y.W + ICPU.ShiftedDB) & 0xffffff;
|
||||
AddCycles(ONE_CYCLE);
|
||||
|
||||
return (addr);
|
||||
}
|
||||
|
||||
Executable → Regular
+9
-11
@@ -132,13 +132,6 @@ void S9xMainLoop (void)
|
||||
|
||||
if (CPU.Flags & SCAN_KEYS_FLAG)
|
||||
{
|
||||
#ifdef DEBUGGER
|
||||
if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
|
||||
#endif
|
||||
{
|
||||
S9xSyncSpeed();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -276,7 +269,6 @@ void S9xDoHEventProcessing (void)
|
||||
if (CPU.V_Counter >= Timings.V_Max) // V ranges from 0 to Timings.V_Max - 1
|
||||
{
|
||||
CPU.V_Counter = 0;
|
||||
Timings.InterlaceField ^= 1;
|
||||
|
||||
// From byuu:
|
||||
// [NTSC]
|
||||
@@ -285,7 +277,7 @@ void S9xDoHEventProcessing (void)
|
||||
// [PAL] <PAL info is unverified on hardware>
|
||||
// interlace mode has 625 scanlines: 313 on the even frame, and 312 on the odd.
|
||||
// non-interlace mode has 624 scanlines: 312 scanlines on both even and odd frames.
|
||||
if (IPPU.Interlace && !Timings.InterlaceField)
|
||||
if (IPPU.Interlace && S9xInterlaceField())
|
||||
Timings.V_Max = Timings.V_Max_Master + 1; // 263 (NTSC), 313?(PAL)
|
||||
else
|
||||
Timings.V_Max = Timings.V_Max_Master; // 262 (NTSC), 312?(PAL)
|
||||
@@ -306,14 +298,14 @@ void S9xDoHEventProcessing (void)
|
||||
// In interlace mode, there are always 341 dots per scanline. Even frames have 263 scanlines,
|
||||
// and odd frames have 262 scanlines.
|
||||
// Interlace mode scanline 240 on odd frames is not missing a dot.
|
||||
if (CPU.V_Counter == 240 && !IPPU.Interlace && Timings.InterlaceField) // V=240
|
||||
if (CPU.V_Counter == 240 && !IPPU.Interlace && S9xInterlaceField()) // V=240
|
||||
Timings.H_Max = Timings.H_Max_Master - ONE_DOT_CYCLE; // HC=1360
|
||||
else
|
||||
Timings.H_Max = Timings.H_Max_Master; // HC=1364
|
||||
|
||||
if (Model->_5A22 == 2)
|
||||
{
|
||||
if (CPU.V_Counter != 240 || IPPU.Interlace || !Timings.InterlaceField) // V=240
|
||||
if (CPU.V_Counter != 240 || IPPU.Interlace || !S9xInterlaceField()) // V=240
|
||||
{
|
||||
if (Timings.WRAMRefreshPos == SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE) // HC=534
|
||||
Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; // HC=538
|
||||
@@ -327,6 +319,12 @@ void S9xDoHEventProcessing (void)
|
||||
if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240).
|
||||
{
|
||||
S9xEndScreenRefresh();
|
||||
#ifdef DEBUGGER
|
||||
if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
|
||||
#endif
|
||||
{
|
||||
S9xSyncSpeed();
|
||||
}
|
||||
|
||||
CPU.Flags |= SCAN_KEYS_FLAG;
|
||||
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
+15
-7
@@ -1406,11 +1406,13 @@ bOP(70Slow, RelativeSlow, CheckOverflow(), 0, CheckEmulation())
|
||||
static void Op82 (void)
|
||||
{
|
||||
S9xSetPCBase(ICPU.ShiftedPB + RelativeLong(JUMP));
|
||||
AddCycles(ONE_CYCLE);
|
||||
}
|
||||
|
||||
static void Op82Slow (void)
|
||||
{
|
||||
S9xSetPCBase(ICPU.ShiftedPB + RelativeLongSlow(JUMP));
|
||||
AddCycles(ONE_CYCLE);
|
||||
}
|
||||
|
||||
/* Flag Instructions ******************************************************* */
|
||||
@@ -2847,6 +2849,7 @@ static void Op22E1 (void)
|
||||
// Note: JSL is a new instruction,
|
||||
// and so doesn't respect the emu-mode stack bounds.
|
||||
uint32 addr = AbsoluteLong(JSR);
|
||||
AddCycles(ONE_CYCLE);
|
||||
PushB(Registers.PB);
|
||||
PushW(Registers.PCw - 1);
|
||||
Registers.SH = 1;
|
||||
@@ -2856,6 +2859,7 @@ static void Op22E1 (void)
|
||||
static void Op22E0 (void)
|
||||
{
|
||||
uint32 addr = AbsoluteLong(JSR);
|
||||
AddCycles(ONE_CYCLE);
|
||||
PushB(Registers.PB);
|
||||
PushW(Registers.PCw - 1);
|
||||
S9xSetPCBase(addr);
|
||||
@@ -2864,6 +2868,7 @@ static void Op22E0 (void)
|
||||
static void Op22Slow (void)
|
||||
{
|
||||
uint32 addr = AbsoluteLongSlow(JSR);
|
||||
AddCycles(ONE_CYCLE);
|
||||
PushB(Registers.PB);
|
||||
PushW(Registers.PCw - 1);
|
||||
if (CheckEmulation())
|
||||
@@ -3381,16 +3386,19 @@ static void Op42 (void)
|
||||
#endif
|
||||
|
||||
case 0x42: // "WDM" = Snapshot
|
||||
char filename[PATH_MAX + 1], drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[PATH_MAX + 1], ext[_MAX_EXT + 1];
|
||||
{
|
||||
char tmp[PATH_MAX + 1];
|
||||
SplitPath split = splitpath(Memory.ROMFilename);
|
||||
|
||||
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
|
||||
snprintf(filename, PATH_MAX, "%s%s%s-%06X.wdm", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, Registers.PBPC & 0xffffff);
|
||||
sprintf(def, "WDM Snapshot at $%02X:%04X: %s", Registers.PB, Registers.PCw, filename);
|
||||
S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, def);
|
||||
S9xFreezeGame(filename);
|
||||
snprintf(tmp, PATH_MAX, "%s-%06X", split.stem.c_str(), Registers.PBPC & 0xffffff);
|
||||
std::string filename = makepath(split.dir, S9xGetDirectory(SNAPSHOT_DIR), tmp, ".wdm");
|
||||
|
||||
break;
|
||||
sprintf(tmp, "WDM Snapshot at $%02X:%04X: %s", Registers.PB, Registers.PCw, filename.c_str());
|
||||
S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, tmp);
|
||||
S9xFreezeGame(filename.c_str());
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
-24
@@ -9,24 +9,6 @@
|
||||
|
||||
#include "snes9x.h"
|
||||
|
||||
enum s9x_getdirtype
|
||||
{
|
||||
DEFAULT_DIR = 0,
|
||||
HOME_DIR,
|
||||
ROMFILENAME_DIR,
|
||||
ROM_DIR,
|
||||
SRAM_DIR,
|
||||
SNAPSHOT_DIR,
|
||||
SCREENSHOT_DIR,
|
||||
SPC_DIR,
|
||||
CHEAT_DIR,
|
||||
PATCH_DIR,
|
||||
BIOS_DIR,
|
||||
LOG_DIR,
|
||||
SAT_DIR,
|
||||
LAST_DIR
|
||||
};
|
||||
|
||||
void S9xUsage (void);
|
||||
char * S9xParseArgs (char **, int);
|
||||
void S9xParseArgsForCheats (char **, int);
|
||||
@@ -40,16 +22,10 @@ void S9xInitDisplay (int, char **);
|
||||
void S9xDeinitDisplay (void);
|
||||
void S9xTextMode (void);
|
||||
void S9xGraphicsMode (void);
|
||||
void S9xSetPalette (void);
|
||||
void S9xToggleSoundChannel (int);
|
||||
bool8 S9xOpenSnapshotFile (const char *, bool8, STREAM *);
|
||||
void S9xCloseSnapshotFile (STREAM);
|
||||
const char * S9xStringInput (const char *);
|
||||
const char * S9xGetDirectory (enum s9x_getdirtype);
|
||||
const char * S9xGetFilename (const char *, enum s9x_getdirtype);
|
||||
const char * S9xGetFilenameInc (const char *, enum s9x_getdirtype);
|
||||
const char * S9xChooseFilename (bool8);
|
||||
const char * S9xBasename (const char *);
|
||||
|
||||
// Routines the port has to implement if it uses command-line
|
||||
|
||||
|
||||
Executable → Regular
Executable → Regular
+64
@@ -1,3 +1,67 @@
|
||||
Snes9x 1.62
|
||||
- Fixed SA1 division with negative dividend again. (Atari2)
|
||||
- Fixed timing on several instructions. (pi1541)
|
||||
- MSU1 audio with no loop point will not repeat from start.
|
||||
- Modernized some old memory-related code.
|
||||
- Fixed a desynchronization in interlaced modes and reporting.
|
||||
- Remove SA1 access to WRAM.
|
||||
- Added second set of registers between S-DSP and S-SMP. Fixes
|
||||
PAL version of Virtual Bart.
|
||||
|
||||
Gtk + Windows:
|
||||
- Added a Vulkan graphics output method. Similar to OpenGL, this
|
||||
can use libretro's slang shaders.
|
||||
- Changed the automatic frame skip throttle to take place immediately
|
||||
before showing the frame, making VRR work better.
|
||||
- Add menu item to clear recent files entries.
|
||||
- Add fixed window size changes up to 10x.
|
||||
|
||||
Windows:
|
||||
- Improved the shader parameters dialog with sliders and resize.
|
||||
- Allow disabling adding registry entries. Deletes any existing
|
||||
entries when the option is disabled.
|
||||
|
||||
Gtk:
|
||||
- Switched to CMake for build system. Removed meson.
|
||||
- Fixed some keys not working with modifiers. (Gutawer)
|
||||
- Removed graphics options most people won't understand or need.
|
||||
- Improved wayland support. Handle fractional DPI properly.
|
||||
|
||||
Snes9x 1.61
|
||||
- Restructured tile.cpp tile renderer from heavy macros into C++
|
||||
templates, significantly lowering compile time. (yoffy)
|
||||
- MichaelBuckley provided a brand new MacOS port that is completely
|
||||
rewritten based on newer, supported APIs.
|
||||
- Fixed an out-of-bound memory access in sound DSP. (Sour, byuu)
|
||||
- Revert default SFX2 clock speed increase.
|
||||
- Added a render position hack. Fixes glitches in several games.
|
||||
- Allow an SRAM mapping up to 128KB.
|
||||
|
||||
Win32:
|
||||
- Apply turbo mode volume when rewinding.
|
||||
- Added menu entry to load oops files, and an option to confirm before
|
||||
saving or loading states.
|
||||
- Fixed sound volume resetting when sound reinitializes.
|
||||
- Added a save-state preview dialog.
|
||||
- Added save banks for up to 100 states
|
||||
- Added support for relative-style save slots
|
||||
- Fixed blargg rf filter.
|
||||
- Show command line options on -h and /?
|
||||
|
||||
Gtk:
|
||||
- Added an option to show time. (taimoorgit)
|
||||
- Use a submodule for glslang, because it doesn't guarantee API stability.
|
||||
- Switched to GTK's C++ interface, gtkmm3. This effectively drops
|
||||
GTK+ 2.0 support.
|
||||
- Joysticks can now be hotplugged. (jraby)
|
||||
|
||||
Unix:
|
||||
- Added audio output threading. (yoffy)
|
||||
- Added screensaver prevention on joystick use. (greg-kennedy)
|
||||
- Fix YUY2 conversion. (greg-kennedy)
|
||||
- Add alsa output support. (cjacker)
|
||||
- Add I420 conversion. (cjacker)
|
||||
|
||||
Snes9x 1.60
|
||||
- Fixed subscreen blending with master brightness < 100%.
|
||||
- Fixed NMI timing when toggling enable bit. Fixes Chou Aniki--hack removed.
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
+1
-13
@@ -12,7 +12,7 @@
|
||||
<body>
|
||||
<h1 style="text-align:center">How to Port Snes9x to a New Platform</h1>
|
||||
<div style="text-align:right">
|
||||
Version: 1.60<br>
|
||||
Version: 1.61<br>
|
||||
</div>
|
||||
<h2>Introduction</h2>
|
||||
<p>
|
||||
@@ -298,14 +298,6 @@
|
||||
<p>
|
||||
Called when Snes9x wants to know the directory <code>dirtype</code>.
|
||||
</p>
|
||||
<h3><code>const char *S9xChooseFilename (bool8 read_only)</code></h3>
|
||||
<p>
|
||||
If your port can match Snes9x's built-in <code>LoadFreezeFile</code>/<code>SaveFreezeFile</code> command (see <code>controls.cpp</code>), you may choose to use this function. Otherwise return <code>NULL</code>.
|
||||
</p>
|
||||
<h3><code>const char *S9xChooseMovieFilename (bool8 read_only)</code></h3>
|
||||
<p>
|
||||
If your port can match Snes9x's built-in <code>BeginRecordingMovie</code>/<code>LoadMovie</code> command (see <code>controls.cpp</code>), you may choose to use this function. Otherwise return <code>NULL</code>.
|
||||
</p>
|
||||
<h3><code>const char *S9xBasename (const char *path)</code></h3>
|
||||
<p>
|
||||
Called when Snes9x wants to know the name of the ROM image. Typically, extract the filename from <code>path</code> and return it.
|
||||
@@ -318,10 +310,6 @@
|
||||
<p>
|
||||
If your port can match Snes9x's built-in <code>SoundChannelXXX</code> command (see <code>controls.cpp</code>), you may choose to use this function. Otherwise return <code>NULL</code>. Basically, turn on/off the sound channel <code>c</code> (0-7), and turn on all channels if <code>c</code> is 8.
|
||||
</p>
|
||||
<h3><code>void S9xSetPalette (void)</code></h3>
|
||||
<p>
|
||||
Called when the SNES color palette has changed. Use this function if your system needs to change its color palette to match the SNES's. Otherwise, leave it empty.
|
||||
</p>
|
||||
<h3><code>void S9xSyncSpeed (void)</code></h3>
|
||||
<p>
|
||||
Called at the end of <code>S9xMainLoop</code> function, when emulating one frame has been done. You should adjust the frame rate in this function.
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+184
-204
@@ -316,11 +316,17 @@ static void DSP1_Inverse (int16 Coefficient, int16 Exponent, int16 *iCoefficient
|
||||
}
|
||||
|
||||
// Step Three: Normalize
|
||||
#ifdef __GNUC__
|
||||
const int shift = __builtin_clz(Coefficient) - (8 * sizeof(int) - 15);
|
||||
Coefficient <<= shift;
|
||||
Exponent -= shift;
|
||||
#else
|
||||
while (Coefficient < 0x4000)
|
||||
{
|
||||
Coefficient <<= 1;
|
||||
Exponent--;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Step Four: Special Case
|
||||
if (Coefficient == 0x4000)
|
||||
@@ -398,9 +404,18 @@ static int16 DSP1_Cos (int16 Angle)
|
||||
|
||||
static void DSP1_Normalize (int16 m, int16 *Coefficient, int16 *Exponent)
|
||||
{
|
||||
int16 i = 0x4000;
|
||||
int16 e = 0;
|
||||
|
||||
#ifdef __GNUC__
|
||||
int16 n = m < 0 ? ~m : m;
|
||||
|
||||
if (n == 0)
|
||||
e = 15;
|
||||
else
|
||||
e = __builtin_clz(n) - (8 * sizeof(int) - 15);
|
||||
#else
|
||||
int16 i = 0x4000;
|
||||
|
||||
if (m < 0)
|
||||
{
|
||||
while ((m & i) && i)
|
||||
@@ -417,6 +432,7 @@ static void DSP1_Normalize (int16 m, int16 *Coefficient, int16 *Exponent)
|
||||
e++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (e > 0)
|
||||
*Coefficient = m * DSP1ROM[0x21 + e] << 1;
|
||||
@@ -430,9 +446,18 @@ static void DSP1_NormalizeDouble (int32 Product, int16 *Coefficient, int16 *Expo
|
||||
{
|
||||
int16 n = Product & 0x7fff;
|
||||
int16 m = Product >> 15;
|
||||
int16 i = 0x4000;
|
||||
int16 e = 0;
|
||||
|
||||
#ifdef __GNUC__
|
||||
int16 t = m < 0 ? ~m : m;
|
||||
|
||||
if (t == 0)
|
||||
e = 15;
|
||||
else
|
||||
e = __builtin_clz(t) - (8 * sizeof(int) - 15);
|
||||
#else
|
||||
int16 i = 0x4000;
|
||||
|
||||
if (m < 0)
|
||||
{
|
||||
while ((m & i) && i)
|
||||
@@ -449,6 +474,7 @@ static void DSP1_NormalizeDouble (int32 Product, int16 *Coefficient, int16 *Expo
|
||||
e++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (e > 0)
|
||||
{
|
||||
@@ -458,6 +484,14 @@ static void DSP1_NormalizeDouble (int32 Product, int16 *Coefficient, int16 *Expo
|
||||
*Coefficient += n * DSP1ROM[0x0040 - e] >> 15;
|
||||
else
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
t = m < 0 ? ~(n | 0x8000) : n;
|
||||
|
||||
if (t == 0)
|
||||
e += 15;
|
||||
else
|
||||
e += __builtin_clz(t) - (8 * sizeof(int) - 15);
|
||||
#else
|
||||
i = 0x4000;
|
||||
|
||||
if (m < 0)
|
||||
@@ -476,6 +510,7 @@ static void DSP1_NormalizeDouble (int32 Product, int16 *Coefficient, int16 *Expo
|
||||
e++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (e > 15)
|
||||
*Coefficient = n * DSP1ROM[0x0012 + e] << 1;
|
||||
@@ -522,7 +557,7 @@ static void DSP1_Op0C (void)
|
||||
|
||||
static void DSP1_Parameter (int16 Fx, int16 Fy, int16 Fz, int16 Lfe, int16 Les, int16 Aas, int16 Azs, int16 *Vof, int16 *Vva, int16 *Cx, int16 *Cy)
|
||||
{
|
||||
const int16 MaxAZS_Exp[16] =
|
||||
static const int16 MaxAZS_Exp[16] =
|
||||
{
|
||||
0x38b4, 0x38b7, 0x38ba, 0x38be, 0x38c0, 0x38c4, 0x38c7, 0x38ca,
|
||||
0x38ce, 0x38d0, 0x38d4, 0x38d7, 0x38da, 0x38dd, 0x38e0, 0x38e4
|
||||
@@ -1231,187 +1266,163 @@ void DSP1SetByte (uint8 byte, uint16 address)
|
||||
break;
|
||||
|
||||
case 0x00: // Multiple
|
||||
DSP1.Op00Multiplicand = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op00Multiplier = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op00Multiplicand = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op00Multiplier = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
|
||||
DSP1_Op00();
|
||||
|
||||
DSP1.out_count = 2;
|
||||
DSP1.output[0] = DSP1.Op00Result & 0xFF;
|
||||
DSP1.output[1] = (DSP1.Op00Result >> 8) & 0xFF;
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op00Result);
|
||||
break;
|
||||
|
||||
case 0x20: // Multiple
|
||||
DSP1.Op20Multiplicand = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op20Multiplier = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op20Multiplicand = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op20Multiplier = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
|
||||
DSP1_Op20();
|
||||
|
||||
DSP1.out_count = 2;
|
||||
DSP1.output[0] = DSP1.Op20Result & 0xFF;
|
||||
DSP1.output[1] = (DSP1.Op20Result >> 8) & 0xFF;
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op20Result);
|
||||
break;
|
||||
|
||||
case 0x30:
|
||||
case 0x10: // Inverse
|
||||
DSP1.Op10Coefficient = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op10Exponent = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op10Coefficient = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op10Exponent = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
|
||||
DSP1_Op10();
|
||||
|
||||
DSP1.out_count = 4;
|
||||
DSP1.output[0] = (uint8) ( ((int16) DSP1.Op10CoefficientR) & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((((int16) DSP1.Op10CoefficientR) >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) ( ((int16) DSP1.Op10ExponentR ) & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((((int16) DSP1.Op10ExponentR ) >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op10CoefficientR);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op10ExponentR);
|
||||
break;
|
||||
|
||||
case 0x24:
|
||||
case 0x04: // Sin and Cos of angle
|
||||
DSP1.Op04Angle = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op04Radius = (uint16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op04Angle = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op04Radius = (uint16) READ_WORD(&DSP1.parameters[2]);
|
||||
|
||||
DSP1_Op04();
|
||||
|
||||
DSP1.out_count = 4;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op04Sin & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op04Sin >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op04Cos & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op04Cos >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op04Sin);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op04Cos);
|
||||
break;
|
||||
|
||||
case 0x08: // Radius
|
||||
DSP1.Op08X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op08Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op08Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op08X = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op08Y = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op08Z = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op08();
|
||||
|
||||
DSP1.out_count = 4;
|
||||
DSP1.output[0] = (uint8) ( ((int16) DSP1.Op08Ll) & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((((int16) DSP1.Op08Ll) >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) ( ((int16) DSP1.Op08Lh) & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((((int16) DSP1.Op08Lh) >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op08Ll);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op08Lh);
|
||||
break;
|
||||
|
||||
case 0x18: // Range
|
||||
|
||||
DSP1.Op18X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op18Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op18Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op18R = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8));
|
||||
DSP1.Op18X = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op18Y = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op18Z = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
DSP1.Op18R = (int16) READ_WORD(&DSP1.parameters[6]);
|
||||
|
||||
DSP1_Op18();
|
||||
|
||||
DSP1.out_count = 2;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op18D & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op18D >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op18D);
|
||||
break;
|
||||
|
||||
case 0x38: // Range
|
||||
|
||||
DSP1.Op38X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op38Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op38Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op38R = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8));
|
||||
DSP1.Op38X = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op38Y = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op38Z = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
DSP1.Op38R = (int16) READ_WORD(&DSP1.parameters[6]);
|
||||
|
||||
DSP1_Op38();
|
||||
|
||||
DSP1.out_count = 2;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op38D & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op38D >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op38D);
|
||||
break;
|
||||
|
||||
case 0x28: // Distance (vector length)
|
||||
DSP1.Op28X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op28Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op28Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op28X = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op28Y = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op28Z = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op28();
|
||||
|
||||
DSP1.out_count = 2;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op28R & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op28R >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op28R);
|
||||
break;
|
||||
|
||||
case 0x2c:
|
||||
case 0x0c: // Rotate (2D rotate)
|
||||
DSP1.Op0CA = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op0CX1 = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op0CY1 = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op0CA = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op0CX1 = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op0CY1 = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op0C();
|
||||
|
||||
DSP1.out_count = 4;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op0CX2 & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op0CX2 >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op0CY2 & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op0CY2 >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op0CX2);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op0CY2);
|
||||
break;
|
||||
|
||||
case 0x3c:
|
||||
case 0x1c: // Polar (3D rotate)
|
||||
DSP1.Op1CZ = (DSP1.parameters[ 0] | (DSP1.parameters[ 1] << 8));
|
||||
DSP1.Op1CZ = READ_WORD(&DSP1.parameters[ 0]);
|
||||
//MK: reversed X and Y on neviksti and John's advice.
|
||||
DSP1.Op1CY = (DSP1.parameters[ 2] | (DSP1.parameters[ 3] << 8));
|
||||
DSP1.Op1CX = (DSP1.parameters[ 4] | (DSP1.parameters[ 5] << 8));
|
||||
DSP1.Op1CXBR = (DSP1.parameters[ 6] | (DSP1.parameters[ 7] << 8));
|
||||
DSP1.Op1CYBR = (DSP1.parameters[ 8] | (DSP1.parameters[ 9] << 8));
|
||||
DSP1.Op1CZBR = (DSP1.parameters[10] | (DSP1.parameters[11] << 8));
|
||||
DSP1.Op1CY = READ_WORD(&DSP1.parameters[ 2]);
|
||||
DSP1.Op1CX = READ_WORD(&DSP1.parameters[ 4]);
|
||||
DSP1.Op1CXBR = READ_WORD(&DSP1.parameters[ 6]);
|
||||
DSP1.Op1CYBR = READ_WORD(&DSP1.parameters[ 8]);
|
||||
DSP1.Op1CZBR = READ_WORD(&DSP1.parameters[10]);
|
||||
|
||||
DSP1_Op1C();
|
||||
|
||||
DSP1.out_count = 6;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op1CXAR & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op1CXAR >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op1CYAR & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op1CYAR >> 8) & 0xFF);
|
||||
DSP1.output[4] = (uint8) (DSP1.Op1CZAR & 0xFF);
|
||||
DSP1.output[5] = (uint8) ((DSP1.Op1CZAR >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op1CXAR);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op1CYAR);
|
||||
WRITE_WORD(&DSP1.output[4], DSP1.Op1CZAR);
|
||||
break;
|
||||
|
||||
case 0x32:
|
||||
case 0x22:
|
||||
case 0x12:
|
||||
case 0x02: // Parameter (Projection)
|
||||
DSP1.Op02FX = (int16) (DSP1.parameters[ 0] | (DSP1.parameters[ 1] << 8));
|
||||
DSP1.Op02FY = (int16) (DSP1.parameters[ 2] | (DSP1.parameters[ 3] << 8));
|
||||
DSP1.Op02FZ = (int16) (DSP1.parameters[ 4] | (DSP1.parameters[ 5] << 8));
|
||||
DSP1.Op02LFE = (int16) (DSP1.parameters[ 6] | (DSP1.parameters[ 7] << 8));
|
||||
DSP1.Op02LES = (int16) (DSP1.parameters[ 8] | (DSP1.parameters[ 9] << 8));
|
||||
DSP1.Op02AAS = (uint16) (DSP1.parameters[10] | (DSP1.parameters[11] << 8));
|
||||
DSP1.Op02AZS = (uint16) (DSP1.parameters[12] | (DSP1.parameters[13] << 8));
|
||||
DSP1.Op02FX = (int16) READ_WORD(&DSP1.parameters[ 0]);
|
||||
DSP1.Op02FY = (int16) READ_WORD(&DSP1.parameters[ 2]);
|
||||
DSP1.Op02FZ = (int16) READ_WORD(&DSP1.parameters[ 4]);
|
||||
DSP1.Op02LFE = (int16) READ_WORD(&DSP1.parameters[ 6]);
|
||||
DSP1.Op02LES = (int16) READ_WORD(&DSP1.parameters[ 8]);
|
||||
DSP1.Op02AAS = (uint16) READ_WORD(&DSP1.parameters[10]);
|
||||
DSP1.Op02AZS = (uint16) READ_WORD(&DSP1.parameters[12]);
|
||||
|
||||
DSP1_Op02();
|
||||
|
||||
DSP1.out_count = 8;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op02VOF & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op02VOF >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op02VVA & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op02VVA >> 8) & 0xFF);
|
||||
DSP1.output[4] = (uint8) (DSP1.Op02CX & 0xFF);
|
||||
DSP1.output[5] = (uint8) ((DSP1.Op02CX >> 8) & 0xFF);
|
||||
DSP1.output[6] = (uint8) (DSP1.Op02CY & 0xFF);
|
||||
DSP1.output[7] = (uint8) ((DSP1.Op02CY >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op02VOF);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op02VVA);
|
||||
WRITE_WORD(&DSP1.output[4], DSP1.Op02CX);
|
||||
WRITE_WORD(&DSP1.output[6], DSP1.Op02CY);
|
||||
break;
|
||||
|
||||
case 0x3a:
|
||||
case 0x2a:
|
||||
case 0x1a: // Raster mode 7 matrix data
|
||||
case 0x0a:
|
||||
DSP1.Op0AVS = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op0AVS = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
|
||||
DSP1_Op0A();
|
||||
|
||||
DSP1.out_count = 8;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op0AA & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op0AA >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op0AB & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op0AB >> 8) & 0xFF);
|
||||
DSP1.output[4] = (uint8) (DSP1.Op0AC & 0xFF);
|
||||
DSP1.output[5] = (uint8) ((DSP1.Op0AC >> 8) & 0xFF);
|
||||
DSP1.output[6] = (uint8) (DSP1.Op0AD & 0xFF);
|
||||
DSP1.output[7] = (uint8) ((DSP1.Op0AD >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op0AA);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op0AB);
|
||||
WRITE_WORD(&DSP1.output[4], DSP1.Op0AC);
|
||||
WRITE_WORD(&DSP1.output[6], DSP1.Op0AD);
|
||||
DSP1.in_index = 0;
|
||||
break;
|
||||
|
||||
@@ -1419,35 +1430,30 @@ void DSP1SetByte (uint8 byte, uint16 address)
|
||||
case 0x26:
|
||||
case 0x36:
|
||||
case 0x06: // Project object
|
||||
DSP1.Op06X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op06Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op06Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op06X = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op06Y = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op06Z = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op06();
|
||||
|
||||
DSP1.out_count = 6;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op06H & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op06H >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op06V & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op06V >> 8) & 0xFF);
|
||||
DSP1.output[4] = (uint8) (DSP1.Op06M & 0xFF);
|
||||
DSP1.output[5] = (uint8) ((DSP1.Op06M >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op06H);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op06V);
|
||||
WRITE_WORD(&DSP1.output[4], DSP1.Op06M);
|
||||
break;
|
||||
|
||||
case 0x1e:
|
||||
case 0x2e:
|
||||
case 0x3e:
|
||||
case 0x0e: // Target
|
||||
DSP1.Op0EH = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op0EV = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op0EH = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op0EV = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
|
||||
DSP1_Op0E();
|
||||
|
||||
DSP1.out_count = 4;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op0EX & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op0EX >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op0EY & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op0EY >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op0EX);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op0EY);
|
||||
break;
|
||||
|
||||
// Extra commands used by Pilot Wings
|
||||
@@ -1455,30 +1461,30 @@ void DSP1SetByte (uint8 byte, uint16 address)
|
||||
case 0x35:
|
||||
case 0x31:
|
||||
case 0x01: // Set attitude matrix A
|
||||
DSP1.Op01m = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op01Zr = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op01Yr = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op01Xr = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8));
|
||||
DSP1.Op01m = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op01Zr = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op01Yr = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
DSP1.Op01Xr = (int16) READ_WORD(&DSP1.parameters[6]);
|
||||
|
||||
DSP1_Op01();
|
||||
break;
|
||||
|
||||
case 0x15:
|
||||
case 0x11: // Set attitude matrix B
|
||||
DSP1.Op11m = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op11Zr = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op11Yr = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op11Xr = (int16) (DSP1.parameters[7] | (DSP1.parameters[7] << 8));
|
||||
DSP1.Op11m = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op11Zr = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op11Yr = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
DSP1.Op11Xr = (int16) READ_WORD(&DSP1.parameters[6]);
|
||||
|
||||
DSP1_Op11();
|
||||
break;
|
||||
|
||||
case 0x25:
|
||||
case 0x21: // Set attitude matrix C
|
||||
DSP1.Op21m = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op21Zr = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op21Yr = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op21Xr = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8));
|
||||
DSP1.Op21m = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op21Zr = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op21Yr = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
DSP1.Op21Xr = (int16) READ_WORD(&DSP1.parameters[6]);
|
||||
|
||||
DSP1_Op21();
|
||||
break;
|
||||
@@ -1487,182 +1493,156 @@ void DSP1SetByte (uint8 byte, uint16 address)
|
||||
case 0x39:
|
||||
case 0x3d:
|
||||
case 0x0d: // Objective matrix A
|
||||
DSP1.Op0DX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op0DY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op0DZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op0DX = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op0DY = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op0DZ = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op0D();
|
||||
|
||||
DSP1.out_count = 6;
|
||||
DSP1.output [0] = (uint8) (DSP1.Op0DF & 0xFF);
|
||||
DSP1.output [1] = (uint8) ((DSP1.Op0DF >> 8) & 0xFF);
|
||||
DSP1.output [2] = (uint8) (DSP1.Op0DL & 0xFF);
|
||||
DSP1.output [3] = (uint8) ((DSP1.Op0DL >> 8) & 0xFF);
|
||||
DSP1.output [4] = (uint8) (DSP1.Op0DU & 0xFF);
|
||||
DSP1.output [5] = (uint8) ((DSP1.Op0DU >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op0DF);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op0DL);
|
||||
WRITE_WORD(&DSP1.output[4], DSP1.Op0DU);
|
||||
break;
|
||||
|
||||
case 0x19:
|
||||
case 0x1d: // Objective matrix B
|
||||
DSP1.Op1DX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op1DY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op1DZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op1DX = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op1DY = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op1DZ = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op1D();
|
||||
|
||||
DSP1.out_count = 6;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op1DF & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op1DF >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op1DL & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op1DL >> 8) & 0xFF);
|
||||
DSP1.output[4] = (uint8) (DSP1.Op1DU & 0xFF);
|
||||
DSP1.output[5] = (uint8) ((DSP1.Op1DU >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op1DF);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op1DL);
|
||||
WRITE_WORD(&DSP1.output[4], DSP1.Op1DU);
|
||||
break;
|
||||
|
||||
case 0x29:
|
||||
case 0x2d: // Objective matrix C
|
||||
DSP1.Op2DX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op2DY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op2DZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op2DX = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op2DY = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op2DZ = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op2D();
|
||||
|
||||
DSP1.out_count = 6;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op2DF & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op2DF >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op2DL & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op2DL >> 8) & 0xFF);
|
||||
DSP1.output[4] = (uint8) (DSP1.Op2DU & 0xFF);
|
||||
DSP1.output[5] = (uint8) ((DSP1.Op2DU >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op2DF);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op2DL);
|
||||
WRITE_WORD(&DSP1.output[4], DSP1.Op2DU);
|
||||
break;
|
||||
|
||||
case 0x33:
|
||||
case 0x03: // Subjective matrix A
|
||||
DSP1.Op03F = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op03L = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op03U = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op03F = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op03L = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op03U = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op03();
|
||||
|
||||
DSP1.out_count = 6;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op03X & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op03X >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op03Y & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op03Y >> 8) & 0xFF);
|
||||
DSP1.output[4] = (uint8) (DSP1.Op03Z & 0xFF);
|
||||
DSP1.output[5] = (uint8) ((DSP1.Op03Z >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op03X);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op03Y);
|
||||
WRITE_WORD(&DSP1.output[4], DSP1.Op03Z);
|
||||
break;
|
||||
|
||||
case 0x13: // Subjective matrix B
|
||||
DSP1.Op13F = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op13L = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op13U = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op13F = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op13L = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op13U = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op13();
|
||||
|
||||
DSP1.out_count = 6;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op13X & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op13X >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op13Y & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op13Y >> 8) & 0xFF);
|
||||
DSP1.output[4] = (uint8) (DSP1.Op13Z & 0xFF);
|
||||
DSP1.output[5] = (uint8) ((DSP1.Op13Z >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op13X);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op13Y);
|
||||
WRITE_WORD(&DSP1.output[4], DSP1.Op13Z);
|
||||
break;
|
||||
|
||||
case 0x23: // Subjective matrix C
|
||||
DSP1.Op23F = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op23L = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op23U = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op23F = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op23L = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op23U = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op23();
|
||||
|
||||
DSP1.out_count = 6;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op23X & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op23X >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op23Y & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op23Y >> 8) & 0xFF);
|
||||
DSP1.output[4] = (uint8) (DSP1.Op23Z & 0xFF);
|
||||
DSP1.output[5] = (uint8) ((DSP1.Op23Z >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op23X);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op23Y);
|
||||
WRITE_WORD(&DSP1.output[4], DSP1.Op23Z);
|
||||
break;
|
||||
|
||||
case 0x3b:
|
||||
case 0x0b:
|
||||
DSP1.Op0BX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op0BY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op0BZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op0BX = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op0BY = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op0BZ = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op0B();
|
||||
|
||||
DSP1.out_count = 2;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op0BS & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op0BS >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op0BS);
|
||||
break;
|
||||
|
||||
case 0x1b:
|
||||
DSP1.Op1BX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op1BY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op1BZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op1BX = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op1BY = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op1BZ = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op1B();
|
||||
|
||||
DSP1.out_count = 2;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op1BS & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op1BS >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op1BS);
|
||||
break;
|
||||
|
||||
case 0x2b:
|
||||
DSP1.Op2BX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op2BY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8));
|
||||
DSP1.Op2BZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8));
|
||||
DSP1.Op2BX = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
DSP1.Op2BY = (int16) READ_WORD(&DSP1.parameters[2]);
|
||||
DSP1.Op2BZ = (int16) READ_WORD(&DSP1.parameters[4]);
|
||||
|
||||
DSP1_Op2B();
|
||||
|
||||
DSP1.out_count = 2;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op2BS & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op2BS >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op2BS);
|
||||
break;
|
||||
|
||||
case 0x34:
|
||||
case 0x14:
|
||||
DSP1.Op14Zr = (int16) (DSP1.parameters[ 0] | (DSP1.parameters[ 1] << 8));
|
||||
DSP1.Op14Xr = (int16) (DSP1.parameters[ 2] | (DSP1.parameters[ 3] << 8));
|
||||
DSP1.Op14Yr = (int16) (DSP1.parameters[ 4] | (DSP1.parameters[ 5] << 8));
|
||||
DSP1.Op14U = (int16) (DSP1.parameters[ 6] | (DSP1.parameters[ 7] << 8));
|
||||
DSP1.Op14F = (int16) (DSP1.parameters[ 8] | (DSP1.parameters[ 9] << 8));
|
||||
DSP1.Op14L = (int16) (DSP1.parameters[10] | (DSP1.parameters[11] << 8));
|
||||
DSP1.Op14Zr = (int16) READ_WORD(&DSP1.parameters[ 0]);
|
||||
DSP1.Op14Xr = (int16) READ_WORD(&DSP1.parameters[ 2]);
|
||||
DSP1.Op14Yr = (int16) READ_WORD(&DSP1.parameters[ 4]);
|
||||
DSP1.Op14U = (int16) READ_WORD(&DSP1.parameters[ 6]);
|
||||
DSP1.Op14F = (int16) READ_WORD(&DSP1.parameters[ 8]);
|
||||
DSP1.Op14L = (int16) READ_WORD(&DSP1.parameters[10]);
|
||||
|
||||
DSP1_Op14();
|
||||
|
||||
DSP1.out_count = 6;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op14Zrr & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op14Zrr >> 8) & 0xFF);
|
||||
DSP1.output[2] = (uint8) (DSP1.Op14Xrr & 0xFF);
|
||||
DSP1.output[3] = (uint8) ((DSP1.Op14Xrr >> 8) & 0xFF);
|
||||
DSP1.output[4] = (uint8) (DSP1.Op14Yrr & 0xFF);
|
||||
DSP1.output[5] = (uint8) ((DSP1.Op14Yrr >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op14Zrr);
|
||||
WRITE_WORD(&DSP1.output[2], DSP1.Op14Xrr);
|
||||
WRITE_WORD(&DSP1.output[4], DSP1.Op14Yrr);
|
||||
break;
|
||||
|
||||
case 0x27:
|
||||
case 0x2F:
|
||||
DSP1.Op2FUnknown = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op2FUnknown = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
|
||||
DSP1_Op2F();
|
||||
|
||||
DSP1.out_count = 2;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op2FSize & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op2FSize >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op2FSize);
|
||||
break;
|
||||
|
||||
|
||||
case 0x07:
|
||||
case 0x0F:
|
||||
DSP1.Op0FRamsize = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8));
|
||||
DSP1.Op0FRamsize = (int16) READ_WORD(&DSP1.parameters[0]);
|
||||
|
||||
DSP1_Op0F();
|
||||
|
||||
DSP1.out_count = 2;
|
||||
DSP1.output[0] = (uint8) (DSP1.Op0FPass & 0xFF);
|
||||
DSP1.output[1] = (uint8) ((DSP1.Op0FPass >> 8) & 0xFF);
|
||||
WRITE_WORD(&DSP1.output[0], DSP1.Op0FPass);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
Executable → Regular
Executable → Regular
+2
-2
@@ -929,12 +929,12 @@ static void DSP3_OP1E_D (int16 move, int16 *lo, int16 *hi)
|
||||
|
||||
static void DSP3_OP1E_D1 (int16 move, int16 *lo, int16 *hi)
|
||||
{
|
||||
const uint16 HiAdd[] =
|
||||
static const uint16 HiAdd[] =
|
||||
{
|
||||
0x00, 0xFF, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00
|
||||
};
|
||||
|
||||
const uint16 LoAdd[] =
|
||||
static const uint16 LoAdd[] =
|
||||
{
|
||||
0x00, 0x00, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x00
|
||||
};
|
||||
|
||||
Executable → Regular
+2
-2
@@ -90,7 +90,7 @@ static int32 DSP4_READ_DWORD (void)
|
||||
static int16 DSP4_Inverse (int16 value)
|
||||
{
|
||||
// Attention: This lookup table is not verified
|
||||
const uint16 div_lut[64] =
|
||||
static const uint16 div_lut[64] =
|
||||
{
|
||||
0x0000, 0x8000, 0x4000, 0x2aaa, 0x2000, 0x1999, 0x1555, 0x1249,
|
||||
0x1000, 0x0e38, 0x0ccc, 0x0ba2, 0x0aaa, 0x09d8, 0x0924, 0x0888,
|
||||
@@ -1080,7 +1080,7 @@ static void DSP4_OP09 (void)
|
||||
|
||||
static void DSP4_OP0A (int16 n2, int16 *o1, int16 *o2, int16 *o3, int16 *o4)
|
||||
{
|
||||
const uint16 OP0A_Values[16] =
|
||||
static const uint16 OP0A_Values[16] =
|
||||
{
|
||||
0x0000, 0x0030, 0x0060, 0x0090, 0x00c0, 0x00f0, 0x0120, 0x0150,
|
||||
0xfe80, 0xfeb0, 0xfee0, 0xff10, 0xff40, 0xff70, 0xffa0, 0xffd0
|
||||
|
||||
Executable → Regular
@@ -0,0 +1,238 @@
|
||||
/*****************************************************************************\
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
This file is licensed under the Snes9x License.
|
||||
For further information, consult the LICENSE file in the root directory.
|
||||
\*****************************************************************************/
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include "display.h"
|
||||
#include "fscompat.h"
|
||||
#include "port.h"
|
||||
#include "memmap.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
bool SplitPath::ext_is(const string &other)
|
||||
{
|
||||
if (strcasecmp(ext.c_str(), other.c_str()) == 0)
|
||||
return true;
|
||||
if (other[0] != '.' && (strcasecmp(other.c_str(), &(ext.c_str()[1])) == 0))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string makepath(const SplitPath &path)
|
||||
{
|
||||
return makepath(path.drive, path.dir, path.stem, path.ext);
|
||||
}
|
||||
|
||||
std::string S9xGetFilename(string filename, string ext, enum s9x_getdirtype dirtype)
|
||||
{
|
||||
auto path = splitpath(filename);
|
||||
auto dir = S9xGetDirectory(dirtype);
|
||||
return makepath(path.drive, dir, path.stem, ext);
|
||||
}
|
||||
|
||||
std::string S9xGetFilename(string ext, enum s9x_getdirtype dirtype)
|
||||
{
|
||||
return S9xGetFilename(Memory.ROMFilename, ext, dirtype);
|
||||
}
|
||||
|
||||
std::string S9xBasename(std::string filename)
|
||||
{
|
||||
auto path = splitpath(filename);
|
||||
return path.stem + path.ext;
|
||||
}
|
||||
|
||||
std::string S9xBasenameNoExt(std::string filename)
|
||||
{
|
||||
return splitpath(filename).stem;
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201703L && 0
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
SplitPath splitpath(string str)
|
||||
{
|
||||
SplitPath output{};
|
||||
fs::path path(str);
|
||||
|
||||
if (path.has_root_name())
|
||||
output.drive = path.root_name().string();
|
||||
|
||||
if (path.has_filename())
|
||||
{
|
||||
output.stem = path.stem().string();
|
||||
output.ext = path.extension().string();
|
||||
path.remove_filename();
|
||||
}
|
||||
|
||||
if (!path.empty())
|
||||
output.dir = path.string();
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
string makepath(const string &drive, const string &dir, const string &stem, const string &ext)
|
||||
{
|
||||
auto dot_position = ext.find('.');
|
||||
|
||||
if (dot_position == string::npos)
|
||||
{
|
||||
fs::path path(drive);
|
||||
path = path / dir / stem;
|
||||
path.replace_extension(ext);
|
||||
return path.string();
|
||||
}
|
||||
|
||||
auto filename = stem + ext;
|
||||
fs::path path(drive);
|
||||
path = path / dir / filename;
|
||||
return path.string();
|
||||
}
|
||||
|
||||
#else
|
||||
constexpr auto npos = std::string::npos;
|
||||
|
||||
SplitPath splitpath(string path)
|
||||
{
|
||||
SplitPath output{};
|
||||
|
||||
#ifdef _WIN32
|
||||
if (path.length() > 2 && path[1] == ':')
|
||||
{
|
||||
output.drive = path.substr(0, 2);
|
||||
path = path.substr(2);
|
||||
}
|
||||
#endif
|
||||
auto slash = path.rfind(SLASH_CHAR);
|
||||
auto dot = path.rfind('.');
|
||||
|
||||
if (dot != npos && slash != npos && dot < slash)
|
||||
{
|
||||
dot = npos;
|
||||
}
|
||||
else if (dot != npos)
|
||||
{
|
||||
output.ext = path.substr(dot);
|
||||
}
|
||||
|
||||
if (slash != npos)
|
||||
{
|
||||
output.dir = path.substr(0, slash + 1);
|
||||
output.stem = path.substr(slash + 1, dot - slash - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
output.stem = path.substr(0, dot);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
string makepath(const string &drive, const string &dir, const string &stem, const string &ext)
|
||||
{
|
||||
string output;
|
||||
|
||||
if (!drive.empty())
|
||||
{
|
||||
if (!(dir.length() > 2 && dir[1] == ':'))
|
||||
{
|
||||
output += drive + ":";
|
||||
if (!dir.empty() && dir[0] != SLASH_CHAR)
|
||||
output += SLASH_CHAR;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dir.empty())
|
||||
{
|
||||
output += dir;
|
||||
if (output[output.length() - 1] != SLASH_CHAR)
|
||||
output += SLASH_CHAR;
|
||||
}
|
||||
|
||||
if (!stem.empty())
|
||||
{
|
||||
output += stem;
|
||||
}
|
||||
|
||||
if (!ext.empty())
|
||||
{
|
||||
if (ext.find('.') == string::npos)
|
||||
output += '.';
|
||||
output += ext;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
void _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext)
|
||||
{
|
||||
char *slash = strrchr((char *)path, SLASH_CHAR);
|
||||
char *dot = strrchr((char *)path, '.');
|
||||
|
||||
*drive = '\0';
|
||||
|
||||
if (dot && slash && dot < slash)
|
||||
{
|
||||
dot = 0;
|
||||
}
|
||||
|
||||
if (!slash)
|
||||
{
|
||||
*dir = '\0';
|
||||
strcpy(fname, path);
|
||||
|
||||
if (dot)
|
||||
{
|
||||
fname[dot - path] = '\0';
|
||||
strcpy(ext, dot + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ext = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(dir, path);
|
||||
dir[slash - path] = '\0';
|
||||
strcpy(fname, slash + 1);
|
||||
|
||||
if (dot)
|
||||
{
|
||||
fname[(dot - slash) - 1] = '\0';
|
||||
strcpy(ext, dot + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ext = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext)
|
||||
{
|
||||
if (dir && *dir)
|
||||
{
|
||||
strcpy(path, dir);
|
||||
strcat(path, "/");
|
||||
}
|
||||
else
|
||||
*path = '\0';
|
||||
|
||||
strcat(path, fname);
|
||||
|
||||
if (ext && *ext)
|
||||
{
|
||||
if (!strchr(ext, '.'))
|
||||
strcat(path, ".");
|
||||
strcat(path, ext);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,52 @@
|
||||
/*****************************************************************************\
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
This file is licensed under the Snes9x License.
|
||||
For further information, consult the LICENSE file in the root directory.
|
||||
\*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <string>
|
||||
|
||||
enum s9x_getdirtype
|
||||
{
|
||||
DEFAULT_DIR = 0,
|
||||
HOME_DIR,
|
||||
ROMFILENAME_DIR,
|
||||
ROM_DIR,
|
||||
SRAM_DIR,
|
||||
SNAPSHOT_DIR,
|
||||
SCREENSHOT_DIR,
|
||||
SPC_DIR,
|
||||
CHEAT_DIR,
|
||||
PATCH_DIR,
|
||||
BIOS_DIR,
|
||||
LOG_DIR,
|
||||
SAT_DIR,
|
||||
LAST_DIR
|
||||
};
|
||||
|
||||
struct SplitPath
|
||||
{
|
||||
bool ext_is(const std::string &ext);
|
||||
std::string drive;
|
||||
std::string dir;
|
||||
std::string stem;
|
||||
std::string ext;
|
||||
};
|
||||
|
||||
SplitPath splitpath(std::string filename);
|
||||
std::string makepath(const std::string &drive,
|
||||
const std::string &directory,
|
||||
const std::string &stem,
|
||||
const std::string &extension);
|
||||
std::string makepath(const SplitPath &);
|
||||
|
||||
std::string S9xBasename (std::string);
|
||||
std::string S9xBasenameNoExt (std::string);
|
||||
std::string S9xGetFilename (std::string ext, enum s9x_getdirtype dirtype);
|
||||
std::string S9xGetFilename (std::string filename, std::string ext, enum s9x_getdirtype dirtype);
|
||||
std::string S9xGetDirectory (enum s9x_getdirtype);
|
||||
std::string S9xGetFilenameInc (std::string, enum s9x_getdirtype);
|
||||
#endif
|
||||
Executable → Regular
Executable → Regular
+11
-20
@@ -144,7 +144,7 @@ void S9xSuperFXExec (void)
|
||||
{
|
||||
if ((Memory.FillRAM[0x3000 + GSU_SFR] & FLG_G) && (Memory.FillRAM[0x3000 + GSU_SCMR] & 0x18) == 0x18)
|
||||
{
|
||||
FxEmulate(((Memory.FillRAM[0x3000 + GSU_CLSR] & 1) ? (SuperFX.speedPerLine * 8 / 3) : SuperFX.speedPerLine) * Settings.SuperFXClockMultiplier / 100);
|
||||
FxEmulate(((Memory.FillRAM[0x3000 + GSU_CLSR] & 1) ? (SuperFX.speedPerLine * 5 / 2) : SuperFX.speedPerLine) * Settings.SuperFXClockMultiplier / 100);
|
||||
|
||||
uint16 GSUStatus = Memory.FillRAM[0x3000 + GSU_SFR] | (Memory.FillRAM[0x3000 + GSU_SFR + 1] << 8);
|
||||
if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ)
|
||||
@@ -196,7 +196,7 @@ static void FxReset (struct FxInfo_s *psFxInfo)
|
||||
else
|
||||
{
|
||||
b %= GSU.nRomBanks * 2;
|
||||
GSU.apvRomBank[i] = &GSU.pvRom[(b << 16) + 0x200000];
|
||||
GSU.apvRomBank[i] = &GSU.pvRom[(b << 16) + 0x800000];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,8 +218,8 @@ static void FxReset (struct FxInfo_s *psFxInfo)
|
||||
|
||||
static void fx_readRegisterSpace (void)
|
||||
{
|
||||
static uint32 avHeight[] = { 128, 160, 192, 256 };
|
||||
static uint32 avMult[] = { 16, 32, 32, 64 };
|
||||
static const uint32 avHeight[] = { 128, 160, 192, 256 };
|
||||
static const uint32 avMult[] = { 16, 32, 32, 64 };
|
||||
|
||||
uint8 *p;
|
||||
int n;
|
||||
@@ -228,16 +228,12 @@ static void fx_readRegisterSpace (void)
|
||||
|
||||
// Update R0-R15
|
||||
p = GSU.pvRegisters;
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
GSU.avReg[i] = *p++;
|
||||
GSU.avReg[i] += ((uint32) (*p++)) << 8;
|
||||
}
|
||||
for (int i = 0; i < 16; i++, p += 2)
|
||||
GSU.avReg[i] = (uint32) READ_WORD(p);
|
||||
|
||||
// Update other registers
|
||||
p = GSU.pvRegisters;
|
||||
GSU.vStatusReg = (uint32) p[GSU_SFR];
|
||||
GSU.vStatusReg |= ((uint32) p[GSU_SFR + 1]) << 8;
|
||||
GSU.vStatusReg = (uint32) READ_WORD(&p[GSU_SFR]);
|
||||
GSU.vPrgBankReg = (uint32) p[GSU_PBR];
|
||||
GSU.vRomBankReg = (uint32) p[GSU_ROMBR];
|
||||
GSU.vRamBankReg = ((uint32) p[GSU_RAMBR]) & (FX_RAM_BANKS - 1);
|
||||
@@ -291,11 +287,8 @@ static void fx_writeRegisterSpace (void)
|
||||
uint8 *p;
|
||||
|
||||
p = GSU.pvRegisters;
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
*p++ = (uint8) GSU.avReg[i];
|
||||
*p++ = (uint8) (GSU.avReg[i] >> 8);
|
||||
}
|
||||
for (int i = 0; i < 16; i++, p += 2)
|
||||
WRITE_WORD(p, GSU.avReg[i]);
|
||||
|
||||
// Update status register
|
||||
if (USEX16(GSU.vZero) == 0)
|
||||
@@ -319,13 +312,11 @@ static void fx_writeRegisterSpace (void)
|
||||
CF(CY);
|
||||
|
||||
p = GSU.pvRegisters;
|
||||
p[GSU_SFR] = (uint8) GSU.vStatusReg;
|
||||
p[GSU_SFR + 1] = (uint8) (GSU.vStatusReg >> 8);
|
||||
WRITE_WORD(&p[GSU_SFR], GSU.vStatusReg);
|
||||
p[GSU_PBR] = (uint8) GSU.vPrgBankReg;
|
||||
p[GSU_ROMBR] = (uint8) GSU.vRomBankReg;
|
||||
p[GSU_RAMBR] = (uint8) GSU.vRamBankReg;
|
||||
p[GSU_CBR] = (uint8) GSU.vCacheBaseReg;
|
||||
p[GSU_CBR + 1] = (uint8) (GSU.vCacheBaseReg >> 8);
|
||||
WRITE_WORD(&p[GSU_CBR], GSU.vCacheBaseReg);
|
||||
|
||||
//fx_restoreCache();
|
||||
}
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+11
-11
@@ -100,7 +100,7 @@ inline uint8 S9xGetByte (uint32 Address)
|
||||
|
||||
case CMemory::MAP_HIROM_SRAM:
|
||||
case CMemory::MAP_RONLY_SRAM:
|
||||
byte = *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));
|
||||
byte = *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0x1f0000) >> 3)) & Memory.SRAMMask));
|
||||
addCyclesInMemoryAccess;
|
||||
return (byte);
|
||||
|
||||
@@ -241,10 +241,10 @@ inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE)
|
||||
case CMemory::MAP_HIROM_SRAM:
|
||||
case CMemory::MAP_RONLY_SRAM:
|
||||
if (Memory.SRAMMask >= MEMMAP_MASK)
|
||||
word = READ_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));
|
||||
word = READ_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0x1f0000) >> 3)) & Memory.SRAMMask));
|
||||
else
|
||||
word = (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) |
|
||||
(*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) << 8));
|
||||
word = (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0x1f0000) >> 3)) & Memory.SRAMMask)) |
|
||||
(*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0x1f0000) >> 3)) & Memory.SRAMMask)) << 8));
|
||||
addCyclesInMemoryAccess_x2;
|
||||
return (word);
|
||||
|
||||
@@ -368,7 +368,7 @@ inline void S9xSetByte (uint8 Byte, uint32 Address)
|
||||
case CMemory::MAP_HIROM_SRAM:
|
||||
if (Memory.SRAMMask)
|
||||
{
|
||||
*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = Byte;
|
||||
*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0x1f0000) >> 3)) & Memory.SRAMMask)) = Byte;
|
||||
CPU.SRAMModified = TRUE;
|
||||
}
|
||||
|
||||
@@ -555,11 +555,11 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON
|
||||
if (Memory.SRAMMask)
|
||||
{
|
||||
if (Memory.SRAMMask >= MEMMAP_MASK)
|
||||
WRITE_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask), Word);
|
||||
WRITE_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0x1f0000) >> 3)) & Memory.SRAMMask), Word);
|
||||
else
|
||||
{
|
||||
*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = (uint8) Word;
|
||||
*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) = Word >> 8;
|
||||
*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0x1f0000) >> 3)) & Memory.SRAMMask)) = (uint8) Word;
|
||||
*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0x1f0000) >> 3)) & Memory.SRAMMask)) = Word >> 8;
|
||||
}
|
||||
|
||||
CPU.SRAMModified = TRUE;
|
||||
@@ -730,7 +730,7 @@ inline void S9xSetPCBase (uint32 Address)
|
||||
if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
|
||||
CPU.PCBase = NULL;
|
||||
else
|
||||
CPU.PCBase = Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff);
|
||||
CPU.PCBase = Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0x1f0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff);
|
||||
return;
|
||||
|
||||
case CMemory::MAP_BWRAM:
|
||||
@@ -786,7 +786,7 @@ inline uint8 * S9xGetBasePointer (uint32 Address)
|
||||
case CMemory::MAP_HIROM_SRAM:
|
||||
if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
|
||||
return (NULL);
|
||||
return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff));
|
||||
return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0x1f0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff));
|
||||
|
||||
case CMemory::MAP_BWRAM:
|
||||
return (Memory.BWRAM - 0x6000 - (Address & 0x8000));
|
||||
@@ -831,7 +831,7 @@ inline uint8 * S9xGetMemPointer (uint32 Address)
|
||||
case CMemory::MAP_HIROM_SRAM:
|
||||
if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
|
||||
return (NULL);
|
||||
return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));
|
||||
return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0x1f0000) >> 3)) & Memory.SRAMMask));
|
||||
|
||||
case CMemory::MAP_BWRAM:
|
||||
return (Memory.BWRAM - 0x6000 + (Address & 0x7fff));
|
||||
|
||||
Executable → Regular
+69
-88
@@ -26,6 +26,7 @@ void (*S9xCustomDisplayString) (const char *, int, int, bool, int) = NULL;
|
||||
|
||||
static void SetupOBJ (void);
|
||||
static void DrawOBJS (int);
|
||||
static void DisplayTime (void);
|
||||
static void DisplayFrameRate (void);
|
||||
static void DisplayPressedKeys (void);
|
||||
static void DisplayWatchedAddresses (void);
|
||||
@@ -48,15 +49,14 @@ bool8 S9xGraphicsInit (void)
|
||||
S9xInitTileRenderer();
|
||||
memset(BlackColourMap, 0, 256 * sizeof(uint16));
|
||||
|
||||
GFX.RealPPL = GFX.Pitch >> 1;
|
||||
IPPU.OBJChanged = TRUE;
|
||||
Settings.BG_Forced = 0;
|
||||
S9xFixColourBrightness();
|
||||
S9xBuildDirectColourMaps();
|
||||
|
||||
GFX.ScreenBuffer.resize(MAX_SNES_WIDTH * (MAX_SNES_HEIGHT + 64));
|
||||
GFX.Screen = &GFX.ScreenBuffer[GFX.RealPPL * 32];
|
||||
GFX.ZERO = (uint16 *) malloc(sizeof(uint16) * 0x10000);
|
||||
|
||||
GFX.ScreenSize = GFX.Pitch / 2 * SNES_HEIGHT_EXTENDED * (Settings.SupportHiRes ? 2 : 1);
|
||||
GFX.SubScreen = (uint16 *) malloc(GFX.ScreenSize * sizeof(uint16));
|
||||
GFX.ZBuffer = (uint8 *) malloc(GFX.ScreenSize);
|
||||
GFX.SubZBuffer = (uint8 *) malloc(GFX.ScreenSize);
|
||||
@@ -117,27 +117,19 @@ void S9xGraphicsScreenResize (void)
|
||||
IPPU.Interlace = Memory.FillRAM[0x2133] & 1;
|
||||
IPPU.InterlaceOBJ = Memory.FillRAM[0x2133] & 2;
|
||||
IPPU.PseudoHires = Memory.FillRAM[0x2133] & 8;
|
||||
|
||||
if (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires))
|
||||
|
||||
if (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires)
|
||||
{
|
||||
GFX.RealPPL = GFX.Pitch >> 1;
|
||||
IPPU.DoubleWidthPixels = TRUE;
|
||||
IPPU.RenderedScreenWidth = SNES_WIDTH << 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef USE_OPENGL
|
||||
if (Settings.OpenGLEnable)
|
||||
GFX.RealPPL = SNES_WIDTH;
|
||||
else
|
||||
#endif
|
||||
GFX.RealPPL = GFX.Pitch >> 1;
|
||||
|
||||
IPPU.DoubleWidthPixels = FALSE;
|
||||
IPPU.RenderedScreenWidth = SNES_WIDTH;
|
||||
}
|
||||
|
||||
if (Settings.SupportHiRes && IPPU.Interlace)
|
||||
if (IPPU.Interlace)
|
||||
{
|
||||
GFX.PPL = GFX.RealPPL << 1;
|
||||
IPPU.DoubleHeightPixels = TRUE;
|
||||
@@ -149,7 +141,7 @@ void S9xGraphicsScreenResize (void)
|
||||
GFX.PPL = GFX.RealPPL;
|
||||
IPPU.DoubleHeightPixels = FALSE;
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void S9xBuildDirectColourMaps (void)
|
||||
@@ -163,13 +155,12 @@ void S9xBuildDirectColourMaps (void)
|
||||
|
||||
void S9xStartScreenRefresh (void)
|
||||
{
|
||||
GFX.InterlaceFrame = !GFX.InterlaceFrame;
|
||||
if (GFX.DoInterlace)
|
||||
GFX.DoInterlace--;
|
||||
|
||||
if (IPPU.RenderThisFrame)
|
||||
{
|
||||
if (!GFX.DoInterlace || !GFX.InterlaceFrame)
|
||||
if (!GFX.DoInterlace || !S9xInterlaceField())
|
||||
{
|
||||
if (!S9xInitUpdate())
|
||||
{
|
||||
@@ -190,7 +181,7 @@ void S9xStartScreenRefresh (void)
|
||||
memset(GFX.SubZBuffer, 0, GFX.ScreenSize);
|
||||
}
|
||||
|
||||
if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0)
|
||||
if (++IPPU.FrameCount == (uint32)Memory.ROMFramesPerSecond)
|
||||
{
|
||||
IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount;
|
||||
IPPU.RenderedFramesCount = 0;
|
||||
@@ -198,7 +189,7 @@ void S9xStartScreenRefresh (void)
|
||||
}
|
||||
|
||||
if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0)
|
||||
GFX.InfoString = NULL;
|
||||
GFX.InfoString.clear();
|
||||
|
||||
IPPU.TotalEmulatedFrames++;
|
||||
}
|
||||
@@ -209,7 +200,7 @@ void S9xEndScreenRefresh (void)
|
||||
{
|
||||
FLUSH_REDRAW();
|
||||
|
||||
if (GFX.DoInterlace && GFX.InterlaceFrame == 0)
|
||||
if (GFX.DoInterlace && S9xInterlaceField() == 0)
|
||||
{
|
||||
S9xControlEOF();
|
||||
S9xContinueUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight);
|
||||
@@ -220,7 +211,6 @@ void S9xEndScreenRefresh (void)
|
||||
{
|
||||
uint32 saved = PPU.CGDATA[0];
|
||||
IPPU.ColorsChanged = FALSE;
|
||||
S9xSetPalette();
|
||||
PPU.CGDATA[0] = saved;
|
||||
}
|
||||
|
||||
@@ -324,7 +314,7 @@ static inline void RenderScreen (bool8 sub)
|
||||
if (!sub)
|
||||
{
|
||||
GFX.S = GFX.Screen;
|
||||
if (GFX.DoInterlace && GFX.InterlaceFrame)
|
||||
if (GFX.DoInterlace && S9xInterlaceField())
|
||||
GFX.S += GFX.RealPPL;
|
||||
GFX.DB = GFX.ZBuffer;
|
||||
GFX.Clip = IPPU.Clip[0];
|
||||
@@ -467,55 +457,31 @@ void S9xUpdateScreen (void)
|
||||
PPU.RecomputeClipWindows = FALSE;
|
||||
}
|
||||
|
||||
if (Settings.SupportHiRes)
|
||||
if (!IPPU.DoubleWidthPixels && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires))
|
||||
{
|
||||
if (!IPPU.DoubleWidthPixels && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires))
|
||||
// Have to back out of the regular speed hack
|
||||
for (uint32 y = 0; y < GFX.StartY; y++)
|
||||
{
|
||||
#ifdef USE_OPENGL
|
||||
if (Settings.OpenGLEnable && GFX.RealPPL == 256)
|
||||
{
|
||||
// Have to back out of the speed up hack where the low res.
|
||||
// SNES image was rendered into a 256x239 sized buffer,
|
||||
// ignoring the true, larger size of the buffer.
|
||||
GFX.RealPPL = GFX.Pitch >> 1;
|
||||
uint16 *p = GFX.Screen + y * GFX.PPL + 255;
|
||||
uint16 *q = GFX.Screen + y * GFX.PPL + 510;
|
||||
|
||||
for (int32 y = (int32) GFX.StartY - 1; y >= 0; y--)
|
||||
{
|
||||
uint16 *p = GFX.Screen + y * GFX.PPL + 255;
|
||||
uint16 *q = GFX.Screen + y * GFX.RealPPL + 510;
|
||||
|
||||
for (int x = 255; x >= 0; x--, p--, q -= 2)
|
||||
*q = *(q + 1) = *p;
|
||||
}
|
||||
|
||||
GFX.PPL = GFX.RealPPL; // = GFX.Pitch >> 1 above
|
||||
}
|
||||
else
|
||||
#endif
|
||||
// Have to back out of the regular speed hack
|
||||
for (uint32 y = 0; y < GFX.StartY; y++)
|
||||
{
|
||||
uint16 *p = GFX.Screen + y * GFX.PPL + 255;
|
||||
uint16 *q = GFX.Screen + y * GFX.PPL + 510;
|
||||
|
||||
for (int x = 255; x >= 0; x--, p--, q -= 2)
|
||||
*q = *(q + 1) = *p;
|
||||
}
|
||||
|
||||
IPPU.DoubleWidthPixels = TRUE;
|
||||
IPPU.RenderedScreenWidth = 512;
|
||||
for (int x = 255; x >= 0; x--, p--, q -= 2)
|
||||
*q = *(q + 1) = *p;
|
||||
}
|
||||
|
||||
if (!IPPU.DoubleHeightPixels && IPPU.Interlace && (PPU.BGMode == 5 || PPU.BGMode == 6))
|
||||
{
|
||||
IPPU.DoubleHeightPixels = TRUE;
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
|
||||
GFX.PPL = GFX.RealPPL << 1;
|
||||
GFX.DoInterlace = 2;
|
||||
IPPU.DoubleWidthPixels = TRUE;
|
||||
IPPU.RenderedScreenWidth = 512;
|
||||
}
|
||||
|
||||
for (int32 y = (int32) GFX.StartY - 2; y >= 0; y--)
|
||||
memmove(GFX.Screen + (y + 1) * GFX.PPL, GFX.Screen + y * GFX.RealPPL, GFX.PPL * sizeof(uint16));
|
||||
}
|
||||
if (!IPPU.DoubleHeightPixels && IPPU.Interlace && (PPU.BGMode == 5 || PPU.BGMode == 6))
|
||||
{
|
||||
IPPU.DoubleHeightPixels = TRUE;
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
|
||||
GFX.PPL = GFX.RealPPL << 1;
|
||||
GFX.DoInterlace = 2;
|
||||
|
||||
for (int32 y = (int32) GFX.StartY - 2; y >= 0; y--)
|
||||
memmove(GFX.Screen + (y + 1) * GFX.PPL, GFX.Screen + y * GFX.RealPPL, GFX.PPL * sizeof(uint16));
|
||||
}
|
||||
|
||||
if ((Memory.FillRAM[0x2130] & 0x30) != 0x30 && (Memory.FillRAM[0x2131] & 0x3f))
|
||||
@@ -534,7 +500,7 @@ void S9xUpdateScreen (void)
|
||||
const uint16 black = BUILD_PIXEL(0, 0, 0);
|
||||
|
||||
GFX.S = GFX.Screen + GFX.StartY * GFX.PPL;
|
||||
if (GFX.DoInterlace && GFX.InterlaceFrame)
|
||||
if (GFX.DoInterlace && S9xInterlaceField())
|
||||
GFX.S += GFX.RealPPL;
|
||||
|
||||
for (uint32 l = GFX.StartY; l <= GFX.EndY; l++, GFX.S += GFX.PPL)
|
||||
@@ -595,7 +561,7 @@ static void SetupOBJ (void)
|
||||
|
||||
int inc = IPPU.InterlaceOBJ ? 2 : 1;
|
||||
|
||||
int startline = (IPPU.InterlaceOBJ && GFX.InterlaceFrame) ? 1 : 0;
|
||||
int startline = (IPPU.InterlaceOBJ && S9xInterlaceField()) ? 1 : 0;
|
||||
|
||||
// OK, we have three cases here. Either there's no priority, priority is
|
||||
// normal FirstSprite, or priority is FirstSprite+Y. The first two are
|
||||
@@ -603,6 +569,7 @@ static void SetupOBJ (void)
|
||||
|
||||
int Height;
|
||||
uint8 S;
|
||||
int sprite_limit = (Settings.MaxSpriteTilesPerLine == 128) ? 128 : 32;
|
||||
|
||||
if (!PPU.OAMPriorityRotation || !(PPU.OAMFlip & PPU.OAMAddr & 1)) // normal case
|
||||
{
|
||||
@@ -613,7 +580,7 @@ static void SetupOBJ (void)
|
||||
{
|
||||
GFX.OBJLines[i].RTOFlags = 0;
|
||||
GFX.OBJLines[i].Tiles = Settings.MaxSpriteTilesPerLine;
|
||||
for (int j = 0; j < 32; j++)
|
||||
for (int j = 0; j < sprite_limit; j++)
|
||||
GFX.OBJLines[i].OBJ[j].Sprite = -1;
|
||||
}
|
||||
|
||||
@@ -641,8 +608,7 @@ static void SetupOBJ (void)
|
||||
{
|
||||
if (HPos < 0)
|
||||
GFX.OBJVisibleTiles[S] = (GFX.OBJWidths[S] + HPos + 7) >> 3;
|
||||
else
|
||||
if (HPos + GFX.OBJWidths[S] > 255)
|
||||
else if (HPos + GFX.OBJWidths[S] > 255)
|
||||
GFX.OBJVisibleTiles[S] = (256 - HPos + 7) >> 3;
|
||||
else
|
||||
GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3;
|
||||
@@ -652,7 +618,7 @@ static void SetupOBJ (void)
|
||||
if (Y >= SNES_HEIGHT_EXTENDED)
|
||||
continue;
|
||||
|
||||
if (LineOBJ[Y] >= 32)
|
||||
if (LineOBJ[Y] >= sprite_limit)
|
||||
{
|
||||
GFX.OBJLines[Y].RTOFlags |= 0x40;
|
||||
continue;
|
||||
@@ -713,8 +679,7 @@ static void SetupOBJ (void)
|
||||
{
|
||||
if (HPos < 0)
|
||||
GFX.OBJVisibleTiles[S] = (GFX.OBJWidths[S] + HPos + 7) >> 3;
|
||||
else
|
||||
if (HPos + GFX.OBJWidths[S] >= 257)
|
||||
else if (HPos + GFX.OBJWidths[S] >= 257)
|
||||
GFX.OBJVisibleTiles[S] = (257 - HPos + 7) >> 3;
|
||||
else
|
||||
GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3;
|
||||
@@ -756,7 +721,7 @@ static void SetupOBJ (void)
|
||||
{
|
||||
if (OBJOnLine[Y][S])
|
||||
{
|
||||
if (j >= 32)
|
||||
if (j >= sprite_limit)
|
||||
{
|
||||
GFX.OBJLines[Y].RTOFlags |= 0x40;
|
||||
break;
|
||||
@@ -773,7 +738,7 @@ static void SetupOBJ (void)
|
||||
} while (S != FirstSprite);
|
||||
}
|
||||
|
||||
if (j < 32)
|
||||
if (j < sprite_limit)
|
||||
GFX.OBJLines[Y].OBJ[j].Sprite = -1;
|
||||
}
|
||||
}
|
||||
@@ -791,15 +756,16 @@ static void DrawOBJS (int D)
|
||||
void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32) = NULL;
|
||||
|
||||
int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1;
|
||||
BG.InterlaceLine = GFX.InterlaceFrame ? 8 : 0;
|
||||
BG.InterlaceLine = S9xInterlaceField() ? 8 : 0;
|
||||
GFX.Z1 = 2;
|
||||
int sprite_limit = (Settings.MaxSpriteTilesPerLine == 128) ? 128 : 32;
|
||||
|
||||
for (uint32 Y = GFX.StartY, Offset = Y * GFX.PPL; Y <= GFX.EndY; Y++, Offset += GFX.PPL)
|
||||
{
|
||||
int I = 0;
|
||||
int tiles = GFX.OBJLines[Y].Tiles;
|
||||
|
||||
for (int S = GFX.OBJLines[Y].OBJ[I].Sprite; S >= 0 && I < 32; S = GFX.OBJLines[Y].OBJ[++I].Sprite)
|
||||
for (int S = GFX.OBJLines[Y].OBJ[I].Sprite; S >= 0 && I < sprite_limit; S = GFX.OBJLines[Y].OBJ[++I].Sprite)
|
||||
{
|
||||
tiles += GFX.OBJVisibleTiles[S];
|
||||
if (tiles <= 0)
|
||||
@@ -925,7 +891,7 @@ static void DrawBackground (int bg, uint8 Zh, uint8 Zl)
|
||||
|
||||
for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines)
|
||||
{
|
||||
uint32 Y2 = HiresInterlace ? Y * 2 + GFX.InterlaceFrame : Y;
|
||||
uint32 Y2 = HiresInterlace ? Y * 2 + S9xInterlaceField() : Y;
|
||||
uint32 VOffset = LineData[Y].BG[bg].VOffset + (HiresInterlace ? 1 : 0);
|
||||
uint32 HOffset = LineData[Y].BG[bg].HOffset;
|
||||
int VirtAlign = ((Y2 + VOffset) & 7) >> (HiresInterlace ? 1 : 0);
|
||||
@@ -1319,7 +1285,7 @@ static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff)
|
||||
|
||||
for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++)
|
||||
{
|
||||
uint32 Y2 = HiresInterlace ? Y * 2 + GFX.InterlaceFrame : Y;
|
||||
uint32 Y2 = HiresInterlace ? Y * 2 + S9xInterlaceField() : Y;
|
||||
uint32 VOff = LineData[Y].BG[2].VOffset - 1;
|
||||
uint32 HOff = LineData[Y].BG[2].HOffset;
|
||||
uint32 HOffsetRow = VOff >> Offset2Shift;
|
||||
@@ -1838,6 +1804,20 @@ static void S9xDisplayStringType (const char *string, int linesFromBottom, int p
|
||||
S9xDisplayString (string, linesFromBottom, pixelsFromLeft, allowWrap);
|
||||
}
|
||||
|
||||
static void DisplayTime (void)
|
||||
{
|
||||
char string[10];
|
||||
|
||||
time_t rawtime;
|
||||
struct tm *timeinfo;
|
||||
|
||||
time (&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
sprintf(string, "%02u:%02u", timeinfo->tm_hour, timeinfo->tm_min);
|
||||
S9xDisplayString(string, 0, 0, false);
|
||||
}
|
||||
|
||||
static void DisplayFrameRate (void)
|
||||
{
|
||||
char string[10];
|
||||
@@ -2000,7 +1980,7 @@ static void DisplayWatchedAddresses (void)
|
||||
break;
|
||||
|
||||
int32 displayNumber = 0;
|
||||
char buf[32];
|
||||
char buf[64];
|
||||
|
||||
for (int r = 0; r < watches[i].size; r++)
|
||||
displayNumber += (Cheat.CWatchRAM[(watches[i].address - 0x7E0000) + r]) << (8 * r);
|
||||
@@ -2014,11 +1994,9 @@ static void DisplayWatchedAddresses (void)
|
||||
{
|
||||
if (watches[i].size == 1)
|
||||
displayNumber = (int32) ((int8) displayNumber);
|
||||
else
|
||||
if (watches[i].size == 2)
|
||||
else if (watches[i].size == 2)
|
||||
displayNumber = (int32) ((int16) displayNumber);
|
||||
else
|
||||
if (watches[i].size == 3)
|
||||
else if (watches[i].size == 3)
|
||||
if (displayNumber >= 8388608)
|
||||
displayNumber -= 16777216;
|
||||
|
||||
@@ -2031,6 +2009,9 @@ static void DisplayWatchedAddresses (void)
|
||||
|
||||
void S9xDisplayMessages (uint16 *screen, int ppl, int width, int height, int scale)
|
||||
{
|
||||
if (Settings.DisplayTime)
|
||||
DisplayTime();
|
||||
|
||||
if (Settings.DisplayFrameRate)
|
||||
DisplayFrameRate();
|
||||
|
||||
@@ -2043,8 +2024,8 @@ void S9xDisplayMessages (uint16 *screen, int ppl, int width, int height, int sca
|
||||
if (Settings.DisplayMovieFrame && S9xMovieActive())
|
||||
S9xDisplayString(GFX.FrameDisplayString, 1, 1, false);
|
||||
|
||||
if (GFX.InfoString && *GFX.InfoString)
|
||||
S9xDisplayString(GFX.InfoString, 5, 1, true);
|
||||
if (!GFX.InfoString.empty())
|
||||
S9xDisplayString(GFX.InfoString.c_str(), 5, 1, true);
|
||||
}
|
||||
|
||||
static uint16 get_crosshair_color (uint8 color)
|
||||
@@ -2117,10 +2098,10 @@ void S9xDrawCrosshair (const char *crosshair, uint8 fgcolor, uint8 bgcolor, int1
|
||||
uint8 p = crosshair[(r / rx) * 15 + (c / cx)];
|
||||
|
||||
if (p == '#' && fgcolor)
|
||||
*s = (fgcolor & 0x10) ? COLOR_ADD1_2(fg, *s) : fg;
|
||||
*s = (fgcolor & 0x10) ? COLOR_ADD::fn1_2(fg, *s) : fg;
|
||||
else
|
||||
if (p == '.' && bgcolor)
|
||||
*s = (bgcolor & 0x10) ? COLOR_ADD1_2(*s, bg) : bg;
|
||||
*s = (bgcolor & 0x10) ? COLOR_ADD::fn1_2(*s, bg) : bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,19 +8,21 @@
|
||||
#define _GFX_H_
|
||||
|
||||
#include "port.h"
|
||||
#include <vector>
|
||||
|
||||
struct SGFX
|
||||
{
|
||||
const uint32 Pitch = sizeof(uint16) * MAX_SNES_WIDTH;
|
||||
const uint32 RealPPL = MAX_SNES_WIDTH; // true PPL of Screen buffer
|
||||
const uint32 ScreenSize = MAX_SNES_WIDTH * MAX_SNES_HEIGHT;
|
||||
std::vector<uint16> ScreenBuffer;
|
||||
uint16 *Screen;
|
||||
uint16 *SubScreen;
|
||||
uint8 *ZBuffer;
|
||||
uint8 *SubZBuffer;
|
||||
uint32 Pitch;
|
||||
uint32 ScreenSize;
|
||||
uint16 *S;
|
||||
uint8 *DB;
|
||||
uint16 *ZERO;
|
||||
uint32 RealPPL; // true PPL of Screen buffer
|
||||
uint32 PPL; // number of pixels on each of Screen buffer
|
||||
uint32 LinesPerTile; // number of lines in 1 tile (4 or 8 due to interlace)
|
||||
uint16 *ScreenColors; // screen colors for rendering main
|
||||
@@ -29,7 +31,6 @@ struct SGFX
|
||||
uint8 Z2; // depth to save
|
||||
uint32 FixedColour;
|
||||
uint8 DoInterlace;
|
||||
uint8 InterlaceFrame;
|
||||
uint32 StartY;
|
||||
uint32 EndY;
|
||||
bool8 ClipColors;
|
||||
@@ -47,7 +48,7 @@ struct SGFX
|
||||
{
|
||||
int8 Sprite;
|
||||
uint8 Line;
|
||||
} OBJ[32];
|
||||
} OBJ[128];
|
||||
} OBJLines[SNES_HEIGHT_EXTENDED];
|
||||
|
||||
void (*DrawBackdropMath) (uint32, uint32, uint32);
|
||||
@@ -63,7 +64,7 @@ struct SGFX
|
||||
void (*DrawMode7BG2Math) (uint32, uint32, int);
|
||||
void (*DrawMode7BG2Nomath) (uint32, uint32, int);
|
||||
|
||||
const char *InfoString;
|
||||
std::string InfoString;
|
||||
uint32 InfoStringTimeout;
|
||||
char FrameDisplayString[256];
|
||||
};
|
||||
@@ -127,60 +128,77 @@ extern struct SGFX GFX;
|
||||
#define V_FLIP 0x8000
|
||||
#define BLANK_TILE 2
|
||||
|
||||
#define COLOR_ADD1_2(C1, C2) \
|
||||
((((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \
|
||||
((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \
|
||||
((C1) & (C2) & RGB_LOW_BITS_MASK)) | ALPHA_BITS_MASK)
|
||||
#define COLOR_ADD_BRIGHTNESS1_2 COLOR_ADD1_2
|
||||
|
||||
inline uint16 COLOR_ADD_BRIGHTNESS(uint16 C1, uint16 C2)
|
||||
struct COLOR_ADD
|
||||
{
|
||||
return ((brightness_cap[ (C1 >> RED_SHIFT_BITS) + (C2 >> RED_SHIFT_BITS) ] << RED_SHIFT_BITS) |
|
||||
(brightness_cap[((C1 >> GREEN_SHIFT_BITS) & 0x1f) + ((C2 >> GREEN_SHIFT_BITS) & 0x1f)] << GREEN_SHIFT_BITS) |
|
||||
// Proper 15->16bit color conversion moves the high bit of green into the low bit.
|
||||
#if GREEN_SHIFT_BITS == 6
|
||||
((brightness_cap[((C1 >> 6) & 0x1f) + ((C2 >> 6) & 0x1f)] & 0x10) << 1) |
|
||||
#endif
|
||||
(brightness_cap[ (C1 & 0x1f) + (C2 & 0x1f)] ));
|
||||
}
|
||||
static alwaysinline uint16 fn(uint16 C1, uint16 C2)
|
||||
{
|
||||
const int RED_MASK = 0x1F << RED_SHIFT_BITS;
|
||||
const int GREEN_MASK = 0x1F << GREEN_SHIFT_BITS;
|
||||
const int BLUE_MASK = 0x1F;
|
||||
|
||||
inline uint16 COLOR_ADD(uint16 C1, uint16 C2)
|
||||
int rb = C1 & (RED_MASK | BLUE_MASK);
|
||||
rb += C2 & (RED_MASK | BLUE_MASK);
|
||||
int rbcarry = rb & ((0x20 << RED_SHIFT_BITS) | (0x20 << 0));
|
||||
int g = (C1 & (GREEN_MASK)) + (C2 & (GREEN_MASK));
|
||||
int rgbsaturate = (((g & (0x20 << GREEN_SHIFT_BITS)) | rbcarry) >> 5) * 0x1f;
|
||||
uint16 retval = (rb & (RED_MASK | BLUE_MASK)) | (g & GREEN_MASK) | rgbsaturate;
|
||||
#if GREEN_SHIFT_BITS == 6
|
||||
retval |= (retval & 0x0400) >> 5;
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
static alwaysinline uint16 fn1_2(uint16 C1, uint16 C2)
|
||||
{
|
||||
return ((((C1 & RGB_REMOVE_LOW_BITS_MASK) +
|
||||
(C2 & RGB_REMOVE_LOW_BITS_MASK)) >> 1) +
|
||||
(C1 & C2 & RGB_LOW_BITS_MASK)) | ALPHA_BITS_MASK;
|
||||
}
|
||||
};
|
||||
|
||||
struct COLOR_ADD_BRIGHTNESS
|
||||
{
|
||||
const int RED_MASK = 0x1F << RED_SHIFT_BITS;
|
||||
const int GREEN_MASK = 0x1F << GREEN_SHIFT_BITS;
|
||||
const int BLUE_MASK = 0x1F;
|
||||
static alwaysinline uint16 fn(uint16 C1, uint16 C2)
|
||||
{
|
||||
return ((brightness_cap[ (C1 >> RED_SHIFT_BITS) + (C2 >> RED_SHIFT_BITS) ] << RED_SHIFT_BITS) |
|
||||
(brightness_cap[((C1 >> GREEN_SHIFT_BITS) & 0x1f) + ((C2 >> GREEN_SHIFT_BITS) & 0x1f)] << GREEN_SHIFT_BITS) |
|
||||
// Proper 15->16bit color conversion moves the high bit of green into the low bit.
|
||||
#if GREEN_SHIFT_BITS == 6
|
||||
((brightness_cap[((C1 >> 6) & 0x1f) + ((C2 >> 6) & 0x1f)] & 0x10) << 1) |
|
||||
#endif
|
||||
(brightness_cap[ (C1 & 0x1f) + (C2 & 0x1f)] ));
|
||||
}
|
||||
|
||||
int rb = C1 & (RED_MASK | BLUE_MASK);
|
||||
rb += C2 & (RED_MASK | BLUE_MASK);
|
||||
int rbcarry = rb & ((0x20 << RED_SHIFT_BITS) | (0x20 << 0));
|
||||
int g = (C1 & (GREEN_MASK)) + (C2 & (GREEN_MASK));
|
||||
int rgbsaturate = (((g & (0x20 << GREEN_SHIFT_BITS)) | rbcarry) >> 5) * 0x1f;
|
||||
uint16 retval = (rb & (RED_MASK | BLUE_MASK)) | (g & GREEN_MASK) | rgbsaturate;
|
||||
#if GREEN_SHIFT_BITS == 6
|
||||
retval |= (retval & 0x0400) >> 5;
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
static alwaysinline uint16 fn1_2(uint16 C1, uint16 C2)
|
||||
{
|
||||
return COLOR_ADD::fn1_2(C1, C2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define COLOR_SUB1_2(C1, C2) \
|
||||
GFX.ZERO[(((C1) | RGB_HI_BITS_MASKx2) - \
|
||||
((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1]
|
||||
|
||||
inline uint16 COLOR_SUB (uint16 C1, uint16 C2)
|
||||
struct COLOR_SUB
|
||||
{
|
||||
int rb1 = (C1 & (THIRD_COLOR_MASK | FIRST_COLOR_MASK)) | ((0x20 << 0) | (0x20 << RED_SHIFT_BITS));
|
||||
int rb2 = C2 & (THIRD_COLOR_MASK | FIRST_COLOR_MASK);
|
||||
int rb = rb1 - rb2;
|
||||
int rbcarry = rb & ((0x20 << RED_SHIFT_BITS) | (0x20 << 0));
|
||||
int g = ((C1 & (SECOND_COLOR_MASK)) | (0x20 << GREEN_SHIFT_BITS)) - (C2 & (SECOND_COLOR_MASK));
|
||||
int rgbsaturate = (((g & (0x20 << GREEN_SHIFT_BITS)) | rbcarry) >> 5) * 0x1f;
|
||||
uint16 retval = ((rb & (THIRD_COLOR_MASK | FIRST_COLOR_MASK)) | (g & SECOND_COLOR_MASK)) & rgbsaturate;
|
||||
static alwaysinline uint16 fn(uint16 C1, uint16 C2)
|
||||
{
|
||||
int rb1 = (C1 & (THIRD_COLOR_MASK | FIRST_COLOR_MASK)) | ((0x20 << 0) | (0x20 << RED_SHIFT_BITS));
|
||||
int rb2 = C2 & (THIRD_COLOR_MASK | FIRST_COLOR_MASK);
|
||||
int rb = rb1 - rb2;
|
||||
int rbcarry = rb & ((0x20 << RED_SHIFT_BITS) | (0x20 << 0));
|
||||
int g = ((C1 & (SECOND_COLOR_MASK)) | (0x20 << GREEN_SHIFT_BITS)) - (C2 & (SECOND_COLOR_MASK));
|
||||
int rgbsaturate = (((g & (0x20 << GREEN_SHIFT_BITS)) | rbcarry) >> 5) * 0x1f;
|
||||
uint16 retval = ((rb & (THIRD_COLOR_MASK | FIRST_COLOR_MASK)) | (g & SECOND_COLOR_MASK)) & rgbsaturate;
|
||||
#if GREEN_SHIFT_BITS == 6
|
||||
retval |= (retval & 0x0400) >> 5;
|
||||
retval |= (retval & 0x0400) >> 5;
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static alwaysinline uint16 fn1_2(uint16 C1, uint16 C2)
|
||||
{
|
||||
return GFX.ZERO[((C1 | RGB_HI_BITS_MASKx2) -
|
||||
(C2 & RGB_REMOVE_LOW_BITS_MASK)) >> 1];
|
||||
}
|
||||
};
|
||||
|
||||
void S9xStartScreenRefresh (void);
|
||||
void S9xEndScreenRefresh (void);
|
||||
@@ -199,7 +217,6 @@ bool8 S9xInitUpdate (void);
|
||||
bool8 S9xDeinitUpdate (int, int);
|
||||
bool8 S9xContinueUpdate (int, int);
|
||||
void S9xReRefresh (void);
|
||||
void S9xSetPalette (void);
|
||||
void S9xSyncSpeed (void);
|
||||
|
||||
// called instead of S9xDisplayString if set to non-NULL
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+420
-1027
File diff suppressed because it is too large
Load Diff
Executable → Regular
+18
-10
@@ -12,10 +12,13 @@
|
||||
#define MEMMAP_SHIFT (12)
|
||||
#define MEMMAP_MASK (MEMMAP_BLOCK_SIZE - 1)
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct CMemory
|
||||
{
|
||||
enum
|
||||
{ MAX_ROM_SIZE = 0x800000 };
|
||||
{ MAX_ROM_SIZE = 0xC00000 };
|
||||
|
||||
enum file_formats
|
||||
{ FILE_ZIP, FILE_JMA, FILE_DEFAULT };
|
||||
@@ -53,10 +56,13 @@ struct CMemory
|
||||
uint8 NSRTHeader[32];
|
||||
int32 HeaderCount;
|
||||
|
||||
uint8 *RAM;
|
||||
uint8 *ROM;
|
||||
uint8 RAM[0x20000];
|
||||
std::vector<uint8_t> ROMStorage;
|
||||
uint8 *ROM;
|
||||
std::vector<uint8_t> SRAMStorage;
|
||||
uint8 *SRAM;
|
||||
uint8 *VRAM;
|
||||
const size_t SRAM_SIZE = 0x80000;
|
||||
uint8 VRAM[0x10000];
|
||||
uint8 *FillRAM;
|
||||
uint8 *BWRAM;
|
||||
uint8 *C4RAM;
|
||||
@@ -70,9 +76,8 @@ struct CMemory
|
||||
uint8 BlockIsROM[MEMMAP_NUM_BLOCKS];
|
||||
uint8 ExtendedFormat;
|
||||
|
||||
char ROMFilename[PATH_MAX + 1];
|
||||
std::string ROMFilename;
|
||||
char ROMName[ROM_NAME_LEN];
|
||||
char RawROMName[ROM_NAME_LEN];
|
||||
char ROMId[5];
|
||||
int32 CompanyId;
|
||||
uint8 ROMRegion;
|
||||
@@ -103,8 +108,7 @@ struct CMemory
|
||||
int First512BytesCountZeroes() const;
|
||||
uint32 HeaderRemove (uint32, uint8 *);
|
||||
uint32 FileLoader (uint8 *, const char *, uint32);
|
||||
uint32 MemLoader (uint8 *, const char*, uint32);
|
||||
bool8 LoadROMMem (const uint8 *, uint32);
|
||||
bool8 LoadROMMem (const uint8 *, uint32, const char* optional_rom_filename = NULL);
|
||||
bool8 LoadROM (const char *);
|
||||
bool8 LoadROMInt (int32);
|
||||
bool8 LoadMultiCartMem (const uint8 *, uint32, const uint8 *, uint32, const uint8 *, uint32);
|
||||
@@ -120,8 +124,6 @@ struct CMemory
|
||||
bool8 SaveSRTC (void);
|
||||
bool8 SaveMPAK (const char *);
|
||||
|
||||
char * Safe (const char *);
|
||||
char * SafeANK (const char *);
|
||||
void ParseSNESHeader (uint8 *);
|
||||
void InitROM (void);
|
||||
|
||||
@@ -170,6 +172,7 @@ struct CMemory
|
||||
bool8 match_nc (const char *);
|
||||
bool8 match_id (const char *);
|
||||
void ApplyROMFixes (void);
|
||||
std::string SafeString(std::string s, bool allow_jis = false);
|
||||
void CheckForAnyPatch (const char *, bool8, int32 &);
|
||||
|
||||
void MakeRomInfoText (char *);
|
||||
@@ -197,6 +200,11 @@ struct SMulti
|
||||
extern CMemory Memory;
|
||||
extern SMulti Multi;
|
||||
|
||||
inline bool S9xInterlaceField()
|
||||
{
|
||||
return (Memory.FillRAM[0x213F] & 0x80) >> 7;
|
||||
}
|
||||
|
||||
void S9xAutoSaveSRAM (void);
|
||||
bool8 LoadZip(const char *, uint32 *, uint8 *);
|
||||
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
+1
-2
@@ -434,7 +434,7 @@ static int read_movie_extrarominfo (FILE *fd, SMovie *movie)
|
||||
|
||||
ptr += 3; // zero bytes
|
||||
movie->ROMCRC32 = Read32(ptr);
|
||||
sstrncpy(movie->ROMName, (char *) ptr, 23);
|
||||
memcpy(movie->ROMName, (char *) ptr, 23);
|
||||
|
||||
return (SUCCESS);
|
||||
}
|
||||
@@ -740,7 +740,6 @@ int S9xMovieCreate (const char *filename, uint8 controllers_mask, uint8 opts, co
|
||||
}
|
||||
|
||||
Movie.ROMCRC32 = Memory.ROMCRC32;
|
||||
strncpy(Movie.ROMName, Memory.RawROMName, 23);
|
||||
|
||||
write_movie_extrarominfo(fd, &Movie);
|
||||
|
||||
|
||||
Executable → Regular
-1
@@ -48,7 +48,6 @@ int S9xMovieGetInfo (const char *, struct MovieInfo *);
|
||||
void S9xMovieStop (bool8);
|
||||
void S9xMovieToggleRecState (void);
|
||||
void S9xMovieToggleFrameDisplay (void);
|
||||
const char * S9xChooseMovieFilename (bool8);
|
||||
|
||||
// methods used by the emulation
|
||||
void S9xMovieInit (void);
|
||||
|
||||
Executable → Regular
+20
-16
@@ -57,27 +57,27 @@ static int unzFindExtension(unzFile &file, const char *ext, bool restart = TRUE,
|
||||
|
||||
STREAM S9xMSU1OpenFile(const char *msu_ext, bool skip_unpacked)
|
||||
{
|
||||
const char *filename = S9xGetFilename(msu_ext, ROMFILENAME_DIR);
|
||||
auto filename = S9xGetFilename(msu_ext, ROMFILENAME_DIR);
|
||||
STREAM file = 0;
|
||||
|
||||
if (!skip_unpacked)
|
||||
{
|
||||
file = OPEN_STREAM(filename, "rb");
|
||||
file = OPEN_STREAM(filename.c_str(), "rb");
|
||||
if (file)
|
||||
printf("Using msu file %s.\n", filename);
|
||||
printf("Using msu file %s.\n", filename.c_str());
|
||||
}
|
||||
|
||||
#ifdef UNZIP_SUPPORT
|
||||
// look for msu1 pack file in the rom or patch dir if msu data file not found in rom dir
|
||||
if (!file)
|
||||
{
|
||||
const char *zip_filename = S9xGetFilename(".msu1", ROMFILENAME_DIR);
|
||||
unzFile unzFile = unzOpen(zip_filename);
|
||||
auto zip_filename = S9xGetFilename(".msu1", ROMFILENAME_DIR);
|
||||
unzFile unzFile = unzOpen(zip_filename.c_str());
|
||||
|
||||
if (!unzFile)
|
||||
{
|
||||
zip_filename = S9xGetFilename(".msu1", PATCH_DIR);
|
||||
unzFile = unzOpen(zip_filename);
|
||||
unzFile = unzOpen(zip_filename.c_str());
|
||||
}
|
||||
|
||||
if (unzFile)
|
||||
@@ -85,7 +85,6 @@ STREAM S9xMSU1OpenFile(const char *msu_ext, bool skip_unpacked)
|
||||
int port = unzFindExtension(unzFile, msu_ext, true, true, true);
|
||||
if (port == UNZ_OK)
|
||||
{
|
||||
printf(" in %s.\n", zip_filename);
|
||||
file = new unzStream(unzFile);
|
||||
}
|
||||
else
|
||||
@@ -112,10 +111,9 @@ static bool AudioOpen()
|
||||
|
||||
AudioClose();
|
||||
|
||||
char ext[_MAX_EXT];
|
||||
snprintf(ext, _MAX_EXT, "-%d.pcm", MSU1.MSU1_CURRENT_TRACK);
|
||||
std::string extension = "-" + std::to_string(MSU1.MSU1_CURRENT_TRACK) + ".pcm";
|
||||
|
||||
audioStream = S9xMSU1OpenFile(ext);
|
||||
audioStream = S9xMSU1OpenFile(extension.c_str());
|
||||
if (audioStream)
|
||||
{
|
||||
if (GETC_STREAM(audioStream) != 'M')
|
||||
@@ -207,15 +205,14 @@ bool S9xMSU1ROMExists(void)
|
||||
return true;
|
||||
}
|
||||
#ifdef UNZIP_SUPPORT
|
||||
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
|
||||
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
|
||||
if (!strcasecmp(ext, ".msu1"))
|
||||
|
||||
if (splitpath(Memory.ROMFilename).ext_is(".msu1"))
|
||||
return true;
|
||||
|
||||
unzFile unzFile = unzOpen(S9xGetFilename(".msu1", ROMFILENAME_DIR));
|
||||
unzFile unzFile = unzOpen(S9xGetFilename(".msu1", ROMFILENAME_DIR).c_str());
|
||||
|
||||
if(!unzFile)
|
||||
unzFile = unzOpen(S9xGetFilename(".msu1", PATCH_DIR));
|
||||
unzFile = unzOpen(S9xGetFilename(".msu1", PATCH_DIR).c_str());
|
||||
|
||||
if (unzFile)
|
||||
{
|
||||
@@ -253,7 +250,14 @@ void S9xMSU1Generate(size_t sample_count)
|
||||
{
|
||||
if (MSU1.MSU1_STATUS & AudioRepeating)
|
||||
{
|
||||
MSU1.MSU1_AUDIO_POS = audioLoopPos;
|
||||
if (audioLoopPos < MSU1.MSU1_AUDIO_POS)
|
||||
{
|
||||
MSU1.MSU1_AUDIO_POS = audioLoopPos;
|
||||
}
|
||||
else // if the loop point is invalid, revert to start
|
||||
{
|
||||
MSU1.MSU1_AUDIO_POS = 8;
|
||||
}
|
||||
REVERT_STREAM(audioStream, MSU1.MSU1_AUDIO_POS, 0);
|
||||
}
|
||||
else
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user