diff options
| author | Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org> | 2020-01-03 11:51:14 -0500 |
|---|---|---|
| committer | Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org> | 2020-01-03 11:51:14 -0500 |
| commit | b43bb071d63e427834291ef1242555b82091ce9d (patch) | |
| tree | bc1e04b142db9d6a8716c50637fc12222cdeac2f | |
| parent | fda114b48f16caac4362b7205ef7111db264d7cc (diff) | |
Indent with tabs.
| -rw-r--r-- | asm.myr | 674 | ||||
| -rw-r--r-- | main.myr | 108 |
2 files changed, 429 insertions, 353 deletions
@@ -2,384 +2,374 @@ use bio use std const strdup = {s - var buf = std.slalloc(s.len) - std.slcp(buf, s) - -> buf + var buf = std.slalloc(s.len) + std.slcp(buf, s) + -> buf } const upcase = {s - var i - var buf = std.mksb() - for i = 0; i < s.len; i++ - std.sbputc(buf, std.toupper((s[i] : char))) - ;; - -> std.sbfin(buf) + var i + var buf = std.mksb() + for i = 0; i < s.len; i++ + std.sbputc(buf, std.toupper((s[i] : char))) + ;; + -> std.sbfin(buf) } const readline = {line - var cmt = std.strfind(line, ";") + var cmt = std.strfind(line, ";") - match cmt - | `std.Some (pos): line = line[:pos] - | `std.None: - ;; + match cmt + | `std.Some (pos): line = line[:pos] + | `std.None: + ;; - if line.len == 0 - -> (`std.None, [][:]) - ;; + if line.len == 0 + -> (`std.None, [][:]) + ;; - var parts = std.strtok(line) - if std.isspace((line[0] : char)) - -> (`std.None, parts) - else - -> (`std.Some(parts[0]), parts[1:]) - ;; + var parts = std.strtok(line) + if std.isspace((line[0] : char)) + -> (`std.None, parts) + else + -> (`std.Some(parts[0]), parts[1:]) + ;; } type literal = union - `Number int - `Register int - `Label byte[:] - `DerefAddr - `Keypress - `AddressRegister - `DelayTimer - `SoundTimer - `Invalid + `Number int + `Register int + `Label byte[:] + `DerefAddr + `Keypress + `AddressRegister + `DelayTimer + `SoundTimer + `Invalid ;; const getnum = {s - -> std.intparsebase((s[1:] : byte[:]), 16) + -> std.intparsebase((s[1:] : byte[:]), 16) } const parselit = {s - if s.len < 1 - -> `Invalid - elif s[0] == ('#' : byte) - match getnum(s) - |`std.Some(n): -> `Number(n) - |`std.None: -> `Invalid - ;; - elif s[0] == ('v' : byte) || s[0] == ('V' : byte) - match getnum(s) - |`std.Some(n): -> `Register(n) - |`std.None: -> `Invalid - ;; - elif std.isdigit((s[0] : char)) - match std.intparsebase((s : byte[:]), 10) - |`std.Some(n): -> `Number(n) - |`std.None: -> `Label(s) - ;; - elif s[0] == ('[' : byte) - -> `DerefAddr - elif s[0] == ('K' : byte) - -> `Keypress - elif s[0] == ('I' : byte) - -> `AddressRegister - elif s[0] == ('D' : byte) - -> `DelayTimer - elif s[0] == ('S' : byte) - -> `SoundTimer - else - -> `Label(s) - ;; + if s.len < 1 + -> `Invalid + elif s[0] == ('#' : byte) + match getnum(s) + |`std.Some(n): -> `Number(n) + |`std.None: -> `Invalid + ;; + elif s[0] == ('v' : byte) || s[0] == ('V' : byte) + match getnum(s) + |`std.Some(n): -> `Register(n) + |`std.None: -> `Invalid + ;; + elif std.isdigit((s[0] : char)) + match std.intparsebase((s : byte[:]), 10) + |`std.Some(n): -> `Number(n) + |`std.None: -> `Label(s) + ;; + elif s[0] == ('[' : byte) + -> `DerefAddr + elif s[0] == ('K' : byte) + -> `Keypress + elif s[0] == ('I' : byte) + -> `AddressRegister + elif s[0] == ('D' : byte) + -> `DelayTimer + elif s[0] == ('S' : byte) + -> `SoundTimer + else + -> `Label(s) + ;; } const emitinstr = {p - var b = `std.None - var mark = `std.None + var b = `std.None + var mark = `std.None - if p.len < 1 - -> `std.Ok(b, mark) - ;; + if p.len < 1 + -> `std.Ok(b, mark) + ;; - match upcase(p[0]) - | "CLS": - b = `std.Some([0x00, 0xe0]) - | "RET": - b = `std.Some([0x00, 0xee]) - | "SYS": - if p.len < 2 - -> `std.Err("SYS missing subroutine address") - ;; - match parselit(p[1]) - | `Number(n): b = `std.Some([0x00 | (n & 0x0f00), (n & 0xff)]) - | `Label(l): b = `std.Some([0x00, 0x00]) - mark = `std.Some(strdup(l)) - | _: - -> `std.Err(std.fmt("invalid arguments to SYS: {}", p[1:])) - ;; - | "CALL": - if p.len < 2 - -> `std.Err("CALL missing subroutine address") - ;; - match parselit(p[1]) - | `Number(n): b = `std.Some([0x20 | (n & 0x0f00), (n & 0xff)]) - | `Label(l): b = `std.Some([0x20, 0x00]) - mark = `std.Some(strdup(l)) - | _: - -> `std.Err(std.fmt("invalid arguments to CALL: {}", p[1:])) - ;; - | "JP": - if p.len < 2 - -> `std.Err("JP missing address") - elif p.len == 2 - match parselit(p[1]) - | `Number(n): b = `std.Some([0x10 | (n & 0x0f00), (n & 0xff)]) - | `Label(l): b = `std.Some([0x10, 0x00]) - mark = `std.Some(strdup(l)) - | _: - -> `std.Err(std.fmt("invalid arguments to JP: {}", p[1:])) - ;; - else - match (parselit(p[1]), parselit(p[2])) - | (`Register(0), `Number(n)): - b = `std.Some([0xb0 | (n & 0x0f00), (n & 0xff)]) - | (`Register(0), `Label(l)): b = `std.Some([0xb0, 0x00]) - mark = `std.Some(strdup(l)) - | _: - -> `std.Err(std.fmt("invalid arguments to JP: {}", p[1:])) - ;; - ;; - | "SE": - if p.len < 3 - -> `std.Err("SE missing arguments") - ;; - match (parselit(p[1]), parselit(p[2])) - | (`Register(m), `Number(n)): - b = `std.Some([0x30 | (m & 0x0f), (n & 0xff)]) - | (`Register(m), `Register(n)): - b = `std.Some([0x50 | (m & 0x0f), (n & 0x0f) << 4]) - | _: - -> `std.Err(std.fmt("invalid arguments to SE: {}", p[1:])) - ;; - | "SNE": - if p.len < 3 - -> `std.Err("SNE missing arguments") - ;; - match (parselit(p[1]), parselit(p[2])) - | (`Register(m), `Number(n)): - b = `std.Some([0x40 | (m & 0x0f), (n & 0xff)]) - | (`Register(m), `Register(n)): - b = `std.Some([0x90 | (m & 0x0f), (n & 0x0f) << 4]) - | _: - -> `std.Err(std.fmt("invalid arguments to SNE: {}", p[1:])) - ;; - | "SKP": - if p.len < 2 - -> `std.Err("SKP missing address") - ;; - match parselit(p[1]) - | `Register(n): b = `std.Some([0xe0 | (n & 0x0f), 0x9e]) - | _: - -> `std.Err(std.fmt("invalid arguments to SKP: {}", p[1:])) - ;; - | "SKNP": - if p.len < 2 - -> `std.Err("SKNP missing address") - ;; - match parselit(p[1]) - | `Register(n): b = `std.Some([0xe0 | (n & 0x0f), 0xa1]) - | _: - -> `std.Err(std.fmt("invalid arguments to SKNP: {}", p[1:])) - ;; - | "LD": - if p.len < 3 - -> `std.Err("LD missing arguments") - ;; - match (parselit(p[1]), parselit(p[2])) - | (`Register(n), `Keypress): b = `std.Some([0xf0 | (n & 0x0f), 0x0a]) - | (`Register(m), `Number(n)): b = `std.Some([0x60 | (m & 0x0f), (n & 0xff)]) - | (`Register(m), `Register(n)): b = `std.Some([0x80 | (n & 0x0f), (m & 0x0f) << 4]) - | (`Register(n), `DelayTimer): b = `std.Some([0xf0 | (n & 0x0f), 0x07]) - | (`DelayTimer, `Register(n)): b = `std.Some([0xf0 | (n & 0x0f), 0x15]) - | (`SoundTimer, `Register(n)): b = `std.Some([0xf0 | (n & 0x0f), 0x18]) - | (`AddressRegister, `Number(n)): b = `std.Some([0xa0 | (n & 0x0f), (n & 0xff)]) - | (`AddressRegister, `Label(l)): b = `std.Some([0xa0, 0x00]) - mark = `std.Some(strdup(l)) - | (`DerefAddr, `Register(n)): b = `std.Some([0xf0 | (n & 0x0f), 0x55]) - | (`Register(n), `DerefAddr): b = `std.Some([0xf0 | (n & 0x0f), 0x65]) - | _: - -> `std.Err(std.fmt("invalid arguments to LD: {}", p[1:])) - ;; - | "ADD": - if p.len < 3 - -> `std.Err("ADD missing arguments") - ;; - match (parselit(p[1]), parselit(p[2])) - | (`AddressRegister, `Register(n)): b = `std.Some([0xf0 | (n & 0x0f), 0x1e]) - | (`Register(m), `Number(n)): b = `std.Some([0x70 | (m & 0x0f), n & 0xff]) - | (`Register(m), `Register(n)): b = `std.Some([0x80 | (m & 0x0f), ((n & 0x0f) << 4) | 0x04]) - | _: - -> `std.Err(std.fmt("invalid arguments to ADD: {}", p[1:])) - ;; - | "SUB": - if p.len < 3 - -> `std.Err("SUB missing arguments") - ;; - match (parselit(p[1]), parselit(p[2])) - | (`Register(m), `Register(n)): b = `std.Some([0x80 | (m & 0x0f), ((n & 0x0f) << 4) | 0x05]) - | _: - -> `std.Err(std.fmt("invalid arguments to SUB: {}", p[1:])) - ;; - | "SUBN": - if p.len < 3 - -> `std.Err("SUBN missing arguments") - ;; - match (parselit(p[1]), parselit(p[2])) - | (`Register(m), `Register(n)): b = `std.Some([0x80 | (m & 0x0f), ((n & 0x0f) << 4) | 0x07]) - | _: - -> `std.Err(std.fmt("invalid arguments to SUBN: {}", p[1:])) - ;; - | "OR": - if p.len < 3 - -> `std.Err("OR missing arguments") - ;; - match (parselit(p[1]), parselit(p[2])) - | (`Register(m), `Register(n)): b = `std.Some([0x80 | (m & 0x0f), ((n & 0x0f) << 4) | 0x01]) - | _: - -> `std.Err(std.fmt("invalid arguments to OR: {}", p[1:])) - ;; - | "AND": - if p.len < 3 - -> `std.Err("AND missing arguments") - ;; - match (parselit(p[1]), parselit(p[2])) - | (`Register(m), `Register(n)): b = `std.Some([0x80 | (m & 0x0f), ((n & 0x0f) << 4) | 0x02]) - | _: - -> `std.Err(std.fmt("invalid arguments to AND: {}", p[1:])) - ;; - | "XOR": - if p.len < 3 - -> `std.Err("XOR missing arguments") - ;; - match (parselit(p[1]), parselit(p[2])) - | (`Register(m), `Register(n)): b = `std.Some([0x80 | (m & 0x0f), ((n & 0x0f) << 4) | 0x03]) - | _: - -> `std.Err(std.fmt("invalid arguments to XOR: {}", p[1:])) - ;; - | "SHR": - if p.len < 2 - -> `std.Err("SHR missing arguments") - ;; - match parselit(p[1]) - | `Register(n): b = `std.Some([0x80 | (n & 0x0f), 0x06]) - | _: - -> `std.Err(std.fmt("invalid arguments to SHR: {}", p[1:])) - ;; - | "SHL": - if p.len < 2 - -> `std.Err("SHL missing arguments") - ;; - match parselit(p[1]) - | `Register(n): b = `std.Some([0x80 | (n & 0x0f), 0x0e]) - | _: - -> `std.Err(std.fmt("invalid arguments to SHL: {}", p[1:])) - ;; - | "BCD": - if p.len < 2 - -> `std.Err("BCD missing arguments") - ;; - match parselit(p[1]) - | `Register(n): `std.Some([0xf0 | (n & 0x0f), 0x33]) - | _: - -> `std.Err(std.fmt("invalid arguments to BCD: {}", p[1:])) - ;; - | "RND": - if p.len < 3 - -> `std.Err("RND missing arguments") - ;; - match (parselit(p[1]), parselit(p[2])) - | (`Register(m), `Number(n)): b = `std.Some([0xc0 | (m & 0x0f), n & 0xff]) - | _: - -> `std.Err(std.fmt("invalid arguments to RND: {}", p[1:])) - ;; - | "DRW": - if p.len < 4 - -> `std.Err("DRW missing arguments") - ;; - match (parselit(p[1]), parselit(p[2]), parselit(p[3])) - | (`Register(m), `Register(n), `Number(q)): b = `std.Some([0xd0 | (m & 0x0f), (n & 0x0f) << 4 | (q & 0x0f)]) - | _: - -> `std.Err(std.fmt("invalid arguments to DRW: {}", p[1:])) - ;; - | _: - -> `std.Err(std.fmt("unrecognized instruction {}", p[0])) - ;; + match upcase(p[0]) + | "CLS": + b = `std.Some([0x00, 0xe0]) + | "RET": + b = `std.Some([0x00, 0xee]) + | "SYS": + if p.len < 2 + -> `std.Err("SYS missing subroutine address") + ;; + match parselit(p[1]) + | `Number(n): b = `std.Some([0x00 | (n & 0x0f00), (n & 0xff)]) + | `Label(l): b = `std.Some([0x00, 0x00]) + mark = `std.Some(strdup(l)) + | _: + -> `std.Err(std.fmt("invalid arguments to SYS: {}", p[1:])) + ;; + | "CALL": + if p.len < 2 + -> `std.Err("CALL missing subroutine address") + ;; + match parselit(p[1]) + | `Number(n): b = `std.Some([0x20 | (n & 0x0f00), (n & 0xff)]) + | `Label(l): b = `std.Some([0x20, 0x00]) + mark = `std.Some(strdup(l)) + | _: + -> `std.Err(std.fmt("invalid arguments to CALL: {}", p[1:])) + ;; + | "JP": + if p.len < 2 + -> `std.Err("JP missing address") + elif p.len == 2 + match parselit(p[1]) + | `Number(n): b = `std.Some([0x10 | (n & 0x0f00), (n & 0xff)]) + | `Label(l): b = `std.Some([0x10, 0x00]) + mark = `std.Some(strdup(l)) + | _: + -> `std.Err(std.fmt("invalid arguments to JP: {}", p[1:])) + ;; + else + match (parselit(p[1]), parselit(p[2])) + | (`Register(0), `Number(n)): + b = `std.Some([0xb0 | (n & 0x0f00), (n & 0xff)]) + | (`Register(0), `Label(l)): b = `std.Some([0xb0, 0x00]) + mark = `std.Some(strdup(l)) + | _: + -> `std.Err(std.fmt("invalid arguments to JP: {}", p[1:])) + ;; + ;; + | "SE": + if p.len < 3 + -> `std.Err("SE missing arguments") + ;; + match (parselit(p[1]), parselit(p[2])) + | (`Register(m), `Number(n)): + b = `std.Some([0x30 | (m & 0x0f), (n & 0xff)]) + | (`Register(m), `Register(n)): + b = `std.Some([0x50 | (m & 0x0f), (n & 0x0f) << 4]) + | _: + -> `std.Err(std.fmt("invalid arguments to SE: {}", p[1:])) + ;; + | "SNE": + if p.len < 3 + -> `std.Err("SNE missing arguments") + ;; + match (parselit(p[1]), parselit(p[2])) + | (`Register(m), `Number(n)): + b = `std.Some([0x40 | (m & 0x0f), (n & 0xff)]) + | (`Register(m), `Register(n)): + b = `std.Some([0x90 | (m & 0x0f), (n & 0x0f) << 4]) + | _: + -> `std.Err(std.fmt("invalid arguments to SNE: {}", p[1:])) + ;; + | "SKP": + if p.len < 2 + -> `std.Err("SKP missing address") + ;; + match parselit(p[1]) + | `Register(n): b = `std.Some([0xe0 | (n & 0x0f), 0x9e]) + | _: + -> `std.Err(std.fmt("invalid arguments to SKP: {}", p[1:])) + ;; + | "SKNP": + if p.len < 2 + -> `std.Err("SKNP missing address") + ;; + match parselit(p[1]) + | `Register(n): b = `std.Some([0xe0 | (n & 0x0f), 0xa1]) + | _: + -> `std.Err(std.fmt("invalid arguments to SKNP: {}", p[1:])) + ;; + | "LD": + if p.len < 3 + -> `std.Err("LD missing arguments") + ;; + match (parselit(p[1]), parselit(p[2])) + | (`Register(n), `Keypress): b = `std.Some([0xf0 | (n & 0x0f), 0x0a]) + | (`Register(m), `Number(n)): b = `std.Some([0x60 | (m & 0x0f), (n & 0xff)]) + | (`Register(m), `Register(n)): b = `std.Some([0x80 | (n & 0x0f), (m & 0x0f) << 4]) + | (`Register(n), `DelayTimer): b = `std.Some([0xf0 | (n & 0x0f), 0x07]) + | (`DelayTimer, `Register(n)): b = `std.Some([0xf0 | (n & 0x0f), 0x15]) + | (`SoundTimer, `Register(n)): b = `std.Some([0xf0 | (n & 0x0f), 0x18]) + | (`AddressRegister, `Number(n)): b = `std.Some([0xa0 | (n & 0x0f), (n & 0xff)]) + | (`AddressRegister, `Label(l)): b = `std.Some([0xa0, 0x00]) + mark = `std.Some(strdup(l)) + | (`DerefAddr, `Register(n)): b = `std.Some([0xf0 | (n & 0x0f), 0x55]) + | (`Register(n), `DerefAddr): b = `std.Some([0xf0 | (n & 0x0f), 0x65]) + | _: + -> `std.Err(std.fmt("invalid arguments to LD: {}", p[1:])) + ;; + | "ADD": + if p.len < 3 + -> `std.Err("ADD missing arguments") + ;; + match (parselit(p[1]), parselit(p[2])) + | (`AddressRegister, `Register(n)): b = `std.Some([0xf0 | (n & 0x0f), 0x1e]) + | (`Register(m), `Number(n)): b = `std.Some([0x70 | (m & 0x0f), n & 0xff]) + | (`Register(m), `Register(n)): b = `std.Some([0x80 | (m & 0x0f), ((n & 0x0f) << 4) | 0x04]) + | _: + -> `std.Err(std.fmt("invalid arguments to ADD: {}", p[1:])) + ;; + | "SUB": + if p.len < 3 + -> `std.Err("SUB missing arguments") + ;; + match (parselit(p[1]), parselit(p[2])) + | (`Register(m), `Register(n)): b = `std.Some([0x80 | (m & 0x0f), ((n & 0x0f) << 4) | 0x05]) + | _: + -> `std.Err(std.fmt("invalid arguments to SUB: {}", p[1:])) + ;; + | "SUBN": + if p.len < 3 + -> `std.Err("SUBN missing arguments") + ;; + match (parselit(p[1]), parselit(p[2])) + | (`Register(m), `Register(n)): b = `std.Some([0x80 | (m & 0x0f), ((n & 0x0f) << 4) | 0x07]) + | _: + -> `std.Err(std.fmt("invalid arguments to SUBN: {}", p[1:])) + ;; + | "OR": + if p.len < 3 + -> `std.Err("OR missing arguments") + ;; + match (parselit(p[1]), parselit(p[2])) + | (`Register(m), `Register(n)): b = `std.Some([0x80 | (m & 0x0f), ((n & 0x0f) << 4) | 0x01]) + | _: + -> `std.Err(std.fmt("invalid arguments to OR: {}", p[1:])) + ;; + | "AND": + if p.len < 3 + -> `std.Err("AND missing arguments") + ;; + match (parselit(p[1]), parselit(p[2])) + | (`Register(m), `Register(n)): b = `std.Some([0x80 | (m & 0x0f), ((n & 0x0f) << 4) | 0x02]) + | _: + -> `std.Err(std.fmt("invalid arguments to AND: {}", p[1:])) + ;; + | "XOR": + if p.len < 3 + -> `std.Err("XOR missing arguments") + ;; + match (parselit(p[1]), parselit(p[2])) + | (`Register(m), `Register(n)): b = `std.Some([0x80 | (m & 0x0f), ((n & 0x0f) << 4) | 0x03]) + | _: + -> `std.Err(std.fmt("invalid arguments to XOR: {}", p[1:])) + ;; + | "SHR": + if p.len < 2 + -> `std.Err("SHR missing arguments") + ;; + match parselit(p[1]) + | `Register(n): b = `std.Some([0x80 | (n & 0x0f), 0x06]) + | _: + -> `std.Err(std.fmt("invalid arguments to SHR: {}", p[1:])) + ;; + | "SHL": + if p.len < 2 + -> `std.Err("SHL missing arguments") + ;; + match parselit(p[1]) + | `Register(n): b = `std.Some([0x80 | (n & 0x0f), 0x0e]) + | _: + -> `std.Err(std.fmt("invalid arguments to SHL: {}", p[1:])) + ;; + | "BCD": + if p.len < 2 + -> `std.Err("BCD missing arguments") + ;; + match parselit(p[1]) + | `Register(n): `std.Some([0xf0 | (n & 0x0f), 0x33]) + | _: + -> `std.Err(std.fmt("invalid arguments to BCD: {}", p[1:])) + ;; + | "RND": + if p.len < 3 + -> `std.Err("RND missing arguments") + ;; + match (parselit(p[1]), parselit(p[2])) + | (`Register(m), `Number(n)): b = `std.Some([0xc0 | (m & 0x0f), n & 0xff]) + | _: + -> `std.Err(std.fmt("invalid arguments to RND: {}", p[1:])) + ;; + | "DRW": + if p.len < 4 + -> `std.Err("DRW missing arguments") + ;; + match (parselit(p[1]), parselit(p[2]), parselit(p[3])) + | (`Register(m), `Register(n), `Number(q)): b = `std.Some([0xd0 | (m & 0x0f), (n & 0x0f) << 4 | (q & 0x0f)]) + | _: + -> `std.Err(std.fmt("invalid arguments to DRW: {}", p[1:])) + ;; + | _: + -> `std.Err(std.fmt("unrecognized instruction {}", p[0])) + ;; - -> `std.Ok((b, mark)) + -> `std.Ok((b, mark)) } -const die_emit = {msg, lc - std.die(std.fmt("{} on line {}\n", msg, lc)) -} - -const die_rewrite = {l, lc - const s = "ref to undefined label '{}' on line {}\n" - std.die(std.fmt(s, l, lc)) -} - - /* convert `arr` to a byte[:] slice */ const itob = {arr - var i - var ret = std.slalloc(arr.len) - for i = 0; i < arr.len; i++; - ret[i] = ((arr[i] & 0xff) : byte) - ;; - -> ret + var i + var ret = std.slalloc(arr.len) + for i = 0; i < arr.len; i++; + ret[i] = ((arr[i] & 0xff) : byte) + ;; + -> ret } const main = { - var fd = bio.mkfile(std.In, bio.Rd) - var src = bio.byline(fd) - var lc = 0 + var fd = bio.mkfile(std.In, bio.Rd) + var src = bio.byline(fd) + var lc = 0 - var offset = 0 - var buf = [][:] - var q = [][:] - var labels = std.mkht() - var res + var offset = 0 + var buf = [][:] + var q = [][:] + var labels = std.mkht() + var res - for line : src ; - match readline(line) - | (`std.None, i): res = emitinstr(i) - | (`std.Some (label), i): res = emitinstr(i) - std.htput(labels, strdup(label), offset) - ;; + for line : src ; + match readline(line) + | (`std.None, i): res = emitinstr(i) + | (`std.Some (label), i): res = emitinstr(i) + std.htput(labels, strdup(label), offset) + ;; - match res - | `std.Err(msg): die_emit(msg, lc) - | `std.Ok((bytes, marker)): - match marker - | `std.Some(label): - q = std.slpush(&q, (label, offset, lc)) - | `std.None: - ;; - match bytes - | `std.Some(arr): - buf = std.sljoin(&buf, arr[:]) - offset += 2 - | `std.None: - ;; - ;; + match res + | `std.Err(msg): std.fatal("{} on line {}\n", msg, lc) + | `std.Ok((bytes, marker)): + match marker + | `std.Some(label): + q = std.slpush(&q, (label, offset, lc)) + | `std.None: + ;; + match bytes + | `std.Some(arr): + buf = std.sljoin(&buf, arr[:]) + offset += 2 + | `std.None: + ;; + ;; - lc++ - ;; + lc++ + ;; - for p : q ; - match p - | (l, buf_pos, linum): - match std.htget(labels, l) - | `std.None: die_rewrite(l, linum) - | `std.Some(addr): - buf[buf_pos] |= ((addr + 0x200) & 0x0f00) >> 8 - buf[buf_pos + 1] |= (addr + 0x200) & 0xff - ;; - ;; - ;; + for p : q ; + match p + | (l, buf_pos, linum): + match std.htget(labels, l) + | `std.None: std.fatal("ref to undefined label '{}' on line {}\n", l, linum) + | `std.Some(addr): + buf[buf_pos] |= ((addr + 0x200) & 0x0f00) >> 8 + buf[buf_pos + 1] |= (addr + 0x200) & 0xff + ;; + ;; + ;; - std.write(std.Out, itob(buf)) + std.write(std.Out, itob(buf)) - bio.free(fd) + bio.free(fd) } @@ -24,7 +24,7 @@ const loadprg = {b, fname match std.open(fname, std.Oread) | `std.Ok(n): fd = n | `std.Err(errno): - std.die(std.fmt("could not open {}\n", fname)) + std.fatal("could not open {}\n", fname) ;; buf = std.slalloc(0xfff - 0x200) @@ -34,7 +34,7 @@ const loadprg = {b, fname b#[i + 0x200] = (buf[i] : uint8) ;; | `std.Err(n): - std.die(std.fmt("could not read {}\n", fname)) + std.fatal("could not read {}\n", fname) ;; } @@ -61,13 +61,35 @@ const main = { var sound : uint8 = 0 clrscr(&gfx, scrsz) - loadprg(&mem, "/home/jakob/Airplane.ch8") + loadprg(&mem, "/tmp/UFO") var opcode, arg 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 @@ -82,23 +104,25 @@ const main = { sp-- // SYS else - std.die("RCA 1802 SYS unimplemted\n") + 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\n") + 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 @@ -166,7 +190,7 @@ const main = { | 0xe: reg[0xf] = reg[opcode & 0x0f] & (1 << 7) reg[opcode & 0x0f] <<= 1 - | _: std.die("unimplemented opcode\n") + | _: std.die("unimplemented opcode") ;; // SNE | 0x9: @@ -184,17 +208,79 @@ const main = { pc <<= 8 pc |= (arg : uint16) pc += (reg[0] : uint16) + pc -= 2 // RND | 0xc: - reg[opcode & 0x0f] = std.rand(0, 256) & arg - | _ : std.die("unimplemented opcode\n") + // 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-- + ;; ;; - sdl.update(tex, (gfx[:] : void#), 64) - sdl.copy(r, tex) - sdl.present(r) + /* sdl.update(tex, (gfx[:] : void#), 64) */ + /* sdl.copy(r, tex) */ + /* sdl.present(r) */ sdl.freerenderer(r) sdl.freewin(win) |