initial commit

master
Drake 1 year ago
commit 9ac52951aa

1
.gitignore vendored

@ -0,0 +1 @@
/target

329
Cargo.lock generated

@ -0,0 +1,329 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "clap"
version = "4.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3"
dependencies = [
"bitflags",
"clap_derive",
"clap_lex",
"is-terminal",
"once_cell",
"strsim",
"termcolor",
]
[[package]]
name = "clap_derive"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "io-lifetimes"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "is-terminal"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef"
dependencies = [
"hermit-abi",
"io-lifetimes",
"rustix",
"windows-sys",
]
[[package]]
name = "libc"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "lris-emu"
version = "0.1.0"
dependencies = [
"clap",
]
[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "os_str_bytes"
version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustix"
version = "0.36.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termcolor"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
dependencies = [
"winapi-util",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
[[package]]
name = "windows_i686_gnu"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
[[package]]
name = "windows_i686_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"

@ -0,0 +1,9 @@
[package]
name = "lris-emu"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = { version = "4.1.6", features = ["derive"] }

@ -0,0 +1,104 @@
NOP
NOP
LOL 01 010f
LOL 01 0112
LOL 01 0117
LOL 00 0117
NOP
LOL 01 0110
LOL 01 0115
LOL 01 0113
LOL 00 0112
LOL 01 0117
LOL 00 0117
NOP
LOL 01 0112
LOL 00 0115
LOL 01 0117
LOL 00 0117
LOL 01 0117
LOL 00 0117
NOP
LOL 01 0114
LOL 01 0115
LOL 01 0117
LOL 00 0117
NOP
LOL 00 0114
LOL 00 0115
LOL 00 010f
LOL 01 0117
LOL 00 0117
NOP
LOL 00 010F
LOL 00 0110
LOL 00 0111
LOL 00 0112
LOL 00 0113
LOL 00 0114
LOL 00 0115
LOL 00 0116
LOL 01 0110
LOL 01 0117
LOL 00 0117
NOP
LOL 01 010f
LOL 01 0111
LOL 01 0113
LOL 01 0114
LOL 01 0115
LOL 01 0117
LOL 00 0117
NOP
LOL 00 0111
LOL 01 0112
LOL 01 0117
LOL 00 0117
NOP
LOL 00 010F
LOL 00 0110
LOL 00 0111
LOL 00 0112
LOL 00 0113
LOL 00 0114
LOL 00 0115
LOL 00 0116
LOL 01 010f
LOL 01 0110
LOL 01 0111
LOL 01 0114
LOL 01 0117
LOL 00 0117
NOP
LOL 00 010F
LOL 00 0110
LOL 00 0111
LOL 00 0112
LOL 00 0113
LOL 00 0114
LOL 00 0115
LOL 00 0116
LOL 01 010f
LOL 01 0110
LOL 01 0112
LOL 01 0113
LOL 01 0117
LOL 00 0117
NOP
LOL 00 0112
LOL 01 0117
LOL 00 0117
NOP
LOL 00 010F
LOL 00 0110
LOL 00 0111
LOL 00 0112
LOL 00 0113
LOL 00 0114
LOL 00 0115
LOL 00 0116
LOL 01 0110
LOL 01 0115
LOL 01 0117
LOL 00 0117
HLT

Binary file not shown.

@ -0,0 +1,57 @@
LOL 1c 011f
LOL 03 0120
LOL 00 0121
LOL 01 0119
LOL 00 0118
LOL 01 0117
LOA 011f 0118
LOL 00 0117
LOL 00 0119
LOL 00 0118
LOL 2f 0122
LOL 00 0118
LOL 01 0117
LOA 0122 0118
LOL 00 0117
LOL 00 0119
LOL 00 0118
LOL 01 0119
LOL 00 0118
LOL 01 0117
LOA 0120 0118
LOL 00 0117
LOL 00 0119
LOL 00 0118
LOL 20 0123
LOL 7e 0124
LOL 3d 0125
LOL 20 0126
LOL 00 0118
LOL 01 0117
LOA 0123 0118
LOA 0124 0118
LOA 0125 0118
LOA 0126 0118
LOL 00 0117
LOL 00 0119
LOL 00 0118
LOL 00 00F2
JML 00b6
SAA 011f 0120
STA 011f
LOL 01 00F0
AAA 0121 00F0
STA 0121
JGT 00a2 011f 00f2
LOL 01 0119
LOL 00 0118
LOL 01 0117
LOA 0121 0118
LOL 00 0117
LOL 00 0119
LOL 00 0118
LOL 01 0116
LOL 01 0117
LOL 00 0116
LOL 00 0117
HLT

Binary file not shown.

@ -0,0 +1,29 @@
NOP
NOP
LOL 01 00ff
LOL 01 0100
NOP
LOL 01 010f
LOL 01 0115
LOL 01 0116
LOL 01 0117
LOL 00 0117
NOP
JEA 00ff 0100 002a
JML 002e
LOL 01 0106
NOP
JEA 010f 0115 0039
JML 003d
LOL 01 0110
LOL 01 0117
LOL 00 0117
NOP
LOA 00ff 0114
LOL 00 00ff
LOL 01 0117
LOL 00 0117
NOP
DBG
DBG
HLT

Binary file not shown.

@ -0,0 +1,94 @@
#the closest thing to writing raw ASM
import re, sys
code = open(sys.argv[1]).read()
outhex = ""
def writeHex(str):
global outhex
#print(f"0x{str}")
outhex += str
count = 1
for i in re.split("\n| ",code):
match i:
case "NOP":
writeHex("00")
case "INC":
writeHex("01")
case "IRA":
writeHex("02")
case "IRX":
writeHex("03")
case "IRY":
writeHex("04")
case "DNC":
writeHex("05")
case "DCA":
writeHex("06")
case "DCX":
writeHex("07")
case "DCY":
writeHex("07")
case "JEA":
writeHex("10")
case "JER":
writeHex("11")
case "JNA":
writeHex("12")
case "JNR":
writeHex("13")
case "JIS":
writeHex("14")
case "JGT":
writeHex("15")
case "JLT":
writeHex("16")
case "JML":
writeHex("1A")
case "JMA":
writeHex("1B")
case "LXA":
writeHex("20")
case "LXL":
writeHex("21")
case "LYA":
writeHex("22")
case "LYL":
writeHex("23")
case "LAA":
writeHex("24")
case "LAL":
writeHex("25")
case "LOA":
writeHex("26")
case "LOL":
writeHex("27")
case "STX":
writeHex("2A")
case "STY":
writeHex("2B")
case "STA":
writeHex("2C")
case "AAA":
writeHex("42")
case "SAA":
writeHex("47")
case "DBG":
writeHex("FF")
case "HLT":
writeHex("FC")
case other:
if len(i) == 4: #assume memory address
writeHex(f"{i[0]+i[1]}")
writeHex(f"{i[2]+i[3]}")
elif len(i) == 2:
writeHex(f"{i}")
#else:
# writeHex("00")
count+=1
#print(outhex)
with open(sys.argv[2], "wb") as f:
f.write(bytes.fromhex(outhex))

@ -0,0 +1,204 @@
use std::process;
#[derive(Default)]
struct CPUFlags {
overflow: bool,
sub: bool,
}
pub struct CPU {
prgmem: [u8; 0xFFFF + 1],
memory: [u8; 0xFFFF + 1],
prc: u16,
acc: u8,
irx: u8,
iry: u8,
pub is_on: bool,
flags: CPUFlags,
}
impl CPU {
//FIXME: pass in debug info here
pub fn from_prg_vec(program: Vec<u8>) -> Self {
let mut prgmem = [0; 0xFFFF + 1];
for (idx, ele) in program.iter().enumerate() {
prgmem[idx] = *ele;
}
CPU {
prgmem: prgmem,
memory: [0; 0xFFFF + 1],
prc: 0,
acc: 0,
irx: 0,
iry: 0,
is_on: true,
flags: CPUFlags::default(),
}
}
fn get_next_8bit_value(&mut self) -> u8 {
self.prgmem[{
self.prc += 1;
self.prc
} as usize]
}
fn get_next_16bit_value(&mut self) -> u16 {
256 * self.prgmem[{
self.prc += 1;
self.prc
} as usize] as u16
+ self.prgmem[{
self.prc += 1;
self.prc
} as usize] as u16
}
fn write_to_serial(&mut self) {
// FIXME: make serial offset configurable
if self.memory[0x010F + 8] > 0 {
let mut charcode = 0;
// FIXME: make this less jank. bit manip maybe?
if self.memory[0x010F] > 0 {
charcode += 64;
}
if self.memory[0x0110] > 0 {
charcode += 32;
}
if self.memory[0x0111] > 0 {
charcode += 16;
}
if self.memory[0x0112] > 0 {
charcode += 8;
}
if self.memory[0x0113] > 0 {
charcode += 4;
}
if self.memory[0x0114] > 0 {
charcode += 2;
}
if self.memory[0x0115] > 0 {
charcode += 1;
}
if self.memory[0x0118] > 0 {
charcode = self.memory[0x0118];
}
if charcode == 0 && self.memory[0x0116] == 0 {
return;
}
if self.memory[0x0119] == 0 {
print!("{}", char::from_u32(charcode.into()).unwrap());
} else {
print!("{}", charcode)
}
if self.memory[0x0116] > 0 {
println!("")
}
}
}
// NOTE: most opcode implementations are translated from C, in all their janky glory
pub fn step(&mut self) {
let inst = self.prgmem[self.prc as usize];
match inst {
0x00 => {}
0x01 => self.memory[self.get_next_16bit_value() as usize] += 1,
0x02 => self.acc += 1,
0x03 => self.irx += 1,
0x04 => self.iry += 1,
0x05 => self.memory[self.get_next_16bit_value() as usize] -= 1,
0x06 => self.acc -= 1,
0x07 => self.irx -= 1,
0x08 => self.iry -= 1,
0x10 => {
let new_prc = self.get_next_16bit_value();
let addr1 = self.get_next_16bit_value() as usize;
let addr2 = self.get_next_16bit_value() as usize;
if self.memory[addr1] == self.memory[addr2] {
self.prc = new_prc - 1
}
}
0x12 => {
let new_prc = self.get_next_16bit_value();
let addr1 = self.get_next_16bit_value() as usize;
let addr2 = self.get_next_16bit_value() as usize;
if self.memory[addr1] != self.memory[addr2] {
self.prc = new_prc - 1
}
}
0x14 => {
// JIS; Jump If SUB (😳)
let new_prc = self.get_next_16bit_value();
if self.flags.sub {
self.flags.sub = false;
self.prc = new_prc - 1;
}
}
0x15 => {
//JGT; Jump If Greater Than
let new_prc = self.get_next_16bit_value();
let addr1 = self.get_next_16bit_value() as usize;
let addr2 = self.get_next_16bit_value() as usize;
if self.memory[addr1] > self.memory[addr2] {
self.prc = new_prc - 1
}
}
0x16 => {
//JGT; Jump If Less Than
let new_prc = self.get_next_16bit_value();
let addr1 = self.get_next_16bit_value() as usize;
let addr2 = self.get_next_16bit_value() as usize;
if self.memory[addr1] < self.memory[addr2] {
self.prc = new_prc - 1
}
}
0x1A => {
let new_prc = self.get_next_16bit_value();
self.prc = new_prc - 1
}
0x20 => self.irx = self.memory[self.get_next_16bit_value() as usize],
0x23 => self.iry = self.memory[self.get_next_16bit_value() as usize],
0x26 => {
let addr1 = self.get_next_16bit_value() as usize;
let addr2 = self.get_next_16bit_value() as usize;
self.memory[addr2] = self.memory[addr1]
}
0x27 => self.memory[self.get_next_16bit_value() as usize] = self.get_next_8bit_value(),
0x2B => self.memory[self.get_next_16bit_value() as usize] = self.iry,
0x2C => self.memory[self.get_next_16bit_value() as usize] = self.acc,
0x42 => {
// ADD absolute
let addr1 = self.get_next_16bit_value() as usize;
let addr2 = self.get_next_16bit_value() as usize;
self.acc = self.memory[addr2] + self.memory[addr1]
}
0x47 => {
// SUB absolute
let addr1 = self.get_next_16bit_value() as usize;
let addr2 = self.get_next_16bit_value() as usize;
let val1: i16 = self.memory[addr1].into();
let val2: i16 = self.memory[addr2].into();
let tmp_val = val1 - val2;
if tmp_val < 0 {
self.flags.sub = true
}
if tmp_val < -255 || tmp_val > 255 {
self.flags.overflow = true
}
self.acc = tmp_val as u8;
}
0x50 => todo!(), // FIXME: wtf does ~(irx & iry) mean
0xFC => self.is_on = false,
0xFF => {}
_ => {
eprintln!("Opcode 0x{:x} not implemented!", inst);
process::exit(1);
}
}
self.prc += 1;
// FIXME: serial io peripheral should be optional
self.write_to_serial();
}
}

@ -0,0 +1,41 @@
use std::{fs::File, io::Read, process};
use clap::Parser;
mod cpu;
use cpu::CPU;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Name of the compiled LRIS program to run
filename: String,
// Enables showing debug information with $FF
#[arg(short, long, default_value_t = true)]
debug: bool,
}
fn main() {
let cli = Args::parse();
let filename = &cli.filename;
let mut file = File::open(filename).unwrap_or_else(|_| {
eprintln!("err: file `{}` doesn't exist", filename);
process::exit(1);
});
let mut buffer = vec![];
file.read_to_end(&mut buffer).unwrap_or_else(|_| {
eprintln!("err: failed to read file `{}`", filename);
process::exit(1);
});
let mut cpu = CPU::from_prg_vec(buffer);
while cpu.is_on {
cpu.step();
}
}
Loading…
Cancel
Save