Skip to content

Commit

Permalink
Implement NMOS quirks
Browse files Browse the repository at this point in the history
  • Loading branch information
breqdev committed Nov 23, 2023
1 parent 29e65b3 commit e5a4004
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 6 deletions.
31 changes: 30 additions & 1 deletion src/cpu/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use crate::cpu::fetch::Fetch;
use crate::cpu::registers::{flags, Alu};
use crate::cpu::{InterruptHandler, MemoryIO, Mos6502, Stack};

use super::Mos6502Variant;

pub trait Execute {
/// Execute the given opcode, returning either the number of cycles used or an error.
fn execute(&mut self, opcode: u8) -> Result<u8, ()>;
Expand Down Expand Up @@ -133,6 +135,10 @@ impl Execute for Mos6502 {
// ASL
let (address, cycles) = self.fetch_operand_address(opcode);
let value = self.read(address);

if let Mos6502Variant::NMOS = self.variant {
self.write(address, value);
}
let result = value << 1;

self.registers.sr.write(flags::CARRY, value & 0x80 != 0);
Expand All @@ -154,6 +160,11 @@ impl Execute for Mos6502 {
// LSR
let (address, cycles) = self.fetch_operand_address(opcode);
let value = self.read(address);

if let Mos6502Variant::NMOS = self.variant {
self.write(address, value);
}

let result = value >> 1;

self.registers.sr.write(flags::CARRY, value & 0x01 != 0);
Expand All @@ -176,6 +187,11 @@ impl Execute for Mos6502 {
// ROL
let (address, cycles) = self.fetch_operand_address(opcode);
let value = self.read(address);

if let Mos6502Variant::NMOS = self.variant {
self.write(address, value);
}

let result = (value << 1) | (self.registers.sr.read(flags::CARRY) as u8);

self.registers.sr.write(flags::CARRY, value & 0x80 != 0);
Expand All @@ -198,6 +214,11 @@ impl Execute for Mos6502 {
// ROR
let (address, cycles) = self.fetch_operand_address(opcode);
let value = self.read(address);

if let Mos6502Variant::NMOS = self.variant {
self.write(address, value);
}

let result = value >> 1 | (self.registers.sr.read(flags::CARRY) as u8) << 7;

self.registers.sr.write(flags::CARRY, value & 0x01 != 0);
Expand Down Expand Up @@ -341,7 +362,15 @@ impl Execute for Mos6502 {
0x4C => (self.fetch_word(), 3),
0x6C => {
let indirect = self.fetch_word();
(self.read_word(indirect), 5)

if self.variant == Mos6502Variant::NMOS && indirect & 0xFF == 0xFF {
let lo = self.read(indirect);
let hi = self.read(indirect & 0xFF00);
((hi as u16) << 8 | lo as u16, 5)
} else {
// normal behavior
(self.read_word(indirect), 5)
}
}
_ => unreachable!(),
};
Expand Down
24 changes: 20 additions & 4 deletions src/cpu/fetch.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::cpu::{MemoryIO, Mos6502};

use super::Mos6502Variant;

/// Fetch values or addresses from memory, optionally dependent on the current
/// opcode.
pub trait Fetch {
Expand Down Expand Up @@ -88,15 +90,29 @@ impl Fetch for Mos6502 {
0x1C | 0x1D => {
// Absolute,X
let base = self.fetch_word();
(base + self.registers.x as u16, 4)
let indexed = base + self.registers.x as u16;

if self.variant == Mos6502Variant::NMOS && base & 0xFF00 != indexed & 0xFF00 {
self.read(base & 0xFF00 | indexed & 0x00FF);
(indexed, 5)
} else {
(indexed, 4)
}
}
0x1E | 0x1F => {
// Absolute,X or Absolute,Y
let base = self.fetch_word();
if opcode & 0xC0 == 0x80 {
(base + self.registers.y as u16, 4)
let indexed = if opcode & 0xC0 == 0x80 {
base + self.registers.y as u16
} else {
base + self.registers.x as u16
};

if self.variant == Mos6502Variant::NMOS && base & 0xFF00 != indexed & 0xFF00 {
self.read(base & 0xFF00 | indexed & 0x00FF);
(indexed, 5)
} else {
(base + self.registers.x as u16, 4)
(indexed, 4)
}
}
_ => unreachable!(),
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use registers::{flags, Registers};

const CLOCKS_PER_POLL: u32 = 100;

#[derive(Copy, Clone)]
#[derive(Copy, Clone, PartialEq)]
pub enum Mos6502Variant {
/// 6502
NMOS,
Expand Down

0 comments on commit e5a4004

Please sign in to comment.