Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70bb250bcd | ||
|
|
a375d365fa |
+126
-29
@@ -31,10 +31,12 @@ struct Machine
|
||||
sound-timer: u8
|
||||
|
||||
struct State
|
||||
clear-screen: bool
|
||||
screen-pixels: [2048 rl/Color]
|
||||
screen-texture: rl/Texture2D
|
||||
font: rl/Font
|
||||
draw-commands: Vec(DrawCommand)
|
||||
page: int
|
||||
clear-screen: bool
|
||||
shift-vx-swap: bool
|
||||
jump-xnn: bool
|
||||
|
||||
@@ -56,21 +58,24 @@ const font: [80 u8] =
|
||||
0xF0, 0x80, 0xF0, 0x80, 0xF0, ;; E
|
||||
0xF0, 0x80, 0xF0, 0x80, 0x80] ;; F
|
||||
|
||||
;; keypad-keys is in layout order, so keypad[i] isn't hex key i. That doesn't matter until EX9E and EXA1.
|
||||
const keypad-keys: [16 rl/Key] =
|
||||
const keypad-mapping: [16 u8] =
|
||||
[1, 2, 3, 0xC, 4, 5, 6, 0xD, 7, 8, 9, 0xE, 0xA, 0, 0xB, 0xF]
|
||||
|
||||
const keypad-keymap: [16 rl/Key] =
|
||||
[:key-one, :key-two, :key-three, :key-four,
|
||||
:key-q, :key-w, :key-e, :key-r,
|
||||
:key-a, :key-s, :key-d, :key-f,
|
||||
:key-z, :key-x, :key-c, :key-v]
|
||||
;; [:key-one, :key-two, :key-three, :key-c,
|
||||
;; :key-four, :key-five, :key-six, :key-d,
|
||||
;; :key-seven, :key-eight, :key-nine, :key-e,
|
||||
;; :key-a, :key-zero, :key-b, :key-f]
|
||||
|
||||
const keypad-chars: str = "123c456d789ea0bf"
|
||||
const hex-numbers: str = "0123456789ABCDEF"
|
||||
|
||||
let screen-width: int = 1024
|
||||
let screen-height: int = 768
|
||||
const reg-names: [16 str] = ["V0", "V1", "V2", "V3", "V4", "V5", "V6", "V7",
|
||||
"V8", "V9", "VA", "VB", "VC", "VD", "VE", "VF"]
|
||||
|
||||
;; let screen-width: int = 1300
|
||||
;; let screen-height: int = 650
|
||||
let screen-width: int = 965
|
||||
let screen-height: int = 550
|
||||
let pixels-width: int = 64
|
||||
let pixels-height: int = 32
|
||||
let ips: int = 700
|
||||
@@ -107,6 +112,7 @@ fn step() -> ()
|
||||
0xEE ->
|
||||
cpu.pc = cpu.stack[cpu.sp]
|
||||
cpu.sp -= 1
|
||||
_ -> println("Unrecognized 0x0 instruction")
|
||||
0x1 -> cpu.pc = inst.nnn
|
||||
0x2 -> ;; Call a subroutine
|
||||
cpu.stack[cpu.sp] = cpu.pc
|
||||
@@ -124,12 +130,12 @@ fn step() -> ()
|
||||
0x2 -> cpu.v[inst.x] &= cpu.v[inst.y]
|
||||
0x3 -> cpu.v[inst.x] ^= cpu.v[inst.y]
|
||||
0x4 ->
|
||||
let sum = cpu.v[inst.x] + cpu.v[inst.y]
|
||||
cpu.v[inst.x] = sum
|
||||
let sum = u16(cpu.v[inst.x]) + u16(cpu.v[inst.y])
|
||||
cpu.v[inst.x] = u8(sum)
|
||||
cpu.v[0xF] = u8(sum >> 8)
|
||||
0x5 ->
|
||||
let diff = u16(cpu.v[inst.x]) - u16(cpu.v[inst.y])
|
||||
cpu.v[inst.x] = diff
|
||||
cpu.v[inst.x] = u8(diff)
|
||||
cpu.v[0xF] = u8(diff >> 8 & 0x1 ^ 1)
|
||||
0x6 ->
|
||||
if state.shift-vx-swap
|
||||
@@ -138,16 +144,18 @@ fn step() -> ()
|
||||
cpu.v[inst.x] = cpu.v[inst.x] >> 1
|
||||
0x7 ->
|
||||
let diff = u16(cpu.v[inst.y]) - u16(cpu.v[inst.x])
|
||||
cpu.v[inst.x] = diff
|
||||
cpu.v[inst.x] = u8(diff)
|
||||
cpu.v[0xF] = u8(diff >> 8 & 0x1 ^ 1)
|
||||
0xE ->
|
||||
if state.shift-vx-swap
|
||||
cpu.v[inst.x] = cpu.v[inst.y]
|
||||
cpu.v[0xF] = (cpu.v[inst.x] & 0x80) >> 7
|
||||
cpu.v[inst.x] = cpu.v[inst.x] << 1
|
||||
_ -> println("Unrecognized 0x8 instruction")
|
||||
0x9 -> if cpu.v[inst.x] != cpu.v[inst.y] then cpu.pc += 2
|
||||
0xA -> cpu.index = inst.nnn
|
||||
0xB ->
|
||||
0xB -> cpu.pc = inst.nnn + if state.jump-xnn then cpu.v[inst.x] else cpu.v[0]
|
||||
0xC -> cpu.v[inst.x] = u8(rand-int()) & inst.nn
|
||||
;; DXYN
|
||||
0xD ->
|
||||
put(state.draw-commands, DrawCommand{.x (cpu.v[inst.x] % u8(pixels-width))
|
||||
@@ -155,13 +163,22 @@ fn step() -> ()
|
||||
.pixels inst.n
|
||||
.addr cpu.index})
|
||||
cpu.v[0xF] = 0
|
||||
0xE ->
|
||||
let pressed = machine.keypad[inst.x]
|
||||
if (inst.nn == 0x9E and pressed) or (inst.nn == 0xA1 and not pressed)
|
||||
cpu.pc += 2
|
||||
_ -> println("Instruction not handled: ", inst.op)
|
||||
|
||||
fn run-update() -> ()
|
||||
cycles += f64(rl/get-frame-time()) * ips
|
||||
for i, key in keypad-keymap
|
||||
machine.keypad[keypad-mapping[int(i)]] = rl/is-key-down(key)
|
||||
|
||||
for i, key in keypad-keys
|
||||
machine.keypad[int(i)] = rl/is-key-down(key)
|
||||
if rl/is-key-pressed(:key-minus)
|
||||
state.page = max(0, state.page - 1)
|
||||
if rl/is-key-pressed(:key-equal)
|
||||
state.page = min(5, state.page + 1)
|
||||
|
||||
cycles += f64(rl/get-frame-time()) * ips
|
||||
|
||||
while cycles >= 1.0
|
||||
step()
|
||||
@@ -175,32 +192,107 @@ fn run-update() -> ()
|
||||
for i,pixel in machine.vbuffer
|
||||
state.screen-pixels[i] = if pixel then rl/white else rl/black
|
||||
|
||||
;; for i,pixel in machine.vbuffer
|
||||
;; if i % 2 == 0 and i / pixels-width % 2 == 0 or i % 2 == 1 and i / pixels-width % 2 == 1
|
||||
;; state.screen-pixels[i] = rl/white
|
||||
for i,pixel in machine.vbuffer
|
||||
if i % 2 == 0 and i / pixels-width % 2 == 0 or i % 2 == 1 and i / pixels-width % 2 == 1
|
||||
state.screen-pixels[i] = rl/white
|
||||
|
||||
rl/update-texture(state.screen-texture, Ptr(const u8)(addr(state.screen-pixels)))
|
||||
|
||||
if machine.delay-timer > 0 then machine.delay-timer -= 1
|
||||
if machine.sound-timer > 0 then machine.sound-timer -= 1
|
||||
|
||||
fn draw-text-normal(text: str, x: $t, y: $t, color: rl/Color) -> () where is-numeric($t)
|
||||
rl/draw-text-ex(state.font, text, rl/Vector2(f32(x), f32(y)), 21, 0.0, color)
|
||||
|
||||
fn run-drawing() -> ()
|
||||
rl/clear-background(rl/black)
|
||||
rl/draw-fps(10, 10)
|
||||
|
||||
rl/draw-text("Keypad", 10, 40, 21, rl/white)
|
||||
let key-size = 30
|
||||
for i, key in keypad-keys
|
||||
draw-text-normal("Keypad", 10, 200, rl/white)
|
||||
let key-size = 25
|
||||
for i, key in keypad-keymap
|
||||
let x = 10 + (key-size * (i % 4))
|
||||
y = 70 + (key-size * (i / 4))
|
||||
y = 230 + (key-size * (i / 4))
|
||||
color = if machine.keypad[keypad-mapping[i]] then rl/green else rl/white
|
||||
rl/draw-rectangle-lines(x, y, key-size, key-size, color)
|
||||
;; TODO: Maybe we don't need hex-numbers anymore?
|
||||
draw-text-normal(hex-numbers[i..i + 1], x + 4, y + 4, color)
|
||||
|
||||
draw-text-normal("Actual", 150, 200, rl/white)
|
||||
for i,key in machine.keypad
|
||||
let x = 150 + (key-size * (i % 4))
|
||||
y = 230 + (key-size * (i / 4))
|
||||
color = if machine.keypad[i] then rl/green else rl/white
|
||||
rl/draw-rectangle-lines(x, y, key-size, key-size, color)
|
||||
rl/draw-text(keypad-chars[i..i + 1], x + key-size / 4, y + key-size / 4, 16, color)
|
||||
draw-text-normal("0123456789ABCDEF"[i..i + 1], x + 4, y + 4, color)
|
||||
|
||||
let scale: f32 = 8.0
|
||||
;; Registers
|
||||
let reg-x = 290
|
||||
for i in 0..16
|
||||
;; draw-text-normal(str(i64->bytes(i64(cpu.v[i]))), 520, 60 + 26 * i, rl/white)
|
||||
let reg-val = tformat("V{:X}=0x{:02X}", i, cpu.v[i])
|
||||
draw-text-normal(reg-val, reg-x, 200 + 21 * i, rl/white)
|
||||
|
||||
let scale: f32 = 5.5
|
||||
src = rl/Rectangle(0, 0, f32(pixels-width), f32(pixels-height))
|
||||
dst = rl/Rectangle(10, 250, f32(pixels-width) * scale, f32(pixels-height) * scale)
|
||||
dst = rl/Rectangle(10, 10, f32(pixels-width) * scale, f32(pixels-height) * scale)
|
||||
rl/draw-texture-pro(state.screen-texture, src, dst, rl/Vector2(0.0, 0.0), 0.0, rl/white)
|
||||
rl/draw-rectangle-lines(i32(dst.x), i32(dst.y), i32(dst.width), i32(dst.height), rl/white)
|
||||
|
||||
for i in 0..16
|
||||
let row = i % 8
|
||||
col = i / 8
|
||||
x = 10
|
||||
y = 20 * row
|
||||
w = 80
|
||||
h = 20
|
||||
start-y = 360
|
||||
idx-txt = tformat(" {:X}|", i)
|
||||
rl/draw-rectangle-lines(x + col * w, start-y + y, w, h, rl/white)
|
||||
draw-text-normal(idx-txt, x + col * w, start-y + y, rl/white)
|
||||
if i < cpu.sp
|
||||
let addr-txt = tformat("0x{:02X}", cpu.stack[i])
|
||||
draw-text-normal(addr-txt, x + 33 + col * w, start-y + y, rl/white)
|
||||
|
||||
let x = 195
|
||||
draw-text-normal(tformat(" i=0x{:02X}", cpu.index), x, 360, rl/white)
|
||||
draw-text-normal(tformat("pc=0x{:02X}", cpu.sp), x, 380, rl/white)
|
||||
draw-text-normal(tformat("dt=0x{:02}", machine.delay-timer), x, 400, rl/white)
|
||||
draw-text-normal(tformat("st=0x{:02}", machine.sound-timer), x, 420, rl/white)
|
||||
|
||||
let hex-rows = 32
|
||||
hex-cols = 24
|
||||
padding = 4
|
||||
cell-w = 24
|
||||
cell-h = 16
|
||||
grid-x = 370
|
||||
grid-y = 25
|
||||
grid-w = hex-cols * cell-w + padding * 2
|
||||
grid-h = hex-rows * cell-h + padding * 2
|
||||
slots-per-page = hex-rows * hex-cols
|
||||
|
||||
for i in 0..4096 / slots-per-page + 1
|
||||
let color = if state.page == i then rl/green else rl/white
|
||||
tab-w = 80
|
||||
start-num = i * slots-per-page
|
||||
end-num = min(4096, (i + 1) * slots-per-page)
|
||||
tab-name = tformat("{:03X}-{:03X}", start-num, end-num - 1)
|
||||
rl/draw-rectangle(grid-x - 1 + i * tab-w + (i * 2), grid-y - 20, tab-w, 20, color)
|
||||
draw-text-normal(tab-name, grid-x + 1 + i * tab-w + (i * 2), grid-y - 20, rl/black)
|
||||
|
||||
rl/draw-rectangle-lines(grid-x, grid-y, grid-w, grid-h, rl/white)
|
||||
for r in 0..hex-rows
|
||||
for c in 0..hex-cols
|
||||
let idx = c + r * hex-cols + hex-cols * hex-rows * state.page
|
||||
if idx < length(machine.memory)
|
||||
let reg-val = tformat("{:02X}", machine.memory[idx])
|
||||
let x-padding = if c % 2 == 0 then 2 else -2
|
||||
draw-text-normal(reg-val, grid-x + x-padding + c * cell-w, grid-y + padding + r * cell-h, rl/white)
|
||||
|
||||
cpu.stack[0] = 0xAA
|
||||
cpu.stack[1] = 0xAB
|
||||
cpu.stack[2] = 0xAC
|
||||
cpu.stack[3] = 0xAD
|
||||
cpu.sp = 15
|
||||
|
||||
fn main() -> i32
|
||||
rl/set-trace-log-level(:log-warning)
|
||||
@@ -208,6 +300,10 @@ fn main() -> i32
|
||||
defer rl/close-window()
|
||||
rl/set-target-fps(60)
|
||||
|
||||
let font = rl/load-font-ex("JetBrainsMono-Regular.otf", 21, [])
|
||||
defer rl/unload-font(state.font)
|
||||
state.font = font
|
||||
state.page = 2
|
||||
cpu.pc = 0x200
|
||||
let img = rl/gen-image-color(pixels-width, pixels-height, rl/black)
|
||||
state.screen-texture = rl/load-texture-from-image(img)
|
||||
@@ -221,6 +317,7 @@ fn main() -> i32
|
||||
run-update()
|
||||
rl/with-drawing:
|
||||
run-drawing()
|
||||
free-temp()
|
||||
restart continue()
|
||||
()
|
||||
0
|
||||
|
||||
Reference in new issue
Block a user