#ifndef GB_H #define GB_H #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #include typedef enum { STATE_RUN, STATE_STOP, STATE_HALT, STATE_INVALID, STATE_NOT_IMPLEMENTED, STATE_LAST, } gb_cpu_state_t; #define GB_BTN_UP 1 #define GB_BTN_DOWN (1 << 1) #define GB_BTN_LEFT (1 << 2) #define GB_BTN_RIGHT (1 << 3) #define GB_BTN_A (1 << 4) #define GB_BTN_B (1 << 5) #define GB_BTN_SELECT (1 << 6) #define GB_BTN_START (1 << 7) typedef struct { struct { _Bool in_bios; // FIXME: combine these? uint8_t bios[0x100]; // bios (256 bytes) uint8_t ram[0x2000]; // working ram (8k) uint8_t eram[65536]; // external ram (banked, up to 64k) uint8_t vram[0x2000]; // vram (8k) uint8_t oam[0xA0]; // oam (160 bytes) uint8_t zram[0x7F]; // zram (128 bytes) // rom (at least 32k) const uint8_t *rom; uint32_t rom_size; union { struct { // current rom bank (5 bits); see note about // rom_ram_mode below uint8_t rom_bank; // is external ram enabled? _Bool ram_enable; // ram bank // rom_ram_mode == 0: high two bits of rom bank // rom_ram_mode == 1: ram bank uint8_t ram_bank; // set interpretation of ram_bank _Bool rom_ram_mode; } mbc1; struct { // current rom bank (4 bits) uint8_t rom_bank; // is eram enabled? _Bool ram_enable; } mbc2; }; // interrupts // ie: interrupt enable (addr: 0xFFFF) // iv: interrupt vector (addr: 0xFF0F) // (gb-manual, p26) uint8_t ie; uint8_t iv; // buttons (addr: 0xFF00) // gb-manual, p23 uint8_t p1_mode; uint8_t btns; } mmu; struct { uint16_t clock; uint8_t mode, lcdc, stat, scy, scx, wy, wx, bgp, obp0, obp1, line, lyc; uint8_t rgb[3 * 160 * 144]; uint32_t frame; } gpu; struct { uint16_t div; uint32_t tima; // NOTE: cannot be uint16_t because of 10-bit shift uint8_t tma, tac; } timer; struct { uint16_t rs[6 /* RW_LAST */]; uint32_t clock; /* FIXME: uint16_t? */ gb_cpu_state_t state; // interrupt master enable _Bool ime; } cpu; } gb_t; #ifdef __cplusplus }; #endif /* __cplusplus */ #endif /* GB_H */