Compare commits

...

4 Commits

Author SHA1 Message Date
d89fc1cd2b decodes all instructions i think.
start of a beneater pc
2025-06-27 12:14:54 -04:00
57544589b3 applies chatgpt suggestions.
...
does not appear to decode everything
2025-06-25 09:34:19 -04:00
1b2fb2c221 from_bytes needs tests
instruction.to_string() passes all its tests.
2025-06-24 11:05:02 -04:00
768e83dfb8 more decode and encode code 2025-06-23 15:35:36 -04:00
45 changed files with 2931 additions and 2035 deletions

5
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/mos6502.iml" filepath="$PROJECT_DIR$/.idea/mos6502.iml" />
</modules>
</component>
</project>

14
.idea/mos6502.iml generated Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="EMPTY_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/cli/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/core/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/macroquad/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

231
Cargo.lock generated
View File

@ -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,44 @@ 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 = "beneater"
version = "0.1.0"
dependencies = [
"core",
"macroquad 0.4.14",
]
[[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 +168,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 +209,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 +231,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 +250,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 +278,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 +313,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 +364,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 +403,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 +422,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 +461,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 +493,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 +549,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 +611,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 +638,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 +663,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 +821,5 @@ version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
dependencies = [
"bitflags",
"bitflags 2.9.1",
]

View File

@ -2,7 +2,8 @@
members = [
"core",
"cli",
"macroquad"
"macroquad",
"beneater"
]
resolver="2"
@ -15,3 +16,4 @@ clap = { version = "4.5", features = ["derive"] }
# trevors_utilities = { git = "https://git.geekback.dev/tmerritt/trevors_utilities" }
trevors_utilities = { path = "/home/tmerritt/Projects/trevors_utilities" }
lipsum = "0.9"
macroquad = "0.4"

8
beneater/Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "beneater"
version = "0.1.0"
edition = "2024"
[dependencies]
core = { path = "../core" }
macroquad.workspace = true

View File

@ -0,0 +1,16 @@
// This is the GUI for the BenEater PC
use macroquad::prelude::*;
#[macroquad::main("Ben Eaters PC")]
async fn main() {
println!("Taxation is Theft");
let computer = BenEaterPC::new();
loop {
clear_background(BLUE);
draw_text("Ben Eater", 20.0, 20.0, 30.0, BLACK);
next_frame().await
}
}

1
beneater/src/lib.rs Normal file
View File

@ -0,0 +1 @@
pub mod parts;

View File

@ -0,0 +1,25 @@
use crate::parts::clock::Clock;
use core::mos6502cpu::Mos6502Cpu;
struct BenEaterPC {
clock: Clock,
cpu: Mos6502Cpu,
}
impl BenEaterPC {
pub fn new() -> Self {
BenEaterPC {
clock: Clock::new(),
cpu: Mos6502Cpu::default()
}
}
pub fn tick_system(&mut self) {
let (address, data, rw) = self.cpu.tick();
if self.cpu.microcode_step == 0 {
// tick the clock.
// tick the memory
// tick the VIA
}
}
}

View File

@ -0,0 +1,24 @@
pub struct Clock {
ticks: u32
}
impl Clock {
pub fn new() -> Self {
Clock {
ticks: 0
}
}
pub fn tick(&mut self) {
self.ticks += 1;
}
pub fn ticks(&self) -> u32 {
self.ticks
}
pub fn reset(&mut self) {
self.ticks = 0;
}
}

View File

@ -0,0 +1,3 @@
pub mod clock;
mod ben_eater_pc;
mod via6522;

View File

@ -0,0 +1,31 @@
#[derive(Default)]
pub struct Via6522 {
port_a_state: u8,
port_b_data: u8,
port_a_direction: u8,
port_b_direction: u8,
memory_offset: u16,
}
impl Via6522 {
pub fn new(offset: u16) -> Self {
Via6522 {
memory_offset: offset,
..Default::default()
}
}
pub fn set_a_direction(&mut self, new_direction: u8) {
}
// check for output pins and see what they say
pub fn update_pins(&mut self) {
}
// check for input mode pins and see what they say
pub fn read_pins(&self) {
}
}

View File

@ -1,12 +1,11 @@
use core::instruction::Instruction;
use core::address_mode::AddressMode;
use core::isa::decoder::Decoder;
fn main() {
println!("Taxation is Theft");
Decoder::decode(vec![0b11100011]);
// Instruction::from_bytes(vec![0b11100011]);
let instruction = Instruction::ADC(AddressMode::Immediate(0x45));
println!("Instruction = {:?}", instruction.to_string());
// let instruction = Instruction::ADC(AddressMode::Immediate);
// println!("Instruction = {:?}", instruction.to_string());
}

View File

@ -3,4 +3,4 @@ name = "core"
version = "0.1.0"
edition = "2024"
[dependencies]
log = "0.4.26"
log = "0.4"

View File

@ -1,16 +1,17 @@
use std::ops::Add;
use crate::mos6502cpu::Mos6502Cpu;
use std::fmt::{Display};
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum AddressMode {
Implied,
Accumulator,
Immediate(u8),
ZeroPage(u8),
ZeroPageX(u8),
Absolute(u16),
AbsoluteX(u16),
AbsoluteY(u16),
IndirectX(u8),
IndirectY(u8),
Immediate,
ZeroPage,
ZeroPageX,
ZeroPageY,
Absolute,
AbsoluteX,
AbsoluteY,
Indirect,
IndirectX,
IndirectY,
}

View File

@ -0,0 +1,9 @@
/// BenEater computer represents the 'Ben Eater' 6502 breadboard computer.
/// This was built along watching the video series where Ben builds a
/// 6502 on a breadboard and explains each step.
///
pub struct BenEater {
}

View File

@ -0,0 +1 @@
pub mod beneater;

View File

@ -0,0 +1,2 @@
pub mod beneater;

View File

@ -1,5 +1,6 @@
// Instruction OP Codes
/// Instruction OP Codes
/// Verified against
/// https://www.nesdev.org/obelisk-6502-guide/reference.html
/// ADC
pub const ISA_OP_ADC_I: u8 = 0x69;
pub const ISA_OP_ADC_Z: u8 = 0x65;
@ -18,78 +19,59 @@ 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;
pub const ISA_OP_CMP_ABS: u8 = 0xcd;
pub const ISA_OP_CMP_ABSX: u8 = 0xdd;
pub const ISA_OP_CMP_ABSY: u8 = 0xd9;
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,50 +80,40 @@ 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;
pub const ISA_OP_LDA_ABS: u8 = 0xAD;
pub const IAS_OP_LDA_ABSX: u8 = 0xBD;
pub const ISA_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_ZPY: u8 = 0xb6;
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 +122,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;
@ -194,7 +157,7 @@ pub const ISA_OP_STA_ABSY: u8 = 0x99;
pub const ISA_OP_STA_INDX: u8 = 0x81;
pub const ISA_OP_STA_INDY: u8 = 0x91;
pub const ISA_OP_STX_ZP: u8 = 0x86;
pub const ISA_OP_STX_ZPX: u8 = 0x96;
pub const ISA_OP_STX_ZPY: u8 = 0x96;
pub const ISA_OP_STX_ABS: u8 = 0x8e;
pub const ISA_OP_STY_ZP: u8 = 0x84;
pub const ISA_OP_STY_ZPX: u8 = 0x94;

View File

@ -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";

View File

@ -0,0 +1,2 @@
pub mod constants_isa_stub;
pub mod constants_isa_op;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
use log::debug;
use crate::address_mode::AddressMode::*;
use crate::constants::constants_isa_op::*;
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
);
}
}

