commit 963004b
zzo38
·
2023-06-01 04:39:21 +0000 UTC
parent 6615d46
Add prg/uhsmake.tal (make UHS hint file) and the documentation of it
2 files changed,
+397,
-0
+51,
-0
1@@ -0,0 +1,51 @@
2+Give two command-line arguments, being the input file name and the output
3+file name. (This program does not operate in GUI mode or interactive mode.)
4+
5+Each line of the input file contains a command, indicated by the first
6+character. The possible commands are:
7+
8+# Comment in the input file; not written to the output. (This is not the
9+same as a comment block.)
10+
11+. A line of text. Only allowed inside of a () or <> or [] block; cannot be
12+used at the top level or inside of a {} block.
13+
14+& Define the title of the hint file. Should occur exactly once.
15+
16+- A separator line (which should not include any text). Only allowed
17+inside of a {} block or a [] block. In a [] block, it will hide all further
18+text in this block until the user tells to reveal the next part (you can
19+have more than one separator; each one stops output until the user tells to
20+continue further output). In a {} block, just makes a blank line.
21+
22+: A link to some other block in the file. Follow by the target label name
23+(which is the label name of any block in the file) and then . and the text
24+of the link.
25+
26+There are also blocks. The characters [ ( < { indicate the beginning of a
27+block and ] ) > } indicate the end of a block. The begin block line will
28+also have the label name (which can be blank if there is no label name)
29+and then . and then the text which is the title of that block. The end
30+block line should not have any text.
31+
32+() Comment: A block of text which is not a hint, but just text. Cannot
33+contain any other blocks, and cannot contain links. (This is not the same
34+as the # command.)
35+
36+<> Credit: Works like comment blocks.
37+
38+{} Subject: A menu block. Can include other blocks but not text lines.
39+(Normally used for grouping hints by the section in the game.)
40+
41+[] Hint: This block can contain text and other blocks. This is used for a
42+game hint and the title is usually a question that will be answered by the
43+text in this block. You can add separator lines so that only one part of
44+the text is revealed at a time.
45+
46+Any line in the input file can optionally be indented by spaces and/or tabs
47+at the beginning of the line; any such indentation is ignored. (You can use
48+this to indent blocks if you wish.)
49+
50+This program will not calculate the checksum of the UHS file; however, the
51+FOSS implementations do not care about the checksum, so it isn't a problem.
52+
+346,
-0
1@@ -0,0 +1,346 @@
2+\\ UHS make (public domain)
3+\\ Requires some nonstandard features of uxn38.
4+
5+|0000
6+ @X $1 @Y $1
7+ $2 \\ padding, used when a block is not given a label name
8+ @Name $2
9+ @Line $2
10+ @LineIn $2
11+ @Tlength $1
12+ @Tend $1
13+|0028 \\ note that this number is on purpose, for purpose of making the key
14+ @Title
15+
16+|0100
17+ \\ Check arguments
18+ #17 DEI [? error "usage: 20 "uhsmake.rom 20 "<inputfile> 20 "<outputfile> 0a ]@
19+ \\ Input file name
20+ LIT2r :filename DUP2r
21+ [; #10 DEO2 BRK ]@
22+ #17 DEI #02 GTH [? #12 DEI STH2rk INC2r STA BRK ]@
23+ #00 STH2r STA
24+ DUP2rk LITr a8 DEO2r
25+ \\ Output file name
26+ [; #10 DEO2 BRK ]@
27+ #17 DEI #02 GTH [? #12 DEI STH2rk INC2r STA BRK ]@
28+ #00 DUPk STH2r STA
29+ LITr b8 DEO2r
30+ #10 DEO2
31+ \\ Write the 88a format heading of the hint file
32+ ;uhshlen #ba DEO2
33+ ;uhshead #be DEO2
34+ \\ Initialize variables
35+ ;firstname .Name STZ2
36+
37+\\ First pass
38+ #0003 .Line STZ2
39+ LIT2r :heap DUP2r \\ keep it for later too
40+ #00 DUPk INC \\ the first entry has 0 to keep track of misnesting
41+ \\ stack entry: ( line-number* block-entry* type )
42+ \\ 00=hint/nesthint 01=subject ff=comment/credit
43+@pass1
44+ GTH2rk STHr ?overflow
45+ nxline [:
46+ ". :p1text
47+ "- :p1brk
48+ "( :p1cc
49+ "< :p1cc
50+ "{ :p1sub
51+ "[ :p1hint
52+ ": :p1link
53+ ") :p1close
54+ "} :p1close
55+ "] :p1close
56+ "> :p1close
57+ "# :p1ign
58+ "& :p1title
59+ 00 ]@
60+
61+\\ Second pass
62+ POP2r
63+ POP #0000 EQU [? error "Unterminated 20 "block 0a ]@
64+ #00a7 DEO ( rewind )
65+ \\ Send first block heading
66+ ;typ/subject .Line LDZ2 #0001 SUB2 nodehead
67+ \\ Send title
68+ ;Tlength LDZ
69+ DUP [? error "Missing 20 "title 0a ]@
70+ #ba DEO2 ;Title #be DEO2 crlf
71+ \\ Make key
72+ \\ In C codes: k[i]+="key"[i%3]^(i+40); while(k[i]>127) k[i]-=96;
73+ LIT2 -Title -Tlength LDZ ADDk .Tend STZ POP
74+ [@
75+ LDZk STH LIT2r :key STHk LITr 03 DIVrk MULr SUBr ADDr LDAr STHk EORr ADDr
76+ STHrk #80 LTH [? DUPr LITr df GTHr INCr LITr 60 MULr SUBr ]@ STHk STZr
77+ INC DUP
78+ ]?
79+ \\ stack entry: ( type )
80+ \\ 00=subject/comment/credit 01=hint ff=nesthint
81+ \\ (The appropriate value is already in the stack)
82+@pass2
83+ nxline [:
84+ ". :p2text
85+ "- :p2brk
86+ "( :p2com
87+ "< :p2cred
88+ "{ :p2sub
89+ "[ :p2hint
90+ ": :p2link
91+ ") :p2close
92+ "} :p2close
93+ "] :p2close
94+ "> :p2close
95+ "# :p2ign
96+ "& :p2ign
97+ 00 ]@
98+
99+\\ Finished
100+ ;verlen #ba DEO2
101+ ;version #be DEO2
102+ #800f DEO
103+
104+\_@2+fe'&(@2+!) \\ alignment
105+@key "yke
106+
107+@overflow
108+ error "Heap 20 "overflow 0a
109+
110+@error
111+ \\ Line number
112+ LIT2r 19 DEO LIT LIT ;number/em STH2k STA INC2r STA2r
113+ .LineIn LDZ2 number #2019 DEO
114+ \\ Text
115+ [@ STH2rk INC2r LDA DUP #19 DEO #0a EOR ]?
116+ #010f DEO BRK
117+
118+@p1link
119+ need95a
120+ DUP [? add1line STH LITr 01 STH2k STAr STHr ]@
121+ badcontext
122+ rname1 ORA [? error "Name 20 "required 20 "for 20 "link 0a ]@
123+ add2line
124+@p1text
125+ DUP #01 NEQ [? error "Text 20 "line 20 "not 20 "allowed 20 "in 20 "subject 20 "block 0a ]@
126+ add1line
127+@p1ign
128+ skline !pass1
129+@p1title
130+ LITr 00 .Title
131+ [@
132+ #ac DEI
133+ DUP #1f GTH [?
134+ LITr -Tlength STZr
135+ POP2 !pass1
136+ ]@
137+ OVR STZ INC INCr
138+ ]!
139+@p1cc
140+ #ff !p1open
141+@p1sub
142+ #01 !p1open
143+@p1hint
144+ #00
145+@p1open
146+ ,&kind STR
147+ badcontext
148+ DUP [? need95a add1line STH LITr 01 STH2k STAr STHr ]@
149+ .Line LDZ2 DUP2 rname1 INC2 INC2
150+ LDA2k DUP2k EOR2 EQU2 [? error "Duplicate 20 "label 0a ]@
151+ STA2 STH2rk LIT &kind $1
152+ #00 DUPk #02 STZ2 STH2rk STA ( nest flag )
153+ INC2r INC2r INC2r ( skip past the newly added record )
154+ add2line !p1ign
155+@p1close
156+ POP ORAk [? error "Block 20 "ended 20 "without 20 "beginning 0a ]@
157+ \\ Set the number of lines in the block record
158+ INC2 SWP2 LITr -Line LDZ2r STH2 SUB2r STH2 STA2r
159+ !p1ign
160+@p1brk
161+ badcontext
162+ LIT2r :p1ign DUP ?add2line !add1line
163+
164+@p2brk
165+ DUP [? ;typ/blank #0002 nodehead ]@
166+ LIT "- emit crlf
167+@p2ign
168+ skline !pass2
169+@p2com
170+ p2open :typ/comment
171+@p2cred
172+ p2open :typ/credit
173+@p2sub
174+ p2open :typ/subject
175+@p2hint
176+ p2open 0000
177+@p2open
178+ INCk [? LIT "= emit crlf ]@
179+ STH2r LDA2
180+ rname2 POP2 \\ ignore the label name, if any
181+ ORAk [?
182+ \\ Read nest flag of current record
183+ LDArk STHr [? POP INC ;typ/hint ][ INC SUB ;typ/nesthint ]@
184+ ][
185+ #00 ROT ROT
186+ ]@
187+ INC2r STH2rk LDA2 nodehead INC2r INC2r
188+@p2plain
189+ plain !pass2
190+@p2close
191+ POP !p2ign
192+@p2link
193+ INCk [? LIT "= emit crlf ]@
194+ ;typ/link #0003 nodehead
195+ rname2 plain
196+ INC2 INC2 LDA2 ORAk [? error "Undefined 20 "label 0a ]@
197+ number crlf !pass2
198+@p2text
199+ INCk [?
200+ \\ Encryption for "nesthint" block
201+ LIT2 -Tend -Title STHk
202+ [@
203+ #ac DEI DUP #20 LTH ?&n
204+ OVR LDZ STHrk EOR ADD
205+ DUP #20 SUB #60 DIVk MUL NIP SUB
206+ emit
207+ INCr INC EQUk .Tlength LDZ MUL SUB
208+ ]!
209+ ]@
210+ DUP ?&h !p2plain
211+ \\ Encryption for "hint" block
212+ [@ DUP #01 AND #5f MUL ADD #20 ADD #01 SFT emit
213+ &h #ac DEI DUP #1f GTH ]? &z POP crlf !pass2
214+ &n POP2 POPr !&z
215+
216+@add2line ( -- ) add1line ( fall through )
217+@add1line ( -- ) .Line LDZ2k INC2 ROT STZ2 JMP2r
218+
219+[@ emit @plain ( -- ) #ac DEI DUP #1f GTH ]? POP !crlf
220+
221+@badcontext ( type -- type )
222+ INCk STH2r JCN2
223+ error "Not 20 "valid 20 "in 20 "this 20 "context 0a
224+
225+@nxline
226+ ;LineIn LDZ2k INC2 ROT STZ2
227+ [@ POP #ac DEI DUP #00 EQU ?&zero DUP #21 LTH ]?
228+ [@ INC2r INC2r
229+ LDArk STHr [? error "Unrecognized 20 "command 0a ]@
230+ STH2rk INC2r LDA OVR NEQ
231+ ]? &zero POP LDA2r JMP2r
232+
233+@skline ( -- )
234+ #ac DEI DUP #0a NEQ MUL ?skline JMP2r
235+
236+@need95a ( -- )
237+ LIT "5 ;version/0 STA JMP2r
238+
239+@rname1 ( -- nameptr* )
240+ LIT2 ". ac DEI NEQk [? EOR DUP JMP2r ]@
241+ ( dot char // heap* return* )
242+ SWP2r DUP2r LIT2r 0006 ADD2r STH2rk ;&ns STA2
243+ ( dot char // return* heap* stringptr* )
244+ [@
245+ STH2rk INC2r STA #ac DEI
246+ DUP #20 GTH [? error "Invalid 20 "character 20 "in 20 "label 20 "name 0a ]@
247+ NEQk
248+ ]?
249+ EOR STH2rk STA ( null terminator )
250+ ( // return* heap* endstr* )
251+ ;firstname &find
252+ LDA2 ORAk [?
253+ \\ Not found; add a new one
254+ INC2r ROT2r ROT2r
255+ INC2rk INC2r SWP2r STA2rk LDA2r
256+ STH2rk STA2k INC2 INC2 STA2
257+ STH2rk .Name STHk LDZ2 STA2 STZ2r STH2r JMP2r
258+ ]@
259+ LIT2r &ns $2 INC2k INC2 INC2 INC2
260+ ( namerec* str1* // return* heap* endstr* str2* )
261+ [@
262+ INC2k SWP2 LDA LDArk STHr INC2r
263+ ( namerec* str1n* char1 char2 // return* heap* endstr* str2n* )
264+ EQUk [? POP2 POP2 POP2r !&find ]@
265+ POP
266+ ]?
267+ \\ Found
268+ POP2r POP2r POP2 DUP2 STH2rk STA2 INC2r INC2r SWP2r JMP2r
269+
270+@rname2 ( -- nameptr* )
271+ LIT2 ". ac DEI NEQ [? #0000 JMP2r ]@
272+ [@ LIT2 ". ac DEI NEQ ]?
273+ STH2r \\ save return address
274+ STH2rk INC2r INC2r LDA2
275+ ( return* nameptr* // newheap* )
276+ \\ Skip past the name record if it is this address
277+ DUP2 STH2rk NEQ2 [?
278+ LIT2r 0004 ADD2r
279+ [@ LDArk STHr INC2r ]?
280+ ]@
281+ SWP2 JMP2
282+
283+@number ( number* -- )
284+ LITr 00
285+ [@
286+ #000a DIV2k STH2k MUL2 SUB2
287+ STH2 SWP2r STH2r
288+ NIPr LITr 30 ADDr
289+ ORAk ]?
290+ POP2
291+ [@ STHr &em emit STHrk ]?
292+ POPr JMP2r
293+
294+@emit ( char -- ) LIT2r 0001 DUP2r STHrk STZ LITr ba DEO2r LITr be DEO2r JMP2r
295+
296+@nodehead ( type* lines* -- )
297+ number #2001 STZ #01bf DEO
298+ #bb DEO #00 SWP ;nodetypes ADD2 #be DEO2
299+ \\ Fallthrough
300+@crlf ( -- ) #0002 #ba DEO2 [; #be DEO2 JMP2r ]@ 0d0a
301+
302+@nodetypes
303+ "nesthint
304+ "subject
305+ "credit
306+ "comment
307+ "link
308+ "blank
309+
310+@version
311+ \_@
312+ "3 20 "version 0d0a
313+ "9 &0 "1a 0d0a
314+ "Compiled 20 "using 20 "uhsmake 20 "of 20 "uxn. 0d0a
315+ 1a 0000 ( checksum )
316+ \_@,- \@verlen
317+
318+\\ Name entry format:
319+\\ next name entry address (16-bits)
320+\\ line number (16-bits)
321+\\ name (null-terminated text)
322+@firstname 0000 0001 ( this one doesn't need text )
323+\\ These following things share the same memory, since @uhshead and
324+\\ @filename are both only used once, so they can be reused to store
325+\\ the heap after initialization.
326+@heap
327+@uhshead \_@ \~not88aonly.uhs \_@,- \@uhshlen
328+@filename
329+
330+\\ Record types (in heap):
331+
332+\\ label/link:
333+\\ address of name entry (16-bits)
334+\\ (if the name entry immediately follows, skip past it)
335+\\ credit/comment/subject/hint/nesthint:
336+\\ nest flag (8-bits; 0=not nest, 1=nest)
337+\\ number of lines (16-bits)
338+
339+@typ
340+ |0008 &nesthint
341+ |0404 &hint
342+ |0807 &subject
343+ |0f06 &credit
344+ |1507 &comment
345+ |1c04 &link
346+ |2005 &blank
347+