diff --git a/src/cpu.rs b/src/cpu.rs index 12160ba..bfae68d 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -240,6 +240,30 @@ impl CPU { self.pc + instruction.length as i32 } } + + pub fn tick(&mut self) { + if self.halted { return } + + match self.fetch() { + Ok(instr) => { + //println!("Instr: {}", instr.opcode); + self.pc = self.execute(instr) + } + + Err(invalidOpcode) => { + self.halted = true; + println!("Error: {}", invalidOpcode) + } + } + } + + pub fn start(&mut self) { + self.halted = false + } + + pub fn running(&self) -> bool { + !self.halted + } } impl Opcode { diff --git a/src/display.rs b/src/display.rs index bfa27b4..c4e2e38 100644 --- a/src/display.rs +++ b/src/display.rs @@ -17,12 +17,12 @@ struct DisplayRegisters { impl Default for DisplayRegisters { fn default() -> Self { Self { - mode: 5, + mode: 0, screen: Word::from(0x10000), palette: Word::from(0x20000 - 0x100), font: Word::from(0x20000 - 0x100 - 0x2000), - height: Word::from(128), - width: Word::from(128), + height: Word::from(60), + width: Word::from(80), row_offset: Word::from(0), col_offset: Word::from(0), } @@ -122,7 +122,7 @@ fn draw_paletted_high_gfx(machine: &P, reg: DisplayRegisters, frame fn draw_paletted_high_text(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { let (display_row, display_col) = (i / 640, i % 640); - let (vulcan_row, vulcan_col) = (Word::from(display_row >> 2), Word::from(display_col >> 2)); + let (vulcan_row, vulcan_col) = (Word::from(display_row >> 3), Word::from(display_col >> 3)); let addr = to_byte_address((vulcan_col, vulcan_row), reg); let char_idx = machine.peek(addr) as u32; @@ -157,7 +157,7 @@ fn draw_text_pixel(pixel: &mut [u8; 4], char_col: u8, char_byte: u8, fg_color: u fn draw_direct_high_text(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { let (display_row, display_col) = (i / 640, i % 640); - let (vulcan_row, vulcan_col) = (Word::from(display_row >> 2), Word::from(display_col >> 2)); + let (vulcan_row, vulcan_col) = (Word::from(display_row >> 3), Word::from(display_col >> 3)); let addr = to_byte_address((vulcan_col, vulcan_row), reg); let char_idx = machine.peek(addr) as u32; @@ -180,7 +180,7 @@ fn draw_direct_high_text(machine: &P, reg: DisplayRegisters, frame: fn draw_direct_low_text(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { let (display_row, display_col) = (i / 640, i % 640); - let (vulcan_row, vulcan_col) = (Word::from(display_row >> 2), Word::from(display_col >> 2)); + let (vulcan_row, vulcan_col) = (Word::from(display_row >> 4), Word::from(display_col >> 4)); let addr = to_byte_address((vulcan_col, vulcan_row), reg); let char_idx = machine.peek(addr) as u32; @@ -203,7 +203,7 @@ fn draw_direct_low_text(machine: &P, reg: DisplayRegisters, frame: fn draw_paletted_low_text(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { let (display_row, display_col) = (i / 640, i % 640); - let (vulcan_row, vulcan_col) = (Word::from(display_row >> 2), Word::from(display_col >> 2)); + let (vulcan_row, vulcan_col) = (Word::from(display_row >> 4), Word::from(display_col >> 4)); let addr = to_byte_address((vulcan_col, vulcan_row), reg); let char_idx = machine.peek(addr) as u32; diff --git a/src/gfx_test.rom b/src/gfx_test.rom new file mode 100644 index 0000000..deae1dd Binary files /dev/null and b/src/gfx_test.rom differ diff --git a/src/main.rs b/src/main.rs index f73ce10..fe4f16d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ use crate::cpu::CPU; use crate::memory::{Memory, PeekPoke}; use crate::word::Word; use pixels::{Pixels, SurfaceTexture}; -use std::time::Instant; +use std::time::{Instant, Duration}; use winit::window::Window; fn main() { @@ -42,12 +42,14 @@ fn main() { let memory = Memory::from(rng); let mut cpu = CPU::new(memory); display::reset(&mut cpu); - for n in 0..128 { - cpu.poke(Word::from(0x10000 + 128 * n), 0b11100000); - cpu.poke(Word::from(0x10000 + n), 0xff); - cpu.poke(Word::from(0x10000 + 128 * n + 127), 0b00000011); - cpu.poke(Word::from(0x10000 + 128 * 127 + n), 0b00011100); - } + // for n in 0..128 { + // cpu.poke(Word::from(0x10000 + 128 * n), 0b11100000); + // cpu.poke(Word::from(0x10000 + n), 0xff); + // cpu.poke(Word::from(0x10000 + 128 * n + 127), 0b00000011); + // cpu.poke(Word::from(0x10000 + 128 * 127 + n), 0b00011100); + // } + cpu.poke_slice(Word::from(0x400), include_bytes!("gfx_test.rom")); + cpu.start(); window_loop(event_loop, window, pixels, cpu) } @@ -60,17 +62,23 @@ fn window_loop(event_loop: EventLoop<()>, window: Window, mut pixels: Pixels, mu event: WindowEvent::CloseRequested, window_id, } if window_id == window.id() => *control_flow = ControlFlow::Exit, + + Event::WindowEvent { + event: WindowEvent::Resized(newSize), + window_id + } if window_id == window.id() => { + pixels.resize_surface(newSize.width, newSize.height); + } + Event::MainEventsCleared => { let start = Instant::now(); draw(pixels.get_frame(), &mut cpu); - let draw_time = Instant::now() - start; pixels.render().expect("Problem displaying framebuffer"); - let total_time = Instant::now() - start; - println!( - "Tick took {} total, {} to draw", - total_time.as_micros(), - draw_time.as_micros() - ); + while Instant::now() < start + Duration::from_millis(25) { + for _ in 1..1000 { + cpu.tick() + } + } } _ => {} } diff --git a/src/opcodes.rs b/src/opcodes.rs index e435376..b13fbb0 100644 --- a/src/opcodes.rs +++ b/src/opcodes.rs @@ -59,6 +59,56 @@ impl Display for InvalidOpcode { impl std::error::Error for InvalidOpcode {} +impl Display for Opcode { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Opcode::Nop => { write!(f, "nop") } + Opcode::Add => { write!(f, "add") } + Opcode::Sub => { write!(f, "sub") } + Opcode::Mul => { write!(f, "mul") } + Opcode::Div => { write!(f, "div") } + Opcode::Mod => { write!(f, "mod") } + Opcode::Rand => { write!(f, "rand") } + Opcode::And => { write!(f, "and") } + Opcode::Or => { write!(f, "or") } + Opcode::Xor => { write!(f, "xor") } + Opcode::Not => { write!(f, "not") } + Opcode::Gt => { write!(f, "gt") } + Opcode::Lt => { write!(f, "lt") } + Opcode::Agt => { write!(f, "agt") } + Opcode::Alt => { write!(f, "alt") } + Opcode::Lshift => { write!(f, "lshift") } + Opcode::Rshift => { write!(f, "rshift") } + Opcode::Arshift => { write!(f, "arshift") } + Opcode::Pop => { write!(f, "pop") } + Opcode::Dup => { write!(f, "dup") } + Opcode::Swap => { write!(f, "swap") } + Opcode::Pick => { write!(f, "pick") } + Opcode::Rot => { write!(f, "rot") } + Opcode::Jmp => { write!(f, "jmp") } + Opcode::Jmpr => { write!(f, "jmpr") } + Opcode::Call => { write!(f, "call") } + Opcode::Ret => { write!(f, "ret") } + Opcode::Brz => { write!(f, "brz") } + Opcode::Brnz => { write!(f, "brnz") } + Opcode::Hlt => { write!(f, "hlt") } + Opcode::Load => { write!(f, "load") } + Opcode::Loadw => { write!(f, "loadw") } + Opcode::Store => { write!(f, "store") } + Opcode::Storew => { write!(f, "storew") } + Opcode::Inton => { write!(f, "inton") } + Opcode::Intoff => { write!(f, "intoff") } + Opcode::Setiv => { write!(f, "setiv") } + Opcode::Sdp => { write!(f, "sdp") } + Opcode::Setsdp => { write!(f, "setsdp") } + Opcode::Pushr => { write!(f, "pushr") } + Opcode::Popr => { write!(f, "popr") } + Opcode::Peekr => { write!(f, "peekr") } + Opcode::Debug => { write!(f, "debug") } + } + } +} + impl TryFrom for Opcode { type Error = InvalidOpcode;