aboutsummaryrefslogtreecommitdiffstats
path: root/src/gb.h
diff options
context:
space:
mode:
authorgbc dev <gbc@localhost>2026-07-04 22:05:31 +0200
committergbc dev <gbc@localhost>2026-07-04 22:05:31 +0200
commit0d0f4f1d23851c0c34e518834f7d316e61dec1f3 (patch)
treee46296c247617ee0ead1fb93e9d0dc475a07f9b9 /src/gb.h
downloadsl0pboy-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.h127
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