all repos — mgba @ 33a4c45f3ff72c83a3f68b5f4e5730764018a743

mGBA Game Boy Advance Emulator

GBA: Add GBACore
Jeffrey Pfau jeffrey@endrift.com
Thu, 04 Feb 2016 00:49:45 -0800
commit

33a4c45f3ff72c83a3f68b5f4e5730764018a743

parent

28268a601bcd1fcc71389c1b8a278dd69bcefd9f

M src/core/core.hsrc/core/core.h

@@ -23,6 +23,7 @@ typedef uint32_t color_t;

#define BYTES_PER_PIXEL 4 #endif +struct blip_t; struct mCoreSync; struct mCore { void* cpu;

@@ -39,6 +40,8 @@ void (*setSync)(struct mCore*, struct mCoreSync*);

void (*desiredVideoDimensions)(struct mCore*, unsigned* width, unsigned* height); void (*setVideoBuffer)(struct mCore*, color_t* buffer, size_t stride); + + struct blip_t* (*getAudioChannel)(struct mCore*, int ch); bool (*isROM)(struct VFile* vf); bool (*loadROM)(struct mCore*, struct VFile* vf);
M src/gb/core.csrc/gb/core.c

@@ -72,6 +72,18 @@ gbcore->renderer.outputBuffer = buffer;

gbcore->renderer.outputBufferStride = stride; } +static struct blip_t* _GBCoreGetAudioChannel(struct mCore* core, int ch) { + struct GB* gb = core->board; + switch (ch) { + case 0: + return gb->audio.left; + case 1: + return gb->audio.right; + default: + return NULL; + } +} + static bool _GBCoreLoadROM(struct mCore* core, struct VFile* vf) { return GBLoadROM(core->board, vf); }

@@ -158,6 +170,7 @@ core->deinit = _GBCoreDeinit;

core->setSync = _GBCoreSetSync; core->desiredVideoDimensions = _GBCoreDesiredVideoDimensions; core->setVideoBuffer = _GBCoreSetVideoBuffer; + core->getAudioChannel = _GBCoreGetAudioChannel; core->isROM = GBIsROM; core->loadROM = _GBCoreLoadROM; core->loadSave = _GBCoreLoadSave;
A src/gba/core.c

@@ -0,0 +1,192 @@

+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "core.h" + +#include "core/core.h" +#include "core/log.h" +#include "gba/gba.h" +#include "gba/renderers/video-software.h" +#include "util/memory.h" + +struct GBACore { + struct mCore d; + struct GBAVideoSoftwareRenderer renderer; + int keys; +}; + +static bool _GBACoreInit(struct mCore* core) { + struct GBACore* gbacore = (struct GBACore*) core; + + struct ARMCore* cpu = anonymousMemoryMap(sizeof(struct ARMCore)); + struct GBA* gba = anonymousMemoryMap(sizeof(struct GBA)); + if (!cpu || !gba) { + free(cpu); + free(gba); + return false; + } + core->cpu = cpu; + core->board = gba; + + GBACreate(gba); + // TODO: Restore debugger and cheats + ARMSetComponents(cpu, &gba->d, 0, 0); + ARMInit(cpu); + + GBAVideoSoftwareRendererCreate(&gbacore->renderer); + GBAVideoAssociateRenderer(&gba->video, &gbacore->renderer.d); + + gba->keySource = &gbacore->keys; + +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 + mDirectorySetInit(&core->dirs); +#endif + + return true; +} + +static void _GBACoreDeinit(struct mCore* core) { + ARMDeinit(core->cpu); + GBADestroy(core->board); + mappedMemoryFree(core->cpu, sizeof(struct ARMCore)); + mappedMemoryFree(core->board, sizeof(struct GBA)); +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 + mDirectorySetDeinit(&core->dirs); +#endif +} + +static void _GBACoreSetSync(struct mCore* core, struct mCoreSync* sync) { + struct GBA* gba = core->board; + gba->sync = sync; +} + +static void _GBACoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) { + UNUSED(core); + *width = VIDEO_HORIZONTAL_PIXELS; + *height = VIDEO_VERTICAL_PIXELS; +} + +static void _GBACoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) { + struct GBACore* gbacore = (struct GBACore*) core; + gbacore->renderer.outputBuffer = buffer; + gbacore->renderer.outputBufferStride = stride; +} + +static struct blip_t* _GBACoreGetAudioChannel(struct mCore* core, int ch) { + struct GBA* gba = core->board; + switch (ch) { + case 0: + return gba->audio.psg.left; + case 1: + return gba->audio.psg.right; + default: + return NULL; + } +} + +static bool _GBACoreLoadROM(struct mCore* core, struct VFile* vf) { + return GBALoadROM2(core->board, vf); +} + +static bool _GBACoreLoadSave(struct mCore* core, struct VFile* vf) { + return GBALoadSave(core->board, vf); +} + +static bool _GBACoreLoadPatch(struct mCore* core, struct VFile* vf) { + // TODO + UNUSED(core); + UNUSED(vf); + mLOG(GBA, STUB, "Patches are not yet supported"); + return false; +} + +static void _GBACoreUnloadROM(struct mCore* core) { + return GBAUnloadROM(core->board); +} + +static void _GBACoreReset(struct mCore* core) { + ARMReset(core->cpu); +} + +static void _GBACoreRunFrame(struct mCore* core) { + struct GBA* gba = core->board; + int32_t frameCounter = gba->video.frameCounter; + while (gba->video.frameCounter == frameCounter) { + ARMRunLoop(core->cpu); + } +} + +static void _GBACoreRunLoop(struct mCore* core) { + ARMRunLoop(core->cpu); +} + +static void _GBACoreStep(struct mCore* core) { + ARMRun(core->cpu); +} + +static void _GBACoreSetKeys(struct mCore* core, uint32_t keys) { + struct GBACore* gbacore = (struct GBACore*) core; + gbacore->keys = keys; +} + +static void _GBACoreAddKeys(struct mCore* core, uint32_t keys) { + struct GBACore* gbacore = (struct GBACore*) core; + gbacore->keys |= keys; +} + +static void _GBACoreClearKeys(struct mCore* core, uint32_t keys) { + struct GBACore* gbacore = (struct GBACore*) core; + gbacore->keys &= ~keys; +} + +static int32_t _GBACoreFrameCounter(struct mCore* core) { + struct GBA* gba = core->board; + return gba->video.frameCounter; +} + +static int32_t _GBACoreFrameCycles(struct mCore* core) { + UNUSED(core); + return VIDEO_TOTAL_LENGTH; +} + +static int32_t _GBACoreFrequency(struct mCore* core) { + UNUSED(core); + return GBA_ARM7TDMI_FREQUENCY; +} + +static void _GBACoreSetRTC(struct mCore* core, struct mRTCSource* rtc) { + struct GBA* gba = core->board; + gba->rtcSource = rtc; +} + +struct mCore* GBACoreCreate(void) { + struct GBACore* gbacore = malloc(sizeof(*gbacore)); + struct mCore* core = &gbacore->d; + core->cpu = 0; + core->board = 0; + core->init = _GBACoreInit; + core->deinit = _GBACoreDeinit; + core->setSync = _GBACoreSetSync; + core->desiredVideoDimensions = _GBACoreDesiredVideoDimensions; + core->setVideoBuffer = _GBACoreSetVideoBuffer; + core->getAudioChannel = _GBACoreGetAudioChannel; + core->isROM = GBAIsROM; + core->loadROM = _GBACoreLoadROM; + core->loadSave = _GBACoreLoadSave; + core->loadPatch = _GBACoreLoadPatch; + core->unloadROM = _GBACoreUnloadROM; + core->reset = _GBACoreReset; + core->runFrame = _GBACoreRunFrame; + core->runLoop = _GBACoreRunLoop; + core->step = _GBACoreStep; + core->setKeys = _GBACoreSetKeys; + core->addKeys = _GBACoreAddKeys; + core->clearKeys = _GBACoreClearKeys; + core->frameCounter = _GBACoreFrameCounter; + core->frameCycles = _GBACoreFrameCycles; + core->frequency = _GBACoreFrequency; + core->setRTC = _GBACoreSetRTC; + return core; +}
A src/gba/core.h

@@ -0,0 +1,12 @@

+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef GBA_CORE_H +#define GBA_CORE_H + +struct mCore; +struct mCore* GBACoreCreate(void); + +#endif
M src/gba/gba.csrc/gba/gba.c

@@ -22,6 +22,8 @@ #include "util/math.h"

#include "util/patch.h" #include "util/vfs.h" +mLOG_DEFINE_CATEGORY(GBA, "GBA"); + const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000; const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;