View File

@ -0,0 +1,7 @@
use crate::address_mode::AddressMode;
use crate::address_mode::AddressMode::*;
use crate::mos6502flags::Mos6502Flag::*;
mod from_bytes;
mod to_bytes;
mod to_string;

View File

@ -0,0 +1,38 @@
use crate::address_mode::AddressMode;
use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Immediate, IndirectX, IndirectY, ZeroPage, ZeroPageX, ZeroPageY};
use crate::constants::constants_isa_op::*;
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);
}
}

View File

@ -0,0 +1,18 @@
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)
prefix.to_string()
}

View File

@ -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)
}
}

View File

@ -0,0 +1,990 @@
use crate::address_mode::AddressMode;
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_ABSX, ISA_OP_AND_ABSY, ISA_OP_AND_I, ISA_OP_AND_INDX, ISA_OP_AND_INDY, 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_BCS, 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, ISA_OP_CLC, ISA_OP_CLD, ISA_OP_CLI, ISA_OP_CLV, ISA_OP_CMP_ABS, ISA_OP_CMP_ABSX, ISA_OP_CMP_ABSY, ISA_OP_CMP_I, ISA_OP_CMP_INDX, ISA_OP_CMP_INDY, ISA_OP_CMP_ZP, ISA_OP_CMP_ZPX, ISA_OP_CPX_ABS, ISA_OP_CPX_I, ISA_OP_CPX_ZP, ISA_OP_CPY_ABS, ISA_OP_CPY_I, ISA_OP_CPY_ZP, ISA_OP_DEC_ABS, ISA_OP_DEC_ABSX, ISA_OP_DEC_ZP, ISA_OP_DEC_ZPX, ISA_OP_DEX, ISA_OP_DEY, ISA_OP_EOR_ABS, ISA_OP_EOR_ABSX, ISA_OP_EOR_ABSY, ISA_OP_EOR_I, ISA_OP_EOR_INDX, ISA_OP_EOR_INDY, ISA_OP_EOR_ZP, ISA_OP_EOR_ZPX, ISA_OP_INC_ABS, ISA_OP_INC_ABSX, ISA_OP_INC_ZP, ISA_OP_INC_ZPX, ISA_OP_INX, ISA_OP_INY, ISA_OP_JMP_ABS, ISA_OP_JMP_IND, ISA_OP_JSR, ISA_OP_LDA_ABS, ISA_OP_LDA_ABSX, ISA_OP_LDA_ABSY, ISA_OP_LDA_I, ISA_OP_LDA_INDX, ISA_OP_LDA_INDY, ISA_OP_LDA_Z, ISA_OP_LDA_ZX, ISA_OP_LDX_ABS, ISA_OP_LDX_ABSY, ISA_OP_LDX_I, ISA_OP_LDX_ZP, ISA_OP_LDX_ZPY, ISA_OP_LDY_ABS, ISA_OP_LDY_ABSX, ISA_OP_LDY_I, ISA_OP_LDY_ZP, ISA_OP_LDY_ZPX, ISA_OP_LSR_A, ISA_OP_LSR_ABS, ISA_OP_LSR_ABSX, ISA_OP_LSR_ZP, ISA_OP_LSR_ZPX, ISA_OP_NOP, ISA_OP_ORA_ABS, ISA_OP_ORA_ABSX, ISA_OP_ORA_ABSY, ISA_OP_ORA_I, ISA_OP_ORA_INDX, ISA_OP_ORA_INDY, ISA_OP_ORA_ZP, ISA_OP_ORA_ZPX, ISA_OP_PHA, ISA_OP_PHP, ISA_OP_PLA, ISA_OP_PLP, ISA_OP_ROL_A, ISA_OP_ROL_ABS, ISA_OP_ROL_ABSX, ISA_OP_ROL_ZP, ISA_OP_ROL_ZPX, ISA_OP_ROR_A, ISA_OP_ROR_ABS, ISA_OP_ROR_ABSX, ISA_OP_ROR_ZP, ISA_OP_ROR_ZPX, ISA_OP_RTI, ISA_OP_RTS, ISA_OP_SBC_ABS, ISA_OP_SBC_ABSX, ISA_OP_SBC_ABSY, ISA_OP_SBC_I, ISA_OP_SBC_INDX, ISA_OP_SBC_INDY, ISA_OP_SBC_ZP, ISA_OP_SBC_ZPX, ISA_OP_SEC, ISA_OP_SED, ISA_OP_SEI, ISA_OP_STA_ABS, ISA_OP_STA_ABSX, ISA_OP_STA_ABSY, ISA_OP_STA_INDX, ISA_OP_STA_INDY, ISA_OP_STA_ZP, ISA_OP_STA_ZPX, ISA_OP_STX_ABS, ISA_OP_STX_ZP, ISA_OP_STX_ZPY, ISA_OP_STY_ABS, ISA_OP_STY_ZP, ISA_OP_STY_ZPX, ISA_OP_TAX, ISA_OP_TAY, ISA_OP_TSX, ISA_OP_TXA, ISA_OP_TXS, ISA_OP_TYA};
use crate::op_info::OpInfo;
use crate::operation::Operation;
use crate::operation::Operation::*;
pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
let mut table: [Option<OpInfo>; 256] = [const { None }; 256];
table[ISA_OP_ADC_I as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_ADC_Z as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_ADC_ZX as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_ADC_ABS as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_ADC_ABSX as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_ADC_ABSY as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_ADC_INDX as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_ADC_INDY as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_AND_I as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_AND_Z as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_AND_ZX as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_AND_ABS as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_AND_ABSX as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_AND_ABSY as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_AND_INDX as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_AND_INDY as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_ASL_A as usize] = Some(OpInfo {
operation: ASL,
mode: AddressMode::Accumulator,
length: 1,
cycles: 2,
});
table[ISA_OP_ASL_Z as usize] = Some(OpInfo {
operation: ASL,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 5,
});
table[ISA_OP_ASL_ZX as usize] = Some(OpInfo {
operation: ASL,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 6,
});
table[ISA_OP_ASL_ABS as usize] = Some(OpInfo {
operation: ASL,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_ASL_ABSX as usize] = Some(OpInfo {
operation: ASL,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 7,
});
table[ISA_OP_BCC as usize] = Some(OpInfo {
operation: BCC,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BCS as usize] = Some(OpInfo {
operation: BCS,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BEQ as usize] = Some(OpInfo {
operation: BEQ,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BIT_ZP as usize] = Some(OpInfo {
operation: BIT,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_BIT_ABS as usize] = Some(OpInfo {
operation: BIT,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_BMI as usize] = Some(OpInfo {
operation: BMI,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BNE as usize] = Some(OpInfo {
operation: BNE,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BPL as usize] = Some(OpInfo {
operation: Operation::BPL,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BRK as usize] = Some(OpInfo {
operation: BRK,
mode: AddressMode::Implied,
length: 1,
cycles: 7,
});
table[ISA_OP_BVC as usize] = Some(OpInfo {
operation: BVC,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BVS as usize] = Some(OpInfo {
operation: BVS,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_CLC as usize] = Some(OpInfo {
operation: CLC,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_CLD as usize] = Some(OpInfo {
operation: CLD,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_CLI as usize] = Some(OpInfo {
operation: CLI,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_CLV as usize] = Some(OpInfo {
operation: CLV,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_CMP_I as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_CMP_ZP as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_CMP_ZPX as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_CMP_ABS as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_CMP_ABSX as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::AbsoluteX,
length: 2,
cycles: 4,
});
table[ISA_OP_CMP_ABSY as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::AbsoluteY,
length: 2,
cycles: 4,
});
table[ISA_OP_CMP_INDX as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_CMP_INDY as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_CPX_I as usize] = Some(OpInfo {
operation: CPX,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_CPX_ZP as usize] = Some(OpInfo {
operation: CPX,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_CPX_ABS as usize] = Some(OpInfo {
operation: CPX,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_CPY_I as usize] = Some(OpInfo {
operation: CPY,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_CPY_ZP as usize] = Some(OpInfo {
operation: CPY,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_CPY_ABS as usize] = Some(OpInfo {
operation: CPY,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_DEC_ZP as usize] = Some(OpInfo {
operation: DEC,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 5,
});
table[ISA_OP_DEC_ZPX as usize] = Some(OpInfo {
operation: DEC,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 6,
});
table[ISA_OP_DEC_ABS as usize] = Some(OpInfo {
operation: DEC,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_DEC_ABSX as usize] = Some(OpInfo {
operation: DEC,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 7,
});
table[ISA_OP_DEX as usize] = Some(OpInfo {
operation: DEX,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_DEY as usize] = Some(OpInfo {
operation: DEY,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_EOR_I as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_EOR_ZP as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_EOR_ZPX as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_EOR_ABS as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_EOR_ABSX as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_EOR_ABSY as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_EOR_INDX as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_EOR_INDY as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_INC_ZP as usize] = Some(OpInfo {
operation: INC,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 5,
});
table[ISA_OP_INC_ZPX as usize] = Some(OpInfo {
operation: INC,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 6,
});
table[ISA_OP_INC_ABS as usize] = Some(OpInfo {
operation: INC,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_INC_ABSX as usize] = Some(OpInfo {
operation: INC,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 7,
});
table[ISA_OP_INX as usize] = Some(OpInfo {
operation: INX,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_INY as usize] = Some(OpInfo {
operation: INY,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_JMP_ABS as usize] = Some(OpInfo {
operation: JMP,
mode: AddressMode::Absolute,
length: 3,
cycles: 3,
});
table[ISA_OP_JMP_IND as usize] = Some(OpInfo {
operation: JMP,
mode: AddressMode::Indirect,
length: 3,
cycles: 5,
});
table[ISA_OP_JSR as usize] = Some(OpInfo {
operation: JSR,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_LDA_I as usize] = Some(OpInfo {
operation: Operation::LDA,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_LDA_Z as usize] = Some(OpInfo {
operation: LDA,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_LDA_ZX as usize] = Some(OpInfo {
operation: LDA,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_LDA_ABS as usize] = Some(OpInfo {
operation: Operation::LDA,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_LDA_ABSX as usize] = Some(OpInfo {
operation: LDA,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_LDA_ABSY as usize] = Some(OpInfo {
operation: LDA,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_LDA_INDX as usize] = Some(OpInfo {
operation: Operation::LDA,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_LDA_INDY as usize] = Some(OpInfo {
operation: LDA,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_LDX_I as usize] = Some(OpInfo {
operation: Operation::LDX,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_LDX_ZP as usize] = Some(OpInfo {
operation: Operation::LDX,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_LDX_ZPY as usize] = Some(OpInfo {
operation: LDX,
mode: AddressMode::ZeroPageY,
length: 2,
cycles: 4,
});
table[ISA_OP_LDX_ABS as usize] = Some(OpInfo {
operation: Operation::LDX,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_LDX_ABSY as usize] = Some(OpInfo {
operation: Operation::LDX,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_LDY_I as usize] = Some(OpInfo {
operation: LDY,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_LDY_ZP as usize] = Some(OpInfo {
operation: LDY,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_LDY_ZPX as usize] = Some(OpInfo {
operation: Operation::LDY,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_LDY_ABS as usize] = Some(OpInfo {
operation: LDY,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_LDY_ABSX as usize] = Some(OpInfo {
operation: LDY,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_LSR_A as usize] = Some(OpInfo {
operation: Operation::LSR,
mode: AddressMode::Accumulator,
length: 1,
cycles: 2,
});
table[ISA_OP_LSR_ZP as usize] = Some(OpInfo {
operation: LSR,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 5,
});
table[ISA_OP_LSR_ZPX as usize] = Some(OpInfo {
operation: LSR,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 6,
});
table[ISA_OP_LSR_ABS as usize] = Some(OpInfo {
operation: Operation::LSR,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_LSR_ABSX as usize] = Some(OpInfo {
operation: Operation::LSR,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 7,
});
table[ISA_OP_NOP as usize] = Some(OpInfo {
operation: Operation::NOP,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_ORA_I as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_ORA_ZP as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_ORA_ZPX as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_ORA_ABS as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_ORA_ABSX as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_ORA_ABSY as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_ORA_INDX as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_ORA_INDY as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_PHA as usize] = Some(OpInfo {
operation: PHA,
mode: AddressMode::Implied,
length: 1,
cycles: 3,
});
table[ISA_OP_PHP as usize] = Some(OpInfo {
operation: Operation::PHP,
mode: AddressMode::Implied,
length: 1,
cycles: 3,
});
table[ISA_OP_PLA as usize] = Some(OpInfo {
operation: Operation::PLA,
mode: AddressMode::Implied,
length: 1,
cycles: 4,
});
table[ISA_OP_PLP as usize] = Some(OpInfo {
operation: Operation::PLP,
mode: AddressMode::Implied,
length: 1,
cycles: 4,
});
table[ISA_OP_ROL_A as usize] = Some(OpInfo {
operation: Operation::ROL,
mode: AddressMode::Accumulator,
length: 1,
cycles: 2,
});
table[ISA_OP_ROL_ZP as usize] = Some(OpInfo {
operation: Operation::ROL,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 5,
});
table[ISA_OP_ROL_ZPX as usize] = Some(OpInfo {
operation: Operation::ROL,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 6,
});
table[ISA_OP_ROL_ABS as usize] = Some(OpInfo {
operation: Operation::ROL,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_ROL_ABSX as usize] = Some(OpInfo {
operation: Operation::ROL,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 7,
});
table[ISA_OP_ROR_A as usize] = Some(OpInfo {
operation: Operation::ROR,
mode: AddressMode::Accumulator,
length: 1,
cycles: 2
});
table[ISA_OP_ROR_ZP as usize] = Some(OpInfo {
operation: Operation::ROR,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 5,
});
table[ISA_OP_ROR_ZPX as usize] = Some(OpInfo {
operation: Operation::ROR,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 6,
});
table[ISA_OP_ROR_ABS as usize] = Some(OpInfo {
operation: Operation::ROR,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_ROR_ABSX as usize] = Some(OpInfo {
operation: Operation::ROR,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 7,
});
table[ISA_OP_RTI as usize] = Some(OpInfo {
operation: Operation::RTI,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_RTS as usize] = Some(OpInfo {
operation: Operation::RTS,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_SBC_I as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_SBC_ZP as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_SBC_ZPX as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_SBC_ABS as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_SBC_ABSX as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_SBC_ABSY as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_SBC_INDX as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_SBC_INDY as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_SEC as usize] = Some(OpInfo {
operation: SEC,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_SED as usize] = Some(OpInfo {
operation: Operation::SED,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_SEI as usize] = Some(OpInfo {
operation: Operation::SEI,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_STA_ZP as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_STA_ZPX as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_STA_ABS as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_STA_ABSX as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 5,
});
table[ISA_OP_STA_ABSY as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 5,
});
table[ISA_OP_STA_INDX as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_STA_INDY as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::IndirectY,
length: 2,
cycles: 6,
});
table[ISA_OP_STX_ZP as usize] = Some(OpInfo {
operation: Operation::STX,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_STX_ZPY as usize] = Some(OpInfo {
operation: Operation::STX,
mode: AddressMode::ZeroPageY,
length: 2,
cycles: 4,
});
table[ISA_OP_STX_ABS as usize] = Some(OpInfo {
operation: Operation::STX,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_STY_ZP as usize] = Some(OpInfo {
operation: Operation::STY,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_STY_ZPX as usize] = Some(OpInfo {
operation: Operation::STY,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_STY_ABS as usize] = Some(OpInfo {
operation: Operation::STY,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_TAX as usize] = Some(OpInfo {
operation: Operation::TAX,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_TAY as usize] = Some(OpInfo {
operation: TAY,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_TSX as usize] = Some(OpInfo {
operation: TSX,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_TXA as usize] = Some(OpInfo {
operation: Operation::TXA,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_TXS as usize] = Some(OpInfo {
operation: Operation::TXS,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_TYA as usize] = Some(OpInfo {
operation: TYA,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table
};
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_instruction_table_completeness() {
use INSTRUCTION_TABLE; // Adjust to your actual path
let mut defined_count = 0;
let mut defined_opcodes = vec![];
for (i, entry) in INSTRUCTION_TABLE.iter().enumerate() {
if let Some(info) = entry {
defined_count += 1;
defined_opcodes.push(i);
// Optional: sanity check
assert!(
info.length > 0 && info.cycles > 0,
"Invalid OpInfo at opcode {:#04x?}",
i
);
}
}
println!("Defined opcodes: {}", defined_count);
for i in 0..256 {
if defined_opcodes.contains(&i) {
print!("{:02x} ", i);
}
}
println!("\nMissing opcodes:");
for i in 0..256 {
if !defined_opcodes.contains(&i) {
print!("{:02X} ", i);
}
}
println!();
// The standard 6502 has 151 documented opcodes
assert_eq!(
defined_count, 151,
"Expected 151 opcodes, found {}",
defined_count
);
}
}

View File

@ -1,74 +0,0 @@
use crate::address_mode::AddressMode::*;
use crate::constants::*;
use crate::instruction::Instruction;
use crate::instruction::Instruction::*;
pub struct Decoder {}
impl Decoder {
/// decode
///
/// Returns the decoded instruction or a NOP.
/// NOP will be returned when an instruction without a valid parameter
/// and more data is required to decode.
pub fn decode(decode_from: Vec<u8>) -> Instruction {
NOP
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn valid_decodes() {
let params = vec![
(vec![ISA_OP_ADC_I, 0xab], ADC(Immediate(0xab))),
(vec![ISA_OP_ADC_Z, 0xab], ADC(ZeroPage(0xab))),
(vec![ISA_OP_ADC_ZX, 0xab], ADC(ZeroPageX(0xab))),
(vec![ISA_OP_ADC_ABS, 0xab, 0xcd], ADC(Absolute(0xcdab))),
(vec![ISA_OP_ADC_ABSX, 0xcd, 0xab], ADC(AbsoluteX(0xabcd))),
(vec![ISA_OP_ADC_ABSY, 0xcd, 0xab], ADC(AbsoluteY(0xabcd))),
(vec![ISA_OP_ADC_INDX, 0xab], ADC(IndirectX(0xab))),
(vec![ISA_OP_ADC_INDY, 0xcd], ADC(IndirectY(0xcd))),
(vec![ISA_OP_AND_I, 0xab], AND(Immediate(0xab))),
(vec![ISA_OP_AND_Z, 0xab], AND(ZeroPage(0xab))),
(vec![ISA_OP_AND_ZX, 0xab], AND(ZeroPageX(0xab))),
(vec![ISA_OP_AND_ABS, 0xcd, 0xab], AND(Absolute(0xabcd))),
(vec![ISA_OP_ASL_A], ASL(Accumulator)),
(vec![ISA_OP_ASL_Z, 0xab], ASL(ZeroPage(0xab))),
(vec![ISA_OP_ASL_ZX, 0xab], ASL(ZeroPageX(0xab))),
(vec![ISA_OP_ASL_ABS, 0xab, 0xcd], ASL(Absolute(0xcdab))),
(vec![ISA_OP_ASL_ABSX, 0xab, 0xcd], ASL(AbsoluteX(0xcdab))),
(vec![ISA_OP_BCC, 0xab], BCC(Immediate(0xab))),
(vec![ISA_OP_BEQ, 0xab], BEQ(Immediate(0xab))),
(vec![ISA_OP_BIT_ZP, 0xab], BIT(ZeroPage(0xab))),
(vec![ISA_OP_BIT_ABS, 0xab, 0xcd], BIT(Absolute(0xcdab))),
(vec![ISA_OP_BMI, 0xab], BMI(Immediate(0xab))),
(vec![ISA_OP_BNE, 0xab], BNE(Immediate(0xab))),
(vec![ISA_OP_BPL, 0xab], BPL(Immediate(0xab))),
(vec![ISA_OP_BVC, 0xab], BVC(Immediate(0xab))),
(vec![ISA_OP_BVS, 0xab], BVS(Immediate(0xab))),
(vec![ISA_OP_BRK], BRK),
];
for (bytes, instruction) in params {
println!("Expecting {:?} to be {:?}", bytes, instruction);
assert_eq!(
Decoder::decode(bytes),
instruction
)
}
}
}

View File

@ -1,129 +0,0 @@
use crate::address_mode::AddressMode::*;
use crate::constants::*;
use crate::instruction::Instruction;
use crate::instruction::Instruction::*;
pub struct Encoder {}
impl Encoder {
pub fn encode(to_encode: Instruction) -> Vec<u8> {
match to_encode {
// ADC(_) => {}
// AND(_) => {}
// ASL(_) => {}
BCC(mode) => {
match mode {
Immediate(address)=> {
vec![ISA_OP_BCC, address]
}
_ => NOP.to_bytes()
}
}
// 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 => {}
_ => NOP.to_bytes()
}
}
}
#[cfg(test)]
mod test {
use crate::constants::*;
use super::*;
#[test]
fn adc_decode() {
let params = vec![
(vec![ISA_OP_ADC_I, 0xab], ADC(Immediate(0xab))),
(vec![ISA_OP_ADC_Z, 0xab], ADC(ZeroPage(0xab))),
(vec![ISA_OP_ADC_ZX, 0xab], ADC(ZeroPageX(0xab))),
(vec![ISA_OP_ADC_ABS, 0xab, 0xcd], ADC(Absolute(0xcdab))),
(vec![ISA_OP_ADC_ABSX, 0xcd, 0xab], ADC(AbsoluteX(0xabcd))),
(vec![ISA_OP_ADC_ABSY, 0xcd, 0xab], ADC(AbsoluteY(0xabcd))),
(vec![ISA_OP_ADC_INDX, 0xab], ADC(IndirectX(0xab))),
(vec![ISA_OP_ADC_INDY, 0xcd], ADC(IndirectY(0xcd))),
(vec![ISA_OP_AND_I, 0xab], AND(Immediate(0xab))),
(vec![ISA_OP_AND_Z, 0xab], AND(ZeroPage(0xab))),
(vec![ISA_OP_AND_ZX, 0xab], AND(ZeroPageX(0xab))),
(vec![ISA_OP_AND_ABS, 0xcd, 0xab], AND(Absolute(0xabcd))),
(vec![ISA_OP_ASL_A], ASL(Accumulator)),
(vec![ISA_OP_ASL_Z, 0xab], ASL(ZeroPage(0xab))),
(vec![ISA_OP_ASL_ZX, 0xab], ASL(ZeroPageX(0xab))),
(vec![ISA_OP_ASL_ABS, 0xab, 0xcd], ASL(Absolute(0xcdab))),
(vec![ISA_OP_ASL_ABSX, 0xab, 0xcd], ASL(AbsoluteX(0xcdab))),
(vec![ISA_OP_BCC, 0xab], BCC(Immediate(0xab))),
(vec![ISA_OP_BEQ, 0xab], BEQ(Immediate(0xab))),
(vec![ISA_OP_BIT_ZP, 0xab], BIT(ZeroPage(0xab))),
(vec![ISA_OP_BIT_ABS, 0xab, 0xcd], BIT(Absolute(0xcdab))),
(vec![ISA_OP_BMI, 0xab], BMI(Immediate(0xab))),
(vec![ISA_OP_BNE, 0xab], BNE(Immediate(0xab))),
(vec![ISA_OP_BPL, 0xab], BPL(Immediate(0xab))),
(vec![ISA_OP_BVC, 0xab], BVC(Immediate(0xab))),
(vec![ISA_OP_BVS, 0xab], BVS(Immediate(0xab))),
(vec![ISA_OP_BRK], BRK),
];
// for (bytes, instruction) in params {
// let encoded = Encoder::encode(bytes);
// assert_eq!(encoded, instruction.into());
// }
}
}

View File

@ -1,18 +0,0 @@
use crate::mos6502flags::Mos6502Flag;
pub enum MicrocodeStep {
ReadRegisterA,
ReadRegisterX,
ReadRegisterY,
ReadFlag(Mos6502Flag),
WriteRegisterA,
WriteRegisterX,
WriteRegisterY,
WriteFlag(Mos6502Flag, bool),
ReadMemory(u16),
WriteMemory(u16, u8),
ALUAdd(u8, u8),
ALUSub(u8, u8),
ALUAddC(u8, u8, bool),
ALUSubC(u8, u8, bool),
}

View File

@ -1,4 +0,0 @@
pub mod encode;
pub mod decoder;
pub mod microcode_steps;

View File

@ -1,7 +1,11 @@
pub mod periph;
pub mod address_mode;
pub mod mos6502cpu;
pub mod instruction;
pub mod mos6502flags;
pub mod isa;
pub mod constants;
mod instruction_stringify;
pub mod operation;
pub mod op_info;
pub mod operand;
pub mod instruction_table;
pub mod computers;

View File

@ -1,6 +1,7 @@
use crate::mos6502flags::{Mos6502Flag, Mos6502Flags};
pub const SIZE_1KB: usize = 1024 * 1024;
pub const SIZE_32KB: usize = SIZE_1KB * 32;
pub const SIZE_64KB: usize = SIZE_1KB * 64;
pub struct Mos6502Cpu {
@ -11,7 +12,28 @@ pub struct Mos6502Cpu {
flags: Mos6502Flags,
pc: u16,
s: u8,
microcode_step: u8
pub microcode_step: u8,
address_bus: u16,
data_bus: u8,
ir: u8 // Instruction Register
}
impl Default for Mos6502Cpu {
fn default() -> Self {
Mos6502Cpu {
memory: [0x00; SIZE_64KB],
a: 0,
x: 0,
y: 0,
flags: Default::default(),
pc: 0,
s: 0,
microcode_step: 0,
address_bus: 0,
data_bus: 0,
ir: 0x00
}
}
}
impl Mos6502Cpu {
@ -24,7 +46,10 @@ impl Mos6502Cpu {
flags: Mos6502Flags::default(),
pc: 0,
s: 0xfd,
microcode_step: 0
microcode_step: 0,
address_bus: 0x0000,
data_bus: 0x00,
ir: 0x00
}
}
@ -66,7 +91,17 @@ impl Mos6502Cpu {
self.y = new_y
}
pub fn tick(&mut self) {
/// Ticks the CPU
/// Returns
/// AddressBus, DataBus, RW flag
pub fn tick(&mut self) -> (u16, u8, bool) {
(0,0,false)
}
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);
}
}

10
core/src/op_info.rs Normal file
View File

@ -0,0 +1,10 @@
use crate::address_mode::AddressMode;
use crate::operation::Operation;
#[derive(Debug, Copy, Clone)]
pub struct OpInfo {
pub operation: Operation,
pub mode: AddressMode,
pub length: u8,
pub cycles: u8,
}

6
core/src/operand.rs Normal file
View File

@ -0,0 +1,6 @@
#[derive(Debug, PartialEq)]
pub enum Operand {
None,
Byte(u8),
Word(u16),
}

1012
core/src/operation.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
use crate::mos6502cpu::SIZE_32KB;
use crate::periph::rom_chip::RomChip;
/// At28C256
///
/// Represents a single At28C256 Chip
///
/// 256kbit storage
/// 32kbyte storage
pub struct At28C256 {
data: [u8; SIZE_32KB]
}
impl RomChip for At28C256 {
fn read(&self, offset: &u16) -> u8 {
self.data[*offset as usize]
}
fn program(new_data: &[u8; SIZE_32KB]) -> Self {
println!("Writing new chip.");
At28C256 {
data: *new_data
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn smoke() {
assert!(true)
}
#[test]
fn programmed_data_reads_back_same() {
print!("Starting test...");
let data_to_write = [0xea; SIZE_32KB];
print!("allocated data for rom...");
let chip: At28C256 = At28C256::program(&data_to_write);
println!("programmed chip...");
print!("testing");
for offset in 0..SIZE_32KB {
if offset.is_multiple_of(1000) {
print!(".");
};
assert_eq!(0xea, chip.read(&(offset as u16)));
}
println!("passed!");
}
}

3
core/src/periph/mod.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod rom_chip;
pub mod at28c256;

View File

@ -0,0 +1,17 @@
use crate::mos6502cpu::SIZE_32KB;
pub trait RomChip {
/// Read
///
/// Reads a single byte from the specified address
fn read(&self, offset: &u16) -> u8;
/// Program
///
/// Replaces all data in the ROM chip
fn program(new_data: &[u8; SIZE_32KB]) -> Self;
}
pub trait RamChip: RomChip {
fn write(&mut self, offset: &u16, value: &u8);
}

View File

View File

@ -2,3 +2,6 @@
name = "macroquad"
version = "0.1.0"
edition = "2024"
[dependencies]
macroquad.workspace = true

View File

@ -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
}
}

Binary file not shown.