summaryrefslogtreecommitdiff
path: root/gb.h
blob: 6be3a94f8e5a80e0989f087c3948d5aa96a8b25f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#ifndef GB_H
#define GB_H

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include <stdint.h>

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 */