@@ -443,7 +445,7 @@ gba->romCrc32 = doCrc32(gba->pristineRom, gba->pristineRomSize);

return true; } -bool GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char* fname) { +bool GBALoadROM2(struct GBA* gba, struct VFile* vf) { GBAUnloadROM(gba); gba->romVf = vf; gba->pristineRomSize = vf->size(vf);

@@ -466,14 +468,26 @@ return false;

} gba->yankedRomSize = 0; gba->memory.rom = gba->pristineRom; - gba->activeFile = fname; gba->memory.romSize = gba->pristineRomSize; gba->memory.romMask = toPow2(gba->memory.romSize) - 1; gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize); - GBASavedataInit(&gba->memory.savedata, sav); GBAHardwareInit(&gba->memory.hw, &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]); + // TODO: error check return true; - // TODO: error check +} + +bool GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char* fname) { + if (!GBALoadROM2(gba, vf)) { + return false; + } + gba->activeFile = fname; + GBALoadSave(gba, sav); + return true; +} + +bool GBALoadSave(struct GBA* gba, struct VFile* sav) { + GBASavedataInit(&gba->memory.savedata, sav); + return true; } void GBAYankROM(struct GBA* gba) {
M src/gba/gba.hsrc/gba/gba.h

@@ -8,7 +8,8 @@ #define GBA_H

#include "util/common.h" -#include "arm.h" +#include "arm/arm.h" +#include "core/log.h" #include "debugger/debugger.h" #include "gba/interface.h"

@@ -58,6 +59,8 @@ struct GBA;

struct GBAThread; struct Patch; struct VFile; + +mLOG_DECLARE_CATEGORY(GBA); DECL_BITFIELD(GBATimerFlags, uint32_t); DECL_BITS(GBATimerFlags, PrescaleBits, 0, 4);

@@ -171,6 +174,8 @@ uint32_t* opcode);

void GBAClearBreakpoint(struct GBA* gba, uint32_t address, enum ExecutionMode mode, uint32_t opcode); bool GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char* fname); +bool GBALoadROM2(struct GBA* gba, struct VFile* vf); +bool GBALoadSave(struct GBA* gba, struct VFile* sav); void GBAYankROM(struct GBA* gba); void GBAUnloadROM(struct GBA* gba); void GBALoadBIOS(struct GBA* gba, struct VFile* vf);
M src/platform/qt/AudioProcessorSDL.cppsrc/platform/qt/AudioProcessorSDL.cpp

@@ -20,7 +20,7 @@ {

} AudioProcessorSDL::~AudioProcessorSDL() { - GBSDLDeinitAudio(&m_audio); + mSDLDeinitAudio(&m_audio); } bool AudioProcessorSDL::start() {

@@ -30,26 +30,26 @@ return false;

} if (m_audio.thread) { - GBSDLResumeAudio(&m_audio); + mSDLResumeAudio(&m_audio); return true; } else { if (!m_audio.samples) { m_audio.samples = input()->audioBuffers; } - return GBSDLInitAudio(&m_audio, input()); + return mSDLInitAudio(&m_audio, input()); } } void AudioProcessorSDL::pause() { - GBSDLPauseAudio(&m_audio); + mSDLPauseAudio(&m_audio); } void AudioProcessorSDL::setBufferSamples(int samples) { AudioProcessor::setBufferSamples(samples); m_audio.samples = samples; if (m_audio.thread) { - GBSDLDeinitAudio(&m_audio); - GBSDLInitAudio(&m_audio, input()); + mSDLDeinitAudio(&m_audio); + mSDLInitAudio(&m_audio, input()); } }

@@ -59,8 +59,8 @@

void AudioProcessorSDL::requestSampleRate(unsigned rate) { m_audio.sampleRate = rate; if (m_audio.thread) { - GBSDLDeinitAudio(&m_audio); - GBSDLInitAudio(&m_audio, input()); + mSDLDeinitAudio(&m_audio); + mSDLInitAudio(&m_audio, input()); } }
M src/platform/qt/AudioProcessorSDL.hsrc/platform/qt/AudioProcessorSDL.h

@@ -34,7 +34,7 @@

virtual void requestSampleRate(unsigned) override; private: - GBSDLAudio m_audio; + mSDLAudio m_audio; }; }
M src/platform/sdl/CMakeLists.txtsrc/platform/sdl/CMakeLists.txt

@@ -70,7 +70,7 @@

