88 lines
2.0 KiB
V
88 lines
2.0 KiB
V
module main
|
|
|
|
import os
|
|
import gg
|
|
import gx
|
|
import time
|
|
|
|
struct Emulator {
|
|
pub mut:
|
|
chip8 Chip8
|
|
graphic &gg.Context = unsafe { nil }
|
|
}
|
|
|
|
fn (mut emulator Emulator) draw_block(i f32, j f32) {
|
|
emulator.graphic.draw_rect_filled(j, i, f32(20), f32(20), gx.rgb(0, 255, 0))
|
|
}
|
|
|
|
fn (mut emulator Emulator) load_rom() ! {
|
|
if os.args.len <= 1 {
|
|
return error('ROM path not especified!')
|
|
}
|
|
mut file := os.open(os.args[1])!
|
|
defer { file.close() }
|
|
println('Loading ROM in the memory...')
|
|
mut instructions := file.read_bytes(1024)
|
|
mut index := u16(0x200)
|
|
emulator.chip8.set_ram(instructions, index)
|
|
println('ROM successfully loaded into memory!')
|
|
}
|
|
|
|
fn frame(mut emulator Emulator) {
|
|
emulator.graphic.begin()
|
|
for y in 0 .. emulator.chip8.screen.display_height {
|
|
for x in 0 .. emulator.chip8.screen.display_width {
|
|
pixel := emulator.chip8.screen.display[y][x]
|
|
if pixel == 1 {
|
|
emulator.draw_block(f32(y * 20), f32(x * 20))
|
|
}
|
|
}
|
|
}
|
|
emulator.graphic.end()
|
|
}
|
|
|
|
fn (mut emulator Emulator) run(ms_per_tick int) {
|
|
for {
|
|
emulator.chip8.run()
|
|
emulator.chip8.cycles++
|
|
emulator.chip8.update_timers()
|
|
if emulator.chip8.cpu_clock == emulator.chip8.cycles {
|
|
emulator.chip8.cycles = 0
|
|
}
|
|
time.sleep(ms_per_tick * time.millisecond)
|
|
}
|
|
}
|
|
|
|
fn on_event(e &gg.Event, mut emulator Emulator) {
|
|
if e.typ == .key_down {
|
|
x := int(e.key_code)
|
|
// eprintln('>>> e.typ: ${e.typ} | e.key_code: ${e.key_code} | x: ${x} | x.hex(): ${x.hex()}')
|
|
emulator.chip8.set_key(x)
|
|
}
|
|
if e.typ == .key_up {
|
|
emulator.chip8.set_key(0)
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
mut emulator := &Emulator{
|
|
chip8: Chip8{}
|
|
}
|
|
emulator.load_rom()!
|
|
emulator.chip8.start_cpu()
|
|
emulator.graphic = gg.new_context(
|
|
bg_color: gx.rgb(0, 0, 0)
|
|
width: 1280
|
|
height: 640
|
|
window_title: 'V CHIP-8 Emulator'
|
|
user_data: emulator
|
|
frame_fn: frame
|
|
event_fn: on_event
|
|
)
|
|
// Ensure a constant rate of updates to the emulator, no matter
|
|
// what the refresh rate is, by running the updates in a separate
|
|
// independent thread:
|
|
spawn emulator.run(8)
|
|
emulator.graphic.run()
|
|
}
|