Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions lib/mos6510/cpu.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ def pc=(new_pc)
@cpu.pc = new_pc
end

def inspect
status = @cpu.p
status_encoded = [
(status & Mos6510::Flag::N) != 0, (status & Mos6510::Flag::V) != 0, (status & Mos6510::Flag::B2) != 0, (status & Mos6510::Flag::B1) != 0, (status & Mos6510::Flag::D) != 0,
(status & Mos6510::Flag::I) != 0, (status & Mos6510::Flag::Z) != 0, (status & Mos6510::Flag::C) != 0
].reduce(0) { |acc, flag| (acc << 1) + (flag ? 1 : 0) }

format(
'a: 0x%02x, x: 0x%02x, y: 0x%02x, sp: 0x%02x, ' \
'pc: 0x%04x, op: 0x%02x, status: 0b%08b, memory: %i',
@cpu.a, @cpu.x, @cpu.y, @cpu.s, @cpu.pc, @cpu.getmem(@cpu.pc), status_encoded, @memory.sum
)
end

def peek(address)
@cpu.getmem(address)
end
Expand Down
69 changes: 42 additions & 27 deletions lib/mos6510/jssid_mos6510.rb
Original file line number Diff line number Diff line change
Expand Up @@ -238,15 +238,11 @@ def setflags(flag, cond)

def push(val)
self.setmem(0x100 + self.s, val)
if self.s > 0
self.s -= 1
end
self.s = (self.s - 1) & 0xff
end

def pop
if self.s < 0xff
self.s += 1
end
self.s = (self.s + 1) & 0xff
self.getmem(0x100 + self.s)
end

Expand Down Expand Up @@ -275,7 +271,7 @@ def reset
self.a = 0
self.x = 0
self.y = 0
self.p = 0
self.p = Flag::B1 | Flag::B2
self.s = 255
self.pc = self.getmem(0xfffc)
self.pc |= 256 * self.getmem(0xfffd)
Expand All @@ -291,12 +287,26 @@ def step