if(BUILD_PANDORA) list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/pandora-sdl.c) else() - list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/sw-sdl.c) + #list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/sw-sdl.c) if(BUILD_GL) list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-sdl.c) list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/opengl/gl.c ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-common.c)
M src/platform/sdl/gl-sdl.csrc/platform/sdl/gl-sdl.c

@@ -8,13 +8,7 @@

#include "gl-common.h" #include "core/core.h" -#ifdef M_CORE_GBA -#include "gba/supervisor/thread.h" -#endif -#ifdef M_CORE_GB -#include "gb/core.h" -#include "gb/gb.h" -#endif +#include "core/thread.h" #include "platform/opengl/gl.h" #define GB_GBA_CENTER ((VIDEO_HORIZONTAL_PIXELS - GB_VIDEO_HORIZONTAL_PIXELS + VIDEO_HORIZONTAL_PIXELS * (VIDEO_VERTICAL_PIXELS - GB_VIDEO_VERTICAL_PIXELS)) / 2)

@@ -27,28 +21,32 @@ v->clear(v);

} #ifdef M_CORE_GBA +#include "gba/gba.h" + static bool mSDLGLInitGBA(struct mSDLRenderer* renderer); -static void mSDLGLRunloopGBA(struct mSDLRenderer* renderer, void* user); -static void mSDLGLDeinitGBA(struct mSDLRenderer* renderer); #endif #ifdef M_CORE_GB +#include "gb/gb.h" + static bool mSDLGLInitGB(struct mSDLRenderer* renderer); -static void mSDLGLRunloopGB(struct mSDLRenderer* renderer, void* user); -static void mSDLGLDeinitGB(struct mSDLRenderer* renderer); #endif +static void mSDLGLRunloop(struct mSDLRenderer* renderer, void* user); +static void mSDLGLDeinit(struct mSDLRenderer* renderer); + #ifdef M_CORE_GBA -void mSDLGLCreate(struct mSDLRenderer* renderer) { +void mSDLGLCreateGBA(struct mSDLRenderer* renderer) { renderer->init = mSDLGLInitGBA; - renderer->deinit = mSDLGLDeinitGBA; - renderer->runloop = mSDLGLRunloopGBA; + renderer->deinit = mSDLGLDeinit; + renderer->runloop = mSDLGLRunloop; } bool mSDLGLInitGBA(struct mSDLRenderer* renderer) { mSDLGLCommonInit(renderer); - renderer->d.outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL); - renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS; + renderer->outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL); + memset(renderer->outputBuffer, 0, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL); + renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, VIDEO_HORIZONTAL_PIXELS); GBAGLContextCreate(&renderer->gl); renderer->gl.d.user = renderer;

@@ -60,53 +58,13 @@

