Compare commits
4 Commits
87ae4e7890
...
d89fc1cd2b
| Author | SHA1 | Date | |
|---|---|---|---|
| d89fc1cd2b | |||
| 57544589b3 | |||
| 1b2fb2c221 | |||
| 768e83dfb8 |
5
.idea/.gitignore
generated
vendored
Normal file
5
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal 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
14
.idea/mos6502.iml
generated
Normal 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
6
.idea/vcs.xml
generated
Normal 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
231
Cargo.lock
generated
@ -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",
|
||||
]
|
||||
|
||||
@ -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
8
beneater/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "beneater"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../core" }
|
||||
macroquad.workspace = true
|
||||
16
beneater/src/bin/beneater.rs
Normal file
16
beneater/src/bin/beneater.rs
Normal 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
1
beneater/src/lib.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod parts;
|
||||
25
beneater/src/parts/ben_eater_pc.rs
Normal file
25
beneater/src/parts/ben_eater_pc.rs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
24
beneater/src/parts/clock.rs
Normal file
24
beneater/src/parts/clock.rs
Normal 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;
|
||||
}
|
||||
}
|
||||
3
beneater/src/parts/mod.rs
Normal file
3
beneater/src/parts/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod clock;
|
||||
mod ben_eater_pc;
|
||||
mod via6522;
|
||||
31
beneater/src/parts/via6522.rs
Normal file
31
beneater/src/parts/via6522.rs
Normal 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) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -3,4 +3,4 @@ name = "core"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
[dependencies]
|
||||
log = "0.4.26"
|
||||
log = "0.4"
|
||||
@ -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,
|
||||
}
|
||||
|
||||
9
core/src/computers/beneater/beneater.rs
Normal file
9
core/src/computers/beneater/beneater.rs
Normal 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 {
|
||||
|
||||
}
|
||||
|
||||
1
core/src/computers/beneater/mod.rs
Normal file
1
core/src/computers/beneater/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod beneater;
|
||||
2
core/src/computers/mod.rs
Normal file
2
core/src/computers/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod beneater;
|
||||
|
||||
@ -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;
|
||||
57
core/src/constants/constants_isa_stub.rs
Normal file
57
core/src/constants/constants_isa_stub.rs
Normal 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";
|
||||
2
core/src/constants/mod.rs
Normal file
2
core/src/constants/mod.rs
Normal 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
23
core/src/instruction2/from_bytes.rs
Normal file
23
core/src/instruction2/from_bytes.rs
Normal 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
|
||||
);
|
||||
}
|
||||
}
|
||||
7
core/src/instruction2/mod.rs
Normal file
7
core/src/instruction2/mod.rs
Normal 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;
|
||||
38
core/src/instruction2/to_bytes.rs
Normal file
38
core/src/instruction2/to_bytes.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
18
core/src/instruction2/to_string.rs
Normal file
18
core/src/instruction2/to_string.rs
Normal 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()
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
990
core/src/instruction_table.rs
Normal file
990
core/src/instruction_table.rs
Normal 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
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
// }
|
||||
}
|
||||
}
|
||||
@ -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),
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
|
||||
pub mod encode;
|
||||
pub mod decoder;
|
||||
pub mod microcode_steps;
|
||||
@ -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;
|
||||
|
||||
@ -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
10
core/src/op_info.rs
Normal 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
6
core/src/operand.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Operand {
|
||||
None,
|
||||
Byte(u8),
|
||||
Word(u16),
|
||||
}
|
||||
1012
core/src/operation.rs
Normal file
1012
core/src/operation.rs
Normal file
File diff suppressed because it is too large
Load Diff
52
core/src/periph/at28c256.rs
Normal file
52
core/src/periph/at28c256.rs
Normal 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
3
core/src/periph/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod rom_chip;
|
||||
|
||||
pub mod at28c256;
|
||||
17
core/src/periph/rom_chip.rs
Normal file
17
core/src/periph/rom_chip.rs
Normal 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);
|
||||
}
|
||||
|
||||
0
core/tests/instruction_encode_decode.rs
Normal file
0
core/tests/instruction_encode_decode.rs
Normal file
@ -2,3 +2,6 @@
|
||||
name = "macroquad"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
macroquad.workspace = true
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
BIN
resources/beneater/roms/nop.bin
Normal file
BIN
resources/beneater/roms/nop.bin
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user