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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
// #define PPU_CTRL_NMI_ENABLE 0x80
// #define PPU_CTRL_MASTER_SLAVE 0x40
// #define PPU_CTRL_SPRITE_HEIGHT 0x20
// #define PPU_CTRL_BG_TILE_SELECT 0x10
// #define PPU_CTRL_SPRITE_TILE_SELECT 0x08
// #define PPU_CTRL_NT_SELECT_Y 0x04
// #define PPU_CTRL_NT_SELECT_X 0x02
// #define PPU_CTRL_VRAM_INCREMENT 0x01
// #define PPU_MASK_SHOW_BG 0x08
// #define PPU_MASK_SHOW_SPRITES 0x10
// #define PPU_STATUS_VBLANK 0x80
// #define PPU_STATUS_SPRITE0_HIT 0x40
// #define PPU_STATUS_OVERFLOW 0x20
#define PPU_CTRL_BG_TILE_SELECT 0x10
#define PPU_CTRL_SPRITE_TILE_SELECT 0x08
#define PPU_CTRL_NMI 0x80
#define PPU_CTRL_VRAM_INCREMENT 0x04
// Define constants for PPU control and mask bits
#define PPU_CTRL_NMI 0x80
#define PPU_CTRL_VRAM_INCREMENT 0x04
#define PPU_CTRL_SPRITE_HEIGHT 0x20
#define PPU_CTRL_SPRITE_TILE 0x08
#define PPU_MASK_SHOW_BG 0x08
#define PPU_MASK_SHOW_SPRITES 0x10
// Define mirroring modes
#define MIRROR_HORIZONTAL 0
#define MIRROR_VERTICAL 1
#define MIRROR_FOURSCREEN 2
struct nes_state;
struct ppu_state {
uint8_t control;
uint8_t mask;
uint8_t fine_x;
uint8_t coarse_x;
uint8_t coarse_y;
uint32_t nt_x_offset;
uint32_t nt_y_offset;
uint8_t fine_y;
uint8_t tmp_fine_x;
uint8_t tmp_coarse_x;
uint8_t tmp_fine_y;
uint8_t tmp_coarse_y;
uint32_t tmp_nt_x;
uint32_t tmp_nt_y;
uint32_t tmp_addr;
uint32_t vram_addr;
uint8_t write_latch;
uint32_t cycle;
uint32_t scanline;
uint32_t dot;
uint32_t frame;
uint32_t bg_shift_lo;
uint32_t bg_shift_hi;
uint32_t attr_shift_lo;
uint32_t attr_shift_hi;
uint8_t bg_attribute_latch;
uint8_t next_tile;
uint8_t next_attr;
uint8_t next_lo;
uint8_t next_hi;
uint8_t vram[2048];
uint8_t palette[32];
uint8_t oam[256];
uint8_t oam_addr;
uint8_t secondary_oam[32];
uint32_t sprite_count;
uint8_t sprite_zero_hit;
uint8_t sprite_overflow;
uint8_t pixels[256 * 240];
uint8_t vblank;
uint8_t frame_ready;
};
struct cpu_state {
uint32_t pc; // Program Counter
uint8_t sp; // Stack Pointer
uint8_t a; // Accumulator
uint8_t x; // X Register
uint8_t y; // Y Register
uint8_t p; // Processor Status Flags (this can be expanded with separate flags if needed)
uint8_t n; // Negative Flag
uint8_t v; // Overflow Flag
// uint8_t b; // Break Flag (Set by BRK instruction)
uint8_t d; // Decimal Flag
uint8_t i; // Interrupt Disable Flag
uint8_t z; // Zero Flag
uint8_t c; // Carry Flag
// --
uint8_t die; // KIL instruction found!
};
struct ines_state {
uint32_t mapper;
uint8_t mirroring; // 0 = H, 1 = V, 2 = 4-screen
uint32_t prg_size;
uint32_t chr_size;
};
struct mapper {
void (*init)(struct nes_state *state);
uint8_t (*read)(struct nes_state *state, uint32_t addr);
void (*write)(struct nes_state *state, uint32_t addr, uint8_t value);
void (*tick)(struct nes_state *state);
};
union mapper_data {
// struct nrom_mapper nrom;
// struct mmc1_mapper mmc1;
// ... others
};
struct nes_state {
struct ines_state ines;
struct cpu_state cpu;
struct ppu_state ppu;
struct mapper mapper;
union mapper_data map;
size_t cycle;
uint8_t ram[2048];
uint8_t rom[4 * 1024 * 1024];
uint8_t chrrom[4 * 1024 * 1024];
uint8_t ciram[2048];
uint8_t palette[0x20];
uint8_t irq_pending;
uint8_t nmi_pending;
};
static uint32_t nes_palette[64] = {
0x757575ff, 0x271a75ff, 0x3b0072ff, 0x4c0f64ff, 0x400048ff, 0x600027ff, 0x600000ff, 0x500f00ff,
0x783a00ff, 0x755c00ff, 0x406c00ff, 0x504764ff, 0x005468ff, 0x000000ff, 0x000000ff, 0x000000ff,
0xbfbfbfff, 0x273aa7ff, 0x5c14a7ff, 0x7514a7ff, 0x751468ff, 0x982727ff, 0xa03a00ff, 0x986c00ff,
0x888800ff, 0x689800ff, 0x3aa700ff, 0x6c6c6cff, 0x007878ff, 0x000000ff, 0x000000ff, 0x000000ff,
0xffffffff, 0x3ab5ffff, 0x5cb5ffff, 0x9888ffff, 0xa778ffff, 0xc87878ff, 0xf05c00ff, 0xf08800ff,
0xe0a700ff, 0xb8b800ff, 0x88c800ff, 0xcccc68ff, 0x00e0d8ff, 0x000000ff, 0x000000ff, 0x000000ff,
0xffffffff, 0xa7e0ffff, 0xb8d8ffff, 0xc8c8ffff, 0xd8b8ffff, 0xd8a7a7ff, 0xf0d0b8ff, 0xf0d898ff,
0xf0c878ff, 0xd8d878ff, 0xb8e078ff, 0xd0e0b8ff, 0xb8f0f0ff, 0x000000ff, 0x000000ff, 0x000000ff
};
|