Core: Add callbacks

This commit is contained in:
Jeffrey Pfau 2016-10-20 17:35:32 -07:00
parent 9756f79f04
commit 8d89fb78ba
12 changed files with 90 additions and 50 deletions

View File

@ -64,6 +64,7 @@ struct mCore {
void (*setAudioBufferSize)(struct mCore*, size_t samples); void (*setAudioBufferSize)(struct mCore*, size_t samples);
size_t (*getAudioBufferSize)(struct mCore*); size_t (*getAudioBufferSize)(struct mCore*);
void (*setCoreCallbacks)(struct mCore*, struct mCoreCallbacks*);
void (*setAVStream)(struct mCore*, struct mAVStream*); void (*setAVStream)(struct mCore*, struct mAVStream*);
bool (*isROM)(struct VFile* vf); bool (*isROM)(struct VFile* vf);

View File

@ -20,6 +20,13 @@ typedef uint32_t color_t;
struct blip_t; struct blip_t;
struct mCoreCallbacks {
void* context;
void (*videoFrameStarted)(void* context);
void (*videoFrameEnded)(void* context);
void (*coreCrashed)(void* context);
};
struct mAVStream { struct mAVStream {
void (*videoDimensionsChanged)(struct mAVStream*, unsigned width, unsigned height); void (*videoDimensionsChanged)(struct mAVStream*, unsigned width, unsigned height);
void (*postVideoFrame)(struct mAVStream*, const color_t* buffer, size_t stride); void (*postVideoFrame)(struct mAVStream*, const color_t* buffer, size_t stride);

View File

@ -85,6 +85,40 @@ static void _pauseThread(struct mCoreThread* threadContext) {
_waitUntilNotState(threadContext, 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) { static THREAD_ENTRY _mCoreThreadRun(void* context) {
struct mCoreThread* threadContext = context; struct mCoreThread* threadContext = context;
#ifdef USE_PTHREADS #ifdef USE_PTHREADS
@ -104,6 +138,13 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
#endif #endif
struct mCore* core = threadContext->core; 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->setSync(core, &threadContext->sync);
core->reset(core); core->reset(core);
@ -179,6 +220,7 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
if (threadContext->cleanCallback) { if (threadContext->cleanCallback) {
threadContext->cleanCallback(threadContext); threadContext->cleanCallback(threadContext);
} }
core->setCoreCallbacks(core, NULL);
return 0; return 0;
} }
@ -483,43 +525,10 @@ struct mCoreThread* mCoreThreadGet(void) {
} }
#endif #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 #else
struct mCoreThread* mCoreThreadGet(void) { struct mCoreThread* mCoreThreadGet(void) {
return NULL; return NULL;
} }
void mCoreThreadFrameStarted(struct mCoreThread* thread) {
UNUSED(thread);
}
void mCoreThreadFrameEnded(struct mCoreThread* thread) {
UNUSED(thread);
}
#endif #endif
static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {

View File

@ -95,10 +95,6 @@ void mCoreThreadStopWaiting(struct mCoreThread* threadContext);
void mCoreThreadSetRewinding(struct mCoreThread* threadContext, bool); void mCoreThreadSetRewinding(struct mCoreThread* threadContext, bool);
struct mCoreThread* mCoreThreadGet(void); struct mCoreThread* mCoreThreadGet(void);
void mCoreThreadFrameStarted(struct mCoreThread*);
void mCoreThreadFrameEnded(struct mCoreThread*);
struct mLogger* mCoreThreadLogger(void); struct mLogger* mCoreThreadLogger(void);
#endif #endif

View File

@ -153,6 +153,11 @@ static size_t _GBCoreGetAudioBufferSize(struct mCore* core) {
return gb->audio.samples; 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) { static void _GBCoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
struct GB* gb = core->board; struct GB* gb = core->board;
gb->stream = stream; gb->stream = stream;
@ -534,6 +539,7 @@ struct mCore* GBCoreCreate(void) {
core->setAudioBufferSize = _GBCoreSetAudioBufferSize; core->setAudioBufferSize = _GBCoreSetAudioBufferSize;
core->getAudioBufferSize = _GBCoreGetAudioBufferSize; core->getAudioBufferSize = _GBCoreGetAudioBufferSize;
core->setAVStream = _GBCoreSetAVStream; core->setAVStream = _GBCoreSetAVStream;
core->setCoreCallbacks = _GBCoreSetCoreCallbacks;
core->isROM = GBIsROM; core->isROM = GBIsROM;
core->loadROM = _GBCoreLoadROM; core->loadROM = _GBCoreLoadROM;
core->loadBIOS = _GBCoreLoadBIOS; core->loadBIOS = _GBCoreLoadBIOS;

View File

@ -76,6 +76,7 @@ static void GBInit(void* cpu, struct mCPUComponent* component) {
gb->pristineRomSize = 0; gb->pristineRomSize = 0;
gb->yankedRomSize = 0; gb->yankedRomSize = 0;
gb->coreCallbacks = NULL;
gb->stream = NULL; gb->stream = NULL;
} }

View File

@ -44,6 +44,7 @@ enum GBIRQVector {
struct mCoreSync; struct mCoreSync;
struct mAVStream; struct mAVStream;
struct mCoreCallbacks;
struct GB { struct GB {
struct mCPUComponent d; struct mCPUComponent d;
@ -72,6 +73,7 @@ struct GB {
int32_t sramDirtAge; int32_t sramDirtAge;
bool sramMaskWriteback; bool sramMaskWriteback;
struct mCoreCallbacks* coreCallbacks;
struct mAVStream* stream; struct mAVStream* stream;
int32_t eiPending; int32_t eiPending;

View File

@ -133,8 +133,10 @@ int32_t GBVideoProcessEvents(struct GBVideo* video, int32_t cycles) {
} }
video->p->memory.io[REG_IF] |= (1 << GB_IRQ_VBLANK); video->p->memory.io[REG_IF] |= (1 << GB_IRQ_VBLANK);
struct mCoreThread* thread = mCoreThreadGet(); struct mCoreCallbacks* callbacks = video->p->coreCallbacks;
mCoreThreadFrameEnded(thread); if (callbacks && callbacks->videoFrameEnded) {
callbacks->videoFrameEnded(callbacks->context);
}
} }
if (GBRegisterSTATIsLYCIRQ(video->stat) && lyc == video->ly) { if (GBRegisterSTATIsLYCIRQ(video->stat) && lyc == video->ly) {
video->p->memory.io[REG_IF] |= (1 << GB_IRQ_LCDSTAT); video->p->memory.io[REG_IF] |= (1 << GB_IRQ_LCDSTAT);
@ -220,8 +222,10 @@ int32_t GBVideoProcessEvents(struct GBVideo* video, int32_t cycles) {
video->renderer->getPixels(video->renderer, &stride, (const void**) &pixels); video->renderer->getPixels(video->renderer, &stride, (const void**) &pixels);
video->p->stream->postVideoFrame(video->p->stream, pixels, stride); video->p->stream->postVideoFrame(video->p->stream, pixels, stride);
} }
struct mCoreThread* thread = mCoreThreadGet(); struct mCoreCallbacks* callbacks = video->p->coreCallbacks;
mCoreThreadFrameStarted(thread); if (callbacks && callbacks->videoFrameStarted) {
callbacks->videoFrameStarted(callbacks->context);
}
} else { } else {
video->nextFrame = 4 - ((video->p->cpu->executionState + 1) & 3); video->nextFrame = 4 - ((video->p->cpu->executionState + 1) & 3);
if (video->nextFrame < video->nextEvent) { if (video->nextFrame < video->nextEvent) {

View File

@ -184,6 +184,11 @@ static size_t _GBACoreGetAudioBufferSize(struct mCore* core) {
return gba->audio.samples; 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) { static void _GBACoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
struct GBA* gba = core->board; struct GBA* gba = core->board;
gba->stream = stream; gba->stream = stream;
@ -550,6 +555,7 @@ struct mCore* GBACoreCreate(void) {
core->getAudioChannel = _GBACoreGetAudioChannel; core->getAudioChannel = _GBACoreGetAudioChannel;
core->setAudioBufferSize = _GBACoreSetAudioBufferSize; core->setAudioBufferSize = _GBACoreSetAudioBufferSize;
core->getAudioBufferSize = _GBACoreGetAudioBufferSize; core->getAudioBufferSize = _GBACoreGetAudioBufferSize;
core->setCoreCallbacks = _GBACoreSetCoreCallbacks;
core->setAVStream = _GBACoreSetAVStream; core->setAVStream = _GBACoreSetAVStream;
core->isROM = GBAIsROM; core->isROM = GBAIsROM;
core->loadROM = _GBACoreLoadROM; core->loadROM = _GBACoreLoadROM;

View File

@ -94,9 +94,11 @@ static void GBAInit(void* cpu, struct mCPUComponent* component) {
gba->romVf = 0; gba->romVf = 0;
gba->biosVf = 0; gba->biosVf = 0;
gba->stream = 0; gba->stream = NULL;
gba->keyCallback = 0; gba->keyCallback = NULL;
gba->stopCallback = 0; gba->stopCallback = NULL;
gba->stopCallback = NULL;
gba->coreCallbacks = NULL;
gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS); gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
@ -854,8 +856,10 @@ void GBABreakpoint(struct ARMCore* cpu, int immediate) {
void GBAFrameStarted(struct GBA* gba) { void GBAFrameStarted(struct GBA* gba) {
UNUSED(gba); UNUSED(gba);
struct mCoreThread* thread = mCoreThreadGet(); struct mCoreCallbacks* callbacks = gba->coreCallbacks;
mCoreThreadFrameStarted(thread); if (callbacks && callbacks->videoFrameStarted) {
callbacks->videoFrameStarted(callbacks->context);
}
} }
void GBAFrameEnded(struct GBA* gba) { void GBAFrameEnded(struct GBA* gba) {
@ -885,10 +889,10 @@ void GBAFrameEnded(struct GBA* gba) {
GBAHardwarePlayerUpdate(gba); GBAHardwarePlayerUpdate(gba);
} }
struct mCoreThread* thread = mCoreThreadGet(); struct mCoreCallbacks* callbacks = gba->coreCallbacks;
mCoreThreadFrameEnded(thread); if (callbacks && callbacks->videoFrameEnded) {
callbacks->videoFrameEnded(callbacks->context);
// TODO: Put back RR }
} }
void GBASetBreakpoint(struct GBA* gba, struct mCPUComponent* component, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) { void GBASetBreakpoint(struct GBA* gba, struct mCPUComponent* component, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) {

View File

@ -112,6 +112,7 @@ struct GBA {
struct mAVStream* stream; struct mAVStream* stream;
struct mKeyCallback* keyCallback; struct mKeyCallback* keyCallback;
struct mStopCallback* stopCallback; struct mStopCallback* stopCallback;
struct mCoreCallbacks* coreCallbacks;
enum GBAIdleLoopOptimization idleOptimization; enum GBAIdleLoopOptimization idleOptimization;
uint32_t idleLoop; uint32_t idleLoop;

View File

@ -310,6 +310,9 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
cpu->memory.activeMask = 0; cpu->memory.activeMask = 0;
if (gba->yankedRomSize || !gba->hardCrash) { if (gba->yankedRomSize || !gba->hardCrash) {
mLOG(GBA_MEM, GAME_ERROR, "Jumped to invalid address: %08X", address); 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 { } else {
mLOG(GBA_MEM, FATAL, "Jumped to invalid address: %08X", address); mLOG(GBA_MEM, FATAL, "Jumped to invalid address: %08X", address);
} }