src/gba/gba.c (view raw)
1#include "gba.h"
2
3#include "gba-bios.h"
4
5#include "debugger.h"
6
7#include <limits.h>
8#include <stdarg.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <sys/mman.h>
12
13enum {
14 SP_BASE_SYSTEM = 0x03FFFF00,
15 SP_BASE_IRQ = 0x03FFFFA0,
16 SP_BASE_SUPERVISOR = 0x03FFFFE0
17};
18
19static void GBAProcessEvents(struct ARMBoard* board);
20static void GBAHitStub(struct ARMBoard* board, uint32_t opcode);
21
22void GBAInit(struct GBA* gba) {
23 gba->errno = GBA_NO_ERROR;
24 gba->errstr = 0;
25
26 ARMInit(&gba->cpu);
27
28 gba->memory.p = gba;
29 GBAMemoryInit(&gba->memory);
30 ARMAssociateMemory(&gba->cpu, &gba->memory.d);
31
32 gba->board.p = gba;
33 GBABoardInit(&gba->board);
34 ARMAssociateBoard(&gba->cpu, &gba->board.d);
35
36 gba->video.p = gba;
37 GBAVideoInit(&gba->video);
38
39 ARMReset(&gba->cpu);
40}
41
42void GBADeinit(struct GBA* gba) {
43 GBAMemoryDeinit(&gba->memory);
44}
45
46void GBABoardInit(struct GBABoard* board) {
47 board->d.reset = GBABoardReset;
48 board->d.processEvents = GBAProcessEvents;
49 board->d.swi16 = GBASwi16;
50 board->d.swi32 = GBASwi32;
51 board->d.hitStub = GBAHitStub;
52}
53
54void GBABoardReset(struct ARMBoard* board) {
55 struct ARMCore* cpu = board->cpu;
56 ARMSetPrivilegeMode(cpu, MODE_IRQ);
57 cpu->gprs[ARM_SP] = SP_BASE_IRQ;
58 ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
59 cpu->gprs[ARM_SP] = SP_BASE_SUPERVISOR;
60 ARMSetPrivilegeMode(cpu, MODE_SYSTEM);
61 cpu->gprs[ARM_SP] = SP_BASE_SYSTEM;
62}
63
64static void GBAProcessEvents(struct ARMBoard* board) {
65 struct GBABoard* gbaBoard = (struct GBABoard*) board;
66 int32_t cycles = board->cpu->cycles;
67 int32_t nextEvent = INT_MAX;
68 int32_t testEvent;
69
70 testEvent = GBAVideoProcessEvents(&gbaBoard->p->video, cycles);
71 if (testEvent < nextEvent) {
72 nextEvent = testEvent;
73 }
74
75 board->cpu->cycles = 0;
76 board->cpu->nextEvent = nextEvent;
77}
78
79void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger) {
80 ARMDebuggerInit(debugger, &gba->cpu);
81 gba->debugger = debugger;
82}
83
84void GBALoadROM(struct GBA* gba, int fd) {
85 gba->memory.rom = mmap(0, SIZE_CART0, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0);
86 // TODO: error check
87}
88
89void GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq) {
90 GBALog(GBA_LOG_STUB, "Attempting to raise IRQ");
91}
92
93void GBALog(int level, const char* format, ...) {
94 va_list args;
95 va_start(args, format);
96 vprintf(format, args);
97 va_end(args);
98 printf("\n");
99}
100
101void GBAHitStub(struct ARMBoard* board, uint32_t opcode) {
102 GBALog(GBA_LOG_STUB, "Stub opcode: %08x", opcode);
103 struct GBABoard* gbaBoard = (struct GBABoard*) board;
104 if (!gbaBoard->p->debugger) {
105 abort();
106 } else {
107 ARMDebuggerEnter(gbaBoard->p->debugger);
108 }
109}