diff --git a/Cargo.lock b/Cargo.lock index 080cf31..ffdcb85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "anstream" version = "0.6.19" @@ -67,12 +73,36 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +[[package]] +name = "bytemuck" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "cfg-if" version = "1.0.1" @@ -130,6 +160,12 @@ dependencies = [ "trevors_utilities", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "colorchoice" version = "1.0.4" @@ -165,6 +201,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" version = "0.3.13" @@ -181,6 +223,15 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + [[package]] name = "flate2" version = "1.1.2" @@ -191,6 +242,22 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "fontdue" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e57e16b3fe8ff4364c0661fdaac543fb38b29ea9bc9c2f45612d90adf931d2b" +dependencies = [ + "hashbrown", + "ttf-parser", +] + [[package]] name = "getrandom" version = "0.3.3" @@ -203,6 +270,23 @@ dependencies = [ "wasi", ] +[[package]] +name = "glam" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9" + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "heck" version = "0.5.0" @@ -221,6 +305,19 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +[[package]] +name = "image" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "num-traits", + "png", +] + [[package]] name = "is-terminal" version = "0.4.16" @@ -259,6 +356,38 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "macroquad" version = "0.1.0" +dependencies = [ + "macroquad 0.4.14", +] + +[[package]] +name = "macroquad" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2befbae373456143ef55aa93a73594d080adfb111dc32ec96a1123a3e4ff4ae" +dependencies = [ + "fontdue", + "glam", + "image", + "macroquad_macro", + "miniquad", + "quad-rand", +] + +[[package]] +name = "macroquad_macro" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64b1d96218903768c1ce078b657c0d5965465c95a60d2682fd97443c9d2483dd" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] [[package]] name = "memchr" @@ -266,6 +395,18 @@ version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +[[package]] +name = "miniquad" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fb3e758e46dbc45716a8a49ca9edc54b15bcca826277e80b1f690708f67f9e3" +dependencies = [ + "libc", + "ndk-sys", + "objc-rs", + "winapi", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -273,6 +414,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", +] + +[[package]] +name = "ndk-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "objc-rs" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a1e7069a2525126bf12a9f1f7916835fafade384fb27cabf698e745e2a1eb8" +dependencies = [ + "malloc_buf", ] [[package]] @@ -287,6 +453,19 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "pretty_env_logger" version = "0.5.0" @@ -306,6 +485,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quad-rand" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a651516ddc9168ebd67b24afd085a718be02f8858fe406591b013d101ce2f40" + [[package]] name = "quote" version = "1.0.40" @@ -356,13 +541,19 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags", + "bitflags 2.9.1", "errno", "libc", "linux-raw-sys", "windows-sys 0.59.0", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "strsim" version = "0.11.1" @@ -412,6 +603,12 @@ dependencies = [ "tempfile", ] +[[package]] +name = "ttf-parser" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -433,6 +630,22 @@ dependencies = [ "wit-bindgen-rt", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.9" @@ -442,6 +655,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.59.0" @@ -594,5 +813,5 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags", + "bitflags 2.9.1", ] diff --git a/core/src/address_mode.rs b/core/src/address_mode.rs index 5854c5c..0492068 100644 --- a/core/src/address_mode.rs +++ b/core/src/address_mode.rs @@ -8,6 +8,7 @@ pub enum AddressMode { Immediate(u8), ZeroPage(u8), ZeroPageX(u8), + ZeroPageY(u8), Absolute(u16), AbsoluteX(u16), AbsoluteY(u16), diff --git a/core/src/constants.rs b/core/src/constants/constants_isa_op.rs similarity index 97% rename from core/src/constants.rs rename to core/src/constants/constants_isa_op.rs index cc4b14a..92f4089 100644 --- a/core/src/constants.rs +++ b/core/src/constants/constants_isa_op.rs @@ -1,4 +1,5 @@ -// Instruction OP Codes +/// Instruction OP Codes + /// ADC pub const ISA_OP_ADC_I: u8 = 0x69; @@ -18,53 +19,39 @@ pub const ISA_OP_AND_ABSX: u8 = 0x3d; pub const ISA_OP_AND_ABSY: u8 = 0x39; pub const ISA_OP_AND_INDX: u8 = 0x21; pub const ISA_OP_AND_INDY: u8 = 0x31; - /// ASL pub const ISA_OP_ASL_A: u8 = 0x0a; pub const ISA_OP_ASL_Z: u8 = 0x06; pub const ISA_OP_ASL_ZX: u8 = 0x16; pub const ISA_OP_ASL_ABS: u8 = 0x0e; pub const ISA_OP_ASL_ABSX: u8 = 0x1e; - /// BCC pub const ISA_OP_BCC: u8 = 0x90; - /// BCS pub const ISA_OP_BCS: u8 = 0xb0; - /// BEQ pub const ISA_OP_BEQ: u8 = 0xf0; /// BIT pub const ISA_OP_BIT_ZP: u8 = 0x24; pub const ISA_OP_BIT_ABS: u8 = 0x2c; - /// BMI pub const ISA_OP_BMI: u8 = 0x30; - /// BNE pub const ISA_OP_BNE: u8 = 0xd0; - /// BPL pub const ISA_OP_BPL: u8 = 0x10; - /// BRK pub const ISA_OP_BRK: u8 = 0x00; /// BVC pub const ISA_OP_BVC: u8 = 0x50; - /// BVS pub const ISA_OP_BVS: u8 = 0x70; - pub const ISA_OP_CLC: u8 = 0x18; - pub const ISA_OP_CLD: u8 = 0xd8; - pub const ISA_OP_CLI: u8 = 0x58; - pub const ISA_OP_CLV: u8 = 0xb8; - pub const ISA_OP_CMP_I: u8 = 0xc9; pub const ISA_OP_CMP_ZP: u8 = 0xc5; pub const ISA_OP_CMP_ZPX: u8 = 0xd5; @@ -72,24 +59,18 @@ pub const ISA_OP_CMP_ABS: u8 = 0xcd; pub const ISA_OP_CMP_ABSX: u8 = 0xdd; pub const ISA_OP_CMP_INDX: u8 = 0xc1; pub const ISA_OP_CMP_INDY: u8 = 0xd1; - pub const ISA_OP_CPX_I: u8 = 0xe0; pub const ISA_OP_CPX_ZP: u8 = 0xe4; pub const ISA_OP_CPX_ABS: u8 = 0xec; - pub const ISA_OP_CPY_I: u8 = 0xc0; pub const ISA_OP_CPY_ZP: u8 = 0xc4; pub const ISA_OP_CPY_ABS: u8 = 0xcc; - pub const ISA_OP_DEC_ZP: u8 = 0xc6; pub const ISA_OP_DEC_ZPX: u8 = 0xd6; pub const ISA_OP_DEC_ABS: u8 = 0xce; pub const ISA_OP_DEC_ABSX: u8 = 0xde; - pub const ISA_OP_DEX: u8 = 0xca; - pub const ISA_OP_DEY: u8 = 0x88; - pub const ISA_OP_EOR_I: u8 = 0x49; pub const ISA_OP_EOR_ZP: u8 = 0x45; pub const ISA_OP_EOR_ZPX: u8 = 0x55; @@ -98,22 +79,15 @@ pub const ISA_OP_EOR_ABSX: u8 = 0x5d; pub const ISA_OP_EOR_ABSY: u8 = 0x59; pub const ISA_OP_EOR_INDX: u8 = 0x41; pub const ISA_OP_EOR_INDY: u8 = 0x51; - pub const ISA_OP_INC_ZP: u8 = 0xe6; pub const ISA_OP_INC_ZPX: u8 = 0xf6; pub const ISA_OP_INC_ABS: u8 = 0xee; pub const ISA_OP_INC_ABSX: u8 = 0xfe; - - pub const ISA_OP_INX: u8 = 0xe8; - pub const ISA_OP_INY: u8 = 0xc8; - pub const ISA_OP_JMP_ABS: u8 = 0x4c; pub const ISA_OP_JMP_IND: u8 = 0x6c; - pub const ISA_OP_JSR: u8 = 0x20; - pub const ISA_OP_LDA_I: u8 = 0xA9; pub const ISA_OP_LDA_Z: u8 = 0xA5; pub const ISA_OP_LDA_ZX: u8 = 0xB5; @@ -122,26 +96,23 @@ pub const IAS_OP_LDA_ABSX: u8 = 0xBD; pub const ISA_OP_LDA_ABSY: u8 = 0xB9; pub const ISA_OP_LDA_INDX: u8 = 0xA1; pub const ISA_OP_LDA_INDY: u8 = 0xB1; - pub const ISA_OP_LDX_I: u8 = 0xa2; pub const ISA_OP_LDX_ZP: u8 = 0xa6; pub const ISA_OP_LDX_ZPY: u8 = 0x86; pub const ISA_OP_LDX_ABS: u8 = 0xae; pub const ISA_OP_LDX_ABSY: u8 = 0xbe; - pub const ISA_OP_LDY_I: u8 = 0xa0; pub const ISA_OP_LDY_ZP: u8 = 0xa4; pub const ISA_OP_LDY_ZPX: u8 = 0xb4; pub const ISA_OP_LDY_ABS: u8 = 0xac; -pub const ISA_OP_LDY_ABSX: u8 = 0xac; +pub const ISA_OP_LDY_ABSX: u8 = 0xbc; + pub const ISA_OP_LSR_A: u8 = 0x4a; pub const ISA_OP_LSR_ZP: u8 = 0x46; pub const ISA_OP_LSR_ZPX: u8 = 0x56; pub const ISA_OP_LSR_ABS: u8 = 0x4e; pub const ISA_OP_LSR_ABSX: u8 = 0x5e; - pub const ISA_OP_NOP: u8 = 0xEA; - pub const ISA_OP_ORA_I: u8 = 0x09; pub const ISA_OP_ORA_ZP: u8 = 0x05; pub const ISA_OP_ORA_ZPX: u8 = 0x15; @@ -150,24 +121,15 @@ pub const ISA_OP_ORA_ABSX: u8 = 0x1d; pub const ISA_OP_ORA_ABSY: u8 = 0x19; pub const ISA_OP_ORA_INDX: u8 = 0x01; pub const ISA_OP_ORA_INDY: u8 = 0x11; - pub const ISA_OP_PHA: u8 = 0x48; - pub const ISA_OP_PHP: u8 = 0x08; -/// pub const ISA_OP_PLA: u8 = 0x68; -/// pub const ISA_OP_PLP: u8 = 0x28; - -/// -/// pub const ISA_OP_ROL_A: u8 = 0x2a; pub const ISA_OP_ROL_ZP: u8 = 0x26; pub const ISA_OP_ROL_ZPX: u8 = 0x36; pub const ISA_OP_ROL_ABS: u8 = 0x2e; pub const ISA_OP_ROL_ABSX: u8 = 0x3e; - -/// pub const ISA_OP_ROR_A: u8 = 0x6a; pub const ISA_OP_ROR_ZP: u8 = 0x66; pub const ISA_OP_ROR_ZPX: u8 = 0x76; @@ -204,4 +166,4 @@ pub const ISA_OP_TAY: u8 = 0xa8; pub const ISA_OP_TSX: u8 = 0xba; pub const ISA_OP_TXA: u8 = 0x8a; pub const ISA_OP_TXS: u8 = 0x9a; -pub const ISA_OP_TYA: u8 = 0x98; +pub const ISA_OP_TYA: u8 = 0x98; \ No newline at end of file diff --git a/core/src/constants/constants_isa_stub.rs b/core/src/constants/constants_isa_stub.rs new file mode 100644 index 0000000..d5fede4 --- /dev/null +++ b/core/src/constants/constants_isa_stub.rs @@ -0,0 +1,57 @@ +/// STUB Parts +pub const ISA_STUB_ADC: &str = "ADC"; +pub const ISA_STUB_AND: &str = "AND"; +pub const ISA_STUB_ASL: &str = "ASL"; +pub const ISA_STUB_BCC: &str = "BCC"; +pub const ISA_STUB_BCS: &str = "BCS"; +pub const ISA_STUB_BEQ: &str = "BEQ"; +pub const ISA_STUB_BIT: &str = "BIT"; +pub const ISA_STUB_BMI: &str = "BMI"; +pub const ISA_STUB_BNE: &str = "BNE"; +pub const ISA_STUB_BPL: &str = "BPL"; +pub const ISA_STUB_BRK: &str = "BRK"; +pub const ISA_STUB_BVC: &str = "BVC"; +pub const ISA_STUB_BVS: &str = "BVS"; +pub const ISA_STUB_CLC: &str = "CLC"; +pub const ISA_STUB_CLD: &str = "CLD"; +pub const ISA_STUB_CLI: &str = "CLI"; +pub const ISA_STUB_CLV: &str = "CLV"; +pub const ISA_STUB_CMP: &str = "CMP"; +pub const ISA_STUB_CPX: &str = "CPX"; +pub const ISA_STUB_CPY: &str = "CPY"; +pub const ISA_STUB_DEC: &str = "DEC"; +pub const ISA_STUB_DEX: &str = "DEX"; +pub const ISA_STUB_DEY: &str = "DEY"; +pub const ISA_STUB_EOR: &str = "EOR"; +pub const ISA_STUB_INC: &str = "INC"; +pub const ISA_STUB_INX: &str = "INX"; +pub const ISA_STUB_INY: &str = "INY"; +pub const ISA_STUB_JMP: &str = "JMP"; +pub const ISA_STUB_JSR: &str = "JSR"; +pub const ISA_STUB_LDA: &str = "LDA"; +pub const ISA_STUB_LDX: &str = "LDX"; +pub const ISA_STUB_LDY: &str = "LDY"; +pub const ISA_STUB_LSR: &str = "LSR"; +pub const ISA_STUB_NOP: &str = "NOP"; +pub const ISA_STUB_ORA: &str = "ORA"; +pub const ISA_STUB_PHA: &str = "PHA"; +pub const ISA_STUB_PHP: &str = "PHP"; +pub const ISA_STUB_PLA: &str = "PLA"; +pub const ISA_STUB_PLP: &str = "PLP"; +pub const ISA_STUB_ROL: &str = "ROL"; +pub const ISA_STUB_ROR: &str = "ROR"; +pub const ISA_STUB_RTI: &str = "RTI"; +pub const ISA_STUB_RTS: &str = "RTS"; +pub const ISA_STUB_SBC: &str = "SBC"; +pub const ISA_STUB_SEC: &str = "SEC"; +pub const ISA_STUB_SED: &str = "SED"; +pub const ISA_STUB_SEI: &str = "SEI"; +pub const ISA_STUB_STA: &str = "STA"; +pub const ISA_STUB_STX: &str = "STX"; +pub const ISA_STUB_STY: &str = "STY"; +pub const ISA_STUB_TAX: &str = "TAX"; +pub const ISA_STUB_TAY: &str = "TAY"; +pub const ISA_STUB_TSX: &str = "TSX"; +pub const ISA_STUB_TXA: &str = "TXA"; +pub const ISA_STUB_TXS: &str = "TXS"; +pub const ISA_STUB_TYA: &str = "TYA"; \ No newline at end of file diff --git a/core/src/constants/mod.rs b/core/src/constants/mod.rs new file mode 100644 index 0000000..3b70666 --- /dev/null +++ b/core/src/constants/mod.rs @@ -0,0 +1,2 @@ +pub mod constants_isa_stub; +pub mod constants_isa_op; diff --git a/core/src/instruction/execute.rs b/core/src/instruction/execute.rs new file mode 100644 index 0000000..825f225 --- /dev/null +++ b/core/src/instruction/execute.rs @@ -0,0 +1,285 @@ +use log::debug; +use crate::address_mode::AddressMode; +use crate::instruction::Instruction; +use crate::mos6502cpu::Mos6502Cpu; +use crate::mos6502flags::Mos6502Flag::{Carry, Decimal, Interrupt, Overflow}; + +impl Instruction { + fn execute(&self, mut system: Mos6502Cpu) { + match self { + // ADC – Add with Carry + // A,Z,C,N = A+M+C + // + // This instruction adds the contents of a memory location to the accumulator together with the carry bit. If overflow occurs the carry bit is set, this enables multiple byte addition to be performed. + // + // Processor Status after use: + // + // C Carry Flag Set if overflow in bit 7 + // Z Zero Flag Set if A = 0 + // I Interrupt Disable Not affected + // D Decimal Mode Flag Not affected + // B Break Command Not affected + // V Overflow Flag Set if sign bit is incorrect + // N Negative Flag Set if bit 7 set + Instruction::ADC(mode) => { + match mode { + AddressMode::Immediate(_) => {} + AddressMode::ZeroPage(_) => {} + AddressMode::ZeroPageX(_) => {} + AddressMode::Absolute(_) => {} + AddressMode::AbsoluteX(_) => {} + AddressMode::AbsoluteY(_) => {} + AddressMode::IndirectX(_) => {} + AddressMode::IndirectY(_) => {} + _ => {} + } + } + Instruction::AND(address) => { + match address { + AddressMode::Immediate(_) => {} + AddressMode::ZeroPage(_) => {} + AddressMode::ZeroPageX(_) => {} + AddressMode::Absolute(_) => {} + AddressMode::AbsoluteX(_) => {} + AddressMode::AbsoluteY(_) => {} + AddressMode::IndirectX(_) => {} + AddressMode::IndirectY(_) => {} + _ => { + // NOOP + } + } + } + Instruction::ASL(mode) => { + match mode { + // ISA_OP_ASL_A + AddressMode::Accumulator => {} + AddressMode::ZeroPage(_) => {} + AddressMode::ZeroPageX(_) => {} + AddressMode::Absolute(_) => {} + AddressMode::AbsoluteX(_) => {} + _ => {} + } + } + Instruction::BCC(mode) => { + match mode { + AddressMode::Immediate(value) => {} + _ => {} + } + } + Instruction::BCS(mode) => { + match mode { + AddressMode::Immediate(value) => {} + _ => {} + } + } + Instruction::BEQ(mode) => { + match mode { + AddressMode::Immediate(value) => {} + _ => {} + } + } + Instruction::BIT(mode) => { + match mode { + AddressMode::ZeroPage(value) => {} + AddressMode::Absolute(value) => {} + _ => {} + } + } + Instruction::BMI(mode) => { + match mode { + AddressMode::Immediate(value) => {} + _ => {} + } + } + Instruction::BNE(mode) => { + match mode { + AddressMode::Immediate(value) => {} + _ => {} + } + } + Instruction::BPL(mode) => { + match mode { + AddressMode::Immediate(value) => {} + _ => {} + } + } + Instruction::BRK => {} + Instruction::BVC(mode) => { + match mode { + AddressMode::Immediate(value) => {} + _ => {} + } + } + Instruction::BVS(mode) => { + match mode { + AddressMode::Immediate(value) => {} + _ => {} + } + } + Instruction::CLC => { + system.poke_flag(Carry, false) + } + Instruction::CLD => { + system.poke_flag(Decimal, false) + } + Instruction::CLI => { + system.poke_flag(Interrupt, false) + } + Instruction::CLV => { + system.poke_flag(Overflow, false) + } + Instruction::CMP(mode) => { + match mode { + AddressMode::Immediate(_) => {} + AddressMode::ZeroPage(_) => {} + AddressMode::ZeroPageX(_) => {} + AddressMode::Absolute(_) => {} + AddressMode::AbsoluteX(_) => {} + AddressMode::AbsoluteY(_) => {} + AddressMode::IndirectX(_) => {} + AddressMode::IndirectY(_) => {} + _ => {} + } + } + Instruction::CPX(mode) => { + match mode { + AddressMode::Immediate(_) => {} + AddressMode::ZeroPage(_) => {} + AddressMode::ZeroPageX(_) => {} + AddressMode::Absolute(_) => {} + AddressMode::AbsoluteX(_) => {} + AddressMode::AbsoluteY(_) => {} + AddressMode::IndirectX(_) => {} + AddressMode::IndirectY(_) => {} + _ => {} + } + } + Instruction::CPY(mode) => { + match mode { + AddressMode::Immediate(_) => {} + AddressMode::ZeroPage(_) => {} + AddressMode::ZeroPageX(_) => {} + AddressMode::Absolute(_) => {} + AddressMode::AbsoluteX(_) => {} + AddressMode::AbsoluteY(_) => {} + AddressMode::IndirectX(_) => {} + AddressMode::IndirectY(_) => {} + _ => {} + } + } + Instruction::DEC(mode) => { + match mode { + AddressMode::ZeroPage(_) => {} + AddressMode::ZeroPageX(_) => {} + AddressMode::Absolute(_) => {} + AddressMode::AbsoluteX(_) => {} + _ => {} + } + } + Instruction::DEX => { + let mut x = system.peek_x(); + x -= 1; + system.poke_x(x); + } + Instruction::DEY => { + let mut y = system.peek_y(); + y -= 1; + system.poke_y(y); + } + Instruction::EOR(mode) => { + match mode { + AddressMode::Immediate(_) => {} + AddressMode::ZeroPage(_) => {} + AddressMode::ZeroPageX(_) => {} + AddressMode::Absolute(_) => {} + AddressMode::AbsoluteX(_) => {} + AddressMode::AbsoluteY(_) => {} + AddressMode::IndirectX(_) => {} + AddressMode::IndirectY(_) => {} + _ => {} + } + } + Instruction::INC(mode) => { + match mode { + AddressMode::ZeroPage(value) => {} + AddressMode::ZeroPageX(value) => {} + AddressMode::Absolute(value) => {} + AddressMode::AbsoluteX(value) => {} + _ => {} + } + } + Instruction::INX => { + let mut x = system.peek_x(); + x += 1; + system.poke_x(x); + } + Instruction::INY => { + let mut y = system.peek_y(); + y += 1; + system.poke_y(y); + } + Instruction::JMP(mode) => { + match mode { + AddressMode::Absolute(_) => {} + AddressMode::IndirectX(_) => {} + _ => {} + } + } + Instruction::JSR(mode) => { + match mode { + AddressMode::Absolute(address) => {} + _ => {} + } + } + Instruction::LDA(mode) => { + match mode { + AddressMode::Immediate(value) => { + system.poke_a(*value) + } + AddressMode::ZeroPage(offset) => { + let value_to_write = system.peek(*offset as u16); + system.poke_a(value_to_write); + } + AddressMode::ZeroPageX(_) => { + let current_x = system.peek_x(); + } + AddressMode::Absolute(_) => {} + AddressMode::AbsoluteX(_) => {} + AddressMode::AbsoluteY(_) => {} + AddressMode::IndirectX(_) => {} + AddressMode::IndirectY(_) => {} + _ => { + debug!("Invalid LDA instruction"); + } + }; + } + Instruction::LDX(_) => {} + Instruction::LDY(_) => {} + Instruction::LSR(_) => {} + Instruction::NOP => {} + Instruction::ORA(_) => {} + Instruction::PHA => {} + Instruction::PHP => {} + Instruction::PLA => {} + Instruction::PLP => {} + Instruction::ROL(_) => {} + Instruction::ROR(_) => {} + Instruction::RTI => {} + Instruction::RTS => {} + Instruction::SBC(_) => {} + Instruction::SEC => {} + Instruction::SED => {} + Instruction::SEI => {} + Instruction::STA(_) => {} + Instruction::STX(_) => {} + Instruction::STY(_) => {} + Instruction::TAX => {} + Instruction::TAY => {} + Instruction::TSX => {} + Instruction::TXA => {} + Instruction::TXS => {} + Instruction::TYA => {} + }; + } + +} \ No newline at end of file diff --git a/core/src/instruction/from_bytes.rs b/core/src/instruction/from_bytes.rs new file mode 100644 index 0000000..fdae24e --- /dev/null +++ b/core/src/instruction/from_bytes.rs @@ -0,0 +1,183 @@ +use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Accumulator, Immediate, Implied, IndirectX, IndirectY, ZeroPage, ZeroPageX, ZeroPageY}; +use crate::constants::constants_isa_op::*; +use crate::instruction::Instruction; +use crate::instruction::Instruction::*; + +fn join_word(low: u8, high: u8) -> u16 { + ((high as u16) << 8) & low as u16 +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_join_word() { + let low: u8 = 0xcd; + let high: u8 = 0xab; + + assert_eq!( + join_word(low, high), + 0xabcd + ); + } +} + +impl Instruction { + pub fn from_bytes(decode_from: Vec) -> Instruction { + let id_byte = decode_from[0]; + + match id_byte { + /// ADC + ISA_OP_ADC_I..=ISA_OP_ADC_I => ADC(Immediate(decode_from[1])), + ISA_OP_ADC_Z..=ISA_OP_ADC_Z => ADC(ZeroPage(decode_from[1])), + ISA_OP_ADC_ZX..=ISA_OP_ADC_ZX => ADC(ZeroPageX(decode_from[1])), + ISA_OP_ADC_ABS..=ISA_OP_ADC_ABS => ADC(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_ADC_ABSX..=ISA_OP_ADC_ABSX => ADC(AbsoluteX(join_word(decode_from[1], decode_from[2]))), + ISA_OP_ADC_ABSY..=ISA_OP_ADC_ABSY => ADC(AbsoluteY(join_word(decode_from[1], decode_from[2]))), + ISA_OP_ADC_INDX..=ISA_OP_ADC_INDX => ADC(IndirectX(decode_from[1])), + ISA_OP_ADC_INDY..=ISA_OP_ADC_INDY => ADC(IndirectY(decode_from[1])), + ISA_OP_AND_I..=ISA_OP_AND_I => AND(Immediate(decode_from[1])), + ISA_OP_AND_Z..=ISA_OP_AND_Z => AND(ZeroPage(decode_from[1])), + ISA_OP_AND_ZX..=ISA_OP_AND_ZX => AND(ZeroPageX(decode_from[1])), + ISA_OP_AND_ABS..=ISA_OP_AND_ABS => AND(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_AND_ABSX..=ISA_OP_AND_ABSX => AND(AbsoluteX(join_word(decode_from[1], decode_from[2]))), + ISA_OP_AND_ABSY..=ISA_OP_AND_ABSY => AND(AbsoluteY(join_word(decode_from[1], decode_from[2]))), + ISA_OP_AND_INDX..=ISA_OP_AND_INDX => AND(IndirectX(decode_from[1])), + ISA_OP_AND_INDY..=ISA_OP_AND_INDY => AND(IndirectY(decode_from[1])), + ISA_OP_ASL_A..=ISA_OP_ASL_A => ASL(Accumulator), + ISA_OP_ASL_Z..=ISA_OP_ASL_Z => ASL(ZeroPage(decode_from[1])), + ISA_OP_ASL_ZX..=ISA_OP_ASL_ZX => ASL(ZeroPageX(decode_from[1])), + ISA_OP_ASL_ABS..=ISA_OP_ASL_ABS => ASL(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_ASL_ABSX..=ISA_OP_ASL_ABSX => ASL(AbsoluteX(join_word(decode_from[1], decode_from[2]))), + ISA_OP_BCC..=ISA_OP_BCC => BCC(Immediate(decode_from[1])), + ISA_OP_BCS..=ISA_OP_BCS => BCS(Immediate(decode_from[1])), + ISA_OP_BEQ..=ISA_OP_BEQ => BEQ(Immediate(decode_from[1])), + ISA_OP_BIT_ZP..=ISA_OP_BIT_ZP => BIT(ZeroPage(decode_from[1])), + ISA_OP_BIT_ABS..=ISA_OP_BIT_ABS => BIT(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_BMI..=ISA_OP_BMI => BMI(Immediate(decode_from[1])), + ISA_OP_BNE..=ISA_OP_BNE => BNE(Immediate(decode_from[1])), + ISA_OP_BPL..=ISA_OP_BPL => BPL(Immediate(decode_from[1])), + ISA_OP_BRK..=ISA_OP_BRK => BRK, + ISA_OP_BVC..=ISA_OP_BVC => BVC(Immediate(decode_from[1])), + ISA_OP_BVS..=ISA_OP_BVS => BVS(Immediate(decode_from[1])), + ISA_OP_CLC..=ISA_OP_CLC => CLC, + ISA_OP_CLD..=ISA_OP_CLD => CLD, + ISA_OP_CLI..=ISA_OP_CLI => CLI, + ISA_OP_CLV..=ISA_OP_CLV => CLV, + ISA_OP_CMP_I..=ISA_OP_CMP_I => CMP(Immediate(decode_from[1])), + ISA_OP_CMP_ZP..=ISA_OP_CMP_ZP => CMP(ZeroPage(decode_from[1])), + ISA_OP_CMP_ZPX..=ISA_OP_CMP_ZPX => CMP(ZeroPageX(decode_from[1])), + ISA_OP_CMP_ABS..=ISA_OP_CMP_ABS => CMP(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_CMP_ABSX..=ISA_OP_CMP_ABSX => CMP(AbsoluteX(join_word(decode_from[1], decode_from[2]))), + ISA_OP_CMP_INDX..=ISA_OP_CMP_INDX => CMP(IndirectX(decode_from[1])), + ISA_OP_CMP_INDY..=ISA_OP_CMP_INDY => CMP(IndirectY(decode_from[1])), + ISA_OP_CPX_I..=ISA_OP_CPX_I => CPX(Immediate(decode_from[1])), + ISA_OP_CPX_ZP..=ISA_OP_CPX_ZP => CPX(ZeroPage(decode_from[1])), + ISA_OP_CPX_ABS..=ISA_OP_CPX_ABS => CPX(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_CPY_I..=ISA_OP_CPY_I => CPY(Immediate(decode_from[1])), + ISA_OP_CPY_ZP..=ISA_OP_CPY_ZP => CPY(ZeroPage(decode_from[1])), + ISA_OP_CPY_ABS..=ISA_OP_CPY_ABS => CPY(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_DEC_ZP..=ISA_OP_DEC_ZP => DEC(ZeroPage(decode_from[1])), + ISA_OP_DEC_ZPX..=ISA_OP_DEC_ZPX => DEC(ZeroPageX(decode_from[1])), + ISA_OP_DEX..=ISA_OP_DEX => DEX, + ISA_OP_DEY..=ISA_OP_DEY => DEY, + ISA_OP_EOR_I..=ISA_OP_EOR_I => EOR(Immediate(decode_from[1])), + ISA_OP_EOR_ZP..=ISA_OP_EOR_ZP => EOR(ZeroPage(decode_from[1])), + ISA_OP_EOR_ZPX..=ISA_OP_EOR_ZPX => EOR(ZeroPageX(decode_from[1])), + ISA_OP_EOR_ABS..=ISA_OP_EOR_ABS => EOR(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_EOR_ABSX..=ISA_OP_EOR_ABSX => EOR(AbsoluteX(join_word(decode_from[1], decode_from[2]))), + ISA_OP_EOR_ABSY..=ISA_OP_EOR_ABSY => EOR(AbsoluteY(join_word(decode_from[1], decode_from[2]))), + ISA_OP_EOR_INDX..=ISA_OP_EOR_INDX => EOR(IndirectX(decode_from[1])), + ISA_OP_EOR_INDY..=ISA_OP_EOR_INDY => EOR(IndirectY(decode_from[1])), + ISA_OP_INC_ZP..=ISA_OP_INC_ZP => INC(ZeroPage(decode_from[1])), + ISA_OP_INC_ZPX..=ISA_OP_INC_ZPX => INC(ZeroPageX(decode_from[1])), + ISA_OP_INC_ABS..=ISA_OP_INC_ABS => INC(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_INC_ABSX..=ISA_OP_INC_ABSX => INC(AbsoluteX(join_word(decode_from[1], decode_from[2]))), + ISA_OP_INX..=ISA_OP_INX => INX, + ISA_OP_INY..=ISA_OP_INY => INY, + ISA_OP_JMP_ABS..=ISA_OP_JMP_ABS => JMP(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_JMP_IND..=ISA_OP_JMP_IND => JMP(IndirectX(decode_from[1])), + ISA_OP_JSR..=ISA_OP_JSR => JSR(Immediate(decode_from[1])), + ISA_OP_LDA_I..=ISA_OP_LDA_I => LDA(Immediate(decode_from[1])), + ISA_OP_LDA_Z..=ISA_OP_LDA_Z => LDA(ZeroPage(decode_from[1])), + ISA_OP_LDA_ZX..=ISA_OP_LDA_ZX => LDA(ZeroPageX(decode_from[1])), + ISA_OP_LDA_ABS..=ISA_OP_LDA_ABS => LDA(Absolute(join_word(decode_from[1], decode_from[2]))), + IAS_OP_LDA_ABSX..=IAS_OP_LDA_ABSX => LDA(AbsoluteX(join_word(decode_from[1], decode_from[2]))), + ISA_OP_LDA_ABSY..=ISA_OP_LDA_ABSY => LDA(AbsoluteY(join_word(decode_from[1], decode_from[2]))), + ISA_OP_LDA_INDX..=ISA_OP_LDA_INDX => LDA(IndirectX(decode_from[1])), + ISA_OP_LDA_INDY..=ISA_OP_LDA_INDY => LDA(IndirectY(decode_from[1])), + ISA_OP_LDX_I..=ISA_OP_LDX_I => LDX(Immediate(decode_from[1])), + ISA_OP_LDX_ZP..=ISA_OP_LDX_ZP => LDX(ZeroPage(decode_from[1])), + ISA_OP_LDX_ZPY..=ISA_OP_LDX_ZPY => LDX(ZeroPageY(decode_from[1])), + ISA_OP_LDX_ABS..=ISA_OP_LDX_ABS => LDX(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_LDX_ABSY..=ISA_OP_LDX_ABSY => LDX(AbsoluteY(join_word(decode_from[1], decode_from[2]))), + ISA_OP_LDY_I..=ISA_OP_LDY_I => LDY(Immediate(decode_from[1])), + ISA_OP_LDY_ZP..=ISA_OP_LDY_ZP => LDY(ZeroPage(decode_from[1])), + ISA_OP_LDY_ZPX..=ISA_OP_LDY_ZPX => LDY(ZeroPageX(decode_from[1])), + ISA_OP_LDY_ABS..=ISA_OP_LDY_ABS => LDY(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_LDY_ABSX..=ISA_OP_LDY_ABSX => LDY(AbsoluteX(join_word(decode_from[1], decode_from[2]))), + ISA_OP_LSR_A..=ISA_OP_LSR_A => LSR(Accumulator), + ISA_OP_LSR_ZP..=ISA_OP_LSR_ZP => LSR(ZeroPage(decode_from[1])), + ISA_OP_LSR_ZPX..=ISA_OP_LSR_ZPX => LSR(ZeroPageX(decode_from[1])), + ISA_OP_LSR_ABS..=ISA_OP_LSR_ABS => LSR(Absolute(join_word(decode_from[1], decode_from[2]))), + ISA_OP_LSR_ABSX..=ISA_OP_LSR_ABSX => LSR(AbsoluteX(join_word(decode_from[1], decode_from[2]))), + ISA_OP_NOP..=ISA_OP_NOP => NOP, + // ISA_OP_ORA_I..=ISA_OP_ORA_I => {} + // ISA_OP_ORA_ZP..=ISA_OP_ORA_ZP => {} + // ISA_OP_ORA_ZPX..=ISA_OP_ORA_ZPX => {} + // ISA_OP_ORA_ABS..=ISA_OP_ORA_ABS => {} + // ISA_OP_ORA_ABSX..=ISA_OP_ORA_ABSX => {} + // ISA_OP_ORA_ABSY..=ISA_OP_ORA_ABSY => {} + // ISA_OP_ORA_INDX..=ISA_OP_ORA_INDX => {} + // ISA_OP_ORA_INDY..=ISA_OP_ORA_INDY => {} + // ISA_OP_PHA..=ISA_OP_PHA => {} + // ISA_OP_PHP..=ISA_OP_PHP => {} + // ISA_OP_PLA..=ISA_OP_PLA => {} + // ISA_OP_PLP..=ISA_OP_PLP => {} + // ISA_OP_ROL_A..=ISA_OP_ROL_A => {} + // ISA_OP_ROL_ZP..=ISA_OP_ROL_ZP => {} + // ISA_OP_ROL_ZPX..=ISA_OP_ROL_ZPX => {} + // ISA_OP_ROL_ABS..=ISA_OP_ROL_ABS => {} + // ISA_OP_ROL_ABSX..=ISA_OP_ROL_ABSX => {} + // ISA_OP_ROR_A..=ISA_OP_ROR_A => {} + // ISA_OP_ROR_ZP..=ISA_OP_ROR_ZP => {} + // ISA_OP_ROR_ZPX..=ISA_OP_ROR_ZPX => {} + // ISA_OP_ROR_ABS..=ISA_OP_ROR_ABS => {} + // ISA_OP_ROR_ABSX..=ISA_OP_ROR_ABSX => {} + // ISA_OP_RTI..=ISA_OP_RTI => {} + // ISA_OP_RTS..=ISA_OP_RTS => {} + // ISA_OP_SBC_I..=ISA_OP_SBC_I => {} + // ISA_OP_SBC_ZP..=ISA_OP_SBC_ZP => {} + // ISA_OP_SBC_ZPX..=ISA_OP_SBC_ZPX => {} + // ISA_OP_SBC_ABS..=ISA_OP_SBC_ABS => {} + // ISA_OP_SBC_ABSX..=ISA_OP_SBC_ABSX => {} + // ISA_OP_SBC_ABSY..=ISA_OP_SBC_ABSY => {} + // ISA_OP_SBC_INDX..=ISA_OP_SBC_INDX => {} + // ISA_OP_SBC_INDY..=ISA_OP_SBC_INDY => {} + // ISA_OP_SEC..=ISA_OP_SEC => {} + // ISA_OP_SED..=ISA_OP_SED => {} + // ISA_OP_SEI..=ISA_OP_SEI => {} + // ISA_OP_STA_ZP..=ISA_OP_STA_ZP => {} + // ISA_OP_STA_ZPX..=ISA_OP_STA_ZPX => {} + // ISA_OP_STA_ABS..=ISA_OP_STA_ABS => {} + // ISA_OP_STA_ABSX..=ISA_OP_STA_ABSX => {} + // ISA_OP_STA_ABSY..=ISA_OP_STA_ABSY => {} + // ISA_OP_STA_INDX..=ISA_OP_STA_INDX => {} + // ISA_OP_STA_INDY..=ISA_OP_STA_INDY => {} + // ISA_OP_STX_ZP..=ISA_OP_STX_ZP => {} + // ISA_OP_STX_ZPX..=ISA_OP_STX_ZPX => {} + // ISA_OP_STX_ABS..=ISA_OP_STX_ABS => {} + // ISA_OP_STY_ZP..=ISA_OP_STY_ZP => {} + // ISA_OP_STY_ZPX..=ISA_OP_STY_ZPX => {} + // ISA_OP_STY_ABS..=ISA_OP_STY_ABS => {} + // ISA_OP_TAX..=ISA_OP_TAX => {} + // ISA_OP_TAY..=ISA_OP_TAY => {} + // ISA_OP_TSX..=ISA_OP_TSX => {} + // ISA_OP_TXA..=ISA_OP_TXA => {} + // ISA_OP_TXS..=ISA_OP_TXS => {} + // ISA_OP_TYA..=ISA_OP_TYA => {} + _ => NOP + } + } +} \ No newline at end of file diff --git a/core/src/instruction.rs b/core/src/instruction/mod.rs similarity index 57% rename from core/src/instruction.rs rename to core/src/instruction/mod.rs index 270e435..6dedbc8 100644 --- a/core/src/instruction.rs +++ b/core/src/instruction/mod.rs @@ -1,15 +1,14 @@ -use std::fmt::format; -use log::debug; use crate::address_mode::AddressMode; use crate::address_mode::AddressMode::*; -use crate::constants::*; use crate::instruction::Instruction::*; -use crate::instruction_stringify::InstructionStringify; -use crate::isa::microcode_steps::MicrocodeStep; -use crate::isa::microcode_steps::MicrocodeStep::{ALUAddC, ReadRegisterA}; -use crate::mos6502cpu::Mos6502Cpu; use crate::mos6502flags::Mos6502Flag::*; +mod from_bytes; +mod to_bytes; +mod execute; +mod stub; +mod to_string; + #[derive(PartialEq, Debug)] pub enum Instruction { /// ADC – Add with Carry @@ -1020,694 +1019,6 @@ pub enum Instruction { TYA, } - -impl Instruction { - pub fn from_bytes(decode_from: Vec) -> Instruction { - let id_byte = decode_from[0]; - - match id_byte { - /// ADC - ISA_OP_ADC_I..=ISA_OP_ADC_I => { - if decode_from.len() == 2 { - ADC(Immediate(decode_from[1])) - } else { - NOP - } - } - ISA_OP_ADC_Z..=ISA_OP_ADC_Z => { - ADC(ZeroPage(decode_from[1])) - } - ISA_OP_ADC_ZX..=ISA_OP_ADC_ZX => { - ADC(ZeroPageX(decode_from[1])) - } - ISA_OP_ADC_ABS..=ISA_OP_ADC_ABS => { - // build the u16 from the u8[1] and u8[2] - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - ADC(Absolute(word)) - } - ISA_OP_ADC_ABSX..=ISA_OP_ADC_ABSX => { - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - ADC(AbsoluteX(word)) - } - ISA_OP_ADC_ABSY..=ISA_OP_ADC_ABSY => { - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - ADC(AbsoluteY(word)) - } - ISA_OP_ADC_INDX..=ISA_OP_ADC_INDX => { - ADC(IndirectX(decode_from[1])) - } - ISA_OP_ADC_INDY..=ISA_OP_ADC_INDY => { - ADC(IndirectY(decode_from[1])) - } - /// AND - ISA_OP_AND_I..=ISA_OP_AND_I => { - AND(Immediate(decode_from[1])) - } - ISA_OP_AND_Z..=ISA_OP_AND_Z => { - AND(ZeroPage(decode_from[1])) - } - ISA_OP_AND_ZX..=ISA_OP_AND_ZX => { - AND(ZeroPageX(decode_from[1])) - } - ISA_OP_AND_ABS..=ISA_OP_AND_ABS => { - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - AND(Absolute(word)) - } - ISA_OP_AND_ABSX..=ISA_OP_AND_ABSX => { - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - AND(AbsoluteX(word)) - } - ISA_OP_AND_ABSY..=ISA_OP_AND_ABSY => { - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - AND(AbsoluteY(word)) - } - ISA_OP_AND_INDX..=ISA_OP_AND_INDX => { - AND(IndirectX(decode_from[1])) - } - ISA_OP_AND_INDY..=ISA_OP_AND_INDY => { - AND(IndirectY(decode_from[1])) - } - ISA_OP_ASL_A..=ISA_OP_ASL_A => { - ASL(Accumulator) - } - ISA_OP_ASL_Z..=ISA_OP_ASL_Z => { - ASL(ZeroPage(decode_from[1])) - } - ISA_OP_ASL_ZX..=ISA_OP_ASL_ZX => { - ASL(ZeroPageX(decode_from[1])) - } - ISA_OP_ASL_ABS..=ISA_OP_ASL_ABS => { - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - ASL(Absolute(word)) - } - ISA_OP_ASL_ABSX..=ISA_OP_ASL_ABSX => { - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - ASL(AbsoluteX(word)) - } - ISA_OP_BCC..=ISA_OP_BCC => { - BCC(Immediate(decode_from[1])) - } - ISA_OP_BCS..=ISA_OP_BCS => { - BCS(Immediate(decode_from[1])) - } - ISA_OP_BEQ..=ISA_OP_BEQ => { - BEQ(Immediate(decode_from[1])) - } - ISA_OP_BIT_ZP..=ISA_OP_BIT_ZP => { - BIT(ZeroPage(decode_from[1])) - } - ISA_OP_BIT_ABS..=ISA_OP_BIT_ABS => { - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - BIT(Absolute(word)) - } - ISA_OP_BMI..=ISA_OP_BMI => { - BMI(Immediate(decode_from[1])) - } - ISA_OP_BNE..=ISA_OP_BNE => { - BNE(Immediate(decode_from[1])) - } - ISA_OP_BPL..=ISA_OP_BPL => { - BPL(Immediate(decode_from[1])) - } - ISA_OP_BRK..=ISA_OP_BRK => { - BRK - } - ISA_OP_BVC..=ISA_OP_BVC => { - BVC(AddressMode::Immediate(decode_from[1])) - } - ISA_OP_BVS..=ISA_OP_BVS => { - BVS(Immediate(decode_from[1])) - } - ISA_OP_CLC..=ISA_OP_CLC => { - CLC - } - ISA_OP_CLD..=ISA_OP_CLD => { - CLD - } - ISA_OP_CLI..=ISA_OP_CLI => { - CLI - } - ISA_OP_CLV..=ISA_OP_CLV => { - CLV - } - ISA_OP_CMP_I..=ISA_OP_CMP_I => { - CMP(Immediate(decode_from[1])) - } - ISA_OP_CMP_ZP..=ISA_OP_CMP_ZP => { - CMP(ZeroPage(decode_from[1])) - } - ISA_OP_CMP_ZPX..=ISA_OP_CMP_ZPX => { - CMP(ZeroPageX(decode_from[1])) - } - ISA_OP_CMP_ABS..=ISA_OP_CMP_ABS => { - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - CMP(Absolute(word)) - } - ISA_OP_CMP_ABSX..=ISA_OP_CMP_ABSX => { - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - CMP(AbsoluteX(word)) - } - ISA_OP_CMP_INDX..=ISA_OP_CMP_INDX => { - CMP(IndirectX(decode_from[1])) - } - ISA_OP_CMP_INDY..=ISA_OP_CMP_INDY => { - CMP(IndirectY(decode_from[1])) - } - ISA_OP_CPX_I..=ISA_OP_CPX_I => { - CPX(Immediate(decode_from[1])) - } - ISA_OP_CPX_ZP..=ISA_OP_CPX_ZP => { - CPX(ZeroPage(decode_from[1])) - } - ISA_OP_CPX_ABS..=ISA_OP_CPX_ABS => { - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - CPX(Absolute(word)) - } - ISA_OP_CPY_I..=ISA_OP_CPY_I => { - CPY(Immediate(decode_from[1])) - } - ISA_OP_CPY_ZP..=ISA_OP_CPY_ZP => { - CPY(ZeroPage(decode_from[1])) - } - ISA_OP_CPY_ABS..=ISA_OP_CPY_ABS => { - let word = ((decode_from[2] as u16) << 8 | decode_from[1] as u16) as u16; - CPY(Absolute(word)) - } - ISA_OP_DEC_ZP..=ISA_OP_DEC_ZP => { - DEC(ZeroPage(decode_from[1])) - } - ISA_OP_DEC_ZPX..=ISA_OP_DEC_ZPX => { - DEC(ZeroPageX(decode_from[1])) - } - _ => NOP - } - } - - pub fn to_bytes(&self) -> Vec { - match self { - ADC(mode) => { - match mode { - Immediate(value) => - vec![ISA_OP_ADC_I, *value], - - ZeroPage(offset) => - vec![ISA_OP_ADC_Z, *offset], - - ZeroPageX(value) => - vec![ISA_OP_ADC_ZX, *value], - - Absolute(offset) => { - let high = ((offset & 0xff00) >> 8) as u8; - let low = (offset & 0x00ff) as u8; - vec![ISA_OP_ADC_ABS, low, high] - } - AbsoluteX(offset) => { - let high = ((offset & 0xff00) >> 8) as u8; - let low = (offset & 0x00ff) as u8; - vec![ISA_OP_ADC_ABSX, low, high] - } - AbsoluteY(offset) => { - let high = ((offset & 0xff00) >> 8) as u8; - let low = (offset & 0x00ff) as u8; - vec![ISA_OP_ADC_ABSY, low, high] - } - IndirectX(offset) => - vec![ISA_OP_ADC_INDX, *offset], - IndirectY(offset) => - vec![ISA_OP_ADC_INDY, *offset], - _ => { vec![] } - } - } - AND(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_AND_I, *value], - ZeroPage(value) => vec![ISA_OP_AND_Z, *value], - ZeroPageX(value) => vec![ISA_OP_AND_ZX, *value], - Absolute(offset) => { - let high = ((offset & 0xff00) >> 8) as u8; - let low = (offset & 0x00ff) as u8; - vec![ISA_OP_AND_ABS, low, high] - } - AbsoluteX(offset) => { - let high = ((offset & 0xff00) >> 8) as u8; - let low = (offset & 0x00ff) as u8; - vec![ISA_OP_AND_ABSX, low, high] - } - AbsoluteY(offset) => { - let high = ((offset & 0xff00) >> 8) as u8; - let low = (offset & 0x00ff) as u8; - vec![ISA_OP_AND_ABSY, low, high] - } - IndirectX(value) => vec![ISA_OP_AND_INDX, *value], - IndirectY(value) => vec![ISA_OP_AND_INDY, *value], - _ => vec![] - } - } - // ASL(_) => {} - // BCC(_) => {} - // BCS(_) => {} - // BEQ(_) => {} - // BIT(_) => {} - // BMI(_) => {} - // BNE(_) => {} - // BPL(_) => {} - // BRK => {} - // BVC(_) => {} - // BVS(_) => {} - // CLC => {} - // CLD => {} - // CLI => {} - // CLV => {} - // CMP(_) => {} - // CPX(_) => {} - // CPY(_) => {} - // DEC(_) => {} - // DEX => {} - // DEY => {} - // EOR(_) => {} - // INC(_) => {} - // INX => {} - // INY => {} - // JMP(_) => {} - // JSR(_) => {} - // LDA(_) => {} - // LDX(_) => {} - // LDY(_) => {} - // LSR(_) => {} - // NOP => {} - // ORA(_) => {} - // PHA => {} - // PHP => {} - // PLA => {} - // PLP => {} - // ROL(_) => {} - // ROR(_) => {} - // RTI => {} - // RTS => {} - // SBC(_) => {} - // SEC => {} - // SED => {} - // SEI => {} - // STA(_) => {} - // STX(_) => {} - // STY(_) => {} - // TAX => {} - // TAY => {} - // TSX => {} - // TXA => {} - // TXS => {} - // TYA => {} - _ => { vec![] } - } - } - - - pub fn to_string(&self) -> String { - match self { - Instruction::ADC(newmode) => { - let prefix = "ADC"; - match newmode { - Immediate(value) => { - InstructionStringify::format(Immediate(*value), prefix) - } - ZeroPage(address) => { - InstructionStringify::format(ZeroPage(*address), prefix) - } - ZeroPageX(address) => { - InstructionStringify::format(ZeroPageX(*address), prefix) - } - Absolute(address) => { - InstructionStringify::format(Absolute(*address), prefix) - } - AbsoluteX(offset) => { - InstructionStringify::format(AbsoluteX(*offset), prefix) - } - AbsoluteY(offset) => { - InstructionStringify::format(AbsoluteY(*offset), prefix) - } - IndirectX(value) => { - InstructionStringify::format(IndirectX(*value), prefix) - - } - IndirectY(value) => { - InstructionStringify::format(IndirectY(*value), prefix) - } - _ => String::from("Invalid instruction") - } - } - Instruction::AND(newmode) => { - let prefix = "AND"; - match newmode { - Immediate(value) => { - InstructionStringify::format(Immediate(*value), prefix) - } - ZeroPage(address) => { - InstructionStringify::format(ZeroPage(*address), prefix) - } - ZeroPageX(address) => { - InstructionStringify::format(ZeroPageX(*address), prefix) - } - Absolute(address) => { - InstructionStringify::format(Absolute(*address), prefix) - } - AbsoluteX(offset) => { - InstructionStringify::format(AbsoluteX(*offset), prefix) - } - AbsoluteY(offset) => { - InstructionStringify::format(AbsoluteY(*offset), prefix) - } - IndirectX(value) => { - InstructionStringify::format(IndirectX(*value), prefix) - - } - IndirectY(value) => { - InstructionStringify::format(IndirectY(*value), prefix) - } - _ => String::from("Invalid instruction") - } - } - Instruction::ASL(_) => { - String::from("TBD") - } - Instruction::BCC(_) => { - String::from("TBD") - } - Instruction::BCS(_) => { - String::from("TBD") - } - Instruction::BEQ(_) => { - String::from("TBD") - } - Instruction::BIT(_) => { - String::from("TBD") - } - Instruction::BMI(_) => { - String::from("TBD") - } - Instruction::BNE(_) => { - String::from("TBD") - } - Instruction::BPL(_) => { - String::from("TBD") - } - Instruction::BRK => { - String::from("TBD") - } - Instruction::BVC(_) => { - String::from("TBD") - } - Instruction::BVS(_) => { - String::from("TBD") - } - Instruction::CLC => { - String::from("CLC") - } - Instruction::CLD => { - String::from("CLD") - } - _ => { - String::from("TBD") - } - } - } - fn execute(&self, mut system: Mos6502Cpu) { - match self { - // ADC – Add with Carry - // A,Z,C,N = A+M+C - // - // This instruction adds the contents of a memory location to the accumulator together with the carry bit. If overflow occurs the carry bit is set, this enables multiple byte addition to be performed. - // - // Processor Status after use: - // - // C Carry Flag Set if overflow in bit 7 - // Z Zero Flag Set if A = 0 - // I Interrupt Disable Not affected - // D Decimal Mode Flag Not affected - // B Break Command Not affected - // V Overflow Flag Set if sign bit is incorrect - // N Negative Flag Set if bit 7 set - Instruction::ADC(mode) => { - match mode { - AddressMode::Immediate(_) => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => {} - } - } - Instruction::AND(address) => { - match address { - AddressMode::Immediate(_) => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => { - // NOOP - } - } - } - Instruction::ASL(mode) => { - match mode { - // ISA_OP_ASL_A - AddressMode::Accumulator => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - _ => {} - } - } - Instruction::BCC(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BCS(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BEQ(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BIT(mode) => { - match mode { - AddressMode::ZeroPage(value) => {} - AddressMode::Absolute(value) => {} - _ => {} - } - } - Instruction::BMI(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BNE(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BPL(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BRK => {} - Instruction::BVC(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BVS(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::CLC => { - system.poke_flag(Carry, false) - } - Instruction::CLD => { - system.poke_flag(Decimal, false) - } - Instruction::CLI => { - system.poke_flag(Interrupt, false) - } - Instruction::CLV => { - system.poke_flag(Overflow, false) - } - Instruction::CMP(mode) => { - match mode { - AddressMode::Immediate(_) => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => {} - } - } - Instruction::CPX(mode) => { - match mode { - AddressMode::Immediate(_) => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => {} - } - } - Instruction::CPY(mode) => { - match mode { - AddressMode::Immediate(_) => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => {} - } - } - Instruction::DEC(mode) => { - match mode { - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - _ => {} - } - } - Instruction::DEX => { - let mut x = system.peek_x(); - x -= 1; - system.poke_x(x); - } - Instruction::DEY => { - let mut y = system.peek_y(); - y -= 1; - system.poke_y(y); - } - Instruction::EOR(mode) => { - match mode { - AddressMode::Immediate(_) => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => {} - } - } - Instruction::INC(mode) => { - match mode { - AddressMode::ZeroPage(value) => {} - AddressMode::ZeroPageX(value) => {} - AddressMode::Absolute(value) => {} - AddressMode::AbsoluteX(value) => {} - _ => {} - } - } - Instruction::INX => { - let mut x = system.peek_x(); - x += 1; - system.poke_x(x); - } - Instruction::INY => { - let mut y = system.peek_y(); - y += 1; - system.poke_y(y); - } - Instruction::JMP(mode) => { - match mode { - AddressMode::Absolute(_) => {} - AddressMode::IndirectX(_) => {} - _ => {} - } - } - Instruction::JSR(mode) => { - match mode { - AddressMode::Absolute(address) => {} - _ => {} - } - } - Instruction::LDA(mode) => { - match mode { - AddressMode::Immediate(value) => { - system.poke_a(*value) - } - AddressMode::ZeroPage(offset) => { - let value_to_write = system.peek(*offset as u16); - system.poke_a(value_to_write); - } - AddressMode::ZeroPageX(_) => { - let current_x = system.peek_x(); - } - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => { - debug!("Invalid LDA instruction"); - } - }; - } - Instruction::LDX(_) => {} - Instruction::LDY(_) => {} - Instruction::LSR(_) => {} - Instruction::NOP => {} - Instruction::ORA(_) => {} - Instruction::PHA => {} - Instruction::PHP => {} - Instruction::PLA => {} - Instruction::PLP => {} - Instruction::ROL(_) => {} - Instruction::ROR(_) => {} - Instruction::RTI => {} - Instruction::RTS => {} - Instruction::SBC(_) => {} - Instruction::SEC => {} - Instruction::SED => {} - Instruction::SEI => {} - Instruction::STA(_) => {} - Instruction::STX(_) => {} - Instruction::STY(_) => {} - Instruction::TAX => {} - Instruction::TAY => {} - Instruction::TSX => {} - Instruction::TXA => {} - Instruction::TXS => {} - Instruction::TYA => {} - }; - } -} - #[cfg(test)] mod test { use crate::address_mode::AddressMode::*; @@ -1715,24 +1026,186 @@ mod test { use super::*; #[test] - fn to_string() { + fn to_string_to_bytes_from_bytes() { let params = vec![ - (ADC(Immediate(0x01)), "ADC #$01"), - (ADC(ZeroPage(0x01)), "ADC $01"), - (ADC(ZeroPageX(0x01)), "ADC $01,X"), - (ADC(Absolute(0xabcd)), "ADC $abcd"), - (ADC(AbsoluteX(0xabcd)), "ADC $abcd,X"), - (ADC(AbsoluteY(0xabcd)), "ADC $abcd,Y"), - (ADC(IndirectX(0xab)), "ADC ($ab,X)"), - (ADC(IndirectY(0xab)), "ADC ($ab),Y"), - (SBC(Immediate(0x01)), "SBC #$01"), - (SBC(ZeroPage(0x01)), "SBC $01"), - (SBC(ZeroPageX(0x01)), "SBC $01,X"), - (SBC(Absolute(0xabcd)), "SBC $abcd"), - (SBC(AbsoluteX(0xabcd)), "SBC $abcd,X"), - (SBC(AbsoluteY(0xabcd)), "SBC $abcd,Y"), - (SBC(IndirectX(0xab)), "SBC ($ab,X)"), - (SBC(IndirectY(0xab)), "SBC ($ab),Y"), + (ADC(Immediate(0x01)), "ADC #$01", vec![0x69, 0x01]), + (ADC(ZeroPage(0x01)), "ADC $01", vec![0x65, 0x01]), + (ADC(ZeroPageX(0x01)), "ADC $01,X", vec![0x75, 0x01]), + (ADC(Absolute(0xabcd)), "ADC $abcd", vec![0x6d, 0xcd, 0xab]), + (ADC(AbsoluteX(0xabcd)), "ADC $abcd,X", vec![0x7d, 0xcd, 0xab]), + (ADC(AbsoluteY(0xabcd)), "ADC $abcd,Y", vec![0x79, 0xcd, 0xab]), + (ADC(IndirectX(0xab)), "ADC ($ab,X)", vec![0x61, 0xab]), + (ADC(IndirectY(0xab)), "ADC ($ab),Y", vec![0x71, 0xab]), + (AND(Immediate(0x01)), "AND #$01", vec![0x29, 0x01]), + (AND(ZeroPage(0x01)), "AND $01", vec![0x25, 0x01]), + (AND(ZeroPageX(0x01)), "AND $01,X", vec![0x35, 0x01]), + (AND(Absolute(0xabcd)), "AND $abcd", vec![0x2d, 0xcd, 0xab]), + (AND(AbsoluteX(0xabcd)), "AND $abcd,X", vec![0x3d, 0xcd, 0xab]), + (AND(AbsoluteY(0xabcd)), "AND $abcd,Y", vec![0x39, 0xcd, 0xab]), + (AND(IndirectX(0xab)), "AND ($ab,X)", vec![0x21, 0xab]), + (AND(IndirectY(0xab)), "AND ($ab),Y", vec![0x31, 0xab]), + (ASL(Accumulator), "ASL A", vec![0x0a]), + (ASL(ZeroPage(0xab)), "ASL $ab", vec![0x06, 0xab]), + (ASL(ZeroPageX(0xab)), "ASL $ab,X", vec![0x16, 0xab]), + (ASL(Absolute(0xabcd)), "ASL $abcd", vec![0x0e, 0xcd, 0xab]), + (ASL(AbsoluteX(0xabcd)), "ASL $abcd,X", vec![0x1e, 0xcd, 0xab]), + (BCC(Immediate(0xab)), "BCC #$ab", vec![0x90, 0xab]), + (BCS(Immediate(0xab)), "BCS #$ab", vec![0xb0, 0xab]), + (BEQ(Immediate(0xab)), "BEQ #$ab", vec![0xf0, 0xab]), + (BIT(ZeroPage(0xab)), "BIT $ab", vec![0x24, 0xab]), + (BIT(Absolute(0xabcd)), "BIT $abcd", vec![0x2c, 0xcd, 0xab]), + (BMI(Immediate(0xab)), "BMI #$ab", vec![0x30, 0xab]), + (BNE(Immediate(0xab)), "BNE #$ab", vec![0xd0, 0xab]), + (BPL(Immediate(0xab)), "BPL #$ab", vec![0x10, 0xab]), + (BVC(Immediate(0xab)), "BVC #$ab", vec![0x50, 0xab]), + (BVS(Immediate(0xab)), "BVS #$ab", vec![0x70, 0xab]), + (CLC, "CLC", vec![0x18]), + (CLD, "CLD", vec![0xd8]), + (CLV, "CLV", vec![0x58]), + (CLI, "CLI", vec![0xb8]), + (CMP(Immediate(0xab)), "CMP #$ab", vec![0xc9, 0xab]), + (CMP(ZeroPage(0xab)), "CMP $ab", vec![0xc5, 0xab]), + (CMP(ZeroPageX(0xab)), "CMP $ab,X", vec![0xd5, 0xab]), + (CMP(Absolute(0xabcd)), "CMP $abcd", vec![0xcd, 0xcd, 0xab]), + (CMP(AbsoluteX(0xabcd)), "CMP $abcd,X", vec![0xdd, 0xcd, 0xab]), + (CMP(IndirectX(0xab)), "CMP ($ab,X)", vec![0xc1, 0xab]), + (CMP(IndirectY(0xab)), "CMP ($ab),Y", vec![0xd1, 0xab]), + (CPX(Immediate(0xab)), "CPX #$ab", vec![0xe0, 0xab]), + (CPX(ZeroPage(0xab)), "CPX $ab", vec![0xe4, 0xab]), + (CPX(Absolute(0xabcd)), "CPX $abcd", vec![0xec, 0xcd, 0xab]), + (CPY(Immediate(0xab)), "CPY #$ab", vec![0xc0, 0xab]), + (CPY(Immediate(0xab)), "CPY #$ab", vec![0xc0, 0xab]), + (CPY(ZeroPage(0xab)), "CPY $ab", vec![0xc4, 0xab]), + (CPY(Absolute(0xabcd)), "CPY $abcd", vec![0xcc, 0xcd, 0xab]), + (DEC(ZeroPage(0xab)), "DEC $ab", vec![0xc6, 0xab]), + (DEC(ZeroPageX(0xab)), "DEC $ab,X", vec![0xd6, 0xab]), + (DEC(Absolute(0xabcd)), "DEC $abcd", vec![0xce, 0xcd, 0xab]), + (DEC(AbsoluteX(0xabcd)), "DEC $abcd,X", vec![0xde, 0xcd, 0xab]), + (DEX, "DEX", vec![0xca]), + (DEY, "DEY", vec![0x88]), + (EOR(Immediate(0xab)), "EOR #$ab", vec![0x49, 0xab]), + (EOR(ZeroPage(0xab)), "EOR $ab", vec![0x45, 0xab]), + (EOR(ZeroPageX(0xab)), "EOR $ab,X", vec![0x55, 0xab]), + (EOR(Absolute(0xabcd)), "EOR $abcd", vec![0x4d, 0xcd, 0xab]), + (EOR(AbsoluteX(0xabcd)), "EOR $abcd,X", vec![0x5d, 0xcd, 0xab]), + (EOR(IndirectX(0xab)), "EOR ($ab,X)", vec![0x41, 0xab]), + (EOR(IndirectY(0xab)), "EOR ($ab),Y", vec![0x51, 0xab]), + (INC(ZeroPage(0xab)), "INC $ab", vec![0xe6, 0xab]), + (INC(ZeroPageX(0xab)), "INC $ab,X", vec![0xf6, 0xab]), + (INC(Absolute(0xabcd)), "INC $abcd", vec![0xee, 0xcd, 0xab]), + (INC(AbsoluteX(0xabcd)), "INC $abcd,X", vec![0xfe, 0xcd, 0xab]), + (INX, "INX", vec![0xe8]), + (INY, "INY", vec![0xc8]), + (JMP(Absolute(0xabcd)), "JMP $abcd", vec![0x4c, 0xcd, 0xab]), + (JMP(IndirectX(0xab)), "JMP $ab,X", vec![0x6c, 0xab]), + (JSR(Immediate(0xab)), "JSR", vec![0x20, 0xab]), + (LDA(Immediate(0xab)), "LDA #$ab", vec![0xa9, 0xab]), + (LDA(ZeroPage(0xab)), "LDA $ab", vec![0xa5, 0xab]), + (LDA(ZeroPageX(0xab)), "LDA $ab,X", vec![0xb5, 0xab]), + (LDA(Absolute(0xabcd)), "LDA $abcd", vec![0xad, 0xcd, 0xab]), + (LDA(AbsoluteX(0xabcd)), "LDA $abcd,X", vec![0xbd, 0xcd, 0xab]), + (LDA(AbsoluteY(0xabcd)), "LDA $abcd,Y", vec![0xb9, 0xcd, 0xab]), + (LDA(IndirectX(0xab)), "LDA ($ab,X)", vec![0xa1, 0xab]), + (LDA(IndirectY(0xab)), "LDA ($ab),Y", vec![0xb1, 0xab]), + (LDX(Immediate(0xab)), "LDX #$ab", vec![0xa2, 0xab]), + (LDX(ZeroPage(0xab)), "LDX $ab", vec![0xa6, 0xab]), + (LDX(ZeroPageX(0xab)), "LDX $ab,X", vec![0x86, 0xab]), + (LDX(Absolute(0xabcd)), "LDX $abcd", vec![0xae, 0xcd, 0xab]), + (LDX(AbsoluteX(0xabcd)), "LDX $abcd,X", vec![0xbe, 0xcd, 0xab]), + (LDY(Immediate(0xab)), "LDY #$ab", vec![0xa0, 0xab]), + (LDY(ZeroPage(0xab)), "LDY $ab", vec![0xa4, 0xab]), + (LDY(ZeroPageX(0xab)), "LDY $ab,X", vec![0x84, 0xab]), + (LDY(Absolute(0xabcd)), "LDY $abcd", vec![0xac, 0xcd, 0xab]), + (LDY(AbsoluteX(0xabcd)), "LDY $abcd,X", vec![0xbc, 0xcd, 0xab]), + (LSR(Accumulator), "LSR A", vec![0x4a]), + (LSR(ZeroPage(0xab)), "LSR $ab", vec![0x46, 0xab]), + (LSR(ZeroPageX(0xab)), "LSR $ab,X", vec![0x56, 0xab]), + (LSR(Absolute(0xabcd)), "LSR $abcd", vec![0x4e, 0xcd, 0xab]), + (LSR(AbsoluteX(0xabcd)), "LSR $abcd,X", vec![0x5e, 0xcd, 0xab]), + // Nop nop nop. + (NOP, "NOP", vec![0xea]), + (ORA(Immediate(0xab)), "ORA #$ab", vec![0x09, 0xab]), + (ORA(ZeroPage(0xab)), "ORA $ab", vec![0x05, 0xab]), + (ORA(ZeroPageX(0xab)), "ORA $ab,X", vec![0x15, 0xab]), + (ORA(Absolute(0xabcd)), "ORA $abcd", vec![0x0d, 0xcd, 0xab]), + (ORA(AbsoluteX(0xabcd)), "ORA $abcd,X", vec![0x1d, 0xcd, 0xab]), + (ORA(AbsoluteY(0xabcd)), "ORA $abcd,Y", vec![0x19, 0xcd, 0xab]), + (ORA(IndirectX(0xab)), "ORA ($ab,X)", vec![0x01, 0xab]), + (ORA(IndirectY(0xab)), "ORA ($ab),Y", vec![0x11, 0xab]), + (PHA, "PHA", vec![0x48]), + (PHP, "PHP", vec![0x08]), + (PLA, "PLA", vec![0x68]), + (PLP, "PLP", vec![0x28]), + (ROL(Accumulator), "ROL A", vec![0x2a]), + (ROL(ZeroPage(0xab)), "ROL $ab", vec![0x26, 0xab]), + (ROL(ZeroPageX(0xab)), "ROL $ab,X", vec![0x36, 0xab]), + (ROL(Absolute(0xabcd)), "ROL $abcd", vec![0x2e, 0xcd, 0xab]), + (ROL(AbsoluteX(0xabcd)), "ROL $abcd,X", vec![0x3e, 0xcd, 0xab]), + (ROR(Accumulator), "ROR A", vec![0x6a]), + (ROR(ZeroPage(0xab)), "ROR $ab", vec![0x66, 0xab]), + (ROR(ZeroPageX(0xab)), "ROR $ab,X", vec![0x76, 0xab]), + (ROR(Absolute(0xabcd)), "ROR $abcd", vec![0x6e, 0xcd, 0xab]), + (ROR(AbsoluteX(0xabcd)), "ROR $abcd,X", vec![0x7e, 0xcd, 0xab]), + + (RTI, "RTI", vec![0x40]), + (RTS, "RTS", vec![0x60]), + (SBC(Immediate(0xab)), "SBC #$ab", vec![0xe9, 0xcd, 0xab]), + (SBC(ZeroPage(0xab)), "SBC $ab", vec![0xe5, 0xab]), + (SBC(ZeroPageX(0xab)), "SBC $ab,X", vec![0xf5, 0xab]), + (SBC(Absolute(0xabcd)), "SBC $abcd", vec![0xed, 0xcd, 0xab]), + (SBC(AbsoluteX(0xabcd)), "SBC $abcd,X", vec![0xfd, 0xcd, 0xab]), + (SBC(AbsoluteY(0xabcd)), "SBC $abcd,Y", vec![0xf9, 0xcd, 0xab]), + (SBC(IndirectX(0xab)), "SBC ($ab,X)", vec![0xe1, 0xab]), + (SBC(IndirectY(0xab)), "SBC ($ab),Y", vec![0xf1, 0xab]), + + (SEC, "SEC", vec![0x38]), + (SED, "SED", vec![0xf8]), + (SEI, "SEI", vec![0x78]), + + (STA(ZeroPage(0xab)), "STA $ab", vec![0x85, 0xab]), + (STA(ZeroPageX(0xab)), "STA $ab,X", vec![0x95, 0xab]), + (STA(Absolute(0xabcd)), "STA $abcd", vec![0x8d, 0xcd, 0xab]), + (STA(AbsoluteX(0xabcd)), "STA $abcd,X", vec![0x9d, 0xcd, 0xab]), + (STA(AbsoluteY(0xabcd)), "STA $abcd,Y", vec![0x99, 0xcd, 0xab]), + (STA(IndirectX(0xab)), "STA ($ab,X)", vec![0x81, 0xab]), + (STA(IndirectY(0xab)), "STA ($ab),Y", vec![0x91, 0xab]), + + (STX(ZeroPage(0xab)), "STX $ab", vec![0x86, 0xab]), + (STX(ZeroPageX(0xab)), "STX $ab,X", vec![0x96, 0xab]), + (STX(Absolute(0xabcd)), "STX $abcd", vec![0x8e, 0xcd, 0xab]), + + (STY(ZeroPage(0xab)), "STY $ab", vec![0x84, 0xab]), + (STY(ZeroPageX(0xab)), "STY $ab,X", vec![0x94, 0xab]), + (STY(Absolute(0xabcd)), "STY $abcd", vec![0x8c, 0xcd, 0xab]), + + (TAX, "TAX", vec![0xaa]), + (TAY, "TAY", vec![0xa8]), + (TSX, "TSX", vec![0xba]), + (TXA, "TXA", vec![0x8a]), + (TXS, "TXS", vec![0x9a]), + (TYA, "TYA", vec![0x98]) ]; + + for (instruction, string, bytes) in params { + + // from instruction to string + assert_eq!( + instruction.to_string(), + string + ); + + // from instruction to bytes + println!("COMPARE OF {} to {:?}", instruction.to_string(), bytes); + assert_eq!( + instruction.to_bytes(), + bytes + ); + + // from bytes to instruction + assert_eq!( + instruction, + Instruction::from_bytes(bytes) + ); + } } } \ No newline at end of file diff --git a/core/src/instruction/stub.rs b/core/src/instruction/stub.rs new file mode 100644 index 0000000..d2ee3fe --- /dev/null +++ b/core/src/instruction/stub.rs @@ -0,0 +1,71 @@ +use crate::instruction::Instruction; +use crate::constants::constants_isa_stub::*; +use crate::instruction::Instruction::*; + +impl Instruction { + /// returns the 'stub' of the instruction. + /// + /// ex: LDA $4452 -> LDA + /// BCC $43 -> BCC + pub fn stub(&self) -> String { + match self { + ADC(_) => ISA_STUB_ADC, + AND(_) => ISA_STUB_AND, + ASL(_) => ISA_STUB_ASL, + BCC(_) => ISA_STUB_BCC, + BCS(_) => ISA_STUB_BCS, + BEQ(_) => ISA_STUB_BEQ, + BIT(_) => ISA_STUB_BIT, + BMI(_) => ISA_STUB_BMI, + BNE(_) => ISA_STUB_BNE, + BPL(_) => ISA_STUB_BPL, + BRK => ISA_STUB_BRK, + BVC(_) => ISA_STUB_BVC, + BVS(_) => ISA_STUB_BVS, + CLC => ISA_STUB_CLC, + CLD => ISA_STUB_CLD, + CLI => ISA_STUB_CLI, + CLV => ISA_STUB_CLV, + CMP(_) => ISA_STUB_CMP, + CPX(_) => ISA_STUB_CPX, + CPY(_) => ISA_STUB_CPY, + DEC(_) => ISA_STUB_DEC, + DEX => ISA_STUB_DEX, + DEY => ISA_STUB_DEY, + EOR(_) => ISA_STUB_EOR, + INC(_) => ISA_STUB_INC, + INX => ISA_STUB_INX, + INY => ISA_STUB_INY, + JMP(_) => ISA_STUB_JMP, + JSR(_) => ISA_STUB_JSR, + LDA(_) => ISA_STUB_LDA, + LDX(_) => ISA_STUB_LDX, + LDY(_) => ISA_STUB_LDY, + LSR(_) => ISA_STUB_LSR, + NOP => ISA_STUB_NOP, + ORA(_) => ISA_STUB_ORA, + PHA => ISA_STUB_PHA, + PHP => ISA_STUB_PHP, + PLA => ISA_STUB_PLA, + PLP => ISA_STUB_PLP, + ROL(_) => ISA_STUB_ROL, + ROR(_) => ISA_STUB_ROR, + RTI => ISA_STUB_RTI, + RTS => ISA_STUB_RTS, + SBC(_) => ISA_STUB_SBC, + SEC => ISA_STUB_SEC, + SED => ISA_STUB_SED, + SEI => ISA_STUB_SEI, + STA(_) => ISA_STUB_STA, + STX(_) => ISA_STUB_STX, + STY(_) => ISA_STUB_STY, + TAX => ISA_STUB_TAX, + TAY => ISA_STUB_TAY, + TSX => ISA_STUB_TSX, + TXA => ISA_STUB_TXA, + TXS => ISA_STUB_TXS, + TYA => ISA_STUB_TYA + }.to_string() + } + +} \ No newline at end of file diff --git a/core/src/instruction/to_bytes.rs b/core/src/instruction/to_bytes.rs new file mode 100644 index 0000000..b51d565 --- /dev/null +++ b/core/src/instruction/to_bytes.rs @@ -0,0 +1,193 @@ +use crate::address_mode::AddressMode; +use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Immediate, IndirectX, IndirectY, ZeroPage, ZeroPageX}; +use crate::constants::constants_isa_op::*; +use crate::instruction::Instruction; +use crate::instruction::Instruction::*; + +fn split_word_hl(to_split: u16) -> (u8, u8) { + let low = (to_split & 0xff) as u8; + let high = ((to_split & 0xff00) >> 8) as u8; + (high, low) +} + +fn split_word_lh(to_split: u16) -> (u8, u8) { + let low = (to_split & 0xff) as u8; + let high = ((to_split & 0xff00) >> 8) as u8; + (low, high) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn split_le() { + let value = 0xabcd; + let (high, low) = split_word_hl(value); + + assert_eq!(low, 0xcd); + assert_eq!(high, 0xab); + } + + #[test] + fn split_be() { + let value = 0xabcd; + let (low, high) = split_word_lh(value); + + assert_eq!(low, 0xcd); + assert_eq!(high, 0xab); + } +} + +impl Instruction { + + pub fn to_bytes(&self) -> Vec { + match self { + ADC(mode) => { + match mode { + Immediate(value) => + vec![ISA_OP_ADC_I, *value], + + ZeroPage(offset) => + vec![ISA_OP_ADC_Z, *offset], + + ZeroPageX(value) => + vec![ISA_OP_ADC_ZX, *value], + + Absolute(offset) => { + let high = ((offset & 0xff00) >> 8) as u8; + let low = (offset & 0x00ff) as u8; + vec![ISA_OP_ADC_ABS, low, high] + } + AbsoluteX(offset) => { + let high = ((offset & 0xff00) >> 8) as u8; + let low = (offset & 0x00ff) as u8; + vec![ISA_OP_ADC_ABSX, low, high] + } + AbsoluteY(offset) => { + let high = ((offset & 0xff00) >> 8) as u8; + let low = (offset & 0x00ff) as u8; + vec![ISA_OP_ADC_ABSY, low, high] + } + IndirectX(offset) => + vec![ISA_OP_ADC_INDX, *offset], + IndirectY(offset) => + vec![ISA_OP_ADC_INDY, *offset], + _ => { vec![] } + } + } + AND(mode) => { + match mode { + Immediate(value) => vec![ISA_OP_AND_I, *value], + ZeroPage(value) => vec![ISA_OP_AND_Z, *value], + ZeroPageX(value) => vec![ISA_OP_AND_ZX, *value], + Absolute(offset) => { + let (h, l) = split_word_hl(*offset); + vec![ISA_OP_AND_ABS, l, h] + } + AbsoluteX(offset) => { + let (h, l) = split_word_hl(*offset); + vec![ISA_OP_AND_ABSX, l,h] + } + AbsoluteY(offset) => { + let (h, l) = split_word_hl(*offset); + vec![ISA_OP_AND_ABSY, l,h] + } + IndirectX(value) => vec![ISA_OP_AND_INDX, *value], + IndirectY(value) => vec![ISA_OP_AND_INDY, *value], + _ => vec![] + } + } + ASL(mode) => { + match mode { + AddressMode::Accumulator => { + vec![ISA_OP_ASL_A] + } + ZeroPage(value) => { + vec![ISA_OP_ASL_Z, *value] + } + ZeroPageX(value) => { + vec![ISA_OP_ASL_ZX, *value] + } + Absolute(offset) => { + let (h, l) = split_word_hl(*offset); + vec![ISA_OP_ASL_ABS, l,h] + } + AbsoluteX(offset) => { + let (h, l) = split_word_hl(*offset); + vec![ISA_OP_ASL_ABSX, l, h] + } + _ => vec![ISA_OP_NOP] + } + } + BCC(mode) => { + match mode { + Immediate(value) => { + vec![ISA_OP_BCC, *value] + } + _ => vec![ISA_OP_NOP] + } + } + BCS(mode) => { + match mode { + Immediate(value) => { + vec![ISA_OP_BCS, *value] + }, + _ => vec![ISA_OP_NOP] + } + } + // BEQ(_) => {} + // BIT(_) => {} + // BMI(_) => {} + // BNE(_) => {} + // BPL(_) => {} + // BRK => {} + // BVC(_) => {} + // BVS(_) => {} + // CLC => {} + // CLD => {} + // CLI => {} + // CLV => {} + // CMP(_) => {} + // CPX(_) => {} + // CPY(_) => {} + // DEC(_) => {} + // DEX => {} + // DEY => {} + // EOR(_) => {} + // INC(_) => {} + // INX => {} + // INY => {} + // JMP(_) => {} + // JSR(_) => {} + // LDA(_) => {} + // LDX(_) => {} + // LDY(_) => {} + // LSR(_) => {} + // NOP => {} + // ORA(_) => {} + // PHA => {} + // PHP => {} + // PLA => {} + // PLP => {} + // ROL(_) => {} + // ROR(_) => {} + // RTI => {} + // RTS => {} + // SBC(_) => {} + // SEC => {} + // SED => {} + // SEI => {} + // STA(_) => {} + // STX(_) => {} + // STY(_) => {} + // TAX => {} + // TAY => {} + // TSX => {} + TXA => vec![ISA_OP_TXA], + TXS => vec![ISA_OP_TXS], + TYA => vec![ISA_OP_TYA], + _ => { vec![] } + } + } +} \ No newline at end of file diff --git a/core/src/instruction/to_string.rs b/core/src/instruction/to_string.rs new file mode 100644 index 0000000..9d9b0ce --- /dev/null +++ b/core/src/instruction/to_string.rs @@ -0,0 +1,42 @@ +use crate::address_mode::AddressMode; +use crate::address_mode::AddressMode::Implied; +use crate::instruction::Instruction; +use crate::instruction::Instruction::*; + +impl Instruction { + pub fn to_string(&self) -> String { + let mode = match self { + ADC(newmode) | AND(newmode) | ASL(newmode) | + BCC(newmode) | BCS(newmode) | BEQ(newmode) | + BIT(newmode) | BMI(newmode) | BNE(newmode) | + BPL(newmode) | BVC(newmode) | BVS(newmode) | + CMP(newmode) | CPX(newmode) | CPY(newmode) | + DEC(newmode) | EOR(newmode) | INC(newmode) | + JMP(newmode) | JSR(newmode) | LDA(newmode) | + LDX(newmode) | LDY(newmode) | LSR(newmode) | + ORA(newmode) | ROL(newmode) | ROR(newmode) | + SBC(newmode) | STA(newmode) | STX(newmode) | + STY(newmode) => newmode, + _ => &Implied + }; + + Instruction::format(mode, &self.stub()) + } + + fn format(mode: &AddressMode, prefix: &str) -> String { + let suffix = match mode { + AddressMode::Implied => "", + AddressMode::Accumulator => " A", + AddressMode::Immediate(value) => &*format!(" #${value:02x}"), + AddressMode::ZeroPage(value) => &*format!(" ${value:02x}"), + AddressMode::ZeroPageX(value) => &*format!(" ${value:02x},X"), + AddressMode::Absolute(offset) => &*format!(" ${offset:04x}"), + AddressMode::AbsoluteX(offset) => &*format!(" ${offset:04x},X"), + AddressMode::AbsoluteY(offset) => &*format!(" ${offset:04x},Y"), + AddressMode::IndirectX(value) => &*format!(" (${value:02x},X)"), + AddressMode::IndirectY(value) => &*format!(" (${value:02x}),Y"), + AddressMode::ZeroPageY(value) => &*format!(" ${value:02x},Y") + }; + format!("{}{}", prefix, suffix) + } +} \ No newline at end of file diff --git a/core/src/instruction_stringify.rs b/core/src/instruction_stringify.rs deleted file mode 100644 index 819e6cf..0000000 --- a/core/src/instruction_stringify.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::address_mode::AddressMode; - -pub struct InstructionStringify {} -impl InstructionStringify { - pub fn format(mode: AddressMode, prefix: &str) -> String { - let suffix = match mode { - AddressMode::Implied => "", - AddressMode::Accumulator => "A", - AddressMode::Immediate(value) => &*format!("#${value:02x}"), - AddressMode::ZeroPage(value) => &*format!("${value:02x}"), - AddressMode::ZeroPageX(value) => &*format!("${value:02x},X"), - AddressMode::Absolute(offset) => &*format!("${offset:04x}"), - AddressMode::AbsoluteX(offset) => &*format!("${offset:04x},X"), - AddressMode::AbsoluteY(offset) => &*format!("${offset:04x},Y"), - AddressMode::IndirectX(value) => &*format!("(${value:02x},X)"), - AddressMode::IndirectY(value) => &*format!("(${value:02x}),Y") - }; - - format!("{} {}", prefix, suffix) - } -} \ No newline at end of file diff --git a/core/src/isa/decoder.rs b/core/src/isa/decoder.rs index 074baaf..3706602 100644 --- a/core/src/isa/decoder.rs +++ b/core/src/isa/decoder.rs @@ -1,5 +1,4 @@ use crate::address_mode::AddressMode::*; -use crate::constants::*; use crate::instruction::Instruction; use crate::instruction::Instruction::*; @@ -13,12 +12,13 @@ impl Decoder { /// NOP will be returned when an instruction without a valid parameter /// and more data is required to decode. pub fn decode(decode_from: Vec) -> Instruction { - NOP + Instruction::from_bytes(decode_from) } } #[cfg(test)] mod test { + use crate::constants::constants_isa_op::{ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX, ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_I, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A, ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BCC, ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK, ISA_OP_BVC, ISA_OP_BVS}; use super::*; @@ -60,6 +60,8 @@ mod test { (vec![ISA_OP_BRK], BRK), + + ]; for (bytes, instruction) in params { diff --git a/core/src/isa/encode.rs b/core/src/isa/encode.rs index 2110d3a..e8b930b 100644 --- a/core/src/isa/encode.rs +++ b/core/src/isa/encode.rs @@ -1,5 +1,5 @@ use crate::address_mode::AddressMode::*; -use crate::constants::*; +use crate::constants::constants_isa_op::ISA_OP_BCC; use crate::instruction::Instruction; use crate::instruction::Instruction::*; @@ -78,7 +78,7 @@ impl Encoder { #[cfg(test)] mod test { - use crate::constants::*; + use crate::constants::constants_isa_op::{ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX, ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_I, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A, ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK, ISA_OP_BVC, ISA_OP_BVS}; use super::*; #[test] diff --git a/core/src/isa/mod.rs b/core/src/isa/mod.rs index 6f28f74..66ddc09 100644 --- a/core/src/isa/mod.rs +++ b/core/src/isa/mod.rs @@ -1,4 +1,3 @@ - pub mod encode; pub mod decoder; pub mod microcode_steps; diff --git a/core/src/lib.rs b/core/src/lib.rs index edbafdc..8537419 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -4,4 +4,3 @@ pub mod instruction; pub mod mos6502flags; pub mod isa; pub mod constants; -mod instruction_stringify; diff --git a/core/src/mos6502cpu.rs b/core/src/mos6502cpu.rs index 2b95e5d..078f8b3 100644 --- a/core/src/mos6502cpu.rs +++ b/core/src/mos6502cpu.rs @@ -11,7 +11,9 @@ pub struct Mos6502Cpu { flags: Mos6502Flags, pc: u16, s: u8, - microcode_step: u8 + microcode_step: u8, + address_bus: u16, + data_bus: u8 } impl Mos6502Cpu { @@ -24,7 +26,9 @@ impl Mos6502Cpu { flags: Mos6502Flags::default(), pc: 0, s: 0xfd, - microcode_step: 0 + microcode_step: 0, + address_bus: 0x0000, + data_bus: 0x00 } } @@ -69,4 +73,9 @@ impl Mos6502Cpu { pub fn tick(&mut self) { } + + pub fn dump(&self) { + println!("CPU State: PC: {:04x} / A: {:02x} / X: {:02x} / Y: {:02x} / ADDRESS: {:04x} / DATA: {:02x}", + self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus); + } } diff --git a/macroquad/Cargo.toml b/macroquad/Cargo.toml index 5c17c4a..0cd6edf 100644 --- a/macroquad/Cargo.toml +++ b/macroquad/Cargo.toml @@ -2,3 +2,6 @@ name = "macroquad" version = "0.1.0" edition = "2024" + +[dependencies] +macroquad = "0.4" \ No newline at end of file diff --git a/macroquad/src/bin/gui.rs b/macroquad/src/bin/gui.rs index e69de29..f2d772e 100644 --- a/macroquad/src/bin/gui.rs +++ b/macroquad/src/bin/gui.rs @@ -0,0 +1,16 @@ +use macroquad::prelude::*; + +#[macroquad::main("BasicShapes")] +async fn main() { + loop { + clear_background(RED); + + draw_line(40.0, 40.0, 100.0, 200.0, 15.0, BLUE); + draw_rectangle(screen_width() / 2.0 - 60.0, 100.0, 120.0, 60.0, GREEN); + draw_circle(screen_width() - 30.0, screen_height() - 30.0, 15.0, YELLOW); + + draw_text("IT WORKS!", 20.0, 20.0, 30.0, DARKGRAY); + + next_frame().await + } +}