all repos — mgba @ 90e2443ccd0f525d67095d6b2c559d2a1fc245c4

mGBA Game Boy Advance Emulator

Split gba.c
Jeffrey Pfau jeffrey@endrift.com
Sun, 14 Apr 2013 13:21:21 -0700
commit

90e2443ccd0f525d67095d6b2c559d2a1fc245c4

parent

1ca648715166fbca34ec4bef3ac591d9ce3a0869

A src/gba/gba-bios.c

@@ -0,0 +1,14 @@

+#include "gba-bios.h" + +#include "gba.h" + +void GBASwi16(struct ARMBoard* board, int immediate) { + switch (immediate) { + default: + GBALog(GBA_LOG_STUB, "Stub software interrupt: %02x", immediate); + } +} + +void GBASwi32(struct ARMBoard* board, int immediate) { + GBASwi32(board, immediate >> 8); +}
A src/gba/gba-bios.h

@@ -0,0 +1,9 @@

+#ifndef GBA_BIOS_H +#define GBA_BIOS_H + +#include "arm.h" + +void GBASwi16(struct ARMBoard* board, int immediate); +void GBASwi32(struct ARMBoard* board, int immediate); + +#endif
A src/gba/gba-io.c

@@ -0,0 +1,9 @@

+#include "gba-io.h" + +void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { + switch (address) { + default: + GBALog(GBA_LOG_STUB, "Stub I/O register: %03x", address); + break; + } +}
A src/gba/gba-io.h

@@ -0,0 +1,146 @@

+#ifndef GBA_IO_H +#define GBA_IO_H + +#include "gba.h" + +enum GBAIORegisters { + REG_DISPCNT = 0x000, + REG_GREENSWP = 0x002, + REG_DISPSTAT = 0x004, + REG_VCOUNT = 0x006, + REG_BG0CNT = 0x008, + REG_BG1CNT = 0x00A, + REG_BG2CNT = 0x00C, + REG_BG3CNT = 0x00E, + REG_BG0HOFS = 0x010, + REG_BG0VOFS = 0x012, + REG_BG1HOFS = 0x014, + REG_BG1VOFS = 0x016, + REG_BG2HOFS = 0x018, + REG_BG2VOFS = 0x01A, + REG_BG3HOFS = 0x01C, + REG_BG3VOFS = 0x01E, + REG_BG2PA = 0x020, + REG_BG2PB = 0x022, + REG_BG2PC = 0x024, + REG_BG2PD = 0x026, + REG_BG2X_LO = 0x028, + REG_BG2X_HI = 0x02A, + REG_BG2Y_LO = 0x02C, + REG_BG2Y_HI = 0x02E, + REG_BG3PA = 0x030, + REG_BG3PB = 0x032, + REG_BG3PC = 0x034, + REG_BG3PD = 0x036, + REG_BG3X_LO = 0x038, + REG_BG3X_HI = 0x03A, + REG_BG3Y_LO = 0x03C, + REG_BG3Y_HI = 0x03E, + REG_WIN0H = 0x040, + REG_WIN1H = 0x042, + REG_WIN0V = 0x044, + REG_WIN1V = 0x046, + REG_WININ = 0x048, + REG_WINOUT = 0x04A, + REG_MOSAIC = 0x04C, + REG_BLDCNT = 0x050, + REG_BLDALPHA = 0x052, + REG_BLDY = 0x054, + + // Sound + REG_SOUND1CNT_LO = 0x060, + REG_SOUND1CNT_HI = 0x062, + REG_SOUND1CNT_X = 0x064, + REG_SOUND2CNT_LO = 0x068, + REG_SOUND2CNT_HI = 0x06C, + REG_SOUND3CNT_LO = 0x070, + REG_SOUND3CNT_HI = 0x072, + REG_SOUND3CNT_X = 0x074, + REG_SOUND4CNT_LO = 0x078, + REG_SOUND4CNT_HI = 0x07C, + REG_SOUNDCNT_LO = 0x080, + REG_SOUNDCNT_HI = 0x082, + REG_SOUNDCNT_X = 0x084, + REG_SOUNDBIAS = 0x088, + REG_WAVE_RAM0_LO = 0x090, + REG_WAVE_RAM0_HI = 0x092, + REG_WAVE_RAM1_LO = 0x094, + REG_WAVE_RAM1_HI = 0x096, + REG_WAVE_RAM2_LO = 0x098, + REG_WAVE_RAM2_HI = 0x09A, + REG_WAVE_RAM3_LO = 0x09C, + REG_WAVE_RAM3_HI = 0x09E, + REG_FIFO_A_LO = 0x0A0, + REG_FIFO_A_HI = 0x0A2, + REG_FIFO_B_LO = 0x0A4, + REG_FIFO_B_HI = 0x0A6, + + // DMA + REG_DMA0SAD_LO = 0x0B0, + REG_DMA0SAD_HI = 0x0B2, + REG_DMA0DAD_LO = 0x0B4, + REG_DMA0DAD_HI = 0x0B6, + REG_DMA0CNT_LO = 0x0B8, + REG_DMA0CNT_HI = 0x0BA, + REG_DMA1SAD_LO = 0x0BC, + REG_DMA1SAD_HI = 0x0BE, + REG_DMA1DAD_LO = 0x0C0, + REG_DMA1DAD_HI = 0x0C2, + REG_DMA1CNT_LO = 0x0C4, + REG_DMA1CNT_HI = 0x0C6, + REG_DMA2SAD_LO = 0x0C8, + REG_DMA2SAD_HI = 0x0CA, + REG_DMA2DAD_LO = 0x0CC, + REG_DMA2DAD_HI = 0x0CE, + REG_DMA2CNT_LO = 0x0D0, + REG_DMA2CNT_HI = 0x0D2, + REG_DMA3SAD_LO = 0x0D4, + REG_DMA3SAD_HI = 0x0D6, + REG_DMA3DAD_LO = 0x0D8, + REG_DMA3DAD_HI = 0x0DA, + REG_DMA3CNT_LO = 0x0DC, + REG_DMA3CNT_HI = 0x0DE, + + // Timers + REG_TM0CNT_LO = 0x100, + REG_TM0CNT_HI = 0x102, + REG_TM1CNT_LO = 0x104, + REG_TM1CNT_HI = 0x106, + REG_TM2CNT_LO = 0x108, + REG_TM2CNT_HI = 0x10A, + REG_TM3CNT_LO = 0x10C, + REG_TM3CNT_HI = 0x10E, + + // SIO (note: some of these are repeated) + REG_SIODATA32_LO = 0x120, + REG_SIOMULTI0 = 0x120, + REG_SIODATA32_HI = 0x122, + REG_SIOMULTI1 = 0x122, + REG_SIOMULTI2 = 0x124, + REG_SIOMULTI3 = 0x126, + REG_SIOCNT = 0x128, + REG_SIOMLT_SEND = 0x12A, + REG_SIODATA8 = 0x12A, + REG_RCNT = 0x134, + REG_JOYCNT = 0x140, + REG_JOY_RECV = 0x150, + REG_JOY_TRANS = 0x154, + REG_JOYSTAT = 0x158, + + // Keypad + REG_KEYINPUT = 0x130, + REG_KEYCNT = 0x132, + + // Interrupts, etc + REG_IE = 0x200, + REG_IF = 0x202, + REG_WAITCNT = 0x204, + REG_IME = 0x208, + + REG_POSTFLG = 0x300, + REG_HALTCNT = 0x301 +}; + +void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value); + +#endif
A src/gba/gba-memory.c

