summaryrefslogtreecommitdiff
path: root/mknes.h
blob: e9d3e0e54cafad15a06fe4a73de4b7cd14a572f6 (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
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



// Define constants for PPU control register bits ($2000)
#define PPU_CTRL_NMI               0x80
#define PPU_CTRL_SPRITE_HEIGHT     0x20
#define PPU_CTRL_BG_TILE_SELECT    0x10
#define PPU_CTRL_SPRITE_TILE       0x08
#define PPU_CTRL_VRAM_INCREMENT    0x04

// Define constants for PPU mask register bits ($2001)
#define PPU_MASK_SHOW_SPRITES      0x10
#define PPU_MASK_SHOW_BG           0x08

// Define constants for PPU status register bits ($2002)
#define PPU_STATUS_VBLANK          0x80
#define PPU_STATUS_SPRITE_ZERO_HIT 0x40
#define PPU_STATUS_SPRITE_OVERFLOW 0x20

// Define constants for sprite attribute bits
#define SPRITE_ATTR_FLIP_VERTICAL  0x80
#define SPRITE_ATTR_FLIP_HORIZONTAL 0x40
#define SPRITE_ATTR_PRIORITY       0x20
#define SPRITE_ATTR_PALETTE_MASK   0x03

// 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 - Number of sprites in secondary OAM (0-8)
	uint8_t palette[32];					// 31

	// NOTE(peter): CACHELINE 2
	uint8_t secondary_oam[32] __attribute__((aligned(64)));

	// 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)) sprites[8] __attribute__((aligned(64)));

	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)

	// 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...
};