Merge remote-tracking branch 'origin/main'

This commit is contained in:
~d6 2025-02-17 14:23:42 -05:00
commit 7dc1b62b7b
5 changed files with 381 additions and 96 deletions

View File

@ -22,10 +22,10 @@
%cr { #0d18 DEO }
%crlf { cr nl }
%ansi { #1b18 DEO #5b18 DEO }
%alternate-buffer-on { ( \e[?1049h )
ansi #3f18 DEO #3118 DEO #3018 DEO #3418 DEO #3918 DEO #6818 DEO }
%alternate-buffer-off { ( \e[?1049l )
ansi #3f18 DEO #3118 DEO #3018 DEO #3418 DEO #3918 DEO #6c18 DEO }
( \e[?1049h )
%alternate-buffer-on { ansi #3f18 DEO #3118 DEO #3018 DEO #3418 DEO #3918 DEO #6818 DEO }
( \e[?1049l )
%alternate-buffer-off { ansi #3f18 DEO #3118 DEO #3018 DEO #3418 DEO #3918 DEO #6c18 DEO }
( emit macros )
( )
@ -732,6 +732,7 @@
( execute a search, using the given search string )
@do-search ( -> )
;tmp LDA ?{ !return } ( ensure non-empty search string )
.cursor/row LDZ2 .searching/orig-row STZ2
.cursor/col LDZ2 .searching/orig-col STZ2
#0000 .searching/regex STZ2
@ -752,6 +753,7 @@
( )
( TODO: handle invalid regular expressions that fail to compile )
@do-regex-search ( -> )
;tmp LDA ?{ !return } ( ensure non-empty search string )
cur-pos DUP2 .searching/start STZ2 .searching/end STZ2
.cursor/row LDZ2 .searching/orig-row STZ2
.cursor/col LDZ2 .searching/orig-col STZ2

251
tar.tal
View File

@ -10,7 +10,6 @@
( - handle 'L' entries )
( - support creating archives )
( - arg validation should depend on mode )
( - validate checksums )
( - better error messages on unsupported files, e.g. symlinks )
( - better usage message )
( - support using "-" for stdin/stdout? )
@ -28,24 +27,33 @@
@panic ( -> $exit )
#010e DEO #010f DEO BRK
@print-usage ( -> )
;usage1 print ;usage2 !print
( handle all provided command-line arguments )
@arg-callback ( -> )
;arg/count LDA
DUP #00 EQU ?&missing-mode
DUP #01 EQU ?&missing-file
#02 GTH ?&toomany !run
&missing-mode ;missing-mode !&error
&missing-file ;missing-filename !&error
&toomany ;too-many-arguments
&error print ;usage print #01 !exit
DUP #00 GTH ?{ POP ;missing-mode !handle-error }
DUP #01 GTH ?{ POP ;missing-filename !handle-error }
POP !run
@error-toomany ( -> BRK )
;too-many-arguments !handle-error
@error-noinput ( -> BRK )
;no-input-arguments !handle-error
@handle-error ( ;msg -> BRK )
print print-usage #01 !exit
( run the program )
@run ( -> BRK )
#01 arg/read .File1/name DEO2
#00 arg/read LDA
DUP LIT "t NEQ ?{ list-entries #00 !exit }
DUP LIT "x NEQ ?{ expand-entries #00 !exit }
POP ;invalid-mode print ;usage print #00 !exit
DUP LIT "c NEQ ?{ POP create-archive #00 !exit }
DUP LIT "t NEQ ?{ POP list-entries #00 !exit }
DUP LIT "x NEQ ?{ POP expand-entries #00 !exit }
POP ;invalid-mode print print-usage #00 !exit
( exit normally )
@exit ( code^ -> BRK )
@ -67,20 +75,72 @@
LDAk #18 DEO INC2 GTH2k ?&loop ( limit* s+1* )
&done POP2 POP2 JMP2r ( )
@print-filename ( -> )
;header/filename sanitize-path #0064 lprint #0a18 DEO JMP2r
@print-long ( hi* lo* -> )
dump-long #0a18 DEO JMP2r
( read 512 bytes of header for the next tar entry. )
( assumes .File1/name is already set. )
@read-header ( -> ok^ )
#0200 .File1/len DEO2
;header .File1/r DEO2
( TODO validate checksum )
.File1/ok DEI2 #0200 EQU2 JMP2r
@validate-checksum ( -> ok^ )
;header/checksum load-octal6 ( chi* clo* )
STH2k SWP2 STH2k SWP2 ( chi* clo* [clo* chi*] )
;u-sum compute-sum ( chi* clo* uhi* ulo* [clo* chi*] )
u32-eq ?&ok1 ( [clo* chi*] )
STH2r STH2r ;s-sum compute-sum ( chi* clo* shi* slo* )
u32-eq ?&ok2 ( )
;invalid-checksum print ( ; error message )
print-filename ( ; filename of affected entry )
;expected print ( ; "expected: " )
;header/checksum load-octal6 print-long ( ; expected checksum )
;found print ( ; "found: " )
;u-sum compute-sum print-long ( ; found checksum )
#00 JMP2r ( 0^ )
&ok1 POP2r POP2r &ok2 #01 JMP2r ( 1^ )
( maximum checksum is 0001fe00 but in practice )
( almost all checksums will fit in 16-bits )
@compute-sum ( fn* -> sum0* sum1* )
STH2 ;header/checksum ;header STH2kr JSR2 ( n0* [fn*] )
#0100 ADD2 ;uheader/end ;header/type STH2r JSR2 ( n1* n2* )
OVR2 ADD2 GTH2k #00 SWP ( n1* sum* carry* )
ROT2 POP2 SWP2 JMP2r ( carry* sum* )
@u32-eq ( xhi* xlo* yhi* ylo* -> bool^ )
ROT2 EQU2 STH EQU2 STHr AND JMP2r
( return 16-bit checksum )
( technically it should be 17-bit. for simplicity we'll )
( just check the lower 16-bits. )
@u-sum ( limit* start* -> sum* )
LIT2r 0000 ( limit* start* [sum*] )
&loop LDAk LITr 00 STH ( limit* start* [sum* n*] )
ADD2r INC2 GTH2k ?&loop ( limit* pos+1* [sum+n*] )
POP2 POP2 STH2r JMP2r ( sum* )
( similar to unsigned-sum but treats 8-bit ascii differently )
( mostly only used for compatibility with old tar files )
@s-sum ( limit* start* -> sum* )
LIT2r 0000 ( limit* start* [sum*] )
&loop LDAk ( limit* start* c^ [sum*] )
DUP #07 SFT #ff MUL SWP STH2 ( limit* start* [sum* n*] )
ADD2r INC2 GTH2k ?&loop ( limit* pos+1* [sum+n*] )
POP2 POP2 STH2r JMP2r ( sum* )
( list all the entries in the tar archive )
@list-entries ( -> )
;arg/count LDA #02 GTH ?error-toomany
read-header ?{ JMP2r }
;header/filename LDA ?&non-null
#800f DEO BRK
&non-null
validate-checksum ( )
;header/type LDA ( type^ )
DUP #00 EQU ?list-file ( type^ )
DUP LIT "0 EQU ?list-file ( type^ )
@ -104,8 +164,7 @@
;unsupported print
#18 DEO #2018 DEO
;header/size load-octal11 dump-longer #2018 DEO
;header/filename sanitize-path
#0064 lprint #0a18 DEO
print-filename
;header/size load-octal11 round-up-to-512 skip !list-entries
( verbose file entry listing )
@ -113,7 +172,7 @@
POP
LIT "f #18 DEO #2018 DEO
;header/size load-octal11 dump-longer #2018 DEO
;header/filename #0064 lprint #0a18 DEO
print-filename
;header/size load-octal11 round-up-to-512 skip !list-entries
( verbose directory entry listing )
@ -121,11 +180,12 @@
POP
LIT "d #18 DEO #2018 DEO
;header/size load-octal11 dump-longer #2018 DEO
;header/filename #0064 lprint #0a18 DEO
print-filename
!list-entries
( expand a .tar archive in the current working directory )
@expand-entries ( -> )
;arg/count LDA #02 GTH ?error-toomany
read-header ?{ JMP2r }
;header/filename LDA ?&non-null
#800f DEO BRK
@ -146,16 +206,14 @@
@expand-file ( type^ -> )
POP
;header/filename sanitize-path
DUP2 #0064 lprint #0a18 DEO
print-filename
.File2/name DEO2
;header/size load-octal11 STH2k write
STH2r remainder-512 skip-lo !expand-entries
@expand-dir ( type^ -> )
POP
;header/filename sanitize-path
DUP2 #0064 lprint #0a18 DEO
print-filename
.File2/name DEO2
#0004 .File2/len DEO2
#0001 .File2/w DEO2
@ -164,13 +222,130 @@
@expand-unsupported ( type^ -> )
;unsupported print
#18 DEO LIT2 ": 18 DEO #2018 DEO
;header/filename sanitize-path
#0064 lprint #0a18 DEO
print-filename
;header/size load-octal11 round-up-to-512 skip !expand-entries
( src and dst should be paths )
@compress-entries ( src* dst* -> )
POP2 POP2 JMP2r
@create-archive ( -> )
;arg/count LDA #03 LTH ?error-noinput
validate-inputs ?{ print-usage #01 !exit }
( ; we know that all input files exist )
#01 arg/read DUP2 path-exists ?&dest-exists
.File1/name DEO2
#00 .File1/append DEO
;arg/count LDA #02
&loop DUP arg/read archive-path INC GTHk ?&loop
POP2 JMP2r
&dest-exists ;destination-exists print
print #0a18 DEO print-usage #01 !exit
@validate-inputs ( -> ok^ )
;arg/count LDA #02 LITr 01 ( count^ 2^ [1^] )
&loop DUP validate-input ( count^ i^ ok1^ [ok0^] )
STH ANDr INC GTHk ?&loop ( count^ i+1^ [ok2^] )
POP2 STHr JMP2r ( ok^ )
@validate-input ( i^ -> ok^ )
arg/read DUP2 path-exists ?&ok1
;missing-input print print #0a18 DEO #00 JMP2r
&ok1 ;long-size LDA LIT "? NEQ ?&ok2
;input-toobig print print #0a18 DEO #00 JMP2r
&ok2 POP2 #01 JMP2r
@path-exists ( path* -> )
path-read-size ;long-size LDA LIT "! NEQ JMP2r
@path-read-size ( path* -> )
.File2/name DEO2
#0008 .File2/len DEO2
;long-size .File2/stat DEO2
JMP2r
@archive-dir ( path* -> )
POP2 JMP2r
@archive-path ( path* -> )
zero-header DUP2 path-read-size ( path* )
;long-size LDA LIT "- EQU ?archive-dir ( path* )
LIT2r =header ( path* [h*] )
STH2kr LDA LIT "/ NEQ ?&rel-path ( path* [h*] )
LIT ". STH2kr STA INC2r ( path* [h+1*] )
&rel-path STH2r copy-str ( ; write file name )
;default-mode ;header/mode copy-str ( ; write file permissions )
;default-id ;header/owner copy-str ( ; write file owner )
;default-id ;header/group copy-str ( ; write file group )
size-to-octal ( ; write file size )
#010e DEO
;default-mtime ;header/mtime copy-str ( ; write mtime )
LIT "0 ;header/type STA ( ; write '0' for normal file )
;u-sum compute-sum ( checksum* )
@ascii-to-short ( s* -> n* )
#0000 SWP2 LITr c0 ( sum* s* [shift^] )
&loop LDAk #30 SUB ( sum0* s* digit^ [shift^] )
#00 SWP ( sum0* s* digit* [shift^] )
STHkr SFT2 ( sum0* s* digit<<shift* [shift^] )
ROT2 ADD2 SWP2 ( sum0+digit<<shift* s* [shift^] )
STHkr #00 EQU ?&done ( sum1* s* [shift^] )
INC2 LITr 40 SUBr !&loop ( sum1* s+1* [shift-64^] )
&done POP2 POPr JMP2r ( sum1* )
@size-to-octal ( -> )
;long-size ascii-to-short ( hi* )
;long-size/mid ascii-to-short ( hi* lo* )
;scratch ( hi* lo* addr* )
render-octal32 ( )
#000b ;header/size save-octal ( )
JMP2r ( )
@render-octal32 ( hi* lo* addr* -> )
short-to-octal STH2 STH ( aaaaaaaa bbbbbbbb [addr+5* 0000000x] )
#0000 ROT ( aaaaaaaa 00000000 00000000 bbbbbbbb [addr+5* 0000000x] )
#10 SFT2 ( aaaaaaaa 00000000 0000000b bbbbbbb0 [addr+5* 0000000x] )
SWP2 #07 SFT2 ( 0000000b bbbbbbb0 0000000a aaaaaaa0 [addr+5* 0000000x] )
SWP2 STH ( 0000000a aaaaaaa0 0000000b [addr+5* 0000000x bbbbbbb0] )
ORA ORAr STHr ( 0000000a aaaaaaab bbbbbbbx [addr+5*] )
STH2r short-to-octal ( 0000000a 0000000z addr+10* )
STH2 SWP #10 SFT ORA ( 000000az [addr+10*] )
LIT "0 ADD STH2kr STA ( [addr+10*] )
STH2r INC2 JMP2r ( addr+11* )
@short-to-octal ( n* addr* -> n>>15^ addr+5* )
byte-to-octal STH2 SWP ( lo>>6^ hi^ [addr+2*] )
DUP #01 AND #20 SFT ROT ORA ( hi^ [[hi&1]<<2]|lo>>6 [addr+2*] )
LIT "0 ADD STH2kr STA ( hi^ [addr+2*] )
#01 SFT INC2r ( hi>>1^ [addr+3*] )
STH2r !byte-to-octal ( hi>>7^ addr+5* )
@byte-to-octal ( n^ addr* -> n>>6^ addr+2* )
STH2 DUP #07 AND LIT "0 ADD ( n^ digit1^ [addr*] )
STH2kr STA #03 SFT INC2r ( n>>3^ [addr+1*] )
DUP #07 AND LIT "0 ADD ( n>>3^ digit2^ [addr+1*] )
STH2kr STA #03 SFT INC2r ( n>>6^ [addr+2*] )
STH2r JMP2r ( n>>6^ addr+2* )
@save-octal ( count* addr* -> )
LIT2r ffff ( count* addr* [ffff*] )
OVR2 ADD2 ( count* addr+count* [ffff*] )
STH2 ( count* [ffff* addr+count*] )
OVR2r ADD2r ( count* [ffff* h=addr+count-1*] )
;scratch SWP2 ( s* count* [ffff* h*] )
OVR2 ADD2 SWP2 ( limit=count+s* s* [ffff* h*] )
&loop LDAk STH2kr STA ( limit* s* [ffff* h*] ; h<-s )
INC2 OVR2r ADD2r GTH2k ?&loop ( limit* s+1* [ffff* h-1*] )
POP2 POP2 POP2r POP2r #010e DEO JMP2r ( )
@copy-str ( s* addr* -> )
STH2
&loop LDAk DUP ?&next POP POP2 POP2r JMP2r
&next STH2kr STA INC2 INC2r !&loop
( we know header is exactly 512 bytes, an even number )
@zero-header ( -> )
;uheader/end ;header LIT2r 0000
&loop STH2kr OVR2 STA2 INC2 INC2 GTH2k ?&loop
POP2r POP2 POP2 JMP2r
( writes `n` bytes from File1 to File2 )
( uses a 32k internal buffer )
@ -275,6 +450,14 @@
#10 SFT #01 SFT2 STH2r ( hi* lo* )
JMP2r ( hi* lo* )
( returns values between #0000 #0000 and #0003 #ffff )
@load-octal6 ( addr* -> hi* lo* )
STH2k LDA octal-digit ( o^ [addr*] )
#0001 SFT2 ( o1^ o2^ [addr*] )
#0000 ROT SWP2 SWP SWP2 ( o1* o2* [addr*] )
STH2r INC2 load-octal5 ( o1* o2* n* )
ORA2 JMP2r ( o1* o2|n* )
( returns values between #0000 and #7fff )
( )
( octal5 of 77777 = #7fff, max value )
@ -350,15 +533,26 @@
JMP2r
( some handy string constants )
@usage "usage: 20 "uxncli 20 "tar.rom 20 "t|x 20 "FILENAME 0a 00
@usage1 "usage: 20 "uxncli 20 "tar.rom 20 "t|x 20 "TARFILE 0a 00
@usage2 20 20 20 20 20 20 20 "uxncli 20 "tar.rom 20 "c 20 "TARFILE 20 "FILE1 20 "... 0a 00
@missing-mode "error: 20 "missing 20 "mode 0a 00
@missing-filename "error: 20 "missing 20 "filename 0a 00
@too-many-arguments "error: 20 "too 20 "many 20 "arguments 0a 00
@no-input-arguments "error: 20 "no 20 "input 20 "files 0a 00
@invalid-mode "error: 20 "invalid 20 "mode 0a 00
@read-error "error 20 "reading 20 "data 0a 00
@write-error "error 20 "writing 20 "data 0a 00
@unsupported "skipped 20 "unsupported 20 "type 20 00
@meta-too-big "extended 20 "metadata 20 "field 20 "too 20 "big: 20 00
@invalid-checksum "error: 20 "invalid 20 "checksum 0a 00
@expected "expected: 20 00
@found "found: 20 20 20 20 00
@missing-input "error: 20 "missing 20 "input 20 "file: 20 00
@input-toobig "error: 20 "input 20 "file 20 "too 20 "large: 20 00
@destination-exists "error: 20 "destination 20 "already 20 "exists: 20 00
@default-mode "0000755 00
@default-id "0000000 00
@default-mtime "07033241577 00
( load argument parser )
~arg.tal
@ -429,8 +623,11 @@
&pad $c ( 0x1f4: padding, 12 bytes )
&end ( 0x200: end of header )
( small scratch buffer )
|77e8 @scratch $10
( up to 8 bytes for long size )
|77f8 @long-size $8
|77f8 @long-size $4 &mid $4
( buffer for up to 2048 characters of long names/paths )
|7800 @long-buf $800

View File

@ -1,45 +1,43 @@
%dbg { #ff #0e DEO }
%sp { #20 #18 DEO }
%nl { #0a #18 DEO }
%exit { #01 #0f DEO BRK }
%sp { #2018 DEO }
%nl { #0a18 DEO }
|0100
;expr1 ;compile JSR2 dbg nl
;emit-stack JSR2 nl
;emit-arena JSR2 nl
;expr1 compile #010e DEO nl
emit-stack nl
emit-arena nl
LIT '= ;emit JSR2 sp
#01 ;emit-bool JSR2 sp
#01 ;emit-bool JSR2 sp
#00 ;emit-bool JSR2 sp
#01 ;emit-bool JSR2 sp
#01 ;emit-bool JSR2 sp
#00 ;emit-bool JSR2 sp
#00 ;emit-bool JSR2 sp
#00 ;emit-bool JSR2 nl
LIT "= emit sp
#01 emit-bool sp
#01 emit-bool sp
#00 emit-bool sp
#01 emit-bool sp
#01 emit-bool sp
#00 emit-bool sp
#00 emit-bool sp
#00 emit-bool nl
LIT 'A ;emit JSR2 sp
;test1 OVR2k ;match JSR2 ;emit-bool JSR2 sp
;test2 OVR2k ;match JSR2 ;emit-bool JSR2 sp
;test3 OVR2k ;match JSR2 ;emit-bool JSR2 sp
;test4 OVR2k ;match JSR2 ;emit-bool JSR2 sp
;test5 OVR2k ;match JSR2 ;emit-bool JSR2 sp
;test6 OVR2k ;match JSR2 ;emit-bool JSR2 sp
;test7 OVR2k ;match JSR2 ;emit-bool JSR2 sp
;test8 OVR2k ;match JSR2 ;emit-bool JSR2 nl
LIT "A emit sp
;test1 OVR2k rx-match emit-bool sp
;test2 OVR2k rx-match emit-bool sp
;test3 OVR2k rx-match emit-bool sp
;test4 OVR2k rx-match emit-bool sp
;test5 OVR2k rx-match emit-bool sp
;test6 OVR2k rx-match emit-bool sp
;test7 OVR2k rx-match emit-bool sp
;test8 OVR2k rx-match emit-bool nl
LIT 'B ;emit JSR2 sp
;test1 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
;test2 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
;test3 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
;test4 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
;test5 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
;test6 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
;test7 ;graph1 ;match JSR2 ;emit-bool JSR2 sp
;test8 ;graph1 ;match JSR2 ;emit-bool JSR2 nl
LIT "B emit sp
;test1 ;graph1 rx-match emit-bool sp
;test2 ;graph1 rx-match emit-bool sp
;test3 ;graph1 rx-match emit-bool sp
;test4 ;graph1 rx-match emit-bool sp
;test5 ;graph1 rx-match emit-bool sp
;test6 ;graph1 rx-match emit-bool sp
;test7 ;graph1 rx-match emit-bool sp
;test8 ;graph1 rx-match emit-bool nl
;reset-arena JSR2
exit
reset-arena
#010f DEO BRK
( corresponds to regex: a(b|c)d* )
@expr1 "a(b|c)d* 00
@ -47,12 +45,12 @@
( corresponds to regex: a(b|c)d* )
( accepts "ab" or "ac" followd by any number of d's )
@graph1
03 'a :x1
@x1 04 :x2 :x3
@x2 03 'b :x4
@x3 03 'c :x4
@x4 05 :x5 0000
@x5 03 'd :x4
03 "a =x1
@x1 04 =x2 =x3
@x2 03 "b =x4
@x3 03 "c =x4
@x4 05 =x5 0000
@x5 03 "d =x4
( test case strings to try matching )
@test1 "ab 00 ( yes )
@ -67,50 +65,50 @@
~regex.tal
@emit ( c^ -- )
emit JMP2r
#18 DEO JMP2r
@emit-short ( short* -- )
SWP ;emit-byte JSR2 ;emit-byte JSR2 JMP2r
SWP emit-byte emit-byte JMP2r
@emit-byte ( byte^ -- )
DUP #04 SFT ,&hex JSR #0f AND ,&hex JMP
DUP #04 SFT ,&hex JSR #0f AND !&hex
&hex #30 ADD DUP #39 GTH #27 MUL ADD emit
JMP2r
@emit-bool ( byte^ -- )
LIT '0 ADD emit JMP2r
LIT "0 ADD emit JMP2r
( print stack size, followed by contents )
@emit-stack ( -> )
space LIT 'n emit LIT '= emit ;stack-pos LDA2 ;stack-bot SUB2 #0004 DIV2 ;emit-short JSR2 LIT ': emit
sp LIT "n emit LIT "= emit ;stack-pos LDA2 ;stack-bot SUB2 #0004 DIV2 emit-short LIT ": emit
;stack-bot
&loop
DUP2 ;stack-pos LDA2 LTH2 ,&ok JCN
POP2 newline JMP2r
DUP2 ;stack-pos LDA2 LTH2 ?&ok
POP2 nl JMP2r
&ok
space LDA2k ;emit-short JSR2
#0002 ADD2 ,&loop JMP
sp LDA2k emit-short
#0002 ADD2 !&loop
( emit n bytes from the given address )
@emit-n ( addr* count^ -> addr2* )
DUP #00 GTH ( addr count count>0? ) ,&ok JCN ( addr count ) POP newline JMP2r
DUP #00 GTH ( addr count count>0? ) ?&ok ( addr count ) POP nl JMP2r
&ok
STH ( addr [count] ) space LDAk ;emit-byte JSR2 INC2 ( addr+1 [count] )
STH ( addr [count] ) sp LDAk emit-byte INC2 ( addr+1 [count] )
STHr #01 SUB ( addr+1 count-1 )
;emit-n JMP2
!emit-n
( emit the arena, with one line per node )
( parses node type, since node size is dynamic (3-5). )
@emit-arena ( -> )
;arena-bot
&loop
DUP2 ;arena-pos LDA2 LTH2 ,&ok JCN POP2 JMP2r
DUP2 ;arena-pos LDA2 LTH2 ?&ok POP2 JMP2r
&ok
DUP2 ;emit-short JSR2
LIT ': emit space
LDAk #01 NEQ ,&!1 JCN #03 ;emit-n JSR2 ,&loop JMP
&!1 LDAk #02 NEQ ,&!2 JCN #03 ;emit-n JSR2 ,&loop JMP
&!2 LDAk #03 NEQ ,&!3 JCN #04 ;emit-n JSR2 ,&loop JMP
&!3 LDAk #04 NEQ ,&!4 JCN #05 ;emit-n JSR2 ,&loop JMP
&!4 LDAk #05 NEQ ,&!5 JCN #05 ;emit-n JSR2 ,&loop JMP
&!5 ;unknown-node-type ;error! JSR2
DUP2 emit-short
LIT ": emit sp
LDAk #01 NEQ ?&c1 #03 emit-n !&loop
&c1 LDAk #02 NEQ ?&c2 #03 emit-n !&loop
&c2 LDAk #03 NEQ ?&c3 #04 emit-n !&loop
&c3 LDAk #04 NEQ ?&c4 #05 emit-n !&loop
&c4 LDAk #05 NEQ ?&c5 #05 emit-n !&loop
&c5 ;unknown-node-type errorm

View File

@ -21,7 +21,7 @@ template = '''
;wst print
@dump-wst
#04 DEI #01 GTH ?&next !emit-wst &next STH !dump-wst
#04 DEI #00 GTH ?&next !emit-wst &next STH !dump-wst
@emit-wst
#05 DEI LIT [ &n $1 ] GTH ?&next #0a18 DEO !start-rst
@ -34,7 +34,7 @@ template = '''
#05 DEI #00 GTH ?&next !emit-rst &next STHr !dump-rst
@emit-rst
#04 DEI #01 GTH ?&next #0a18 DEO #800f DEO BRK
#04 DEI #00 GTH ?&next #0a18 DEO #800f DEO BRK
&next emit #2018 DEO !emit-rst
@print ( addr* -> )

88
varvara.7 Normal file
View File

@ -0,0 +1,88 @@
.\" Manpage reference for varvara.
.\" by Eiríkr Åsheim
.\" Contact d_m@plastic-idolatry.com to correct errors or typos.
.TH varvara 7 "14 Nov 2024" "1.0" "Varvara Reference Guide"
.SH NAME
varvara \- virtual machine for the Uxn CPU
.SH DESCRIPTION
Varvara is a virtual machine for the Uxn CPU. It provides devices that allow
ROMs to perform effects such as I/O, drawing to the screen, playing sounds,
and more.
.SH DEVICES
Each device consists of 16 ports, each of which are one byte of device memory. Data can be read from ports with \fBDEI\fP and written to them with \fBDEO\fP.
.SH TERMS
.SS Devices
.SS Ports
.SS Vectors
.SS Banks
.SH DEVICE LAYOUT
0x00 \fBSystem\fP 0x80 \fBController\fP
0x10 \fBConsole\fP 0x90 \fBMouse\fP
0x20 \fBScreen\fP 0xa0 \fBFile 0\fP
0x30 \fBAudio 0\fP 0xb0 \fBFile 1\fP
0x40 \fBAudio 1\fP 0xc0 \fBDateTime\fP
0x50 \fBAudio 2\fP 0xd0 \fB(reserved)\fP
0x60 \fBAudio 3\fP 0xe0 \fB(reserved)\fP
0x70 \fB(unused)\fP 0xf0 \fB(unused)\fP
.SH SYSTEM (0x00)
0x00 \fBvector*\fP 0x08 \fBred*\fP
0x01 0x09
0x02 \fBexpansion*\fP 0x0a \fBgreen*\fP
0x03 0x0b
0x04 \fBwst\fP 0x0c \fBblue*\fP
0x05 \fBrst\fP 0x0d
0x06 \fBmetadata*\fP 0x0e \fBdebug\fP
0x07 0x0f \fBstate\fP
.SS System/vector
Currently unused.
.SS System/expansion
Values written to the expansion port will be interpreted as an absolute address pointing to memory containing an expansion command.
\fBCODE NAME DATA\fP
00 \fBfill\fP 00 length* bank* addr* const
01 \fBcpyl\fP 01 length* src-bank* src-addr* dst-bank* dst-addr*
02 \fBcpyr\fP 02 length* src-bank* src-addr* dst-bank* dst-addr*
\fBCODE NAME DESC\fP
00 \fBfill\fP fill a range of memory with a constant value.
01 \fBcpyl\fP copy a range of memory starting from the first byte.
02 \fBcpyr\fP copy a range of memory starting from the last byte.
Each bank contains 64k (65536 bytes) of data. Bank 0 is main memory. Banks are optional but emulators are encouraged to support at least 16 of them when possible.
.SH CONSOLE (0x10)
.SH SCREEN (0x20)
.SH AUDIO (0x30, 0x40, 0x50, 0x60)
.SH CONTROLLER (0x80)
.SH MOUSE (0x90)
.SH FILE (0xa0, 0xb0)
.SH DATETIME (0xc0)
.SH RESERVED (0xd0, 0xe0)
.SH UNUSED (0x70, 0xf0)
.SH SEE ALSO
https://wiki.xxiivv.com/site/uxntal_opcodes.html \fIUxntal Opcodes\fP
https://wiki.xxiivv.com/site/uxntal_syntax.html \fIUxntal Syntax\fP
https://wiki.xxiivv.com/site/uxntal_modes.html \fIUxntal Modes\fP
https://wiki.xxiivv.com/site/uxntal_immediate.html \fIImmediate opcodes\fP
https://wiki.xxiivv.com/site/varvara.html \fIVarvara\fP