I really should be using branches for diff experiments, but we can display in the terminal now!

This commit is contained in:
august kline 2024-06-23 13:23:29 -04:00
parent f9198cd0b1
commit 229b8b450d
10 changed files with 1967 additions and 2298 deletions

701
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1,3 +1,3 @@
char_rom = "./src/roms/cozette.rom"
rom = "./src/roms/test.rom"
rom = "./src/roms/george.rom"

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -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)?;

894
src/opcodes.in Normal file
View File

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

View File

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