tis100

Reimplementation of Zachtronics TIS-100 as a TUI game
git clone https://git.sinitax.com/sinitax/tis100
Log | Files | Refs | sfeed.txt

commit ae4a7b241a033627ed136b2ef66922034cfbeae1
parent f2ada47e6be185cc31c475c996c4ccf6735f7bb0
Author: Louis Burda <quent.burda@gmail.com>
Date:   Mon, 25 Dec 2023 03:08:10 +0100

Add more fixes for game compatibility

Diffstat:
Masm.c | 5+++--
Mtis100-curses.c | 2+-
Mtis100.c | 2+-
Mtpu.c | 45++++++++++++++++++++++++---------------------
Mtpu.h | 4++--
5 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/asm.c b/asm.c @@ -339,6 +339,8 @@ tis_load_asm(struct tis *tis, const char *filepath) size_t len; char c; + tis->asm_filepath = strdup(filepath); + tokenizer.filepath = filepath; tokenizer.file = fopen(filepath, "r"); if (!tokenizer.file) die("load: fopen '%s':", filepath); @@ -544,10 +546,9 @@ tis_load(struct tis *tis, const char **argv) /* after tis_load_asm.. */ arg++; } else { - if (tis->asm_init) + if (tis->asm_filepath) die("multiple asm files"); tis_load_asm(tis, *arg); - tis->asm_init = true; } } diff --git a/tis100-curses.c b/tis100-curses.c @@ -452,7 +452,7 @@ reset(int ifd, int argc, const char **argv, bool watch) tis_load(&tis, argv); if (watch) { - if (inotify_add_watch(ifd, argv[1], IN_MODIFY) < 0) + if (inotify_add_watch(ifd, tis.asm_filepath, IN_MODIFY) < 0) die("inotify_add_watch '%s':", argv[1]); } diff --git a/tis100.c b/tis100.c @@ -59,7 +59,7 @@ main(int argc, const char **argv) printf("=== stats ===\n"); printf(" cycles: %zu\n", stats.steps); printf(" nodes: %zu\n", stats.nodes); - printf(" insts: %zu\n", stats.nodes); + printf(" insts: %zu\n", stats.insts); printf(" idle: %2.1f%%\n", stats.idle * 100); printf("=============\n"); } diff --git a/tpu.c b/tpu.c @@ -137,7 +137,6 @@ tpu_port_init(struct tpu_port *port, struct tpu *tpu) port->dst_port = NULL; port->type = PORT_BIDI; port->reset_in = false; - port->reading = false; port->writing = false; port->avail = false; port->in = -1; @@ -166,13 +165,14 @@ tpu_port_update(struct tpu_port *port) if (port->reset_in && (!port->tpu || !port->tpu->idle)) { port->avail = false; port->dst_port->writing = false; - port->reset_in = false; if ((tpu = port->dst_port->tpu)) { - /* hacky: only allow mode to be RUN after receive */ + /* hacky: switch mode to RUN after receive */ + assert(tpu->mode == MODE_WRITE); tpu->mode = MODE_RUN; tpu->idle = false; if (++tpu->pc >= tpu->inst_cnt) tpu->pc = 0; } + port->reset_in = false; } } @@ -352,18 +352,16 @@ tpu_add_inst(struct tpu *tpu, enum tpu_inst_type inst_type, return &tpu->insts[tpu->inst_cnt++]; } -/* tpu can only read values if there is a writer attached and offering a - * value (->dst_port->out) -- which is cleared on successful read */ +/* tpu can only read values if there is a writer attached and offering + * a value -- this value is cleared on successful read */ static bool tpu_port_read(struct tpu *tpu, enum tpu_port_dir dir, int *lit) { struct tpu_port *port = &tpu->ports[dir]; - if (!port->avail) { - port->reading = true; + if (!port->avail) return false; - } *lit = port->in; port->reset_in = true; @@ -371,23 +369,20 @@ tpu_port_read(struct tpu *tpu, enum tpu_port_dir dir, int *lit) return true; } -/* tpu can always write values (->out) but only finish writing once the - * written value is read and cleared by the reader (->dst_port->in) */ +/* tpu can write value to ->out immediately but only finish the instruction + * once the written value is read and cleared by the reader */ static bool tpu_port_write(struct tpu *tpu, enum tpu_port_dir dir, int lit) { struct tpu_port *port = &tpu->ports[dir]; - if (port->writing) { + if (port->writing) return false; - } port->writing = true; port->out = lit; - /* port writing never succeeds right away, only after - * value was read in tpu_update is tpu->idle/mode fixed up */ return true; } @@ -473,16 +468,21 @@ tpu_exec(struct tpu *tpu, struct tpu_inst *inst) tpu->pc += 1; return MODE_RUN; case INST_MOV: - if (tpu->mode != MODE_WRITE) { - if (!tpu_exec_get(tpu, &inst->ops[0], &lit)) { - tpu->idle = true; - return MODE_READ; - } + if (tpu->mode == MODE_WRITE) { + tpu->idle = true; + return MODE_WRITE; + } + if (!tpu_exec_get(tpu, &inst->ops[0], &lit)) { + tpu->idle = true; + return MODE_READ; } if (!tpu_exec_put(tpu, &inst->ops[1], lit)) { tpu->idle = true; return MODE_WRITE; } + /* if MOV to port, set WRITE tentatively and fix on reset_in */ + if (inst->ops[1].type != OP_ACC && inst->ops[1].type != OP_NIL) + return MODE_WRITE; tpu->pc += 1; return MODE_RUN; case INST_SWP: @@ -504,8 +504,10 @@ tpu_exec(struct tpu *tpu, struct tpu_inst *inst) tpu->pc += 1; return MODE_RUN; case INST_SUB: - if (!tpu_exec_get(tpu, &inst->ops[0], &val)) + if (!tpu_exec_get(tpu, &inst->ops[0], &val)) { + tpu->idle = true; return MODE_READ; + } tpu->acc = MIN(MAX(tpu->acc - val, -999), 999); tpu->pc += 1; return MODE_RUN; @@ -640,7 +642,7 @@ tis_init(struct tis *tis) memset(&tis->out_ports, 0, TIS_MAX_IO_PORTS * sizeof(void *)); tis->steps = 0; tis->show_stats = false; - tis->asm_init = false; + tis->asm_filepath = NULL; } void @@ -659,6 +661,7 @@ tis_deinit(struct tis *tis) free(tis->out_ports[i]); } } + free(tis->asm_filepath); } bool diff --git a/tpu.h b/tpu.h @@ -73,7 +73,7 @@ struct tpu_port { bool attached; int in, out; - bool avail, reading, writing; + bool avail, writing; bool reset_in; }; @@ -126,7 +126,7 @@ struct tis { struct tpu_io_port *out_ports[TIS_MAX_IO_PORTS]; size_t steps; bool show_stats; - bool asm_init; + char *asm_filepath; }; struct tis_stats {