@@ -0,0 +1,344 @@

+#include "gba-memory.h" + +#include "gba-io.h" + +#include <string.h> +#include <sys/mman.h> + +static const char* GBA_CANNOT_MMAP = "Could not map memory"; + +static int32_t GBALoad32(struct ARMMemory* memory, uint32_t address); +static int16_t GBALoad16(struct ARMMemory* memory, uint32_t address); +static uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address); +static int8_t GBALoad8(struct ARMMemory* memory, uint32_t address); +static uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address); + +static void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value); +static void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value); +static void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value); + +static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t region); + +void GBAMemoryInit(struct GBAMemory* memory) { + memory->d.load32 = GBALoad32; + memory->d.load16 = GBALoad16; + memory->d.loadU16 = GBALoadU16; + memory->d.load8 = GBALoad8; + memory->d.loadU8 = GBALoadU8; + memory->d.store32 = GBAStore32; + memory->d.store16 = GBAStore16; + memory->d.store8 = GBAStore8; + + memory->bios = 0; + memory->wram = mmap(0, SIZE_WORKING_RAM, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + memory->iwram = mmap(0, SIZE_WORKING_IRAM, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + memory->rom = 0; + memset(memory->io, 0, sizeof(memory->io)); + + if (!memory->wram || !memory->iwram) { + GBAMemoryDeinit(memory); + memory->p->errno = GBA_OUT_OF_MEMORY; + memory->p->errstr = GBA_CANNOT_MMAP; + } + + memory->d.activeRegion = 0; + memory->d.activeMask = 0; + memory->d.setActiveRegion = GBASetActiveRegion; +} + +void GBAMemoryDeinit(struct GBAMemory* memory) { + munmap(memory->wram, SIZE_WORKING_RAM); + munmap(memory->iwram, SIZE_WORKING_IRAM); +} + +static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) { + struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + + switch (address & ~OFFSET_MASK) { + case BASE_BIOS: + memory->activeRegion = gbaMemory->bios; + memory->activeMask = 0; + break; + case BASE_WORKING_RAM: + memory->activeRegion = gbaMemory->wram; + memory->activeMask = SIZE_WORKING_RAM - 1; + break; + case BASE_WORKING_IRAM: + memory->activeRegion = gbaMemory->iwram; + memory->activeMask = SIZE_WORKING_IRAM - 1; + break; + case BASE_CART0: + case BASE_CART0_EX: + case BASE_CART1: + case BASE_CART1_EX: + case BASE_CART2: + case BASE_CART2_EX: + memory->activeRegion = gbaMemory->rom; + memory->activeMask = SIZE_CART0 - 1; + break; + default: + memory->activeRegion = 0; + memory->activeMask = 0; + break; + } +} + +int32_t GBALoad32(struct ARMMemory* memory, uint32_t address) { + struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + + switch (address & ~OFFSET_MASK) { + case BASE_BIOS: + break; + case BASE_WORKING_RAM: + return gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2]; + case BASE_WORKING_IRAM: + return gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2]; + case BASE_IO: + break; + case BASE_PALETTE_RAM: + break; + case BASE_VRAM: + break; + case BASE_OAM: + break; + case BASE_CART0: + case BASE_CART0_EX: + case BASE_CART1: + case BASE_CART1_EX: + case BASE_CART2: + case BASE_CART2_EX: + return gbaMemory->rom[(address & (SIZE_CART0 - 1)) >> 2]; + case BASE_CART_SRAM: + break; + default: + break; + } + + return 0; +} + +int16_t GBALoad16(struct ARMMemory* memory, uint32_t address) { + struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + + switch (address & ~OFFSET_MASK) { + case BASE_BIOS: + break; + case BASE_WORKING_RAM: + return ((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1]; + case BASE_WORKING_IRAM: + return ((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1]; + case BASE_IO: + break; + case BASE_PALETTE_RAM: + break; + case BASE_VRAM: + break; + case BASE_OAM: + break; + case BASE_CART0: + case BASE_CART0_EX: + case BASE_CART1: + case BASE_CART1_EX: + case BASE_CART2: + case BASE_CART2_EX: + return ((int16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1]; + case BASE_CART_SRAM: + break; + default: + break; + } + + return 0; +} + +uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address) { + struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + + switch (address & ~OFFSET_MASK) { + case BASE_BIOS: + break; + case BASE_WORKING_RAM: + return ((uint16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1]; + case BASE_WORKING_IRAM: + return ((uint16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1]; + case BASE_IO: + break; + case BASE_PALETTE_RAM: + break; + case BASE_VRAM: + break; + case BASE_OAM: + break; + case BASE_CART0: + case BASE_CART0_EX: + case BASE_CART1: + case BASE_CART1_EX: + case BASE_CART2: + case BASE_CART2_EX: + return ((uint16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1]; + case BASE_CART_SRAM: + break; + default: + break; + } + + return 0; +} + +int8_t GBALoad8(struct ARMMemory* memory, uint32_t address) { + struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + + switch (address & ~OFFSET_MASK) { + case BASE_BIOS: + break; + case BASE_WORKING_RAM: + return ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)]; + case BASE_WORKING_IRAM: + return ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)]; + case BASE_IO: + break; + case BASE_PALETTE_RAM: + break; + case BASE_VRAM: + break; + case BASE_OAM: + break; + case BASE_CART0: + case BASE_CART0_EX: + case BASE_CART1: + case BASE_CART1_EX: + case BASE_CART2: + case BASE_CART2_EX: + return ((int8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)]; + case BASE_CART_SRAM: + break; + default: + break; + } + + return 0; +} + +uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address) { + struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + + switch (address & ~OFFSET_MASK) { + case BASE_BIOS: + break; + case BASE_WORKING_RAM: + return ((uint8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)]; + break; + case BASE_WORKING_IRAM: + return ((uint8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)]; + break; + case BASE_IO: + break; + case BASE_PALETTE_RAM: + break; + case BASE_VRAM: + break; + case BASE_OAM: + break; + case BASE_CART0: + case BASE_CART0_EX: + case BASE_CART1: + case BASE_CART1_EX: + case BASE_CART2: + case BASE_CART2_EX: + return ((uint8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)]; + case BASE_CART_SRAM: + break; + default: + break; + } + + return 0; +} + +void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value) { + struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + + switch (address & ~OFFSET_MASK) { + case BASE_WORKING_RAM: + gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2] = value; + break; + case BASE_WORKING_IRAM: + gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2] = value; + break; + case BASE_IO: + break; + case BASE_PALETTE_RAM: + break; + case BASE_VRAM: + break; + case BASE_OAM: + break; + case BASE_CART0: + break; + case BASE_CART2_EX: + break; + case BASE_CART_SRAM: + break; + default: + break; + } +} + +void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value) { + struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + + switch (address & ~OFFSET_MASK) { + case BASE_WORKING_RAM: + ((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1] = value; + break; + case BASE_WORKING_IRAM: + ((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1] = value; + break; + case BASE_IO: + GBAIOWrite(gbaMemory->p, address & (SIZE_IO - 1), value); + break; + case BASE_PALETTE_RAM: + break; + case BASE_VRAM: + break; + case BASE_OAM: + break; + case BASE_CART0: + break; + case BASE_CART2_EX: + break; + case BASE_CART_SRAM: + break; + default: + break; + } +} + +void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value) { + struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + + switch (address & ~OFFSET_MASK) { + case BASE_WORKING_RAM: + ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)] = value; + break; + case BASE_WORKING_IRAM: + ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value; + break; + case BASE_IO: + break; + case BASE_PALETTE_RAM: + break; + case BASE_VRAM: + break; + case BASE_OAM: + break; + case BASE_CART0: + break; + case BASE_CART2_EX: + break; + case BASE_CART_SRAM: + break; + default: + break; + } +}
A src/gba/gba-memory.h