case cmd
when Inst::ADC
self.wval = self.a + self.getaddr(addr) + ((self.p & Flag::C) != 0 ? 1 : 0)
self.setflags(Flag::C, self.wval & 0x100)
value = self.getaddr(addr)
carry = (self.p & Flag::C) != 0 ? 1 : 0
if (self.p & Flag::D) != 0
value_bcd = (value & 0xf) + (value >> 4 & 0xf) * 10
a_bcd = (self.a & 0xf) + (self.a >> 4 & 0xf) * 10
sum = value_bcd + a_bcd + carry
self.wval = (sum % 10) + (((sum / 10) % 10) << 4) + ((sum / 100) << 8)
self.setflags(Flag::C, sum >= 100)
self.setflags(Flag::V, self.wval > 127 || self.wval < -128)
else
self.wval = self.a + value + carry
v = (((self.a & 0x7f) + (value & 0x7f) + carry) >> 7) ^ (self.wval >> 8)
# TODO: Shouldn't this work?
#v = self.wval > 127 || self.wval < -128
self.setflags(Flag::C, self.wval & 0x100)
self.setflags(Flag::V, v)
end
self.a = self.wval & 0xff
self.setflags(Flag::Z, self.a == 0)
self.setflags(Flag::N, self.a & 0x80)
self.setflags(Flag::V, ((self.p & Flag::C) != 0 ? 1 : 0) ^ ((self.p & Flag::N) != 0 ? 1 : 0))
self.setflags(Flag::Z, self.a == 0)
when Inst::AND
self.bval = self.getaddr(addr)
self.a &= self.bval
Expand Down Expand Up @@ -331,14 +341,14 @@ def step
self.setflags(Flag::N, self.bval & 0x80)
self.setflags(Flag::V, self.bval & 0x40)
when Inst::BRK
pc = 0 # just quit per rockbox
#self.push(self.pc & 0xff);
#self.push(self.pc >> 8);
#self.push(self.p);
#self.setflags(jsSID.MOS6510.Flag::B, 1);
# FIXME: should Z be set as well?
#self.pc = self.getmem(0xfffe);
#self.cycles += 7;
self.pcinc()
self.push(self.pc >> 8)
self.push(self.pc & 0xff)
self.push(self.p)
self.setflags(Flag::B1, true)
self.setflags(Flag::I, true)
self.pc = self.getmem(0xfffe) + (self.getmem(0xffff) << 8)
self.cycles += 7
when Inst::CLC
self.cycles += 2
self.setflags(Flag::C, 0)
Expand Down Expand Up @@ -491,7 +501,7 @@ def step
self.setflags(Flag::N, self.a & 0x80)
self.cycles += 4
when Inst::PLP
self.p = self.pop
self.p = self.pop | Flag::B1 | Flag::B2
self.cycles += 4
when Inst::ROL
self.bval = self.getaddr(addr)
Expand All @@ -513,20 +523,25 @@ def step
self.setflags(Flag::N, self.bval & 0x80)
self.setflags(Flag::Z, self.bval == 0)
when Inst::RTI
# treat like RTS
self.p = self.pop
self.pc = self.pop + (self.pop << 8)
self.cycles += 6
when Inst::RTS
self.wval = self.pop
self.wval |= 256 * self.pop
self.pc = self.wval + 1
self.cycles += 6
when Inst::SBC
self.bval = self.getaddr(addr) ^ 0xff
self.wval = self.a + self.bval + ((self.p & Flag::C) != 0 ? 1 : 0)
# Almost identical to SBC, just inverting value
value = self.getaddr(addr) ^ 0xff
carry = (self.p & Flag::C) != 0 ? 1 : 0
self.wval = self.a + value + carry
v = (((self.a & 0x7f) + (value & 0x7f) + carry) >> 7) ^ (self.wval >> 8)
self.setflags(Flag::C, self.wval & 0x100)
self.a = self.wval & 0xff
self.setflags(Flag::Z, self.a == 0)
self.setflags(Flag::N, self.a > 127)
self.setflags(Flag::V, ((self.p & Flag::C) != 0 ? 1 : 0) ^ ((self.p & Flag::N) != 0 ? 1 : 0))
self.setflags(Flag::N, self.a & 0x80)
self.setflags(Flag::V, v)
when Inst::SEC
self.cycles += 2
self.setflags(Flag::C, 1)
Expand Down Expand Up @@ -583,7 +598,7 @@ def jsr(npc, na)
self.a = na
self.x = 0
self.y = 0
self.p = 0
self.p = Flag::B1 | Flag::B2
self.s = 255
self.pc = npc
self.push(0)
Expand All @@ -598,7 +613,7 @@ def jsr(npc, na)

# Flags Enum
module Flag
N = 128; V = 64; B = 16; D = 8; I = 4; Z = 2; C = 1
N = 128; V = 64; B2 = 32; B1 = 16; D = 8; I = 4; Z = 2; C = 1
end

# Opcodes Enum
Expand Down
6 changes: 3 additions & 3 deletions spec/cpu_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Mos6510
expect(cpu.peek(4000)).to eq(7)
end

it "can run the whole Klaus Dormann functional test suite", skip: "Needs more work!" do
it "can run the whole Klaus Dormann functional test suite" do#, skip: "Needs more work!" do
# TODO: This suite does _not_ pass currently. It relies on you copying
# bin_files/6502_functional_test.bin from https://github.com/Klaus2m5/6502_65C02_functional_tests
# (and even then, it ends up on the wrong PC)
Expand All @@ -29,9 +29,9 @@ module Mos6510
last_pc = 0
while last_pc != cpu.pc
last_pc = cpu.pc
#puts cpu.inspect
puts cpu.inspect

puts "Stepping: #{last_pc}"
#puts "Stepping: #{last_pc}"
cpu.step
end

Expand Down