mirror of https://github.com/mgba-emu/mgba.git
Split gba.c
This commit is contained in:
parent
1ca6487151
commit
90e2443ccd
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
367
src/gba/gba.c
367
src/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";
|
||||
enum {
|
||||
SP_BASE_SYSTEM = 0x03FFFF00,
|
||||
SP_BASE_IRQ = 0x03FFFFA0,
|
||||
SP_BASE_SUPERVISOR = 0x03FFFFE0
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
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 @@ void GBALoadROM(struct GBA* gba, int fd) {
|
|||
// 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 @@ void GBAHitStub(struct ARMBoard* board, uint32_t opcode) {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
216
src/gba/gba.h
216
src/gba/gba.h
|
@ -1,8 +1,10 @@
|
|||
#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,
|
||||
GBA_OUT_OF_MEMORY = -1
|
||||
|
@ -12,216 +14,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 {
|
||||
struct ARMBoard d;
|
||||
struct GBA* p;
|
||||
|
|
Loading…
Reference in New Issue