@@ -0,0 +1,72 @@

+#ifndef GBA_MEMORY_H +#define GBA_MEMORY_H + +#include "arm.h" + +enum GBAMemoryRegion { + REGION_BIOS = 0x0, + REGION_WORKING_RAM = 0x2, + REGION_WORKING_IRAM = 0x3, + REGION_IO = 0x4, + REGION_PALETTE_RAM = 0x5, + REGION_VRAM = 0x6, + REGION_OAM = 0x7, + REGION_CART0 = 0x8, + REGION_CART0_EX = 0x9, + REGION_CART1 = 0xA, + REGION_CART1_EX = 0xB, + REGION_CART2 = 0xC, + REGION_CART2_EX = 0xD, + REGION_CART_SRAM = 0xE +}; + +enum GBAMemoryBase { + BASE_BIOS = 0x00000000, + BASE_WORKING_RAM = 0x02000000, + BASE_WORKING_IRAM = 0x03000000, + BASE_IO = 0x04000000, + BASE_PALETTE_RAM = 0x05000000, + BASE_VRAM = 0x06000000, + BASE_OAM = 0x07000000, + BASE_CART0 = 0x08000000, + BASE_CART0_EX = 0x09000000, + BASE_CART1 = 0x0A000000, + BASE_CART1_EX = 0x0B000000, + BASE_CART2 = 0x0C000000, + BASE_CART2_EX = 0x0D000000, + BASE_CART_SRAM = 0x0E000000 +}; + +enum { + SIZE_BIOS = 0x00004000, + SIZE_WORKING_RAM = 0x00040000, + SIZE_WORKING_IRAM = 0x00008000, + SIZE_IO = 0x00000400, + SIZE_PALETTE_RAM = 0x00000400, + SIZE_VRAM = 0x00018000, + SIZE_OAM = 0x00000400, + SIZE_CART0 = 0x02000000, + SIZE_CART1 = 0x02000000, + SIZE_CART2 = 0x02000000, + SIZE_CART_SRAM = 0x00008000, + SIZE_CART_FLASH512 = 0x00010000, + SIZE_CART_FLASH1M = 0x00020000, + SIZE_CART_EEPROM = 0x00002000 +}; + +enum { + OFFSET_MASK = 0x00FFFFFF +}; + +struct GBAMemory { + struct ARMMemory d; + struct GBA* p; + + uint32_t* bios; + uint32_t* wram; + uint32_t* iwram; + uint32_t* rom; + uint16_t io[SIZE_IO >> 1]; +}; + +#endif
M src/gba/gba.csrc/gba/gba.c

