I really should be using branches for diff experiments, but we can display in the terminal now!
This commit is contained in:
parent
f9198cd0b1
commit
229b8b450d
File diff suppressed because it is too large
Load Diff
10
Cargo.toml
10
Cargo.toml
|
@ -8,10 +8,18 @@ edition = "2021"
|
|||
[dependencies]
|
||||
anyhow = "1.0.81"
|
||||
bdf = "0.6.0"
|
||||
bitvec = "1.0.1"
|
||||
clap = { version = "4.5.4", features = ["derive"] }
|
||||
criterion = "0.4"
|
||||
crossterm = "0.27.0"
|
||||
minifb = "0.25.0"
|
||||
ratatui = "0.26.3"
|
||||
serde = { version = "1.0.197", features = ["serde_derive", "derive"] }
|
||||
toml = "0.8.12"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = {version = "0.4", features = ["html_reports"]}
|
||||
|
||||
[[bench]]
|
||||
name = "benchmark"
|
||||
path = "src/benches/benchmark.rs"
|
||||
harness = false
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
char_rom = "./src/roms/cozette.rom"
|
||||
rom = "./src/roms/test.rom"
|
||||
rom = "./src/roms/george.rom"
|
||||
|
||||
|
|
66
src/cpu.rs
66
src/cpu.rs
|
@ -1,6 +1,7 @@
|
|||
use crate::instructions::{get_instruction, Instruction};
|
||||
use crate::memory::{MemHandle, MemoryReader, MemoryWriter};
|
||||
use crate::types::{Byte, Word};
|
||||
use std::fmt::Display;
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
|
@ -68,6 +69,7 @@ pub struct CpuState {
|
|||
pub nmi: bool,
|
||||
}
|
||||
|
||||
// #[derive(Clone)]
|
||||
pub struct Cpu {
|
||||
pub a: Byte, // Accumulator Register
|
||||
pub x: Byte, // X Register
|
||||
|
@ -81,8 +83,14 @@ pub struct Cpu {
|
|||
pub pending_cycles: usize,
|
||||
receiver: CpuReceiver,
|
||||
stopped: bool,
|
||||
cycle_count: usize,
|
||||
state_tx: Sender<CpuState>,
|
||||
// cycle_count: usize,
|
||||
// state_tx: Sender<CpuState>,
|
||||
}
|
||||
|
||||
impl Display for Cpu {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{},{}", self.a, self.x)
|
||||
}
|
||||
}
|
||||
|
||||
impl MemoryReader for Cpu {
|
||||
|
@ -97,7 +105,8 @@ impl MemoryWriter for Cpu {
|
|||
}
|
||||
|
||||
impl Cpu {
|
||||
pub fn new(memory: MemHandle, receiver: CpuReceiver, state_tx: Sender<CpuState>) -> Self {
|
||||
pub fn new(memory: MemHandle, receiver: CpuReceiver) -> Self {
|
||||
// pub fn new(memory: MemHandle) -> Self {
|
||||
Cpu {
|
||||
a: 0x00,
|
||||
x: 0x00,
|
||||
|
@ -111,8 +120,8 @@ impl Cpu {
|
|||
memory,
|
||||
stopped: false,
|
||||
pending_cycles: 0,
|
||||
cycle_count: 0,
|
||||
state_tx,
|
||||
// cycle_count: 0,
|
||||
// state_tx,
|
||||
}
|
||||
}
|
||||
pub fn reset(&mut self) -> Result<()> {
|
||||
|
@ -121,15 +130,6 @@ impl Cpu {
|
|||
self.pending_cycles = 0;
|
||||
Ok(())
|
||||
}
|
||||
// pub fn read(&self, address: Word) -> Result<Byte> {
|
||||
// let memory = match self.memory.lock() {
|
||||
// Ok(read) => read,
|
||||
// Err(_) => {
|
||||
// bail!("Couldn't acquire lock on memory in cpu thread")
|
||||
// }
|
||||
// };
|
||||
// Ok(memory.read(address))
|
||||
// }
|
||||
pub fn read_word(&self, address: Word) -> Result<Word> {
|
||||
let low_byte = self.read(address);
|
||||
let high_byte = self.read(address + 0x1);
|
||||
|
@ -209,24 +209,24 @@ impl Cpu {
|
|||
CpuControl::Irq => self.irq = true,
|
||||
CpuControl::Stop => self.stopped = true,
|
||||
CpuControl::Resume => self.stopped = false,
|
||||
CpuControl::Data => self
|
||||
.state_tx
|
||||
.send(CpuState {
|
||||
a: self.a.clone(), // Accumulator Register
|
||||
x: self.x.clone(), // X Register
|
||||
y: self.y.clone(), // Y Register
|
||||
pc: self.pc.clone(), // Program Counter
|
||||
s: self.s.clone(), // Stack Pointer
|
||||
p: self.p.clone(), // Status Register
|
||||
irq: self.irq.clone(),
|
||||
nmi: self.nmi.clone(),
|
||||
})
|
||||
.unwrap(),
|
||||
CpuControl::Data => {} // self
|
||||
// .state_tx
|
||||
// .send(CpuState {
|
||||
// a: self.a.clone(), // Accumulator Register
|
||||
// x: self.x.clone(), // X Register
|
||||
// y: self.y.clone(), // Y Register
|
||||
// pc: self.pc.clone(), // Program Counter
|
||||
// s: self.s.clone(), // Stack Pointer
|
||||
// p: self.p.clone(), // Status Register
|
||||
// irq: self.irq.clone(),
|
||||
// nmi: self.nmi.clone(),
|
||||
// })
|
||||
// .unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cycle(&mut self) {
|
||||
self.receive_control();
|
||||
// self.receive_control();
|
||||
if self.stopped {
|
||||
return;
|
||||
}
|
||||
|
@ -239,13 +239,6 @@ impl Cpu {
|
|||
self.interrupt();
|
||||
}
|
||||
let opcode = self.read(self.pc);
|
||||
// let opcode = match self.read(&self.memory, self.pc) {
|
||||
// Ok(byte) => byte,
|
||||
// Err(_) => {
|
||||
// println!("Failed to read from memory at address {:#06x}!", self.pc);
|
||||
// return;
|
||||
// }
|
||||
// };
|
||||
let instruction = get_instruction(opcode);
|
||||
match instruction {
|
||||
Instruction::Valid(valid_instruction) => {
|
||||
|
@ -278,7 +271,8 @@ impl Cpu {
|
|||
}
|
||||
},
|
||||
}
|
||||
self.cycle_count += 1;
|
||||
// self.cycle_count += 1;
|
||||
sleep(Duration::from_nanos(100));
|
||||
}
|
||||
pub fn stop(&mut self) {
|
||||
self.stopped = true;
|
||||
|
|
|
@ -8,258 +8,258 @@
|
|||
# column #3 the Unicode name (follows a comment sign, '#')
|
||||
|
||||
0x00 0x00 #
|
||||
0x01 0x2591 #
|
||||
0x02 0x2592 # ᴥ
|
||||
0x03 0x2593 # ʔ
|
||||
0x04 0x2661 # White heart
|
||||
0x05 0x2665 # Black heart
|
||||
0x06 0x2B50 # White star
|
||||
0x07 0x272D # Black star
|
||||
0x08 0xF005 # Alternate Black Star
|
||||
0x09 0x2726 # Black four pointed star
|
||||
0x0a 0x2728 # Sparkles
|
||||
0x0b 0x2640 # Female Sign
|
||||
0x0c 0x2642 # Male Sign
|
||||
0x0d 0x26A2 # Doubled female sign
|
||||
0x0E 0x26A3 # Doubled male sign
|
||||
0x0F 0x26A5 # Male and Female sign0x000E
|
||||
0x10 0x2669 # Quarter Note
|
||||
0x11 0x266A # Eighth note
|
||||
0x12 0x266B # Beamed eighth notes
|
||||
0x13 0x266C # Beamed sixteenth notes
|
||||
0x14 0xFC5D #
|
||||
0x15 0xF026 #
|
||||
0x16 0xF027 #
|
||||
0x17 0xF028 #
|
||||
0x18 0xFA7E #
|
||||
0x19 0xFA7F #
|
||||
0x1A 0xFA80 #
|
||||
0x1B 0xFC5C #
|
||||
0x1C 0xFC5B #
|
||||
0x1D 0xF0AC #
|
||||
0x1E 0xF04B #
|
||||
0x1F 0xF04D #
|
||||
0x20 0x0020 # SPACE
|
||||
0x21 0x0021 # EXCLAMATION MARK
|
||||
0x22 0x0022 # QUOTATION MARK
|
||||
0x23 0x0023 # NUMBER SIGN
|
||||
0x24 0x0024 # DOLLAR SIGN
|
||||
0x25 0x0025 # PERCENT SIGN
|
||||
0x26 0x0026 # AMPERSAND
|
||||
0x27 0x0027 # APOSTROPHE
|
||||
0x28 0x0028 # LEFT PARENTHESIS
|
||||
0x29 0x0029 # RIGHT PARENTHESIS
|
||||
0x2A 0x002A # ASTERISK
|
||||
0x2B 0x002B # PLUS SIGN
|
||||
0x2C 0x002C # COMMA
|
||||
0x2D 0x002D # HYPHEN-MINUS
|
||||
0x2E 0x002E # FULL STOP
|
||||
0x2F 0x002F # SOLIDUS
|
||||
0x30 0x0030 # DIGIT ZERO
|
||||
0x31 0x0031 # DIGIT ONE
|
||||
0x32 0x0032 # DIGIT TWO
|
||||
0x33 0x0033 # DIGIT THREE
|
||||
0x34 0x0034 # DIGIT FOUR
|
||||
0x35 0x0035 # DIGIT FIVE
|
||||
0x36 0x0036 # DIGIT SIX
|
||||
0x37 0x0037 # DIGIT SEVEN
|
||||
0x38 0x0038 # DIGIT EIGHT
|
||||
0x39 0x0039 # DIGIT NINE
|
||||
0x3A 0x003A # COLON
|
||||
0x3B 0x003B # SEMICOLON
|
||||
0x3C 0x003C # LESS-THAN SIGN
|
||||
0x3D 0x003D # EQUALS SIGN
|
||||
0x3E 0x003E # GREATER-THAN SIGN
|
||||
0x3F 0x003F # QUESTION MARK
|
||||
0x40 0x0040 # COMMERCIAL AT
|
||||
0x41 0x0041 # LATIN CAPITAL LETTER A
|
||||
0x42 0x0042 # LATIN CAPITAL LETTER B
|
||||
0x43 0x0043 # LATIN CAPITAL LETTER C
|
||||
0x44 0x0044 # LATIN CAPITAL LETTER D
|
||||
0x45 0x0045 # LATIN CAPITAL LETTER E
|
||||
0x46 0x0046 # LATIN CAPITAL LETTER F
|
||||
0x47 0x0047 # LATIN CAPITAL LETTER G
|
||||
0x48 0x0048 # LATIN CAPITAL LETTER H
|
||||
0x49 0x0049 # LATIN CAPITAL LETTER I
|
||||
0x4A 0x004A # LATIN CAPITAL LETTER J
|
||||
0x4B 0x004B # LATIN CAPITAL LETTER K
|
||||
0x4C 0x004C # LATIN CAPITAL LETTER L
|
||||
0x4D 0x004D # LATIN CAPITAL LETTER M
|
||||
0x4E 0x004E # LATIN CAPITAL LETTER N
|
||||
0x4F 0x004F # LATIN CAPITAL LETTER O
|
||||
0x50 0x0050 # LATIN CAPITAL LETTER P
|
||||
0x51 0x0051 # LATIN CAPITAL LETTER Q
|
||||
0x52 0x0052 # LATIN CAPITAL LETTER R
|
||||
0x53 0x0053 # LATIN CAPITAL LETTER S
|
||||
0x54 0x0054 # LATIN CAPITAL LETTER T
|
||||
0x55 0x0055 # LATIN CAPITAL LETTER U
|
||||
0x56 0x0056 # LATIN CAPITAL LETTER V
|
||||
0x57 0x0057 # LATIN CAPITAL LETTER W
|
||||
0x58 0x0058 # LATIN CAPITAL LETTER X
|
||||
0x59 0x0059 # LATIN CAPITAL LETTER Y
|
||||
0x5A 0x005A # LATIN CAPITAL LETTER Z
|
||||
0x5B 0x005B # LEFT SQUARE BRACKET
|
||||
0x5C 0x005C # REVERSE SOLIDUS
|
||||
0x5D 0x005D # RIGHT SQUARE BRACKET
|
||||
0x5E 0x005E # CIRCUMFLEX ACCENT
|
||||
0x5F 0x005F # LOW LINE
|
||||
0x60 0x0060 # GRAVE ACCENT
|
||||
0x61 0x0061 # LATIN SMALL LETTER A
|
||||
0x62 0x0062 # LATIN SMALL LETTER B
|
||||
0x63 0x0063 # LATIN SMALL LETTER C
|
||||
0x64 0x0064 # LATIN SMALL LETTER D
|
||||
0x65 0x0065 # LATIN SMALL LETTER E
|
||||
0x66 0x0066 # LATIN SMALL LETTER F
|
||||
0x67 0x0067 # LATIN SMALL LETTER G
|
||||
0x68 0x0068 # LATIN SMALL LETTER H
|
||||
0x69 0x0069 # LATIN SMALL LETTER I
|
||||
0x6A 0x006A # LATIN SMALL LETTER J
|
||||
0x6B 0x006B # LATIN SMALL LETTER K
|
||||
0x6C 0x006C # LATIN SMALL LETTER L
|
||||
0x6D 0x006D # LATIN SMALL LETTER M
|
||||
0x6E 0x006E # LATIN SMALL LETTER N
|
||||
0x6F 0x006F # LATIN SMALL LETTER O
|
||||
0x70 0x0070 # LATIN SMALL LETTER P
|
||||
0x71 0x0071 # LATIN SMALL LETTER Q
|
||||
0x72 0x0072 # LATIN SMALL LETTER R
|
||||
0x73 0x0073 # LATIN SMALL LETTER S
|
||||
0x74 0x0074 # LATIN SMALL LETTER T
|
||||
0x75 0x0075 # LATIN SMALL LETTER U
|
||||
0x76 0x0076 # LATIN SMALL LETTER V
|
||||
0x77 0x0077 # LATIN SMALL LETTER W
|
||||
0x78 0x0078 # LATIN SMALL LETTER X
|
||||
0x79 0x0079 # LATIN SMALL LETTER Y
|
||||
0x7A 0x007A # LATIN SMALL LETTER Z
|
||||
0x7B 0x007B # LEFT CURLY BRACKET
|
||||
0x7C 0x007C # VERTICAL LINE
|
||||
0x7D 0x007D # RIGHT CURLY BRACKET
|
||||
0x7E 0x007E # TILDE
|
||||
0x7F 0x2500 # Box Drawings light horizontal
|
||||
0x80 0x2502 # Box drawings light vertical
|
||||
0x81 0x250C # Box drawing light down and right
|
||||
0x82 0x2514 # Box drawing light up and right
|
||||
0x83 0x251C # Box drawings light vertical and right
|
||||
0x84 0x2524 #
|
||||
0x85 0x252C #
|
||||
0x86 0x2534 #
|
||||
0x87 0x253C #
|
||||
0x88 0x256D #
|
||||
0x89 0x256E #
|
||||
0x8A 0x256F #
|
||||
0x8B 0x2570 #
|
||||
0x8C 0x2571 #
|
||||
0x8D 0x2572 #
|
||||
0x8E 0x2573 #
|
||||
0x8F 0x2550 #
|
||||
0x90 0x2551 #
|
||||
0x91 0x2554 #
|
||||
0x92 0x2557 #
|
||||
0x93 0x255a #
|
||||
0x94 0x255D #
|
||||
0x95 0x2560 #
|
||||
0x96 0x2563 #
|
||||
0x97 0x2566 #
|
||||
0x98 0x2569 #
|
||||
0x99 0x256C #
|
||||
0x9A 0xF04E #
|
||||
0x9B 0xF050 #
|
||||
0x9C 0xF051 #
|
||||
0x9D 0xF052 #
|
||||
0x9E 0xF048 #
|
||||
0x9F 0xE0B0 #
|
||||
0xA0 0xE0B2 #
|
||||
0xA1 0xE0B4 #
|
||||
0xA2 0xE0B6 #
|
||||
0xA3 0xE0B8 #
|
||||
0xA4 0xE0BA #
|
||||
0xA5 0xE0BC #
|
||||
0xA6 0xE0BE #
|
||||
0xA7 0x2581 #
|
||||
0xA8 0x2582 #
|
||||
0xA9 0x2583 #
|
||||
0xAA 0x2584 #
|
||||
0xAB 0x2585 #
|
||||
0xAC 0x2586 #
|
||||
0xAD 0x2587 #
|
||||
0xAE 0x2588 #
|
||||
0xAF 0x2589 #
|
||||
0xB0 0x258A #
|
||||
0xB1 0x258B #
|
||||
0xB2 0x258C #
|
||||
0xB3 0x258D #
|
||||
0xB4 0x258E #
|
||||
0xB5 0x258F #
|
||||
0xB6 0x0295 #
|
||||
0xB7 0x00B7 #
|
||||
0xB8 0x1D25 #
|
||||
0xB9 0x0294
|
||||
0xBA 0x2596
|
||||
0xBB 0x2597
|
||||
0xBC 0x2598
|
||||
0xBD 0x2599
|
||||
0xBE 0x259A
|
||||
0xBF 0x259B
|
||||
0xC0 0x259C
|
||||
0xC1 0x259D
|
||||
0xC2 0x259E
|
||||
0xC3 0x259F
|
||||
0xC4 0x2190
|
||||
0xC5 0x2191
|
||||
0xC6 0x2192
|
||||
0xC7 0x2193
|
||||
0xC8 0x2B60
|
||||
0xC9 0x2B61
|
||||
0xCA 0x2B62
|
||||
0xCB 0x2B63
|
||||
0xCC 0x2B80
|
||||
0xCD 0x2B81
|
||||
0xCE 0x2B82
|
||||
0xCF 0x2B83
|
||||
0xD0 0xF049
|
||||
0xD1 0xF04A
|
||||
0xD2 0x23F3
|
||||
0xD3 0xF07B
|
||||
0xD4 0xF07C
|
||||
0xD5 0xF114
|
||||
0xD6 0xF115
|
||||
0xD7 0xF250
|
||||
0xD8 0xF251
|
||||
0xD9 0xF253
|
||||
0xDA 0xF254
|
||||
0xDB 0xF461
|
||||
0xDC 0xF016
|
||||
0xDD 0xF401
|
||||
0xDE 0x1F52E
|
||||
0xDF 0xF2DB
|
||||
0xE0 0xF008
|
||||
0xE1 0x25C7
|
||||
0xE2 0x25C8
|
||||
0xE3 0x1F311
|
||||
0xE4 0x1F312
|
||||
0xE5 0x1F313
|
||||
0xE6 0x1F314
|
||||
0xE7 0x1F315
|
||||
0xE8 0x1F316
|
||||
0xE9 0x1F317
|
||||
0xEA 0x1F318
|
||||
0xEB 0xF04C
|
||||
0xEC 0x2714
|
||||
0xED 0x2718
|
||||
0xEE 0x25C6
|
||||
0xEF 0xF15D
|
||||
0xF0 0xF15E
|
||||
0xF1 0xF071
|
||||
0xF2 0xF449
|
||||
0xF3 0xF529
|
||||
0xF4 0xF658
|
||||
0xF5 0xF659 #
|
||||
0xF6 0x1f381 # Space
|
||||
0xF7 0xf05a # Space
|
||||
0xF8 0xf06a # Space
|
||||
0xF9 0xf834 # Space
|
||||
0xFA 0xf835 # Space
|
||||
0xFB 0x2690 # Space
|
||||
0xFC 0x2691 # Space
|
||||
0xFD 0xf8d7 # Space
|
||||
0xFE 0xf0e7 # Space
|
||||
0xFF 0xf7d9 # Space
|
||||
0x01 0x2591 # ░
|
||||
0x02 0x2592 # ▒
|
||||
0x03 0x2593 # ▓
|
||||
0x04 0x2661 # ♡
|
||||
0x05 0x2665 # ♥
|
||||
0x06 0x2B50 # ⭐
|
||||
0x07 0x272D # ✭
|
||||
0x08 0xF005 #
|
||||
0x09 0x2726 # ✦
|
||||
0x0a 0x2728 # ✨
|
||||
0x0b 0x2640 # ♀
|
||||
0x0c 0x2642 # ♂
|
||||
0x0d 0x26A2 # ⚢
|
||||
0x0E 0x26A3 # ⚣
|
||||
0x0F 0x26A5 # ⚥
|
||||
0x10 0x2669 # ♩
|
||||
0x11 0x266A # ♪
|
||||
0x12 0x266B # ♫
|
||||
0x13 0x266C # ♬
|
||||
0x14 0xFC5D # ﱝ
|
||||
0x15 0xF026 #
|
||||
0x16 0xF027 #
|
||||
0x17 0xF028 #
|
||||
0x18 0xFA7E # 奄
|
||||
0x19 0xFA7F # 奔
|
||||
0x1A 0xFA80 # 婢
|
||||
0x1B 0xFC5C # ﱜ
|
||||
0x1C 0xFC5B # ﱛ
|
||||
0x1D 0xF0AC #
|
||||
0x1E 0xF04B #
|
||||
0x1F 0xF04D #
|
||||
0x20 0x0020 #
|
||||
0x21 0x0021 # !
|
||||
0x22 0x0022 # "
|
||||
0x23 0x0023 # #
|
||||
0x24 0x0024 # $
|
||||
0x25 0x0025 # %
|
||||
0x26 0x0026 # &
|
||||
0x27 0x0027 # '
|
||||
0x28 0x0028 # (
|
||||
0x29 0x0029 # )
|
||||
0x2A 0x002A # *
|
||||
0x2B 0x002B # +
|
||||
0x2C 0x002C # ,
|
||||
0x2D 0x002D # -
|
||||
0x2E 0x002E # .
|
||||
0x2F 0x002F # /
|
||||
0x30 0x0030 # 0
|
||||
0x31 0x0031 # 1
|
||||
0x32 0x0032 # 2
|
||||
0x33 0x0033 # 3
|
||||
0x34 0x0034 # 4
|
||||
0x35 0x0035 # 5
|
||||
0x36 0x0036 # 6
|
||||
0x37 0x0037 # 7
|
||||
0x38 0x0038 # 8
|
||||
0x39 0x0039 # 9
|
||||
0x3A 0x003A # :
|
||||
0x3B 0x003B # ;
|
||||
0x3C 0x003C # <
|
||||
0x3D 0x003D # =
|
||||
0x3E 0x003E # >
|
||||
0x3F 0x003F # ?
|
||||
0x40 0x0040 # @
|
||||
0x41 0x0041 # A
|
||||
0x42 0x0042 # B
|
||||
0x43 0x0043 # C
|
||||
0x44 0x0044 # D
|
||||
0x45 0x0045 # E
|
||||
0x46 0x0046 # F
|
||||
0x47 0x0047 # G
|
||||
0x48 0x0048 # H
|
||||
0x49 0x0049 # I
|
||||
0x4A 0x004A # J
|
||||
0x4B 0x004B # K
|
||||
0x4C 0x004C # L
|
||||
0x4D 0x004D # M
|
||||
0x4E 0x004E # N
|
||||
0x4F 0x004F # O
|
||||
0x50 0x0050 # P
|
||||
0x51 0x0051 # Q
|
||||
0x52 0x0052 # R
|
||||
0x53 0x0053 # S
|
||||
0x54 0x0054 # T
|
||||
0x55 0x0055 # U
|
||||
0x56 0x0056 # V
|
||||
0x57 0x0057 # W
|
||||
0x58 0x0058 # X
|
||||
0x59 0x0059 # Y
|
||||
0x5A 0x005A # Z
|
||||
0x5B 0x005B # [
|
||||
0x5C 0x005C # \
|
||||
0x5D 0x005D # ]
|
||||
0x5E 0x005E # ^
|
||||
0x5F 0x005F # _
|
||||
0x60 0x0060 # `
|
||||
0x61 0x0061 # a
|
||||
0x62 0x0062 # b
|
||||
0x63 0x0063 # c
|
||||
0x64 0x0064 # d
|
||||
0x65 0x0065 # e
|
||||
0x66 0x0066 # f
|
||||
0x67 0x0067 # g
|
||||
0x68 0x0068 # h
|
||||
0x69 0x0069 # i
|
||||
0x6A 0x006A # j
|
||||
0x6B 0x006B # k
|
||||
0x6C 0x006C # l
|
||||
0x6D 0x006D # m
|
||||
0x6E 0x006E # n
|
||||
0x6F 0x006F # o
|
||||
0x70 0x0070 # p
|
||||
0x71 0x0071 # q
|
||||
0x72 0x0072 # r
|
||||
0x73 0x0073 # s
|
||||
0x74 0x0074 # t
|
||||
0x75 0x0075 # u
|
||||
0x76 0x0076 # v
|
||||
0x77 0x0077 # w
|
||||
0x78 0x0078 # x
|
||||
0x79 0x0079 # y
|
||||
0x7A 0x007A # z
|
||||
0x7B 0x007B # {
|
||||
0x7C 0x007C # |
|
||||
0x7D 0x007D # }
|
||||
0x7E 0x007E # ~
|
||||
0x7F 0x2500 # ─
|
||||
0x80 0x2502 # │
|
||||
0x81 0x250C # ┌
|
||||
0x82 0x2514 # └
|
||||
0x83 0x251C # ├
|
||||
0x84 0x2524 # ┤
|
||||
0x85 0x252C # ┬
|
||||
0x86 0x2534 # ┴
|
||||
0x87 0x253C # ┼
|
||||
0x88 0x256D # ╭
|
||||
0x89 0x256E # ╮
|
||||
0x8A 0x256F # ╯
|
||||
0x8B 0x2570 # ╰
|
||||
0x8C 0x2571 # ╱
|
||||
0x8D 0x2572 # ╲
|
||||
0x8E 0x2573 # ╳
|
||||
0x8F 0x2550 # ═
|
||||
0x90 0x2551 # ║
|
||||
0x91 0x2554 # ╔
|
||||
0x92 0x2557 # ╗
|
||||
0x93 0x255a # ╚
|
||||
0x94 0x255D # ╝
|
||||
0x95 0x2560 # ╠
|
||||
0x96 0x2563 # ╣
|
||||
0x97 0x2566 # ╦
|
||||
0x98 0x2569 # ╩
|
||||
0x99 0x256C # ╬
|
||||
0x9A 0xF04E #
|
||||
0x9B 0xF050 #
|
||||
0x9C 0xF051 #
|
||||
0x9D 0xF052 #
|
||||
0x9E 0xF048 #
|
||||
0x9F 0xE0B0 #
|
||||
0xA0 0xE0B2 #
|
||||
0xA1 0xE0B4 #
|
||||
0xA2 0xE0B6 #
|
||||
0xA3 0xE0B8 #
|
||||
0xA4 0xE0BA #
|
||||
0xA5 0xE0BC #
|
||||
0xA6 0xE0BE #
|
||||
0xA7 0x2581 # ▁
|
||||
0xA8 0x2582 # ▂
|
||||
0xA9 0x2583 # ▃
|
||||
0xAA 0x2584 # ▄
|
||||
0xAB 0x2585 # ▅
|
||||
0xAC 0x2586 # ▆
|
||||
0xAD 0x2587 # ▇
|
||||
0xAE 0x2588 # █
|
||||
0xAF 0x2589 # ▉
|
||||
0xB0 0x258A # ▊
|
||||
0xB1 0x258B # ▋
|
||||
0xB2 0x258C # ▌
|
||||
0xB3 0x258D # ▍
|
||||
0xB4 0x258E # ▎
|
||||
0xB5 0x258F # ▏
|
||||
0xB6 0x0295 # ʕ
|
||||
0xB7 0x00B7 # ·
|
||||
0xB8 0x1D25 # ᴥ
|
||||
0xB9 0x0294 # ʔ
|
||||
0xBA 0x2596 # ▖
|
||||
0xBB 0x2597 # ▗
|
||||
0xBC 0x2598 # ▘
|
||||
0xBD 0x2599 # ▙
|
||||
0xBE 0x259A # ▚
|
||||
0xBF 0x259B # ▛
|
||||
0xC0 0x259C # ▜
|
||||
0xC1 0x259D # ▝
|
||||
0xC2 0x259E # ▞
|
||||
0xC3 0x259F # ▟
|
||||
0xC4 0x2190 # ←
|
||||
0xC5 0x2191 # ↑
|
||||
0xC6 0x2192 # →
|
||||
0xC7 0x2193 # ↓
|
||||
0xC8 0x2B60 # ⭠
|
||||
0xC9 0x2B61 # ⭡
|
||||
0xCA 0x2B62 # ⭢
|
||||
0xCB 0x2B63 # ⭣
|
||||
0xCC 0x2B80 # ⮀
|
||||
0xCD 0x2B81 # ⮁
|
||||
0xCE 0x2B82 # ⮂
|
||||
0xCF 0x2B83 # ⮃
|
||||
0xD0 0xF049 #
|
||||
0xD1 0xF04A #
|
||||
0xD2 0x23F3 # ⏳
|
||||
0xD3 0xF07B #
|
||||
0xD4 0xF07C #
|
||||
0xD5 0xF114 #
|
||||
0xD6 0xF115 #
|
||||
0xD7 0xF250 #
|
||||
0xD8 0xF251 #
|
||||
0xD9 0xF253 #
|
||||
0xDA 0xF254 #
|
||||
0xDB 0xF461 #
|
||||
0xDC 0xF016 #
|
||||
0xDD 0xF401 #
|
||||
0xDE 0x1F52E # 🔮
|
||||
0xDF 0xF2DB #
|
||||
0xE0 0xF008 #
|
||||
0xE1 0x25C7 # ◇
|
||||
0xE2 0x25C8 # ◈
|
||||
0xE3 0x1F311 # 🌑
|
||||
0xE4 0x1F312 # 🌒
|
||||
0xE5 0x1F313 # 🌓
|
||||
0xE6 0x1F314 # 🌔
|
||||
0xE7 0x1F315 # 🌕
|
||||
0xE8 0x1F316 # 🌖
|
||||
0xE9 0x1F317 # 🌗
|
||||
0xEA 0x1F318 # 🌘
|
||||
0xEB 0xF04C #
|
||||
0xEC 0x2714 # ✔
|
||||
0xED 0x2718 # ✘
|
||||
0xEE 0x25C6 # ◆
|
||||
0xEF 0xF15D #
|
||||
0xF0 0xF15E #
|
||||
0xF1 0xF071 #
|
||||
0xF2 0xF449 #
|
||||
0xF3 0xF529 #
|
||||
0xF4 0xF658 #
|
||||
0xF5 0xF659 #
|
||||
0xF6 0x1f381 # 🎁
|
||||
0xF7 0xf05a #
|
||||
0xF8 0xf06a #
|
||||
0xF9 0xf834 #
|
||||
0xFA 0xf835 #
|
||||
0xFB 0x2690 # ⚐
|
||||
0xFC 0x2691 # ⚑
|
||||
0xFD 0xf8d7 #
|
||||
0xFE 0xf0e7 #
|
||||
0xFF 0xf7d9 #
|
||||
|
|
1808
src/instructions.rs
1808
src/instructions.rs
File diff suppressed because it is too large
Load Diff
111
src/main.rs
111
src/main.rs
|
@ -12,12 +12,16 @@ mod video;
|
|||
use crate::cpu::Cpu;
|
||||
use crate::keyboard::Keyboard;
|
||||
use crate::memory::Mem;
|
||||
use crate::video::Crtc;
|
||||
use crate::video::{Screen, TerminalRenderer};
|
||||
|
||||
use cpu::{CpuController, CpuReceiver};
|
||||
use crossterm::cursor::Hide;
|
||||
use crossterm::execute;
|
||||
use crossterm::terminal::{size, Clear, ClearType, SetSize};
|
||||
// use cpu::CpuController;
|
||||
use memory::MemHandle;
|
||||
// use clap::Parser;
|
||||
use minifb::{Scale, ScaleMode, Window, WindowOptions};
|
||||
// use minifb::{Scale, ScaleMode, Window, WindowOptions};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use std::{
|
||||
|
@ -30,13 +34,12 @@ use std::{
|
|||
};
|
||||
|
||||
use crossterm::{
|
||||
cursor,
|
||||
event::{self, KeyCode, KeyEventKind},
|
||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||
ExecutableCommand,
|
||||
// ExecutableCommand,
|
||||
};
|
||||
|
||||
use ratatui::prelude::{CrosstermBackend, Terminal};
|
||||
|
||||
// use toml::Table;
|
||||
|
||||
//#[derive(Parser)]
|
||||
|
@ -53,10 +56,10 @@ struct Config {
|
|||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
stdout().execute(EnterAlternateScreen)?;
|
||||
let mut stdout = stdout();
|
||||
let (cols, rows) = size()?;
|
||||
execute!(stdout, SetSize(64, 29), cursor::Hide, EnterAlternateScreen)?;
|
||||
enable_raw_mode()?;
|
||||
let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
|
||||
terminal.clear()?;
|
||||
|
||||
let config: Config = match File::open("./config.toml") {
|
||||
Ok(mut file) => {
|
||||
|
@ -86,50 +89,60 @@ fn main() -> Result<()> {
|
|||
let keyboard_memory = shared_memory.clone();
|
||||
|
||||
let (cpu_tx, cpu_rx) = mpsc::channel();
|
||||
let (state_tx, state_rx) = mpsc::channel();
|
||||
// let (state_tx, state_rx) = mpsc::channel();
|
||||
let screen_cpu_tx = cpu_tx.clone();
|
||||
let (window_tx, window_rx) = mpsc::channel();
|
||||
// let (window_tx, window_rx) = mpsc::channel();
|
||||
|
||||
thread::spawn(move || {
|
||||
let mut screen = Crtc::new(
|
||||
screen_memory,
|
||||
config.char_rom.as_ref(),
|
||||
CpuController::new(screen_cpu_tx),
|
||||
window_tx,
|
||||
);
|
||||
screen.run();
|
||||
});
|
||||
// thread::spawn(move || {
|
||||
// let mut screen = Crtc::new(
|
||||
// screen_memory,
|
||||
// config.char_rom.as_ref(),
|
||||
// CpuController::new(screen_cpu_tx),
|
||||
// window_tx,
|
||||
// );
|
||||
// screen.run();
|
||||
// });
|
||||
|
||||
let mut window = Window::new(
|
||||
"ʕ·ᴥ·ʔ-☆",
|
||||
512,
|
||||
380,
|
||||
WindowOptions {
|
||||
resize: true,
|
||||
borderless: true,
|
||||
title: true,
|
||||
transparency: false,
|
||||
scale: Scale::X2,
|
||||
scale_mode: ScaleMode::AspectRatioStretch,
|
||||
topmost: false,
|
||||
none: true,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
// let mut window = Window::new(
|
||||
// "ʕ·ᴥ·ʔ-☆",
|
||||
// 512,
|
||||
// 380,
|
||||
// WindowOptions {
|
||||
// resize: true,
|
||||
// borderless: true,
|
||||
// title: true,
|
||||
// transparency: false,
|
||||
// scale: Scale::X2,
|
||||
// scale_mode: ScaleMode::AspectRatioStretch,
|
||||
// topmost: false,
|
||||
// none: true,
|
||||
// },
|
||||
// )
|
||||
// .unwrap();
|
||||
|
||||
window.set_input_callback(Box::new(Keyboard::new(keyboard_memory)));
|
||||
// window.set_input_callback(Box::new(Keyboard::new(keyboard_memory)));
|
||||
|
||||
let mut cpu = Cpu::new(cpu_memory, CpuReceiver::new(cpu_rx), state_tx);
|
||||
let mut tui = tui::App::new(
|
||||
CpuController::new(cpu_tx.clone()),
|
||||
shared_memory.clone(),
|
||||
state_rx,
|
||||
);
|
||||
let mut cpu = Cpu::new(cpu_memory, CpuReceiver::new(cpu_rx));
|
||||
// let mut cpu = Cpu::new(cpu_memory);
|
||||
// let mut tui = tui::App::new(
|
||||
// CpuController::new(cpu_tx.clone()),
|
||||
// shared_memory.clone(),
|
||||
// state_rx,
|
||||
// );
|
||||
thread::spawn(move || {
|
||||
cpu.reset().unwrap();
|
||||
cpu.memory.write(0x4400, 0b0000_0100);
|
||||
cpu.execute()
|
||||
});
|
||||
|
||||
let stdout_lock = stdout.lock();
|
||||
let renderer = TerminalRenderer::new(screen_memory, stdout_lock);
|
||||
let mut screen = Screen::new(CpuController::new(cpu_tx.clone()), renderer);
|
||||
|
||||
// thread::spawn(move || {
|
||||
// screen.run();
|
||||
// });
|
||||
|
||||
loop {
|
||||
if event::poll(std::time::Duration::from_millis(16))? {
|
||||
if let event::Event::Key(key) = event::read()? {
|
||||
|
@ -138,11 +151,17 @@ fn main() -> Result<()> {
|
|||
}
|
||||
}
|
||||
}
|
||||
let buffer = window_rx.recv().unwrap();
|
||||
window.update_with_buffer(&buffer, 512, 380).unwrap();
|
||||
tui.update(&mut terminal)?;
|
||||
// let buffer = window_rx.recv().unwrap();
|
||||
screen.draw()
|
||||
// tui.update(&mut terminal)?;
|
||||
}
|
||||
stdout().execute(LeaveAlternateScreen)?;
|
||||
|
||||
execute!(
|
||||
stdout,
|
||||
LeaveAlternateScreen,
|
||||
SetSize(cols, rows),
|
||||
Clear(ClearType::Purge)
|
||||
)?;
|
||||
disable_raw_mode()?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -53,12 +53,18 @@ pub struct Mem {
|
|||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Mem {
|
||||
pub fn new() -> Self {
|
||||
impl Default for Mem {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
data: vec![0; u16::MAX as usize + 1],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mem {
|
||||
pub fn new() -> Self {
|
||||
Mem::default()
|
||||
}
|
||||
pub fn dump(&self, path: PathBuf) -> io::Result<()> {
|
||||
let mut outfile = File::create(path)?;
|
||||
outfile.write_all(&self.data)?;
|
||||
|
|
|
@ -0,0 +1,894 @@
|
|||
vec![
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BRK(AddressingMode::Implied),
|
||||
cycles: 7,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ORA(AddressingMode::ZeroPageIndexedIndirect),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x02 }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x03 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::TSB(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ORA(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ASL(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::RMB0(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::PHP(AddressingMode::Stack),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ORA(AddressingMode::Immediate),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ASL(AddressingMode::Accumulator),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x0b }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::TSB(AddressingMode::AbsoluteA),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ORA(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ASL(AddressingMode::AbsoluteA),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBR0(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BPL(AddressingMode::ProgramCounterRelative),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ORA(AddressingMode::AbsoluteIndexedWithY),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ORA(AddressingMode::ZeroPageIndirect),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x13 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::TRB(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ORA(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ASL(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::RMB1(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CLC(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ORA(AddressingMode::AbsoluteIndexedWithY),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::INC(AddressingMode::Accumulator),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x1b }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::TRB(AddressingMode::AbsoluteA),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ORA(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ASL(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 7,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBR1(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::JSR(AddressingMode::AbsoluteA),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::AND(AddressingMode::ZeroPageIndexedIndirect),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x22 }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x23 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BIT(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::AND(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ROL(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::RMB2(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::PLP(AddressingMode::Stack),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::AND(AddressingMode::Immediate),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ROL(AddressingMode::Accumulator),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x2b }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BIT(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::AND(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ROL(AddressingMode::AbsoluteA),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBR2(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BMI(AddressingMode::ProgramCounterRelative),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::AND(AddressingMode::ZeroPageIndirectIndexedWithY),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::AND(AddressingMode::ZeroPageIndirect),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x33 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BIT(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::AND(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ROL(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::RMB3(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SEC(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::AND(AddressingMode::AbsoluteIndexedWithY),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::DEC(AddressingMode::Accumulator),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x3b }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BIT(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::AND(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ROL(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 7,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBR3(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::RTI(AddressingMode::Implied),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::EOR(AddressingMode::ZeroPageIndexedIndirect),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x42 }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x43 }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x44 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::EOR(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LSR(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::RMB4(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::PHA(AddressingMode::Stack),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::EOR(AddressingMode::Immediate),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LSR(AddressingMode::Accumulator),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x4b }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::JMP(AddressingMode::AbsoluteA),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::EOR(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LSR(AddressingMode::AbsoluteA),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBR4(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BVC(AddressingMode::ProgramCounterRelative),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::EOR(AddressingMode::ZeroPageIndirectIndexedWithY),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::EOR(AddressingMode::ZeroPageIndirect),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x53 }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x54 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::EOR(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LSR(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::RMB5(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CLI(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::EOR(AddressingMode::AbsoluteIndexedWithY),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::PHY(AddressingMode::Stack),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x5b }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x5c }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::EOR(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LSR(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 7,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBR5(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::RTS(AddressingMode::Stack),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ADC(AddressingMode::ZeroPageIndexedIndirect),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x62 }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x63 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STZ(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ADC(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ROR(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::RMB6(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::PLA(AddressingMode::Stack),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ADC(AddressingMode::Immediate),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ROR(AddressingMode::Accumulator),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x6b }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::JMP(AddressingMode::AbsoluteIndirect),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ADC(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ROR(AddressingMode::AbsoluteA),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBR6(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BVS(AddressingMode::ProgramCounterRelative),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ADC(AddressingMode::ZeroPageIndirectIndexedWithY),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ADC(AddressingMode::ZeroPageIndirect),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x73 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STZ(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ADC(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ROR(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::RMB7(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SEI(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ADC(AddressingMode::AbsoluteIndexedWithY),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::PLY(AddressingMode::Stack),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x7b }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::JMP(AddressingMode::AbsoluteIndexedIndirect),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ADC(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::ROR(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 7,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBR7(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BRA(AddressingMode::ProgramCounterRelative),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STA(AddressingMode::ZeroPageIndexedIndirect),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x82 }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x83 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STY(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STA(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STX(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SMB0(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::DEY(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BIT(AddressingMode::Immediate),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::TXA(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x8b }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STY(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STA(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STX(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBS0(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BCC(AddressingMode::ProgramCounterRelative),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STA(AddressingMode::ZeroPageIndirectIndexedWithY),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STA(AddressingMode::ZeroPageIndirect),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x93 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STY(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STA(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STX(AddressingMode::ZeroPageIndexedWithY),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SMB1(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::TYA(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STA(AddressingMode::AbsoluteIndexedWithY),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::TXS(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0x9b }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STZ(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STA(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STZ(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBS1(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDY(AddressingMode::Immediate),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDA(AddressingMode::ZeroPageIndexedIndirect),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDX(AddressingMode::Immediate),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xa3 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDY(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDA(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDX(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SMB2(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::TAY(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDA(AddressingMode::Immediate),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::TAX(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xab }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDY(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDA(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDX(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBS2(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BCS(AddressingMode::ProgramCounterRelative),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDA(AddressingMode::ZeroPageIndirectIndexedWithY),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDA(AddressingMode::ZeroPageIndirect),
|
||||
cycles: 5, // Unsure, see https://cx16.dk/65c02/reference.html#LDA
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xb3 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDY(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDA(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDX(AddressingMode::ZeroPageIndexedWithY),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SMB3(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CLV(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDA(AddressingMode::AbsoluteIndexedWithY),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::TSX(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xbb }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDY(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDA(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::LDX(AddressingMode::AbsoluteIndexedWithY),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBS3(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CPY(AddressingMode::Immediate),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CMP(AddressingMode::ZeroPageIndexedIndirect),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xc2 }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xc3 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CPY(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CMP(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::DEC(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SMB4(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::INY(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CMP(AddressingMode::Immediate),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::DEX(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::WAI(AddressingMode::Implied),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CPY(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CMP(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::DEC(AddressingMode::AbsoluteA),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBS4(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BNE(AddressingMode::ProgramCounterRelative),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CMP(AddressingMode::ZeroPageIndirectIndexedWithY),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CMP(AddressingMode::ZeroPageIndirect),
|
||||
cycles: 5, // Unsure, look here: https://cx16.dk/65c02/reference.html#CMP
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xd3 }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xd4 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CMP(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::DEC(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SMB5(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CLD(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CMP(AddressingMode::AbsoluteIndexedWithY),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::PHX(AddressingMode::Stack),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::STP(AddressingMode::Implied),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xdc }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CMP(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::DEC(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 7,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBS5(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CPX(AddressingMode::Immediate),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SBC(AddressingMode::ZeroPageIndexedIndirect),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xe2 }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xe3 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CPX(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SBC(AddressingMode::ZeroPage),
|
||||
cycles: 3,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::INC(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SMB6(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::INX(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SBC(AddressingMode::Immediate),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::NOP(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xeb }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::CPX(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SBC(AddressingMode::AbsoluteA),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::INC(AddressingMode::AbsoluteA),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBS6(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BEQ(AddressingMode::ProgramCounterRelative),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SBC(AddressingMode::ZeroPageIndirectIndexedWithY),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SBC(AddressingMode::ZeroPageIndirect),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xf3 }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xf4 }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SBC(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::INC(AddressingMode::ZeroPageIndexedWithX),
|
||||
cycles: 6,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SMB7(AddressingMode::ZeroPage),
|
||||
cycles: 5,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SED(AddressingMode::Implied),
|
||||
cycles: 2,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SBC(AddressingMode::AbsoluteIndexedWithY),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::PLX(AddressingMode::Stack),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xfb }),
|
||||
Instruction::Invalid(InvalidInstruction { opcode: 0xfc }),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::SBC(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 4,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::INC(AddressingMode::AbsoluteIndexedWithX),
|
||||
cycles: 7,
|
||||
}),
|
||||
Instruction::Valid(ValidInstruction {
|
||||
opcode: Opcode::BBS7(AddressingMode::ProgramCounterRelativeTest),
|
||||
cycles: 4,
|
||||
}),
|
||||
]
|
151
src/video.rs
151
src/video.rs
|
@ -1,9 +1,22 @@
|
|||
use crossterm::{
|
||||
cursor::{MoveTo, SavePosition},
|
||||
execute, queue,
|
||||
style::{Color, PrintStyledContent, Stylize},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
cpu::CpuController,
|
||||
memory::{MemHandle, MemoryReader},
|
||||
memory::{self, MemHandle, MemoryReader},
|
||||
types::{Byte, Word},
|
||||
};
|
||||
use std::{fs::File, io::Read, path::Path, sync::mpsc::Sender, thread::sleep, time::Duration};
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{Read, Stdout, StdoutLock, Write},
|
||||
path::Path,
|
||||
sync::mpsc::Sender,
|
||||
thread::sleep,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
const FG_COLOR: u32 = 0xFFCC00;
|
||||
const BG_COLOR: u32 = 0x110500;
|
||||
|
@ -27,44 +40,37 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Crtc {
|
||||
memory: MemHandle,
|
||||
buffer: Vec<u32>,
|
||||
trait Renderer {
|
||||
fn render(&mut self) {}
|
||||
}
|
||||
|
||||
pub struct WindowRenderer {
|
||||
char_rom: Vec<u8>,
|
||||
cpu_controller: CpuController,
|
||||
window: Sender<Vec<u32>>,
|
||||
memory: MemHandle,
|
||||
}
|
||||
|
||||
impl MemoryReader for Crtc {
|
||||
fn read(&self, address: Word) -> Byte {
|
||||
self.memory.read(address)
|
||||
}
|
||||
}
|
||||
|
||||
impl Crtc {
|
||||
pub fn new<P>(
|
||||
memory: MemHandle,
|
||||
char_rom: Option<P>,
|
||||
cpu_controller: CpuController,
|
||||
window: Sender<Vec<u32>>,
|
||||
) -> Self
|
||||
impl WindowRenderer {
|
||||
pub fn new<P>(memory: MemHandle, char_rom: Option<P>, window: Sender<Vec<u32>>) -> Self
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let char_rom = get_char_bin(char_rom);
|
||||
Self {
|
||||
memory,
|
||||
buffer: vec![0; 512 * 380],
|
||||
window,
|
||||
char_rom,
|
||||
cpu_controller,
|
||||
}
|
||||
}
|
||||
fn draw(&mut self) {
|
||||
}
|
||||
|
||||
impl Renderer for WindowRenderer {
|
||||
fn render(&mut self) {
|
||||
// the rest of this function is arcane wizardry
|
||||
// based on the specifics of george's weird
|
||||
// display and characters... don't fuck around w it
|
||||
let mut i = 0;
|
||||
let mut buffer = vec![0; 512 * 380];
|
||||
for char_row in 0..29 {
|
||||
for char_col in 0..64 {
|
||||
let ascii = self.memory.read(0x6000 + i);
|
||||
|
@ -75,23 +81,114 @@ impl Crtc {
|
|||
let buffer_index =
|
||||
((char_row) * 13 + (row)) * 512 + (char_col * 8 + bit_index);
|
||||
if (byte << bit_index) & 0x80 == 0x80 {
|
||||
self.buffer[buffer_index] = FG_COLOR;
|
||||
buffer[buffer_index] = FG_COLOR;
|
||||
} else {
|
||||
self.buffer[buffer_index] = BG_COLOR;
|
||||
buffer[buffer_index] = BG_COLOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _ = self.window.send(buffer.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let buffer = self.buffer.to_owned();
|
||||
impl MemoryReader for WindowRenderer {
|
||||
fn read(&self, address: Word) -> Byte {
|
||||
self.memory.read(address)
|
||||
}
|
||||
}
|
||||
|
||||
let _ = self.window.send(buffer);
|
||||
pub struct TerminalRenderer<'a> {
|
||||
memory: MemHandle,
|
||||
// stdout: Stdout,
|
||||
stdout: StdoutLock<'a>,
|
||||
}
|
||||
|
||||
impl<'a> TerminalRenderer<'a> {
|
||||
pub fn new(memory: MemHandle, stdout: StdoutLock<'a>) -> Self {
|
||||
Self { memory, stdout }
|
||||
}
|
||||
}
|
||||
|
||||
impl MemoryReader for TerminalRenderer<'_> {
|
||||
fn read(&self, address: Word) -> Byte {
|
||||
self.memory.read(address)
|
||||
}
|
||||
}
|
||||
|
||||
static ASCII_LOOPUP: [&str; 256] = [
|
||||
" ", "░", "▒", "▓", "♡", "♥", "⭐", "✭", "", "✦", "✨", "♀", "♂", "⚢", "⚣", "⚥", "♩", "♪",
|
||||
"♫", "♬", "ﱝ", "", "", "", "奄", "奔", "婢", "ﱜ", "ﱛ", "", "", "", " ", "!", "\"", "#",
|
||||
"$", "%", "&", "\'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6",
|
||||
"7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I",
|
||||
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\",
|
||||
"]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
|
||||
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "─", "│", "┌", "└",
|
||||
"├", "┤", "┬", "┴", "┼", "╭", "╮", "╯", "╰", "╱", "╲", "╳", "═", "║", "╔", "╗", "╚", "╝", "╠",
|
||||
"╣", "╦", "╩", "╬", "", "", "", "", "", "", "", "", "", "", "", "", "", "▁", "▂",
|
||||
"▃", "▄", "▅", "▆", "▇", "█", "▉", "▊", "▋", "▌", "▍", "▎", "▏", "ʕ", "·", "ᴥ", "ʔ", "▖", "▗",
|
||||
"▘", "▙", "▚", "▛", "▜", "▝", "▞", "▟", "←", "↑", "→", "↓", "⭠", "⭡", "⭢", "⭣", "⮀", "⮁", "⮂",
|
||||
"⮃", "", "", "⏳", "", "", "", "", "", "", "", "", "", "", "", "🔮", "", "",
|
||||
"◇", "◈", "🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘", "", "✔", "✘", "◆", "", "", "",
|
||||
"", "", "", "", "🎁", "", "", "", "", "⚐", "⚑", "", "", "",
|
||||
];
|
||||
|
||||
impl Renderer for TerminalRenderer<'_> {
|
||||
fn render(&mut self) {
|
||||
let _ = execute!(self.stdout, SavePosition);
|
||||
let mut i = 0;
|
||||
for char_row in 0..29 {
|
||||
for char_col in 0..64 {
|
||||
let ascii = self.memory.read(0x6000 + i);
|
||||
i += 1;
|
||||
let char = ASCII_LOOPUP[ascii as usize];
|
||||
let _ = queue!(
|
||||
// FG_COLOR = 0xFFCC00
|
||||
// BG_COLOR = 0x110500
|
||||
self.stdout,
|
||||
MoveTo(char_col, char_row),
|
||||
PrintStyledContent(
|
||||
char.with(Color::Rgb {
|
||||
r: 0xFF,
|
||||
g: 0xCC,
|
||||
b: 0x00
|
||||
})
|
||||
.on(Color::Rgb {
|
||||
r: 0x11,
|
||||
g: 0x05,
|
||||
b: 0x00
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
let _ = self.stdout.flush();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Screen<'a> {
|
||||
cpu_controller: CpuController,
|
||||
// renderer: Box<dyn Renderer>,
|
||||
renderer: TerminalRenderer<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Screen<'a> {
|
||||
// pub fn new(cpu_controller: CpuController, renderer: Box<dyn Renderer>) -> Self {
|
||||
pub fn new(cpu_controller: CpuController, renderer: TerminalRenderer<'a>) -> Self {
|
||||
Self {
|
||||
cpu_controller,
|
||||
renderer,
|
||||
}
|
||||
}
|
||||
pub fn draw(&mut self) {
|
||||
self.renderer.render();
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
loop {
|
||||
let _ = self.cpu_controller.irq();
|
||||
self.cpu_controller.irq();
|
||||
sleep(Duration::from_millis(16));
|
||||
self.draw();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue