PancakeNESEmu
A homebrewed NES Emulator written in C
Loading...
Searching...
No Matches
macros.h
Go to the documentation of this file.
1#ifndef macros_h
2#define macros_h
3
4// Some Constants
5#define EXIT_SUCCESS 0
6#define EXIT_FAILURE 1
7
8// #define NULL ((void*)0)
9
10#define NES_SIGNATURE 0x4e45531a
11
12// Note: 65536 = 64KiB
13#define TOTAL_MEM_SIZE 65536
14
15// Error codes
16
17#define ERR_ABN_OPCODE 0xff
18
19// Some bit mask on 8-bits
20#define BIT_7_MASK 0b10000000
21#define BIT_6_MASK 0b01000000
22#define BIT_5_MASK 0b00100000
23#define BIT_4_MASK 0b00010000
24#define BIT_3_MASK 0b00001000
25#define BIT_2_MASK 0b00000100
26#define BIT_1_MASK 0b00000010
27#define BIT_0_MASK 0b00000001
28
29#define NBIT_7_MASK 0b01111111
30#define NBIT_6_MASK 0b10111111
31#define NBIT_5_MASK 0b11011111
32#define NBIT_4_MASK 0b11101111
33#define NBIT_3_MASK 0b11110111
34#define NBIT_2_MASK 0b11111011
35#define NBIT_1_MASK 0b11111101
36#define NBIT_0_MASK 0b11111110
37
38// Get lower of higher part of a 16-bits word
39
40#define GET_LOWER(x) (x & 0x00FF)
41#define GET_HIGHER(x) ((x >> 8) & 0x00FF)
42
43// Remarkable pointers
44
45#define STACK_START 0x11FF
46#define STACK_END 0x1100
47
48#define RAM_START 0x0000
49#define RAM_END 0x07FF
50
51#define RAM_MIRROR_1_START 0x0800
52#define RAM_MIRROR_1_END 0x0FFF
53
54#define RAM_MIRROR_2_START 0x1000
55#define RAM_MIRROR_2_END 0x17FF
56
57#define RAM_MIRROR_3_START 0x1800
58#define RAM_MIRROR_3_END 0x1FFF
59
60#define IO_START 0x2000
61
62#define PPU_REG_ZERO 0x2000
63#define PPU_REG_ONE 0x2001
64#define PPU_REG_TWO 0x2002
65#define PPU_REG_THREE 0x2003
66#define PPU_REG_FOUR 0x2004
67#define PPU_REG_FIVE 0x2005
68#define PPU_REG_SIX 0x2006
69#define PPU_REG_SEVEN 0x2007
70
71#define PPU_REG_START PPU_REG_ZERO
72#define PPU_REG_END PPU_REG_SEVEN
73
74// Note: the PPU mirrors are repeated every 8 bytes between the address below
75#define PPU_MIRRORS_START_ZERO 0x2008
76#define PPU_MIRRORS_START_ONE 0x2009
77#define PPU_MIRRORS_START_TWO 0x200a
78#define PPU_MIRRORS_START_THREE 0x200b
79#define PPU_MIRRORS_START_FOUR 0x200c
80#define PPU_MIRRORS_START_FIVE 0x200d
81#define PPU_MIRRORS_START_SIX 0x200e
82#define PPU_MIRRORS_START_SEVEN 0x200f
83
84#define PPU_MIRRORS_END 0x3FFF
85
86#define APU_REG_START 0x4000
87#define APU_SQUARE_ONE_START APU_REG_START
88
89// DDLC VVVV | D duty time (form of the wave) | L looping | C Constant_vol ? | V: MultiPurpose
90// DT: 12.5% (sequence: 0 1 0 0 0 0 0 0) | 25% (0 1 1 0 0 0 0 0) | 50% (0 1 1 1 1 0 0 0) | -25% (1 0
91// 0 1 1 1 1 1)
92// If not(L) && not(C) => V=length of the note (works like an envelope)
93// If L && not(C) => V=how fast the note is repeated
94// If not(L) && C => V=volume of the channel
95// If L && C => V=volume of the channel & note repeat infinitly until we change the value at x4000
96#define APU_SQUARE_ONE_CONF APU_SQUARE_ONE_START
97
98// EPPP NSSS | E Enable frequency sweep | P (smaller = faster sweep) | N 0=Sweep down 1=Sweep up
99// S (smaller = faster sweep)
100#define APU_SQUARE_ONE_FREQ_SWEEP 0x4001
101
102// TTTT TTTT | T lower byte of the frequency
103#define APU_SQUARE_ONE_FREQ_LOW 0x4002
104
105// LLLL LTTT | L Length of the note (assuming it is not played constantly)
106// WARNING: 0000 1 => very very long note
107// T 3 high bits of the note's frequency
108#define APU_SQUARE_ONE_FREQ_HIGH 0x4003
109
110// The second square channel works exactly in the same way
111#define APU_SQUARE_TWO_START 0x4004
112#define APU_SQUARE_TWO_CONF APU_SQUARE_TWO_START
113#define APU_SQUARE_TWO_FREQ_SWEEP 0x4005
114#define APU_SQUARE_TWO_FREQ_LOW 0x4006
115#define APU_SQUARE_TWO_FREQ_HIGH 0x4007
116
117#define APU_TRIANGLE_START 0x4008
118
119// CRRR RRRR | C = constant note
120// R changes the length of the note
121// However, its behavior is rly strange. For instance: $FF = constant note | $80 = channel off
122// $7F = length controlled by the register 0x400b
123#define APU_TRIANGLE_CONF APU_TRIANGLE_START
124
125#define APU_TRIANGLE_UNUSED 0x4009
126
127// TTTT TTTT | T lower byte of the frequency
128#define APU_TRIANGLE_FREQ_LOW 0x400a
129
130// LLLL LTTT | L length of the note if triangle_conf = $7F
131// T 3 high bits of the note's frequency
132#define APU_TRIANGLE_FREQ_HIGH 0x400b
133
134#define APU_NOISE_START 0x400c
135
136// --LC VVVV | Like square channel but without a duty time
137#define APU_NOISE_CONF APU_NOISE_START
138
139#define APU_NOISE_UNUSED 0x400d
140
141// Z--- TTTT | Z 1=metal noise 0=white noise
142// T lower value => higher pitch (highest pitch when TTTT = 0)
143#define APU_NOISE_FREQUENCY 0x400e
144
145// LLLL L--- | L length of the noise
146#define APU_NOISE_LENGTH 0x400f
147
148#define APU_DMC_START 0x4010
149
150// IL-- RRRR | I sets DMC triggers IRQs | L loop sample | R sample rate
151#define APU_DMC_CONF APU_DMC_START
152
153// -DDD DDDD | D starting volume of the sample
154#define APU_DMC_VOLUME 0x4011
155
156// AAAA AAAA | address to the sample
157// Note: %11AAAAAA AA000000
158// Therefore: Lowest Sample addr: $C000 | Highest $FFC0
159#define APU_DMC_SAMPLE_ADDR 0x4012
160
161// LLLL LLLL | L length of the sample
162#define APU_DMC_LENGTH 0x4013
163
164#define APU_DMC_UNUSED 0x4014
165
166// ---D TN21 | D DMC | T triangle | N noise | 2 square2 | 1 square1
167// 1 to enable | 0 to disable
168#define APU_CONTROL_WRITE 0x4015
169
170// IF-D NT21 | I DMC interrupt | F frame input
171// The rest are the same as above (1 is enabled, 0 if not)
172#define APU_CONTROL_READ APU_CONTROL_WRITE
173
174#define APU_UNSUSED 0x4016
175
176// SD-- ---- | S 5-frame sequence | D disable frame interrupts
177// Mode 0: 4-frame sequence
178// Mode 1: 5-frame sequence
179// Note: see https://www.nesdev.org/wiki/APU_Frame_Counter , basically, it changes the clock rate of
180// the APU
181#define APU_FRAME_COUNTER 0x4017
182#define APU_REG_END APU_FRAME_COUNTER
183
184#define TEST_MODE_IO_REG_START 0x4018
185#define TEST_MODE_IO_REG_END 0x401F
186
187#define IO_END 0x401F
188
189#define CARTRIDGE_START 0x4020
190
191#define CARTRIDGE_RAM_START 0x6000
192#define CARTRIDGE_RAM_END 0x7FFF
193
194#define GAME_ROM_START 0x8000
195
196#define APU_DCM_START 0xC000
197#define APU_DCM_END 0xFFF1
198
199#define GAME_ROM_END 0xFFFF
200
201#define CARTRIDGE_END 0xFFFF
202
203// Interrupt vector pointers
204
205#define NMI_HIGH 0xFFFA
206#define NMI_LOW 0xFFFB
207
208#define RESET_HIGH 0xFFFC
209#define RESET_LOW 0xFFFD
210
211#define IRQ_BRK_HIGH 0xFFFE
212#define IRQ_BRK_LOW 0xFFFF
213
214#endif // !macros_h