virt_ic/chip/cpu/nes6502.rs
1pub mod assembler;
2pub mod opcodes;
3
4pub use assembler::Assembler;
5pub use opcodes::{AddressingMode, Opcode};
6
7use crate::{
8 chip::{ChipBuilder, ChipRunner, ChipSet, Pin, PinType},
9 generate_chip, State,
10};
11
12use bitflags::bitflags;
13
14use super::Reg;
15
16bitflags! {
17 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
19 pub struct StatusRegister: u8 {
20 /// Negative
21 const N = 0b10000000;
22 /// Overflow
23 const V = 0b01000000;
24 /// Break
25 const B = 0b00010000;
26 /// Decimal
27 const D = 0b00001000;
28 /// Interrupt Disable
29 const I = 0b00000100;
30 /// Zero
31 const Z = 0b00000010;
32 /// Carry
33 const C = 0b00000001;
34 }
35}
36
37#[derive(Debug, Clone, Copy)]
38#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39pub enum CpuState {
40 Reset,
41 ResetCollectHighByte,
42 ResetCollectLowByte,
43 NmiCollectHighByte,
44 NmiCollectLowByte,
45 IrqCollectHighByte,
46 IrqCollectLowByte,
47 Fetch,
48 Arg1(Opcode),
49 Arg2(Opcode),
50 Execute(Opcode, usize),
51 Halted,
52}
53
54#[derive(Debug, Clone, Copy, Default)]
55#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
56pub struct Registers {
57 pub a: Reg<u8>,
58 pub x: Reg<u8>,
59 pub y: Reg<u8>,
60 pub pc: Reg<u16>,
61 pub s: Reg<u8>,
62 pub p: StatusRegister,
63}
64
65impl ToString for Registers {
66 fn to_string(&self) -> std::string::String {
67 format!(
68 "A={:0X}\tX={:0X}\tY={:0X}\tS={:0X}\tPC={:0X}\tP={}{}{}{}{}{}{}{}",
69 *self.a,
70 *self.x,
71 *self.y,
72 *self.s,
73 *self.pc,
74 if self.p.contains(StatusRegister::N) {
75 "N"
76 } else {
77 "-"
78 },
79 if self.p.contains(StatusRegister::V) {
80 "V"
81 } else {
82 "-"
83 },
84 "-",
85 if self.p.contains(StatusRegister::B) {
86 "B"
87 } else {
88 "-"
89 },
90 if self.p.contains(StatusRegister::D) {
91 "D"
92 } else {
93 "-"
94 },
95 if self.p.contains(StatusRegister::I) {
96 "I"
97 } else {
98 "-"
99 },
100 if self.p.contains(StatusRegister::Z) {
101 "Z"
102 } else {
103 "-"
104 },
105 if self.p.contains(StatusRegister::C) {
106 "C"
107 } else {
108 "-"
109 },
110 )
111 }
112}
113
114/// <https://www.nesdev.org/wiki/CPU_pinout>
115/// Without the APU part yet
116/// Neither the interrupt handling and decimal mode
117/// WARNING: Not cycle accurate yet!
118///
119/// ```txt
120/// .--\/--.
121/// AD1 <- |01 40| -- +5V
122/// AD2 <- |02 39| -> OUT0
123/// /RST -> |03 38| -> OUT1
124/// A00 <- |04 37| -> OUT2
125/// A01 <- |05 36| -> /OE1
126/// A02 <- |06 35| -> /OE2
127/// A03 <- |07 34| -> R/W
128/// A04 <- |08 33| <- /NMI
129/// A05 <- |09 32| <- /IRQ
130/// A06 <- |10 31| -> M2
131/// A07 <- |11 30| <- TST (usually GND)
132/// A08 <- |12 29| <- CLK
133/// A09 <- |13 28| <> D0
134/// A10 <- |14 27| <> D1
135/// A11 <- |15 26| <> D2
136/// A12 <- |16 25| <> D3
137/// A13 <- |17 24| <> D4
138/// A14 <- |18 23| <> D5
139/// A15 <- |19 22| <> D6
140/// GND -- |20 21| <> D7
141/// `------'
142/// ```
143#[derive(Debug, Clone)]
144#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
145pub struct Nes6502 {
146 powered: bool,
147 clock: bool,
148 state: CpuState,
149 registers: Registers,
150 buffer: u16,
151 pub vcc: Pin,
152 pub gnd: Pin,
153 pub rst: Pin,
154 pub out0: Pin,
155 pub out1: Pin,
156 pub out2: Pin,
157 pub oe1: Pin,
158 pub oe2: Pin,
159 pub rw: Pin,
160 pub nmi: Pin,
161 pub irq: Pin,
162 pub m2: Pin,
163 pub tst: Pin,
164 pub clk: Pin,
165 pub ad1: Pin,
166 pub ad2: Pin,
167 pub a0: Pin,
168 pub a1: Pin,
169 pub a2: Pin,
170 pub a3: Pin,
171 pub a4: Pin,
172 pub a5: Pin,
173 pub a6: Pin,
174 pub a7: Pin,
175 pub a8: Pin,
176 pub a9: Pin,
177 pub a10: Pin,
178 pub a11: Pin,
179 pub a12: Pin,
180 pub a13: Pin,
181 pub a14: Pin,
182 pub a15: Pin,
183 pub d0: Pin,
184 pub d1: Pin,
185 pub d2: Pin,
186 pub d3: Pin,
187 pub d4: Pin,
188 pub d5: Pin,
189 pub d6: Pin,
190 pub d7: Pin,
191}
192
193impl Nes6502 {
194 pub const VCC: usize = 40;
195 pub const GND: usize = 20;
196 pub const RST: usize = 3;
197 pub const OUT0: usize = 39;
198 pub const OUT1: usize = 38;
199 pub const OUT2: usize = 37;
200 pub const OE1: usize = 36;
201 pub const OE2: usize = 35;
202 /// Read/write signal, which is used to indicate operations of the same names. Low is write. R/W stays high/low during the entire read/write cycle.
203 pub const RW: usize = 34;
204 /// Non-maskable interrupt pin. See the 6502 manual and CPU interrupts for more details.
205 pub const NMI: usize = 33;
206 /// Interrupt pin. See the 6502 manual and CPU interrupts for more details
207 pub const IRQ: usize = 32;
208 pub const M2: usize = 31;
209 pub const TST: usize = 30;
210 pub const CLK: usize = 29;
211 pub const AD1: usize = 1;
212 pub const AD2: usize = 2;
213 pub const A0: usize = 4;
214 pub const A1: usize = 5;
215 pub const A2: usize = 6;
216 pub const A3: usize = 7;
217 pub const A4: usize = 8;
218 pub const A5: usize = 9;
219 pub const A6: usize = 10;
220 pub const A7: usize = 11;
221 pub const A8: usize = 12;
222 pub const A9: usize = 13;
223 pub const A10: usize = 14;
224 pub const A11: usize = 15;
225 pub const A12: usize = 16;
226 pub const A13: usize = 17;
227 pub const A14: usize = 18;
228 pub const A15: usize = 19;
229 pub const D0: usize = 28;
230 pub const D1: usize = 27;
231 pub const D2: usize = 26;
232 pub const D3: usize = 25;
233 pub const D4: usize = 24;
234 pub const D5: usize = 23;
235 pub const D6: usize = 22;
236 pub const D7: usize = 21;
237}
238
239generate_chip!(
240 Nes6502,
241 vcc: Nes6502::VCC,
242 gnd: Nes6502::GND,
243 rst: Nes6502::RST,
244 out0: Nes6502::OUT0,
245 out1: Nes6502::OUT1,
246 out2: Nes6502::OUT2,
247 oe1: Nes6502::OE1,
248 oe2: Nes6502::OE2,
249 rw: Nes6502::RW,
250 nmi: Nes6502::NMI,
251 irq: Nes6502::IRQ,
252 m2: Nes6502::M2,
253 tst: Nes6502::TST,
254 clk: Nes6502::CLK,
255 ad1: Nes6502::AD1,
256 ad2: Nes6502::AD2,
257 a0: Nes6502::A0,
258 a1: Nes6502::A1,
259 a2: Nes6502::A2,
260 a3: Nes6502::A3,
261 a4: Nes6502::A4,
262 a5: Nes6502::A5,
263 a6: Nes6502::A6,
264 a7: Nes6502::A7,
265 a8: Nes6502::A8,
266 a9: Nes6502::A9,
267 a10: Nes6502::A10,
268 a11: Nes6502::A11,
269 a12: Nes6502::A12,
270 a13: Nes6502::A13,
271 a14: Nes6502::A14,
272 a15: Nes6502::A15,
273 d0: Nes6502::D0,
274 d1: Nes6502::D1,
275 d2: Nes6502::D2,
276 d3: Nes6502::D3,
277 d4: Nes6502::D4,
278 d5: Nes6502::D5,
279 d6: Nes6502::D6,
280 d7: Nes6502::D7
281);
282
283impl ChipBuilder<ChipSet> for Nes6502 {
284 fn build() -> ChipSet {
285 ChipSet::Nes6502(Box::new(Nes6502 {
286 powered: false,
287 clock: false,
288 state: CpuState::Reset,
289 registers: Registers::default(),
290 buffer: 0,
291 vcc: Pin::from(PinType::Input),
292 gnd: Pin::from(PinType::Output),
293 rst: Pin::from(PinType::Input),
294 out0: Pin::from(PinType::Output),
295 out1: Pin::from(PinType::Output),
296 out2: Pin::from(PinType::Output),
297 oe1: Pin::from(PinType::Output),
298 oe2: Pin::from(PinType::Output),
299 rw: Pin::from(PinType::Output),
300 nmi: Pin::from(PinType::Input),
301 irq: Pin::from(PinType::Input),
302 m2: Pin::from(PinType::Output),
303 tst: Pin::from(PinType::Input),
304 clk: Pin::from(PinType::Input),
305 ad1: Pin::from(PinType::Output),
306 ad2: Pin::from(PinType::Output),
307 a0: Pin::from(PinType::Output),
308 a1: Pin::from(PinType::Output),
309 a2: Pin::from(PinType::Output),
310 a3: Pin::from(PinType::Output),
311 a4: Pin::from(PinType::Output),
312 a5: Pin::from(PinType::Output),
313 a6: Pin::from(PinType::Output),
314 a7: Pin::from(PinType::Output),
315 a8: Pin::from(PinType::Output),
316 a9: Pin::from(PinType::Output),
317 a10: Pin::from(PinType::Output),
318 a11: Pin::from(PinType::Output),
319 a12: Pin::from(PinType::Output),
320 a13: Pin::from(PinType::Output),
321 a14: Pin::from(PinType::Output),
322 a15: Pin::from(PinType::Output),
323 d0: Pin::from(PinType::Floating),
324 d1: Pin::from(PinType::Floating),
325 d2: Pin::from(PinType::Floating),
326 d3: Pin::from(PinType::Floating),
327 d4: Pin::from(PinType::Floating),
328 d5: Pin::from(PinType::Floating),
329 d6: Pin::from(PinType::Floating),
330 d7: Pin::from(PinType::Floating),
331 }))
332 }
333}
334
335impl Nes6502 {
336 pub fn set_addr(&mut self, addr: u16) {
337 Pin::write(
338 &mut [
339 &mut self.a0,
340 &mut self.a1,
341 &mut self.a2,
342 &mut self.a3,
343 &mut self.a4,
344 &mut self.a5,
345 &mut self.a6,
346 &mut self.a7,
347 &mut self.a8,
348 &mut self.a9,
349 &mut self.a10,
350 &mut self.a11,
351 &mut self.a12,
352 &mut self.a13,
353 &mut self.a14,
354 &mut self.a15,
355 ],
356 addr as usize,
357 );
358 }
359
360 fn set_data_type(&mut self, pin_type: PinType) {
361 match pin_type {
362 PinType::Input => self.rw.state = State::High,
363 PinType::Output => self.rw.state = State::Low,
364 PinType::Floating => {}
365 }
366 self.d0.pin_type = pin_type;
367 self.d1.pin_type = pin_type;
368 self.d2.pin_type = pin_type;
369 self.d3.pin_type = pin_type;
370 self.d4.pin_type = pin_type;
371 self.d5.pin_type = pin_type;
372 self.d6.pin_type = pin_type;
373 self.d7.pin_type = pin_type;
374 }
375
376 pub fn set_data(&mut self, data: u8) {
377 Pin::write(
378 &mut [
379 &mut self.d0,
380 &mut self.d1,
381 &mut self.d2,
382 &mut self.d3,
383 &mut self.d4,
384 &mut self.d5,
385 &mut self.d6,
386 &mut self.d7,
387 ],
388 data as usize,
389 );
390 }
391
392 pub fn get_data(&self) -> u8 {
393 Pin::read_threshold(
394 &[
395 &self.d0, &self.d1, &self.d2, &self.d3, &self.d4, &self.d5, &self.d6, &self.d7,
396 ],
397 3.3,
398 ) as u8
399 }
400}
401
402impl ChipRunner for Nes6502 {
403 fn run(&mut self, _: std::time::Duration) {
404 if self.vcc.state.as_logic(3.3) == State::High {
405 if !self.powered {
406 self.state = CpuState::Reset;
407 self.registers.p = StatusRegister::from_bits_retain(0x34);
408 self.registers.a = 0.into();
409 self.registers.x = 0.into();
410 self.registers.y = 0.into();
411 self.registers.s = 0xFD.into();
412 self.registers.pc = 0xFFFC.into();
413
414 self.powered = true;
415 }
416
417 if self.clock != self.clk.state.as_logic(3.3).into() {
418 self.clock = self.clk.state.as_logic(3.3).into();
419 self.m2.state = State::from(self.clock);
420 if self.clock {
421 match self.state {
422 CpuState::Reset
423 | CpuState::ResetCollectHighByte
424 | CpuState::ResetCollectLowByte
425 | CpuState::NmiCollectHighByte
426 | CpuState::NmiCollectLowByte
427 | CpuState::IrqCollectHighByte
428 | CpuState::IrqCollectLowByte
429 | CpuState::Fetch
430 | CpuState::Arg1(_)
431 | CpuState::Arg2(_) => {
432 self.set_data_type(PinType::Input);
433 }
434 CpuState::Execute(_, _) => {}
435 CpuState::Halted => self.set_data_type(PinType::Floating),
436 }
437 } else {
438 match self.state {
439 CpuState::Reset => {
440 self.set_addr(*self.registers.pc);
441 self.registers.pc.inc();
442 self.state = CpuState::ResetCollectHighByte;
443 }
444 CpuState::ResetCollectHighByte => {
445 self.buffer = (self.get_data() as u16) << 8;
446 self.set_addr(*self.registers.pc);
447 self.registers.pc.inc();
448 self.state = CpuState::ResetCollectLowByte;
449 }
450 CpuState::ResetCollectLowByte => {
451 self.buffer = self.buffer.wrapping_add(self.get_data() as u16);
452 self.registers.pc = self.buffer.into();
453 self.set_addr(*self.registers.pc);
454 self.registers.pc.inc();
455 self.state = CpuState::Fetch;
456 }
457 CpuState::NmiCollectHighByte => todo!(),
458 CpuState::NmiCollectLowByte => todo!(),
459 CpuState::IrqCollectHighByte => todo!(),
460 CpuState::IrqCollectLowByte => todo!(),
461 CpuState::Fetch => {
462 let opcode = Opcode::from(self.get_data());
463 if opcode.require_arg1() {
464 self.set_addr(*self.registers.pc);
465 self.registers.pc.inc();
466 self.state = CpuState::Arg1(opcode);
467 } else {
468 self.state = CpuState::Execute(opcode, 0);
469 }
470 }
471 CpuState::Arg1(mut opcode) => {
472 opcode.set_arg1(self.get_data());
473 if opcode.require_arg2() {
474 self.set_addr(*self.registers.pc);
475 self.registers.pc.inc();
476 self.state = CpuState::Arg2(opcode);
477 } else {
478 self.state = CpuState::Execute(opcode, 0);
479 }
480 }
481 CpuState::Arg2(mut opcode) => {
482 opcode.set_arg2(self.get_data());
483 self.state = CpuState::Execute(opcode, 0);
484 }
485 CpuState::Execute(mut opcode, mut step) => {
486 if opcode.need_compute() {
487 opcode.compute(self, step);
488 if !opcode.need_compute() {
489 step = 0;
490 } else {
491 step += 1;
492 }
493 } else {
494 match opcode {
495 Opcode::ADC(a) => match a {
496 AddressingMode::Immediate(i) => self.run_adc(i),
497 AddressingMode::ZeroPage(z) => {
498 if step == 0 {
499 self.set_addr(z as u16);
500 self.set_data_type(PinType::Input);
501 step += 1;
502 } else {
503 self.run_adc(self.get_data());
504 }
505 }
506 AddressingMode::Absolute(a) => {
507 if step == 0 {
508 self.set_addr(a);
509 self.set_data_type(PinType::Input);
510 step += 1;
511 } else {
512 self.run_adc(self.get_data());
513 }
514 }
515 _ => unreachable!(),
516 },
517 Opcode::AND(a) => match a {
518 AddressingMode::Immediate(i) => self.run_and(i),
519 AddressingMode::ZeroPage(z) => {
520 if step == 0 {
521 self.set_addr(z as u16);
522 self.set_data_type(PinType::Input);
523 step += 1;
524 } else {
525 self.run_and(self.get_data());
526 }
527 }
528 AddressingMode::Absolute(a) => {
529 if step == 0 {
530 self.set_addr(a);
531 self.set_data_type(PinType::Input);
532 step += 1;
533 } else {
534 self.run_and(self.get_data());
535 }
536 }
537 _ => unreachable!(),
538 },
539 Opcode::ASL(a) => match a {
540 AddressingMode::Implicit => {
541 self.registers.p.set(
542 StatusRegister::C,
543 (self.registers.a & 0x80) > 0,
544 );
545 self.registers.a <<= 1;
546 self.set_flags_nz(*self.registers.a);
547 self.state = CpuState::Fetch;
548 }
549 AddressingMode::ZeroPage(z) => {
550 if step == 0 {
551 self.set_addr(z as u16);
552 self.set_data_type(PinType::Input);
553 step += 1;
554 } else if step == 1 {
555 let mut data = self.get_data();
556 self.registers
557 .p
558 .set(StatusRegister::C, (data & 0x80) > 0);
559 data <<= 1;
560 self.set_data(data);
561 self.set_data_type(PinType::Output);
562 self.set_flags_nz(data);
563 step += 1;
564 } else {
565 self.state = CpuState::Fetch
566 }
567 }
568 AddressingMode::Absolute(a) => {
569 if step == 0 {
570 self.set_addr(a);
571 self.set_data_type(PinType::Input);
572 step += 1;
573 } else if step == 1 {
574 let mut data = self.get_data();
575 self.registers
576 .p
577 .set(StatusRegister::C, (data & 0x80) > 0);
578 data <<= 1;
579 self.set_data(data);
580 self.set_data_type(PinType::Output);
581 self.set_flags_nz(data);
582 step += 1;
583 } else {
584 self.state = CpuState::Fetch
585 }
586 }
587 _ => unreachable!(),
588 },
589 Opcode::BIT(a) => match a {
590 AddressingMode::ZeroPage(z) => {
591 if step == 0 {
592 self.set_addr(z as u16);
593 self.set_data_type(PinType::Input);
594 step += 1;
595 } else {
596 self.run_bit(self.get_data());
597 }
598 }
599 AddressingMode::Absolute(a) => {
600 if step == 0 {
601 self.set_addr(a);
602 self.set_data_type(PinType::Input);
603 step += 1;
604 } else {
605 self.run_bit(self.get_data());
606 }
607 }
608 _ => unreachable!(),
609 },
610 Opcode::BPL(ra) => {
611 if !self.registers.p.contains(StatusRegister::N) {
612 self.jump_relative(ra);
613 }
614 self.state = CpuState::Fetch;
615 }
616 Opcode::BMI(ra) => {
617 if self.registers.p.contains(StatusRegister::N) {
618 self.jump_relative(ra);
619 }
620 self.state = CpuState::Fetch;
621 }
622 Opcode::BVC(ra) => {
623 if !self.registers.p.contains(StatusRegister::V) {
624 self.jump_relative(ra);
625 }
626 self.state = CpuState::Fetch;
627 }
628 Opcode::BVS(ra) => {
629 if self.registers.p.contains(StatusRegister::V) {
630 self.jump_relative(ra);
631 }
632 self.state = CpuState::Fetch;
633 }
634 Opcode::BCC(ra) => {
635 if !self.registers.p.contains(StatusRegister::C) {
636 self.jump_relative(ra);
637 }
638 self.state = CpuState::Fetch;
639 }
640 Opcode::BCS(ra) => {
641 if self.registers.p.contains(StatusRegister::C) {
642 self.jump_relative(ra);
643 }
644 self.state = CpuState::Fetch;
645 }
646 Opcode::BNE(ra) => {
647 if !self.registers.p.contains(StatusRegister::Z) {
648 self.jump_relative(ra);
649 }
650 self.state = CpuState::Fetch;
651 }
652 Opcode::BEQ(ra) => {
653 if self.registers.p.contains(StatusRegister::Z) {
654 self.jump_relative(ra);
655 }
656 self.state = CpuState::Fetch;
657 }
658 Opcode::BRK => todo!(),
659 Opcode::CMP(a) => match a {
660 AddressingMode::Immediate(i) => {
661 self.run_cmp(self.registers.a, i);
662 }
663 AddressingMode::ZeroPage(z) => {
664 if step == 0 {
665 self.set_addr(z as u16);
666 self.set_data_type(PinType::Input);
667 step += 1;
668 } else {
669 self.run_cmp(self.registers.a, self.get_data());
670 }
671 }
672 AddressingMode::Absolute(a) => {
673 if step == 0 {
674 self.set_addr(a);
675 self.set_data_type(PinType::Input);
676 step += 1;
677 } else {
678 self.run_cmp(self.registers.a, self.get_data());
679 }
680 }
681 _ => unreachable!(),
682 },
683 Opcode::CPX(a) => match a {
684 AddressingMode::Immediate(i) => {
685 self.run_cmp(self.registers.x, i);
686 }
687 AddressingMode::ZeroPage(z) => {
688 if step == 0 {
689 self.set_addr(z as u16);
690 self.set_data_type(PinType::Input);
691 step += 1;
692 } else {
693 self.run_cmp(self.registers.x, self.get_data());
694 }
695 }
696 AddressingMode::Absolute(a) => {
697 if step == 0 {
698 self.set_addr(a);
699 self.set_data_type(PinType::Input);
700 step += 1;
701 } else {
702 self.run_cmp(self.registers.x, self.get_data());
703 }
704 }
705 _ => unreachable!(),
706 },
707 Opcode::CPY(a) => match a {
708 AddressingMode::Immediate(i) => {
709 self.run_cmp(self.registers.y, i);
710 }
711 AddressingMode::ZeroPage(z) => {
712 if step == 0 {
713 self.set_addr(z as u16);
714 self.set_data_type(PinType::Input);
715 step += 1;
716 } else {
717 self.run_cmp(self.registers.y, self.get_data());
718 }
719 }
720 AddressingMode::Absolute(a) => {
721 if step == 0 {
722 self.set_addr(a);
723 self.set_data_type(PinType::Input);
724 step += 1;
725 } else {
726 self.run_cmp(self.registers.y, self.get_data());
727 }
728 }
729 _ => unreachable!(),
730 },
731 Opcode::DEC(a) => match a {
732 AddressingMode::ZeroPage(z) => {
733 if step == 0 {
734 self.set_addr(z as u16);
735 self.set_data_type(PinType::Input);
736 step += 1;
737 } else if step == 1 {
738 let data = self.get_data().wrapping_sub(1);
739 self.set_flags_nz(data);
740 self.set_data(data);
741 self.set_data_type(PinType::Output);
742 step += 1;
743 } else {
744 self.state = CpuState::Fetch;
745 }
746 }
747 AddressingMode::Absolute(a) => {
748 if step == 0 {
749 self.set_addr(a);
750 self.set_data_type(PinType::Input);
751 step += 1;
752 } else if step == 1 {
753 let data = self.get_data().wrapping_sub(1);
754 self.set_flags_nz(data);
755 self.set_data(data);
756 self.set_data_type(PinType::Output);
757 step += 1;
758 } else {
759 self.state = CpuState::Fetch;
760 }
761 }
762 _ => unreachable!(),
763 },
764 Opcode::EOR(a) => match a {
765 AddressingMode::Immediate(i) => self.run_eor(i),
766 AddressingMode::ZeroPage(z) => {
767 if step == 0 {
768 self.set_addr(z as u16);
769 self.set_data_type(PinType::Input);
770 step += 1;
771 } else {
772 self.run_eor(self.get_data());
773 }
774 }
775 AddressingMode::Absolute(a) => {
776 if step == 0 {
777 self.set_addr(a);
778 self.set_data_type(PinType::Input);
779 step += 1;
780 } else {
781 self.run_eor(self.get_data());
782 }
783 }
784 _ => unreachable!(),
785 },
786 Opcode::CLC => {
787 self.registers.p.set(StatusRegister::C, false);
788 self.state = CpuState::Fetch
789 }
790 Opcode::SEC => {
791 self.registers.p.set(StatusRegister::C, true);
792 self.state = CpuState::Fetch
793 }
794 Opcode::CLI => {
795 self.registers.p.set(StatusRegister::I, false);
796 self.state = CpuState::Fetch
797 }
798 Opcode::SEI => {
799 self.registers.p.set(StatusRegister::I, true);
800 self.state = CpuState::Fetch
801 }
802 Opcode::CLV => {
803 self.registers.p.set(StatusRegister::V, false);
804 self.state = CpuState::Fetch
805 }
806 Opcode::INC(a) => match a {
807 AddressingMode::ZeroPage(z) => {
808 if step == 0 {
809 self.set_addr(z as u16);
810 self.set_data_type(PinType::Input);
811 step += 1;
812 } else if step == 1 {
813 let data = self.get_data().wrapping_add(1);
814 self.set_flags_nz(data);
815 self.set_data(data);
816 self.set_data_type(PinType::Output);
817 step += 1;
818 } else {
819 self.state = CpuState::Fetch;
820 }
821 }
822 AddressingMode::Absolute(a) => {
823 if step == 0 {
824 self.set_addr(a);
825 self.set_data_type(PinType::Input);
826 step += 1;
827 } else if step == 1 {
828 let data = self.get_data().wrapping_add(1);
829 self.set_flags_nz(data);
830 self.set_data(data);
831 self.set_data_type(PinType::Output);
832 step += 1;
833 } else {
834 self.state = CpuState::Fetch;
835 }
836 }
837 _ => unreachable!(),
838 },
839 Opcode::JMP(AddressingMode::Absolute(a)) => {
840 self.registers.pc = a.into();
841 self.state = CpuState::Fetch;
842 }
843 Opcode::JMP(_) => unreachable!(),
844 Opcode::JSR(AddressingMode::Absolute(a)) => {
845 if step == 0 {
846 let alt_pc = (*self.registers.pc).wrapping_sub(1);
847 self.push_stack((alt_pc >> 8) as u8);
848 step += 1;
849 } else if step == 1 {
850 let alt_pc = (*self.registers.pc).wrapping_sub(1);
851 self.push_stack(alt_pc as u8);
852 step += 1;
853 } else {
854 self.registers.pc = a.into();
855 self.state = CpuState::Fetch;
856 }
857 }
858 Opcode::JSR(_) => unreachable!(),
859 Opcode::LDA(a) => match a {
860 AddressingMode::Immediate(i) => {
861 self.run_lda(i);
862 }
863 AddressingMode::ZeroPage(z) => {
864 if step == 0 {
865 self.set_addr(z as u16);
866 self.set_data_type(PinType::Input);
867 step += 1;
868 } else {
869 self.run_lda(self.get_data());
870 }
871 }
872 AddressingMode::Absolute(a) => {
873 if step == 0 {
874 self.set_addr(a);
875 self.set_data_type(PinType::Input);
876 step += 1;
877 } else {
878 self.run_lda(self.get_data());
879 }
880 }
881 _ => unreachable!(),
882 },
883 Opcode::LDX(a) => match a {
884 AddressingMode::Immediate(i) => {
885 self.run_ldx(i);
886 }
887 AddressingMode::ZeroPage(z) => {
888 if step == 0 {
889 self.set_addr(z as u16);
890 self.set_data_type(PinType::Input);
891 step += 1;
892 } else {
893 self.run_ldx(self.get_data());
894 }
895 }
896 AddressingMode::Absolute(a) => {
897 if step == 0 {
898 self.set_addr(a);
899 self.set_data_type(PinType::Input);
900 step += 1;
901 } else {
902 self.run_ldx(self.get_data());
903 }
904 }
905 _ => unreachable!(),
906 },
907 Opcode::LDY(a) => match a {
908 AddressingMode::Immediate(i) => {
909 self.run_ldy(i);
910 }
911 AddressingMode::ZeroPage(z) => {
912 if step == 0 {
913 self.set_addr(z as u16);
914 self.set_data_type(PinType::Input);
915 step += 1;
916 } else {
917 self.run_ldy(self.get_data());
918 }
919 }
920 AddressingMode::Absolute(a) => {
921 if step == 0 {
922 self.set_addr(a);
923 self.set_data_type(PinType::Input);
924 step += 1;
925 } else {
926 self.run_ldy(self.get_data());
927 }
928 }
929 _ => unreachable!(),
930 },
931 Opcode::LSR(a) => match a {
932 AddressingMode::Implicit => {
933 self.registers.p.set(
934 StatusRegister::C,
935 (self.registers.a & 0x01) > 0,
936 );
937 self.registers.a >>= 1;
938 self.set_flags_nz(*self.registers.a);
939 self.state = CpuState::Fetch;
940 }
941 AddressingMode::ZeroPage(z) => {
942 if step == 0 {
943 self.set_addr(z as u16);
944 self.set_data_type(PinType::Input);
945 step += 1;
946 } else if step == 1 {
947 let mut data = self.get_data();
948 self.registers
949 .p
950 .set(StatusRegister::C, (data & 0x01) > 0);
951 data >>= 1;
952 self.set_data(data);
953 self.set_data_type(PinType::Output);
954 self.set_flags_nz(data);
955 step += 1;
956 } else {
957 self.state = CpuState::Fetch
958 }
959 }
960 AddressingMode::Absolute(a) => {
961 if step == 0 {
962 self.set_addr(a);
963 self.set_data_type(PinType::Input);
964 step += 1;
965 } else if step == 1 {
966 let mut data = self.get_data();
967 self.registers
968 .p
969 .set(StatusRegister::C, (data & 0x01) > 0);
970 data >>= 1;
971 self.set_data(data);
972 self.set_data_type(PinType::Output);
973 self.set_flags_nz(data);
974 step += 1;
975 } else {
976 self.state = CpuState::Fetch
977 }
978 }
979 _ => unreachable!(),
980 },
981 Opcode::NOP => self.state = CpuState::Fetch,
982 Opcode::ORA(a) => match a {
983 AddressingMode::Immediate(i) => self.run_ora(i),
984 AddressingMode::ZeroPage(z) => {
985 if step == 0 {
986 self.set_addr(z as u16);
987 self.set_data_type(PinType::Input);
988 step += 1;
989 } else {
990 self.run_ora(self.get_data());
991 }
992 }
993 AddressingMode::Absolute(a) => {
994 if step == 0 {
995 self.set_addr(a);
996 self.set_data_type(PinType::Input);
997 step += 1;
998 } else {
999 self.run_ora(self.get_data());
1000 }
1001 }
1002 _ => unreachable!(),
1003 },
1004 Opcode::TAX => {
1005 self.registers.x = self.registers.a;
1006 self.set_flags_nz(*self.registers.x);
1007 self.state = CpuState::Fetch
1008 }
1009 Opcode::TXA => {
1010 self.registers.a = self.registers.x;
1011 self.set_flags_nz(*self.registers.a);
1012 self.state = CpuState::Fetch
1013 }
1014 Opcode::DEX => {
1015 self.registers.x.dec();
1016 self.set_flags_nz(*self.registers.x);
1017 self.state = CpuState::Fetch
1018 }
1019 Opcode::INX => {
1020 self.registers.x.inc();
1021 self.set_flags_nz(*self.registers.x);
1022 self.state = CpuState::Fetch
1023 }
1024 Opcode::TAY => {
1025 self.registers.y = self.registers.a;
1026 self.set_flags_nz(*self.registers.y);
1027 self.state = CpuState::Fetch
1028 }
1029 Opcode::TYA => {
1030 self.registers.a = self.registers.y;
1031 self.set_flags_nz(*self.registers.a);
1032 self.state = CpuState::Fetch
1033 }
1034 Opcode::DEY => {
1035 self.registers.y.dec();
1036 self.set_flags_nz(*self.registers.y);
1037 self.state = CpuState::Fetch
1038 }
1039 Opcode::INY => {
1040 self.registers.y.inc();
1041 self.set_flags_nz(*self.registers.y);
1042 self.state = CpuState::Fetch
1043 }
1044 Opcode::ROL(a) => match a {
1045 AddressingMode::Implicit => {
1046 let old_carry =
1047 self.registers.p.contains(StatusRegister::C) as u8;
1048 self.registers.p.set(
1049 StatusRegister::C,
1050 (self.registers.a & 0x80) > 0,
1051 );
1052 self.registers.a <<= 1;
1053 self.registers.a += old_carry;
1054 self.set_flags_nz(*self.registers.a);
1055 self.state = CpuState::Fetch;
1056 }
1057 AddressingMode::ZeroPage(z) => {
1058 if step == 0 {
1059 self.set_addr(z as u16);
1060 self.set_data_type(PinType::Input);
1061 step += 1;
1062 } else if step == 1 {
1063 let mut data = self.get_data();
1064 let old_carry =
1065 self.registers.p.contains(StatusRegister::C)
1066 as u8;
1067 self.registers
1068 .p
1069 .set(StatusRegister::C, (data & 0x80) > 0);
1070 data <<= 1;
1071 data += old_carry;
1072 self.set_data(data);
1073 self.set_data_type(PinType::Output);
1074 self.set_flags_nz(data);
1075 step += 1;
1076 } else {
1077 self.state = CpuState::Fetch;
1078 }
1079 }
1080 AddressingMode::Absolute(a) => {
1081 if step == 0 {
1082 self.set_addr(a);
1083 self.set_data_type(PinType::Input);
1084 step += 1;
1085 } else if step == 1 {
1086 let mut data = self.get_data();
1087 let old_carry =
1088 self.registers.p.contains(StatusRegister::C)
1089 as u8;
1090 self.registers
1091 .p
1092 .set(StatusRegister::C, (data & 0x80) > 0);
1093 data <<= 1;
1094 data += old_carry;
1095 self.set_data(data);
1096 self.set_data_type(PinType::Output);
1097 self.set_flags_nz(data);
1098 step += 1;
1099 } else {
1100 self.state = CpuState::Fetch;
1101 }
1102 }
1103 _ => unreachable!(),
1104 },
1105 Opcode::ROR(a) => match a {
1106 AddressingMode::Implicit => {
1107 let old_carry =
1108 self.registers.p.contains(StatusRegister::C) as u8;
1109 self.registers.p.set(
1110 StatusRegister::C,
1111 (self.registers.a & 0x01) > 0,
1112 );
1113 self.registers.a >>= 1;
1114 self.registers.a += old_carry << 7;
1115 self.set_flags_nz(*self.registers.a);
1116 self.state = CpuState::Fetch;
1117 }
1118 AddressingMode::ZeroPage(z) => {
1119 if step == 0 {
1120 self.set_addr(z as u16);
1121 self.set_data_type(PinType::Input);
1122 step += 1;
1123 } else if step == 1 {
1124 let mut data = self.get_data();
1125 let old_carry =
1126 self.registers.p.contains(StatusRegister::C)
1127 as u8;
1128 self.registers
1129 .p
1130 .set(StatusRegister::C, (data & 0x01) > 0);
1131 data >>= 1;
1132 data += old_carry << 7;
1133 self.set_data(data);
1134 self.set_data_type(PinType::Output);
1135 self.set_flags_nz(data);
1136 step += 1;
1137 } else {
1138 self.state = CpuState::Fetch;
1139 }
1140 }
1141 AddressingMode::Absolute(a) => {
1142 if step == 0 {
1143 self.set_addr(a);
1144 self.set_data_type(PinType::Input);
1145 step += 1;
1146 } else if step == 1 {
1147 let mut data = self.get_data();
1148 let old_carry =
1149 self.registers.p.contains(StatusRegister::C)
1150 as u8;
1151 self.registers
1152 .p
1153 .set(StatusRegister::C, (data & 0x01) > 0);
1154 data <<= 1;
1155 data += old_carry << 7;
1156 self.set_data(data);
1157 self.set_data_type(PinType::Output);
1158 self.set_flags_nz(data);
1159 step += 1;
1160 } else {
1161 self.state = CpuState::Fetch;
1162 }
1163 }
1164 _ => unreachable!(),
1165 },
1166 Opcode::RTI => todo!(),
1167 Opcode::RTS => {
1168 if step == 0 {
1169 self.buffer = 0;
1170 self.pop_stack_prepare();
1171 step += 1;
1172 } else if step == 1 {
1173 self.buffer = self.get_data() as u16;
1174 self.pop_stack_prepare();
1175 step += 1;
1176 } else {
1177 self.buffer += (self.get_data() as u16) << 8;
1178 self.registers.pc = self.buffer.wrapping_add(1).into();
1179 self.state = CpuState::Fetch;
1180 }
1181 }
1182 Opcode::SBC(a) => match a {
1183 AddressingMode::Immediate(i) => self.run_sbc(i),
1184 AddressingMode::ZeroPage(z) => {
1185 if step == 0 {
1186 self.set_addr(z as u16);
1187 self.set_data_type(PinType::Input);
1188 step += 1;
1189 } else {
1190 self.run_sbc(self.get_data());
1191 }
1192 }
1193 AddressingMode::Absolute(a) => {
1194 if step == 0 {
1195 self.set_addr(a);
1196 self.set_data_type(PinType::Input);
1197 step += 1;
1198 } else {
1199 self.run_sbc(self.get_data());
1200 }
1201 }
1202 _ => unreachable!(),
1203 },
1204
1205 Opcode::TXS => {
1206 self.registers.s = self.registers.x;
1207 self.state = CpuState::Fetch
1208 }
1209 Opcode::TSX => {
1210 self.registers.x = self.registers.s;
1211 self.state = CpuState::Fetch
1212 }
1213 Opcode::PHA => {
1214 if step == 0 {
1215 self.push_stack(*self.registers.a);
1216 step += 1;
1217 } else {
1218 self.state = CpuState::Fetch;
1219 }
1220 }
1221 Opcode::PLA => {
1222 if step == 0 {
1223 self.pop_stack_prepare();
1224 step += 1;
1225 } else {
1226 self.registers.a = self.get_data().into();
1227 }
1228 }
1229 Opcode::PHP => {
1230 if step == 0 {
1231 self.push_stack(self.registers.p.bits());
1232 step += 1;
1233 } else {
1234 self.state = CpuState::Fetch;
1235 }
1236 }
1237 Opcode::PLP => {
1238 if step == 0 {
1239 self.pop_stack_prepare();
1240 step += 1;
1241 } else {
1242 self.registers.p =
1243 StatusRegister::from_bits_retain(self.get_data());
1244 }
1245 }
1246 Opcode::STA(a) => match a {
1247 AddressingMode::ZeroPage(z) => {
1248 if step == 0 {
1249 self.run_st(*self.registers.a, z as u16);
1250 step += 1;
1251 } else {
1252 self.state = CpuState::Fetch;
1253 }
1254 }
1255 AddressingMode::Absolute(a) => {
1256 if step == 0 {
1257 step += 1;
1258 } else if step == 1 {
1259 self.run_st(*self.registers.a, a);
1260 step += 1;
1261 } else {
1262 self.state = CpuState::Fetch;
1263 }
1264 }
1265 _ => unreachable!(),
1266 },
1267 Opcode::STX(a) => match a {
1268 AddressingMode::ZeroPage(z) => {
1269 if step == 0 {
1270 self.run_st(*self.registers.x, z as u16);
1271 step += 1;
1272 } else {
1273 self.state = CpuState::Fetch;
1274 }
1275 }
1276 AddressingMode::Absolute(a) => {
1277 if step == 0 {
1278 step += 1;
1279 } else if step == 1 {
1280 self.run_st(*self.registers.x, a);
1281 step += 1;
1282 } else {
1283 self.state = CpuState::Fetch;
1284 }
1285 }
1286 _ => unreachable!(),
1287 },
1288 Opcode::STY(a) => match a {
1289 AddressingMode::ZeroPage(z) => {
1290 if step == 0 {
1291 self.run_st(*self.registers.y, z as u16);
1292 step += 1;
1293 } else {
1294 self.state = CpuState::Fetch;
1295 }
1296 }
1297 AddressingMode::Absolute(a) => {
1298 if step == 0 {
1299 step += 1;
1300 } else if step == 1 {
1301 self.run_st(*self.registers.y, a);
1302 step += 1;
1303 } else {
1304 self.state = CpuState::Fetch;
1305 }
1306 }
1307 _ => unreachable!(),
1308 },
1309 }
1310 }
1311 if matches!(self.state, CpuState::Execute(_, _)) {
1312 self.state = CpuState::Execute(opcode, step);
1313 }
1314 if matches!(self.state, CpuState::Fetch) {
1315 self.set_addr(*self.registers.pc);
1316 self.registers.pc.inc();
1317 }
1318 }
1319 CpuState::Halted => {}
1320 }
1321 }
1322 }
1323 } else if self.powered {
1324 self.state = CpuState::Halted;
1325 self.powered = false;
1326 }
1327 }
1328}
1329
1330impl Nes6502 {
1331 fn set_flags_nz(&mut self, val: u8) {
1332 self.registers.p.set(StatusRegister::Z, val == 0);
1333 self.registers.p.set(StatusRegister::N, (val & 0x80) > 0);
1334 }
1335
1336 fn jump_relative(&mut self, val: i8) {
1337 self.registers.pc = ((*self.registers.pc as i32 + val as i32) as u16).into()
1338 }
1339
1340 fn push_stack(&mut self, val: u8) {
1341 self.run_st(val, 0x100 + *self.registers.s as u16);
1342 self.registers.s.dec();
1343 }
1344
1345 fn pop_stack_prepare(&mut self) {
1346 self.registers.s.inc();
1347 self.set_addr(0x100 + *self.registers.s as u16);
1348 self.set_data_type(PinType::Input);
1349 }
1350
1351 fn run_adc(&mut self, val: u8) {
1352 let rhs = val.wrapping_add(self.registers.p.contains(StatusRegister::C) as u8);
1353 let sum = *self.registers.a as u16 + rhs as u16;
1354
1355 self.registers.p.set(StatusRegister::C, sum > 0xFF);
1356 let sum: Reg<u8> = (sum as u8).into();
1357
1358 self.set_flags_nz(*sum);
1359 self.registers.p.set(
1360 StatusRegister::V,
1361 (!(*self.registers.a ^ val) & (*self.registers.a ^ *sum) & 0x80) > 0,
1362 );
1363 self.registers.a = sum;
1364 self.state = CpuState::Fetch;
1365 }
1366
1367 fn run_and(&mut self, val: u8) {
1368 self.registers.a &= val;
1369
1370 self.set_flags_nz(*self.registers.a);
1371
1372 self.state = CpuState::Fetch;
1373 }
1374
1375 fn run_bit(&mut self, val: u8) {
1376 self.registers
1377 .p
1378 .set(StatusRegister::Z, (*self.registers.a & val) == 0);
1379 self.registers.p.set(StatusRegister::N, (val & 0x80) > 0);
1380 self.registers.p.set(StatusRegister::V, (val & 0x40) > 0);
1381
1382 self.state = CpuState::Fetch;
1383 }
1384
1385 fn run_cmp(&mut self, base: Reg<u8>, val: u8) {
1386 let val = !val;
1387 let rhs = val.wrapping_add(self.registers.p.contains(StatusRegister::C) as u8);
1388 let sum = *base as u16 + rhs as u16;
1389
1390 self.registers.p.set(StatusRegister::C, sum > 0xFF);
1391 let sum: Reg<u8> = (sum as u8).into();
1392
1393 self.set_flags_nz(*sum);
1394 self.registers.p.set(
1395 StatusRegister::V,
1396 (!(*base ^ val) & (*base ^ *sum) & 0x80) > 0,
1397 );
1398 self.state = CpuState::Fetch;
1399 }
1400
1401 fn run_eor(&mut self, val: u8) {
1402 self.registers.a ^= val;
1403
1404 self.set_flags_nz(*self.registers.a);
1405
1406 self.state = CpuState::Fetch;
1407 }
1408
1409 fn run_lda(&mut self, val: u8) {
1410 self.registers.a = val.into();
1411 self.set_flags_nz(*self.registers.a);
1412 self.state = CpuState::Fetch;
1413 }
1414 fn run_ldx(&mut self, val: u8) {
1415 self.registers.x = val.into();
1416 self.set_flags_nz(*self.registers.x);
1417 self.state = CpuState::Fetch;
1418 }
1419 fn run_ldy(&mut self, val: u8) {
1420 self.registers.y = val.into();
1421 self.set_flags_nz(*self.registers.y);
1422 self.state = CpuState::Fetch;
1423 }
1424
1425 fn run_ora(&mut self, val: u8) {
1426 self.registers.a |= val;
1427
1428 self.set_flags_nz(*self.registers.a);
1429
1430 self.state = CpuState::Fetch;
1431 }
1432
1433 fn run_sbc(&mut self, val: u8) {
1434 self.run_adc(!val)
1435 }
1436
1437 fn run_st(&mut self, val: u8, addr: u16) {
1438 self.set_addr(addr);
1439 self.set_data(val);
1440 self.set_data_type(PinType::Output);
1441 }
1442}
1443
1444impl ToString for Nes6502 {
1445 fn to_string(&self) -> std::string::String {
1446 format!("state={:?}\n{}", self.state, self.registers.to_string())
1447 }
1448}