fixes reset from exection completion
adds 'default.oc8' adds control window size to state for load/save of settings maybe? moves TestCompressionTool code into InstructionUtil remove gemmautil and moves into gemma
This commit is contained in:
@@ -74,7 +74,6 @@ fn main() {
|
||||
system.wait_for_instruction();
|
||||
} else {
|
||||
// do we need to release it?
|
||||
|
||||
if system.is_key_pressed(key_reg) {
|
||||
system.release_key(key_reg);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ use log::debug;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
use imgui::sys::ImGuiIO;
|
||||
use gemma::chip8::instructions::Chip8CpuInstructions;
|
||||
|
||||
const ROM_ROOT: &str = "resources/roms";
|
||||
|
||||
@@ -43,70 +45,186 @@ impl GemmaImguiSupport {
|
||||
pub fn video_display(system_to_control: &Chip8Computer, gui_state: &ImGuiUiState, ui: &Ui) {
|
||||
// draw area size
|
||||
let (width, height) = system_to_control.video_memory.get_resolution();
|
||||
let draw_area_size = ui.io().display_size;
|
||||
// println!("DRAW_AREA_SIZE = {}x{}", draw_area_size[0], draw_area_size[1]);
|
||||
let cell_width = ((draw_area_size[0] as i32 / width) * 6) / 10;
|
||||
let cell_height = ((draw_area_size[1] as i32 / height) * 6) / 10;
|
||||
ui.window("Video")
|
||||
.size([gui_state.video_window_size[0] as f32, gui_state.video_window_size[1] as f32], Condition::Once)
|
||||
.build(|| {
|
||||
let draw_area_size = ui.window_size();
|
||||
let draw_offset = ui.window_pos();
|
||||
// now lets move the draw_offset by 0,20 to get it off the window title bar
|
||||
let draw_offset = [draw_offset[0], draw_offset[1] + 20.0];
|
||||
// and reduce the draw area size by the same values. {}
|
||||
let draw_area_size = [draw_area_size[0], draw_area_size[1] - 20.0];
|
||||
// println!("DRAW_AREA_SIZE = {}x{}", draw_area_size[0], draw_area_size[1]);
|
||||
let cell_width = ((draw_area_size[0] as i32 / width));
|
||||
let cell_height = ((draw_area_size[1] as i32 / height));
|
||||
|
||||
let origin = ui.cursor_pos();
|
||||
let fg = ui.get_foreground_draw_list();
|
||||
if system_to_control.video_memory.is_highres() {
|
||||
// ui.text("High Def Video here");
|
||||
for current_row in 0..=height {
|
||||
let y_offset = origin[1] as i32 + (current_row * cell_height);
|
||||
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 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 {
|
||||
gui_state.on_colour
|
||||
} else {
|
||||
gui_state.off_colour
|
||||
};
|
||||
fg.add_rect_filled_multicolor(
|
||||
current_origin,
|
||||
current_limit,
|
||||
color,
|
||||
color,
|
||||
color,
|
||||
color,
|
||||
);
|
||||
let origin = draw_offset;
|
||||
let fg = ui.get_foreground_draw_list();
|
||||
for current_row in 0..height {
|
||||
let y_offset = origin[1] as i32 + (current_row * cell_height);
|
||||
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 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 {
|
||||
gui_state.on_colour
|
||||
} else {
|
||||
gui_state.off_colour
|
||||
};
|
||||
fg.add_rect_filled_multicolor(
|
||||
current_origin,
|
||||
current_limit,
|
||||
color,
|
||||
color,
|
||||
color,
|
||||
color,
|
||||
);
|
||||
}
|
||||
}
|
||||
}).expect("cant draw the video i guess");
|
||||
}
|
||||
|
||||
pub fn quirks_picker(system: &mut Chip8ComputerManager,
|
||||
ui: &Ui) {
|
||||
let selectors = [Chip8, SChipModern, XOChip];
|
||||
for current_selector in selectors {
|
||||
let mut working_selector =
|
||||
ui.selectable_config(current_selector.clone().to_string());
|
||||
match system.quirks_mode() {
|
||||
Chip8 => {
|
||||
working_selector = working_selector.selected(true);
|
||||
}
|
||||
SChipModern => {
|
||||
working_selector = working_selector.selected(true);
|
||||
}
|
||||
XOChip => {
|
||||
working_selector = working_selector.selected(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for current_row in 0..height {
|
||||
let y_offset = origin[1] as i32 + (current_row * cell_height);
|
||||
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 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 {
|
||||
gui_state.on_colour
|
||||
} else {
|
||||
gui_state.off_colour
|
||||
};
|
||||
fg.add_rect_filled_multicolor(
|
||||
current_origin,
|
||||
current_limit,
|
||||
color,
|
||||
color,
|
||||
color,
|
||||
color,
|
||||
if working_selector.build() {
|
||||
system.reset(current_selector);
|
||||
println!("CLICK ON {}", ¤t_selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn control_pickers(
|
||||
system: &mut Chip8ComputerManager,
|
||||
gui_state: &mut ImGuiUiState,
|
||||
ui: &Ui,
|
||||
) {
|
||||
if CollapsingHeader::new("Controls").build(ui) {
|
||||
// if the system has no program loaded hide the buttons.
|
||||
let bytes: [u8; 2] = [
|
||||
system.state().memory.peek(0x200),
|
||||
system.state().memory.peek(0x201),
|
||||
];
|
||||
let show_buttons = true; // bytes[0] != 0 || bytes[1] == 0xe0;
|
||||
|
||||
if show_buttons {
|
||||
if ui.button("Step") {
|
||||
system.step();
|
||||
};
|
||||
ui.same_line();
|
||||
if ui.button("Run") {
|
||||
system.start();
|
||||
}
|
||||
}
|
||||
ui.same_line();
|
||||
if ui.button("Stop") {
|
||||
system.stop();
|
||||
}
|
||||
ui.same_line();
|
||||
if ui.button("Reset") {
|
||||
system.reset(system.quirks_mode());
|
||||
}
|
||||
if ui.button("Dump Video Memory") {
|
||||
println!("{}", system.dump_to_string(Video));
|
||||
}
|
||||
ui.same_line();
|
||||
if ui.button("Dump Keypad State") {
|
||||
println!("{}", system.dump_to_string(Keyboard));
|
||||
}
|
||||
ui.same_line();
|
||||
if ui.button("Dump Registers") {
|
||||
println!("{}", system.dump_to_string(Registers));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn system_summary(
|
||||
system: &Chip8ComputerManager,
|
||||
ui: &Ui,
|
||||
) {
|
||||
/* System Step Counter */
|
||||
ui.text(format!("Step {:04x}", system.num_cycles()).as_str());
|
||||
ui.text(format!("Mode {}", system.quirks_mode()));
|
||||
}
|
||||
|
||||
fn rom_lister(
|
||||
system: &mut Chip8ComputerManager,
|
||||
gui_state: &mut ImGuiUiState,
|
||||
ui: &Ui,
|
||||
) {
|
||||
/* ROM Lister */
|
||||
if CollapsingHeader::new("Roms").build(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<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.load_new_program_to_system_memory(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn display_options(
|
||||
gui_state: &mut ImGuiUiState,
|
||||
ui: &Ui,
|
||||
) {
|
||||
if CollapsingHeader::new("Options").build(ui) {
|
||||
ui.checkbox("Show Memory", &mut gui_state.show_memory);
|
||||
ui.same_line();
|
||||
ui.checkbox("Show Video", &mut gui_state.show_video);
|
||||
ui.same_line();
|
||||
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();
|
||||
};
|
||||
}
|
||||
|
||||
pub fn system_controls(
|
||||
system_to_control: &mut Chip8ComputerManager,
|
||||
gui_state: &mut ImGuiUiState,
|
||||
@@ -116,114 +234,15 @@ impl GemmaImguiSupport {
|
||||
ui.window("!!!! CONTROLS !!!!")
|
||||
.position([100.0, 640.0], Condition::FirstUseEver)
|
||||
.build(|| {
|
||||
/* System Step Counter */
|
||||
ui.text(format!("Step {:04x}", system_to_control.num_cycles()).as_str());
|
||||
ui.text(format!("Mode {}", system_to_control.quirks_mode()));
|
||||
/* ROM Lister */
|
||||
if CollapsingHeader::new("Roms").build(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<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);
|
||||
GemmaImguiSupport::system_summary(system_to_control, ui);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
GemmaImguiSupport::rom_lister(system_to_control, gui_state, ui);
|
||||
|
||||
if CollapsingHeader::new("Controls").build(ui) {
|
||||
// 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),
|
||||
];
|
||||
let show_buttons = bytes[0] != 0 || bytes[1] == 0xe0;
|
||||
GemmaImguiSupport::control_pickers(system_to_control, gui_state, ui);
|
||||
|
||||
if show_buttons {
|
||||
if ui.button("Step") {
|
||||
system_to_control.step();
|
||||
};
|
||||
ui.same_line();
|
||||
if ui.button("Run") {
|
||||
system_to_control.start();
|
||||
}
|
||||
}
|
||||
ui.same_line();
|
||||
if ui.button("Stop") {
|
||||
system_to_control.stop();
|
||||
}
|
||||
ui.same_line();
|
||||
if ui.button("Reset") {
|
||||
system_to_control.reset(system_to_control.quirks_mode());
|
||||
}
|
||||
if ui.button("Dump Video Memory") {
|
||||
println!("{}", system_to_control.dump_to_string(Video));
|
||||
}
|
||||
ui.same_line();
|
||||
if ui.button("Dump Keypad State") {
|
||||
debug!("{}", system_to_control.dump_to_string(Keyboard));
|
||||
}
|
||||
ui.same_line();
|
||||
if ui.button("Dump Registers") {
|
||||
debug!("{}", system_to_control.dump_to_string(Registers));
|
||||
}
|
||||
}
|
||||
GemmaImguiSupport::display_options(gui_state, ui);
|
||||
|
||||
if CollapsingHeader::new("Options").build(ui) {
|
||||
ui.checkbox("Show Memory", &mut gui_state.show_memory);
|
||||
ui.same_line();
|
||||
ui.checkbox("Show Video", &mut gui_state.show_video);
|
||||
ui.same_line();
|
||||
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();
|
||||
};
|
||||
|
||||
let selectors = [Chip8, SChipModern, XOChip];
|
||||
for current_selector in selectors {
|
||||
let mut working_selector =
|
||||
ui.selectable_config(current_selector.clone().to_string());
|
||||
match system_to_control.quirks_mode() {
|
||||
Chip8 => {
|
||||
working_selector = working_selector.selected(true);
|
||||
}
|
||||
SChipModern => {
|
||||
working_selector = working_selector.selected(true);
|
||||
}
|
||||
XOChip => {
|
||||
working_selector = working_selector.selected(true);
|
||||
}
|
||||
}
|
||||
if working_selector.build() {
|
||||
system_to_control.reset(current_selector);
|
||||
println!("CLICK ON {}", ¤t_selector);
|
||||
}
|
||||
}
|
||||
GemmaImguiSupport::quirks_picker(system_to_control, ui);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -232,7 +251,7 @@ impl GemmaImguiSupport {
|
||||
.position([100.0, 640.0], Condition::FirstUseEver)
|
||||
.build(|| {
|
||||
ui.text("Registers");
|
||||
for i in 1..0x10 {
|
||||
for i in 0..0x10 {
|
||||
ui.text(format!("V{:X}: {}", i, system.registers.peek(i)));
|
||||
if i != 7 {
|
||||
ui.same_line();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::ffi::OsString;
|
||||
use std::fs::read_dir;
|
||||
use std::path::PathBuf;
|
||||
use imgui::Ui;
|
||||
use imgui::{ChildWindow, Ui};
|
||||
use log::debug;
|
||||
|
||||
pub struct GuiFileList {}
|
||||
@@ -20,16 +20,22 @@ impl GuiFileList {
|
||||
|
||||
known_files.sort();
|
||||
|
||||
for (index, entry) in known_files.iter().enumerate() {
|
||||
let mut working_select = ui.selectable_config(entry.clone().into_string().unwrap().to_string());
|
||||
if *entry.to_str().unwrap() == *selected_filename.as_str() {
|
||||
working_select = working_select.selected(true);
|
||||
}
|
||||
if working_select.build() {
|
||||
debug!("SELECTED {index} / {entry:?}");
|
||||
working_filename = entry.clone().into_string().unwrap();
|
||||
};
|
||||
}
|
||||
ui.child_window("Item List")
|
||||
.size([0.0, 200.0])
|
||||
.border(false)
|
||||
.build(|| {
|
||||
for (index, entry) in known_files.iter().enumerate() {
|
||||
let mut working_select = ui.selectable_config(entry.clone().into_string().unwrap().to_string());
|
||||
if *entry.to_str().unwrap() == *selected_filename.as_str() {
|
||||
working_select = working_select.selected(true);
|
||||
}
|
||||
if working_select.build() {
|
||||
debug!("SELECTED {index} / {entry:?}");
|
||||
working_filename = entry.clone().into_string().unwrap();
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
working_filename
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ pub fn create_context() -> imgui::Context {
|
||||
}),
|
||||
},
|
||||
]);
|
||||
imgui.set_ini_filename(None);
|
||||
// imgui.set_ini_filename(None);
|
||||
|
||||
imgui
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@ pub struct ImGuiUiState {
|
||||
pub frame_time: u32,
|
||||
pub last_frame_instant: Instant,
|
||||
pub target_ips: i32,
|
||||
pub roms_root_path: PathBuf
|
||||
pub roms_root_path: PathBuf,
|
||||
pub video_window_size: [i32; 2],
|
||||
pub control_window_size: [i32; 2]
|
||||
}
|
||||
|
||||
impl Clone for ImGuiUiState {
|
||||
@@ -33,7 +35,9 @@ impl Clone for ImGuiUiState {
|
||||
frame_time: self.frame_time,
|
||||
last_frame_instant: self.last_frame_instant,
|
||||
target_ips: self.target_ips,
|
||||
roms_root_path: self.roms_root_path.to_owned()
|
||||
roms_root_path: self.roms_root_path.to_owned(),
|
||||
video_window_size: self.video_window_size,
|
||||
control_window_size: self.control_window_size
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,8 +55,10 @@ impl Default for ImGuiUiState {
|
||||
is_running: false,
|
||||
frame_time: 16,
|
||||
last_frame_instant: Instant::now(),
|
||||
target_ips: 200000,
|
||||
roms_root_path: PathBuf::from(ROMPATH_DEFAULT)
|
||||
target_ips: 20,
|
||||
roms_root_path: PathBuf::from(ROMPATH_DEFAULT),
|
||||
control_window_size: [200, 600],
|
||||
video_window_size: [800, 600]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user