@@ -1,30 +1,20 @@

#include "gba.h" +#include "gba-bios.h" + #include "debugger.h" #include <stdarg.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <sys/mman.h> -#include <unistd.h> - -static const char* GBA_CANNOT_MMAP = "Could not map memory"; -static int32_t GBALoad32(struct ARMMemory* memory, uint32_t address); -static int16_t GBALoad16(struct ARMMemory* memory, uint32_t address); -static uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address); -static int8_t GBALoad8(struct ARMMemory* memory, uint32_t address); -static uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address); - -static void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value); -static void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value); -static void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value); - -static void GBASwi16(struct ARMBoard* board, int immediate); -static void GBASwi32(struct ARMBoard* board, int immediate); +enum { + SP_BASE_SYSTEM = 0x03FFFF00, + SP_BASE_IRQ = 0x03FFFFA0, + SP_BASE_SUPERVISOR = 0x03FFFFE0 +}; -static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t region); static void GBAHitStub(struct ARMBoard* board, uint32_t opcode); static void _GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value);

@@ -50,38 +40,6 @@ void GBADeinit(struct GBA* gba) {

GBAMemoryDeinit(&gba->memory); } -void GBAMemoryInit(struct GBAMemory* memory) { - memory->d.load32 = GBALoad32; - memory->d.load16 = GBALoad16; - memory->d.loadU16 = GBALoadU16; - memory->d.load8 = GBALoad8; - memory->d.loadU8 = GBALoadU8; - memory->d.store32 = GBAStore32; - memory->d.store16 = GBAStore16; - memory->d.store8 = GBAStore8; - - memory->bios = 0; - memory->wram = mmap(0, SIZE_WORKING_RAM, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - memory->iwram = mmap(0, SIZE_WORKING_IRAM, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - memory->rom = 0; - memset(memory->io, 0, sizeof(memory->io)); - - if (!memory->wram || !memory->iwram) { - GBAMemoryDeinit(memory); - memory->p->errno = GBA_OUT_OF_MEMORY; - memory->p->errstr = GBA_CANNOT_MMAP; - } - - memory->d.activeRegion = 0; - memory->d.activeMask = 0; - memory->d.setActiveRegion = GBASetActiveRegion; -} - -void GBAMemoryDeinit(struct GBAMemory* memory) { - munmap(memory->wram, SIZE_WORKING_RAM); - munmap(memory->iwram, SIZE_WORKING_IRAM); -} - void GBABoardInit(struct GBABoard* board) { board->d.reset = GBABoardReset; board->d.swi16 = GBASwi16;

@@ -109,309 +67,6 @@ gba->memory.rom = mmap(0, SIZE_CART0, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0);

// TODO: error check } -static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) { - struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; - - switch (address & ~OFFSET_MASK) { - case BASE_BIOS: - memory->activeRegion = gbaMemory->bios; - memory->activeMask = 0; - break; - case BASE_WORKING_RAM: - memory->activeRegion = gbaMemory->wram; - memory->activeMask = SIZE_WORKING_RAM - 1; - break; - case BASE_WORKING_IRAM: - memory->activeRegion = gbaMemory->iwram; - memory->activeMask = SIZE_WORKING_IRAM - 1; - break; - case BASE_CART0: - case BASE_CART0_EX: - case BASE_CART1: - case BASE_CART1_EX: - case BASE_CART2: - case BASE_CART2_EX: - memory->activeRegion = gbaMemory->rom; - memory->activeMask = SIZE_CART0 - 1; - break; - default: - memory->activeRegion = 0; - memory->activeMask = 0; - break; - } -} - -int32_t GBALoad32(struct ARMMemory* memory, uint32_t address) { - struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; - - switch (address & ~OFFSET_MASK) { - case BASE_BIOS: - break; - case BASE_WORKING_RAM: - return gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2]; - case BASE_WORKING_IRAM: - return gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2]; - case BASE_IO: - break; - case BASE_PALETTE_RAM: - break; - case BASE_VRAM: - break; - case BASE_OAM: - break; - case BASE_CART0: - case BASE_CART0_EX: - case BASE_CART1: - case BASE_CART1_EX: - case BASE_CART2: - case BASE_CART2_EX: - return gbaMemory->rom[(address & (SIZE_CART0 - 1)) >> 2]; - case BASE_CART_SRAM: - break; - default: - break; - } - - return 0; -} - -int16_t GBALoad16(struct ARMMemory* memory, uint32_t address) { - struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; - - switch (address & ~OFFSET_MASK) { - case BASE_BIOS: - break; - case BASE_WORKING_RAM: - return ((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1]; - case BASE_WORKING_IRAM: - return ((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1]; - case BASE_IO: - break; - case BASE_PALETTE_RAM: - break; - case BASE_VRAM: - break; - case BASE_OAM: - break; - case BASE_CART0: - case BASE_CART0_EX: - case BASE_CART1: - case BASE_CART1_EX: - case BASE_CART2: - case BASE_CART2_EX: - return ((int16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1]; - case BASE_CART_SRAM: - break; - default: - break; - } - - return 0; -} - -uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address) { - struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; - - switch (address & ~OFFSET_MASK) { - case BASE_BIOS: - break; - case BASE_WORKING_RAM: - return ((uint16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1]; - case BASE_WORKING_IRAM: - return ((uint16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1]; - case BASE_IO: - break; - case BASE_PALETTE_RAM: - break; - case BASE_VRAM: - break; - case BASE_OAM: - break; - case BASE_CART0: - case BASE_CART0_EX: - case BASE_CART1: - case BASE_CART1_EX: - case BASE_CART2: - case BASE_CART2_EX: - return ((uint16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1]; - case BASE_CART_SRAM: - break; - default: - break; - } - - return 0; -} - -int8_t GBALoad8(struct ARMMemory* memory, uint32_t address) { - struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; - - switch (address & ~OFFSET_MASK) { - case BASE_BIOS: - break; - case BASE_WORKING_RAM: - return ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)]; - case BASE_WORKING_IRAM: - return ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)]; - case BASE_IO: - break; - case BASE_PALETTE_RAM: - break; - case BASE_VRAM: - break; - case BASE_OAM: - break; - case BASE_CART0: - case BASE_CART0_EX: - case BASE_CART1: - case BASE_CART1_EX: - case BASE_CART2: - case BASE_CART2_EX: - return ((int8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)]; - case BASE_CART_SRAM: - break; - default: - break; - } - - return 0; -} - -uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address) { - struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; - - switch (address & ~OFFSET_MASK) { - case BASE_BIOS: - break; - case BASE_WORKING_RAM: - return ((uint8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)]; - break; - case BASE_WORKING_IRAM: - return ((uint8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)]; - break; - case BASE_IO: - break; - case BASE_PALETTE_RAM: - break; - case BASE_VRAM: - break; - case BASE_OAM: - break; - case BASE_CART0: - case BASE_CART0_EX: - case BASE_CART1: - case BASE_CART1_EX: - case BASE_CART2: - case BASE_CART2_EX: - return ((uint8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)]; - case BASE_CART_SRAM: - break; - default: - break; - } - - return 0; -} - -void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value) { - struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; - - switch (address & ~OFFSET_MASK) { - case BASE_WORKING_RAM: - gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2] = value; - break; - case BASE_WORKING_IRAM: - gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2] = value; - break; - case BASE_IO: - break; - case BASE_PALETTE_RAM: - break; - case BASE_VRAM: - break; - case BASE_OAM: - break; - case BASE_CART0: - break; - case BASE_CART2_EX: - break; - case BASE_CART_SRAM: - break; - default: - break; - } -} - -void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value) { - struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; - - switch (address & ~OFFSET_MASK) { - case BASE_WORKING_RAM: - ((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1] = value; - break; - case BASE_WORKING_IRAM: - ((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1] = value; - break; - case BASE_IO: - _GBAIOWrite(gbaMemory->p, address & (SIZE_IO - 1), value); - break; - case BASE_PALETTE_RAM: - break; - case BASE_VRAM: - break; - case BASE_OAM: - break; - case BASE_CART0: - break; - case BASE_CART2_EX: - break; - case BASE_CART_SRAM: - break; - default: - break; - } -} - -void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value) { - struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; - - switch (address & ~OFFSET_MASK) { - case BASE_WORKING_RAM: - ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)] = value; - break; - case BASE_WORKING_IRAM: - ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value; - break; - case BASE_IO: - break; - case BASE_PALETTE_RAM: - break; - case BASE_VRAM: - break; - case BASE_OAM: - break; - case BASE_CART0: - break; - case BASE_CART2_EX: - break; - case BASE_CART_SRAM: - break; - default: - break; - } -} - -static void GBASwi16(struct ARMBoard* board, int immediate) { - switch (immediate) { - default: - GBALog(GBA_LOG_STUB, "Stub software interrupt: %02x", immediate); - } -} - -static void GBASwi32(struct ARMBoard* board, int immediate) { - GBASwi32(board, immediate >> 8); -} - void GBALog(int level, const char* format, ...) { va_list args; va_start(args, format);

@@ -429,11 +84,3 @@ } else {

ARMDebuggerEnter(gbaBoard->p->debugger); } } - -static void _GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { - switch (address) { - default: - GBALog(GBA_LOG_STUB, "Stub I/O register: %03x", address); - break; - } -}
M src/gba/gba.hsrc/gba/gba.h

@@ -1,7 +1,9 @@

-#ifndef GBA_MEMORY_H -#define GBA_MEMORY_H +#ifndef GBA_H +#define GBA_H #include "arm.h" + +#include "gba-memory.h" enum GBAError { GBA_NO_ERROR = 0,

@@ -10,216 +12,6 @@ };

