Basic hello world, running the CPU

This commit is contained in:
2022-02-26 01:42:32 -06:00
parent 889f85f1dd
commit 81b805f338
5 changed files with 103 additions and 21 deletions
+24
View File
@@ -240,6 +240,30 @@ impl CPU {
self.pc + instruction.length as i32 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 { impl Opcode {
+7 -7
View File
@@ -17,12 +17,12 @@ struct DisplayRegisters {
impl Default for DisplayRegisters { impl Default for DisplayRegisters {
fn default() -> Self { fn default() -> Self {
Self { Self {
mode: 5, mode: 0,
screen: Word::from(0x10000), screen: Word::from(0x10000),
palette: Word::from(0x20000 - 0x100), palette: Word::from(0x20000 - 0x100),
font: Word::from(0x20000 - 0x100 - 0x2000), font: Word::from(0x20000 - 0x100 - 0x2000),
height: Word::from(128), height: Word::from(60),
width: Word::from(128), width: Word::from(80),
row_offset: Word::from(0), row_offset: Word::from(0),
col_offset: Word::from(0), col_offset: Word::from(0),
} }
@@ -122,7 +122,7 @@ fn draw_paletted_high_gfx<P: PeekPoke>(machine: &P, reg: DisplayRegisters, frame
fn draw_paletted_high_text<P: PeekPoke>(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { fn draw_paletted_high_text<P: PeekPoke>(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) {
for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
let (display_row, display_col) = (i / 640, i % 640); 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 addr = to_byte_address((vulcan_col, vulcan_row), reg);
let char_idx = machine.peek(addr) as u32; 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<P: PeekPoke>(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { fn draw_direct_high_text<P: PeekPoke>(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) {
for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
let (display_row, display_col) = (i / 640, i % 640); 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 addr = to_byte_address((vulcan_col, vulcan_row), reg);
let char_idx = machine.peek(addr) as u32; let char_idx = machine.peek(addr) as u32;
@@ -180,7 +180,7 @@ fn draw_direct_high_text<P: PeekPoke>(machine: &P, reg: DisplayRegisters, frame:
fn draw_direct_low_text<P: PeekPoke>(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { fn draw_direct_low_text<P: PeekPoke>(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) {
for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
let (display_row, display_col) = (i / 640, i % 640); 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 addr = to_byte_address((vulcan_col, vulcan_row), reg);
let char_idx = machine.peek(addr) as u32; let char_idx = machine.peek(addr) as u32;
@@ -203,7 +203,7 @@ fn draw_direct_low_text<P: PeekPoke>(machine: &P, reg: DisplayRegisters, frame:
fn draw_paletted_low_text<P: PeekPoke>(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { fn draw_paletted_low_text<P: PeekPoke>(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) {
for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
let (display_row, display_col) = (i / 640, i % 640); 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 addr = to_byte_address((vulcan_col, vulcan_row), reg);
let char_idx = machine.peek(addr) as u32; let char_idx = machine.peek(addr) as u32;
BIN
View File
Binary file not shown.
+22 -14
View File
@@ -16,7 +16,7 @@ use crate::cpu::CPU;
use crate::memory::{Memory, PeekPoke}; use crate::memory::{Memory, PeekPoke};
use crate::word::Word; use crate::word::Word;
use pixels::{Pixels, SurfaceTexture}; use pixels::{Pixels, SurfaceTexture};
use std::time::Instant; use std::time::{Instant, Duration};
use winit::window::Window; use winit::window::Window;
fn main() { fn main() {
@@ -42,12 +42,14 @@ fn main() {
let memory = Memory::from(rng); let memory = Memory::from(rng);
let mut cpu = CPU::new(memory); let mut cpu = CPU::new(memory);
display::reset(&mut cpu); display::reset(&mut cpu);
for n in 0..128 { // for n in 0..128 {
cpu.poke(Word::from(0x10000 + 128 * n), 0b11100000); // cpu.poke(Word::from(0x10000 + 128 * n), 0b11100000);
cpu.poke(Word::from(0x10000 + n), 0xff); // cpu.poke(Word::from(0x10000 + n), 0xff);
cpu.poke(Word::from(0x10000 + 128 * n + 127), 0b00000011); // cpu.poke(Word::from(0x10000 + 128 * n + 127), 0b00000011);
cpu.poke(Word::from(0x10000 + 128 * 127 + n), 0b00011100); // 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) 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, event: WindowEvent::CloseRequested,
window_id, window_id,
} if window_id == window.id() => *control_flow = ControlFlow::Exit, } 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 => { Event::MainEventsCleared => {
let start = Instant::now(); let start = Instant::now();
draw(pixels.get_frame(), &mut cpu); draw(pixels.get_frame(), &mut cpu);
let draw_time = Instant::now() - start;
pixels.render().expect("Problem displaying framebuffer"); pixels.render().expect("Problem displaying framebuffer");
let total_time = Instant::now() - start; while Instant::now() < start + Duration::from_millis(25) {
println!( for _ in 1..1000 {
"Tick took {} total, {} to draw", cpu.tick()
total_time.as_micros(), }
draw_time.as_micros() }
);
} }
_ => {} _ => {}
} }
+50
View File
@@ -59,6 +59,56 @@ impl Display for InvalidOpcode {
impl std::error::Error 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<u8> for Opcode { impl TryFrom<u8> for Opcode {
type Error = InvalidOpcode; type Error = InvalidOpcode;