_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d); return true; } - -void mSDLGLRunloopGBA(struct mSDLRenderer* renderer, void* user) { - struct GBAThread* context = user; - SDL_Event event; - struct VideoBackend* v = &renderer->gl.d; - renderer->audio.psg = &context->gba->audio.psg; - - while (context->state < THREAD_EXITING) { - while (SDL_PollEvent(&event)) { - mSDLHandleEventGBA(context, &renderer->player, &event); -#if SDL_VERSION_ATLEAST(2, 0, 0) - // Event handling can change the size of the screen - if (renderer->player.windowUpdated) { - SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight); - _doViewport(renderer->viewportWidth, renderer->viewportHeight, v); - renderer->player.windowUpdated = 0; - } -#endif - } - - if (mCoreSyncWaitFrameStart(&context->sync)) { - v->postFrame(v, renderer->d.outputBuffer); - } - mCoreSyncWaitFrameEnd(&context->sync); - v->drawFrame(v); - v->swap(v); - } - - renderer->audio.psg = 0; -} - -void mSDLGLDeinitGBA(struct mSDLRenderer* renderer) { - if (renderer->gl.d.deinit) { - renderer->gl.d.deinit(&renderer->gl.d); - } - free(renderer->d.outputBuffer); -#if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_GL_DeleteContext(renderer->glCtx); -#endif -} #endif #ifdef M_CORE_GB void mSDLGLCreateGB(struct mSDLRenderer* renderer) { renderer->init = mSDLGLInitGB; - renderer->deinit = mSDLGLDeinitGB; - renderer->runloop = mSDLGLRunloopGB; + renderer->deinit = mSDLGLDeinit; + renderer->runloop = mSDLGLRunloop; } bool mSDLGLInitGB(struct mSDLRenderer* renderer) {

@@ -127,12 +85,12 @@

_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d); return true; } +#endif -void mSDLGLRunloopGB(struct mSDLRenderer* renderer, void* user) { +void mSDLGLRunloop(struct mSDLRenderer* renderer, void* user) { struct mCoreThread* context = user; SDL_Event event; struct VideoBackend* v = &renderer->gl.d; - renderer->audio.psg = &((struct GB*) renderer->core->board)->audio; while (context->state < THREAD_EXITING) { while (SDL_PollEvent(&event)) {

@@ -154,10 +112,9 @@ mCoreSyncWaitFrameEnd(&context->sync);

v->drawFrame(v); v->swap(v); } - renderer->audio.psg = 0; } -void mSDLGLDeinitGB(struct mSDLRenderer* renderer) { +void mSDLGLDeinit(struct mSDLRenderer* renderer) { if (renderer->gl.d.deinit) { renderer->gl.d.deinit(&renderer->gl.d); }

@@ -166,4 +123,3 @@ #if SDL_VERSION_ATLEAST(2, 0, 0)

SDL_GL_DeleteContext(renderer->glCtx); #endif } -#endif
M src/platform/sdl/main.csrc/platform/sdl/main.c

@@ -15,8 +15,11 @@ #endif

#include "core/core.h" #include "core/config.h" +#include "core/input.h" #include "core/thread.h" +#include "gba/input.h" #ifdef M_CORE_GBA +#include "gba/core.h" #include "gba/gba.h" #include "gba/supervisor/thread.h" #include "gba/video.h"

@@ -52,9 +55,7 @@ // TODO: Clean up signatures

#ifdef M_CORE_GBA static int mSDLRunGBA(struct mSDLRenderer* renderer, struct GBAArguments* args, struct GBAOptions* opts, struct mCoreConfig* config); #endif -#ifdef M_CORE_GB -static int mSDLRunGB(struct mSDLRenderer* renderer, struct GBAArguments* args); -#endif +static int mSDLRun(struct mSDLRenderer* renderer, struct GBAArguments* args); int main(int argc, char** argv) {

@@ -119,9 +120,9 @@ }

if (!opts.height) { opts.height = VIDEO_VERTICAL_PIXELS; } - GBAVideoSoftwareRendererCreate(&renderer.d); + renderer.core = GBACoreCreate(); #ifdef BUILD_GL - mSDLGLCreate(&renderer); + mSDLGLCreateGBA(&renderer); #elif defined(BUILD_GLES2) || defined(USE_EPOXY) mSDLGLES2Create(&renderer); #else

@@ -149,7 +150,7 @@ #endif

} #endif else { - printf("Could not run game. Are you sure the file exists and is a Game Boy Advance game?\n"); + printf("Could not run game. Are you sure the file exists and is a compatible game?\n"); freeArguments(&args); mCoreConfigFreeOpts(&opts); mCoreConfigDeinit(&config);

@@ -197,17 +198,8 @@ mSDLPlayerLoadConfig(&renderer.player, mCoreConfigGetInput(&config));

int ret; - switch (platform) { - case PLATFORM_GBA: - ret = mSDLRunGBA(&renderer, &args, &opts, &config); - break; - case PLATFORM_GB: - ret = mSDLRunGB(&renderer, &args); - break; - default: - ret = 1; - break; - } + // TODO: Use opts and config + ret = mSDLRun(&renderer, &args); mSDLDetachPlayer(&renderer.events, &renderer.player); mInputMapDeinit(&inputMap);

@@ -223,7 +215,6 @@

#ifdef M_CORE_GBA int mSDLRunGBA(struct mSDLRenderer* renderer, struct GBAArguments* args, struct GBAOptions* opts, struct mCoreConfig* config) { struct GBAThread context = { - .renderer = &renderer->d.d, .userData = renderer };

@@ -240,7 +231,7 @@ renderer->audio.sampleRate = 44100;

