1mod addressing;
73mod bus;
74mod cpu;
75pub mod ines;
76mod instructions;
77mod opcodes;
78pub mod state;
79mod status;
80pub mod trace;
81
82pub use addressing::AddressingMode;
84pub use bus::{Bus, CpuBus};
85pub use cpu::Cpu;
86pub use ines::{INesHeader, INesRom};
87pub use status::StatusFlags;
88pub use trace::CpuTracer;
89
90pub use opcodes::OPCODE_TABLE;
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 struct TestBus {
98 memory: Vec<u8>,
99 }
100
101 impl TestBus {
102 fn new() -> Self {
103 Self {
104 memory: vec![0; 0x10000],
105 }
106 }
107
108 fn load_program(&mut self, start: u16, program: &[u8]) {
109 let start = start as usize;
110 self.memory[start..start + program.len()].copy_from_slice(program);
111 }
112 }
113
114 impl Bus for TestBus {
115 fn read(&mut self, addr: u16) -> u8 {
116 self.memory[addr as usize]
117 }
118
119 fn write(&mut self, addr: u16, value: u8) {
120 self.memory[addr as usize] = value;
121 }
122 }
123
124 #[test]
125 fn test_lda_immediate() {
126 let mut cpu = Cpu::new();
127 let mut bus = TestBus::new();
128
129 bus.load_program(0x8000, &[0xA9, 0x42]);
131 bus.memory[0xFFFC] = 0x00;
132 bus.memory[0xFFFD] = 0x80;
133
134 cpu.reset(&mut bus);
135 assert_eq!(cpu.pc, 0x8000);
136
137 let cycles = cpu.step(&mut bus);
138 assert_eq!(cycles, 2);
139 assert_eq!(cpu.a, 0x42);
140 assert_eq!(cpu.pc, 0x8002);
141 }
142
143 #[test]
144 fn test_tax_transfer() {
145 let mut cpu = Cpu::new();
146 let mut bus = TestBus::new();
147
148 bus.load_program(0x8000, &[0xA9, 0x42, 0xAA]);
150 bus.memory[0xFFFC] = 0x00;
151 bus.memory[0xFFFD] = 0x80;
152
153 cpu.reset(&mut bus);
154
155 cpu.step(&mut bus); assert_eq!(cpu.a, 0x42);
157
158 cpu.step(&mut bus); assert_eq!(cpu.x, 0x42);
160 }
161
162 #[test]
163 fn test_adc_carry() {
164 let mut cpu = Cpu::new();
165 let mut bus = TestBus::new();
166
167 bus.load_program(0x8000, &[0xA9, 0xFF, 0x69, 0x01]);
169 bus.memory[0xFFFC] = 0x00;
170 bus.memory[0xFFFD] = 0x80;
171
172 cpu.reset(&mut bus);
173
174 cpu.step(&mut bus); assert_eq!(cpu.a, 0xFF);
176
177 cpu.step(&mut bus); assert_eq!(cpu.a, 0x00); assert!(cpu.status.contains(StatusFlags::ZERO));
180 assert!(cpu.status.contains(StatusFlags::CARRY));
181 }
182
183 #[test]
184 fn test_branch_not_taken() {
185 let mut cpu = Cpu::new();
186 let mut bus = TestBus::new();
187
188 bus.load_program(0x8000, &[0xA9, 0x00, 0xD0, 0x02]);
190 bus.memory[0xFFFC] = 0x00;
191 bus.memory[0xFFFD] = 0x80;
192
193 cpu.reset(&mut bus);
194
195 cpu.step(&mut bus); let cycles = cpu.step(&mut bus); assert_eq!(cycles, 2); assert_eq!(cpu.pc, 0x8004);
200 }
201
202 #[test]
203 fn test_branch_taken_same_page() {
204 let mut cpu = Cpu::new();
205 let mut bus = TestBus::new();
206
207 bus.load_program(0x8000, &[0xA9, 0x01, 0xD0, 0x02]);
209 bus.memory[0xFFFC] = 0x00;
210 bus.memory[0xFFFD] = 0x80;
211
212 cpu.reset(&mut bus);
213
214 cpu.step(&mut bus); let cycles = cpu.step(&mut bus); assert_eq!(cycles, 3); assert_eq!(cpu.pc, 0x8006);
219 }
220
221 #[test]
222 fn test_jsr_rts() {
223 let mut cpu = Cpu::new();
224 let mut bus = TestBus::new();
225
226 bus.load_program(0x8000, &[0x20, 0x10, 0x80]);
228 bus.memory[0x8010] = 0x60; bus.memory[0xFFFC] = 0x00;
230 bus.memory[0xFFFD] = 0x80;
231
232 cpu.reset(&mut bus);
233
234 let old_sp = cpu.sp;
235 cpu.step(&mut bus); assert_eq!(cpu.pc, 0x8010);
237 assert_eq!(cpu.sp, old_sp.wrapping_sub(2)); cpu.step(&mut bus); assert_eq!(cpu.pc, 0x8003); assert_eq!(cpu.sp, old_sp); }
243
244 #[test]
245 fn test_unofficial_lax() {
246 let mut cpu = Cpu::new();
247 let mut bus = TestBus::new();
248
249 bus.load_program(0x8000, &[0xA7, 0x42]);
251 bus.memory[0x0042] = 0x55;
252 bus.memory[0xFFFC] = 0x00;
253 bus.memory[0xFFFD] = 0x80;
254
255 cpu.reset(&mut bus);
256
257 let cycles = cpu.step(&mut bus);
258 assert_eq!(cycles, 3);
259 assert_eq!(cpu.a, 0x55);
260 assert_eq!(cpu.x, 0x55);
261 }
262
263 #[test]
264 fn test_stack_operations() {
265 let mut cpu = Cpu::new();
266 let mut bus = TestBus::new();
267
268 bus.load_program(0x8000, &[0xA9, 0x42, 0x48, 0xA9, 0x00, 0x68]);
270 bus.memory[0xFFFC] = 0x00;
271 bus.memory[0xFFFD] = 0x80;
272
273 cpu.reset(&mut bus);
274
275 cpu.step(&mut bus); let sp = cpu.sp;
277 cpu.step(&mut bus); assert_eq!(cpu.sp, sp.wrapping_sub(1));
279
280 cpu.step(&mut bus); assert_eq!(cpu.a, 0x00);
282
283 cpu.step(&mut bus); assert_eq!(cpu.a, 0x42);
285 assert_eq!(cpu.sp, sp);
286 }
287}