From 825c70bbf7ec2c6a26f542b0bd1f3a897259a62f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Aug 2018 23:13:26 -0700 Subject: [PATCH 01/10] Wii: Move audio handling to callbacks (fixes #803) --- CHANGES | 1 + src/platform/wii/main.c | 46 ++++++++++++++++++++++++++--------------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/CHANGES b/CHANGES index 7ba90f525..0287f3d6b 100644 --- a/CHANGES +++ b/CHANGES @@ -74,6 +74,7 @@ Misc: - FFmpeg: Support lossless h.264 encoding - Feature: Added loading savestates from command line - Qt: Allow pausing game at load (fixes mgba.io/i/1129) + - Wii: Move audio handling to callbacks (fixes mgba.io/i/803) 0.6.3: (2017-04-14) Bugfixes: diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index ef0c3f84c..9085edbd2 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -67,6 +67,7 @@ static enum VideoMode { static void _retraceCallback(u32 count); +static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right); static void _audioDMA(void); static void _setRumble(struct mRumble* rumble, int enable); static void _sampleRotation(struct mRotationSource* source); @@ -93,6 +94,7 @@ static s8 WPAD_StickX(u8 chan, u8 right); static s8 WPAD_StickY(u8 chan, u8 right); static void* outputBuffer; +static struct mAVStream stream; static struct mRumble rumble; static struct mRotationSource rotation; static GXRModeObj* vmode; @@ -222,7 +224,7 @@ static void reconfigureScreen(struct mGUIRunner* runner) { runner->params.width = vmode->fbWidth * guiScale * wAdjust; runner->params.height = vmode->efbHeight * guiScale * hAdjust; if (runner->core) { - double ratio = GBAAudioCalculateRatio(1,audioSampleRate, 1); + double ratio = GBAAudioCalculateRatio(1, audioSampleRate, 1); blip_set_rates(runner->core->getAudioChannel(runner->core, 0), runner->core->frequency(runner->core), 48000 * ratio); blip_set_rates(runner->core->getAudioChannel(runner->core, 1), runner->core->frequency(runner->core), 48000 * ratio); @@ -317,6 +319,11 @@ int main(int argc, char* argv[]) { rotation.readTiltY = _readTiltY; rotation.readGyroZ = _readGyroZ; + stream.videoDimensionsChanged = NULL; + stream.postVideoFrame = NULL; + stream.postAudioFrame = NULL; + stream.postAudioBuffer = _postAudioBuffer; + struct mGUIRunner runner = { .params = { 720, 480, @@ -554,6 +561,25 @@ static void _audioDMA(void) { audioBufferSize = 0; } +static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) { + UNUSED(stream); + int available = blip_samples_avail(left); + if (available + audioBufferSize > SAMPLES) { + available = SAMPLES - audioBufferSize; + } + available &= ~((32 / sizeof(struct GBAStereoSample)) - 1); // Force align to 32 bytes + if (available > 0) { + // These appear to be reversed for AUDIO_InitDMA + blip_read_samples(left, &audioBuffer[currentAudioBuffer][audioBufferSize].right, available, true); + blip_read_samples(right, &audioBuffer[currentAudioBuffer][audioBufferSize].left, available, true); + audioBufferSize += available; + } + if (audioBufferSize == SAMPLES && !AUDIO_GetDMAEnableFlag()) { + _audioDMA(); + AUDIO_StartDMA(); + } +} + static void _drawStart(void) { VIDEO_SetBlack(false); @@ -665,6 +691,7 @@ void _guiPrepare(void) { void _setup(struct mGUIRunner* runner) { runner->core->setPeripheral(runner->core, mPERIPH_ROTATION, &rotation); runner->core->setPeripheral(runner->core, mPERIPH_RUMBLE, &rumble); + runner->core->setAVStream(runner->core, &stream); _mapKey(&runner->core->inputMap, GCN1_INPUT, PAD_BUTTON_A, GBA_KEY_A); _mapKey(&runner->core->inputMap, GCN1_INPUT, PAD_BUTTON_B, GBA_KEY_B); @@ -783,22 +810,7 @@ void _unpaused(struct mGUIRunner* runner) { } void _drawFrame(struct mGUIRunner* runner, bool faded) { - int available = blip_samples_avail(runner->core->getAudioChannel(runner->core, 0)); - if (available + audioBufferSize > SAMPLES) { - available = SAMPLES - audioBufferSize; - } - available &= ~((32 / sizeof(struct GBAStereoSample)) - 1); // Force align to 32 bytes - if (available > 0) { - // These appear to be reversed for AUDIO_InitDMA - blip_read_samples(runner->core->getAudioChannel(runner->core, 0), &audioBuffer[currentAudioBuffer][audioBufferSize].right, available, true); - blip_read_samples(runner->core->getAudioChannel(runner->core, 1), &audioBuffer[currentAudioBuffer][audioBufferSize].left, available, true); - audioBufferSize += available; - } - if (audioBufferSize == SAMPLES && !AUDIO_GetDMAEnableFlag()) { - _audioDMA(); - AUDIO_StartDMA(); - } - + UNUSED(runner); uint32_t color = 0xFFFFFF3F; if (!faded) { color |= 0xC0; From 35a56e9507426870654ba367c969e047c5242d2f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 3 Aug 2018 18:39:26 -0700 Subject: [PATCH 02/10] GB MBC: Fix MMM01 detection heuristic --- src/gb/mbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gb/mbc.c b/src/gb/mbc.c index 05160d876..2da6a264e 100644 --- a/src/gb/mbc.c +++ b/src/gb/mbc.c @@ -141,7 +141,7 @@ void GBMBCInit(struct GB* gb) { if (gb->memory.rom) { if (gb->memory.romSize >= 0x8000) { const struct GBCartridge* cartFooter = (const struct GBCartridge*) &gb->memory.rom[gb->memory.romSize - 0x7F00]; - if (doCrc32(cartFooter->logo, sizeof(cartFooter->logo)) == GB_LOGO_HASH) { + if (doCrc32(cartFooter->logo, sizeof(cartFooter->logo)) == GB_LOGO_HASH && cartFooter->type >= 0x0B && cartFooter->type <= 0x0D) { cart = cartFooter; } } From 6c5d30e2507fd45df39fa76eb63b6af4e84de3f0 Mon Sep 17 00:00:00 2001 From: JaceCearK1 Date: Fri, 3 Aug 2018 21:13:03 +0200 Subject: [PATCH 03/10] Fix a typo. --- src/platform/qt/ts/mgba-de.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/ts/mgba-de.ts b/src/platform/qt/ts/mgba-de.ts index 4a21bb1a1..aee09472e 100644 --- a/src/platform/qt/ts/mgba-de.ts +++ b/src/platform/qt/ts/mgba-de.ts @@ -3781,7 +3781,7 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. Open debugger console... - Debugger-Konsole äffnen... + Debugger-Konsole öffnen... From 8f7a0e6858b47a713b4b8776b5004cfa0a046a40 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 4 Aug 2018 10:16:31 -0700 Subject: [PATCH 04/10] GBA Video: Make layer disabling work consistently --- CHANGES | 1 + src/gba/renderers/video-software.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 0287f3d6b..369634b11 100644 --- a/CHANGES +++ b/CHANGES @@ -44,6 +44,7 @@ Bugfixes: - GB Video: Fix SCX timing - GBA Video: Improve sprite cycle counting (fixes mgba.io/i/1126) - GB, GBA Savedata: Fix savestate loading overwriting saves on reset + - GBA Video: Make layer disabling work consistently Misc: - GBA Timer: Use global cycles for timers - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index c0387ccb4..2b80ac998 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -722,7 +722,7 @@ static void GBAVideoSoftwareRendererPutPixels(struct GBAVideoRenderer* renderer, } static void _enableBg(struct GBAVideoSoftwareRenderer* renderer, int bg, bool active) { - if (renderer->d.disableBG[bg] || !active) { + if (!active) { renderer->bg[bg].enabled = 0; } else if (!renderer->bg[bg].enabled && active) { if (renderer->nextY == 0) { @@ -799,6 +799,7 @@ static void GBAVideoSoftwareRendererWriteBLDCNT(struct GBAVideoSoftwareRenderer* } #define TEST_LAYER_ENABLED(X) \ + !renderer->d.disableBG[X] && \ (renderer->bg[X].enabled == 4 && \ (GBAWindowControlIsBg ## X ## Enable(renderer->currentWindow.packed) || \ (GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt) && GBAWindowControlIsBg ## X ## Enable (renderer->objwin.packed))) && \ From d18177888339cfc7892b186741e4de603d05b7f4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Aug 2018 20:59:23 -0700 Subject: [PATCH 05/10] Wii: Simplify analog stick reading --- src/platform/wii/main.c | 60 +++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index 9085edbd2..d62fe7e77 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -998,77 +998,65 @@ int32_t _readGyroZ(struct mRotationSource* source) { } static s8 WPAD_StickX(u8 chan, u8 right) { - float mag = 0.0; - float ang = 0.0; - WPADData *data = WPAD_Data(chan); + struct expansion_t exp; + WPAD_Expansion(chan, &exp); + struct joystick_t* js = NULL; - switch (data->exp.type) { + switch (exp.type) { case WPAD_EXP_NUNCHUK: case WPAD_EXP_GUITARHERO3: if (right == 0) { - mag = data->exp.nunchuk.js.mag; - ang = data->exp.nunchuk.js.ang; + js = &exp.nunchuk.js; } break; case WPAD_EXP_CLASSIC: if (right == 0) { - mag = data->exp.classic.ljs.mag; - ang = data->exp.classic.ljs.ang; + js = &exp.classic.ljs; } else { - mag = data->exp.classic.rjs.mag; - ang = data->exp.classic.rjs.ang; + js = &exp.classic.rjs; } break; default: break; } - /* calculate X value (angle need to be converted into radian) */ - if (mag > 1.0) { - mag = 1.0; - } else if (mag < -1.0) { - mag = -1.0; + if (!js) { + return 0; } - double val = mag * sinf(M_PI * ang / 180.0f); - - return (s8)(val * 128.0f); + int centered = (int) js->pos.x - (int) js->center.x; + int range = js->max.x - js->min.x; + return (centered * 0xFF) / range; } static s8 WPAD_StickY(u8 chan, u8 right) { - float mag = 0.0; - float ang = 0.0; - WPADData *data = WPAD_Data(chan); + struct expansion_t exp; + WPAD_Expansion(chan, &exp); + struct joystick_t* js = NULL; - switch (data->exp.type) { + switch (exp.type) { case WPAD_EXP_NUNCHUK: case WPAD_EXP_GUITARHERO3: if (right == 0) { - mag = data->exp.nunchuk.js.mag; - ang = data->exp.nunchuk.js.ang; + js = &exp.nunchuk.js; } break; case WPAD_EXP_CLASSIC: if (right == 0) { - mag = data->exp.classic.ljs.mag; - ang = data->exp.classic.ljs.ang; + js = &exp.classic.ljs; } else { - mag = data->exp.classic.rjs.mag; - ang = data->exp.classic.rjs.ang; + js = &exp.classic.rjs; } break; default: break; } - /* calculate X value (angle need to be converted into radian) */ - if (mag > 1.0) { - mag = 1.0; - } else if (mag < -1.0) { - mag = -1.0; + if (!js) { + return 0; } - double val = mag * cosf(M_PI * ang / 180.0f); - - return (s8)(val * 128.0f); + int centered = (int) js->pos.y - (int) js->center.y; + int range = js->max.y - js->min.y; + return (centered * 0xFF) / range; } void _retraceCallback(u32 count) { From 54cb257b3ffa537964b8d6812bbcc965c291ac1c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Aug 2018 21:01:21 -0700 Subject: [PATCH 06/10] Wii: Increase analog stick deadzone --- src/platform/wii/main.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index d62fe7e77..185771dd6 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -35,6 +35,8 @@ #define TEX_W 256 #define TEX_H 224 +#define ANALOG_DEADZONE 0x30 + static void _mapKey(struct mInputMap* map, uint32_t binding, int nativeKey, enum GBAKey key) { mInputBindKey(map, binding, __builtin_ctz(nativeKey), key); } @@ -637,16 +639,16 @@ static uint32_t _pollInput(const struct mInputMap* map) { int y = PAD_StickY(0); int w_x = WPAD_StickX(0, 0); int w_y = WPAD_StickY(0, 0); - if (x < -0x20 || w_x < -0x20) { + if (x < -ANALOG_DEADZONE || w_x < -ANALOG_DEADZONE) { keys |= 1 << GUI_INPUT_LEFT; } - if (x > 0x20 || w_x > 0x20) { + if (x > ANALOG_DEADZONE || w_x > ANALOG_DEADZONE) { keys |= 1 << GUI_INPUT_RIGHT; } - if (y < -0x20 || w_y <- 0x20) { + if (y < -ANALOG_DEADZONE || w_y < -ANALOG_DEADZONE) { keys |= 1 << GUI_INPUT_DOWN; } - if (y > 0x20 || w_y > 0x20) { + if (y > ANALOG_DEADZONE || w_y > ANALOG_DEADZONE) { keys |= 1 << GUI_INPUT_UP; } return keys; @@ -727,10 +729,10 @@ void _setup(struct mGUIRunner* runner) { _mapKey(&runner->core->inputMap, CLASSIC_INPUT, WPAD_CLASSIC_BUTTON_FULL_L, GBA_KEY_L); _mapKey(&runner->core->inputMap, CLASSIC_INPUT, WPAD_CLASSIC_BUTTON_FULL_R, GBA_KEY_R); - struct mInputAxis desc = { GBA_KEY_RIGHT, GBA_KEY_LEFT, 0x20, -0x20 }; + struct mInputAxis desc = { GBA_KEY_RIGHT, GBA_KEY_LEFT, ANALOG_DEADZONE, -ANALOG_DEADZONE }; mInputBindAxis(&runner->core->inputMap, GCN1_INPUT, 0, &desc); mInputBindAxis(&runner->core->inputMap, CLASSIC_INPUT, 0, &desc); - desc = (struct mInputAxis) { GBA_KEY_UP, GBA_KEY_DOWN, 0x20, -0x20 }; + desc = (struct mInputAxis) { GBA_KEY_UP, GBA_KEY_DOWN, ANALOG_DEADZONE, -ANALOG_DEADZONE }; mInputBindAxis(&runner->core->inputMap, GCN1_INPUT, 1, &desc); mInputBindAxis(&runner->core->inputMap, CLASSIC_INPUT, 1, &desc); From 1fb4d2be4dacbf68e1506f78fd3eb77c3aae40e4 Mon Sep 17 00:00:00 2001 From: Thomas Winwood Date: Mon, 6 Aug 2018 00:24:15 +0100 Subject: [PATCH 07/10] GBA: Zero DebugString buffer when handling messages --- src/gba/gba.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gba/gba.c b/src/gba/gba.c index 45025f228..4c96d7129 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -525,6 +525,7 @@ void GBADebug(struct GBA* gba, uint16_t flags) { level &= 0x1F; char oolBuf[0x101]; strncpy(oolBuf, gba->debugString, sizeof(gba->debugString)); + memset(gba->debugString, 0, sizeof(gba->debugString)); oolBuf[0x100] = '\0'; mLog(_mLOG_CAT_GBA_DEBUG(), level, "%s", oolBuf); } From 25cda2d7b2f1777ec4d7a004ee78079080958898 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 9 Aug 2018 19:11:26 -0700 Subject: [PATCH 08/10] GB: Fix IRQ disabling on the same T-cycle as an assert --- CHANGES | 1 + .../gb/mooneye-gb/acceptance/rapid_di_ei/manifest.yml | 1 - src/gb/gb.c | 11 +++++++---- src/lr35902/lr35902.c | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) delete mode 100644 cinema/gb/mooneye-gb/acceptance/rapid_di_ei/manifest.yml diff --git a/CHANGES b/CHANGES index 369634b11..3181ae785 100644 --- a/CHANGES +++ b/CHANGES @@ -45,6 +45,7 @@ Bugfixes: - GBA Video: Improve sprite cycle counting (fixes mgba.io/i/1126) - GB, GBA Savedata: Fix savestate loading overwriting saves on reset - GBA Video: Make layer disabling work consistently + - GB: Fix IRQ disabling on the same T-cycle as an assert Misc: - GBA Timer: Use global cycles for timers - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) diff --git a/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/manifest.yml b/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/manifest.yml deleted file mode 100644 index a697ada66..000000000 --- a/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/manifest.yml +++ /dev/null @@ -1 +0,0 @@ -fail: true diff --git a/src/gb/gb.c b/src/gb/gb.c index d5f809fb2..14404fddf 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -625,7 +625,11 @@ void GBUpdateIRQs(struct GB* gb) { } gb->cpu->halted = false; - if (!gb->memory.ime || gb->cpu->irqPending) { + if (!gb->memory.ime) { + gb->cpu->irqPending = false; + return; + } + if (gb->cpu->irqPending) { return; } LR35902RaiseIRQ(gb->cpu); @@ -661,12 +665,11 @@ void GBProcessEvents(struct LR35902Core* cpu) { void GBSetInterrupts(struct LR35902Core* cpu, bool enable) { struct GB* gb = (struct GB*) cpu->master; + mTimingDeschedule(&gb->timing, &gb->eiPending); if (!enable) { - gb->memory.ime = enable; - mTimingDeschedule(&gb->timing, &gb->eiPending); + gb->memory.ime = false; GBUpdateIRQs(gb); } else { - mTimingDeschedule(&gb->timing, &gb->eiPending); mTimingSchedule(&gb->timing, &gb->eiPending, 4); } } diff --git a/src/lr35902/lr35902.c b/src/lr35902/lr35902.c index 23878c310..4ae2a1e07 100644 --- a/src/lr35902/lr35902.c +++ b/src/lr35902/lr35902.c @@ -137,7 +137,7 @@ static void _LR35902Step(struct LR35902Core* cpu) { } void LR35902Tick(struct LR35902Core* cpu) { - if (cpu->cycles >= cpu->nextEvent) { + while (cpu->cycles >= cpu->nextEvent) { cpu->irqh.processEvents(cpu); } _LR35902Step(cpu); From c5ff781ed6cdf5d36b7e59748c1506709c5e2e5d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 11 Aug 2018 12:46:46 -0700 Subject: [PATCH 09/10] GBA Video: Remove dead code --- src/gba/renderers/software-obj.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/gba/renderers/software-obj.c b/src/gba/renderers/software-obj.c index ea0eca245..615e13ce2 100644 --- a/src/gba/renderers/software-obj.c +++ b/src/gba/renderers/software-obj.c @@ -9,9 +9,6 @@ SPRITE_YBASE_ ## DEPTH(inY); \ unsigned tileData; \ for (; outX < condition; ++outX, inX += xOffset) { \ - if (!(renderer->row[outX] & FLAG_UNWRITTEN)) { \ - continue; \ - } \ renderer->spriteCyclesRemaining -= 1; \ SPRITE_XBASE_ ## DEPTH(inX); \ SPRITE_DRAW_PIXEL_ ## DEPTH ## _ ## TYPE(inX); \ From 9ed127d5244406b1c01dfe374c5ba11b3ffb9074 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 19 Aug 2018 09:53:21 -0700 Subject: [PATCH 10/10] SDL: Fix input when caps/num lock are on (fixes #774) --- src/platform/sdl/sdl-events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c index 62007faa1..97f58f229 100644 --- a/src/platform/sdl/sdl-events.c +++ b/src/platform/sdl/sdl-events.c @@ -407,7 +407,7 @@ static void _pauseAfterFrame(struct mCoreThread* context) { static void _mSDLHandleKeypress(struct mCoreThread* context, struct mSDLPlayer* sdlContext, const struct SDL_KeyboardEvent* event) { int key = -1; - if (!event->keysym.mod) { + if (!(event->keysym.mod & ~(KMOD_NUM | KMOD_CAPS))) { key = mInputMapKey(sdlContext->bindings, SDL_BINDING_KEY, event->keysym.sym); } if (key != -1) {