if (opts->sampleRate) { renderer->audio.sampleRate = opts->sampleRate; } - if (!GBSDLInitAudio(&renderer->audio, &context)) { + if (!mSDLInitAudio(&renderer->audio, &context)) { didFail = true; }

@@ -250,9 +241,7 @@ mSDLSetScreensaverSuspendable(&renderer->events, opts->suspendScreensaver);

mSDLSuspendScreensaver(&renderer->events); #endif if (GBAThreadStart(&context)) { - renderer->audio.psg = &context.gba->audio.psg; renderer->runloop(renderer, &context); - renderer->audio.psg = 0; GBAThreadJoin(&context); } else { didFail = true;

@@ -276,8 +265,7 @@ return didFail;

} #endif -#ifdef M_CORE_GB -int mSDLRunGB(struct mSDLRenderer* renderer, struct GBAArguments* args) { +int mSDLRun(struct mSDLRenderer* renderer, struct GBAArguments* args) { struct mCoreThread thread = { .core = renderer->core, .sync = {

@@ -292,18 +280,18 @@

renderer->audio.samples = 1024; renderer->audio.sampleRate = 44100; - bool didFail = !GBSDLInitAudio(&renderer->audio, 0); + bool didFail = !mSDLInitAudio(&renderer->audio, 0); if (!didFail) { + renderer->audio.core = renderer->core; renderer->audio.sync = &thread.sync; if (mCoreThreadStart(&thread)) { - renderer->audio.psg = 0; - GBSDLResumeAudio(&renderer->audio); + mSDLResumeAudio(&renderer->audio); renderer->runloop(renderer, &thread); mCoreThreadJoin(&thread); } else { didFail = true; - printf("Could not run game. Are you sure the file exists and is a Game Boy game?\n"); + printf("Could not run game. Are you sure the file exists and is a compatible game?\n"); } if (mCoreThreadHasCrashed(&thread)) {

@@ -314,7 +302,6 @@ }

renderer->core->unloadROM(renderer->core); return didFail; } -#endif static bool mSDLInit(struct mSDLRenderer* renderer) { if (SDL_Init(SDL_INIT_VIDEO) < 0) {

@@ -327,7 +314,7 @@ }

static void mSDLDeinit(struct mSDLRenderer* renderer) { mSDLDeinitEvents(&renderer->events); - GBSDLDeinitAudio(&renderer->audio); + mSDLDeinitAudio(&renderer->audio); #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_DestroyWindow(renderer->window); #endif
M src/platform/sdl/main.hsrc/platform/sdl/main.h

@@ -44,11 +44,8 @@ struct mCore;

struct mSDLRenderer { struct mCore* core; color_t* outputBuffer; -#ifdef M_CORE_GBA - // TODO: Remove - struct GBAVideoSoftwareRenderer d; -#endif - struct GBSDLAudio audio; + + struct mSDLAudio audio; struct mSDLEvents events; struct mSDLPlayer player;

@@ -101,7 +98,7 @@

void mSDLSWCreate(struct mSDLRenderer* renderer); #ifdef BUILD_GL -void mSDLGLCreate(struct mSDLRenderer* renderer); +void mSDLGLCreateGBA(struct mSDLRenderer* renderer); void mSDLGLCreateGB(struct mSDLRenderer* renderer); #endif
M src/platform/sdl/sdl-audio.csrc/platform/sdl/sdl-audio.c

@@ -12,9 +12,9 @@ #include "third-party/blip_buf/blip_buf.h"

#define BUFFER_SIZE (GBA_AUDIO_SAMPLES >> 2) -static void _GBSDLAudioCallback(void* context, Uint8* data, int len); +static void _mSDLAudioCallback(void* context, Uint8* data, int len); -bool GBSDLInitAudio(struct GBSDLAudio* context, struct GBAThread* threadContext) { +bool mSDLInitAudio(struct mSDLAudio* context, struct GBAThread* threadContext) { if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { GBALog(0, GBA_LOG_ERROR, "Could not initialize SDL sound system: %s", SDL_GetError()); return false;

@@ -24,7 +24,7 @@ context->desiredSpec.freq = context->sampleRate;

context->desiredSpec.format = AUDIO_S16SYS; context->desiredSpec.channels = 2; context->desiredSpec.samples = context->samples; - context->desiredSpec.callback = _GBSDLAudioCallback; + context->desiredSpec.callback = _mSDLAudioCallback; context->desiredSpec.userdata = context; #if SDL_VERSION_ATLEAST(2, 0, 0)

@@ -37,7 +37,7 @@ GBALog(0, GBA_LOG_ERROR, "Could not open SDL sound system");

return false; } context->samples = context->obtainedSpec.samples; - context->psg = 0; + context->core = 0; context->thread = 0; if (threadContext) {

@@ -59,9 +59,8 @@

return true; } -void GBSDLDeinitAudio(struct GBSDLAudio* context) { +void mSDLDeinitAudio(struct mSDLAudio* context) { UNUSED(context); - context->psg = 0; #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_PauseAudioDevice(context->deviceId, 1); SDL_CloseAudioDevice(context->deviceId);

@@ -72,7 +71,7 @@ #endif

SDL_QuitSubSystem(SDL_INIT_AUDIO); } -void GBSDLPauseAudio(struct GBSDLAudio* context) { +void mSDLPauseAudio(struct mSDLAudio* context) { #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_PauseAudioDevice(context->deviceId, 1); #else

@@ -81,7 +80,7 @@ SDL_PauseAudio(1);

#endif } -void GBSDLResumeAudio(struct GBSDLAudio* context) { +void mSDLResumeAudio(struct mSDLAudio* context) { #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_PauseAudioDevice(context->deviceId, 0); #else

@@ -90,31 +89,39 @@ SDL_PauseAudio(0);

#endif } -static void _GBSDLAudioCallback(void* context, Uint8* data, int len) { - struct GBSDLAudio* audioContext = context; - if (!context || (!audioContext->psg && !audioContext->thread)) { +static void _mSDLAudioCallback(void* context, Uint8* data, int len) { + struct mSDLAudio* audioContext = context; + if (!context || (!audioContext->core && !audioContext->thread)) { memset(data, 0, len); return; } - struct GBAudio* psg = audioContext->psg; - if (!psg) { - psg = &audioContext->thread->gba->audio.psg; + blip_t* left = NULL; + blip_t* right = NULL; + int32_t clockRate; + if (audioContext->core) { + left = audioContext->core->getAudioChannel(audioContext->core, 0); + right = audioContext->core->getAudioChannel(audioContext->core, 1); + clockRate = audioContext->core->frequency(audioContext->core); + } else if (audioContext->thread) { + left = audioContext->thread->gba->audio.psg.left; + right = audioContext->thread->gba->audio.psg.right; + clockRate = GBA_ARM7TDMI_FREQUENCY; } double fauxClock = 1; if (audioContext->thread) { fauxClock = GBAAudioCalculateRatio(1, audioContext->thread->fpsTarget, 1); mCoreSyncLockAudio(&audioContext->thread->sync); } - blip_set_rates(psg->left, psg->clockRate, audioContext->obtainedSpec.freq * fauxClock); - blip_set_rates(psg->right, psg->clockRate, audioContext->obtainedSpec.freq * fauxClock); + blip_set_rates(left, clockRate, audioContext->obtainedSpec.freq * fauxClock); + blip_set_rates(right, clockRate, audioContext->obtainedSpec.freq * fauxClock); len /= 2 * audioContext->obtainedSpec.channels; - int available = blip_samples_avail(psg->left); + int available = blip_samples_avail(left); if (available > len) { available = len; } - blip_read_samples(psg->left, (short*) data, available, audioContext->obtainedSpec.channels == 2); + blip_read_samples(left, (short*) data, available, audioContext->obtainedSpec.channels == 2); if (audioContext->obtainedSpec.channels == 2) { - blip_read_samples(psg->right, ((short*) data) + 1, available, 1); + blip_read_samples(right, ((short*) data) + 1, available, 1); } if (audioContext->sync) {
M src/platform/sdl/sdl-audio.hsrc/platform/sdl/sdl-audio.h

@@ -10,7 +10,7 @@ #include "util/common.h"

#include <SDL.h> -struct GBSDLAudio { +struct mSDLAudio { // Input size_t samples; unsigned sampleRate;

@@ -22,14 +22,14 @@ #if SDL_VERSION_ATLEAST(2, 0, 0)

SDL_AudioDeviceID deviceId; #endif - struct GBAudio* psg; + struct mCore* core; struct GBAThread* thread; struct mCoreSync* sync; }; -bool GBSDLInitAudio(struct GBSDLAudio* context, struct GBAThread*); -void GBSDLDeinitAudio(struct GBSDLAudio* context); -void GBSDLPauseAudio(struct GBSDLAudio* context); -void GBSDLResumeAudio(struct GBSDLAudio* context); +bool mSDLInitAudio(struct mSDLAudio* context, struct GBAThread*); +void mSDLDeinitAudio(struct mSDLAudio* context); +void mSDLPauseAudio(struct mSDLAudio* context); +void mSDLResumeAudio(struct mSDLAudio* context); #endif