december adventure 2023 the goal is to work on something small every day in december. my goal: get unix extensions to uxn's console device working with uxn11 in particular here are some of the things i plan to work on: * making sure the console.txt spec is clear and complete * getting uxn11 (and uxncli) correctly implementing the spec * writing demo and test programs * updating determ (term.tal) to use the console device * updating femto to use the console device * implement uxntal bindings for some useful tools: - ispell - netcat / stunnel - links / hget - mpv / mpg123 my uxn11 branch is here ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡ december 2023 calendar day 1 day 9 day 17 day 25 day 2 day 10 day 18 day 26 day 3 day 11 day 19 day 27 day 4 day 12 day 20 day 28 day 5 day 13 day 21 day 29 day 6 day 14 day 22 day 30 day 7 day 15 day 23 day 31 day 8 day 16 day 24 ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡ dec 1: fixing bugs i fixed some bugs preventing the make demo from running correctly. additionally i started looking at fleshing out the ispell demo. dec 2: more bugs and a spec change i spent a couple of hours hitting some issues with the ispell demo. this is the first test that actually reads/writes data so i expected some problems. it turns out there were numerous issues: - delayed initialization was losing process information - file descriptor issues - writing to the wrong port (0x2 instead of 0x4) one thing i realized is that everything should use the stdin port (0x2). proc-get (0x4) and host-get (0x5) don't really have a point, since they all happen on the same vector (0x2) and the type port (0x7) already makes it clear what type of data we have. so i'm going to update the spec so that all reads are from stdin (0x2). that will simplify the console.c code, reduce user errors, and also simplify porting determ a bit. (but all those updates will have to wait until tomorrow.) dec 3: ispell is working! after finding even more bugs (shocking, i know) i have the ispell demo completely working: ispell.tal the basic idea is that it reads a line from stdin and passes it to ispell. for example: $ uxncli ispell.rom >hello hello 1 >helo helo 0 > note that is is demo quality code. if you type a bunch of words on one line it may behave weirdly (e.g. messed up formatting). but it does show off bi-directional pipes from within a uxn process. hurrah! i also combined the stdin, proc-get, and host-get ports as i mentioned, and updated the spec: console.txt anyway, that's an end to my adventures for the day. be well! dec 4: snow day i was pretty tired so i didn't do too much. dec 5: femto i ported the femto editor to the subprocess code. even though it runs using uxncli it benefits from the changes. in particular, we previously used a wrapper to run stty raw -echo to put the terminal in raw mode before launching the ROM. now we can make the same call as a child process which removes the need to use any wrapper. (i also fixed a small femto bug.) one of the goals of using subprocesses from uxn is to eliminate the need for external wrappers and launchers. now that femto is working, the next step will be porting determ and getting that to run in a stand-alone way (as well as features like using the SHELL environment variable). beyond terminal emulation, this would also make it possible for programs to do various kinds of networking without needing an external wrapper or driver program. (they would still need some kind of program such as netcat but they could launch it themselves.) dec 6: determ the determ terminal emulator (term.tal) is working! this ROM provided the biggest impetus for implementing subprocess support, since it requires a lot of things that varvara can't usually do: - allocate a PTY - manage terminal attributes - fork a child process - set environment variables most of the real work was porting the ROM to use Console/proc-get instead of Console/stdin. after spending awhile tracking down one last bug we got the terminal launching! one thing i noticed yesterday is that we could probably compress the range of Console/type values we are using. currently we use up to 0x83 but it would be easy to reduce that to 0x1b for example. another thing i need to do is decide whether i need to add any host actions to set more terminal attributes. it's possible that running stty will be enough but i'm not totally sure -- it might be more straightforward to do it in code; for one thing it would make it easier for the terminal to be resized dynamically. we'll see. beyond that i think we're ready to start making a patch for upstream uxn11! be well! dec 7: bug hunt for awhile now there have been some highlighting bugs in determ when you use the pointer to select text. i'm not sure exactly when they started, but they were exacerbated when the blending modes were changed. after looking into it a bit more, i'm pretty sure i see what is going on: - everything is drawn to the fg layer (contradicting my memory) - clearing and redrawing the pointer wipes out overlapping selections - there's a 4 pixel inaccuracy with some addressing. at one point i was experimenting with "backgrounds" for determ and i think maybe i inadvertently changed how drawing works and forgot to revert. that would explain why the mouse expects to be able to safely clear and redraw. i think i will probably try to go back to doing most drawing on the bg layer and reserve the fg for pointers, menus, etc. dec 8: rest day other than giving a bit of advice on the #DecemberAdventure hashtag i didn't to any adventuring today. dec 9: lots of small fixes i spend a bit of time fixing some quality of life issues: - added -2x and -3x arguments to uxn11 to start zoomed in - fixed the selection but that had been plaguing determ - added code in uxn11 to update width/height when windows resize that last one would allow uxn ROMs to notice that the screen has changed sizes by reading Screen/width and Screen/height and comparing them to previous values. i got the idea after accidentally resizing determ and wishing it actually "worked" properly. (update: the resize detection code has some problems. it seems to break rescaling. i'm not too worried -- i think i'm just using Xlib incorrectly. it should be easy to fix later.) i need to finalize the console spec and send neauoire a patch but i'm waffling. Console/type uses 256 distinct sentinel values and the spec is adding a bunch of new ranges: - 0x05 - 0x07 (host response, host response end, stdin end) - 0x20 - 0x23 (child N sent data) - 0x40 - 0x43 (child N data end) - 0x80 - 0x83 (child N exited) there are some convenient aspects to this but arguably just compressing the last ranges down into 0x10 - 0x1c would be a bit kinder to future extensions. if i want to change it then now is the time to do it. i'm just feeling indecisive. i wanted to produce a cool demo video but it turns out that currently femto can't run within determ. i think the issue is that the pty that determ runs in is having trouble being put into "raw" mode by femto. dec 10: another break nothing significant to report today. dec 11: mpg123 detour i got interested in the idea of writing an mp3 player for varvara, and started investigating options. it turns out that mpg123 has a really nice generic command interface using stdin and stdout. basically you enter a command (terminated by a newline), and it emits one or more lines, each of which starts with @. here's an example session from running mpg123 -R. input to the process starts with > and output from the process starts with <. < @R MPG123 (ThOr) v10 ; startup banner > L spectra.mp3 ; load command < @I { ; start id3 < @I ID3v2.title:Spectra ; song title < @I ID3v2.artist:Chipzel ; artist name < @I ID3v2.album:Spectra ; album title < @I ID3v2.year:2013 ; song year < @I ... ; other info possible < @I } ; end id3 < @P 2 ; song playing < @S 1.0 3 44100 Joint-Stereo 2 1044 2 0 0 0 320 0 1 ; sound info < @F 0 9052 0.00 236.46 ; first frame output < @F ... ; lots of frames of output < @F 9051 1 236.43 0.03 ; last frame output < @P 3 ; song ended < @P 0 ; stopped i got far enough to convince myself this was possible and it would work. that said it's a bit of a distraction so it's probably something i will be coming back to later. dec 12: no idea? if i did anything on this day i have no recollection of it. dec 13: preparing a patch against uxn11 i took some time to create a draft patch against the mainline uxn11. looking at the diff as a whole exposed some things that needed a bit more clean up or documentation. that said, i was overall happy with how the patch looked: 5 paths 17 groups, +204 lines (+353 -149) (this doesn't include the design doc, demo programs, or my own ROMs.) dec 14: it's looking ready this was a big one! i did most of the clean up tasks i noticed the previous day, and also fixed a bunch of bugs across console.c, term.tal, and femto.tal: - getting and setting environment variables was broken - calling stty from subshells was not reliable - killing a non-running subprocess could have strange effects - determ was failing to respond to DSR queries correctly - femto was not able to run inside determ - femto was not exiting cleanly at this point running determ and femto via uxn11 and uxncli is just as good (or better) than using the old wrapper scripts. obligatory screenshots and video: uxn11-15.mp4 (9.5 MB, 1:28, has music) (it's worth noting that there are some graphical glitches in the video. when i started determ i aimed to just implement TERM=ansi, but it turns out many programs aren't 100% compatible with "pure" ansi terminals. so i pivoted to quasi-vt100 compatibility but am still missing some fairly critical vt-100 features.) dec 15: draft patch for uxn11 all my uxn11 changes in one place. mostly i wanted to see all the changes in one place and get a sense of how reasonable (or unreasonable) it might look. i was pretty pleased with the result! dec 17: took saturday off wasn't feeling motivated, took a break. dec 17: also took sunday off still wasn't feeling motivated. continued my break. dec 18: uuid-based extensions for uxn11 one problem with using an enhanced console only available in uxn11 is that it is incompatible with the current approach of using stdin and stdout with wrapper scripts. this means i will either need to drop support for uxnemu or else maintain two versions of my ROMs. one idea i had was to include support for both approaches, and then choose at runtime based on the emulator version. however, there is currently not a good way for ROMs to figure this out. while talking with neauoire about this they reminded me of the extensions proposed by zzo38. these use the expansion port to send and receive information about optional device features. perfect! currently only the uxn38 emulator supports UUID-based extensions, but adding them to uxn11 ended up being pretty easy. i have also updated the specification to describe their use with the console. dec 19: another pause took a bit of a break. dec 20: still paused still was not feeling adventurous. dec 21: uxntal support for linguist one weird thing about respositories with uxntal code is that sites like github/codeberg/etc. don't know about the language, so the language summary ends up listing other languages like shell, lua, python, etc. instead. i finally got tired of this state of affairs and submitted a PR to the linguist project to add uxntal support. this mostly involved reading contributor guidelines, looking at other PRs, and installing a bunch of linguist dependencies. linguist uses textmate grammars for syntax highlighting but fortunately there's already an implementation for uxn. anyway, the pull request is here. dec 22: pr updates took care of some minor issues noted on the PR. i expect nothing will be merged before 2024 but i'm hopeful that soon we'll have uxntal support in a linguist release. dec 23: top-secret project i paused my adventure to work on a top secret project. dec 24: top-secret project (continued) the top secret project continued to take all my time. dec 25: top-secret project revealed without sharing any actual details about it, the top-secret project was related to a christmas gift for kate. dec 26: post-holiday break after all the chaos of the holidays it was nice to take a break. dec 27: break still taking a break (i was hoping to restore some energy for future work but (spoiler alert) i ended up getting sick and not doing anything else for the rest of the month. dec 28: illness i got sick today. dec 29: very sick even more sick today. dec 30: still very sick still very sick today. dec 31: starting to recover starting to feel better, but still sick. so in conclusion: my adventure ended in an incomplete state, partially due to holiday chaos and partially due to illness. still, i had a good time and did get a lot done! thanks, eli!