diff options
| author | gbc dev <gbc@localhost> | 2026-07-04 22:05:31 +0200 |
|---|---|---|
| committer | gbc dev <gbc@localhost> | 2026-07-04 22:05:31 +0200 |
| commit | 0d0f4f1d23851c0c34e518834f7d316e61dec1f3 (patch) | |
| tree | e46296c247617ee0ead1fb93e9d0dc475a07f9b9 /src/gb.h | |
| download | sl0pboy-0d0f4f1d23851c0c34e518834f7d316e61dec1f3.tar.gz sl0pboy-0d0f4f1d23851c0c34e518834f7d316e61dec1f3.tar.xz sl0pboy-0d0f4f1d23851c0c34e518834f7d316e61dec1f3.zip | |
scaffolding: build system, cartridge loader with MBC1/2/3/5, core types
Diffstat (limited to 'src/gb.h')
| -rw-r--r-- | src/gb.h | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/gb.h b/src/gb.h new file mode 100644 index 0000000..806daba --- /dev/null +++ b/src/gb.h @@ -0,0 +1,127 @@ +#ifndef GBC_GB_H +#define GBC_GB_H + +#include "types.h" +#include "cart.h" + +// Interrupt bit flags (IE/IF at 0xFFFF / 0xFF0F) +enum { + INT_VBLANK = 0x01, + INT_LCDSTAT= 0x02, + INT_TIMER = 0x04, + INT_SERIAL = 0x08, + INT_JOYPAD = 0x10, +}; + +// Joypad button bits (as used by our input state; 1 = pressed) +enum { + BTN_A = 0x01, + BTN_B = 0x02, + BTN_SELECT = 0x04, + BTN_START = 0x08, + BTN_RIGHT = 0x10, + BTN_LEFT = 0x20, + BTN_UP = 0x40, + BTN_DOWN = 0x80, +}; + +#define SCREEN_W 160 +#define SCREEN_H 144 + +typedef struct GB GB; + +// ---- CPU (Sharp SM83) ---- +typedef struct { + union { struct { u8 f, a; }; u16 af; }; + union { struct { u8 c, b; }; u16 bc; }; + union { struct { u8 e, d; }; u16 de; }; + union { struct { u8 l, h; }; u16 hl; }; + u16 sp, pc; + bool ime; // interrupt master enable + bool ime_pending; // EI delayed enable + bool halted; + bool halt_bug; + bool stopped; +} CPU; + +// ---- PPU ---- +typedef struct { + u8 vram[0x4000]; // 2 banks (CGB) + u8 oam[0xA0]; + u8 vram_bank; // CGB + + // registers + u8 lcdc, stat, scy, scx, ly, lyc, wy, wx, bgp, obp0, obp1; + u8 vbk; // vram bank select reg (bit0) + + // CGB palettes + u8 bcps, ocps; + u8 bg_pal[64]; // 8 palettes * 4 colors * 2 bytes + u8 obj_pal[64]; + + int mode; // 0 hblank,1 vblank,2 oam,3 draw + int dots; // dot counter within current line + bool frame_ready; + u8 wly; // internal window line counter + + // framebuffer: RGB888 + u8 fb[SCREEN_H][SCREEN_W][3]; +} PPU; + +// ---- Timer ---- +typedef struct { + u16 div; // internal 16-bit counter; DIV is upper 8 bits + u8 tima, tma, tac; + bool overflow_pending; + int reload_delay; +} Timer; + +struct GB { + CPU cpu; + PPU ppu; + Timer timer; + Cart cart; + + u8 wram[0x8000]; // 8 banks of 4KB (CGB); DMG uses 2 + u8 hram[0x7F]; + u8 wram_bank; // svbk (1-7) + + u8 ie; // 0xFFFF + u8 iff; // 0xFF0F interrupt flags + u8 joyp_sel; // 0xFF00 selection bits + u8 buttons; // our pressed state (1=pressed) + + // serial + u8 sb, sc; + + // DMA + u8 dma; + + // CGB + bool cgb_mode; // running in CGB mode + u8 key1; // speed switch + bool double_speed; + + // HDMA / GDMA (CGB) + u16 hdma_src, hdma_dst; + u8 hdma_len; + bool hdma_active; + + u64 cycles; // total T-cycles elapsed + bool serial_log; // print serial output to stderr (blargg tests) +}; + +void gb_init(GB *gb); +void gb_reset(GB *gb); +// Run one full CPU instruction (advancing all subsystems). Returns T-cycles. +int gb_step(GB *gb); +void gb_run_frame(GB *gb); + +// bus access +u8 gb_read(GB *gb, u16 addr); +void gb_write(GB *gb, u16 addr, u8 val); +void gb_tick(GB *gb, int tcycles); // advance ppu/timer/dma by t-cycles + +void gb_request_interrupt(GB *gb, u8 flag); + +#endif |