enum GBALogLevel { GBA_LOG_STUB -}; - -enum GBAMemoryRegion { - REGION_BIOS = 0x0, - REGION_WORKING_RAM = 0x2, - REGION_WORKING_IRAM = 0x3, - REGION_IO = 0x4, - REGION_PALETTE_RAM = 0x5, - REGION_VRAM = 0x6, - REGION_OAM = 0x7, - REGION_CART0 = 0x8, - REGION_CART0_EX = 0x9, - REGION_CART1 = 0xA, - REGION_CART1_EX = 0xB, - REGION_CART2 = 0xC, - REGION_CART2_EX = 0xD, - REGION_CART_SRAM = 0xE -}; - -enum GBAMemoryBase { - BASE_BIOS = 0x00000000, - BASE_WORKING_RAM = 0x02000000, - BASE_WORKING_IRAM = 0x03000000, - BASE_IO = 0x04000000, - BASE_PALETTE_RAM = 0x05000000, - BASE_VRAM = 0x06000000, - BASE_OAM = 0x07000000, - BASE_CART0 = 0x08000000, - BASE_CART0_EX = 0x09000000, - BASE_CART1 = 0x0A000000, - BASE_CART1_EX = 0x0B000000, - BASE_CART2 = 0x0C000000, - BASE_CART2_EX = 0x0D000000, - BASE_CART_SRAM = 0x0E000000 -}; - -enum { - SIZE_BIOS = 0x00004000, - SIZE_WORKING_RAM = 0x00040000, - SIZE_WORKING_IRAM = 0x00008000, - SIZE_IO = 0x00000400, - SIZE_PALETTE_RAM = 0x00000400, - SIZE_VRAM = 0x00018000, - SIZE_OAM = 0x00000400, - SIZE_CART0 = 0x02000000, - SIZE_CART1 = 0x02000000, - SIZE_CART2 = 0x02000000, - SIZE_CART_SRAM = 0x00008000, - SIZE_CART_FLASH512 = 0x00010000, - SIZE_CART_FLASH1M = 0x00020000, - SIZE_CART_EEPROM = 0x00002000 -}; - -enum GBAIORegisters { - REG_DISPCNT = 0x000, - REG_GREENSWP = 0x002, - REG_DISPSTAT = 0x004, - REG_VCOUNT = 0x006, - REG_BG0CNT = 0x008, - REG_BG1CNT = 0x00A, - REG_BG2CNT = 0x00C, - REG_BG3CNT = 0x00E, - REG_BG0HOFS = 0x010, - REG_BG0VOFS = 0x012, - REG_BG1HOFS = 0x014, - REG_BG1VOFS = 0x016, - REG_BG2HOFS = 0x018, - REG_BG2VOFS = 0x01A, - REG_BG3HOFS = 0x01C, - REG_BG3VOFS = 0x01E, - REG_BG2PA = 0x020, - REG_BG2PB = 0x022, - REG_BG2PC = 0x024, - REG_BG2PD = 0x026, - REG_BG2X_LO = 0x028, - REG_BG2X_HI = 0x02A, - REG_BG2Y_LO = 0x02C, - REG_BG2Y_HI = 0x02E, - REG_BG3PA = 0x030, - REG_BG3PB = 0x032, - REG_BG3PC = 0x034, - REG_BG3PD = 0x036, - REG_BG3X_LO = 0x038, - REG_BG3X_HI = 0x03A, - REG_BG3Y_LO = 0x03C, - REG_BG3Y_HI = 0x03E, - REG_WIN0H = 0x040, - REG_WIN1H = 0x042, - REG_WIN0V = 0x044, - REG_WIN1V = 0x046, - REG_WININ = 0x048, - REG_WINOUT = 0x04A, - REG_MOSAIC = 0x04C, - REG_BLDCNT = 0x050, - REG_BLDALPHA = 0x052, - REG_BLDY = 0x054, - - // Sound - REG_SOUND1CNT_LO = 0x060, - REG_SOUND1CNT_HI = 0x062, - REG_SOUND1CNT_X = 0x064, - REG_SOUND2CNT_LO = 0x068, - REG_SOUND2CNT_HI = 0x06C, - REG_SOUND3CNT_LO = 0x070, - REG_SOUND3CNT_HI = 0x072, - REG_SOUND3CNT_X = 0x074, - REG_SOUND4CNT_LO = 0x078, - REG_SOUND4CNT_HI = 0x07C, - REG_SOUNDCNT_LO = 0x080, - REG_SOUNDCNT_HI = 0x082, - REG_SOUNDCNT_X = 0x084, - REG_SOUNDBIAS = 0x088, - REG_WAVE_RAM0_LO = 0x090, - REG_WAVE_RAM0_HI = 0x092, - REG_WAVE_RAM1_LO = 0x094, - REG_WAVE_RAM1_HI = 0x096, - REG_WAVE_RAM2_LO = 0x098, - REG_WAVE_RAM2_HI = 0x09A, - REG_WAVE_RAM3_LO = 0x09C, - REG_WAVE_RAM3_HI = 0x09E, - REG_FIFO_A_LO = 0x0A0, - REG_FIFO_A_HI = 0x0A2, - REG_FIFO_B_LO = 0x0A4, - REG_FIFO_B_HI = 0x0A6, - - // DMA - REG_DMA0SAD_LO = 0x0B0, - REG_DMA0SAD_HI = 0x0B2, - REG_DMA0DAD_LO = 0x0B4, - REG_DMA0DAD_HI = 0x0B6, - REG_DMA0CNT_LO = 0x0B8, - REG_DMA0CNT_HI = 0x0BA, - REG_DMA1SAD_LO = 0x0BC, - REG_DMA1SAD_HI = 0x0BE, - REG_DMA1DAD_LO = 0x0C0, - REG_DMA1DAD_HI = 0x0C2, - REG_DMA1CNT_LO = 0x0C4, - REG_DMA1CNT_HI = 0x0C6, - REG_DMA2SAD_LO = 0x0C8, - REG_DMA2SAD_HI = 0x0CA, - REG_DMA2DAD_LO = 0x0CC, - REG_DMA2DAD_HI = 0x0CE, - REG_DMA2CNT_LO = 0x0D0, - REG_DMA2CNT_HI = 0x0D2, - REG_DMA3SAD_LO = 0x0D4, - REG_DMA3SAD_HI = 0x0D6, - REG_DMA3DAD_LO = 0x0D8, - REG_DMA3DAD_HI = 0x0DA, - REG_DMA3CNT_LO = 0x0DC, - REG_DMA3CNT_HI = 0x0DE, - - // Timers - REG_TM0CNT_LO = 0x100, - REG_TM0CNT_HI = 0x102, - REG_TM1CNT_LO = 0x104, - REG_TM1CNT_HI = 0x106, - REG_TM2CNT_LO = 0x108, - REG_TM2CNT_HI = 0x10A, - REG_TM3CNT_LO = 0x10C, - REG_TM3CNT_HI = 0x10E, - - // SIO (note: some of these are repeated) - REG_SIODATA32_LO = 0x120, - REG_SIOMULTI0 = 0x120, - REG_SIODATA32_HI = 0x122, - REG_SIOMULTI1 = 0x122, - REG_SIOMULTI2 = 0x124, - REG_SIOMULTI3 = 0x126, - REG_SIOCNT = 0x128, - REG_SIOMLT_SEND = 0x12A, - REG_SIODATA8 = 0x12A, - REG_RCNT = 0x134, - REG_JOYCNT = 0x140, - REG_JOY_RECV = 0x150, - REG_JOY_TRANS = 0x154, - REG_JOYSTAT = 0x158, - - // Keypad - REG_KEYINPUT = 0x130, - REG_KEYCNT = 0x132, - - // Interrupts, etc - REG_IE = 0x200, - REG_IF = 0x202, - REG_WAITCNT = 0x204, - REG_IME = 0x208, - - REG_POSTFLG = 0x300, - REG_HALTCNT = 0x301 -}; - -enum { - SP_BASE_SYSTEM = 0x03FFFF00, - SP_BASE_IRQ = 0x03FFFFA0, - SP_BASE_SUPERVISOR = 0x03FFFFE0 -}; - -enum { - OFFSET_MASK = 0x00FFFFFF -}; - -struct GBAMemory { - struct ARMMemory d; - struct GBA* p; - - uint32_t* bios; - uint32_t* wram; - uint32_t* iwram; - uint32_t* rom; - uint16_t io[SIZE_IO >> 1]; }; struct GBABoard {