Advertisement
Guest User

NES' CPU implementation

a guest
Sep 24th, 2020
44
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 4.77 KB | None | 0 0
  1. pub enum Flag {
  2.     Carry = 1 << 0,
  3.     Zero = 1 << 1,
  4.     Interrupt = 1 << 2,
  5.     Decimal = 1 << 3,
  6.     Overflow = 1 << 6,
  7.     Negative = 1 << 7,
  8. }
  9.  
  10. pub struct Registers {
  11.     pub a: u8,   // Accumulator
  12.     pub x: u8,   // X index
  13.     pub y: u8,   // Y index
  14.     pub pc: u16, // Program Counter
  15.     pub s: u8,   // Stack pointer
  16.     pub p: u8,   // Status register
  17. }
  18.  
  19. impl Registers {
  20.     pub fn get_flag(&self, flag: Flag) -> bool {
  21.         self.p & flag as u8 != 0
  22.     }
  23.     pub fn set_flag(&mut self, flag: Flag) {
  24.         self.p |= flag as u8;
  25.     }
  26. }
  27.  
  28. const NMI_VECTOR: u16 = 0xFFFA;
  29. const RESET_VECTOR: u16 = 0xFFFC;
  30. const IRQ_VECTOR: u16 = 0xFFFE;
  31.  
  32. pub struct CPU {
  33.     regs: Registers,
  34.     cycles: u64,
  35.     nmi: bool,
  36.     irq: bool,
  37.     ram: Ram,
  38. }
  39.  
  40. impl CPU {
  41.     pub fn new() -> CPU {
  42.         CPU {
  43.             regs: Registers {
  44.                 a: 0,
  45.                 x: 0,
  46.                 y: 0,
  47.                 p: 0x34,
  48.                 s: 0xFD,
  49.                 pc: 0,
  50.             },
  51.             cycles: 0,
  52.             nmi: false,
  53.             irq: false,
  54.             ram: Ram::default(),
  55.         }
  56.     }
  57.     pub fn reset(&mut self) {
  58.         unimplemented!();
  59.     }
  60.     pub fn step(&mut self) {
  61.         let opcode = self.ram.read_byte(self.regs.pc);
  62.         let instruction = INSTRUCTIONS[opcode as usize];
  63.  
  64.         instruction.exec(self);
  65.     }
  66.     fn read<A: AddressingMode>(&self, add_mode: A) -> u8 {
  67.         add_mode.read(self)
  68.     }
  69.     fn write<A: AddressingMode>(&mut self, add_mode: A, val: u8) {
  70.         add_mode.write(self, val);
  71.     }
  72. }
  73.  
  74. trait AddressingMode {
  75.     fn read(&self, cpu: &CPU) -> u8;
  76.     fn write(&self, cpu: &mut CPU, val: u8);
  77. }
  78.  
  79. #[derive(Clone, Copy)]
  80. struct Immediate;
  81. impl AddressingMode for Immediate {
  82.     fn read(&self, cpu: &CPU) -> u8 {
  83.         cpu.ram.read_byte(cpu.regs.pc)
  84.     }
  85.     fn write(&self, _: &mut CPU, _: u8) {
  86.         panic!("Cannot write to immediate!");
  87.     }
  88. }
  89.  
  90. #[derive(Clone, Copy)]
  91. struct ZeroPage;
  92. impl AddressingMode for ZeroPage {
  93.     fn read(&self, cpu: &CPU) -> u8 {
  94.         let address: u8 = cpu.read(Immediate);
  95.         cpu.ram.read_byte(address as u16)
  96.     }
  97.     fn write(&self, cpu: &mut CPU, val: u8) {
  98.         let address: u8 = cpu.read(Immediate);
  99.         cpu.ram.write_byte(address as u16, val);
  100.     }
  101. }
  102.  
  103. #[derive(Clone, Copy)]
  104. struct Absolute;
  105. impl AddressingMode for Absolute {
  106.     fn read(&self, cpu: &CPU) -> u8 {
  107.         let address: u16 = cpu.ram.read_word(cpu.regs.pc);
  108.         cpu.ram.read_byte(address)
  109.     }
  110.     fn write(&self, cpu: &mut CPU, val: u8) {
  111.         let address: u16 = cpu.ram.read_word(cpu.regs.pc);
  112.         cpu.ram.write_byte(address, val);
  113.     }
  114. }
  115.  
  116. #[derive(Clone, Copy)]
  117. enum AddMode {
  118.     Immediate(Immediate),
  119.     ZeroPage(ZeroPage),
  120.     Absolute(Absolute),
  121. }
  122.  
  123. impl AddressingMode for AddMode {
  124.     fn read(&self, cpu: &CPU) -> u8 {
  125.         match self {
  126.             Self::Immediate(x) => x.read(cpu),
  127.             Self::ZeroPage(x) => x.read(cpu),
  128.             Self::Absolute(x) => x.read(cpu),
  129.         }
  130.     }
  131.     fn write(&self, cpu: &mut CPU, val: u8) {
  132.         match self {
  133.             Self::Immediate(x) => x.write(cpu, val),
  134.             Self::ZeroPage(x) => x.write(cpu, val),
  135.             Self::Absolute(x) => x.write(cpu, val),
  136.         }
  137.     }
  138. }
  139.  
  140. impl From<Immediate> for AddMode {
  141.     fn from(x: Immediate) -> Self {
  142.         Self::Immediate(x)
  143.     }
  144. }
  145.  
  146. impl From<ZeroPage> for AddMode {
  147.     fn from(x: ZeroPage) -> Self {
  148.         Self::ZeroPage(x)
  149.     }
  150. }
  151.  
  152. impl From<Absolute> for AddMode {
  153.     fn from(x: Absolute) -> Self {
  154.         Self::Absolute(x)
  155.     }
  156. }
  157.  
  158. #[derive(Clone, Copy)]
  159. struct Instruction {
  160.     pub name: &'static str,
  161.    pub cycles: usize,
  162.    pub bytes: usize,
  163.    pub add_mode: AddMode,
  164.    pub handler: fn(&mut CPU, mode: AddMode),
  165.    pub extra_cycle_on_page_cross: bool,
  166. }
  167.  
  168. impl Instruction {
  169.    fn exec(&self, cpu: &mut CPU) {
  170.        (self.handler)(cpu, self.add_mode);
  171.        cpu.regs.pc += self.bytes as u16;
  172.        cpu.cycles += self.cycles as u64;
  173.    }
  174. }
  175.  
  176. fn lda(cpu: &mut CPU, mode: AddMode) {
  177.    cpu.regs.a = mode.read(cpu);
  178. }
  179.  
  180. fn sta(cpu: &mut CPU, mode: AddMode) {
  181.    mode.write(cpu, cpu.regs.a);
  182. }
  183.  
  184. // TODO: Add instructions
  185. lazy_static! {
  186.    static ref INSTRUCTIONS: [Instruction; 2] = [
  187.        Instruction {
  188.            name: "LDA",
  189.            cycles: 3,
  190.            bytes: 2,
  191.            add_mode: ZeroPage.into(),
  192.            handler: lda,
  193.            extra_cycle_on_page_cross: false,
  194.        },
  195.        Instruction {
  196.            name: "STA",
  197.            cycles: 4,
  198.            bytes: 2,
  199.            add_mode: ZeroPage.into(),
  200.            handler: sta,
  201.            extra_cycle_on_page_cross: false,
  202.        }
  203.    ];
  204. }
  205.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement