Basic hello world, running the CPU
This commit is contained in:
+24
@@ -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
@@ -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;
|
||||||
|
|||||||
Binary file not shown.
+22
-14
@@ -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()
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user