summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>2020-01-03 13:55:09 -0500
committerJakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>2020-01-03 13:55:09 -0500
commita7a846114e43f6e058ecf83b84c2c58917db7886 (patch)
treeceb2a18c98425b4c1d322f2b13b0b79b96c22e9c
parentb43bb071d63e427834291ef1242555b82091ce9d (diff)
I'm done with this.
-rw-r--r--main.myr578
-rw-r--r--sdl.glue.c12
-rw-r--r--sdl.myr64
3 files changed, 365 insertions, 289 deletions
diff --git a/main.myr b/main.myr
index feac70c..9d22f46 100644
--- a/main.myr
+++ b/main.myr
@@ -12,277 +12,335 @@ const memsz = 4096
const stksz = 16
const regsz = 16
+const fntoff = 0x50
+const fntsz = 80
+const fnt = [
+ 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
+ 0x20, 0x60, 0x20, 0x20, 0x70, // 1
+ 0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
+ 0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
+ 0x90, 0x90, 0xF0, 0x10, 0x10, // 4
+ 0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
+ 0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
+ 0xF0, 0x10, 0x20, 0x40, 0x40, // 7
+ 0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
+ 0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
+ 0xF0, 0x90, 0xF0, 0x90, 0x90, // A
+ 0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
+ 0xF0, 0x80, 0x80, 0x80, 0xF0, // C
+ 0xE0, 0x90, 0x90, 0x90, 0xE0, // D
+ 0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
+ 0xF0, 0x80, 0xF0, 0x80, 0x80 // F
+];
+
const clrscr = {b, n
- var i
- for i = 0; i < n; i++;
- b#[i] = 0
- ;;
+ var i
+ for i = 0; i < n; i++;
+ b#[i] = 0
+ ;;
}
const loadprg = {b, fname
- var fd, i, buf
- match std.open(fname, std.Oread)
- | `std.Ok(n): fd = n
- | `std.Err(errno):
- std.fatal("could not open {}\n", fname)
- ;;
+ var fd, i, buf
+ match std.open(fname, std.Oread)
+ | `std.Ok(n): fd = n
+ | `std.Err(errno):
+ std.fatal("could not open {}\n", fname)
+ ;;
- buf = std.slalloc(0xfff - 0x200)
- match std.read(fd, buf)
- | `std.Ok(n):
- for i = 0; i < 0xfff - 0x200; i++;
- b#[i + 0x200] = (buf[i] : uint8)
- ;;
- | `std.Err(n):
- std.fatal("could not read {}\n", fname)
- ;;
+ buf = std.slalloc(0xfff - 0x200)
+ match std.read(fd, buf)
+ | `std.Ok(n):
+ for i = 0; i < 0xfff - 0x200; i++;
+ b#[i + 0x200] = (buf[i] : uint8)
+ ;;
+ | `std.Err(n):
+ std.fatal("could not read {}\n", fname)
+ ;;
}
-const main = {
- var win, r, tex
- sdl.init(sdl.INIT_VIDEO)
- win = sdl.mkwin(("chip\0" : byte#),
- sdl.WIN_POS_UNSPEC,
- sdl.WIN_POS_UNSPEC,
- winwidth,
- winheight,
- sdl.WIN_OPENGL)
- r = sdl.mkrenderer(win, -1, sdl.RENDERER_ACCEL)
- tex = sdl.mktexture(r, sdl.PIXFMT_RGB332, sdl.TEXACCESS_STREAM, 64, 32)
+const loadfnt = {b
+ var i
+ for i = 0; i < fntsz; i++;
+ b#[i+fntoff] = fnt[i]
+ ;;
+}
- var gfx : uint8[scrsz]
- var mem : uint8[memsz]
- var reg : uint8[regsz]
- var stk : uint16[stksz]
- var pc : uint16 = 0x200
- var sp : uint16 = 0
- var I : uint16 = 0
- var delay : uint8 = 0
- var sound : uint8 = 0
+const getkeys = {
+ var state = sdl.getkbd()
+ -> [
+ state#[sdl.SCANCODE_1],
+ state#[sdl.SCANCODE_2],
+ state#[sdl.SCANCODE_3],
+ state#[sdl.SCANCODE_4],
+ state#[sdl.SCANCODE_Q],
+ state#[sdl.SCANCODE_W],
+ state#[sdl.SCANCODE_E],
+ state#[sdl.SCANCODE_R],
+ state#[sdl.SCANCODE_A],
+ state#[sdl.SCANCODE_S],
+ state#[sdl.SCANCODE_D],
+ state#[sdl.SCANCODE_F],
+ state#[sdl.SCANCODE_Z],
+ state#[sdl.SCANCODE_X],
+ state#[sdl.SCANCODE_C],
+ state#[sdl.SCANCODE_V],
+ state#[sdl.SCANCODE_ESC],
+ ]
+}
+
+const main = {
+ var win, r, tex
+ sdl.init(sdl.INIT_VIDEO)
+ win = sdl.mkwin(("chip\0" : byte#),
+ sdl.WIN_POS_UNSPEC,
+ sdl.WIN_POS_UNSPEC,
+ winwidth,
+ winheight,
+ sdl.WIN_OPENGL)
+ r = sdl.mkrenderer(win, -1, sdl.RENDERER_ACCEL)
+ tex = sdl.mktexture(r, sdl.PIXFMT_RGB332, sdl.TEXACCESS_STREAM, 64, 32)
- clrscr(&gfx, scrsz)
- loadprg(&mem, "/tmp/UFO")
+ var gfx : uint8[scrsz]
+ var mem : uint8[memsz]
+ var reg : uint8[regsz]
+ var stk : uint16[stksz]
+ var pc : uint16 = 0x200
+ var sp : uint16 = 0
+ var I : uint16 = 0
+ var delay : uint8 = 0
+ var sound : uint8 = 0
+ var keys
- var opcode, arg
+ clrscr(&gfx, scrsz)
+ loadprg(&mem, "/tmp/UFO")
+ loadfnt(&mem)
- while true
- sdl.delay(1000)
- opcode = mem[pc]
- arg = mem[pc + 1]
- std.put("\x1b[H\x1b[2J")
- std.put("v0: {}\n", reg[0])
- std.put("v1: {}\n", reg[1])
- std.put("v2: {}\n", reg[2])
- std.put("v3: {}\n", reg[3])
- std.put("v4: {}\n", reg[4])
- std.put("v5: {}\n", reg[5])
- std.put("v6: {}\n", reg[6])
- std.put("v7: {}\n", reg[7])
- std.put("v8: {}\n", reg[8])
- std.put("v9: {}\n", reg[9])
- std.put("va: {}\n", reg[10])
- std.put("vb: {}\n", reg[11])
- std.put("vc: {}\n", reg[12])
- std.put("vd: {}\n", reg[13])
- std.put("ve: {}\n", reg[14])
- std.put("vf: {}\n", reg[15])
- std.put("\n")
- std.put("I: {}, d: {}, s: {}\n", I, delay, sound)
- std.put("sp: {}, stk: {}\n", sp, stk)
- std.put("{p=0,x}: {p=0,x} {p=0,x}\n", pc, opcode, arg)
- match (opcode & 0xf0) >> 4
- | 0x0:
- // CLS
- if (opcode & 0x0f) == 0 && (arg & 0x0f) == 0
- clrscr(&gfx, scrsz)
- // RET
- elif (opcode & 0x0f) == 0
- if sp == 0
- std.die("stack underflow")
- ;;
- pc = stk[sp]
- sp--
- // SYS
- else
- std.die("RCA 1802 SYS unimplemted")
- ;;
- // JP
- | 0x1:
- pc = (opcode & 0x0f : uint16)
- pc <<= 8
- pc |= (arg : uint16)
- pc -= 2
- // CALL
- | 0x2:
- sp++
- if sp >= stksz
- std.die("stack overflow")
- ;;
- stk[sp] = pc
- pc = (opcode & 0x0f : uint16)
- pc <<= 8
- pc |= (arg : uint16)
- pc -= 2
- // SE
- | 0x3:
- if reg[opcode & 0x0f] == arg
- pc += 2
- ;;
- // SNE
- | 0x4:
- if reg[opcode & 0x0f] != arg
- pc += 2
- ;;
- // SE
- | 0x5:
- if reg[opcode & 0x0f] == reg[(arg & 0xf0) >> 4]
- pc += 2
- ;;
- // LD
- | 0x6:
- reg[opcode & 0x0f] = arg
- // ADD (without overflow)
- | 0x7:
- reg[opcode & 0x0f] += arg
- | 0x8:
- match arg & 0x0f
- // LD
- | 0x0:
- reg[opcode & 0x0f] = reg[(arg & 0xf0) >> 8]
- // OR
- | 0x1:
- reg[opcode & 0x0f] |= reg[(arg & 0xf0) >> 8]
- // AND
- | 0x2:
- reg[opcode & 0x0f] &= reg[(arg & 0xf0) >> 8]
- // XOR
- | 0x3:
- reg[opcode & 0x0f] ^= reg[(arg & 0xf0) >> 8]
- // ADD
- | 0x4:
- if (0xff - reg[opcode & 0x0f]) < reg[(arg & 0xf0) >> 8]
- reg[0xf] = 1
- else
- reg[0xf] = 0
- ;;
- reg[opcode & 0x0f] += reg[(arg & 0xf0) >> 8]
- // SUB
- | 0x5:
- if (0xff - reg[opcode & 0x0f]) < reg[(arg & 0xf0) >> 8]
- reg[0xf] = 1
- else
- reg[0xf] = 0
- ;;
- reg[opcode & 0x0f] -= reg[(arg & 0xf0) >> 8]
- // SHR
- | 0x6:
- reg[0xf] = reg[opcode & 0x0f] & 1
- reg[opcode & 0x0f] >>= 1
- // SUBN
- | 0x7:
- if (0xff - reg[(arg & 0xf0) >> 8]) < reg[opcode & 0x0f]
- reg[0xf] = 1
- else
- reg[0xf] = 0
- ;;
- reg[opcode & 0x0f] = reg[(arg & 0xf0) >> 8] - reg[opcode & 0x0f]
- // SHL
- | 0xe:
- reg[0xf] = reg[opcode & 0x0f] & (1 << 7)
- reg[opcode & 0x0f] <<= 1
- | _: std.die("unimplemented opcode")
- ;;
- // SNE
- | 0x9:
- if reg[opcode & 0x0f] != reg[(arg & 0xf0) >> 4]
- pc += 2
- ;;
- // LD (I)
- | 0xa:
- I = (opcode & 0x0f : uint16)
- I <<= 8
- I |= (arg : uint16)
- // JP + V0
- | 0xb:
- pc = (opcode & 0x0f : uint16)
- pc <<= 8
- pc |= (arg : uint16)
- pc += (reg[0] : uint16)
- pc -= 2
- // RND
- | 0xc:
- // HACK: SIGFPE when calling std.rand(0, 256)
- reg[opcode & 0x0f] = (std.rand(0, 255) + std.rand(0, 2)) & arg
- // DRW
- | 0xd:
- var x = (reg[opcode & 0x0f] : uint16)
- var y = (reg[(arg & 0xf0) >> 8] : uint16)
- var n = (arg & 0x0f : uint16)
- var i, j
- for i = 0; i < n; i++;
- for j = 0; j < 8; j++
- if (y + i) * scrwidth + x + j < scrsz
- if mem[I + i * 8 + j] != 0
- gfx[(y + i) * scrwidth + x + j] = 0xff
- else
- gfx[(y + i) * scrwidth + x + j] = 0x00
- ;;
- ;;
- ;;
- ;;
- sdl.update(tex, (gfx[:] : void#), 64)
- sdl.copy(r, tex)
- sdl.present(r)
- | 0xe:
- // SKP
- if arg == 0x9e
- // SKNP
- elif arg == 0xa1
- pc += 2
- else
- std.die("unimplemented opcode")
- ;;
- | 0xf:
- match arg
- | 0x07:
- reg[opcode & 0x0f] = delay
- | 0x0a:
- std.die("unimplemented opcode")
- | 0x15:
- delay = reg[opcode & 0x0f]
- | 0x18:
- sound = reg[opcode & 0x0f]
- | 0x1e:
- // TODO: Deal with overflow
- I += (reg[opcode & 0x0f] : uint16)
- | 0x29:
- // TODO
- I = 0
- | 0x33:
- // TODO
- | 0x55:
- // TODO
- | 0x65:
- // TODO
- | _:
- std.die("unimplemented opcode")
- ;;
- | _ : std.die("unimplemented opcode")
- ;;
- pc += 2
- if delay > 0
- delay--
- ;;
- if sound > 0
- sound--
- ;;
- ;;
+ var opcode, arg
- /* sdl.update(tex, (gfx[:] : void#), 64) */
- /* sdl.copy(r, tex) */
- /* sdl.present(r) */
+ while true
+ opcode = mem[pc]
+ arg = mem[pc + 1]
+ keys = getkeys()
+ sdl.delay(2)
+ if keys[0x10] != 0
+ break
+ ;;
+ match (opcode & 0xf0) >> 4
+ | 0x0:
+ // CLS
+ if (opcode & 0x0f) == 0 && (arg & 0x0f) == 0
+ clrscr(&gfx, scrsz)
+ // RET
+ elif (opcode & 0x0f) == 0
+ if sp == 0
+ std.die("stack underflow")
+ ;;
+ sp--
+ pc = stk[sp]
+ // SYS
+ else
+ std.die("RCA 1802 SYS unimplented")
+ ;;
+ // JP
+ | 0x1:
+ pc = (opcode & 0x0f : uint16)
+ pc <<= 8
+ pc |= (arg : uint16)
+ pc -= 2
+ // CALL
+ | 0x2:
+ if sp >= stksz
+ std.die("stack overflow")
+ ;;
+ stk[sp] = pc
+ sp++
+ pc = (opcode & 0x0f : uint16)
+ pc <<= 8
+ pc |= (arg : uint16)
+ pc -= 2
+ // SE
+ | 0x3:
+ if reg[opcode & 0x0f] == arg
+ pc += 2
+ ;;
+ // SNE
+ | 0x4:
+ if reg[opcode & 0x0f] != arg
+ pc += 2
+ ;;
+ // SE
+ | 0x5:
+ if reg[opcode & 0x0f] == reg[(arg & 0xf0) >> 4]
+ pc += 2
+ ;;
+ // LD
+ | 0x6:
+ reg[opcode & 0x0f] = arg
+ // ADD (without overflow)
+ | 0x7:
+ reg[opcode & 0x0f] += arg
+ | 0x8:
+ match arg & 0x0f
+ // LD
+ | 0x0:
+ reg[opcode & 0x0f] = reg[(arg & 0xf0) >> 4]
+ // OR
+ | 0x1:
+ reg[opcode & 0x0f] |= reg[(arg & 0xf0) >> 4]
+ // AND
+ | 0x2:
+ reg[opcode & 0x0f] &= reg[(arg & 0xf0) >> 4]
+ // XOR
+ | 0x3:
+ reg[opcode & 0x0f] ^= reg[(arg & 0xf0) >> 4]
+ // ADD
+ | 0x4:
+ if (0xff - reg[opcode & 0x0f]) < reg[(arg & 0xf0) >> 4]
+ reg[0xf] = 1
+ else
+ reg[0xf] = 0
+ ;;
+ reg[opcode & 0x0f] += reg[(arg & 0xf0) >> 4]
+ // SUB
+ | 0x5:
+ if (0xff - reg[opcode & 0x0f]) < reg[(arg & 0xf0) >> 4]
+ reg[0xf] = 1
+ else
+ reg[0xf] = 0
+ ;;
+ reg[opcode & 0x0f] -= reg[(arg & 0xf0) >> 4]
+ // SHR
+ | 0x6:
+ reg[0xf] = reg[opcode & 0x0f] & 1
+ reg[opcode & 0x0f] >>= 1
+ // SUBN
+ | 0x7:
+ if (0xff - reg[(arg & 0xf0) >> 4]) < reg[opcode & 0x0f]
+ reg[0xf] = 1
+ else
+ reg[0xf] = 0
+ ;;
+ reg[opcode & 0x0f] = reg[(arg & 0xf0) >> 4] - reg[opcode & 0x0f]
+ // SHL
+ | 0xe:
+ reg[0xf] = reg[opcode & 0x0f] & (1 << 7)
+ reg[opcode & 0x0f] <<= 1
+ | _: std.die("unimplemented opcode")
+ ;;
+ // SNE
+ | 0x9:
+ if reg[opcode & 0x0f] != reg[(arg & 0xf0) >> 4]
+ pc += 2
+ ;;
+ // LD (I)
+ | 0xa:
+ I = (opcode & 0x0f : uint16)
+ I <<= 8
+ I |= (arg : uint16)
+ // JP + V0
+ | 0xb:
+ pc = (opcode & 0x0f : uint16)
+ pc <<= 8
+ pc |= (arg : uint16)
+ pc += (reg[0] : uint16)
+ pc -= 2
+ // RND
+ | 0xc:
+ // HACK: SIGFPE when calling std.rand(0, 256)
+ reg[opcode & 0x0f] = (std.rand(0, 255) + std.rand(0, 2)) & arg
+ // DRW
+ | 0xd:
+ var x = (reg[opcode & 0x0f] : uint16)
+ var y = (reg[(arg & 0xf0) >> 4] : uint16)
+ var n = (arg & 0x0f : uint16)
+ var i, j
+ reg[0xf] = 0
+ for i = 0; i < n; i++;
+ for j = 0; j < 8; j++;
+ if (y + i) * scrwidth + x + j < scrsz
+ if mem[I + i] & ((0x80 >> j) : uint8) != 0
+ if gfx[(y + i) * scrwidth + x + j] != 0
+ reg[0xf] = 1
+ ;;
+ gfx[(y + i) * scrwidth + x + j] ^= 0xff
+ ;;
+ ;;
+ ;;
+ ;;
+ sdl.update(tex, (gfx[:] : void#), 64)
+ sdl.copy(r, tex)
+ sdl.present(r)
+ | 0xe:
+ // SKP
+ if arg == 0x9e
+ if keys[reg[opcode & 0x0f]] != 0
+ pc += 2
+ ;;
+ // SKNP
+ elif arg == 0xa1
+ if keys[reg[opcode & 0x0f]] == 0
+ pc += 2
+ ;;
+ else
+ std.die("unimplemented opcode")
+ ;;
+ | 0xf:
+ match arg
+ // LD
+ | 0x07:
+ reg[opcode & 0x0f] = delay
+ // LD
+ | 0x0a:
+ std.die("unimplemented opcode")
+ // LD
+ | 0x15:
+ delay = reg[opcode & 0x0f]
+ // LD
+ | 0x18:
+ sound = reg[opcode & 0x0f]
+ // ADD
+ | 0x1e:
+ I += (reg[opcode & 0x0f] : uint16)
+ if I > 0xfff
+ reg[0xf] = 1
+ ;;
+ // LD
+ | 0x29:
+ I = fntoff + 5 * (reg[opcode & 0x0f] : uint16)
+ // BCD
+ | 0x33:
+ mem[I] = reg[(opcode & 0x0f)] / 100
+ mem[I + 1] = (reg[(opcode & 0x0f)] % 100) / 10
+ // HACK: Assembler error on (opcode & 0x0f) % 10
+ mem[I + 2] = reg[(opcode & 0x0f)] - mem[I + 1] * 10 - mem[I] * 100
+ // LD
+ | 0x55:
+ var i
+ for i = 0; i <= ((opcode & 0x0f) : uint16); i++;
+ mem[I + i] = reg[i]
+ ;;
+ // LD
+ | 0x65:
+ var i
+ for i = 0; i <= ((opcode & 0x0f) : uint16); i++;
+ reg[i] = mem[I + i]
+ ;;
+ | _:
+ std.die("unimplemented opcode")
+ ;;
+ | _ : std.die("unimplemented opcode")
+ ;;
+ pc += 2
+ if delay > 0
+ delay--
+ ;;
+ if sound > 0
+ sound--
+ ;;
+ ;;
- sdl.freerenderer(r)
- sdl.freewin(win)
- sdl.quit()
+ sdl.freerenderer(r)
+ sdl.freewin(win)
+ sdl.quit()
}
diff --git a/sdl.glue.c b/sdl.glue.c
index 18eceee..89d90cd 100644
--- a/sdl.glue.c
+++ b/sdl.glue.c
@@ -64,10 +64,8 @@ void sdl$delay(uint32_t ms)
SDL_Delay(ms);
}
-// SDL_GetKeyboardState
-// SDL_SCANCODE_{}
-
-// 1 2 3 C 1 2 3 4
-// 4 5 6 D This is emulated with these Q W E R
-// 7 8 9 E keyboard keys --> A S D F
-// A 0 B F Z X C V
+const uint8_t *sdl$getkbd(void)
+{
+ SDL_PumpEvents();
+ return SDL_GetKeyboardState(NULL);
+}
diff --git a/sdl.myr b/sdl.myr
index 31026c0..bcbc166 100644
--- a/sdl.myr
+++ b/sdl.myr
@@ -1,36 +1,56 @@
use std
pkg sdl =
- const INIT_VIDEO : uint32 = 32
-
- extern const init : (flags : uint32 -> int)
- extern const quit : (-> void)
+ const INIT_VIDEO : uint32 = 32
- type win = void#
+ extern const init : (flags : uint32 -> int)
+ extern const quit : (-> void)
- const WIN_POS_UNSPEC : int = 536805376
- const WIN_OPENGL : uint32 = 2
+ type win = void#
- extern const mkwin : (title : byte#, x : int, y : int, w : int, h : int, flags : uint32 -> win)
- extern const freewin : (win : win -> void)
+ const WIN_POS_UNSPEC : int = 536805376
+ const WIN_OPENGL : uint32 = 2
- type renderer = void#
+ extern const mkwin : (title : byte#, x : int, y : int, w : int, h : int, flags : uint32 -> win)
+ extern const freewin : (win : win -> void)
- const RENDERER_ACCEL : uint32 = 2
+ type renderer = void#
- extern const mkrenderer : (win : win, index : int, flags: uint32 -> renderer)
- extern const copy : (r : renderer, tex : texture -> int)
- extern const present : (r : renderer -> void)
- extern const freerenderer : (r : renderer -> void)
+ const RENDERER_ACCEL : uint32 = 2
- type texture = void#
+ extern const mkrenderer : (win : win, index : int, flags: uint32 -> renderer)
+ extern const copy : (r : renderer, tex : texture -> int)
+ extern const present : (r : renderer -> void)
+ extern const freerenderer : (r : renderer -> void)
- const PIXFMT_RGB332 : uint32 = 336660481
- const TEXACCESS_STREAM : int = 1
+ type texture = void#
- extern const mktexture : (r : renderer, fmt : uint32, access : int, w : int, h : int -> texture)
- extern const update : (tex : texture, pixels : void#, pitch : int -> int)
- extern const freetexture : (tex : texture -> void)
+ const PIXFMT_RGB332 : uint32 = 336660481
+ const TEXACCESS_STREAM : int = 1
- extern const delay : (ms : uint32 -> void)
+ extern const mktexture : (r : renderer, fmt : uint32, access : int, w : int, h : int -> texture)
+ extern const update : (tex : texture, pixels : void#, pitch : int -> int)
+ extern const freetexture : (tex : texture -> void)
+
+ extern const delay : (ms : uint32 -> void)
+
+ const SCANCODE_1 : uint8 = 30
+ const SCANCODE_2 : uint8 = 31
+ const SCANCODE_3 : uint8 = 32
+ const SCANCODE_4 : uint8 = 33
+ const SCANCODE_Q : uint8 = 20
+ const SCANCODE_W : uint8 = 26
+ const SCANCODE_E : uint8 = 8
+ const SCANCODE_R : uint8 = 21
+ const SCANCODE_A : uint8 = 4
+ const SCANCODE_S : uint8 = 22
+ const SCANCODE_D : uint8 = 7
+ const SCANCODE_F : uint8 = 9
+ const SCANCODE_Z : uint8 = 29
+ const SCANCODE_X : uint8 = 27
+ const SCANCODE_C : uint8 = 6
+ const SCANCODE_V : uint8 = 25
+ const SCANCODE_ESC : uint8 = 41
+
+ extern const getkbd : ( -> uint8[256]#)
;;