mirror of https://github.com/mgba-emu/mgba.git
Core: Cores can now have multiple sets of callbacks
This commit is contained in:
parent
be3e884ba5
commit
3ac0b20ff8
1
CHANGES
1
CHANGES
|
@ -68,6 +68,7 @@ Misc:
|
||||||
- Util: Add 8-bit PNG write support
|
- Util: Add 8-bit PNG write support
|
||||||
- Qt: Rename "Resample video" option to "Bilinear filtering"
|
- Qt: Rename "Resample video" option to "Bilinear filtering"
|
||||||
- GBA Video: Optimize when BLD* registers are written frequently
|
- GBA Video: Optimize when BLD* registers are written frequently
|
||||||
|
- Core: Cores can now have multiple sets of callbacks
|
||||||
|
|
||||||
0.5.2: (2016-12-31)
|
0.5.2: (2016-12-31)
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
|
|
@ -73,7 +73,8 @@ 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 (*addCoreCallbacks)(struct mCore*, struct mCoreCallbacks*);
|
||||||
|
void (*clearCoreCallbacks)(struct mCore*);
|
||||||
void (*setAVStream)(struct mCore*, struct mAVStream*);
|
void (*setAVStream)(struct mCore*, struct mAVStream*);
|
||||||
|
|
||||||
bool (*isROM)(struct VFile* vf);
|
bool (*isROM)(struct VFile* vf);
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
CXX_GUARD_START
|
CXX_GUARD_START
|
||||||
|
|
||||||
|
#include <mgba-util/vector.h>
|
||||||
|
|
||||||
struct mCore;
|
struct mCore;
|
||||||
|
|
||||||
#ifdef COLOR_16_BIT
|
#ifdef COLOR_16_BIT
|
||||||
|
@ -37,6 +39,8 @@ struct mCoreCallbacks {
|
||||||
void (*coreCrashed)(void* context);
|
void (*coreCrashed)(void* context);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DECLARE_VECTOR(mCoreCallbacksList, struct mCoreCallbacks);
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
CXX_GUARD_START
|
CXX_GUARD_START
|
||||||
|
|
||||||
#include <mgba/core/cpu.h>
|
#include <mgba/core/cpu.h>
|
||||||
|
#include <mgba/core/interface.h>
|
||||||
#include <mgba/core/log.h>
|
#include <mgba/core/log.h>
|
||||||
#include <mgba/core/timing.h>
|
#include <mgba/core/timing.h>
|
||||||
|
|
||||||
|
@ -46,7 +47,6 @@ enum GBIRQVector {
|
||||||
struct LR35902Core;
|
struct LR35902Core;
|
||||||
struct mCoreSync;
|
struct mCoreSync;
|
||||||
struct mAVStream;
|
struct mAVStream;
|
||||||
struct mCoreCallbacks;
|
|
||||||
struct GB {
|
struct GB {
|
||||||
struct mCPUComponent d;
|
struct mCPUComponent d;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ struct GB {
|
||||||
int32_t sramDirtAge;
|
int32_t sramDirtAge;
|
||||||
bool sramMaskWriteback;
|
bool sramMaskWriteback;
|
||||||
|
|
||||||
struct mCoreCallbacks* coreCallbacks;
|
struct mCoreCallbacksList coreCallbacks;
|
||||||
struct mAVStream* stream;
|
struct mAVStream* stream;
|
||||||
|
|
||||||
bool cpuBlocked;
|
bool cpuBlocked;
|
||||||
|
|
|
@ -100,7 +100,7 @@ struct GBA {
|
||||||
struct mAVStream* stream;
|
struct mAVStream* stream;
|
||||||
struct mKeyCallback* keyCallback;
|
struct mKeyCallback* keyCallback;
|
||||||
struct mStopCallback* stopCallback;
|
struct mStopCallback* stopCallback;
|
||||||
struct mCoreCallbacks* coreCallbacks;
|
struct mCoreCallbacksList coreCallbacks;
|
||||||
|
|
||||||
enum GBAIdleLoopOptimization idleOptimization;
|
enum GBAIdleLoopOptimization idleOptimization;
|
||||||
uint32_t idleLoop;
|
uint32_t idleLoop;
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include <mgba/core/core.h>
|
#include <mgba/core/core.h>
|
||||||
|
|
||||||
|
DEFINE_VECTOR(mCoreCallbacksList, struct mCoreCallbacks);
|
||||||
|
|
||||||
static time_t _rtcGenericCallback(struct mRTCSource* source) {
|
static time_t _rtcGenericCallback(struct mRTCSource* source) {
|
||||||
struct mRTCGenericSource* rtc = (struct mRTCGenericSource*) source;
|
struct mRTCGenericSource* rtc = (struct mRTCGenericSource*) source;
|
||||||
switch (rtc->override) {
|
switch (rtc->override) {
|
||||||
|
|
|
@ -143,7 +143,7 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
||||||
.coreCrashed = _crashed,
|
.coreCrashed = _crashed,
|
||||||
.context = threadContext
|
.context = threadContext
|
||||||
};
|
};
|
||||||
core->setCoreCallbacks(core, &callbacks);
|
core->addCoreCallbacks(core, &callbacks);
|
||||||
core->setSync(core, &threadContext->sync);
|
core->setSync(core, &threadContext->sync);
|
||||||
core->reset(core);
|
core->reset(core);
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
||||||
if (threadContext->cleanCallback) {
|
if (threadContext->cleanCallback) {
|
||||||
threadContext->cleanCallback(threadContext);
|
threadContext->cleanCallback(threadContext);
|
||||||
}
|
}
|
||||||
core->setCoreCallbacks(core, NULL);
|
core->clearCoreCallbacks(core);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,9 +156,14 @@ static size_t _GBCoreGetAudioBufferSize(struct mCore* core) {
|
||||||
return gb->audio.samples;
|
return gb->audio.samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBCoreSetCoreCallbacks(struct mCore* core, struct mCoreCallbacks* coreCallbacks) {
|
static void _GBCoreAddCoreCallbacks(struct mCore* core, struct mCoreCallbacks* coreCallbacks) {
|
||||||
struct GB* gb = core->board;
|
struct GB* gb = core->board;
|
||||||
gb->coreCallbacks = coreCallbacks;
|
*mCoreCallbacksListAppend(&gb->coreCallbacks) = *coreCallbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBCoreClearCoreCallbacks(struct mCore* core) {
|
||||||
|
struct GB* gb = core->board;
|
||||||
|
mCoreCallbacksListClear(&gb->coreCallbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBCoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
|
static void _GBCoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
|
||||||
|
@ -576,7 +581,8 @@ 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->addCoreCallbacks = _GBCoreAddCoreCallbacks;
|
||||||
|
core->clearCoreCallbacks = _GBCoreClearCoreCallbacks;
|
||||||
core->isROM = GBIsROM;
|
core->isROM = GBIsROM;
|
||||||
core->loadROM = _GBCoreLoadROM;
|
core->loadROM = _GBCoreLoadROM;
|
||||||
core->loadBIOS = _GBCoreLoadBIOS;
|
core->loadBIOS = _GBCoreLoadBIOS;
|
||||||
|
|
|
@ -83,7 +83,7 @@ static void GBInit(void* cpu, struct mCPUComponent* component) {
|
||||||
gb->pristineRomSize = 0;
|
gb->pristineRomSize = 0;
|
||||||
gb->yankedRomSize = 0;
|
gb->yankedRomSize = 0;
|
||||||
|
|
||||||
gb->coreCallbacks = NULL;
|
mCoreCallbacksListInit(&gb->coreCallbacks, 0);
|
||||||
gb->stream = NULL;
|
gb->stream = NULL;
|
||||||
|
|
||||||
mTimingInit(&gb->timing, &gb->cpu->cycles, &gb->cpu->nextEvent);
|
mTimingInit(&gb->timing, &gb->cpu->cycles, &gb->cpu->nextEvent);
|
||||||
|
@ -349,6 +349,7 @@ void GBDestroy(struct GB* gb) {
|
||||||
GBAudioDeinit(&gb->audio);
|
GBAudioDeinit(&gb->audio);
|
||||||
GBVideoDeinit(&gb->video);
|
GBVideoDeinit(&gb->video);
|
||||||
GBSIODeinit(&gb->sio);
|
GBSIODeinit(&gb->sio);
|
||||||
|
mCoreCallbacksListDeinit(&gb->coreCallbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBInterruptHandlerInit(struct LR35902InterruptHandler* irqh) {
|
void GBInterruptHandlerInit(struct LR35902InterruptHandler* irqh) {
|
||||||
|
|
|
@ -129,9 +129,12 @@ void _endMode0(struct mTiming* timing, void* context, uint32_t cyclesLate) {
|
||||||
}
|
}
|
||||||
video->p->memory.io[REG_IF] |= (1 << GB_IRQ_VBLANK);
|
video->p->memory.io[REG_IF] |= (1 << GB_IRQ_VBLANK);
|
||||||
|
|
||||||
struct mCoreCallbacks* callbacks = video->p->coreCallbacks;
|
size_t c;
|
||||||
if (callbacks && callbacks->videoFrameEnded) {
|
for (c = 0; c < mCoreCallbacksListSize(&video->p->coreCallbacks); ++c) {
|
||||||
callbacks->videoFrameEnded(callbacks->context);
|
struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&video->p->coreCallbacks, c);
|
||||||
|
if (callbacks->videoFrameEnded) {
|
||||||
|
callbacks->videoFrameEnded(callbacks->context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!GBRegisterSTATIsHblankIRQ(video->stat) && GBRegisterSTATIsLYCIRQ(video->stat) && lyc == video->ly) {
|
if (!GBRegisterSTATIsHblankIRQ(video->stat) && GBRegisterSTATIsLYCIRQ(video->stat) && lyc == video->ly) {
|
||||||
|
@ -244,9 +247,12 @@ void _updateFrameCount(struct mTiming* timing, void* context, uint32_t cyclesLat
|
||||||
video->p->stream->postVideoFrame(video->p->stream, pixels, stride);
|
video->p->stream->postVideoFrame(video->p->stream, pixels, stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mCoreCallbacks* callbacks = video->p->coreCallbacks;
|
size_t c;
|
||||||
if (callbacks && callbacks->videoFrameStarted) {
|
for (c = 0; c < mCoreCallbacksListSize(&video->p->coreCallbacks); ++c) {
|
||||||
callbacks->videoFrameStarted(callbacks->context);
|
struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&video->p->coreCallbacks, c);
|
||||||
|
if (callbacks->videoFrameEnded) {
|
||||||
|
callbacks->videoFrameStarted(callbacks->context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GBRegisterLCDCIsEnable(video->p->memory.io[REG_LCDC])) {
|
if (!GBRegisterLCDCIsEnable(video->p->memory.io[REG_LCDC])) {
|
||||||
|
|
|
@ -186,9 +186,14 @@ static size_t _GBACoreGetAudioBufferSize(struct mCore* core) {
|
||||||
return gba->audio.samples;
|
return gba->audio.samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBACoreSetCoreCallbacks(struct mCore* core, struct mCoreCallbacks* coreCallbacks) {
|
static void _GBACoreAddCoreCallbacks(struct mCore* core, struct mCoreCallbacks* coreCallbacks) {
|
||||||
struct GBA* gba = core->board;
|
struct GBA* gba = core->board;
|
||||||
gba->coreCallbacks = coreCallbacks;
|
*mCoreCallbacksListAppend(&gba->coreCallbacks) = *coreCallbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _GBACoreClearCoreCallbacks(struct mCore* core) {
|
||||||
|
struct GBA* gba = core->board;
|
||||||
|
mCoreCallbacksListClear(&gba->coreCallbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBACoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
|
static void _GBACoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
|
||||||
|
@ -589,7 +594,8 @@ 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->addCoreCallbacks = _GBACoreAddCoreCallbacks;
|
||||||
|
core->clearCoreCallbacks = _GBACoreClearCoreCallbacks;
|
||||||
core->setAVStream = _GBACoreSetAVStream;
|
core->setAVStream = _GBACoreSetAVStream;
|
||||||
core->isROM = GBAIsROM;
|
core->isROM = GBAIsROM;
|
||||||
core->loadROM = _GBACoreLoadROM;
|
core->loadROM = _GBACoreLoadROM;
|
||||||
|
|
|
@ -91,7 +91,7 @@ static void GBAInit(void* cpu, struct mCPUComponent* component) {
|
||||||
gba->keyCallback = NULL;
|
gba->keyCallback = NULL;
|
||||||
gba->stopCallback = NULL;
|
gba->stopCallback = NULL;
|
||||||
gba->stopCallback = NULL;
|
gba->stopCallback = NULL;
|
||||||
gba->coreCallbacks = NULL;
|
mCoreCallbacksListInit(&gba->coreCallbacks, 0);
|
||||||
|
|
||||||
gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
|
gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
|
||||||
|
|
||||||
|
@ -152,6 +152,7 @@ void GBADestroy(struct GBA* gba) {
|
||||||
GBASIODeinit(&gba->sio);
|
GBASIODeinit(&gba->sio);
|
||||||
gba->rr = 0;
|
gba->rr = 0;
|
||||||
mTimingDeinit(&gba->timing);
|
mTimingDeinit(&gba->timing);
|
||||||
|
mCoreCallbacksListDeinit(&gba->coreCallbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh) {
|
void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh) {
|
||||||
|
@ -632,9 +633,12 @@ void GBABreakpoint(struct ARMCore* cpu, int immediate) {
|
||||||
void GBAFrameStarted(struct GBA* gba) {
|
void GBAFrameStarted(struct GBA* gba) {
|
||||||
UNUSED(gba);
|
UNUSED(gba);
|
||||||
|
|
||||||
struct mCoreCallbacks* callbacks = gba->coreCallbacks;
|
size_t c;
|
||||||
if (callbacks && callbacks->videoFrameStarted) {
|
for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) {
|
||||||
callbacks->videoFrameStarted(callbacks->context);
|
struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c);
|
||||||
|
if (callbacks->videoFrameEnded) {
|
||||||
|
callbacks->videoFrameStarted(callbacks->context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,9 +669,12 @@ void GBAFrameEnded(struct GBA* gba) {
|
||||||
GBAHardwarePlayerUpdate(gba);
|
GBAHardwarePlayerUpdate(gba);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mCoreCallbacks* callbacks = gba->coreCallbacks;
|
size_t c;
|
||||||
if (callbacks && callbacks->videoFrameEnded) {
|
for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) {
|
||||||
callbacks->videoFrameEnded(callbacks->context);
|
struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c);
|
||||||
|
if (callbacks->videoFrameEnded) {
|
||||||
|
callbacks->videoFrameEnded(callbacks->context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -303,9 +303,15 @@ 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) {
|
} else if (mCoreCallbacksListSize(&gba->coreCallbacks)) {
|
||||||
mLOG(GBA_MEM, GAME_ERROR, "Jumped to invalid address: %08X", address);
|
mLOG(GBA_MEM, GAME_ERROR, "Jumped to invalid address: %08X", address);
|
||||||
gba->coreCallbacks->coreCrashed(gba->coreCallbacks->context);
|
size_t c;
|
||||||
|
for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) {
|
||||||
|
struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c);
|
||||||
|
if (callbacks->coreCrashed) {
|
||||||
|
callbacks->coreCrashed(callbacks->context);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mLOG(GBA_MEM, FATAL, "Jumped to invalid address: %08X", address);
|
mLOG(GBA_MEM, FATAL, "Jumped to invalid address: %08X", address);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue