11 Commits

Author SHA1 Message Date
clobber 6b1495d48b Merge pull request #8 from ShutOstrich/master
Update to Snes9x 1.62.3
2023-04-29 20:53:21 -06:00
ShutOstrich c0e0b5580c Update to Snes9x 1.62.3 2023-04-30 00:32:42 +02:00
clobber d2dc097eff Restore OpenEmu workarounds from commits 622eb6ab8a & c6c5306cbd 2022-12-18 22:49:29 -07:00
clobber 4fad1f3005 Update to Snes9x 1.61 2022-12-18 01:01:46 -07:00
clobber b10c052626 Remove executable flag from source files. 2022-12-17 22:03:45 -07:00
C.W. Betts 652dd3ec0a Fix some static analyzer warnings about null dereferencing an error pointer.
Other Static analysis warnings.
2021-02-20 02:54:09 -07:00
C.W. Betts f31480c0be Poke the plists: get the development language from Xcode build. 2020-10-01 01:51:37 -06:00
C.W. Betts 61284bed2b Fix locations of the system plugin headers.
Minor Xcode maintenance.
2020-10-01 01:26:41 -06:00
Stuart Carnie 869c2f6680 fix: Remove VALID_ARCH restriction to allow universal support 2020-07-06 17:42:38 -07:00
C.W. Betts 7b86e8c494 Update language resources.
This quiets warnings in newer Xcode releases.

Also update framework locations.
2020-01-07 16:43:54 -07:00
Stuart Carnie 1f4dce126a fix: aggregate samples, single call -[OEAudioBuffer write:maxLength:] 2019-06-08 10:36:07 -07:00
151 changed files with 3448 additions and 3757 deletions
Binary file not shown.
+3 -3
View File
@@ -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>
+31 -14
View File
@@ -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
View File
@@ -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()
{
}
+2
View File
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
Executable → Regular
View File
Executable → Regular
+6 -4
View File
@@ -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
View File
@@ -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
View File
Executable → Regular
+10 -2
View File
@@ -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
View File
@@ -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
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
View File
View File
View File
View File
View File
View File
View File
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
-11
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
Executable → Regular
+18 -22
View File
@@ -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
View File
@@ -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
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
+1 -107
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
+67
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
Executable → Regular
+2 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
Executable → Regular
View File
Executable → Regular
+15 -7
View File
@@ -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
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
-24
View File
@@ -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
View File
Executable → Regular
View File
Executable → Regular
+64
View File
@@ -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
View File
Executable → Regular
View File
Executable → Regular
+1 -13
View File
@@ -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
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
+184 -204
View File
@@ -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
View File
Executable → Regular
+2 -2
View File
@@ -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
View File
@@ -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
View File
+238
View File
@@ -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
+52
View File
@@ -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
View File
Executable → Regular
+11 -20
View File
@@ -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
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
+11 -11
View File
@@ -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
View File
@@ -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;
}
}
}
Executable → Regular
+69 -52
View File
@@ -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
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
+420 -1027
View File
File diff suppressed because it is too large Load Diff
Executable → Regular
+18 -10
View File
@@ -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
View File
Executable → Regular
View File
Executable → Regular
+1 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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