1use alloc::format;
6use alloc::string::{String, ToString};
7use alloc::vec::Vec;
8use crate::{
9 apu::{Apu, Channel},
10 bus::CpuBus,
11 cart::Cart,
12 common::{Clock, ResetKind, NesRegion, Regional, Reset},
13 input::{FourPlayer, Joypad, Player, Zapper},
14 mapper::Mapper,
15 mem::{Access, Mem},
16 ppu::Ppu,
17};
18use bitflags::{bitflags, Flags};
19use instr::{
20 AddrMode::{ABS, ABX, ABY, ACC, IDX, IDY, IMM, IMP, IND, REL, ZP0, ZPX, ZPY},
21 Instr,
22 Operation::{
23 ADC, AHX, ALR, ANC, AND, ARR, ASL, AXS, BCC, BCS, BEQ, BIT, BMI, BNE, BPL, BRK, BVC, BVS,
24 CLC, CLD, CLI, CLV, CMP, CPX, CPY, DCP, DEC, DEX, DEY, EOR, IGN, INC, INX, INY, ISB, JMP,
25 JSR, LAS, LAX, LDA, LDX, LDY, LSR, NOP, ORA, PHA, PHP, PLA, PLP, RLA, ROL, ROR, RRA, RTI,
26 RTS, SAX, SBC, SEC, SED, SEI, SKB, SLO, SRE, STA, STX, STY, SXA, SYA, TAS, TAX, TAY, TSX,
27 TXA, TXS, TYA, XAA, XXX,
28 },
29};
30use serde::{Deserialize, Serialize};
31use core::fmt::{self, Write};
32use anyhow::Result;
33
34pub mod instr;
35
36bitflags! {
37 #[derive(Default, Serialize, Deserialize, Debug, Copy, Clone)]
38 #[must_use]
39 pub struct Irq: u8 {
40 const MAPPER = 1 << 1;
41 const FRAME_COUNTER = 1 << 2;
42 const DMC = 1 << 3;
43 }
44}
45
46bitflags! {
60 #[derive(Default, Serialize, Deserialize, Debug, Copy, Clone)]
61 #[must_use]
62 pub struct Status: u8 {
63 const C = 1; const Z = 1 << 1; const I = 1 << 2; const D = 1 << 3; const B = 1 << 4; const U = 1 << 5; const V = 1 << 6; const N = 1 << 7; }
72}
73
74#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
76enum Cycle {
77 Read,
78 Write,
79}
80
81#[derive(Clone, Serialize, Deserialize)]
83#[must_use]
84pub struct Cpu {
85 cycle: usize,
86 region: NesRegion,
88 master_clock: u64,
89 clock_divider: u64,
90 start_clocks: u64,
91 end_clocks: u64,
92 pc: u16,
93 sp: u8,
95 acc: u8,
97 x: u8,
99 y: u8,
101 status: Status,
103 bus: CpuBus,
105 instr: Instr,
106 abs_addr: u16,
108 rel_addr: u16,
110 fetched_data: u8,
112 irq: Irq,
114 run_irq: bool,
116 prev_run_irq: bool,
117 nmi: bool,
118 prev_nmi: bool,
119 prev_nmi_pending: bool,
120 #[serde(skip)]
121 corrupted: bool,
122 dmc_dma: bool,
124 halt: bool,
125 dummy_read: bool,
126 cycle_accurate: bool,
127 disasm: String,
128}
129
130impl Cpu {
131 const NTSC_MASTER_CLOCK_RATE: f32 = 21_477_272.0;
135 const NTSC_CPU_CLOCK_RATE: f32 = Self::NTSC_MASTER_CLOCK_RATE / 12.0;
136 const PAL_MASTER_CLOCK_RATE: f32 = 26_601_712.0;
137 const PAL_CPU_CLOCK_RATE: f32 = Self::PAL_MASTER_CLOCK_RATE / 16.0;
138 const DENDY_CPU_CLOCK_RATE: f32 = Self::PAL_MASTER_CLOCK_RATE / 15.0;
139
140 const PPU_OFFSET: u64 = 1;
142
143 const NMI_VECTOR: u16 = 0xFFFA;
144 const IRQ_VECTOR: u16 = 0xFFFE;
146 const RESET_VECTOR: u16 = 0xFFFC;
148 const POWER_ON_STATUS: Status = Status::U.union(Status::I);
150 const POWER_ON_SP: u8 = 0xFD;
151 const SP_BASE: u16 = 0x0100; pub fn new(bus: CpuBus) -> Self {
154 let mut cpu = Self {
155 cycle: 0,
156 region: NesRegion::default(),
157 master_clock: 0,
158 clock_divider: 0,
159 start_clocks: 0,
160 end_clocks: 0,
161 pc: 0x0000,
162 sp: 0x00,
163 acc: 0x00,
164 x: 0x00,
165 y: 0x00,
166 status: Self::POWER_ON_STATUS,
167 bus,
168 instr: Cpu::INSTRUCTIONS[0x00],
169 abs_addr: 0x0000,
170 rel_addr: 0x0000,
171 fetched_data: 0x00,
172 irq: Irq::empty(),
173 run_irq: false,
174 prev_run_irq: false,
175 nmi: false,
176 prev_nmi: false,
177 prev_nmi_pending: false,
178 corrupted: false,
179 dmc_dma: false,
180 halt: false,
181 dummy_read: false,
182 cycle_accurate: true,
183 disasm: String::with_capacity(100),
184 };
185 cpu.set_region(cpu.region);
186 cpu
187 }
188
189 #[inline]
190 #[must_use]
191 pub const fn region_clock_rate(region: NesRegion) -> f32 {
192 match region {
193 NesRegion::Ntsc => Self::NTSC_CPU_CLOCK_RATE,
194 NesRegion::Pal => Self::PAL_CPU_CLOCK_RATE,
195 NesRegion::Dendy => Self::DENDY_CPU_CLOCK_RATE,
196 }
197 }
198
199 #[inline]
200 #[must_use]
201 pub const fn clock_rate(&self) -> f32 {
202 Self::region_clock_rate(self.region)
203 }
204
205 #[inline]
206 #[must_use]
207 pub const fn cycle(&self) -> usize {
208 self.cycle
209 }
210
211 #[inline]
212 #[must_use]
213 pub const fn pc(&self) -> u16 {
214 self.pc
215 }
216
217 #[inline]
218 #[must_use]
219 pub const fn sp(&self) -> u8 {
220 self.sp
221 }
222
223 #[inline]
224 #[must_use]
225 pub const fn a(&self) -> u8 {
226 self.acc
227 }
228
229 #[inline]
230 #[must_use]
231 pub const fn x(&self) -> u8 {
232 self.x
233 }
234
235 #[inline]
236 #[must_use]
237 pub const fn y(&self) -> u8 {
238 self.y
239 }
240
241 #[inline]
242 pub const fn status(&self) -> Status {
243 self.status
244 }
245
246 #[inline]
247 #[must_use]
248 pub const fn corrupted(&self) -> bool {
249 self.corrupted
250 }
251
252 #[inline]
253 #[must_use]
254 pub fn disasm(&self) -> &str {
255 &self.disasm
256 }
257
258 #[inline]
259 pub const fn ppu(&self) -> &Ppu {
260 self.bus.ppu()
261 }
262
263 #[inline]
264 pub fn ppu_mut(&mut self) -> &mut Ppu {
265 self.bus.ppu_mut()
266 }
267
268 #[inline]
269 pub const fn apu(&self) -> &Apu {
270 self.bus.apu()
271 }
272
273 #[inline]
274 pub fn apu_mut(&mut self) -> &mut Apu {
275 self.bus.apu_mut()
276 }
277
278 #[inline]
279 pub const fn mapper(&self) -> &Mapper {
280 self.bus.mapper()
281 }
282
283 #[inline]
284 pub fn mapper_mut(&mut self) -> &mut Mapper {
285 self.bus.mapper_mut()
286 }
287
288 #[inline]
289 pub const fn joypad(&self, slot: Player) -> &Joypad {
290 self.bus.joypad(slot)
291 }
292
293 #[inline]
294 pub fn joypad_mut(&mut self, slot: Player) -> &mut Joypad {
295 self.bus.joypad_mut(slot)
296 }
297
298 #[inline]
299 pub fn connect_zapper(&mut self, enabled: bool) {
300 self.bus.connect_zapper(enabled);
301 }
302
303 #[inline]
304 pub const fn zapper(&self) -> &Zapper {
305 self.bus.zapper()
306 }
307
308 #[inline]
309 pub fn zapper_mut(&mut self) -> &mut Zapper {
310 self.bus.zapper_mut()
311 }
312
313 #[inline]
314 pub fn load_cart(&mut self, cart: Cart) {
315 self.bus.load_cart(cart);
316 }
317
318 #[inline]
319 #[must_use]
320 pub const fn cart_battery_backed(&self) -> bool {
321 self.bus.cart_battery_backed()
322 }
323
324 #[inline]
325 #[must_use]
326 pub fn sram(&self) -> &[u8] {
327 self.bus.sram()
328 }
329
330 #[inline]
331 pub fn load_sram(&mut self, sram: Vec<u8>) {
332 self.bus.load_sram(sram);
333 }
334
335 #[inline]
336 #[must_use]
337 pub fn wram(&self) -> &[u8] {
338 self.bus.wram()
339 }
340
341 #[inline]
347 pub fn add_genie_code(&mut self, genie_code: String) -> Result<()> {
348 self.bus.add_genie_code(genie_code)
349 }
350
351 #[inline]
352 pub fn remove_genie_code(&mut self, genie_code: &str) {
353 self.bus.remove_genie_code(genie_code);
354 }
355
356 #[inline]
357 #[must_use]
358 pub const fn ppu_cycle(&self) -> u32 {
359 self.bus.ppu_cycle()
360 }
361
362 #[inline]
363 #[must_use]
364 pub const fn ppu_scanline(&self) -> u32 {
365 self.bus.ppu_scanline()
366 }
367
368 #[inline]
369 #[must_use]
370 pub fn frame_buffer(&self) -> &[u16] {
371 self.bus.frame_buffer()
372 }
373
374 #[inline]
375 #[must_use]
376 pub const fn frame_number(&self) -> u32 {
377 self.bus.frame_number()
378 }
379
380 #[inline]
381 #[must_use]
382 pub const fn audio_channel_enabled(&self, channel: Channel) -> bool {
383 self.bus.audio_channel_enabled(channel)
384 }
385
386 #[inline]
387 pub fn toggle_audio_channel(&mut self, channel: Channel) {
388 self.bus.toggle_audio_channel(channel);
389 }
390
391 #[inline]
392 #[must_use]
393 pub fn audio_samples(&self) -> &[f32] {
394 self.bus.audio_samples()
395 }
396
397 #[inline]
398 pub fn clear_audio_samples(&mut self) {
399 self.bus.clear_audio_samples();
400 }
401
402 #[inline]
403 pub const fn four_player(&self) -> FourPlayer {
404 self.bus.four_player()
405 }
406
407 #[inline]
408 pub fn set_four_player(&mut self, four_player: FourPlayer) {
409 self.bus.set_four_player(four_player);
410 }
411
412 #[inline]
413 pub fn set_cycle_accurate(&mut self, enabled: bool) {
414 self.cycle_accurate = enabled;
415 }
416
417 pub fn irq(&mut self) {
428 self.read(self.pc, Access::Dummy);
429 self.read(self.pc, Access::Dummy);
430 self.push_u16(self.pc);
431
432 let status = ((self.status | Status::U) & !Status::B).bits();
438
439 if self.nmi {
440 self.nmi = false;
441 self.push(status);
442 self.status.set(Status::I, true);
443
444 self.pc = self.read_u16(Self::NMI_VECTOR);
445 log::trace!("NMI: {}", self.cycle);
446 } else {
447 self.push(status);
448 self.status.set(Status::I, true);
449
450 self.pc = self.read_u16(Self::IRQ_VECTOR);
451 log::trace!("IRQ: {}", self.cycle);
452 }
453 }
454
455 fn handle_interrupts(&mut self) {
456 self.prev_nmi = self.nmi;
462
463 let nmi_pending = self.bus.nmi_pending();
468 if !self.prev_nmi_pending && nmi_pending {
469 self.nmi = true;
470 log::trace!("NMI Edge Detected: {}", self.cycle);
471 }
472 self.prev_nmi_pending = nmi_pending;
473
474 self.irq = self.bus.irqs_pending();
475
476 self.prev_run_irq = self.run_irq;
479 self.run_irq = !self.irq.is_empty() && !self.status.intersects(Status::I);
480 if self.run_irq {
481 log::trace!("IRQ Level Detected: {}: {:?}", self.cycle, self.irq);
482 }
483
484 if self.bus.dmc_dma() {
485 self.dmc_dma = true;
486 self.halt = true;
487 self.dummy_read = true;
488 }
489 }
490
491 fn start_cycle(&mut self, cycle: Cycle) {
492 self.master_clock += if cycle == Cycle::Read {
493 self.start_clocks - 1
494 } else {
495 self.start_clocks + 1
496 };
497 self.cycle = self.cycle.wrapping_add(1);
498
499 if self.cycle_accurate {
500 self.bus.clock_to(self.master_clock - Self::PPU_OFFSET);
501 self.bus.clock();
502 }
503 }
504
505 fn end_cycle(&mut self, cycle: Cycle) {
506 self.master_clock += if cycle == Cycle::Read {
507 self.end_clocks + 1
508 } else {
509 self.end_clocks - 1
510 };
511
512 if self.cycle_accurate {
513 self.bus.clock_to(self.master_clock - Self::PPU_OFFSET);
514 }
515
516 self.handle_interrupts();
517 }
518
519 fn process_dma_cycle(&mut self) {
520 if self.halt {
522 self.halt = false;
523 } else if self.dummy_read {
524 self.dummy_read = false;
525 }
526 self.start_cycle(Cycle::Read);
527 }
528
529 fn handle_dma(&mut self, addr: u16) {
530 self.start_cycle(Cycle::Read);
531 self.bus.read(addr, Access::Dummy);
532 self.end_cycle(Cycle::Read);
533 self.halt = false;
534
535 let skip_dummy_reads = addr == 0x4016 || addr == 0x4017;
536
537 let oam_base_addr = self.bus.oam_dma_addr();
538 let mut oam_offset = 0;
539 let mut oam_dma_count = 0;
540 let mut read_val = 0;
541
542 while self.bus.oam_dma() || self.dmc_dma {
543 if self.cycle & 0x01 == 0x00 {
544 if self.dmc_dma && !self.halt && !self.dummy_read {
545 self.process_dma_cycle();
547 read_val = self.bus.read(self.bus.dmc_dma_addr(), Access::Dummy);
548 self.end_cycle(Cycle::Read);
549 self.bus.load_dmc_buffer(read_val);
550 self.dmc_dma = false;
551 } else if self.bus.oam_dma() {
552 self.process_dma_cycle();
554 read_val = self.bus.read(oam_base_addr + oam_offset, Access::Dummy);
555 self.end_cycle(Cycle::Read);
556 oam_offset += 1;
557 oam_dma_count += 1;
558 } else {
559 debug_assert!(self.halt || self.dummy_read);
562 self.process_dma_cycle();
563 if !skip_dummy_reads {
564 self.bus.read(addr, Access::Dummy); }
566 self.end_cycle(Cycle::Read);
567 }
568 } else if self.bus.oam_dma() && oam_dma_count & 0x01 == 0x01 {
569 self.process_dma_cycle();
571 self.bus.write(0x2004, read_val, Access::Dummy);
572 self.end_cycle(Cycle::Read);
573 oam_dma_count += 1;
574 if oam_dma_count == 0x200 {
575 self.bus.oam_dma_finish();
576 }
577 } else {
578 self.process_dma_cycle();
580 if !skip_dummy_reads {
581 self.bus.read(addr, Access::Dummy); }
583 self.end_cycle(Cycle::Read);
584 }
585 }
586 }
587
588 #[inline]
592 fn set_zn_status(&mut self, val: u8) {
593 self.status.set(Status::Z, val == 0x00);
594 self.status.set(Status::N, val & 0x80 == 0x80);
595 }
596
597 #[inline]
598 const fn status_bit(&self, reg: Status) -> u8 {
599 self.status.intersection(reg).bits()
600 }
601
602 #[inline]
606 fn push(&mut self, val: u8) {
607 self.write(Self::SP_BASE | u16::from(self.sp), val, Access::Write);
608 self.sp = self.sp.wrapping_sub(1);
609 }
610
611 #[must_use]
613 #[inline]
614 fn pop(&mut self) -> u8 {
615 self.sp = self.sp.wrapping_add(1);
616 self.read(Self::SP_BASE | u16::from(self.sp), Access::Read)
617 }
618
619 #[must_use]
621 #[inline]
622 pub fn peek_stack(&self) -> u8 {
623 self.peek(
624 Self::SP_BASE | u16::from(self.sp.wrapping_add(1)),
625 Access::Dummy,
626 )
627 }
628
629 #[must_use]
631 #[inline]
632 pub fn peek_stack_u16(&self) -> u16 {
633 let lo = self.peek(Self::SP_BASE | u16::from(self.sp), Access::Dummy);
634 let hi = self.peek(
635 Self::SP_BASE | u16::from(self.sp.wrapping_add(1)),
636 Access::Dummy,
637 );
638 u16::from_le_bytes([lo, hi])
639 }
640
641 #[inline]
643 fn push_u16(&mut self, val: u16) {
644 let [lo, hi] = val.to_le_bytes();
645 self.push(hi);
646 self.push(lo);
647 }
648
649 #[inline]
651 fn pop_u16(&mut self) -> u16 {
652 let lo = self.pop();
653 let hi = self.pop();
654 u16::from_le_bytes([lo, hi])
655 }
656
657 fn fetch_data(&mut self) {
662 let mode = self.instr.addr_mode();
663 self.fetched_data = match mode {
664 IMP | ACC => self.acc,
665 ABX | ABY | IDY => {
666 match self.instr.op() {
668 LDA | LDX | LDY | EOR | AND | ORA | ADC | SBC | CMP | BIT | LAX | NOP | IGN
669 | LAS => {
670 let reg = match mode {
671 ABX => self.x,
672 ABY | IDY => self.y,
673 _ => unreachable!("not possible"),
674 };
675 if (self.abs_addr & 0x00FF) < u16::from(reg) {
681 self.read(self.abs_addr, Access::Read)
682 } else {
683 self.fetched_data
684 }
685 }
686 _ => self.read(self.abs_addr, Access::Read), }
688 }
689 _ => self.read(self.abs_addr, Access::Read), };
691 }
692
693 #[inline]
696 fn write_fetched(&mut self, val: u8) {
697 match self.instr.addr_mode() {
698 IMP | ACC => self.acc = val,
699 IMM => (), _ => self.write(self.abs_addr, val, Access::Write),
701 }
702 }
703
704 #[must_use]
706 #[inline]
707 fn read_instr(&mut self) -> u8 {
708 let val = self.read(self.pc, Access::Read);
709 self.pc = self.pc.wrapping_add(1);
710 val
711 }
712
713 #[must_use]
715 #[inline]
716 fn read_instr_u16(&mut self) -> u16 {
717 let lo = self.read_instr();
718 let hi = self.read_instr();
719 u16::from_le_bytes([lo, hi])
720 }
721
722 #[must_use]
724 #[inline]
725 pub fn read_u16(&mut self, addr: u16) -> u16 {
726 let lo = self.read(addr, Access::Read);
727 let hi = self.read(addr.wrapping_add(1), Access::Read);
728 u16::from_le_bytes([lo, hi])
729 }
730
731 #[must_use]
733 #[inline]
734 pub fn peek_u16(&self, addr: u16) -> u16 {
735 let lo = self.peek(addr, Access::Dummy);
736 let hi = self.peek(addr.wrapping_add(1), Access::Dummy);
737 u16::from_le_bytes([lo, hi])
738 }
739
740 #[must_use]
742 #[inline]
743 fn read_zp_u16(&mut self, addr: u8) -> u16 {
744 let lo = self.read(addr.into(), Access::Read);
745 let hi = self.read(addr.wrapping_add(1).into(), Access::Read);
746 u16::from_le_bytes([lo, hi])
747 }
748
749 #[must_use]
751 #[inline]
752 fn peek_zp_u16(&self, addr: u8) -> u16 {
753 let lo = self.peek(addr.into(), Access::Dummy);
754 let hi = self.peek(addr.wrapping_add(1).into(), Access::Dummy);
755 u16::from_le_bytes([lo, hi])
756 }
757
758 pub fn disassemble(&mut self, pc: &mut u16) {
759 let opcode = self.peek(*pc, Access::Dummy);
760 let instr = Cpu::INSTRUCTIONS[opcode as usize];
761 let mut bytes = Vec::with_capacity(3);
762 self.disasm.clear();
763 let _ = write!(self.disasm, "{pc:04X} ");
764 bytes.push(opcode);
765 let mut addr = pc.wrapping_add(1);
766 let mode = match instr.addr_mode() {
767 IMM => {
768 bytes.push(self.peek(addr, Access::Dummy));
769 addr = addr.wrapping_add(1);
770 format!(" #${:02X}", bytes[1])
771 }
772 ZP0 => {
773 bytes.push(self.peek(addr, Access::Dummy));
774 addr = addr.wrapping_add(1);
775 let val = self.peek(bytes[1].into(), Access::Dummy);
776 format!(" ${:02X} = #${val:02X}", bytes[1])
777 }
778 ZPX => {
779 bytes.push(self.peek(addr, Access::Dummy));
780 addr = addr.wrapping_add(1);
781 let x_offset = bytes[1].wrapping_add(self.x);
782 let val = self.peek(x_offset.into(), Access::Dummy);
783 format!(" ${:02X},X @ ${x_offset:02X} = #${val:02X}", bytes[1])
784 }
785 ZPY => {
786 bytes.push(self.peek(addr, Access::Dummy));
787 addr = addr.wrapping_add(1);
788 let y_offset = bytes[1].wrapping_add(self.y);
789 let val = self.peek(y_offset.into(), Access::Dummy);
790 format!(" ${:02X},Y @ ${y_offset:02X} = #${val:02X}", bytes[1])
791 }
792 ABS => {
793 bytes.push(self.peek(addr, Access::Dummy));
794 bytes.push(self.peek(addr.wrapping_add(1), Access::Dummy));
795 let abs_addr = self.peek_u16(addr);
796 addr = addr.wrapping_add(2);
797 if instr.op() == JMP || instr.op() == JSR {
798 format!(" ${abs_addr:04X}")
799 } else {
800 let val = self.peek(abs_addr, Access::Dummy);
801 format!(" ${abs_addr:04X} = #${val:02X}")
802 }
803 }
804 ABX => {
805 bytes.push(self.peek(addr, Access::Dummy));
806 bytes.push(self.peek(addr.wrapping_add(1), Access::Dummy));
807 let abs_addr = self.peek_u16(addr);
808 addr = addr.wrapping_add(2);
809 let x_offset = abs_addr.wrapping_add(self.x.into());
810 let val = self.peek(x_offset, Access::Dummy);
811 format!(" ${abs_addr:04X},X @ ${x_offset:04X} = #${val:02X}")
812 }
813 ABY => {
814 bytes.push(self.peek(addr, Access::Dummy));
815 bytes.push(self.peek(addr.wrapping_add(1), Access::Dummy));
816 let abs_addr = self.peek_u16(addr);
817 addr = addr.wrapping_add(2);
818 let y_offset = abs_addr.wrapping_add(self.y.into());
819 let val = self.peek(y_offset, Access::Dummy);
820 format!(" ${abs_addr:04X},Y @ ${y_offset:04X} = #${val:02X}")
821 }
822 IND => {
823 bytes.push(self.peek(addr, Access::Dummy));
824 bytes.push(self.peek(addr.wrapping_add(1), Access::Dummy));
825 let abs_addr = self.peek_u16(addr);
826 addr = addr.wrapping_add(2);
827 let lo = self.peek(abs_addr, Access::Dummy);
828 let hi = if abs_addr & 0x00FF == 0x00FF {
829 self.peek(abs_addr & 0xFF00, Access::Dummy)
830 } else {
831 self.peek(abs_addr + 1, Access::Dummy)
832 };
833 let val = u16::from_le_bytes([lo, hi]);
834 format!(" (${abs_addr:04X}) = ${val:04X}")
835 }
836 IDX => {
837 bytes.push(self.peek(addr, Access::Dummy));
838 addr = addr.wrapping_add(1);
839 let x_offset = bytes[1].wrapping_add(self.x);
840 let abs_addr = self.peek_zp_u16(x_offset);
841 let val = self.peek(abs_addr, Access::Dummy);
842 format!(" (${:02X},X) @ ${abs_addr:04X} = #${val:02X}", bytes[1])
843 }
844 IDY => {
845 bytes.push(self.peek(addr, Access::Dummy));
846 addr = addr.wrapping_add(1);
847 let abs_addr = self.peek_zp_u16(bytes[1]);
848 let y_offset = abs_addr.wrapping_add(self.y.into());
849 let val = self.peek(y_offset, Access::Dummy);
850 format!(" (${:02X}),Y @ ${y_offset:04X} = #${val:02X}", bytes[1])
851 }
852 REL => {
853 bytes.push(self.peek(addr, Access::Dummy));
854 let mut rel_addr: u16 = self.peek(addr, Access::Dummy).into();
855 addr = addr.wrapping_add(1);
856 if rel_addr & 0x80 == 0x80 {
857 rel_addr |= 0xFF00;
859 }
860 format!(" ${:04X}", addr.wrapping_add(rel_addr))
861 }
862 ACC | IMP => "".to_string(),
863 };
864 *pc = addr;
865 for byte in &bytes {
866 let _ = write!(self.disasm, "{byte:02X} ");
867 }
868 for _ in 0..(3 - bytes.len()) {
869 self.disasm.push_str(" ");
870 }
871 let _ = write!(self.disasm, "{instr:?}{mode}");
872 }
873
874 pub fn trace_instr(&mut self) {
876 let mut pc = self.pc;
877 self.disassemble(&mut pc);
878
879 let status_str = |status: Status, set: char, clear: char| {
880 if self.status.contains(status) {
881 set
882 } else {
883 clear
884 }
885 };
886
887 log::trace!(
888 "{:<50} A:{:02X} X:{:02X} Y:{:02X} P:{}{}--{}{}{}{} SP:{:02X} PPU:{:3},{:3} CYC:{}",
889 self.disasm,
890 self.acc,
891 self.x,
892 self.y,
893 status_str(Status::N, 'N', 'n'),
894 status_str(Status::V, 'V', 'v'),
895 status_str(Status::D, 'd', 'd'),
896 status_str(Status::I, 'I', 'i'),
897 status_str(Status::Z, 'Z', 'z'),
898 status_str(Status::C, 'C', 'c'),
899 self.sp,
900 self.bus.ppu_cycle(),
901 self.bus.ppu_scanline(),
902 self.cycle,
903 );
904 }
905
906 #[must_use]
908 #[inline]
909 const fn pages_differ(addr1: u16, addr2: u16) -> bool {
910 (addr1 & 0xFF00) != (addr2 & 0xFF00)
911 }
912}
913
914impl Cpu {
915 pub fn clock_inspect<F>(&mut self, mut inspect: F) -> usize
916 where
917 F: FnMut(&mut Cpu),
918 {
919 let start_cycle = self.cycle;
920
921 if log::log_enabled!(log::Level::Trace) {
922 self.trace_instr();
923 }
924 inspect(self);
925
926 let opcode = self.read_instr(); self.instr = Cpu::INSTRUCTIONS[opcode as usize];
928
929 match self.instr.addr_mode() {
930 IMM => self.imm(),
931 ZP0 => self.zp0(),
932 ZPX => self.zpx(),
933 ZPY => self.zpy(),
934 ABS => self.abs(),
935 ABX => self.abx(),
936 ABY => self.aby(),
937 IND => self.ind(),
938 IDX => self.idx(),
939 IDY => self.idy(),
940 REL => self.rel(),
941 ACC => self.acc(),
942 IMP => self.imp(),
943 };
944
945 match self.instr.op() {
946 ADC => self.adc(), AND => self.and(), ASL => self.asl(), BCC => self.bcc(), BCS => self.bcs(), BEQ => self.beq(), BIT => self.bit(), BMI => self.bmi(), BNE => self.bne(), BPL => self.bpl(), BRK => self.brk(), BVC => self.bvc(), BVS => self.bvs(), CLC => self.clc(), CLD => self.cld(), CLI => self.cli(), CLV => self.clv(), CMP => self.cmp(), CPX => self.cpx(), CPY => self.cpy(), DEC => self.dec(), DEX => self.dex(), DEY => self.dey(), EOR => self.eor(), INC => self.inc(), INX => self.inx(), INY => self.iny(), JMP => self.jmp(), JSR => self.jsr(), LDA => self.lda(), LDX => self.ldx(), LDY => self.ldy(), LSR => self.lsr(), NOP => self.nop(), SKB => self.skb(), IGN => self.ign(), ORA => self.ora(), PHA => self.pha(), PHP => self.php(), PLA => self.pla(), PLP => self.plp(), ROL => self.rol(), ROR => self.ror(), RTI => self.rti(), RTS => self.rts(), SBC => self.sbc(), SEC => self.sec(), SED => self.sed(), SEI => self.sei(), STA => self.sta(), STX => self.stx(), STY => self.sty(), TAX => self.tax(), TAY => self.tay(), TSX => self.tsx(), TXA => self.txa(), TXS => self.txs(), TYA => self.tya(), ISB => self.isb(), DCP => self.dcp(), AXS => self.axs(), LAS => self.las(), LAX => self.lax(), AHX => self.ahx(), SAX => self.sax(), XAA => self.xaa(), SXA => self.sxa(), RRA => self.rra(), TAS => self.tas(), SYA => self.sya(), ARR => self.arr(), SRE => self.sre(), ALR => self.alr(), RLA => self.rla(), ANC => self.anc(), SLO => self.slo(), XXX => self.xxx(), }
1024
1025 if self.prev_run_irq || self.prev_nmi {
1026 self.irq();
1027 }
1028
1029 if !self.cycle_accurate {
1030 self.bus.clock_to(self.master_clock - Self::PPU_OFFSET);
1031 let cycles = self.cycle - start_cycle;
1032 for _ in 0..cycles {
1033 self.bus.clock();
1034 }
1035 self.handle_interrupts();
1036 }
1037
1038 self.cycle - start_cycle
1039 }
1040}
1041
1042impl Clock for Cpu {
1043 fn clock(&mut self) -> usize {
1045 self.clock_inspect(|_| {})
1046 }
1047}
1048
1049impl Mem for Cpu {
1050 fn read(&mut self, addr: u16, access: Access) -> u8 {
1051 if self.halt || self.bus.oam_dma() {
1052 self.handle_dma(addr);
1053 }
1054
1055 self.start_cycle(Cycle::Read);
1056 let val = self.bus.read(addr, access);
1057 self.end_cycle(Cycle::Read);
1058 val
1059 }
1060
1061 fn peek(&self, addr: u16, access: Access) -> u8 {
1062 self.bus.peek(addr, access)
1063 }
1064
1065 fn write(&mut self, addr: u16, val: u8, access: Access) {
1066 self.start_cycle(Cycle::Write);
1067 self.bus.write(addr, val, access);
1068 self.end_cycle(Cycle::Write);
1069 }
1070}
1071
1072impl Regional for Cpu {
1073 #[inline]
1074 fn region(&self) -> NesRegion {
1075 self.region
1076 }
1077
1078 fn set_region(&mut self, region: NesRegion) {
1079 let (clock_divider, start_clocks, end_clocks) = match region {
1080 NesRegion::Ntsc => (12, 6, 6),
1081 NesRegion::Pal => (16, 8, 8),
1082 NesRegion::Dendy => (15, 7, 8),
1083 };
1084 self.region = region;
1085 self.clock_divider = clock_divider;
1086 self.start_clocks = start_clocks;
1087 self.end_clocks = end_clocks;
1088 self.bus.set_region(region);
1089 }
1090}
1091
1092impl Reset for Cpu {
1093 fn reset(&mut self, kind: ResetKind) {
1099 log::trace!("{:?} RESET", kind);
1100
1101 match kind {
1102 ResetKind::Soft => {
1103 self.status.set(Status::I, true);
1104 self.sp = self.sp.wrapping_sub(0x03);
1107 }
1108 ResetKind::Hard => {
1109 self.acc = 0x00;
1110 self.x = 0x00;
1111 self.y = 0x00;
1112 self.status = Self::POWER_ON_STATUS;
1113 self.sp = Self::POWER_ON_SP;
1114 }
1115 }
1116
1117 self.bus.reset(kind);
1118 self.cycle = 0;
1119 self.master_clock = 0;
1120 self.irq = Irq::empty();
1121 self.run_irq = false;
1122 self.prev_run_irq = false;
1123 self.nmi = false;
1124 self.prev_nmi = false;
1125 self.prev_nmi_pending = false;
1126 self.corrupted = false;
1127 self.halt = false;
1128 self.dummy_read = false;
1129
1130 let lo = self.bus.read(Self::RESET_VECTOR, Access::Read);
1132 let hi = self.bus.read(Self::RESET_VECTOR + 1, Access::Read);
1133 self.pc = u16::from_le_bytes([lo, hi]);
1134
1135 for _ in 0..7 {
1136 self.start_cycle(Cycle::Read);
1137 self.end_cycle(Cycle::Read);
1138 }
1139 }
1140}
1141
1142impl fmt::Debug for Cpu {
1143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::result::Result<(), fmt::Error> {
1144 f.debug_struct("Cpu")
1145 .field("cycle", &self.cycle)
1146 .field("pc", &format_args!("${:04X}", self.pc))
1147 .field("sp", &format_args!("${:02X}", self.sp))
1148 .field("acc", &format_args!("${:02X}", self.acc))
1149 .field("x", &format_args!("${:02X}", self.x))
1150 .field("y", &format_args!("${:02X}", self.y))
1151 .field("status", &self.status)
1152 .field("bus", &self.bus)
1153 .field("instr", &self.instr)
1154 .field("abs_addr", &format_args!("${:04X}", self.abs_addr))
1155 .field("rel_addr", &format_args!("${:04X}", self.rel_addr))
1156 .field("fetched_data", &format_args!("${:02X}", self.fetched_data))
1157 .field("irq", &self.irq)
1158 .field("nmi", &self.nmi)
1159 .field("prev_nmi", &self.prev_nmi)
1160 .field("prev_nmi_pending", &self.prev_nmi_pending)
1161 .field("corrupted", &self.corrupted)
1162 .field("run_irq", &self.run_irq)
1163 .field("last_run_irq", &self.prev_run_irq)
1164 .field("halt", &self.halt)
1165 .field("dummy_read", &self.dummy_read)
1166 .finish()
1167 }
1168}
1169
1170#[cfg(test)]
1171mod tests {
1172 use crate::common::ResetKind;
1173
1174 #[test]
1175 fn cycle_timing() {
1176 use super::*;
1177 let mut cpu = Cpu::new(CpuBus::default());
1178 let cart = Cart::empty();
1179 cpu.load_cart(cart);
1180 cpu.reset(ResetKind::Hard);
1181 cpu.clock();
1182
1183 assert_eq!(cpu.cycle, 14, "cpu after power + one clock");
1184
1185 for instr in Cpu::INSTRUCTIONS.iter() {
1186 let extra_cycle = match instr.op() {
1187 BCC | BNE | BPL | BVC => 1,
1188 _ => 0,
1189 };
1190 if instr.op() == XXX {
1192 continue;
1193 }
1194 cpu.reset(ResetKind::Hard);
1195 cpu.bus.write(0x0000, instr.opcode(), Access::Write);
1196 cpu.clock();
1197 let cpu_cyc = 7 + instr.cycles() + extra_cycle;
1198 assert_eq!(
1199 cpu.cycle,
1200 cpu_cyc,
1201 "cpu ${:02X} {:?} #{:?}",
1202 instr.opcode(),
1203 instr.op(),
1204 instr.addr_mode()
1205 );
1206 }
1207 }
1208}