graphics, strcmp, basic shell, wallpaper

This commit is contained in:
Sarah Jamie Lewis 2021-11-12 01:32:30 -08:00
parent 01cc63c7f1
commit 2947f12356
13 changed files with 794 additions and 73 deletions

251
Cargo.lock generated
View File

@ -8,6 +8,12 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "adler32"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]]
name = "aho-corasick"
version = "0.7.18"
@ -78,6 +84,18 @@ version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "bytemuck"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72957246c41db82b8ef88a5486143830adeb8227ef9837740bdec67724cf2c5b"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.71"
@ -140,6 +158,12 @@ dependencies = [
"cc",
]
[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "crc32fast"
version = "1.2.1"
@ -149,12 +173,72 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"cfg-if 1.0.0",
"lazy_static",
]
[[package]]
name = "deflate"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
dependencies = [
"adler32",
"byteorder",
]
[[package]]
name = "downcast-rs"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "encoding_rs"
version = "0.8.29"
@ -198,7 +282,7 @@ dependencies = [
"cfg-if 1.0.0",
"crc32fast",
"libc",
"miniz_oxide",
"miniz_oxide 0.4.4",
]
[[package]]
@ -218,6 +302,16 @@ dependencies = [
"wasi",
]
[[package]]
name = "gif"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b"
dependencies = [
"color_quant",
"weezl",
]
[[package]]
name = "glob"
version = "0.3.0"
@ -239,6 +333,34 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "image"
version = "0.23.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"gif",
"jpeg-decoder",
"num-iter",
"num-rational",
"num-traits",
"png",
"scoped_threadpool",
"tiff",
]
[[package]]
name = "jpeg-decoder"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
dependencies = [
"rayon",
]
[[package]]
name = "js-sys"
version = "0.3.55"
@ -325,6 +447,15 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
dependencies = [
"adler32",
]
[[package]]
name = "miniz_oxide"
version = "0.4.4"
@ -369,6 +500,57 @@ dependencies = [
"version_check",
]
[[package]]
name = "num-integer"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "once_cell"
version = "1.8.0"
@ -402,6 +584,18 @@ version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f"
[[package]]
name = "png"
version = "0.16.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
dependencies = [
"bitflags",
"crc32fast",
"deflate",
"miniz_oxide 0.3.7",
]
[[package]]
name = "ppv-lite86"
version = "0.2.15"
@ -475,6 +669,31 @@ dependencies = [
"libc",
]
[[package]]
name = "rayon"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
dependencies = [
"autocfg",
"crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"lazy_static",
"num_cpus",
]
[[package]]
name = "redox_syscall"
version = "0.2.10"
@ -516,6 +735,18 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "scoped_threadpool"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sdl2"
version = "0.34.5"
@ -555,6 +786,7 @@ name = "side"
version = "0.1.0"
dependencies = [
"font8x8",
"image",
"minifb",
]
@ -624,6 +856,17 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "tiff"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
dependencies = [
"jpeg-decoder",
"miniz_oxide 0.4.4",
"weezl",
]
[[package]]
name = "unicode-width"
version = "0.1.9"
@ -805,6 +1048,12 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "weezl"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e"
[[package]]
name = "which"
version = "3.1.1"

View File

@ -7,4 +7,5 @@ edition = "2018"
[dependencies]
minifb = "0.19.3"
font8x8 = "0.3.1"
font8x8 = "0.3.1"
image = "0.23.14"

View File

