From e176ee56385a7ba26fa6f55426f24e86bc26bb0d Mon Sep 17 00:00:00 2001 From: Trevor Merritt Date: Thu, 10 Oct 2024 10:19:34 -0400 Subject: [PATCH] 8xy4 and 8xy5 pass. more flag tests passing removes legacy code moves 'gemmaemu' into 'gemma' crate moves 'gemmaimgui' into its own crate update to gemma --- Cargo.lock | 40 +- Cargo.toml | 2 +- chip8_core/Cargo.toml | 9 - chip8_core/src/chip8_constants.rs | 21 - chip8_core/src/chip8_mnemonics.rs | 207 -------- chip8_core/src/lib.rs | 8 - chip8_core/src/parts/CPU.rs | 461 ------------------ chip8_core/src/parts/Display.rs | 27 - chip8_core/src/parts/Keyboard.rs | 82 ---- chip8_toy/Cargo.lock | 7 - chip8_toy/Cargo.toml | 19 - chip8_toy/src/app.rs | 15 - chip8_toy/src/gui/display.rs | 69 --- chip8_toy/src/lib.rs | 7 - chip8_toy/src/main.rs | 143 ------ chip8_toy/src/support/clipboard.rs | 18 - chip8_toy/src/support/mod.rs | 164 ------- gemma/Cargo.toml | 2 +- gemma/src/bin/emma.rs | 168 ------- gemma/src/bin/font/text_rendering.rs | 40 -- gemma/src/chip8/computer.rs | 9 +- gemma/src/chip8/instructions.rs | 160 ++++-- gemma/src/chip8/keypad.rs | 3 - gemma/src/chip8/registers.rs | 4 - gemma/src/chip8/sound_timer.rs | 2 - gemma/src/chip8/system_memory.rs | 13 +- gemma/src/chip8/util.rs | 2 +- gemma/tests/computer_tests.rs | 3 +- gemmaegui/Cargo.toml | 2 +- gemmaegui/src/bin/gemmaegui.rs | 2 +- gemmaimgui/Cargo.toml | 20 + .../src/bin/gemmaimgui.rs | 8 +- .../src/bin/support/clipboard.rs | 0 .../src/bin/support/emmagui_support.rs | 6 +- {gemma => gemmaimgui}/src/bin/support/mod.rs | 0 35 files changed, 191 insertions(+), 1552 deletions(-) delete mode 100644 chip8_core/Cargo.toml delete mode 100644 chip8_core/src/chip8_constants.rs delete mode 100644 chip8_core/src/chip8_mnemonics.rs delete mode 100644 chip8_core/src/lib.rs delete mode 100644 chip8_core/src/parts/CPU.rs delete mode 100644 chip8_core/src/parts/Display.rs delete mode 100644 chip8_core/src/parts/Keyboard.rs delete mode 100644 chip8_toy/Cargo.lock delete mode 100644 chip8_toy/Cargo.toml delete mode 100644 chip8_toy/src/app.rs delete mode 100644 chip8_toy/src/gui/display.rs delete mode 100644 chip8_toy/src/lib.rs delete mode 100644 chip8_toy/src/main.rs delete mode 100644 chip8_toy/src/support/clipboard.rs delete mode 100644 chip8_toy/src/support/mod.rs delete mode 100644 gemma/src/bin/emma.rs delete mode 100644 gemma/src/bin/font/text_rendering.rs create mode 100644 gemmaimgui/Cargo.toml rename gemma/src/bin/emmagui.rs => gemmaimgui/src/bin/gemmaimgui.rs (94%) rename {gemma => gemmaimgui}/src/bin/support/clipboard.rs (100%) rename {gemma => gemmaimgui}/src/bin/support/emmagui_support.rs (98%) rename {gemma => gemmaimgui}/src/bin/support/mod.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index ccf2087..accce1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1646,16 +1646,7 @@ dependencies = [ ] [[package]] -name = "gemmaegui" -version = "0.1.0" -dependencies = [ - "eframe", - "egui", - "gemmaemu", -] - -[[package]] -name = "gemmaemu" +name = "gemma" version = "0.1.0" dependencies = [ "beep", @@ -1674,6 +1665,35 @@ dependencies = [ "winit 0.27.5", ] +[[package]] +name = "gemmaegui" +version = "0.1.0" +dependencies = [ + "eframe", + "egui", + "gemma", +] + +[[package]] +name = "gemmaimgui" +version = "0.1.0" +dependencies = [ + "beep", + "chrono", + "copypasta", + "dimensioned", + "gemma", + "glium", + "image 0.23.14", + "imgui", + "imgui-glium-renderer", + "imgui-winit-support", + "log", + "pretty_env_logger", + "rand 0.9.0-alpha.2", + "winit 0.27.5", +] + [[package]] name = "generic-array" version = "0.14.7" diff --git a/Cargo.toml b/Cargo.toml index 4f8c90e..8f72452 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,4 @@ [workspace] -members = ["gemma", "gemmaegui"] +members = ["gemma", "gemmaegui", "gemmaimgui" ] resolver = "2" diff --git a/chip8_core/Cargo.toml b/chip8_core/Cargo.toml deleted file mode 100644 index e7f9fc8..0000000 --- a/chip8_core/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "trevors_chip8_core" -version = "0.1.0" -edition = "2021" - -[dependencies] -bitmask = "0.5.0" - -[lib] diff --git a/chip8_core/src/chip8_constants.rs b/chip8_core/src/chip8_constants.rs deleted file mode 100644 index bb8637f..0000000 --- a/chip8_core/src/chip8_constants.rs +++ /dev/null @@ -1,21 +0,0 @@ - -pub const CHIP8_MEMORY_SIZE: u16 = 0x1000; -pub const CHIP8_MEMORY_SIZE_USIZE: usize = 0x1000; - -pub const FONT_0: [u8; 5] = [0xF0, 0x90, 0x90, 0x90, 0xF0]; -pub const FONT_1: [u8; 5] = [0x20, 0x60, 0x20, 0x20, 0x70]; -pub const FONT_2: [u8; 5] = [0xF0, 0x10, 0xF0, 0x80, 0xF0]; -pub const FONT_3: [u8; 5] = [0xF0, 0x10, 0xF0, 0x10, 0xF0]; -pub const FONT_4: [u8; 5] = [0x90, 0x90, 0xF0, 0x10, 0x10]; -pub const FONT_5: [u8; 5] = [0xF0, 0x80, 0xF0, 0x10, 0xF0]; -pub const FONT_6: [u8; 5] = [0xF0, 0x80, 0xF0, 0x90, 0xF0]; -pub const FONT_7: [u8; 5] = [0xF0, 0x10, 0x20, 0x40, 0x40]; -pub const FONT_8: [u8; 5] = [0xF0, 0x90, 0xF0, 0x90, 0xF0]; -pub const FONT_9: [u8; 5] = [0xF0, 0x90, 0xF0, 0x10, 0xF0]; -pub const FONT_A: [u8; 5] = [0xF0, 0x90, 0xF0, 0x90, 0x90]; -pub const FONT_B: [u8; 5] = [0xE0, 0x90, 0xE0, 0x90, 0xE0]; -pub const FONT_C: [u8; 5] = [0xF0, 0x80, 0x80, 0x80, 0xF0]; -pub const FONT_D: [u8; 5] = [0xE0, 0x90, 0x90, 0x90, 0xE0]; -pub const FONT_E: [u8; 5] = [0xF0, 0x80, 0xF0, 0x80, 0xF0]; -pub const FONT_F: [u8; 5] = [0xF0, 0x80, 0xf0, 0x80, 0x80]; - diff --git a/chip8_core/src/chip8_mnemonics.rs b/chip8_core/src/chip8_mnemonics.rs deleted file mode 100644 index eb12cf2..0000000 --- a/chip8_core/src/chip8_mnemonics.rs +++ /dev/null @@ -1,207 +0,0 @@ -use bitmask::bitmask; - -use crate::{chip8_constants::CHIP8_MEMORY_SIZE, parts::Display::Chip8Display}; - -enum Chip8StartOffset { - STANDARD, - ETI600, - OTHER, -} - -struct Chip8Registers { - V: [u8; 16], - I: u16, - DelayTimer: u16, - SoundTimer: u16, - StackPointer: u8, - ProgramCounter: u16, -} - -impl Default for Chip8Registers { - fn default() -> Self { - Chip8Registers { - DelayTimer: 60, - V: [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - ], - I: 0x00, - SoundTimer: 60, - StackPointer: 255, - ProgramCounter: 0x200, - } - } -} - -enum Chip8Instruction { - SYS(u16), - CLS, - RET, - JMP(u16), - CALL(u16), - SNEQ(u8, u16), - SNNE(u8, u8), - SNRE(u8, u8), - STOR(u8, u16), - ADD(u8, u16), - MOV(u8, u8), - OR(u8, u8), - AND(u8, u8), - XOR(u8, u8), - ADC(u8, u8), - SBC(u8, u8), - RSR(u8, u8), - LSR(u8, u8), - SNE(u8, u8), - STO(i16), - JMPI(u16), - RND(u8, u8), - SETD(u8), - SETT(u8), - BCD(u8), -} - -enum Chip8Keys { - KEY0, - KEY1, - KEY2, - KEY3, - KEY4, - KEY5, - KEY6, - KEY7, - KEY8, - KEY9, - KEYA, - KEYB, - KEYC, - KEYD, - KEYE, - KEYF, -} - -pub fn display_video_memory(system_memory: [u8; CHIP8_MEMORY_SIZE as usize]) { - // Assumes memory addresses from -} - -const ZERO: u16 = 0b0000000000000000; -const BOTTOM_BYTE: u16 = 0b0000000011111111; -const TOP_BYTE: u16 = 0b1111111100000000; -const NIBBLE0: u16 = 0b1111000000000000; -const NIBBLE1: u16 = 0b0000111100000000; -const NIBBLE2: u16 = 0b0000000011110000; -const NIBBLE3: u16 = 0b0000000000001111; -const NIBBLE0_BALANCE: u16 = 0x0FFF; -const PMSK_0000: i16 = 0x0000; -const PMSK_00X0: i16 = 0x00F0; -const PMSK_0X00: i16 = 0x0F00; -const PMSK_0XXX: i16 = 0x0FFF; - -// AND against the possible operand to find which one we have -bitmask! { - mask Chip8Instructions: u16 where flags Chip8InstructionFlags { - SYS = 0x00, - CLR = 0b0000000011100000, - RTS = 0b0000000011101110, - JUMP = 0b0001000000000000, - CALL = 0b0010000000000000, - SKE = 0b0011000000000000, - SKNE = 0b0100000000000000, - SKRE = 0b0101000000000000, - LOAD = 0b0110000000000000, - ADD = 0b0111000000000000, - MOVE = 0b1000000000000000, - OR = 0b1000000000000001, - AND = 0b1000000000000010, - XOR = 0b1000000000000011, - ADDR = 0b1000000000000100, - SUB = 0b1000000000000101, - SHR = 0b1000000000000110, - SHL = 0b1000000000001110, - SKRNE = 0b1001000000000000, - LOADI = 0b1010000000000000, - JUMPI = 0b1011000000000000, - RAND = 0b1100000000000000, - DRAW = 0b1101000000000000, - SKPR = 0b1110000000001110, - SKUP = 0b1111000010100001, - MOVED = 0b1111000000000111, - KEYD = 0b1111000000001010, - LOADD = 0b1111000000010101, - LOADS = 0b1111000000011000, - ADDI = 0b1111000000011110, - LDSPR = 0b1111000000101001, - BCD = 0b1111000000110011, - STOR = 0b1111000001010101, - MEMCPY = 0b1111000001100101 - } -} - -enum Chip8Asm { - SYS(u16), - CLR(), - RTS(), - JUMP(u16), - CALL(u16), - SKE(u8, u8), - SKNE(u8, u8), - SKRE(u8, u8), - LOAD(u8, u8), - ADD(u8, u8), - MOVE(u8, u8), - OR(u8, u8), - AND(u8, u8), - XOR(u8, u8), - ADDR(u8, u8), - SUB(u8, u8), - SHR(u8, u8), - SHL(u8, u8), - SKRNE(u8, u8), - LOADI(u16), - JUMPI(u16), - RAND(u8, u8), - DRAW(u8, u8, u8), - SKPR(u8), - SKUP(u8), - MOVED(u8), - KEYD(u8), - LOADD(u8), - LOADS(u8), - ADDI(u8), - LDSPR(u8), - BCD(u8), - STOR(u8), - READ(u8), -} - -struct Chip8Cpu {} - -struct Chip8System { - registers: Chip8Registers, - system_memory: [u8; 2048] -} - -impl Chip8System { - pub fn tick(mut self) { - println!(" Ticking Chip8System"); - - let next_instruction = self.system_memory[self.registers.ProgramCounter as usize] as u16; - println!("READ INSTRUCTION {next_instruction}"); - self.registers.ProgramCounter += 0x2; - - &self.delay_timer_tick(); - &self.sound_timer_tick(); - - // self.screen.tick(); - } - - fn delay_timer_tick(&mut self) { - self.registers.DelayTimer = self.registers.DelayTimer - 1; - - } - - fn sound_timer_tick(&mut self) { - self.registers.SoundTimer = self.registers.SoundTimer - 1; - - } -} diff --git a/chip8_core/src/lib.rs b/chip8_core/src/lib.rs deleted file mode 100644 index 74c7582..0000000 --- a/chip8_core/src/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub mod chip8_mnemonics; -pub mod chip8_constants; - -pub mod parts { - pub mod CPU; - pub mod Display; - pub mod Keyboard; -} \ No newline at end of file diff --git a/chip8_core/src/parts/CPU.rs b/chip8_core/src/parts/CPU.rs deleted file mode 100644 index e0ca010..0000000 --- a/chip8_core/src/parts/CPU.rs +++ /dev/null @@ -1,461 +0,0 @@ -struct Chip8Registers { - -} - - -impl Chip8Registers { - pub fn tick(self: &Self) { - println!("Ticking Registers"); - } -} - -pub struct Chip8InstructionParameter { - pub mask: u16 -} - -pub struct Chip8Instruction { - pub id: String, - pub mask: u16, - pub pattern: u16, - pub arguments: Vec, - pub description: Box -} - -pub fn fill_chip8_instructions() -> [Chip8Instruction; 34] { - [ - Chip8Instruction { - id: "SYS".to_string(), - mask: 0x00, - pattern: 0x00, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0FFF - } - ], - description: "Execute method at address referenced by parameter".into() - }, - Chip8Instruction { - id: "CLR".to_string(), - mask: 0x00E0, - pattern: 0x00E0, - arguments: vec![], - description: "Clear the Screen".into() - }, - Chip8Instruction { - id: "RET".to_string(), - mask: 0x00EE, - pattern: 0x00EE, - arguments: vec![], - description: "Return from Subroutine".into() - }, - Chip8Instruction { - id: "JMP".to_string(), - mask: 0x1FFF, - pattern: 0x1000, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0fff - } - ], - description: "Jump to specified location".into() - }, - Chip8Instruction { - id: "SEQ".to_string(), - mask: 0x3FFF, - pattern: 0x3000, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00ff - } - ], - description: "Skip next instruction if Register does equal parameter".into() - }, - Chip8Instruction { - id: "SNE".to_string(), - mask: 0x4FFF, - pattern: 0x4000, - arguments: vec! [ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00ff - } - ], - description: "Skip next instruction if Register doesn't equal parameter".into() - }, - Chip8Instruction { - id: "SREQ".to_string(), - mask: 0x5FF0, - pattern: 0x5000, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00f0 - } - ], - description: "TBD".into() - }, - Chip8Instruction { - id: "STO".to_string(), - mask: 0x6FFF, - pattern: 0x6000, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00ff - } - ], - description: "Store value into register".into() - }, - Chip8Instruction { - id: "ADD".to_string(), - mask: 0x7FFF, - pattern: 0x7000, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00ff - } - ], - description: "Add value in register 0x0f00 with value 0x00ff".into() - }, - Chip8Instruction { - id: "CPY".to_string(), - mask: 0x8FF0, - pattern: 0x8000, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00f0 - } - ], - description: "Copy value between Register X and Y".into() - }, - Chip8Instruction { - id: "OR".to_string(), - mask: 0x8FF1, - pattern: 0x8001, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00f0 - } - ], - description: "Logical OR of registers placing result in first register".into() - }, - Chip8Instruction { - id: "AND".to_string(), - mask: 0x8FF2, - pattern: 0x8002, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00f0 - } - ], - description: "Logical AND of registers placing result in first register".into() - }, - Chip8Instruction { - id: "XOR".to_string(), - mask: 0x8FF3, - pattern: 0x8003, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00f0 - } - ], - description: "Logical XOR of registers placing result in first register".into() - }, - Chip8Instruction { - id: "ADC".to_string(), - mask: 0x8FF4, - pattern: 0x8004, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00f0 - } - ], - description: "Add 2 Registers with carry flag".into() - }, - Chip8Instruction { - id: "SUBC".to_string(), - mask: 0x8FF5, - pattern: 0x8005, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00f0 - } - ], - description: "Subtract 2 Registers with carry flag".into() - }, - Chip8Instruction { - id: "RSR".to_string(), - mask: 0x8FF6, - pattern: 0x8006, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00f0 - } - ], - description: "Register Shifted Right".into() - }, - Chip8Instruction { - id: "SUBC".to_string(), - mask: 0x8FF7, - pattern: 0x8007, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00f0 - } - ], - description: "Subtract 2 Regiters with Carry".into() - }, - Chip8Instruction { - id: "RSL".to_string(), - mask: 0x8FFE, - pattern: 0x800E, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00f0 - } - ], - description: "Register Shifted Left".into() - }, - Chip8Instruction { - id: "SRNE".to_string(), - mask: 0x9FF0, - pattern: 0x9000, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00f0 - } - ], - description: "Skip next instruction if registers not equal".into() - }, - Chip8Instruction { - id: "LDI".to_string(), - mask: 0xAFFF, - pattern: 0xA000, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0fff - } - ], - description: "Load Data from Memory Address".into() - }, - Chip8Instruction { - id: "JMPI".to_string(), - mask: 0xBFFF, - pattern: 0xB000, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0fff - } - ], - description: "Jump to Memory Address".into() - }, - Chip8Instruction { - id: "RNG".to_string(), - mask: 0xCFFF, - pattern: 0xC000, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00ff - } - ], - description: "Random number Generator".into() - }, - Chip8Instruction { - id: "SPR".to_string(), - mask: 0xDFFF, - pattern: 0xD000, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - }, - Chip8InstructionParameter { - mask: 0x00f0 - }, - Chip8InstructionParameter { - mask: 0x000f - } - - ], - description: "TBD".into() - }, - Chip8Instruction { - id: "JNK".to_string(), - mask: 0xEF9E, - pattern: 0xE09E, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - } - ], - description: "Jump over next instruction if Key Pressed".into() - }, - Chip8Instruction { - id: "JKP".to_string(), - mask: 0xEFA1, - pattern: 0xE0A1, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - } - ], - description: "Jump over next instruction if Key Not Pressed".into() - }, - Chip8Instruction { - id: "SDT".to_string(), - mask: 0xFF07, - pattern: 0xF007, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0F00 - } - ], - description: "TBD".into() - }, - Chip8Instruction { - id: "WKP".to_string(), - mask: 0xFF0A, - pattern: 0xF00A, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - } - ], - description: "Wait for a Key to be pressed".into() - }, - Chip8Instruction { - id: "LDT".to_string(), - mask: 0xFF15, - pattern: 0xF015, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - } - ], - description: "Load Data Timer".into() - }, - Chip8Instruction { - id: "LST".to_string(), - mask: 0xFF18, - pattern: 0xF018, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - } - ], - description: "Load Sound Timer".into() - }, - Chip8Instruction { - id: "ADDI".to_string(), - mask: 0xFF1E, - pattern: 0xF01E, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - } - ], - description: "Add register with value at I".into() - }, - Chip8Instruction { - id: "SETI".to_string(), - mask: 0xFF29, - pattern: 0xF029, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - } - ], - description: "TBD".into() - }, - Chip8Instruction{ - id: "BCD".to_string(), - mask: 0xFF33, - pattern: 0xF033, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - } - ], - description: "Binary Coded Decimal of register".into() - }, - Chip8Instruction{ - id: "MSTO".to_string(), - mask: 0xFF55, - pattern: 0xF055, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - } - ], - description: "Store value in register X at offset I".into() - }, - Chip8Instruction { - id: "MLOAD".to_string(), - mask: 0xFF65, - pattern: 0xF065, - arguments: vec![ - Chip8InstructionParameter { - mask: 0x0f00 - } - ], - description: "Load value into register X at offset I".into() - } - ] -} - - -struct Chip8System { - -} - -impl Chip8System { - -} - -trait CpuInstruction { - fn execute(input: Chip8System) -> Chip8System; -} \ No newline at end of file diff --git a/chip8_core/src/parts/Display.rs b/chip8_core/src/parts/Display.rs deleted file mode 100644 index 4ba3222..0000000 --- a/chip8_core/src/parts/Display.rs +++ /dev/null @@ -1,27 +0,0 @@ - -pub struct Chip8Display { - // 64w x 32h - pub memory: [bool; 512], -} - -impl Chip8Display { - pub fn tick(self: &Self) { - println!("Ticking the display"); - } - - pub fn render_chip8_display(to_render: Chip8Display) { - // 32 rows... - for index_row in 0..=32 { - // ...64 columns - for index_col in 0..=64 { - let offset = (index_row * 64) + index_col; - if to_render.memory[offset] { - print!("*") - } else { - print!(" ") - }; - } - println!(); - } - } -} diff --git a/chip8_core/src/parts/Keyboard.rs b/chip8_core/src/parts/Keyboard.rs deleted file mode 100644 index 181135d..0000000 --- a/chip8_core/src/parts/Keyboard.rs +++ /dev/null @@ -1,82 +0,0 @@ - -#[derive(Clone)] -struct Chip8Keyboard { - keys_state: [bool; 16] -} - -impl Default for Chip8Keyboard { - fn default() -> Self { - Self { keys_state: [ - false, false, false, false, - false, false, false, false, - false, false, false, false, - false, false, false, false - ] } - } -} - -impl Chip8Keyboard { - - fn display_keyboard_key(self: Self, key_id: u8) { - let filler = if self.is_pressed(key_id) { "*" } else { " " }; - print!("{}{}{}", filler, key_id, filler) - } - - fn display_keyboard_horizontal_line(self: Self, row_values: [u8; 4]) { - print!("|"); - for current in row_values { - self.clone().display_keyboard_key(current); - print!("|"); - } - println!(); - } - - fn display_keyboard_seperator_line(self: Self) { - println!("+---+---+---+---+"); - - } - - pub fn display_keyboard(self: Self) { - self.clone().display_keyboard_seperator_line(); - self.clone().display_keyboard_horizontal_line( - [1,2,3,0xC] - ); - println!("+---+---+---+---+"); - println!("| 4 | 5 | 6 | D |"); - println!("+---+---+---+---+"); - println!("| 7 | 8 | 9 | E |"); - println!("+---+---+---+---+"); - println!("| A | 0 | B | F |"); - println!("+---+---+---+---+"); - } - - pub fn press_key(self: &mut Self, key_id: u8) { - self.keys_state[key_id as usize] = true; - } - - pub fn release_key(self: &mut Self, key_id: u8) { - self.keys_state[key_id as usize] = false; - } - - pub fn is_pressed(self: Self, key_id: u8) -> bool { - self.keys_state[key_id as usize] - } -} - - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn smoke_test() { - assert_eq!(true, true); - } - - #[test] - fn basic_keyboard_display_works() { - let basic_keyboard = Chip8Keyboard::default(); - - - } -} \ No newline at end of file diff --git a/chip8_toy/Cargo.lock b/chip8_toy/Cargo.lock deleted file mode 100644 index 6e32adb..0000000 --- a/chip8_toy/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "trevors_chip8_toy" -version = "0.1.0" diff --git a/chip8_toy/Cargo.toml b/chip8_toy/Cargo.toml deleted file mode 100644 index 58f4052..0000000 --- a/chip8_toy/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "trevors_chip8_toy" -version = "0.1.0" -edition = "2021" - -[dependencies] -trevors_chip8_core = { path = "../chip8_core" } -log ="0.4" -glutin = "0.32" -glutin-winit = { version = "0.5", optional = true } -raw-window-handle = "0.6" -arboard = { version = "3", optional = true, default-features = false } -winit = { version = "0.30", features = ["x11", "mint"] } -copypasta = "0.10.1" -glium = { version = "0.34.0", default-features = true } -image = "0.25.2" -imgui = { version = "0.12.0", features = ["tables-api"] } -imgui-glium-renderer = "0.12.0" -imgui-winit-support = "0.12.0" diff --git a/chip8_toy/src/app.rs b/chip8_toy/src/app.rs deleted file mode 100644 index 8c9649a..0000000 --- a/chip8_toy/src/app.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* - -#[derive(Default)] -pub struct App; - -impl UiBuilder for App { - fn do_ui(&mut self, ui: &Ui) { - #[cfg(feature = "docking")] - { - ui.dock_space_over_viewport(0, imgui::DockNodeFlags::None); - } - ui.show_demo_window(None); - - } -}*/ \ No newline at end of file diff --git a/chip8_toy/src/gui/display.rs b/chip8_toy/src/gui/display.rs deleted file mode 100644 index 751a5ef..0000000 --- a/chip8_toy/src/gui/display.rs +++ /dev/null @@ -1,69 +0,0 @@ -use winit::{application::ApplicationHandler, event_loop::ActiveEventLoop, window::{Window, WindowAttributes}}; - -/* -pub struct Chip8Display { - pub window: MainWindowWithRenderer, -} - -impl Chip8Display { - pub fn new(event_loop: &ActiveEventLoop) -> Chip8Display { - Chip8Display { window: MainWindowWithRenderer::new( - MainWindow::new::<()>(&event_loop, Window::default_attributes().with_title("Chip8 Display")).unwrap()) - } - } - - pub fn render(ui: &Ui) { - - } -} - -impl UiBuilder for Chip8AppHandler { - fn do_ui(&mut self, ui: &Ui) { - - ui.text("This is where the Chip8 UI Goes"); - ui.text("Controls for Start/Stop/Load/Run Maybe?"); - - - } -} - -#[derive(Default)] -pub struct Chip8AppHandler { - pub windows: Vec, - // pub display: Chip8Display -} - -impl ApplicationHandler for Chip8AppHandler { - fn suspended(&mut self, _event_loop: &ActiveEventLoop) { - self.windows.clear(); - } - - fn resumed(&mut self, event_loop: &ActiveEventLoop) { - self.windows.push(Chip8Display::new(event_loop).window); - } - - fn window_event( - &mut self, - event_loop: &ActiveEventLoop, - window_id: winit::window::WindowId, - event: winit::event::WindowEvent, - ) { - for window in &mut self.windows { - if window.main_window().window().id() != window_id { - continue; - } - } - } - fn new_events(&mut self, _event_loop: &ActiveEventLoop, _cause: winit::event::StartCause) { - for window in &mut self.windows { - window.new_events(); - } - } - fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) { - for window in &mut self.windows { - window.about_to_wait(); - } - } - -} -*/ \ No newline at end of file diff --git a/chip8_toy/src/lib.rs b/chip8_toy/src/lib.rs deleted file mode 100644 index f06c689..0000000 --- a/chip8_toy/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod app; - -pub mod gui { - pub mod display; -} - -pub mod support; \ No newline at end of file diff --git a/chip8_toy/src/main.rs b/chip8_toy/src/main.rs deleted file mode 100644 index 03a15d1..0000000 --- a/chip8_toy/src/main.rs +++ /dev/null @@ -1,143 +0,0 @@ -use trevors_chip8_core::parts::CPU::fill_chip8_instructions; -use trevors_chip8_toy::support; -use winit::{event::WindowEvent, event_loop::EventLoop}; - -use imgui::*; -/* -pub fn display_instruction_table(current_index: u32, ui: &Ui) -> u32 { - let to_display = fill_chip8_instructions(); - let mut return_index = current_index; - let current_instruction = to_display.get(return_index as usize).unwrap(); - ui.text("Instructions"); - ui.set_next_item_width(100f32); - ui.with_group(|| { - ui.text(format!("{}", current_instruction.description).as_str()); - if current_instruction.arguments.is_empty() { - ui.text("No Parameters"); - } else { - for current_parameter in current_instruction.arguments { - ui.text(format!("{}", current_parameter.mask).as_str()); - } - } - ui.text(format!("{:#}", current_instruction.arguments).as_str()); - ui.text("This is where cool stuff happens part 2"); - }); - ui.same_line(); - ui.with_group(|| { - for (index, current) in to_display.iter().enumerate() { - if ui - .selectable_config(current.id.clone()) - .selected(index == return_index as usize) - .build() - { - return_index = index as u32; - } - } - }); - return_index -} -*/ - -fn chip8_instructions(initial_index: u32, ui: &mut Ui) -> u32 { - let to_display = fill_chip8_instructions(); - let mut return_index = initial_index; - let instruction_to_display = to_display.get(return_index as usize).unwrap(); - let instruction_window = ui - .window("Instructions") - .size([400.0, 400.0], Condition::FirstUseEver) - .build(|| { - ui.text("This should be my current instruction example"); - ui.same_line(); - ui.set_next_item_width(-1.0f32); - for (index, instruction) in to_display.iter().enumerate() { - if ui - .selectable_config(instruction.id.to_string()) - .selected(index as u32 == return_index) - .build() - { - return_index = index as u32; - println!("RETURN INDEX {return_index}"); - } - } - }); - return_index -} - -fn main() { - let mut value = 0; - let choices = ["test test this is 1", "test test this is 2"]; - - let mut selected_instruction = 0; - - support::simple_init(file!(), move |_, ui| { - selected_instruction = chip8_instructions(selected_instruction, ui); - - ui.window("Hello world") - .size([300.0, 110.0], Condition::FirstUseEver) - .build(|| { - ui.text_wrapped("Hello world!"); - if ui.button(choices[value]) { - value += 1; - value %= 2; - } - - ui.button("This...is...imgui-rs!"); - ui.separator(); - let mouse_pos = ui.io().mouse_pos; - ui.text(format!( - "Mouse Position: ({:.1},{:.1})", - mouse_pos[0], mouse_pos[1] - )); - }); - }); -} -/* -fn main() { - let event_loop = EventLoop::new().unwrap(); - - let mut main = AppHandler::::default(); - main.attributes().title = String::from("Example-420"); - - event_loop.run_app(&mut main).unwrap(); -} - -#[derive(Default)] -pub struct App { - pub selected_instruction_index: u32, -} - -impl App {} - -impl Application for App { - type UserEvent = (); - type Data = (); - fn new(_: Args<()>) -> App { - App { - selected_instruction_index: 0, - } - } - fn window_event(&mut self, args: Args<()>, _event: WindowEvent, res: EventResult) { - if res.window_closed { - args.event_loop.exit(); - } - } -} - -impl imgui::UiBuilder for App { - fn do_ui(&mut self, ui: &imgui::Ui) { - #[cfg(feature = "docking")] - { - ui.dock_space_over_viewport(0, imgui::DockNodeFlags::None); - } - - let x = ui.collapsing_header_config("collapsing header"); - - ui.with_group(|| { - self.selected_instruction_index = - display_instruction_table(self.selected_instruction_index, ui); - }); - - ui.show_demo_window(None); - } -} -*/ diff --git a/chip8_toy/src/support/clipboard.rs b/chip8_toy/src/support/clipboard.rs deleted file mode 100644 index dd74d06..0000000 --- a/chip8_toy/src/support/clipboard.rs +++ /dev/null @@ -1,18 +0,0 @@ -use copypasta::{ClipboardContext, ClipboardProvider}; -use imgui::ClipboardBackend; - -pub struct ClipboardSupport(pub ClipboardContext); - -pub fn init() -> Option { - ClipboardContext::new().ok().map(ClipboardSupport) -} - -impl ClipboardBackend for ClipboardSupport { - fn get(&mut self) -> Option { - self.0.get_contents().ok() - } - fn set(&mut self, text: &str) { - // ignore errors? - let _ = self.0.set_contents(text.to_owned()); - } -} diff --git a/chip8_toy/src/support/mod.rs b/chip8_toy/src/support/mod.rs deleted file mode 100644 index 8a730ab..0000000 --- a/chip8_toy/src/support/mod.rs +++ /dev/null @@ -1,164 +0,0 @@ -use glium::glutin::surface::WindowSurface; -use glium::{Display, Surface}; -use imgui::{Context, FontConfig, FontGlyphRanges, FontSource, Ui}; -use imgui_glium_renderer::Renderer; -use imgui_winit_support::winit::dpi::LogicalSize; -use imgui_winit_support::winit::event::{Event, WindowEvent}; -use imgui_winit_support::winit::event_loop::EventLoop; -use imgui_winit_support::winit::window::WindowBuilder; -use imgui_winit_support::{HiDpiMode, WinitPlatform}; -use std::path::Path; -use std::time::Instant; - -mod clipboard; - -pub const FONT_SIZE: f32 = 13.0; - -#[allow(dead_code)] // annoyingly, RA yells that this is unusued -pub fn simple_init(title: &str, run_ui: F) { - init_with_startup(title, |_, _, _| {}, run_ui); -} - -pub fn init_with_startup(title: &str, mut startup: FInit, mut run_ui: FUi) -where - FInit: FnMut(&mut Context, &mut Renderer, &Display) + 'static, - FUi: FnMut(&mut bool, &mut Ui) + 'static, -{ - let mut imgui = create_context(); - - let title = match Path::new(&title).file_name() { - Some(file_name) => file_name.to_str().unwrap(), - None => title, - }; - let event_loop = EventLoop::new().expect("Failed to create EventLoop"); - - let builder = WindowBuilder::new() - .with_title(title) - .with_inner_size(LogicalSize::new(1024, 768)); - let (window, display) = glium::backend::glutin::SimpleWindowBuilder::new() - .set_window_builder(builder) - .build(&event_loop); - let mut renderer = Renderer::init(&mut imgui, &display).expect("Failed to initialize renderer"); - - if let Some(backend) = clipboard::init() { - imgui.set_clipboard_backend(backend); - } else { - eprintln!("Failed to initialize clipboard"); - } - - let mut platform = WinitPlatform::init(&mut imgui); - { - let dpi_mode = if let Ok(factor) = std::env::var("IMGUI_EXAMPLE_FORCE_DPI_FACTOR") { - // Allow forcing of HiDPI factor for debugging purposes - match factor.parse::() { - Ok(f) => HiDpiMode::Locked(f), - Err(e) => panic!("Invalid scaling factor: {}", e), - } - } else { - HiDpiMode::Default - }; - - platform.attach_window(imgui.io_mut(), &window, dpi_mode); - } - - let mut last_frame = Instant::now(); - - startup(&mut imgui, &mut renderer, &display); - - event_loop - .run(move |event, window_target| match event { - Event::NewEvents(_) => { - let now = Instant::now(); - imgui.io_mut().update_delta_time(now - last_frame); - last_frame = now; - } - Event::AboutToWait => { - platform - .prepare_frame(imgui.io_mut(), &window) - .expect("Failed to prepare frame"); - window.request_redraw(); - } - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - .. - } => { - let ui = imgui.frame(); - - let mut run = true; - run_ui(&mut run, ui); - if !run { - window_target.exit(); - } - - let mut target = display.draw(); - target.clear_color_srgb(1.0, 1.0, 1.0, 1.0); - platform.prepare_render(ui, &window); - let draw_data = imgui.render(); - renderer - .render(&mut target, draw_data) - .expect("Rendering failed"); - target.finish().expect("Failed to swap buffers"); - } - Event::WindowEvent { - event: WindowEvent::Resized(new_size), - .. - } => { - if new_size.width > 0 && new_size.height > 0 { - display.resize((new_size.width, new_size.height)); - } - platform.handle_event(imgui.io_mut(), &window, &event); - } - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => window_target.exit(), - event => { - platform.handle_event(imgui.io_mut(), &window, &event); - } - }) - .expect("EventLoop error"); -} - -/// Creates the imgui context -pub fn create_context() -> imgui::Context { - let mut imgui = Context::create(); - // Fixed font size. Note imgui_winit_support uses "logical - // pixels", which are physical pixels scaled by the devices - // scaling factor. Meaning, 13.0 pixels should look the same size - // on two different screens, and thus we do not need to scale this - // value (as the scaling is handled by winit) - imgui.fonts().add_font(&[ - FontSource::TtfData { - data: include_bytes!("../../../resources/Roboto-Regular.ttf"), - size_pixels: FONT_SIZE, - config: Some(FontConfig { - // As imgui-glium-renderer isn't gamma-correct with - // it's font rendering, we apply an arbitrary - // multiplier to make the font a bit "heavier". With - // default imgui-glow-renderer this is unnecessary. - rasterizer_multiply: 1.5, - // Oversampling font helps improve text rendering at - // expense of larger font atlas texture. - oversample_h: 4, - oversample_v: 4, - ..FontConfig::default() - }), - }, - FontSource::TtfData { - data: include_bytes!("../../../resources/mplus-1p-regular.ttf"), - size_pixels: FONT_SIZE, - config: Some(FontConfig { - // Oversampling font helps improve text rendering at - // expense of larger font atlas texture. - oversample_h: 4, - oversample_v: 4, - // Range of glyphs to rasterize - glyph_ranges: FontGlyphRanges::japanese(), - ..FontConfig::default() - }), - }, - ]); - imgui.set_ini_filename(None); - - imgui -} diff --git a/gemma/Cargo.toml b/gemma/Cargo.toml index b364cd8..288e83b 100644 --- a/gemma/Cargo.toml +++ b/gemma/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "gemmaemu" +name = "gemma" version = "0.1.0" edition = "2021" autobenches = true diff --git a/gemma/src/bin/emma.rs b/gemma/src/bin/emma.rs deleted file mode 100644 index d27d490..0000000 --- a/gemma/src/bin/emma.rs +++ /dev/null @@ -1,168 +0,0 @@ -use std::io::{stdout, Result}; -/* -use emmaemu::{chip8::{computer::Chip8Computer, video::Chip8Video}, constants::{CHIP8_MEMORY_SIZE, CHIP8_REGISTER_COUNT, CHIP8_ROM_SIZE, CHIP8_VIDEO_MEMORY}}; -use ratatui::{ - backend::CrosstermBackend, - crossterm::{ - event::{self, KeyCode, KeyEventKind}, - terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, - ExecutableCommand, - }, - layout::{Alignment, Rect}, - style::{Style, Stylize}, - widgets::{List, Paragraph, Widget}, - Frame, Terminal, -}; - - -fn system_memory_to_text_render(data_to_dump: [u8; 2048]) -> String { - let mut to_return = String::new(); - - for i in 0..256 { - to_return += &format!("{:x}\t", data_to_dump[i as usize]).to_string(); - - if ((i + 1) % CHIP8_REGISTER_COUNT) == 0 { - to_return += "\n"; - } - } - - to_return -} - -fn dump_memory_to_console(data_to_dump: [u8; 2048]) { - println!("STARTING TO DUMP MEMORY TO CONSOLE"); - println!("{}", system_memory_to_text_render(data_to_dump)); - println!("DONE DUMPING!"); - panic!("DONE DUMPING"); -} - -struct ControlKeyboard { - -} - -impl Widget for ControlKeyboard { - fn render(self, area: Rect, buf: &mut ratatui::prelude::Buffer) - where - Self: Sized { - let style = Style::new(); - buf.set_string(0, 0, "F1 to cycle foreground - F2 to cycle background", style) - } -} - - -#[derive(Clone)] -struct AppState { - pub menu_items: Vec, - pub selected_menu_item: i32, - pub system: Chip8Computer, -} - -impl Default for AppState { - fn default() -> Self { - println!("Creating new AppState"); - Self { - menu_items: vec![ - "Step CPU ".into(), - "Reset CPU ".into(), - "Item 3".into(), - ], - selected_menu_item: 0, - system: Chip8Computer { - ..Default::default() - }, - } - } -} - -fn main() -> Result<()> { - stdout().execute(EnterAlternateScreen)?; - enable_raw_mode()?; - let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; - terminal.clear()?; - - let app = AppState::default(); - - loop { - // Draw Ui... - terminal.draw(|frame| { - frame.render_widget(app.system.memory, frame.area()); - // frame.render_widget(app.control_keyboard, area); - //render_cpu_state(app.system.clone(), frame); - // render_video_state(app.system.video_memory, frame); - // render_menu_list(app.clone(), frame); - })?; - // ...handle Events. - if event::poll(std::time::Duration::from_millis(16))? { - if let event::Event::Key(key) = event::read()? { - match key.kind { - KeyEventKind::Press => match key.code { - KeyCode::F(5) => { - println!("Execute Next Instruction"); - } - KeyCode::F(12) => { - println!("Resetting CPU"); - } - KeyCode::Char('q') => { break; } - _ => (), - }, - _ => (), - } - } - } - } - - // stdout().execute(LeaveAlternateScreen)?; - // disable_raw_mode()?; - Ok(()) -} - -#[cfg(test)] -mod test { - use emmaemu::constants::{CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_WIDTH}; - - use crate::*; - #[test] - fn blank_screen_renders_to_text() { - let test_video = Chip8Video::default(); - - - let blank_data: [bool; CHIP8_VIDEO_MEMORY] = [false; CHIP8_VIDEO_MEMORY]; - let blank_screen = (" ".repeat(CHIP8_VIDEO_WIDTH.try_into().unwrap()) + "\n") - .repeat(CHIP8_VIDEO_HEIGHT.try_into().unwrap()); - - assert_eq!(Chip8Video::new(blank_data).format_as_string(), blank_screen); - } - - #[test] - fn filled_screen_renders_to_text() { - let filled_data: [bool; CHIP8_VIDEO_MEMORY] = [true; CHIP8_VIDEO_MEMORY]; - let filled_screen = ("*".repeat(CHIP8_VIDEO_WIDTH.try_into().unwrap()) + "\n") - .repeat(CHIP8_VIDEO_HEIGHT.try_into().unwrap()); - assert_eq!(Chip8Video::new(filled_data).format_as_string(), filled_screen); - } - - #[test] - fn grid_pattern_renders_to_text() { - let mut grid_data: [bool; CHIP8_VIDEO_MEMORY] = [false; CHIP8_VIDEO_MEMORY]; - let mut expected_data = String::new(); - for i in 0..CHIP8_VIDEO_MEMORY { - grid_data[i] = (i % 2 == 0); - if i % 2 == 0 { - grid_data[i] = true; - expected_data += "*"; - } else { - grid_data[i] = false; - expected_data += " "; - } - if (i as i32 % CHIP8_VIDEO_WIDTH as i32 == CHIP8_VIDEO_WIDTH - 1) { - expected_data += "\n"; - } - } - - assert_eq!(Chip8Video::new(grid_data).format_as_string(), expected_data); - } -} -*/ -fn main() { - println!("Taxation is theft"); -} \ No newline at end of file diff --git a/gemma/src/bin/font/text_rendering.rs b/gemma/src/bin/font/text_rendering.rs deleted file mode 100644 index 0781aea..0000000 --- a/gemma/src/bin/font/text_rendering.rs +++ /dev/null @@ -1,40 +0,0 @@ -use ratatui::{style::Stylize, widgets::{List, Paragraph}, Frame}; - -use crate::{AppState, Chip8Computer, CHIP8_REGISTER_COUNT, CHIP8_VIDEO_MEMORY}; - - -pub fn render_cpu_state(cpu_state: Chip8Computer, frame: &mut Frame) { - let mut area = frame.area(); - - let mut current_state: Vec = vec![]; - - current_state.push(format!("Delay Timer {:X}", cpu_state.delay_timer)); - current_state.push(format!("Sound Timer {:X}", cpu_state.sound_timer)); - current_state.push(format!("PC {:X}", cpu_state.pc)); - for i in 0 .. CHIP8_REGISTER_COUNT { - current_state.push(format!("V{}: {}", i, cpu_state.registers[i as usize])); - } - - frame.render_widget( - List::new(current_state).blue().on_white(), area) -} - -pub fn render_menu_list(state: AppState, frame: &mut Frame) { - let mut area = frame.area(); - - frame.render_widget(List::new(state.menu_items).blue().on_white(), area); -} - -pub fn render_hello_world(frame: &mut Frame) { - let area = frame.area(); - frame.render_widget( - Paragraph::new("Hello Ratatui! (press 'q' to quit)") - .white() - .on_blue(), - area, - ); -} - -pub fn render_video_state(video_memory: [bool; CHIP8_VIDEO_MEMORY], frame: &mut Frame) { - -} \ No newline at end of file diff --git a/gemma/src/chip8/computer.rs b/gemma/src/chip8/computer.rs index 05fa023..45c03d6 100644 --- a/gemma/src/chip8/computer.rs +++ b/gemma/src/chip8/computer.rs @@ -1,19 +1,14 @@ -use log::{debug, error}; +use log::{debug}; use crate::chip8::delay_timer::DelayTimer; -use crate::chip8::instructions::Chip8CpuInstructions::XXXXERRORINSTRUCTION; use crate::chip8::keypad::Keypad; use crate::chip8::registers::Chip8Registers; use crate::chip8::sound_timer::SoundTimer; use crate::chip8::stack::Chip8Stack; -use crate::chip8::util::InstructionUtil; -use crate::constants::{CHIP8_MEMORY_SIZE, CHIP8_REGISTER_COUNT}; use super::{ cpu_states::Chip8CpuStates, instructions::Chip8CpuInstructions, system_memory::Chip8SystemMemory, video::Chip8Video, }; -const STACK_POINTER_DEFAULT: i16 = 0x100; - #[derive(Clone)] pub struct Chip8Computer { pub memory: Chip8SystemMemory, @@ -85,7 +80,7 @@ impl Chip8Computer { debug!("Stepping System 1 Step"); // read the next instruction - let mut working_instruction: u16 = 0b0000000000000000; + // let mut working_instruction: u16 = 0b0000000000000000; let start_pc = self.registers.peek_pc(); let high_byte = (self.memory.clone().peek(start_pc) as u16).rotate_left(8); let low_byte = self.memory.clone().peek(start_pc + 1) as u16; diff --git a/gemma/src/chip8/instructions.rs b/gemma/src/chip8/instructions.rs index 4ca55d5..825e607 100644 --- a/gemma/src/chip8/instructions.rs +++ b/gemma/src/chip8/instructions.rs @@ -1,12 +1,10 @@ -use std::ops::{Shl, Shr}; -use imgui::ColorPicker3; +use std::ops::{BitAnd, Shl, Shr}; use log::debug; use rand::random; use crate::chip8::computer::{Chip8Computer}; use crate::chip8::cpu_states::Chip8CpuStates::WaitingForKey; use crate::chip8::instructions::Chip8CpuInstructions::XXXXERRORINSTRUCTION; use crate::chip8::util::InstructionUtil; -use crate::chip8::video::Chip8Video; /* nnn or addr - A 12-bit value, the lowest 12 bits of the instruction @@ -137,7 +135,7 @@ impl Chip8CpuInstructions { (0x2000 | (address & 0x0FFF)) as u16 } Chip8CpuInstructions::SeVxByte(vx_register, byte) => { - (0x3000 | (vx_register << 8 | byte) as u16) + 0x3000 | ((*vx_register as u16) << 8 | *byte as u16) as u16 } Chip8CpuInstructions::SneVxByte(vx_register, byte) => { 0x4000u16 | (*vx_register as u16) << 8 | *byte as u16 @@ -418,7 +416,7 @@ impl Chip8CpuInstructions { } } - pub fn execute(&self, mut input: &mut Chip8Computer) -> Chip8Computer { + pub fn execute(&self, input: &mut Chip8Computer) -> Chip8Computer { let start_pc = input.registers.peek_pc(); input.registers.poke_pc(start_pc + 2); let _ = match self { @@ -461,10 +459,18 @@ impl Chip8CpuInstructions { } // 0x4xkk Skip next instruction if Vx != kk Chip8CpuInstructions::SneVxByte(x, byte) => { - if input.registers.peek(*x as u8) != *byte as u8 { + // 4xkk - SNE Vx, byte + // Skip next instruction if Vx != kk. + // + // The interpreter compares register Vx to kk, and if they are not equal, + // increments the program counter by 2. + let lhs = input.registers.peek(*x); + let rhs = *byte; + + if lhs != rhs { input.registers.advance_pc(); } - debug!("SneVxByte [0x{x:1x}] [0x{byte:2x}"); + debug!("SneVxByte [0x{x:02x}] [0x{byte:02x}"); } // 0x5xy0 Skip next instruction if Vx == Vy Chip8CpuInstructions::SeVxVy(x, y) => { @@ -527,37 +533,54 @@ impl Chip8CpuInstructions { let lhs = input.registers.peek(*x as u8) as i16; let rhs = input.registers.peek(*y as u8) as i16; let working = lhs + rhs; - if working > 0xff { - input.registers.poke(0xf, 0x01); - } input.registers.poke(*x as u8, working as u8); + + if working >= 0x100 { + input.registers.poke(0xf, 0x01); + } else { + input.registers.poke(0x0f, 0x00); + } } Chip8CpuInstructions::SubVxVy(x, y) => { // 8xy5 - SUB Vx, Vy // Set Vx = Vx - Vy, set VF = NOT borrow. // // If Vx > Vy, then VF is set to 1, otherwise 0. Then Vy is subtracted from Vx, and the results stored in Vx. - let mut x_value: u16 = input.registers.peek(*x as u8) as u16; - let y_value = input.registers.peek(*y as u8); - // do we borrow? - if y_value >= x_value as u8 { - x_value += 256; - input.registers.poke(0xf, 1); + + let lhs = input.registers.peek(*x); + let rhs = input.registers.peek(*y); + + let mut result = 0; + + let borrow_flag: u8 = if rhs > lhs { + result = (lhs as u16 + 0x100) - rhs as u16; + 0 } else { - input.registers.poke(0xf, 0); - } - let result = (x_value - y_value as u16) as u8; - input.registers.poke(*x as u8, result); + result = lhs as u16 - rhs as u16; + 1 + }; + + input.registers.poke(*x as u8, result as u8); + input.registers.poke(0x0f, borrow_flag); } Chip8CpuInstructions::ShrVxVy(x, _) => { // 8xy6 - SHR Vx {, Vy} // Set Vx = Vx SHR 1. - // + // SHIFT 1 Bit ----> // If the least-significant bit of Vx is 1, then VF is set to 1, otherwise 0. Then Vx is divided by 2. let initial_value = input.registers.peek(*x as u8); - if 0xb1 & initial_value == 1 { - input.registers.poke(0xf, 1); + + // overflow check + + if initial_value.bitand(0b1) == 1 { + input.registers.poke(0x0f, 0x01); + } else { + input.registers.poke(0x0f, 0x00); } + + let rotated = initial_value >> 1; + println!("[{initial_value:80b}] / [{rotated:80b}]"); + input.registers.poke(*x as u8, initial_value.shr(1)); } Chip8CpuInstructions::SubnVxVy(x, y) => { @@ -567,14 +590,17 @@ impl Chip8CpuInstructions { // If Vy > Vx, then VF is set to 1, otherwise 0. Then Vx is subtracted from Vy, and the results stored in Vx. let y_register = input.registers.peek(*y as u8); let x_register = input.registers.peek(*x as u8); - let new_value = if y_register <= x_register { 1 } else { 0 }; - let value_to_poke = if y_register <= x_register { - ((y_register as u16 + 256) - x_register as u16) as u8 - } else { - y_register - x_register + let mut value_to_poke = 0; + + let new_value = if y_register <= x_register { + value_to_poke = (y_register as u16 + 256) - x_register as u16; + 1 } else { + value_to_poke = (y_register - x_register) as u16; + 0 }; + input.registers.poke(0xf, new_value); - input.registers.poke(*x as u8, value_to_poke); + input.registers.poke(*x as u8, value_to_poke as u8); } Chip8CpuInstructions::ShlVxVy(x, _) => { @@ -583,10 +609,13 @@ impl Chip8CpuInstructions { // // If the most-significant bit of Vx is 1, then VF is set to 1, otherwise to 0. Then Vx is multiplied by 2. let initial_value = input.registers.peek(*x as u8); - if 0x80 & initial_value == 0x80 { - input.registers.poke(0xf, 1); + let rotated = initial_value.shl(1); + if 0b10000000 & initial_value == 0b10000000 { + input.registers.poke(0x0f, 0x01); + } else { + input.registers.poke(0x0f, 0x00); } - input.registers.poke(*x as u8, initial_value.shl(1)); + input.registers.poke(*x as u8,rotated); } Chip8CpuInstructions::SneVxVy(vx_register, vy_register) => { // 9xy0 - SNE Vx, Vy @@ -624,7 +653,7 @@ impl Chip8CpuInstructions { // which is then ANDed with the value kk. // The results are stored in Vx. let new_value: u8 = random(); - input.registers.poke(*x as u8, (new_value & *byte as u8)) + input.registers.poke(*x as u8, new_value & *byte as u8) } Chip8CpuInstructions::DrawVxVyNibble(y,x, n) => { // Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision. @@ -762,8 +791,7 @@ impl Chip8CpuInstructions { let units = to_convert % 10; // Convert to BCD - let result = ((hundreds as u16) << 8) | units as u16; - (tens << 4) | units; + let result = ((hundreds as u16) << 8) | units as u16 | ((tens as u16) << 4) | units as u16; // write them to the memory pointed to by I, I+1, and I+2 let target_start_offset = input.registers.peek_i(); input.memory.poke(target_start_offset, hundreds); @@ -775,7 +803,6 @@ impl Chip8CpuInstructions { // // The interpreter copies the values of registers V0 through Vx into memory, // starting at the address in I. - let num_loops = x; let offset = input.registers.peek_i(); for i in 0..=*x { input.memory.poke(offset + i as u16, input.registers.peek(i as u8)); @@ -1461,4 +1488,65 @@ mod test { Chip8CpuInstructions::LdVxK(0x1).execute(&mut x); assert!(matches!(x.state, WaitingForKey)); } + + #[test] + fn series8xy4_corex_tests() { + /// 8xy4 + /// Set Vx = Vx + Vy + /// Set VF=1 if Carry + /// + + // 1 + 1 + let mut x = Chip8Computer::new(); + x.registers.poke(0x01, 0x01); + x.registers.poke(0x02, 0x01); + Chip8CpuInstructions::AddVxVy(0x01, 0x02).execute(&mut x); + assert_eq!(x.registers.peek(0x01), 0x02); + assert_eq!(x.registers.peek(0x0f), 0x00); + + // 255+1 + let mut x = Chip8Computer::new(); + x.registers.poke(0x01, 0xff); + x.registers.poke(0x02, 0x01); + Chip8CpuInstructions::AddVxVy(0x01, 0x02).execute(&mut x); + assert_eq!(x.registers.peek(0x01), 0x00); + assert_eq!(x.registers.peek(0x0f), 0x01); + + // 128+192 + let mut x = Chip8Computer::new(); + x.registers.poke(0x01, 128); + x.registers.poke(0x02, 192); + Chip8CpuInstructions::AddVxVy(0x01, 0x02).execute(&mut x); + assert_eq!(x.registers.peek(0x01), 64); + assert_eq!(x.registers.peek(0x0f), 1); + } + + #[test] + fn series8xy6_corex_tests() { + // 8xy6 - SHR Vx {, Vy} + // Set Vx = Vx SHR 1. + // + // If the least-significant bit of Vx is 1, then VF is set to 1, + // otherwise 0. Then Vx is divided by 2. + let mut x = Chip8Computer::new(); + // 0b10000000 -> 0b01000000 + let start_value = 0b10000000; + let end_value = 0b01000000; + x.registers.poke(0x01, start_value); + Chip8CpuInstructions::ShrVxVy(0x01, 0x00).execute(&mut x); + assert_eq!(x.registers.peek(0x01), end_value); + assert_eq!(x.registers.peek(0x0f), 0); + + // 0b00000001 -> 0b00000000 + let start_value = 0b00000001; + let end_value = 0b00000000; + let mut x = Chip8Computer::new(); + let start_value = 1; + x.registers.poke(0x01, start_value); + Chip8CpuInstructions::ShrVxVy(0x01, 0x00).execute(&mut x); + assert_eq!(x.registers.peek(0x01), end_value); + assert_eq!(x.registers.peek(0x0f), 1); + let end_value = start_value / 2; + assert_eq!(end_value, 0); + } } diff --git a/gemma/src/chip8/keypad.rs b/gemma/src/chip8/keypad.rs index 9ae148d..16b7da8 100644 --- a/gemma/src/chip8/keypad.rs +++ b/gemma/src/chip8/keypad.rs @@ -1,6 +1,3 @@ -use imgui::Key; - - #[derive(Clone, Copy)] pub struct Keypad { keys: [bool; 0x10], diff --git a/gemma/src/chip8/registers.rs b/gemma/src/chip8/registers.rs index a232bf7..d05f4da 100644 --- a/gemma/src/chip8/registers.rs +++ b/gemma/src/chip8/registers.rs @@ -1,5 +1,3 @@ -use log::debug; - /// Registers. numbered 1-16 publicly. /// Privately using zero base array so -1 to shift from pub to priv. #[derive(Clone, Copy)] @@ -7,7 +5,6 @@ pub struct Chip8Registers { registers: [u8; 16], i_register: u16, pc: u16, - sp: u16, } impl Chip8Registers { @@ -22,7 +19,6 @@ impl Default for Chip8Registers { registers: [0x00; 16], i_register: 0x00, pc: 0x200, - sp: 0x100, } } } diff --git a/gemma/src/chip8/sound_timer.rs b/gemma/src/chip8/sound_timer.rs index 659e72f..257eb1e 100644 --- a/gemma/src/chip8/sound_timer.rs +++ b/gemma/src/chip8/sound_timer.rs @@ -1,5 +1,3 @@ -use std::{thread, time}; -use beep::beep; use log::trace; #[derive(Clone, Copy)] diff --git a/gemma/src/chip8/system_memory.rs b/gemma/src/chip8/system_memory.rs index 1629d51..b880435 100644 --- a/gemma/src/chip8/system_memory.rs +++ b/gemma/src/chip8/system_memory.rs @@ -1,11 +1,6 @@ -use glium::RawUniformValue::Vec2; -use image::load; -use imgui::sys::ImColor; -use imgui::{ImColor32, Ui}; -use log::{debug, trace}; -use ratatui::{style::Style, widgets::Widget}; +use log::{trace}; -use crate::constants::{CHIP8_MEMORY_SIZE, CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_WIDTH}; +use crate::constants::{CHIP8_MEMORY_SIZE}; pub const CHIP8_PROGRAM_LOAD_OFFSET: i32 = 0x200; pub const CHIP8FONT_0: [u8; 5] = [0xF0, 0x90, 0x90, 0x90, 0xF0]; @@ -41,10 +36,6 @@ impl Default for Chip8SystemMemory { x } } - -const cell_width: i32 = 5i32; -const cell_height: i32 = 5i32; - impl Chip8SystemMemory { pub fn new() -> Self { diff --git a/gemma/src/chip8/util.rs b/gemma/src/chip8/util.rs index c912309..719d84a 100644 --- a/gemma/src/chip8/util.rs +++ b/gemma/src/chip8/util.rs @@ -55,7 +55,7 @@ impl InstructionUtil { // kk or byte - An 8-bit value, the lowest 8 bits of the instruction pub fn read_byte_from_instruction(instruction_to_read_from: u16) -> u16 { - (instruction_to_read_from & 0x00FF) + instruction_to_read_from & 0x00FF } pub fn read_upper_byte_lower_nibble(to_read_from: u16) -> u16 { diff --git a/gemma/tests/computer_tests.rs b/gemma/tests/computer_tests.rs index c4f373d..91d36db 100644 --- a/gemma/tests/computer_tests.rs +++ b/gemma/tests/computer_tests.rs @@ -1,4 +1,4 @@ -use gemmaemu::chip8::computer::Chip8Computer; +use gemma::chip8::computer::Chip8Computer; #[test] fn smoke() { assert!(true) } @@ -6,4 +6,5 @@ fn smoke() { assert!(true) } #[test] fn test_rom_1_works() { let mut x = Chip8Computer::new(); + } diff --git a/gemmaegui/Cargo.toml b/gemmaegui/Cargo.toml index d59bc8a..d6edb48 100644 --- a/gemmaegui/Cargo.toml +++ b/gemmaegui/Cargo.toml @@ -4,6 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] -gemmaemu = { path = "../gemma" } +gemma = { path = "../gemma" } egui = "0.29.1" eframe = "0.29.1" diff --git a/gemmaegui/src/bin/gemmaegui.rs b/gemmaegui/src/bin/gemmaegui.rs index 481b441..52de01e 100644 --- a/gemmaegui/src/bin/gemmaegui.rs +++ b/gemmaegui/src/bin/gemmaegui.rs @@ -1,7 +1,7 @@ use eframe::egui; use egui::Ui; -use gemmaemu::chip8::computer::Chip8Computer; +use gemma::chip8::computer::Chip8Computer; struct EmmaEGuiState { pub display_video: bool, diff --git a/gemmaimgui/Cargo.toml b/gemmaimgui/Cargo.toml new file mode 100644 index 0000000..a0b7506 --- /dev/null +++ b/gemmaimgui/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "gemmaimgui" +version = "0.1.0" +edition = "2021" + +[dependencies] +gemma = { path = "../gemma" } +glium = { version = "0.34.0", default-features = true } +image = "0.23" +imgui = { version ="0.12.0", features = ["tables-api"] } +imgui-glium-renderer = { version = "0.12.0" } +imgui-winit-support = { version = "0.12.0" } +winit = { version = "0.27", features = ["x11", "mint"] } +pretty_env_logger = "0.5.0" +copypasta = "0.8" +rand = "0.9.0-alpha.2" +log = "0.4.22" +beep = "0.3.0" +chrono = "0.4.38" +dimensioned = "0.8.0" diff --git a/gemma/src/bin/emmagui.rs b/gemmaimgui/src/bin/gemmaimgui.rs similarity index 94% rename from gemma/src/bin/emmagui.rs rename to gemmaimgui/src/bin/gemmaimgui.rs index 190a411..cc8c48f 100644 --- a/gemma/src/bin/emmagui.rs +++ b/gemmaimgui/src/bin/gemmaimgui.rs @@ -1,19 +1,17 @@ use std::default::Default; use std::fs::DirEntry; use std::time::Instant; -use gemmaemu::{ +use gemma::{ chip8::computer::Chip8Computer, constants::{CHIP8_MEMORY_SIZE, CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_WIDTH}, }; use imgui::*; -use ratatui::symbols::half_block; use sys::{ImColor, ImVec2, ImVector_ImU32}; use rand::random; -use gemmaemu::chip8::system_memory::Chip8SystemMemory; +use gemma::chip8::system_memory::Chip8SystemMemory; use support::emmagui_support::EmmaGui; mod support; - struct UiState { pub show_registers: bool, pub show_memory: bool, @@ -50,7 +48,7 @@ impl Default for UiState { on_colour: ImColor32::from_rgb(0xff, 0xff, 0x00), off_colour: ImColor32::from_rgb(0x00, 0xff, 0xff), is_running: false, - frame_time: 32.0 + frame_time: 10.0 } } } diff --git a/gemma/src/bin/support/clipboard.rs b/gemmaimgui/src/bin/support/clipboard.rs similarity index 100% rename from gemma/src/bin/support/clipboard.rs rename to gemmaimgui/src/bin/support/clipboard.rs diff --git a/gemma/src/bin/support/emmagui_support.rs b/gemmaimgui/src/bin/support/emmagui_support.rs similarity index 98% rename from gemma/src/bin/support/emmagui_support.rs rename to gemmaimgui/src/bin/support/emmagui_support.rs index 89c3578..e71281f 100644 --- a/gemma/src/bin/support/emmagui_support.rs +++ b/gemmaimgui/src/bin/support/emmagui_support.rs @@ -5,9 +5,9 @@ use std::thread::sleep; use std::time::Duration; use imgui::{Condition, ImColor32, Ui}; use log::debug; -use gemmaemu::chip8::computer::Chip8Computer; -use gemmaemu::chip8::system_memory::Chip8SystemMemory; -use gemmaemu::constants::{CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_WIDTH}; +use gemma::chip8::computer::Chip8Computer; +use gemma::chip8::system_memory::Chip8SystemMemory; +use gemma::constants::{CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_WIDTH}; use crate::UiState; diff --git a/gemma/src/bin/support/mod.rs b/gemmaimgui/src/bin/support/mod.rs similarity index 100% rename from gemma/src/bin/support/mod.rs rename to gemmaimgui/src/bin/support/mod.rs