more validation tests for gemma video rendering
Adds 'doom like' 3dviprmaze-vip for demo (VERY VERY SLOW) updates egui interface to let user select from files in resources/roms updates cargo to centralize dependencies 95 passing tests
This commit is contained in:
parent
939fd83e80
commit
b4b8bfb24b
31
Cargo.lock
generated
31
Cargo.lock
generated
@ -489,16 +489,6 @@ dependencies = [
|
|||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "beep"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "add99ab8e6fa29e525696f04be01c6e18815f5d799e026a06c8b09af8301bd5a"
|
|
||||||
dependencies = [
|
|
||||||
"lazy_static",
|
|
||||||
"nix 0.20.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit-set"
|
name = "bit-set"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@ -1615,7 +1605,6 @@ dependencies = [
|
|||||||
name = "gemmaimgui"
|
name = "gemmaimgui"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"beep",
|
|
||||||
"chrono",
|
"chrono",
|
||||||
"copypasta",
|
"copypasta",
|
||||||
"dimensioned",
|
"dimensioned",
|
||||||
@ -1631,6 +1620,13 @@ dependencies = [
|
|||||||
"winit 0.27.5",
|
"winit 0.27.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gemmatelnet"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"gemma",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.7"
|
version = "0.14.7"
|
||||||
@ -2525,19 +2521,6 @@ dependencies = [
|
|||||||
"jni-sys",
|
"jni-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nix"
|
|
||||||
version = "0.20.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f5e06129fb611568ef4e868c14b326274959aa70ff7776e9d55323531c374945"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.2.1",
|
|
||||||
"cc",
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"memoffset 0.6.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.24.3"
|
version = "0.24.3"
|
||||||
|
|||||||
22
Cargo.toml
22
Cargo.toml
@ -1,3 +1,23 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = ["gemma", "gemmaegui", "gemmaimgui" ]
|
members = ["gemma", "gemmaegui", "gemmaimgui", "gemmatelnet" ]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
pretty_env_logger = { version = "0.5.0" }
|
||||||
|
log = { version = "0.4.22" }
|
||||||
|
rand = { version = "0.9.0-alpha.2" }
|
||||||
|
chrono = { version = "0.4.38" }
|
||||||
|
dimensioned = { version = "0.8.0" }
|
||||||
|
|
||||||
|
# EGUI
|
||||||
|
egui = { version = "0.29" }
|
||||||
|
eframe = { version = "0.29" }
|
||||||
|
|
||||||
|
# IMGUI
|
||||||
|
glium = { version = "0.34.0" }
|
||||||
|
image = { version = "0.23" }
|
||||||
|
imgui = { version = "0.12.0" }
|
||||||
|
imgui-glium-renderer = { version = "0.12.0" }
|
||||||
|
imgui-winit-support = { version = "0.12.0" }
|
||||||
|
winit = { version = "0.27", features = ["x11", "mint"]}
|
||||||
|
copypasta = { version = "0.8" }
|
||||||
|
|||||||
@ -5,9 +5,9 @@ edition = "2021"
|
|||||||
autobenches = true
|
autobenches = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
pretty_env_logger = "0.5.0"
|
pretty_env_logger.workspace = true
|
||||||
rand = "0.9.0-alpha.2"
|
rand.workspace = true
|
||||||
log = "0.4.22"
|
log.workspace = true
|
||||||
# beep = "0.3.0"
|
# beep = "0.3.0"
|
||||||
chrono = "0.4.38"
|
chrono.workspace = true
|
||||||
dimensioned = "0.8.0"
|
dimensioned.workspace = true
|
||||||
|
|||||||
@ -58,14 +58,15 @@ impl Chip8Computer {
|
|||||||
self.video_memory.format_as_string()
|
self.video_memory.format_as_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_program(new_program: Box<Vec<u16>>) -> Self {
|
pub fn new_with_program(new_program: Vec<u16>) -> Self {
|
||||||
let mut working = Chip8Computer::new();
|
let mut working = Chip8Computer::new();
|
||||||
for i in 0..new_program.len() {
|
|
||||||
let high_byte = (new_program[i as usize] >> 8) as u8;
|
for (i, &word) in new_program.iter().enumerate() {
|
||||||
let low_byte = (new_program[i] & 0xff) as u8;
|
let high = (word >> 8) as u8;
|
||||||
let base_offset = i * 2;
|
let low = (word & 0xff) as u8;
|
||||||
working.memory.poke(base_offset as u16, high_byte);
|
let base_offset = (i * 2) as u16;
|
||||||
working.memory.poke((base_offset + 1) as u16, low_byte);
|
working.memory.poke(base_offset, high);
|
||||||
|
working.memory.poke(base_offset + 1, low);
|
||||||
}
|
}
|
||||||
working
|
working
|
||||||
}
|
}
|
||||||
@ -85,11 +86,12 @@ impl Chip8Computer {
|
|||||||
pub fn step_system(&mut self) -> &mut Chip8Computer {
|
pub fn step_system(&mut self) -> &mut Chip8Computer {
|
||||||
debug!("Stepping System 1 Step");
|
debug!("Stepping System 1 Step");
|
||||||
// read the next instruction
|
// read the next instruction
|
||||||
|
let local_memory = &self.memory;
|
||||||
|
|
||||||
// let mut working_instruction: u16 = 0b0000000000000000;
|
// let mut working_instruction: u16 = 0b0000000000000000;
|
||||||
let start_pc = self.registers.peek_pc();
|
let start_pc = self.registers.peek_pc();
|
||||||
let high_byte = (self.memory.clone().peek(start_pc) as u16).rotate_left(8);
|
let high_byte = (local_memory.peek(start_pc) as u16).rotate_left(8);
|
||||||
let low_byte = self.memory.clone().peek(start_pc + 1) as u16;
|
let low_byte = local_memory.peek(start_pc + 1) as u16;
|
||||||
let result = high_byte | low_byte;
|
let result = high_byte | low_byte;
|
||||||
let decoded_instruction =
|
let decoded_instruction =
|
||||||
Chip8CpuInstructions::decode(result);
|
Chip8CpuInstructions::decode(result);
|
||||||
@ -101,9 +103,10 @@ impl Chip8Computer {
|
|||||||
self.sound_timer.tick();
|
self.sound_timer.tick();
|
||||||
self.delay_timer.tick();
|
self.delay_timer.tick();
|
||||||
self.video_memory.tick();
|
self.video_memory.tick();
|
||||||
|
self.num_cycles += 1;
|
||||||
}
|
}
|
||||||
Chip8CpuStates::WaitingForKey => {
|
Chip8CpuStates::WaitingForKey => {
|
||||||
println!("waiting for a key press...");
|
debug!("waiting for a key press...");
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use std::ops::{BitAnd, Shr};
|
use std::ops::{BitAnd, Shr};
|
||||||
|
use std::time::Instant;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use rand::{random, Rng};
|
use rand::{random, Rng};
|
||||||
use crate::chip8::computer::{Chip8Computer};
|
use crate::chip8::computer::{Chip8Computer};
|
||||||
@ -417,6 +418,8 @@ impl Chip8CpuInstructions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(&self, input: &mut Chip8Computer) -> Chip8Computer {
|
pub fn execute(&self, input: &mut Chip8Computer) -> Chip8Computer {
|
||||||
|
print!("INSTRUCTION {:04x}", self.encode());
|
||||||
|
let start_time = Instant::now();
|
||||||
let start_pc = input.registers.peek_pc();
|
let start_pc = input.registers.peek_pc();
|
||||||
input.registers.poke_pc(start_pc + 2);
|
input.registers.poke_pc(start_pc + 2);
|
||||||
let _ = match self {
|
let _ = match self {
|
||||||
@ -681,19 +684,16 @@ impl Chip8CpuInstructions {
|
|||||||
|
|
||||||
for byte_index in 0..num_bytes_to_read {
|
for byte_index in 0..num_bytes_to_read {
|
||||||
let current_byte = input.memory.peek(byte_index as u16 + source_memory_offset);
|
let current_byte = input.memory.peek(byte_index as u16 + source_memory_offset);
|
||||||
|
let x_offset: u16 = (x_offset + byte_index) as u16 * 64;
|
||||||
for bit_index in 0..8 {
|
for bit_index in 0..8 {
|
||||||
let data_offset = ((x_offset as u16 + byte_index as u16) * 64) + (y_offset as u16 + bit_index as u16) as u16;
|
let data_offset = x_offset + (y_offset as u16 + bit_index as u16);
|
||||||
let current_bit = (current_byte & (0x80 >> bit_index)) != 0;
|
let current_bit = (current_byte & (0x80 >> bit_index)) != 0;
|
||||||
let previous_bit = input.video_memory.peek(data_offset);
|
let previous_bit = input.video_memory.peek(data_offset);
|
||||||
let new_bit = previous_bit ^ current_bit;
|
|
||||||
if previous_bit && !new_bit {
|
|
||||||
did_change = true;
|
|
||||||
}
|
|
||||||
input.video_memory.poke(data_offset, current_bit);
|
input.video_memory.poke(data_offset, current_bit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if did_change {
|
if input.video_memory.has_frame_changed {
|
||||||
input.registers.poke(0xf, 1u8);
|
input.registers.poke(0xf, 1u8);
|
||||||
} else {
|
} else {
|
||||||
input.registers.poke(0xf, 0u8);
|
input.registers.poke(0xf, 0u8);
|
||||||
@ -827,7 +827,9 @@ impl Chip8CpuInstructions {
|
|||||||
}
|
}
|
||||||
Chip8CpuInstructions::XXXXERRORINSTRUCTION => {}
|
Chip8CpuInstructions::XXXXERRORINSTRUCTION => {}
|
||||||
};
|
};
|
||||||
input.clone()
|
let cycle_time = Instant::now().duration_since(start_time).as_nanos();
|
||||||
|
println!("Took {cycle_time}ms");
|
||||||
|
input.to_owned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,9 +14,7 @@ impl Chip8Video {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn cls(&mut self) {
|
pub fn cls(&mut self) {
|
||||||
for i in 0..CHIP8_VIDEO_MEMORY {
|
self.memory = [false; CHIP8_VIDEO_MEMORY];
|
||||||
self.memory[i] = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_frame(&mut self) {
|
pub fn start_frame(&mut self) {
|
||||||
|
|||||||
@ -4,22 +4,12 @@ use gemma::constants::CHIP8_VIDEO_MEMORY;
|
|||||||
#[test]
|
#[test]
|
||||||
fn smoke() { assert!(true) }
|
fn smoke() { assert!(true) }
|
||||||
|
|
||||||
#[test]
|
fn load_result(to_load: &str) -> String {
|
||||||
fn test_rom_1_works() {
|
std::fs::read_to_string(format!("../resources/test/{}", to_load)).unwrap()
|
||||||
let mut x = Chip8Computer::new();
|
}
|
||||||
// Load the IBM rom and run it.
|
|
||||||
// it takes 39 cycles to get to the end so lets run it 40.
|
|
||||||
|
|
||||||
let test_rom_to_run = std::fs::read("../resources/roms/2-ibm-logo.ch8").unwrap();
|
fn load_rom(to_load: &str) -> Vec<u8> {
|
||||||
x.load_bytes_to_memory(0x200, (&test_rom_to_run).into());
|
std::fs::read(format!("../resources/roms/{}", to_load)).unwrap()
|
||||||
|
|
||||||
for i in 0..40 {
|
|
||||||
x.step_system();
|
|
||||||
}
|
|
||||||
// ...then verify that the current video memory of the chip-8
|
|
||||||
// simulator matches what we expect it to be
|
|
||||||
|
|
||||||
assert_eq!(x.dump_video_to_string(), std::fs::read_to_string("../resources/test/gemma_integration_ibm_rom_output.asc").unwrap());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -39,3 +29,75 @@ fn reset_clears_video() {
|
|||||||
assert!(!x.video_memory.peek(i as u16));
|
assert!(!x.video_memory.peek(i as u16));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn level1_test() {
|
||||||
|
let mut x = Chip8Computer::new();
|
||||||
|
let level_1_rom = load_rom("1-chip8-logo.ch8");
|
||||||
|
x.load_bytes_to_memory(0x200, (&level_1_rom).into());
|
||||||
|
|
||||||
|
// run for 0x40 cycles
|
||||||
|
while x.num_cycles < 0x40 {
|
||||||
|
x.step_system();
|
||||||
|
}
|
||||||
|
assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_level_1_test.asc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn level2_test() {
|
||||||
|
let mut x = Chip8Computer::new();
|
||||||
|
// Load the IBM rom and run it.
|
||||||
|
// it takes 39 cycles to get to the end so lets run it 40.
|
||||||
|
|
||||||
|
let test_rom_to_run = load_rom("2-ibm-logo.ch8");
|
||||||
|
x.load_bytes_to_memory(0x200, (&test_rom_to_run).into());
|
||||||
|
|
||||||
|
for i in 0..40 {
|
||||||
|
x.step_system();
|
||||||
|
}
|
||||||
|
// ...then verify that the current video memory of the chip-8
|
||||||
|
// simulator matches what we expect it to be
|
||||||
|
|
||||||
|
assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_ibm_rom_output.asc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn level3_test() {
|
||||||
|
let mut x = Chip8Computer::new();
|
||||||
|
|
||||||
|
x.load_bytes_to_memory(
|
||||||
|
0x200, (&load_rom("3-corax+.ch8")).into()
|
||||||
|
);
|
||||||
|
for i in 0..0x180 {
|
||||||
|
x.step_system();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_corax_plus.asc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rps_test() {
|
||||||
|
let mut x = Chip8Computer::new();
|
||||||
|
x.load_bytes_to_memory(0x200, &load_rom("RPS.ch8").into());
|
||||||
|
for i in 0..0xF0 {
|
||||||
|
x.step_system();
|
||||||
|
}
|
||||||
|
assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_rps_stage1.asc"));
|
||||||
|
x.keypad.push_key(0x01);
|
||||||
|
for i in 0..0x200 {
|
||||||
|
x.step_system();
|
||||||
|
}
|
||||||
|
assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_rps_stage2.asc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn level4_test() {
|
||||||
|
// flags
|
||||||
|
let mut x = Chip8Computer::new();
|
||||||
|
x.load_bytes_to_memory(0x200, &load_rom("4-flags.ch8").into());
|
||||||
|
for i in 0..0x400 {
|
||||||
|
x.step_system();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_flags.asc"));
|
||||||
|
}
|
||||||
|
|||||||
@ -5,5 +5,5 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gemma = { path = "../gemma" }
|
gemma = { path = "../gemma" }
|
||||||
egui = "0.29.1"
|
egui.workspace = true
|
||||||
eframe = "0.29.1"
|
eframe.workspace = true
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use std::time::Instant;
|
||||||
use crate::support::gemma_egui_support::GemmaEguiSupport;
|
use crate::support::gemma_egui_support::GemmaEguiSupport;
|
||||||
use crate::support::gemma_egui_state::GemmaEGuiState;
|
use crate::support::gemma_egui_state::GemmaEGuiState;
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
@ -16,26 +17,46 @@ fn main() -> eframe::Result {
|
|||||||
|
|
||||||
let mut state = GemmaEGuiState::default();
|
let mut state = GemmaEGuiState::default();
|
||||||
let mut computer = Chip8Computer::new();
|
let mut computer = Chip8Computer::new();
|
||||||
|
let mut cps_counter = 0;
|
||||||
|
let mut last_counter_update = Instant::now();
|
||||||
|
let cps_refresh = 5;
|
||||||
|
|
||||||
|
let mut last_frame_start = Instant::now();
|
||||||
|
|
||||||
eframe::run_simple_native("EGUI Emma", options, move |ctx, _frame| {
|
eframe::run_simple_native("EGUI Emma", options, move |ctx, _frame| {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
if state.display_video {
|
let should_render_frame = Instant::now().duration_since(last_frame_start).as_millis() >= 10;
|
||||||
GemmaEguiSupport::video_view(&computer, ui);
|
|
||||||
|
if should_render_frame {
|
||||||
|
last_frame_start = Instant::now();
|
||||||
|
if state.display_video {
|
||||||
|
GemmaEguiSupport::video_view(&computer, ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.heading("EGUI Gemma");
|
||||||
|
GemmaEguiSupport::controls_view(&mut computer, &mut state, ui);
|
||||||
|
|
||||||
|
|
||||||
|
if state.display_memory {
|
||||||
|
GemmaEguiSupport::memory_view(&computer, &mut state, ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.display_registers {
|
||||||
|
GemmaEguiSupport::registers_view(&computer, ui);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.heading("EGUI Gemma");
|
|
||||||
GemmaEguiSupport::controls_view(&mut computer, &mut state, ui);
|
|
||||||
|
|
||||||
|
|
||||||
if state.display_memory {
|
|
||||||
GemmaEguiSupport::memory_view(&computer, &mut state, ui);
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.display_registers {
|
|
||||||
GemmaEguiSupport::registers_view(&computer, ui);
|
|
||||||
}
|
|
||||||
if state.is_running {
|
if state.is_running {
|
||||||
computer.step_system();
|
computer.step_system();
|
||||||
|
cps_counter += 1;
|
||||||
|
}
|
||||||
|
let rt = Instant::now();
|
||||||
|
let ms = rt.duration_since(last_counter_update).as_millis();
|
||||||
|
if ms > 5000 {
|
||||||
|
let cps = (cps_counter * 1000) / ms;
|
||||||
|
println!("Executing {cps} instructions per 5s ({ms}/{cps_counter})");
|
||||||
|
last_counter_update = rt;
|
||||||
|
cps_counter = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,7 +5,8 @@ pub struct GemmaEGuiState {
|
|||||||
pub display_registers: bool,
|
pub display_registers: bool,
|
||||||
pub memory_view_min: i32,
|
pub memory_view_min: i32,
|
||||||
pub memory_view_max: i32,
|
pub memory_view_max: i32,
|
||||||
pub is_running: bool
|
pub is_running: bool,
|
||||||
|
pub selected_rom_filename: String
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GemmaEGuiState {
|
impl Default for GemmaEGuiState {
|
||||||
@ -16,7 +17,8 @@ impl Default for GemmaEGuiState {
|
|||||||
display_registers: true,
|
display_registers: true,
|
||||||
memory_view_min: 0x00,
|
memory_view_min: 0x00,
|
||||||
memory_view_max: 0x100,
|
memory_view_max: 0x100,
|
||||||
is_running: false
|
is_running: false,
|
||||||
|
selected_rom_filename: String::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,10 +3,12 @@ use std::ops::Index;
|
|||||||
use std::path::{Display, PathBuf};
|
use std::path::{Display, PathBuf};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use egui::{Align, Color32, ComboBox, Direction, Pos2};
|
use egui::{Align, Color32, ComboBox, Direction, Pos2, Response, TextBuffer};
|
||||||
|
use egui::accesskit::Role::ListBox;
|
||||||
use egui::Rect;
|
use egui::Rect;
|
||||||
use egui::Vec2;
|
use egui::Vec2;
|
||||||
use egui::Ui;
|
use egui::Ui;
|
||||||
|
use egui::WidgetType::SelectableLabel;
|
||||||
use crate::support::gemma_egui_state::GemmaEGuiState;
|
use crate::support::gemma_egui_state::GemmaEGuiState;
|
||||||
use crate::Chip8Computer;
|
use crate::Chip8Computer;
|
||||||
|
|
||||||
@ -17,20 +19,29 @@ pub struct EGuiFileList {}
|
|||||||
impl EGuiFileList {
|
impl EGuiFileList {
|
||||||
pub fn display_path(root: PathBuf, selected_filename: &mut String, ui: &mut Ui) {
|
pub fn display_path(root: PathBuf, selected_filename: &mut String, ui: &mut Ui) {
|
||||||
let mut working_filename = selected_filename.clone();
|
let mut working_filename = selected_filename.clone();
|
||||||
ui.label(format!("Displaying {}", root.to_str().unwrap_or("Unable to Load Path")));
|
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
|
||||||
|
// ui.label(format!("Displaying {}", root.to_str().unwrap_or("Unable to Load Path")));
|
||||||
|
ComboBox::from_label("Select ROM")
|
||||||
|
.selected_text(selected_filename.clone())
|
||||||
|
.show_ui(ui, |ui| {
|
||||||
|
|
||||||
ComboBox::from_label("Choose an option")
|
let mut sorted_options = vec![];
|
||||||
.selected_text(selected_filename.clone())
|
for option in read_dir(root.as_path()).unwrap() {
|
||||||
.show_ui(ui, |ui| {
|
let to_push = option.unwrap().file_name().into_string().unwrap_or( String::new());
|
||||||
for option in read_dir(root.as_path()).unwrap() {
|
sorted_options.push(to_push);
|
||||||
|
}
|
||||||
|
|
||||||
|
sorted_options.sort();
|
||||||
|
for item in sorted_options {
|
||||||
// Add each option to the ComboBox
|
// Add each option to the ComboBox
|
||||||
let mut label = option.unwrap().file_name();
|
if ui.selectable_label(selected_filename.eq(&item.as_str()), item.clone()).clicked()
|
||||||
ui.selectable_value(selected_filename, selected_filename.clone(), label.into_string().unwrap());
|
{
|
||||||
}
|
*selected_filename = item;
|
||||||
});
|
}
|
||||||
|
}
|
||||||
// Display the selected option
|
});
|
||||||
ui.label(format!("Selected value: {}", selected_filename));
|
// Display the selected option
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,34 +50,33 @@ pub struct GemmaEguiSupport {}
|
|||||||
impl GemmaEguiSupport {
|
impl GemmaEguiSupport {
|
||||||
pub fn controls_view(mut system: &mut Chip8Computer, state: &mut GemmaEGuiState, ui: &mut Ui) {
|
pub fn controls_view(mut system: &mut Chip8Computer, state: &mut GemmaEGuiState, ui: &mut Ui) {
|
||||||
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
|
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
|
||||||
if ui.button("Start").clicked() {
|
if ui.button("Start").clicked() {
|
||||||
println!("Start");
|
println!("Start");
|
||||||
state.is_running = true;
|
state.is_running = true;
|
||||||
|
}
|
||||||
|
if ui.button("Step").clicked() {
|
||||||
|
system.step_system();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
if ui.button("Stop").clicked() {
|
||||||
if ui.button("Step").clicked() {
|
println!("STOP");
|
||||||
system.step_system();
|
state.is_running = false;
|
||||||
}
|
}
|
||||||
|
if ui.button("Reset").clicked() {
|
||||||
|
system.reset();
|
||||||
|
state.is_running = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if ui.button("Stop").clicked() {
|
if ui.button(format!("Load {}", state.selected_rom_filename)).clicked() {
|
||||||
println!("STOP");
|
|
||||||
state.is_running = false;
|
|
||||||
}
|
|
||||||
if ui.button("Reset").clicked() {
|
|
||||||
system.reset();
|
|
||||||
system.video_memory.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ui.button("Load initial rom").clicked() {
|
|
||||||
println!("CLICK ON LOAD");
|
|
||||||
// load the bin...
|
// load the bin...
|
||||||
let read_bin = std::fs::read(PathBuf::from("resources/roms/1-chip8-logo.ch8")).unwrap();
|
let read_bin = std::fs::read(PathBuf::from(format!("resources/roms/{}", state.selected_rom_filename))).unwrap();
|
||||||
// ...then feed the system.
|
// ...then feed the system.
|
||||||
system.load_bytes_to_memory(0x200, &read_bin);
|
system.load_bytes_to_memory(0x200, &read_bin);
|
||||||
|
println!("Loaded {}", state.selected_rom_filename);
|
||||||
}
|
}
|
||||||
let mut target = String::new();
|
EGuiFileList::display_path(PathBuf::from("resources/roms"), &mut state.selected_rom_filename, ui);
|
||||||
EGuiFileList::display_path(PathBuf::from("resources/roms"), &mut target, ui);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
ui.with_layout(egui::Layout::left_to_right(Align::TOP), |ui| {
|
ui.with_layout(egui::Layout::left_to_right(Align::TOP), |ui| {
|
||||||
|
|||||||
@ -5,16 +5,15 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gemma = { path = "../gemma" }
|
gemma = { path = "../gemma" }
|
||||||
glium = { version = "0.34.0", default-features = true }
|
glium.workspace = true
|
||||||
image = "0.23"
|
image.workspace = true
|
||||||
imgui = { version ="0.12.0", features = ["tables-api"] }
|
imgui.workspace = true
|
||||||
imgui-glium-renderer = { version = "0.12.0" }
|
imgui-glium-renderer.workspace = true
|
||||||
imgui-winit-support = { version = "0.12.0" }
|
imgui-winit-support.workspace = true
|
||||||
winit = { version = "0.27", features = ["x11", "mint"] }
|
winit.workspace = true
|
||||||
pretty_env_logger = "0.5.0"
|
pretty_env_logger.workspace = true
|
||||||
copypasta = "0.8"
|
copypasta.workspace = true
|
||||||
rand = "0.9.0-alpha.2"
|
rand.workspace = true
|
||||||
log = "0.4.22"
|
log.workspace = true
|
||||||
beep = "0.3.0"
|
chrono.workspace = true
|
||||||
chrono = "0.4.38"
|
dimensioned.workspace = true
|
||||||
dimensioned = "0.8.0"
|
|
||||||
|
|||||||
@ -100,6 +100,9 @@ impl GemmaImguiSupport {
|
|||||||
ui.window("!!!! CONTROLS !!!!")
|
ui.window("!!!! CONTROLS !!!!")
|
||||||
.size([345.0, 200.0], Condition::FirstUseEver)
|
.size([345.0, 200.0], Condition::FirstUseEver)
|
||||||
.build(|| {
|
.build(|| {
|
||||||
|
/* System Step Counter */
|
||||||
|
ui.text(format!("Step {:04x}", system_to_control.num_cycles).as_str());
|
||||||
|
|
||||||
/* ROM Lister */
|
/* ROM Lister */
|
||||||
let new_filename = GuiFileList::display_path(PathBuf::from("resources/roms"), &gui_state.filename_to_load, ui);
|
let new_filename = GuiFileList::display_path(PathBuf::from("resources/roms"), &gui_state.filename_to_load, ui);
|
||||||
if !new_filename.is_empty() {
|
if !new_filename.is_empty() {
|
||||||
@ -137,7 +140,7 @@ impl GemmaImguiSupport {
|
|||||||
*system_to_control = Chip8Computer::new();
|
*system_to_control = Chip8Computer::new();
|
||||||
}
|
}
|
||||||
if ui.button("Dump Video Memory") {
|
if ui.button("Dump Video Memory") {
|
||||||
debug!("{}", system_to_control.dump_video_to_string());
|
println!("{}", system_to_control.dump_video_to_string());
|
||||||
}
|
}
|
||||||
ui.same_line();
|
ui.same_line();
|
||||||
if ui.button("Dump Keypad State") {
|
if ui.button("Dump Keypad State") {
|
||||||
|
|||||||
7
gemmatelnet/Cargo.toml
Normal file
7
gemmatelnet/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "gemmatelnet"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
gemma = { path = "../gemma" }
|
||||||
3
gemmatelnet/src/bin/gemmatelnetd.rs
Normal file
3
gemmatelnet/src/bin/gemmatelnetd.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("Taxation is Theft");
|
||||||
|
}
|
||||||
BIN
resources/roms/3dviprmaze-vip.ch8
Normal file
BIN
resources/roms/3dviprmaze-vip.ch8
Normal file
Binary file not shown.
32
resources/test/gemma_integration_corax_plus.asc
Normal file
32
resources/test/gemma_integration_corax_plus.asc
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
*** * * *** * * *** * * *** ***
|
||||||
|
** * * * * * * * *** *** * * * ** * *
|
||||||
|
* * * ** ** * * ** * * * ** ** * **
|
||||||
|
*** * * * *** * * * *** * * * ** *
|
||||||
|
|
||||||
|
* * * * *** *** *** *** *** ***
|
||||||
|
*** * * * * * ** * * *** ** * * * ** * *
|
||||||
|
* * * ** * * * ** * * * ** ** * **
|
||||||
|
* * * * *** *** * *** ** * * *** *
|
||||||
|
|
||||||
|
*** * * *** *** *** *** *** ***
|
||||||
|
** * * * *** * * * * *** * * * * ** * *
|
||||||
|
* * * ** * * * * ** * * * ** ** * **
|
||||||
|
** * * * *** *** * *** * * * *** *
|
||||||
|
|
||||||
|
*** * * *** ** *** ** * *
|
||||||
|
* * * * *** * * * *** * * * * * * * *
|
||||||
|
* * * ** * * * ** * * *** ** * * * * **
|
||||||
|
* * * * *** *** * *** *** * * * * *
|
||||||
|
|
||||||
|
*** * * *** *** *** ***
|
||||||
|
*** * * * *** * * * *** ** * *
|
||||||
|
* * * ** * * ** ** * * * **
|
||||||
|
** * * * *** *** * *** *** *
|
||||||
|
|
||||||
|
** * * *** *** *** ** * * ***
|
||||||
|
* * * * *** ** * * * * * * * * *** *
|
||||||
|
* * * ** * * * ** ** *** ** * * * **
|
||||||
|
*** * * * *** *** * * *** * * * * ***
|
||||||
|
|
||||||
|
|
||||||
32
resources/test/gemma_integration_flags.asc
Normal file
32
resources/test/gemma_integration_flags.asc
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
* * * ** ** * * ** ***
|
||||||
|
*** * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* * *** ** ** * * ** ** ** ** ** ** **
|
||||||
|
* * * * * * * *** * * * *** * * *
|
||||||
|
|
||||||
|
*** * * ***
|
||||||
|
** * * * * * * *** * * * * * * * * ** * * * * * * * *
|
||||||
|
* ** ** ** * ** ** ** ** * ** ** ** **
|
||||||
|
*** * * * * * * * * ** * * * *
|
||||||
|
|
||||||
|
*** *** ***
|
||||||
|
* * * * * * * * * * * * * * * * ** * * * * * *
|
||||||
|
*** ** ** ** * ** ** ** ** * ** ** **
|
||||||
|
*** * * * * * * * * *** * * *
|
||||||
|
|
||||||
|
|
||||||
|
*** * ** ** * * * * ***
|
||||||
|
* * * * * * * * * *** * * * * * * * * ** * * * * * * * *
|
||||||
|
* *** ** ** * * ** ** ** ** * ** ** ** **
|
||||||
|
*** * * * * * * * * * * * * ** * * * *
|
||||||
|
|
||||||
|
*** *** ***
|
||||||
|
* * * * * * * * * * * * * * * * ** * * * * * *
|
||||||
|
*** ** ** ** * ** ** ** ** * ** ** **
|
||||||
|
*** * * * * * * * * *** * * *
|
||||||
|
|
||||||
|
|
||||||
|
*** *** * * *** ** *** *** * * ***
|
||||||
|
* * * *** ** * * * ** * * * * * * *** *
|
||||||
|
* * * * * * ** ** * ** ** * * * **
|
||||||
|
*** * * * *** * * * *** * * * * * ***
|
||||||
|
|
||||||
32
resources/test/gemma_integration_level_1_test.asc
Normal file
32
resources/test/gemma_integration_level_1_test.asc
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
***** * * **
|
||||||
|
* ** * ** *** *** * * ** *
|
||||||
|
* * * * * * * * * * * * * *
|
||||||
|
* * * * **** * * * * * * *
|
||||||
|
* * * * * * * * * * * *
|
||||||
|
* * * * *** * * *** *** **
|
||||||
|
|
||||||
|
|
||||||
|
***** ** ** ***** *******
|
||||||
|
******* *** *** ******* *** ***
|
||||||
|
*** ** *** *** *** *** *** **
|
||||||
|
*** *** *** ** *** **
|
||||||
|
*** * * *** ** *** ** *** **
|
||||||
|
*** ****** *** *** ** *** **
|
||||||
|
*** * * ******* *** *** ** **** ******
|
||||||
|
*** *** *** *** *** *** *** **** *** ***
|
||||||
|
*** *** ** *** ******* *** ***
|
||||||
|
*** *** ** *** ****** *** **
|
||||||
|
*** *** ** *** *** *** **
|
||||||
|
*** *** ** *** *** * * *** *** **
|
||||||
|
*** ** *** ** *** *** *** * **** ***
|
||||||
|
******* *** ** *** *** * ** *********
|
||||||
|
***** *** ** *** *** * * *** *******
|
||||||
|
|
||||||
|
|
||||||
|
*** ** ** * ** * * **
|
||||||
|
* * * * *** * * * *** * *
|
||||||
|
* **** * * * * * * * ****
|
||||||
|
* * * * * * * * * *
|
||||||
|
* *** ** ** ** *** * ** ***
|
||||||
|
|
||||||
32
resources/test/gemma_integration_rps_stage1.asc
Normal file
32
resources/test/gemma_integration_rps_stage1.asc
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
****************************************************************
|
||||||
|
****************************************************************
|
||||||
|
****************************************************************
|
||||||
|
******************************* *******************************
|
||||||
|
****************************** ******************************
|
||||||
|
************* ************** ************** *************
|
||||||
|
************** ********** ********** **************
|
||||||
|
************* * ***** ***** * *************
|
||||||
|
*************** ***************
|
||||||
|
************** * *** *** * **************
|
||||||
|
*************** * ****** ******* ****** * ***************
|
||||||
|
** ******* ******** ******* **
|
||||||
|
** *** ******* *** *** *** * *** **
|
||||||
|
*** *** *** *** *** ** *** *** ***
|
||||||
|
****** **** *** *** *** *** **** ** **** ******
|
||||||
|
********* ****** ******* ******** *********
|
||||||
|
************* ****** ****** ******** *************
|
||||||
|
************ ******* *** *** ************
|
||||||
|
********* *** **** *** ****** *********
|
||||||
|
***** *** *** *** ******* *****
|
||||||
|
** *** ** *** ***** **
|
||||||
|
** ************** * * ** ************** **
|
||||||
|
*** * * ***
|
||||||
|
*************** * * ***************
|
||||||
|
************** **** * * **** **************
|
||||||
|
************** *** * * * * *** **************
|
||||||
|
************* *** ****** * * ****** *** *************
|
||||||
|
*************** ********** * * ********** ***************
|
||||||
|
***************************** * * *****************************
|
||||||
|
****************************** ** ******************************
|
||||||
|
******************************* *******************************
|
||||||
|
****************************************************************
|
||||||
32
resources/test/gemma_integration_rps_stage2.asc
Normal file
32
resources/test/gemma_integration_rps_stage2.asc
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
****************************************************************
|
||||||
|
**************** * * ***** * * * *** *****************
|
||||||
|
**************** * * * * ****** * *** *** * *****************
|
||||||
|
**************** ** *** ***** * * ** *** *****************
|
||||||
|
**************** * * *** ***** * * * * *******************
|
||||||
|
****************************************************************
|
||||||
|
***** ************ ************ *********** * ********* * ****
|
||||||
|
**** * ********* * ********* * ******** * ******* * ***
|
||||||
|
*** * ******* * ******* * ****** * ***** * **
|
||||||
|
** * ***** * ***** * **** * *** * *
|
||||||
|
* * *** * *** * ** * * *
|
||||||
|
* * * * * ** *
|
||||||
|
* * * **** ** **
|
||||||
|
**** * ** * * * *
|
||||||
|
* * * *** ** **
|
||||||
|
* * * * * ****
|
||||||
|
* * ** * * **
|
||||||
|
* * * * * * ** **
|
||||||
|
* * ** * * ** **
|
||||||
|
* * ** ****** * *
|
||||||
|
****
|
||||||
|
|
||||||
|
******** ******** ********
|
||||||
|
* * * * * *
|
||||||
|
* **** * * * * * * **** *
|
||||||
|
* * * * ** * * * *
|
||||||
|
* * * * ** * * * *
|
||||||
|
* **** * * * * * * **** *
|
||||||
|
* * * * * *
|
||||||
|
******** ******** ********
|
||||||
|
|
||||||
|
****************************************************************
|
||||||
Loading…
x
Reference in New Issue
Block a user