weekend work
This commit is contained in:
@@ -10,11 +10,11 @@ rand.workspace = true
|
||||
log.workspace = true
|
||||
chrono.workspace = true
|
||||
dimensioned.workspace = true
|
||||
clap.workspace = true
|
||||
imgui-glium-renderer = { version = "0.12.0" }
|
||||
imgui-winit-support = { version = "0.12.0" }
|
||||
glium = { version = "0.34.0" }
|
||||
image = { version = "0.23" }
|
||||
imgui = { version = "0.12.0" }
|
||||
winit = { version = "0.27", features = ["x11", "mint"]}
|
||||
winit = { version = "0.27", features = ["x11", "mint"] }
|
||||
copypasta = { version = "0.8" }
|
||||
clap = { version = "4.5.20", features = ["derive"] }
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::default::Default;
|
||||
use std::time::Instant;
|
||||
use clap::{Parser, Subcommand};
|
||||
use gemma::chip8::computer_manager::Chip8ComputerManager;
|
||||
use std::path::Path;
|
||||
use std::time::Instant;
|
||||
use std::{default::Default, path::PathBuf};
|
||||
use support::{emmagui_support::GemmaImguiSupport, ui_state::ImGuiUiState};
|
||||
|
||||
|
||||
mod support;
|
||||
|
||||
/// Keypad Mappings for my Linux box
|
||||
@@ -12,16 +13,39 @@ mod support;
|
||||
/// 7 8 9 E
|
||||
/// A 0 B F
|
||||
|
||||
const LIN_KEYS: [(u16, u8); 0x10] = [(537, 0x01),(538, 0x02),(539, 0x03),(540, 0x0c),
|
||||
(562, 0x04),(568, 0x05),(550, 0x06),(563, 0x0d),
|
||||
(546, 7),(564, 8),(549, 9),(551, 0xe),
|
||||
(571, 0xa),(569, 0),(548, 0xb),(567, 0xf)];
|
||||
const LIN_KEYS: [(u16, u8); 0x10] = [
|
||||
(537, 0x01),
|
||||
(538, 0x02),
|
||||
(539, 0x03),
|
||||
(540, 0x0c),
|
||||
(562, 0x04),
|
||||
(568, 0x05),
|
||||
(550, 0x06),
|
||||
(563, 0x0d),
|
||||
(546, 0x7),
|
||||
(564, 0x8),
|
||||
(549, 0x9),
|
||||
(551, 0xe),
|
||||
(571, 0xa),
|
||||
(569, 0x0),
|
||||
(548, 0xb),
|
||||
(567, 0xf),
|
||||
];
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct GemmaImguiCLIOptions {
|
||||
roms_directory: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
pretty_env_logger::init();
|
||||
|
||||
let cli_options = GemmaImguiCLIOptions::parse();
|
||||
|
||||
let mut system = Chip8ComputerManager::default();
|
||||
let mut ui_state = ImGuiUiState::default();
|
||||
println!("GOT A ROMS_DIRECTORY => [{:?}]", cli_options.roms_directory);
|
||||
let mut ui_state = ImGuiUiState::new(cli_options.roms_directory);
|
||||
|
||||
support::simple_init(file!(), move |_, ui| {
|
||||
let current_time = Instant::now();
|
||||
@@ -53,14 +77,21 @@ fn main() {
|
||||
|
||||
let target_ms = ui_state.frame_time;
|
||||
let loop_start_time = Instant::now();
|
||||
while Instant::now().duration_since(current_time).as_millis() < target_ms as u128 && num_cycles < ui_state.target_ips {
|
||||
while Instant::now().duration_since(current_time).as_millis() < target_ms as u128
|
||||
&& num_cycles < ui_state.target_ips
|
||||
{
|
||||
if system.tick() {
|
||||
num_cycles += 1;
|
||||
}
|
||||
}
|
||||
let cycles_time = Instant::now().duration_since(loop_start_time);
|
||||
if num_cycles > 0 {
|
||||
println!("Ran for {}ms and executed {}/{} cycles.", cycles_time.as_millis(), num_cycles, ui_state.target_ips);
|
||||
println!(
|
||||
"Ran for {}ms and executed {}/{} cycles.",
|
||||
cycles_time.as_millis(),
|
||||
num_cycles,
|
||||
ui_state.target_ips
|
||||
);
|
||||
}
|
||||
// GUI Parts
|
||||
if ui_state.show_video {
|
||||
@@ -75,7 +106,12 @@ fn main() {
|
||||
|
||||
if ui_state.show_memory {
|
||||
let active_instruction = system.state().registers.peek_pc();
|
||||
GemmaImguiSupport::hex_memory_display(system.state().memory, (0x100, 0x10), active_instruction as i16, ui);
|
||||
GemmaImguiSupport::hex_memory_display(
|
||||
system.state().memory.clone(),
|
||||
(0x100, 0x10),
|
||||
active_instruction as i16,
|
||||
ui,
|
||||
);
|
||||
}
|
||||
|
||||
if ui_state.show_keypad {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use gemma::constants::CHIP8_KEYBOARD;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
use imgui::{CollapsingHeader, Condition, ImColor32, Ui};
|
||||
use log::debug;
|
||||
use crate::support::gui_file_list::GuiFileList;
|
||||
use crate::ImGuiUiState;
|
||||
use gemma::chip8::computer::Chip8Computer;
|
||||
use gemma::chip8::computer_manager::Chip8ComputerManager;
|
||||
use gemma::chip8::computer_manager::ManagerDumpables::{Keyboard, Registers, Video};
|
||||
use gemma::chip8::system_memory::Chip8SystemMemory;
|
||||
use crate::ImGuiUiState;
|
||||
use crate::support::gui_file_list::GuiFileList;
|
||||
use gemma::constants::CHIP8_KEYBOARD;
|
||||
use imgui::{CollapsingHeader, Condition, ImColor32, Ui};
|
||||
use log::debug;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
const ROM_ROOT: &str = "resources/roms";
|
||||
|
||||
@@ -55,7 +55,10 @@ impl GemmaImguiSupport {
|
||||
for current_column in 0..=width {
|
||||
let x_offset = origin[0] as i32 + (current_column * cell_width);
|
||||
let current_origin = [x_offset as f32, y_offset as f32];
|
||||
let current_limit = [(x_offset + cell_width) as f32, (y_offset + cell_height) as f32];
|
||||
let current_limit = [
|
||||
(x_offset + cell_width) as f32,
|
||||
(y_offset + cell_height) as f32,
|
||||
];
|
||||
let memory_offset = (current_row * width + current_column) as u16;
|
||||
let to_render = system_to_control.video_memory.peek(memory_offset);
|
||||
let color: ImColor32 = if to_render {
|
||||
@@ -63,7 +66,14 @@ impl GemmaImguiSupport {
|
||||
} else {
|
||||
gui_state.off_colour
|
||||
};
|
||||
fg.add_rect_filled_multicolor(current_origin, current_limit, color, color, color, color);
|
||||
fg.add_rect_filled_multicolor(
|
||||
current_origin,
|
||||
current_limit,
|
||||
color,
|
||||
color,
|
||||
color,
|
||||
color,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -72,7 +82,10 @@ impl GemmaImguiSupport {
|
||||
for current_column in 0..width {
|
||||
let x_offset = origin[0] as i32 + (current_column * cell_width);
|
||||
let current_origin = [x_offset as f32, y_offset as f32];
|
||||
let current_limit = [(x_offset + cell_width) as f32, (y_offset + cell_height) as f32];
|
||||
let current_limit = [
|
||||
(x_offset + cell_width) as f32,
|
||||
(y_offset + cell_height) as f32,
|
||||
];
|
||||
let memory_offset = (current_row * width + current_column) as u16;
|
||||
let to_render = system_to_control.video_memory.peek(memory_offset);
|
||||
let color: ImColor32 = if to_render {
|
||||
@@ -80,12 +93,23 @@ impl GemmaImguiSupport {
|
||||
} else {
|
||||
gui_state.off_colour
|
||||
};
|
||||
fg.add_rect_filled_multicolor(current_origin, current_limit, color, color, color, color);
|
||||
fg.add_rect_filled_multicolor(
|
||||
current_origin,
|
||||
current_limit,
|
||||
color,
|
||||
color,
|
||||
color,
|
||||
color,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn system_controls(system_to_control: &mut Chip8ComputerManager, gui_state: &mut ImGuiUiState, ui: &Ui) {
|
||||
pub fn system_controls(
|
||||
system_to_control: &mut Chip8ComputerManager,
|
||||
gui_state: &mut ImGuiUiState,
|
||||
ui: &Ui,
|
||||
) {
|
||||
// let mut state: Chip8Computer = system_to_control;
|
||||
ui.window("!!!! CONTROLS !!!!")
|
||||
.position([100.0, 640.0], Condition::FirstUseEver)
|
||||
@@ -95,19 +119,35 @@ impl GemmaImguiSupport {
|
||||
|
||||
/* ROM Lister */
|
||||
if CollapsingHeader::new("Roms").build(ui) {
|
||||
let new_filename = GuiFileList::display_path(PathBuf::from(ROM_ROOT), &gui_state.filename_to_load, ui);
|
||||
let new_filename = GuiFileList::display_path(
|
||||
gui_state.roms_root_path.clone(),
|
||||
&gui_state.filename_to_load,
|
||||
ui,
|
||||
);
|
||||
if !new_filename.is_empty() {
|
||||
if new_filename != gui_state.filename_to_load {
|
||||
debug!("NEW FILENAME SELECTED -> {new_filename}");
|
||||
gui_state.filename_to_load = new_filename;
|
||||
}
|
||||
if ui.button("Load Program") {
|
||||
let mut buffer = Vec::new();
|
||||
debug!("PREPARING TO LOAD {}", gui_state.filename_to_load);
|
||||
// let mut input_file = File::open(Path::new("./1-chip8-logo.ch8")).expect("put 1-chip8-logo.ch8 in this directory");
|
||||
let mut input_file = File::open(Path::new(&(ROM_ROOT.to_string() + "/" + &gui_state.filename_to_load))).expect("put 1-chip8-logo.ch8 in this directory");
|
||||
input_file.read_to_end(&mut buffer).expect("unable to read file");
|
||||
system_to_control.load_new_program_to_system_memory((&*buffer).into());
|
||||
let mut buffer: Vec<u8> = Vec::new();
|
||||
let full_name = format!(
|
||||
"{}/{}",
|
||||
gui_state
|
||||
.roms_root_path
|
||||
.clone()
|
||||
.as_os_str()
|
||||
.to_string_lossy(),
|
||||
gui_state.filename_to_load.to_string()
|
||||
);
|
||||
debug!("PREPARING TO LOAD {}", full_name);
|
||||
|
||||
let input_file = File::open(Path::new(&full_name));
|
||||
input_file
|
||||
.unwrap()
|
||||
.read_to_end(&mut buffer)
|
||||
.expect("Unable to read rom.");
|
||||
system_to_control.load_new_program_to_system_memory(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,7 +156,7 @@ impl GemmaImguiSupport {
|
||||
// if the system has no program loaded hide the buttons.
|
||||
let bytes: [u8; 2] = [
|
||||
system_to_control.state().memory.peek(0x200),
|
||||
system_to_control.state().memory.peek(0x201)
|
||||
system_to_control.state().memory.peek(0x201),
|
||||
];
|
||||
let mut show_buttons = bytes[0] != 0 || bytes[1] == 0xe0;
|
||||
|
||||
@@ -158,7 +198,8 @@ impl GemmaImguiSupport {
|
||||
ui.checkbox("Show Registers", &mut gui_state.show_registers);
|
||||
ui.same_line();
|
||||
ui.checkbox("Show Keypad", &mut gui_state.show_keypad);
|
||||
ui.input_int("Target IPS", &mut gui_state.target_ips).build();
|
||||
ui.input_int("Target IPS", &mut gui_state.target_ips)
|
||||
.build();
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -185,7 +226,12 @@ impl GemmaImguiSupport {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn hex_memory_display(bytes: Chip8SystemMemory, position: (i32, i32), active: i16, ui: &Ui) {
|
||||
pub fn hex_memory_display(
|
||||
bytes: Chip8SystemMemory,
|
||||
position: (i32, i32),
|
||||
active: i16,
|
||||
ui: &Ui,
|
||||
) {
|
||||
let rows = position.0;
|
||||
let cols = position.1;
|
||||
ui.window("System Memory")
|
||||
@@ -207,16 +253,22 @@ impl GemmaImguiSupport {
|
||||
y: text_location[1] + text_size[1],
|
||||
};
|
||||
|
||||
let hovering = ui.is_mouse_hovering_rect(text_location, [bounding_box.x, bounding_box.y]);
|
||||
let hovering = ui.is_mouse_hovering_rect(
|
||||
text_location,
|
||||
[bounding_box.x, bounding_box.y],
|
||||
);
|
||||
let is_active = data_offset == active as i32;
|
||||
|
||||
ui.text_colored(if hovering {
|
||||
[0., 1., 1., 1.]
|
||||
} else if is_active {
|
||||
[1., 0., 1., 1.]
|
||||
} else {
|
||||
[1., 1., 0., 1.]
|
||||
}, formatted_text.clone());
|
||||
ui.text_colored(
|
||||
if hovering {
|
||||
[0., 1., 1., 1.]
|
||||
} else if is_active {
|
||||
[1., 0., 1., 1.]
|
||||
} else {
|
||||
[1., 1., 0., 1.]
|
||||
},
|
||||
formatted_text.clone(),
|
||||
);
|
||||
|
||||
// if we are hovering show that at the bottom...
|
||||
if hovering {
|
||||
@@ -226,7 +278,12 @@ impl GemmaImguiSupport {
|
||||
|
||||
// Check if the left mouse button is clicked while hovering over the text
|
||||
if ui.is_mouse_clicked(imgui::MouseButton::Left) {
|
||||
debug!("Offset: [{}] [0x{:02x}] Value: [{}]", data_offset, data_offset, formatted_text.clone());
|
||||
debug!(
|
||||
"Offset: [{}] [0x{:02x}] Value: [{}]",
|
||||
data_offset,
|
||||
data_offset,
|
||||
formatted_text.clone()
|
||||
);
|
||||
// Perform any action here, e.g., call a function, trigger an event, etc.
|
||||
}
|
||||
}
|
||||
@@ -237,7 +294,10 @@ impl GemmaImguiSupport {
|
||||
}
|
||||
}
|
||||
}
|
||||
ui.text(format!("Offset 0x{:03x}", current_x_hover * cols + current_y_hover));
|
||||
ui.text(format!(
|
||||
"Offset 0x{:03x}",
|
||||
current_x_hover * cols + current_y_hover
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
use std::time::Instant;
|
||||
use imgui::ImColor32;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
|
||||
pub const ROMPATH_DEFAULT: &str = "resources/roms";
|
||||
|
||||
pub struct ImGuiUiState {
|
||||
pub show_registers: bool,
|
||||
@@ -12,7 +15,8 @@ pub struct ImGuiUiState {
|
||||
pub is_running: bool,
|
||||
pub frame_time: u32,
|
||||
pub last_frame_instant: Instant,
|
||||
pub target_ips: i32
|
||||
pub target_ips: i32,
|
||||
pub roms_root_path: PathBuf,
|
||||
}
|
||||
|
||||
impl Clone for ImGuiUiState {
|
||||
@@ -28,7 +32,9 @@ impl Clone for ImGuiUiState {
|
||||
is_running: self.is_running,
|
||||
frame_time: self.frame_time,
|
||||
last_frame_instant: self.last_frame_instant,
|
||||
target_ips: self.target_ips
|
||||
target_ips: self.target_ips,
|
||||
|
||||
roms_root_path: self.roms_root_path.to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +52,21 @@ impl Default for ImGuiUiState {
|
||||
is_running: false,
|
||||
frame_time: 16,
|
||||
last_frame_instant: Instant::now(),
|
||||
target_ips: 200000
|
||||
target_ips: 200000,
|
||||
roms_root_path: PathBuf::from(ROMPATH_DEFAULT),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ImGuiUiState {
|
||||
pub fn new(rom_path: Option<PathBuf>) -> ImGuiUiState {
|
||||
let unwrapped = rom_path.clone().unwrap_or(PathBuf::from(ROMPATH_DEFAULT));
|
||||
|
||||
println!("UNWRAPPED => [{:?}]", unwrapped);
|
||||
|
||||
ImGuiUiState {
|
||||
roms_root_path: rom_path.unwrap_or(PathBuf::from(ROMPATH_DEFAULT)),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user