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



#define PPU_CTRL_NMI                0x80
#define PPU_CTRL_BG_TILE_SELECT     0x10
#define PPU_CTRL_SPRITE_TILE_SELECT 0x08
#define PPU_CTRL_VRAM_INCREMENT     0x04

// 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 {
	uint8_t pixels[256 * 240];

	uint8_t oam[256];
	uint8_t oam_addr;
	uint8_t oam_data;
	uint8_t secondary_oam[32];

	uint8_t reg_ctrl;
	uint8_t reg_mask;
	uint8_t reg_status;
	uint8_t reg_scroll[2];
	uint8_t reg_addr[2];
	uint8_t reg_latch;

	uint32_t vram_addr;
	uint32_t temp_addr;
	uint32_t fine_x;

	uint8_t vram_read_buffer;
	uint8_t write_latch;

	uint8_t open_bus;

	uint8_t palette[0x20];

	uint32_t scanline;
	uint32_t dot;
	uint8_t even_frame;
	uint8_t frame_ready;

	uint8_t sprite_indexes[8];
	uint8_t sprite_zero_hit_possible;
	uint8_t sprite_count;
	uint32_t sprite_patterns[8];
	uint8_t sprite_positions[8];
	uint8_t sprite_priorities[8];
	uint8_t sprite_shift_lo[8];
	uint8_t sprite_shift_hi[8];

	uint32_t bg_shift_pattern_low;
	uint32_t bg_shift_pattern_high;
	uint32_t bg_shift_attrib_low;
	uint32_t bg_shift_attrib_high;

	uint8_t bg_next_tile_id;
	uint8_t bg_next_tile_attrib;
	uint8_t bg_next_tile_lsb;
	uint8_t bg_next_tile_msb;
};


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 nes_state {
	struct ines_state ines;
	struct cpu_state cpu;
	struct ppu_state ppu;
	struct mapper mapper;
	union mapper_data map;
	size_t cycles;
	uint8_t irq_pending;
	uint8_t nmi_pending;
	uint8_t ram[0x800];
	uint8_t sram[0x2000];
	uint8_t ciram[0x1000];				// NOTE(peter): Originally 0x800 bytes, but extended as it should work for up to fourway, this is optimization, reality is 2kb, but there is no side-effects, so this is fine!
	uint8_t prg_rom[4 * 1024 * 1024];
	uint8_t chr_rom[4 * 1024 * 1024];
};


__attribute__((aligned(4096))) static uint32_t nes_palette[64] = {
	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
};