Gemma:
- Adding SCHIP instructions SDL2: - Sorting out Joystick/Gamepad/Whatever Util: - Disassembler in progress
This commit is contained in:
parent
be6e652982
commit
dea4b1aa92
129
Cargo.lock
generated
129
Cargo.lock
generated
@ -226,6 +226,55 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.89"
|
||||
@ -758,6 +807,46 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim 0.11.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
version = "3.1.1"
|
||||
@ -848,6 +937,12 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
|
||||
|
||||
[[package]]
|
||||
name = "com"
|
||||
version = "0.6.0"
|
||||
@ -1095,7 +1190,7 @@ dependencies = [
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"strsim 0.10.0",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
@ -1734,6 +1829,14 @@ dependencies = [
|
||||
"gemma",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gemmautil"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"gemma",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
@ -2068,6 +2171,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.4.0"
|
||||
@ -2269,6 +2378,12 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "jni"
|
||||
version = "0.21.1"
|
||||
@ -3804,6 +3919,12 @@ version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
@ -4091,6 +4212,12 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
[workspace]
|
||||
members = ["gemma", "gemmaegui", "gemmaimgui", "gemmatelnet", "gemmasdl2" ]
|
||||
members = ["gemma", "gemmaegui", "gemmaimgui", "gemmatelnet", "gemmasdl2", "gemmautil" ]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.dependencies]
|
||||
|
||||
@ -143,6 +143,8 @@ pub enum Chip8CpuInstructions {
|
||||
/// Dxyn
|
||||
/// Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision.
|
||||
///
|
||||
/// In Chip-8,
|
||||
///
|
||||
/// The interpreter reads n bytes from memory, starting at the address stored in I.
|
||||
/// These bytes are then displayed as sprites on screen at coordinates (Vx, Vy).
|
||||
/// Sprites are XORed onto the existing screen. If this causes any pixels to be erased,
|
||||
@ -150,6 +152,11 @@ pub enum Chip8CpuInstructions {
|
||||
/// it is outside the coordinates of the display, it wraps around to the opposite side
|
||||
/// of the screen. See instruction 8xy3 for more information on XOR, and section 2.4,
|
||||
/// Display, for more information on the Chip-8 screen and sprites.
|
||||
///
|
||||
/// In SCHIP
|
||||
///
|
||||
/// Show N-byte sprite from M(I) at Coords (VX,VY) VF = Collision.
|
||||
/// If N=0 AND ExtendedMode, 16x16 sprite
|
||||
DrawVxVyNibble(u8, u8, u8),
|
||||
/// Ex9E
|
||||
/// Skip next instruction if key with the value of Vx is pressed.
|
||||
@ -213,153 +220,127 @@ pub enum Chip8CpuInstructions {
|
||||
/// V0 through Vx.
|
||||
LdVxI(u8),
|
||||
XXXXERRORINSTRUCTION,
|
||||
/* START OF SCHIP-8 */
|
||||
/// 00CN
|
||||
///
|
||||
/// Scrolll Display N Lines Down
|
||||
ScrDn(u8),
|
||||
/// 00FB
|
||||
///
|
||||
/// Scroll 4 lines Right
|
||||
ScrRt,
|
||||
/// 00FC
|
||||
///
|
||||
/// Scroll 4 lines Left
|
||||
ScrLf,
|
||||
/// 00FE
|
||||
///
|
||||
/// Disable Extended Mode
|
||||
VidDis,
|
||||
/// 00FF
|
||||
///
|
||||
/// Enable Extended Mode
|
||||
VidEna,
|
||||
/// 00FD
|
||||
///
|
||||
/// Exit App
|
||||
Exit,
|
||||
/// FX30
|
||||
///
|
||||
/// Point I to 10 yte font sprite for digit VX (0..9)
|
||||
LdFVx10(u8),
|
||||
/// FX75
|
||||
///
|
||||
/// Store V0..VX in RPL user flags (X <= 7
|
||||
StRpl(u8),
|
||||
/// FX85
|
||||
///
|
||||
/// Load V0..VX from RPL user flags (X <= 7)
|
||||
LdRpl(u8),
|
||||
}
|
||||
|
||||
impl Chip8CpuInstructions {
|
||||
pub fn name(&self) -> &str {
|
||||
match self {
|
||||
Chip8CpuInstructions::SysAddr(_) => {
|
||||
"SYS"
|
||||
}
|
||||
Chip8CpuInstructions::CLS => {
|
||||
"CLS"
|
||||
}
|
||||
Chip8CpuInstructions::RET => {
|
||||
"RET"
|
||||
}
|
||||
Chip8CpuInstructions::JpAddr(_) => {
|
||||
"JPA"
|
||||
}
|
||||
Chip8CpuInstructions::CallAddr(_) => {
|
||||
"CALL"
|
||||
}
|
||||
Chip8CpuInstructions::SeVxByte(_, _) => {
|
||||
"SeVxByte"
|
||||
}
|
||||
Chip8CpuInstructions::SneVxByte(_, _) => {
|
||||
"SneVxByte"
|
||||
}
|
||||
Chip8CpuInstructions::SeVxVy(_, _) => {
|
||||
"SeVeVy"
|
||||
}
|
||||
Chip8CpuInstructions::LdVxByte(_, _) => {
|
||||
"LdVxByte"
|
||||
}
|
||||
Chip8CpuInstructions::AddVxByte(_, _) => {
|
||||
"AddVxByte"
|
||||
}
|
||||
Chip8CpuInstructions::LdVxVy(_, _) => {
|
||||
"LdVxVy"
|
||||
}
|
||||
Chip8CpuInstructions::OrVxVy(_, _) => {
|
||||
"OrVxVy"
|
||||
}
|
||||
Chip8CpuInstructions::AndVxVy(_, _) => {
|
||||
"AndVxVy"
|
||||
}
|
||||
Chip8CpuInstructions::XorVxVy(_, _) => {
|
||||
"XorVxVy"
|
||||
}
|
||||
Chip8CpuInstructions::AddVxVy(_, _) => {
|
||||
"AddVxVy"
|
||||
}
|
||||
Chip8CpuInstructions::SubVxVy(_, _) => {
|
||||
"SubVxVy"
|
||||
}
|
||||
Chip8CpuInstructions::ShrVxVy(_, _) => {
|
||||
"ShrVxVy"
|
||||
}
|
||||
Chip8CpuInstructions::SubnVxVy(_, _) => {
|
||||
"SubnVxVy"
|
||||
}
|
||||
Chip8CpuInstructions::ShlVxVy(_, _) => {
|
||||
"ShlVxVy"
|
||||
}
|
||||
Chip8CpuInstructions::SneVxVy(_, _) => {
|
||||
"SneVxVy"
|
||||
}
|
||||
Chip8CpuInstructions::LdIAddr(_) => {
|
||||
"LdIAddr"
|
||||
}
|
||||
Chip8CpuInstructions::JpV0Addr(_) => {
|
||||
"JpV0Addr"
|
||||
}
|
||||
Chip8CpuInstructions::RndVxByte(_, _) => {
|
||||
"RndVxByte"
|
||||
}
|
||||
Chip8CpuInstructions::DrawVxVyNibble(_, _, _) => {
|
||||
"DrawVxVyNibble"
|
||||
}
|
||||
Chip8CpuInstructions::SkpVx(_) => {
|
||||
"SkpVx"
|
||||
}
|
||||
Chip8CpuInstructions::SnkpVx(_) => {
|
||||
"SnkpVx"
|
||||
}
|
||||
Chip8CpuInstructions::LdVxDt(_) => {
|
||||
"LdVxDt"
|
||||
}
|
||||
Chip8CpuInstructions::LdVxK(_) => {
|
||||
"LdVxK"
|
||||
}
|
||||
Chip8CpuInstructions::LdDtVx(_) => {
|
||||
"LdDtVx"
|
||||
}
|
||||
Chip8CpuInstructions::LdStVx(_) => {
|
||||
"LdStVx"
|
||||
}
|
||||
Chip8CpuInstructions::AddIVx(_) => {
|
||||
"AddIVx"
|
||||
}
|
||||
Chip8CpuInstructions::LdFVx(_) => {
|
||||
"LdFVx"
|
||||
}
|
||||
Chip8CpuInstructions::LdBVx(_) => {
|
||||
"LdBVx"
|
||||
}
|
||||
Chip8CpuInstructions::LdIVx(_) => {
|
||||
"LdIVx"
|
||||
}
|
||||
Chip8CpuInstructions::LdVxI(_) => {
|
||||
"LdVxI"
|
||||
}
|
||||
XXXXERRORINSTRUCTION => {
|
||||
"XX ERROR XX"
|
||||
}
|
||||
Chip8CpuInstructions::AddIVx(_) => "AddIVx",
|
||||
Chip8CpuInstructions::AddVxByte(_, _) => "AddVxByte",
|
||||
Chip8CpuInstructions::AddVxVy(_, _) => "AddVxVy",
|
||||
Chip8CpuInstructions::AndVxVy(_, _) => "AndVxVy",
|
||||
Chip8CpuInstructions::CLS => "CLS",
|
||||
Chip8CpuInstructions::CallAddr(_) => "CALL",
|
||||
Chip8CpuInstructions::DrawVxVyNibble(_, _, _) => "DrawVxVyNibble",
|
||||
Chip8CpuInstructions::Exit => "EXIT",
|
||||
Chip8CpuInstructions::JpAddr(_) => "JPA",
|
||||
Chip8CpuInstructions::JpV0Addr(_) => "JpV0Addr",
|
||||
Chip8CpuInstructions::LdBVx(_) => "LdBVx",
|
||||
Chip8CpuInstructions::LdDtVx(_) => "LdDtVx",
|
||||
Chip8CpuInstructions::LdFVx(_) => "LdFVx",
|
||||
Chip8CpuInstructions::LdFVx10(x) => "LdFVx10",
|
||||
Chip8CpuInstructions::LdIAddr(_) => "LdIAddr",
|
||||
Chip8CpuInstructions::LdIVx(_) => "LdIVx",
|
||||
Chip8CpuInstructions::LdRpl(x) => "LdRpl",
|
||||
Chip8CpuInstructions::LdStVx(_) => "LdStVx",
|
||||
Chip8CpuInstructions::LdVxByte(_, _) => "LdVxByte",
|
||||
Chip8CpuInstructions::LdVxDt(_) => "LdVxDt",
|
||||
Chip8CpuInstructions::LdVxI(_) => "LdVxI",
|
||||
Chip8CpuInstructions::LdVxK(_) => "LdVxK",
|
||||
Chip8CpuInstructions::LdVxVy(_, _) => "LdVxVy",
|
||||
Chip8CpuInstructions::OrVxVy(_, _) => "OrVxVy",
|
||||
Chip8CpuInstructions::RET => "RET",
|
||||
Chip8CpuInstructions::RndVxByte(_, _) => "RndVxByte",
|
||||
Chip8CpuInstructions::ScrDn(_) => "ScrDn",
|
||||
Chip8CpuInstructions::ScrLf => "ScrLf",
|
||||
Chip8CpuInstructions::ScrRt => "ScrRt",
|
||||
Chip8CpuInstructions::SeVxByte(_, _) => "SeVxByte",
|
||||
Chip8CpuInstructions::SeVxVy(_, _) => "SeVeVy",
|
||||
Chip8CpuInstructions::ShlVxVy(_, _) => "ShlVxVy",
|
||||
Chip8CpuInstructions::ShrVxVy(_, _) => "ShrVxVy",
|
||||
Chip8CpuInstructions::SkpVx(_) => "SkpVx",
|
||||
Chip8CpuInstructions::SneVxByte(_, _) => "SneVxByte",
|
||||
Chip8CpuInstructions::SneVxVy(_, _) => "SneVxVy",
|
||||
Chip8CpuInstructions::SnkpVx(_) => "SnkpVx",
|
||||
Chip8CpuInstructions::StRpl(x) => "StRpl",
|
||||
Chip8CpuInstructions::SubVxVy(_, _) => "SubVxVy",
|
||||
Chip8CpuInstructions::SubnVxVy(_, _) => "SubnVxVy",
|
||||
Chip8CpuInstructions::SysAddr(_) => "SYS",
|
||||
Chip8CpuInstructions::VidDis => "VidDis",
|
||||
Chip8CpuInstructions::VidEna => "VidEna",
|
||||
Chip8CpuInstructions::XorVxVy(_, _) => "XorVxVy",
|
||||
XXXXERRORINSTRUCTION => "XX ERROR XX",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn operands(&self) -> String {
|
||||
match self {
|
||||
Chip8CpuInstructions::SysAddr(addr) |
|
||||
Chip8CpuInstructions::JpV0Addr(addr) |
|
||||
Chip8CpuInstructions::JpV0Addr(addr) |
|
||||
Chip8CpuInstructions::JpAddr(addr) |
|
||||
Chip8CpuInstructions::LdIAddr(addr) |
|
||||
Chip8CpuInstructions::CallAddr(addr) => {
|
||||
format!("{addr:04x}")
|
||||
format!("0x{addr:04x}")
|
||||
}
|
||||
Chip8CpuInstructions::SeVxByte(x, byte) |
|
||||
Chip8CpuInstructions::SneVxByte(x, byte) |
|
||||
Chip8CpuInstructions::LdVxByte(x, byte) |
|
||||
Chip8CpuInstructions::RndVxByte(x, byte) |
|
||||
Chip8CpuInstructions::AddVxByte(x, byte) => {
|
||||
format!("{x:02x}, {byte:04x}")
|
||||
format!("0x{x:02x}, 0x{byte:02x}")
|
||||
}
|
||||
Chip8CpuInstructions::SeVxVy(x,y) |
|
||||
Chip8CpuInstructions::LdVxVy(x,y) |
|
||||
Chip8CpuInstructions::OrVxVy(x,y) |
|
||||
Chip8CpuInstructions::AndVxVy(x,y) |
|
||||
Chip8CpuInstructions::XorVxVy(x,y) |
|
||||
Chip8CpuInstructions::AddVxVy(x,y) |
|
||||
Chip8CpuInstructions::SubVxVy(x,y) |
|
||||
Chip8CpuInstructions::ShrVxVy(x,y) |
|
||||
Chip8CpuInstructions::SubnVxVy(x,y) |
|
||||
Chip8CpuInstructions::ShlVxVy(x,y) |
|
||||
Chip8CpuInstructions::SneVxVy(x,y) => {
|
||||
format!("{x:02x}, {y:02x}")
|
||||
Chip8CpuInstructions::SeVxVy(x, y) |
|
||||
Chip8CpuInstructions::LdVxVy(x, y) |
|
||||
Chip8CpuInstructions::OrVxVy(x, y) |
|
||||
Chip8CpuInstructions::AndVxVy(x, y) |
|
||||
Chip8CpuInstructions::XorVxVy(x, y) |
|
||||
Chip8CpuInstructions::AddVxVy(x, y) |
|
||||
Chip8CpuInstructions::SubVxVy(x, y) |
|
||||
Chip8CpuInstructions::ShrVxVy(x, y) |
|
||||
Chip8CpuInstructions::SubnVxVy(x, y) |
|
||||
Chip8CpuInstructions::ShlVxVy(x, y) |
|
||||
Chip8CpuInstructions::SneVxVy(x, y) => {
|
||||
format!("0x{x:02x}, 0x{y:02x}")
|
||||
}
|
||||
Chip8CpuInstructions::DrawVxVyNibble(x,y,nibble) => {
|
||||
format!("{x:02x}, {y:02x}, {nibble:02x}")
|
||||
Chip8CpuInstructions::DrawVxVyNibble(x, y, nibble) => {
|
||||
format!("0x{x:02x}, 0x{y:02x}, 0x{nibble:02x}")
|
||||
}
|
||||
Chip8CpuInstructions::LdDtVx(x) |
|
||||
Chip8CpuInstructions::LdStVx(x) |
|
||||
@ -371,12 +352,13 @@ impl Chip8CpuInstructions {
|
||||
Chip8CpuInstructions::LdVxDt(x) |
|
||||
Chip8CpuInstructions::LdVxK(x) |
|
||||
Chip8CpuInstructions::LdVxI(x) |
|
||||
Chip8CpuInstructions::SnkpVx(x) => {
|
||||
format!("{x:02x}")
|
||||
}
|
||||
_ => {
|
||||
"".parse().unwrap()
|
||||
Chip8CpuInstructions::LdFVx10(x) |
|
||||
Chip8CpuInstructions::StRpl(x) |
|
||||
Chip8CpuInstructions::LdRpl(x) |
|
||||
Chip8CpuInstructions::SnkpVx(x) => {
|
||||
format!("0x{x:02x}")
|
||||
}
|
||||
_ => { String::new() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -427,7 +409,16 @@ impl Chip8CpuInstructions {
|
||||
Chip8CpuInstructions::LdBVx(x_register) => 0xF033 | ((*x_register as u16) << 8),
|
||||
Chip8CpuInstructions::LdIVx(x_register) => 0xF055 | ((*x_register as u16) << 8),
|
||||
Chip8CpuInstructions::LdVxI(x_register) => 0xF065 | ((*x_register as u16) << 8),
|
||||
XXXXERRORINSTRUCTION => 0xFFFF,
|
||||
Chip8CpuInstructions::ScrDn(x_register) => 0x00C0 | (*x_register as u16),
|
||||
Chip8CpuInstructions::ScrRt => 0x00FB,
|
||||
Chip8CpuInstructions::ScrLf => 0x00FC,
|
||||
Chip8CpuInstructions::VidDis => 0x00FE,
|
||||
Chip8CpuInstructions::VidEna => 0x00FF,
|
||||
Chip8CpuInstructions::Exit => 0x00FD,
|
||||
Chip8CpuInstructions::LdFVx10(x_register) => 0xF030 | ((*x_register as u16) << 8),
|
||||
Chip8CpuInstructions::StRpl(x_register) => 0xF075 | ((*x_register as u16) << 8),
|
||||
Chip8CpuInstructions::LdRpl(x_register) => 0xF085 | ((*x_register as u16) << 8),
|
||||
XXXXERRORINSTRUCTION => 0xFFFF
|
||||
}
|
||||
}
|
||||
pub fn decode(input: u16) -> Chip8CpuInstructions {
|
||||
@ -441,8 +432,14 @@ impl Chip8CpuInstructions {
|
||||
let last_nibble = (input & 0xF) as u8;
|
||||
|
||||
match input {
|
||||
0x00C0..=0x00CF => Chip8CpuInstructions::ScrDn(last_nibble),
|
||||
0x00E0 => Chip8CpuInstructions::CLS,
|
||||
0x00EE => Chip8CpuInstructions::RET,
|
||||
0x00FB => Chip8CpuInstructions::ScrRt,
|
||||
0x00FC => Chip8CpuInstructions::ScrLf,
|
||||
0x00FD => Chip8CpuInstructions::Exit,
|
||||
0x00FE => Chip8CpuInstructions::VidDis,
|
||||
0x00FF => Chip8CpuInstructions::VidEna,
|
||||
0x0000..=0x0FFF => Chip8CpuInstructions::SysAddr(addr_param),
|
||||
0x1000..=0x1FFF => Chip8CpuInstructions::JpAddr(addr_param),
|
||||
0x2000..=0x2FFF => Chip8CpuInstructions::CallAddr(addr_param),
|
||||
@ -480,9 +477,12 @@ impl Chip8CpuInstructions {
|
||||
0x18 => Chip8CpuInstructions::LdStVx(ubln),
|
||||
0x1E => Chip8CpuInstructions::AddIVx(ubln),
|
||||
0x29 => Chip8CpuInstructions::LdFVx(ubln),
|
||||
0x30 => Chip8CpuInstructions::LdFVx10(ubln),
|
||||
0x33 => Chip8CpuInstructions::LdBVx(ubln),
|
||||
0x55 => Chip8CpuInstructions::LdIVx(ubln),
|
||||
0x65 => Chip8CpuInstructions::LdVxI(ubln),
|
||||
0x75 => Chip8CpuInstructions::StRpl(ubln),
|
||||
0x85 => Chip8CpuInstructions::LdRpl(ubln),
|
||||
_ => XXXXERRORINSTRUCTION
|
||||
}
|
||||
_ => XXXXERRORINSTRUCTION
|
||||
@ -865,6 +865,33 @@ impl Chip8CpuInstructions {
|
||||
input.registers.poke_i(offset + 1);
|
||||
}
|
||||
Chip8CpuInstructions::XXXXERRORINSTRUCTION => {}
|
||||
Chip8CpuInstructions::ScrDn(x) => {
|
||||
println!("SCROLLING DOWN {x} LINES");
|
||||
}
|
||||
Chip8CpuInstructions::ScrRt => {
|
||||
println!("SCROLING RIGHT 4 LINES");
|
||||
}
|
||||
Chip8CpuInstructions::ScrLf => {
|
||||
println!("SCROLLING LEFT 4 LINES");
|
||||
}
|
||||
Chip8CpuInstructions::VidDis => {
|
||||
println!("DISABLE VIDEO MODE");
|
||||
}
|
||||
Chip8CpuInstructions::VidEna => {
|
||||
println!("ENABLE VIDEO MODE");
|
||||
}
|
||||
Chip8CpuInstructions::Exit => {
|
||||
println!("EXIT INTERPRETER");
|
||||
}
|
||||
Chip8CpuInstructions::LdFVx10(x) => {
|
||||
println!("POINTING TO FONT AT {x:02x}");
|
||||
}
|
||||
Chip8CpuInstructions::StRpl(x) => {
|
||||
println!("STORING FROM RPL FOR {x}");
|
||||
}
|
||||
Chip8CpuInstructions::LdRpl(x) => {
|
||||
println!("LOADING FROM RPL FOR {x}");
|
||||
}
|
||||
};
|
||||
let cycle_time = Instant::now().duration_since(start_time).as_nanos();
|
||||
// println!("\t\tTook {cycle_time}ms");
|
||||
@ -920,6 +947,26 @@ mod test {
|
||||
assert_eq!(Chip8CpuInstructions::LdBVx(0xd).encode(), 0xfd33);
|
||||
assert_eq!(Chip8CpuInstructions::LdIVx(0xe).encode(), 0xfe55);
|
||||
assert_eq!(Chip8CpuInstructions::LdVxI(0x3).encode(), 0xf365);
|
||||
assert_eq!(Chip8CpuInstructions::ScrDn(0x1).encode(), 0x00C1);
|
||||
assert_eq!(Chip8CpuInstructions::ScrLf.encode(), 0x00FC);
|
||||
assert_eq!(Chip8CpuInstructions::ScrRt.encode(), 0x00FB);
|
||||
assert_eq!(Chip8CpuInstructions::Exit.encode(), 0x00FD);
|
||||
assert_eq!(Chip8CpuInstructions::VidEna.encode(), 0x00FF);
|
||||
assert_eq!(Chip8CpuInstructions::VidDis.encode(), 0x00FE);
|
||||
assert_eq!(Chip8CpuInstructions::LdFVx10(0).encode(), 0xF030);
|
||||
assert_eq!(Chip8CpuInstructions::StRpl(1).encode(), 0xF175);
|
||||
assert_eq!(Chip8CpuInstructions::LdRpl(1).encode(), 0xF185);
|
||||
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0xF175), Chip8CpuInstructions::StRpl(1)));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0xF185), Chip8CpuInstructions::LdRpl(1)));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x00C1u16), Chip8CpuInstructions::ScrDn(0x01)));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x00FCu16), Chip8CpuInstructions::ScrLf));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x00FBu16), Chip8CpuInstructions::ScrRt));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x00FDu16), Chip8CpuInstructions::Exit));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x00FEu16), Chip8CpuInstructions::VidDis));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x00FFu16), Chip8CpuInstructions::VidEna));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0xF030u16), Chip8CpuInstructions::LdFVx10(0)));
|
||||
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x00E0u16), Chip8CpuInstructions::CLS));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x00EEu16), Chip8CpuInstructions::RET));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x0123), Chip8CpuInstructions::SysAddr(0x123)));
|
||||
|
||||
@ -1,10 +1,18 @@
|
||||
use log::{debug};
|
||||
use crate::chip8::video::Chip8VideoModes::{HighRes, LowRes};
|
||||
use crate::constants::{CHIP8_VIDEO_MEMORY, CHIP8_VIDEO_WIDTH};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum Chip8VideoModes {
|
||||
LowRes,
|
||||
HighRes
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Chip8Video {
|
||||
memory: [bool; CHIP8_VIDEO_MEMORY],
|
||||
pub has_frame_changed: bool,
|
||||
current_res: Chip8VideoModes
|
||||
}
|
||||
|
||||
impl Chip8Video {
|
||||
@ -13,8 +21,28 @@ impl Chip8Video {
|
||||
self.start_frame();
|
||||
}
|
||||
|
||||
pub fn set_highres(&mut self) {
|
||||
self.current_res = HighRes
|
||||
}
|
||||
|
||||
pub fn set_lowres(&mut self) {
|
||||
self.current_res = LowRes
|
||||
}
|
||||
|
||||
pub fn get_screen_resolution(&mut self) -> Chip8VideoModes {
|
||||
self.current_res
|
||||
}
|
||||
|
||||
pub fn cls(&mut self) {
|
||||
self.memory = [false; CHIP8_VIDEO_MEMORY];
|
||||
match self.current_res {
|
||||
LowRes => {
|
||||
self.memory = [false; CHIP8_VIDEO_MEMORY];
|
||||
}
|
||||
HighRes => {
|
||||
|
||||
// self.memory = [0u8; ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_frame(&mut self) {
|
||||
@ -25,6 +53,7 @@ impl Chip8Video {
|
||||
Self {
|
||||
memory: initial_configuration,
|
||||
has_frame_changed: false,
|
||||
current_res: Chip8VideoModes::LowRes,
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,7 +114,7 @@ impl Chip8Video {
|
||||
|
||||
impl Default for Chip8Video {
|
||||
fn default() -> Self {
|
||||
Chip8Video { memory: [false; CHIP8_VIDEO_MEMORY], has_frame_changed: false }
|
||||
Chip8Video { memory: [false; CHIP8_VIDEO_MEMORY], has_frame_changed: false, current_res: Chip8VideoModes::LowRes }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,3 +12,6 @@ pub const CHIP8_KEYBOARD: [[u8; 4]; 4] = [
|
||||
[0x0A, 0x00, 0x0B, 0x0F]
|
||||
];
|
||||
|
||||
pub const SCHIP_VIDEO_HEIGHT: i32 = 64;
|
||||
pub const SCHIP_VIDEO_WIDTH: i32 = 128;
|
||||
pub const SCHIP_VIDE_MEMORY: usize = (SCHIP_VIDEO_HEIGHT * SCHIP_VIDEO_WIDTH) as usize;
|
||||
|
||||
@ -17,7 +17,6 @@ async fn run() -> anyhow::Result<String> {
|
||||
let sdl = sdl2::init().map_err(|e| anyhow::anyhow!("Failed to create SDL context: {}", e))?;
|
||||
let mut video = sdl.video().map_err(|e| anyhow::anyhow!("Failed to initialize SDL video subsystem: {}", e))?;
|
||||
|
||||
|
||||
// Create SDL2 window and OpenGL context
|
||||
let window = video.window("Window", SCREEN_WIDTH, SCREEN_HEIGHT)
|
||||
.opengl()
|
||||
@ -114,6 +113,12 @@ async fn run() -> anyhow::Result<String> {
|
||||
Event::ControllerButtonDown { button, .. } => {
|
||||
println!("BUTTON {:?}", button);
|
||||
}
|
||||
Event::JoyButtonDown {button_idx, .. } => {
|
||||
println!("JoyButtonDown {}", button_idx);
|
||||
}
|
||||
Event::JoyAxisMotion { which, axis_idx, .. } => {
|
||||
println!("JoyAxismotion {which} {axis_idx}");
|
||||
}
|
||||
_ => platform.handle_event(&event, &sdl, &video),
|
||||
}
|
||||
}
|
||||
@ -122,6 +127,9 @@ async fn run() -> anyhow::Result<String> {
|
||||
if let Some(fps) = timestep.frame_rate() {
|
||||
println!("{:?} fps", fps);
|
||||
}
|
||||
|
||||
let num_js = sdl.joystick().unwrap().num_joysticks().unwrap();
|
||||
println!("NUM JS = {num_js}");
|
||||
}
|
||||
|
||||
Ok(("").parse()?)
|
||||
|
||||
8
gemmautil/Cargo.toml
Normal file
8
gemmautil/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "gemmautil"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
gemma = { path = "../gemma" }
|
||||
clap = { version = "4.5.20", features = ["derive"] }
|
||||
58
gemmautil/src/bin/ch8disasm.rs
Normal file
58
gemmautil/src/bin/ch8disasm.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use std::path::Path;
|
||||
use clap::{command, Parser};
|
||||
use gemma::chip8::instructions::Chip8CpuInstructions;
|
||||
use gemma::chip8::instructions::Chip8CpuInstructions::XXXXERRORINSTRUCTION;
|
||||
|
||||
/// ch8disasm
|
||||
///
|
||||
/// Provide disassembled version of the CH8 file provided.
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct DisassemblerApp {
|
||||
#[arg(short)]
|
||||
input_file: Box<Path>,
|
||||
#[arg(short)]
|
||||
output_file: Option<Box<Path>>
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Taxation is Theft");
|
||||
let result = DisassemblerApp::parse();
|
||||
println!("PREPARING TO DISASSEMBLE {:?}", result.input_file.file_name());
|
||||
let mut last_byte: u8 = 0x00;
|
||||
let mut working_instruction: u16 = 0x0000;
|
||||
// read the input file and loop through it byte by byte.
|
||||
|
||||
for (offset, byte) in std::fs::read(result.input_file).unwrap().iter().enumerate() {
|
||||
working_instruction = (working_instruction << 8) | (*byte as u16);
|
||||
if offset % 2 != 0 {
|
||||
// println!("ODD BYTE -> {:02x} / WORKING: {working_instruction:04x}", *byte as u16);
|
||||
let decoded = Chip8CpuInstructions::decode(working_instruction);
|
||||
match decoded {
|
||||
XXXXERRORINSTRUCTION => {
|
||||
println!("\t\t; ERROR: BYTES: {} OFFSET: {}", working_instruction, offset);
|
||||
println!("FOUND ERROR INSTRUCTION. LIKELY DATA.");
|
||||
}
|
||||
Chip8CpuInstructions::JpAddr(x) => {
|
||||
if x == (offset + 0x1ff) as u16 {
|
||||
println!("FOUND JUMP TO SELF. INFINITE LOOP DETECTED.");
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
println!("{}\t\t; Bytes [{:04x}] ending offset [{:04x}]", decoded, working_instruction, offset);
|
||||
}
|
||||
}
|
||||
working_instruction = 0x0000;
|
||||
}
|
||||
}
|
||||
|
||||
match result.output_file {
|
||||
None => {
|
||||
println!("Output to console.");
|
||||
}
|
||||
Some(target) => {
|
||||
println!("Output to {:?}", target);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user