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