mgba/src/gba.c

370 lines
8.2 KiB
C
Raw Normal View History

2013-04-05 09:17:22 +00:00
#include "gba.h"
#include <sys/mman.h>
2013-04-07 08:46:28 +00:00
#include <unistd.h>
2013-04-05 09:17:22 +00:00
2013-04-06 11:34:19 +00:00
static const char* GBA_CANNOT_MMAP = "Could not map memory";
2013-04-10 05:20:35 +00:00
static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t region);
2013-04-05 09:17:22 +00:00
void GBAInit(struct GBA* gba) {
2013-04-06 11:34:19 +00:00
gba->errno = GBA_NO_ERROR;
gba->errstr = 0;
2013-04-05 09:17:22 +00:00
ARMInit(&gba->cpu);
2013-04-06 11:34:19 +00:00
2013-04-06 11:20:44 +00:00
gba->memory.p = gba;
2013-04-05 09:17:22 +00:00
GBAMemoryInit(&gba->memory);
2013-04-07 08:46:28 +00:00
ARMAssociateMemory(&gba->cpu, &gba->memory.d);
2013-04-07 20:25:45 +00:00
GBABoardInit(&gba->board);
ARMAssociateBoard(&gba->cpu, &gba->board.d);
ARMReset(&gba->cpu);
2013-04-05 09:17:22 +00:00
}
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;
2013-04-06 11:20:44 +00:00
memory->d.store32 = GBAStore32;
memory->d.store16 = GBAStore16;
memory->d.store8 = GBAStore8;
2013-04-05 09:17:22 +00:00
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;
2013-04-06 11:34:19 +00:00
if (!memory->wram || !memory->iwram) {
GBAMemoryDeinit(memory);
memory->p->errno = GBA_OUT_OF_MEMORY;
memory->p->errstr = GBA_CANNOT_MMAP;
}
2013-04-10 05:20:35 +00:00
memory->d.activeRegion = 0;
memory->d.activeMask = 0;
memory->d.setActiveRegion = GBASetActiveRegion;
2013-04-05 09:17:22 +00:00
}
void GBAMemoryDeinit(struct GBAMemory* memory) {
munmap(memory->wram, SIZE_WORKING_RAM);
munmap(memory->iwram, SIZE_WORKING_IRAM);
}
2013-04-07 20:25:45 +00:00
void GBABoardInit(struct GBABoard* board) {
board->d.reset = GBABoardReset;
}
void GBABoardReset(struct ARMBoard* board) {
struct ARMCore* cpu = board->cpu;
ARMSetPrivilegeMode(cpu, MODE_IRQ);
cpu->gprs[ARM_SP] = SP_BASE_IRQ;
ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
cpu->gprs[ARM_SP] = SP_BASE_SUPERVISOR;
ARMSetPrivilegeMode(cpu, MODE_SYSTEM);
cpu->gprs[ARM_SP] = SP_BASE_SYSTEM;
}
2013-04-07 08:46:28 +00:00
void GBALoadROM(struct GBA* gba, int fd) {
gba->memory.rom = mmap(0, SIZE_CART0, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0);
// TODO: error check
}
2013-04-10 05:20:35 +00:00
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;
}
}
2013-04-05 09:17:22 +00:00
int32_t GBALoad32(struct ARMMemory* memory, uint32_t address) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
2013-04-07 08:46:28 +00:00
switch (address & ~OFFSET_MASK) {
case BASE_BIOS:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_WORKING_RAM:
2013-04-08 10:13:37 +00:00
return gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2];
2013-04-07 08:46:28 +00:00
case BASE_WORKING_IRAM:
2013-04-08 10:13:37 +00:00
return gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2];
2013-04-07 08:46:28 +00:00
case BASE_IO:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_PALETTE_RAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_VRAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_OAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
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:
2013-04-05 09:17:22 +00:00
break;
default:
break;
}
return 0;
}
int16_t GBALoad16(struct ARMMemory* memory, uint32_t address) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
2013-04-07 08:46:28 +00:00
switch (address & ~OFFSET_MASK) {
case BASE_BIOS:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_WORKING_RAM:
2013-04-08 10:13:37 +00:00
return ((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1];
2013-04-07 08:46:28 +00:00
case BASE_WORKING_IRAM:
2013-04-08 10:13:37 +00:00
return ((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1];
2013-04-07 08:46:28 +00:00
case BASE_IO:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_PALETTE_RAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_VRAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_OAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART0:
case BASE_CART0_EX:
case BASE_CART1:
case BASE_CART1_EX:
case BASE_CART2:
case BASE_CART2_EX:
2013-04-08 09:13:40 +00:00
return ((int16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1];
2013-04-07 08:46:28 +00:00
case BASE_CART_SRAM:
2013-04-05 09:17:22 +00:00
break;
default:
break;
}
return 0;
}
uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
2013-04-07 08:46:28 +00:00
switch (address & ~OFFSET_MASK) {
case BASE_BIOS:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_WORKING_RAM:
2013-04-08 10:13:37 +00:00
return ((uint16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1];
2013-04-07 08:46:28 +00:00
case BASE_WORKING_IRAM:
2013-04-08 10:13:37 +00:00
return ((uint16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1];
2013-04-07 08:46:28 +00:00
case BASE_IO:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_PALETTE_RAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_VRAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_OAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART0:
case BASE_CART0_EX:
case BASE_CART1:
case BASE_CART1_EX:
case BASE_CART2:
case BASE_CART2_EX:
2013-04-08 09:13:40 +00:00
return ((uint16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1];
2013-04-07 08:46:28 +00:00
case BASE_CART_SRAM:
2013-04-05 09:17:22 +00:00
break;
default:
break;
}
return 0;
}
int8_t GBALoad8(struct ARMMemory* memory, uint32_t address) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
2013-04-07 08:46:28 +00:00
switch (address & ~OFFSET_MASK) {
case BASE_BIOS:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_WORKING_RAM:
2013-04-08 10:13:37 +00:00
return ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)];
2013-04-07 08:46:28 +00:00
case BASE_WORKING_IRAM:
2013-04-08 10:13:37 +00:00
return ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
2013-04-07 08:46:28 +00:00
case BASE_IO:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_PALETTE_RAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_VRAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_OAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART0:
case BASE_CART0_EX:
case BASE_CART1:
case BASE_CART1_EX:
case BASE_CART2:
case BASE_CART2_EX:
2013-04-08 10:13:37 +00:00
return ((int8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
2013-04-07 08:46:28 +00:00
case BASE_CART_SRAM:
2013-04-05 09:17:22 +00:00
break;
default:
break;
}
return 0;
}
uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
2013-04-07 08:46:28 +00:00
switch (address & ~OFFSET_MASK) {
case BASE_BIOS:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_WORKING_RAM:
2013-04-08 10:13:37 +00:00
return ((uint8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)];
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_WORKING_IRAM:
2013-04-08 10:13:37 +00:00
return ((uint8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_IO:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_PALETTE_RAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_VRAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_OAM:
2013-04-05 09:17:22 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART0:
case BASE_CART0_EX:
case BASE_CART1:
case BASE_CART1_EX:
case BASE_CART2:
case BASE_CART2_EX:
2013-04-08 10:13:37 +00:00
return ((uint8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
2013-04-07 08:46:28 +00:00
case BASE_CART_SRAM:
2013-04-05 09:17:22 +00:00
break;
default:
break;
}
return 0;
2013-04-06 11:20:44 +00:00
}
void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
2013-04-07 08:46:28 +00:00
switch (address & ~OFFSET_MASK) {
case BASE_WORKING_RAM:
2013-04-08 10:13:37 +00:00
gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2] = value;
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_WORKING_IRAM:
2013-04-08 10:13:37 +00:00
gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2] = value;
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_IO:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_PALETTE_RAM:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_VRAM:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_OAM:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART0:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART2_EX:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART_SRAM:
2013-04-06 11:20:44 +00:00
break;
default:
break;
}
}
void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
2013-04-07 08:46:28 +00:00
switch (address & ~OFFSET_MASK) {
case BASE_WORKING_RAM:
2013-04-08 10:13:37 +00:00
((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1] = value;
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_WORKING_IRAM:
2013-04-08 10:13:37 +00:00
((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1] = value;
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_IO:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_PALETTE_RAM:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_VRAM:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_OAM:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART0:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART2_EX:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART_SRAM:
2013-04-06 11:20:44 +00:00
break;
default:
break;
}
}
void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value) {
struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
2013-04-07 08:46:28 +00:00
switch (address & ~OFFSET_MASK) {
case BASE_WORKING_RAM:
2013-04-08 10:13:37 +00:00
((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_WORKING_IRAM:
2013-04-08 10:13:37 +00:00
((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_IO:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_PALETTE_RAM:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_VRAM:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_OAM:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART0:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART2_EX:
2013-04-06 11:20:44 +00:00
break;
2013-04-07 08:46:28 +00:00
case BASE_CART_SRAM:
2013-04-06 11:20:44 +00:00
break;
default:
break;
}
2013-04-07 08:46:28 +00:00
}