@ -62,12 +62,12 @@ The below represents some ideas for projects to tackle within Boo OS.
- [ ] Heap Design
- [ ] Implement Helper Functions `alloc` and `free`
- [ ] Memory Safety
- [ ] Keyboard Input
- [ ] Designing Input Interaction (poll v.s. interrupts)
- [ ] Create a Console Shell to Interact with the System
- [ ] At first this shell will be limited to pre-programmed commands
- [X] Keyboard Input
- [X] Designing Input Interaction (Register Based)
- [X] Create a Console Shell to Interact with the System
- [X] At first this shell will be limited to pre-programmed commands
- [ ] But, it should quickly all the construction of new commands from old ones
- [ ] Finally, the shell should facilitate saving and loading of images
- [ ] Finally, the shell should facilitate saving and loading of disk-images
- [ ] Write a Bootstrapped Assembler Application in Boo Bytecode Assembly
@ -119,9 +119,6 @@ Prefix 0x1#,0x2#,0x3# are given to dynamin register based commands
- 0x6n ISTORE(n)
- 0x7n x LDSTORE Load the Address Stored in n into reg(x)
- 0x8n x Transfer R(n) to R(x)
- 0x9n Shift
## Arithmetic
@ -134,6 +131,14 @@ Prefix 0xa# is given to arithmetic functions
- 0xa5 SHIFT (R2 >> R3 -> RAX)
- 0xa6 AND (R2 & R3 -> RAX)
# Buffers
Buffers are declared in Boo Assembler as `data buffer <label> <length>`
- 0xB0 ADDR (`bclear LABEL`)- Clear the Buffer at Address ADDR.
- 0xB(N) ADDR (`bappend R(X) LABEL`)- Append the word in R(N) to the Buffer at Address ADDR. Safely handles length.
Sets `$4` to `0` on success and `1` on failure.
# Stack
@ -142,6 +147,8 @@ Prefix 0xc# allows call stack manipulation. The machine denotes 64 memory addres
- 0xc0 RET
- 0xc1 PUSH Call Stack
# Jumps and Branches (0x5#)
- 0xE0 JMP $Addr - Unconditional jump to $Addr

BIN
booos-small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
booos.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -287,4 +287,6 @@ label char_delete:
$00000000
$00000000
data ascii HEX_TABLE 0123456789ABCDEF
data ascii HEX_TABLE 0123456789ABCDEF
data ascii KEYCODES 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()-=+_{}[];':"<>,.?/`~|\

View File

@ -2,7 +2,7 @@
label vbuf:
@ $4B000:
$5B000 ; Set Instruction Pointer to $5B000
$CB000 ; Set Instruction Pointer to $5B000
label RAX:
$0000000 ; RAX
$0000000 ; R2 - Temp Scratch
@ -14,52 +14,112 @@
$0000000 ; R8 - ARG 5
$0000000 ; RX
$0000000 ; RY
label R(B):
$0000000 ; RVBUF (RY * 640) + RX
label R(c):
$0000001 ; Ghost Post
@ $4B040:
label CycleCount:
$0000000; Cycles
label KeyPressedState:
$0000000; The ID of a Key Being Pressed (If Any)
@ $4B0C0:
import display.asm
import charset.asm
import strings.asm
import util.asm
import display.asm ; setpos
import charset.asm ; charset + hex strings
import strings.asm ; draw_char, draw_string
import util.asm ; print_addr
import graphics.asm; draw_vline, draw_hline, draw_rect
; Common Strings
data ascii boo_os_version Boo OS v0.0.1
data ascii HelloWorld Welcome to Boo OS Running on Boo Byte Code!
data ascii Welcome !@#$%^&*()_+=-0987654321
data ascii Introspection We Can Now Do Introspection:
data ascii label_rax RAX:
data ascii label_rip RIP:
data ascii label_cycles Instruction Count:
data ascii label_keypress Current Key Pressed:
data image boo_os.png booos.png
data image boo_os_small.png booos-small.png
data image wallpaper.png wallpaper.png
data ascii quit_label QUIT
data buffer command_line_input 256
meta
; strcmp compares 2 strings in a byte-by-byte manner, incrementing ptrs as it goes. Returns 1 if both bytes
; point to 0. Returns 0 (fail) if it encounters 2 different bytes
; clobbers $1 $2 $4 $5
label strcmp:
label strcmp_loop:
ldstore $4 $1
ldstore $5 $2
jeq +3 ; if either of these differ then return 0 to indicate these strings don't match
loadi $1 0
ret
loadi $2 0
jneq +3 ; if both are 0 then we have reached the end of the string
loadi $1 1
ret
inc $4
inc $5
jmp strcmp_loop
label handle_keypress:
; Check for Backspace
loadi $1 $7F
tx $2 $4
jneq +3
bdelete $4 command_line_input
ret
; Check for Return
loadi $1 $0A
tx $2 $4
jneq +8
loadi $4 @command_line_input
loadi $5 quit_label
call strcmp
loadi $2 1
jneq +2 ; if the command is QUIT, then hlt the machine!! A shell is born
hlt
ret
bappend $4 command_line_input
ret
; Kernel Begins
@ $5B000:
loadi $9 1;
loadi $A 1;
call set_pos
@ $CB000:
loadi $4 HelloWorld
loadi $9 $0; 640-64
loadi $A $0; 480-64
call set_pos
loadi $4 wallpaper.png
call draw_image
loadi $4 $0
loadi $5 $0
loadi $6 $280
loadi $7 $10
loadi $8 $222222
call draw_filled_rect
loadi $9 $5;
loadi $A $5;
call set_pos
loadi $4 boo_os_version
call draw_string;
loadi $9 1;
loadi $A 10;
loadi $9 $1A0;
loadi $A $5;
call set_pos
loadi $4 Welcome
call draw_string;
; OK! Time for some self referencing!!
loadi $9 1;
loadi $A 20;
call set_pos
loadi $4 Introspection
call draw_string;
loadi $9 1;
loadi $A 30;
call set_pos
loadi $4 label_cycles
call draw_string;
@ -67,5 +127,31 @@ data ascii label_cycles Instruction Count:
loadi $2 $40
add $2 $4 $4
call print_addr
loadi $9 1;
loadi $A 20;
call set_pos
loadi $4 HelloWorld
call draw_string;
loadi $1 0
load $2 KeyPressedState
store $1 KeyPressedState
jeq +3
tx $4 $2
call handle_keypress
loadi $9 1;
loadi $A 60;
call set_pos
loadi $4 @command_line_input
call draw_string;
updsp
jmp $5B000;
clr
jmp $CB000;

