diff --git a/src/arm/arm.c b/src/arm/arm.c index b16c026c7..885a1bdcb 100644 --- a/src/arm/arm.c +++ b/src/arm/arm.c @@ -117,4 +117,7 @@ void ARMRun(struct ARMCore* cpu) { } else { ARMStep(cpu); } + if (cpu->cycles >= cpu->nextEvent) { + cpu->board->processEvents(cpu->board); + } } diff --git a/src/arm/arm.h b/src/arm/arm.h index 2635da3f8..b8ecafe08 100644 --- a/src/arm/arm.h +++ b/src/arm/arm.h @@ -87,7 +87,7 @@ struct ARMMemory { struct ARMBoard { struct ARMCore* cpu; void (*reset)(struct ARMBoard* board); - void (*nextEvent)(struct ARMBoard* board); + void (*processEvents)(struct ARMBoard* board); void (*swi16)(struct ARMBoard* board, int immediate); void (*swi32)(struct ARMBoard* board, int immediate); @@ -99,8 +99,8 @@ struct ARMCore { union PSR cpsr; union PSR spsr; - uint32_t cycles; - uint32_t nextEvent; + int32_t cycles; + int32_t nextEvent; int32_t bankedRegisters[6][7]; int32_t bankedSPSRs[6]; diff --git a/src/gba/gba-video.c b/src/gba/gba-video.c new file mode 100644 index 000000000..052fc031b --- /dev/null +++ b/src/gba/gba-video.c @@ -0,0 +1,27 @@ +#include "gba-video.h" + +#include + +void GBAVideoInit(struct GBAVideo* video) { + video->inHblank = 0; + video->inVblank = 0; + video->vcounter = 0; + video->vblankIRQ = 0; + video->hblankIRQ = 0; + video->vcounterIRQ = 0; + video->vcountSetting = 0; + + video->vcount = -1; + + video->lastHblank = 0; + video->nextHblank = VIDEO_HDRAW_LENGTH; + video->nextEvent = video->nextHblank; + + video->nextHblankIRQ = 0; + video->nextVblankIRQ = 0; + video->nextVcounterIRQ = 0; +} + +int32_t GBAVideoProcessEvents(struct GBAVideo* video, int32_t cycles) { + return INT_MAX; +} diff --git a/src/gba/gba-video.h b/src/gba/gba-video.h new file mode 100644 index 000000000..d04f2d5cc --- /dev/null +++ b/src/gba/gba-video.h @@ -0,0 +1,61 @@ +#ifndef GBA_VIDEO_H +#define GBA_VIDEO_H + +#include + +enum { + VIDEO_CYCLES_PER_PIXEL = 4, + + VIDEO_HORIZONTAL_PIXELS = 240, + VIDEO_HBLANK_PIXELS = 68, + VIDEO_HDRAW_LENGTH = 1006, + VIDEO_HBLANK_LENGTH = 226, + VIDEO_HORIZONTAL_LENGTH = 1232, + + VIDEO_VERTICAL_PIXELS = 160, + VIDEO_VBLANK_PIXELS = 68, + VIDEO_VERTICAL_TOTAL_PIXELS = 228, + + VIDEO_TOTAL_LENGTH = 280896, + + REG_DISPSTAT_MASK = 0xFF38 +}; + +struct GBAVideoRenderer { + void (*init)(struct GBAVideoRenderer* renderer); + void (*deinit)(struct GBAVideoRenderer* renderer); + + uint16_t (*writeVideoRegister)(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value); + void (*drawScanline)(struct GBAVideoRenderer* video, int y); + void (*finishFrame)(struct GBAVideoRenderer* video); +}; + +struct GBAVideo { + struct GBAVideoRenderer renderer; + + // DISPSTAT + int inHblank; + int inVblank; + int vcounter; + int blankIRQ; + int vblankIRQ; + int hblankIRQ; + int vcounterIRQ; + int vcountSetting; + + // VCOUNT + int vcount; + + int32_t lastHblank; + int32_t nextHblank; + int32_t nextEvent; + + int32_t nextHblankIRQ; + int32_t nextVblankIRQ; + int32_t nextVcounterIRQ; +}; + +void GBAVideoInit(struct GBAVideo* video); +int32_t GBAVideoProcessEvents(struct GBAVideo* video, int32_t cycles); + +#endif diff --git a/src/gba/gba.c b/src/gba/gba.c index bb3a25987..daec554f5 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -4,6 +4,7 @@ #include "debugger.h" +#include #include #include #include @@ -15,6 +16,7 @@ enum { SP_BASE_SUPERVISOR = 0x03FFFFE0 }; +static void GBAProcessEvents(struct ARMBoard* board); static void GBAHitStub(struct ARMBoard* board, uint32_t opcode); void GBAInit(struct GBA* gba) { @@ -40,6 +42,7 @@ void GBADeinit(struct GBA* gba) { void GBABoardInit(struct GBABoard* board) { board->d.reset = GBABoardReset; + board->d.processEvents = GBAProcessEvents; board->d.swi16 = GBASwi16; board->d.swi32 = GBASwi32; board->d.hitStub = GBAHitStub; @@ -55,6 +58,21 @@ void GBABoardReset(struct ARMBoard* board) { cpu->gprs[ARM_SP] = SP_BASE_SYSTEM; } +static void GBAProcessEvents(struct ARMBoard* board) { + struct GBABoard* gbaBoard = (struct GBABoard*) board; + int32_t cycles = board->cpu->cycles; + int32_t nextEvent = INT_MAX; + int32_t testEvent; + + testEvent = GBAVideoProcessEvents(&gbaBoard->p->video, cycles); + if (testEvent < nextEvent) { + nextEvent = testEvent; + } + + board->cpu->cycles = 0; + board->cpu->nextEvent = nextEvent; +} + void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger) { ARMDebuggerInit(debugger, &gba->cpu); gba->debugger = debugger; diff --git a/src/gba/gba.h b/src/gba/gba.h index 1257c94f4..896d909cd 100644 --- a/src/gba/gba.h +++ b/src/gba/gba.h @@ -4,6 +4,7 @@ #include "arm.h" #include "gba-memory.h" +#include "gba-video.h" enum GBAError { GBA_NO_ERROR = 0, @@ -23,6 +24,7 @@ struct GBA { struct ARMCore cpu; struct GBABoard board; struct GBAMemory memory; + struct GBAVideo video; struct ARMDebugger* debugger;