├── .build.yml ├── .clang-format ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── build.sh ├── etc ├── asma-test.sh ├── asma.lua ├── asma.moon ├── mkuxn-fast.lua ├── mkuxn-fast.moon ├── tables │ ├── build.sh │ └── tables.c ├── tal.sublime-syntax ├── utos │ ├── build.sh │ └── utos.c ├── uxambly-translate.moon └── wavpcm │ ├── build.sh │ └── wavpcm.c ├── mkfile ├── projects ├── examples │ ├── blank.tal │ ├── demos │ │ ├── asma-piano.tal │ │ ├── automata.tal │ │ ├── bifurcan.tal │ │ ├── darena.tal │ │ ├── drum-rack.tal │ │ ├── fizzbuzz.tal │ │ ├── font.tal │ │ ├── life.tal │ │ ├── move.tal │ │ ├── piano.tal │ │ ├── polycat.tal │ │ ├── prng.tal │ │ └── theme.tal │ ├── devices │ │ ├── audio.channels.tal │ │ ├── audio.tal │ │ ├── console.echo.tal │ │ ├── console.lib.tal │ │ ├── console.tal │ │ ├── controller.tal │ │ ├── datetime.tal │ │ ├── file.load.tal │ │ ├── file.save.tal │ │ ├── file.tal │ │ ├── mouse.tal │ │ └── screen.tal │ └── gui │ │ ├── animation.tal │ │ ├── hover.tal │ │ ├── label.tal │ │ ├── picture.tal │ │ ├── proportional-font.tal │ │ ├── shapes.tal │ │ └── wallpaper.tal ├── fonts │ ├── acorn8-italic.uf1 │ ├── acorn8-regular.uf1 │ ├── atari8.uf1 │ ├── bbcmicro8.uf1 │ ├── chicago12.uf2 │ ├── diamond12.uf2 │ ├── diamond20.uf3 │ ├── geneva12.uf2 │ ├── geneva14.uf2 │ ├── geneva24.uf3 │ ├── helvetica12.uf2 │ ├── helvetica14.uf2 │ ├── helvetica24.uf3 │ ├── left8.uf1 │ ├── losangeles12.uf2 │ ├── newyork12.uf2 │ ├── newyork14.uf2 │ ├── newyork24.uf3 │ ├── orca8.uf1 │ ├── palatino12.uf2 │ ├── palatino14.uf2 │ ├── palatino24.uf3 │ ├── sans10-bold.uf2 │ ├── sans10-regular.uf2 │ ├── sapphire14.uf2 │ ├── sapphire19.uf3 │ ├── specter8.uf1 │ ├── terminal12.uf2 │ ├── times12.uf2 │ ├── times15.uf2 │ ├── times24.uf3 │ └── venice14.uf2 ├── library │ ├── asma.tal │ ├── binary-tree.tal │ ├── file-read-chunks.tal │ ├── heap.tal │ ├── load-rom.tal │ └── string.tal ├── pictures │ ├── akane2010.bit │ ├── ako10x10.chr │ ├── cibo.bit │ ├── cyr10x8.chr │ ├── dafu80x80.bit │ ├── daria10x10.chr │ ├── ergo100x0c0.bit │ ├── felix0cx0c.chr │ ├── logo1x1.bit │ ├── macpaint4020.bit │ ├── pc98.chr │ ├── tima2a1a.bit │ ├── zerotwo10x10.chr │ └── zerotwo20x20.chr ├── software │ ├── asma.tal │ ├── calc.tal │ ├── hexes.tal │ ├── launcher.tal │ ├── neralie.tal │ └── repl.tal └── sounds │ ├── bdr1.pcm │ ├── bdr2.pcm │ ├── chat.pcm │ ├── cym1.pcm │ ├── hhat.pcm │ ├── kck1.pcm │ ├── kck2.pcm │ ├── ohat.pcm │ ├── pad1.pcm │ ├── pad2.pcm │ ├── piano.pcm │ ├── ride.pcm │ ├── saw.pcm │ ├── sid1.pcm │ ├── sid2.pcm │ ├── sin.pcm │ ├── snr1.pcm │ ├── snr2.pcm │ ├── sqr.pcm │ ├── sub1.pcm │ ├── syn1.pcm │ ├── syn2.pcm │ ├── tri.pcm │ └── violin.pcm └── src ├── devices ├── apu.c ├── apu.h ├── ppu.c └── ppu.h ├── libretro.h ├── uxn-fast.c ├── uxn.c ├── uxn.h ├── uxnasm.c ├── uxncli.c └── uxnemu.c /.build.yml: -------------------------------------------------------------------------------- 1 | image: debian/oldstable 2 | packages: 3 | - curl 4 | - build-essential 5 | - libsdl2-dev 6 | - rsync 7 | oauth: pages.sr.ht/PAGES:RW 8 | environment: 9 | SITE: rabbits.srht.site 10 | SSH_HOST_KEYS: | 11 | [w1.uxn-build.ald.nu]:2222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP+IYCB4JrKklFjWSMRkPBTqUjBqUuhlDQy6/X3l8xj5 12 | [m1.uxn-build.ald.nu]:2223 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDvWVqlHh3XQ5ziEbT55K896/mW2BVDdkU6hWgIfU9md 13 | secrets: 14 | - 138ad607-a4ec-4d74-88a1-8f3be2ba2d03 15 | tasks: 16 | - prepare: | 17 | rm -f out 18 | mkdir -p out 19 | umask 077 20 | mkdir -p ~/.ssh 21 | printf '%s\n' "${SSH_HOST_KEYS}" > ~/.ssh/known_hosts 22 | printf 'User build\nStrictHostKeyChecking yes\nCheckHostIP no\nHost win\nHostName w1.uxn-build.ald.nu\nPort 2222\nHost mac\nHostName m1.uxn-build.ald.nu\nPort 2223\n' > ~/.ssh/config 23 | - build-linux: | 24 | cd uxn 25 | sed -i -e 's/.*Running.*/exit/' build.sh 26 | ./build.sh 27 | mv bin uxn 28 | tar -czf ../out/uxn-linux-amd64.tar.gz uxn 29 | cd .. 30 | - build-windows: | 31 | ssh win "rm -f uxn-windows-64bit.zip; export PATH=\"\${PATH}:/mingw64/bin\"; set -ex; cd uxn; git fetch; git checkout .; git clean -xfd; git checkout $(cd uxn && git rev-parse HEAD); sed -i -e 's/.*Running.*/exit/' build.sh; MSYSTEM=MSYS ./build.sh; mv bin uxn; zip -qr ../uxn-windows-64bit.zip uxn" 32 | rsync win:uxn-windows-64bit.zip out/ 33 | - build-macos: | 34 | ssh mac "rm -f uxn-macos.tar.gz; export PATH=\"\${PATH}:/usr/local/bin\"; set -ex; cd uxn; git fetch; git checkout .; git clean -xfd; git checkout $(cd uxn && git rev-parse HEAD); sed -i -e 's/.*Running.*/exit/' build.sh; ./build.sh; mv bin uxn; tar -zcf ../uxn-macos.tar.gz uxn" 35 | rsync mac:uxn-macos.tar.gz out/ 36 | - upload: | 37 | ls -l out 38 | tar -czf out.tar.gz -C out uxn-linux-amd64.tar.gz uxn-windows-64bit.zip uxn-macos.tar.gz 39 | acurl() { 40 | set +x 41 | curl -H "Authorization: Bearer ${OAUTH2_TOKEN}" "${@}" 42 | set -x 43 | } 44 | acurl -f "https://pages.sr.ht/publish/${SITE}" -Fcontent=@out.tar.gz 45 | acurl -f "https://pages.sr.ht/publish/${SITE}" -Fcontent=@out.tar.gz -Fprotocol=GEMINI 46 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | AlignAfterOpenBracket: DontAlign 2 | AlignEscapedNewlines: DontAlign 3 | AlignOperands: DontAlign 4 | AllowShortBlocksOnASingleLine: Always 5 | AllowShortCaseLabelsOnASingleLine: true 6 | AllowShortEnumsOnASingleLine: true 7 | AllowShortIfStatementsOnASingleLine: true 8 | AllowShortLoopsOnASingleLine: true 9 | AlwaysBreakAfterDefinitionReturnType: TopLevel 10 | BinPackArguments: false 11 | BinPackParameters: false 12 | BreakBeforeBraces: WebKit 13 | IndentCaseLabels: false 14 | TabWidth: 4 15 | IndentWidth: 4 16 | ContinuationIndentWidth: 4 17 | UseTab: ForContinuationAndIndentation 18 | ColumnLimit: 0 19 | ReflowComments: false 20 | SortIncludes: false 21 | SpaceBeforeParens: false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS* 2 | *jpg~ 3 | *png~ 4 | *gif~ 5 | *bmp~ 6 | /bin 7 | *io.bit 8 | *.bak 9 | /*-test 10 | /screenshot-*.bmp 11 | 12 | *snarf 13 | *theme 14 | 15 | *.rom 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Devine Lu Linvega 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHARED := -shared 2 | TARGET := uxn_libretro.so 3 | 4 | ifeq ($(shell uname -s),) # win 5 | SHARED := -shared 6 | TARGET := uxn_libretro.dll 7 | else ifneq ($(findstring MINGW,$(shell uname -s)),) # win 8 | SHARED := -shared 9 | TARGET := uxn_libretro.dll 10 | else ifneq ($(findstring Darwin,$(shell uname -s)),) # osx 11 | SHARED := -dynamiclib 12 | TARGET := uxn_libretro.dylib 13 | endif 14 | 15 | CFLAGS += -O3 -fPIC -flto 16 | 17 | OBJ = src/devices/ppu.o src/devices/apu.o src/uxn-fast.o src/uxnemu.o 18 | 19 | %.o: %.c 20 | $(CC) -c -o $@ $< $(CFLAGS) 21 | 22 | $(TARGET): $(OBJ) 23 | $(CC) $(SHARED) -o $@ $^ $(CFLAGS) 24 | 25 | clean: 26 | rm $(OBJ) $(TARGET) 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Uxn 2 | 3 | An assembler and emulator for the [Uxn stack-machine](https://wiki.xxiivv.com/site/uxn.html), written in ANSI C. 4 | 5 | ## Download binaries 6 | 7 | Binaries are available for 64-bit x86 computers running [Linux](https://rabbits.srht.site/uxn-linux-amd64.tar.gz) and [Windows](https://rabbits.srht.site/uxn-windows-64bit.zip). 8 | 9 | ## Build 10 | 11 | ### Linux/OS X 12 | 13 | To build the Uxn emulator, you must install [SDL2](https://wiki.libsdl.org/) for your distro. If you are using a package manager: 14 | 15 | ```sh 16 | sudo pacman -Sy sdl2 # Arch 17 | sudo apt install libsdl2-dev # Ubuntu 18 | brew install sdl2 # OS X 19 | ``` 20 | 21 | Build the assembler and emulator by running the `build.sh` script. The assembler(`uxnasm`) and emulator(`uxnemu`) are created in the `/bin` folder. 22 | 23 | ```sh 24 | ./build.sh 25 | --debug # Add debug flags to compiler 26 | --format # Format source code 27 | ``` 28 | 29 | If you wish to build the emulator without graphics mode: 30 | 31 | ```sh 32 | cc src/uxn.c -DNDEBUG -Os -g0 -s src/uxncli.c -o bin/uxncli 33 | ``` 34 | 35 | ### Plan 9 36 | 37 | To build the Uxn emulator on [9front](http://9front.org/), via [npe](https://git.sr.ht/~ft/npe): 38 | 39 | ```rc 40 | mk 41 | ``` 42 | 43 | If the build fails on 9front because of missing headers or functions, try again after `rm -r /sys/include/npe`. 44 | 45 | ### Windows 46 | 47 | Uxn can be built on Windows with [MSYS2](https://www.msys2.org/). Install by downloading from their website or with Chocolatey with `choco install msys2`. In the MSYS shell, type: 48 | 49 | ```sh 50 | pacman -S git mingw-w64-x86_64-gcc mingw64/mingw-w64-x86_64-SDL2 51 | export PATH="${PATH}:/mingw64/bin" 52 | git clone https://git.sr.ht/~rabbits/uxn 53 | cd uxn 54 | ./build.sh 55 | ``` 56 | 57 | ## Getting Started 58 | 59 | ### Emulator 60 | 61 | To launch a `.rom` in the emulator, point the emulator to the target rom file: 62 | 63 | ```sh 64 | bin/uxnemu bin/piano.rom 65 | ``` 66 | 67 | You can also use the emulator without graphics by using `uxncli`. You can find additional roms [here](https://sr.ht/~rabbits/uxn/sources), you can find prebuilt rom files [here](https://itch.io/c/248074/uxn-roms). 68 | 69 | ### Assembler 70 | 71 | The following command will create an Uxn-compatible rom from an [uxntal file](https://wiki.xxiivv.com/site/uxntal.html). Point the assembler to a `.tal` file, followed by and the rom name: 72 | 73 | ```sh 74 | bin/uxnasm projects/examples/demos/life.tal bin/life.rom 75 | ``` 76 | 77 | ### I/O 78 | 79 | You can send events from Uxn to another application, or another instance of uxn, with the Unix pipe. For a companion application that translates notes data into midi, see the [shim](https://git.sr.ht/~rabbits/shim). 80 | 81 | ```sh 82 | uxnemu orca.rom | shim 83 | ``` 84 | 85 | ## Emulator Options 86 | 87 | - `-s 1`, `-s 2` or `-s 3` set zoom (default 1) 88 | 89 | ## Emulator Controls 90 | 91 | - `F1` toggle zoom 92 | - `F2` toggle debug 93 | - `F3` capture screen 94 | 95 | ## Need a hand? 96 | 97 | Find us in `#uxn`, on irc.esper.net 98 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | echo "Cleaning.." 4 | rm -f ./bin/uxnasm 5 | rm -f ./bin/uxnemu 6 | rm -f ./bin/uxncli 7 | rm -f ./bin/boot.rom 8 | 9 | # When clang-format is present 10 | 11 | if [ "${1}" = '--format' ]; 12 | then 13 | echo "Formatting.." 14 | clang-format -i src/uxn.h 15 | clang-format -i src/uxn.c 16 | clang-format -i src/devices/ppu.h 17 | clang-format -i src/devices/ppu.c 18 | clang-format -i src/devices/apu.h 19 | clang-format -i src/devices/apu.c 20 | clang-format -i src/uxnasm.c 21 | clang-format -i src/uxnemu.c 22 | clang-format -i src/uxncli.c 23 | fi 24 | 25 | mkdir -p bin 26 | CFLAGS="-std=c89 -Wall -Wno-unknown-pragmas" 27 | case "$(uname -s 2>/dev/null)" in 28 | MSYS_NT*) # MSYS2 on Windows 29 | UXNEMU_LDFLAGS="-static $(sdl2-config --cflags --static-libs)" 30 | ;; 31 | Darwin) # macOS 32 | CFLAGS="${CFLAGS} -Wno-typedef-redefinition" 33 | UXNEMU_LDFLAGS="/usr/local/lib/libSDL2.a $(sdl2-config --cflags --static-libs | sed -e 's/-lSDL2 //')" 34 | ;; 35 | Linux|*) 36 | UXNEMU_LDFLAGS="-L/usr/local/lib $(sdl2-config --cflags --libs)" 37 | ;; 38 | esac 39 | 40 | if [ "${1}" = '--debug' ]; 41 | then 42 | echo "[debug]" 43 | CFLAGS="${CFLAGS} -DDEBUG -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined" 44 | CORE='src/uxn.c' 45 | else 46 | CFLAGS="${CFLAGS} -DNDEBUG -Os -g0 -s" 47 | CORE='src/uxn-fast.c' 48 | fi 49 | 50 | echo "Building.." 51 | cc ${CFLAGS} src/uxnasm.c -o bin/uxnasm 52 | cc ${CFLAGS} ${CORE} src/devices/ppu.c src/devices/apu.c src/uxnemu.c ${UXNEMU_LDFLAGS} -o bin/uxnemu 53 | cc ${CFLAGS} ${CORE} src/uxncli.c -o bin/uxncli 54 | 55 | if [ -d "$HOME/bin" ] 56 | then 57 | echo "Installing in $HOME/bin" 58 | cp bin/uxnemu bin/uxnasm bin/uxncli $HOME/bin/ 59 | fi 60 | 61 | # echo "Assembling(uxnasm).." 62 | # ./bin/uxnasm projects/examples/demos/piano.tal bin/piano.rom 63 | 64 | echo "Assembling(asma).." 65 | ./bin/uxnasm projects/software/asma.tal bin/asma.rom 66 | 67 | echo "Assembling(piano).." 68 | echo projects/examples/demos/piano.tal | bin/uxncli bin/asma.rom > bin/piano.rom 2> bin/piano.log 69 | 70 | echo "Running.." 71 | ./bin/uxnemu bin/piano.rom 72 | 73 | echo "Done." 74 | -------------------------------------------------------------------------------- /etc/asma-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | cd "$(dirname "${0}")/.." 4 | rm -rf asma-test 5 | mkdir asma-test 6 | 7 | expect_failure() { 8 | cat > asma-test/in.tal 9 | echo asma-test/in.tal | bin/uxncli asma-test/asma.rom > asma-test/out.rom 2> asma-test/asma.log 10 | if ! grep -qF "${1}" asma-test/asma.log; then 11 | echo "error: asma didn't report error ${1} in faulty code" 12 | cat asma-test/asma.log 13 | fi 14 | } 15 | 16 | echo 'Assembling asma with uxnasm' 17 | bin/uxnasm projects/software/asma.tal asma-test/asma.rom > asma-test/uxnasm.log 18 | for F in $(find projects -path projects/library -prune -false -or -type f -name '*.tal' | sort); do 19 | echo "Comparing assembly of ${F}" 20 | 21 | UASM_BASE="asma-test/uxnasm-$(basename "${F%.tal}")" 22 | if ! bin/uxnasm "${F}" "${UASM_BASE}.rom" 2> "${UASM_BASE}.log"; then 23 | echo "error: uxnasm failed to assemble ${F}" 24 | cat "${UASM_BASE}.log" 25 | exit 1 26 | fi 27 | xxd "${UASM_BASE}.rom" > "${UASM_BASE}.hex" 28 | 29 | ASMA_BASE="asma-test/asma-$(basename "${F%.tal}")" 30 | echo "${F}" | bin/uxncli asma-test/asma.rom > "${ASMA_BASE}.rom" 2> "${ASMA_BASE}.log" 31 | if ! grep -qF 'bytes of heap used' "${ASMA_BASE}.log"; then 32 | echo "error: asma failed to assemble ${F}, while uxnasm succeeded" 33 | cat "${ASMA_BASE}.log" 34 | exit 1 35 | fi 36 | xxd "${ASMA_BASE}.rom" > "${ASMA_BASE}.hex" 37 | 38 | diff -u "${UASM_BASE}.hex" "${ASMA_BASE}.hex" 39 | done 40 | expect_failure 'Invalid hexadecimal: $defg' <<'EOD' 41 | |1000 $defg 42 | EOD 43 | expect_failure 'Invalid hexadecimal: #defg' <<'EOD' 44 | |1000 #defg 45 | EOD 46 | expect_failure 'Address not in zero page: .hello' <<'EOD' 47 | |1000 @hello 48 | .hello 49 | EOD 50 | expect_failure 'Address outside range: ,hello' <<'EOD' 51 | |1000 @hello 52 | |2000 ,hello 53 | EOD 54 | expect_failure 'Label not found: hello' <<'EOD' 55 | hello 56 | EOD 57 | expect_failure 'Macro already exists: %me' <<'EOD' 58 | %me { #00 } 59 | %me { #01 } 60 | EOD 61 | expect_failure 'Memory overwrite: SUB' <<'EOD' 62 | |2000 ADD 63 | |1000 SUB 64 | EOD 65 | expect_failure 'Recursion level too deep:' <<'EOD' 66 | %me { you } 67 | %you { me } 68 | |1000 me 69 | EOD 70 | expect_failure 'Recursion level too deep: include' <<'EOD' 71 | include asma-test/in.tal 72 | EOD 73 | echo 'All OK' 74 | 75 | -------------------------------------------------------------------------------- /etc/asma.lua: -------------------------------------------------------------------------------- 1 | local spairs 2 | spairs = function(t) 3 | local keys 4 | do 5 | local _accum_0 = { } 6 | local _len_0 = 1 7 | for k in pairs(t) do 8 | _accum_0[_len_0] = k 9 | _len_0 = _len_0 + 1 10 | end 11 | keys = _accum_0 12 | end 13 | table.sort(keys) 14 | local i = 0 15 | return function() 16 | i = i + 1 17 | return keys[i], t[keys[i]] 18 | end 19 | end 20 | local trees = { 21 | ['asma-opcodes'] = { } 22 | } 23 | local opcodes_in_order = { } 24 | do 25 | local wanted = false 26 | for l in assert(io.lines('src/uxnasm.c')) do 27 | if l == 'static char ops[][4] = {' then 28 | wanted = true 29 | elseif wanted then 30 | if l == '};' then 31 | break 32 | end 33 | for w in l:gmatch('[^%s",][^%s",][^%s",]') do 34 | if w ~= '---' then 35 | trees['asma-opcodes'][w] = { 36 | ('"%s 00'):format(w), 37 | '' 38 | } 39 | end 40 | table.insert(opcodes_in_order, w) 41 | end 42 | end 43 | end 44 | assert(#opcodes_in_order == 32, 'didn\'t find 32 opcodes in assembler code!') 45 | end 46 | do 47 | local representation = setmetatable({ 48 | ['&'] = '26 00 ( & )' 49 | }, { 50 | __index = function(self, c) 51 | return ("'%s 00"):format(c) 52 | end 53 | }) 54 | local process 55 | process = function(label, t) 56 | trees[label] = { } 57 | for k, v in pairs(t) do 58 | trees[label][('%02x'):format(k:byte())] = { 59 | representation[k], 60 | (':%s'):format(v) 61 | } 62 | end 63 | end 64 | process('asma-first-char-normal', { 65 | ['%'] = 'asma-macro-define', 66 | ['|'] = 'asma-pad-absolute', 67 | ['$'] = 'asma-pad-relative', 68 | ['@'] = 'asma-label-define', 69 | ['&'] = 'asma-sublabel-define', 70 | ['#'] = 'asma-literal-hex', 71 | ['.'] = 'asma-literal-zero-addr', 72 | [','] = 'asma-literal-rel-addr', 73 | [';'] = 'asma-literal-abs-addr', 74 | [':'] = 'asma-abs-addr', 75 | ["'"] = 'asma-raw-char', 76 | ['"'] = 'asma-raw-word', 77 | ['{'] = 'asma-ignore', 78 | ['}'] = 'asma-ignore', 79 | ['['] = 'asma-ignore', 80 | [']'] = 'asma-ignore', 81 | ['('] = 'asma-comment-start', 82 | [')'] = 'asma-comment-end' 83 | }) 84 | process('asma-first-char-macro', { 85 | ['('] = 'asma-comment-start', 86 | [')'] = 'asma-comment-end', 87 | ['{'] = 'asma-ignore', 88 | ['}'] = 'asma-macro-end' 89 | }) 90 | process('asma-first-char-comment', { 91 | [')'] = 'asma-comment-end' 92 | }) 93 | end 94 | local traverse_node 95 | traverse_node = function(t, min, max, lefts, rights) 96 | local i = math.ceil((min + max) / 2) 97 | if min < i then 98 | lefts[t[i]] = (':&%s'):format(traverse_node(t, min, i - 1, lefts, rights)) 99 | end 100 | if i < max then 101 | rights[t[i]] = (':&%s'):format(traverse_node(t, i + 1, max, lefts, rights)) 102 | end 103 | return t[i] 104 | end 105 | local traverse_tree 106 | traverse_tree = function(t) 107 | local lefts, rights = { }, { } 108 | local keys 109 | do 110 | local _accum_0 = { } 111 | local _len_0 = 1 112 | for k in pairs(t) do 113 | _accum_0[_len_0] = k 114 | _len_0 = _len_0 + 1 115 | end 116 | keys = _accum_0 117 | end 118 | table.sort(keys) 119 | return lefts, rights, traverse_node(keys, 1, #keys, lefts, rights) 120 | end 121 | local ptr 122 | ptr = function(s) 123 | if s then 124 | return (':&%s'):format(s) 125 | end 126 | return ' $2' 127 | end 128 | local ordered_opcodes 129 | ordered_opcodes = function(t) 130 | local i = 0 131 | return function() 132 | i = i + 1 133 | local v = opcodes_in_order[i] 134 | if t[v] then 135 | return v, t[v] 136 | elseif v then 137 | return false, { 138 | '"--- 00', 139 | '' 140 | } 141 | end 142 | end 143 | end 144 | local printout = true 145 | local fmt 146 | fmt = function(...) 147 | return (('\t%-11s %-10s %-12s %-14s %s '):format(...):gsub(' +$', '\n')) 148 | end 149 | do 150 | local _with_0 = assert(io.open('projects/software/asma.tal.tmp', 'w')) 151 | for l in assert(io.lines('projects/software/asma.tal')) do 152 | if l:match('--- cut here ---') then 153 | break 154 | end 155 | _with_0:write(l) 156 | _with_0:write('\n') 157 | end 158 | _with_0:write('( --- 8< ------- 8< --- cut here --- 8< ------- 8< --- )\n') 159 | _with_0:write('( automatically generated code below )\n') 160 | _with_0:write('( see etc/asma.moon for instructions )\n') 161 | _with_0:write('\n(') 162 | _with_0:write(fmt('label', 'less', 'greater', 'key', 'binary')) 163 | _with_0:write(fmt('', 'than', 'than', 'string', 'data )')) 164 | _with_0:write('\n') 165 | for name, tree in spairs(trees) do 166 | _with_0:write(('@%s\n'):format(name)) 167 | local lefts, rights, entry = traverse_tree(tree) 168 | local sort_fn 169 | if name == 'asma-opcodes' then 170 | if rights[opcodes_in_order[1]] then 171 | rights[opcodes_in_order[1]] = rights[opcodes_in_order[1]] .. ' &_disasm' 172 | else 173 | rights[opcodes_in_order[1]] = ' $2 &_disasm' 174 | end 175 | sort_fn = ordered_opcodes 176 | else 177 | sort_fn = spairs 178 | end 179 | for k, v in sort_fn(tree) do 180 | local label 181 | if k == entry then 182 | label = '&_entry' 183 | elseif k then 184 | label = ('&%s'):format(k) 185 | else 186 | label = '' 187 | end 188 | _with_0:write(fmt(label, lefts[k] or ' $2', rights[k] or ' $2', unpack(v))) 189 | end 190 | _with_0:write('\n') 191 | end 192 | _with_0:write([[( 193 | Heap, a large temporary area for keeping track of labels. More complex 194 | programs need more of this space. If there's insufficient space then the 195 | assembly process will fail, but having extra space above what the most 196 | complex program needs provides no benefit. 197 | 198 | This heap, and the buffers below, are free to be used to hold temporary 199 | data between assembly runs, and do not need to be initialized with any 200 | particular contents to use the assembler. 201 | ) 202 | 203 | @asma-heap 204 | 205 | |e000 &end 206 | 207 | ( 208 | Buffer for use with loading source code. 209 | The minimum size is the length of the longest token plus one, which is 210 | 0x21 to keep the same capability of the C assembler. 211 | Larger sizes are more efficient, provided there is enough 212 | heap space to keep track of all the labels. 213 | ) 214 | 215 | @asma-read-buffer 216 | 217 | |f800 &end 218 | 219 | ( 220 | Buffer for use with writing output. 221 | The minimum size is 1, and larger sizes are more efficient. 222 | ) 223 | 224 | @asma-write-buffer 225 | 226 | |ffff &end 227 | 228 | ]]) 229 | _with_0:close() 230 | end 231 | return os.execute('mv projects/software/asma.tal.tmp projects/software/asma.tal') 232 | -------------------------------------------------------------------------------- /etc/asma.moon: -------------------------------------------------------------------------------- 1 | -- 2 | -- Asma tree helper script 3 | -- 4 | -- This script updates the trees at the end of projects/software/asma.tal when 5 | -- Uxn's opcode set changes or new runes (first character of tokens) are 6 | -- created, so that new changes in the C assembler can be incorporated rapidly 7 | -- into asma. 8 | -- 9 | -- To run, you need Lua or LuaJIT, and just run etc/asma.lua from the top 10 | -- directory of Uxn's git repository: 11 | -- 12 | -- lua etc/asma.lua 13 | -- 14 | -- This file is written in MoonScript, which is a language that compiles to 15 | -- Lua, the same way as e.g. CoffeeScript compiles to JavaScript. Since 16 | -- installing MoonScript has more dependencies than Lua, the compiled 17 | -- etc/asma.lua is kept in Uxn's repository and will be kept updated as this 18 | -- file changes. 19 | -- 20 | 21 | spairs = (t) -> 22 | keys = [ k for k in pairs t ] 23 | table.sort keys 24 | i = 0 25 | -> 26 | i = i + 1 27 | keys[i], t[keys[i]] 28 | 29 | trees = { 30 | ['asma-opcodes']: {} 31 | } 32 | 33 | opcodes_in_order = {} 34 | 35 | do -- opcodes 36 | wanted = false 37 | for l in assert io.lines 'src/uxnasm.c' 38 | if l == 'static char ops[][4] = {' 39 | wanted = true 40 | elseif wanted 41 | if l == '};' 42 | break 43 | for w in l\gmatch '[^%s",][^%s",][^%s",]' 44 | if w != '---' 45 | trees['asma-opcodes'][w] = { 46 | '"%s 00'\format w 47 | '' 48 | } 49 | table.insert opcodes_in_order, w 50 | assert #opcodes_in_order == 32, 'didn\'t find 32 opcodes in assembler code!' 51 | 52 | do -- first characters 53 | representation = setmetatable { 54 | '&': '26 00 ( & )' 55 | }, 56 | __index: (c) => "'%s 00"\format c 57 | process = (label, t) -> 58 | trees[label] = {} 59 | for k, v in pairs t 60 | trees[label]['%02x'\format k\byte!] = { 61 | representation[k] 62 | ':%s'\format v 63 | } 64 | process 'asma-first-char-normal', 65 | '%': 'asma-macro-define' 66 | '|': 'asma-pad-absolute' 67 | '$': 'asma-pad-relative' 68 | '@': 'asma-label-define' 69 | '&': 'asma-sublabel-define' 70 | '#': 'asma-literal-hex' 71 | '.': 'asma-literal-zero-addr' 72 | ',': 'asma-literal-rel-addr' 73 | ';': 'asma-literal-abs-addr' 74 | ':': 'asma-abs-addr' 75 | "'": 'asma-raw-char' 76 | '"': 'asma-raw-word' 77 | '{': 'asma-ignore' 78 | '}': 'asma-ignore' 79 | '[': 'asma-ignore' 80 | ']': 'asma-ignore' 81 | '(': 'asma-comment-start' 82 | ')': 'asma-comment-end' 83 | process 'asma-first-char-macro', 84 | '(': 'asma-comment-start' 85 | ')': 'asma-comment-end' 86 | '{': 'asma-ignore' 87 | '}': 'asma-macro-end' 88 | process 'asma-first-char-comment', 89 | ')': 'asma-comment-end' 90 | 91 | traverse_node = (t, min, max, lefts, rights) -> 92 | i = math.ceil (min + max) / 2 93 | if min < i 94 | lefts[t[i]] = ':&%s'\format traverse_node t, min, i - 1, lefts, rights 95 | if i < max 96 | rights[t[i]] = ':&%s'\format traverse_node t, i + 1, max, lefts, rights 97 | return t[i] 98 | 99 | traverse_tree = (t) -> 100 | lefts, rights = {}, {} 101 | keys = [ k for k in pairs t ] 102 | table.sort keys 103 | lefts, rights, traverse_node keys, 1, #keys, lefts, rights 104 | 105 | ptr = (s) -> 106 | if s 107 | return ':&%s'\format s 108 | return ' $2' 109 | 110 | ordered_opcodes = (t) -> 111 | i = 0 112 | -> 113 | i = i + 1 114 | v = opcodes_in_order[i] 115 | if t[v] 116 | return v, t[v] 117 | elseif v 118 | return false, { '"--- 00', '' } 119 | 120 | printout = true 121 | 122 | fmt = (...) -> 123 | ('\t%-11s %-10s %-12s %-14s %s '\format(...)\gsub ' +$', '\n') 124 | 125 | with assert io.open 'projects/software/asma.tal.tmp', 'w' 126 | for l in assert io.lines 'projects/software/asma.tal' 127 | if l\match '--- cut here ---' 128 | break 129 | \write l 130 | \write '\n' 131 | \write '( --- 8< ------- 8< --- cut here --- 8< ------- 8< --- )\n' 132 | \write '( automatically generated code below )\n' 133 | \write '( see etc/asma.moon for instructions )\n' 134 | \write '\n(' 135 | \write fmt 'label', 'less', 'greater', 'key', 'binary' 136 | \write fmt '', 'than', 'than', 'string', 'data )' 137 | \write '\n' 138 | for name, tree in spairs trees 139 | \write '@%s\n'\format name 140 | lefts, rights, entry = traverse_tree tree 141 | sort_fn = if name == 'asma-opcodes' 142 | if rights[opcodes_in_order[1]] 143 | rights[opcodes_in_order[1]] ..= ' &_disasm' 144 | else 145 | rights[opcodes_in_order[1]] = ' $2 &_disasm' 146 | ordered_opcodes 147 | else 148 | spairs 149 | for k, v in sort_fn tree 150 | label = if k == entry 151 | '&_entry' 152 | elseif k 153 | '&%s'\format k 154 | else 155 | '' 156 | \write fmt label, lefts[k] or ' $2', rights[k] or ' $2', unpack v 157 | \write '\n' 158 | \write [[( 159 | Heap, a large temporary area for keeping track of labels. More complex 160 | programs need more of this space. If there's insufficient space then the 161 | assembly process will fail, but having extra space above what the most 162 | complex program needs provides no benefit. 163 | 164 | This heap, and the buffers below, are free to be used to hold temporary 165 | data between assembly runs, and do not need to be initialized with any 166 | particular contents to use the assembler. 167 | ) 168 | 169 | @asma-heap 170 | 171 | |e000 &end 172 | 173 | ( 174 | Buffer for use with loading source code. 175 | The minimum size is the length of the longest token plus one, which is 176 | 0x21 to keep the same capability of the C assembler. 177 | Larger sizes are more efficient, provided there is enough 178 | heap space to keep track of all the labels. 179 | ) 180 | 181 | @asma-read-buffer 182 | 183 | |f800 &end 184 | 185 | ( 186 | Buffer for use with writing output. 187 | The minimum size is 1, and larger sizes are more efficient. 188 | ) 189 | 190 | @asma-write-buffer 191 | 192 | |ffff &end 193 | 194 | ]] 195 | \close! 196 | os.execute 'mv projects/software/asma.tal.tmp projects/software/asma.tal' 197 | 198 | -------------------------------------------------------------------------------- /etc/tables/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Formatting.." 4 | clang-format -i tables.c 5 | 6 | echo "Cleaning.." 7 | rm -f ../../bin/tables 8 | 9 | echo "Building.." 10 | mkdir -p ../../bin 11 | 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 tables.c -o ../../bin/tables 12 | 13 | echo "Assembling.." 14 | ../../bin/tables 15 | 16 | echo "Done." 17 | -------------------------------------------------------------------------------- /etc/tables/tables.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | Copyright (c) 2020 Devine Lu Linvega 6 | 7 | Permission to use, copy, modify, and distribute this software for any 8 | purpose with or without fee is hereby granted, provided that the above 9 | copyright notice and this permission notice appear in all copies. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | WITH REGARD TO THIS SOFTWARE. 13 | */ 14 | 15 | #define PI 3.14159265358979323846 16 | 17 | typedef unsigned char Uint8; 18 | 19 | int 20 | clamp(int val, int min, int max) 21 | { 22 | return (val >= min) ? (val <= max) ? val : max : min; 23 | } 24 | 25 | int 26 | main() 27 | { 28 | int i; 29 | printf("60 points on a circle128(bytex,bytey):\n\n"); 30 | for(i = 0; i < 60; ++i) { 31 | double cx = 128, cy = 128, r = 128; 32 | double pos = (i - 15) % 60; 33 | double deg = (pos / 60.0) * 360.0; 34 | double rad = deg * (PI / 180); 35 | double x = cx + r * cos(rad); 36 | double y = cy + r * sin(rad); 37 | if(i > 0 && i % 8 == 0) 38 | printf("\n"); 39 | printf("%02x%02x ", (Uint8)clamp(x, 0x00, 0xff), (Uint8)clamp(y, 0x00, 0xff)); 40 | } 41 | printf("\n\n"); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /etc/tal.sublime-syntax: -------------------------------------------------------------------------------- 1 | %YAML 1.2 2 | --- 3 | # See http://www.sublimetext.com/docs/3/syntax.html 4 | name: Uxn Assembly 5 | scopeName: tal. 6 | fileTypes: [tal] 7 | file_extensions: 8 | - tal 9 | scope: source.tal 10 | 11 | contexts: 12 | main: 13 | 14 | # get 15 | - match: '\.(\S+)\sDEI2' 16 | scope: entity.name.type.typedef 17 | pop: true 18 | - match: '\.(\S+)\sDEI' 19 | scope: entity.name.type.typedef 20 | pop: true 21 | - match: '\.(\S+)\sLDZ2' 22 | scope: entity.name.type.typedef 23 | pop: true 24 | - match: '\.(\S+)\sLDZ' 25 | scope: entity.name.type.typedef 26 | pop: true 27 | - match: '\,(\S+)\sLDR2' 28 | scope: entity.name.type.typedef 29 | pop: true 30 | - match: '\,(\S+)\sLDR' 31 | scope: entity.name.type.typedef 32 | pop: true 33 | - match: '\;(\S+)\sLDA2' 34 | scope: entity.name.type.typedef 35 | pop: true 36 | - match: '\;(\S+)\sLDA' 37 | scope: entity.name.type.typedef 38 | pop: true 39 | # set 40 | - match: '\.(\S+)\sDEO2' 41 | scope: constant.numeric 42 | pop: true 43 | - match: '\.(\S+)\sDEO' 44 | scope: constant.numeric 45 | pop: true 46 | - match: '\.(\S+)\sSTZ2' 47 | scope: constant.numeric 48 | pop: true 49 | - match: '\.(\S+)\sSTZ' 50 | scope: constant.numeric 51 | pop: true 52 | - match: '\,(\S+)\sSTR2' 53 | scope: constant.numeric 54 | pop: true 55 | - match: '\,(\S+)\sSTR' 56 | scope: constant.numeric 57 | pop: true 58 | - match: '\;(\S+)\sSTA2' 59 | scope: constant.numeric 60 | pop: true 61 | - match: '\;(\S+)\sSTA' 62 | scope: constant.numeric 63 | pop: true 64 | 65 | # label 66 | - match: '\@(\S+)\s?' 67 | scope: string.control 68 | pop: true 69 | # sublabel 70 | - match: '\&(\S+)\s?' 71 | scope: string.control 72 | pop: true 73 | # include 74 | - match: 'include' 75 | scope: string.control 76 | pop: true 77 | 78 | # jump 79 | - match: '\|(\S+)\s?' 80 | scope: entity.name.tag.structure.any 81 | pop: true 82 | # pad 83 | - match: '\$(\S+)\s?' 84 | scope: entity.name.tag.structure.any 85 | pop: true 86 | 87 | # Pushing to stack 88 | - match: '\"(\S+)\s?' 89 | scope: variable.parameter.option 90 | pop: true 91 | 92 | # Addressing 93 | - match: '\.(\S+)\s?' # zero-page 94 | scope: variable.function.shell 95 | pop: true 96 | - match: '\,(\S+)\s?' # relative 97 | scope: entity.name.tag.yaml 98 | pop: true 99 | - match: '\;(\S+)\s?' # absolute 100 | scope: keyword.control 101 | pop: true 102 | - match: '\:(\S+)\s?' # raw 103 | scope: keyword.control 104 | pop: true 105 | 106 | # Blocks 107 | - match: '\[\s?' 108 | scope: comment 109 | pop: true 110 | - match: '\]\s?' 111 | scope: comment 112 | pop: true 113 | 114 | - match: '\{' 115 | scope: variable.control 116 | push: 117 | - meta_scope: variable.control 118 | - match: '\}' 119 | pop: true 120 | 121 | - match: '\( ' 122 | scope: comment 123 | push: 124 | - meta_scope: comment.line 125 | - match: ' \)' 126 | pop: true 127 | -------------------------------------------------------------------------------- /etc/utos/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Formatting.." 4 | clang-format -i utos.c 5 | 6 | echo "Cleaning.." 7 | rm -f ../../bin/utos 8 | 9 | echo "Building.." 10 | mkdir -p ../../bin 11 | 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 12 | 13 | echo "Running.." 14 | ../../bin/utos ../../projects/sounds/pad1.ss8 ../../projects/sounds/pad1.pcm 15 | 16 | echo "Done." 17 | -------------------------------------------------------------------------------- /etc/utos/utos.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | Copyright (c) 2020 Devine Lu Linvega 6 | 7 | Permission to use, copy, modify, and distribute this software for any 8 | purpose with or without fee is hereby granted, provided that the above 9 | copyright notice and this permission notice appear in all copies. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | WITH REGARD TO THIS SOFTWARE. 13 | */ 14 | 15 | typedef unsigned char Uint8; 16 | typedef signed char Sint8; 17 | typedef unsigned short Uint16; 18 | typedef signed short Sint16; 19 | 20 | int 21 | main(int argc, char **argv) 22 | { 23 | FILE *f; 24 | Uint8 *buffer; 25 | Uint16 filelen, i; 26 | if(argc < 2 || !(f = fopen(argv[1], "rb"))) 27 | return 1; 28 | fseek(f, 0, SEEK_END); 29 | filelen = ftell(f); 30 | rewind(f); 31 | buffer = (Uint8 *)malloc(filelen * sizeof(Uint8)); 32 | fread(buffer, filelen, 1, f); 33 | fclose(f); 34 | for(i = 0; i < filelen; ++i) 35 | buffer[i] += 0x80; 36 | printf("\n\n"); 37 | fwrite(buffer, filelen, 1, fopen(argv[2], "wb")); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /etc/uxambly-translate.moon: -------------------------------------------------------------------------------- 1 | -- Used for porting Uxntal code for use with the old assembler 2 | -- in commit 82f7103a55c21b13f898b20e5d1e174e501bc825 with the 3 | -- assembler that replaced it straight afterwards. 4 | 5 | import P, R, S, C, Ct, Cp, V from require 'lpeg' 6 | 7 | local labels, filename 8 | 9 | opcode_translate = 10 | LDZ2: 'LDA' 11 | STZ2: 'STA' 12 | LDR: 'LDZ2' 13 | STR: 'STZ2' 14 | LDR2: 'LDA2' 15 | STR2: 'STA2' 16 | 17 | grammar = P { 18 | 'file' 19 | file: Ct(V'ows' * (V'atom' * V'ows') ^ 0) * Cp! 20 | ws: C S' \n\t' ^ 1 21 | ows: C S' \n\t' ^ 0 22 | 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' 23 | comment: C P'(' * (1-V'ws'*P')') ^ 0 * V'ws' * P')' 24 | variable: (P';' / -> '@') * C(V'name') * V'ws' * (P'{' / ->'[') * V'ws' * ((P'' / -> '&') * C(V'name') * V'ws' * (P'' / -> '$') * C(V'name') * V'ws') ^ 0 * (P'}' / -> ']') / (...) -> 25 | var = select 2, ... 26 | r, w = if var\sub(1, 1) == var\sub(1, 1)\upper! 27 | ' DEI', ' DEO' 28 | else 29 | ' LDZ', ' STZ' 30 | for i = 7, select('#', ...), 6 31 | k = select i, ... 32 | rr, ww = if '2' == select i + 3, ... 33 | r .. '2', w .. '2' 34 | else 35 | r, w 36 | labels['~' .. var .. '.' .. k] = '.' .. var .. '/' .. k .. rr 37 | labels['=' .. var .. '.' .. k] = '.' .. var .. '/' .. k .. ww 38 | if i == 7 39 | labels['~' .. var] = '.' .. var .. rr 40 | labels['=' .. var] = '.' .. var .. ww 41 | ... 42 | name: R('az', 'AZ', '09', '__', '--', '++', '**', '//', '??') ^ 1 43 | addr: C(P'|') * (C(V'hex') / (i) -> 44 | if i == '0200' 45 | return '0100' 46 | if i\match '^01..$' 47 | return i\sub 3 48 | return i 49 | ) 50 | literal: C P'#' * V'hex' 51 | hex: R('09', 'af', 'AF') ^ 1 52 | setter: C(P'=' * V'label') / (s) -> 53 | if not labels[s] 54 | error 'label not found: %q in %s'\format s, filename 55 | return labels[s] 56 | getter: C(P'~' * V'label') / (s) -> 57 | if not labels[s] 58 | error 'label not found: %q in %s'\format s, filename 59 | return labels[s] 60 | label: R('az', 'AZ', '09', '__', '--', '..', '$$', ']]', '))', '@@', '""', ',,', '##', '||', '{{', '}}', '%%', ';;', '^^', '~~', '==', '//') ^ 1 61 | short: (P',' / -> ';') * (C(V'label') / (s) -> (s\gsub '%$', '&')) 62 | rawshort: (P'.' / -> ':') * (C(V'label') / (s) -> (s\gsub '%$', '&')) 63 | opcode: (C(R'AZ' * R'AZ' * R'AZ' * P'2' ^ -1) / (s) -> opcode_translate[s] or s) * C P'r' ^ -1 * #V'ws' 64 | labeldef: C P'@' * V'label' 65 | relative: (P'^' / -> ',') * (C(V'label') / (s) -> (s\gsub '%$', '&')) 66 | sublabel: (P'$' / -> '&') * (C(V'label') / (s) -> (s\gsub '%$', '&')) 67 | data: C(P'[') * V'ws' * (V'data_item' * V'ws') ^ 0 * C(P']') 68 | macro: C(P'%' * V'name' * V'ws' * P'{') * V'ws' * (V'atom' * V'ows') ^ 0 * C P'}' 69 | macroref: C V'name' 70 | data_item: C(V'hex' * #V'ws') + V'data_string' 71 | data_string: C((1 - S' \n\t') ^ 1 - P']') / (s) -> '"', s 72 | } 73 | 74 | translate = (_filename) -> 75 | filename = _filename 76 | labels = {} 77 | f = assert io.open filename 78 | contents = f\read '*a' 79 | f\close! 80 | t, len = grammar\match contents 81 | if len <= #contents 82 | print '\027[32m%s\027[0;1m%s\027[0m'\format contents\sub(len - 100, len - 1), contents\sub(len, len + 100) 83 | error 'no match' 84 | filename = filename\gsub 'attic', 'auto' 85 | f = assert io.open filename, 'w' 86 | f\write table.concat(t) 87 | f\close! 88 | f = assert io.popen 'bin/assembler %s bin/boot.rom'\format filename 89 | for l in f\lines! 90 | print l 91 | if l == 'Error: Assembly[Failed]' 92 | os.exit 1 93 | f\close! 94 | os.exit 0 95 | 96 | translate 'attic/software/assembler.tal' 97 | os.exit 0 98 | 99 | translate 'attic/tests/opcodes.tal' 100 | translate 'attic/tests/basics.tal' 101 | 102 | -- for k, v in pairs t 103 | -- print k 104 | -------------------------------------------------------------------------------- /etc/wavpcm/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Formatting.." 4 | clang-format -i wavpcm.c 5 | 6 | echo "Cleaning.." 7 | rm -f ../../bin/wavpcm 8 | 9 | echo "Building.." 10 | mkdir -p ../../bin 11 | 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 wavpcm.c -o ../../bin/wavpcm 12 | 13 | echo "Running.." 14 | ../../bin/wavpcm 15 | 16 | echo "Done." 17 | -------------------------------------------------------------------------------- /etc/wavpcm/wavpcm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | Copyright (c) 2020 Devine Lu Linvega 6 | 7 | Permission to use, copy, modify, and distribute this software for any 8 | purpose with or without fee is hereby granted, provided that the above 9 | copyright notice and this permission notice appear in all copies. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | WITH REGARD TO THIS SOFTWARE. 13 | */ 14 | 15 | #define PI 3.14159265358979323846 16 | #define SAMPLES 256 17 | #define RATE 1 18 | 19 | typedef unsigned char Uint8; 20 | 21 | int 22 | clamp(int val, int min, int max) 23 | { 24 | return (val >= min) ? (val <= max) ? val : max : min; 25 | } 26 | 27 | Uint8 28 | sinw(int i) 29 | { 30 | return 0x7f * sin(i * RATE * 2 * PI / SAMPLES); 31 | } 32 | 33 | Uint8 34 | triw(int i) 35 | { 36 | if(i < 0x40) 37 | return i * 2; 38 | if(i >= 0xc0) 39 | return (i - 0xc0) * 2 - 0x7f; 40 | return 0x7f - (i - 0x40) * 2; 41 | } 42 | 43 | Uint8 44 | sqrw(int i) 45 | { 46 | return ((i * RATE) % 0xff) < 0x80 ? 0x7f : 0x80; 47 | } 48 | 49 | int 50 | main() 51 | { 52 | int i; 53 | printf("%d:\n\n", SAMPLES); 54 | for(i = 0; i < SAMPLES; ++i) { 55 | if(i % 0x10 == 0) 56 | printf("\n"); 57 | else if(i % 2 == 0) 58 | printf(" "); 59 | printf("%02x", (triw(i) + sinw(i)) / 2); 60 | } 61 | printf("\n\n"); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /mkfile: -------------------------------------------------------------------------------- 1 | /dev/null 30 | 31 | bin/uxncli: uxncli.$O uxn.$O 32 | $LD $LDFLAGS -o $target $prereq 33 | 34 | bin/uxnasm: uxnasm.$O 35 | $LD $LDFLAGS -o $target $prereq 36 | 37 | bin/uxnemu: uxnemu.$O apu.$O ppu.$O uxn.$O 38 | $LD $LDFLAGS -o $target $prereq 39 | 40 | (uxnasm|uxncli|uxnemu|uxn)\.$O:R: src/\1.c 41 | $CC $CFLAGS -Isrc -o $target src/$stem1.c 42 | 43 | (apu|ppu)\.$O:R: src/devices/\1.c 44 | $CC $CFLAGS -Isrc -o $target src/devices/$stem1.c 45 | 46 | nuke:V: clean 47 | 48 | clean:V: 49 | rm -f *.[$OS] [$OS].??* $TARG $CLEANFILES 50 | 51 | %.clean:V: 52 | rm -f $stem.[$OS] [$OS].$stem $stem 53 | 54 | install:QV: all 55 | exit 'Sorry, there is no install rule yet' 56 | 57 | #LDFLAGS=-p 58 | -------------------------------------------------------------------------------- /projects/examples/blank.tal: -------------------------------------------------------------------------------- 1 | ( a blank file ) 2 | 3 | %+ { ADD } %- { SUB } %/ { DIV } 4 | %< { LTH } %> { GTH } %= { EQU } %! { NEQ } 5 | %++ { ADD2 } %-- { SUB2 } %// { DIV2 } 6 | %<< { LTH2 } %>> { GTH2 } %== { EQU2 } %!! { NEQ2 } 7 | 8 | %DEBUG { ;print-hex JSR2 #0a .Console/write DEO } 9 | %DEBUG2 { SWP ;print-hex JSR2 ;print-hex JSR2 #0a .Console/write DEO } 10 | 11 | %RTN { JMP2r } 12 | 13 | ( devices ) 14 | 15 | |00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1 ] 16 | |10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ] 17 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 18 | |30 @Audio0 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] 19 | |40 @Audio1 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] 20 | |50 @Audio2 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] 21 | |60 @Audio3 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] 22 | |80 @Controller [ &vector $2 &button $1 &key $1 ] 23 | |90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ] 24 | |a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ] 25 | |b0 @DateTime [ &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 ] 26 | 27 | ( variables ) 28 | 29 | |0000 30 | 31 | @lista $3 32 | @listb $3 33 | @listc $3 34 | 35 | ( program ) 36 | 37 | |0100 ( -> ) 38 | 39 | ( theme ) 40 | #0fe5 .System/r DEO2 41 | #0fc5 .System/g DEO2 42 | #0f25 .System/b DEO2 43 | 44 | #01 .lista STZ 45 | #02 .lista INC STZ 46 | #03 .lista #02 + STZ 47 | 48 | #10 .listb STZ 49 | #20 .listb INC STZ 50 | #30 .listb #02 + STZ 51 | 52 | .lista .listb .listc ;add-lists-loop JSR2 53 | 54 | .listc LDZ DEBUG 55 | .listc INC LDZ DEBUG 56 | .listc #02 + LDZ DEBUG 57 | 58 | BRK 59 | 60 | ( Write a Forth word to add together two integer 61 | vectors (a.k.a. arrays) of three elements each. ) 62 | 63 | @add-lists-linear ( a b c -- ) 64 | 65 | STH 66 | ( a[0] b[0] + ) LDZk STH SWP LDZk STHr + STHkr STZ 67 | ( a[1] b[1] + ) INC LDZk STH SWP INC LDZk STHr + STHkr INC STZ 68 | ( a[2] b[2] + ) INC LDZ SWP INC LDZ + STHr #02 + STZ 69 | 70 | RTN 71 | 72 | @add-lists-loop ( a b c -- ) 73 | 74 | STH 75 | #00 #03 76 | &loop 77 | ( get incr ) OVR STH 78 | ( get a[x] ) OVR2 STHkr ADD LDZ 79 | ( get b[x] ) SWP STHkr ADD LDZ 80 | ( set c[x] ) ADD STHr STHkr ADD STZ 81 | ( incr ) SWP INC SWP 82 | LTHk ,&loop JCN 83 | POP2 POP2 POPr 84 | 85 | JMP2r 86 | 87 | @print-hex ( value -- ) 88 | 89 | STHk #04 SFT ,&parse JSR .Console/write DEO 90 | STHr #0f AND ,&parse JSR .Console/write DEO 91 | RTN 92 | &parse ( value -- char ) 93 | DUP #09 GTH ,&above JCN #30 ADD RTN &above #09 SUB #60 ADD RTN 94 | 95 | RTN -------------------------------------------------------------------------------- /projects/examples/demos/asma-piano.tal: -------------------------------------------------------------------------------- 1 | ( devices ) 2 | 3 | |00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1 ] 4 | |10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ] 5 | |a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ] 6 | 7 | ( vectors ) 8 | 9 | |0100 @reset 10 | ( 11 | Set the log level for helping to debug stuff. 12 | Its value is the bitwise OR of all the following output types: 13 | #01 prints the number of lines in the source code, 14 | #04 dumps all defined labels at end, and 15 | #08 prints the heap usage. 16 | ) 17 | #0d ;asma/log-level STA 18 | 19 | ;asma-heap ;heap STA2 20 | 21 | ( 22 | Assemble the source code into an output ROM file. 23 | 24 | If all you want is to use asma.tal to assemble files, insert a BRK 25 | after this statement. 26 | ) 27 | ;&source-file ;&dest-file ;asma-assemble-file JSR2 28 | 29 | ( 30 | If an error has occurred, BRK here, otherwise continue. (The error 31 | message will already have been printed to the Console in 32 | asma-assemble-file.) 33 | ) 34 | ;asma/error LDA2 #0000 EQU2 JMP BRK 35 | 36 | ( 37 | Load the output ROM over the currently running program, almost as if 38 | we loaded the ROM with uxnemu directly! 39 | 40 | It's not a totally pristine environment, as File/load doesn't zero out 41 | memory beyond the end of the file. So if the assembled program assumes 42 | that all memory above it is zero, it may misbehave. 43 | 44 | Asma itself doesn't use the zero page, but this example code writes a 45 | DEO2 instruction to 0x00ff. In order to execute File/load and have the 46 | CPU continue at memory location 0x0100, we write the final DEO2 47 | instruction there and jump there as our final act. 48 | 49 | Just in case the assembled code is zero-length (which can occur when 50 | assembling an empty source file), we write a BRK to the reset vector so 51 | that will prevent an infinite loop. 52 | ) 53 | ;&dest-file .File/name DEO2 54 | #0000 .File/offset-ls DEO2 55 | #ff00 .File/length DEO2 56 | #0100 .File/load 57 | LIT DEO2 #00ff STA 58 | LIT BRK #0100 STA 59 | #00ff JMP2 60 | 61 | &source-file 62 | "projects/examples/demos/piano.tal 00 63 | &dest-file 64 | "bin/asma-boot.rom 00 65 | 66 | include projects/library/asma.tal 67 | 68 | ( 69 | Heap, a large temporary area for keeping track of labels. More complex 70 | programs need more of this space. If there's insufficient space then the 71 | assembly process will fail, but having extra space above what the most 72 | complex program needs provides no benefit. 73 | 74 | This heap, and the buffers below, are free to be used to hold temporary 75 | data between assembly runs, and do not need to be initialized with any 76 | particular contents to use the assembler. 77 | ) 78 | 79 | @asma-heap 80 | 81 | |e000 &end 82 | 83 | ( 84 | Buffer for use with loading source code. 85 | The minimum size is the length of the longest token plus one, which is 86 | 0x21 to keep the same capability of the C assembler. 87 | Larger sizes are more efficient, provided there is enough 88 | heap space to keep track of all the labels. 89 | ) 90 | 91 | @asma-read-buffer 92 | 93 | |f800 &end 94 | 95 | ( 96 | Buffer for use with writing output. 97 | The minimum size is 1, and larger sizes are more efficient. 98 | ) 99 | 100 | @asma-write-buffer 101 | 102 | |ffff &end 103 | 104 | -------------------------------------------------------------------------------- /projects/examples/demos/automata.tal: -------------------------------------------------------------------------------- 1 | ( Project by Alex Schroeder - https://alexschroeder.ch ) 2 | 3 | %RTN { JMP2r } 4 | %INCR { SWP INC SWP } 5 | %CELL { #1000 } 6 | %NEXT { #2000 } 7 | 8 | ( devices ) 9 | 10 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 11 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 12 | |b0 @DateTime [ &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 ] 13 | 14 | |0000 15 | 16 | ( program ) 17 | 18 | @seed [ &x $1 &w $2 &s $2 ] 19 | 20 | |0100 ( -> ) 21 | 22 | ( theme ) 23 | #2aac .System/r DEO2 24 | #269b .System/g DEO2 25 | #378d .System/b DEO2 26 | 27 | ;seed-line JSR2 28 | 29 | ( run for a few generations ) 30 | #00 #ff 31 | &loop 32 | OVR #00 SWP ;print-line JSR2 33 | ;compute-next JSR2 34 | ;copy-next JSR2 35 | ( incr ) INCR 36 | ( loop ) LTHk ,&loop JCN 37 | POP2 38 | 39 | BRK 40 | 41 | @print-line ( y -- ) 42 | 43 | ( set ) .Screen/y DEO2 44 | ( loop through cells ) 45 | #00 #ff 46 | &loop 47 | ( copy ) OVR #00 SWP DUP2 48 | ( pos ) .Screen/x DEO2 49 | ( addr ) CELL ADD2 50 | ( draw ) LDA .Screen/pixel DEO 51 | ( incr ) INCR 52 | ( loop ) LTHk ,&loop JCN 53 | POP2 54 | 55 | RTN 56 | 57 | @compute-next ( -- ) 58 | 59 | ( loop through 62 cells ) 60 | #01 #fe 61 | &loop 62 | OVR DUP DUP ( three copies of the counter ) 63 | #01 SUB #00 SWP CELL ADD2 LDA 64 | SWP 65 | INC #00 SWP CELL ADD2 LDA 66 | ( the cell dies if the neighbors are either both dead or both alive, i.e. Rule 90 ) 67 | NEQ 68 | ( one copy of the counter and the life value ) 69 | SWP #00 SWP NEXT ADD2 STA 70 | ( incr ) INCR 71 | ( loop ) LTHk ,&loop JCN 72 | POP2 73 | 74 | RTN 75 | 76 | @copy-next ( -- ) 77 | 78 | ( loop through cells ) 79 | #00 #ff 80 | &loop 81 | OVR DUP ( two copies of the counter ) 82 | #00 SWP NEXT ADD2 LDA ( one copy of the counter and the value ) 83 | SWP #00 SWP CELL ADD2 STA 84 | ( incr ) INCR 85 | ( loop ) LTHk ,&loop JCN 86 | POP2 87 | 88 | RTN 89 | 90 | @seed-line ( -- ) 91 | 92 | .DateTime/second DEI .seed/x STZ 93 | #0000 .seed/w STZ2 94 | #e2a9 .seed/s STZ2 95 | ( loop through cells ) 96 | #01 #fe 97 | &loop 98 | OVR ( one copy of the counter ) 99 | ;rand JSR2 100 | #10 AND ( pick a bit ) 101 | SWP #00 SWP CELL ADD2 STA 102 | ( incr ) INCR 103 | ( loop ) LTHk ,&loop JCN 104 | POP2 105 | 106 | RTN 107 | 108 | ( https://en.wikipedia.org/wiki/Middle-square_method ) 109 | 110 | @rand ( -- 1 ) 111 | 112 | .seed/x LDZ #00 SWP DUP2 MUL2 113 | .seed/w LDZ2 .seed/s LDZ2 ADD2 114 | DUP2 .seed/w STZ2 115 | ADD2 116 | #04 SFT SWP #40 SFT ADD 117 | DUP .seed/x STZ 118 | 119 | RTN -------------------------------------------------------------------------------- /projects/examples/demos/bifurcan.tal: -------------------------------------------------------------------------------- 1 | ( 2 | Bifurcan 3 | Every second, the Labyrinth reorganize itself to display the time. 4 | ) 5 | 6 | %RTN { JMP2r } 7 | %MOD { DUP2 DIV MUL SUB } 8 | %TOS { #00 SWP } 9 | %2// { #01 SFT2 } 10 | %8** { #30 SFT2 } 11 | 12 | ( devices ) 13 | 14 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 15 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 16 | |90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ] 17 | |b0 @DateTime [ &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 ] 18 | |80 @Controller [ &vector $2 &button $1 &key $1 ] 19 | 20 | ( variables ) 21 | 22 | |0000 23 | 24 | @last $1 25 | @style $1 26 | @pointer [ &x $2 &y $2 ] 27 | @center [ &x $2 &y $2 ] 28 | @anchor [ &x $2 &y $2 ] 29 | 30 | ( program ) 31 | 32 | |0100 ( -> ) 33 | 34 | ( theme ) 35 | #0f3a .System/r DEO2 36 | #0fda .System/g DEO2 37 | #0faa .System/b DEO2 38 | 39 | ( vectors ) 40 | ;on-frame .Screen/vector DEO2 41 | ;on-mouse .Mouse/vector DEO2 42 | ;on-button .Controller/vector DEO2 43 | 44 | ( find center ) 45 | .Screen/width DEI2 2// .center/x STZ2 46 | .Screen/height DEI2 2// .center/y STZ2 47 | 48 | ( background ) 49 | ;tiles ;cover-pattern JSR2 50 | ;redraw JSR2 51 | 52 | BRK 53 | 54 | @on-frame ( -> ) 55 | 56 | ( only draw once per second ) 57 | .DateTime/second DEI .last LDZ NEQ #01 JCN [ BRK ] 58 | 59 | .DateTime/second DEI .last STZ 60 | ;redraw JSR2 61 | 62 | BRK 63 | 64 | @on-mouse ( -> ) 65 | 66 | ;draw-cursor JSR2 67 | 68 | .Mouse/state DEI #00 EQU ,&no-touch JCN 69 | ( incr ) .style LDZ INC #03 MOD .style STZ 70 | ( bg ) ;tiles .style LDZ #40 SFT TOS ADD2 ;cover-pattern JSR2 71 | ( fg ) ;redraw JSR2 72 | ( release ) #00 .Mouse/state DEO 73 | &no-touch 74 | 75 | BRK 76 | 77 | @on-button ( -> ) 78 | 79 | .Controller/button DEI #00 EQU ,&no-touch JCN 80 | ( incr ) .style LDZ INC #03 MOD .style STZ 81 | ( bg ) ;tiles .style LDZ #40 SFT TOS ADD2 ;cover-pattern JSR2 82 | ( fg ) ;redraw JSR2 83 | ( release ) #00 .Mouse/state DEO 84 | &no-touch 85 | 86 | BRK 87 | 88 | @redraw ( -- ) 89 | 90 | ( hrs ) 91 | [ .center/x LDZ2 #0018 SUB2 ] 92 | [ .center/y LDZ2 #0048 SUB2 ] 93 | .DateTime/hour DEI #0a DIV ;draw-number JSR2 94 | [ .center/x LDZ2 #0008 ADD2 ] 95 | [ .center/y LDZ2 #0048 SUB2 ] 96 | .DateTime/hour DEI #0a MOD ;draw-number JSR2 97 | ( min ) 98 | [ .center/x LDZ2 #0018 SUB2 ] 99 | [ .center/y LDZ2 #0018 SUB2 ] 100 | .DateTime/minute DEI #0a DIV ;draw-number JSR2 101 | [ .center/x LDZ2 #0008 ADD2 ] 102 | [ .center/y LDZ2 #0018 SUB2 ] 103 | .DateTime/minute DEI #0a MOD ;draw-number JSR2 104 | ( sec ) 105 | [ .center/x LDZ2 #0018 SUB2 ] 106 | [ .center/y LDZ2 #0018 ADD2 ] 107 | .DateTime/second DEI #0a DIV 108 | ;draw-number JSR2 109 | [ .center/x LDZ2 #0008 ADD2 ] 110 | [ .center/y LDZ2 #0018 ADD2 ] 111 | .DateTime/second DEI #0a MOD 112 | ;draw-number JSR2 113 | 114 | RTN 115 | 116 | @draw-number ( x* y* n -- ) 117 | 118 | STH 119 | ( save pos ) .anchor/y STZ2 .anchor/x STZ2 120 | #00 #0f 121 | &loop 122 | ( save-x ) OVR #03 MOD TOS 8** .anchor/x LDZ2 ADD2 .Screen/x DEO2 123 | ( save-y ) OVR #03 DIV TOS 8** .anchor/y LDZ2 ADD2 .Screen/y DEO2 124 | ( get digit* ) OVR STHkr DUP ADD TOS ;digits ADD2 LDA2 125 | ( get bit ) ROT #0e SWP SUB SFT2 #0001 AND2 126 | ( set tile ) 8** ;tiles ADD2 127 | ( set style ) .style LDZ #40 SFT TOS ADD2 128 | .Screen/addr DEO2 129 | ( draw ) #01 .Screen/sprite DEO 130 | ( incr ) SWP INC SWP 131 | LTHk ,&loop JCN 132 | POP2 133 | POPr 134 | 135 | RTN 136 | 137 | @cover-pattern ( addr* -- ) 138 | 139 | ( load ) .Screen/addr DEO2 140 | #0000 .Screen/height DEI2 141 | &ver 142 | ( save ) OVR2 .Screen/y DEO2 143 | #0000 .Screen/width DEI2 144 | &hor 145 | ( save ) OVR2 .Screen/x DEO2 146 | ( draw ) #01 .Screen/sprite DEO 147 | ( incr ) SWP2 #0008 ADD2 SWP2 148 | LTH2k ,&hor JCN 149 | POP2 POP2 150 | ( incr ) SWP2 #0008 ADD2 SWP2 151 | LTH2k ,&ver JCN 152 | POP2 POP2 153 | 154 | RTN 155 | 156 | @draw-cursor ( -- ) 157 | 158 | ( clear last cursor ) 159 | ;cursor .Screen/addr DEO2 160 | .pointer/x LDZ2 .Screen/x DEO2 161 | .pointer/y LDZ2 .Screen/y DEO2 162 | #40 .Screen/sprite DEO 163 | ( record pointer positions ) 164 | .Mouse/x DEI2 DUP2 .pointer/x STZ2 .Screen/x DEO2 165 | .Mouse/y DEI2 DUP2 .pointer/y STZ2 .Screen/y DEO2 166 | ( colorize on state ) 167 | #41 [ .Mouse/state DEI #00 NEQ ] ADD .Screen/sprite DEO 168 | 169 | RTN 170 | 171 | @cursor [ 172 | 80c0 e0f0 f8e0 1000 ] 173 | 174 | @digits [ 175 | 7b6f 2492 73e7 73cf 176 | 5bc9 79cf 49ef 7249 177 | 7bef 7bc9 ] 178 | 179 | @tiles [ 180 | 0102 0408 1020 4080 181 | 8040 2010 0804 0201 182 | 0718 2040 4080 8080 183 | 0101 0102 0204 18e0 184 | 0808 0810 e304 0808 185 | 0808 0804 e310 0808 ] 186 | -------------------------------------------------------------------------------- /projects/examples/demos/fizzbuzz.tal: -------------------------------------------------------------------------------- 1 | ( FizzBuzz: a program that prints the integers from 1 to 100. 2 | for multiples of three, print "Fizz" 3 | for multiples of five, print "Buzz" 4 | for multiples of both three and five, print "FizzBuzz" ) 5 | 6 | %MOD { DIVk MUL SUB } 7 | %HALT { #01 #0f DEO } 8 | %EMIT { #18 DEO } 9 | %RTN { JMP2r } 10 | 11 | @program 12 | 13 | |0100 ( -> ) 14 | 15 | #6400 16 | &loop 17 | LITr 00 18 | DUP #03 MOD ,&no3 JCN ;fizz-txt ;print-str JSR2 INCr &no3 19 | DUP #05 MOD ,&no5 JCN ;buzz-txt ;print-str JSR2 INCr &no5 20 | STHr ,&resume JCN 21 | ( print decimal ) 22 | DUPk #0a DIV #30 ADD EMIT 23 | #0a MOD #30 ADD EMIT 24 | &resume 25 | ( add linebreak ) #0a EMIT 26 | INC GTHk ,&loop JCN 27 | POP2 28 | 29 | HALT 30 | 31 | BRK 32 | 33 | @print-str ( addr* -- ) 34 | 35 | &loop 36 | LDAk EMIT 37 | INC2 LDAk ,&loop JCN 38 | POP2 39 | 40 | RTN 41 | 42 | @fizz-txt "Fizz $1 43 | @buzz-txt "Buzz $1 44 | -------------------------------------------------------------------------------- /projects/examples/demos/font.tal: -------------------------------------------------------------------------------- 1 | ( font ) 2 | 3 | %+ { ADD } %- { SUB } %* { MUL } %/ { DIV } 4 | %< { LTH } %> { GTH } %= { EQU } %! { NEQ } 5 | %++ { ADD2 } %-- { SUB2 } %** { MUL2 } %// { DIV2 } 6 | %<< { LTH2 } %>> { GTH2 } %== { EQU2 } %!! { NEQ2 } 7 | 8 | %RTN { JMP2r } 9 | %TOS { #00 SWP } 10 | 11 | ( devices ) 12 | 13 | |00 @System &vector $2 &pad $6 &r $2 &g $2 &b $2 14 | |20 @Screen &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 15 | |a0 @File &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 16 | 17 | ( variables ) 18 | 19 | |0000 20 | 21 | ( init ) 22 | 23 | |0100 ( -> ) 24 | 25 | ( theme ) 26 | #0fa7 .System/r DEO2 27 | #0fa7 .System/g DEO2 28 | #0fa7 .System/b DEO2 29 | 30 | ( load font ) 31 | #4900 .File/length DEO2 32 | ;font-path-large .File/name DEO2 33 | ;font-data .File/load DEO2 34 | ( draw label ) 35 | #0020 #0020 ;title #01 ;draw-uf3 JSR2 36 | 37 | ( load font ) 38 | #2100 .File/length DEO2 39 | ;font-path-medium .File/name DEO2 40 | ;font-data .File/load DEO2 41 | ( draw label ) 42 | #0020 #0048 ;body #02 ;draw-uf2 JSR2 43 | 44 | ( load font ) 45 | #0900 .File/length DEO2 46 | ;font-path-small .File/name DEO2 47 | ;font-data .File/load DEO2 48 | ( draw label ) 49 | #0030 #00b8 ;footer #03 ;draw-uf1 JSR2 50 | 51 | BRK 52 | 53 | @draw-uf1 ( x* y* text* color -- ) 54 | 55 | STH 56 | SWP2 .Screen/y DEO2 57 | SWP2 DUP2 .Screen/x DEO2 SWP2 58 | &loop 59 | LDAk 60 | DUP #0a ! ,&no-linebreak JCN 61 | ( move down ) STH OVR2 .Screen/x DEO2 STHr 62 | ( incr y ) .Screen/y DEI2 #0010 ++ .Screen/y DEO2 63 | POP ,&continue JMP &no-linebreak 64 | ( get addr ) STHk TOS #30 SFT2 ;font-data #0100 ++ ++ .Screen/addr DEO2 65 | ( get width ) STHr TOS ;font-data ++ LDA TOS 66 | ( draw ) STHkr .Screen/sprite DEO 67 | ( use width ) .Screen/x DEI2 ++ .Screen/x DEO2 68 | &continue 69 | ( incr addr ) INC2 70 | LDAk ,&loop JCN 71 | POP2 POP2 POPr 72 | 73 | RTN 74 | 75 | @draw-uf2 ( x* y* text* color -- ) 76 | 77 | STH 78 | SWP2 .Screen/y DEO2 79 | SWP2 DUP2 .Screen/x DEO2 SWP2 80 | &loop 81 | LDAk 82 | DUP #0a ! ,&no-linebreak JCN 83 | ( move down ) STH OVR2 .Screen/x DEO2 STHr 84 | ( incr y ) .Screen/y DEI2 #0010 ++ .Screen/y DEO2 85 | POP ,&continue JMP &no-linebreak 86 | STHkr ,&sprite JSR 87 | &continue 88 | ( incr addr ) INC2 89 | LDAk ,&loop JCN 90 | POP2 POP2 POPr 91 | RTN 92 | 93 | &sprite ( char color -- ) 94 | STH 95 | ( get addr ) STHk TOS #50 SFT2 ;font-data #0100 ++ ++ .Screen/addr DEO2 96 | ( get width ) STHkr TOS ;font-data ++ LDA TOS 97 | SWPr 98 | ( left-top ) STHkr .Screen/sprite DEO 99 | .Screen/y DEI2 #0008 ++ .Screen/y DEO2 100 | .Screen/addr DEI2 #0010 ++ .Screen/addr DEO2 101 | ( left-bottom ) STHkr .Screen/sprite DEO 102 | .Screen/x DEI2 #0008 ++ .Screen/x DEO2 103 | .Screen/y DEI2 #0008 -- .Screen/y DEO2 104 | DUP #0a < ,&thin JCN 105 | .Screen/addr DEI2 #0008 -- .Screen/addr DEO2 106 | ( right-top ) STHkr .Screen/sprite DEO 107 | .Screen/addr DEI2 #0010 ++ .Screen/addr DEO2 108 | .Screen/y DEI2 #0008 ++ .Screen/y DEO2 109 | ( right-bottom ) STHkr .Screen/sprite DEO 110 | .Screen/y DEI2 #0008 -- .Screen/y DEO2 &thin 111 | SWPr 112 | ( use width ) .Screen/x DEI2 ++ #0008 -- .Screen/x DEO2 113 | POPr POPr 114 | RTN 115 | 116 | RTN 117 | 118 | @draw-uf3 ( x* y* text* color -- ) 119 | 120 | STH 121 | SWP2 .Screen/y DEO2 122 | SWP2 DUP2 .Screen/x DEO2 SWP2 123 | &loop 124 | LDAk 125 | DUP #0a ! ,&no-linebreak JCN 126 | ( move down ) OVR2 .Screen/x DEO2 127 | ( incr y ) .Screen/y DEI2 #0010 ++ .Screen/y DEO2 128 | POP ,&continue JMP &no-linebreak 129 | STHkr ,&sprite JSR 130 | &continue 131 | ( incr addr ) INC2 132 | LDAk ,&loop JCN 133 | POP2 POP2 POPr 134 | RTN 135 | 136 | &sprite ( char color -- ) 137 | STH 138 | ( get addr ) DUP TOS #30 SFT2 #30 SFT2k ROT POP ADD2 ;font-data #0100 ++ ++ .Screen/addr DEO2 139 | ( get width ) TOS ;font-data ++ LDA TOS 140 | #0300 141 | &ver 142 | #0300 143 | &hor 144 | STHkr .Screen/sprite DEO 145 | .Screen/x DEI2 #0008 ++ .Screen/x DEO2 146 | .Screen/addr DEI2 #0008 ++ .Screen/addr DEO2 147 | INC GTHk ,&hor JCN 148 | POP2 149 | .Screen/y DEI2 #0008 ++ .Screen/y DEO2 150 | .Screen/x DEI2 #0018 -- .Screen/x DEO2 151 | INC GTHk ,&ver JCN 152 | POP2 153 | .Screen/y DEI2 #0018 -- .Screen/y DEO2 154 | ( use width ) .Screen/x DEI2 ++ .Screen/x DEO2 155 | POPr 156 | RTN 157 | 158 | RTN 159 | 160 | @title 161 | 5468 6520 466f 6720 486f 726e $1 162 | 163 | @body 164 | 4927 6c6c 206d 616b 6520 6120 736f 756e 165 | 6420 7468 6174 2773 2073 6f20 616c 6f6e 166 | 6520 0a74 6861 7420 6e6f 206f 6e65 2063 167 | 616e 206d 6973 7320 6974 2c20 7468 6174 168 | 2077 686f 6576 6572 200a 6865 6172 7320 169 | 6974 2077 696c 6c20 7765 6570 2069 6e20 170 | 7468 6569 7220 736f 756c 732c 200a 616e 171 | 6420 6865 6172 7468 7320 7769 6c6c 2073 172 | 6565 6d20 7761 726d 6572 2c20 0a61 6e64 173 | 2062 6569 6e67 2069 6e73 6964 6520 7769 174 | 6c6c 2073 6565 6d20 6265 7474 6572 200a 175 | 746f 2061 6c6c 2077 686f 2068 6561 7220 176 | 6974 2069 6e20 7468 6520 6469 7374 616e 177 | 7420 746f 776e 732e 20 $1 178 | 179 | @footer 180 | 2d20 4279 2052 6179 2042 7261 6462 7572 181 | 79 $1 182 | 183 | @font-path-large 184 | "projects/fonts/geneva24.uf3 $1 185 | @font-path-medium 186 | "projects/fonts/venice14.uf2 $1 187 | @font-path-small 188 | "projects/fonts/atari8.uf1 $1 189 | 190 | @font-data -------------------------------------------------------------------------------- /projects/examples/demos/life.tal: -------------------------------------------------------------------------------- 1 | ( Game Of Life 2 | Any live cell with fewer than two live neighbours dies, as if by underpopulation. 3 | Any live cell with two or three live neighbours lives on to the next generation. 4 | Any live cell with more than three live neighbours dies, as if by overpopulation. 5 | Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. ) 6 | 7 | %+ { ADD } %- { SUB } 8 | %< { LTH } %> { GTH } %= { EQU } %! { NEQ } 9 | %++ { ADD2 } %-- { SUB2 } 10 | %<< { LTH2 } %>> { GTH2 } %== { EQU2 } %!! { NEQ2 } 11 | 12 | %2/ { #01 SFT } 13 | %8/ { #03 SFT } 14 | %2// { #01 SFT2 } %8// { #03 SFT2 } 15 | %2** { #10 SFT2 } %8** { #30 SFT2 } 16 | %40** { #60 SFT2 } 17 | %8MOD { #07 AND } %2MOD { #01 AND } 18 | 19 | %TOS { #00 SWP } 20 | %RTN { JMP2r } 21 | %SFL { #40 SFT SFT } 22 | 23 | %WIDTH { #40 } %HEIGHT { #40 } 24 | %WIDTH-MOD { #3f AND } %HEIGHT-MOD { #3f AND } 25 | 26 | %BANK1 { #8000 } %BANK2 { #a000 } 27 | 28 | %GET-SIZE { WIDTH TOS 8// 40** } 29 | %GET-ITERATORS { SWP2k POP NIP } 30 | %GET-ITER { OVR2 NIP OVR SWP } 31 | 32 | ( devices ) 33 | 34 | |00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 ] 35 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 36 | |30 @Audio0 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] 37 | |80 @Controller [ &vector $2 &button $1 &key $1 ] 38 | |90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ] 39 | 40 | ( variables ) 41 | 42 | |0000 43 | 44 | @world [ &frame $1 &count $2 ] 45 | @anchor [ &x $2 &y $2 ] 46 | @pointer [ &x $2 &y $2 ] 47 | 48 | ( program ) 49 | 50 | |0100 ( -> ) 51 | 52 | ( theme ) 53 | #02cf .System/r DEO2 54 | #02ff .System/g DEO2 55 | #024f .System/b DEO2 56 | 57 | ( vectors ) 58 | ;on-frame .Screen/vector DEO2 59 | ;on-mouse .Mouse/vector DEO2 60 | ;on-control .Controller/vector DEO2 61 | 62 | ( glider ) 63 | #07 #03 ;set-cell JSR2 64 | #07 #04 ;set-cell JSR2 65 | #05 #04 ;set-cell JSR2 66 | #07 #05 ;set-cell JSR2 67 | #06 #05 ;set-cell JSR2 68 | 69 | .Screen/width DEI2 2// WIDTH TOS -- .anchor/x STZ2 70 | .Screen/height DEI2 2// HEIGHT TOS -- .anchor/y STZ2 71 | 72 | BRK 73 | 74 | @on-frame-paused ( -> ) 75 | 76 | BRK 77 | 78 | @on-frame ( -> ) 79 | 80 | .Mouse/state DEI #00 = #01 JCN [ BRK ] 81 | 82 | ( incr frame ) .world/frame LDZ INC [ DUP ] .world/frame STZ 83 | ( reset count ) #0000 .world/count STZ2 84 | 85 | #03 AND #00 = #01 JCN [ BRK ] 86 | 87 | ( clear buffer ) 88 | BANK2 STH2k GET-SIZE ++ STH2r 89 | &clear-loop 90 | DUP2 #0000 SWP2 STA2 91 | INC2 INC2 GTH2k ,&clear-loop JCN 92 | POP2 POP2 93 | 94 | ( run grid ) 95 | #00 HEIGHT 96 | &ver 97 | #00 WIDTH 98 | &hor 99 | GET-ITERATORS 100 | ( x y ) DUP2 101 | ( neighbours ) DUP2 ;get-neighbours JSR2 102 | ( state ) ROT ROT ;get-cell JSR2 103 | ,run-cell JSR 104 | SWP INC SWP 105 | LTHk ,&hor JCN 106 | POP2 107 | SWP INC SWP 108 | LTHk ,&ver JCN 109 | POP2 110 | 111 | ( move buffer ) 112 | BANK2 DUP2 GET-SIZE ++ SWP2 113 | ©-loop 114 | DUP2 LDA2k 115 | SWP2 #2000 -- STA2 116 | INC2 INC2 GTH2k ,©-loop JCN 117 | POP2 POP2 118 | 119 | ;draw-grid JSR2 120 | 121 | BRK 122 | 123 | @run-cell ( x y neighbours state -- ) 124 | 125 | #00 = ,&dead JCN 126 | &alive 127 | DUP #02 < ,&dies JCN 128 | DUP #03 > ,&dies JCN 129 | &lives POP ,save-cell JSR RTN 130 | &dies POP POP2 RTN 131 | &dead 132 | DUP #03 = ,&birth JCN POP POP2 RTN 133 | &birth POP ,save-cell JSR RTN 134 | 135 | RTN 136 | 137 | @save-cell ( x y -- ) 138 | 139 | ( get index ) 140 | HEIGHT-MOD SWP WIDTH-MOD SWP 141 | TOS 8** ROT 8/ TOS ++ [ BANK2 ++ ] 142 | ( incr count ) 143 | .world/count LDZ2 INC2 .world/count STZ2 144 | ( save in buffer ) 145 | STH2 146 | DUP2 POP 8MOD #01 SWP SFL 147 | LDAkr STHr SWP ORA 148 | STH2r STA 149 | 150 | RTN 151 | 152 | @on-mouse ( -> ) 153 | 154 | ( clear last cursor ) 155 | ;cursor .Screen/addr DEO2 156 | .pointer/x LDZ2 .Screen/x DEO2 157 | .pointer/y LDZ2 .Screen/y DEO2 158 | #40 .Screen/sprite DEO 159 | 160 | ( record pointer positions ) 161 | .Mouse/x DEI2 DUP2 .pointer/x STZ2 .Screen/x DEO2 162 | .Mouse/y DEI2 DUP2 .pointer/y STZ2 .Screen/y DEO2 163 | 164 | ( colorize on state ) 165 | #42 [ .Mouse/state DEI #00 ! ] + .Screen/sprite DEO 166 | 167 | .Mouse/state DEI #00 ! #01 JCN [ BRK ] 168 | 169 | .Mouse/x DEI2 DUP2 .anchor/x LDZ2 >> ROT ROT .anchor/x LDZ2 WIDTH DUP ADD TOS ++ INC2 << #0101 == 170 | .Mouse/y DEI2 DUP2 .anchor/y LDZ2 >> ROT ROT .anchor/y LDZ2 HEIGHT DUP ADD TOS ++ << #0101 == 171 | #0101 == #01 JCN [ BRK ] 172 | 173 | .Mouse/x DEI2 .anchor/x LDZ2 SUB2 2/ NIP 174 | .Mouse/y DEI2 .anchor/y LDZ2 SUB2 2/ NIP 175 | ;set-cell JSR2 176 | 177 | ;draw-grid JSR2 178 | 179 | BRK 180 | 181 | @on-control ( -> ) 182 | 183 | .Controller/key DEI #00 ! #01 JCN [ BRK ] 184 | 185 | .Controller/key DEI #20 ! ,&no-toggle JCN 186 | ;on-frame 187 | .Screen/vector DEI2 ;on-frame-paused == ,&swap JCN 188 | POP2 ;on-frame-paused 189 | &swap 190 | .Screen/vector DEO2 191 | &no-toggle 192 | 193 | BRK 194 | 195 | @draw-grid ( -- ) 196 | 197 | ( draw cell count ) 198 | .anchor/x LDZ2 .Screen/x DEO2 199 | .anchor/y LDZ2 HEIGHT DUP ADD TOS ++ .Screen/y DEO2 200 | .world/count LDZ2 #03 ;draw-short JSR2 201 | 202 | HEIGHT #00 203 | &ver 204 | DUP TOS 2** .anchor/y LDZ2 ++ .Screen/y DEO2 205 | WIDTH #00 206 | &hor 207 | DUP TOS 2** .anchor/x LDZ2 ++ .Screen/x DEO2 208 | GET-ITER ,get-cell JSR INC .Screen/pixel DEO 209 | INC GTHk ,&hor JCN 210 | POP2 211 | INC GTHk ,&ver JCN 212 | POP2 213 | 214 | RTN 215 | 216 | @get-index ( x y -- index* ) 217 | 218 | HEIGHT-MOD SWP WIDTH-MOD SWP 219 | TOS 8** ROT 8/ TOS ++ [ BANK1 ++ ] 220 | 221 | RTN 222 | 223 | @set-cell ( x y -- ) 224 | 225 | DUP2 ,get-index JSR STH2 226 | POP 8MOD #01 SWP SFL 227 | LDAkr STHr SWP ORA 228 | STH2r STA 229 | 230 | RTN 231 | 232 | @get-cell ( x y -- cell ) 233 | 234 | DUP2 ,get-index JSR LDA 235 | NIP SWP 236 | 8MOD 237 | SFT 2MOD 238 | 239 | RTN 240 | 241 | @get-neighbours ( x y -- neighbours ) 242 | 243 | ( -1,-1 ) DUP2 #01 - [ SWP #01 - SWP ] ,get-cell JSR STH 244 | ( 0,-1 ) DUP2 #01 - ,get-cell JSR STH ADDr 245 | ( +1,-1 ) DUP2 #01 - [ SWP INC SWP ] ,get-cell JSR STH ADDr 246 | ( -1, 0 ) DUP2 [ SWP #01 - SWP ] ,get-cell JSR STH ADDr 247 | ( +1, 0 ) DUP2 [ SWP INC SWP ] ,get-cell JSR STH ADDr 248 | ( -1,+1 ) DUP2 INC [ SWP #01 - SWP ] ,get-cell JSR STH ADDr 249 | ( 0,+1 ) DUP2 INC ,get-cell JSR STH ADDr 250 | ( +1,+1 ) INC [ SWP INC SWP ] ,get-cell JSR STH ADDr 251 | STHr 252 | 253 | RTN 254 | 255 | @draw-short ( short* color -- ) 256 | 257 | STH SWP 258 | DUP #04 SFT TOS 8** ;font-hex ++ .Screen/addr DEO2 259 | ( draw ) STHkr .Screen/sprite DEO 260 | #0f AND TOS 8** ;font-hex ++ .Screen/addr DEO2 261 | .Screen/x DEI2 #0008 ++ .Screen/x DEO2 262 | ( draw ) STHkr .Screen/sprite DEO 263 | DUP #04 SFT TOS 8** ;font-hex ++ .Screen/addr DEO2 264 | .Screen/x DEI2 #0008 ++ .Screen/x DEO2 265 | ( draw ) STHkr .Screen/sprite DEO 266 | #0f AND TOS 8** ;font-hex ++ .Screen/addr DEO2 267 | .Screen/x DEI2 #0008 ++ .Screen/x DEO2 268 | ( draw ) STHr .Screen/sprite DEO 269 | 270 | RTN 271 | 272 | @cursor 273 | 80c0 e0f0 f8e0 1000 274 | 275 | @font-hex 276 | 007c 8282 8282 827c 0030 1010 1010 1010 277 | 007c 8202 7c80 80fe 007c 8202 1c02 827c 278 | 000c 1424 4484 fe04 00fe 8080 7c02 827c 279 | 007c 8280 fc82 827c 007c 8202 1e02 0202 280 | 007c 8282 7c82 827c 007c 8282 7e02 827c 281 | 007c 8202 7e82 827e 00fc 8282 fc82 82fc 282 | 007c 8280 8080 827c 00fc 8282 8282 82fc 283 | 007c 8280 f080 827c 007c 8280 f080 8080 284 | -------------------------------------------------------------------------------- /projects/examples/demos/move.tal: -------------------------------------------------------------------------------- 1 | ( dev/controller/buttons ) 2 | 3 | %++ { INC2 } 4 | %-- { #0001 SUB2 } 5 | %2// { #01 SFT2 } 6 | 7 | ( devices ) 8 | 9 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 10 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 11 | |80 @Controller [ &vector $2 &button $1 &key $1 ] 12 | 13 | ( variables ) 14 | 15 | |0000 16 | 17 | @slime $1 18 | 19 | ( init ) 20 | 21 | |0100 ( -> ) 22 | 23 | ( theme ) 24 | #0daf .System/r DEO2 25 | #02ff .System/g DEO2 26 | #035f .System/b DEO2 27 | 28 | ( vectors ) 29 | ;on-frame .Screen/vector DEO2 30 | 31 | ( set origin ) 32 | .Screen/width DEI2 2// .Screen/x DEO2 33 | .Screen/height DEI2 2// .Screen/y DEO2 34 | 35 | ;default_icn .Screen/addr DEO2 36 | #41 .Screen/sprite DEO 37 | #0a .slime STZ 38 | 39 | BRK 40 | 41 | @on-frame ( -> ) 42 | 43 | #0a .slime STZ 44 | ;default_icn .Screen/addr DEO2 45 | 46 | ( hold ctrl key to change slime color ) 47 | .Controller/button DEI #0f AND 48 | DUP #01 NEQ ,&no-ctrl JCN #05 .slime STZ &no-ctrl 49 | DUP #02 NEQ ,&no-alt JCN #0f .slime STZ &no-alt 50 | POP 51 | 52 | ( clear ) #40 .Screen/sprite DEO 53 | 54 | ( detect movement ) 55 | .Controller/button DEI #f0 AND 56 | DUP #04 SFT #01 AND #01 NEQ ,&no-up JCN 57 | ( move ) 58 | .Screen/y DEI2 -- .Screen/y DEO2 59 | ;up_icn .Screen/addr DEO2 &no-up 60 | DUP #05 SFT #01 AND #01 NEQ ,&no-down JCN 61 | ( move ) 62 | .Screen/y DEI2 ++ .Screen/y DEO2 63 | ;down_icn .Screen/addr DEO2 &no-down 64 | DUP #06 SFT #01 AND #01 NEQ ,&no-left JCN 65 | ( move ) 66 | .Screen/x DEI2 -- .Screen/x DEO2 67 | ;left_icn .Screen/addr DEO2 &no-left 68 | DUP #07 SFT #01 AND #01 NEQ ,&no-right JCN 69 | ( move ) 70 | .Screen/x DEI2 ++ .Screen/x DEO2 71 | ;right_icn .Screen/addr DEO2 &no-right 72 | POP 73 | 74 | ( draw face ) 75 | #41 .Screen/sprite DEO 76 | 77 | ( draw slime ) 78 | ;slime_icn .Screen/addr DEO2 79 | .slime LDZ .Screen/sprite DEO 80 | 81 | BRK 82 | 83 | @default_icn [ 3c7e ffdb ffe7 7e3c ] 84 | @up_icn [ 2466 e7db ffff 7e3c ] 85 | @down_icn [ 3c7e ffff dbe7 6624 ] 86 | @left_icn [ 3c7e ef1f 1fef 7e3c ] 87 | @right_icn [ 3c7e f7f8 f8f7 7e3c ] 88 | @slime_icn [ 0000 183c 3c18 0000 ] 89 | 90 | -------------------------------------------------------------------------------- /projects/examples/demos/polycat.tal: -------------------------------------------------------------------------------- 1 | ( polycat ) 2 | 3 | %RTN { JMP2r } 4 | %2// { #01 SFT2 } 5 | %4// { #02 SFT2 } 6 | %!~ { NEQk NIP } 7 | 8 | ( devices ) 9 | 10 | |00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 ] 11 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 12 | |90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ] 13 | 14 | ( variables ) 15 | 16 | |0000 17 | 18 | @cat [ &x $2 &y $2 &timer $1 ] 19 | @pointer [ &x $2 &y $2 ] 20 | 21 | ( program ) 22 | 23 | |0100 ( -> ) 24 | 25 | ( theme ) 26 | #0a3f .System/r DEO2 27 | #05df .System/g DEO2 28 | #0caf .System/b DEO2 29 | 30 | ( find center ) 31 | .Screen/width DEI2 2// #0008 SUB2 .cat/x STZ2 32 | .Screen/height DEI2 4// DUP2k ADD2 ADD2 #0018 SUB2 .cat/y STZ2 33 | 34 | ( vectors ) 35 | ;on-mouse .Mouse/vector DEO2 36 | ;on-frame .Screen/vector DEO2 37 | 38 | ;draw-polycat JSR2 39 | ;draw-ground JSR2 40 | 41 | BRK 42 | 43 | @on-mouse ( -> ) 44 | 45 | ;draw-cursor JSR2 46 | 47 | .Mouse/x DEI2 .cat/x LDZ2 GTH2 #50 SFT 48 | .Mouse/y DEI2 .cat/y LDZ2 GTH2 #60 SFT 49 | ADD #00 SWP ;draw-eye JSR2 50 | 51 | BRK 52 | 53 | @on-frame ( -> ) 54 | 55 | .cat/timer LDZ INC [ DUP ] .cat/timer STZ 56 | DUP ,&skip0 JCN #0000 ;draw-tail JSR2 &skip0 57 | [ #10 ] !~ ,&skip1 JCN #0001 ;draw-tail JSR2 &skip1 58 | [ #20 ] !~ ,&skip2 JCN #0002 ;draw-tail JSR2 &skip2 59 | [ #30 ] !~ ,&skip3 JCN #0003 ;draw-tail JSR2 &skip3 60 | [ #40 ] !~ ,&skip4 JCN #0002 ;draw-tail JSR2 &skip4 61 | [ #50 ] !~ ,&skip5 JCN #0001 ;draw-tail JSR2 &skip5 62 | POP 63 | 64 | BRK 65 | 66 | @draw-polycat ( -- ) 67 | 68 | ( ears ) 69 | .cat/y LDZ2 .Screen/y DEO2 70 | .cat/x LDZ2 STH2k #0008 SUB2 .Screen/x DEO2 71 | ;ears .Screen/addr DEO2 72 | #81 .Screen/sprite DEO 73 | STH2r .Screen/x DEO2 74 | ;ears #0010 ADD2 .Screen/addr DEO2 75 | #81 .Screen/sprite DEO 76 | 77 | #0000 ,draw-eye JSR 78 | #0000 ,draw-tail JSR 79 | 80 | RTN 81 | 82 | @draw-eye ( quad* -- ) 83 | 84 | .cat/y LDZ2 #0008 ADD2 .Screen/y DEO2 85 | .cat/x LDZ2 STH2k #0008 SUB2 .Screen/x DEO2 86 | DUP2 ;eye ADD2 .Screen/addr DEO2 87 | ( draw ) #81 .Screen/sprite DEO 88 | STH2r .Screen/x DEO2 89 | ;eye #0010 ADD2 ADD2 .Screen/addr DEO2 90 | ( draw ) #81 .Screen/sprite DEO 91 | 92 | RTN 93 | 94 | @draw-tail ( frame* -- ) 95 | 96 | .cat/y LDZ2 #0010 ADD2 .Screen/y DEO2 97 | .cat/x LDZ2 STH2k #0008 SUB2 .Screen/x DEO2 98 | ;body .Screen/addr DEO2 99 | ( draw ) #81 .Screen/sprite DEO 100 | STH2r .Screen/x DEO2 101 | #40 SFT2 ;body #0010 ADD2 ADD2 .Screen/addr DEO2 102 | ( draw ) #81 .Screen/sprite DEO 103 | 104 | RTN 105 | 106 | @draw-cursor ( -- ) 107 | 108 | ( clear last cursor ) 109 | ;cursor .Screen/addr DEO2 110 | .pointer/x LDZ2 .Screen/x DEO2 111 | .pointer/y LDZ2 .Screen/y DEO2 112 | #40 .Screen/sprite DEO 113 | 114 | ( record pointer positions ) 115 | .Mouse/x DEI2 DUP2 .pointer/x STZ2 .Screen/x DEO2 116 | .Mouse/y DEI2 DUP2 .pointer/y STZ2 .Screen/y DEO2 117 | 118 | ( colorize on state ) 119 | #41 [ .Mouse/state DEI #00 NEQ ] ADD .Screen/sprite DEO 120 | 121 | RTN 122 | 123 | @draw-ground ( -- ) 124 | 125 | .cat/y LDZ2 #0018 ADD2 .Screen/y DEO2 126 | .cat/x LDZ2 #0010 SUB2 .Screen/x DEO2 127 | ;ground .Screen/addr DEO2 128 | 129 | #10 #00 130 | &loop 131 | ( draw ) #01 .Screen/sprite DEO 132 | ( sety ) .Screen/addr DEI2 #0008 ADD2 .Screen/addr DEO2 133 | ( setx ) .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 134 | ( incr ) INC 135 | GTHk ,&loop JCN 136 | POP2 137 | 138 | RTN 139 | 140 | @cursor 141 | 80c0 e0f0 f8e0 1000 142 | 143 | @ears 144 | 081c 3e3e 7f7f ffff 081c 3e3e 7f7f fffc 145 | 081c 3c3e 7e7e ffff 081c 3c3e 7e7e ff1f 146 | 147 | @eye 148 | ffff ffff ff7f 3f0f f7ef cfe7 f07c 3f0f 149 | ffff ffff fffe fcf0 87c3 c183 071e fcf0 150 | ffff ffff ff7f 3f0f f0e1 c1e0 f07c 3f0f 151 | ffff ffff fffe fcf0 f7fb f9f3 071e fcf0 152 | ffff ffff ff7f 3f0f f0e7 cfef f77c 3f0f 153 | ffff ffff fffe fcf0 0783 c1c3 871e fcf0 154 | ffff ffff ff7f 3f0f f0e0 c1e1 f07c 3f0f 155 | ffff ffff fffe fcf0 07f3 f9fb f71e fcf0 156 | 157 | @body 158 | 0707 0707 0302 0200 0107 0707 0300 0000 159 | e0f0 f0e0 e080 8000 c0f2 f9f9 fef8 b000 160 | e0f0 f0e0 e080 8000 c0f2 f9f9 fef8 b000 161 | e0f0 f0e0 e080 8000 c0f2 faf9 fef8 b000 162 | e0f0 f0e0 e080 8000 c0f1 faf9 fef8 b000 163 | 0707 0707 0f08 1000 0307 0707 0f00 0000 164 | e0e0 e0e0 e080 8000 f2f9 f9fe b884 8400 165 | 166 | @ground 167 | bf00 5c02 0202 020c ef10 6f90 8080 8074 168 | ff00 fe01 0100 0116 fd00 3c40 4040 4028 169 | -------------------------------------------------------------------------------- /projects/examples/demos/prng.tal: -------------------------------------------------------------------------------- 1 | ( pseudo-random number generator, 2 | based on two 16-bit xorshift algorithms by George Marsaglia 3 | http://www.jstatsoft.org/v08/i14/paper ) 4 | 5 | ( devices ) 6 | 7 | |00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1 ] 8 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 9 | |b0 @DateTime [ &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 ] 10 | 11 | ( variables ) 12 | 13 | |0000 14 | 15 | ( program ) 16 | 17 | |0100 ( -> ) 18 | ( init ) 19 | ;on-frame .Screen/vector DEO2 20 | 21 | ( seed prng (must be nonzero) ) 22 | #00 .DateTime/second DEI 23 | #00 .DateTime/minute DEI #60 SFT2 EOR2 24 | #00 .DateTime/hour DEI #c0 SFT2 EOR2 ;prng2/x STA2 25 | #00 .DateTime/hour DEI #04 SFT2 26 | #00 .DateTime/day DEI #10 SFT2 EOR2 27 | #00 .DateTime/month DEI #60 SFT2 EOR2 28 | .DateTime/year DEI2 #a0 SFT2 EOR2 ;prng2/y STA2 29 | ;prng2/x LDA2 ;prng2/y LDA2 EOR2 30 | ORAk ,&non-zero JCN INC2 &non-zero 31 | ;prng/seed STA2 32 | 33 | ( theme ) 34 | #0fe5 .System/r DEO2 35 | #0fc5 .System/g DEO2 36 | #0f25 .System/b DEO2 37 | BRK 38 | 39 | @on-frame ( -> ) 40 | #c0 41 | &loop 42 | ,draw-pixel JSR 43 | INC 44 | DUP ,&loop JCN 45 | POP 46 | BRK 47 | 48 | @draw-pixel 49 | ,prng2 JSR 50 | #00 SWP .Screen/x DEO2 51 | #00 SWP .Screen/y DEO2 52 | #01 .Screen/pixel DEO 53 | JMP2r 54 | 55 | @prng ( -- number* ) 56 | ( returns the next number in a 65,535-long sequence, 57 | which is never zero but every other 16-bit number 58 | appears once before the sequence repeats ) 59 | ( http://www.retroprogramming.com/2017/07/xorshift-pseudorandom-numbers-in-z80.html ) 60 | ,&seed LDR2 61 | DUP2 #70 SFT2 EOR2 62 | DUP2 #09 SFT2 EOR2 63 | DUP2 #80 SFT2 EOR2 64 | ,&seed STR2k POP 65 | JMP2r 66 | 67 | &seed $2 68 | 69 | @prng2 ( -- number* ) 70 | ( returns the next number in a (2^32-1)-long sequence ) 71 | ( http://b2d-f9r.blogspot.com/2010/08/16-bit-xorshift-rng-now-with-more.html ) 72 | ,&x LDR2 73 | DUP2 #50 SFT2 EOR2 74 | DUP2 #03 SFT2 EOR2 75 | ,&y LDR2 DUP2 ,&x STR2 76 | DUP2 #01 SFT2 EOR2 EOR2 77 | ,&y STR2k POP 78 | JMP2r 79 | 80 | &x $2 81 | &y $2 82 | 83 | -------------------------------------------------------------------------------- /projects/examples/devices/audio.channels.tal: -------------------------------------------------------------------------------- 1 | ( dev/audio ) 2 | 3 | %MOD { DUP2 DIV MUL SUB } 4 | 5 | ( devices ) 6 | 7 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 8 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 9 | |30 @Audio0 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] 10 | |40 @Audio1 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] 11 | |50 @Audio2 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] 12 | |60 @Audio3 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] 13 | 14 | ( variables ) 15 | 16 | |0000 17 | 18 | @timer $1 19 | @counter $1 20 | 21 | |0100 ( -> ) 22 | 23 | ( theme ) 24 | #00ff .System/r DEO2 25 | #0f0f .System/g DEO2 26 | #0ff0 .System/b DEO2 27 | 28 | ( vectors ) 29 | ;on-frame .Screen/vector DEO2 30 | 31 | ( setup synth ) 32 | #1202 .Audio0/adsr DEO2 33 | ;saw .Audio0/addr DEO2 34 | #0100 .Audio0/length DEO2 35 | #88 .Audio0/volume DEO 36 | 37 | #0101 .Audio1/adsr DEO2 38 | ;tri .Audio1/addr DEO2 39 | #0100 .Audio1/length DEO2 40 | #88 .Audio1/volume DEO 41 | 42 | #0112 .Audio2/adsr DEO2 43 | ;sin .Audio2/addr DEO2 44 | #0100 .Audio2/length DEO2 45 | #88 .Audio2/volume DEO 46 | 47 | #0022 .Audio3/adsr DEO2 48 | ;piano .Audio3/addr DEO2 49 | #0100 .Audio3/length DEO2 50 | #88 .Audio3/volume DEO 51 | 52 | BRK 53 | 54 | @on-frame ( -> ) 55 | 56 | ( incr ) .timer LDZ INC .timer STZ 57 | ( skip ) .timer LDZ #10 EQU #01 JCN [ BRK ] 58 | 59 | ( get note ) 60 | .counter LDZ #18 MOD #30 ADD 61 | .Audio0/pitch .counter LDZ #03 AND #40 SFT ADD DEO 62 | 63 | .counter LDZ INC .counter STZ 64 | #00 .timer STZ 65 | 66 | BRK 67 | 68 | @saw 69 | 0003 0609 0c0f 1215 181b 1e21 2427 2a2d 70 | 3033 3639 3b3e 4143 4649 4b4e 5052 5557 71 | 595b 5e60 6264 6667 696b 6c6e 7071 7274 72 | 7576 7778 797a 7b7b 7c7d 7d7e 7e7e 7e7e 73 | 7f7e 7e7e 7e7e 7d7d 7c7b 7b7a 7978 7776 74 | 7574 7271 706e 6c6b 6967 6664 6260 5e5b 75 | 5957 5552 504e 4b49 4643 413e 3b39 3633 76 | 302d 2a27 2421 1e1b 1815 120f 0c09 0603 77 | 00fd faf7 f4f1 eeeb e8e5 e2df dcd9 d6d3 78 | d0cd cac7 c5c2 bfbd bab7 b5b2 b0ae aba9 79 | a7a5 a2a0 9e9c 9a99 9795 9492 908f 8e8c 80 | 8b8a 8988 8786 8585 8483 8382 8282 8282 81 | 8182 8282 8282 8383 8485 8586 8788 898a 82 | 8b8c 8e8f 9092 9495 9799 9a9c 9ea0 a2a5 83 | a7a9 abae b0b2 b5b7 babd bfc2 c5c7 cacd 84 | d0d3 d6d9 dcdf e2e5 e8eb eef1 f4f7 fafd 85 | @tri 86 | 8082 8486 888a 8c8e 9092 9496 989a 9c9e 87 | a0a2 a4a6 a8aa acae b0b2 b4b6 b8ba bcbe 88 | c0c2 c4c6 c8ca ccce d0d2 d4d6 d8da dcde 89 | e0e2 e4e6 e8ea ecee f0f2 f4f6 f8fa fcfe 90 | fffd fbf9 f7f5 f3f1 efed ebe9 e7e5 e3e1 91 | dfdd dbd9 d7d5 d3d1 cfcd cbc9 c7c5 c3c1 92 | bfbd bbb9 b7b5 b3b1 afad aba9 a7a5 a3a1 93 | 9f9d 9b99 9795 9391 8f8d 8b89 8785 8381 94 | 7f7d 7b79 7775 7371 6f6d 6b69 6765 6361 95 | 5f5d 5b59 5755 5351 4f4d 4b49 4745 4341 96 | 3f3d 3b39 3735 3331 2f2d 2b29 2725 2321 97 | 1f1d 1b19 1715 1311 0f0d 0b09 0705 0301 98 | 0103 0507 090b 0d0f 1113 1517 191b 1d1f 99 | 2123 2527 292b 2d2f 3133 3537 393b 3d3f 100 | 4143 4547 494b 4d4f 5153 5557 595b 5d5f 101 | 6163 6567 696b 6d6f 7173 7577 797b 7d7f 102 | @sin 103 | 8083 8689 8c8f 9295 989b 9ea1 a4a7 aaad 104 | b0b3 b6b9 bbbe c1c3 c6c9 cbce d0d2 d5d7 105 | d9db dee0 e2e4 e6e7 e9eb ecee f0f1 f2f4 106 | f5f6 f7f8 f9fa fbfb fcfd fdfe fefe fefe 107 | fffe fefe fefe fdfd fcfb fbfa f9f8 f7f6 108 | f5f4 f2f1 f0ee eceb e9e7 e6e4 e2e0 dedb 109 | d9d7 d5d2 d0ce cbc9 c6c3 c1be bbb9 b6b3 110 | b0ad aaa7 a4a1 9e9b 9895 928f 8c89 8683 111 | 807d 7a77 7471 6e6b 6865 625f 5c59 5653 112 | 504d 4a47 4542 3f3d 3a37 3532 302e 2b29 113 | 2725 2220 1e1c 1a19 1715 1412 100f 0e0c 114 | 0b0a 0908 0706 0505 0403 0302 0202 0202 115 | 0102 0202 0202 0303 0405 0506 0708 090a 116 | 0b0c 0e0f 1012 1415 1719 1a1c 1e20 2225 117 | 2729 2b2e 3032 3537 3a3d 3f42 4547 4a4d 118 | 5053 5659 5c5f 6265 686b 6e71 7477 7a7d 119 | @piano 120 | 8182 8588 8d91 959b a1a6 aaad b2b5 b8bd 121 | c1c7 cbd0 d5d9 dde1 e5e5 e4e4 e1dc d7d1 122 | cbc5 bfb8 b2ac a6a2 9c97 928d 8884 807c 123 | 7977 7574 7372 7272 7273 7372 706d 6964 124 | 605b 5650 4d49 4643 4342 4244 4548 4a4d 125 | 5052 5556 5758 5554 5150 4c4a 4744 423f 126 | 3d3c 3a38 3835 3431 3030 2f31 3336 393e 127 | 4449 4e54 5a60 666b 7175 7b82 8990 989e 128 | a6ab b1b6 babd bebf bfbe bbb9 b6b3 b0ae 129 | aaa8 a6a3 a19e 9c9a 9997 9696 9798 9b9e 130 | a1a4 a6a9 a9ac adad adae aeaf b0b0 b1b1 131 | b3b3 b4b4 b4b3 b3b1 b0ad abab a9a9 a8a8 132 | a7a5 a19d 9891 8b84 7e77 726e 6b6b 6b6c 133 | 6f71 7477 7776 7370 6c65 5e56 4e48 423f 134 | 3d3c 3b3a 3a39 3838 3839 393a 3c3e 4146 135 | 4a50 575b 6064 686a 6e70 7274 7677 7a7d 136 | 137 | @melody [ 138 | 54 52 54 4f 4b 4f 48 ff 139 | 54 52 54 4f 4b 4f 48 ff 140 | 54 56 57 56 57 54 56 54 141 | 56 52 54 52 54 50 54 ff ] 142 | -------------------------------------------------------------------------------- /projects/examples/devices/audio.tal: -------------------------------------------------------------------------------- 1 | ( dev/audio ) 2 | 3 | %2// { #01 SFT2 } 4 | %4** { #20 SFT2 } 5 | %8** { #30 SFT2 } 6 | %20MOD { #1f AND } 7 | %RTN { JMP2r } 8 | 9 | %GET-NOTE { #00 SWP ;melody ADD2 LDA } 10 | %GET-HEXCHAR { #00 SWP 8** ;font-hex ADD2 .Screen/addr DEO2 } 11 | 12 | ( devices ) 13 | 14 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 15 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 16 | |30 @Audio0 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] 17 | |80 @Controller [ &vector $2 &button $1 &key $1 ] 18 | 19 | ( variables ) 20 | 21 | |0000 22 | 23 | @timer $1 24 | @progress $1 25 | @selection $1 26 | @offset 27 | &x $2 &y $2 28 | 29 | |0100 ( -> ) 30 | 31 | ( theme ) 32 | #0f8f .System/r DEO2 33 | #0f8f .System/g DEO2 34 | #0f80 .System/b DEO2 35 | 36 | ( vectors ) 37 | ;on-frame .Screen/vector DEO2 38 | ;on-button .Controller/vector DEO2 39 | 40 | ( setup synth ) 41 | #0208 .Audio0/adsr DEO2 42 | ;saw .Audio0/addr DEO2 43 | #0100 .Audio0/length DEO2 44 | #dd .Audio0/volume DEO ( TODO: turn ON ) 45 | 46 | ( center ) 47 | .Screen/width DEI2 2// #0080 SUB2 .offset/x STZ2 48 | .Screen/height DEI2 2// #0040 SUB2 .offset/y STZ2 49 | 50 | ;draw JSR2 51 | #02 ;draw-selector JSR2 52 | 53 | BRK 54 | 55 | @on-button ( -> ) 56 | 57 | .Controller/button DEI #04 SFT 58 | [ #01 ] NEQk NIP ,&no-up JCN 59 | .selection LDZ STHk 60 | #00 ;draw-note JSR2 61 | [ STHkr GET-NOTE INC ] #00 STHkr ;melody ADD2 STA 62 | STHr #01 ;draw-note JSR2 63 | #02 ;draw-selector JSR2 64 | &no-up 65 | [ #02 ] NEQk NIP ,&no-down JCN 66 | .selection LDZ STHk 67 | #00 ;draw-note JSR2 68 | [ STHkr GET-NOTE #01 SUB ] #00 STHkr ;melody ADD2 STA 69 | STHr #01 ;draw-note JSR2 70 | #02 ;draw-selector JSR2 71 | &no-down 72 | [ #04 ] NEQk NIP ,&no-left JCN 73 | #00 ;draw-selector JSR2 74 | .selection LDZ #01 SUB 20MOD .selection STZ 75 | #02 ;draw-selector JSR2 76 | &no-left 77 | [ #08 ] NEQk NIP ,&no-right JCN 78 | #00 ;draw-selector JSR2 79 | .selection LDZ INC 20MOD .selection STZ 80 | #02 ;draw-selector JSR2 81 | &no-right 82 | POP 83 | 84 | BRK 85 | 86 | @on-frame ( -> ) 87 | 88 | ( incr ) .timer LDZ INC .timer STZ 89 | ( skip ) .timer LDZ #10 EQU #01 JCN [ BRK ] 90 | .progress LDZ 91 | ( play note ) DUP GET-NOTE .Audio0/pitch DEO 92 | ( erase last ) DUP #01 SUB 20MOD #01 ,draw-note JSR 93 | ( draw current ) #01 ,draw-note JSR 94 | ( incr ) .progress LDZ INC 20MOD .progress STZ 95 | #00 .timer STZ 96 | 97 | BRK 98 | 99 | @draw ( -- ) 100 | 101 | #20 #00 102 | &loop 103 | DUP #01 ,draw-note JSR 104 | INC GTHk ,&loop JCN 105 | POP2 106 | 107 | RTN 108 | 109 | @draw-note ( id color -- ) 110 | 111 | STH STH 112 | ( set x ) [ #00 STHkr ] 8** .offset/x LDZ2 ADD2 .Screen/x DEO2 113 | ( set y ) [ #00 #00 STHkr ;melody ADD2 LDA ] 4** #0100 SWP2 SUB2 .offset/y LDZ2 ADD2 #0080 ADD2 .Screen/y DEO2 114 | ( set addr ) ;marker-icn [ #00 .progress LDZ STHr EQU #08 MUL ADD2 ] .Screen/addr DEO2 115 | ( draw ) STHr .Screen/sprite DEO 116 | 117 | RTN 118 | 119 | @draw-selector ( color -- ) 120 | 121 | STH 122 | [ #00 .selection LDZ ] 8** .offset/x LDZ2 ADD2 .Screen/x DEO2 123 | #0070 .offset/y LDZ2 ADD2 .Screen/y DEO2 124 | ;selector-icn .Screen/addr DEO2 125 | STHkr .Screen/sprite DEO 126 | 127 | .Screen/y DEI2 #0008 ADD2 .Screen/y DEO2 128 | .selection LDZ GET-NOTE STHr ,draw-byte JSR 129 | 130 | RTN 131 | 132 | @draw-byte ( byte color -- ) 133 | 134 | STH 135 | DUP 136 | #04 SFT GET-HEXCHAR 137 | ( draw ) STHkr .Screen/sprite DEO 138 | .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 139 | #0f AND GET-HEXCHAR 140 | ( draw ) STHr .Screen/sprite DEO 141 | 142 | RTN 143 | 144 | @melody 145 | 54 52 54 4f 4b 4f 48 ff 146 | 54 52 54 4f 4b 4f 48 ff 147 | 54 56 57 56 57 54 56 54 148 | 56 52 54 52 54 50 54 ff 149 | 150 | @selector-icn 151 | 0000 0010 387c 0000 152 | 153 | @marker-icn 154 | 3844 8282 8244 3800 155 | 387c fefe fe7c 3800 156 | 157 | @saw 158 | 0003 0609 0c0f 1215 181b 1e21 2427 2a2d 159 | 3033 3639 3b3e 4143 4649 4b4e 5052 5557 160 | 595b 5e60 6264 6667 696b 6c6e 7071 7274 161 | 7576 7778 797a 7b7b 7c7d 7d7e 7e7e 7e7e 162 | 7f7e 7e7e 7e7e 7d7d 7c7b 7b7a 7978 7776 163 | 7574 7271 706e 6c6b 6967 6664 6260 5e5b 164 | 5957 5552 504e 4b49 4643 413e 3b39 3633 165 | 302d 2a27 2421 1e1b 1815 120f 0c09 0603 166 | 00fd faf7 f4f1 eeeb e8e5 e2df dcd9 d6d3 167 | d0cd cac7 c5c2 bfbd bab7 b5b2 b0ae aba9 168 | a7a5 a2a0 9e9c 9a99 9795 9492 908f 8e8c 169 | 8b8a 8988 8786 8585 8483 8382 8282 8282 170 | 8182 8282 8282 8383 8485 8586 8788 898a 171 | 8b8c 8e8f 9092 9495 9799 9a9c 9ea0 a2a5 172 | a7a9 abae b0b2 b5b7 babd bfc2 c5c7 cacd 173 | d0d3 d6d9 dcdf e2e5 e8eb eef1 f4f7 fafd 174 | 175 | @font-hex ( 0-F ) 176 | 007c 8282 8282 827c 0030 1010 1010 1010 177 | 007c 8202 7c80 80fe 007c 8202 1c02 827c 178 | 000c 1424 4484 fe04 00fe 8080 7c02 827c 179 | 007c 8280 fc82 827c 007c 8202 1e02 0202 180 | 007c 8282 7c82 827c 007c 8282 7e02 827c 181 | 007c 8202 7e82 827e 00fc 8282 fc82 82fc 182 | 007c 8280 8080 827c 00fc 8282 8282 82fc 183 | 007c 8280 f080 827c 007c 8280 f080 8080 -------------------------------------------------------------------------------- /projects/examples/devices/console.echo.tal: -------------------------------------------------------------------------------- 1 | ( dev/console ) 2 | 3 | ( 4 | Copies data from stdin to both stdout and stderr. 5 | ) 6 | 7 | |10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ] 8 | 9 | ( init ) 10 | 11 | |0100 ( -> ) 12 | 13 | ;on-stdin .Console/vector DEO2 14 | 15 | BRK 16 | 17 | @on-stdin ( -> ) 18 | 19 | .Console/read DEI 20 | DUP .Console/write DEO 21 | .Console/error DEO 22 | 23 | BRK 24 | -------------------------------------------------------------------------------- /projects/examples/devices/console.lib.tal: -------------------------------------------------------------------------------- 1 | ( dev/console ) 2 | 3 | %RTN { JMP2r } 4 | %PRINT { ;print JSR2 } 5 | %BR { #0a .Console/write DEO } 6 | 7 | ( devices ) 8 | 9 | |10 @Console [ &pad $8 &write $1 ] 10 | 11 | ( variables ) 12 | 13 | |0000 14 | 15 | @number [ &started $1 ] 16 | 17 | ( init ) 18 | 19 | |0100 ( -> ) 20 | 21 | ;char-txt PRINT #42 .Console/write DEO BR 22 | ;byte-txt PRINT #ab ;print-byte JSR2 BR 23 | ;short-txt PRINT #cdef ;print-short JSR2 BR 24 | ;string-txt PRINT ;hello-word ;print JSR2 BR 25 | 26 | ;hello-word ;print JSR2 27 | #ffff ;print-short JSR2 28 | ;is-word ;print JSR2 29 | #ffff ;print-short-decimal JSR2 30 | 31 | BRK 32 | 33 | @print ( addr* -- ) 34 | 35 | &loop 36 | ( send ) LDAk .Console/write DEO 37 | ( incr ) INC2 38 | ( loop ) LDAk ,&loop JCN 39 | POP2 40 | 41 | RTN 42 | 43 | @print-short ( short* -- ) 44 | LIT '0 .Console/write DEO 45 | LIT 'x .Console/write DEO 46 | OVR #04 SFT ,&hex JSR 47 | SWP #0f AND ,&hex JSR 48 | DUP #04 SFT ,&hex JSR 49 | #0f AND ,&hex JMP 50 | 51 | &hex 52 | #30 ADD DUP #3a LTH ,¬-alpha JCN 53 | #27 ADD 54 | ¬-alpha 55 | .Console/write DEO 56 | RTN 57 | 58 | @print-byte ( byte -- ) 59 | LIT '0 .Console/write DEO 60 | LIT 'x .Console/write DEO 61 | DUP #04 SFT ,&hex JSR 62 | #0f AND ,&hex JMP 63 | 64 | &hex 65 | #30 ADD DUP #39 GTH #27 MUL ADD .Console/write DEO 66 | RTN 67 | 68 | @print-short-decimal ( short -- ) 69 | #00 .number/started STZ 70 | DUP2 #2710 DIV2 DUP2 ,&digit JSR #2710 MUL2 SUB2 71 | DUP2 #03e8 DIV2 DUP2 ,&digit JSR #03e8 MUL2 SUB2 72 | DUP2 #0064 DIV2 DUP2 ,&digit JSR #0064 MUL2 SUB2 73 | DUP2 #000a DIV2 DUP2 ,&digit JSR #000a MUL2 SUB2 74 | ,&digit JSR 75 | .number/started LDZ ,&end JCN 76 | LIT '0 .Console/write DEO 77 | &end 78 | RTN 79 | 80 | &digit 81 | NIP 82 | DUP .number/started LDZ ORA #02 JCN 83 | POP JMP2r 84 | LIT '0 ADD .Console/write DEO 85 | #01 .number/started STZ 86 | RTN 87 | 88 | @char-txt "char: 20 $1 89 | @byte-txt "byte: 20 $1 90 | @short-txt "short: 20 $1 91 | @string-txt "string: 20 $1 92 | 93 | @hello-word "hello 20 "World! 0a 00 94 | @is-word 20 "is 20 00 95 | -------------------------------------------------------------------------------- /projects/examples/devices/console.tal: -------------------------------------------------------------------------------- 1 | ( dev/console ) 2 | 3 | |00 @System $e &debug 4 | |10 @Console $8 &write 5 | 6 | ( init ) 7 | 8 | |0100 ( -> ) 9 | 10 | ;hello-word 11 | &while 12 | ( send ) LDAk .Console/write DEO 13 | INC2 LDAk ,&while JCN 14 | POP2 15 | ( show debugger ) #01 .System/debug DEO 16 | 17 | BRK 18 | 19 | @hello-word "Hello 20 "Uxn! -------------------------------------------------------------------------------- /projects/examples/devices/controller.tal: -------------------------------------------------------------------------------- 1 | ( dev/controller/keys ) 2 | 3 | %+ { ADD } %- { SUB } %/ { DIV } 4 | %< { LTH } %> { GTH } %= { EQU } %! { NEQ } 5 | %++ { ADD2 } %-- { SUB2 } %// { DIV2 } 6 | %<< { LTH2 } %>> { GTH2 } %== { EQU2 } %!! { NEQ2 } 7 | 8 | %RTN { JMP2r } 9 | %TOS { #00 SWP } 10 | %LTS2 { #8000 ++ SWP2 #8000 ++ >> } 11 | 12 | ( devices ) 13 | 14 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 15 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 16 | |80 @Controller [ &vector $2 &button $1 &key $1 ] 17 | 18 | ( variables ) 19 | 20 | |0000 21 | 22 | @center 23 | &x $2 24 | &y $2 25 | @frame 26 | &w $2 &h $2 27 | &x0 $2 &y0 $2 28 | &x1 $2 &y1 $2 29 | @color $1 30 | @rect 31 | &x1 $2 &y1 $2 32 | &x2 $2 &y2 $2 33 | 34 | ( init ) 35 | 36 | |0100 ( -> ) 37 | 38 | ( theme ) 39 | #0ff7 .System/r DEO2 40 | #0f07 .System/g DEO2 41 | #0f07 .System/b DEO2 42 | 43 | ( find center ) 44 | .Screen/width DEI2 #01 SFT2 .center/x STZ2 45 | .Screen/height DEI2 #01 SFT2 .center/y STZ2 46 | 47 | ( place controller ) 48 | #0068 .frame/w STZ2 49 | #0030 .frame/h STZ2 50 | .center/x LDZ2 .frame/w LDZ2 #0002 // -- .frame/x0 STZ2 51 | .center/y LDZ2 .frame/h LDZ2 #0002 // -- .frame/y0 STZ2 52 | .frame/x0 LDZ2 .frame/w LDZ2 ++ .frame/x1 STZ2 53 | .frame/y0 LDZ2 .frame/h LDZ2 ++ .frame/y1 STZ2 54 | 55 | ( vectors ) 56 | ;on-button .Controller/vector DEO2 57 | 58 | ;draw-controller JSR2 59 | 60 | BRK 61 | 62 | @on-button ( -> ) 63 | 64 | ;draw-controller JSR2 65 | 66 | BRK 67 | 68 | @draw-controller ( -- ) 69 | 70 | .Controller/button DEI STH 71 | 72 | ( frame ) 73 | .frame/x0 LDZ2 .frame/y0 LDZ2 74 | .frame/x1 LDZ2 .frame/y1 LDZ2 75 | #01 ;line-rect JSR2 76 | ( d-pad ) 77 | .frame/x0 LDZ2 #0010 ++ .Screen/x DEO2 78 | .frame/y0 LDZ2 #0010 ++ .Screen/y DEO2 79 | ;controller-icn/dpad-up .Screen/addr DEO2 80 | #03 [ STHkr #04 SFT #01 AND DUP + - ] .Screen/sprite DEO 81 | .Screen/y DEI2 #0010 ++ .Screen/y DEO2 82 | ;controller-icn/dpad-down .Screen/addr DEO2 83 | #03 [ STHkr #05 SFT #01 AND DUP + - ] .Screen/sprite DEO 84 | .Screen/y DEI2 #0008 -- .Screen/y DEO2 85 | .Screen/x DEI2 #0008 -- .Screen/x DEO2 86 | ;controller-icn/dpad-left .Screen/addr DEO2 87 | #03 [ STHkr #06 SFT #01 AND DUP + - ] .Screen/sprite DEO 88 | .Screen/x DEI2 #0010 ++ .Screen/x DEO2 89 | ;controller-icn/dpad-right .Screen/addr DEO2 90 | #03 [ STHkr #07 SFT #01 AND DUP + - ] .Screen/sprite DEO 91 | .Screen/x DEI2 #0008 -- .Screen/x DEO2 92 | ;controller-icn/dpad .Screen/addr DEO2 93 | #03 .Screen/sprite DEO 94 | 95 | ( options ) 96 | .center/y LDZ2 #0009 ++ .Screen/y DEO2 97 | .center/x LDZ2 #0009 -- .Screen/x DEO2 98 | ;controller-icn/option .Screen/addr DEO2 99 | #03 [ STHkr #02 SFT #01 AND DUP + - ] .Screen/sprite DEO 100 | .center/x LDZ2 #0004 ++ .Screen/x DEO2 101 | ;controller-icn/option .Screen/addr DEO2 102 | #03 [ STHkr #03 SFT #01 AND DUP + - ] .Screen/sprite DEO 103 | 104 | ( buttons ) 105 | .center/y LDZ2 #0000 ++ .Screen/y DEO2 106 | .center/x LDZ2 #0018 ++ .Screen/x DEO2 107 | ;controller-icn/button .Screen/addr DEO2 108 | #03 [ STHkr #01 SFT #01 AND - ] .Screen/sprite DEO 109 | .Screen/y DEI2 #000a ++ .Screen/y DEO2 110 | ;font-hex #000b #30 SFT2 ++ .Screen/addr DEO2 111 | #03 .Screen/sprite DEO 112 | 113 | .center/y LDZ2 #0000 ++ .Screen/y DEO2 114 | .center/x LDZ2 #0024 ++ .Screen/x DEO2 115 | ;controller-icn/button .Screen/addr DEO2 116 | #03 [ STHr #01 AND - ] .Screen/sprite DEO 117 | .Screen/y DEI2 #000a ++ .Screen/y DEO2 118 | ;font-hex #000a #30 SFT2 ++ .Screen/addr DEO2 119 | #03 .Screen/sprite DEO 120 | 121 | .center/x LDZ2 #0010 -- .Screen/x DEO2 122 | .center/y LDZ2 #0010 -- .Screen/y DEO2 123 | .Controller/button DEI2 #03 ;draw-short JSR2 124 | 125 | RTN 126 | 127 | ( generics ) 128 | 129 | @draw-short ( short* color -- ) 130 | 131 | STH SWP 132 | DUP #04 SFT TOS #30 SFT2 ;font-hex ++ .Screen/addr DEO2 133 | ( draw ) STHkr .Screen/sprite DEO 134 | #0f AND TOS #30 SFT2 ;font-hex ++ .Screen/addr DEO2 135 | .Screen/x DEI2 #0008 ++ .Screen/x DEO2 136 | ( draw ) STHkr .Screen/sprite DEO 137 | DUP #04 SFT TOS #30 SFT2 ;font-hex ++ .Screen/addr DEO2 138 | .Screen/x DEI2 #0008 ++ .Screen/x DEO2 139 | ( draw ) STHkr .Screen/sprite DEO 140 | #0f AND TOS #30 SFT2 ;font-hex ++ .Screen/addr DEO2 141 | .Screen/x DEI2 #0008 ++ .Screen/x DEO2 142 | ( draw ) STHr .Screen/sprite DEO 143 | 144 | RTN 145 | 146 | @line-rect ( x1* y1* x2* y2* color -- ) 147 | 148 | ( load ) .color STZ DUP2 STH2 .rect/y2 STZ2 .rect/x2 STZ2 DUP2 STH2 .rect/y1 STZ2 .rect/x1 STZ2 149 | STH2r INC2 STH2r 150 | &ver 151 | ( save ) OVR2 .Screen/y DEO2 152 | ( draw ) .rect/x1 LDZ2 .Screen/x DEO2 .color LDZ DUP .Screen/pixel DEO 153 | ( draw ) .rect/x2 LDZ2 .Screen/x DEO2 .Screen/pixel DEO 154 | ( incr ) SWP2 INC2 SWP2 155 | OVR2 OVR2 LTS2 ,&ver JCN 156 | POP2 POP2 157 | .rect/x1 LDZ2 INC2 .rect/x2 LDZ2 #0001 -- 158 | &hor 159 | ( save ) OVR2 .Screen/x DEO2 160 | ( draw ) .rect/y1 LDZ2 .Screen/y DEO2 .color LDZ DUP .Screen/pixel DEO 161 | ( draw ) .rect/y2 LDZ2 .Screen/y DEO2 .Screen/pixel DEO 162 | ( incr ) SWP2 INC2 SWP2 163 | OVR2 OVR2 INC2 LTS2 ,&hor JCN 164 | POP2 POP2 165 | 166 | RTN 167 | 168 | @controller-icn 169 | &dpad ffff ffff ffff ffff 170 | &dpad-up 7eff e7c3 ffff ffff 171 | &dpad-down ffff ffff c3e7 ff7e 172 | &dpad-left 7fff efcf cfef ff7f 173 | &dpad-right feff f7f3 f3f7 fffe 174 | &option 0000 7eff ff7e 0000 175 | &button 3c7e ffff ffff 7e3c 176 | 177 | @font-hex 178 | 003c 4242 4242 3c00 0018 0808 0808 1c00 179 | 003c 4202 3c40 7e00 003c 421c 0242 3c00 180 | 000c 1424 447e 0400 007e 407c 0242 3c00 181 | 003c 407c 4242 3c00 007e 0204 0810 1000 182 | 003c 423c 4242 3c00 003c 4242 3e02 3c00 183 | 003c 4242 7e42 4200 007c 427c 4242 7c00 184 | 003c 4240 4042 3c00 007c 4242 4242 7c00 185 | 007e 4078 4040 7e00 007e 4078 4040 4000 186 | -------------------------------------------------------------------------------- /projects/examples/devices/datetime.tal: -------------------------------------------------------------------------------- 1 | ( Dev/Time ) 2 | 3 | %+ { ADD } %- { SUB } %/ { DIV } 4 | %< { LTH } %> { GTH } %= { EQU } %! { NEQ } 5 | %++ { ADD2 } %-- { SUB2 } %// { DIV2 } 6 | %<< { LTH2 } %>> { GTH2 } %== { EQU2 } %!! { NEQ2 } 7 | 8 | %8* { #30 SFT } 9 | %2// { #01 SFT2 } 10 | %4// { #02 SFT2 } 11 | %2** { #10 SFT2 } 12 | 13 | %DIAMETER { #0080 } 14 | %RADIUS { DIAMETER 2// } 15 | 16 | %TOS { #00 SWP } 17 | %RTN { JMP2r } 18 | %MOD { DUP2 DIV MUL SUB } 19 | %ABS2 { DUP2 #0f SFT2 EQU #05 JCN #0000 SWP2 -- } 20 | %SCALEX { 2// .Screen/width DEI2 2// ++ RADIUS -- } 21 | %SCALEY { 2// .Screen/height DEI2 2// ++ RADIUS -- } 22 | %12HOURS { DUP #0c GTH #0c MUL SUB } 23 | %LTS2 { #8000 ++ SWP2 #8000 ++ GTH2 } 24 | %GTS2 { #8000 ++ SWP2 #8000 ++ LTH2 } 25 | %GET-CHAR-SPRITE { 8* TOS ;font-hex ++ } 26 | 27 | ( devices ) 28 | 29 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 30 | |10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ] 31 | |20 @Screen [ &vector $2 &width $2 &height $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 32 | |b0 @DateTime [ &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 ] 33 | 34 | ( variables ) 35 | 36 | |0000 37 | 38 | @color $1 39 | @current $1 40 | @center 41 | &x $2 &y $2 42 | @needles [ &hx $2 &hy $2 &mx $2 &my $2 &sx $2 &sy $2 ] 43 | @line [ &x0 $2 &y0 $2 &x $2 &y $2 &sx $2 &sy $2 &dx $2 &dy $2 &e1 $2 &e2 $2 ] 44 | 45 | ( program ) 46 | 47 | |0100 ( -> ) 48 | 49 | ( theme ) 50 | #e0f8 .System/r DEO2 51 | #e008 .System/g DEO2 52 | #e008 .System/b DEO2 53 | 54 | #00f0 .Screen/width DEO2 55 | #00f0 .Screen/height DEO2 56 | 57 | ( vectors ) 58 | ;on-frame .Screen/vector DEO2 59 | 60 | DIAMETER SCALEX .center/x STZ2 61 | DIAMETER SCALEY .center/y STZ2 62 | 63 | 64 | BRK 65 | 66 | @on-frame ( -> ) 67 | 68 | ( only draw once per second ) 69 | .DateTime/second DEI .current LDZ = ,&skip JCN 70 | ;draw-clock JSR2 71 | ;draw-display JSR2 72 | &skip 73 | 74 | .DateTime/second DEI .current STZ 75 | 76 | BRK 77 | 78 | @draw-clock ( -- ) 79 | 80 | ( clear ) 81 | .center/x LDZ2 .center/y LDZ2 .needles/sx LDZ2 .needles/sy LDZ2 #00 ;draw-line JSR2 82 | .center/x LDZ2 .center/y LDZ2 .needles/mx LDZ2 .needles/my LDZ2 #00 ;draw-line JSR2 83 | .center/x LDZ2 .center/y LDZ2 .needles/hx LDZ2 .needles/hy LDZ2 #00 ;draw-line JSR2 84 | 85 | ( place ) 86 | #00 .DateTime/second DEI 2** ;table ++ LDA2 87 | TOS SCALEY .needles/sy STZ2 88 | TOS SCALEX .needles/sx STZ2 89 | #00 .DateTime/minute DEI 2** ;table ++ LDA2 90 | TOS 4// DUP2k ++ ++ #0020 ++ SCALEY .needles/my STZ2 91 | TOS 4// DUP2k ++ ++ #0020 ++ SCALEX .needles/mx STZ2 92 | #00 .DateTime/hour DEI 12HOURS #20 SFTk NIP ADD 2** ;table ++ LDA2 93 | TOS 2// RADIUS ++ SCALEY .needles/hy STZ2 94 | TOS 2// RADIUS ++ SCALEX .needles/hx STZ2 95 | 96 | ( needles ) 97 | .center/x LDZ2 .center/y LDZ2 .needles/sx LDZ2 .needles/sy LDZ2 #02 ;draw-line JSR2 98 | .center/x LDZ2 .center/y LDZ2 .needles/mx LDZ2 .needles/my LDZ2 #01 ;draw-line JSR2 99 | .center/x LDZ2 .center/y LDZ2 .needles/hx LDZ2 .needles/hy LDZ2 #03 ;draw-line JSR2 100 | 101 | ( circle ) 102 | #3c #00 103 | &loop 104 | ( load ) DUP TOS 2** ;table ++ LDA2 105 | TOS SCALEY .Screen/y DEO2 106 | TOS SCALEX .Screen/x DEO2 107 | DUP #0f MOD #00 EQU INC .Screen/pixel DEO 108 | INC GTHk ,&loop JCN 109 | POP2 110 | 111 | RTN 112 | 113 | @draw-display ( -- ) 114 | 115 | ( auto x ) #01 .Screen/auto DEO 116 | 117 | ( date ) 118 | .Screen/height DEI2 2// #0058 -- .Screen/y DEO2 119 | .Screen/width DEI2 2// #0014 -- .Screen/x DEO2 120 | .DateTime/month DEI INC 121 | DUP #0a DIV GET-CHAR-SPRITE .Screen/addr DEO2 122 | #03 .Screen/sprite DEO 123 | #0a MOD GET-CHAR-SPRITE .Screen/addr DEO2 124 | #03 .Screen/sprite DEO 125 | .Screen/x DEI2 #0008 ++ .Screen/x DEO2 126 | .DateTime/day DEI 127 | DUP #0a DIV GET-CHAR-SPRITE .Screen/addr DEO2 128 | #03 .Screen/sprite DEO 129 | #0a MOD GET-CHAR-SPRITE .Screen/addr DEO2 130 | #03 .Screen/sprite DEO 131 | 132 | ( time ) 133 | .Screen/height DEI2 2// #0050 ++ .Screen/y DEO2 134 | .Screen/width DEI2 2// #0020 -- .Screen/x DEO2 135 | .DateTime/hour DEI 136 | DUP #0a DIV GET-CHAR-SPRITE .Screen/addr DEO2 137 | #01 .Screen/sprite DEO 138 | #0a MOD GET-CHAR-SPRITE .Screen/addr DEO2 139 | #01 .Screen/sprite DEO 140 | ;spacer-icn .Screen/addr DEO2 141 | .DateTime/second DEI #01 AND .Screen/sprite DEO 142 | .DateTime/minute DEI 143 | DUP #0a DIV GET-CHAR-SPRITE .Screen/addr DEO2 144 | #01 .Screen/sprite DEO 145 | #0a MOD GET-CHAR-SPRITE .Screen/addr DEO2 146 | #01 .Screen/sprite DEO 147 | ;spacer-icn .Screen/addr DEO2 148 | .DateTime/second DEI #01 AND .Screen/sprite DEO 149 | .DateTime/second DEI 150 | DUP #0a DIV GET-CHAR-SPRITE .Screen/addr DEO2 151 | #01 .Screen/sprite DEO 152 | #0a MOD GET-CHAR-SPRITE .Screen/addr DEO2 153 | #01 .Screen/sprite DEO 154 | 155 | ( auto none ) #00 .Screen/auto DEO 156 | 157 | RTN 158 | 159 | @draw-line ( x1 y1 x2 y2 color -- ) 160 | 161 | ( load ) .color STZ .line/y0 STZ2 .line/x0 STZ2 .line/y STZ2 .line/x STZ2 162 | .line/x0 LDZ2 .line/x LDZ2 -- ABS2 .line/dx STZ2 163 | .line/y0 LDZ2 .line/y LDZ2 -- ABS2 #0000 SWP2 -- .line/dy STZ2 164 | #ffff #00 .line/x LDZ2 .line/x0 LDZ2 LTS2 2** ++ .line/sx STZ2 165 | #ffff #00 .line/y LDZ2 .line/y0 LDZ2 LTS2 2** ++ .line/sy STZ2 166 | .line/dx LDZ2 .line/dy LDZ2 ++ .line/e1 STZ2 167 | &loop 168 | .line/x LDZ2 .Screen/x DEO2 169 | .line/y LDZ2 .Screen/y DEO2 170 | .color LDZ .Screen/pixel DEO 171 | [ .line/x LDZ2 .line/x0 LDZ2 == ] 172 | [ .line/y LDZ2 .line/y0 LDZ2 == ] #0101 == ,&end JCN 173 | .line/e1 LDZ2 2** .line/e2 STZ2 174 | .line/e2 LDZ2 .line/dy LDZ2 LTS2 ,&skipy JCN 175 | .line/e1 LDZ2 .line/dy LDZ2 ++ .line/e1 STZ2 176 | .line/x LDZ2 .line/sx LDZ2 ++ .line/x STZ2 177 | &skipy 178 | .line/e2 LDZ2 .line/dx LDZ2 GTS2 ,&skipx JCN 179 | .line/e1 LDZ2 .line/dx LDZ2 ++ .line/e1 STZ2 180 | .line/y LDZ2 .line/sy LDZ2 ++ .line/y STZ2 181 | &skipx 182 | ;&loop JMP2 183 | &end 184 | 185 | RTN 186 | 187 | @table ( 60 positions on a circle in bytes ) 188 | 8000 8d00 9a02 a706 b40b c011 cb18 d520 189 | df2a e734 ee40 f44b f958 fd65 ff72 ff80 190 | ff8d fd9a f9a7 f4b4 eec0 e7cb dfd5 d5df 191 | cbe7 c0ee b4f4 a7f9 9afd 8dff 80ff 72ff 192 | 65fd 58f9 4bf4 40ee 34e7 2adf 20d5 18cb 193 | 11c0 0bb4 06a7 029a 008d 0080 0072 0265 194 | 0658 0b4b 113f 1834 202a 2a20 3418 3f11 195 | 4b0b 5806 6502 7200 196 | 197 | @spacer-icn 198 | 0000 0010 0010 0000 199 | 200 | @font-hex ( 0-F ) 201 | 007c 8282 8282 827c 0030 1010 1010 1010 202 | 007c 8202 7c80 80fe 007c 8202 1c02 827c 203 | 000c 1424 4484 fe04 00fe 8080 7c02 827c 204 | 007c 8280 fc82 827c 007c 8202 1e02 0202 205 | 007c 8282 7c82 827c 007c 8282 7e02 827c 206 | 007c 8202 7e82 827e 00fc 8282 fc82 82fc 207 | 007c 8280 8080 827c 00fc 8282 8282 82fc 208 | 007c 8280 f080 827c 007c 8280 f080 8080 209 | -------------------------------------------------------------------------------- /projects/examples/devices/file.load.tal: -------------------------------------------------------------------------------- 1 | ( simple Dev/File reading example ) 2 | 3 | ( devices ) 4 | 5 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 6 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 7 | |a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ] 8 | 9 | ( variables ) 10 | 11 | |0000 12 | 13 | ( program ) 14 | 15 | |0100 ( -> ) 16 | ;try-load JSR2 17 | BRK 18 | 19 | @try-load ( -- ) 20 | ( load contents from file ) 21 | #1000 .File/length DEO2 22 | ;filename .File/name DEO2 23 | ;contents .File/load DEO2 24 | 25 | .File/success DEI2 ORA ,&success JCN 26 | ( failed to read: bright yellow background ) 27 | #f0f7 .System/r DEO2 28 | #f0f7 .System/g DEO2 29 | #00f7 .System/b DEO2 30 | JMP2r 31 | 32 | &success 33 | ( read successful: dark blue background, show contents ) 34 | #00f7 .System/r DEO2 35 | #00f7 .System/g DEO2 36 | #40f7 .System/b DEO2 37 | ;contents DUP2 .File/success DEI2 ADD2 SWP2 ;draw JSR2 38 | JMP2r 39 | 40 | @draw ( end-ptr* ptr* -- ) 41 | EQU2k ,&end JCN 42 | LDAk 43 | DUP #0a EQU ,&linefeed JCN 44 | #0005 SFT2 ;font ADD2 45 | .Screen/addr DEO2 46 | #09 .Screen/sprite DEO 47 | .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 48 | &next 49 | INC2 50 | ,draw JMP 51 | 52 | &linefeed 53 | POP 54 | #0000 .Screen/x DEO2 55 | .Screen/y DEI2 #0008 ADD2 .Screen/y DEO2 56 | ,&next JMP 57 | 58 | &end 59 | POP2 POP2 60 | JMP2r 61 | 62 | @get-x-advance ( font-char-addr* -- advance* ) 63 | ( Save two 00 bytes for later use ) 64 | #0000 SWP2 65 | ( First, load the eight bytes that make up the character ) 66 | LDA2k SWP2 #0002 ADD2 67 | LDA2k SWP2 #0002 ADD2 68 | LDA2k SWP2 #0002 ADD2 69 | LDA2 70 | ( OR all the bytes together, so we know which columns contain filled pixels ) 71 | ORA2 ORA2 ORA2 ORA 72 | ( Find the lowest set bit (using one of the 00 bytes at the top, but not consuming it) ) 73 | SUBk AND 74 | ( Convert the nine possible values (00-80) into an offset into the magic table (00-08). ) 75 | ( They get jumbled up with these two operations, but each possible value remains unique ) 76 | #a3 MUL #16 DIV 77 | ( Load the byte from the magic table, return a short (consuming/returning the 00 bytes at the top) ) 78 | ;&magic ADD2 LDA 79 | JMP2r 80 | ( The magic table performs the last bit of arithmetic we want: 81 | * the advance in x should be one more than the number of columns with filled pixels, 82 | * with a maximum of 8, and 83 | * a minimum of 3. ) 84 | &magic 85 | 03 ( lowest set bit is 00, 0 columns wide ) 86 | 06 ( lowest set bit is 08, 5 columns wide ) 87 | 05 ( lowest set bit is 10, 4 columns wide ) 88 | 08 ( lowest set bit is 02, 7 columns wide ) 89 | 04 ( lowest set bit is 20, 3 columns wide ) 90 | 03 ( lowest set bit is 80, 1 column wide ) 91 | 07 ( lowest set bit is 04, 6 columns wide ) 92 | 08 ( lowest set bit is 01, 8 columns wide ) 93 | 03 ( lowest set bit is 40, 2 columns wide ) 94 | 95 | @font ( spectrum-zx font ) 96 | [ 97 | 0000 0000 0000 0000 0000 2400 7e3c 0000 0000 2400 3c42 0000 0000 6c7c 7c38 1000 98 | 0010 387c 7c38 1000 0038 387c 6c10 3800 0010 387c 7c10 3800 0000 0018 1800 0000 99 | 007e 4242 4242 7e00 0000 1824 2418 0000 0018 2442 4224 1800 001e 063a 4a48 3000 100 | 0038 446c 107c 1000 000c 0808 0838 3800 003e 2222 2266 6600 0000 0822 0022 0800 101 | 0000 1018 1c18 1000 0000 0818 3818 0800 0008 1c00 001c 0800 0028 2828 2800 2800 102 | 003e 4a4a 3a0a 0a00 000c 3046 620c 3000 0000 0000 0000 ffff 0010 3800 3810 0038 103 | 0008 1c2a 0808 0800 0008 0808 2a1c 0800 0000 0804 7e04 0800 0000 1020 7e20 1000 104 | 0000 4040 7e00 0000 0000 0024 6624 0000 0000 1038 7c00 0000 0000 007c 3810 0000 105 | 0000 0000 0000 0000 0008 0808 0800 0800 0014 1400 0000 0000 0024 7e24 247e 2400 106 | 0008 1e28 1c0a 3c08 0042 0408 1020 4200 0030 4832 4c44 3a00 0008 1000 0000 0000 107 | 0004 0808 0808 0400 0010 0808 0808 1000 0000 1408 3e08 1400 0000 0808 3e08 0800 108 | 0000 0000 0008 0810 0000 0000 3c00 0000 0000 0000 0000 0800 0000 0204 0810 2000 109 | 003c 464a 5262 3c00 0018 2808 0808 3e00 003c 4202 3c40 7e00 003c 421c 0242 3c00 110 | 0008 1828 487e 0800 007e 407c 0242 3c00 003c 407c 4242 3c00 007e 0204 0810 1000 111 | 003c 423c 4242 3c00 003c 4242 3e02 3c00 0000 0008 0000 0800 0000 0800 0008 0810 112 | 0000 0810 2010 0800 0000 003e 003e 0000 0000 1008 0408 1000 003c 4202 0c00 0800 113 | 003c 425a 5442 3c00 0018 2442 7e42 4200 007c 427c 4242 7c00 003c 4240 4042 3c00 114 | 0078 4442 4244 7800 007e 407c 4040 7e00 003e 4040 7c40 4000 003c 4240 4e42 3c00 115 | 0042 427e 4242 4200 003e 0808 0808 3e00 0002 0202 4242 3c00 0044 4870 4844 4200 116 | 0040 4040 4040 7e00 0042 665a 4242 4200 0042 6252 4a46 4200 003c 4242 4242 3c00 117 | 007c 4242 7c40 4000 003c 4242 524a 3c00 007c 4242 7c44 4200 003c 403c 0242 3c00 118 | 00fe 1010 1010 1000 0042 4242 4242 3c00 0042 4242 4224 1800 0042 4242 5a66 4200 119 | 0042 2418 1824 4200 0082 4428 1010 1000 007e 0408 1020 7e00 000c 0808 0808 0c00 120 | 0040 2010 0804 0200 0018 0808 0808 1800 0008 1422 0000 0000 0000 0000 0000 7e00 121 | 0008 0400 0000 0000 0000 1c02 1e22 1e00 0020 203c 2222 3c00 0000 1e20 2020 1e00 122 | 0002 021e 2222 1e00 0000 1c22 3c20 1e00 000c 101c 1010 1000 0000 1c22 221e 021c 123 | 0020 202c 3222 2200 0008 0018 0808 0400 0008 0008 0808 4830 0020 2428 3028 2400 124 | 0010 1010 1010 0c00 0000 6854 5454 5400 0000 5864 4444 4400 0000 3844 4444 3800 125 | 0000 7844 4478 4040 0000 3c44 443c 0406 0000 2c30 2020 2000 0000 3840 3804 7800 126 | 0010 103c 1010 0c00 0000 4444 4444 3800 0000 4444 2828 1000 0000 4454 5454 2800 127 | 0000 4428 1028 4400 0000 4444 443c 0438 0000 7c08 1020 7c00 000c 0810 1008 0c00 128 | 0008 0808 0808 0800 0030 1008 0810 3000 0000 0032 4c00 0000 3c42 99a1 a199 423c 129 | ] 130 | 131 | @filename "hello.txt 00 132 | @contents 133 | 134 | -------------------------------------------------------------------------------- /projects/examples/devices/file.save.tal: -------------------------------------------------------------------------------- 1 | ( simple Dev/File writing example ) 2 | 3 | ( devices ) 4 | 5 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 6 | |a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ] 7 | 8 | ( variables ) 9 | 10 | |0000 11 | 12 | ( init ) 13 | 14 | |0100 ( -> ) 15 | ;try-save JSR2 16 | BRK 17 | 18 | @try-save ( -- ) 19 | ( save contents to file ) 20 | ;contents/end ;contents SUB2 .File/length DEO2 21 | ;filename .File/name DEO2 22 | ;contents .File/save DEO2 23 | 24 | .File/success DEI2 ORA ,&success JCN 25 | ( failed to write: bright yellow background ) 26 | #f0f7 .System/r DEO2 27 | #f0f7 .System/g DEO2 28 | #00f7 .System/b DEO2 29 | JMP2r 30 | 31 | &success 32 | ( write successful: dark blue background ) 33 | #00f7 .System/r DEO2 34 | #00f7 .System/g DEO2 35 | #40f7 .System/b DEO2 36 | JMP2r 37 | 38 | @filename "hello.txt 00 39 | @contents "Hello 20 "world, 0a "how 20 "are 20 "you? 0a 40 | &end 41 | 42 | -------------------------------------------------------------------------------- /projects/examples/devices/file.tal: -------------------------------------------------------------------------------- 1 | ( Dev/File ) 2 | 3 | %8+ { #0008 ADD2 } 4 | %MEMORY { #1000 } 5 | 6 | ( devices ) 7 | 8 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 9 | |10 @Console [ &pad $8 &write $1 ] 10 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 11 | |a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ] 12 | 13 | ( variables ) 14 | 15 | |0000 16 | 17 | ( init ) 18 | 19 | |0100 ( -> ) 20 | 21 | ( theme ) 22 | #0efc .System/r DEO2 23 | #03cc .System/g DEO2 24 | #03ac .System/b DEO2 25 | 26 | ( load file ) 27 | #1000 .File/length DEO2 28 | ;srcpath .File/name DEO2 29 | MEMORY .File/load DEO2 30 | 31 | .File/success DEI2 ORA ;on-success JCN2 32 | 33 | ;failedtxt ;print-string JSR2 34 | 35 | BRK 36 | 37 | @on-success ( -> ) 38 | 39 | ;successtxt ;print-string JSR2 40 | 41 | ( draw image ) 42 | MEMORY .Screen/addr DEO2 43 | #0000 #0080 44 | &ver 45 | ( save ) OVR2 .Screen/y DEO2 46 | #0000 #0080 47 | &hor 48 | ( save ) OVR2 .Screen/x DEO2 49 | ( draw ) #81 .Screen/sprite DEO 50 | ( incr ) .Screen/addr DEI2 #0010 ADD2 .Screen/addr DEO2 51 | ( incr ) SWP2 8+ SWP2 52 | LTH2k ,&hor JCN 53 | POP2 POP2 54 | ( incr ) SWP2 8+ SWP2 55 | LTH2k ,&ver JCN 56 | POP2 POP2 57 | 58 | ( save file ) 59 | #1000 .File/length DEO2 60 | ;dstpath .File/name DEO2 61 | MEMORY .File/save DEO2 62 | 63 | BRK 64 | 65 | @print-string ( ptr* -- ) 66 | LDAk DUP ,&keep-going JCN 67 | POP POP2 JMP2r 68 | 69 | &keep-going 70 | .Console/write DEO 71 | INC2 72 | ,print-string JMP 73 | 74 | @successtxt "Success! 09 $1 75 | @failedtxt "Failed. 09 $1 76 | 77 | @srcpath "projects/pictures/ako10x10.chr $1 78 | @dstpath "bin/image-copy.chr $1 79 | -------------------------------------------------------------------------------- /projects/examples/devices/mouse.tal: -------------------------------------------------------------------------------- 1 | ( dev/mouse ) 2 | 3 | %RTN { JMP2r } 4 | %ABS2 { DUP2 #0f SFT2 EQU #05 JCN #0000 SWP2 SUB2 } 5 | %LTS2 { #8000 ADD2 SWP2 #8000 ADD2 GTH2 } 6 | %GTS2 { #8000 ADD2 SWP2 #8000 ADD2 LTH2 } 7 | %2** { #10 SFT2 } 8 | 9 | ( devices ) 10 | 11 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 12 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 13 | |90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ] 14 | 15 | |0000 16 | 17 | @color $1 18 | @line [ &x0 $2 &y0 $2 &x $2 &y $2 &sx $2 &sy $2 &dx $2 &dy $2 &e1 $2 &e2 $2 ] 19 | @pointer [ &x $2 &y $2 &lastx $2 &lasty $2 &state $1 ] 20 | 21 | ( program ) 22 | 23 | |0100 ( -> ) 24 | 25 | ( theme ) 26 | #f030 .System/r DEO2 27 | #f04f .System/g DEO2 28 | #f050 .System/b DEO2 29 | 30 | ( vectors ) 31 | ;on-mouse .Mouse/vector DEO2 32 | 33 | BRK 34 | 35 | @on-mouse ( -> ) 36 | 37 | ;draw-cursor JSR2 38 | 39 | ( on down ) 40 | .Mouse/state DEI #00 NEQ .pointer/state LDZ #00 EQU #0101 EQU2 ,on-mouse-down JCN 41 | 42 | ( on drag ) 43 | .Mouse/state DEI ,on-mouse-drag JCN 44 | .Mouse/state DEI .pointer/state STZ 45 | 46 | BRK 47 | 48 | @on-mouse-down ( -> ) 49 | 50 | ( record start position ) 51 | .Mouse/x DEI2 DUP2 .pointer/x STZ2 .pointer/lastx STZ2 52 | .Mouse/y DEI2 DUP2 .pointer/y STZ2 .pointer/lasty STZ2 53 | .Mouse/state DEI .pointer/state STZ 54 | 55 | BRK 56 | 57 | @on-mouse-drag ( -> ) 58 | 59 | ( draw line ) 60 | .pointer/lastx LDZ2 61 | .pointer/lasty LDZ2 62 | .pointer/x LDZ2 63 | .pointer/y LDZ2 64 | #01 [ .Mouse/state DEI #10 EQU DUP ADD ADD ] 65 | ;draw-line JSR2 66 | 67 | ( record last position ) 68 | .Mouse/x DEI2 .pointer/lastx STZ2 69 | .Mouse/y DEI2 .pointer/lasty STZ2 70 | .Mouse/state DEI .pointer/state STZ 71 | 72 | BRK 73 | 74 | @draw-cursor ( -- ) 75 | 76 | ;pointer_icn .Screen/addr DEO2 77 | ( clear last cursor ) 78 | .pointer/x LDZ2 .Screen/x DEO2 79 | .pointer/y LDZ2 .Screen/y DEO2 80 | #40 .Screen/sprite DEO 81 | 82 | ( record pointer positions ) 83 | .Mouse/x DEI2 .pointer/x STZ2 84 | .Mouse/y DEI2 .pointer/y STZ2 85 | 86 | ( draw new cursor ) 87 | .pointer/x LDZ2 .Screen/x DEO2 88 | .pointer/y LDZ2 .Screen/y DEO2 89 | #43 .Mouse/state DEI #00 NEQ DUP ADD SUB .Screen/sprite DEO 90 | 91 | RTN 92 | 93 | @draw-line ( x1 y1 x2 y2 color -- ) 94 | 95 | ( load ) .color STZ .line/y0 STZ2 .line/x0 STZ2 .line/y STZ2 .line/x STZ2 96 | .line/x0 LDZ2 .line/x LDZ2 SUB2 ABS2 .line/dx STZ2 97 | .line/y0 LDZ2 .line/y LDZ2 SUB2 ABS2 #0000 SWP2 SUB2 .line/dy STZ2 98 | #ffff #00 .line/x LDZ2 .line/x0 LDZ2 LTS2 2** ADD2 .line/sx STZ2 99 | #ffff #00 .line/y LDZ2 .line/y0 LDZ2 LTS2 2** ADD2 .line/sy STZ2 100 | .line/dx LDZ2 .line/dy LDZ2 ADD2 .line/e1 STZ2 101 | &loop 102 | .line/x LDZ2 .Screen/x DEO2 103 | .line/y LDZ2 .Screen/y DEO2 104 | .color LDZ .Screen/pixel DEO 105 | [ .line/x LDZ2 .line/x0 LDZ2 EQU2 ] 106 | [ .line/y LDZ2 .line/y0 LDZ2 EQU2 ] #0101 EQU2 ,&end JCN 107 | .line/e1 LDZ2 2** .line/e2 STZ2 108 | .line/e2 LDZ2 .line/dy LDZ2 LTS2 ,&skipy JCN 109 | .line/e1 LDZ2 .line/dy LDZ2 ADD2 .line/e1 STZ2 110 | .line/x LDZ2 .line/sx LDZ2 ADD2 .line/x STZ2 111 | &skipy 112 | .line/e2 LDZ2 .line/dx LDZ2 GTS2 ,&skipx JCN 113 | .line/e1 LDZ2 .line/dx LDZ2 ADD2 .line/e1 STZ2 114 | .line/y LDZ2 .line/sy LDZ2 ADD2 .line/y STZ2 115 | &skipx 116 | ;&loop JMP2 117 | &end 118 | 119 | RTN 120 | 121 | @pointer_icn [ 80c0 e0f0 f8e0 1000 ] 122 | -------------------------------------------------------------------------------- /projects/examples/devices/screen.tal: -------------------------------------------------------------------------------- 1 | ( dev/screen ) 2 | 3 | %RTN { JMP2r } 4 | %2/ { #01 SFT } 5 | %4/ { #02 SFT } 6 | 7 | ( devices ) 8 | 9 | |00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1 ] 10 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 11 | 12 | ( variables ) 13 | 14 | |0000 15 | 16 | @count $2 17 | @center 18 | &x $2 &y $2 19 | 20 | ( init ) 21 | 22 | |0100 ( -> ) 23 | 24 | ( vector ) 25 | ;on-frame .Screen/vector DEO2 26 | 27 | ( theme ) 28 | #f07f .System/r DEO2 29 | #f0e0 .System/g DEO2 30 | #f0c0 .System/b DEO2 31 | 32 | ( find screen center ) 33 | .Screen/width DEI2 #01 SFT2 #0020 SUB2 .center/x STZ2 34 | .Screen/height DEI2 #01 SFT2 .center/y STZ2 35 | 36 | ( draw ) 37 | ;draw-table JSR2 38 | ;draw-sprites JSR2 39 | ;draw-1bpp JSR2 40 | ;draw-2bpp JSR2 41 | ;draw-pixels JSR2 42 | 43 | BRK 44 | 45 | @on-frame ( -> ) 46 | 47 | .count LDZ2 INC2 [ DUP2 ] .count STZ2 48 | 49 | .center/x LDZ2 #0048 ADD2 .Screen/x DEO2 50 | .center/y LDZ2 #0050 SUB2 .Screen/y DEO2 51 | 52 | ( color ) #01 STH 53 | 54 | SWP 55 | DUP #04 SFT [ #00 SWP ] #30 SFT2 ;font-hex ADD2 .Screen/addr DEO2 56 | ( draw ) STHkr .Screen/sprite DEO 57 | #0f AND [ #00 SWP ] #30 SFT2 ;font-hex ADD2 .Screen/addr DEO2 58 | .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 59 | ( draw ) STHkr .Screen/sprite DEO 60 | DUP #04 SFT [ #00 SWP ] #30 SFT2 ;font-hex ADD2 .Screen/addr DEO2 61 | .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 62 | ( draw ) STHkr .Screen/sprite DEO 63 | #0f AND [ #00 SWP ] #30 SFT2 ;font-hex ADD2 .Screen/addr DEO2 64 | .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 65 | ( draw ) STHr .Screen/sprite DEO 66 | 67 | BRK 68 | 69 | @draw-table ( -- ) 70 | 71 | #10 #00 72 | &loop 73 | DUP #30 SFT #00 SWP ;font-hex ADD2 .Screen/addr DEO2 74 | ( x-axis ) 75 | DUP #30 SFT #00 SWP 76 | .center/x LDZ2 #0040 SUB2 ADD2 .Screen/x DEO2 77 | .center/y LDZ2 #0050 SUB2 .Screen/y DEO2 78 | ( draw ) #01 .Screen/sprite DEO 79 | ( y-axis ) 80 | DUP #30 SFT #00 SWP 81 | .center/y LDZ2 #0040 SUB2 ADD2 .Screen/y DEO2 82 | .center/x LDZ2 #0050 SUB2 .Screen/x DEO2 83 | ( draw ) #01 .Screen/sprite DEO 84 | INC GTHk ,&loop JCN 85 | POP2 86 | 87 | RTN 88 | 89 | @draw-sprites ( -- ) 90 | 91 | ;preview_icn .Screen/addr DEO2 92 | #00 #00 93 | &loop 94 | ( move ) DUP #0f AND #40 SFT 2/ #00 SWP 95 | .center/x LDZ2 #0040 SUB2 ADD2 .Screen/x DEO2 96 | ( move ) DUP #f0 AND 2/ #00 SWP 97 | .center/y LDZ2 #0040 SUB2 ADD2 .Screen/y DEO2 98 | ( draw ) DUP .Screen/sprite DEO 99 | INC NEQk ,&loop JCN 100 | POP2 101 | 102 | RTN 103 | 104 | @draw-1bpp ( -- ) 105 | 106 | #10 #00 107 | &loop 108 | ( color ) STHk 109 | ( y ) DUP 4/ [ #00 SWP ] #40 SFT2 110 | [ .center/y LDZ2 #0040 SUB2 ADD2 ] STH2 111 | ( x ) DUP #03 AND [ #00 SWP ] #40 SFT2 #0040 ADD2 112 | [ .center/x LDZ2 #0008 ADD2 ADD2 ] 113 | STH2r STHr #00 ;draw-circle JSR2 114 | INC GTHk ,&loop JCN 115 | POP2 116 | 117 | RTN 118 | 119 | @draw-2bpp ( -- ) 120 | 121 | #10 #00 122 | &loop 123 | ( color ) STHk 124 | ( y ) DUP 4/ [ #00 SWP ] #40 SFT2 125 | [ .center/y LDZ2 ADD2 ] STH2 126 | ( x ) DUP #03 AND [ #00 SWP ] #40 SFT2 #0040 ADD2 127 | [ .center/x LDZ2 #0008 ADD2 ADD2 ] 128 | STH2r STHr #80 ;draw-circle JSR2 129 | INC GTHk ,&loop JCN 130 | POP2 131 | 132 | RTN 133 | 134 | @draw-circle ( x* y* color depth -- ) 135 | 136 | ADD STH 137 | ;preview_icn .Screen/addr DEO2 138 | .Screen/y DEO2 139 | .Screen/x DEO2 140 | 141 | #00 STHkr ADD .Screen/sprite DEO 142 | .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 143 | #10 STHkr ADD .Screen/sprite DEO 144 | .Screen/x DEI2 #0008 SUB2 .Screen/x DEO2 145 | .Screen/y DEI2 #0008 ADD2 .Screen/y DEO2 146 | #20 STHkr ADD .Screen/sprite DEO 147 | .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 148 | #30 STHr ADD .Screen/sprite DEO 149 | 150 | RTN 151 | 152 | @draw-pixels ( -- ) 153 | 154 | .center/y LDZ2 #0040 SUB2 .Screen/y DEO2 155 | .center/x LDZ2 #0048 ADD2 .Screen/x DEO2 156 | #00 .Screen/pixel DEO 157 | .center/x LDZ2 #0049 ADD2 .Screen/x DEO2 158 | #01 .Screen/pixel DEO 159 | .center/x LDZ2 #004a ADD2 .Screen/x DEO2 160 | #02 .Screen/pixel DEO 161 | .center/x LDZ2 #004b ADD2 .Screen/x DEO2 162 | #03 .Screen/pixel DEO 163 | 164 | RTN 165 | 166 | @preview_icn [ 167 | 0f38 675f dfbf bfbf 0007 1820 2344 4848 168 | 169 | @font-hex 170 | 007c 8282 8282 827c 0030 1010 1010 1010 171 | 007c 8202 7c80 80fe 007c 8202 1c02 827c 172 | 000c 1424 4484 fe04 00fe 8080 7c02 827c 173 | 007c 8280 fc82 827c 007c 8202 1e02 0202 174 | 007c 8282 7c82 827c 007c 8282 7e02 827c 175 | 007c 8202 7e82 827e 00fc 8282 fc82 82fc 176 | 007c 8280 8080 827c 00fc 8282 8282 82fc 177 | 007c 8280 f080 827c 007c 8280 f080 8080 178 | -------------------------------------------------------------------------------- /projects/examples/gui/animation.tal: -------------------------------------------------------------------------------- 1 | ( GUI Animation ) 2 | 3 | %2// { #01 SFT2 } 4 | 5 | ( devices ) 6 | 7 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 8 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 9 | 10 | |0000 11 | 12 | @dvd [ &x $2 &y $2 &dx $1 &dy $1 ] 13 | 14 | ( program ) 15 | 16 | |0100 ( -> ) 17 | 18 | ( theme ) 19 | #4cfd .System/r DEO2 20 | #4cf3 .System/g DEO2 21 | #dcf2 .System/b DEO2 22 | 23 | ( vectors ) 24 | ;on-frame .Screen/vector DEO2 25 | 26 | ( starting position ) 27 | .Screen/width DEI2 2// .dvd/x STZ2 28 | .Screen/height DEI2 2// .dvd/y STZ2 29 | 30 | #01 ;draw-dvd JSR2 31 | 32 | BRK 33 | 34 | @on-frame ( -> ) 35 | 36 | ( clear ) #00 ;draw-dvd JSR2 37 | ( case: hit-right ) .dvd/x LDZ2 .Screen/width DEI2 #0020 SUB2 EQU2 38 | ( case: hit-left ) .dvd/x LDZ2 #0000 EQU2 39 | #0000 EQU2 ,&no-flipx JCN 40 | .dvd/dx LDZ #00 EQU .dvd/dx STZ &no-flipx 41 | ( case: hit-bottom ) .dvd/y LDZ2 .Screen/height DEI2 #0010 SUB2 EQU2 42 | ( case: hit-top ) .dvd/y LDZ2 #0000 EQU2 43 | #0000 EQU2 ,&no-flipy JCN 44 | .dvd/dy LDZ #00 EQU .dvd/dy STZ &no-flipy 45 | ( incr ) .dvd/x LDZ2 #0001 #00 .dvd/dx LDZ #00 EQU DUP2 ADD2 SUB2 ADD2 .dvd/x STZ2 46 | ( incr ) .dvd/y LDZ2 #0001 #00 .dvd/dy LDZ #00 EQU DUP2 ADD2 SUB2 ADD2 .dvd/y STZ2 47 | ( draw ) #01 ;draw-dvd JSR2 48 | 49 | BRK 50 | 51 | @draw-dvd ( color -- ) 52 | 53 | ( stash ) STH 54 | ;dvd_icn .Screen/addr DEO2 55 | [ .dvd/y LDZ2 #0010 ADD2 ] .dvd/y LDZ2 56 | &ver 57 | DUP2 .Screen/y DEO2 58 | [ .dvd/x LDZ2 #0020 ADD2 ] .dvd/x LDZ2 59 | &hor 60 | DUP2 .Screen/x DEO2 61 | ( draw ) STHkr .Screen/sprite DEO 62 | ( next ) .Screen/addr DEI2 #0008 ADD2 .Screen/addr DEO2 63 | ( incr ) #0008 ADD2 64 | GTH2k ,&hor JCN 65 | POP2 POP2 66 | ( incr ) #0008 ADD2 67 | GTH2k ,&ver JCN 68 | POP2 POP2 69 | ( destroy ) POPr 70 | 71 | JMP2r 72 | 73 | @dvd_icn [ 74 | 001f 3f38 3838 787f 00fe fe7e 7777 e3c3 75 | 000f 1f3b 7b77 e7c7 00fc fe8f 8707 0efc 76 | 7f00 000f ff7f 0700 0301 00ff f0f8 ff00 77 | 8700 00ff 7f7f ff00 f000 00e0 fcfc 8000 78 | ] -------------------------------------------------------------------------------- /projects/examples/gui/hover.tal: -------------------------------------------------------------------------------- 1 | ( GUI Hover ) 2 | 3 | %RTN { JMP2r } 4 | %GTS2 { #8000 ADD2 SWP2 #8000 ADD2 LTH2 } 5 | 6 | ( devices ) 7 | 8 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 9 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 10 | |90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ] 11 | 12 | ( variables ) 13 | 14 | |0000 15 | 16 | @color $1 17 | @pointer [ &x $2 &y $2 &sprite $2 ] 18 | @rect [ &x1 $2 &y1 $2 &x2 $2 &y2 $2 ] 19 | @r1 [ &x1 $2 &y1 $2 &x2 $2 &y2 $2 ] 20 | @r2 [ &x1 $2 &y1 $2 &x2 $2 &y2 $2 ] 21 | @r3 [ &x1 $2 &y1 $2 &x2 $2 &y2 $2 ] 22 | 23 | ( program ) 24 | 25 | |0100 26 | 27 | ( theme ) 28 | #0f0f .System/r DEO2 29 | #0fff .System/g DEO2 30 | #0ff0 .System/b DEO2 31 | 32 | ( vectors ) ;on-mouse .Mouse/vector DEO2 33 | 34 | #0020 #0030 #0060 #0060 .r1/y2 STZ2 .r1/x2 STZ2 .r1/y1 STZ2 .r1/x1 STZ2 35 | #0058 #0050 #0090 #0080 .r2/y2 STZ2 .r2/x2 STZ2 .r2/y1 STZ2 .r2/x1 STZ2 36 | #0048 #0048 #0080 #0098 .r3/y2 STZ2 .r3/x2 STZ2 .r3/y1 STZ2 .r3/x1 STZ2 37 | 38 | ( no BRK, run through to on-mouse ) 39 | 40 | @on-mouse 41 | 42 | ;pointer_icn .pointer/sprite STZ2 43 | 44 | #01 .color STZ 45 | .Mouse/x DEI2 .Mouse/y DEI2 .r1 ;within-rect JSR2 #00 EQU ,&draw1 JCN 46 | #02 .color STZ 47 | ;hand_icn .pointer/sprite STZ2 48 | &draw1 49 | .r1/x1 LDZ2 .r1/y1 LDZ2 .r1/x2 LDZ2 .r1/y2 LDZ2 .color LDZ ;line-rect JSR2 50 | 51 | #01 .color STZ 52 | .Mouse/x DEI2 .Mouse/y DEI2 .r2 ;within-rect JSR2 #00 EQU ,&draw2 JCN 53 | #03 .color STZ 54 | ;hand_icn .pointer/sprite STZ2 55 | &draw2 56 | .r2/x1 LDZ2 .r2/y1 LDZ2 .r2/x2 LDZ2 .r2/y2 LDZ2 .color LDZ ;line-rect JSR2 57 | 58 | #01 .color STZ 59 | .Mouse/x DEI2 .Mouse/y DEI2 .r3 ;within-rect JSR2 #00 EQU ,&draw3 JCN 60 | #02 .color STZ 61 | ;hand_icn .pointer/sprite STZ2 62 | &draw3 63 | .r3/x1 LDZ2 .r3/y1 LDZ2 .r3/x2 LDZ2 .r3/y2 LDZ2 .color LDZ ;line-rect JSR2 64 | 65 | ( clear last cursor ) 66 | .pointer/x LDZ2 .Screen/x DEO2 67 | .pointer/y LDZ2 .Screen/y DEO2 68 | #40 .Screen/sprite DEO 69 | 70 | ( record pointer positions ) 71 | .Mouse/x DEI2 DUP2 .pointer/x STZ2 .Screen/x DEO2 72 | .Mouse/y DEI2 DUP2 .pointer/y STZ2 .Screen/y DEO2 73 | .pointer/sprite LDZ2 .Screen/addr DEO2 74 | 75 | ( draw new cursor ) 76 | #41 .Screen/sprite DEO 77 | 78 | BRK 79 | 80 | @within-rect ( x* y* rect -- flag ) 81 | 82 | STH 83 | ( y < rect.y1 ) DUP2 STHkr #02 ADD LDZ2 LTH2 ,&skip JCN 84 | ( y > rect.y2 ) DUP2 STHkr #06 ADD LDZ2 GTH2 ,&skip JCN 85 | SWP2 86 | ( x < rect.x1 ) DUP2 STHkr LDZ2 LTH2 ,&skip JCN 87 | ( x > rect.x2 ) DUP2 STHkr #04 ADD LDZ2 GTH2 ,&skip JCN 88 | POP2 POP2 POPr 89 | #01 90 | RTN 91 | &skip 92 | POP2 POP2 POPr 93 | #00 94 | 95 | RTN 96 | 97 | @line-rect ( x1* y1* x2* y2* color -- ) 98 | 99 | ( load ) .color STZ 100 | STH2k .rect/y2 STZ2 .rect/x2 STZ2 101 | STH2k .rect/y1 STZ2 .rect/x1 STZ2 102 | STH2r STH2r SWP2 103 | &ver 104 | ( save ) DUP2 .Screen/y DEO2 105 | ( draw ) .rect/x1 LDZ2 .Screen/x DEO2 .color LDZ DUP .Screen/pixel DEO 106 | ( draw ) .rect/x2 LDZ2 .Screen/x DEO2 .Screen/pixel DEO 107 | ( incr ) INC2 108 | OVR2 OVR2 GTS2 ,&ver JCN 109 | POP2 POP2 110 | .rect/x1 LDZ2 .rect/x2 LDZ2 SWP2 111 | &hor 112 | ( save ) DUP2 .Screen/x DEO2 113 | ( draw ) .rect/y1 LDZ2 .Screen/y DEO2 .color LDZ DUP .Screen/pixel DEO 114 | ( draw ) .rect/y2 LDZ2 .Screen/y DEO2 .Screen/pixel DEO 115 | ( incr ) INC2 116 | OVR2 OVR2 GTS2 ,&hor JCN 117 | POP2 POP2 118 | 119 | RTN 120 | 121 | @pointer_icn [ 80c0 e0f0 f8e0 1000 ] 122 | @hand_icn [ 4040 4070 f8f8 f870 ] 123 | -------------------------------------------------------------------------------- /projects/examples/gui/label.tal: -------------------------------------------------------------------------------- 1 | ( GUI Labels ) 2 | 3 | %RTN { JMP2r } 4 | %2// { #01 SFT2 } 5 | %8** { #30 SFT2 } 6 | 7 | ( devices ) 8 | 9 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 10 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 11 | 12 | ( variables ) 13 | 14 | |0000 15 | 16 | @label [ &x $2 &y $2 &color $1 &addr $2 ] 17 | @center [ &x $2 &y $2 ] 18 | 19 | ( program ) 20 | 21 | |0100 22 | 23 | ( theme ) 24 | #0f0f .System/r DEO2 25 | #0fff .System/g DEO2 26 | #0ff0 .System/b DEO2 27 | 28 | ( find screen center ) 29 | .Screen/width DEI2 2// .center/x STZ2 30 | .Screen/height DEI2 2// .center/y STZ2 31 | 32 | ( draw ver line ) 33 | .center/x LDZ2 .Screen/x DEO2 #0000 .Screen/y DEO2 34 | &draw-ver 35 | ( draw ) #02 .Screen/pixel DEO 36 | ( incr ) .Screen/y DEI2 #0002 ADD2 .Screen/y DEO2 37 | .Screen/y DEI2 .Screen/height DEI2 LTH2 ,&draw-ver JCN 38 | 39 | .center/x LDZ2 .center/y LDZ2 #0010 SUB2 #0c ;text1 ;draw-label-left JSR2 40 | .center/x LDZ2 .center/y LDZ2 #0c ;text2 ;draw-label-middle JSR2 41 | .center/x LDZ2 .center/y LDZ2 #0010 ADD2 #0c ;text3 ;draw-label-right JSR2 42 | .center/x LDZ2 .center/y LDZ2 #0020 ADD2 #0c ;text4 ;draw-label-middle JSR2 43 | .center/x LDZ2 .center/y LDZ2 #0030 ADD2 #0c ;text5 ;draw-label-middle JSR2 44 | 45 | RTN 46 | 47 | @draw-label-left ( x y color addr -- ) 48 | 49 | ( load ) .label/addr STZ2 .label/color STZ .Screen/y DEO2 .Screen/x DEO2 50 | .label/addr LDZ2 51 | &loop 52 | ( draw ) LDAk #00 SWP 8** ;font ADD2 .Screen/addr DEO2 .label/color LDZ .Screen/sprite DEO 53 | ( incr ) INC2 54 | ( incr ) .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 55 | LDAk ,&loop JCN 56 | POP2 57 | 58 | RTN 59 | 60 | @draw-label-middle ( x y color addr -- ) 61 | 62 | ( load ) .label/addr STZ2 .label/color STZ .Screen/y DEO2 63 | ( align ) .label/addr LDZ2 ;get-text-length JSR2 8** 2// SUB2 .Screen/x DEO2 64 | .label/addr LDZ2 65 | &loop 66 | ( draw ) LDAk #00 SWP 8** ;font ADD2 .Screen/addr DEO2 .label/color LDZ .Screen/sprite DEO 67 | ( incr ) INC2 68 | ( incr ) .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 69 | LDAk ,&loop JCN 70 | POP2 71 | 72 | RTN 73 | 74 | @draw-label-right ( x y color addr -- ) 75 | 76 | ( load ) .label/addr STZ2 .label/color STZ .Screen/y DEO2 77 | ( align ) .label/addr LDZ2 ;get-text-length JSR2 8** SUB2 .Screen/x DEO2 78 | .label/addr LDZ2 79 | &loop 80 | ( draw ) LDAk #00 SWP 8** ;font ADD2 .Screen/addr DEO2 .label/color LDZ .Screen/sprite DEO 81 | ( incr ) INC2 82 | ( incr ) .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 83 | LDAk ,&loop JCN 84 | POP2 85 | 86 | RTN 87 | 88 | @get-text-length ( label* -- length ) 89 | 90 | #0000 ( counter ) 91 | &loop 92 | ( incr ) INC2 OVR2 OVR2 ADD2 93 | LDA ,&loop JCN 94 | NIP2 95 | 96 | RTN 97 | 98 | @font ( spectrum-zx font ) 99 | [ 100 | 0000 0000 0000 0000 0000 2400 7e3c 0000 0000 2400 3c42 0000 0000 6c7c 7c38 1000 101 | 0010 387c 7c38 1000 0038 387c 6c10 3800 0010 387c 7c10 3800 0000 0018 1800 0000 102 | 007e 4242 4242 7e00 0000 1824 2418 0000 0018 2442 4224 1800 001e 063a 4a48 3000 103 | 0038 446c 107c 1000 000c 0808 0838 3800 003e 2222 2266 6600 0000 0822 0022 0800 104 | 0000 1018 1c18 1000 0000 0818 3818 0800 0008 1c00 001c 0800 0028 2828 2800 2800 105 | 003e 4a4a 3a0a 0a00 000c 3046 620c 3000 0000 0000 0000 ffff 0010 3800 3810 0038 106 | 0008 1c2a 0808 0800 0008 0808 2a1c 0800 0000 0804 7e04 0800 0000 1020 7e20 1000 107 | 0000 4040 7e00 0000 0000 0024 6624 0000 0000 1038 7c00 0000 0000 007c 3810 0000 108 | 0000 0000 0000 0000 0008 0808 0800 0800 0014 1400 0000 0000 0024 7e24 247e 2400 109 | 0008 1e28 1c0a 3c08 0042 0408 1020 4200 0030 4832 4c44 3a00 0008 1000 0000 0000 110 | 0004 0808 0808 0400 0010 0808 0808 1000 0000 1408 3e08 1400 0000 0808 3e08 0800 111 | 0000 0000 0008 0810 0000 0000 3c00 0000 0000 0000 0000 0800 0000 0204 0810 2000 112 | 003c 464a 5262 3c00 0018 2808 0808 3e00 003c 4202 3c40 7e00 003c 421c 0242 3c00 113 | 0008 1828 487e 0800 007e 407c 0242 3c00 003c 407c 4242 3c00 007e 0204 0810 1000 114 | 003c 423c 4242 3c00 003c 4242 3e02 3c00 0000 0008 0000 0800 0000 0800 0008 0810 115 | 0000 0810 2010 0800 0000 003e 003e 0000 0000 1008 0408 1000 003c 4202 0c00 0800 116 | 003c 425a 5442 3c00 0018 2442 7e42 4200 007c 427c 4242 7c00 003c 4240 4042 3c00 117 | 0078 4442 4244 7800 007e 407c 4040 7e00 003e 4040 7c40 4000 003c 4240 4e42 3c00 118 | 0042 427e 4242 4200 003e 0808 0808 3e00 0002 0202 4242 3c00 0044 4870 4844 4200 119 | 0040 4040 4040 7e00 0042 665a 4242 4200 0042 6252 4a46 4200 003c 4242 4242 3c00 120 | 007c 4242 7c40 4000 003c 4242 524a 3c00 007c 4242 7c44 4200 003c 403c 0242 3c00 121 | 00fe 1010 1010 1000 0042 4242 4242 3c00 0042 4242 4224 1800 0042 4242 5a66 4200 122 | 0042 2418 1824 4200 0082 4428 1010 1000 007e 0408 1020 7e00 000c 0808 0808 0c00 123 | 0040 2010 0804 0200 0018 0808 0808 1800 0008 1422 0000 0000 0000 0000 0000 7e00 124 | 0008 0400 0000 0000 0000 1c02 1e22 1e00 0020 203c 2222 3c00 0000 1e20 2020 1e00 125 | 0002 021e 2222 1e00 0000 1c22 3c20 1e00 000c 101c 1010 1000 0000 1c22 221e 021c 126 | 0020 202c 3222 2200 0008 0018 0808 0400 0008 0008 0808 4830 0020 2428 3028 2400 127 | 0010 1010 1010 0c00 0000 6854 5454 5400 0000 5864 4444 4400 0000 3844 4444 3800 128 | 0000 7844 4478 4040 0000 3c44 443c 0406 0000 2c30 2020 2000 0000 3840 3804 7800 129 | 0010 103c 1010 0c00 0000 4444 4444 3800 0000 4444 2828 1000 0000 4454 5454 2800 130 | 0000 4428 1028 4400 0000 4444 443c 0438 0000 7c08 1020 7c00 000c 0810 1008 0c00 131 | 0008 0808 0808 0800 0030 1008 0810 3000 0000 0032 4c00 0000 3c42 99a1 a199 423c 132 | ] 133 | 134 | @text1 [ "Left 20 "Aligned 00 ] 135 | @text2 [ "Middle 20 "Aligned 00 ] 136 | @text3 [ "Right 20 "Aligned 00 ] 137 | @text4 [ "even 00 ] 138 | @text5 [ "odd 00 ] -------------------------------------------------------------------------------- /projects/examples/gui/picture.tal: -------------------------------------------------------------------------------- 1 | ( GUI Picture ) 2 | 3 | %RTN { JMP2r } 4 | %LOAD-IMAGE { .File/length DEO2 .File/name DEO2 ;image .File/load DEO2 } 5 | 6 | ( devices ) 7 | 8 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 9 | |20 @Screen [ &vector $2 &width $2 &height $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 10 | |a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ] 11 | 12 | ( variables ) 13 | 14 | |0000 15 | 16 | @position 17 | &x $2 &y $2 18 | @size 19 | &width $2 &height $2 20 | 21 | ( program ) 22 | 23 | |0100 24 | 25 | ( theme ) 26 | #072f .System/r DEO2 27 | #072f .System/g DEO2 28 | #072f .System/b DEO2 29 | 30 | ( background ) ;checker-icn #02 ;cover-pattern JSR2 31 | 32 | ( load ) ;icn1-path #1800 LOAD-IMAGE 33 | ( draw ) #0008 #0008 #0100 #00c0 ;image #01 ;draw-icn JSR2 34 | ( load ) ;icn2-path #0800 LOAD-IMAGE 35 | ( draw ) #0010 #00a8 #0080 #0080 ;image #03 ;draw-icn JSR2 36 | ( load ) ;chr1-path #4000 LOAD-IMAGE 37 | ( draw ) #00e8 #0080 #0100 #0080 ;image #81 ;draw-chr JSR2 38 | ( load ) ;chr2-path #0900 LOAD-IMAGE 39 | ( draw ) #0068 #0098 #0060 #0060 ;image #85 ;draw-chr JSR2 40 | 41 | 42 | ( auto-x ) 43 | #01 .Screen/auto DEO 44 | #0070 .Screen/x DEO2 45 | #0070 .Screen/y DEO2 46 | ;checker-icn .Screen/addr DEO2 47 | #03 .Screen/sprite DEO 48 | #03 .Screen/sprite DEO 49 | #03 .Screen/sprite DEO 50 | #03 .Screen/sprite DEO 51 | #03 .Screen/sprite DEO 52 | #00 .Screen/auto DEO 53 | 54 | BRK 55 | 56 | @draw-icn ( x* y* width* height* addr* color -- ) 57 | 58 | ( load ) STH .Screen/addr DEO2 .size/height STZ2 .size/width STZ2 .position/y STZ2 .position/x STZ2 59 | .size/height LDZ2 #0000 60 | &ver 61 | ( save ) DUP2 .position/y LDZ2 ADD2 .Screen/y DEO2 62 | .size/width LDZ2 #0000 63 | &hor 64 | ( save ) DUP2 .position/x LDZ2 ADD2 .Screen/x DEO2 65 | ( draw ) STHkr .Screen/sprite DEO 66 | ( incr ) .Screen/addr DEI2 #0008 ADD2 .Screen/addr DEO2 67 | #0008 ADD2 GTH2k ,&hor JCN 68 | POP2 POP2 69 | #0008 ADD2 GTH2k ,&ver JCN 70 | POP2 POP2 71 | POPr 72 | 73 | RTN 74 | 75 | @draw-chr ( x* y* width* height* addr* color -- ) 76 | 77 | ( load ) STH .Screen/addr DEO2 .size/height STZ2 .size/width STZ2 .position/y STZ2 .position/x STZ2 78 | .size/height LDZ2 #0000 79 | &ver 80 | ( save ) DUP2 .position/y LDZ2 ADD2 .Screen/y DEO2 81 | .size/width LDZ2 #0000 82 | &hor 83 | ( save ) DUP2 .position/x LDZ2 ADD2 .Screen/x DEO2 84 | ( draw ) STHkr .Screen/sprite DEO 85 | ( incr ) .Screen/addr DEI2 #0010 ADD2 .Screen/addr DEO2 86 | #0008 ADD2 GTH2k ,&hor JCN 87 | POP2 POP2 88 | #0008 ADD2 GTH2k ,&ver JCN 89 | POP2 POP2 90 | POPr 91 | 92 | RTN 93 | 94 | @cover-pattern ( addr* color -- ) 95 | 96 | ( load ) STH .Screen/addr DEO2 97 | .Screen/height DEI2 #0000 98 | &ver 99 | ( save ) DUP2 .Screen/y DEO2 100 | .Screen/width DEI2 #0000 101 | &hor 102 | ( save ) DUP2 .Screen/x DEO2 103 | ( draw ) STHkr .Screen/sprite DEO 104 | #0008 ADD2 GTH2k ,&hor JCN 105 | POP2 POP2 106 | #0008 ADD2 GTH2k ,&ver JCN 107 | POP2 POP2 108 | POPr 109 | 110 | RTN 111 | 112 | @checker-icn f0f0 f0f0 0f0f 0f0f 113 | @icn1-path "projects/pictures/ergo100x0c0.bit 00 114 | @icn2-path "projects/pictures/dafu80x80.bit 00 115 | @chr1-path "projects/pictures/pc98.chr 00 116 | @chr2-path "projects/pictures/felix0cx0c.chr 00 117 | 118 | @image [ ] -------------------------------------------------------------------------------- /projects/examples/gui/proportional-font.tal: -------------------------------------------------------------------------------- 1 | ( GUI Proportional font ) 2 | 3 | ( devices ) 4 | 5 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 6 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 7 | 8 | ( variables ) 9 | 10 | |0000 11 | 12 | ( program ) 13 | 14 | |0100 15 | 16 | ( theme ) #0f9f .System/r DEO2 #0f3f .System/g DEO2 #0f30 .System/b DEO2 17 | 18 | #0000 ;draw JSR2 19 | #0001 ;draw JSR2 20 | #0002 ;draw JSR2 21 | 22 | BRK 23 | 24 | @draw ( extra-spacing* -- ) 25 | STH2 26 | ;text 27 | &loop 28 | LDAk 29 | DUP #00 EQU ,&end JCN 30 | DUP #0a EQU ,&linefeed JCN 31 | #0005 SFT2 ;font ADD2 32 | DUP2 .Screen/addr DEO2 33 | #09 .Screen/sprite DEO 34 | ,get-x-advance JSR .Screen/x DEI2 ADD2 STH2kr ADD2 .Screen/x DEO2 35 | &next 36 | INC2 37 | ,&loop JMP 38 | 39 | &linefeed 40 | POP 41 | #0000 .Screen/x DEO2 42 | #0008 .Screen/y DEI2 ADD2 STH2kr ADD2 .Screen/y DEO2 43 | ,&next JMP 44 | 45 | &end 46 | POP POP2 POP2r 47 | JMP2r 48 | 49 | @get-x-advance ( font-char-addr* -- advance* ) 50 | ( Save two 00 bytes for later use ) 51 | #0000 SWP2 52 | ( First, load the eight bytes that make up the character ) 53 | LDA2k SWP2 #0002 ADD2 54 | LDA2k SWP2 #0002 ADD2 55 | LDA2k SWP2 #0002 ADD2 56 | LDA2 57 | ( OR all the bytes together, so we know which columns contain filled pixels ) 58 | ORA2 ORA2 ORA2 ORA 59 | ( Find the lowest set bit (using one of the 00 bytes at the top, but not consuming it) ) 60 | SUBk AND 61 | ( Convert the nine possible values (00-80) into an offset into the magic table (00-08). ) 62 | ( They get jumbled up with these two operations, but each possible value remains unique ) 63 | #a3 MUL #16 DIV 64 | ( Load the byte from the magic table, return a short (consuming/returning the 00 bytes at the top) ) 65 | ;&magic ADD2 LDA 66 | JMP2r 67 | ( The magic table performs the last bit of arithmetic we want: 68 | * the advance in x should be one more than the number of columns with filled pixels, 69 | * with a maximum of 8, and 70 | * a minimum of 3. ) 71 | &magic 72 | 03 ( lowest set bit is 00, 0 columns wide ) 73 | 06 ( lowest set bit is 08, 5 columns wide ) 74 | 05 ( lowest set bit is 10, 4 columns wide ) 75 | 08 ( lowest set bit is 02, 7 columns wide ) 76 | 04 ( lowest set bit is 20, 3 columns wide ) 77 | 03 ( lowest set bit is 80, 1 column wide ) 78 | 07 ( lowest set bit is 04, 6 columns wide ) 79 | 08 ( lowest set bit is 01, 8 columns wide ) 80 | 03 ( lowest set bit is 40, 2 columns wide ) 81 | 82 | @font ( spectrum-zx font, with each character moved to be flush left in its cell ) 83 | [ 84 | 0000 0000 0000 0000 0000 4800 fc78 0000 0000 4800 7884 0000 0000 d8f8 f870 2000 85 | 0020 70f8 f870 2000 0070 70f8 d820 7000 0020 70f8 f820 7000 0000 00c0 c000 0000 86 | 00fc 8484 8484 fc00 0000 6090 9060 0000 0030 4884 8448 3000 003c 0c74 9490 6000 87 | 0070 88d8 20f8 2000 0030 2020 20e0 e000 007c 4444 44cc cc00 0000 2088 0088 2000 88 | 0000 80c0 e0c0 8000 0000 2060 e060 2000 0040 e000 00e0 4000 00a0 a0a0 a000 a000 89 | 007c 9494 7414 1400 0018 608c c418 6000 0000 0000 0000 ffff 0040 e000 e040 00e0 90 | 0020 70a8 2020 2000 0020 2020 a870 2000 0000 1008 fc08 1000 0000 2040 fc40 2000 91 | 0000 8080 fc00 0000 0000 0048 cc48 0000 0000 2070 f800 0000 0000 00f8 7020 0000 92 | 0000 0000 0000 0000 0080 8080 8000 8000 00a0 a000 0000 0000 0048 fc48 48fc 4800 93 | 0020 78a0 7028 f020 0084 0810 2040 8400 0060 9064 9888 7400 0040 8000 0000 0000 94 | 0040 8080 8080 4000 0080 4040 4040 8000 0000 5020 f820 5000 0000 2020 f820 2000 95 | 0000 0000 0040 4080 0000 0000 f000 0000 0000 0000 0000 8000 0000 0810 2040 8000 96 | 0078 8c94 a4c4 7800 0060 a020 2020 f800 0078 8404 7880 fc00 0078 8438 0484 7800 97 | 0010 3050 90fc 1000 00fc 80f8 0484 7800 0078 80f8 8484 7800 00fc 0408 1020 2000 98 | 0078 8478 8484 7800 0078 8484 7c04 7800 0000 0080 0000 8000 0000 4000 0040 4080 99 | 0000 2040 8040 2000 0000 00f8 00f8 0000 0000 8040 2040 8000 0078 8404 1800 1000 100 | 0078 84b4 a884 7800 0030 4884 fc84 8400 00f8 84f8 8484 f800 0078 8480 8084 7800 101 | 00f0 8884 8488 f000 00fc 80f8 8080 fc00 007c 8080 f880 8000 0078 8480 9c84 7800 102 | 0084 84fc 8484 8400 00f8 2020 2020 f800 0004 0404 8484 7800 0088 90e0 9088 8400 103 | 0080 8080 8080 fc00 0084 ccb4 8484 8400 0084 c4a4 948c 8400 0078 8484 8484 7800 104 | 00f8 8484 f880 8000 0078 8484 a494 7800 00f8 8484 f888 8400 0078 8078 0484 7800 105 | 00fe 1010 1010 1000 0084 8484 8484 7800 0084 8484 8448 3000 0084 8484 b4cc 8400 106 | 0084 4830 3048 8400 0082 4428 1010 1000 00fc 0810 2040 fc00 00c0 8080 8080 c000 107 | 0080 4020 1008 0400 00c0 4040 4040 c000 0020 5088 0000 0000 0000 0000 0000 fc00 108 | 0080 4000 0000 0000 0000 7008 7888 7800 0080 80f0 8888 f000 0000 7880 8080 7800 109 | 0008 0878 8888 7800 0000 7088 f080 7800 0060 80e0 8080 8000 0000 7088 8878 0870 110 | 0080 80b0 c888 8800 0040 00c0 4040 2000 0010 0010 1010 9060 0080 90a0 c0a0 9000 111 | 0080 8080 8080 6000 0000 d0a8 a8a8 a800 0000 b0c8 8888 8800 0000 7088 8888 7000 112 | 0000 f088 88f0 8080 0000 7888 8878 080c 0000 b0c0 8080 8000 0000 7080 7008 f000 113 | 0040 40f0 4040 3000 0000 8888 8888 7000 0000 8888 5050 2000 0000 88a8 a8a8 5000 114 | 0000 8850 2050 8800 0000 8888 8878 0870 0000 f810 2040 f800 0060 4080 8040 6000 115 | 0080 8080 8080 8000 00c0 4020 2040 c000 0000 0064 9800 0000 3c42 99a1 a199 423c 116 | ] 117 | 118 | @text "Are 20 "proportional 20 "fonts 20 "a 20 "good 20 "idea? 0a 0a 119 | "The 20 "jury 20 "is 20 "still 20 "out, 20 "but 20 "one 20 "thing 20 "is 20 "certain: 0a 120 | "it 20 "is 20 "possible 20 "to 20 "print 20 "with 20 "these 20 "fonts 20 "in 20 "Uxn. 0a 0a 0a 00 121 | 122 | -------------------------------------------------------------------------------- /projects/examples/gui/shapes.tal: -------------------------------------------------------------------------------- 1 | ( GUI Shapes ) 2 | 3 | %RTN { JMP2r } 4 | %8++ { #0008 ADD2 } 5 | %2** { #10 SFT2 } 6 | %4** { #20 SFT2 } 7 | %2// { #01 SFT2 } 8 | %4// { #02 SFT2 } 9 | %ABS2 { DUP2 #0f SFT2 EQU #05 JCN #0000 SWP2 SUB2 } 10 | %LTS2 { #8000 ADD2 SWP2 #8000 ADD2 GTH2 } 11 | %GTS2 { #8000 ADD2 SWP2 #8000 ADD2 LTH2 } 12 | 13 | %SIZE-TO-RECT { 14 | STH2 STH2 OVR2 STH2r ADD2 OVR2 STH2r ADD2 15 | } ( x y w h -- x1 y1 x2 y2 ) 16 | 17 | %WIDTH { #0100 } %HEIGHT { #00a0 } 18 | 19 | ( devices ) 20 | 21 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 22 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 23 | 24 | ( variables ) 25 | 26 | |0000 27 | 28 | ( draw requirements ) 29 | @color [ &byte $1 ] 30 | 31 | @rect [ &x1 $2 &y1 $2 &x2 $2 &y2 $2 ] 32 | @line [ &x0 $2 &y0 $2 &x $2 &y $2 &sx $2 &sy $2 &dx $2 &dy $2 &e1 $2 &e2 $2 ] 33 | @circle [ &xc $2 &yc $2 &x $2 &y $2 &r $2 &d $2 ] 34 | 35 | ( program ) 36 | 37 | |0100 38 | 39 | ( theme ) 40 | #f0ff .System/r DEO2 41 | #f03c .System/g DEO2 42 | #f03f .System/b DEO2 43 | 44 | ( background ) ;checker_icn #03 ;cover-pattern JSR2 45 | 46 | .Screen/width DEI2 2// WIDTH 2// SUB2 #0008 ADD2 47 | .Screen/height DEI2 2// HEIGHT 2// SUB2 #0008 ADD2 48 | WIDTH HEIGHT 49 | SIZE-TO-RECT #02 ;fill-rect JSR2 50 | 51 | .Screen/width DEI2 2// WIDTH 2// SUB2 52 | .Screen/height DEI2 2// HEIGHT 2// SUB2 53 | WIDTH HEIGHT 54 | SIZE-TO-RECT #01 ;fill-rect JSR2 55 | 56 | .Screen/width DEI2 2// WIDTH 2// SUB2 #0008 ADD2 57 | .Screen/height DEI2 2// HEIGHT 2// SUB2 #0008 ADD2 58 | WIDTH #0010 SUB2 HEIGHT #0010 SUB2 59 | SIZE-TO-RECT #03 ;line-rect JSR2 60 | 61 | .Screen/width DEI2 2// .Screen/height DEI2 2// WIDTH 4// #02 ;draw-circle JSR2 62 | 63 | #0010 #0030 #0068 #02 ;line-hor JSR2 64 | #0020 #0058 #0078 #02 ;line-ver JSR2 65 | 66 | BRK 67 | 68 | @line-slow ( x1 y1 x2 y2 color -- ) 69 | 70 | ( load ) .color STZ #0001 SUB2 .line/y0 STZ2 #0001 SUB2 .line/x0 STZ2 .line/y STZ2 .line/x STZ2 71 | .line/x0 LDZ2 .line/x LDZ2 SUB2 ABS2 .line/dx STZ2 72 | .line/y0 LDZ2 .line/y LDZ2 SUB2 ABS2 #0000 SWP2 SUB2 .line/dy STZ2 73 | #ffff #00 .line/x LDZ2 .line/x0 LDZ2 LTS2 2** ADD2 .line/sx STZ2 74 | #ffff #00 .line/y LDZ2 .line/y0 LDZ2 LTS2 2** ADD2 .line/sy STZ2 75 | .line/dx LDZ2 .line/dy LDZ2 ADD2 .line/e1 STZ2 76 | &loop 77 | .line/x LDZ2 .Screen/x DEO2 .line/y LDZ2 .Screen/y DEO2 .color LDZ .Screen/pixel DEO 78 | .line/x LDZ2 .line/x0 LDZ2 EQU2 .line/y LDZ2 .line/y0 LDZ2 EQU2 #0101 EQU2 ,&end JCN 79 | .line/e1 LDZ2 2** .line/e2 STZ2 80 | .line/e2 LDZ2 .line/dy LDZ2 LTS2 ,&skipy JCN 81 | .line/e1 LDZ2 .line/dy LDZ2 ADD2 .line/e1 STZ2 82 | .line/x LDZ2 .line/sx LDZ2 ADD2 .line/x STZ2 83 | &skipy 84 | .line/e2 LDZ2 .line/dx LDZ2 GTS2 ,&skipx JCN 85 | .line/e1 LDZ2 .line/dx LDZ2 ADD2 .line/e1 STZ2 86 | .line/y LDZ2 .line/sy LDZ2 ADD2 .line/y STZ2 87 | &skipx 88 | ;&loop JMP2 89 | 90 | &end 91 | 92 | RTN 93 | 94 | @line-rect ( x1* y1* x2* y2* color -- ) 95 | 96 | ( load ) STH 97 | STH2k ,&y2 STR2 ,&x2 STR2 98 | STH2k ,&y1 STR2 ,&x1 STR2 99 | STH2r STH2r SWP2 100 | &ver 101 | ( save ) DUP2 .Screen/y DEO2 102 | ( draw ) ,&x1 LDR2 .Screen/x DEO2 STHkr .Screen/pixel DEO 103 | ( draw ) ,&x2 LDR2 .Screen/x DEO2 STHkr .Screen/pixel DEO 104 | ( incr ) INC2 105 | OVR2 OVR2 GTS2 ,&ver JCN 106 | POP2 POP2 107 | ,&x1 LDR2 ,&x2 LDR2 SWP2 108 | &hor 109 | ( save ) DUP2 .Screen/x DEO2 110 | ( draw ) ,&y1 LDR2 .Screen/y DEO2 STHkr .Screen/pixel DEO 111 | ( draw ) ,&y2 LDR2 .Screen/y DEO2 STHkr .Screen/pixel DEO 112 | ( incr ) INC2 113 | OVR2 INC2 OVR2 GTS2 ,&hor JCN 114 | POP2 POP2 POPr 115 | 116 | RTN 117 | &x1 $2 &y1 $2 &x2 $2 &y2 $2 118 | 119 | @fill-rect ( x1* y1* x2* y2* color -- ) 120 | 121 | ,&color STR 122 | ( x1 x2 y1 y2 ) ROT2 123 | &ver 124 | ( save ) DUP2 .Screen/y DEO2 125 | STH2 STH2 OVR2 OVR2 SWP2 126 | &hor 127 | ( save ) DUP2 .Screen/x DEO2 128 | ( draw ) ,&color LDR .Screen/pixel DEO 129 | ( incr ) INC2 130 | OVR2 OVR2 GTS2 ,&hor JCN 131 | POP2 POP2 STH2r STH2r 132 | ( incr ) INC2 133 | OVR2 OVR2 GTS2 ,&ver JCN 134 | POP2 POP2 POP2 POP2 135 | 136 | RTN 137 | &color $1 138 | 139 | @draw-circle ( xc yc r color -- ) 140 | 141 | ( load ) .color STZ .circle/r STZ2 .circle/yc STZ2 .circle/xc STZ2 142 | #0000 .circle/x STZ2 .circle/r LDZ2 .circle/y STZ2 143 | .circle/r LDZ2 2** .circle/d STZ2 144 | ( draw ) ;&seg JSR2 145 | &loop 146 | ( incr ) .circle/x LDZ2 INC2 .circle/x STZ2 147 | .circle/d LDZ2 #0001 LTS2 ,&else JCN 148 | ( decr ) .circle/y LDZ2 #0001 SUB2 .circle/y STZ2 149 | .circle/x LDZ2 .circle/y LDZ2 SUB2 4** .circle/d LDZ2 ADD2 .circle/d STZ2 150 | ;&end JMP2 151 | &else 152 | .circle/x LDZ2 4** .circle/d LDZ2 ADD2 .circle/d STZ2 153 | &end 154 | ( draw ) ;&seg JSR2 155 | .circle/y LDZ2 .circle/x LDZ2 #0001 SUB2 GTS2 ,&loop JCN 156 | RTN 157 | &seg 158 | .circle/xc LDZ2 .circle/x LDZ2 ADD2 .Screen/x DEO2 .circle/yc LDZ2 .circle/y LDZ2 ADD2 .Screen/y DEO2 .color LDZ .Screen/pixel DEO 159 | .circle/xc LDZ2 .circle/x LDZ2 SUB2 .Screen/x DEO2 .circle/yc LDZ2 .circle/y LDZ2 ADD2 .Screen/y DEO2 .color LDZ .Screen/pixel DEO 160 | .circle/xc LDZ2 .circle/x LDZ2 ADD2 .Screen/x DEO2 .circle/yc LDZ2 .circle/y LDZ2 SUB2 .Screen/y DEO2 .color LDZ .Screen/pixel DEO 161 | .circle/xc LDZ2 .circle/x LDZ2 SUB2 .Screen/x DEO2 .circle/yc LDZ2 .circle/y LDZ2 SUB2 .Screen/y DEO2 .color LDZ .Screen/pixel DEO 162 | .circle/xc LDZ2 .circle/y LDZ2 ADD2 .Screen/x DEO2 .circle/yc LDZ2 .circle/x LDZ2 ADD2 .Screen/y DEO2 .color LDZ .Screen/pixel DEO 163 | .circle/xc LDZ2 .circle/y LDZ2 SUB2 .Screen/x DEO2 .circle/yc LDZ2 .circle/x LDZ2 ADD2 .Screen/y DEO2 .color LDZ .Screen/pixel DEO 164 | .circle/xc LDZ2 .circle/y LDZ2 ADD2 .Screen/x DEO2 .circle/yc LDZ2 .circle/x LDZ2 SUB2 .Screen/y DEO2 .color LDZ .Screen/pixel DEO 165 | .circle/xc LDZ2 .circle/y LDZ2 SUB2 .Screen/x DEO2 .circle/yc LDZ2 .circle/x LDZ2 SUB2 .Screen/y DEO2 .color LDZ .Screen/pixel DEO 166 | 167 | RTN 168 | 169 | @cover-pattern ( addr* color -- ) 170 | 171 | ( load ) STH .Screen/addr DEO2 172 | .Screen/height DEI2 #0000 173 | &ver 174 | ( save ) DUP2 .Screen/y DEO2 175 | .Screen/width DEI2 #0000 176 | &hor 177 | ( save ) DUP2 .Screen/x DEO2 178 | ( draw ) STHkr .Screen/sprite DEO 179 | #0008 ADD2 GTH2k ,&hor JCN 180 | POP2 POP2 181 | #0008 ADD2 GTH2k ,&ver JCN 182 | POP2 POP2 183 | POPr 184 | 185 | RTN 186 | 187 | @line-hor ( x0* x1* y* color -- ) 188 | 189 | STH .Screen/y DEO2 190 | SWP2 191 | &loop 192 | ( save ) DUP2 .Screen/x DEO2 193 | ( draw ) STHkr .Screen/pixel DEO 194 | INC2 GTH2k ,&loop JCN 195 | POP2 POP2 POPr 196 | 197 | RTN 198 | 199 | @line-ver ( x* y0* y1* color -- ) 200 | 201 | STH ROT2 .Screen/x DEO2 202 | SWP2 203 | &loop 204 | ( save ) DUP2 .Screen/y DEO2 205 | ( draw ) STHkr .Screen/pixel DEO 206 | INC2 GTH2k ,&loop JCN 207 | POP2 POP2 POPr 208 | 209 | RTN 210 | 211 | @checker_icn [ f0f0 f0f0 0f0f 0f0f ] 212 | -------------------------------------------------------------------------------- /projects/examples/gui/wallpaper.tal: -------------------------------------------------------------------------------- 1 | ( devices ) 2 | 3 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 4 | |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 5 | 6 | ( variables ) 7 | 8 | |0000 9 | 10 | @scroll [ &x $2 &y $2 &wait $1 ] 11 | 12 | |0100 ( -> ) 13 | #90ff .System/r DEO2 #9000 .System/g DEO2 #900f .System/b DEO2 14 | #08e0 .Screen/width DEI2 #01 SFT2 SUB2 .scroll/x STZ2 15 | #09b0 .scroll/y STZ2 16 | ;frame .Screen/vector DEO2 17 | #30 .scroll/wait STZ 18 | BRK 19 | 20 | @frame ( -> ) 21 | #ffff 22 | &loop 23 | DUP2 ,row JSR 24 | INC2 25 | DUP2 .Screen/height DEI2 LTH2 ,&loop JCN 26 | POP2 27 | .scroll/wait LDZ ,&noscroll JCN 28 | .scroll/y LDZ2 INC2 .scroll/y STZ2 29 | BRK 30 | 31 | &noscroll 32 | .scroll/wait LDZ #01 SUB .scroll/wait STZ 33 | BRK 34 | 35 | @row ( y* -- ) 36 | DUP2 .Screen/y DEO2 37 | .scroll/y LDZ2 ADD2 38 | 39 | .Screen/width DEI2 40 | &loop 41 | #0001 SUB2 42 | OVR2 OVR2 .scroll/x LDZ2 ADD2 EOR2 DUP2 #0013 DIV2 #0013 MUL2 SUB2 43 | DUP #00 EQU ,&draw JCN 44 | DUP #05 EQU ,&draw JCN 45 | POP2 46 | &rest 47 | DUP2 ORA ,&loop JCN 48 | POP2 POP2 49 | JMP2r 50 | 51 | #15 .Screen/pixel DEO 52 | JMP2r 53 | 54 | &draw 55 | OVR2 .Screen/x DEO2 56 | #05 ADD .Screen/pixel DEO 57 | .Screen/y DEI2 58 | DUP2 INC2 .Screen/y DEO2 59 | #00 .Screen/pixel DEO 60 | .Screen/y DEO2 61 | POP 62 | ,&rest JMP 63 | 64 | -------------------------------------------------------------------------------- /projects/fonts/acorn8-italic.uf1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/acorn8-italic.uf1 -------------------------------------------------------------------------------- /projects/fonts/acorn8-regular.uf1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/acorn8-regular.uf1 -------------------------------------------------------------------------------- /projects/fonts/atari8.uf1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/atari8.uf1 -------------------------------------------------------------------------------- /projects/fonts/bbcmicro8.uf1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/bbcmicro8.uf1 -------------------------------------------------------------------------------- /projects/fonts/chicago12.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/chicago12.uf2 -------------------------------------------------------------------------------- /projects/fonts/diamond12.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/diamond12.uf2 -------------------------------------------------------------------------------- /projects/fonts/diamond20.uf3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/diamond20.uf3 -------------------------------------------------------------------------------- /projects/fonts/geneva12.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/geneva12.uf2 -------------------------------------------------------------------------------- /projects/fonts/geneva14.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/geneva14.uf2 -------------------------------------------------------------------------------- /projects/fonts/geneva24.uf3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/geneva24.uf3 -------------------------------------------------------------------------------- /projects/fonts/helvetica12.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/helvetica12.uf2 -------------------------------------------------------------------------------- /projects/fonts/helvetica14.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/helvetica14.uf2 -------------------------------------------------------------------------------- /projects/fonts/helvetica24.uf3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/helvetica24.uf3 -------------------------------------------------------------------------------- /projects/fonts/left8.uf1: -------------------------------------------------------------------------------- 1 | """""@>!R$%B>AB8B=*>*>> @>AAAAA>~>@@~>~!A@@>~>A@~AA>>AA>AA>>AA? >A>A]UEY&>AAAAA~AA~AA~>A@@@A>|BAAAB|?@@@@?@@~@@@>APNAA>AAAAAA~ABDxDBA@@@@@@cUIAAAAaQQIIEC"AAA"~AA~@@@>AAAEB=~AA~DBA?@@>~AAAAAB=AAAA"AAAAIUcA""AA" @@ "~>A}@~AA~>A@A>?AA?>A~@??@~@@?A?~@~AAA|AFxFA@@@@?vIAAAaQIEC>AAA>~A~@@?A?^a@@@?@>~AAAB=AA"AAAI7A""AA">@ 0I -------------------------------------------------------------------------------- /projects/fonts/losangeles12.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/losangeles12.uf2 -------------------------------------------------------------------------------- /projects/fonts/newyork12.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/newyork12.uf2 -------------------------------------------------------------------------------- /projects/fonts/newyork14.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/newyork14.uf2 -------------------------------------------------------------------------------- /projects/fonts/newyork24.uf3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/newyork24.uf3 -------------------------------------------------------------------------------- /projects/fonts/orca8.uf1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/orca8.uf1 -------------------------------------------------------------------------------- /projects/fonts/palatino12.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/palatino12.uf2 -------------------------------------------------------------------------------- /projects/fonts/palatino14.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/palatino14.uf2 -------------------------------------------------------------------------------- /projects/fonts/palatino24.uf3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/palatino24.uf3 -------------------------------------------------------------------------------- /projects/fonts/sans10-bold.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/sans10-bold.uf2 -------------------------------------------------------------------------------- /projects/fonts/sans10-regular.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/sans10-regular.uf2 -------------------------------------------------------------------------------- /projects/fonts/sapphire14.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/sapphire14.uf2 -------------------------------------------------------------------------------- /projects/fonts/sapphire19.uf3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/sapphire19.uf3 -------------------------------------------------------------------------------- /projects/fonts/specter8.uf1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/specter8.uf1 -------------------------------------------------------------------------------- /projects/fonts/terminal12.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/terminal12.uf2 -------------------------------------------------------------------------------- /projects/fonts/times12.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/times12.uf2 -------------------------------------------------------------------------------- /projects/fonts/times15.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/times15.uf2 -------------------------------------------------------------------------------- /projects/fonts/times24.uf3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/times24.uf3 -------------------------------------------------------------------------------- /projects/fonts/venice14.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/fonts/venice14.uf2 -------------------------------------------------------------------------------- /projects/library/binary-tree.tal: -------------------------------------------------------------------------------- 1 | ( 2 | 3 | binary tree node layout: 4 | 5 | +--+--+ 6 | | ' | incoming-ptr* 7 | +--+--+ key: null optional 8 | v left right terminated binary 9 | | ptr ptr string data 10 | \ +--+--+--+--+---------+--+----- - - 11 | ---> | ' | ' | U x n .00| 12 | +--+--+--+--+---------+--+----- - - 13 | 14 | All of the pointers (ptr) are shorts that have the value of the memory 15 | location of the next node, or 0000 to mean that pointer is empty. The very 16 | simplest tree is one where the incoming-ptr* is empty: 17 | 18 | +--+--+ 19 | |00'00| incoming-ptr* 20 | +--+--+ 21 | 22 | traverse-tree does two jobs at once, depending on whether the search-key is 23 | found: 24 | 25 | * if the search-key exists in the tree, return a pointer to the binary data 26 | that follows that node's key string; 27 | 28 | * if the search-key is not present in the key, return the incoming-ptr* that 29 | should be written when adding this node yourself. 30 | 31 | ) 32 | 33 | @traverse-tree ( incoming-ptr* search-key* -- binary-ptr* 00 if key found 34 | OR node-incoming-ptr* 01 if key not found ) 35 | STH2 36 | &loop ( incoming-ptr* / search-key* ) 37 | LDA2k ORA ,&valid-node JCN 38 | POP2r #01 JMP2r 39 | 40 | &valid-node ( incoming-ptr* / search-key* ) 41 | LDA2 ( node* / search-key* ) 42 | DUP2 #0004 ADD2 ( node* node-key* / search-key* ) 43 | STH2kr ( node* node-key* search-key* / search-key* ) 44 | ,strcmp JSR ( node* node-end* search-end* order nomatch / search-key* ) 45 | ,&nomatch JCN ( node* node-end* search-end* order / search-key* ) 46 | POP POP2 ( node* node-end* / search-key* ) 47 | INC2 NIP2 ( binary-ptr* / search-key* ) 48 | POP2r #00 ( binary-ptr* 00 ) 49 | JMP2r 50 | 51 | &nomatch ( node* node-end* search-end* order / search-key* ) 52 | #80 AND #06 SFT #00 SWP STH2 ( node* node-end* search-end* / search-key* node-offset^ ) 53 | POP2 POP2 ( node* / search-key* node-offset^ ) 54 | STH2r ADD2 ( incoming-ptr* / search-key* ) 55 | ,&loop JMP 56 | 57 | -------------------------------------------------------------------------------- /projects/library/file-read-chunks.tal: -------------------------------------------------------------------------------- 1 | ( 2 | 3 | # Summary 4 | 5 | Reads a file in chunks - perfect for when you have a small buffer or when you 6 | don't know the file size. Copes with files up to 4,294,967,295 bytes long. 7 | 8 | # Code 9 | 10 | ) 11 | @file-read-chunks ( func* udata* buf* size* filename* -- func* udata'* buf* size* filename* ) 12 | 13 | #0000 DUP2 ( F* U* B* SZ* FN* OL* OH* / ) 14 | &resume 15 | ROT2 STH2 ( F* U* B* SZ* OL* OH* / FN* ) 16 | ROT2 ( F* U* B* OL* OH* SZ* / FN* ) 17 | 18 | &loop 19 | STH2kr .File/name DEO2 ( F* U* B* OL* OH* SZ* / FN* ) 20 | STH2k .File/length DEO2 ( F* U* B* OL* OH* / FN* SZ* ) 21 | STH2k .File/offset-hs DEO2 ( F* U* B* OL* / FN* SZ* OH* ) 22 | STH2k .File/offset-ls DEO2 ( F* U* B* / FN* SZ* OH* OL* ) 23 | SWP2 ( F* B* U* / FN* SZ* OH* OL* ) 24 | ROT2k NIP2 ( F* B* U* B* F* / FN* SZ* OH* OL* ) 25 | OVR2 .File/load DEO2 ( F* B* U* B* F* / FN* SZ* OH* OL* ) 26 | .File/success DEI2 SWP2 ( F* B* U* B* length* F* / FN* SZ* OH* OL* ) 27 | JSR2 ( F* B* U'* done-up-to* / FN* SZ* OH* OL* ) 28 | ROT2 SWP2 ( F* U'* B* done-up-to* / FN* SZ* OH* OL* ) 29 | SUB2k NIP2 ( F* U'* B* -done-length* / FN* SZ* OH* OL* ) 30 | ORAk ,¬-end JCN ( F* U'* B* -done-length* / FN* SZ* OH* OL* ) 31 | 32 | POP2 POP2r POP2r ( F* U'* B* / FN* SZ* ) 33 | STH2r STH2r ( F* U'* B* SZ* FN* / ) 34 | JMP2r 35 | 36 | ¬-end 37 | STH2r SWP2 ( F* U'* B* OL* -done-length* / FN* SZ* OH* ) 38 | LTH2k JMP INC2r ( F* U'* B* OL* -done-length* / FN* SZ* OH'* ) 39 | SUB2 ( F* U'* B* OL'* / FN* SZ* OH'* ) 40 | STH2r STH2r ( F* U'* B* OL'* OH'* SZ* / FN* ) 41 | ,&loop JMP 42 | 43 | ( 44 | 45 | # Arguments 46 | 47 | * func* - address of callback routine 48 | * udata* - userdata to pass to callback routine 49 | * buf* - address of first byte of buffer of file's contents 50 | * size* - size in bytes of buffer 51 | * filename* - address of filename string (zero-terminated) 52 | 53 | All of the arguments are shorts (suffixed by asterisks *). 54 | 55 | # Callback routine 56 | 57 | If you make use of userdata, the signature of the callback routine is: 58 | ) 59 | ( udata* buf* length* -- udata'* done-up-to* ) 60 | ( 61 | 62 | * udata* and buf* are as above. 63 | * length* is the length of the chunk being worked on, which could be less than 64 | size* when near the end of the file, and func* is called with zero length* to 65 | signify end of file. 66 | * udata'* is the (potentially) modified userdata, to be passed on to the next 67 | callback routine call and returned by file-read-chunks after the last chunk. 68 | * done-up-to* is the pointer to the first unprocessed byte in the buffer, or 69 | buf* + length* if the whole chunk was processed. 70 | 71 | If you don't make use of any userdata, feel free to pretend the signature is: 72 | ) 73 | ( buf* length* -- done-up-to* ) 74 | ( 75 | 76 | # Userdata 77 | 78 | The udata* parameter is not processed by file-read-chunks, except to keep the 79 | one returned from one callback to the next. The meaning of its contents is up 80 | to you - it could simply be a short integer or a pointer to a region of memory. 81 | 82 | # Operation 83 | 84 | file-read-chunks reads a file into the buffer you provide and calls func* with 85 | JSR2 with each chunk of data, finishing with an empty chunk at end of file. 86 | 87 | file-read-chunks loops until done-up-to* equals buf*, equivalent to when no 88 | data is processed by func*. This could be because processing cannot continue 89 | without a larger buffer, an error is detected in the data and further 90 | processing is pointless, or because the end-of-file empty chunk leaves the 91 | callback routine with no other choice. 92 | 93 | # Return values 94 | 95 | Since file-read-chunks's input parameters remain available throughout its 96 | operation, they are not automatically discarded in case they are useful to the 97 | caller. 98 | 99 | # Discussion about done-up-to* 100 | 101 | file-read-chunks is extra flexible because it doesn't just give you one chance 102 | to process each part of the file. Consider a func* routine that splits the 103 | chunk's contents into words separated by whitespace. If the buffer ends with a 104 | letter, you can't assume that letter is the end of that word - it's more likely 105 | to be the in the middle of a word that continues on. If func* returns the 106 | address of the first letter of the word so far, it will be called again with 107 | that first letter as the first character of the next chunk's buffer. There's no 108 | need to remember the earlier part of the word because you get presented with 109 | the whole lot again to give parsing another try. 110 | 111 | That said, func* must make at least _some_ progress through the chunk: if it 112 | returns the address at the beginning of the buffer, buf*, file-read-chunks will 113 | terminate and return to its caller. With our word example, a buffer of ten 114 | bytes will be unable to make progress with words that are ten or more letters 115 | long. Depending on your application, either make the buffer big enough so that 116 | progress should always be possible, or find a way to discern this error 117 | condition from everything working fine. 118 | 119 | # Discussion about recursion 120 | 121 | Since all of file-read-chunks's data is on the working and return stacks, it 122 | can be called recursively by code running in the callback routine. For example, 123 | a code assembler can process the phrase "include library.tal" by calling 124 | file-read-chunks again with library.tal as the filename. There are a couple of 125 | caveats: 126 | 127 | * the filename string must not reside inside file-read-chunk's working buffer, 128 | otherwise it gets overwritten by the file's contents and subsequent chunks 129 | will fail to be read properly; and 130 | 131 | * if the buffer is shared with the parent file-read-chunk, the callback routine 132 | should stop further processing and return with done-up-to* straight away, 133 | since the buffer contents have already been replaced by the child 134 | file-read-chunk. 135 | 136 | # Resuming / starting operation from an arbitrary offset 137 | 138 | You can call file-read-chunks/resume instead of the main routine if you'd like 139 | to provide your own offset shorts rather than beginning at the start of the 140 | file. The effective signature for file-read-chunks/resume is: 141 | ) 142 | ( func* udata* buf* size* filename* offset-ls* offset-hs* -- func* udata'* buf* size* filename* ) 143 | ( 144 | 145 | # Example callback routines 146 | 147 | This minimal routine is a no-op that "processes" the entire buffer each time 148 | and returns a valid done-up-to*: 149 | 150 | @quick-but-useless 151 | ADD2 JMP2r 152 | 153 | This extremely inefficient callback routine simply prints a single character 154 | from the buffer and asks for the next one. It operates with a buffer that is 155 | just one byte long, but for extra inefficiency you can assign a much larger 156 | buffer and it will ignore everything after the first byte each time. If the 157 | buffer is zero length it returns done-up-to* == buf* so that file-read-chunks 158 | returns properly. 159 | 160 | @one-at-a-time 161 | #0000 NEQ2 JMP JMP2r 162 | LDAk .Console/write DEO 163 | INC2 JMP2r 164 | 165 | This more efficient example writes the entire chunk to the console before 166 | requesting the next one by returning. How short can you make a routine that 167 | does the same? 168 | 169 | @chunk-at-a-time 170 | &loop 171 | ORAk ,¬-eof JCN 172 | POP2 JMP2r 173 | 174 | ¬-eof 175 | STH2 176 | LDAk .Console/write DEO 177 | INC2 STH2r #0001 SUB2 178 | ,&loop JMP 179 | 180 | ) 181 | -------------------------------------------------------------------------------- /projects/library/heap.tal: -------------------------------------------------------------------------------- 1 | ( 2 | heap functions 3 | 4 | The heap is an area of memory that is written from the bottom up. These 5 | are a few convenience functions to do that writing. 6 | 7 | There is a global short called "heap" that must be written to before using 8 | these functions, otherwise the zero page and program memory could be 9 | overwritten. 10 | 11 | A simple program could use all unallocated memory for the heap like so: 12 | 13 | |0100 @reset 14 | ;my-heap ;heap STA2 15 | 16 | (the rest of your code) 17 | 18 | @my-heap 19 | 20 | Note that if there is a risk that the heap may overflow its bounds, it is 21 | strongly recommended to check where it is writing to. ";heap LDA2" will 22 | tell you where the next byte is written. 23 | ) 24 | 25 | @heap $2 26 | 27 | @append-heap-byte ( byte -- ) 28 | ,heap LDR2 ( byte heap* ) 29 | INC2k ,heap STR2 30 | STA 31 | JMP2r 32 | 33 | @append-heap-short ( short^ -- ) 34 | ,heap LDR2 ( short^ heap* ) 35 | INC2k INC2 ,heap STR2 36 | STA2 37 | JMP2r 38 | 39 | @append-heap-string ( string* -- ) 40 | ( copies a null-terminated string onto the heap, including the null ) 41 | STH2 ,heap LDR2 ( heap* / string* ) 42 | #01 JMP ( skip past INC2r ) 43 | 44 | &loop 45 | INC2r ( heap* / string* ) 46 | LDAkr DUPr STH2k STAr ( heap* / string* byte ) 47 | INC2 48 | LITr f7 JCNr ( f7 is the value ",&loop" would produce ) 49 | POP2r ( heap* ) 50 | ,heap STR2 51 | JMP2r 52 | 53 | -------------------------------------------------------------------------------- /projects/library/load-rom.tal: -------------------------------------------------------------------------------- 1 | @load-rom ( filename* -- ) 2 | ( 3 | Attempts to load the ROM from filename* and executes it. If the file exists 4 | and has non-zero length, this function does not return, because the new ROM 5 | is executing in its place. 6 | 7 | The screen and both stacks are cleared and all the device vectors are 8 | written to zero as a convenience. All other device bytes are left 9 | untouched, so they could introduce a device state to the next ROM that 10 | it's not expecting. 11 | ) 12 | 13 | .File/name DEO2 14 | #0000 .File/offset-hs DEO2 15 | #0000 .File/offset-ls DEO2 16 | 17 | ( return if file can't be found, or zero length ) 18 | #0001 .File/length DEO2 19 | ;&tmp .File/load DEO2 20 | .File/success DEI2 ORA JMP JMP2r 21 | 22 | ( clear wst ) 23 | #ab 24 | &wst-loop 25 | POP 26 | .System/wst STH DEIr STHr ,&wst-loop JCN 27 | 28 | ( clear rst ) 29 | LITr ab 30 | &rst-loop 31 | POPr 32 | .System/rst DEI ,&rst-loop JCN 33 | 34 | ( clear screen ) 35 | #01 .Screen/auto DEO 36 | #0000 .Screen/y DEO2 37 | .Screen/width DEI2 #0007 ADD2 #03 SFT2 #ffff MUL2 STH2 38 | &screen-yloop 39 | #0000 .Screen/x DEO2 40 | STH2kr 41 | &screen-xloop-bg 42 | #00 .Screen/sprite DEO 43 | INC2 44 | ORAk ,&screen-xloop-bg JCN 45 | POP2 46 | #0000 .Screen/x DEO2 47 | STH2kr 48 | &screen-xloop-fg 49 | #40 .Screen/sprite DEO 50 | INC2 51 | ORAk ,&screen-xloop-fg JCN 52 | POP2 53 | .Screen/y DEI2 #0008 ADD2 54 | DUP2 .Screen/y DEO2 55 | .Screen/height DEI2 LTH2 ,&screen-yloop JCN 56 | POP2r 57 | #00 .Screen/auto DEO 58 | 59 | ( reset device vectors ) 60 | LIT2r 0000 #00 61 | &device-vector-loop 62 | DUP2r STHk DEO2r 63 | #10 ADD 64 | DUP ,&device-vector-loop JCN 65 | POP POP2r 66 | 67 | ( copy the zero-page-loader into f0-ff ) 68 | ;&zero-page-loader LITr f0 69 | ©-loop 70 | LDAk STHkr STZ 71 | INC2 INCr 72 | STHkr ,©-loop JCN 73 | POP2 ( leave 00 on return stack ) 74 | 75 | ( prepare the stack for the zero-page-loader ) 76 | ( the more we prepare here in advance, the less we'll have to overwrite ) 77 | STHkr #00fe ( arguments for STZ2 at ff ) 78 | STHkr ( argument for JMP at fe (carry on) ) 79 | DUPk #fcfe ( arguments for STZ2 at fd and JMP (repeat) ) 80 | OVR2 #fafe ( arguments for STZ2 at fd and JMP (repeat) ) 81 | OVR2 #f8fe ( arguments for STZ2 at fd and JMP (repeat) ) 82 | OVR2 #f6fe ( arguments for STZ2 at fd and JMP (repeat) ) 83 | OVR2 #f401 ( arguments for STZ2 at fd, plus an extra 01 ) 84 | STHkr ( first argument for ADD2 ) 85 | .File/success ( argument for DEI2 ) 86 | #0100 .File/load ( arguments for DEO2 ) 87 | #ff00 .File/length DEO2 88 | #00f0 JMP2 89 | 90 | &zero-page-loader 91 | ( f0 ) DEO2 92 | ( f1 ) DEI2 93 | ( f2 ) ADD2 94 | ( f3 ) &loop DUPr 95 | ( f4 ) STH2k 96 | ( f5 ) STAr 97 | ( f6 ) INC2 98 | ( f7 ) NEQ2k 99 | ( f8 ) ,&loop 100 | ( f9 ) 101 | ( fa ) JCN 102 | ( fb ) POPr 103 | ( fc ) POP2 104 | ( fd ) STZ2 ( deletes f4-fd through looping ) 105 | ( fe ) JMP 106 | ( ff ) STZ2 ( deletes fe-ff ) 107 | 108 | &tmp $1 109 | 110 | -------------------------------------------------------------------------------- /projects/library/string.tal: -------------------------------------------------------------------------------- 1 | @strcmp ( a* b* -- a-end* b-end* order nonzero if strings differ 2 | OR a-end* b-end* 00 00 if strings match ) 3 | STH2 4 | ,&entry JMP 5 | 6 | &loop ( a* a b / b* ) 7 | SUB ,&nomatch JCNk ( a* a-b nonzero / b* ) 8 | POP2 ( a* / b* ) 9 | INC2 INC2r 10 | &entry ( a* / b* ) 11 | LDAk LDAkr STHr ( a* a b / b* ) 12 | ORAk ,&loop JCN 13 | 14 | &nomatch ( a* a-b flag / b* ) 15 | STH2r SWP2 ( a* b* a-b flag ) 16 | JMP2r 17 | 18 | @strlen ( string-ptr* -- length^ ) 19 | LIT2r 0000 20 | ,&entry JMP 21 | 22 | &loop 23 | INC2 INC2r 24 | &entry 25 | LDAk ,&loop JCN 26 | POP2 STH2r 27 | JMP2r 28 | 29 | -------------------------------------------------------------------------------- /projects/pictures/akane2010.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/akane2010.bit -------------------------------------------------------------------------------- /projects/pictures/ako10x10.chr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/ako10x10.chr -------------------------------------------------------------------------------- /projects/pictures/cibo.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/cibo.bit -------------------------------------------------------------------------------- /projects/pictures/cyr10x8.chr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/cyr10x8.chr -------------------------------------------------------------------------------- /projects/pictures/dafu80x80.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/dafu80x80.bit -------------------------------------------------------------------------------- /projects/pictures/daria10x10.chr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/daria10x10.chr -------------------------------------------------------------------------------- /projects/pictures/ergo100x0c0.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/ergo100x0c0.bit -------------------------------------------------------------------------------- /projects/pictures/felix0cx0c.chr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/felix0cx0c.chr -------------------------------------------------------------------------------- /projects/pictures/logo1x1.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/logo1x1.bit -------------------------------------------------------------------------------- /projects/pictures/macpaint4020.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/macpaint4020.bit -------------------------------------------------------------------------------- /projects/pictures/pc98.chr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/pc98.chr -------------------------------------------------------------------------------- /projects/pictures/tima2a1a.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/tima2a1a.bit -------------------------------------------------------------------------------- /projects/pictures/zerotwo10x10.chr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/zerotwo10x10.chr -------------------------------------------------------------------------------- /projects/pictures/zerotwo20x20.chr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/pictures/zerotwo20x20.chr -------------------------------------------------------------------------------- /projects/software/asma.tal: -------------------------------------------------------------------------------- 1 | ( devices ) 2 | 3 | |00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1 ] 4 | |10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ] 5 | |a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ] 6 | 7 | ( vectors ) 8 | 9 | |0100 @reset 10 | ( 11 | Set the log level for helping to debug stuff. 12 | Its value is the bitwise OR of all the following output types: 13 | #01 prints the number of lines in the source code, 14 | #04 dumps all defined labels at end, and 15 | #08 prints the heap usage. 16 | ) 17 | #09 ;asma/log-level STA 18 | 19 | ;asma-heap ;heap STA2 20 | 21 | ;on-input .Console/vector DEO2 22 | BRK 23 | 24 | @on-input ( -> ) 25 | .Console/read DEI 26 | DUP #0a EQU ,&newline JCN 27 | ;append-heap-byte JSR2 28 | BRK 29 | 30 | &newline ( 0a ) 31 | DUP EOR ( 00 ) 32 | ;append-heap-byte JSR2 ( ) 33 | 34 | ;asma-heap #0000 ;asma-assemble-file JSR2 35 | #01 .System/halt DEO 36 | BRK 37 | 38 | include projects/library/asma.tal 39 | 40 | @asma-heap 41 | |e000 &end 42 | 43 | @asma-read-buffer 44 | |f800 &end 45 | 46 | @asma-write-buffer 47 | |ffff &end 48 | 49 | -------------------------------------------------------------------------------- /projects/software/hexes.tal: -------------------------------------------------------------------------------- 1 | ( hexes 2 | 3 | A small utility that prints incoming console messages as hex values. ) 4 | 5 | %RTN { JMP2r } 6 | 7 | |10 @Console [ &vector $2 &read $1 &pad $5 &write $1 ] 8 | 9 | ( init ) 10 | 11 | |0100 ( -> ) 12 | 13 | ;on-message .Console/vector DEO2 14 | 15 | BRK 16 | 17 | @on-message ( -> ) 18 | 19 | .Console/read DEI ,print-hex JSR 20 | 21 | BRK 22 | 23 | @print-hex ( value -- ) 24 | 25 | STHk #04 SFT ,&parse JSR .Console/write DEO 26 | STHr #0f AND ,&parse JSR .Console/write DEO 27 | RTN 28 | &parse ( value -- char ) 29 | DUP #09 GTH ,&above JCN #30 ADD RTN &above #09 SUB #60 ADD RTN 30 | 31 | RTN 32 | -------------------------------------------------------------------------------- /projects/software/neralie.tal: -------------------------------------------------------------------------------- 1 | ( 2 | app/neralie : clock with arvelie date 3 | 4 | TODO 5 | - use splash screen when FPS calculation is unstable 6 | ) 7 | 8 | %+ { ADD } %- { SUB } %/ { DIV } 9 | %< { LTH } %> { GTH } %= { EQU } %! { NEQ } 10 | %++ { ADD2 } %-- { SUB2 } %// { DIV2 } 11 | %<< { LTH2 } %>> { GTH2 } %== { EQU2 } %!! { NEQ2 } 12 | 13 | %2* { #10 SFT } %2/ { #01 SFT } 14 | %4* { #20 SFT } %4/ { #02 SFT } 15 | %8* { #30 SFT } %8/ { #03 SFT } 16 | %10* { #40 SFT } %10/ { #04 SFT } 17 | %20* { #50 SFT } %20/ { #05 SFT } 18 | 19 | %2** { #10 SFT2 } %2// { #01 SFT2 } 20 | %4** { #20 SFT2 } %4// { #02 SFT2 } 21 | %8** { #30 SFT2 } %8// { #03 SFT2 } 22 | %10** { #40 SFT2 } %10// { #04 SFT2 } 23 | %20** { #50 SFT2 } %20// { #05 SFT2 } 24 | 25 | %MOD { DUP2 DIV MUL SUB } 26 | %MOD2 { DIV2k MUL2 SUB2 } 27 | %TOS { #00 SWP } 28 | 29 | %h { .DateTime/hour DEI } 30 | %m { .DateTime/minute DEI } 31 | %s { .DateTime/second DEI } 32 | 33 | %1-- { #0001 -- } 34 | 35 | %PAD { #0018 } 36 | %RTN { JMP2r } 37 | 38 | ( devices ) 39 | 40 | |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] 41 | |10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ] 42 | |20 @Screen [ &vector $2 &width $2 &height $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] 43 | |b0 @DateTime [ &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 ] 44 | 45 | ( variables ) 46 | 47 | |0000 48 | 49 | @fps [ ¤t $1 &next $1 &second $1 ] 50 | @number [ &started $1 &count $1 ] 51 | @lines [ &addr $1 ] 52 | @neralie [ &n0123 $2 &n4 $1 &n5 $1 &n6 $1 &n7 $1 &n8 $1 &n9 $1 &color $1 &x $2 &y $2 &w $2 &h $2 ] 53 | @mul [ &ahi $1 &alo $1 &bhi $1 &blo $1 ] 54 | @frame 55 | &x1 $2 &x2 $2 &y1 $2 &y2 $2 56 | 57 | ( program ) 58 | 59 | |0100 60 | 61 | ( theme ) 62 | #0f3d .System/r DEO2 63 | #0fe3 .System/g DEO2 64 | #0fb2 .System/b DEO2 65 | 66 | ( vectors ) 67 | ;on-screen .Screen/vector DEO2 68 | 69 | ( window ) 70 | #0160 .Screen/width DEO2 71 | #0110 .Screen/height DEO2 72 | 73 | #01 .fps/current STZ 74 | 75 | ( set size ) 76 | PAD 77 | DUP2 .frame/x1 STZ2 78 | DUP2 .frame/y1 STZ2 79 | DUP2 .Screen/width DEI2 SWP2 -- #0001 -- .frame/x2 STZ2 80 | .Screen/height DEI2 SWP2 -- .frame/y2 STZ2 81 | 82 | #01 .neralie/color STZ 83 | 84 | .frame/x1 LDZ2 .frame/x2 LDZ2 85 | OVR2 OVR2 .frame/y1 LDZ2 ;h JSR2 86 | .frame/y2 LDZ2 ;h JSR2 87 | .frame/y1 LDZ2 #0001 -- .frame/y2 LDZ2 INC2 88 | OVR2 OVR2 .frame/x1 LDZ2 ;v JSR2 89 | .frame/x2 LDZ2 ;v JSR2 90 | 91 | @on-screen ( -> ) 92 | 93 | ;update-fps JSR2 94 | 95 | #00 .neralie/color STZ 96 | ;draw-clock JSR2 97 | ;neralie-calc JSR2 98 | 99 | #01 .neralie/color STZ 100 | ;draw-date JSR2 101 | ;draw-clock JSR2 102 | 103 | BRK 104 | 105 | @neralie-calc ( -- ) 106 | 107 | ( add up fractions of a pulse, store tenths in n6 ) 108 | #0120 #00 h MUL2 109 | #00c0 #00 m MUL2 ADD2 110 | #00f8 #00 s MUL2 ADD2 111 | #0271 #00 .fps/next LDZ MUL2 #00 .fps/current LDZ DIV2 8** ADD2 112 | #01b0 ;modf JSR2 SWP2 #0017 MUL2 #03e8 DIV2 .neralie/n6 STZ POP 113 | 114 | ( add up units and tens of pulses, store in n5 and n4 ) 115 | #0042 #00 h MUL2 ADD2 116 | #005e #00 m MUL2 ADD2 117 | #000b #00 s MUL2 ADD2 118 | #000a ;modf JSR2 SWP2 .neralie/n5 STZ POP 119 | #000a ;modf JSR2 SWP2 .neralie/n4 STZ POP 120 | 121 | ( add up hundreds of pulses + 10 x beats, store in n0123 ) 122 | #01a0 #00 h MUL2 ADD2 123 | #0006 #00 m MUL2 ADD2 .neralie/n0123 STZ2 124 | 125 | RTN 126 | 127 | @draw-date ( -- ) 128 | 129 | ( auto x ) #01 .Screen/auto DEO 130 | 131 | .Screen/width DEI2 2// #0034 -- .Screen/x DEO2 132 | .Screen/height DEI2 #0010 -- .Screen/y DEO2 133 | 134 | ( arvelie ) 135 | .DateTime/year DEI2 #07d6 -- NIP 136 | DUP #0a DIV TOS 8** ;font-numbers ++ .Screen/addr DEO2 137 | #01 .Screen/sprite DEO 138 | #0a MOD TOS 8** ;font-numbers ++ .Screen/addr DEO2 139 | #01 .Screen/sprite DEO 140 | .DateTime/doty DEI2 141 | DUP2 #000e DIV2 8** ;font-letters ++ .Screen/addr DEO2 142 | #01 .Screen/sprite DEO 143 | #000e MOD2 144 | DUP2 #000a DIV2 ,digit JSR 145 | #000a MOD2 ,digit JSR 146 | 147 | .Screen/x DEI2 #0008 ++ .Screen/x DEO2 148 | 149 | ( neralie ) 150 | .neralie/n0123 LDZ2 151 | #03e8 ;modf JSR2 ,digit JSR 152 | #0064 ;modf JSR2 ,digit JSR 153 | #000a ;modf JSR2 ,digit JSR 154 | #000b ,digit JSR ( the colon ) 155 | ,digit JSR 156 | #00 .neralie/n4 LDZ ,digit JSR 157 | #00 .neralie/n5 LDZ ,digit JSR 158 | 159 | ( auto none ) #00 .Screen/auto DEO 160 | 161 | RTN 162 | 163 | @digit ( index* -- ) 164 | 165 | 8** ;font-numbers ++ .Screen/addr DEO2 166 | .neralie/color LDZ .Screen/sprite DEO 167 | 168 | RTN 169 | 170 | @draw-clock ( -- ) 171 | 172 | .frame/x2 LDZ2 .frame/x1 LDZ2 173 | DUP2 .neralie/x STZ2 SUB2 .neralie/w STZ2 174 | .frame/y2 LDZ2 .frame/y1 LDZ2 175 | DUP2 .neralie/y STZ2 SUB2 .neralie/h STZ2 176 | 177 | ;neralie/n4 NIP .neralie/n0123 LDZ2 178 | 179 | DUP2 ;&h JSR2 180 | 181 | ;&next JSR2 #0008 .Screen/x DEO2 .neralie/y LDZ2 #0003 SUB2 .Screen/y DEO2 ,digit JSR 182 | 183 | DUP2 ;&v JSR2 184 | #04 ;v/spacing STA 185 | .frame/y1 LDZ2 #0003 SUB2 .neralie/y LDZ2 .neralie/x LDZ2 ;v JSR2 186 | #01 ;v/spacing STA 187 | ,&next JSR #0008 .Screen/y DEO2 .neralie/x LDZ2 #0003 SUB2 .Screen/x DEO2 ;digit JSR2 188 | DUP2 ,&h JSR 189 | ,&next JSR .Screen/width DEI2 #0010 SUB2 .Screen/x DEO2 .neralie/y LDZ2 #0003 SUB2 .Screen/y DEO2 ;digit JSR2 190 | DUP2 ,&v JSR 191 | ,&next JSR POP2 192 | DUP2 ,&h JSR 193 | ,&next JSR POP2 194 | DUP2 ,&v JSR 195 | POP2 POP 196 | JMP2r 197 | 198 | &next ( digit-addr number* -- next-digit-addr next-number* prev-digit* ) 199 | #03e8 ;modf JSR2 STH2 #000a MUL2 200 | ROT DUP STH INC ROT ROT 201 | #00 STHr LDZ ADD2 202 | STH2r 203 | JMP2r 204 | 205 | &h ( number* -- ) 206 | ,scale JSR 207 | .neralie/h LDZ2 ;mul2hi JSR2 208 | ORAk #02 JCN POP2 JMP2r 209 | DUP2 .neralie/y LDZ2 ADD2 .neralie/y STZ2 210 | .neralie/h LDZ2 SWP2 SUB2 .neralie/h STZ2 211 | .neralie/x LDZ2 DUP2 .neralie/w LDZ2 ADD2 .neralie/y LDZ2 ,h JMP 212 | 213 | &v ( number* -- ) 214 | ,scale JSR 215 | .neralie/w LDZ2 ;mul2hi JSR2 216 | ORAk #02 JCN POP2 JMP2r 217 | DUP2 .neralie/x LDZ2 ADD2 .neralie/x STZ2 218 | .neralie/w LDZ2 SWP2 SUB2 .neralie/w STZ2 219 | .neralie/y LDZ2 DUP2 .neralie/h LDZ2 ADD2 .neralie/x LDZ2 ,v JMP 220 | 221 | @scale ( 0..10000* -- 0..65535* ) 222 | DUP2 #8db8 ;mul2hi JSR2 223 | SWP2 #0006 MUL2 ADD2 224 | JMP2r 225 | 226 | @h ( x1* x2* y* -- ) 227 | .Screen/y DEO2 228 | .Screen/x .lines/addr STZ 229 | ,v/draw-line JMP 230 | 231 | @v ( y1* y2* x* -- ) 232 | .Screen/x DEO2 233 | .Screen/y .lines/addr STZ 234 | 235 | &draw-line ( v1* v2* -- ) 236 | OVR2 OVR2 LTH2 #01 JCN SWP2 237 | STH2 238 | 239 | &loop 240 | LIT2 [ 00 ] &spacing [ 01 ] ADD2 241 | DUP2 DUP2r STH2r LTH2 ,&keep-going JCN 242 | POP2 POP2r 243 | JMP2r 244 | 245 | &keep-going 246 | DUP2 .lines/addr LDZ DEO2 247 | .neralie/color LDZ .Screen/pixel DEO 248 | ,&loop JMP 249 | 250 | @update-fps ( -- ) 251 | .fps/next LDZ INC .fps/next STZ 252 | s .fps/second LDZ NEQ JMP JMP2r 253 | s .fps/second STZ 254 | .fps/next LDZ .fps/current STZ 255 | 256 | ( ~fps.next ^print-byte-decimal JSR 257 | ,strings-fps ^print-string JSR ) 258 | 259 | #00 .fps/next STZ 260 | JMP2r 261 | 262 | @modf ( dividend* divisor* -- remainder* quotient* ) 263 | OVR2 OVR2 DIV2 DUP2 STH2 MUL2 SUB2 STH2r JMP2r 264 | 265 | @mul2hi ( a* b* -- product-top-16-bits* ) 266 | ( 267 | Multiplying two 16-bit numbers yields a 32-bit number. 268 | MUL2 returns the lowest 16 bits, we want the highest. 269 | 270 | We split each short into hi and lo bytes, then sum 271 | the following multiplications: 272 | 273 | 31..24 23..16 15..08 07..00 274 | { ahi * bhi } 275 | { alo * bhi } 276 | { ahi * blo } 277 | { alo * blo } 278 | 279 | Bits 07..00 can be ignored, but each sum in bits 23..16 280 | can end up overflowing into bit 24. 281 | ) 282 | 283 | ;mul/bhi STA2 ;mul/ahi STA2 284 | #00 285 | #00 286 | #00 .mul/alo LDZ #00 .mul/blo LDZ MUL2 287 | POP 288 | #00 .mul/ahi LDZ #00 .mul/blo LDZ MUL2 ,&adc JSR 289 | #00 .mul/alo LDZ #00 .mul/bhi LDZ MUL2 ,&adc JSR 290 | POP 291 | #00 .mul/ahi LDZ #00 .mul/bhi LDZ MUL2 ADD2 292 | JMP2r 293 | 294 | &adc ( 31..24 a* b* -- 31..24 sum* ) 295 | OVR2 ADD2 SWP2 OVR2 296 | GTH2 ,&carry JCN 297 | JMP2r 298 | &carry 299 | ROT INC ROT ROT 300 | JMP2r 301 | 302 | @font-numbers 303 | 7cc6 ced6 e6c6 7c00 1838 1818 1818 7e00 3c66 063c 6066 7e00 304 | 3c66 061c 0666 3c00 1c3c 6ccc fe0c 1e00 7e62 607c 0666 3c00 305 | 3c66 607c 6666 3c00 7e66 060c 1818 1800 3c66 663c 6666 3c00 306 | 3c66 663e 0666 3c00 7cc6 ced6 e6c6 7c00 0018 1800 1818 0000 307 | 308 | @font-letters 309 | 183c 6666 7e66 6600 fc66 667c 6666 fc00 3c66 c0c0 c066 3c00 310 | f86c 6666 666c f800 fe62 6878 6862 fe00 fe62 6878 6860 f000 311 | 3c66 c0c0 ce66 3e00 6666 667e 6666 6600 7e18 1818 1818 7e00 312 | 1e0c 0c0c cccc 7800 e666 6c78 6c66 e600 f060 6060 6266 fe00 313 | c6ee fefe d6c6 c600 c6e6 f6de cec6 c600 386c c6c6 c66c 3800 314 | fc66 667c 6060 f000 386c c6c6 dacc 7600 fc66 667c 6c66 e600 315 | 3c66 603c 0666 3c00 7e5a 1818 1818 3c00 6666 6666 6666 3c00 316 | 6666 6666 663c 1800 c6c6 c6d6 feee c600 c66c 3838 6cc6 c600 317 | 6666 663c 1818 3c00 fec6 8c18 3266 fe00 0018 187e 1818 0000 318 | -------------------------------------------------------------------------------- /projects/software/repl.tal: -------------------------------------------------------------------------------- 1 | ( repl 2 | 3 | implemented: hardly anything 4 | 5 | yet to implement: practically everything 6 | ) 7 | 8 | ( devices ) 9 | 10 | |00 @System &vector $2 &pad $6 &r $2 &g $2 &b $2 11 | |20 @Screen &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 12 | |80 @Controller [ &vector $2 &button $1 &key $1 ] 13 | |a0 @File &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 14 | 15 | ( init ) 16 | 17 | |0100 ( -> ) 18 | @user-program 19 | ;init ;repl/fn STA2 20 | #2000 JMP2 21 | &erase-end 22 | 23 | |2000 ( -> ) 24 | &end 25 | ,repl/fn LDR2 JSR2 26 | BRK 27 | 28 | @repl [ &fn $2 &font-height $1 &font-cells $1 ] 29 | @buffer [ &cursor $2 &end $2 ] 30 | 31 | @init 32 | ( theme ) 33 | #0fa7 .System/r DEO2 34 | #0fa7 .System/g DEO2 35 | #0fa7 .System/b DEO2 36 | 37 | ( vectors ) 38 | #2000 .Screen/vector DEO2 39 | ;on-key .Controller/vector DEO2 40 | 41 | ( default function ) 42 | ;main ,repl/fn STR2 43 | 44 | ( buffer ) 45 | ;ring-buffer 46 | DUP2 ,buffer/cursor STR2 47 | ,buffer/end STR2 48 | 49 | ( clear out user-program ) 50 | ;user-program/erase-end ;user-program 51 | &clear-loop 52 | #0000 OVR2 STA2 53 | #0002 ADD2 54 | GTH2k ,&clear-loop JCN 55 | POP2 POP2 56 | 57 | ( load font ) 58 | ;font ;load-font JMP2 ( tail call ) 59 | 60 | @main ( -- ) 61 | JMP2r 62 | 63 | @on-key ( -> ) 64 | .Controller/button DEI #01 AND ,&skip JCN 65 | .Controller/key DEI 66 | DUP #e0 AND ,&append JCN 67 | DUP #08 EQU ,&backspace JCN 68 | DUP #0d EQU ,&execute JCN 69 | POP &skip BRK 70 | 71 | &append 72 | ;buffer/cursor LDA2 73 | STH2k STA 74 | STH2r INC2 ;ring-buffer ORA2 ;buffer/cursor STA2 75 | ,&draw JMP 76 | 77 | &backspace 78 | &execute 79 | DUP EOR 80 | ;buffer/cursor LDA2 81 | #0001 SUB2 ;ring-buffer ORA2 DUP2 ;buffer/cursor STA2 82 | STA 83 | 84 | &draw 85 | #0000 DUP2 .Screen/x DEO2 .Screen/y DEO2 86 | ;ring-buffer ;wrapped-write JSR2 87 | 88 | #00 ;draw-glyph JSR2 89 | BRK 90 | 91 | @load-font ( filename* -- ) 92 | DUP2 .File/name DEO2 93 | ( find end of string for suffix ) 94 | &loop 95 | INC2 96 | LDAk ,&loop JCN 97 | ( suffix is cell size ) 98 | #0001 SUB2 LDAk #0f AND ;repl/font-cells STA 99 | ( search backwards for number ) 100 | &loop2 101 | #0001 SUB2 102 | LDAk DUP #2f GTH STH #3a LTH STHr #0101 NEQ2 ,&loop2 JCN 103 | ( parse number to find font height ) 104 | #0001 STH2 105 | &loop3 106 | LDAk DUPk #2f GTH STH #3a LTH STHr #0101 NEQ2 ,&end-loop3 JCN 107 | #30 SUB STHr MULk STH ADDr #0a MUL STH POP 108 | #0001 SUB2 109 | ,&loop3 JMP 110 | &end-loop3 111 | STH2r POP ;repl/font-height STA 112 | POP 113 | POP2 114 | 115 | ;repl/font-cells LDA DUP MUL #08 MUL INC #00 .File/length DEO2 116 | ;font-data .File/load DEO2 117 | 118 | JMP2r 119 | 120 | @get-word-width ( string* -- string* width* ) 121 | DUP2 LIT2r 0000 122 | &loop 123 | LDAk DUP #20 GTH ,¬-end JCN 124 | POP 125 | POP2 STH2r 126 | JMP2r 127 | 128 | ¬-end 129 | #00 SWP ;font-data ADD2 LDA 130 | LITr 00 STH ADD2r 131 | INC2 132 | ,&loop JMP 133 | 134 | @wrapped-write ( string* -- ) 135 | LDAk ,¬-end JCN 136 | POP2 137 | JMP2r 138 | 139 | ¬-end 140 | ,get-word-width JSR .Screen/x DEI2 ADD2 .Screen/width DEI2 LTH2 ,&no-cr JCN 141 | ,cr JSR 142 | &no-cr 143 | ,write JSR 144 | ,wrapped-write JMP 145 | 146 | @cr ( -- ) 147 | #0000 .Screen/x DEO2 148 | .Screen/y DEI2 #00 ;repl/font-height LDA ADD2 .Screen/y DEO2 149 | JMP2r 150 | 151 | @write ( string* -- end-of-string* ) 152 | LDAk DUP ,¬-end JCN 153 | POP 154 | JMP2r 155 | 156 | ¬-end 157 | #00 SWP #00 ;repl/font-cells LDA MUL2k MUL2 #0008 MUL2 #0100 ADD2 ( string* char* tile* ) 158 | ;font-data ADD2 .Screen/addr DEO2 159 | #0d ,draw-glyph JSR 160 | #00 ;repl/font-cells LDA #fff8 MUL2 .Screen/y DEI2 ADD2 .Screen/y DEO2 161 | ;font-data ADD2 LDA #00 SWP .Screen/x DEI2 ADD2 .Screen/x DEO2 162 | LDAk STH 163 | INC2 164 | STHr #20 GTH ;write JCN2 165 | JMP2r 166 | 167 | @draw-glyph ( color -- ) 168 | STH 169 | ;repl/font-cells LDA 170 | &outer 171 | DUP #00 EQU ,&end-outer JCN 172 | ;repl/font-cells LDA 173 | &inner 174 | DUP #00 EQU ,&end-inner JCN 175 | STHkr .Screen/sprite DEO 176 | #0008 DUP2 177 | .Screen/x DEI2 ADD2 .Screen/x DEO2 178 | .Screen/addr DEI2 ADD2 .Screen/addr DEO2 179 | #01 SUB 180 | ,&inner JMP 181 | &end-inner 182 | POP 183 | #00 ;repl/font-cells LDA #fff8 MUL2 .Screen/x DEI2 ADD2 .Screen/x DEO2 184 | #0008 .Screen/y DEI2 ADD2 .Screen/y DEO2 185 | #01 SUB 186 | ,&outer JMP 187 | &end-outer 188 | POP 189 | POPr 190 | JMP2r 191 | 192 | @body 193 | 4927 6c6c 206d 616b 6520 6120 736f 756e 194 | 6420 7468 6174 2773 2073 6f20 616c 6f6e 195 | 6520 74 6861 7420 6e6f 206f 6e65 2063 196 | 616e 206d 6973 7320 6974 2c20 7468 6174 197 | 2077 686f 6576 6572 20 6865 6172 7320 198 | 6974 2077 696c 6c20 7765 6570 2069 6e20 199 | 7468 6569 7220 736f 756c 732c 20 616e 200 | 6420 6865 6172 7468 7320 7769 6c6c 2073 201 | 6565 6d20 7761 726d 6572 2c20 61 6e64 202 | 2062 6569 6e67 2069 6e73 6964 6520 7769 203 | 6c6c 2073 6565 6d20 6265 7474 6572 20 204 | 746f 2061 6c6c 2077 686f 2068 6561 7220 205 | 6974 2069 6e20 7468 6520 6469 7374 616e 206 | 7420 746f 776e 732e 20 $1 207 | 208 | @font 209 | "projects/fonts/venice14.uf2 $1 210 | 211 | @font-data 212 | 213 | |fe00 @ring-buffer 214 | 215 | -------------------------------------------------------------------------------- /projects/sounds/bdr1.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/bdr1.pcm -------------------------------------------------------------------------------- /projects/sounds/bdr2.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/bdr2.pcm -------------------------------------------------------------------------------- /projects/sounds/chat.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/chat.pcm -------------------------------------------------------------------------------- /projects/sounds/cym1.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/cym1.pcm -------------------------------------------------------------------------------- /projects/sounds/hhat.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/hhat.pcm -------------------------------------------------------------------------------- /projects/sounds/kck1.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/kck1.pcm -------------------------------------------------------------------------------- /projects/sounds/kck2.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/kck2.pcm -------------------------------------------------------------------------------- /projects/sounds/ohat.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/ohat.pcm -------------------------------------------------------------------------------- /projects/sounds/pad1.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/pad1.pcm -------------------------------------------------------------------------------- /projects/sounds/pad2.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/pad2.pcm -------------------------------------------------------------------------------- /projects/sounds/piano.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/piano.pcm -------------------------------------------------------------------------------- /projects/sounds/ride.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/ride.pcm -------------------------------------------------------------------------------- /projects/sounds/saw.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/saw.pcm -------------------------------------------------------------------------------- /projects/sounds/sid1.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/sid1.pcm -------------------------------------------------------------------------------- /projects/sounds/sid2.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/sid2.pcm -------------------------------------------------------------------------------- /projects/sounds/sin.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/sin.pcm -------------------------------------------------------------------------------- /projects/sounds/snr1.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/snr1.pcm -------------------------------------------------------------------------------- /projects/sounds/snr2.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/snr2.pcm -------------------------------------------------------------------------------- /projects/sounds/sqr.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/sqr.pcm -------------------------------------------------------------------------------- /projects/sounds/sub1.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/sub1.pcm -------------------------------------------------------------------------------- /projects/sounds/syn1.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/syn1.pcm -------------------------------------------------------------------------------- /projects/sounds/syn2.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/syn2.pcm -------------------------------------------------------------------------------- /projects/sounds/tri.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/tri.pcm -------------------------------------------------------------------------------- /projects/sounds/violin.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivutar/uxn/9e483ae8b129029152a2b3e1ebb6762078378e65/projects/sounds/violin.pcm -------------------------------------------------------------------------------- /src/devices/apu.c: -------------------------------------------------------------------------------- 1 | #include "../uxn.h" 2 | #include "apu.h" 3 | 4 | /* 5 | Copyright (c) 2021 Devine Lu Linvega 6 | Copyright (c) 2021 Andrew Alderwick 7 | 8 | Permission to use, copy, modify, and distribute this software for any 9 | purpose with or without fee is hereby granted, provided that the above 10 | copyright notice and this permission notice appear in all copies. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 | WITH REGARD TO THIS SOFTWARE. 14 | */ 15 | 16 | #define NOTE_PERIOD (SAMPLE_FREQUENCY * 0x4000 / 11025) 17 | #define ADSR_STEP (SAMPLE_FREQUENCY / 0xf) 18 | 19 | /* clang-format off */ 20 | 21 | static Uint32 advances[12] = { 22 | 0x80000, 0x879c8, 0x8facd, 0x9837f, 0xa1451, 0xaadc1, 23 | 0xb504f, 0xbfc88, 0xcb2ff, 0xd7450, 0xe411f, 0xf1a1c 24 | }; 25 | 26 | /* clang-format on */ 27 | 28 | static Sint32 29 | envelope(Apu *c, Uint32 age) 30 | { 31 | if(!c->r) return 0x0888; 32 | if(age < c->a) return 0x0888 * age / c->a; 33 | if(age < c->d) return 0x0444 * (2 * c->d - c->a - age) / (c->d - c->a); 34 | if(age < c->s) return 0x0444; 35 | if(age < c->r) return 0x0444 * (c->r - age) / (c->r - c->s); 36 | c->advance = 0; 37 | return 0x0000; 38 | } 39 | 40 | int 41 | apu_render(Apu *c, Sint16 *sample, Sint16 *end) 42 | { 43 | Sint32 s; 44 | if(!c->advance || !c->period) return 0; 45 | while(sample < end) { 46 | c->count += c->advance; 47 | c->i += c->count / c->period; 48 | c->count %= c->period; 49 | if(c->i >= c->len) { 50 | if(!c->repeat) { 51 | c->advance = 0; 52 | break; 53 | } 54 | c->i %= c->len; 55 | } 56 | s = (Sint8)(c->addr[c->i] + 0x80) * envelope(c, c->age++); 57 | *sample++ += s * c->volume[0] / 0x180; 58 | *sample++ += s * c->volume[1] / 0x180; 59 | } 60 | if(!c->advance) apu_finished_handler(c); 61 | return 1; 62 | } 63 | 64 | void 65 | apu_start(Apu *c, Uint16 adsr, Uint8 pitch) 66 | { 67 | if(pitch < 108 && c->len) 68 | c->advance = advances[pitch % 12] >> (8 - pitch / 12); 69 | else { 70 | c->advance = 0; 71 | return; 72 | } 73 | c->a = ADSR_STEP * (adsr >> 12); 74 | c->d = ADSR_STEP * (adsr >> 8 & 0xf) + c->a; 75 | c->s = ADSR_STEP * (adsr >> 4 & 0xf) + c->d; 76 | c->r = ADSR_STEP * (adsr >> 0 & 0xf) + c->s; 77 | c->age = 0; 78 | c->i = 0; 79 | if(c->len <= 0x100) /* single cycle mode */ 80 | c->period = NOTE_PERIOD * 337 / 2 / c->len; 81 | else /* sample repeat mode */ 82 | c->period = NOTE_PERIOD; 83 | } 84 | 85 | Uint8 86 | apu_get_vu(Apu *c) 87 | { 88 | int i; 89 | Sint32 sum[2] = {0, 0}; 90 | if(!c->advance || !c->period) return 0; 91 | for(i = 0; i < 2; ++i) { 92 | if(!c->volume[i]) continue; 93 | sum[i] = 1 + envelope(c, c->age) * c->volume[i] / 0x800; 94 | if(sum[i] > 0xf) sum[i] = 0xf; 95 | } 96 | return (sum[0] << 4) | sum[1]; 97 | } 98 | -------------------------------------------------------------------------------- /src/devices/apu.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021 Devine Lu Linvega 3 | Copyright (c) 2021 Andrew Alderwick 4 | 5 | Permission to use, copy, modify, and distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE. 11 | */ 12 | 13 | typedef unsigned int Uint32; 14 | typedef signed int Sint32; 15 | 16 | #define SAMPLE_FREQUENCY 44100 17 | 18 | typedef struct { 19 | Uint8 *addr; 20 | Uint32 count, advance, period, age, a, d, s, r; 21 | Uint16 i, len; 22 | Sint8 volume[2]; 23 | Uint8 pitch, repeat; 24 | } Apu; 25 | 26 | int apu_render(Apu *c, Sint16 *sample, Sint16 *end); 27 | void apu_start(Apu *c, Uint16 adsr, Uint8 pitch); 28 | Uint8 apu_get_vu(Apu *c); 29 | void apu_finished_handler(Apu *c); 30 | -------------------------------------------------------------------------------- /src/devices/ppu.c: -------------------------------------------------------------------------------- 1 | #include "ppu.h" 2 | 3 | /* 4 | Copyright (c) 2021 Devine Lu Linvega 5 | Copyright (c) 2021 Andrew Alderwick 6 | 7 | Permission to use, copy, modify, and distribute this software for any 8 | purpose with or without fee is hereby granted, provided that the above 9 | copyright notice and this permission notice appear in all copies. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | WITH REGARD TO THIS SOFTWARE. 13 | */ 14 | 15 | static Uint8 blending[5][16] = { 16 | {0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0}, 17 | {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}, 18 | {1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1}, 19 | {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}, 20 | {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}}; 21 | 22 | static void 23 | ppu_clear(Ppu *p) 24 | { 25 | Uint32 row, bound = p->height * p->width / 2; 26 | for(row = 0; row < bound; ++row) 27 | p->pixels[row] = 0; 28 | } 29 | 30 | Uint8 31 | ppu_set_size(Ppu *p, Uint16 width, Uint16 height) 32 | { 33 | ppu_clear(p); 34 | p->width = width; 35 | p->height = height; 36 | p->pixels = realloc(p->pixels, p->width * p->height * sizeof(Uint8) / 2); 37 | ppu_clear(p); 38 | return !!p->pixels; 39 | } 40 | 41 | Uint8 42 | ppu_read(Ppu *p, Uint16 x, Uint16 y) 43 | { 44 | if(x < p->width && y < p->height) { 45 | Uint32 row = (x + y * p->width) / 0x2; 46 | Uint8 shift = !(x & 0x1) << 2; 47 | Uint8 pix = p->pixels[row] >> shift; 48 | if(pix & 0x0c) 49 | pix = pix >> 2; 50 | return pix & 0x3; 51 | } 52 | return 0x0; 53 | } 54 | 55 | void 56 | ppu_write(Ppu *p, Uint8 layer, Uint16 x, Uint16 y, Uint8 color) 57 | { 58 | if(x < p->width && y < p->height) { 59 | Uint32 row = (x + y * p->width) / 0x2; 60 | Uint8 shift = (!(x & 0x1) << 2) + (layer << 1); 61 | Uint8 pix = p->pixels[row]; 62 | Uint8 mask = ~(0x3 << shift); 63 | Uint8 pixnew = (pix & mask) + (color << shift); 64 | if(x < p->width && y < p->height) 65 | p->pixels[row] = pixnew; 66 | if(pix != pixnew) 67 | p->reqdraw = 1; 68 | } 69 | } 70 | 71 | void 72 | ppu_1bpp(Ppu *p, Uint8 layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy) 73 | { 74 | Uint16 v, h; 75 | for(v = 0; v < 8; v++) 76 | for(h = 0; h < 8; h++) { 77 | Uint8 ch1 = (sprite[v] >> (7 - h)) & 0x1; 78 | if(ch1 || blending[4][color]) 79 | ppu_write(p, 80 | layer, 81 | x + (flipx ? 7 - h : h), 82 | y + (flipy ? 7 - v : v), 83 | blending[ch1][color]); 84 | } 85 | } 86 | 87 | void 88 | ppu_2bpp(Ppu *p, Uint8 layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy) 89 | { 90 | Uint16 v, h; 91 | for(v = 0; v < 8; v++) 92 | for(h = 0; h < 8; h++) { 93 | Uint8 ch1 = ((sprite[v] >> (7 - h)) & 0x1); 94 | Uint8 ch2 = ((sprite[v + 8] >> (7 - h)) & 0x1); 95 | Uint8 ch = ch1 + ch2 * 2; 96 | if(ch || blending[4][color]) 97 | ppu_write(p, 98 | layer, 99 | x + (flipx ? 7 - h : h), 100 | y + (flipy ? 7 - v : v), 101 | blending[ch][color]); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/devices/ppu.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | Copyright (c) 2021 Devine Lu Linvega 6 | Copyright (c) 2021 Andrew Alderwick 7 | 8 | Permission to use, copy, modify, and distribute this software for any 9 | purpose with or without fee is hereby granted, provided that the above 10 | copyright notice and this permission notice appear in all copies. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 | WITH REGARD TO THIS SOFTWARE. 14 | */ 15 | 16 | typedef unsigned char Uint8; 17 | typedef unsigned short Uint16; 18 | typedef unsigned int Uint32; 19 | 20 | typedef struct Ppu { 21 | Uint8 *pixels, reqdraw; 22 | Uint16 width, height; 23 | } Ppu; 24 | 25 | Uint8 ppu_set_size(Ppu *p, Uint16 width, Uint16 height); 26 | Uint8 ppu_read(Ppu *p, Uint16 x, Uint16 y); 27 | void ppu_write(Ppu *p, Uint8 layer, Uint16 x, Uint16 y, Uint8 color); 28 | void ppu_frame(Ppu *p); 29 | void ppu_1bpp(Ppu *p, Uint8 layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy); 30 | void ppu_2bpp(Ppu *p, Uint8 layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy); 31 | -------------------------------------------------------------------------------- /src/uxn.c: -------------------------------------------------------------------------------- 1 | #include "uxn.h" 2 | 3 | /* 4 | Copyright (u) 2021 Devine Lu Linvega 5 | Copyright (u) 2021 Andrew Alderwick 6 | 7 | Permission to use, copy, modify, and distribute this software for any 8 | purpose with or without fee is hereby granted, provided that the above 9 | copyright notice and this permission notice appear in all copies. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | WITH REGARD TO THIS SOFTWARE. 13 | */ 14 | 15 | #define MODE_SHORT 0x20 16 | #define MODE_RETURN 0x40 17 | #define MODE_KEEP 0x80 18 | 19 | #pragma mark - Operations 20 | 21 | /* clang-format off */ 22 | 23 | /* Utilities */ 24 | static void (*push)(Stack *s, Uint16 a); 25 | static Uint16 (*pop8)(Stack *s); 26 | static Uint16 (*pop)(Stack *s); 27 | static void (*poke)(Uint8 *m, Uint16 a, Uint16 b); 28 | static Uint16 (*peek)(Uint8 *m, Uint16 a); 29 | static int (*devw)(Device *d, Uint8 a, Uint16 b); 30 | static Uint16 (*devr)(Device *d, Uint8 a); 31 | static void (*warp)(Uxn *u, Uint16 a); 32 | static void (*pull)(Uxn *u); 33 | /* byte mode */ 34 | static void push8(Stack *s, Uint16 a) { if(s->ptr == 0xff) { s->error = 2; return; } s->dat[s->ptr++] = a; } 35 | static Uint16 pop8k(Stack *s) { if(s->kptr == 0) { s->error = 1; return 0; } return s->dat[--s->kptr]; } 36 | static Uint16 pop8d(Stack *s) { if(s->ptr == 0) { s->error = 1; return 0; } return s->dat[--s->ptr]; } 37 | static void poke8(Uint8 *m, Uint16 a, Uint16 b) { m[a] = b; } 38 | static Uint16 peek8(Uint8 *m, Uint16 a) { return m[a]; } 39 | static int devw8(Device *d, Uint8 a, Uint16 b) { d->dat[a & 0xf] = b; return d->talk(d, a & 0x0f, 1); } 40 | static Uint16 devr8(Device *d, Uint8 a) { d->talk(d, a & 0x0f, 0); return d->dat[a & 0xf]; } 41 | static void warp8(Uxn *u, Uint16 a){ u->ram.ptr += (Sint8)a; } 42 | static void pull8(Uxn *u){ push8(u->src, peek8(u->ram.dat, u->ram.ptr++)); } 43 | /* short mode */ 44 | static void push16(Stack *s, Uint16 a) { push8(s, a >> 8); push8(s, a); } 45 | static Uint16 pop16(Stack *s) { Uint8 a = pop8(s), b = pop8(s); return a + (b << 8); } 46 | void poke16(Uint8 *m, Uint16 a, Uint16 b) { poke8(m, a, b >> 8); poke8(m, a + 1, b); } 47 | Uint16 peek16(Uint8 *m, Uint16 a) { return (peek8(m, a) << 8) + peek8(m, a + 1); } 48 | static int devw16(Device *d, Uint8 a, Uint16 b) { return devw8(d, a, b >> 8) && devw8(d, a + 1, b); } 49 | static Uint16 devr16(Device *d, Uint8 a) { return (devr8(d, a) << 8) + devr8(d, a + 1); } 50 | static void warp16(Uxn *u, Uint16 a){ u->ram.ptr = a; } 51 | static void pull16(Uxn *u){ push16(u->src, peek16(u->ram.dat, u->ram.ptr++)); u->ram.ptr++; } 52 | 53 | #pragma mark - Core 54 | 55 | int 56 | uxn_eval(Uxn *u, Uint16 vec) 57 | { 58 | Uint8 instr; 59 | Uint16 a,b,c; 60 | if(!vec || u->dev[0].dat[0xf]) 61 | return 0; 62 | u->ram.ptr = vec; 63 | if(u->wst.ptr > 0xf8) u->wst.ptr = 0xf8; 64 | while((instr = u->ram.dat[u->ram.ptr++])) { 65 | /* Return Mode */ 66 | if(instr & MODE_RETURN) { 67 | u->src = &u->rst; 68 | u->dst = &u->wst; 69 | } else { 70 | u->src = &u->wst; 71 | u->dst = &u->rst; 72 | } 73 | /* Keep Mode */ 74 | if(instr & MODE_KEEP) { 75 | pop8 = pop8k; 76 | u->src->kptr = u->src->ptr; 77 | } else { 78 | pop8 = pop8d; 79 | } 80 | /* Short Mode */ 81 | if(instr & MODE_SHORT) { 82 | push = push16; pop = pop16; 83 | poke = poke16; peek = peek16; 84 | devw = devw16; devr = devr16; 85 | warp = warp16; pull = pull16; 86 | } else { 87 | push = push8; pop = pop8; 88 | poke = poke8; peek = peek8; 89 | devw = devw8; devr = devr8; 90 | warp = warp8; pull = pull8; 91 | } 92 | switch(instr & 0x1f){ 93 | /* Stack */ 94 | case 0x00: /* LIT */ pull(u); break; 95 | case 0x01: /* INC */ a = pop(u->src); push(u->src, a + 1); break; 96 | case 0x02: /* POP */ pop(u->src); break; 97 | case 0x03: /* DUP */ a = pop(u->src); push(u->src, a); push(u->src, a); break; 98 | case 0x04: /* NIP */ a = pop(u->src); pop(u->src); push(u->src, a); break; 99 | case 0x05: /* SWP */ a = pop(u->src), b = pop(u->src); push(u->src, a); push(u->src, b); break; 100 | case 0x06: /* OVR */ a = pop(u->src), b = pop(u->src); push(u->src, b); push(u->src, a); push(u->src, b); break; 101 | case 0x07: /* ROT */ a = pop(u->src), b = pop(u->src), c = pop(u->src); push(u->src, b); push(u->src, a); push(u->src, c); break; 102 | /* Logic */ 103 | case 0x08: /* EQU */ a = pop(u->src), b = pop(u->src); push8(u->src, b == a); break; 104 | case 0x09: /* NEQ */ a = pop(u->src), b = pop(u->src); push8(u->src, b != a); break; 105 | case 0x0a: /* GTH */ a = pop(u->src), b = pop(u->src); push8(u->src, b > a); break; 106 | case 0x0b: /* LTH */ a = pop(u->src), b = pop(u->src); push8(u->src, b < a); break; 107 | case 0x0c: /* JMP */ a = pop(u->src); warp(u, a); break; 108 | case 0x0d: /* JNZ */ a = pop(u->src); if(pop8(u->src)) warp(u, a); break; 109 | case 0x0e: /* JSR */ a = pop(u->src); push16(u->dst, u->ram.ptr); warp(u, a); break; 110 | case 0x0f: /* STH */ a = pop(u->src); push(u->dst, a); break; 111 | /* Memory */ 112 | case 0x10: /* LDZ */ a = pop8(u->src); push(u->src, peek(u->ram.dat, a)); break; 113 | case 0x11: /* STZ */ a = pop8(u->src); b = pop(u->src); poke(u->ram.dat, a, b); break; 114 | case 0x12: /* LDR */ a = pop8(u->src); push(u->src, peek(u->ram.dat, u->ram.ptr + (Sint8)a)); break; 115 | case 0x13: /* STR */ a = pop8(u->src); b = pop(u->src); poke(u->ram.dat, u->ram.ptr + (Sint8)a, b); break; 116 | case 0x14: /* LDA */ a = pop16(u->src); push(u->src, peek(u->ram.dat, a)); break; 117 | case 0x15: /* STA */ a = pop16(u->src); b = pop(u->src); poke(u->ram.dat, a, b); break; 118 | case 0x16: /* DEI */ a = pop8(u->src); push(u->src, devr(&u->dev[a >> 4], a)); break; 119 | case 0x17: /* DEO */ a = pop8(u->src); b = pop(u->src); if (!devw(&u->dev[a >> 4], a, b)) return 1; break; 120 | /* Arithmetic */ 121 | case 0x18: /* ADD */ a = pop(u->src), b = pop(u->src); push(u->src, b + a); break; 122 | case 0x19: /* SUB */ a = pop(u->src), b = pop(u->src); push(u->src, b - a); break; 123 | case 0x1a: /* MUL */ a = pop(u->src), b = pop(u->src); push(u->src, b * a); break; 124 | case 0x1b: /* DIV */ a = pop(u->src), b = pop(u->src); if(a == 0) { u->src->error = 3; a = 1; } push(u->src, b / a); break; 125 | case 0x1c: /* AND */ a = pop(u->src), b = pop(u->src); push(u->src, b & a); break; 126 | case 0x1d: /* ORA */ a = pop(u->src), b = pop(u->src); push(u->src, b | a); break; 127 | case 0x1e: /* EOR */ a = pop(u->src), b = pop(u->src); push(u->src, b ^ a); break; 128 | case 0x1f: /* SFT */ a = pop8(u->src), b = pop(u->src); push(u->src, b >> (a & 0x0f) << ((a & 0xf0) >> 4)); break; 129 | } 130 | if(u->wst.error) return uxn_halt(u, u->wst.error, "Working-stack", instr); 131 | if(u->rst.error) return uxn_halt(u, u->rst.error, "Return-stack", instr); 132 | } 133 | return 1; 134 | } 135 | 136 | /* clang-format on */ 137 | 138 | int 139 | uxn_boot(Uxn *u) 140 | { 141 | unsigned int i; 142 | char *cptr = (char *)u; 143 | for(i = 0; i < sizeof(*u); i++) 144 | cptr[i] = 0x00; 145 | return 1; 146 | } 147 | 148 | Device * 149 | uxn_port(Uxn *u, Uint8 id, int (*talkfn)(Device *d, Uint8 b0, Uint8 w)) 150 | { 151 | Device *d = &u->dev[id]; 152 | d->addr = id * 0x10; 153 | d->u = u; 154 | d->mem = u->ram.dat; 155 | d->talk = talkfn; 156 | return d; 157 | } 158 | -------------------------------------------------------------------------------- /src/uxn.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021 Devine Lu Linvega 3 | 4 | Permission to use, copy, modify, and distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE. 10 | */ 11 | 12 | typedef unsigned char Uint8; 13 | typedef signed char Sint8; 14 | typedef unsigned short Uint16; 15 | typedef signed short Sint16; 16 | 17 | #define PAGE_PROGRAM 0x0100 18 | 19 | typedef struct { 20 | Uint8 ptr, kptr, error; 21 | Uint8 dat[256]; 22 | } Stack; 23 | 24 | typedef struct { 25 | Uint16 ptr; 26 | Uint8 dat[65536]; 27 | } Memory; 28 | 29 | typedef struct Device { 30 | struct Uxn *u; 31 | Uint8 addr, dat[16], *mem; 32 | Uint16 vector; 33 | int (*talk)(struct Device *d, Uint8, Uint8); 34 | } Device; 35 | 36 | typedef struct Uxn { 37 | Stack wst, rst, *src, *dst; 38 | Memory ram; 39 | Device dev[16]; 40 | } Uxn; 41 | 42 | struct Uxn; 43 | 44 | void poke16(Uint8 *m, Uint16 a, Uint16 b); 45 | Uint16 peek16(Uint8 *m, Uint16 a); 46 | 47 | int uxn_boot(Uxn *c); 48 | int uxn_eval(Uxn *u, Uint16 vec); 49 | int uxn_halt(Uxn *u, Uint8 error, char *name, int id); 50 | Device *uxn_port(Uxn *u, Uint8 id, int (*talkfn)(Device *, Uint8, Uint8)); 51 | -------------------------------------------------------------------------------- /src/uxncli.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "uxn.h" 6 | 7 | /* 8 | Copyright (c) 2021 Devine Lu Linvega 9 | 10 | Permission to use, copy, modify, and distribute this software for any 11 | purpose with or without fee is hereby granted, provided that the above 12 | copyright notice and this permission notice appear in all copies. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 15 | WITH REGARD TO THIS SOFTWARE. 16 | */ 17 | 18 | #pragma mark - Core 19 | 20 | static Device *devsystem, *devconsole; 21 | 22 | static int 23 | error(char *msg, const char *err) 24 | { 25 | fprintf(stderr, "Error %s: %s\n", msg, err); 26 | return 0; 27 | } 28 | 29 | static void 30 | inspect(Stack *s, char *name) 31 | { 32 | Uint8 x, y; 33 | fprintf(stderr, "\n%s\n", name); 34 | for(y = 0; y < 0x04; ++y) { 35 | for(x = 0; x < 0x08; ++x) { 36 | Uint8 p = y * 0x08 + x; 37 | fprintf(stderr, 38 | p == s->ptr ? "[%02x]" : " %02x ", 39 | s->dat[p]); 40 | } 41 | fprintf(stderr, "\n"); 42 | } 43 | } 44 | 45 | #pragma mark - Devices 46 | 47 | static int 48 | system_talk(Device *d, Uint8 b0, Uint8 w) 49 | { 50 | if(!w) { /* read */ 51 | switch(b0) { 52 | case 0x2: d->dat[0x2] = d->u->wst.ptr; break; 53 | case 0x3: d->dat[0x3] = d->u->rst.ptr; break; 54 | } 55 | } else { /* write */ 56 | switch(b0) { 57 | case 0x2: d->u->wst.ptr = d->dat[0x2]; break; 58 | case 0x3: d->u->rst.ptr = d->dat[0x3]; break; 59 | case 0xe: 60 | inspect(&d->u->wst, "Working-stack"); 61 | inspect(&d->u->rst, "Return-stack"); 62 | break; 63 | case 0xf: return 0; 64 | } 65 | } 66 | return 1; 67 | } 68 | 69 | static int 70 | console_talk(Device *d, Uint8 b0, Uint8 w) 71 | { 72 | if(w && b0 > 0x7) 73 | write(b0 - 0x7, (char *)&d->dat[b0], 1); 74 | return 1; 75 | } 76 | 77 | static int 78 | file_talk(Device *d, Uint8 b0, Uint8 w) 79 | { 80 | Uint8 read = b0 == 0xd; 81 | if(w && (read || b0 == 0xf)) { 82 | char *name = (char *)&d->mem[peek16(d->dat, 0x8)]; 83 | Uint16 result = 0, length = peek16(d->dat, 0xa); 84 | long offset = (peek16(d->dat, 0x4) << 16) + peek16(d->dat, 0x6); 85 | Uint16 addr = peek16(d->dat, b0 - 1); 86 | FILE *f = fopen(name, read ? "rb" : (offset ? "ab" : "wb")); 87 | if(f) { 88 | if(fseek(f, offset, SEEK_SET) != -1) 89 | result = read ? fread(&d->mem[addr], 1, length, f) : fwrite(&d->mem[addr], 1, length, f); 90 | fclose(f); 91 | } 92 | poke16(d->dat, 0x2, result); 93 | } 94 | return 1; 95 | } 96 | 97 | static int 98 | datetime_talk(Device *d, Uint8 b0, Uint8 w) 99 | { 100 | time_t seconds = time(NULL); 101 | struct tm *t = localtime(&seconds); 102 | t->tm_year += 1900; 103 | poke16(d->dat, 0x0, t->tm_year); 104 | d->dat[0x2] = t->tm_mon; 105 | d->dat[0x3] = t->tm_mday; 106 | d->dat[0x4] = t->tm_hour; 107 | d->dat[0x5] = t->tm_min; 108 | d->dat[0x6] = t->tm_sec; 109 | d->dat[0x7] = t->tm_wday; 110 | poke16(d->dat, 0x08, t->tm_yday); 111 | d->dat[0xa] = t->tm_isdst; 112 | (void)b0; 113 | (void)w; 114 | return 1; 115 | } 116 | 117 | static int 118 | nil_talk(Device *d, Uint8 b0, Uint8 w) 119 | { 120 | (void)d; 121 | (void)b0; 122 | (void)w; 123 | return 1; 124 | } 125 | 126 | #pragma mark - Generics 127 | 128 | static const char *errors[] = {"underflow", "overflow", "division by zero"}; 129 | 130 | int 131 | uxn_halt(Uxn *u, Uint8 error, char *name, int id) 132 | { 133 | fprintf(stderr, "Halted: %s %s#%04x, at 0x%04x\n", name, errors[error - 1], id, u->ram.ptr); 134 | return 0; 135 | } 136 | 137 | static void 138 | run(Uxn *u) 139 | { 140 | Uint16 vec = PAGE_PROGRAM; 141 | uxn_eval(u, vec); 142 | while((!u->dev[0].dat[0xf]) && (read(0, &devconsole->dat[0x2], 1) > 0)) { 143 | vec = peek16(devconsole->dat, 0); 144 | if(!vec) vec = u->ram.ptr; /* continue after last BRK */ 145 | uxn_eval(u, vec); 146 | } 147 | } 148 | 149 | static int 150 | load(Uxn *u, char *filepath) 151 | { 152 | FILE *f; 153 | if(!(f = fopen(filepath, "rb"))) 154 | return 0; 155 | fread(u->ram.dat + PAGE_PROGRAM, sizeof(u->ram.dat) - PAGE_PROGRAM, 1, f); 156 | fprintf(stderr, "Loaded %s\n", filepath); 157 | return 1; 158 | } 159 | 160 | int 161 | main(int argc, char **argv) 162 | { 163 | Uxn u; 164 | 165 | if(argc < 2) 166 | return error("Input", "Missing"); 167 | if(!uxn_boot(&u)) 168 | return error("Boot", "Failed"); 169 | if(!load(&u, argv[1])) 170 | return error("Load", "Failed"); 171 | 172 | /* system */ devsystem = uxn_port(&u, 0x0, system_talk); 173 | /* console */ devconsole = uxn_port(&u, 0x1, console_talk); 174 | /* empty */ uxn_port(&u, 0x2, nil_talk); 175 | /* empty */ uxn_port(&u, 0x3, nil_talk); 176 | /* empty */ uxn_port(&u, 0x4, nil_talk); 177 | /* empty */ uxn_port(&u, 0x5, nil_talk); 178 | /* empty */ uxn_port(&u, 0x6, nil_talk); 179 | /* empty */ uxn_port(&u, 0x7, nil_talk); 180 | /* empty */ uxn_port(&u, 0x8, nil_talk); 181 | /* empty */ uxn_port(&u, 0x9, nil_talk); 182 | /* file */ uxn_port(&u, 0xa, file_talk); 183 | /* datetime */ uxn_port(&u, 0xb, datetime_talk); 184 | /* empty */ uxn_port(&u, 0xc, nil_talk); 185 | /* empty */ uxn_port(&u, 0xd, nil_talk); 186 | /* empty */ uxn_port(&u, 0xe, nil_talk); 187 | /* empty */ uxn_port(&u, 0xf, nil_talk); 188 | 189 | run(&u); 190 | 191 | return 0; 192 | } 193 | --------------------------------------------------------------------------------