153
graphics.asm Normal file
View File

@ -0,0 +1,153 @@
; $4: y_origin
; $5 x_origin
; $6 x_target
; $7 color
label draw_hline:
tx $1 $5 ; set i = x_origin
tx $3 $6 ;
tx $A $4 ; set screen y pointer to y_origin
label draw_hline_pixels:
tx $9 $1 ; set screen x pointer to x_origin
call set_pos
rstore $7 $B
inc $1
tx $2 $3
jneq +2
ret
jmp draw_hline_pixels
; $4: x_origin
; $5 y_origin
; $6 y_target
; $7 color
label draw_vline:
tx $1 $5 ; set i = y_origin
tx $3 $6 ;
tx $9 $4 ; set screen x pointer to x_origin
label draw_vline_pixels:
tx $A $1 ; set screen x pointer to x_origin
call set_pos
rstore $7 $B
inc $1
tx $2 $3
jneq +2
ret
jmp draw_vline_pixels
; $4: x_origin
; $5 y_origin
; $6 width
; $7 height
; $8 color
label _draw_filled_rect_cache:
nop ; xo
nop ; yo
nop ; width
nop ; height
nop ; color
nop ; counter
label draw_filled_rect:
store $4 _draw_filled_rect_cache
store $5 _draw_filled_rect_cache+1
store $5 _draw_filled_rect_cache+5
store $6 _draw_filled_rect_cache+2
store $7 _draw_filled_rect_cache+3
store $8 _draw_filled_rect_cache+4
label draw_filled_rect_inner:
load $4 _draw_filled_rect_cache+5 ;yo
load $5 _draw_filled_rect_cache; xo
load $6 _draw_filled_rect_cache+2; width
add $6 $5 $6 ; width + xo = x_target
load $7 _draw_filled_rect_cache+4 ; color
call draw_hline
tx $1 $4
load $2 _draw_filled_rect_cache+1 ; load y_origin into $1
load $3 _draw_filled_rect_cache+3 ; load height in $2
add $2 $3 $2
jeq +4
inc $4
store $4 _draw_filled_rect_cache+5
jmp draw_filled_rect_inner
ret
; $4: x_origin
; $5 y_origin
; $6 width
; $7 height
; $8 color
label _draw_rect_cache:
nop ; xo
nop ; yo
nop ; width
nop ; height
nop ; color
label draw_rect:
store $4 _draw_rect_cache
store $5 _draw_rect_cache+1
store $6 _draw_rect_cache+2
store $7 _draw_rect_cache+3
store $8 _draw_rect_cache+4
load $4 _draw_rect_cache ;xo
load $5 _draw_rect_cache+1; yo
load $6 _draw_rect_cache+3; height
add $6 $5 $6 ; height + yo = y_target
load $7 _draw_rect_cache+4 ; color
call draw_vline
load $4 _draw_rect_cache ;xo
load $8 _draw_rect_cache+2 ; width
add $8 $4 $4; xo + width = xo
load $5 _draw_rect_cache+1; yo
load $6 _draw_rect_cache+3; height
add $6 $5 $6 ; height + yo = y_target
load $7 _draw_rect_cache+4 ; color
call draw_vline
load $4 _draw_rect_cache+1 ;yo
load $5 _draw_rect_cache; xo
load $6 _draw_rect_cache+2; width
add $6 $5 $6 ; width + xo = x_target
load $7 _draw_rect_cache+4 ; color
call draw_hline
load $4 _draw_rect_cache+1 ;yo
load $8 _draw_rect_cache+3 ; width
add $8 $4 $4; yo + height = yo
load $5 _draw_rect_cache; xo
load $6 _draw_rect_cache+2; width
add $6 $5 $6 ; width + xo = x_target
load $7 _draw_rect_cache+4 ; color
call draw_hline
ret
label draw_image:
ldstore $4 $7 ; width
inc $4
ldstore $4 $8 ; height
inc $4
loadi $3 $0
loadi $6 $0
label draw_pixels:
ldstore $4 $5
rstore $5 $B
inc $B; Increment VBuf Pointer
inc $4
inc $3
tx $2 $3
tx $1 $7
jneq +10
loadi 3 $280
sub $3 $7 $3
add $3 $B $B ; Move VBUF
loadi 3 $0
inc $6
tx $1 $8
tx $2 $6
jneq +2
ret
jmp draw_pixels

