Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b1495d48b | |||
| c0e0b5580c |
+1
-1
@@ -19,7 +19,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.61</string>
|
||||
<string>1.62.3</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>OEGameCoreController</string>
|
||||
<key>OEGameCoreClass</key>
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
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 */; };
|
||||
@@ -158,6 +159,8 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
@@ -394,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 */,
|
||||
@@ -668,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 */,
|
||||
@@ -716,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 = (
|
||||
@@ -745,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;
|
||||
|
||||
+6
-54
@@ -101,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;
|
||||
@@ -123,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();
|
||||
@@ -666,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"]];
|
||||
@@ -907,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -935,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];
|
||||
@@ -982,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1019,27 +982,16 @@ 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 *S9xGetFilename(const char *extension, enum s9x_getdirtype dirtype)
|
||||
std::string S9xGetFilenameInc(std::string, enum s9x_getdirtype)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *S9xGetFilenameInc(const char *, enum s9x_getdirtype)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool S9xPollButton(uint32 id, bool *pressed)
|
||||
{
|
||||
return true;
|
||||
|
||||
+4
-4
@@ -21,7 +21,7 @@
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2022 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 - 2022 BearOso
|
||||
(c) Copyright 2004 - 2023 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
@@ -147,13 +147,13 @@
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2022 OV2
|
||||
(c) Copyright 2009 - 2023 OV2
|
||||
|
||||
Original Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2011 zones
|
||||
New MacOS GUI code
|
||||
(c) Copyright 2022 Michael Donald Buckley
|
||||
(c) Copyright 2022 - 2023 Michael Donald Buckley
|
||||
|
||||
Libretro port
|
||||
(c) Copyright 2011 - 2017 Hans-Kristian Arntzen,
|
||||
|
||||
+54
-91
@@ -5,6 +5,7 @@
|
||||
\*****************************************************************************/
|
||||
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include "../snes9x.h"
|
||||
#include "apu.h"
|
||||
#include "../msu1.h"
|
||||
@@ -36,10 +37,10 @@ namespace spc {
|
||||
static apu_callback callback = NULL;
|
||||
static void *callback_data = NULL;
|
||||
|
||||
static bool8 sound_in_sync = TRUE;
|
||||
static bool8 sound_enabled = FALSE;
|
||||
static bool8 sound_in_sync = true;
|
||||
static bool8 sound_enabled = false;
|
||||
|
||||
static Resampler *resampler = NULL;
|
||||
static Resampler resampler;
|
||||
|
||||
static int32 reference_time;
|
||||
static uint32 remainder;
|
||||
@@ -56,9 +57,8 @@ static double dynamic_rate_multiplier = 1.0;
|
||||
|
||||
namespace msu {
|
||||
// Always 16-bit, Stereo; 1.5x dsp buffer to never overflow
|
||||
static Resampler *resampler = NULL;
|
||||
static int16 *resample_buffer = NULL;
|
||||
static int resample_buffer_size = 0;
|
||||
static Resampler resampler;
|
||||
static std::vector<int16_t> resampler_buffer;
|
||||
} // namespace msu
|
||||
|
||||
static void UpdatePlaybackRate(void);
|
||||
@@ -74,44 +74,32 @@ bool8 S9xMixSamples(uint8 *dest, int sample_count)
|
||||
{
|
||||
memset(out, 0, sample_count << 1);
|
||||
S9xClearSamples();
|
||||
spc::sound_in_sync = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
if (spc::resampler.avail() < sample_count)
|
||||
{
|
||||
if (spc::resampler->avail() >= sample_count)
|
||||
{
|
||||
spc::resampler->read((short *)out, sample_count);
|
||||
memset(out, 0, sample_count << 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Settings.MSU1)
|
||||
{
|
||||
if (msu::resampler->avail() >= sample_count)
|
||||
{
|
||||
if (msu::resample_buffer_size < sample_count)
|
||||
{
|
||||
if (msu::resample_buffer)
|
||||
delete[] msu::resample_buffer;
|
||||
msu::resample_buffer = new int16[sample_count];
|
||||
msu::resample_buffer_size = sample_count;
|
||||
}
|
||||
msu::resampler->read(msu::resample_buffer,
|
||||
sample_count);
|
||||
for (int i = 0; i < sample_count; ++i)
|
||||
{
|
||||
int32 mixed = (int32)out[i] + msu::resample_buffer[i];
|
||||
out[i] = ((int16)mixed != mixed) ? (mixed >> 31) ^ 0x7fff : mixed;
|
||||
}
|
||||
}
|
||||
else // should never occur
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
spc::resampler.read((short *)out, sample_count);
|
||||
|
||||
if (Settings.MSU1)
|
||||
{
|
||||
if ((int)msu::resampler_buffer.size() < sample_count)
|
||||
msu::resampler_buffer.resize(sample_count);
|
||||
|
||||
msu::resampler.read(msu::resampler_buffer.data(), sample_count);
|
||||
for (int i = 0; i < sample_count; ++i)
|
||||
{
|
||||
memset(out, 0, sample_count << 1);
|
||||
return false;
|
||||
int32 mixed = (int32)out[i] + msu::resampler_buffer[i];
|
||||
out[i] = ((int16)mixed != mixed) ? (mixed >> 31) ^ 0x7fff : mixed;
|
||||
}
|
||||
}
|
||||
|
||||
if (spc::resampler->space_empty() >= 535 * 2 || !Settings.SoundSync ||
|
||||
if (spc::resampler.space_empty() >= 535 * 2 || !Settings.SoundSync ||
|
||||
Settings.TurboMode || Settings.Mute)
|
||||
spc::sound_in_sync = true;
|
||||
else
|
||||
@@ -122,7 +110,10 @@ bool8 S9xMixSamples(uint8 *dest, int sample_count)
|
||||
|
||||
int S9xGetSampleCount(void)
|
||||
{
|
||||
return spc::resampler->avail();
|
||||
int avail = spc::resampler.avail();
|
||||
if (Settings.MSU1) // return minimum available samples, otherwise we can run into the assert above due to partial sample generation in msu1
|
||||
avail = Resampler::min(avail, msu::resampler.avail());
|
||||
return avail;
|
||||
}
|
||||
|
||||
void S9xLandSamples(void)
|
||||
@@ -130,7 +121,7 @@ void S9xLandSamples(void)
|
||||
if (spc::callback != NULL)
|
||||
spc::callback(spc::callback_data);
|
||||
|
||||
if (spc::resampler->space_empty() >= 535 * 2 || !Settings.SoundSync ||
|
||||
if (spc::resampler.space_empty() >= 535 * 2 || !Settings.SoundSync ||
|
||||
Settings.TurboMode || Settings.Mute)
|
||||
spc::sound_in_sync = true;
|
||||
else
|
||||
@@ -139,15 +130,15 @@ void S9xLandSamples(void)
|
||||
|
||||
void S9xClearSamples(void)
|
||||
{
|
||||
spc::resampler->clear();
|
||||
spc::resampler.clear();
|
||||
if (Settings.MSU1)
|
||||
msu::resampler->clear();
|
||||
msu::resampler.clear();
|
||||
}
|
||||
|
||||
bool8 S9xSyncSound(void)
|
||||
{
|
||||
if (!Settings.SoundSync || spc::sound_in_sync)
|
||||
return (TRUE);
|
||||
return true;
|
||||
|
||||
S9xLandSamples();
|
||||
|
||||
@@ -180,12 +171,12 @@ static void UpdatePlaybackRate(void)
|
||||
time_ratio *= spc::dynamic_rate_multiplier;
|
||||
}
|
||||
|
||||
spc::resampler->time_ratio(time_ratio);
|
||||
spc::resampler.time_ratio(time_ratio);
|
||||
|
||||
if (Settings.MSU1)
|
||||
{
|
||||
time_ratio = (44100.0 / Settings.SoundPlaybackRate) * (Settings.SoundInputRate / 32040.0);
|
||||
msu::resampler->time_ratio(time_ratio);
|
||||
time_ratio = time_ratio * 44100 / 32040;
|
||||
msu::resampler.time_ratio(time_ratio);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,27 +189,11 @@ bool8 S9xInitSound(int buffer_ms)
|
||||
if (requested_buffer_size_samples > buffer_size_samples)
|
||||
buffer_size_samples = requested_buffer_size_samples;
|
||||
|
||||
if (!spc::resampler)
|
||||
{
|
||||
spc::resampler = new Resampler(buffer_size_samples);
|
||||
if (!spc::resampler)
|
||||
return (FALSE);
|
||||
}
|
||||
else
|
||||
spc::resampler->resize(buffer_size_samples);
|
||||
spc::resampler.resize(buffer_size_samples);
|
||||
msu::resampler.resize(buffer_size_samples * 3 / 2);
|
||||
|
||||
|
||||
if (!msu::resampler)
|
||||
{
|
||||
msu::resampler = new Resampler(buffer_size_samples * 3 / 2);
|
||||
if (!msu::resampler)
|
||||
return (FALSE);
|
||||
}
|
||||
else
|
||||
msu::resampler->resize(buffer_size_samples * 3 / 2);
|
||||
|
||||
SNES::dsp.spc_dsp.set_output(spc::resampler);
|
||||
S9xMSU1SetOutput(msu::resampler);
|
||||
SNES::dsp.spc_dsp.set_output(&spc::resampler);
|
||||
S9xMSU1SetOutput(&msu::resampler);
|
||||
|
||||
UpdatePlaybackRate();
|
||||
|
||||
@@ -236,7 +211,7 @@ void S9xSetSoundMute(bool8 mute)
|
||||
{
|
||||
Settings.Mute = mute;
|
||||
if (!spc::sound_enabled)
|
||||
Settings.Mute = TRUE;
|
||||
Settings.Mute = true;
|
||||
}
|
||||
|
||||
void S9xDumpSPCSnapshot(void)
|
||||
@@ -246,33 +221,22 @@ void S9xDumpSPCSnapshot(void)
|
||||
|
||||
static void SPCSnapshotCallback(void)
|
||||
{
|
||||
S9xSPCDump(S9xGetFilenameInc((".spc"), SPC_DIR));
|
||||
S9xSPCDump(S9xGetFilenameInc((".spc"), SPC_DIR).c_str());
|
||||
printf("Dumped key-on triggered spc snapshot.\n");
|
||||
}
|
||||
|
||||
bool8 S9xInitAPU(void)
|
||||
{
|
||||
spc::resampler = NULL;
|
||||
msu::resampler = NULL;
|
||||
spc::resampler.clear();
|
||||
msu::resampler.clear();
|
||||
|
||||
return (TRUE);
|
||||
return true;
|
||||
}
|
||||
|
||||
void S9xDeinitAPU(void)
|
||||
{
|
||||
if (spc::resampler)
|
||||
{
|
||||
delete spc::resampler;
|
||||
spc::resampler = NULL;
|
||||
}
|
||||
|
||||
if (msu::resampler)
|
||||
{
|
||||
delete msu::resampler;
|
||||
msu::resampler = NULL;
|
||||
}
|
||||
|
||||
S9xMSU1DeInit();
|
||||
msu::resampler_buffer.clear();
|
||||
}
|
||||
|
||||
static inline int S9xAPUGetClock(int32 cpucycles)
|
||||
@@ -306,10 +270,10 @@ void S9xAPUSetReferenceTime(int32 cpucycles)
|
||||
|
||||
void S9xAPUExecute(void)
|
||||
{
|
||||
SNES::smp.clock -= S9xAPUGetClock(CPU.Cycles);
|
||||
SNES::smp.enter();
|
||||
|
||||
int cycles = S9xAPUGetClock(CPU.Cycles);
|
||||
spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles);
|
||||
SNES::smp.clock -= cycles;
|
||||
SNES::smp.enter();
|
||||
|
||||
S9xAPUSetReferenceTime(CPU.Cycles);
|
||||
}
|
||||
@@ -319,7 +283,7 @@ void S9xAPUEndScanline(void)
|
||||
S9xAPUExecute();
|
||||
SNES::dsp.synchronize();
|
||||
|
||||
if (spc::resampler->space_filled() >= APU_SAMPLE_BLOCK || !spc::sound_in_sync)
|
||||
if (spc::resampler.space_filled() >= APU_SAMPLE_BLOCK)
|
||||
S9xLandSamples();
|
||||
}
|
||||
|
||||
@@ -386,7 +350,6 @@ void S9xAPULoadState(uint8 *block)
|
||||
|
||||
SNES::smp.load_state(&ptr);
|
||||
SNES::dsp.load_state(&ptr);
|
||||
|
||||
spc::reference_time = SNES::get_le32(ptr);
|
||||
ptr += sizeof(int32);
|
||||
spc::remainder = SNES::get_le32(ptr);
|
||||
@@ -515,9 +478,9 @@ bool8 S9xSPCDump(const char *filename)
|
||||
|
||||
fs = fopen(filename, "wb");
|
||||
if (!fs)
|
||||
return (FALSE);
|
||||
return false;
|
||||
|
||||
S9xSetSoundMute(TRUE);
|
||||
S9xSetSoundMute(true);
|
||||
|
||||
SNES::smp.save_spc(buf);
|
||||
|
||||
@@ -530,7 +493,7 @@ bool8 S9xSPCDump(const char *filename)
|
||||
|
||||
fclose(fs);
|
||||
|
||||
S9xSetSoundMute(FALSE);
|
||||
S9xSetSoundMute(false);
|
||||
|
||||
return (TRUE);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -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 ) \
|
||||
{\
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
+5
-3
@@ -65,10 +65,9 @@ class Resampler
|
||||
|
||||
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()
|
||||
@@ -220,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();
|
||||
|
||||
+15
-23
@@ -738,16 +738,14 @@ void S9xBSXSetStream1 (uint8 count)
|
||||
if (BSX.sat_stream1.is_open())
|
||||
BSX.sat_stream1.close(); //If Stream already opened for one file: Close it.
|
||||
|
||||
char path[PATH_MAX + 1], name[PATH_MAX + 1];
|
||||
std::string path = S9xGetDirectory(SAT_DIR) + SLASH_STR;
|
||||
|
||||
strcpy(path, S9xGetDirectory(SAT_DIR));
|
||||
strcat(path, SLASH_STR);
|
||||
|
||||
snprintf(name, PATH_MAX + 1, "BSX%04X-%d.bin", (BSX.PPU[0x2188 - BSXPPUBASE] | (BSX.PPU[0x2189 - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin
|
||||
strcat(path, name);
|
||||
char name[PATH_MAX];
|
||||
snprintf(name, PATH_MAX, "BSX%04X-%d.bin", (BSX.PPU[0x2188 - BSXPPUBASE] | (BSX.PPU[0x2189 - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin
|
||||
path += name;
|
||||
|
||||
BSX.sat_stream1.clear();
|
||||
BSX.sat_stream1.open(path, std::ios::in | std::ios::binary);
|
||||
BSX.sat_stream1.open(path.c_str(), std::ios::in | std::ios::binary);
|
||||
if (BSX.sat_stream1.good())
|
||||
{
|
||||
BSX.sat_stream1.seekg(0, BSX.sat_stream1.end);
|
||||
@@ -770,16 +768,15 @@ void S9xBSXSetStream2 (uint8 count)
|
||||
if (BSX.sat_stream2.is_open())
|
||||
BSX.sat_stream2.close(); //If Stream already opened for one file: Close it.
|
||||
|
||||
char path[PATH_MAX + 1], name[PATH_MAX + 1];
|
||||
|
||||
strcpy(path, S9xGetDirectory(SAT_DIR));
|
||||
strcat(path, SLASH_STR);
|
||||
std::string path = S9xGetDirectory(SAT_DIR) + SLASH_STR;
|
||||
|
||||
snprintf(name, PATH_MAX + 1, "BSX%04X-%d.bin", (BSX.PPU[0x218E - BSXPPUBASE] | (BSX.PPU[0x218F - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin
|
||||
strcat(path, name);
|
||||
char name[PATH_MAX];
|
||||
snprintf(name, PATH_MAX, "BSX%04X-%d.bin", (BSX.PPU[0x218E - BSXPPUBASE] | (BSX.PPU[0x218F - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin
|
||||
path += name;
|
||||
|
||||
BSX.sat_stream2.clear();
|
||||
BSX.sat_stream2.open(path, std::ios::in | std::ios::binary);
|
||||
BSX.sat_stream2.open(path.c_str(), std::ios::in | std::ios::binary);
|
||||
if (BSX.sat_stream2.good())
|
||||
{
|
||||
BSX.sat_stream2.seekg(0, BSX.sat_stream2.end);
|
||||
@@ -1207,20 +1204,15 @@ uint8 * S9xGetBasePointerBSX (uint32 address)
|
||||
static bool8 BSX_LoadBIOS (void)
|
||||
{
|
||||
FILE *fp;
|
||||
char path[PATH_MAX + 1], name[PATH_MAX + 1];
|
||||
bool8 r = FALSE;
|
||||
|
||||
strcpy(path, S9xGetDirectory(BIOS_DIR));
|
||||
strcat(path, SLASH_STR);
|
||||
strcpy(name, path);
|
||||
strcat(name, "BS-X.bin");
|
||||
std::string name = S9xGetDirectory(BIOS_DIR) + SLASH_STR + "BS-X.bin";
|
||||
|
||||
fp = fopen(name, "rb");
|
||||
fp = fopen(name.c_str(), "rb");
|
||||
if (!fp)
|
||||
{
|
||||
strcpy(name, path);
|
||||
strcat(name, "BS-X.bios");
|
||||
fp = fopen(name, "rb");
|
||||
name = S9xGetDirectory(BIOS_DIR) + SLASH_STR + "BS-X.bios";
|
||||
fp = fopen(name.c_str(), "rb");
|
||||
}
|
||||
|
||||
if (fp)
|
||||
@@ -1255,7 +1247,7 @@ void S9xInitBSX (void)
|
||||
{
|
||||
Settings.BS = FALSE;
|
||||
|
||||
if (is_BSX_BIOS(Memory.ROM,Memory.CalculatedSize))
|
||||
if (is_BSX_BIOS(Memory.ROM,Memory.CalculatedSize))
|
||||
{
|
||||
// BS-X itself
|
||||
|
||||
|
||||
-106
@@ -37,112 +37,6 @@
|
||||
(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);
|
||||
|
||||
+17
-21
@@ -23,14 +23,14 @@ 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[0x80000];
|
||||
@@ -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 (const 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
|
||||
|
||||
+299
-283
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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,313 +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;
|
||||
}
|
||||
|
||||
free(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 (const 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 (const char *name, const 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.c_str(), "cheat"))
|
||||
{
|
||||
const char *desc = NULL;
|
||||
const 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 = c->find_subnode("name");
|
||||
if (!tmp)
|
||||
desc = (char *) "";
|
||||
else
|
||||
desc = tmp->data.c_str();
|
||||
std::string name;
|
||||
subnode = c.find_subnode("name");
|
||||
if (subnode)
|
||||
name = subnode->data;
|
||||
|
||||
tmp = c->find_subnode("code");
|
||||
if (tmp)
|
||||
code = tmp->data.c_str();
|
||||
bool enable = false;
|
||||
if (c.find_subnode("enable"))
|
||||
enable = true;
|
||||
|
||||
if (c->find_subnode("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;
|
||||
if (!bml.parse_file(filename))
|
||||
{
|
||||
return S9xLoadCheatFileClassic (filename);
|
||||
return S9xLoadCheatFileClassic(filename);
|
||||
}
|
||||
|
||||
bml_node *n = bml.find_subnode("cheat");
|
||||
if (n)
|
||||
{
|
||||
S9xLoadCheatsFromBMLNode (&bml);
|
||||
S9xLoadCheatsFromBMLNode(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;
|
||||
|
||||
@@ -719,17 +738,17 @@ 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)
|
||||
{
|
||||
char sha256_txt[65];
|
||||
char hextable[] = "0123456789abcdef";
|
||||
@@ -746,19 +765,16 @@ 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.c_str(), "cartridge"))
|
||||
if (!strcasecmp(c.name.c_str(), "cartridge"))
|
||||
{
|
||||
bml_node *n;
|
||||
auto n = c.find_subnode("sha256");
|
||||
|
||||
if ((n = bml.child[i].find_subnode ("sha256")))
|
||||
if (n && !strcasecmp(n->data.c_str(), sha256_txt))
|
||||
{
|
||||
if (!strcasecmp (n->data.c_str(), sha256_txt))
|
||||
{
|
||||
S9xLoadCheatsFromBMLNode (&bml.child[i]);
|
||||
return 0;
|
||||
}
|
||||
S9xLoadCheatsFromBMLNode(c);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-66
@@ -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;
|
||||
@@ -2276,16 +2259,12 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
|
||||
|
||||
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");
|
||||
@@ -2313,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
|
||||
@@ -2342,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;
|
||||
}
|
||||
|
||||
@@ -2771,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;
|
||||
@@ -2796,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;
|
||||
@@ -3265,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)
|
||||
@@ -3289,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)
|
||||
|
||||
+2
-5
@@ -13,7 +13,6 @@
|
||||
#include "srtc.h"
|
||||
#include "snapshot.h"
|
||||
#include "cheats.h"
|
||||
#include "logger.h"
|
||||
#ifdef DEBUGGER
|
||||
#include "debug.h"
|
||||
#endif
|
||||
@@ -76,7 +75,6 @@ static void S9xSoftResetCPU (void)
|
||||
SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation);
|
||||
ClearFlags(Decimal);
|
||||
|
||||
Timings.InterlaceField = FALSE;
|
||||
Timings.H_Max = Timings.H_Max_Master;
|
||||
Timings.V_Max = Timings.V_Max_Master;
|
||||
Timings.NMITriggerPos = 0xffff;
|
||||
@@ -99,10 +97,9 @@ static void S9xSoftResetCPU (void)
|
||||
void S9xReset (void)
|
||||
{
|
||||
S9xResetSaveTimer(FALSE);
|
||||
S9xResetLogger();
|
||||
|
||||
memset(Memory.RAM, 0x55, 0x20000);
|
||||
memset(Memory.VRAM, 0x00, 0x10000);
|
||||
memset(Memory.RAM, 0x55, sizeof(Memory.RAM));
|
||||
memset(Memory.VRAM, 0x00, sizeof(Memory.VRAM));
|
||||
memset(Memory.FillRAM, 0, 0x8000);
|
||||
|
||||
S9xResetBSX();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+9
-11
@@ -132,13 +132,6 @@ void S9xMainLoop (void)
|
||||
|
||||
if (CPU.Flags & SCAN_KEYS_FLAG)
|
||||
{
|
||||
#ifdef DEBUGGER
|
||||
if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
|
||||
#endif
|
||||
{
|
||||
S9xSyncSpeed();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -276,7 +269,6 @@ void S9xDoHEventProcessing (void)
|
||||
if (CPU.V_Counter >= Timings.V_Max) // V ranges from 0 to Timings.V_Max - 1
|
||||
{
|
||||
CPU.V_Counter = 0;
|
||||
Timings.InterlaceField ^= 1;
|
||||
|
||||
// From byuu:
|
||||
// [NTSC]
|
||||
@@ -285,7 +277,7 @@ void S9xDoHEventProcessing (void)
|
||||
// [PAL] <PAL info is unverified on hardware>
|
||||
// interlace mode has 625 scanlines: 313 on the even frame, and 312 on the odd.
|
||||
// non-interlace mode has 624 scanlines: 312 scanlines on both even and odd frames.
|
||||
if (IPPU.Interlace && !Timings.InterlaceField)
|
||||
if (IPPU.Interlace && S9xInterlaceField())
|
||||
Timings.V_Max = Timings.V_Max_Master + 1; // 263 (NTSC), 313?(PAL)
|
||||
else
|
||||
Timings.V_Max = Timings.V_Max_Master; // 262 (NTSC), 312?(PAL)
|
||||
@@ -306,14 +298,14 @@ void S9xDoHEventProcessing (void)
|
||||
// In interlace mode, there are always 341 dots per scanline. Even frames have 263 scanlines,
|
||||
// and odd frames have 262 scanlines.
|
||||
// Interlace mode scanline 240 on odd frames is not missing a dot.
|
||||
if (CPU.V_Counter == 240 && !IPPU.Interlace && Timings.InterlaceField) // V=240
|
||||
if (CPU.V_Counter == 240 && !IPPU.Interlace && S9xInterlaceField()) // V=240
|
||||
Timings.H_Max = Timings.H_Max_Master - ONE_DOT_CYCLE; // HC=1360
|
||||
else
|
||||
Timings.H_Max = Timings.H_Max_Master; // HC=1364
|
||||
|
||||
if (Model->_5A22 == 2)
|
||||
{
|
||||
if (CPU.V_Counter != 240 || IPPU.Interlace || !Timings.InterlaceField) // V=240
|
||||
if (CPU.V_Counter != 240 || IPPU.Interlace || !S9xInterlaceField()) // V=240
|
||||
{
|
||||
if (Timings.WRAMRefreshPos == SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE) // HC=534
|
||||
Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; // HC=538
|
||||
@@ -327,6 +319,12 @@ void S9xDoHEventProcessing (void)
|
||||
if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240).
|
||||
{
|
||||
S9xEndScreenRefresh();
|
||||
#ifdef DEBUGGER
|
||||
if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
|
||||
#endif
|
||||
{
|
||||
S9xSyncSpeed();
|
||||
}
|
||||
|
||||
CPU.Flags |= SCAN_KEYS_FLAG;
|
||||
|
||||
|
||||
+15
-7
@@ -1406,11 +1406,13 @@ bOP(70Slow, RelativeSlow, CheckOverflow(), 0, CheckEmulation())
|
||||
static void Op82 (void)
|
||||
{
|
||||
S9xSetPCBase(ICPU.ShiftedPB + RelativeLong(JUMP));
|
||||
AddCycles(ONE_CYCLE);
|
||||
}
|
||||
|
||||
static void Op82Slow (void)
|
||||
{
|
||||
S9xSetPCBase(ICPU.ShiftedPB + RelativeLongSlow(JUMP));
|
||||
AddCycles(ONE_CYCLE);
|
||||
}
|
||||
|
||||
/* Flag Instructions ******************************************************* */
|
||||
@@ -2847,6 +2849,7 @@ static void Op22E1 (void)
|
||||
// Note: JSL is a new instruction,
|
||||
// and so doesn't respect the emu-mode stack bounds.
|
||||
uint32 addr = AbsoluteLong(JSR);
|
||||
AddCycles(ONE_CYCLE);
|
||||
PushB(Registers.PB);
|
||||
PushW(Registers.PCw - 1);
|
||||
Registers.SH = 1;
|
||||
@@ -2856,6 +2859,7 @@ static void Op22E1 (void)
|
||||
static void Op22E0 (void)
|
||||
{
|
||||
uint32 addr = AbsoluteLong(JSR);
|
||||
AddCycles(ONE_CYCLE);
|
||||
PushB(Registers.PB);
|
||||
PushW(Registers.PCw - 1);
|
||||
S9xSetPCBase(addr);
|
||||
@@ -2864,6 +2868,7 @@ static void Op22E0 (void)
|
||||
static void Op22Slow (void)
|
||||
{
|
||||
uint32 addr = AbsoluteLongSlow(JSR);
|
||||
AddCycles(ONE_CYCLE);
|
||||
PushB(Registers.PB);
|
||||
PushW(Registers.PCw - 1);
|
||||
if (CheckEmulation())
|
||||
@@ -3381,16 +3386,19 @@ static void Op42 (void)
|
||||
#endif
|
||||
|
||||
case 0x42: // "WDM" = Snapshot
|
||||
char filename[PATH_MAX + 1], drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[PATH_MAX + 1], ext[_MAX_EXT + 1];
|
||||
{
|
||||
char tmp[PATH_MAX + 1];
|
||||
SplitPath split = splitpath(Memory.ROMFilename);
|
||||
|
||||
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
|
||||
snprintf(filename, PATH_MAX, "%s%s%s-%06X.wdm", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, Registers.PBPC & 0xffffff);
|
||||
sprintf(def, "WDM Snapshot at $%02X:%04X: %s", Registers.PB, Registers.PCw, filename);
|
||||
S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, def);
|
||||
S9xFreezeGame(filename);
|
||||
snprintf(tmp, PATH_MAX, "%s-%06X", split.stem.c_str(), Registers.PBPC & 0xffffff);
|
||||
std::string filename = makepath(split.dir, S9xGetDirectory(SNAPSHOT_DIR), tmp, ".wdm");
|
||||
|
||||
break;
|
||||
sprintf(tmp, "WDM Snapshot at $%02X:%04X: %s", Registers.PB, Registers.PCw, filename.c_str());
|
||||
S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, tmp);
|
||||
S9xFreezeGame(filename.c_str());
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -44,10 +26,6 @@ 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 * S9xBasename (const char *);
|
||||
|
||||
// Routines the port has to implement if it uses command-line
|
||||
|
||||
|
||||
@@ -1,3 +1,32 @@
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
/*****************************************************************************\
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
This file is licensed under the Snes9x License.
|
||||
For further information, consult the LICENSE file in the root directory.
|
||||
\*****************************************************************************/
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include "display.h"
|
||||
#include "fscompat.h"
|
||||
#include "port.h"
|
||||
#include "memmap.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
bool SplitPath::ext_is(const string &other)
|
||||
{
|
||||
if (strcasecmp(ext.c_str(), other.c_str()) == 0)
|
||||
return true;
|
||||
if (other[0] != '.' && (strcasecmp(other.c_str(), &(ext.c_str()[1])) == 0))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string makepath(const SplitPath &path)
|
||||
{
|
||||
return makepath(path.drive, path.dir, path.stem, path.ext);
|
||||
}
|
||||
|
||||
std::string S9xGetFilename(string filename, string ext, enum s9x_getdirtype dirtype)
|
||||
{
|
||||
auto path = splitpath(filename);
|
||||
auto dir = S9xGetDirectory(dirtype);
|
||||
return makepath(path.drive, dir, path.stem, ext);
|
||||
}
|
||||
|
||||
std::string S9xGetFilename(string ext, enum s9x_getdirtype dirtype)
|
||||
{
|
||||
return S9xGetFilename(Memory.ROMFilename, ext, dirtype);
|
||||
}
|
||||
|
||||
std::string S9xBasename(std::string filename)
|
||||
{
|
||||
auto path = splitpath(filename);
|
||||
return path.stem + path.ext;
|
||||
}
|
||||
|
||||
std::string S9xBasenameNoExt(std::string filename)
|
||||
{
|
||||
return splitpath(filename).stem;
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201703L && 0
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
SplitPath splitpath(string str)
|
||||
{
|
||||
SplitPath output{};
|
||||
fs::path path(str);
|
||||
|
||||
if (path.has_root_name())
|
||||
output.drive = path.root_name().string();
|
||||
|
||||
if (path.has_filename())
|
||||
{
|
||||
output.stem = path.stem().string();
|
||||
output.ext = path.extension().string();
|
||||
path.remove_filename();
|
||||
}
|
||||
|
||||
if (!path.empty())
|
||||
output.dir = path.string();
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
string makepath(const string &drive, const string &dir, const string &stem, const string &ext)
|
||||
{
|
||||
auto dot_position = ext.find('.');
|
||||
|
||||
if (dot_position == string::npos)
|
||||
{
|
||||
fs::path path(drive);
|
||||
path = path / dir / stem;
|
||||
path.replace_extension(ext);
|
||||
return path.string();
|
||||
}
|
||||
|
||||
auto filename = stem + ext;
|
||||
fs::path path(drive);
|
||||
path = path / dir / filename;
|
||||
return path.string();
|
||||
}
|
||||
|
||||
#else
|
||||
constexpr auto npos = std::string::npos;
|
||||
|
||||
SplitPath splitpath(string path)
|
||||
{
|
||||
SplitPath output{};
|
||||
|
||||
#ifdef _WIN32
|
||||
if (path.length() > 2 && path[1] == ':')
|
||||
{
|
||||
output.drive = path.substr(0, 2);
|
||||
path = path.substr(2);
|
||||
}
|
||||
#endif
|
||||
auto slash = path.rfind(SLASH_CHAR);
|
||||
auto dot = path.rfind('.');
|
||||
|
||||
if (dot != npos && slash != npos && dot < slash)
|
||||
{
|
||||
dot = npos;
|
||||
}
|
||||
else if (dot != npos)
|
||||
{
|
||||
output.ext = path.substr(dot);
|
||||
}
|
||||
|
||||
if (slash != npos)
|
||||
{
|
||||
output.dir = path.substr(0, slash + 1);
|
||||
output.stem = path.substr(slash + 1, dot - slash - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
output.stem = path.substr(0, dot);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
string makepath(const string &drive, const string &dir, const string &stem, const string &ext)
|
||||
{
|
||||
string output;
|
||||
|
||||
if (!drive.empty())
|
||||
{
|
||||
if (!(dir.length() > 2 && dir[1] == ':'))
|
||||
{
|
||||
output += drive + ":";
|
||||
if (!dir.empty() && dir[0] != SLASH_CHAR)
|
||||
output += SLASH_CHAR;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dir.empty())
|
||||
{
|
||||
output += dir;
|
||||
if (output[output.length() - 1] != SLASH_CHAR)
|
||||
output += SLASH_CHAR;
|
||||
}
|
||||
|
||||
if (!stem.empty())
|
||||
{
|
||||
output += stem;
|
||||
}
|
||||
|
||||
if (!ext.empty())
|
||||
{
|
||||
if (ext.find('.') == string::npos)
|
||||
output += '.';
|
||||
output += ext;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
void _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext)
|
||||
{
|
||||
char *slash = strrchr((char *)path, SLASH_CHAR);
|
||||
char *dot = strrchr((char *)path, '.');
|
||||
|
||||
*drive = '\0';
|
||||
|
||||
if (dot && slash && dot < slash)
|
||||
{
|
||||
dot = 0;
|
||||
}
|
||||
|
||||
if (!slash)
|
||||
{
|
||||
*dir = '\0';
|
||||
strcpy(fname, path);
|
||||
|
||||
if (dot)
|
||||
{
|
||||
fname[dot - path] = '\0';
|
||||
strcpy(ext, dot + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ext = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(dir, path);
|
||||
dir[slash - path] = '\0';
|
||||
strcpy(fname, slash + 1);
|
||||
|
||||
if (dot)
|
||||
{
|
||||
fname[(dot - slash) - 1] = '\0';
|
||||
strcpy(ext, dot + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ext = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext)
|
||||
{
|
||||
if (dir && *dir)
|
||||
{
|
||||
strcpy(path, dir);
|
||||
strcat(path, "/");
|
||||
}
|
||||
else
|
||||
*path = '\0';
|
||||
|
||||
strcat(path, fname);
|
||||
|
||||
if (ext && *ext)
|
||||
{
|
||||
if (!strchr(ext, '.'))
|
||||
strcat(path, ".");
|
||||
strcat(path, ext);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,52 @@
|
||||
/*****************************************************************************\
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
This file is licensed under the Snes9x License.
|
||||
For further information, consult the LICENSE file in the root directory.
|
||||
\*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <string>
|
||||
|
||||
enum s9x_getdirtype
|
||||
{
|
||||
DEFAULT_DIR = 0,
|
||||
HOME_DIR,
|
||||
ROMFILENAME_DIR,
|
||||
ROM_DIR,
|
||||
SRAM_DIR,
|
||||
SNAPSHOT_DIR,
|
||||
SCREENSHOT_DIR,
|
||||
SPC_DIR,
|
||||
CHEAT_DIR,
|
||||
PATCH_DIR,
|
||||
BIOS_DIR,
|
||||
LOG_DIR,
|
||||
SAT_DIR,
|
||||
LAST_DIR
|
||||
};
|
||||
|
||||
struct SplitPath
|
||||
{
|
||||
bool ext_is(const std::string &ext);
|
||||
std::string drive;
|
||||
std::string dir;
|
||||
std::string stem;
|
||||
std::string ext;
|
||||
};
|
||||
|
||||
SplitPath splitpath(std::string filename);
|
||||
std::string makepath(const std::string &drive,
|
||||
const std::string &directory,
|
||||
const std::string &stem,
|
||||
const std::string &extension);
|
||||
std::string makepath(const SplitPath &);
|
||||
|
||||
std::string S9xBasename (std::string);
|
||||
std::string S9xBasenameNoExt (std::string);
|
||||
std::string S9xGetFilename (std::string ext, enum s9x_getdirtype dirtype);
|
||||
std::string S9xGetFilename (std::string filename, std::string ext, enum s9x_getdirtype dirtype);
|
||||
std::string S9xGetDirectory (enum s9x_getdirtype);
|
||||
std::string S9xGetFilenameInc (std::string, enum s9x_getdirtype);
|
||||
#endif
|
||||
+1
-1
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+44
-82
@@ -49,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);
|
||||
@@ -118,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;
|
||||
@@ -150,7 +141,7 @@ void S9xGraphicsScreenResize (void)
|
||||
GFX.PPL = GFX.RealPPL;
|
||||
IPPU.DoubleHeightPixels = FALSE;
|
||||
IPPU.RenderedScreenHeight = PPU.ScreenHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void S9xBuildDirectColourMaps (void)
|
||||
@@ -164,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())
|
||||
{
|
||||
@@ -199,7 +189,7 @@ void S9xStartScreenRefresh (void)
|
||||
}
|
||||
|
||||
if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0)
|
||||
GFX.InfoString = NULL;
|
||||
GFX.InfoString.clear();
|
||||
|
||||
IPPU.TotalEmulatedFrames++;
|
||||
}
|
||||
@@ -210,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);
|
||||
@@ -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
|
||||
@@ -642,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;
|
||||
@@ -714,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;
|
||||
@@ -792,10 +756,10 @@ 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;
|
||||
@@ -927,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);
|
||||
@@ -1321,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;
|
||||
@@ -1843,7 +1807,7 @@ static void S9xDisplayStringType (const char *string, int linesFromBottom, int p
|
||||
static void DisplayTime (void)
|
||||
{
|
||||
char string[10];
|
||||
|
||||
|
||||
time_t rawtime;
|
||||
struct tm *timeinfo;
|
||||
|
||||
@@ -2016,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);
|
||||
@@ -2030,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;
|
||||
|
||||
@@ -2049,7 +2011,7 @@ void S9xDisplayMessages (uint16 *screen, int ppl, int width, int height, int sca
|
||||
{
|
||||
if (Settings.DisplayTime)
|
||||
DisplayTime();
|
||||
|
||||
|
||||
if (Settings.DisplayFrameRate)
|
||||
DisplayFrameRate();
|
||||
|
||||
@@ -2062,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)
|
||||
|
||||
@@ -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;
|
||||
@@ -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];
|
||||
};
|
||||
|
||||
+339
-910
File diff suppressed because it is too large
Load Diff
+18
-10
@@ -12,10 +12,13 @@
|
||||
#define MEMMAP_SHIFT (12)
|
||||
#define MEMMAP_MASK (MEMMAP_BLOCK_SIZE - 1)
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct CMemory
|
||||
{
|
||||
enum
|
||||
{ MAX_ROM_SIZE = 0x800000 };
|
||||
{ MAX_ROM_SIZE = 0xC00000 };
|
||||
|
||||
enum file_formats
|
||||
{ FILE_ZIP, FILE_JMA, FILE_DEFAULT };
|
||||
@@ -53,10 +56,13 @@ struct CMemory
|
||||
uint8 NSRTHeader[32];
|
||||
int32 HeaderCount;
|
||||
|
||||
uint8 *RAM;
|
||||
uint8 *ROM;
|
||||
uint8 RAM[0x20000];
|
||||
std::vector<uint8_t> ROMStorage;
|
||||
uint8 *ROM;
|
||||
std::vector<uint8_t> SRAMStorage;
|
||||
uint8 *SRAM;
|
||||
uint8 *VRAM;
|
||||
const size_t SRAM_SIZE = 0x80000;
|
||||
uint8 VRAM[0x10000];
|
||||
uint8 *FillRAM;
|
||||
uint8 *BWRAM;
|
||||
uint8 *C4RAM;
|
||||
@@ -70,9 +76,8 @@ struct CMemory
|
||||
uint8 BlockIsROM[MEMMAP_NUM_BLOCKS];
|
||||
uint8 ExtendedFormat;
|
||||
|
||||
char ROMFilename[PATH_MAX + 1];
|
||||
std::string ROMFilename;
|
||||
char ROMName[ROM_NAME_LEN];
|
||||
char RawROMName[ROM_NAME_LEN];
|
||||
char ROMId[5];
|
||||
int32 CompanyId;
|
||||
uint8 ROMRegion;
|
||||
@@ -103,8 +108,7 @@ struct CMemory
|
||||
int First512BytesCountZeroes() const;
|
||||
uint32 HeaderRemove (uint32, uint8 *);
|
||||
uint32 FileLoader (uint8 *, const char *, uint32);
|
||||
uint32 MemLoader (uint8 *, const char*, uint32);
|
||||
bool8 LoadROMMem (const uint8 *, uint32);
|
||||
bool8 LoadROMMem (const uint8 *, uint32, const char* optional_rom_filename = NULL);
|
||||
bool8 LoadROM (const char *);
|
||||
bool8 LoadROMInt (int32);
|
||||
bool8 LoadMultiCartMem (const uint8 *, uint32, const uint8 *, uint32, const uint8 *, uint32);
|
||||
@@ -120,8 +124,6 @@ struct CMemory
|
||||
bool8 SaveSRTC (void);
|
||||
bool8 SaveMPAK (const char *);
|
||||
|
||||
char * Safe (const char *);
|
||||
char * SafeANK (const char *);
|
||||
void ParseSNESHeader (uint8 *);
|
||||
void InitROM (void);
|
||||
|
||||
@@ -170,6 +172,7 @@ struct CMemory
|
||||
bool8 match_nc (const char *);
|
||||
bool8 match_id (const char *);
|
||||
void ApplyROMFixes (void);
|
||||
std::string SafeString(std::string s, bool allow_jis = false);
|
||||
void CheckForAnyPatch (const char *, bool8, int32 &);
|
||||
|
||||
void MakeRomInfoText (char *);
|
||||
@@ -197,6 +200,11 @@ struct SMulti
|
||||
extern CMemory Memory;
|
||||
extern SMulti Multi;
|
||||
|
||||
inline bool S9xInterlaceField()
|
||||
{
|
||||
return (Memory.FillRAM[0x213F] & 0x80) >> 7;
|
||||
}
|
||||
|
||||
void S9xAutoSaveSRAM (void);
|
||||
bool8 LoadZip(const char *, uint32 *, uint8 *);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+20
-16
@@ -57,27 +57,27 @@ static int unzFindExtension(unzFile &file, const char *ext, bool restart = TRUE,
|
||||
|
||||
STREAM S9xMSU1OpenFile(const char *msu_ext, bool skip_unpacked)
|
||||
{
|
||||
const char *filename = S9xGetFilename(msu_ext, ROMFILENAME_DIR);
|
||||
auto filename = S9xGetFilename(msu_ext, ROMFILENAME_DIR);
|
||||
STREAM file = 0;
|
||||
|
||||
if (!skip_unpacked)
|
||||
{
|
||||
file = OPEN_STREAM(filename, "rb");
|
||||
file = OPEN_STREAM(filename.c_str(), "rb");
|
||||
if (file)
|
||||
printf("Using msu file %s.\n", filename);
|
||||
printf("Using msu file %s.\n", filename.c_str());
|
||||
}
|
||||
|
||||
#ifdef UNZIP_SUPPORT
|
||||
// look for msu1 pack file in the rom or patch dir if msu data file not found in rom dir
|
||||
if (!file)
|
||||
{
|
||||
const char *zip_filename = S9xGetFilename(".msu1", ROMFILENAME_DIR);
|
||||
unzFile unzFile = unzOpen(zip_filename);
|
||||
auto zip_filename = S9xGetFilename(".msu1", ROMFILENAME_DIR);
|
||||
unzFile unzFile = unzOpen(zip_filename.c_str());
|
||||
|
||||
if (!unzFile)
|
||||
{
|
||||
zip_filename = S9xGetFilename(".msu1", PATCH_DIR);
|
||||
unzFile = unzOpen(zip_filename);
|
||||
unzFile = unzOpen(zip_filename.c_str());
|
||||
}
|
||||
|
||||
if (unzFile)
|
||||
@@ -85,7 +85,6 @@ STREAM S9xMSU1OpenFile(const char *msu_ext, bool skip_unpacked)
|
||||
int port = unzFindExtension(unzFile, msu_ext, true, true, true);
|
||||
if (port == UNZ_OK)
|
||||
{
|
||||
printf(" in %s.\n", zip_filename);
|
||||
file = new unzStream(unzFile);
|
||||
}
|
||||
else
|
||||
@@ -112,10 +111,9 @@ static bool AudioOpen()
|
||||
|
||||
AudioClose();
|
||||
|
||||
char ext[_MAX_EXT];
|
||||
snprintf(ext, _MAX_EXT, "-%d.pcm", MSU1.MSU1_CURRENT_TRACK);
|
||||
std::string extension = "-" + std::to_string(MSU1.MSU1_CURRENT_TRACK) + ".pcm";
|
||||
|
||||
audioStream = S9xMSU1OpenFile(ext);
|
||||
audioStream = S9xMSU1OpenFile(extension.c_str());
|
||||
if (audioStream)
|
||||
{
|
||||
if (GETC_STREAM(audioStream) != 'M')
|
||||
@@ -207,15 +205,14 @@ bool S9xMSU1ROMExists(void)
|
||||
return true;
|
||||
}
|
||||
#ifdef UNZIP_SUPPORT
|
||||
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
|
||||
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
|
||||
if (!strcasecmp(ext, ".msu1"))
|
||||
|
||||
if (splitpath(Memory.ROMFilename).ext_is(".msu1"))
|
||||
return true;
|
||||
|
||||
unzFile unzFile = unzOpen(S9xGetFilename(".msu1", ROMFILENAME_DIR));
|
||||
unzFile unzFile = unzOpen(S9xGetFilename(".msu1", ROMFILENAME_DIR).c_str());
|
||||
|
||||
if(!unzFile)
|
||||
unzFile = unzOpen(S9xGetFilename(".msu1", PATCH_DIR));
|
||||
unzFile = unzOpen(S9xGetFilename(".msu1", PATCH_DIR).c_str());
|
||||
|
||||
if (unzFile)
|
||||
{
|
||||
@@ -253,7 +250,14 @@ void S9xMSU1Generate(size_t sample_count)
|
||||
{
|
||||
if (MSU1.MSU1_STATUS & AudioRepeating)
|
||||
{
|
||||
MSU1.MSU1_AUDIO_POS = audioLoopPos;
|
||||
if (audioLoopPos < MSU1.MSU1_AUDIO_POS)
|
||||
{
|
||||
MSU1.MSU1_AUDIO_POS = audioLoopPos;
|
||||
}
|
||||
else // if the loop point is invalid, revert to start
|
||||
{
|
||||
MSU1.MSU1_AUDIO_POS = 8;
|
||||
}
|
||||
REVERT_STREAM(audioStream, MSU1.MSU1_AUDIO_POS, 0);
|
||||
}
|
||||
else
|
||||
|
||||
+1
-1
@@ -647,7 +647,7 @@ bool8 S9xNPGetROMImage (uint32 len)
|
||||
S9xNPSetAction ("Receiving ROM filename...");
|
||||
uint32 filename_len = len - Memory.CalculatedSize - 5;
|
||||
if (filename_len > PATH_MAX ||
|
||||
!S9xNPGetData (NetPlay.Socket, (uint8 *) Memory.ROMFilename, filename_len))
|
||||
!S9xNPGetData (NetPlay.Socket, (uint8 *) Memory.ROMFilename.c_str(), filename_len))
|
||||
{
|
||||
S9xNPSetError ("Error while receiving ROM filename from server.");
|
||||
S9xNPDisconnect ();
|
||||
|
||||
+4
-13
@@ -99,11 +99,7 @@ __extension__
|
||||
#endif
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
#ifdef PTR_NOT_INT
|
||||
typedef size_t pint;
|
||||
#else // __PTR_NOT_INT
|
||||
typedef size_t pint;
|
||||
#endif // __PTR_NOT_INT
|
||||
#endif // __WIN32__
|
||||
#endif // HAVE_STDINT_H
|
||||
#endif // snes9x_types_defined
|
||||
@@ -120,22 +116,17 @@ typedef size_t pint;
|
||||
|
||||
#ifndef __WIN32__
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 1024
|
||||
#define PATH_MAX 1024
|
||||
#endif
|
||||
#define _MAX_DRIVE 1
|
||||
#define _MAX_DIR PATH_MAX
|
||||
#define _MAX_FNAME PATH_MAX
|
||||
#define _MAX_EXT PATH_MAX
|
||||
#define _MAX_PATH PATH_MAX
|
||||
#else
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX _MAX_PATH
|
||||
#define PATH_MAX _MAX_PATH
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "fscompat.h"
|
||||
|
||||
#ifndef __WIN32__
|
||||
void _splitpath (const char *, char *, char *, char *, char *);
|
||||
void _makepath (char *, const char *, const char *, const char *, const char *);
|
||||
#define S9xDisplayString DisplayStringFromBottom
|
||||
#else // __WIN32__
|
||||
#define snprintf _snprintf
|
||||
|
||||
+5
-6
@@ -94,7 +94,7 @@ static int CyclesUntilNext (int hc, int vc)
|
||||
// Add number of lines
|
||||
total += (vc - vpos) * Timings.H_Max_Master;
|
||||
// If line 240 is in there and we're odd, subtract a dot
|
||||
if (vpos <= 240 && vc > 240 && Timings.InterlaceField & !IPPU.Interlace)
|
||||
if (vpos <= 240 && vc > 240 && S9xInterlaceField() & !IPPU.Interlace)
|
||||
total -= ONE_DOT_CYCLE;
|
||||
}
|
||||
else
|
||||
@@ -105,11 +105,11 @@ static int CyclesUntilNext (int hc, int vc)
|
||||
}
|
||||
|
||||
total += (Timings.V_Max - vpos) * Timings.H_Max_Master;
|
||||
if (vpos <= 240 && Timings.InterlaceField && !IPPU.Interlace)
|
||||
if (vpos <= 240 && S9xInterlaceField() && !IPPU.Interlace)
|
||||
total -= ONE_DOT_CYCLE;
|
||||
|
||||
total += (vc) * Timings.H_Max_Master;
|
||||
if (vc > 240 && !Timings.InterlaceField && !IPPU.Interlace)
|
||||
if (vc > 240 && !S9xInterlaceField() && !IPPU.Interlace)
|
||||
total -= ONE_DOT_CYCLE;
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ void S9xUpdateIRQPositions (bool initial)
|
||||
}
|
||||
|
||||
// Check for short dot scanline
|
||||
if (v_pos == 240 && Timings.InterlaceField && !IPPU.Interlace)
|
||||
if (v_pos == 240 && S9xInterlaceField() && !IPPU.Interlace)
|
||||
{
|
||||
Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 322 ? ONE_DOT_CYCLE / 2 : 0;
|
||||
Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 326 ? ONE_DOT_CYCLE / 2 : 0;
|
||||
@@ -164,7 +164,7 @@ void S9xUpdateIRQPositions (bool initial)
|
||||
Timings.NextIRQTimer = CyclesUntilNext (PPU.HTimerPosition, PPU.VTimerPosition);
|
||||
|
||||
// Check for short dot scanline
|
||||
int field = Timings.InterlaceField;
|
||||
int field = S9xInterlaceField();
|
||||
|
||||
if (PPU.VTimerPosition < CPU.V_Counter ||
|
||||
(PPU.VTimerPosition == CPU.V_Counter && Timings.NextIRQTimer > Timings.H_Max))
|
||||
@@ -1894,7 +1894,6 @@ void S9xSoftResetPPU (void)
|
||||
memset(IPPU.TileCached[TILE_4BIT_EVEN], 0, MAX_4BIT_TILES);
|
||||
memset(IPPU.TileCached[TILE_4BIT_ODD], 0, MAX_4BIT_TILES);
|
||||
PPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better?
|
||||
GFX.InterlaceFrame = 0;
|
||||
GFX.DoInterlace = 0;
|
||||
IPPU.Interlace = FALSE;
|
||||
IPPU.InterlaceOBJ = FALSE;
|
||||
|
||||
+3
-2
@@ -563,8 +563,9 @@ void S9xSetSA1 (uint8 byte, uint32 address)
|
||||
{
|
||||
int16 dividend = (int16) SA1.op1;
|
||||
uint16 divisor = (uint16) SA1.op2;
|
||||
uint16 remainder = (dividend >= 0) ? dividend % divisor : (dividend % divisor) + divisor;
|
||||
uint16 quotient = (dividend - remainder) / divisor;
|
||||
uint32 dividend_ext = dividend + (uint32)divisor * 65536;
|
||||
uint16 remainder = dividend_ext % divisor;
|
||||
uint16 quotient = dividend_ext / divisor;
|
||||
SA1.sum = (remainder << 16) | quotient;
|
||||
}
|
||||
|
||||
|
||||
+9
-12
@@ -23,11 +23,10 @@ bool8 S9xDoScreenshot (int width, int height)
|
||||
png_infop info_ptr;
|
||||
png_color_8 sig_bit;
|
||||
int imgwidth, imgheight;
|
||||
const char *fname;
|
||||
|
||||
fname = S9xGetFilenameInc(".png", SCREENSHOT_DIR);
|
||||
std::string fname = S9xGetFilenameInc(".png", SCREENSHOT_DIR);
|
||||
|
||||
fp = fopen(fname, "wb");
|
||||
fp = fopen(fname.c_str(), "wb");
|
||||
if (!fp)
|
||||
{
|
||||
S9xMessage(S9X_ERROR, 0, "Failed to take screenshot.");
|
||||
@@ -38,7 +37,7 @@ bool8 S9xDoScreenshot (int width, int height)
|
||||
if (!png_ptr)
|
||||
{
|
||||
fclose(fp);
|
||||
remove(fname);
|
||||
remove(fname.c_str());
|
||||
S9xMessage(S9X_ERROR, 0, "Failed to take screenshot.");
|
||||
return (FALSE);
|
||||
}
|
||||
@@ -48,7 +47,7 @@ bool8 S9xDoScreenshot (int width, int height)
|
||||
{
|
||||
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
|
||||
fclose(fp);
|
||||
remove(fname);
|
||||
remove(fname.c_str());
|
||||
S9xMessage(S9X_ERROR, 0, "Failed to take screenshot.");
|
||||
return (FALSE);
|
||||
}
|
||||
@@ -57,7 +56,7 @@ bool8 S9xDoScreenshot (int width, int height)
|
||||
{
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
fclose(fp);
|
||||
remove(fname);
|
||||
remove(fname.c_str());
|
||||
S9xMessage(S9X_ERROR, 0, "Failed to take screenshot.");
|
||||
return (FALSE);
|
||||
}
|
||||
@@ -70,8 +69,7 @@ bool8 S9xDoScreenshot (int width, int height)
|
||||
if (width > SNES_WIDTH && height <= SNES_HEIGHT_EXTENDED)
|
||||
imgheight = height << 1;
|
||||
}
|
||||
else
|
||||
if (Settings.StretchScreenshots == 2)
|
||||
else if (Settings.StretchScreenshots == 2)
|
||||
{
|
||||
if (width <= SNES_WIDTH)
|
||||
imgwidth = width << 1;
|
||||
@@ -130,11 +128,10 @@ bool8 S9xDoScreenshot (int width, int height)
|
||||
|
||||
fclose(fp);
|
||||
|
||||
fprintf(stderr, "%s saved.\n", fname);
|
||||
fprintf(stderr, "%s saved.\n", fname.c_str());
|
||||
|
||||
const char *base = S9xBasename(fname);
|
||||
sprintf(String, "Saved screenshot %s", base);
|
||||
S9xMessage(S9X_INFO, 0, String);
|
||||
std::string base = "Saved screenshot " + S9xBasename(fname);
|
||||
S9xMessage(S9X_INFO, 0, base.c_str());
|
||||
|
||||
return (TRUE);
|
||||
#else
|
||||
|
||||
+3
-3
@@ -960,7 +960,7 @@ bool8 S9xNPSendROMImageToClient (int c)
|
||||
uint8 header [7 + 1 + 4];
|
||||
uint8 *ptr = header;
|
||||
int len = sizeof (header) + Memory.CalculatedSize +
|
||||
strlen (Memory.ROMFilename) + 1;
|
||||
Memory.ROMFilename.length() + 1;
|
||||
*ptr++ = NP_SERV_MAGIC;
|
||||
*ptr++ = NPServer.Clients [c].SendSequenceNum++;
|
||||
*ptr++ = NP_SERV_ROM_IMAGE;
|
||||
@@ -972,8 +972,8 @@ bool8 S9xNPSendROMImageToClient (int c)
|
||||
if (!S9xNPSSendData (NPServer.Clients [c].Socket, header, sizeof (header)) ||
|
||||
!S9xNPSSendData (NPServer.Clients [c].Socket, Memory.ROM,
|
||||
Memory.CalculatedSize) ||
|
||||
!S9xNPSSendData (NPServer.Clients [c].Socket, (uint8 *) Memory.ROMFilename,
|
||||
strlen (Memory.ROMFilename) + 1))
|
||||
!S9xNPSSendData (NPServer.Clients [c].Socket, (uint8 *) Memory.ROMFilename.c_str(),
|
||||
Memory.ROMFilename.length() + 1))
|
||||
{
|
||||
S9xNPShutdownClient (c, TRUE);
|
||||
return (FALSE);
|
||||
|
||||
+66
-47
@@ -48,7 +48,7 @@ enum
|
||||
};
|
||||
|
||||
#define COUNT(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))
|
||||
#define Offset(field, structure) ((int) (((char *) (&(((structure) NULL)->field))) - ((char *) NULL)))
|
||||
#define Offset(field, structure) ((int) (((char *) (&(((structure) 1)->field))) - ((char *) 1)))
|
||||
#define OFFSET(f) Offset(f, STRUCT *)
|
||||
#define DUMMY(f) Offset(f, struct Obsolete *)
|
||||
#define DELETED(f) (-1)
|
||||
@@ -1009,13 +1009,9 @@ void S9xResetSaveTimer (bool8 dontsave)
|
||||
|
||||
if (!Settings.DontSaveOopsSnapshot && !dontsave && t != -1 && time(NULL) - t > 300)
|
||||
{
|
||||
char filename[PATH_MAX + 1];
|
||||
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
|
||||
|
||||
_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");
|
||||
auto filename = S9xGetFilename("oops", SNAPSHOT_DIR);
|
||||
S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, SAVE_INFO_OOPS);
|
||||
S9xFreezeGame(filename);
|
||||
S9xFreezeGame(filename.c_str());
|
||||
}
|
||||
|
||||
t = time(NULL);
|
||||
@@ -1047,11 +1043,11 @@ bool8 S9xFreezeGame (const char *filename)
|
||||
|
||||
S9xResetSaveTimer(TRUE);
|
||||
|
||||
const char *base = S9xBasename(filename);
|
||||
auto base = S9xBasename(filename);
|
||||
if (S9xMovieActive())
|
||||
sprintf(String, MOVIE_INFO_SNAPSHOT " %s", base);
|
||||
sprintf(String, MOVIE_INFO_SNAPSHOT " %s", base.c_str());
|
||||
else
|
||||
sprintf(String, SAVE_INFO_SNAPSHOT " %s", base);
|
||||
sprintf(String, SAVE_INFO_SNAPSHOT " %s", base.c_str());
|
||||
|
||||
S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String);
|
||||
|
||||
@@ -1104,12 +1100,10 @@ void S9xMessageFromResult(int result, const char* base)
|
||||
bool8 S9xUnfreezeGame (const char *filename)
|
||||
{
|
||||
STREAM stream = NULL;
|
||||
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
|
||||
|
||||
const char *base = S9xBasename(filename);
|
||||
|
||||
_splitpath(filename, drive, dir, def, ext);
|
||||
S9xResetSaveTimer(!strcmp(ext, "oops") || !strcmp(ext, "oop") || !strcmp(ext, ".oops") || !strcmp(ext, ".oop"));
|
||||
auto base = S9xBasename(filename);
|
||||
auto path = splitpath(filename);
|
||||
S9xResetSaveTimer(path.ext_is(".oops") || path.ext_is(".oop"));
|
||||
|
||||
if (S9xOpenSnapshotFile(filename, TRUE, &stream))
|
||||
{
|
||||
@@ -1120,26 +1114,26 @@ bool8 S9xUnfreezeGame (const char *filename)
|
||||
|
||||
if (result != SUCCESS)
|
||||
{
|
||||
S9xMessageFromResult(result, base);
|
||||
S9xMessageFromResult(result, base.c_str());
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (S9xMovieActive())
|
||||
{
|
||||
if (S9xMovieReadOnly())
|
||||
sprintf(String, MOVIE_INFO_REWIND " %s", base);
|
||||
sprintf(String, MOVIE_INFO_REWIND " %s", base.c_str());
|
||||
else
|
||||
sprintf(String, MOVIE_INFO_RERECORD " %s", base);
|
||||
sprintf(String, MOVIE_INFO_RERECORD " %s", base.c_str());
|
||||
}
|
||||
else
|
||||
sprintf(String, SAVE_INFO_LOAD " %s", base);
|
||||
sprintf(String, SAVE_INFO_LOAD " %s", base.c_str());
|
||||
|
||||
S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
sprintf(String, SAVE_ERR_SAVE_NOT_FOUND, base);
|
||||
sprintf(String, SAVE_ERR_SAVE_NOT_FOUND, base.c_str());
|
||||
S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String);
|
||||
|
||||
return (FALSE);
|
||||
@@ -1149,7 +1143,7 @@ bool8 S9xUnfreezeScreenshot(const char *filename, uint16 **image_buffer, int &wi
|
||||
{
|
||||
STREAM stream = NULL;
|
||||
|
||||
const char *base = S9xBasename(filename);
|
||||
auto base = S9xBasename(filename);
|
||||
|
||||
if(S9xOpenSnapshotFile(filename, TRUE, &stream))
|
||||
{
|
||||
@@ -1160,14 +1154,14 @@ bool8 S9xUnfreezeScreenshot(const char *filename, uint16 **image_buffer, int &wi
|
||||
|
||||
if(result != SUCCESS)
|
||||
{
|
||||
S9xMessageFromResult(result, base);
|
||||
S9xMessageFromResult(result, base.c_str());
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
sprintf(String, SAVE_ERR_SAVE_NOT_FOUND, base);
|
||||
sprintf(String, SAVE_ERR_SAVE_NOT_FOUND, base.c_str());
|
||||
S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String);
|
||||
|
||||
return (FALSE);
|
||||
@@ -1181,7 +1175,7 @@ void S9xFreezeToStream (STREAM stream)
|
||||
sprintf(buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION);
|
||||
WRITE_STREAM(buffer, strlen(buffer), stream);
|
||||
|
||||
sprintf(buffer, "NAM:%06d:%s%c", (int) strlen(Memory.ROMFilename) + 1, Memory.ROMFilename, 0);
|
||||
sprintf(buffer, "NAM:%06d:%s%c", (int) Memory.ROMFilename.length() + 1, Memory.ROMFilename.c_str(), 0);
|
||||
WRITE_STREAM(buffer, strlen(buffer) + 1, stream);
|
||||
|
||||
FreezeStruct(stream, "CPU", &CPU, SnapCPU, COUNT(SnapCPU));
|
||||
@@ -1195,11 +1189,11 @@ void S9xFreezeToStream (STREAM stream)
|
||||
dma_snap.dma[d] = DMA[d];
|
||||
FreezeStruct(stream, "DMA", &dma_snap, SnapDMA, COUNT(SnapDMA));
|
||||
|
||||
FreezeBlock (stream, "VRA", Memory.VRAM, 0x10000);
|
||||
FreezeBlock (stream, "VRA", Memory.VRAM, sizeof(Memory.VRAM));
|
||||
|
||||
FreezeBlock (stream, "RAM", Memory.RAM, 0x20000);
|
||||
FreezeBlock (stream, "RAM", Memory.RAM, sizeof(Memory.RAM));
|
||||
|
||||
FreezeBlock (stream, "SRA", Memory.SRAM, 0x80000);
|
||||
FreezeBlock (stream, "SRA", Memory.SRAM, Memory.SRAM_SIZE);
|
||||
|
||||
FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000);
|
||||
|
||||
@@ -1210,6 +1204,7 @@ void S9xFreezeToStream (STREAM stream)
|
||||
S9xControlPreSaveState(&ctl_snap);
|
||||
FreezeStruct(stream, "CTL", &ctl_snap, SnapControls, COUNT(SnapControls));
|
||||
|
||||
Timings.InterlaceField = S9xInterlaceField();
|
||||
FreezeStruct(stream, "TIM", &Timings, SnapTimings, COUNT(SnapTimings));
|
||||
|
||||
if (Settings.SuperFX)
|
||||
@@ -1397,16 +1392,16 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
break;
|
||||
|
||||
if (fast)
|
||||
result = UnfreezeBlock(stream, "RAM", Memory.RAM, 0x20000);
|
||||
result = UnfreezeBlock(stream, "RAM", Memory.RAM, sizeof(Memory.RAM));
|
||||
else
|
||||
result = UnfreezeBlockCopy(stream, "RAM", &local_ram, 0x20000);
|
||||
result = UnfreezeBlockCopy(stream, "RAM", &local_ram, sizeof(Memory.RAM));
|
||||
if (result != SUCCESS)
|
||||
break;
|
||||
|
||||
if (fast)
|
||||
result = UnfreezeBlock(stream, "SRA", Memory.SRAM, 0x80000);
|
||||
result = UnfreezeBlock(stream, "SRA", Memory.SRAM, Memory.SRAM_SIZE);
|
||||
else
|
||||
result = UnfreezeBlockCopy (stream, "SRA", &local_sram, 0x80000);
|
||||
result = UnfreezeBlockCopy (stream, "SRA", &local_sram, Memory.SRAM_SIZE);
|
||||
if (result != SUCCESS)
|
||||
break;
|
||||
|
||||
@@ -1576,21 +1571,46 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
memcpy(Memory.RAM, local_ram, 0x20000);
|
||||
|
||||
if (local_sram)
|
||||
memcpy(Memory.SRAM, local_sram, 0x80000);
|
||||
memcpy(Memory.SRAM, local_sram, Memory.SRAM_SIZE);
|
||||
|
||||
if (local_fillram)
|
||||
memcpy(Memory.FillRAM, local_fillram, 0x8000);
|
||||
|
||||
if(version < SNAPSHOT_VERSION_BAPU) {
|
||||
if (version < SNAPSHOT_VERSION_BAPU)
|
||||
{
|
||||
printf("Using Blargg APU snapshot loading (snapshot version %d, current is %d)\n...", version, SNAPSHOT_VERSION);
|
||||
S9xAPULoadBlarggState(local_apu_sound);
|
||||
} else
|
||||
S9xAPULoadState(local_apu_sound);
|
||||
}
|
||||
else if (version < 12)
|
||||
{
|
||||
printf("Adjusting old APU snapshot (snapshot version %d, current is %d)\n", version, SNAPSHOT_VERSION);
|
||||
const size_t spc_block_size = 65700;
|
||||
const size_t old_dsp_block_size = 514;
|
||||
const size_t added_bytes_v12 = 128;
|
||||
const size_t bytes_afterward = 16;
|
||||
// Shift end to make room for extra 128 bytes
|
||||
memmove(local_apu_sound + spc_block_size + old_dsp_block_size + added_bytes_v12,
|
||||
local_apu_sound + spc_block_size + old_dsp_block_size,
|
||||
bytes_afterward);
|
||||
// Copy saved internal registers to external registers
|
||||
const size_t new_dsp_registers_position = spc_block_size + 513;
|
||||
|
||||
struct SControlSnapshot ctl_snap;
|
||||
UnfreezeStructFromCopy(&ctl_snap, SnapControls, COUNT(SnapControls), local_control_data, version);
|
||||
memmove(local_apu_sound + new_dsp_registers_position,
|
||||
local_apu_sound + spc_block_size,
|
||||
added_bytes_v12);
|
||||
// the extra 0 byte between external registers and bytes_afterward is already present due to memset in S9xAPUSaveState
|
||||
|
||||
UnfreezeStructFromCopy(&Timings, SnapTimings, COUNT(SnapTimings), local_timing_data, version);
|
||||
S9xAPULoadState(local_apu_sound);
|
||||
}
|
||||
else if (version >= 12)
|
||||
{
|
||||
S9xAPULoadState(local_apu_sound);
|
||||
}
|
||||
|
||||
struct SControlSnapshot ctl_snap;
|
||||
UnfreezeStructFromCopy(&ctl_snap, SnapControls, COUNT(SnapControls), local_control_data, version);
|
||||
|
||||
UnfreezeStructFromCopy(&Timings, SnapTimings, COUNT(SnapTimings), local_timing_data, version);
|
||||
|
||||
if (local_superfx)
|
||||
{
|
||||
@@ -1695,12 +1715,11 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
IPPU.ColorsChanged = TRUE;
|
||||
IPPU.OBJChanged = TRUE;
|
||||
IPPU.RenderThisFrame = TRUE;
|
||||
|
||||
GFX.InterlaceFrame = Timings.InterlaceField;
|
||||
|
||||
GFX.DoInterlace = 0;
|
||||
|
||||
S9xGraphicsScreenResize();
|
||||
|
||||
|
||||
if (Settings.FastSavestates == 0)
|
||||
memset(GFX.Screen,0,GFX.Pitch * MAX_SNES_HEIGHT);
|
||||
|
||||
@@ -1754,11 +1773,11 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
|
||||
UnfreezeStructFromCopy(ssi, SnapScreenshot, COUNT(SnapScreenshot), local_screenshot, version);
|
||||
|
||||
IPPU.RenderedScreenWidth = min(ssi->Width, IMAGE_WIDTH);
|
||||
IPPU.RenderedScreenHeight = min(ssi->Height, IMAGE_HEIGHT);
|
||||
IPPU.RenderedScreenWidth = min(ssi->Width, MAX_SNES_WIDTH);
|
||||
IPPU.RenderedScreenHeight = min(ssi->Height, MAX_SNES_HEIGHT);
|
||||
const bool8 scaleDownX = IPPU.RenderedScreenWidth < ssi->Width;
|
||||
const bool8 scaleDownY = IPPU.RenderedScreenHeight < ssi->Height && ssi->Height > SNES_HEIGHT_EXTENDED;
|
||||
GFX.DoInterlace = Settings.SupportHiRes ? ssi->Interlaced : 0;
|
||||
GFX.DoInterlace = ssi->Interlaced;
|
||||
|
||||
uint8 *rowpix = ssi->Data;
|
||||
uint16 *screen = GFX.Screen;
|
||||
@@ -1795,7 +1814,7 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
}
|
||||
|
||||
// black out what we might have missed
|
||||
for (uint32 y = IPPU.RenderedScreenHeight; y < (uint32) (IMAGE_HEIGHT); y++)
|
||||
for (uint32 y = IPPU.RenderedScreenHeight; y < (uint32) (MAX_SNES_HEIGHT); y++)
|
||||
memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL * 2);
|
||||
|
||||
delete ssi;
|
||||
@@ -1893,8 +1912,8 @@ int S9xUnfreezeScreenshotFromStream(STREAM stream, uint16 **image_buffer, int &w
|
||||
|
||||
UnfreezeStructFromCopy(ssi, SnapScreenshot, COUNT(SnapScreenshot), local_screenshot, version);
|
||||
|
||||
width = min(ssi->Width, IMAGE_WIDTH);
|
||||
height = min(ssi->Height, IMAGE_HEIGHT);
|
||||
width = min(ssi->Width, MAX_SNES_WIDTH);
|
||||
height = min(ssi->Height, MAX_SNES_HEIGHT);
|
||||
|
||||
*image_buffer = (uint16 *)malloc(width * height * sizeof(uint16));
|
||||
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
#define SNAPSHOT_VERSION_IRQ 7
|
||||
#define SNAPSHOT_VERSION_BAPU 8
|
||||
#define SNAPSHOT_VERSION_IRQ_2018 11 // irq changes were introduced earlier, since this we store NextIRQTimer directly
|
||||
#define SNAPSHOT_VERSION 11
|
||||
#define SNAPSHOT_VERSION 12
|
||||
|
||||
#define SUCCESS 1
|
||||
#define WRONG_FORMAT (-1)
|
||||
|
||||
+9
-20
@@ -39,26 +39,19 @@ static bool parse_controller_spec (int port, const char *arg)
|
||||
{
|
||||
if (!strcasecmp(arg, "none"))
|
||||
S9xSetController(port, CTL_NONE, 0, 0, 0, 0);
|
||||
else
|
||||
if (!strncasecmp(arg, "pad", 3) && arg[3] >= '1' && arg[3] <= '8' && arg[4] == '\0')
|
||||
else if (!strncasecmp(arg, "pad", 3) && arg[3] >= '1' && arg[3] <= '8' && arg[4] == '\0')
|
||||
S9xSetController(port, CTL_JOYPAD, arg[3] - '1', 0, 0, 0);
|
||||
else
|
||||
if (!strncasecmp(arg, "mouse", 5) && arg[5] >= '1' && arg[5] <= '2' && arg[6] == '\0')
|
||||
else if (!strncasecmp(arg, "mouse", 5) && arg[5] >= '1' && arg[5] <= '2' && arg[6] == '\0')
|
||||
S9xSetController(port, CTL_MOUSE, arg[5] - '1', 0, 0, 0);
|
||||
else
|
||||
if (!strcasecmp(arg, "superscope"))
|
||||
else if (!strcasecmp(arg, "superscope"))
|
||||
S9xSetController(port, CTL_SUPERSCOPE, 0, 0, 0, 0);
|
||||
else
|
||||
if (!strcasecmp(arg, "justifier"))
|
||||
else if (!strcasecmp(arg, "justifier"))
|
||||
S9xSetController(port, CTL_JUSTIFIER, 0, 0, 0, 0);
|
||||
else
|
||||
if (!strcasecmp(arg, "two-justifiers"))
|
||||
else if (!strcasecmp(arg, "two-justifiers"))
|
||||
S9xSetController(port, CTL_JUSTIFIER, 1, 0, 0, 0);
|
||||
else
|
||||
if (!strcasecmp(arg, "macsrifle"))
|
||||
else if (!strcasecmp(arg, "macsrifle"))
|
||||
S9xSetController(port, CTL_MACSRIFLE, 0, 0, 0, 0);
|
||||
else
|
||||
if (!strncasecmp(arg, "mp5:", 4) && ((arg[4] >= '1' && arg[4] <= '8') || arg[4] == 'n') &&
|
||||
else if (!strncasecmp(arg, "mp5:", 4) && ((arg[4] >= '1' && arg[4] <= '8') || arg[4] == 'n') &&
|
||||
((arg[5] >= '1' && arg[5] <= '8') || arg[5] == 'n') &&
|
||||
((arg[6] >= '1' && arg[6] <= '8') || arg[6] == 'n') &&
|
||||
((arg[7] >= '1' && arg[7] <= '8') || arg[7] == 'n') && arg[8] == '\0')
|
||||
@@ -247,7 +240,6 @@ void S9xLoadConfigFiles (char **argv, int argc)
|
||||
|
||||
// Display
|
||||
|
||||
Settings.SupportHiRes = conf.GetBool("Display::HiRes", true);
|
||||
Settings.Transparency = conf.GetBool("Display::Transparency", true);
|
||||
Settings.DisableGraphicWindows = !conf.GetBool("Display::GraphicWindows", true);
|
||||
Settings.DisplayTime = conf.GetBool("Display::DisplayTime", false);
|
||||
@@ -471,7 +463,7 @@ void S9xParseArgsForCheats (char **argv, int argc)
|
||||
}
|
||||
else
|
||||
{
|
||||
S9xEnableCheatGroup (Cheat.g.size() - 1);
|
||||
S9xEnableCheatGroup (Cheat.group.size() - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -550,9 +542,6 @@ char * S9xParseArgs (char **argv, int argc)
|
||||
if (!strcasecmp(argv[i], "-displaykeypress"))
|
||||
Settings.DisplayPressedKeys = TRUE;
|
||||
else
|
||||
if (!strcasecmp(argv[i], "-nohires"))
|
||||
Settings.SupportHiRes = FALSE;
|
||||
else
|
||||
if (!strcasecmp(argv[i], "-notransparency"))
|
||||
Settings.Transparency = FALSE;
|
||||
else
|
||||
@@ -658,7 +647,7 @@ char * S9xParseArgs (char **argv, int argc)
|
||||
}
|
||||
else
|
||||
{
|
||||
S9xEnableCheatGroup (Cheat.g.size() - 1);
|
||||
S9xEnableCheatGroup (Cheat.group.size() - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
+6
-7
@@ -8,7 +8,7 @@
|
||||
#define _SNES9X_H_
|
||||
|
||||
#ifndef VERSION
|
||||
#define VERSION "1.61"
|
||||
#define VERSION "1.62.3"
|
||||
#endif
|
||||
|
||||
#include "port.h"
|
||||
@@ -58,11 +58,13 @@
|
||||
#define SNES_HEIGHT_EXTENDED 239
|
||||
#define MAX_SNES_WIDTH (SNES_WIDTH * 2)
|
||||
#define MAX_SNES_HEIGHT (SNES_HEIGHT_EXTENDED * 2)
|
||||
#define IMAGE_WIDTH (Settings.SupportHiRes ? MAX_SNES_WIDTH : SNES_WIDTH)
|
||||
#define IMAGE_HEIGHT (Settings.SupportHiRes ? MAX_SNES_HEIGHT : SNES_HEIGHT_EXTENDED)
|
||||
|
||||
#define NTSC_MASTER_CLOCK 21477272.727272 // 21477272 + 8/11 exact
|
||||
#define PAL_MASTER_CLOCK 21281370.0
|
||||
#define NTSC_PROGRESSIVE_FRAME_RATE 60.09881389744051
|
||||
#define NTSC_INTERLACED_FRAME_RATE 59.94005994
|
||||
#define PAL_PROGRESSIVE_FRAME_RATE 50.006977968
|
||||
|
||||
|
||||
#define SNES_MAX_NTSC_VCOUNTER 262
|
||||
#define SNES_MAX_PAL_VCOUNTER 312
|
||||
@@ -215,7 +217,7 @@ struct SSettings
|
||||
bool8 JustifierMaster;
|
||||
bool8 MultiPlayer5Master;
|
||||
bool8 MacsRifleMaster;
|
||||
|
||||
|
||||
bool8 ForceLoROM;
|
||||
bool8 ForceHiROM;
|
||||
bool8 ForceHeader;
|
||||
@@ -242,7 +244,6 @@ struct SSettings
|
||||
int32 DynamicRateLimit; /* Multiplied by 1000 */
|
||||
int32 InterpolationMethod;
|
||||
|
||||
bool8 SupportHiRes;
|
||||
bool8 Transparency;
|
||||
uint8 BG_Forced;
|
||||
bool8 DisableGraphicWindows;
|
||||
@@ -303,8 +304,6 @@ struct SSettings
|
||||
bool8 DontSaveOopsSnapshot;
|
||||
bool8 UpAndDown;
|
||||
|
||||
bool8 OpenGLEnable;
|
||||
|
||||
bool8 SeparateEchoBuffer;
|
||||
uint32 SuperFXClockMultiplier;
|
||||
int OverclockMode;
|
||||
|
||||
Reference in New Issue
Block a user