mirror of
https://github.com/OpenEmu/mGBA-Core.git
synced 2025-11-01 11:06:53 +00:00
Update to mGBA 0.13.1
This commit is contained in:
+3
-3
@@ -17,7 +17,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.10.2</string>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>OEGameCoreController</string>
|
||||
<key>OEGameCoreClass</key>
|
||||
@@ -37,7 +37,7 @@
|
||||
</dict>
|
||||
</dict>
|
||||
<key>OEGameCorePlayerCount</key>
|
||||
<string>1</string>
|
||||
<integer>1</integer>
|
||||
<key>OEProjectURL</key>
|
||||
<string>https://mgba.io/</string>
|
||||
<key>OESystemIdentifiers</key>
|
||||
@@ -45,7 +45,7 @@
|
||||
<string>openemu.system.gba</string>
|
||||
</array>
|
||||
<key>SUEnableAutomaticChecks</key>
|
||||
<string>1</string>
|
||||
<true/>
|
||||
<key>SUFeedURL</key>
|
||||
<string>https://raw.github.com/OpenEmu/OpenEmu-Update/master/mgba_appcast.xml</string>
|
||||
</dict>
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct option;
|
||||
|
||||
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
|
||||
|
||||
#ifdef REPLACE_GETOPT
|
||||
|
||||
@@ -204,6 +204,7 @@ static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress)
|
||||
err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
|
||||
#endif
|
||||
if (err) {
|
||||
SocketCloseQuiet(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ void GBAMemoryInit(struct GBA* gba);
|
||||
void GBAMemoryDeinit(struct GBA* gba);
|
||||
|
||||
void GBAMemoryReset(struct GBA* gba);
|
||||
void GBAMemoryClearAGBPrint(struct GBA* gba);
|
||||
|
||||
uint32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
|
||||
uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter);
|
||||
|
||||
@@ -97,7 +97,7 @@ CXX_GUARD_START
|
||||
#define mSCRIPT_TYPE_MS_CS(STRUCT) (&mSTStructConst_ ## STRUCT)
|
||||
#define mSCRIPT_TYPE_MS_S_METHOD(STRUCT, NAME) (&_mSTStructBindingType_ ## STRUCT ## _ ## NAME)
|
||||
#define mSCRIPT_TYPE_MS_PS(STRUCT) (&mSTStructPtr_ ## STRUCT)
|
||||
#define mSCRIPT_TYPE_MS_PCS(STRUCT) (&mSTStructConstPtr_ ## STRUCT)
|
||||
#define mSCRIPT_TYPE_MS_PCS(STRUCT) (&mSTStructPtrConst_ ## STRUCT)
|
||||
#define mSCRIPT_TYPE_MS_WSTR (&mSTStringWrapper)
|
||||
#define mSCRIPT_TYPE_MS_WLIST (&mSTListWrapper)
|
||||
#define mSCRIPT_TYPE_MS_W(TYPE) (&mSTWrapper_ ## TYPE)
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
8701D2A71D19D30E00E8A7D8 /* OEGBASystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OEGBASystemResponderClient.h; path = "../OpenEmu/SystemPlugins/GameBoy Advance/OEGBASystemResponderClient.h"; sourceTree = "<group>"; };
|
||||
8701D2A81D19D36600E8A7D8 /* mGBAGameCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mGBAGameCore.h; path = src/platform/openemu/mGBAGameCore.h; sourceTree = "<group>"; };
|
||||
8701D2A91D19D36600E8A7D8 /* mGBAGameCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = mGBAGameCore.m; path = src/platform/openemu/mGBAGameCore.m; sourceTree = "<group>"; };
|
||||
8701D2A91D19D36600E8A7D8 /* mGBAGameCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = mGBAGameCore.m; path = src/platform/openemu/mGBAGameCore.m; sourceTree = "<group>"; usesTabs = 0; };
|
||||
8701D2AD1D19D4A900E8A7D8 /* arm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = arm.c; sourceTree = "<group>"; };
|
||||
8701D2AF1D19D4A900E8A7D8 /* decoder-arm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "decoder-arm.c"; sourceTree = "<group>"; };
|
||||
8701D2B11D19D4A900E8A7D8 /* decoder-thumb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "decoder-thumb.c"; sourceTree = "<group>"; };
|
||||
@@ -851,6 +851,7 @@
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 0.10.3;
|
||||
EXPORTED_SYMBOLS_FILE = "";
|
||||
FRAMEWORK_SEARCH_PATHS = "";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
@@ -887,6 +888,7 @@
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 0.10.3;
|
||||
EXPORTED_SYMBOLS_FILE = "";
|
||||
FRAMEWORK_SEARCH_PATHS = "";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
@@ -922,7 +924,6 @@
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_EXPERIMENTAL = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
@@ -960,7 +961,6 @@
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_EXPERIMENTAL = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
|
||||
+3
-1
@@ -663,7 +663,9 @@ DEFINE_INSTRUCTION_ARM(MRC, ARM_STUB)
|
||||
|
||||
// Begin miscellaneous definitions
|
||||
|
||||
DEFINE_INSTRUCTION_ARM(BKPT, cpu->irqh.bkpt32(cpu, ((opcode >> 4) & 0xFFF0) | (opcode & 0xF))); // Not strictly in ARMv4T, but here for convenience
|
||||
DEFINE_INSTRUCTION_ARM(BKPT,
|
||||
cpu->irqh.bkpt32(cpu, ((opcode >> 4) & 0xFFF0) | (opcode & 0xF));
|
||||
currentCycles = 0;); // Not strictly in ARMv4T, but here for convenience
|
||||
DEFINE_INSTRUCTION_ARM(ILL, ARM_ILL) // Illegal opcode
|
||||
|
||||
DEFINE_INSTRUCTION_ARM(MSR,
|
||||
|
||||
+4
-6
@@ -381,7 +381,9 @@ DEFINE_LOAD_STORE_MULTIPLE_THUMB(PUSHR,
|
||||
cpu->gprs[ARM_SP] = address)
|
||||
|
||||
DEFINE_INSTRUCTION_THUMB(ILL, ARM_ILL)
|
||||
DEFINE_INSTRUCTION_THUMB(BKPT, cpu->irqh.bkpt16(cpu, opcode & 0xFF);)
|
||||
DEFINE_INSTRUCTION_THUMB(BKPT,
|
||||
cpu->irqh.bkpt16(cpu, opcode & 0xFF);
|
||||
currentCycles = 0;) // Not strictly in ARMv4T, but here for convenience
|
||||
DEFINE_INSTRUCTION_THUMB(B,
|
||||
int16_t immediate = (opcode & 0x07FF) << 5;
|
||||
cpu->gprs[ARM_PC] += (((int32_t) immediate) >> 4);
|
||||
@@ -401,11 +403,7 @@ DEFINE_INSTRUCTION_THUMB(BL2,
|
||||
DEFINE_INSTRUCTION_THUMB(BX,
|
||||
int rm = (opcode >> 3) & 0xF;
|
||||
_ARMSetMode(cpu, cpu->gprs[rm] & 0x00000001);
|
||||
int misalign = 0;
|
||||
if (rm == ARM_PC) {
|
||||
misalign = cpu->gprs[rm] & 0x00000002;
|
||||
}
|
||||
cpu->gprs[ARM_PC] = (cpu->gprs[rm] & 0xFFFFFFFE) - misalign;
|
||||
cpu->gprs[ARM_PC] = cpu->gprs[rm] & 0xFFFFFFFE;
|
||||
if (cpu->executionMode == MODE_THUMB) {
|
||||
currentCycles += ThumbWritePC(cpu);
|
||||
} else {
|
||||
|
||||
@@ -127,6 +127,7 @@ struct mCore* mCoreFind(const char* path) {
|
||||
}
|
||||
|
||||
bool mCoreLoadFile(struct mCore* core, const char* path) {
|
||||
core->unloadROM(core);
|
||||
#ifdef FIXED_ROM_BUFFER
|
||||
return mCorePreloadFile(core, path);
|
||||
#else
|
||||
|
||||
+12
-12
@@ -713,33 +713,33 @@ static struct mScriptTextBuffer* _mScriptConsoleCreateBuffer(struct mScriptConso
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void mScriptConsoleLog(struct mScriptConsole* console, struct mScriptString* msg) {
|
||||
static void mScriptConsoleLog(struct mScriptConsole* console, const char* msg) {
|
||||
if (console->logger) {
|
||||
mLogExplicit(console->logger, _mLOG_CAT_SCRIPT, mLOG_INFO, "%s", msg->buffer);
|
||||
mLogExplicit(console->logger, _mLOG_CAT_SCRIPT, mLOG_INFO, "%s", msg);
|
||||
} else {
|
||||
mLog(_mLOG_CAT_SCRIPT, mLOG_INFO, "%s", msg->buffer);
|
||||
mLog(_mLOG_CAT_SCRIPT, mLOG_INFO, "%s", msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void mScriptConsoleWarn(struct mScriptConsole* console, struct mScriptString* msg) {
|
||||
static void mScriptConsoleWarn(struct mScriptConsole* console, const char* msg) {
|
||||
if (console->logger) {
|
||||
mLogExplicit(console->logger, _mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg->buffer);
|
||||
mLogExplicit(console->logger, _mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg);
|
||||
} else {
|
||||
mLog(_mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg->buffer);
|
||||
mLog(_mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void mScriptConsoleError(struct mScriptConsole* console, struct mScriptString* msg) {
|
||||
static void mScriptConsoleError(struct mScriptConsole* console, const char* msg) {
|
||||
if (console->logger) {
|
||||
mLogExplicit(console->logger, _mLOG_CAT_SCRIPT, mLOG_ERROR, "%s", msg->buffer);
|
||||
mLogExplicit(console->logger, _mLOG_CAT_SCRIPT, mLOG_ERROR, "%s", msg);
|
||||
} else {
|
||||
mLog(_mLOG_CAT_SCRIPT, mLOG_WARN, "%s", msg->buffer);
|
||||
mLog(_mLOG_CAT_SCRIPT, mLOG_ERROR, "%s", msg);
|
||||
}
|
||||
}
|
||||
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptConsole, log, mScriptConsoleLog, 1, STR, msg);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptConsole, warn, mScriptConsoleWarn, 1, STR, msg);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptConsole, error, mScriptConsoleError, 1, STR, msg);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptConsole, log, mScriptConsoleLog, 1, CHARP, msg);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptConsole, warn, mScriptConsoleWarn, 1, CHARP, msg);
|
||||
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptConsole, error, mScriptConsoleError, 1, CHARP, msg);
|
||||
mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mScriptConsole, S(mScriptTextBuffer), createBuffer, _mScriptConsoleCreateBuffer, 1, CHARP, name);
|
||||
|
||||
mSCRIPT_DEFINE_STRUCT(mScriptConsole)
|
||||
|
||||
+39
-24
@@ -100,22 +100,24 @@ void GBAudioReset(struct GBAudio* audio) {
|
||||
audio->ch3 = (struct GBAudioWaveChannel) { .bank = 0 };
|
||||
audio->ch4 = (struct GBAudioNoiseChannel) { .nSamples = 0 };
|
||||
// TODO: DMG randomness
|
||||
audio->ch3.wavedata8[0] = 0x00;
|
||||
audio->ch3.wavedata8[1] = 0xFF;
|
||||
audio->ch3.wavedata8[2] = 0x00;
|
||||
audio->ch3.wavedata8[3] = 0xFF;
|
||||
audio->ch3.wavedata8[4] = 0x00;
|
||||
audio->ch3.wavedata8[5] = 0xFF;
|
||||
audio->ch3.wavedata8[6] = 0x00;
|
||||
audio->ch3.wavedata8[7] = 0xFF;
|
||||
audio->ch3.wavedata8[8] = 0x00;
|
||||
audio->ch3.wavedata8[9] = 0xFF;
|
||||
audio->ch3.wavedata8[10] = 0x00;
|
||||
audio->ch3.wavedata8[11] = 0xFF;
|
||||
audio->ch3.wavedata8[12] = 0x00;
|
||||
audio->ch3.wavedata8[13] = 0xFF;
|
||||
audio->ch3.wavedata8[14] = 0x00;
|
||||
audio->ch3.wavedata8[15] = 0xFF;
|
||||
if (audio->style != GB_AUDIO_GBA) {
|
||||
audio->ch3.wavedata8[0] = 0x00;
|
||||
audio->ch3.wavedata8[1] = 0xFF;
|
||||
audio->ch3.wavedata8[2] = 0x00;
|
||||
audio->ch3.wavedata8[3] = 0xFF;
|
||||
audio->ch3.wavedata8[4] = 0x00;
|
||||
audio->ch3.wavedata8[5] = 0xFF;
|
||||
audio->ch3.wavedata8[6] = 0x00;
|
||||
audio->ch3.wavedata8[7] = 0xFF;
|
||||
audio->ch3.wavedata8[8] = 0x00;
|
||||
audio->ch3.wavedata8[9] = 0xFF;
|
||||
audio->ch3.wavedata8[10] = 0x00;
|
||||
audio->ch3.wavedata8[11] = 0xFF;
|
||||
audio->ch3.wavedata8[12] = 0x00;
|
||||
audio->ch3.wavedata8[13] = 0xFF;
|
||||
audio->ch3.wavedata8[14] = 0x00;
|
||||
audio->ch3.wavedata8[15] = 0xFF;
|
||||
}
|
||||
audio->ch4 = (struct GBAudioNoiseChannel) { .envelope = { .dead = 2 } };
|
||||
audio->frame = 0;
|
||||
audio->sampleInterval = SAMPLE_INTERVAL * GB_MAX_SAMPLES;
|
||||
@@ -506,7 +508,7 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels) {
|
||||
GBAudioSample(audio, timestamp);
|
||||
}
|
||||
|
||||
if (audio->playingCh1 && (channels & 0x1) && audio->ch1.envelope.dead != 2) {
|
||||
if ((channels & 0x1) && ((audio->playingCh1 && audio->ch1.envelope.dead != 2) || timestamp - audio->ch1.lastUpdate > 0x40000000 || (channels == 0x1))) {
|
||||
int period = 4 * (2048 - audio->ch1.control.frequency) * audio->timingFactor;
|
||||
int32_t diff = timestamp - audio->ch1.lastUpdate;
|
||||
if (diff >= period) {
|
||||
@@ -516,7 +518,7 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels) {
|
||||
_updateSquareSample(&audio->ch1);
|
||||
}
|
||||
}
|
||||
if (audio->playingCh2 && (channels & 0x2) && audio->ch2.envelope.dead != 2) {
|
||||
if ((channels & 0x2) && ((audio->playingCh2 && audio->ch2.envelope.dead != 2) || timestamp - audio->ch2.lastUpdate > 0x40000000 || (channels == 0x2))) {
|
||||
int period = 4 * (2048 - audio->ch2.control.frequency) * audio->timingFactor;
|
||||
int32_t diff = timestamp - audio->ch2.lastUpdate;
|
||||
if (diff >= period) {
|
||||
@@ -647,7 +649,9 @@ void GBAudioUpdateFrame(struct GBAudio* audio) {
|
||||
if (audio->ch1.sweep.enable) {
|
||||
--audio->ch1.sweep.step;
|
||||
if (audio->ch1.sweep.step == 0) {
|
||||
audio->playingCh1 = _updateSweep(&audio->ch1, false);
|
||||
if (!_updateSweep(&audio->ch1, false)) {
|
||||
audio->playingCh1 = false;
|
||||
}
|
||||
*audio->nr52 &= ~0x0001;
|
||||
*audio->nr52 |= audio->playingCh1;
|
||||
}
|
||||
@@ -846,9 +850,6 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
||||
bool _resetEnvelope(struct GBAudioEnvelope* envelope) {
|
||||
envelope->currentVolume = envelope->initialVolume;
|
||||
_updateEnvelopeDead(envelope);
|
||||
if (!envelope->dead) {
|
||||
envelope->nextStep = envelope->stepTime;
|
||||
}
|
||||
return envelope->initialVolume || envelope->direction;
|
||||
}
|
||||
|
||||
@@ -880,12 +881,25 @@ void _writeDuty(struct GBAudioEnvelope* envelope, uint8_t value) {
|
||||
}
|
||||
|
||||
bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudioStyle style) {
|
||||
bool oldDirection = envelope->direction;
|
||||
envelope->stepTime = GBAudioRegisterSweepGetStepTime(value);
|
||||
envelope->direction = GBAudioRegisterSweepGetDirection(value);
|
||||
envelope->initialVolume = GBAudioRegisterSweepGetInitialVolume(value);
|
||||
if (style == GB_AUDIO_DMG && !envelope->stepTime) {
|
||||
if (!envelope->stepTime) {
|
||||
// TODO: Improve "zombie" mode
|
||||
++envelope->currentVolume;
|
||||
if (style == GB_AUDIO_DMG) {
|
||||
++envelope->currentVolume;
|
||||
} else if (style == GB_AUDIO_CGB) {
|
||||
if (envelope->direction == oldDirection) {
|
||||
if (envelope->direction) {
|
||||
++envelope->currentVolume;
|
||||
} else {
|
||||
envelope->currentVolume += 2;
|
||||
}
|
||||
} else {
|
||||
envelope->currentVolume = 0;
|
||||
}
|
||||
}
|
||||
envelope->currentVolume &= 0xF;
|
||||
}
|
||||
_updateEnvelopeDead(envelope);
|
||||
@@ -933,6 +947,7 @@ static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope) {
|
||||
envelope->dead = 1;
|
||||
} else {
|
||||
envelope->dead = 0;
|
||||
envelope->nextStep = envelope->stepTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -644,8 +644,10 @@ static void _GBCoreReset(struct mCore* core) {
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(gbcore->memoryBlocks) / sizeof(*gbcore->memoryBlocks); ++i) {
|
||||
if (gbcore->memoryBlocks[i].id == GB_REGION_CART_BANK0) {
|
||||
gbcore->memoryBlocks[i].size = gb->memory.romSize;
|
||||
gbcore->memoryBlocks[i].maxSegment = gb->memory.romSize / GB_SIZE_CART_BANK0;
|
||||
} else if (gbcore->memoryBlocks[i].id == GB_REGION_EXTERNAL_RAM) {
|
||||
gbcore->memoryBlocks[i].size = gb->sramSize;
|
||||
gbcore->memoryBlocks[i].maxSegment = gb->sramSize / GB_SIZE_EXTERNAL_RAM;
|
||||
} else {
|
||||
continue;
|
||||
@@ -1050,7 +1052,7 @@ static void _GBCoreDetachDebugger(struct mCore* core) {
|
||||
static void _GBCoreLoadSymbols(struct mCore* core, struct VFile* vf) {
|
||||
core->symbolTable = mDebuggerSymbolTableCreate();
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
if (!vf) {
|
||||
if (!vf && core->dirs.base) {
|
||||
vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".sym", O_RDONLY);
|
||||
}
|
||||
#endif
|
||||
|
||||
+10
@@ -455,6 +455,9 @@ void GBApplyPatch(struct GB* gb, struct Patch* patch) {
|
||||
if (patchedSize > GB_SIZE_CART_MAX) {
|
||||
patchedSize = GB_SIZE_CART_MAX;
|
||||
}
|
||||
|
||||
const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
|
||||
uint8_t type = cart->type;
|
||||
void* newRom = anonymousMemoryMap(GB_SIZE_CART_MAX);
|
||||
if (!patch->applyPatch(patch, gb->memory.rom, gb->pristineRomSize, newRom, patchedSize)) {
|
||||
mappedMemoryFree(newRom, GB_SIZE_CART_MAX);
|
||||
@@ -473,6 +476,12 @@ void GBApplyPatch(struct GB* gb, struct Patch* patch) {
|
||||
}
|
||||
gb->memory.rom = newRom;
|
||||
gb->memory.romSize = patchedSize;
|
||||
|
||||
cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
|
||||
if (cart->type != type) {
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
GBMBCInit(gb);
|
||||
}
|
||||
gb->romCrc32 = doCrc32(gb->memory.rom, gb->memory.romSize);
|
||||
gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc);
|
||||
}
|
||||
@@ -817,6 +826,7 @@ void GBDetectModel(struct GB* gb) {
|
||||
gb->model = GB_MODEL_SGB2;
|
||||
break;
|
||||
case CGB_BIOS_CHECKSUM:
|
||||
case CGB0_BIOS_CHECKSUM:
|
||||
gb->model = GB_MODEL_CGB;
|
||||
break;
|
||||
case AGB_BIOS_CHECKSUM:
|
||||
|
||||
+1
-1
@@ -491,7 +491,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
|
||||
return;
|
||||
case GB_REG_SVBK:
|
||||
GBMemorySwitchWramBank(&gb->memory, value);
|
||||
value = gb->memory.wramCurrentBank;
|
||||
value &= 7;
|
||||
break;
|
||||
default:
|
||||
goto failed;
|
||||
|
||||
+3
-1
@@ -91,11 +91,13 @@ void GBSIOWriteSB(struct GBSIO* sio, uint8_t sb) {
|
||||
void GBSIOWriteSC(struct GBSIO* sio, uint8_t sc) {
|
||||
sio->period = GBSIOCyclesPerTransfer[GBRegisterSCGetClockSpeed(sc)]; // TODO Shift Clock
|
||||
if (GBRegisterSCIsEnable(sc)) {
|
||||
mTimingDeschedule(&sio->p->timing, &sio->event);
|
||||
if (GBRegisterSCIsShiftClock(sc)) {
|
||||
mTimingDeschedule(&sio->p->timing, &sio->event);
|
||||
mTimingSchedule(&sio->p->timing, &sio->event, sio->period * (2 - sio->p->doubleSpeed));
|
||||
sio->remainingBits = 8;
|
||||
}
|
||||
} else {
|
||||
mTimingDeschedule(&sio->p->timing, &sio->event);
|
||||
}
|
||||
if (sio->driver) {
|
||||
sio->driver->writeSC(sio->driver, sc);
|
||||
|
||||
+25
-12
@@ -131,17 +131,24 @@ void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA*
|
||||
mLOG(GBA_AUDIO, GAME_ERROR, "Invalid FIFO destination: 0x%08X", info->dest);
|
||||
return;
|
||||
}
|
||||
uint32_t source = info->source;
|
||||
uint32_t magic[2] = {
|
||||
audio->p->cpu->memory.load32(audio->p->cpu, source - 0x350, NULL),
|
||||
audio->p->cpu->memory.load32(audio->p->cpu, source - 0x980, NULL)
|
||||
};
|
||||
if (audio->mixer) {
|
||||
if (magic[0] - MP2K_MAGIC <= MP2K_LOCK_MAX) {
|
||||
audio->mixer->engage(audio->mixer, source - 0x350);
|
||||
} else if (magic[1] - MP2K_MAGIC <= MP2K_LOCK_MAX) {
|
||||
audio->mixer->engage(audio->mixer, source - 0x980);
|
||||
} else {
|
||||
uint32_t source = info->source;
|
||||
uint32_t offsets[] = { 0x350, 0x980 };
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(offsets) / sizeof(*offsets); ++i) {
|
||||
if (source < BASE_WORKING_RAM + offsets[i]) {
|
||||
continue;
|
||||
}
|
||||
if (source >= BASE_IO + offsets[i]) {
|
||||
continue;
|
||||
}
|
||||
uint32_t value = GBALoad32(audio->p->cpu, source - offsets[i], NULL);
|
||||
if (value - MP2K_MAGIC <= MP2K_LOCK_MAX) {
|
||||
audio->mixer->engage(audio->mixer, source - offsets[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == sizeof(offsets) / sizeof(*offsets)) {
|
||||
audio->externalMixing = false;
|
||||
}
|
||||
}
|
||||
@@ -253,11 +260,17 @@ void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) {
|
||||
}
|
||||
|
||||
void GBAAudioWriteSOUNDBIAS(struct GBAAudio* audio, uint16_t value) {
|
||||
int32_t timestamp = mTimingCurrentTime(&audio->p->timing);
|
||||
GBAAudioSample(audio, timestamp);
|
||||
audio->soundbias = value;
|
||||
int32_t oldSampleInterval = audio->sampleInterval;
|
||||
audio->sampleInterval = 0x200 >> GBARegisterSOUNDBIASGetResolution(value);
|
||||
if (oldSampleInterval != audio->sampleInterval && audio->p->stream && audio->p->stream->audioRateChanged) {
|
||||
audio->p->stream->audioRateChanged(audio->p->stream, GBA_ARM7TDMI_FREQUENCY / audio->sampleInterval);
|
||||
if (oldSampleInterval != audio->sampleInterval) {
|
||||
timestamp -= audio->lastSample;
|
||||
audio->sampleIndex = timestamp >> (9 - GBARegisterSOUNDBIASGetResolution(value));
|
||||
if (audio->p->stream && audio->p->stream->audioRateChanged) {
|
||||
audio->p->stream->audioRateChanged(audio->p->stream, GBA_ARM7TDMI_FREQUENCY / audio->sampleInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -421,8 +421,8 @@ void GBAHardwareTiltWrite(struct GBACartridgeHardware* hw, uint32_t address, uin
|
||||
int32_t x = rotationSource->readTiltX(rotationSource);
|
||||
int32_t y = rotationSource->readTiltY(rotationSource);
|
||||
// Normalize to ~12 bits, focused on 0x3A0
|
||||
hw->tiltX = (x >> 21) + 0x3A0; // Crop off an extra bit so that we can't go negative
|
||||
hw->tiltY = (y >> 21) + 0x3A0;
|
||||
hw->tiltX = 0x3A0 - (x >> 22);
|
||||
hw->tiltY = 0x3A0 - (y >> 22);
|
||||
} else {
|
||||
mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
|
||||
}
|
||||
|
||||
+3
-3
@@ -111,7 +111,7 @@ static const struct mCoreMemoryBlock _GBAMemoryBlocksFlash1M[] = {
|
||||
{ REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED },
|
||||
{ REGION_CART_SRAM, "sram", "Flash", "Flash Memory (64kiB)", BASE_CART_SRAM, BASE_CART_SRAM + SIZE_CART_FLASH512, SIZE_CART_FLASH1M, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 1 },
|
||||
{ REGION_CART_SRAM, "sram", "Flash", "Flash Memory (128kiB)", BASE_CART_SRAM, BASE_CART_SRAM + SIZE_CART_FLASH512, SIZE_CART_FLASH1M, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 1 },
|
||||
};
|
||||
|
||||
static const struct mCoreMemoryBlock _GBAMemoryBlocksEEPROM[] = {
|
||||
@@ -1116,12 +1116,12 @@ static void _GBACoreLoadSymbols(struct mCore* core, struct VFile* vf) {
|
||||
core->symbolTable = mDebuggerSymbolTableCreate();
|
||||
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
|
||||
#ifdef USE_ELF
|
||||
if (!vf) {
|
||||
if (!vf && core->dirs.base) {
|
||||
closeAfter = true;
|
||||
vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".elf", O_RDONLY);
|
||||
}
|
||||
#endif
|
||||
if (!vf) {
|
||||
if (!vf && core->dirs.base) {
|
||||
closeAfter = true;
|
||||
vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".sym", O_RDONLY);
|
||||
}
|
||||
|
||||
@@ -245,9 +245,6 @@ static void _mp2kReload(struct GBAAudioMixer* mixer) {
|
||||
}
|
||||
|
||||
bool _mp2kEngage(struct GBAAudioMixer* mixer, uint32_t address) {
|
||||
if (address < BASE_WORKING_RAM) {
|
||||
return false;
|
||||
}
|
||||
if (address != mixer->contextAddress) {
|
||||
mixer->contextAddress = address;
|
||||
mixer->p->externalMixing = true;
|
||||
|
||||
@@ -132,6 +132,7 @@ static void GBAInit(void* cpu, struct mCPUComponent* component) {
|
||||
}
|
||||
|
||||
void GBAUnloadROM(struct GBA* gba) {
|
||||
GBAMemoryClearAGBPrint(gba);
|
||||
if (gba->memory.rom && !gba->isPristine) {
|
||||
if (gba->yankedRomSize) {
|
||||
gba->yankedRomSize = 0;
|
||||
|
||||
+4
-4
@@ -50,13 +50,13 @@ const uint8_t hleBios[SIZE_BIOS] = {
|
||||
0x0c, 0x80, 0xbd, 0xe8, 0x30, 0x40, 0x2d, 0xe9, 0x02, 0x46, 0xa0, 0xe1,
|
||||
0x00, 0xc0, 0xa0, 0xe1, 0x01, 0x50, 0xa0, 0xe1, 0x01, 0x04, 0x12, 0xe3,
|
||||
0x0f, 0x00, 0x00, 0x0a, 0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a,
|
||||
0x24, 0x45, 0x85, 0xe0, 0x08, 0x00, 0xbc, 0xe8, 0x04, 0x00, 0x55, 0xe1,
|
||||
0x08, 0x00, 0xa5, 0xb8, 0xfc, 0xff, 0xff, 0xba, 0x14, 0x00, 0x00, 0xea,
|
||||
0x24, 0x45, 0x85, 0xe0, 0x08, 0x00, 0xb0, 0xe8, 0x04, 0x00, 0x51, 0xe1,
|
||||
0x08, 0x00, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba, 0x14, 0x00, 0x00, 0xea,
|
||||
0x01, 0xc0, 0xcc, 0xe3, 0x01, 0x50, 0xc5, 0xe3, 0xa4, 0x45, 0x85, 0xe0,
|
||||
0xb0, 0x30, 0xdc, 0xe1, 0x04, 0x00, 0x55, 0xe1, 0xb2, 0x30, 0xc5, 0xb0,
|
||||
0xfc, 0xff, 0xff, 0xba, 0x0c, 0x00, 0x00, 0xea, 0x01, 0x03, 0x12, 0xe3,
|
||||
0x05, 0x00, 0x00, 0x0a, 0x24, 0x45, 0x85, 0xe0, 0x04, 0x00, 0x55, 0xe1,
|
||||
0x08, 0x00, 0xbc, 0xb8, 0x08, 0x00, 0xa5, 0xb8, 0xfb, 0xff, 0xff, 0xba,
|
||||
0x05, 0x00, 0x00, 0x0a, 0x24, 0x45, 0x85, 0xe0, 0x04, 0x00, 0x51, 0xe1,
|
||||
0x08, 0x00, 0xb0, 0xb8, 0x08, 0x00, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba,
|
||||
0x04, 0x00, 0x00, 0xea, 0xa4, 0x45, 0x85, 0xe0, 0x04, 0x00, 0x55, 0xe1,
|
||||
0xb2, 0x30, 0xdc, 0xb0, 0xb2, 0x30, 0xc5, 0xb0, 0xfb, 0xff, 0xff, 0xba,
|
||||
0x17, 0x3e, 0xa0, 0xe3, 0x30, 0x80, 0xbd, 0xe8, 0xf0, 0x47, 0x2d, 0xe9,
|
||||
|
||||
+6
-6
@@ -209,10 +209,10 @@ tst r2, #0x04000000
|
||||
beq 1f
|
||||
@ Word
|
||||
add r4, r5, r4, lsr #10
|
||||
ldmia r12!, {r3}
|
||||
ldmia r0!, {r3}
|
||||
2:
|
||||
cmp r5, r4
|
||||
stmltia r5!, {r3}
|
||||
cmp r1, r4
|
||||
stmltia r1!, {r3}
|
||||
blt 2b
|
||||
b 3f
|
||||
@ Halfword
|
||||
@@ -233,9 +233,9 @@ beq 1f
|
||||
@ Word
|
||||
add r4, r5, r4, lsr #10
|
||||
2:
|
||||
cmp r5, r4
|
||||
ldmltia r12!, {r3}
|
||||
stmltia r5!, {r3}
|
||||
cmp r1, r4
|
||||
ldmltia r0!, {r3}
|
||||
stmltia r1!, {r3}
|
||||
blt 2b
|
||||
b 3f
|
||||
@ Halfword
|
||||
|
||||
+15
-11
@@ -128,6 +128,21 @@ void GBAMemoryReset(struct GBA* gba) {
|
||||
GBAAdjustWaitstates(gba, 0);
|
||||
GBAAdjustEWRAMWaitstates(gba, 0x0D00);
|
||||
|
||||
GBAMemoryClearAGBPrint(gba);
|
||||
|
||||
gba->memory.prefetch = false;
|
||||
gba->memory.lastPrefetchedPc = 0;
|
||||
|
||||
if (!gba->memory.wram || !gba->memory.iwram) {
|
||||
GBAMemoryDeinit(gba);
|
||||
mLOG(GBA_MEM, FATAL, "Could not map memory");
|
||||
}
|
||||
|
||||
GBADMAReset(gba);
|
||||
memset(&gba->memory.matrix, 0, sizeof(gba->memory.matrix));
|
||||
}
|
||||
|
||||
void GBAMemoryClearAGBPrint(struct GBA* gba) {
|
||||
gba->memory.activeRegion = -1;
|
||||
gba->memory.agbPrintProtect = 0;
|
||||
gba->memory.agbPrintBase = 0;
|
||||
@@ -140,17 +155,6 @@ void GBAMemoryReset(struct GBA* gba) {
|
||||
mappedMemoryFree(gba->memory.agbPrintBufferBackup, SIZE_AGB_PRINT);
|
||||
gba->memory.agbPrintBufferBackup = NULL;
|
||||
}
|
||||
|
||||
gba->memory.prefetch = false;
|
||||
gba->memory.lastPrefetchedPc = 0;
|
||||
|
||||
if (!gba->memory.wram || !gba->memory.iwram) {
|
||||
GBAMemoryDeinit(gba);
|
||||
mLOG(GBA_MEM, FATAL, "Could not map memory");
|
||||
}
|
||||
|
||||
GBADMAReset(gba);
|
||||
memset(&gba->memory.matrix, 0, sizeof(gba->memory.matrix));
|
||||
}
|
||||
|
||||
static void _analyzeForIdleLoop(struct GBA* gba, struct ARMCore* cpu, uint32_t address) {
|
||||
|
||||
@@ -602,14 +602,23 @@ void GBASavedataRTCWrite(struct GBASavedata* savedata) {
|
||||
size_t size = GBASavedataSize(savedata);
|
||||
savedata->vf->seek(savedata->vf, size & ~0xFF, SEEK_SET);
|
||||
|
||||
int bank = 0;
|
||||
if ((savedata->vf->size(savedata->vf) & 0xFF) != sizeof(buffer)) {
|
||||
// Writing past the end of the file can invalidate the file mapping
|
||||
if (savedata->type == SAVEDATA_FLASH1M) {
|
||||
bank = savedata->currentBank == &savedata->data[0x10000];
|
||||
}
|
||||
savedata->vf->unmap(savedata->vf, savedata->data, size);
|
||||
savedata->data = NULL;
|
||||
}
|
||||
savedata->vf->write(savedata->vf, &buffer, sizeof(buffer));
|
||||
if (!savedata->data) {
|
||||
savedata->data = savedata->vf->map(savedata->vf, size, MAP_WRITE);
|
||||
if (savedata->type == SAVEDATA_FLASH1M) {
|
||||
savedata->currentBank = &savedata->data[bank << 16];
|
||||
} else if (savedata->type == SAVEDATA_FLASH512) {
|
||||
savedata->currentBank = savedata->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -127,10 +127,10 @@ bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver) {
|
||||
break;
|
||||
case SIO_NORMAL_8:
|
||||
case SIO_NORMAL_32:
|
||||
if (ATOMIC_ADD(node->p->attachedNormal, 1) > node->id + 1 && node->id < 3) {
|
||||
node->d.p->siocnt = GBASIONormalSetSi(node->d.p->siocnt, GBASIONormalGetIdleSo(node->p->players[node->id + 1]->d.p->siocnt));
|
||||
if (ATOMIC_ADD(node->p->attachedNormal, 1) > node->id + 1 && node->id > 0) {
|
||||
node->d.p->siocnt = GBASIONormalSetSi(node->d.p->siocnt, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt));
|
||||
} else {
|
||||
node->d.p->siocnt = GBASIONormalFillSi(node->d.p->siocnt);
|
||||
node->d.p->siocnt = GBASIONormalClearSi(node->d.p->siocnt);
|
||||
}
|
||||
node->d.writeRegister = GBASIOLockstepNodeNormalWriteRegister;
|
||||
break;
|
||||
@@ -514,20 +514,20 @@ static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* drive
|
||||
int attached;
|
||||
ATOMIC_LOAD(attached, node->p->attachedNormal);
|
||||
value &= 0xFF8B;
|
||||
if (node->id < 3 && attached > node->id + 1) {
|
||||
value = GBASIONormalSetSi(value, GBASIONormalGetIdleSo(node->p->players[node->id + 1]->d.p->siocnt));
|
||||
if (node->id > 0) {
|
||||
value = GBASIONormalSetSi(value, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt));
|
||||
} else {
|
||||
value = GBASIONormalFillSi(value);
|
||||
value = GBASIONormalClearSi(value);
|
||||
}
|
||||
|
||||
enum mLockstepPhase transferActive;
|
||||
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
|
||||
if (node->id > 0 && transferActive == TRANSFER_IDLE) {
|
||||
if (node->id < 3 && attached > node->id + 1 && transferActive == TRANSFER_IDLE) {
|
||||
int try;
|
||||
for (try = 0; try < 3; ++try) {
|
||||
GBASIONormal parentSiocnt;
|
||||
ATOMIC_LOAD(parentSiocnt, node->p->players[node->id - 1]->d.p->siocnt);
|
||||
if (ATOMIC_CMPXCHG(node->p->players[node->id - 1]->d.p->siocnt, parentSiocnt, GBASIONormalSetSi(parentSiocnt, GBASIONormalGetIdleSo(value)))) {
|
||||
GBASIONormal nextSiocnct;
|
||||
ATOMIC_LOAD(nextSiocnct, node->p->players[node->id + 1]->d.p->siocnt);
|
||||
if (ATOMIC_CMPXCHG(node->p->players[node->id + 1]->d.p->siocnt, nextSiocnct, GBASIONormalSetSi(nextSiocnct, GBASIONormalGetIdleSo(value)))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,8 +48,6 @@
|
||||
#endif
|
||||
|
||||
const char* const binaryName = "mGBA";
|
||||
const char* const projectName = "mGBA";
|
||||
const char* projectVersion;
|
||||
|
||||
@interface mGBAGameCore () <OEGBASystemResponderClient>
|
||||
{
|
||||
@@ -93,7 +91,6 @@ static struct mLogger logger = { .log = _log };
|
||||
outputBuffer = malloc(width * height * BYTES_PER_PIXEL);
|
||||
core->setVideoBuffer(core, outputBuffer, width);
|
||||
core->setAudioBufferSize(core, SAMPLES);
|
||||
|
||||
cheatSets = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
|
||||
@@ -111,8 +108,6 @@ static struct mLogger logger = { .log = _log };
|
||||
|
||||
- (BOOL)loadFileAtPath:(NSString *)path error:(NSError **)error
|
||||
{
|
||||
projectVersion = [self.owner.bundle.infoDictionary[@"CFBundleVersion"] UTF8String];
|
||||
|
||||
NSString *batterySavesDirectory = [self batterySavesDirectoryPath];
|
||||
[[NSFileManager defaultManager] createDirectoryAtURL:[NSURL fileURLWithPath:batterySavesDirectory]
|
||||
withIntermediateDirectories:YES
|
||||
@@ -132,6 +127,7 @@ static struct mLogger logger = { .log = _log };
|
||||
mCoreAutoloadSave(core);
|
||||
|
||||
core->reset(core);
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -183,8 +179,7 @@ static struct mLogger logger = { .log = _log };
|
||||
{
|
||||
OEIntSize bufferSize = [self bufferSize];
|
||||
|
||||
if (!hint)
|
||||
{
|
||||
if (!hint) {
|
||||
hint = outputBuffer;
|
||||
}
|
||||
|
||||
@@ -316,19 +311,8 @@ const int GBAMap[] = {
|
||||
cheatSet->copyProperties(cheatSet, *mCheatSetsGetPointer(&cheats->cheats, size - 1));
|
||||
}
|
||||
int codeType = GBA_CHEAT_AUTODETECT;
|
||||
// NOTE: This is deprecated and was only meant to test cheats with the UI using cheats-database.xml
|
||||
// Will be replaced with a sqlite database in the future.
|
||||
// if ([type isEqual:@"GameShark"]) {
|
||||
// codeType = GBA_CHEAT_GAMESHARK;
|
||||
// } else if ([type isEqual:@"Action Replay"]) {
|
||||
// codeType = GBA_CHEAT_PRO_ACTION_REPLAY;
|
||||
// }
|
||||
NSArray *codeSet = [code componentsSeparatedByString:@"+"];
|
||||
for (id c in codeSet) {
|
||||
// if ([c length] == 12)
|
||||
// codeType = GBA_CHEAT_CODEBREAKER;
|
||||
// if ([c length] == 16) // default to GS/AR v1/v2 code (can't determine GS/AR v1/v2 vs AR v3 because same length)
|
||||
// codeType = GBA_CHEAT_GAMESHARK;
|
||||
mCheatAddLine(cheatSet, [c UTF8String], codeType);
|
||||
}
|
||||
cheatSet->enabled = enabled;
|
||||
|
||||
@@ -133,7 +133,7 @@ bool _vdDeleteFile(struct VDir* vd, const char* path) {
|
||||
char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2));
|
||||
sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
|
||||
|
||||
bool ret = !unlink(combined);
|
||||
bool ret = !remove(combined);
|
||||
free(combined);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+57
-11
@@ -7,7 +7,9 @@
|
||||
|
||||
#ifdef USE_LZMA
|
||||
|
||||
#include <mgba-util/memory.h>
|
||||
#include <mgba-util/string.h>
|
||||
#include <mgba-util/table.h>
|
||||
|
||||
#include "third-party/lzma/7z.h"
|
||||
#include "third-party/lzma/7zAlloc.h"
|
||||
@@ -26,15 +28,19 @@ struct VDirEntry7z {
|
||||
char* utf8;
|
||||
};
|
||||
|
||||
struct VDir7zAlloc {
|
||||
ISzAlloc d;
|
||||
struct Table allocs;
|
||||
};
|
||||
|
||||
struct VDir7z {
|
||||
struct VDir d;
|
||||
struct VDirEntry7z dirent;
|
||||
|
||||
// What is all this garbage?
|
||||
CFileInStream archiveStream;
|
||||
CLookToRead2 lookStream;
|
||||
CSzArEx db;
|
||||
ISzAlloc allocImp;
|
||||
struct VDir7zAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
};
|
||||
|
||||
@@ -70,6 +76,43 @@ static bool _vd7zDeleteFile(struct VDir* vd, const char* path);
|
||||
static const char* _vde7zName(struct VDirEntry* vde);
|
||||
static enum VFSType _vde7zType(struct VDirEntry* vde);
|
||||
|
||||
static void* _vd7zAlloc(ISzAllocPtr p, size_t size) {
|
||||
struct VDir7zAlloc* alloc = (struct VDir7zAlloc*) p;
|
||||
void* address;
|
||||
if (size >= 0x10000) {
|
||||
address = anonymousMemoryMap(size);
|
||||
} else {
|
||||
address = malloc(size);
|
||||
}
|
||||
if (address) {
|
||||
TableInsert(&alloc->allocs, (uintptr_t) address >> 2, (void*) size);
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
static void _vd7zFree(ISzAllocPtr p, void* address) {
|
||||
struct VDir7zAlloc* alloc = (struct VDir7zAlloc*) p;
|
||||
size_t size = (size_t) TableLookup(&alloc->allocs, (uintptr_t) address >> 2);
|
||||
if (size) {
|
||||
if (size >= 0x10000) {
|
||||
mappedMemoryFree(address, size);
|
||||
} else {
|
||||
free(address);
|
||||
}
|
||||
TableRemove(&alloc->allocs, (uintptr_t) address >> 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void* _vd7zAllocTemp(ISzAllocPtr p, size_t size) {
|
||||
UNUSED(p);
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void _vd7zFreeTemp(ISzAllocPtr p, void* address) {
|
||||
UNUSED(p);
|
||||
free(address);
|
||||
}
|
||||
|
||||
struct VDir* VDirOpen7z(const char* path, int flags) {
|
||||
if (flags & O_WRONLY || flags & O_CREAT) {
|
||||
return 0;
|
||||
@@ -83,11 +126,12 @@ struct VDir* VDirOpen7z(const char* path, int flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
vd->allocImp.Alloc = SzAlloc;
|
||||
vd->allocImp.Free = SzFree;
|
||||
vd->allocImp.d.Alloc = _vd7zAlloc;
|
||||
vd->allocImp.d.Free = _vd7zFree;
|
||||
TableInit(&vd->allocImp.allocs, 0, NULL);
|
||||
|
||||
vd->allocTempImp.Alloc = SzAllocTemp;
|
||||
vd->allocTempImp.Free = SzFreeTemp;
|
||||
vd->allocTempImp.Alloc = _vd7zAllocTemp;
|
||||
vd->allocTempImp.Free = _vd7zFreeTemp;
|
||||
|
||||
FileInStream_CreateVTable(&vd->archiveStream);
|
||||
LookToRead2_CreateVTable(&vd->lookStream, False);
|
||||
@@ -101,11 +145,12 @@ struct VDir* VDirOpen7z(const char* path, int flags) {
|
||||
CrcGenerateTable();
|
||||
|
||||
SzArEx_Init(&vd->db);
|
||||
SRes res = SzArEx_Open(&vd->db, &vd->lookStream.vt, &vd->allocImp, &vd->allocTempImp);
|
||||
SRes res = SzArEx_Open(&vd->db, &vd->lookStream.vt, &vd->allocImp.d, &vd->allocTempImp);
|
||||
if (res != SZ_OK) {
|
||||
SzArEx_Free(&vd->db, &vd->allocImp);
|
||||
SzArEx_Free(&vd->db, &vd->allocImp.d);
|
||||
File_Close(&vd->archiveStream.file);
|
||||
free(vd->lookStream.buf);
|
||||
TableDeinit(&vd->allocImp.allocs);
|
||||
free(vd);
|
||||
return 0;
|
||||
}
|
||||
@@ -128,7 +173,7 @@ struct VDir* VDirOpen7z(const char* path, int flags) {
|
||||
|
||||
bool _vf7zClose(struct VFile* vf) {
|
||||
struct VFile7z* vf7z = (struct VFile7z*) vf;
|
||||
IAlloc_Free(&vf7z->vd->allocImp, vf7z->outBuffer);
|
||||
IAlloc_Free(&vf7z->vd->allocImp.d, vf7z->outBuffer);
|
||||
free(vf7z);
|
||||
return true;
|
||||
}
|
||||
@@ -215,12 +260,13 @@ ssize_t _vf7zSize(struct VFile* vf) {
|
||||
|
||||
bool _vd7zClose(struct VDir* vd) {
|
||||
struct VDir7z* vd7z = (struct VDir7z*) vd;
|
||||
SzArEx_Free(&vd7z->db, &vd7z->allocImp);
|
||||
SzArEx_Free(&vd7z->db, &vd7z->allocImp.d);
|
||||
File_Close(&vd7z->archiveStream.file);
|
||||
|
||||
free(vd7z->lookStream.buf);
|
||||
free(vd7z->dirent.utf8);
|
||||
vd7z->dirent.utf8 = 0;
|
||||
TableDeinit(&vd7z->allocImp.allocs);
|
||||
|
||||
free(vd7z);
|
||||
return true;
|
||||
@@ -292,7 +338,7 @@ struct VFile* _vd7zOpenFile(struct VDir* vd, const char* path, int mode) {
|
||||
SRes res = SzArEx_Extract(&vd7z->db, &vd7z->lookStream.vt, i, &blockIndex,
|
||||
&vf->outBuffer, &outBufferSize,
|
||||
&vf->bufferOffset, &vf->size,
|
||||
&vd7z->allocImp, &vd7z->allocTempImp);
|
||||
&vd7z->allocImp.d, &vd7z->allocTempImp);
|
||||
|
||||
if (res != SZ_OK) {
|
||||
free(vf);
|
||||
|
||||
Reference in New Issue
Block a user