Finished implementing instructions
+ added all legal instructions
This commit is contained in:
parent
012992c4ad
commit
051cfe6611
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
||||
/target
|
||||
.log
|
||||
|
||||
|
||||
78380
output.log
78380
output.log
File diff suppressed because one or more lines are too long
36
src/bus.rs
36
src/bus.rs
@ -48,19 +48,19 @@ impl Bus {
|
||||
let mut ram = Ram::<0x800>::new();
|
||||
|
||||
//TODO temporary for instruction tests
|
||||
ram.buffer[0x01] = 0x0A;
|
||||
ram.buffer[0x02] = 0x90;;
|
||||
ram.buffer[0x03] = (-3 as i8) as u8;
|
||||
ram.buffer[0x04] = 0x90;
|
||||
ram.buffer[0x05] = (-3 as i8) as u8;
|
||||
ram.buffer[0x06] = 0x0A;
|
||||
ram.buffer[0x07] = 0x0A;
|
||||
ram.buffer[0x08] = 0x0A;
|
||||
ram.buffer[0x09] = 0x01;
|
||||
ram.buffer[0x0A] = 0x3D;
|
||||
ram.buffer[0x0B] = 0xFE;
|
||||
ram.buffer[0x0C] = 0x01;
|
||||
ram.buffer[0x0D] = 0x39;
|
||||
ram.buffer[0x01] = 0xE9; //sbc
|
||||
ram.buffer[0x02] = (-3 as i8) as u8;
|
||||
ram.buffer[0x03] = 0x09;
|
||||
ram.buffer[0x04] = 0x00;
|
||||
ram.buffer[0x05] = 0xA9; //lda
|
||||
ram.buffer[0x06] = 0x01;
|
||||
ram.buffer[0x07] = 0x4C; //jmp
|
||||
ram.buffer[0x08] = 0x00;
|
||||
ram.buffer[0x09] = 0x00;
|
||||
ram.buffer[0x0A] = 0x2A; //fn rol
|
||||
ram.buffer[0x0B] = 0x90; //bcc
|
||||
ram.buffer[0x0C] = (-3 as i8) as u8;
|
||||
ram.buffer[0x0D] = 0x60; //rts
|
||||
ram.buffer[0x0E] = 0xFD;
|
||||
ram.buffer[0x0F] = 0x01;
|
||||
ram.buffer[0x10] = 0x21;
|
||||
@ -94,7 +94,15 @@ impl Bus {
|
||||
|
||||
// val
|
||||
ram.buffer[0x01FF] = 0x01;
|
||||
ram.buffer[0x0300] = 0x01; //boundary
|
||||
ram.buffer[0x02FF] = 0xFF; //boundary
|
||||
ram.buffer[0x0300] = 0x03;
|
||||
|
||||
// ptr to test
|
||||
ram.buffer[0x030F] = 0xFF;
|
||||
ram.buffer[0x0310] = 0x03;
|
||||
|
||||
// jmp test
|
||||
ram.buffer[0x0400] = 0xE6;
|
||||
|
||||
Bus {
|
||||
ram,
|
||||
|
||||
492
src/cpu.rs
492
src/cpu.rs
@ -8,6 +8,8 @@ use crate::{
|
||||
memory::Memory,
|
||||
};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
trait Input {
|
||||
@ -27,7 +29,7 @@ trait RWInput: RInput + WInput {}
|
||||
struct Accumulator {}
|
||||
|
||||
impl Input for Accumulator {
|
||||
fn get_cycles(&self) -> u32 { 2 }
|
||||
fn get_cycles(&self) -> u32 { 0 } //only used in +2 instructions
|
||||
}
|
||||
|
||||
impl RInput for Accumulator {
|
||||
@ -136,7 +138,6 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Cpu {
|
||||
a: u8,
|
||||
x: u8,
|
||||
@ -147,6 +148,22 @@ pub struct Cpu {
|
||||
bus: Bus,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Cpu {
|
||||
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("Cpu")
|
||||
.field("acc", &format_args!("0x{:0>2X}", self.a))
|
||||
.field("x ", &format_args!("0x{:0>2X}", self.x))
|
||||
.field("y ", &format_args!("0x{:0>2X}", self.y))
|
||||
.field("prg_count", &format_args!("0x{:0>4X}", self.pc))
|
||||
.field("stack_ptr", &format_args!("0x{:0>2X}", self.s))
|
||||
.field("status", &self.p)
|
||||
.field("bus", &self.bus)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Cpu {
|
||||
|
||||
pub fn new() -> Self {
|
||||
@ -155,8 +172,8 @@ impl Cpu {
|
||||
x: 1, //TODO temporary
|
||||
y: 2, //TODO temporary
|
||||
pc: 0, //TODO to be verified
|
||||
s: 0x34,
|
||||
p: StatusReg::from_bits(0xFD).unwrap(),
|
||||
s: 0xFD,
|
||||
p: StatusReg::from_bits(0x35).unwrap(),
|
||||
bus: Bus::new(),
|
||||
}
|
||||
}
|
||||
@ -239,6 +256,123 @@ impl Cpu {
|
||||
|
||||
0xCA => dex(mode_implicit),
|
||||
0x88 => dey(mode_implicit),
|
||||
|
||||
0x49 => eor(mode_immediate),
|
||||
0x45 => eor(mode_zero_page),
|
||||
0x55 => eor(mode_zero_page_x),
|
||||
0x4D => eor(mode_absolute),
|
||||
0x5D => eor(mode_absolute_x),
|
||||
0x59 => eor(mode_absolute_y),
|
||||
0x41 => eor(mode_indirect_x),
|
||||
0x51 => eor(mode_indirect_y),
|
||||
|
||||
0xE6 => inc(mode_zero_page),
|
||||
0xF6 => inc(mode_zero_page_x),
|
||||
0xEE => inc(mode_absolute),
|
||||
0xFE => inc(mode_absolute_x),
|
||||
|
||||
0xE8 => inx(mode_implicit),
|
||||
0xC8 => iny(mode_implicit),
|
||||
|
||||
0x4C => jmp(mode_absolute),
|
||||
0x6C => jmp(mode_indirect),
|
||||
|
||||
0x20 => jsr(mode_absolute),
|
||||
|
||||
0xA9 => lda(mode_immediate),
|
||||
0xA5 => lda(mode_zero_page),
|
||||
0xB5 => lda(mode_zero_page_x),
|
||||
0xAD => lda(mode_absolute),
|
||||
0xBD => lda(mode_absolute_x),
|
||||
0xB9 => lda(mode_absolute_y),
|
||||
0xA1 => lda(mode_indirect_x),
|
||||
0xB1 => lda(mode_indirect_y),
|
||||
|
||||
0xA2 => ldx(mode_immediate),
|
||||
0xA6 => ldx(mode_zero_page),
|
||||
0xB6 => ldx(mode_zero_page_y),
|
||||
0xAE => ldx(mode_absolute),
|
||||
0xBE => ldx(mode_absolute_y),
|
||||
|
||||
0xA0 => ldy(mode_immediate),
|
||||
0xA4 => ldy(mode_zero_page),
|
||||
0xB4 => ldy(mode_zero_page_y),
|
||||
0xAC => ldy(mode_absolute),
|
||||
0xBC => ldy(mode_absolute_y),
|
||||
|
||||
0x4A => lsr(mode_accumulator),
|
||||
0x46 => lsr(mode_zero_page),
|
||||
0x56 => lsr(mode_zero_page_x),
|
||||
0x4E => lsr(mode_absolute),
|
||||
0x5E => lsr(mode_absolute_x),
|
||||
|
||||
0xEA => nop(mode_implicit),
|
||||
|
||||
0x09 => ora(mode_immediate),
|
||||
0x05 => ora(mode_zero_page),
|
||||
0x15 => ora(mode_zero_page_x),
|
||||
0x0D => ora(mode_absolute),
|
||||
0x1D => ora(mode_absolute_x),
|
||||
0x19 => ora(mode_absolute_y),
|
||||
0x01 => ora(mode_indirect_x),
|
||||
0x11 => ora(mode_indirect_y),
|
||||
|
||||
0x48 => pha(mode_implicit),
|
||||
0x08 => php(mode_implicit),
|
||||
0x68 => pla(mode_implicit),
|
||||
0x28 => plp(mode_implicit),
|
||||
|
||||
0x2A => rol(mode_accumulator),
|
||||
0x26 => rol(mode_zero_page),
|
||||
0x36 => rol(mode_zero_page_x),
|
||||
0x2E => rol(mode_absolute),
|
||||
0x3E => rol(mode_absolute_x),
|
||||
|
||||
0x6A => ror(mode_accumulator),
|
||||
0x66 => ror(mode_zero_page),
|
||||
0x76 => ror(mode_zero_page_x),
|
||||
0x6E => ror(mode_absolute),
|
||||
0x7E => ror(mode_absolute_x),
|
||||
|
||||
0x40 => rti(mode_implicit),
|
||||
0x60 => rts(mode_implicit),
|
||||
|
||||
0xE9 => sbc(mode_immediate),
|
||||
0xE5 => sbc(mode_zero_page),
|
||||
0xF5 => sbc(mode_zero_page_x),
|
||||
0xED => sbc(mode_absolute),
|
||||
0xFD => sbc(mode_absolute_x),
|
||||
0xF9 => sbc(mode_absolute_y),
|
||||
0xE1 => sbc(mode_indirect_x),
|
||||
0xF1 => sbc(mode_indirect_y),
|
||||
|
||||
0x38 => sec(mode_implicit),
|
||||
0xF8 => sed(mode_implicit),
|
||||
0x78 => sei(mode_implicit),
|
||||
|
||||
0x85 => sta(mode_zero_page),
|
||||
0x95 => sta(mode_zero_page_x),
|
||||
0x8D => sta(mode_absolute),
|
||||
0x9D => sta(mode_absolute_x),
|
||||
0x99 => sta(mode_absolute_y),
|
||||
0x81 => sta(mode_indirect_x),
|
||||
0x91 => sta(mode_indirect_y),
|
||||
|
||||
0x86 => stx(mode_zero_page),
|
||||
0x96 => stx(mode_zero_page_y),
|
||||
0x8E => stx(mode_absolute),
|
||||
|
||||
0x84 => sty(mode_zero_page),
|
||||
0x94 => sty(mode_zero_page_x),
|
||||
0x8C => sty(mode_absolute),
|
||||
|
||||
0xAA => tax(mode_implicit),
|
||||
0xA8 => tay(mode_implicit),
|
||||
0xBA => tsx(mode_implicit),
|
||||
0x8A => txa(mode_implicit),
|
||||
0x9A => txs(mode_implicit),
|
||||
0x98 => tya(mode_implicit),
|
||||
|
||||
);
|
||||
|
||||
info!("0x{:X}: {} cycles", opcode, cycles);
|
||||
@ -430,6 +564,20 @@ impl Cpu {
|
||||
val
|
||||
}
|
||||
|
||||
/// Write data, then decrement stack pointer. The stack is stored between 0x01FF and 0x0100
|
||||
fn push_stack(&mut self, data: u8) {
|
||||
self.bus.write_addr(self.s as u16 | 0x0100, data);
|
||||
self.s = self.s.wrapping_sub(1);
|
||||
}
|
||||
|
||||
/// Read data, then increment stack pointer
|
||||
fn pop_stack(&mut self) -> u8 {
|
||||
self.s = self.s.wrapping_add(1);
|
||||
let data = self.bus.read_addr(self.s as u16 | 0x0100);
|
||||
|
||||
data
|
||||
}
|
||||
|
||||
fn adc<I: RInput>(&mut self, input: I) -> u32 {
|
||||
let val = input.read(&self.a, &self.bus);
|
||||
|
||||
@ -455,8 +603,6 @@ impl Cpu {
|
||||
// truncate accumulator to 8 bits
|
||||
self.a = a as u8;
|
||||
|
||||
// handle zero bit
|
||||
|
||||
input.get_cycles()
|
||||
}
|
||||
|
||||
@ -497,7 +643,6 @@ impl Cpu {
|
||||
true => {
|
||||
let old_pc = self.pc;
|
||||
self.pc = self.pc.wrapping_add(offset as u16);
|
||||
debug!("PC: 0x{:X}", self.pc);
|
||||
match old_pc & 0xFF00 == self.pc & 0xFF00 {
|
||||
true => input.get_cycles() + 1,
|
||||
false => input.get_cycles() + 2,
|
||||
@ -545,9 +690,24 @@ impl Cpu {
|
||||
}
|
||||
|
||||
fn brk(&mut self, _: ()) -> u32 {
|
||||
|
||||
// store PC on stack
|
||||
self.push_stack((self.pc >> 8) as u8);
|
||||
self.push_stack(self.pc as u8);
|
||||
|
||||
//TODO
|
||||
panic!("BRK not implemented");
|
||||
// store status register
|
||||
self.p.set(StatusReg::B, true);
|
||||
self.push_stack(self.p.bits() as u8);
|
||||
|
||||
// load interrupt vector
|
||||
let pc_lo = self.bus.read_addr(0xFFFE) as u16;
|
||||
let pc_hi = self.bus.read_addr(0xFFFF) as u16;
|
||||
self.pc = pc_lo | (pc_hi << 8);
|
||||
|
||||
// inhibit further interrupts
|
||||
self.p.set(StatusReg::I, true);
|
||||
|
||||
7
|
||||
}
|
||||
|
||||
fn bvc<I: RInput>(&mut self, input: I) -> u32 {
|
||||
@ -633,7 +793,321 @@ impl Cpu {
|
||||
2
|
||||
}
|
||||
|
||||
fn eor<I: RInput>(&mut self, input: I) -> u32 {
|
||||
let val = input.read(&self.a, &self.bus);
|
||||
|
||||
// compute
|
||||
self.a = (!self.a & val) | (self.a & !val);
|
||||
self.p.set(StatusReg::Z, self.y == 0);
|
||||
self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0);
|
||||
|
||||
input.get_cycles()
|
||||
}
|
||||
|
||||
fn inc<I:RWInput>(&mut self, mut input: I) -> u32 {
|
||||
let mut val = input.read(&self.a, &self.bus);
|
||||
|
||||
// compute
|
||||
val = val.wrapping_add(1);
|
||||
self.p.set(StatusReg::Z, self.y == 0);
|
||||
self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0);
|
||||
|
||||
// store result
|
||||
input.write(&mut self.a, &mut self.bus, val);
|
||||
input.get_cycles() + 2
|
||||
}
|
||||
|
||||
fn inx(&mut self, _: ()) -> u32 {
|
||||
|
||||
// compute
|
||||
self.x = self.x.wrapping_add(1);
|
||||
self.p.set(StatusReg::Z, self.y == 0);
|
||||
self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0);
|
||||
|
||||
2
|
||||
}
|
||||
|
||||
fn iny(&mut self, _: ()) -> u32 {
|
||||
|
||||
// compute
|
||||
self.y = self.y.wrapping_add(1);
|
||||
self.p.set(StatusReg::Z, self.y == 0);
|
||||
self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0);
|
||||
|
||||
2
|
||||
}
|
||||
|
||||
fn jmp(&mut self, input: MemoryVal) -> u32 {
|
||||
self.pc = input.addr;
|
||||
input.get_cycles() - 1
|
||||
}
|
||||
|
||||
fn jsr(&mut self, input: MemoryVal) -> u32 {
|
||||
|
||||
// store return point
|
||||
self.push_stack((self.pc >> 8) as u8);
|
||||
self.push_stack(self.pc as u8);
|
||||
|
||||
// load target address
|
||||
self.pc = input.addr;
|
||||
|
||||
return input.get_cycles() + 2
|
||||
}
|
||||
|
||||
fn lda<I: RInput>(&mut self, input: I) -> u32 {
|
||||
|
||||
// store value and compute flags
|
||||
self.a = input.read(&self.a, &self.bus);
|
||||
self.p.set(StatusReg::Z, self.a == 0);
|
||||
self.p.set(StatusReg::N, (self.a & (0x1 << 7)) != 0);
|
||||
|
||||
input.get_cycles()
|
||||
}
|
||||
|
||||
fn ldx<I: RInput>(&mut self, input: I) -> u32 {
|
||||
|
||||
// store value and compute flags
|
||||
self.x = input.read(&self.a, &self.bus);
|
||||
self.p.set(StatusReg::Z, self.x == 0);
|
||||
self.p.set(StatusReg::N, (self.x & (0x1 << 7)) != 0);
|
||||
|
||||
input.get_cycles()
|
||||
}
|
||||
|
||||
fn ldy<I: RInput>(&mut self, input: I) -> u32 {
|
||||
|
||||
// store value and compute flags
|
||||
self.y = input.read(&self.a, &self.bus);
|
||||
self.p.set(StatusReg::Z, self.y == 0);
|
||||
self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0);
|
||||
|
||||
input.get_cycles()
|
||||
}
|
||||
|
||||
fn lsr<I: RWInput>(&mut self, mut input: I) -> u32 {
|
||||
let mut target = input.read(&self.a, &self.bus);
|
||||
|
||||
// set carry bit
|
||||
self.p.set(StatusReg::C, (target & 0x1) != 0);
|
||||
|
||||
// shift value
|
||||
target = target >> 1;
|
||||
|
||||
// set zero and negative bits
|
||||
self.p.set(StatusReg::Z, target == 0);
|
||||
self.p.set(StatusReg::N, false); //bit 7 is always 0
|
||||
|
||||
// store value
|
||||
input.write(&mut self.a, &mut self.bus, target);
|
||||
input.get_cycles() + 2
|
||||
}
|
||||
|
||||
fn nop(&self, _: ()) -> u32 {
|
||||
// do nothing
|
||||
2
|
||||
}
|
||||
|
||||
fn ora<I: RInput>(&mut self, input: I) -> u32 {
|
||||
let val = input.read(&self.a, &self.bus);
|
||||
|
||||
// compute
|
||||
self.a = self.a | val;
|
||||
self.p.set(StatusReg::Z, self.a == 0);
|
||||
self.p.set(StatusReg::N, (self.a & (0x1 << 7)) != 0);
|
||||
|
||||
input.get_cycles()
|
||||
}
|
||||
|
||||
fn pha(&mut self, _: ()) -> u32 {
|
||||
self.push_stack(self.a);
|
||||
3
|
||||
}
|
||||
|
||||
fn php(&mut self, _: ()) -> u32 {
|
||||
self.push_stack(self.p.bits() as u8);
|
||||
3
|
||||
}
|
||||
|
||||
fn pla(&mut self, _: ()) -> u32 {
|
||||
self.a = self.pop_stack();
|
||||
4
|
||||
}
|
||||
|
||||
fn plp(&mut self, _: ()) -> u32 {
|
||||
self.p = StatusReg::from_bits_truncate(self.pop_stack());
|
||||
self.p.remove(StatusReg::B | StatusReg::U);
|
||||
4
|
||||
}
|
||||
|
||||
fn rol<I: RWInput>(&mut self, mut input: I) -> u32 {
|
||||
let mut val = input.read(&self.a, &self.bus);
|
||||
|
||||
// store bit 7 and compute
|
||||
let carry = val & (0x1 << 7) != 0;
|
||||
val = val << 1;
|
||||
|
||||
// update bit 0 and carry bit
|
||||
if self.p.contains(StatusReg::C) {
|
||||
val |= 0x1 << 0;
|
||||
}
|
||||
self.p.set(StatusReg::C, carry);
|
||||
|
||||
// store value
|
||||
input.write(&mut self.a, &mut self.bus, val);
|
||||
input.get_cycles() + 2
|
||||
}
|
||||
|
||||
fn ror<I: RWInput>(&mut self, mut input: I) -> u32 {
|
||||
let mut val = input.read(&self.a, &self.bus);
|
||||
|
||||
// store bit 0 and compute
|
||||
let carry = val & (0x1 << 0) != 0;
|
||||
val = val >> 1;
|
||||
|
||||
// update bit 7 and carry bit
|
||||
if self.p.contains(StatusReg::C) {
|
||||
val |= 0x1 << 7;
|
||||
}
|
||||
self.p.set(StatusReg::C, carry);
|
||||
|
||||
// store value
|
||||
input.write(&mut self.a, &mut self.bus, val);
|
||||
input.get_cycles() + 2
|
||||
}
|
||||
|
||||
fn rti(&mut self, _: ()) -> u32 {
|
||||
|
||||
// load status register (B is cleared and I overrided)
|
||||
self.p = StatusReg::from_bits_truncate(self.pop_stack());
|
||||
self.p.set(StatusReg::B, false);
|
||||
|
||||
// load pc
|
||||
let pc_lo = self.pop_stack() as u16;
|
||||
let pc_hi = self.pop_stack() as u16;
|
||||
self.pc = pc_lo | (pc_hi << 8);
|
||||
|
||||
6
|
||||
}
|
||||
|
||||
fn rts(&mut self, _: ()) -> u32 {
|
||||
|
||||
// load pc
|
||||
let pc_lo = self.pop_stack() as u16;
|
||||
let pc_hi = self.pop_stack() as u16;
|
||||
self.pc = pc_lo | (pc_hi << 8);
|
||||
|
||||
6
|
||||
}
|
||||
|
||||
fn sbc<I: RInput>(&mut self, input: I) -> u32 {
|
||||
let val = input.read(&self.a, &self.bus);
|
||||
|
||||
// sub acc and value
|
||||
let prev_a = self.a as u16;
|
||||
let mut a = self.a as u16;
|
||||
if !self.p.contains(StatusReg::C) {
|
||||
a = a.wrapping_sub(1);
|
||||
}
|
||||
a = a.wrapping_sub((val & 0xFF) as u16);
|
||||
|
||||
// handle status bits
|
||||
self.p.set(StatusReg::C, a & 0xFF00 == 0);
|
||||
self.p.set(StatusReg::Z, a & 0xFF == 0);
|
||||
if ((prev_a & 0x80) !=0 && (val & 0x80) != 0 && (a & 0x80) == 0)
|
||||
|| ((prev_a & 0x80) == 0 && (val & 0x80) == 0 && (a & 0x80) != 0) {
|
||||
self.p.set(StatusReg::V, true);
|
||||
} else {
|
||||
self.p.set(StatusReg::V, false);
|
||||
}
|
||||
self.p.set(StatusReg::N, a & 0x80 != 0);
|
||||
|
||||
// truncate accumulator to 8 bits
|
||||
self.a = a as u8;
|
||||
|
||||
input.get_cycles()
|
||||
}
|
||||
|
||||
fn sec(&mut self, _: ()) -> u32 {
|
||||
self.p.set(StatusReg::C, true);
|
||||
2
|
||||
}
|
||||
|
||||
fn sed(&mut self, _: ()) -> u32 {
|
||||
self.p.set(StatusReg::D, true);
|
||||
2
|
||||
}
|
||||
|
||||
fn sei(&mut self, _: ()) -> u32 {
|
||||
self.p.set(StatusReg::I, true);
|
||||
2
|
||||
}
|
||||
|
||||
fn sta<I: RWInput>(&mut self, mut input: I) -> u32 {
|
||||
let a = self.a;
|
||||
input.write(&mut self.a, &mut self.bus, a);
|
||||
input.get_cycles()
|
||||
}
|
||||
|
||||
fn stx<I: RWInput>(&mut self, mut input: I) -> u32 {
|
||||
let x = self.x;
|
||||
input.write(&mut self.a, &mut self.bus, x);
|
||||
input.get_cycles()
|
||||
}
|
||||
|
||||
fn sty<I: RWInput>(&mut self, mut input: I) -> u32 {
|
||||
let y = self.y;
|
||||
input.write(&mut self.a, &mut self.bus, y);
|
||||
input.get_cycles()
|
||||
}
|
||||
|
||||
fn tax(&mut self, _: ()) -> u32 {
|
||||
|
||||
self.x = self.a;
|
||||
self.p.set(StatusReg::Z, self.x == 0);
|
||||
self.p.set(StatusReg::N, (self.x & (0x1 << 7)) != 0);
|
||||
|
||||
2
|
||||
}
|
||||
|
||||
fn tay(&mut self, _: ()) -> u32 {
|
||||
|
||||
self.y = self.a;
|
||||
self.p.set(StatusReg::Z, self.y == 0);
|
||||
self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0);
|
||||
|
||||
2
|
||||
}
|
||||
|
||||
fn tsx(&mut self, _: ()) -> u32 {
|
||||
|
||||
self.x = self.s;
|
||||
self.p.set(StatusReg::Z, self.x == 0);
|
||||
self.p.set(StatusReg::N, (self.x & (0x1 << 7)) != 0);
|
||||
|
||||
2
|
||||
}
|
||||
|
||||
fn txa(&mut self, _: ()) -> u32 {
|
||||
|
||||
self.a = self.x;
|
||||
self.p.set(StatusReg::Z, self.a == 0);
|
||||
self.p.set(StatusReg::N, (self.a & (0x1 << 7)) != 0);
|
||||
|
||||
2
|
||||
}
|
||||
|
||||
fn txs(&mut self, _: ()) -> u32 {
|
||||
self.s = self.x;
|
||||
2
|
||||
}
|
||||
|
||||
fn tya(&mut self, _: ()) -> u32 {
|
||||
|
||||
self.a = self.y;
|
||||
self.p.set(StatusReg::Z, self.a == 0);
|
||||
self.p.set(StatusReg::N, (self.a & (0x1 << 7)) != 0);
|
||||
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
15
src/main.rs
15
src/main.rs
@ -15,6 +15,7 @@ fn main() -> Result<(), &'static str> {
|
||||
dpi::LogicalSize,
|
||||
};
|
||||
use mini_gl_fb::config;
|
||||
use std::fmt::Write;
|
||||
|
||||
// setup
|
||||
setup_logger().map_err(|_| "Failed to setup logger")?;
|
||||
@ -29,15 +30,19 @@ fn main() -> Result<(), &'static str> {
|
||||
let mut buffer = PixelBuffer::new(800, 600);
|
||||
let mut renderer = FontRenderer::new(20.0, [0u8, 0, 0]);
|
||||
|
||||
// first image
|
||||
let mut cpu = Cpu::new();
|
||||
let mut debug_str = String::new();
|
||||
write!(debug_str, "{:#?}", cpu).unwrap();
|
||||
buffer.fill([20, 20], [760, 560], Pixel::rgba(255, 255, 255, 255));
|
||||
renderer.draw(&mut buffer, &debug_str, [20, 20], [760, 560]);
|
||||
|
||||
let vec: Vec<[u8; 4]> = (&buffer).into();
|
||||
fb.update_buffer(&vec);
|
||||
|
||||
let mut cpu = Cpu::new();
|
||||
|
||||
// event loop
|
||||
fb.glutin_handle_basic_input(&mut event_loop, |fb, input| {
|
||||
use winit::event::VirtualKeyCode;
|
||||
use std::fmt::Write;
|
||||
|
||||
// wait for input before updating
|
||||
input.wait = true;
|
||||
@ -47,9 +52,9 @@ fn main() -> Result<(), &'static str> {
|
||||
return false
|
||||
}
|
||||
|
||||
// execute next cpu instruction
|
||||
// execute next cpu instruction (step mode)
|
||||
if input.key_pressed(VirtualKeyCode::S) {
|
||||
cpu.tick();
|
||||
cpu.tick();
|
||||
|
||||
let mut debug_str = String::new();
|
||||
write!(debug_str, "{:#?}", cpu).unwrap();
|
||||
|
||||
@ -60,7 +60,6 @@ impl From<&Pixel> for [u8; 4] {
|
||||
pub struct PixelBuffer {
|
||||
buffer: Vec<Pixel>,
|
||||
h: usize,
|
||||
w: usize,
|
||||
}
|
||||
|
||||
impl PixelBuffer {
|
||||
@ -69,7 +68,6 @@ impl PixelBuffer {
|
||||
PixelBuffer {
|
||||
buffer: vec![Pixel::rgba(255u8, 255u8, 255u8, 255); h * w],
|
||||
h,
|
||||
w,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user