Update to mGBA 0.13.1

This commit is contained in:
C.W. Betts
2024-04-05 02:58:13 -06:00
parent 8e956c93d5
commit 48ede563a1
28 changed files with 222 additions and 134 deletions
+3 -3
View File
@@ -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
+1
View File
@@ -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;
}
+1
View File
@@ -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);
+1 -1
View File
@@ -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)
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
-3
View File
@@ -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;
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
+9
View File
@@ -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
View File
@@ -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;
}
}
+2 -18
View File
@@ -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;
+1 -1
View File
@@ -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
View File
@@ -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);