Merge pull request #4 from spytheman/improvements

Fix compilation with latest V, separate updates from the display refresh rate, improve keyboard handling, run `v fmt -w .`, enable running on macos and windows.
This commit is contained in:
Vinicius Silva 2025-04-08 08:53:19 -03:00 committed by GitHub
commit 0424fa56b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 198 additions and 283 deletions

View File

@ -1,37 +1,25 @@
import rand import rand
const keyboard := { const keyboard = {
0x1 : 0x1 //1 - 1 0x31: 0x01 // keycode 1 - 1
0x2 : 0x2 //2 - 2 0x32: 0x02 // keycode 2 - 2
0x3 : 0x3 //3 - 3 0x33: 0x03 // keycode 3 - 3
0x4 : 0x43 //4 - C 0x34: 0x0C // keycode 4 - C
0x51 : 0x4 //Q - 4 0x51: 0x04 // keycode Q - 4
0x71 : 0x4 //q - 4 0x57: 0x05 // keycode W - 5
0x57 : 0x5 //W - 5 0x45: 0x06 // keycode E - 6
0x77 : 0x5 //w - 5 0x52: 0x0D // keycode R - D
0x45 : 0x6 //E - 6 0x41: 0x07 // keycode A - 7
0x65 : 0x6 //e - 6 0x53: 0x08 // keycode S - 8
0x52 : 0x44 //R - D 0x44: 0x09 // keycode D - 9
0x72 : 0x44 //r - D 0x46: 0x0E // keycode F - E
0x41 : 0x7 //A - 7 0x5A: 0x0A // keycode Z - A
0x61 : 0x7 //a - 7 0x58: 0x00 // keycode X - 0
0x53 : 0x8 //S - 8 0x43: 0x0B // keycode C - B
0x73 : 0x8 //s - 8 0x56: 0x0F // keycode V - F
0x44 : 0x9 //D - 9
0x64 : 0x9 //d - 9
0x46 : 0x45 //F - E
0x66 : 0x45 //f - E
0x5A : 0x41 //Z - A
0x7A : 0x41 //z - A
0x58 : 0x30 //X - 0
0x78 : 0x30 //x - 0
0x43 : 0x42 //C - B
0x63 : 0x42 //c - B
0x56 : 0x46 //V - F
0x76 : 0x46 //v - F
} }
const font := [ const font = [
[u8(0xF0), u8(0x90), u8(0x90), u8(0x90), u8(0xF0)], // 0 [u8(0xF0), u8(0x90), u8(0x90), u8(0x90), u8(0xF0)], // 0
[u8(0x20), u8(0x60), u8(0x20), u8(0x20), u8(0x70)], // 1 [u8(0x20), u8(0x60), u8(0x20), u8(0x20), u8(0x70)], // 1
[u8(0xF0), u8(0x10), u8(0xF0), u8(0x80), u8(0xF0)], // 2 [u8(0xF0), u8(0x10), u8(0xF0), u8(0x80), u8(0xF0)], // 2
@ -50,11 +38,11 @@ const font := [
[u8(0xF0), u8(0x80), u8(0xF0), u8(0x80), u8(0x80)], // F [u8(0xF0), u8(0x80), u8(0xF0), u8(0x80), u8(0x80)], // F
] ]
struct Screen{ struct Screen {
pub: pub:
display_width int = 64 display_width int = 64
display_height int = 32 display_height int = 32
mut: mut:
display [32][64]u8 display [32][64]u8
} }
@ -62,9 +50,9 @@ const mem_size = 4096
const num_of_registers = 16 const num_of_registers = 16
const f = 15 const f = 15
struct Chip8{ struct Chip8 {
cpu_clock u8 = 9 cpu_clock u8 = 9
pub mut: pub mut:
ram [mem_size]u8 ram [mem_size]u8
v [num_of_registers]u8 v [num_of_registers]u8
screen Screen screen Screen
@ -78,8 +66,7 @@ struct Chip8{
cycles u8 cycles u8
} }
fn (mut chip Chip8) start_cpu(){ fn (mut chip Chip8) start_cpu() {
chip.screen = Screen{} chip.screen = Screen{}
// load font in the memory // load font in the memory
@ -88,39 +75,33 @@ fn (mut chip Chip8) start_cpu(){
} }
} }
fn (mut chip Chip8) run(){ fn (mut chip Chip8) run() {
mut instruction := chip.fetch() mut instruction := chip.fetch()
chip.decode_and_run(instruction) chip.decode_and_run(instruction)
} }
@[direct_array_access]
fn (mut chip Chip8) set_ram(instructions []u8, index u16) { fn (mut chip Chip8) set_ram(instructions []u8, index u16) {
mut j := index mut j := index
for i := 0; i < instructions.len; i++ { for i := 0; i < instructions.len; i++ {
chip.ram[j] = instructions[i] chip.ram[j] = instructions[i]
j++ j++
} }
} }
fn (mut chip Chip8) fetch() u16{ @[direct_array_access]
fn (mut chip Chip8) fetch() u16 {
mut instruction := u16(0x00) mut instruction := u16(0x00)
mut half_instruction := chip.ram[chip.pc] mut half_instruction := chip.ram[chip.pc]
instruction = instruction | half_instruction instruction = instruction | half_instruction
instruction = instruction << 8 instruction = instruction << 8
half_instruction = chip.ram[chip.pc + 1] half_instruction = chip.ram[chip.pc + 1]
instruction = instruction | half_instruction instruction = instruction | half_instruction
return instruction return instruction
} }
@[direct_array_access]
fn (mut chip Chip8) decode_and_run(instruction u16) { fn (mut chip Chip8) decode_and_run(instruction u16) {
mut nnn, mut nn, mut n, mut x, mut y := 0x00, 0x00, 0x00, 0x00, 0x00 mut nnn, mut nn, mut n, mut x, mut y := 0x00, 0x00, 0x00, 0x00, 0x00
mut opcode_msb := instruction & 0xF000 mut opcode_msb := instruction & 0xF000
@ -128,49 +109,45 @@ fn (mut chip Chip8) decode_and_run(instruction u16) {
mut is_jump := false mut is_jump := false
chip.is_draw = false chip.is_draw = false
if chip.delay_timer > 0 { chip.delay_timer-- } if chip.delay_timer > 0 {
if chip.sound_timer > 0 { chip.sound_timer-- } chip.delay_timer--
}
match opcode_msb{ if chip.sound_timer > 0 {
chip.sound_timer--
}
match opcode_msb {
0x0000 { 0x0000 {
match opcode_lsb { match opcode_lsb {
0xEE { 0xEE {
chip.pc = chip.stack.pop() or { panic(err) } chip.pc = chip.stack.pop() or { panic(err) }
// Returns from a subroutine // Returns from a subroutine
} }
0xE0 { 0xE0 {
chip.is_draw = true chip.is_draw = true
for i := 0; i < chip.screen.display_height; i++{ for i := 0; i < chip.screen.display_height; i++ {
for j := 0; j < chip.screen.display_width; j++ { for j := 0; j < chip.screen.display_width; j++ {
chip.screen.display[i][j] = 0 chip.screen.display[i][j] = 0
} }
} }
} }
// 0NNN {
//0NNN {
// nnn = instruction & 0x0FFF // nnn = instruction & 0x0FFF
// Calls machine code routine // Calls machine code routine
//} //}
else {
else{
nnn = instruction & 0x0FFF nnn = instruction & 0x0FFF
//panic('Invalid instruction! 0x${instruction.hex()}') // panic('Invalid instruction! 0x${instruction.hex()}')
} }
} }
} }
0x1000 { 0x1000 {
nnn = instruction & 0x0FFF nnn = instruction & 0x0FFF
chip.pc = u16(nnn) chip.pc = u16(nnn)
is_jump = true is_jump = true
// Jumps to address NNN // Jumps to address NNN
} }
0x2000 { 0x2000 {
nnn = instruction & 0x0FFF nnn = instruction & 0x0FFF
chip.stack.push(chip.pc) chip.stack.push(chip.pc)
@ -178,31 +155,33 @@ fn (mut chip Chip8) decode_and_run(instruction u16) {
is_jump = true is_jump = true
// Calls subroutine at NNN // Calls subroutine at NNN
} }
0x3000 { 0x3000 {
x = (instruction & 0x0F00) >> 8 x = (instruction & 0x0F00) >> 8
nn = instruction & 0x00FF nn = instruction & 0x00FF
if chip.v[x] == nn { chip.pc += 2 } if chip.v[x] == nn {
chip.pc += 2
}
// Skips the next instruction if VX equals NN // Skips the next instruction if VX equals NN
} }
0x4000 { 0x4000 {
x = (instruction & 0x0F00) >> 8 x = (instruction & 0x0F00) >> 8
nn = instruction & 0x00FF nn = instruction & 0x00FF
if chip.v[x] != nn { chip.pc += 2 } if chip.v[x] != nn {
chip.pc += 2
}
// Skips the next instruction if VX does not equal NN // Skips the next instruction if VX does not equal NN
} }
0x5000 { 0x5000 {
x = (instruction & 0x0F00) >> 8 x = (instruction & 0x0F00) >> 8
y = (instruction & 0x00F0) >> 4 y = (instruction & 0x00F0) >> 4
if chip.v[x] == chip.v[y] { chip.pc += 2 } if chip.v[x] == chip.v[y] {
chip.pc += 2
}
// Skips the next instruction if VX equals VY // Skips the next instruction if VX equals VY
} }
0x6000 { 0x6000 {
x = (instruction & 0x0F00) >> 8 x = (instruction & 0x0F00) >> 8
nn = instruction & 0x00FF nn = instruction & 0x00FF
@ -210,7 +189,6 @@ fn (mut chip Chip8) decode_and_run(instruction u16) {
chip.v[x] = u8(nn) chip.v[x] = u8(nn)
// Sets VX to NN // Sets VX to NN
} }
0x7000 { 0x7000 {
x = (instruction & 0x0F00) >> 8 x = (instruction & 0x0F00) >> 8
nn = instruction & 0x00FF nn = instruction & 0x00FF
@ -218,7 +196,6 @@ fn (mut chip Chip8) decode_and_run(instruction u16) {
chip.v[x] += u8(nn) chip.v[x] += u8(nn)
// Adds NN to VX (carry flag is not changed) // Adds NN to VX (carry flag is not changed)
} }
0x8000 { 0x8000 {
x = (instruction & 0x0F00) >> 8 x = (instruction & 0x0F00) >> 8
y = (instruction & 0x00F0) >> 4 y = (instruction & 0x00F0) >> 4
@ -229,114 +206,96 @@ fn (mut chip Chip8) decode_and_run(instruction u16) {
chip.v[x] = chip.v[y] chip.v[x] = chip.v[y]
// Sets VX to the value of VY // Sets VX to the value of VY
} }
0x01 { 0x01 {
chip.v[x] |= chip.v[y] chip.v[x] |= chip.v[y]
// Sets VX to VX or VY. (bitwise OR operation). // Sets VX to VX or VY. (bitwise OR operation).
} }
0x02 { 0x02 {
chip.v[x] &= chip.v[y] chip.v[x] &= chip.v[y]
// Sets VX to VX and VY. (bitwise AND operation) // Sets VX to VX and VY. (bitwise AND operation)
} }
0x03 { 0x03 {
chip.v[x] ^= chip.v[y] chip.v[x] ^= chip.v[y]
// Sets VX to VX xor VY // Sets VX to VX xor VY
} }
0x04 { 0x04 {
xy := chip.v[x] + chip.v[y] xy := chip.v[x] + chip.v[y]
if xy > 255 { if xy > 255 {
chip.v[f] = 1 chip.v[f] = 1
}else{ } else {
chip.v[f] = 0 chip.v[f] = 0
} }
chip.v[x] = (xy & 0xFF) chip.v[x] = (xy & 0xFF)
// Adds VY to VX. VF is set to 1 when there's an overflow, and to 0 when there is not. // Adds VY to VX. VF is set to 1 when there's an overflow, and to 0 when there is not.
} }
0x05 { 0x05 {
if chip.v[x] > chip.v[y] { if chip.v[x] > chip.v[y] {
chip.v[f] = 1 chip.v[f] = 1
}else{ } else {
chip.v[f] = 0 chip.v[f] = 0
} }
chip.v[x] -= chip.v[y] chip.v[x] -= chip.v[y]
// VY is subtracted from VX. VF is set to 0 when there's an underflow, and 1 when there is not. (i.e. VF set to 1 if VX >= VY and 0 if not) // VY is subtracted from VX. VF is set to 0 when there's an underflow, and 1 when there is not. (i.e. VF set to 1 if VX >= VY and 0 if not)
} }
0x06 { 0x06 {
if chip.v[x] % 2 == 1 { if chip.v[x] % 2 == 1 {
chip.v[f] = 1; chip.v[f] = 1
} } else {
else { chip.v[f] = 0
chip.v[f] = 0;
} }
chip.v[x] = chip.v[x] >> 1 chip.v[x] = chip.v[x] >> 1
// Stores the least significant bit of VX in VF and then shifts VX to the right by 1 // Stores the least significant bit of VX in VF and then shifts VX to the right by 1
} }
0x07 { 0x07 {
xy := chip.v[y] - chip.v[x] xy := chip.v[y] - chip.v[x]
if chip.v[y] > chip.v[x] { if chip.v[y] > chip.v[x] {
chip.v[f] = 1 chip.v[f] = 1
}else{ } else {
chip.v[f] = 0 chip.v[f] = 0
} }
chip.v[x] = xy chip.v[x] = xy
// Sets VX to VY minus VX. VF is set to 0 when there's an underflow, and 1 when there is not. (i.e. VF set to 1 if VY >= VX). // Sets VX to VY minus VX. VF is set to 0 when there's an underflow, and 1 when there is not. (i.e. VF set to 1 if VY >= VX).
} }
0x0E { 0x0E {
if (chip.v[x] & 10000000) == 1 { if (chip.v[x] & 10000000) == 1 {
chip.v[f] = 1; chip.v[f] = 1
} } else {
else { chip.v[f] = 0
chip.v[f] = 0;
} }
chip.v[x] = chip.v[x] << 1 chip.v[x] = chip.v[x] << 1
// Stores the most significant bit of VX in VF and then shifts VX to the left by 1. // Stores the most significant bit of VX in VF and then shifts VX to the left by 1.
} }
else {
else{
panic('Invalid instruction! 0x${instruction.hex()}') panic('Invalid instruction! 0x${instruction.hex()}')
} }
} }
} }
0x9000 { 0x9000 {
x = (instruction & 0x0F00) >> 8 x = (instruction & 0x0F00) >> 8
y = (instruction & 0x00F0) >> 4 y = (instruction & 0x00F0) >> 4
if chip.v[x] != chip.v[y] { chip.pc += 2 } if chip.v[x] != chip.v[y] {
chip.pc += 2
}
} }
0xA000 { 0xA000 {
nnn = instruction & 0x0FFF nnn = instruction & 0x0FFF
chip.i = u16(nnn) chip.i = u16(nnn)
} }
0xB000 { 0xB000 {
nnn = instruction & 0x0FFF nnn = instruction & 0x0FFF
chip.pc = u16(nnn + chip.v[0]) chip.pc = u16(nnn + chip.v[0])
is_jump = true is_jump = true
} }
0xC000 { 0xC000 {
x = (instruction & 0x0F00) >> 8 x = (instruction & 0x0F00) >> 8
nn = instruction & 0x00FF nn = instruction & 0x00FF
@ -345,9 +304,7 @@ fn (mut chip Chip8) decode_and_run(instruction u16) {
chip.v[x] = u8(randint & nn) chip.v[x] = u8(randint & nn)
} }
0xD000 { 0xD000 {
chip.is_draw = true chip.is_draw = true
x = (instruction & 0x0F00) >> 8 x = (instruction & 0x0F00) >> 8
y = (instruction & 0x00F0) >> 4 y = (instruction & 0x00F0) >> 4
@ -359,12 +316,11 @@ fn (mut chip Chip8) decode_and_run(instruction u16) {
chip.v[f] = 0 chip.v[f] = 0
for y_coord := 0; y_coord < n; y_coord++ { for y_coord := 0; y_coord < n; y_coord++ {
pixel := chip.ram[chip.i + y_coord] pixel := chip.ram[chip.i + y_coord]
for x_coord := 0; x_coord < 8; x_coord++ { for x_coord := 0; x_coord < 8; x_coord++ {
if (regvy + y_coord) < chip.screen.display_height
if (regvy + y_coord) < chip.screen.display_height && (regvx + x_coord) < chip.screen.display_width { && (regvx + x_coord) < chip.screen.display_width {
if (pixel & (0x80 >> x_coord)) != 0 { if (pixel & (0x80 >> x_coord)) != 0 {
if chip.screen.display[regvy + y_coord][regvx + x_coord] == 1 { if chip.screen.display[regvy + y_coord][regvx + x_coord] == 1 {
chip.v[f] = 1 chip.v[f] = 1
@ -376,98 +332,90 @@ fn (mut chip Chip8) decode_and_run(instruction u16) {
} }
} }
} }
0xE000 { 0xE000 {
x = (instruction & 0x0F00) >> 8 x = (instruction & 0x0F00) >> 8
opcode_lsb = instruction & 0x00FF opcode_lsb = instruction & 0x00FF
match opcode_lsb { match opcode_lsb {
0x9E { 0x9E {
if chip.key == chip.v[x] {
if chip.key == chip.v[x] { chip.pc += 2 } chip.pc += 2
}
} }
0xA1 { 0xA1 {
if chip.key != chip.v[x] {
if chip.key != chip.v[x] { chip.pc += 2 } chip.pc += 2
} }
}
else{ else {
panic('Invalid instruction 0x${instruction.hex()}') panic('Invalid instruction 0x${instruction.hex()}')
} }
} }
} }
0xF000 { 0xF000 {
x = (instruction & 0x0F00) >> 8 x = (instruction & 0x0F00) >> 8
opcode_lsb = instruction & 0x00FF opcode_lsb = instruction & 0x00FF
match opcode_lsb { match opcode_lsb {
0x07{ 0x07 {
chip.v[x] = chip.delay_timer chip.v[x] = chip.delay_timer
} }
0x0A {
0x0A{
chip.v[x] = chip.key chip.v[x] = chip.key
} }
0x15 {
0x15{
chip.delay_timer = chip.v[x] chip.delay_timer = chip.v[x]
} }
0x18 {
0x18{
chip.sound_timer = chip.v[x] chip.sound_timer = chip.v[x]
} }
0x1E {
0x1E{
chip.i += chip.v[x] chip.i += chip.v[x]
} }
0x29 {
0x29{
chip.i = u16(chip.v[x] * 0x5) chip.i = u16(chip.v[x] * 0x5)
} }
0x33 {
0x33{
chip.ram[chip.i] = u8(chip.v[x] / 100) chip.ram[chip.i] = u8(chip.v[x] / 100)
chip.ram[chip.i + 1] = u8((u8(chip.v[x] / 10)) % 10) chip.ram[chip.i + 1] = u8((u8(chip.v[x] / 10)) % 10)
chip.ram[chip.i + 2] = u8(chip.v[x] % 100) % 10 chip.ram[chip.i + 2] = u8(chip.v[x] % 100) % 10
} }
0x55 {
0x55{
for i := chip.v[0]; i <= x; i++ { for i := chip.v[0]; i <= x; i++ {
chip.ram[chip.i + i] = chip.v[i] chip.ram[chip.i + i] = chip.v[i]
} }
chip.i = u16(x + 1) chip.i = u16(x + 1)
} }
0x65 {
0x65{
for i := chip.v[0]; i <= x; i++ { for i := chip.v[0]; i <= x; i++ {
chip.v[x] = chip.ram[chip.i + i] chip.v[x] = chip.ram[chip.i + i]
} }
chip.i = u16(x + 1) chip.i = u16(x + 1)
} }
else { else {
panic('Invalid instruction! 0x${instruction.hex()}') panic('Invalid instruction! 0x${instruction.hex()}')
} }
} }
} }
else { else {
panic('Invalid instruction! 0x${instruction.hex()}') panic('Invalid instruction! 0x${instruction.hex()}')
} }
} }
if !is_jump { chip.pc += 2 } if !is_jump {
chip.pc += 2
}
} }
fn (mut chip Chip8) update_timers(){ fn (mut chip Chip8) update_timers() {
if chip.delay_timer > 0 { chip.delay_timer-- } if chip.delay_timer > 0 {
if chip.sound_timer > 0 { chip.sound_timer-- } chip.delay_timer--
}
if chip.sound_timer > 0 {
chip.sound_timer--
}
} }
fn (mut chip Chip8) set_key(key int){ @[direct_array_access]
fn (mut chip Chip8) set_key(key int) {
chip.key = u8(keyboard[key]) chip.key = u8(keyboard[key])
} }

View File

@ -3,107 +3,85 @@ module main
import os import os
import gg import gg
import gx import gx
import time
struct Emulator{ struct Emulator {
pub mut:
pub mut:
chip8 Chip8 chip8 Chip8
graphic &gg.Context = unsafe { nil } graphic &gg.Context = unsafe { nil }
is_graphic bool = is_graphic()
} }
fn (mut emulator Emulator) draw_block(i f32, j f32) { 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)) emulator.graphic.draw_rect_filled(j, i, f32(20), f32(20), gx.rgb(0, 255, 0))
} }
fn (mut emulator Emulator) load_rom() !{ fn (mut emulator Emulator) load_rom() ! {
if os.args.len <= 1 {
arguments := os.args.clone() return error('ROM path not especified!')
}
if arguments.len > 1 { mut file := os.open(os.args[1])!
mut file := os.open(arguments[1])!
defer { file.close() } defer { file.close() }
println('Loading ROM in the memory...')
println(' Loading ROM in the memory...\n')
load_animate()
mut instructions := file.read_bytes(1024) mut instructions := file.read_bytes(1024)
mut index := u16(0x200) mut index := u16(0x200)
emulator.chip8.set_ram(instructions, index) emulator.chip8.set_ram(instructions, index)
println('ROM successfully loaded into memory!') println('ROM successfully loaded into memory!')
}else{
panic('ROM path not especified!')
}
} }
fn frame(mut emulator Emulator){ fn frame(mut emulator Emulator) {
emulator.graphic.begin() emulator.graphic.begin()
for y in 0 .. emulator.chip8.screen.display_height {
emulator.chip8.run() for x in 0 .. emulator.chip8.screen.display_width {
emulator.chip8.cycles++;
emulator.chip8.update_timers()
display_height := emulator.chip8.screen.display_height
display_width := emulator.chip8.screen.display_width
for y := 0; y < display_height; y++ {
for x := 0; x < display_width; x++ {
pixel := emulator.chip8.screen.display[y][x] pixel := emulator.chip8.screen.display[y][x]
if pixel == 1 { if pixel == 1 {
emulator.draw_block(f32((y)*20), f32((x)*20)) emulator.draw_block(f32(y * 20), f32(x * 20))
} }
} }
} }
if emulator.chip8.cpu_clock == emulator.chip8.cycles {
emulator.chip8.cycles = 0
}
emulator.graphic.end() emulator.graphic.end()
} }
fn (mut emulator Emulator) show_display(){ fn (mut emulator Emulator) run(ms_per_tick int) {
emulator.graphic.run() 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 is_graphic() bool{ fn on_event(e &gg.Event, mut emulator Emulator) {
return os.environ()['DISPLAY'] != '' 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() { fn main() {
mut emulator := &Emulator{ mut emulator := &Emulator{
chip8 : Chip8{} chip8: Chip8{}
} }
if emulator.is_graphic {
emulator.load_rom()! emulator.load_rom()!
emulator.chip8.start_cpu() emulator.chip8.start_cpu()
emulator.graphic = gg.new_context( emulator.graphic = gg.new_context(
bg_color: gx.rgb(0, 0, 0) bg_color: gx.rgb(0, 0, 0)
width: 1280 width: 1280
height: 640 height: 640
window_title: 'V CHIP-8 Emulator' window_title: 'V CHIP-8 Emulator'
user_data: emulator user_data: emulator
frame_fn : frame frame_fn: frame
event_fn: on_event event_fn: on_event
) )
// Ensure a constant rate of updates to the emulator, no matter
emulator.show_display() // what the refresh rate is, by running the updates in a separate
// independent thread:
}else{ spawn emulator.run(8)
panic('System is not graphic!') emulator.graphic.run()
}
}
fn on_event(e &gg.Event, mut emulator Emulator){
emulator.chip8.set_key(e.char_code)
} }

View File

@ -1,40 +1,29 @@
module main module main
import time struct Stack {
pub mut:
struct Stack{
pub mut:
addresses [16]u16 addresses [16]u16
i_control int i_control int
} }
fn (stack Stack) is_empty() bool{ fn (stack Stack) is_empty() bool {
return stack.i_control == 0 return stack.i_control == 0
} }
fn (mut stack Stack) push(address u16){ @[direct_array_access]
fn (mut stack Stack) push(address u16) {
stack.addresses[stack.i_control] = address stack.addresses[stack.i_control] = address
stack.i_control++ stack.i_control++
} }
fn (mut stack Stack) pop() !u16{ @[direct_array_access]
fn (mut stack Stack) pop() !u16 {
if stack.is_empty() { if stack.is_empty() {
return error('Stack is empty!') return error('Stack is empty!')
}else{ } else {
val := stack.addresses[stack.i_control-1] val := stack.addresses[stack.i_control - 1]
stack.addresses[stack.i_control-1] = 0 stack.addresses[stack.i_control - 1] = 0
stack.i_control-- stack.i_control--
return val return val
} }
} }
fn load_animate() {
mut bars := ['|','/','-','\\']
for i := 0; i < 4000; i++ {
print('[${bars[i%4]}]\r ')
time.sleep(400000)
}
}