summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>2020-01-03 11:51:14 -0500
committerJakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>2020-01-03 11:51:14 -0500
commitb43bb071d63e427834291ef1242555b82091ce9d (patch)
treebc1e04b142db9d6a8716c50637fc12222cdeac2f
parentfda114b48f16caac4362b7205ef7111db264d7cc (diff)
Indent with tabs.
-rw-r--r--asm.myr674
-rw-r--r--main.myr108
2 files changed, 429 insertions, 353 deletions
diff --git a/asm.myr b/asm.myr
index 40e89fb..086e352 100644
--- a/asm.myr
+++ b/asm.myr
@@ -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)
}
diff --git a/main.myr b/main.myr
index 0684871..feac70c 100644
--- a/main.myr
+++ b/main.myr
@@ -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)