View File

@ -1,9 +1,12 @@
use crate::{Machine, MEMORY};
use std::collections::HashMap;
use std::fs::read_to_string;
use image::png::PngDecoder;
use image::io::Reader;
use image::GenericImageView;
pub struct ImageAssembler {
memory: [u32; MEMORY],
memory: Vec<u32>,
ptr: usize,
labels: HashMap<String, usize>,
}
@ -11,7 +14,7 @@ pub struct ImageAssembler {
impl ImageAssembler {
pub fn new() -> ImageAssembler {
ImageAssembler {
memory: [0; MEMORY],
memory: vec![0; MEMORY],
ptr: 0,
labels: HashMap::new(),
}
@ -29,11 +32,18 @@ impl ImageAssembler {
for line in lines {
let parts = line.split_once(';');
let command = match parts {
Some((command, _comment)) => command.trim(),
let mut command = match parts {
Some((command, _comment)) => {
command.trim()
},
_ => line.trim(),
};
if command.starts_with("data") {
command = line.trim();
}
let command_parts = command.split_whitespace().collect::<Vec<&str>>();
if command_parts.is_empty() {
@ -42,6 +52,9 @@ impl ImageAssembler {
if command_parts.len() == 1 {
match command_parts[0] {
"meta" => {
println!("Headers + Imports Stop at {:x}", self.ptr);
}
"nop" => {
self.memory[self.ptr] = 0x00000000;
self.ptr += 1;
@ -57,18 +70,8 @@ impl ImageAssembler {
self.ptr += 1;
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
}
"inc1" => {
self.memory[self.ptr] = 0x41000000;
self.ptr += 1;
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
}
"inc2" => {
self.memory[self.ptr] = 0x42000000;
self.ptr += 1;
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
}
"inc3" => {
self.memory[self.ptr] = 0x43000000;
"clr" => {
self.memory[self.ptr] = 0x04000000;
self.ptr += 1;
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
}
@ -113,6 +116,12 @@ impl ImageAssembler {
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
self.ptr += 1;
}
"jeq" => {
let addr = self.parse_addr(command_parts[1]);
self.memory[self.ptr] = 0xE1000000 + addr;
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
self.ptr += 1;
}
"jneq" => {
let addr = self.parse_addr(command_parts[1]);
self.memory[self.ptr] = 0xE2000000 + addr;
@ -187,8 +196,24 @@ impl ImageAssembler {
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
self.ptr += 1;
}
"bappend" => {
let target_reg = self.parse_addr(command_parts[1]);
let inst = (0xB0 + target_reg) << 24;
let reg = self.parse_addr(command_parts[2]);
self.memory[self.ptr] = inst + reg;
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
self.ptr += 1;
}
"bdelete" => {
let target_reg = self.parse_addr(command_parts[1]);
let inst = (0x03 + target_reg) << 24;
let reg = self.parse_addr(command_parts[2]);
self.memory[self.ptr] = inst + reg;
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
self.ptr += 1;
}
_ => {
panic!("unknown opcpde {}", command_parts[0])
panic!("unknown opcopde {}", command_parts[0])
}
}
} else if command_parts.len() == 4 && command_parts[0] != "data" {
@ -249,6 +274,45 @@ impl ImageAssembler {
}
self.memory[self.ptr] = 0x00;
self.ptr += 1;
},
"image" => {
if command_parts.len() !=4 {
panic!("data buffer label len")
}
self.labels
.insert(command_parts[2].replace(":", ""), self.ptr);
let img = Reader::open(command_parts[3]).unwrap().decode().unwrap();
self.memory[self.ptr] = img.width(); self.ptr+=1;
self.memory[self.ptr] = img.height(); self.ptr+=1;
for h in 0..img.height() {
for w in 0..img.width() {
let pixel = img.get_pixel(w,h).0;
let a = (pixel[3] as u32) << 24;
let r = (pixel[0] as u32) << 16;
let g = (pixel[1] as u32) << 8;
let b = (pixel[2] as u32);
self.memory[self.ptr] = a+r+g+b ; self.ptr+=1;
}
}
self.memory[self.ptr] = 0x00;
self.ptr+=1;
}
"buffer" => {
if command_parts.len() !=4 {
panic!("data buffer label len")
}
self.labels
.insert(command_parts[2].replace(":", ""), self.ptr);
let len = command_parts[3].parse().unwrap_or_default();
self.memory[self.ptr] = len;
self.ptr+=1;
self.memory[self.ptr] = 0x00;
self.ptr+=1;
// Pad with 0's
for i in 0..=len {
self.memory[self.ptr] = 0x00;
self.ptr+=1
}
}
_ => {
panic!("unknown type {}", command_parts[1])
@ -263,18 +327,63 @@ impl ImageAssembler {
}
fn parse_addr(&self, input: &str) -> u32 {
if input.starts_with('@') {
match self.labels.get(input.replace("@", "").as_str()){
Some(addr) => {
return addr.clone() as u32 +2;
}
None =>{
}
}
}
if input.starts_with('+') {
match usize::from_str_radix(input.replace("+", "").as_str(),10) {
Ok(offeset) => {
return (self.ptr + offeset) as u32;
}
_ => {
panic!("Not a Relative Address {:?}", input)
}
}
}
match u32::from_str_radix(input.replace("$", "").replace(":", "").as_str(), 16) {
Ok(addr) => {
return addr;
}
_ => match self.labels.get(input) {
Some(addr) => {
return addr.clone() as u32;
_ => {
match input.split_once("+") {
Some((input, offset)) => {
match self.labels.get(input) {
Some(addr) => {
match usize::from_str_radix(offset.replace("+", "").as_str(), 10) {
Ok(offset) => {
return addr.clone() as u32 + offset as u32;
}
_ => {
panic!("Not a Hex Encoded Address {:?}", input)
}
}
}
_ => {
panic!("Not a Hex Encoded Address {:?}", input)
}
}
},
_ => {
match self.labels.get(input) {
Some(addr) => {
return addr.clone() as u32;
}
_ => {
panic!("Not a Hex Encoded Address {:?}", input)
}
}
}
}
_ => {
panic!("Not a Hex Encoded Address {:?}", input)
}
},
}
}
}
}

View File

@ -4,29 +4,33 @@ pub const VRAM: usize = 640 * 480;
pub const REGISTER_PAGE: usize = VRAM;
pub const INPUT_PAGE: usize = VRAM + 64;
pub const OFFSET: usize = INPUT_PAGE;
pub const MEM_SIZE: usize = 65535;
pub const MEM_SIZE: usize = 0x0FFFFF - OFFSET;
pub const MEMORY: usize = OFFSET + MEM_SIZE;
pub struct Machine {
pub memory: [u32; MEMORY],
pub memory: Vec<u32>,
}
impl Machine {
pub fn new() -> Machine {
let mut memory = [0; MEMORY];
let mut memory = vec![0; MEMORY];
memory[REGISTER_PAGE] = 0x00;
Machine { memory }
}
pub fn load(&mut self, memory: [u32; MEMORY]) {
pub fn set_keypress(&mut self, char: u32) {
self.memory[INPUT_PAGE+1] = char
}
pub fn load(&mut self, memory: Vec<u32>) {
self.memory = memory;
self.memory[INPUT_PAGE] = 0x00;
}
pub fn dump(&self) -> [u32; MEMORY] {
return self.memory;
pub fn dump(&self) -> Vec<u32> {
return self.memory.clone();
}
pub fn cycle(&mut self) {
@ -69,6 +73,20 @@ impl Machine {
panic!("HLT");
}
0x04 => {
for i in 0..VRAM{
self.memory[i] = 0x00;
}
self.memory[REGISTER_PAGE + 63] = 0x00;
}
0x07 => {
let addr = (instruction & 0x00FFFFFF) as usize;
let ptr = (self.memory[addr+1]) as usize;
if ptr > 0 {
self.memory[addr+1]-=1;
self.memory[addr+2+ptr-1] = 0x00;
}
}
op => {
unimplemented!("0x0 Meta Instruction {}", op)
}
@ -180,6 +198,18 @@ impl Machine {
}
}
}
0x0B => {
let input_reg = ((instruction) >> 24 & 0x0F) as usize;
let addr = (instruction & 0x00FFFFFF) as usize;
if input_reg != 0 {
let max_len = (self.memory[addr]) as usize;
let ptr = (self.memory[addr+1]) as usize;
if ptr < max_len {
self.memory[addr+1]+=1;
self.memory[addr+2+ptr] = self.memory[REGISTER_PAGE + input_reg];
}
}
}
0x0C => {
match instruction >> 24 {
// RET (Pops call stack and JMPs)
@ -200,6 +230,9 @@ impl Machine {
unimplemented!("0x0 Call Strack Instruction {}", op)
}
}
}
0x0D => {
}
0x0E => {
match instruction >> 24 {
@ -208,6 +241,13 @@ impl Machine {
let mem = instruction & 0x00FFFFFF;
self.memory[REGISTER_PAGE] = mem - 1;
}
0xE1 => {
// JEQ ADDR if R(1) != R(2)
if self.memory[REGISTER_PAGE + 1] == self.memory[REGISTER_PAGE + 2] {
let mem = instruction & 0x00FFFFFF;
self.memory[REGISTER_PAGE] = mem - 1;
}
}
0xE2 => {
// JEQ ADDR if R(1) != R(2)
if self.memory[REGISTER_PAGE + 1] != self.memory[REGISTER_PAGE + 2] {

View File

@ -1,14 +1,15 @@
extern crate minifb;
use minifb::{Key, Scale, Window, WindowOptions};
use minifb::{Key, Scale, Window, WindowOptions, KeyRepeat};
use side::assembler::ImageAssembler;
use side::{Machine, REGISTER_PAGE};
use std::env;
use std::time::Duration;
//use font8x8::{BASIC_FONTS, UnicodeFonts};
const WIDTH: usize = 640;
const HEIGHT: usize = 360;
const HEIGHT: usize = 480;
fn main() {
// for font in BASIC_FONTS.iter().skip(0x20) {
@ -36,19 +37,86 @@ fn main() {
let mut opts = WindowOptions::default();
opts.scale = Scale::X1;
let mut window = Window::new("Test - ESC to exit", WIDTH, HEIGHT, opts).unwrap_or_else(|e| {
panic!("{}", e);
});
while window.is_open() && !window.is_key_down(Key::Escape) {
machine.cycle();
if machine.memory[REGISTER_PAGE + 63] == 0x01 {
// We unwrap here as we want this code to exit if it fails. Real applications may want to handle this in a different way
window
.update_with_buffer(&machine.memory, WIDTH, HEIGHT)
.unwrap();
machine.memory[REGISTER_PAGE + 63] = 0x00;
match window.get_keys_pressed(KeyRepeat::No) {
None => {}
Some(keys) => {
match keys.get(0) {
None => {
//machine.set_keypress(0)
}
Some(key) => {
match key {
Key::Key0 => {machine.set_keypress('0' as u32)}
Key::Key1 => {machine.set_keypress('1' as u32)}
Key::Key2 => {machine.set_keypress('2' as u32)}
Key::Key3 =>{machine.set_keypress('3' as u32)}
Key::Key4 => {machine.set_keypress('4' as u32)}
Key::Key5 => {machine.set_keypress('5' as u32)}
Key::Key6 => {machine.set_keypress('6' as u32)}
Key::Key7 => {machine.set_keypress('7' as u32)}
Key::Key8 => {machine.set_keypress('8' as u32)}
Key::Key9 => {machine.set_keypress('9' as u32)}
Key::A => {machine.set_keypress('A' as u32)}
Key::B => {machine.set_keypress('B' as u32)}
Key::C => {machine.set_keypress('C' as u32)}
Key::D => {machine.set_keypress('D' as u32)}
Key::E => {machine.set_keypress('E' as u32)}
Key::F => {machine.set_keypress('F' as u32)}
Key::G => {machine.set_keypress('G' as u32)}
Key::H => {machine.set_keypress('H' as u32)}
Key::I => {machine.set_keypress('I' as u32)}
Key::J => {machine.set_keypress('J' as u32)}
Key::K => {machine.set_keypress('K' as u32)}
Key::L => {machine.set_keypress('L' as u32)}
Key::M => {machine.set_keypress('M' as u32)}
Key::N => {machine.set_keypress('N' as u32)}
Key::O => {machine.set_keypress('O' as u32)}
Key::P => {machine.set_keypress('P' as u32)}
Key::Q => {machine.set_keypress('Q' as u32)}
Key::R => {machine.set_keypress('R' as u32)}
Key::S => {machine.set_keypress('S' as u32)}
Key::T => {machine.set_keypress('T' as u32)}
Key::U => {machine.set_keypress('U' as u32)}
Key::V => {machine.set_keypress('V' as u32)}
Key::W => {machine.set_keypress('W' as u32)}
Key::X => {machine.set_keypress('X' as u32)}
Key::Y => {machine.set_keypress('Y' as u32)}
Key::Z => {machine.set_keypress('Z' as u32)}
Key::Space => {machine.set_keypress(' ' as u32)}
Key::Backspace => {machine.set_keypress(0x7F as u32)}
Key::Enter => {machine.set_keypress(0x0A as u32)}
_=> {
machine.set_keypress('!' as u32)
}
}
}
};
}
};
}
}
}

View File

@ -8,8 +8,13 @@
loadi 6 $FFFFFF
mul 1 6 1;
rstore 1 $B; Transfer RAX to the Address Stored in R11
tx $C $2
loadi $2 0
jeq +2
rstore 1 $B; Transfer RAX to the Address Stored in R11
tx $2 $C
inc $B; Increment VBuf Pointer
inc 2; INC Scratch Pixel
@ -97,6 +102,7 @@
call draw_char_pixels
ret
label _scratch_draw_string:
nop

BIN
wallpaper.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB