working on gemmaegui to build a usable UI
This commit is contained in:
parent
ef0250b519
commit
c9ef6d4e04
@ -1,74 +1,10 @@
|
|||||||
|
use crate::support::GemmaEGuiSupport::GemmaEGui;
|
||||||
|
use crate::support::EmmaEGuiState::EmmaEGuiState;
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use egui::Ui;
|
use egui::Ui;
|
||||||
use gemma::chip8::computer::Chip8Computer;
|
use gemma::chip8::computer::Chip8Computer;
|
||||||
|
|
||||||
struct EmmaEGuiState {
|
mod support;
|
||||||
pub display_video: bool,
|
|
||||||
pub display_memory: bool,
|
|
||||||
pub display_registers: bool
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for EmmaEGuiState {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self { display_video: true,
|
|
||||||
display_memory: true,
|
|
||||||
display_registers: true }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn controls_view(mut system: &mut Chip8Computer, state: &mut EmmaEGuiState, ui: &mut Ui) {
|
|
||||||
if ui.button("Step").clicked() {
|
|
||||||
system.step_system();
|
|
||||||
}
|
|
||||||
if ui.button("Start").clicked() {
|
|
||||||
println!("Start");
|
|
||||||
}
|
|
||||||
if ui.button("Stop").clicked() {
|
|
||||||
println!("STOP");
|
|
||||||
|
|
||||||
}
|
|
||||||
if ui.button("Reset").clicked() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.checkbox(&mut state.display_memory, "Display Memory");
|
|
||||||
ui.checkbox(&mut state.display_video, "Display Video");
|
|
||||||
ui.checkbox(&mut state.display_registers, "Display Registers");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn registers_view(system: &Chip8Computer, ui:& mut Ui) {
|
|
||||||
ui.label(format!("V0-7: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} ",
|
|
||||||
system.registers.peek(0x00),
|
|
||||||
system.registers.peek(0x01),
|
|
||||||
system.registers.peek(0x02),
|
|
||||||
system.registers.peek(0x03),
|
|
||||||
system.registers.peek(0x04),
|
|
||||||
system.registers.peek(0x05),
|
|
||||||
system.registers.peek(0x06),
|
|
||||||
system.registers.peek(0x07)
|
|
||||||
));
|
|
||||||
ui.label(format!("V8-F: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} ",
|
|
||||||
system.registers.peek(0x08),
|
|
||||||
system.registers.peek(0x09),
|
|
||||||
system.registers.peek(0x0A),
|
|
||||||
system.registers.peek(0x0B),
|
|
||||||
system.registers.peek(0x0C),
|
|
||||||
system.registers.peek(0x0D),
|
|
||||||
system.registers.peek(0x0E),
|
|
||||||
system.registers.peek(0x0F)
|
|
||||||
));
|
|
||||||
ui.label(format!("PC: {:04x}\tI: {:04x}" , system.registers.peek_pc(), system.registers.peek_i()));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn video_view(system: &Chip8Computer, ui: &mut Ui) {
|
|
||||||
ui.label("Video goes here");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn memory_view(system: &Chip8Computer, ui: &mut Ui) {
|
|
||||||
ui.label("Memory View");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn main() -> eframe::Result {
|
fn main() -> eframe::Result {
|
||||||
println!("Taxation is Theft");
|
println!("Taxation is Theft");
|
||||||
@ -85,18 +21,18 @@ fn main() -> eframe::Result {
|
|||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
ui.heading("Gemma");
|
ui.heading("Gemma");
|
||||||
|
|
||||||
controls_view(&mut computer, &mut state, ui);
|
GemmaEGui::controls_view(&mut computer, &mut state, ui);
|
||||||
|
|
||||||
if state.display_memory {
|
if state.display_memory {
|
||||||
memory_view(&computer, ui);
|
GemmaEGui::memory_view(&computer, ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.display_video {
|
if state.display_video {
|
||||||
video_view(&computer, ui);
|
GemmaEGui::video_view(&computer, ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.display_registers {
|
if state.display_registers {
|
||||||
registers_view(&computer, ui);
|
GemmaEGui::registers_view(&computer, ui);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|||||||
16
gemmaegui/src/bin/support/EmmaEGuiState.rs
Normal file
16
gemmaegui/src/bin/support/EmmaEGuiState.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
pub struct EmmaEGuiState {
|
||||||
|
pub display_video: bool,
|
||||||
|
pub display_memory: bool,
|
||||||
|
pub display_registers: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EmmaEGuiState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
display_video: true,
|
||||||
|
display_memory: true,
|
||||||
|
display_registers: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
75
gemmaegui/src/bin/support/GemmaEGuiSupport.rs
Normal file
75
gemmaegui/src/bin/support/GemmaEGuiSupport.rs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
use egui::Color32;
|
||||||
|
use egui::Rect;
|
||||||
|
use egui::Pos2;
|
||||||
|
use egui::Vec2;
|
||||||
|
use egui::Ui;
|
||||||
|
use crate::support::EmmaEGuiState::EmmaEGuiState;
|
||||||
|
use crate::Chip8Computer;
|
||||||
|
|
||||||
|
pub struct GemmaEGui {}
|
||||||
|
impl GemmaEGui {
|
||||||
|
pub fn controls_view(mut system: &mut Chip8Computer, state: &mut EmmaEGuiState, ui: &mut Ui) {
|
||||||
|
if ui.button("Step").clicked() {
|
||||||
|
system.step_system();
|
||||||
|
}
|
||||||
|
if ui.button("Start").clicked() {
|
||||||
|
println!("Start");
|
||||||
|
}
|
||||||
|
if ui.button("Stop").clicked() {
|
||||||
|
println!("STOP");
|
||||||
|
}
|
||||||
|
if ui.button("Reset").clicked() {}
|
||||||
|
|
||||||
|
ui.checkbox(&mut state.display_memory, "Display Memory");
|
||||||
|
ui.checkbox(&mut state.display_video, "Display Video");
|
||||||
|
ui.checkbox(&mut state.display_registers, "Display Registers");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn registers_view(system: &Chip8Computer, ui: &mut Ui) {
|
||||||
|
ui.label(format!("V0-7: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} ",
|
||||||
|
system.registers.peek(0x00),
|
||||||
|
system.registers.peek(0x01),
|
||||||
|
system.registers.peek(0x02),
|
||||||
|
system.registers.peek(0x03),
|
||||||
|
system.registers.peek(0x04),
|
||||||
|
system.registers.peek(0x05),
|
||||||
|
system.registers.peek(0x06),
|
||||||
|
system.registers.peek(0x07)
|
||||||
|
));
|
||||||
|
ui.label(format!("V8-F: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} ",
|
||||||
|
system.registers.peek(0x08),
|
||||||
|
system.registers.peek(0x09),
|
||||||
|
system.registers.peek(0x0A),
|
||||||
|
system.registers.peek(0x0B),
|
||||||
|
system.registers.peek(0x0C),
|
||||||
|
system.registers.peek(0x0D),
|
||||||
|
system.registers.peek(0x0E),
|
||||||
|
system.registers.peek(0x0F)
|
||||||
|
));
|
||||||
|
ui.label(format!("PC: {:04x}\tI: {:04x}", system.registers.peek_pc(), system.registers.peek_i()));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn video_view(system: &Chip8Computer, ui: &mut Ui) {
|
||||||
|
ui.label("Video goes here");
|
||||||
|
let (resp, painter) = ui.allocate_painter(Vec2::new(400.0, 500.0), egui::Sense::hover());
|
||||||
|
for current_row in 0..32 {
|
||||||
|
for current_col in 0..64 {
|
||||||
|
let data_offset = current_row * 32 + current_col;
|
||||||
|
let origin = ui.next_widget_position();
|
||||||
|
let colour = if system.video_memory.peek(data_offset) {
|
||||||
|
Color32::RED
|
||||||
|
} else {
|
||||||
|
Color32::BLUE
|
||||||
|
};
|
||||||
|
let rect = Rect::from_min_size(origin, Vec2::new(10.0, 10.0));
|
||||||
|
painter.rect_filled(rect, 0.0, colour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub fn memory_view(system: &Chip8Computer, ui: &mut Ui) {
|
||||||
|
ui.label("Memory View");
|
||||||
|
}
|
||||||
|
}
|
||||||
2
gemmaegui/src/bin/support/mod.rs
Normal file
2
gemmaegui/src/bin/support/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod EmmaEGuiState;
|
||||||
|
pub mod GemmaEGuiSupport;
|
||||||
@ -9,50 +9,20 @@ use imgui::*;
|
|||||||
use sys::{ImColor, ImVec2, ImVector_ImU32};
|
use sys::{ImColor, ImVec2, ImVector_ImU32};
|
||||||
use rand::random;
|
use rand::random;
|
||||||
use gemma::chip8::system_memory::Chip8SystemMemory;
|
use gemma::chip8::system_memory::Chip8SystemMemory;
|
||||||
use support::emmagui_support::EmmaGui;
|
use support::{emmagui_support::EmmaGui, ui_state::UiState};
|
||||||
|
|
||||||
mod support;
|
mod support;
|
||||||
|
|
||||||
struct UiState {
|
/// Keypad Mappings for my Linux box
|
||||||
pub show_registers: bool,
|
/// 1 2 3 C
|
||||||
pub show_memory: bool,
|
/// 4 5 6 D
|
||||||
pub show_video: bool,
|
/// 7 8 9 E
|
||||||
pub filename_to_load: String,
|
/// A 0 B F
|
||||||
pub on_colour: ImColor32,
|
|
||||||
pub off_colour: ImColor32,
|
|
||||||
pub is_running: bool,
|
|
||||||
pub frame_time: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for UiState {
|
const LIN_KEYS: [(u16, u8); 0x10] = [(537, 0x01),(538, 0x02),(539, 0x03),(540, 0x0c),
|
||||||
fn clone(&self) -> Self {
|
(562, 0x04),(568, 0x05),(550, 0x06),(563, 0x0d),
|
||||||
UiState {
|
(546, 7),(564, 8),(549, 9),(551, 0xe),
|
||||||
show_registers: self.show_registers,
|
(571, 0xa),(569, 0),(548, 0xb),(569, 0xf)];
|
||||||
show_memory: self.show_memory,
|
|
||||||
show_video: self.show_video,
|
|
||||||
filename_to_load: self.filename_to_load.to_string(),
|
|
||||||
on_colour: self.on_colour,
|
|
||||||
off_colour: self.off_colour,
|
|
||||||
is_running: self.is_running,
|
|
||||||
frame_time: self.frame_time,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for UiState {
|
|
||||||
fn default() -> Self {
|
|
||||||
UiState {
|
|
||||||
show_registers: false,
|
|
||||||
show_memory: false,
|
|
||||||
show_video: true,
|
|
||||||
filename_to_load: String::new(),
|
|
||||||
on_colour: ImColor32::from_rgb(0xff, 0xff, 0x00),
|
|
||||||
off_colour: ImColor32::from_rgb(0x00, 0xff, 0xff),
|
|
||||||
is_running: false,
|
|
||||||
frame_time: 10.0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
@ -62,9 +32,35 @@ fn main() {
|
|||||||
|
|
||||||
support::simple_init(file!(), move |_, ui| {
|
support::simple_init(file!(), move |_, ui| {
|
||||||
let current_time = Instant::now();
|
let current_time = Instant::now();
|
||||||
|
|
||||||
|
let down_keys = ui.io().keys_down;
|
||||||
|
for (key_code, key_reg) in LIN_KEYS {
|
||||||
|
if down_keys[key_code as usize] {
|
||||||
|
system.keypad.push_key(key_reg);
|
||||||
|
} else {
|
||||||
|
// do we need to release it?
|
||||||
|
if system.keypad.pressed(key_reg) {
|
||||||
|
system.keypad.release_key(key_reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// println!("KEYS DOWN = {:?}", ui.io().keys_down);
|
||||||
let time_since_last_tick = current_time.duration_since(last_tick_time).as_millis();
|
let time_since_last_tick = current_time.duration_since(last_tick_time).as_millis();
|
||||||
if ui_state.is_running && time_since_last_tick > ui_state.frame_time as u128 {
|
if ui_state.is_running && time_since_last_tick > ui_state.frame_time as u128 {
|
||||||
system.step_system();
|
match system.state {
|
||||||
|
gemma::chip8::cpu_states::Chip8CpuStates::WaitingForInstruction => {
|
||||||
|
// this is the 'regular' mode for the CPU when we get here
|
||||||
|
system.step_system();
|
||||||
|
},
|
||||||
|
gemma::chip8::cpu_states::Chip8CpuStates::WaitingForKey => {
|
||||||
|
// waiting for a keychange...
|
||||||
|
},
|
||||||
|
gemma::chip8::cpu_states::Chip8CpuStates::ExecutingInstruction => { // should never see this.
|
||||||
|
},
|
||||||
|
gemma::chip8::cpu_states::Chip8CpuStates::Error => {
|
||||||
|
panic!("System in undefined state.");
|
||||||
|
},
|
||||||
|
}
|
||||||
last_tick_time = current_time;
|
last_tick_time = current_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,5 +78,9 @@ fn main() {
|
|||||||
let active_instruction = system.registers.peek_pc();
|
let active_instruction = system.registers.peek_pc();
|
||||||
EmmaGui::hex_memory_display(system.memory.clone(), (0x100, 0x10), active_instruction as i16, ui);
|
EmmaGui::hex_memory_display(system.memory.clone(), (0x100, 0x10), active_instruction as i16, ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ui_state.show_keypad {
|
||||||
|
EmmaGui::keypad_display(&system, ui);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use gemma::constants::CHIP8_KEYBOARD;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -10,6 +11,8 @@ use gemma::chip8::system_memory::Chip8SystemMemory;
|
|||||||
use gemma::constants::{CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_WIDTH};
|
use gemma::constants::{CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_WIDTH};
|
||||||
use crate::UiState;
|
use crate::UiState;
|
||||||
|
|
||||||
|
use super::ui_state;
|
||||||
|
|
||||||
pub struct EmmaGui {}
|
pub struct EmmaGui {}
|
||||||
|
|
||||||
const CELL_WIDTH: i32 = 5i32;
|
const CELL_WIDTH: i32 = 5i32;
|
||||||
@ -39,6 +42,23 @@ impl GuiFileList {
|
|||||||
|
|
||||||
|
|
||||||
impl EmmaGui {
|
impl EmmaGui {
|
||||||
|
pub fn keypad_display(system_to_display: &Chip8Computer, ui: &Ui) {
|
||||||
|
ui.text("Keypad");
|
||||||
|
|
||||||
|
for row in CHIP8_KEYBOARD {
|
||||||
|
for key in row {
|
||||||
|
let label = if system_to_display.keypad.pressed(key) {
|
||||||
|
format!("*{:1x}*", key)
|
||||||
|
} else {
|
||||||
|
format!("{:1x}", key)
|
||||||
|
};
|
||||||
|
ui.text(format!("{}", label));
|
||||||
|
ui.same_line();
|
||||||
|
}
|
||||||
|
ui.text("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn video_display(system_to_control: &Chip8Computer, gui_state: &UiState, ui: &Ui) {
|
pub fn video_display(system_to_control: &Chip8Computer, gui_state: &UiState, ui: &Ui) {
|
||||||
// draw area size
|
// draw area size
|
||||||
let draw_area_size = ui.io().display_size;
|
let draw_area_size = ui.io().display_size;
|
||||||
@ -46,7 +66,7 @@ impl EmmaGui {
|
|||||||
let cell_height = ((draw_area_size[1] as i32 / 32) * 6) / 10;
|
let cell_height = ((draw_area_size[1] as i32 / 32) * 6) / 10;
|
||||||
|
|
||||||
ui.window(format!("Display {cell_width}x{cell_height}"))
|
ui.window(format!("Display {cell_width}x{cell_height}"))
|
||||||
.size([300.0, 300.0], Condition::FirstUseEver)
|
.size([300.0, 300.0], Condition::Once)
|
||||||
.build(|| {
|
.build(|| {
|
||||||
let origin = ui.cursor_screen_pos();
|
let origin = ui.cursor_screen_pos();
|
||||||
let fg = ui.get_window_draw_list();
|
let fg = ui.get_window_draw_list();
|
||||||
@ -94,16 +114,19 @@ impl EmmaGui {
|
|||||||
if ui.button("Step") {
|
if ui.button("Step") {
|
||||||
system_to_control.step_system();
|
system_to_control.step_system();
|
||||||
};
|
};
|
||||||
|
ui.same_line();
|
||||||
if ui.button("Run") {
|
if ui.button("Run") {
|
||||||
gui_state.is_running = true;
|
gui_state.is_running = true;
|
||||||
debug!("STARTING THE SYSTEM");
|
debug!("STARTING THE SYSTEM");
|
||||||
}
|
}
|
||||||
|
ui.same_line();
|
||||||
if ui.button("Stop") {
|
if ui.button("Stop") {
|
||||||
gui_state.is_running = false;
|
gui_state.is_running = false;
|
||||||
debug!("STOPPING THE SYSTEM");
|
debug!("STOPPING THE SYSTEM");
|
||||||
}
|
}
|
||||||
ui.same_line();
|
ui.same_line();
|
||||||
if ui.button("Reset") {
|
if ui.button("Reset") {
|
||||||
|
gui_state.is_running = false;
|
||||||
*system_to_control = Chip8Computer::new();
|
*system_to_control = Chip8Computer::new();
|
||||||
}
|
}
|
||||||
if ui.button("Dump Video Memory") {
|
if ui.button("Dump Video Memory") {
|
||||||
|
|||||||
@ -10,6 +10,7 @@ use imgui_winit_support::{HiDpiMode, WinitPlatform};
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
pub mod ui_state;
|
||||||
pub mod emmagui_support;
|
pub mod emmagui_support;
|
||||||
use copypasta::{ClipboardContext, ClipboardProvider};
|
use copypasta::{ClipboardContext, ClipboardProvider};
|
||||||
use imgui::ClipboardBackend;
|
use imgui::ClipboardBackend;
|
||||||
|
|||||||
46
gemmaimgui/src/bin/support/ui_state.rs
Normal file
46
gemmaimgui/src/bin/support/ui_state.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
use imgui::ImColor32;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct UiState {
|
||||||
|
pub show_registers: bool,
|
||||||
|
pub show_memory: bool,
|
||||||
|
pub show_video: bool,
|
||||||
|
pub show_keypad: bool,
|
||||||
|
pub filename_to_load: String,
|
||||||
|
pub on_colour: ImColor32,
|
||||||
|
pub off_colour: ImColor32,
|
||||||
|
pub is_running: bool,
|
||||||
|
pub frame_time: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for UiState {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
UiState {
|
||||||
|
show_registers: self.show_registers,
|
||||||
|
show_memory: self.show_memory,
|
||||||
|
show_video: self.show_video,
|
||||||
|
show_keypad: self.show_keypad,
|
||||||
|
filename_to_load: self.filename_to_load.to_string(),
|
||||||
|
on_colour: self.on_colour,
|
||||||
|
off_colour: self.off_colour,
|
||||||
|
is_running: self.is_running,
|
||||||
|
frame_time: self.frame_time,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for UiState {
|
||||||
|
fn default() -> Self {
|
||||||
|
UiState {
|
||||||
|
show_registers: false,
|
||||||
|
show_memory: false,
|
||||||
|
show_video: true,
|
||||||
|
show_keypad: true,
|
||||||
|
filename_to_load: String::new(),
|
||||||
|
on_colour: ImColor32::from_rgb(0xff, 0xff, 0x00),
|
||||||
|
off_colour: ImColor32::from_rgb(0x00, 0xff, 0xff),
|
||||||
|
is_running: false,
|
||||||
|
frame_time: 10.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
resources/roms/octojam2title.ch8
Normal file
BIN
resources/roms/octojam2title.ch8
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user