interrupts work now!
This commit is contained in:
parent
7f8e00af23
commit
dcaeece7fa
59
src/cpu.rs
59
src/cpu.rs
|
@ -27,8 +27,7 @@ pub struct CpuController(Sender<CpuControl>);
|
|||
pub enum CpuControl {
|
||||
Irq,
|
||||
Nmi,
|
||||
Stop,
|
||||
Resume,
|
||||
Toggle,
|
||||
Data,
|
||||
Cycle,
|
||||
}
|
||||
|
@ -43,11 +42,8 @@ impl CpuController {
|
|||
pub fn nmi(&self) {
|
||||
self.0.send(CpuControl::Nmi);
|
||||
}
|
||||
pub fn stop(&self) {
|
||||
self.0.send(CpuControl::Stop);
|
||||
}
|
||||
pub fn resume(&self) {
|
||||
self.0.send(CpuControl::Resume);
|
||||
pub fn toggle(&self) {
|
||||
self.0.send(CpuControl::Toggle);
|
||||
}
|
||||
pub fn cycle(&self) {
|
||||
self.0.send(CpuControl::Cycle);
|
||||
|
@ -215,8 +211,9 @@ impl Cpu {
|
|||
match control {
|
||||
CpuControl::Nmi => self.nmi = true,
|
||||
CpuControl::Irq => self.irq = true,
|
||||
CpuControl::Stop => self.stopped = true,
|
||||
CpuControl::Resume => self.stopped = false,
|
||||
CpuControl::Toggle => {
|
||||
self.stopped = !self.stopped;
|
||||
}
|
||||
CpuControl::Cycle => self.cycle = true,
|
||||
CpuControl::Data => {} // self
|
||||
// .state_tx
|
||||
|
@ -239,9 +236,13 @@ impl Cpu {
|
|||
|
||||
pub fn cycle(&mut self) {
|
||||
self.receive_control();
|
||||
if self.stopped {
|
||||
|
||||
if self.stopped & !self.cycle {
|
||||
// self.set_flag(StatusFlag::IrqDisable, true);
|
||||
return;
|
||||
}
|
||||
self.cycle = false;
|
||||
|
||||
while self.pending_cycles != 0 {
|
||||
// roughly cycle-accurate timing
|
||||
sleep(Duration::from_nanos(500));
|
||||
|
@ -253,38 +254,12 @@ impl Cpu {
|
|||
let opcode = self.read(self.pc);
|
||||
let instruction = get_instruction(opcode);
|
||||
instruction.call(self);
|
||||
// match instruction {
|
||||
// Instruction::Valid(valid_instruction) => {
|
||||
// // println!("a: {a:#04x}, x: {x:#04x}, y: {y:#04x}, pc: {pc:#06x}, sp: {s:#04x}, sr: {p:#010b}, irq: {irq:?}, nmi: {nmi:?}", a = self.a, x = self.x, y = self.y, pc = self.pc, s = self.s, p = self.p, irq = self.irq, nmi = self.nmi);
|
||||
// // println!(
|
||||
// // "Instruction: {:?}, {:#04x}",
|
||||
// // valid_instruction.opcode, opcode
|
||||
// // );
|
||||
// // println!("");
|
||||
// self.pc += 1;
|
||||
// match valid_instruction.opcode.call(self) {
|
||||
// Ok(_) => {
|
||||
// self.pending_cycles += valid_instruction.cycles as usize;
|
||||
// }
|
||||
// Err(_) => {
|
||||
// println!("An IncompatibleAddrMode was used at address {:#06x} for instruction {:?}", self.pc, valid_instruction);
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// Instruction::Invalid(invalid_instruction) => match invalid_instruction.opcode {
|
||||
// 0x02 => {
|
||||
// // println!("a: {a:#04x}, x: {x:#04x}, y: {y:#04x}, pc: {pc:#06x}, sp: {s:#04x}, sr: {p:#010b}, irq: {irq:?}, nmi: {nmi:?}", a = self.a, x = self.x, y = self.y, pc = self.pc, s = self.s, p = self.p, irq = self.irq.try_recv().unwrap_or_default(), nmi = self.nmi);
|
||||
// let _ = &self.memory.dump();
|
||||
// }
|
||||
// _ => {
|
||||
// println!(
|
||||
// "An invalid instruction with opcode {:#04x} was called at address {:#06x}",
|
||||
// invalid_instruction.opcode, self.pc
|
||||
// );
|
||||
// }
|
||||
// },
|
||||
// }
|
||||
// self.cycle_count += 1;
|
||||
// println!("a: {a:#04x}, x: {x:#04x}, y: {y:#04x}, pc: {pc:#06x}, sp: {s:#04x}, sr: {p:#010b}, irq: {irq:?}, nmi: {nmi:?}", a = self.a, x = self.x, y = self.y, pc = self.pc, s = self.s, p = self.p, irq = self.irq, nmi = self.nmi);
|
||||
// println!(
|
||||
// "Instruction: {:?}, {:#04x}",
|
||||
// valid_instruction.opcode, opcode
|
||||
// );
|
||||
// println!("");
|
||||
}
|
||||
pub fn stop(&mut self) {
|
||||
self.stopped = true;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use core::panic;
|
||||
|
||||
use termion::cursor::Goto;
|
||||
use termion::{clear, color};
|
||||
|
||||
use crate::cpu::{Cpu, StatusFlag};
|
||||
use crate::memory::{MemoryReader, MemoryWriter};
|
||||
|
@ -20,13 +21,39 @@ pub struct Instruction<'a> {
|
|||
|
||||
impl Instruction<'_> {
|
||||
pub fn call(&self, cpu: &mut Cpu) {
|
||||
print!("{}{}instruction: {:?}, a: {a:#04x}, x: {x:#04x}, y: {y:#04x}, pc: {pc:#06x}, sp: {s:#04x}, sr: {p:#010b}, irq: {irq:?}, nmi: {nmi:?}", Goto(0, 31),clear::UntilNewline, self.name, a = cpu.a, x = cpu.x, y = cpu.y, pc = cpu.pc, s = cpu.s, p = cpu.p, irq = cpu.irq, nmi = cpu.nmi);
|
||||
// print!(
|
||||
// "{}instruction: {:?}, pc: {:#04x}",
|
||||
// Goto(0, 31),
|
||||
// self.name,
|
||||
// cpu.pc
|
||||
// );
|
||||
print!(
|
||||
"{}{:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {}{}{:02x}{}{} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x}",
|
||||
Goto(0, 32),
|
||||
cpu.read(cpu.pc.wrapping_sub(8)),
|
||||
cpu.read(cpu.pc.wrapping_sub(7)),
|
||||
cpu.read(cpu.pc.wrapping_sub(6)),
|
||||
cpu.read(cpu.pc.wrapping_sub(5)),
|
||||
cpu.read(cpu.pc.wrapping_sub(4)),
|
||||
cpu.read(cpu.pc.wrapping_sub(3)),
|
||||
cpu.read(cpu.pc.wrapping_sub(2)),
|
||||
cpu.read(cpu.pc.wrapping_sub(1)),
|
||||
color::Bg(color::Rgb(0xFF, 0xCC, 0x00)),
|
||||
color::Fg(color::Rgb(0x11, 0x05, 0x00)),
|
||||
cpu.read(cpu.pc),
|
||||
color::Fg(color::Rgb(0xFF, 0xCC, 0x00)),
|
||||
color::Bg(color::Rgb(0x11, 0x05, 0x00)),
|
||||
cpu.read(cpu.pc.wrapping_add(1)),
|
||||
cpu.read(cpu.pc.wrapping_add(2)),
|
||||
cpu.read(cpu.pc.wrapping_add(3)),
|
||||
cpu.read(cpu.pc.wrapping_add(4)),
|
||||
cpu.read(cpu.pc.wrapping_add(5)),
|
||||
cpu.read(cpu.pc.wrapping_add(6)),
|
||||
cpu.read(cpu.pc.wrapping_add(7)),
|
||||
cpu.read(cpu.pc.wrapping_add(8)),
|
||||
);
|
||||
cpu.pc = cpu.pc.wrapping_add(1); // read instruction byte
|
||||
// println!(
|
||||
// "{}instruction: {:?}, pc: {:#04x}",
|
||||
// Goto(0, 31),
|
||||
// self.name,
|
||||
// cpu.pc
|
||||
// );
|
||||
match self.instr_fn {
|
||||
// existence of instr_fn means this is a valid instruction
|
||||
Some(instr_fn) => {
|
||||
|
@ -732,7 +759,10 @@ fn rti(cpu: &mut Cpu, _address: Option<u16>) {
|
|||
|
||||
fn rts(cpu: &mut Cpu, _address: Option<u16>) {
|
||||
let return_address = cpu.pop_stack_word();
|
||||
cpu.pc = return_address + 3; // Go back to where we jsr'ed, skipping the operand
|
||||
// cpu.pc = return_address + 3; // Go back to where we jsr'ed, skipping the operand
|
||||
cpu.pc = return_address.wrapping_add(1); // we love an off by 2 error!
|
||||
// TODO: figure out why
|
||||
// this needs to be like this
|
||||
}
|
||||
|
||||
fn sbc(cpu: &mut Cpu, address: Option<u16>) {
|
||||
|
|
|
@ -60,8 +60,9 @@ fn main() {
|
|||
Key::Char('q') => {
|
||||
break 'main;
|
||||
}
|
||||
// Key::Char(' ') => cpu_controller.stop(),
|
||||
// Key::Char('\n') => cpu_controller.resume(),
|
||||
Key::Char(' ') => cpu_controller.toggle(),
|
||||
Key::Char('\n') => cpu_controller.cycle(),
|
||||
Key::Char('i') => cpu_controller.irq(),
|
||||
_ => keyboard.read_keys(key),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,30 +10,39 @@ reset:
|
|||
sei
|
||||
ldx #0; initialize data stack pointer
|
||||
|
||||
initdisplay:
|
||||
lda #0
|
||||
ldy #0
|
||||
; initdisplay:
|
||||
; lda #0
|
||||
; ldy #0
|
||||
|
||||
cleardisplay:
|
||||
sta $6000,y
|
||||
sta $6100,y
|
||||
sta $6200,y
|
||||
sta $6300,y
|
||||
sta $6400,y
|
||||
sta $6500,y
|
||||
sta $6600,y
|
||||
sta $6700,y ; this goes slightly over but it's fine
|
||||
iny
|
||||
bne cleardisplay
|
||||
; cleardisplay:
|
||||
; sta $6000,y
|
||||
; sta $6100,y
|
||||
; sta $6200,y
|
||||
; sta $6300,y
|
||||
; sta $6400,y
|
||||
; sta $6500,y
|
||||
; sta $6600,y
|
||||
; sta $6700,y ; this goes slightly over but it's fine
|
||||
; iny
|
||||
; bne cleardisplay
|
||||
cli
|
||||
|
||||
main:
|
||||
; jsr read_keys
|
||||
jsr test
|
||||
; lda key_buffer
|
||||
lda $4400
|
||||
sta $6000
|
||||
; lda $4400
|
||||
; sta $6000
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
jmp main
|
||||
|
||||
test:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
rts
|
||||
|
||||
; first, let's do the simplest case of just the letter a being pressed
|
||||
; 1. check row 2 ($4402, where the a key is) for pressed keys
|
||||
; 2. if any keys are pressed, check if the key is a (bit 0)
|
||||
|
@ -104,6 +113,8 @@ fill: ; fills an area from (x1, y1) to (x2, y2) will character c, (n1: c n2: x1
|
|||
jsr get_char_address
|
||||
|
||||
irq:
|
||||
lda $4400
|
||||
sta $6000
|
||||
rts
|
||||
|
||||
isr: ; interrupt service routine
|
||||
|
|
|
@ -204,7 +204,7 @@ impl Screen {
|
|||
}
|
||||
}
|
||||
pub fn draw(&mut self) {
|
||||
// self.controller.irq();
|
||||
self.controller.irq();
|
||||
self.renderer.render();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue