diff --git a/etc/asma-test.sh b/etc/asma-test.sh deleted file mode 100755 index 5cb8904..0000000 --- a/etc/asma-test.sh +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/sh -set -e -cd "$(dirname "${0}")/.." -rm -rf asma-test -mkdir asma-test - -expect_failure() { - cat > asma-test/in.tal - bin/uxncli asma-test/asma.rom asma-test/in.tal asma-test/out.rom 2> asma-test/asma.log - if ! grep -qF "${1}" asma-test/asma.log; then - echo "error: asma didn't report error ${1} in faulty code" - cat asma-test/asma.log - exit 1 - fi -} - -echo 'Assembling asma with uxnasm' -if ! bin/uxnasm projects/software/asma.tal asma-test/asma.rom > asma-test/uxnasm.log; then - echo 'Failed to assemble asma!' - cat asma-test/uxnasm.log - exit 1 -fi -for F in $(find projects -path projects/library -prune -false -or -path projects/assets -prune -false -or -type f -name '*.tal' | sort); do - echo "Comparing assembly of ${F}" - - UASM_BASE="asma-test/uxnasm-$(basename "${F%.tal}")" - if ! bin/uxnasm "${F}" "${UASM_BASE}.rom" 2> "${UASM_BASE}.log"; then - echo "error: uxnasm failed to assemble ${F}" - cat "${UASM_BASE}.log" - exit 1 - fi - xxd "${UASM_BASE}.rom" > "${UASM_BASE}.hex" - - ASMA_BASE="asma-test/asma-$(basename "${F%.tal}")" - bin/uxncli asma-test/asma.rom "${F}" "${ASMA_BASE}.rom" 2> "${ASMA_BASE}.log" - if ! grep -qF 'bytes of heap used' "${ASMA_BASE}.log"; then - echo "error: asma failed to assemble ${F}, while uxnasm succeeded" - cat "${ASMA_BASE}.log" - exit 1 - fi - xxd "${ASMA_BASE}.rom" > "${ASMA_BASE}.hex" - - diff -u "${UASM_BASE}.hex" "${ASMA_BASE}.hex" -done -expect_failure 'Invalid hexadecimal: $defg' <<'EOD' -|1000 $defg -EOD -expect_failure 'Invalid hexadecimal: #defg' <<'EOD' -|1000 #defg -EOD -expect_failure 'Invalid hexadecimal: #' <<'EOD' -|1000 # -EOD -expect_failure 'Invalid hexadecimal: #0' <<'EOD' -|1000 #0 -EOD -expect_failure 'Invalid hexadecimal: #000' <<'EOD' -|1000 #000 -EOD -expect_failure 'Label not found: 0' <<'EOD' -|1000 0 -EOD -expect_failure 'Label not found: 000' <<'EOD' -|1000 000 -EOD -expect_failure 'Address not in zero page: .hello' <<'EOD' -|1000 @hello - .hello -EOD -expect_failure 'Address not in zero page: -hello' <<'EOD' -|1000 @hello - -hello -EOD -expect_failure 'Address outside range: ,hello' <<'EOD' -|1000 @hello -|2000 ,hello -EOD -expect_failure 'Label not found: hello' <<'EOD' -hello -EOD -expect_failure 'Macro already exists: %me' <<'EOD' -%me { #00 } -%me { #01 } -EOD -expect_failure 'Memory overwrite: SUB' <<'EOD' -|2000 ADD -|1000 SUB -EOD -# expect_failure 'Recursion level too deep:' <<'EOD' -# %me { you } -# %you { me } -# |1000 me -# EOD -# expect_failure 'Recursion level too deep: ~asma-test/in.tal' <<'EOD' -# ~asma-test/in.tal -# EOD -expect_failure 'Label not found: ;blah' <<'EOD' -|1000 ;blah -EOD -expect_failure 'Label not found: :blah' <<'EOD' -|1000 :blah -EOD -expect_failure 'Label not found: =blah' <<'EOD' -|1000 =blah -EOD -expect_failure 'Label not found: -blah' <<'EOD' -|1000 -blah -EOD -expect_failure 'Label not found: ,blah' <<'EOD' -|1000 ,blah -EOD -expect_failure 'Label not found: .blah' <<'EOD' -|1000 .blah -EOD -expect_failure "Label not found: 'a" <<'EOD' -|1000 'a -EOD -echo 'All OK' - diff --git a/etc/asma.lua b/etc/asma.lua deleted file mode 100644 index 471e1be..0000000 --- a/etc/asma.lua +++ /dev/null @@ -1,103 +0,0 @@ -local output = assert(io.open('.asma.tal', 'w')) -local process_subtree -process_subtree = function(items) - local middle = math.floor(#items / 2 + 1.25) - local node = items[middle] - if not node then - return - end - node.left = process_subtree((function() - local _accum_0 = { } - local _len_0 = 1 - for i, item in ipairs(items) do - if i < middle then - _accum_0[_len_0] = item - _len_0 = _len_0 + 1 - end - end - return _accum_0 - end)()) - node.right = process_subtree((function() - local _accum_0 = { } - local _len_0 = 1 - for i, item in ipairs(items) do - if i > middle then - _accum_0[_len_0] = item - _len_0 = _len_0 + 1 - end - end - return _accum_0 - end)()) - return node -end -local process_tree -process_tree = function(items) - local sorted_items - do - local _accum_0 = { } - local _len_0 = 1 - for _index_0 = 1, #items do - local item = items[_index_0] - _accum_0[_len_0] = item - _len_0 = _len_0 + 1 - end - sorted_items = _accum_0 - end - table.sort(sorted_items, function(a, b) - return a.order < b.order - end); - (process_subtree(sorted_items)).label = '&_entry' - for _index_0 = 1, #items do - local item = items[_index_0] - output:write(('\t%-11s %-10s %-12s %s%s\n'):format(item.label, item.left and item.left.ref or ' $2', (item.right and item.right.ref or ' $2') .. item.extra, item.key, item.rest)) - end -end -local parse_tree -parse_tree = function(it) - local items = { } - for l in it do - if l == '' then - process_tree(items) - output:write('\n') - return - end - local item = { - extra = '' - } - item.key, item.rest = l:match('^%s*%S+%s+%S+%s+%S+%s+(%S+)(.*)') - if item.key:match('^%&') then - item.extra = (' %s'):format(item.key) - item.key, item.rest = item.rest:match('^%s+(%S+)(.*)') - end - if item.key:match('^%"') then - item.order = item.key:sub(2) - elseif item.key:match('^%x%x') then - item.order = string.char(tonumber(item.key, 16)) - else - error(('unknown key: %q'):format(item.key)) - end - if item.order:match('^%a') then - item.label = ('&%s'):format(item.order) - elseif item.order:match('^.$') then - item.label = ('&%x'):format(item.order:byte()) - else - error(('unknown label: %q'):format(item.order)) - end - item.ref = (':%s'):format(item.label) - table.insert(items, item) - end -end -local it = assert(io.lines('projects/library/asma.tal')) -local waiting_for_cut = true -for l in it do - output:write(l) - output:write('\n') - if l:find('--- cut here ---', 1, true) then - waiting_for_cut = false - end - if not waiting_for_cut and '@' == l:sub(1, 1) then - parse_tree(it) - end -end -output:close() -return os.execute('mv .asma.tal projects/library/asma.tal') diff --git a/etc/asma.moon b/etc/asma.moon deleted file mode 100644 index 9cadef5..0000000 --- a/etc/asma.moon +++ /dev/null @@ -1,74 +0,0 @@ --- --- Asma tree helper script --- --- This script balances the trees at the end of projects/library/asma.tal. --- --- To run, you need Lua or LuaJIT, and just run etc/asma.lua from the top --- directory of Uxn's git repository: --- --- lua etc/asma.lua --- --- This file is written in MoonScript, which is a language that compiles to --- Lua, the same way as e.g. CoffeeScript compiles to JavaScript. Since --- installing MoonScript has more dependencies than Lua, the compiled --- etc/asma.lua is kept in Uxn's repository and will be kept updated as this --- file changes. --- - -output = assert io.open '.asma.tal', 'w' - -process_subtree = (items) -> - middle = math.floor #items / 2 + 1.25 - node = items[middle] - if not node - return - node.left = process_subtree [ item for i, item in ipairs items when i < middle ] - node.right = process_subtree [ item for i, item in ipairs items when i > middle ] - node - -process_tree = (items) -> - sorted_items = [ item for item in *items ] - table.sort sorted_items, (a, b) -> a.order < b.order - (process_subtree sorted_items).label = '&_entry' - for item in *items - output\write '\t%-11s %-10s %-12s %s%s\n'\format item.label, item.left and item.left.ref or ' $2', (item.right and item.right.ref or ' $2') .. item.extra, item.key, item.rest - -parse_tree = (it) -> - items = {} - for l in it - if l == '' - process_tree items - output\write '\n' - return - item = { extra: '' } - item.key, item.rest = l\match '^%s*%S+%s+%S+%s+%S+%s+(%S+)(.*)' - if item.key\match '^%&' - item.extra = ' %s'\format item.key - item.key, item.rest = item.rest\match '^%s+(%S+)(.*)' - if item.key\match '^%"' - item.order = item.key\sub 2 - elseif item.key\match '^%x%x' - item.order = string.char tonumber item.key, 16 - else - error 'unknown key: %q'\format item.key - if item.order\match '^%a' - item.label = '&%s'\format item.order - elseif item.order\match '^.$' - item.label = '&%x'\format item.order\byte! - else - error 'unknown label: %q'\format item.order - item.ref = ':%s'\format item.label - table.insert items, item - -it = assert io.lines 'projects/library/asma.tal' -waiting_for_cut = true -for l in it - output\write l - output\write '\n' - if l\find '--- cut here ---', 1, true - waiting_for_cut = false - if not waiting_for_cut and '@' == l\sub 1, 1 - parse_tree it -output\close! -os.execute 'mv .asma.tal projects/library/asma.tal' - diff --git a/etc/autotest/.gitignore b/etc/autotest/.gitignore deleted file mode 100644 index d341452..0000000 --- a/etc/autotest/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/autotest -/fix_fft.c -/test.ppm diff --git a/etc/autotest/asoundrc b/etc/autotest/asoundrc deleted file mode 100644 index 493a1d0..0000000 --- a/etc/autotest/asoundrc +++ /dev/null @@ -1,11 +0,0 @@ -pcm.!default { - type file - slave.pcm null - file /proc/self/fd/3 - format "raw" -} - -pcm.null { - type null -} - diff --git a/etc/autotest/main.c b/etc/autotest/main.c deleted file mode 100644 index b46f3e2..0000000 --- a/etc/autotest/main.c +++ /dev/null @@ -1,332 +0,0 @@ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define WIDTH 512 -#define HEIGHT 320 - -#define str(x) stra(x) -#define stra(x) #x - -#define die(fnname) \ - do { \ - perror(fnname); \ - exit(EXIT_FAILURE); \ - } while(0) - -#define x(fn, ...) \ - do { \ - if(fn(__VA_ARGS__) < 0) { \ - perror(#fn); \ - exit(EXIT_FAILURE); \ - } \ - } while(0) - -int fix_fft(short *fr, short *fi, short m, short inverse); - -static pid_t -launch_xvfb(void) -{ - char displayfd[16]; - int r; - pid_t pid; - int fds[2]; - x(pipe2, &fds[0], 0); - pid = fork(); - if(pid < 0) { - die("fork"); - } else if(!pid) { - x(snprintf, displayfd, sizeof(displayfd), "%d", fds[1]); - x(close, fds[0]); - execlp("Xvfb", "Xvfb", "-screen", "0", str(WIDTH) "x" str(HEIGHT) "x24", "-fbdir", ".", "-displayfd", displayfd, "-nolisten", "tcp", NULL); - die("execl"); - exit(EXIT_FAILURE); - } - x(close, fds[1]); - r = read(fds[0], &displayfd[1], sizeof(displayfd) - 1); - if(r < 0) die("read"); - x(close, fds[0]); - displayfd[r] = '\0'; - displayfd[0] = ':'; - x(setenv, "DISPLAY", displayfd, 1); - x(setenv, "ALSA_CONFIG_PATH", "asoundrc", 1); - return pid; -} - -static pid_t -launch_uxnemu(int *write_fd, int *read_fd, int *sound_fd) -{ - pid_t pid; - int fds[6]; - x(pipe2, &fds[0], O_CLOEXEC); - x(pipe2, &fds[2], O_CLOEXEC); - x(pipe2, &fds[4], O_CLOEXEC); - pid = fork(); - if(pid < 0) { - die("fork"); - } else if(!pid) { - x(dup2, fds[0], 0); - x(dup2, fds[3], 1); - x(dup2, fds[5], 3); - execl("../../bin/uxnemu", "uxnemu", "autotest.rom", NULL); - die("execl"); - } - x(close, fds[0]); - x(close, fds[3]); - x(close, fds[5]); - *write_fd = fds[1]; - *read_fd = fds[2]; - *sound_fd = fds[4]; - return pid; -} - -static void -terminate(pid_t pid) -{ - int signals[] = {SIGINT, SIGTERM, SIGKILL}; - int status; - size_t i; - for(i = 0; i < sizeof(signals) / sizeof(int) * 10; ++i) { - if(kill(pid, signals[i / 10])) { - break; - } - usleep(100000); - if(pid == waitpid(pid, &status, WNOHANG)) { - return; - } - } - waitpid(pid, &status, 0); -} - -static int -open_framebuffer(void) -{ - for(;;) { - int fd = open("Xvfb_screen0", O_RDONLY | O_CLOEXEC); - if(fd >= 0) { - return fd; - } - if(errno != ENOENT) { - perror("open"); - return fd; - } - usleep(100000); - } -} - -#define PPM_HEADER "P6\n" str(WIDTH) " " str(HEIGHT) "\n255\n" - -static void -save_screenshot(int fb_fd, const char *filename) -{ - unsigned char screen[WIDTH * HEIGHT * 4 + 4]; - int fd = open(filename, O_WRONLY | O_CREAT, 0666); - int i; - if(fd < 0) { - die("screenshot open"); - } - x(write, fd, PPM_HEADER, strlen(PPM_HEADER)); - x(lseek, fb_fd, 0xca0, SEEK_SET); - x(read, fb_fd, &screen[4], WIDTH * HEIGHT * 4); - for(i = 0; i < WIDTH * HEIGHT; ++i) { - screen[i * 3 + 2] = screen[i * 4 + 4]; - screen[i * 3 + 1] = screen[i * 4 + 5]; - screen[i * 3 + 0] = screen[i * 4 + 6]; - } - x(write, fd, screen, WIDTH * HEIGHT * 3); - x(close, fd); -} - -static void -systemf(char *format, ...) -{ - char *command; - va_list ap; - va_start(ap, format); - x(vasprintf, &command, format, ap); - system(command); - free(command); -} - -int uxn_read_fd, sound_fd; - -static int -byte(void) -{ - char c; - if(read(uxn_read_fd, &c, 1) != 1) { - return 0; - } - return (unsigned char)c; -} - -#define NEW_FFT_SIZE_POW2 10 -#define NEW_FFT_SIZE (1 << NEW_FFT_SIZE_POW2) -#define NEW_FFT_USEC (5000 * NEW_FFT_SIZE / 441) - -unsigned char left_peak, right_peak; - -static int -detect_peak(short *real, short *imag) -{ - int i, peak = 0, peak_i; - for(i = 0; i < NEW_FFT_SIZE; ++i) { - int v = real[i] * real[i] + imag[i] * imag[i]; - if(peak < v) { - peak = v; - peak_i = i; - } else if(peak > v * 10) { - return peak_i; - } - } - return 0; -} - -static int -analyse_sound(short *samples) -{ - short real[NEW_FFT_SIZE], imag[NEW_FFT_SIZE]; - int i; - for(i = 0; i < NEW_FFT_SIZE * 2; ++i) { - if(samples[i * 2]) break; - } - if(i == NEW_FFT_SIZE * 2) return 0; - for(i = 0; i < NEW_FFT_SIZE; ++i) { - real[i] = samples[i * 4]; - imag[i] = samples[i * 4 + 2]; - } - fix_fft(real, imag, NEW_FFT_SIZE_POW2, 0); - return detect_peak(real, imag); -} - -static int -read_sound(void) -{ - static short samples[NEW_FFT_SIZE * 4]; - static size_t len = 0; - int r = read(sound_fd, ((char *)samples) + len, sizeof(samples) - len); - if(r > 0) { - len += r; - if(len == sizeof(samples)) { - left_peak = analyse_sound(&samples[0]); - right_peak = analyse_sound(&samples[1]); - len = 0; - return 1; - } - } - return 0; -} - -static void -main_loop(int uxn_write_fd, int fb_fd) -{ - struct timeval next_sound = {0, 0}; - for(;;) { - struct timeval now; - struct timeval *timeout; - fd_set fds; - FD_ZERO(&fds); - FD_SET(uxn_read_fd, &fds); - x(gettimeofday, &now, NULL); - if(now.tv_sec > next_sound.tv_sec || (now.tv_sec == next_sound.tv_sec && now.tv_usec > next_sound.tv_usec)) { - FD_SET(sound_fd, &fds); - timeout = NULL; - } else { - now.tv_sec = 0; - now.tv_usec = NEW_FFT_USEC; - timeout = &now; - } - x(select, uxn_read_fd > sound_fd ? uxn_read_fd + 1 : sound_fd + 1, &fds, NULL, NULL, timeout); - if(FD_ISSET(uxn_read_fd, &fds)) { - int c, x, y; - unsigned char blue; - switch(c = byte()) { - case 0x00: /* also used for EOF */ - printf("exiting\n"); - return; - /* 01-06 mouse */ - case 0x01 ... 0x05: - systemf("xdotool click %d", c); - break; - case 0x06: - x = (byte() << 8) | byte(); - y = (byte() << 8) | byte(); - systemf("xdotool mousemove %d %d", x, y); - break; - /* 07-08 Screen */ - case 0x07: - x = (byte() << 8) | byte(); - y = (byte() << 8) | byte(); - lseek(fb_fd, 0xca0 + (x + y * WIDTH) * 4, SEEK_SET); - read(fb_fd, &blue, 1); - blue = blue / 0x11; - write(uxn_write_fd, &blue, 1); - break; - case 0x08: - save_screenshot(fb_fd, "test.ppm"); - break; - /* 09-0a Audio */ - case 0x09: - write(uxn_write_fd, &left_peak, 1); - break; - case 0x0a: - write(uxn_write_fd, &right_peak, 1); - break; - /* 11-7e Controller/key */ - case 0x11 ... 0x1c: - systemf("xdotool key F%d", c - 0x10); - break; - case '0' ... '9': - case 'A' ... 'Z': - case 'a' ... 'z': - systemf("xdotool key %c", c); - break; - default: - printf("unhandled command 0x%02x\n", c); - break; - } - } - if(FD_ISSET(sound_fd, &fds)) { - if(!next_sound.tv_sec) { - x(gettimeofday, &next_sound, NULL); - } - next_sound.tv_usec += NEW_FFT_USEC * read_sound(); - if(next_sound.tv_usec > 1000000) { - next_sound.tv_usec -= 1000000; - ++next_sound.tv_sec; - } - } - } -} - -int -main(void) -{ - pid_t xvfb_pid = launch_xvfb(); - int fb_fd = open_framebuffer(); - if(fb_fd >= 0) { - int uxn_write_fd; - pid_t uxnemu_pid = launch_uxnemu(&uxn_write_fd, &uxn_read_fd, &sound_fd); - main_loop(uxn_write_fd, fb_fd); - terminate(uxnemu_pid); - x(close, uxn_write_fd); - x(close, uxn_read_fd); - x(close, sound_fd); - x(close, fb_fd); - } - terminate(xvfb_pid); - return 0; -} diff --git a/etc/autotest/run.sh b/etc/autotest/run.sh deleted file mode 100755 index ce7cf21..0000000 --- a/etc/autotest/run.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -e -cd "$(dirname "${0}")" -if ! which Xvfb 2>/dev/null; then - echo "error: ${0} depends on Xvfb" - exit 1 -fi -if ! which xdotool 2>/dev/null; then - echo "error: ${0} depends on xdotool" - exit 1 -fi -if [ ! -e fix_fft.c ]; then - wget https://gist.githubusercontent.com/Tomwi/3842231/raw/67149b6ec81cfb6ac1056fd23a3bb6ce1f0a5188/fix_fft.c -fi -if which clang-format 2>/dev/null; then - ( cd ../.. && clang-format -i etc/autotest/main.c ) -fi -../../bin/uxnasm autotest.tal autotest.rom -gcc -std=gnu89 -Wall -Wextra -o autotest main.c fix_fft.c -lm -./autotest - diff --git a/etc/cores/uxn-abc-disp.c b/etc/cores/uxn-abc-disp.c deleted file mode 100644 index e19502b..0000000 --- a/etc/cores/uxn-abc-disp.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "uxn.h" - -/* -Copyright (u) 2022-2023 Devine Lu Linvega, Andrew Alderwick, Andrew Richards - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE. -*/ - -#define FLIP { s = ins & 0x40 ? &u->wst : &u->rst; } -#define JUMP(x) { if(m2) pc = (x); else pc += (Sint8)(x); } -#define POP1(o) { o = s->dat[--*sp]; } -#define POP2(o) { o = s->dat[--*sp] | (s->dat[--*sp] << 0x8); } -#define POPx(o) { if(m2) { POP2(o) } else POP1(o) } -#define PUSH1(y) { s->dat[s->ptr++] = (y); } -#define PUSH2(y) { tt = (y); s->dat[s->ptr++] = tt >> 0x8; s->dat[s->ptr++] = tt; } -#define PUSHx(y) { if(m2) { PUSH2(y) } else PUSH1(y) } -#define PEEK(o, x, r) { if(m2) { r = (x); o = ram[r++] << 8 | ram[r]; } else o = ram[(x)]; } -#define POKE(x, y, r) { if(m2) { r = (x); ram[r++] = y >> 8; ram[r] = y; } else ram[(x)] = (y); } -#define DEVR(o, p) { if(m2) { o = (emu_dei(u, p) << 8) | emu_dei(u, p + 1); } else o = emu_dei(u, p); } -#define DEVW(p, y) { if(m2) { emu_deo(u, p, y >> 8); emu_deo(u, p + 1, y); } else emu_deo(u, p, y); } -#define next { ins = ram[pc++]; \ - m2 = ins & 0x20; \ - s = ins & 0x40 ? &u->rst : &u->wst; \ - if(ins & 0x80) kp = s->ptr, sp = &kp; else sp = &s->ptr; \ - goto *lut[ins & 0x1f]; } - -int -uxn_eval(Uxn *u, Uint16 pc) -{ - Uint8 t, kp, *sp, ins, m2, *ram = u->ram; - Uint16 tt, a, b, c; - Stack *s; - static void* lut[] = { - &&_imm, &&_inc, &&_pop, &&_nip, &&_swp, &&_rot, &&_dup, &&_ovr, - &&_equ, &&_neq, &&_gth, &&_lth, &&_jmp, &&_jcn, &&_jsr, &&_sth, - &&_ldz, &&_stz, &&_ldr, &&_str, &&_lda, &&_sta, &&_dei, &&_deo, - &&_add, &&_sub, &&_mul, &&_div, &&_and, &&_ora, &&_eor, &&_sft }; - if(!pc || u->dev[0x0f]) return 0; - next - _imm: - switch(ins) { - case 0x00: /* BRK */ return 1; - case 0x20: /* JCI */ POP1(b) if(!b) { pc += 2; break; } - case 0x40: /* JMI */ a = ram[pc++] << 8 | ram[pc++]; pc += a; break; - case 0x60: /* JSI */ PUSH2(pc + 2) a = ram[pc++] << 8 | ram[pc++]; pc += a; break; - case 0x80: case 0xc0: /* LIT */ PUSH1(ram[pc++]) break; - case 0xa0: case 0xe0: /* LIT2 */ PUSH1(ram[pc++]) PUSH1(ram[pc++]) break; - } next - _inc: POPx(a) PUSHx(a + 1) next - _pop: POPx(a) next - _nip: POPx(a) POPx(b) PUSHx(a) next - _swp: POPx(a) POPx(b) PUSHx(a) PUSHx(b) next - _rot: POPx(a) POPx(b) POPx(c) PUSHx(b) PUSHx(a) PUSHx(c) next - _dup: POPx(a) PUSHx(a) PUSHx(a) next - _ovr: POPx(a) POPx(b) PUSHx(b) PUSHx(a) PUSHx(b) next - _equ: POPx(a) POPx(b) PUSH1(b == a) next - _neq: POPx(a) POPx(b) PUSH1(b != a) next - _gth: POPx(a) POPx(b) PUSH1(b > a) next - _lth: POPx(a) POPx(b) PUSH1(b < a) next - _jmp: POPx(a) JUMP(a) next - _jcn: POPx(a) POP1(b) if(b) JUMP(a) next - _jsr: POPx(a) FLIP PUSH2(pc) JUMP(a) next - _sth: POPx(a) FLIP PUSHx(a) next - _ldz: POP1(a) PEEK(b, a, t) PUSHx(b) next - _stz: POP1(a) POPx(b) POKE(a, b, t) next - _ldr: POP1(a) PEEK(b, pc + (Sint8)a, tt) PUSHx(b) next - _str: POP1(a) POPx(b) POKE(pc + (Sint8)a, b, tt) next - _lda: POP2(a) PEEK(b, a, tt) PUSHx(b) next - _sta: POP2(a) POPx(b) POKE(a, b, tt) next - _dei: POP1(a) DEVR(b, a) PUSHx(b) next - _deo: POP1(a) POPx(b) DEVW(a, b) next - _add: POPx(a) POPx(b) PUSHx(b + a) next - _sub: POPx(a) POPx(b) PUSHx(b - a) next - _mul: POPx(a) POPx(b) PUSHx(b * a) next - _div: POPx(a) POPx(b) PUSHx(a ? b / a : 0) next - _and: POPx(a) POPx(b) PUSHx(b & a) next - _ora: POPx(a) POPx(b) PUSHx(b | a) next - _eor: POPx(a) POPx(b) PUSHx(b ^ a) next - _sft: POP1(a) POPx(b) PUSHx(b >> (a & 0xf) << (a >> 4)) next -} \ No newline at end of file diff --git a/etc/cores/uxn-abc.c b/etc/cores/uxn-abc.c deleted file mode 100644 index 16de64b..0000000 --- a/etc/cores/uxn-abc.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "uxn.h" - -/* -Copyright (u) 2022-2023 Devine Lu Linvega, Andrew Alderwick, Andrew Richards - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE. -*/ - -#define FLIP { s = ins & 0x40 ? &u->wst : &u->rst; } -#define JUMP(x) { if(m2) pc = (x); else pc += (Sint8)(x); } -#define POP1(o) { o = s->dat[--*sp]; } -#define POP2(o) { o = s->dat[--*sp] | (s->dat[--*sp] << 0x8); } -#define POPx(o) { if(m2) { POP2(o) } else POP1(o) } -#define PUSH1(y) { s->dat[s->ptr++] = (y); } -#define PUSH2(y) { tt = (y); s->dat[s->ptr++] = tt >> 0x8; s->dat[s->ptr++] = tt; } -#define PUSHx(y) { if(m2) { PUSH2(y) } else PUSH1(y) } -#define PEEK(o, x, r) { if(m2) { r = (x); o = ram[r++] << 8 | ram[r]; } else o = ram[(x)]; } -#define POKE(x, y, r) { if(m2) { r = (x); ram[r++] = y >> 8; ram[r] = y; } else ram[(x)] = (y); } -#define DEVR(o, p) { if(m2) { o = (emu_dei(u, p) << 8) | emu_dei(u, p + 1); } else o = emu_dei(u, p); } -#define DEVW(p, y) { if(m2) { emu_deo(u, p, y >> 8); emu_deo(u, p + 1, y); } else emu_deo(u, p, y); } - -int -uxn_eval(Uxn *u, Uint16 pc) -{ - Uint8 t, kp, *sp, *ram = u->ram; - Uint16 tt, a, b, c; - if(!pc || u->dev[0x0f]) return 0; - for(;;) { - Uint8 ins = ram[pc++]; - /* 2 */ Uint8 m2 = ins & 0x20; - /* r */ Stack *s = ins & 0x40 ? &u->rst : &u->wst; - /* k */ if(ins & 0x80) kp = s->ptr, sp = &kp; else sp = &s->ptr; - switch(ins & 0x1f) { - case 0x00: - switch(ins) { - case 0x00: /* BRK */ return 1; - case 0x20: /* JCI */ POP1(b) if(!b) { pc += 2; break; } - case 0x40: /* JMI */ a = ram[pc++] << 8 | ram[pc++]; pc += a; break; - case 0x60: /* JSI */ PUSH2(pc + 2) a = ram[pc++] << 8 | ram[pc++]; pc += a; break; - case 0x80: case 0xc0: /* LIT */ PUSH1(ram[pc++]) break; - case 0xa0: case 0xe0: /* LIT2 */ PUSH1(ram[pc++]) PUSH1(ram[pc++]) break; - } break; - case 0x01: /* INC */ POPx(a) PUSHx(a + 1) break; - case 0x02: /* POP */ POPx(a) break; - case 0x03: /* NIP */ POPx(a) POPx(b) PUSHx(a) break; - case 0x04: /* SWP */ POPx(a) POPx(b) PUSHx(a) PUSHx(b) break; - case 0x05: /* ROT */ POPx(a) POPx(b) POPx(c) PUSHx(b) PUSHx(a) PUSHx(c) break; - case 0x06: /* DUP */ POPx(a) PUSHx(a) PUSHx(a) break; - case 0x07: /* OVR */ POPx(a) POPx(b) PUSHx(b) PUSHx(a) PUSHx(b) break; - case 0x08: /* EQU */ POPx(a) POPx(b) PUSH1(b == a) break; - case 0x09: /* NEQ */ POPx(a) POPx(b) PUSH1(b != a) break; - case 0x0a: /* GTH */ POPx(a) POPx(b) PUSH1(b > a) break; - case 0x0b: /* LTH */ POPx(a) POPx(b) PUSH1(b < a) break; - case 0x0c: /* JMP */ POPx(a) JUMP(a) break; - case 0x0d: /* JCN */ POPx(a) POP1(b) if(b) JUMP(a) break; - case 0x0e: /* JSR */ POPx(a) FLIP PUSH2(pc) JUMP(a) break; - case 0x0f: /* STH */ POPx(a) FLIP PUSHx(a) break; - case 0x10: /* LDZ */ POP1(a) PEEK(b, a, t) PUSHx(b) break; - case 0x11: /* STZ */ POP1(a) POPx(b) POKE(a, b, t) break; - case 0x12: /* LDR */ POP1(a) PEEK(b, pc + (Sint8)a, tt) PUSHx(b) break; - case 0x13: /* STR */ POP1(a) POPx(b) POKE(pc + (Sint8)a, b, tt) break; - case 0x14: /* LDA */ POP2(a) PEEK(b, a, tt) PUSHx(b) break; - case 0x15: /* STA */ POP2(a) POPx(b) POKE(a, b, tt) break; - case 0x16: /* DEI */ POP1(a) DEVR(b, a) PUSHx(b) break; - case 0x17: /* DEO */ POP1(a) POPx(b) DEVW(a, b) break; - case 0x18: /* ADD */ POPx(a) POPx(b) PUSHx(b + a) break; - case 0x19: /* SUB */ POPx(a) POPx(b) PUSHx(b - a) break; - case 0x1a: /* MUL */ POPx(a) POPx(b) PUSHx(b * a) break; - case 0x1b: /* DIV */ POPx(a) POPx(b) PUSHx(a ? b / a : 0) break; - case 0x1c: /* AND */ POPx(a) POPx(b) PUSHx(b & a) break; - case 0x1d: /* ORA */ POPx(a) POPx(b) PUSHx(b | a) break; - case 0x1e: /* EOR */ POPx(a) POPx(b) PUSHx(b ^ a) break; - case 0x1f: /* SFT */ POP1(a) POPx(b) PUSHx(b >> (a & 0xf) << (a >> 4)) break; - } - } -} diff --git a/etc/cores/uxn-tnl.c b/etc/cores/uxn-tnl.c deleted file mode 100644 index ae7463c..0000000 --- a/etc/cores/uxn-tnl.c +++ /dev/null @@ -1,123 +0,0 @@ -#include "uxn.h" - -/* -Copyright (u) 2022-2023 Devine Lu Linvega, Andrew Alderwick, Andrew Richards - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE. -*/ - -/* Registers -[ Z ][ Y ][ X ][ L ][ N ][ T ] < -[ . ][ . ][ . ][ H2 ][ . ] < -[ L2 ][ N2 ][ T2 ] < -*/ - -#define T *(s->dat + s->ptr) -#define N *(s->dat + (Uint8)(s->ptr - 1)) -#define L *(s->dat + (Uint8)(s->ptr - 2)) -#define X *(s->dat + (Uint8)(s->ptr - 3)) -#define Y *(s->dat + (Uint8)(s->ptr - 4)) -#define Z *(s->dat + (Uint8)(s->ptr - 5)) -#define T2 (N << 8 | T) -#define H2 (L << 8 | N) -#define N2 (X << 8 | L) -#define L2 (Z << 8 | Y) -#define T2_(v) { r = (v); T = r; N = r >> 8; } -#define N2_(v) { r = (v); L = r; X = r >> 8; } -#define L2_(v) { r = (v); Y = r; Z = r >> 8; } -#define FLIP { s = ins & 0x40 ? &u->wst : &u->rst; } -#define SHIFT(y) { s->ptr += (y); } -#define SET(x, y) { SHIFT((ins & 0x80) ? x + y : y) } - -int -uxn_eval(Uxn *u, Uint16 pc) -{ - Uint16 t, n, l, r; - Uint8 *ram = u->ram, *rr; - if(!pc || u->dev[0x0f]) return 0; - for(;;) { - Uint8 ins = ram[pc++]; - Stack *s = ins & 0x40 ? &u->rst : &u->wst; - switch(ins & 0x3f) { - /* IMM */ - case 0x00: case 0x20: - switch(ins) { - case 0x00: /* BRK */ return 1; - case 0x20: /* JCI */ t=T; SHIFT(-1) if(!t) { pc += 2; break; } /* fall-through */ - case 0x40: /* JMI */ rr = ram + pc; pc += 2 + PEEK2(rr); break; - case 0x60: /* JSI */ SHIFT( 2) rr = ram + pc; pc += 2; T2_(pc); pc += PEEK2(rr); break; - case 0x80: /* LIT */ case 0xc0: SHIFT( 1) T = ram[pc++]; break; - case 0xa0: /* LIT2 */ case 0xe0: SHIFT( 2) N = ram[pc++]; T = ram[pc++]; break; - } break; - /* ALU */ - case 0x01: /* INC */ t=T; SET(1, 0) T = t + 1; break; - case 0x21: /* INC2 */ t=T2; SET(2, 0) T2_(t + 1) break; - case 0x02: /* POP */ SET(1,-1) break; - case 0x22: /* POP2 */ SET(2,-2) break; - case 0x03: /* NIP */ t=T; SET(2,-1) T = t; break; - case 0x23: /* NIP2 */ t=T2; SET(4,-2) T2_(t) break; - case 0x04: /* SWP */ t=T;n=N; SET(2, 0) T = n; N = t; break; - case 0x24: /* SWP2 */ t=T2;n=N2; SET(4, 0) T2_(n) N2_(t) break; - case 0x05: /* ROT */ t=T;n=N;l=L; SET(3, 0) T = l; N = t; L = n; break; - case 0x25: /* ROT2 */ t=T2;n=N2;l=L2; SET(6, 0) T2_(l) N2_(t) L2_(n) break; - case 0x06: /* DUP */ t=T; SET(1, 1) T = t; N = t; break; - case 0x26: /* DUP2 */ t=T2; SET(2, 2) T2_(t) N2_(t) break; - case 0x07: /* OVR */ t=T;n=N; SET(2, 1) T = n; N = t; L = n; break; - case 0x27: /* OVR2 */ t=T2;n=N2; SET(4, 2) T2_(n) N2_(t) L2_(n) break; - case 0x08: /* EQU */ t=T;n=N; SET(2,-1) T = n == t; break; - case 0x28: /* EQU2 */ t=T2;n=N2; SET(4,-3) T = n == t; break; - case 0x09: /* NEQ */ t=T;n=N; SET(2,-1) T = n != t; break; - case 0x29: /* NEQ2 */ t=T2;n=N2; SET(4,-3) T = n != t; break; - case 0x0a: /* GTH */ t=T;n=N; SET(2,-1) T = n > t; break; - case 0x2a: /* GTH2 */ t=T2;n=N2; SET(4,-3) T = n > t; break; - case 0x0b: /* LTH */ t=T;n=N; SET(2,-1) T = n < t; break; - case 0x2b: /* LTH2 */ t=T2;n=N2; SET(4,-3) T = n < t; break; - case 0x0c: /* JMP */ t=T; SET(1,-1) pc += (Sint8)t; break; - case 0x2c: /* JMP2 */ t=T2; SET(2,-2) pc = t; break; - case 0x0d: /* JCN */ t=T;n=N; SET(2,-2) if(n) pc += (Sint8)t; break; - case 0x2d: /* JCN2 */ t=T2;n=L; SET(3,-3) if(n) pc = t; break; - case 0x0e: /* JSR */ t=T; SET(1,-1) FLIP SHIFT(2) T2_(pc) pc += (Sint8)t; break; - case 0x2e: /* JSR2 */ t=T2; SET(2,-2) FLIP SHIFT(2) T2_(pc) pc = t; break; - case 0x0f: /* STH */ t=T; SET(1,-1) FLIP SHIFT(1) T = t; break; - case 0x2f: /* STH2 */ t=T2; SET(2,-2) FLIP SHIFT(2) T2_(t) break; - case 0x10: /* LDZ */ t=T; SET(1, 0) T = ram[t]; break; - case 0x30: /* LDZ2 */ t=T; SET(1, 1) N = ram[t++]; T = ram[(Uint8)t]; break; - case 0x11: /* STZ */ t=T;n=N; SET(2,-2) ram[t] = n; break; - case 0x31: /* STZ2 */ t=T;n=H2; SET(3,-3) ram[t++] = n >> 8; ram[(Uint8)t] = n; break; - case 0x12: /* LDR */ t=T; SET(1, 0) r = pc + (Sint8)t; T = ram[r]; break; - case 0x32: /* LDR2 */ t=T; SET(1, 1) r = pc + (Sint8)t; N = ram[r++]; T = ram[r]; break; - case 0x13: /* STR */ t=T;n=N; SET(2,-2) r = pc + (Sint8)t; ram[r] = n; break; - case 0x33: /* STR2 */ t=T;n=H2; SET(3,-3) r = pc + (Sint8)t; ram[r++] = n >> 8; ram[r] = n; break; - case 0x14: /* LDA */ t=T2; SET(2,-1) T = ram[t]; break; - case 0x34: /* LDA2 */ t=T2; SET(2, 0) N = ram[t++]; T = ram[t]; break; - case 0x15: /* STA */ t=T2;n=L; SET(3,-3) ram[t] = n; break; - case 0x35: /* STA2 */ t=T2;n=N2; SET(4,-4) ram[t++] = n >> 8; ram[t] = n; break; - case 0x16: /* DEI */ t=T; SET(1, 0) T = emu_dei(u, t); break; - case 0x36: /* DEI2 */ t=T; SET(1, 1) N = emu_dei(u, t++); T = emu_dei(u, t); break; - case 0x17: /* DEO */ t=T;n=N; SET(2,-2) emu_deo(u, t, n); break; - case 0x37: /* DEO2 */ t=T;n=N;l=L; SET(3,-3) emu_deo(u, t++, l); emu_deo(u, t, n); break; - case 0x18: /* ADD */ t=T;n=N; SET(2,-1) T = n + t; break; - case 0x38: /* ADD2 */ t=T2;n=N2; SET(4,-2) T2_(n + t) break; - case 0x19: /* SUB */ t=T;n=N; SET(2,-1) T = n - t; break; - case 0x39: /* SUB2 */ t=T2;n=N2; SET(4,-2) T2_(n - t) break; - case 0x1a: /* MUL */ t=T;n=N; SET(2,-1) T = n * t; break; - case 0x3a: /* MUL2 */ t=T2;n=N2; SET(4,-2) T2_(n * t) break; - case 0x1b: /* DIV */ t=T;n=N; SET(2,-1) T = t ? n / t : 0; break; - case 0x3b: /* DIV2 */ t=T2;n=N2; SET(4,-2) T2_(t ? n / t : 0) break; - case 0x1c: /* AND */ t=T;n=N; SET(2,-1) T = n & t; break; - case 0x3c: /* AND2 */ t=T2;n=N2; SET(4,-2) T2_(n & t) break; - case 0x1d: /* ORA */ t=T;n=N; SET(2,-1) T = n | t; break; - case 0x3d: /* ORA2 */ t=T2;n=N2; SET(4,-2) T2_(n | t) break; - case 0x1e: /* EOR */ t=T;n=N; SET(2,-1) T = n ^ t; break; - case 0x3e: /* EOR2 */ t=T2;n=N2; SET(4,-2) T2_(n ^ t) break; - case 0x1f: /* SFT */ t=T;n=N; SET(2,-1) T = n >> (t & 0xf) << (t >> 4); break; - case 0x3f: /* SFT2 */ t=T;n=H2; SET(3,-1) T2_(n >> (t & 0xf) << (t >> 4)) break; - } - } -} - diff --git a/etc/utos/build.sh b/etc/utos/build.sh deleted file mode 100755 index b7a4cb9..0000000 --- a/etc/utos/build.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -echo "Formatting.." -clang-format -i utos.c - -echo "Cleaning.." -rm -f ../../bin/utos - -echo "Building.." -mkdir -p ../../bin -cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined -lm utos.c -o ../../bin/utos - -echo "Running.." -../../bin/utos ../../projects/sounds/pad1.ss8 ../../projects/sounds/pad1.pcm - -echo "Done." diff --git a/etc/utos/utos.c b/etc/utos/utos.c deleted file mode 100644 index 6948a72..0000000 --- a/etc/utos/utos.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include - -/* -Copyright (c) 2020 Devine Lu Linvega - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE. -*/ - -typedef unsigned char Uint8; -typedef signed char Sint8; -typedef unsigned short Uint16; -typedef signed short Sint16; - -int -main(int argc, char **argv) -{ - FILE *f; - Uint8 *buffer; - Uint16 filelen, i; - if(argc < 2 || !(f = fopen(argv[1], "rb"))) - return 1; - fseek(f, 0, SEEK_END); - filelen = ftell(f); - rewind(f); - buffer = (Uint8 *)malloc(filelen * sizeof(Uint8)); - fread(buffer, filelen, 1, f); - fclose(f); - for(i = 0; i < filelen; ++i) - buffer[i] += 0x80; - printf("\n\n"); - fwrite(buffer, filelen, 1, fopen(argv[2], "wb")); - return 0; -} diff --git a/etc/uxambly-translate.moon b/etc/uxambly-translate.moon deleted file mode 100644 index 04a7578..0000000 --- a/etc/uxambly-translate.moon +++ /dev/null @@ -1,103 +0,0 @@ --- Used for porting Uxntal code for use with the old assembler --- in commit 82f7103a55c21b13f898b20e5d1e174e501bc825 with the --- assembler that replaced it straight afterwards. - -import P, R, S, C, Ct, Cp, V from require 'lpeg' - -local labels, filename - -opcode_translate = - LDZ2: 'LDA' - STZ2: 'STA' - LDR: 'LDZ2' - STR: 'STZ2' - LDR2: 'LDA2' - STR2: 'STA2' - -grammar = P { - 'file' - file: Ct(V'ows' * (V'atom' * V'ows') ^ 0) * Cp! - ws: C S' \n\t' ^ 1 - ows: C S' \n\t' ^ 0 - atom: V'opcode' + V'comment' + V'variable' + V'addr' + V'literal' + V'setter' + V'getter' + V'short' + V'labeldef' + V'relative' + V'sublabel' + V'data' + V'macro' + V'macroref' + V'rawshort' - comment: C P'(' * (1-V'ws'*P')') ^ 0 * V'ws' * P')' - variable: (P';' / -> '@') * C(V'name') * V'ws' * (P'{' / ->'[') * V'ws' * ((P'' / -> '&') * C(V'name') * V'ws' * (P'' / -> '$') * C(V'name') * V'ws') ^ 0 * (P'}' / -> ']') / (...) -> - var = select 2, ... - r, w = if var\sub(1, 1) == var\sub(1, 1)\upper! - ' DEI', ' DEO' - else - ' LDZ', ' STZ' - for i = 7, select('#', ...), 6 - k = select i, ... - rr, ww = if '2' == select i + 3, ... - r .. '2', w .. '2' - else - r, w - labels['~' .. var .. '.' .. k] = '.' .. var .. '/' .. k .. rr - labels['=' .. var .. '.' .. k] = '.' .. var .. '/' .. k .. ww - if i == 7 - labels['~' .. var] = '.' .. var .. rr - labels['=' .. var] = '.' .. var .. ww - ... - name: R('az', 'AZ', '09', '__', '--', '++', '**', '//', '??') ^ 1 - addr: C(P'|') * (C(V'hex') / (i) -> - if i == '0200' - return '0100' - if i\match '^01..$' - return i\sub 3 - return i - ) - literal: C P'#' * V'hex' - hex: R('09', 'af', 'AF') ^ 1 - setter: C(P'=' * V'label') / (s) -> - if not labels[s] - error 'label not found: %q in %s'\format s, filename - return labels[s] - getter: C(P'~' * V'label') / (s) -> - if not labels[s] - error 'label not found: %q in %s'\format s, filename - return labels[s] - label: R('az', 'AZ', '09', '__', '--', '..', '$$', ']]', '))', '@@', '""', ',,', '##', '||', '{{', '}}', '%%', ';;', '^^', '~~', '==', '//') ^ 1 - short: (P',' / -> ';') * (C(V'label') / (s) -> (s\gsub '%$', '&')) - rawshort: (P'.' / -> ':') * (C(V'label') / (s) -> (s\gsub '%$', '&')) - opcode: (C(R'AZ' * R'AZ' * R'AZ' * P'2' ^ -1) / (s) -> opcode_translate[s] or s) * C P'r' ^ -1 * #V'ws' - labeldef: C P'@' * V'label' - relative: (P'^' / -> ',') * (C(V'label') / (s) -> (s\gsub '%$', '&')) - sublabel: (P'$' / -> '&') * (C(V'label') / (s) -> (s\gsub '%$', '&')) - data: C(P'[') * V'ws' * (V'data_item' * V'ws') ^ 0 * C(P']') - macro: C(P'%' * V'name' * V'ws' * P'{') * V'ws' * (V'atom' * V'ows') ^ 0 * C P'}' - macroref: C V'name' - data_item: C(V'hex' * #V'ws') + V'data_string' - data_string: C((1 - S' \n\t') ^ 1 - P']') / (s) -> '"', s -} - -translate = (_filename) -> - filename = _filename - labels = {} - f = assert io.open filename - contents = f\read '*a' - f\close! - t, len = grammar\match contents - if len <= #contents - print '\027[32m%s\027[0;1m%s\027[0m'\format contents\sub(len - 100, len - 1), contents\sub(len, len + 100) - error 'no match' - filename = filename\gsub 'attic', 'auto' - f = assert io.open filename, 'w' - f\write table.concat(t) - f\close! - f = assert io.popen 'bin/assembler %s bin/boot.rom'\format filename - for l in f\lines! - print l - if l == 'Error: Assembly[Failed]' - os.exit 1 - f\close! - os.exit 0 - -translate 'attic/software/assembler.tal' -os.exit 0 - -translate 'attic/tests/opcodes.tal' -translate 'attic/tests/basics.tal' - --- for k, v in pairs t --- print k