evolve egui interface

move more control back up to the ComputerManager
This commit is contained in:
Trevor Merritt 2024-10-22 08:25:08 -04:00
parent 665309c2e4
commit eccc3fe9e3
9 changed files with 338 additions and 202 deletions

152
.idea/workspace.xml generated
View File

@ -9,12 +9,13 @@
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="9bcba7c5-ac1d-4216-959a-63faee7047bc" name="Changes" comment=""> <list default="true" id="9bcba7c5-ac1d-4216-959a-63faee7047bc" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gemma/src/chip8/instructions.rs" beforeDir="false" afterPath="$PROJECT_DIR$/gemma/src/chip8/instructions.rs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Cargo.lock" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.lock" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gemma/src/constants.rs" beforeDir="false" afterPath="$PROJECT_DIR$/gemma/src/constants.rs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/gemma/src/chip8/computer_manager.rs" beforeDir="false" afterPath="$PROJECT_DIR$/gemma/src/chip8/computer_manager.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gemmaegui/src/bin/gemmaegui_viewer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/gemmaegui/src/bin/gemmaegui_viewer.rs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/gemmaegui/src/bin/gemmaegui.rs" beforeDir="false" afterPath="$PROJECT_DIR$/gemmaegui/src/bin/gemmaegui.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gemmaimgui/src/bin/gemmaimgui.rs" beforeDir="false" afterPath="$PROJECT_DIR$/gemmaimgui/src/bin/gemmaimgui.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gemmautil/Cargo.toml" beforeDir="false" afterPath="$PROJECT_DIR$/gemmautil/Cargo.toml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gemmautil/src/bin/ch8asm.rs" beforeDir="false" afterPath="$PROJECT_DIR$/gemmautil/src/bin/ch8asm.rs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/gemmautil/src/bin/ch8asm.rs" beforeDir="false" afterPath="$PROJECT_DIR$/gemmautil/src/bin/ch8asm.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gemmautil/src/bin/ch8disasm.rs" beforeDir="false" afterPath="$PROJECT_DIR$/gemmautil/src/bin/ch8disasm.rs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/gemmautil/src/bin/ch8disasm.rs" beforeDir="false" afterPath="$PROJECT_DIR$/gemmautil/src/bin/ch8disasm.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/resources/test/gemma_disassembler_1_chip_logo_ch8_asm.asc" beforeDir="false" afterPath="$PROJECT_DIR$/resources/test/gemma_disassembler_1_chip_logo_ch8_asm.asc" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -42,87 +43,88 @@
<option name="hideEmptyMiddlePackages" value="true" /> <option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" /> <option name="showLibraryContents" value="true" />
</component> </component>
<component name="PropertiesComponent">{ <component name="PropertiesComponent"><![CDATA[{
&quot;keyToString&quot;: { "keyToString": {
&quot;Cargo.Build `Run emmagui`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Run emmagui`.executor": "Run",
&quot;Cargo.Build `Run gemmaegui_viewer`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Run gemmaegui_viewer`.executor": "Run",
&quot;Cargo.Build `Run gemmaegui`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Run gemmaegui`.executor": "Run",
&quot;Cargo.Build `Run gemmaimgui`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Run gemmaimgui`.executor": "Run",
&quot;Cargo.Build `Run trevors_chip8_toy`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Run trevors_chip8_toy`.executor": "Run",
&quot;Cargo.Build `Test chip8::computer::test::cls_test`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Test chip8::computer::test::cls_test`.executor": "Run",
&quot;Cargo.Build `Test chip8::instructions::test::LdStVx_test`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Test chip8::instructions::test::LdStVx_test`.executor": "Run",
&quot;Cargo.Build `Test chip8::instructions::test::random_produces_different_numbers`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Test chip8::instructions::test::random_produces_different_numbers`.executor": "Run",
&quot;Cargo.Build `Test chip8::instructions::test::series8xy6_corex_tests`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Test chip8::instructions::test::series8xy6_corex_tests`.executor": "Run",
&quot;Cargo.Build `Test chip8::instructions::test::shl_vx_vy_test`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Test chip8::instructions::test::shl_vx_vy_test`.executor": "Run",
&quot;Cargo.Build `Test chip8::util::test::byte_to_bool_changes`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Test chip8::util::test::byte_to_bool_changes`.executor": "Run",
&quot;Cargo.Build `Test chip8::util::test::ubln`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Test chip8::util::test::ubln`.executor": "Run",
&quot;Cargo.Build `Test chip8::video::test::poke_byte_test`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Test chip8::video::test::poke_byte_test`.executor": "Run",
&quot;Cargo.Build `Test chip8::video::test::poke_byte`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Test chip8::video::test::poke_byte`.executor": "Run",
&quot;Cargo.Build `Test computer::test`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Test computer::test`.executor": "Run",
&quot;Cargo.Build `Test instructions::test (1)`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Test instructions::test (1)`.executor": "Run",
&quot;Cargo.Build `Test instructions::test`.executor&quot;: &quot;Run&quot;, "Cargo.Build `Test instructions::test`.executor": "Run",
&quot;Cargo.Build gemma.executor&quot;: &quot;Run&quot;, "Cargo.Build gemma.executor": "Run",
&quot;Cargo.Run emmagui.executor&quot;: &quot;Run&quot;, "Cargo.Run emmagui.executor": "Run",
&quot;Cargo.Run gemmaegui.executor&quot;: &quot;Run&quot;, "Cargo.Run gemmaegui.executor": "Debug",
&quot;Cargo.Run gemmaegui_viewer.executor&quot;: &quot;Debug&quot;, "Cargo.Run gemmaegui_viewer.executor": "Debug",
&quot;Cargo.Run gemmaimgui.executor&quot;: &quot;Run&quot;, "Cargo.Run gemmaimgui.executor": "Run",
&quot;Cargo.Run trevors_chip8_toy.executor&quot;: &quot;Debug&quot;, "Cargo.Run trevors_chip8_toy.executor": "Debug",
&quot;Cargo.Test chip8::computer::test::cls_test.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::computer::test::cls_test.executor": "Run",
&quot;Cargo.Test chip8::computer::test::decoder_test_valid_instructions.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::computer::test::decoder_test_valid_instructions.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::LdStVx_test.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::LdStVx_test.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::LdVxDt_test.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::LdVxDt_test.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::LdiAddr_test.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::LdiAddr_test.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::RndVxByte_test.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::RndVxByte_test.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::ShrVxVy_test.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::ShrVxVy_test.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::SneVxVy_test.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::SneVxVy_test.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::decoder_test_invalid_instructions.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::decoder_test_invalid_instructions.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::draw_nibble_vx_vy_n_test.executor&quot;: &quot;Debug&quot;, "Cargo.Test chip8::instructions::test::draw_nibble_vx_vy_n_test.executor": "Debug",
&quot;Cargo.Test chip8::instructions::test::encode_decode_test.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::encode_decode_test.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::random_produces_different_numbers.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::random_produces_different_numbers.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::series4000_corex_tests.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::series4000_corex_tests.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::series8xy4_corex_tests.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::series8xy4_corex_tests.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::series8xy6_corex_tests.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::series8xy6_corex_tests.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::shl_vx_vy_test.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::shl_vx_vy_test.executor": "Run",
&quot;Cargo.Test chip8::instructions::test::subn_vx_vy_test.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::instructions::test::subn_vx_vy_test.executor": "Run",
&quot;Cargo.Test chip8::util::test::bool_to_byte_changes.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::util::test::bool_to_byte_changes.executor": "Run",
&quot;Cargo.Test chip8::util::test::byte_to_bool_changes.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::util::test::byte_to_bool_changes.executor": "Run",
&quot;Cargo.Test chip8::util::test::ubln.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::util::test::ubln.executor": "Run",
&quot;Cargo.Test chip8::video::test::poke_byte.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::video::test::poke_byte.executor": "Run",
&quot;Cargo.Test chip8::video::test::poke_byte_test.executor&quot;: &quot;Run&quot;, "Cargo.Test chip8::video::test::poke_byte_test.executor": "Run",
&quot;Cargo.Test chip8::video::test::poke_sprite_test.executor&quot;: &quot;Debug&quot;, "Cargo.Test chip8::video::test::poke_sprite_test.executor": "Debug",
&quot;Cargo.Test computer::test.executor&quot;: &quot;Debug&quot;, "Cargo.Test computer::test.executor": "Debug",
&quot;Cargo.Test instructions::test (1).executor&quot;: &quot;Debug&quot;, "Cargo.Test instructions::test (1).executor": "Debug",
&quot;Cargo.Test instructions::test.executor&quot;: &quot;Debug&quot;, "Cargo.Test instructions::test.executor": "Debug",
&quot;Cargo.Test sound_timer::test.executor&quot;: &quot;Run&quot;, "Cargo.Test sound_timer::test.executor": "Run",
&quot;Cargo.Test util::test.executor&quot;: &quot;Run&quot;, "Cargo.Test util::test.executor": "Run",
&quot;Cargo.Test video::test.executor&quot;: &quot;Coverage&quot;, "Cargo.Test video::test.executor": "Coverage",
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;, "RunOnceActivity.ShowReadmeOnStart": "true",
&quot;RunOnceActivity.rust.reset.selective.auto.import&quot;: &quot;true&quot;, "RunOnceActivity.rust.reset.selective.auto.import": "true",
&quot;git-widget-placeholder&quot;: &quot;rename__instructions&quot;, "git-widget-placeholder": "master",
&quot;last_opened_file_path&quot;: &quot;/home/tmerritt/Projects/chip8_toy/gemmaimgui&quot;, "last_opened_file_path": "/home/tmerritt/Projects/chip8_toy/gemmaimgui",
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;, "node.js.detected.package.eslint": "true",
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;, "node.js.selected.package.eslint": "(autodetect)",
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;, "nodejs_package_manager_path": "npm",
&quot;org.rust.cargo.project.model.PROJECT_DISCOVERY&quot;: &quot;true&quot;, "org.rust.cargo.project.model.PROJECT_DISCOVERY": "true",
&quot;org.rust.cargo.project.model.impl.CargoExternalSystemProjectAware.subscribe.first.balloon&quot;: &quot;&quot;, "org.rust.cargo.project.model.impl.CargoExternalSystemProjectAware.subscribe.first.balloon": "",
&quot;org.rust.first.attach.projects&quot;: &quot;true&quot;, "org.rust.first.attach.projects": "true",
&quot;settings.editor.selected.configurable&quot;: &quot;language.rust.build.tool.cargo&quot; "settings.editor.selected.configurable": "language.rust.build.tool.cargo"
}, },
&quot;keyToStringList&quot;: { "keyToStringList": {
&quot;com.intellij.ide.scratch.ScratchImplUtil$2/New Scratch File&quot;: [ "com.intellij.ide.scratch.ScratchImplUtil$2/New Scratch File": [
&quot;TEXT&quot; "TEXT"
] ]
} }
}</component> }]]></component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS"> <key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/gemmaimgui" /> <recent name="$PROJECT_DIR$/gemmaimgui" />
</key> </key>
<key name="MoveFile.RECENT_KEYS"> <key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/gemmautil/src" />
<recent name="$PROJECT_DIR$/gemmaimgui/src/bin" /> <recent name="$PROJECT_DIR$/gemmaimgui/src/bin" />
</key> </key>
</component> </component>
<component name="RunManager" selected="Cargo.Run gemmaegui_viewer"> <component name="RunManager" selected="Cargo.Run gemmaegui">
<configuration name="Run gemmaegui" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true"> <configuration name="Run gemmaegui" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="command" value="run --package gemmaegui --bin gemmaegui" /> <option name="command" value="run --package gemmaegui --bin gemmaegui" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" /> <option name="workingDirectory" value="file://$PROJECT_DIR$" />
@ -193,8 +195,8 @@
</configuration> </configuration>
<recent_temporary> <recent_temporary>
<list> <list>
<item itemvalue="Cargo.Run gemmaegui_viewer" />
<item itemvalue="Cargo.Run gemmaegui" /> <item itemvalue="Cargo.Run gemmaegui" />
<item itemvalue="Cargo.Run gemmaegui_viewer" />
<item itemvalue="Cargo.Run gemmaimgui" /> <item itemvalue="Cargo.Run gemmaimgui" />
<item itemvalue="Cargo.Run gemmaimgui" /> <item itemvalue="Cargo.Run gemmaimgui" />
<item itemvalue="Cargo.Run gemmaegui" /> <item itemvalue="Cargo.Run gemmaegui" />

64
Cargo.lock generated
View File

@ -1835,6 +1835,8 @@ version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"gemma", "gemma",
"pest",
"pest_derive",
] ]
[[package]] [[package]]
@ -3216,6 +3218,51 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pest"
version = "2.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442"
dependencies = [
"memchr",
"thiserror",
"ucd-trie",
]
[[package]]
name = "pest_derive"
version = "2.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd"
dependencies = [
"pest",
"pest_generator",
]
[[package]]
name = "pest_generator"
version = "2.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.79",
]
[[package]]
name = "pest_meta"
version = "2.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d"
dependencies = [
"once_cell",
"pest",
"sha2",
]
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.1.6" version = "1.1.6"
@ -3748,6 +3795,17 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]] [[package]]
name = "shlex" name = "shlex"
version = "1.3.0" version = "1.3.0"
@ -4151,6 +4209,12 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "ucd-trie"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
[[package]] [[package]]
name = "uds_windows" name = "uds_windows"
version = "1.1.0" version = "1.1.0"

View File

@ -3,6 +3,7 @@ use std::thread;
use std::thread::{sleep, JoinHandle, Thread}; use std::thread::{sleep, JoinHandle, Thread};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use crate::chip8::computer::Chip8Computer; use crate::chip8::computer::Chip8Computer;
use crate::chip8::cpu_states::Chip8CpuStates;
use crate::chip8::cpu_states::Chip8CpuStates::WaitingForInstruction; use crate::chip8::cpu_states::Chip8CpuStates::WaitingForInstruction;
pub enum ManagerDumpables { pub enum ManagerDumpables {
@ -13,10 +14,10 @@ pub enum ManagerDumpables {
pub struct Chip8ComputerManager { pub struct Chip8ComputerManager {
pub core_should_run: bool, core_should_run: bool,
pub one_step: bool, one_step: bool,
pub core_cycle_timer: bool, core_cycle_timer: bool,
pub core_last_cycle_start: Instant, core_last_cycle_start: Instant,
computer: Chip8Computer computer: Chip8Computer
} }
@ -41,11 +42,10 @@ impl Chip8ComputerManager {
let core_handle = thread::spawn(move || { let core_handle = thread::spawn(move || {
loop { loop {
let start_time = Instant::now(); let start_time = Instant::now();
println!("Core Thread starting at {start_time:?}"); // println!("Core Thread starting at {start_time:?}");
let sleep_time = Instant::now().duration_since(start_time).as_millis(); let sleep_time = Instant::now().duration_since(start_time).as_millis();
println!("Core Thread sleeping for {sleep_time}ms"); // println!("Core Thread sleeping for {sleep_time}ms");
sleep(Duration::from_millis((16 - sleep_time) as u64)); sleep(Duration::from_millis((16 - sleep_time) as u64));
} }
}); });
@ -53,16 +53,16 @@ impl Chip8ComputerManager {
Chip8ComputerManager::default() Chip8ComputerManager::default()
} }
pub fn start(managed: &mut Chip8ComputerManager) { pub fn start(&mut self) {
managed.core_should_run = true; self.core_should_run = true;
} }
pub fn stop(managed: &mut Chip8ComputerManager) { pub fn stop(&mut self) {
managed.core_should_run = false self.core_should_run = false
} }
pub fn step(managed: &mut Chip8ComputerManager) { pub fn step(&mut self) {
managed.one_step = true; self.one_step = true;
} }
pub fn state(&mut self) -> &Chip8Computer { pub fn state(&mut self) -> &Chip8Computer {
@ -70,11 +70,16 @@ impl Chip8ComputerManager {
} }
pub fn tick( &mut self) { pub fn tick( &mut self) {
println!("STARTING TICK"); // println!("STARTING TICK");
if self.one_step | self.core_should_run { if self.one_step | self.core_should_run {
self.core_last_cycle_start = Instant::now(); match self.computer.state {
self.computer.step_system(); WaitingForInstruction => {
println!("SYSTEM STEP"); self.core_last_cycle_start = Instant::now();
self.computer.step_system();
println!("SYSTEM STEP");
}
_ => {}
}
}; };
if self.one_step { if self.one_step {
println!("SYSTEM HALTED AFTER 1 STEP"); println!("SYSTEM HALTED AFTER 1 STEP");
@ -86,6 +91,9 @@ impl Chip8ComputerManager {
pub fn press_key(&mut self, key_index: u8) { pub fn press_key(&mut self, key_index: u8) {
self.computer.keypad.push_key(key_index); self.computer.keypad.push_key(key_index);
if matches!(self.computer.state, Chip8CpuStates::WaitingForKey) {
self.computer.state = WaitingForInstruction
}
} }
pub fn release_key(&mut self, key_index: u8) { pub fn release_key(&mut self, key_index: u8) {
self.computer.keypad.release_key(key_index); self.computer.keypad.release_key(key_index);

View File

@ -1,23 +1,31 @@
use std::path::PathBuf;
use std::time::Instant; use std::time::Instant;
use crate::support::gemma_egui_support::{EGuiFileList, GemmaEguiSupport}; use crate::support::gemma_egui_support::{EGuiFileList, GemmaEguiSupport};
use crate::support::gemma_egui_state::GemmaEGuiState; use crate::support::gemma_egui_state::GemmaEGuiState;
use eframe::egui; use eframe::egui;
use egui::Ui; use egui::{Key, Ui};
use gemma::chip8::computer::Chip8Computer; use gemma::chip8::computer::Chip8Computer;
use gemma::chip8::computer_manager::Chip8ComputerManager; use gemma::chip8::computer_manager::Chip8ComputerManager;
mod support; mod support;
const LIN_KEYS: [[(Key, u8); 4]; 4] = [
[(Key::Num1, 0x01), (Key::Num2, 0x02), (Key::Num3, 0x03), (Key::Num4, 0x0c)],
[(Key::Q, 0x04), (Key::W, 0x05), (Key::E, 0x06), (Key::R, 0x0d)],
[(Key::A, 0x07), (Key::S, 0x08), (Key::D, 0x09), (Key::F, 0x0e)],
[(Key::Z, 0x0a), (Key::X, 0x00), (Key::C, 0x0b), (Key::V, 0x0F)]
];
#[derive(Default)] #[derive(Default)]
struct DisplayOptions { struct DisplayOptions {
pub video: bool, pub video: bool,
pub registers: bool, pub registers: bool,
pub memory: bool pub memory: bool,
} }
pub struct GemmaViewerState { pub struct GemmaViewerState {
pub selected_file_index: i32, pub selected_file_index: i32,
pub selected_filename: String, pub selected_filename: String,
pub display_options: DisplayOptions pub display_options: DisplayOptions,
} }
impl Default for GemmaViewerState { impl Default for GemmaViewerState {
@ -25,7 +33,7 @@ impl Default for GemmaViewerState {
GemmaViewerState { GemmaViewerState {
selected_file_index: -1, selected_file_index: -1,
selected_filename: String::new(), selected_filename: String::new(),
display_options: Default::default() display_options: Default::default(),
} }
} }
} }
@ -54,28 +62,28 @@ fn main() -> eframe::Result {
computer.tick(); computer.tick();
let local_computer = computer.state(); let local_computer = computer.state();
//if state.display_video { //if state.display_video {
GemmaEguiSupport::video_view(local_computer, ui); GemmaEguiSupport::video_view(local_computer, ui);
// } // }
ui.heading("EGUI Gemma"); ui.heading("EGUI Gemma");
// if state.display_memory { // if state.display_memory {
GemmaEguiSupport::memory_view(&local_computer, ui); GemmaEguiSupport::memory_view(&local_computer, ui);
// } // }
// if state.display_registers { // if state.display_registers {
GemmaEguiSupport::registers_view(&local_computer, ui); GemmaEguiSupport::registers_view(&local_computer, 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() {
computer.core_should_run = true; computer.start();
} }
if ui.button("Step").clicked() { if ui.button("Step").clicked() {
computer.one_step = true; computer.step();
} }
if ui.button("Stop").clicked() { if ui.button("Stop").clicked() {
computer.core_should_run = false; computer.stop();
// state.is_running = false; // state.is_running = false;
} }
if ui.button("Reset").clicked() { if ui.button("Reset").clicked() {
@ -84,17 +92,31 @@ fn main() -> eframe::Result {
} }
}); });
if ui.button(format!("Load {}", state.selected_filename)).clicked() { if ui.button(format!("Load {}", state.selected_filename)).clicked() {
// println!("Should load the bin now");
} let read_bin = std::fs::read(PathBuf::from(format!("resources/roms/{}", state.selected_filename))).unwrap();
// // load the bin... computer.load_bytes_to_system_memory(read_bin);
// let read_bin = std::fs::read(PathBuf::from(format!("resources/roms/{}", state.selected_rom_filename))).unwrap(); };
// // ...then feed the system. EGuiFileList::display_path(PathBuf::from("resources/roms"), &mut state.selected_filename, ui);
// system.load_bytes_to_memory(0x200, &read_bin); let input = ctx.input(|input| {
// println!("Loaded {}", state.selected_rom_filename); // loop through the keys we are checking...
// } for row in LIN_KEYS {
// EGuiFileList::display_path(PathBuf::from("resources/roms"), &mut state.selected_rom_filename, ui); for (keyboard_key, keypad_key) in row {
if input.key_pressed(keyboard_key) {
computer.press_key(keypad_key);
// println!("KEY {keypad_key:02x} DOWN");
} else {
// release it if the user just did
if computer.is_key_pressed(keypad_key) {
computer.release_key(keypad_key);
// println!("KEY {keypad_key:02x} up");
}
}
}
}
});
ctx.request_repaint();
}); });
}) })
} }

View File

@ -45,10 +45,8 @@ fn main() {
} }
// END DEBUG CODE // END DEBUG CODE
for (key_code, key_reg) in LIN_KEYS { for (key_code, key_reg) in LIN_KEYS {
if down_keys[key_code as usize] { if down_keys[key_code as usize] {
system.press_key(key_reg);
system.press_key(key_reg); system.press_key(key_reg);
system.wait_for_instruction(); system.wait_for_instruction();
} else { } else {

View File

@ -6,3 +6,5 @@ edition = "2021"
[dependencies] [dependencies]
gemma = { path = "../gemma" } gemma = { path = "../gemma" }
clap = { version = "4.5.20", features = ["derive"] } clap = { version = "4.5.20", features = ["derive"] }
pest = "2.7.14"
pest_derive = "2.7.14"

View File

@ -1,59 +1,87 @@
use std::fs::File; use std::fs;
use std::io; // Ch8Asm
use std::io::BufRead; // Converts well formed CH8ASM.
use std::path::Path; // no variables.
use clap::Parser; // no labels.
use gemma::chip8::instructions::Chip8CpuInstructions; // nothing fun.
use pest::Parser;
/// Ch8Asm use pest_derive::Parser;
/// Converts well formed CH8ASM.
/// no variables.
/// no labels.
/// nothing fun.
pub struct Assembler {}
impl Assembler {
}
#[derive(Parser)] #[derive(Parser)]
#[command(version, about, long_about = None)] #[grammar = "chip8_asm.pest"]
struct AssemblerApp { pub struct Chip8AsmParser;
#[arg(short)]
input_file: Box<Path>,
}
fn main() { fn main() {
println!("Taxation is Theft"); println!("Taxation is Theft");
let result = AssemblerApp::parse();
let mut assembled_code: Vec<u8> = vec![];
// println!("Preparing to assemble {}", result.input_file.file_name()); let unparsed = fs::read_to_string("resources/test/gemma_disassembler_1_chip_logo_ch8_asm.asc").expect("Unable to read input");
let path = Path::new(result.input_file); let file = Chip8AsmParser::parse(Rule::file, &unparsed).expect("Unable to parse. Try again.")
.next().unwrap();
// Open the file in read-only mode for record in file.into_inner() {
let file = File::open(&path)?; match record.as_rule() {
Rule::instruction => {
// Use a buffered reader for efficient reading println!("INSTRUCTION = {:?}", record.into_inner().flatten())
let reader = io::BufReader::new(file); }
_ => {
// Read the file line by line println!("UNHANDLED PART.");
for line in reader.lines() { }
// Get the line, handling possible errors
let line = line?;
// Split the line by ';' and collect parts into a vector
let parts: Vec<&str> = line.split(';').collect();
// Print each part or process it as needed
for part in &parts {
println!("{}", part);
} }
} }
// read the line split by a semicolon }
mod test {
use super::*;
#[test]
fn bits_all_parse() {
println!("PARSED: {:?}",
Chip8AsmParser::parse(Rule::instruction, "CLS")
);
println!("PARSED: {:?}",
Chip8AsmParser::parse(Rule::parameter, "0x01")
);
let parsed = Chip8AsmParser::parse(Rule::comment, "; comment").unwrap();
for i in parsed {
println!("PARSED COMMENT -> {:?}", i);
}
let parsed =
Chip8AsmParser::parse(Rule::record, "CLS ; comment").unwrap();
for i in parsed {
println!("RULE PAIR THING: {:?}", i);
}
let parsed = Chip8AsmParser::parse(Rule::record, "ADDI 0x01 ; comment");
for i in parsed {
println!("RULE PAIR THING: {:?}", i);
}
let parsed = Chip8AsmParser::parse(Rule::record, "ADDI ; comment");
for i in parsed {
println!("RULE PAIR THING: {:?}", i);
}
println!("PARSED: {:?}",
Chip8AsmParser::parse(Rule::record, "ADD 0x01 0x02 ; Comment")
);
println!("PARSED: {:?}",
Chip8AsmParser::parse(Rule::record, "ADD ADD ADD")
);
println!("PARSED: {:?}",
Chip8AsmParser::parse(Rule::record, "ADD 0x01 0x02 ; Comment")
);
println!("PARSED: {:?}",
Chip8AsmParser::parse(Rule::record, "ADD 0x01 0x02 ; Comment")
);
}
} }

View File

@ -18,7 +18,41 @@ struct DisassemblerApp {
struct Disassembler {} struct Disassembler {}
impl Disassembler { impl Disassembler {
pub fn disassemble(from_data: Vec<u8>) -> String { pub fn disassemble(from_data: Vec<u8>) -> String {
String::new() let mut working_instruction: u16 = 0x0000;
// read the input data and loop through it byte by byte.
let mut output_string = String::new();
for (offset, byte) in from_data.iter().enumerate() {
working_instruction = (working_instruction << 8) | (*byte as u16);
if offset % 2 != 0 {
let decoded = Chip8CpuInstructions::decode(working_instruction);
let decoded_string = decoded.to_string();
let mut current_parts = String::new();
match decoded {
XXXXERRORINSTRUCTION => {
current_parts = format!("DW 0x{:04x}", working_instruction);
}
_ => {
current_parts = format!("{}", decoded);
}
};
let target_length: i32 = 25;
let spacing_length = target_length.saturating_sub(current_parts.len() as i32);
// now add the rest after the string
let x = spacing_length as usize;
current_parts = format!("{}{:<x$}; Bytes [0x{:04x}] offset [0x{:04x}]\n", current_parts, " ", working_instruction, offset -1);
// println!("SHOULD OUTPUT: [{current_parts}]");
output_string = output_string.to_string() + &*current_parts.to_string();
working_instruction = 0x0000;
}
}
output_string
} }
} }
@ -26,51 +60,22 @@ fn main() {
println!("Taxation is Theft"); println!("Taxation is Theft");
let result = DisassemblerApp::parse(); let result = DisassemblerApp::parse();
println!("PREPARING TO DISASSEMBLE {:?}", result.input_file.file_name()); println!("PREPARING TO DISASSEMBLE {:?}", result.input_file.file_name());
// let target_file =
let source_file = result.input_file.to_str().unwrap(); let source_file = result.input_file.to_str().unwrap();
let mut working_instruction: u16 = 0x0000; let decompiled_program = Disassembler::disassemble(
std::fs::read(source_file).unwrap()
);
// read the input file and loop through it byte by byte.
let mut output_string = String::new();
for (offset, byte) in std::fs::read(source_file).unwrap().iter().enumerate() {
working_instruction = (working_instruction << 8) | (*byte as u16);
if offset % 2 != 0 {
let decoded = Chip8CpuInstructions::decode(working_instruction);
let decoded_string = decoded.to_string();
let mut current_parts = String::new();
match decoded {
XXXXERRORINSTRUCTION => {
current_parts = format!("DW 0x{:04x}", working_instruction);
}
_ => {
current_parts = format!("{}", decoded);
}
};
let target_length: i32 = 25;
let spacing_length = target_length.saturating_sub(current_parts.len() as i32);
// now add the rest after the string
let x = spacing_length as usize;
current_parts = format!("{}{:<x$}; Bytes [0x{:04x}] offset [0x{:04x}]\n", current_parts, " ", working_instruction, offset -1);
// println!("SHOULD OUTPUT: [{current_parts}]");
output_string = output_string.to_string() + &*current_parts.to_string();
working_instruction = 0x0000;
}
}
match result.output_file { match result.output_file {
None => { None => {
println!("Output to console."); println!("Output to console.");
println!("OS: \n\n{}", output_string); println!("OS: \n\n{}", decompiled_program);
} }
Some(target) => { Some(target) => {
println!("Output to {:?}", target); println!("Output to {:?}", target);
std::fs::write(target, output_string).unwrap(); std::fs::write(target, decompiled_program).unwrap();
} }
} }
} }

View File

@ -0,0 +1,7 @@
WHITESPACE = _{ " " }
instruction = { ASCII_ALPHA+ }
parameter = { "0X" ~ ASCII_HEX_DIGIT+ }
comment = { ";" ~ WHITESPACE* ~ ASCII* }
parameters = { parameter ~ (WHITESPACE* ~ "," ~ WHITESPACE* ~ parameter)* }
record = { instruction ~ WHITESPACE ~ parameters? ~ WHITESPACE* ~ comment? }
file = { SOI ~ (record ~ ("\r\n" | "\n"))* ~ EOI }