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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "adler32"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.7.18" version = "0.7.18"
@ -78,6 +84,18 @@ version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" 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]] [[package]]
name = "cc" name = "cc"
version = "1.0.71" version = "1.0.71"
@ -140,6 +158,12 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]] [[package]]
name = "crc32fast" name = "crc32fast"
version = "1.2.1" version = "1.2.1"
@ -149,12 +173,72 @@ dependencies = [
"cfg-if 1.0.0", "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]] [[package]]
name = "downcast-rs" name = "downcast-rs"
version = "1.2.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]] [[package]]
name = "encoding_rs" name = "encoding_rs"
version = "0.8.29" version = "0.8.29"
@ -198,7 +282,7 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"crc32fast", "crc32fast",
"libc", "libc",
"miniz_oxide", "miniz_oxide 0.4.4",
] ]
[[package]] [[package]]
@ -218,6 +302,16 @@ dependencies = [
"wasi", "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]] [[package]]
name = "glob" name = "glob"
version = "0.3.0" version = "0.3.0"
@ -239,6 +333,34 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" 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]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.55" version = "0.3.55"
@ -325,6 +447,15 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 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]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.4.4" version = "0.4.4"
@ -369,6 +500,57 @@ dependencies = [
"version_check", "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]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.8.0" version = "1.8.0"
@ -402,6 +584,18 @@ version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" 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]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.15" version = "0.2.15"
@ -475,6 +669,31 @@ dependencies = [
"libc", "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]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.10" version = "0.2.10"
@ -516,6 +735,18 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 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]] [[package]]
name = "sdl2" name = "sdl2"
version = "0.34.5" version = "0.34.5"
@ -555,6 +786,7 @@ name = "side"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"font8x8", "font8x8",
"image",
"minifb", "minifb",
] ]
@ -624,6 +856,17 @@ dependencies = [
"unicode-width", "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]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.9" version = "0.1.9"
@ -805,6 +1048,12 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "weezl"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e"
[[package]] [[package]]
name = "which" name = "which"
version = "3.1.1" version = "3.1.1"

View File

@ -7,4 +7,5 @@ edition = "2018"
[dependencies] [dependencies]
minifb = "0.19.3" 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 - [ ] Heap Design
- [ ] Implement Helper Functions `alloc` and `free` - [ ] Implement Helper Functions `alloc` and `free`
- [ ] Memory Safety - [ ] Memory Safety
- [ ] Keyboard Input - [X] Keyboard Input
- [ ] Designing Input Interaction (poll v.s. interrupts) - [X] Designing Input Interaction (Register Based)
- [ ] Create a Console Shell to Interact with the System - [X] Create a Console Shell to Interact with the System
- [ ] At first this shell will be limited to pre-programmed commands - [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 - [ ] 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 - [ ] 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) - 0x6n ISTORE(n)
- 0x7n x LDSTORE Load the Address Stored in n into reg(x) - 0x7n x LDSTORE Load the Address Stored in n into reg(x)
- 0x8n x Transfer R(n) to R(x) - 0x8n x Transfer R(n) to R(x)
- 0x9n Shift
## Arithmetic ## Arithmetic
@ -134,6 +131,14 @@ Prefix 0xa# is given to arithmetic functions
- 0xa5 SHIFT (R2 >> R3 -> RAX) - 0xa5 SHIFT (R2 >> R3 -> RAX)
- 0xa6 AND (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 # Stack
@ -142,6 +147,8 @@ Prefix 0xc# allows call stack manipulation. The machine denotes 64 memory addres
- 0xc0 RET - 0xc0 RET
- 0xc1 PUSH Call Stack - 0xc1 PUSH Call Stack
# Jumps and Branches (0x5#) # Jumps and Branches (0x5#)
- 0xE0 JMP $Addr - Unconditional jump to $Addr - 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
$00000000 $00000000
data ascii HEX_TABLE 0123456789ABCDEF data ascii HEX_TABLE 0123456789ABCDEF
data ascii KEYCODES 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()-=+_{}[];':"<>,.?/`~|\

View File

@ -2,7 +2,7 @@
label vbuf: label vbuf:
@ $4B000: @ $4B000:
$5B000 ; Set Instruction Pointer to $5B000 $CB000 ; Set Instruction Pointer to $5B000
label RAX: label RAX:
$0000000 ; RAX $0000000 ; RAX
$0000000 ; R2 - Temp Scratch $0000000 ; R2 - Temp Scratch
@ -14,52 +14,112 @@
$0000000 ; R8 - ARG 5 $0000000 ; R8 - ARG 5
$0000000 ; RX $0000000 ; RX
$0000000 ; RY $0000000 ; RY
label R(B):
$0000000 ; RVBUF (RY * 640) + RX $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: @ $4B0C0:
import display.asm import display.asm ; setpos
import charset.asm import charset.asm ; charset + hex strings
import strings.asm import strings.asm ; draw_char, draw_string
import util.asm import util.asm ; print_addr
import graphics.asm; draw_vline, draw_hline, draw_rect
; Common Strings ; 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 HelloWorld Welcome to Boo OS Running on Boo Byte Code!
data ascii Welcome !@#$%^&*()_+=-0987654321 data ascii Welcome !@#$%^&*()_+=-0987654321
data ascii Introspection We Can Now Do Introspection: data ascii Introspection We Can Now Do Introspection:
data ascii label_rax RAX: data ascii label_rax RAX:
data ascii label_rip RIP: data ascii label_rip RIP:
data ascii label_cycles Instruction Count: 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 ; Kernel Begins
@ $5B000: @ $CB000:
loadi $9 1;
loadi $A 1;
call set_pos
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; call draw_string;
loadi $9 1; loadi $9 $1A0;
loadi $A 10; loadi $A $5;
call set_pos 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 loadi $4 label_cycles
call draw_string; call draw_string;
@ -67,5 +127,31 @@ data ascii label_cycles Instruction Count:
loadi $2 $40 loadi $2 $40
add $2 $4 $4 add $2 $4 $4
call print_addr 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 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 crate::{Machine, MEMORY};
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::read_to_string; use std::fs::read_to_string;
use image::png::PngDecoder;
use image::io::Reader;
use image::GenericImageView;
pub struct ImageAssembler { pub struct ImageAssembler {
memory: [u32; MEMORY], memory: Vec<u32>,
ptr: usize, ptr: usize,
labels: HashMap<String, usize>, labels: HashMap<String, usize>,
} }
@ -11,7 +14,7 @@ pub struct ImageAssembler {
impl ImageAssembler { impl ImageAssembler {
pub fn new() -> ImageAssembler { pub fn new() -> ImageAssembler {
ImageAssembler { ImageAssembler {
memory: [0; MEMORY], memory: vec![0; MEMORY],
ptr: 0, ptr: 0,
labels: HashMap::new(), labels: HashMap::new(),
} }
@ -29,11 +32,18 @@ impl ImageAssembler {
for line in lines { for line in lines {
let parts = line.split_once(';'); 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(), _ => line.trim(),
}; };
if command.starts_with("data") {
command = line.trim();
}
let command_parts = command.split_whitespace().collect::<Vec<&str>>(); let command_parts = command.split_whitespace().collect::<Vec<&str>>();
if command_parts.is_empty() { if command_parts.is_empty() {
@ -42,6 +52,9 @@ impl ImageAssembler {
if command_parts.len() == 1 { if command_parts.len() == 1 {
match command_parts[0] { match command_parts[0] {
"meta" => {
println!("Headers + Imports Stop at {:x}", self.ptr);
}
"nop" => { "nop" => {
self.memory[self.ptr] = 0x00000000; self.memory[self.ptr] = 0x00000000;
self.ptr += 1; self.ptr += 1;
@ -57,18 +70,8 @@ impl ImageAssembler {
self.ptr += 1; self.ptr += 1;
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
} }
"inc1" => { "clr" => {
self.memory[self.ptr] = 0x41000000; self.memory[self.ptr] = 0x04000000;
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;
self.ptr += 1; self.ptr += 1;
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
} }
@ -113,6 +116,12 @@ impl ImageAssembler {
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
self.ptr += 1; 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" => { "jneq" => {
let addr = self.parse_addr(command_parts[1]); let addr = self.parse_addr(command_parts[1]);
self.memory[self.ptr] = 0xE2000000 + addr; self.memory[self.ptr] = 0xE2000000 + addr;
@ -187,8 +196,24 @@ impl ImageAssembler {
println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]);
self.ptr += 1; 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" { } else if command_parts.len() == 4 && command_parts[0] != "data" {
@ -249,6 +274,45 @@ impl ImageAssembler {
} }
self.memory[self.ptr] = 0x00; self.memory[self.ptr] = 0x00;
self.ptr += 1; 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]) panic!("unknown type {}", command_parts[1])
@ -263,18 +327,63 @@ impl ImageAssembler {
} }
fn parse_addr(&self, input: &str) -> u32 { 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) { match u32::from_str_radix(input.replace("$", "").replace(":", "").as_str(), 16) {
Ok(addr) => { Ok(addr) => {
return addr; return addr;
} }
_ => match self.labels.get(input) { _ => {
Some(addr) => { match input.split_once("+") {
return addr.clone() as u32; 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 REGISTER_PAGE: usize = VRAM;
pub const INPUT_PAGE: usize = VRAM + 64; pub const INPUT_PAGE: usize = VRAM + 64;
pub const OFFSET: usize = INPUT_PAGE; 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 const MEMORY: usize = OFFSET + MEM_SIZE;
pub struct Machine { pub struct Machine {
pub memory: [u32; MEMORY], pub memory: Vec<u32>,
} }
impl Machine { impl Machine {
pub fn new() -> Machine { pub fn new() -> Machine {
let mut memory = [0; MEMORY]; let mut memory = vec![0; MEMORY];
memory[REGISTER_PAGE] = 0x00; memory[REGISTER_PAGE] = 0x00;
Machine { memory } 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 = memory;
self.memory[INPUT_PAGE] = 0x00; self.memory[INPUT_PAGE] = 0x00;
} }
pub fn dump(&self) -> [u32; MEMORY] { pub fn dump(&self) -> Vec<u32> {
return self.memory; return self.memory.clone();
} }
pub fn cycle(&mut self) { pub fn cycle(&mut self) {
@ -69,6 +73,20 @@ impl Machine {
panic!("HLT"); 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 => { op => {
unimplemented!("0x0 Meta Instruction {}", 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 => { 0x0C => {
match instruction >> 24 { match instruction >> 24 {
// RET (Pops call stack and JMPs) // RET (Pops call stack and JMPs)
@ -200,6 +230,9 @@ impl Machine {
unimplemented!("0x0 Call Strack Instruction {}", op) unimplemented!("0x0 Call Strack Instruction {}", op)
} }
} }
}
0x0D => {
} }
0x0E => { 0x0E => {
match instruction >> 24 { match instruction >> 24 {
@ -208,6 +241,13 @@ impl Machine {
let mem = instruction & 0x00FFFFFF; let mem = instruction & 0x00FFFFFF;
self.memory[REGISTER_PAGE] = mem - 1; 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 => { 0xE2 => {
// JEQ ADDR if R(1) != R(2) // JEQ ADDR if R(1) != R(2)
if self.memory[REGISTER_PAGE + 1] != self.memory[REGISTER_PAGE + 2] { if self.memory[REGISTER_PAGE + 1] != self.memory[REGISTER_PAGE + 2] {

View File

@ -1,14 +1,15 @@
extern crate minifb; extern crate minifb;
use minifb::{Key, Scale, Window, WindowOptions}; use minifb::{Key, Scale, Window, WindowOptions, KeyRepeat};
use side::assembler::ImageAssembler; use side::assembler::ImageAssembler;
use side::{Machine, REGISTER_PAGE}; use side::{Machine, REGISTER_PAGE};
use std::env; use std::env;
use std::time::Duration;
//use font8x8::{BASIC_FONTS, UnicodeFonts}; //use font8x8::{BASIC_FONTS, UnicodeFonts};
const WIDTH: usize = 640; const WIDTH: usize = 640;
const HEIGHT: usize = 360; const HEIGHT: usize = 480;
fn main() { fn main() {
// for font in BASIC_FONTS.iter().skip(0x20) { // for font in BASIC_FONTS.iter().skip(0x20) {
@ -36,19 +37,86 @@ fn main() {
let mut opts = WindowOptions::default(); let mut opts = WindowOptions::default();
opts.scale = Scale::X1; opts.scale = Scale::X1;
let mut window = Window::new("Test - ESC to exit", WIDTH, HEIGHT, opts).unwrap_or_else(|e| { let mut window = Window::new("Test - ESC to exit", WIDTH, HEIGHT, opts).unwrap_or_else(|e| {
panic!("{}", e); panic!("{}", e);
}); });
while window.is_open() && !window.is_key_down(Key::Escape) { while window.is_open() && !window.is_key_down(Key::Escape) {
machine.cycle(); machine.cycle();
if machine.memory[REGISTER_PAGE + 63] == 0x01 { 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 // 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 window
.update_with_buffer(&machine.memory, WIDTH, HEIGHT) .update_with_buffer(&machine.memory, WIDTH, HEIGHT)
.unwrap(); .unwrap();
machine.memory[REGISTER_PAGE + 63] = 0x00; 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 loadi 6 $FFFFFF
mul 1 6 1; 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 $B; Increment VBuf Pointer
inc 2; INC Scratch Pixel inc 2; INC Scratch Pixel
@ -97,6 +102,7 @@
call draw_char_pixels call draw_char_pixels
ret ret
label _scratch_draw_string: label _scratch_draw_string:
nop nop

BIN
wallpaper.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB