all repos — mgba @ 8d89fb78ba9b76e53b1fba0f9c0549db4a220b1d

mGBA Game Boy Advance Emulator

Core: Add callbacks
Jeffrey Pfau jeffrey@endrift.com
Thu, 20 Oct 2016 17:35:32 -0700
commit

8d89fb78ba9b76e53b1fba0f9c0549db4a220b1d

parent

9756f79f044767052280bcc7d7d1225b1f326698

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

@@ -64,6 +64,7 @@ struct blip_t* (*getAudioChannel)(struct mCore*, int ch);

void (*setAudioBufferSize)(struct mCore*, size_t samples); size_t (*getAudioBufferSize)(struct mCore*); + void (*setCoreCallbacks)(struct mCore*, struct mCoreCallbacks*); void (*setAVStream)(struct mCore*, struct mAVStream*); bool (*isROM)(struct VFile* vf);
M src/core/interface.hsrc/core/interface.h

@@ -20,6 +20,13 @@ #endif

struct blip_t; +struct mCoreCallbacks { + void* context; + void (*videoFrameStarted)(void* context); + void (*videoFrameEnded)(void* context); + void (*coreCrashed)(void* context); +}; + struct mAVStream { void (*videoDimensionsChanged)(struct mAVStream*, unsigned width, unsigned height); void (*postVideoFrame)(struct mAVStream*, const color_t* buffer, size_t stride);
M src/core/thread.csrc/core/thread.c

@@ -85,6 +85,40 @@ threadContext->state = THREAD_PAUSING;

_waitUntilNotState(threadContext, THREAD_PAUSING); } +void _frameStarted(void* context) { + struct mCoreThread* thread = context; + if (!thread) { + return; + } + if (thread->core->opts.rewindEnable && thread->core->opts.rewindBufferCapacity > 0) { + if (thread->state != THREAD_REWINDING) { + mCoreRewindAppend(&thread->rewind, thread->core); + } else if (thread->state == THREAD_REWINDING) { + if (!mCoreRewindRestore(&thread->rewind, thread->core)) { + mCoreRewindAppend(&thread->rewind, thread->core); + } + } + } +} + +void _frameEnded(void* context) { + struct mCoreThread* thread = context; + if (!thread) { + return; + } + if (thread->frameCallback) { + thread->frameCallback(thread); + } +} + +void _crashed(void* context) { + struct mCoreThread* thread = context; + if (!thread) { + return; + } + _changeState(thread, THREAD_CRASHED, true); +} + static THREAD_ENTRY _mCoreThreadRun(void* context) { struct mCoreThread* threadContext = context; #ifdef USE_PTHREADS

@@ -104,6 +138,13 @@ pthread_sigmask(SIG_SETMASK, &signals, 0);

#endif struct mCore* core = threadContext->core; + struct mCoreCallbacks callbacks = { + .videoFrameStarted = _frameStarted, + .videoFrameEnded = _frameEnded, + .coreCrashed = _crashed, + .context = threadContext + }; + core->setCoreCallbacks(core, &callbacks); core->setSync(core, &threadContext->sync); core->reset(core);

@@ -179,6 +220,7 @@

if (threadContext->cleanCallback) { threadContext->cleanCallback(threadContext); } + core->setCoreCallbacks(core, NULL); return 0; }

@@ -483,43 +525,10 @@ return NULL;

} #endif -void mCoreThreadFrameStarted(struct mCoreThread* thread) { - if (!thread) { - return; - } - if (thread->core->opts.rewindEnable && thread->core->opts.rewindBufferCapacity > 0) { - if (thread->state != THREAD_REWINDING) { - mCoreRewindAppend(&thread->rewind, thread->core); - } else if (thread->state == THREAD_REWINDING) { - if (!mCoreRewindRestore(&thread->rewind, thread->core)) { - mCoreRewindAppend(&thread->rewind, thread->core); - } - } - } -} - -void mCoreThreadFrameEnded(struct mCoreThread* thread) { - if (!thread) { - return; - } - if (thread->frameCallback) { - thread->frameCallback(thread); - } -} - #else struct mCoreThread* mCoreThreadGet(void) { return NULL; } - -void mCoreThreadFrameStarted(struct mCoreThread* thread) { - UNUSED(thread); -} - -void mCoreThreadFrameEnded(struct mCoreThread* thread) { - UNUSED(thread); -} - #endif static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {
M src/core/thread.hsrc/core/thread.h

@@ -95,10 +95,6 @@

void mCoreThreadSetRewinding(struct mCoreThread* threadContext, bool); struct mCoreThread* mCoreThreadGet(void); - -void mCoreThreadFrameStarted(struct mCoreThread*); -void mCoreThreadFrameEnded(struct mCoreThread*); - struct mLogger* mCoreThreadLogger(void); #endif
M src/gb/core.csrc/gb/core.c

@@ -153,6 +153,11 @@ struct GB* gb = core->board;

return gb->audio.samples; } +static void _GBCoreSetCoreCallbacks(struct mCore* core, struct mCoreCallbacks* coreCallbacks) { + struct GB* gb = core->board; + gb->coreCallbacks = coreCallbacks; +} + static void _GBCoreSetAVStream(struct mCore* core, struct mAVStream* stream) { struct GB* gb = core->board; gb->stream = stream;

@@ -534,6 +539,7 @@ core->getAudioChannel = _GBCoreGetAudioChannel;

core->setAudioBufferSize = _GBCoreSetAudioBufferSize; core->getAudioBufferSize = _GBCoreGetAudioBufferSize; core->setAVStream = _GBCoreSetAVStream; + core->setCoreCallbacks = _GBCoreSetCoreCallbacks; core->isROM = GBIsROM; core->loadROM = _GBCoreLoadROM; core->loadBIOS = _GBCoreLoadBIOS;
M src/gb/gb.csrc/gb/gb.c

@@ -76,6 +76,7 @@ gb->pristineRom = 0;

gb->pristineRomSize = 0; gb->yankedRomSize = 0; + gb->coreCallbacks = NULL; gb->stream = NULL; }
M src/gb/gb.hsrc/gb/gb.h

@@ -44,6 +44,7 @@ };

struct mCoreSync; struct mAVStream; +struct mCoreCallbacks; struct GB { struct mCPUComponent d;

@@ -72,6 +73,7 @@ int sramDirty;

int32_t sramDirtAge; bool sramMaskWriteback; + struct mCoreCallbacks* coreCallbacks; struct mAVStream* stream; int32_t eiPending;
M src/gb/video.csrc/gb/video.c

@@ -133,8 +133,10 @@ video->p->memory.io[REG_IF] |= (1 << GB_IRQ_LCDSTAT);

} video->p->memory.io[REG_IF] |= (1 << GB_IRQ_VBLANK); - struct mCoreThread* thread = mCoreThreadGet(); - mCoreThreadFrameEnded(thread); + struct mCoreCallbacks* callbacks = video->p->coreCallbacks; + if (callbacks && callbacks->videoFrameEnded) { + callbacks->videoFrameEnded(callbacks->context); + } } if (GBRegisterSTATIsLYCIRQ(video->stat) && lyc == video->ly) { video->p->memory.io[REG_IF] |= (1 << GB_IRQ_LCDSTAT);

@@ -220,8 +222,10 @@ size_t stride;

video->renderer->getPixels(video->renderer, &stride, (const void**) &pixels); video->p->stream->postVideoFrame(video->p->stream, pixels, stride); } - struct mCoreThread* thread = mCoreThreadGet(); - mCoreThreadFrameStarted(thread); + struct mCoreCallbacks* callbacks = video->p->coreCallbacks; + if (callbacks && callbacks->videoFrameStarted) { + callbacks->videoFrameStarted(callbacks->context); + } } else { video->nextFrame = 4 - ((video->p->cpu->executionState + 1) & 3); if (video->nextFrame < video->nextEvent) {
M src/gba/core.csrc/gba/core.c

@@ -184,6 +184,11 @@ struct GBA* gba = core->board;

return gba->audio.samples; } +static void _GBACoreSetCoreCallbacks(struct mCore* core, struct mCoreCallbacks* coreCallbacks) { + struct GBA* gba = core->board; + gba->coreCallbacks = coreCallbacks; +} + static void _GBACoreSetAVStream(struct mCore* core, struct mAVStream* stream) { struct GBA* gba = core->board; gba->stream = stream;

@@ -550,6 +555,7 @@ core->putPixels = _GBACorePutPixels;

core->getAudioChannel = _GBACoreGetAudioChannel; core->setAudioBufferSize = _GBACoreSetAudioBufferSize; core->getAudioBufferSize = _GBACoreGetAudioBufferSize; + core->setCoreCallbacks = _GBACoreSetCoreCallbacks; core->setAVStream = _GBACoreSetAVStream; core->isROM = GBAIsROM; core->loadROM = _GBACoreLoadROM;
M src/gba/gba.csrc/gba/gba.c

@@ -94,9 +94,11 @@

gba->romVf = 0; gba->biosVf = 0; - gba->stream = 0; - gba->keyCallback = 0; - gba->stopCallback = 0; + gba->stream = NULL; + gba->keyCallback = NULL; + gba->stopCallback = NULL; + gba->stopCallback = NULL; + gba->coreCallbacks = NULL; gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);

@@ -854,8 +856,10 @@

void GBAFrameStarted(struct GBA* gba) { UNUSED(gba); - struct mCoreThread* thread = mCoreThreadGet(); - mCoreThreadFrameStarted(thread); + struct mCoreCallbacks* callbacks = gba->coreCallbacks; + if (callbacks && callbacks->videoFrameStarted) { + callbacks->videoFrameStarted(callbacks->context); + } } void GBAFrameEnded(struct GBA* gba) {

@@ -885,10 +889,10 @@ if (gba->memory.hw.devices & (HW_GB_PLAYER | HW_GB_PLAYER_DETECTION)) {

GBAHardwarePlayerUpdate(gba); } - struct mCoreThread* thread = mCoreThreadGet(); - mCoreThreadFrameEnded(thread); - - // TODO: Put back RR + struct mCoreCallbacks* callbacks = gba->coreCallbacks; + if (callbacks && callbacks->videoFrameEnded) { + callbacks->videoFrameEnded(callbacks->context); + } } void GBASetBreakpoint(struct GBA* gba, struct mCPUComponent* component, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) {
M src/gba/gba.hsrc/gba/gba.h

@@ -112,6 +112,7 @@

struct mAVStream* stream; struct mKeyCallback* keyCallback; struct mStopCallback* stopCallback; + struct mCoreCallbacks* coreCallbacks; enum GBAIdleLoopOptimization idleOptimization; uint32_t idleLoop;
M src/gba/memory.csrc/gba/memory.c

@@ -310,6 +310,9 @@ cpu->memory.activeRegion = _deadbeef;

cpu->memory.activeMask = 0; if (gba->yankedRomSize || !gba->hardCrash) { mLOG(GBA_MEM, GAME_ERROR, "Jumped to invalid address: %08X", address); + } else if (gba->coreCallbacks && gba->coreCallbacks->coreCrashed) { + mLOG(GBA_MEM, GAME_ERROR, "Jumped to invalid address: %08X", address); + gba->coreCallbacks->coreCrashed(gba->coreCallbacks->context); } else { mLOG(GBA_MEM, FATAL, "Jumped to invalid address: %08X", address); }