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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
|
#define PPU_CTRL_BG_TILE_SELECT 0x10
#define PPU_CTRL_SPRITE_TILE_SELECT 0x08
// Define constants for PPU control and mask bits
#define PPU_CTRL_NMI 0x80
#define PPU_CTRL_SPRITE_HEIGHT 0x20
#define PPU_CTRL_SPRITE_TILE 0x08
#define PPU_CTRL_VRAM_INCREMENT 0x04
#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 ppu_state {
uint16_t bg_shift_pattern_low; // 0
uint16_t bg_shift_pattern_high; // 2
uint16_t bg_shift_attrib_low; // 4
uint16_t bg_shift_attrib_high; // 6
uint16_t scanline; // 8
uint16_t dot; // 10
uint16_t vram_addr; // 12
uint16_t temp_addr; // 14
uint8_t fine_x; // 16
uint8_t bg_next_tile_id; // 17
uint8_t bg_next_tile_attrib; // 18
uint8_t bg_next_tile_lsb; // 19
uint8_t bg_next_tile_msb; // 20
uint8_t oam_addr; // 21
uint8_t oam_data; // 22
uint8_t even_frame; // 23
uint8_t reg_ctrl; // 24
uint8_t reg_mask; // 25
uint8_t reg_status; // 26
uint8_t write_latch; // 27
uint8_t vram_read_buffer; // 28
uint8_t open_bus; // 29
uint8_t sprite_count; // 30
uint8_t overflow_scheduled_dot; // 31
uint8_t palette[32]; // 32
// NOTE(peter): CACHELINE 2
uint8_t secondary_oam[32] __attribute__((aligned(64)));
uint8_t temp_secondary_oam[32];
// NOTE(peter): CACHELINE 3
struct sprite_data {
uint8_t shift_lo;
uint8_t shift_hi;
uint8_t position;
uint8_t priority;
uint8_t palette;
} __attribute__((packed, aligned(64))) sprites[8];
uint8_t input[2]; // 40 - Controller 1 & 2
uint8_t input_latch[2]; // 42 - Latched inputs after strobe
uint8_t input_bit[2]; // 44 - Current bit position being shifted out
uint8_t input_strobe; // 46 - Control bit (0 or 1)
uint8_t frame_ready; // 47
uint8_t sprite_zero_in_range; // 48 - Boolean: is sprite 0 in range (will always be slot 0 if true)
uint8_t sprite_count_next; // 49 - Sprite count for next scanline
// 15 bytes left.
// NOTE(peter): CACHELINE 4
uint8_t oam[256] __attribute__((aligned(64)));
} __attribute__((packed));
struct apu_state {
uint32_t frame_cycle;
uint16_t dmc_current_addr;
uint16_t dmc_bytes_remaining;
uint16_t dmc_sample_timer;
uint8_t mode;
uint8_t irq_inhibit;
uint8_t irq_pending;
uint8_t dmc_irq_enable;
uint8_t dmc_loop_flag;
uint8_t dmc_dma_enabled;
uint8_t dmc_freq_index;
uint8_t dmc_sample_addr;
uint8_t dmc_sample_len;
} __attribute__((packed));
struct cpu_state {
size_t cycles;
uint16_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) -- does not exist outside the stack
uint8_t d; // Decimal Flag (exists but ignored on NES)
uint8_t i; // Interrupt Disable Flag
uint8_t z; // Zero Flag
uint8_t c; // Carry Flag
// --
uint8_t irq_pending;
uint8_t nmi_pending;
};
struct ines_state {
uint8_t mapper;
uint8_t submapper;
uint8_t mirroring; // 0 = H, 1 = V, 2 = 4-screen
uint32_t prg_size;
uint32_t chr_size;
};
struct nes_state {
struct ppu_state ppu __attribute__((aligned(4096)));
struct mapper_functions mapper_function __attribute__((aligned(64)));
union mapper_data mapper_data __attribute__((aligned(64)));
struct cpu_state cpu __attribute__((aligned(64)));
struct ines_state ines __attribute__((aligned(64)));
struct apu_state apu __attribute__((aligned(64)));
uint8_t ram[RAM_SIZE] __attribute__((aligned(4096)));
uint8_t ciram[CIRAM_SIZE] __attribute__((aligned(4096)));
uint8_t prg_rom[PRG_ROM_SIZE] __attribute__((aligned(4096)));
uint8_t chr_rom[CHR_ROM_SIZE] __attribute__((aligned(4096)));
uint8_t chr_ram[CHR_RAM_SIZE] __attribute__((aligned(4096)));
uint8_t pixels[PIXELS_SIZE] __attribute__((aligned(4096)));
uint8_t sram[SRAM_SIZE] __attribute__((aligned(4096)));
};
__attribute__((aligned(4096))) static uint32_t nes_palette[65] = {
0x585858ff, 0x00237cff, 0x0d1099ff, 0x300092ff, 0x4f006cff, 0x600035ff, 0x5c0500ff, 0x461800ff,
0x272d00ff, 0x093e00ff, 0x004500ff, 0x004106ff, 0x003545ff, 0x000000ff, 0x000000ff, 0x000000ff,
0xa1a1a1ff, 0x0b53d7ff, 0x3337feff, 0x6621f7ff, 0x9515beff, 0xac166eff, 0xa62721ff, 0x864300ff,
0x596200ff, 0x2d7a00ff, 0x0c8500ff, 0x007f2aff, 0x006d85ff, 0x000000ff, 0x000000ff, 0x000000ff,
0xffffffff, 0x51a5feff, 0x8084feff, 0xbc6afeff, 0xf15bfeff, 0xfe5ec4ff, 0xfe7269ff, 0xe19321ff,
0xadb600ff, 0x79d300ff, 0x51df21ff, 0x3ad974ff, 0x39c3dfff, 0x424242ff, 0x000000ff, 0x000000ff,
0xffffffff, 0xb5d9feff, 0xcacafeff, 0xe3befeff, 0xf9b8feff, 0xfebae7ff, 0xfec3bcff, 0xf4d199ff,
0xdee086ff, 0xc6ec87ff, 0xb2f29dff, 0xa7f0c3ff, 0xa8e7f0ff, 0xacacacff, 0x000000ff, 0x000000ff,
0xffffffff // one extra for debug-coloring...
};
struct remake_state {
struct { int32_t x, y, w, h; } viewport;
int32_t mouse_dx;
int32_t mouse_dy;
float contrast;
float saturation;
float brightness;
float tone_data[4];
// OpenGL Objects
GLuint shader_program;
GLuint persistence_program;
// GLuint upscale_program;
GLuint upscale_warp_program;
GLuint bloom_extract_program;
GLuint bloom_blur_program;
GLuint bloom_warp_program;
GLuint bloom_composite_program;
GLuint texture;
GLuint persistence_texture;
GLuint persistence_output_texture;
GLuint crt_output_texture;
GLuint bloom_texture;
GLuint bloom_temp_texture;
GLuint bloom_warped_texture;
GLuint upscaled_source_texture;
GLuint persistence_fbo;
GLuint upscaled_source_fbo;
GLuint crt_fbo;
GLuint bloom_fbo;
GLuint bloom_temp_fbo;
GLuint bloom_warp_fbo;
GLuint vao;
GLuint vbo;
GLuint ebo;
// CRT Shader Uniforms
GLuint uniform_resolution;
GLuint uniform_src_image_size;
GLuint uniform_brightness;
GLuint uniform_tone;
GLuint uniform_crt_emulation;
GLuint uniform_apply_mask;
GLuint uniform_sampler_location;
// Bloom Shader Uniforms
GLuint bloom_uniform_threshold;
GLuint bloom_uniform_sampler;
GLuint blur_uniform_horizontal;
GLuint blur_uniform_sampler;
GLuint composite_uniform_bloom_strength;
GLuint composite_uniform_crt_sampler;
GLuint composite_uniform_bloom_sampler;
// Bloom settings
float bloom_threshold;
float bloom_strength;
uint32_t bloom_width;
uint32_t bloom_height;
// Phosphor persistence
float persistence_decay;
// Rendering & Dynamic Resolution
uint32_t render_width; // The actual remake resolution (e.g., 360)
uint32_t render_height; // The actual remake resolution (e.g., 270)
uint32_t frame_number;
uint8_t running;
uint8_t toggle_crt_emulation;
uint8_t toggle_bloom;
uint8_t fullscreen;
uint8_t viewport_changed; // Flag to signal render thread to recreate FBOs
};
// static struct remake_state state;
|