Create readable text `.bas' for each tokenized BASIC `,ffb' file.
[ssr] / StraySrc / Libraries / BAS / src / b / bas.bas
CommitLineData
c1b567d8
MW
1REM Basic Assembler Supplement 1.00 © 1996-1998 Straylight
2REMÂÁÓhack
3
4REM ----- Licensing note ----------------------------------------------------
5REM
6REM This file is part of Straylight's BASIC Assembler Supplement (BAS)
7REM
8REM BAS is free software; you can redistribute it and/or modify
9REM it under the terms of the GNU General Public License as published by
10REM the Free Software Foundation; either version 2, or (at your option)
11REM any later version
12REM
13REM BAS is distributed in the hope that it will be useful,
14REM but WITHOUT ANY WARRANTY; without even the implied warranty of
15REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16REM GNU General Public License for more details.
17REM
18REM You should have received a copy of the GNU General Public License
19REM along with BAS. If not, write to the Free Software Foundation,
20REM 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22REM --- Hacking warning ---
23REM
24REM That gorp on the second line is a magic marker word inserted by hand
25REM (the three letters `BAS' with their top bits set) and space for an offset
26REM word which marks the offset of the code section from the beginning of
27REM the LIBRARY link block. Don't play with them unless you (a) know what
28REM you're doing (and it should be perfectly clear by now that I don't have
29REM a clue), and (b) want to seriously upset the library search code below.
30
31ERROR 0,"You can't run the Basic Assembler Supplement"
32
33REM --- A note ---
34REM
35REM To make this program particularly easy to strip down and transmogrify,
36REM it contains directives which are picked up by a sed script during
37REM munging. The directives currently are `del ... edel' which deletes
38REM all the enclosed lines, and `hex' which inserts the generated hex version
39REM of the library search code. Directives are enclosed in square brackets.
40REM It's usual to put them in REM statements.
41
42REM ----- Initialisation ----------------------------------------------------
43
44REM [del]
45DEF FNbas_assign(RETURN d,v%):d=v%:=0
46DEF PROCbas_const(var$,val%)
47IF bas_cf% THEN BPUT #bas_cf%,"/\<"+var$+"\>/s//"+STR$(val%)+"/g"
48IF EVAL("FNbas_assign("+var$+",val%)")
49ENDPROC
50
51DEF FNnext:R%+=4:=R%-4
52
53DEF PROCbas_saveconst
54bas_cf%=OPENOUT("work.basconst")
55
56DEF PROCbas_constants
57bas_cf%=bas_cf%
58R%=0
59PROCbas_const("bcode_wSize",FNnext)
60PROCbas_const("bcode_init",FNnext)
61PROCbas_const("bcode_aofInit",FNnext)
62PROCbas_const("bcode_newPass",FNnext)
63PROCbas_const("bcode_import",FNnext)
64PROCbas_const("bcode_export",FNnext)
65PROCbas_const("bcode_get",FNnext)
66PROCbas_const("bcode_area",FNnext)
67PROCbas_const("bcode_reloc",FNnext)
68PROCbas_const("bcode_noReloc",FNnext)
69PROCbas_const("bcode_entry",FNnext)
70PROCbas_const("bcode_save",FNnext)
71PROCbas_const("bcode_align",FNnext)
72PROCbas_const("bcode_reserve",FNnext)
73PROCbas_const("bcode_lit",FNnext)
74PROCbas_const("bcode_ltorg",FNnext)
75PROCbas_const("bcode_saveOpt",FNnext)
76PROCbas_const("bcode_restoreOpt",FNnext)
77IF bas_cf% THEN CLOSE #bas_cf%
78ENDPROC
79REM [edel]
80
81REM --- Unexplainable horridness ---
82REM
83REM Tim wants to be able to embed the code into this library file, so
84REM that it doesn't have to be searched for. I'll therefore have to write
85REM some code to scan the library list and locate this one, and find the
86REM code tacked onto the end. Yuk.
87
88DEF PROCbas_init
89LOCAL type%,size% :REM [dl]
90LOCAL workSize%,H%,len%,f%
91PROCbas_constants :REM [dl]
92
93REM --- Old code to load the library from disk ---
94
95REM [del]
96IF TRUE THEN
97 DIM bas_scratch% 300
98 SYS "OS_File",17,"libs:BAScode" TO type%,,,,size%
99 IF type%<>1 THEN ERROR 0,"BAS code not found"
100 DIM bas_code% size%
101 SYS "OS_File",16,"libs:BAScode",bas_code%,0
102ELSE
103DEF PROCbas_dumpcode
104REM [edel]
105
106REM --- New hacking to scan the library list ---
107REM
108REM This must be done in assembler, of course ;-) Time to put on my pointy
109REM Rincewind hat... I've tried to do this in one pass because I'm lazy --
110REM I guess that's why it's unreadable.
111
112 DIM bas_scratch% 300
113 P%=bas_scratch%
114 [ opt 0
115
116 ; exit with r0 == pointer to code, or 0 if not found (erk!)
117
118 ldr r2,[pc] ; load the magic marker word
119 mov pc,pc ; skip over the magic marker word
120 dcd &d3c1c2f4 ; this is `REMBAS', with the top bits set
121
122 ldr r0,[r14,#&24] ; find offset of TIMEOF
123 add r0,r8,r0 ; add on ARGP to find TIMEOF
124 ldr r0,[r0,#&c] ; load the library list base
125
126;.loop
127 cmp r0,#0 ; is that the end of it all?
128 moveqs pc,r14 ; yes -- oh, well -- it was a nice try
129
130 ldr r1,[r0,#&44] ; load mystic recognition word
131 cmp r1,r2 ; does it match?
132 ldrne r0,[r0] ; if not there, load the next link
133 subne pc,pc,#28 ; and jump back to `loop' (erk)
134
135 ldr r1,[r0,#&48] ; load the code offset
136 add r0,r1,r0 ; and add it to the base address
137 movs pc,r14
138 ]
139
140 REM --- Now some code to dump that out as hex ---
141
142 bas_code%=USR bas_scratch%
143 IF bas_code%=0 THEN ERROR 0,"BAS code not found: is the library corrupt?"
144
145REM [del]
146ENDIF
147REM [edel]
148
149REM --- Back to life as normal ---
150
151workSize%=USR(bas_code%+bcode_wSize)
152DIM bas_workspace% workSize%
153H%=bas_workspace%
154CALL bas_code%+bcode_init
155SYS "XOS_ReadVarVal","BAS$Output",bas_scratch%,256,3 TO ,,len%;f%
156IF f% AND 1 THEN
157 bas_fileName$=""
158ELSE
159 bas_scratch%?len%=13
160 bas_fileName$=$bas_scratch%
161ENDIF
162ENDPROC
163
164DEF PROCbas_aofInit(size%)
165LOCAL H%
166IF size% THEN DIM bas_asmCode% size% ELSE bas_asmCode%=bas_asmCode%
167IF bas_asmCode%=0 THEN ERROR 0,"No buffer allocated for assembler code"
168H%=bas_workspace%
169CALL bas_code%+bcode_aofInit,bas_asmCode%
170ENDPROC
171
172REM This function saves a few bytes and tidies up the code a bit.
173
174DEF FNbas_call(offset%)
175LOCAL H%
176H%=bas_workspace%
177=USR(bas_code%+offset%)
178
179REM ----- AOF code generation -----------------------------------------------
180
181DEF PROCbas_aofSaveAs(name$)
182LOCAL H%
183H%=bas_workspace%
184CALL bas_code%+bcode_save,name$
185ENDPROC
186
187DEF PROCbas_aofSave
188IF bas_fileName$="" THEN ERROR 0,"No implicit filename"
189PROCbas_aofSaveAs(bas_fileName$)
190bas_fileName$=""
191ENDPROC
192
193DEF FNpass=FNbas_call(bcode_newPass)
194
195DEF FNbas_port(offset%,A%,s$,t$)
196LOCAL H%
197H%=bas_workspace%
198CALL bas_code%+offset%,s$,t$
199=0
200
201DEF FNimport(var$)=FNbas_port(bcode_import,0,var$,var$)
202DEF FNimportAs(sym$,var$)=FNbas_port(bcode_import,0,sym$,var$)
203DEF FNimportWeak(var$)=FNbas_port(bcode_import,1,var$,var$)
204DEF FNimportWeakAs(sym$,var$)=FNbas_port(bcode_import,1,sym$,var$)
205DEF FNexport(var$)=FNbas_port(bcode_export,0,var$,var$)
206DEF FNexportAs(var$,sym$)=FNbas_port(bcode_export,0,var$,sym$)
207DEF FNexportStrong(var$)=FNbas_port(bcode_export,1,var$,var$)
208DEF FNexportStrongAs(var$,sym$)=FNbas_port(bcode_export,1,var$,sym$)
209
210DEF FNget(file$)
211LOCAL H%
212H%=bas_workspace%
213CALL bas_code%+bcode_get,file$
214=0
215
216DEF FNbas_lib(lib$)
217LOCAL err%,leaf$,lower$,i%
218leaf$=lib$
219FOR i%=1 TO LEN(lib$)
220 IF INSTR(":.",MID$(lib$,i%,1)) THEN leaf$=MID$(lib$,i%+1)
221NEXT
222FOR i%=1 TO LEN(leaf$)
223 lower$+=CHR$(ASC(MID$(leaf$,i%,1)) OR &20)
224NEXT
225LOCAL ERROR
226ON ERROR LOCAL err%=TRUE
227IF err%=FALSE THEN
228 IF EVAL("FN"+lower$+"_test")
229ENDIF
230RESTORE ERROR
231IF err%=TRUE THEN LIBRARY lib$
232=0
233
234DEF FNarea(name$,attr$)
235LOCAL A%,H%
236A%=2
237IF INSTR(attr$,"CODE") THEN A%+=&200
238IF INSTR(attr$,"COMDEF") THEN A%+=&400
239IF INSTR(attr$,"COMMON") THEN A%+=&800
240IF INSTR(attr$,"NOINIT") THEN A%+=&1000
241IF INSTR(attr$,"READONLY") THEN A%+=&2000
242IF INSTR(attr$,"DEBUG") THEN A%+=&8000
243IF A% AND &800 THEN A%=A% OR &1000
244IF A% AND &200 THEN A%=A% OR &2000
245H%=bas_workspace%
246CALL bas_code%+bcode_area,name$
247=0
248
249DEF FNreloc=FNbas_call(bcode_reloc)
250DEF FNnoReloc=FNbas_call(bcode_noReloc)
251
252DEF FNentry=FNbas_call(bcode_entry)
253
254REM ----- Literal handling --------------------------------------------------
255
256DEF PROClitStart
257bas_litStart%=P%
258bas_savedOpt%=USR(bas_code%+bcode_saveOpt)
259ENDPROC
260
261DEF FNlitw(val%)
262PROClitStart
263[ opt 4: dcd val%:]
264=FNlitAlign
265
266DEF FNlits(str$)
267PROClitStart
268[ opt 4: equs str$:]
269=FNlit
270
271DEF FNlitmagic(str$)
272PROClitStart
273[ opt 4: equs str$:]
274=FNlitAlign
275
276DEF FNlitsz(str$)
277PROClitStart
278[ opt 4: equs str$+CHR$0:]
279=FNliteral
280
281DEF FNliterr(err%,str$)
282PROClitStart
283[ opt 4: dcd err%: equs str$+CHR$0:]
284=FNlitAlign
285
286DEF FNliteral
287LOCAL A%,B%,C%
288A%=bas_savedOpt%
289CALL bas_code%+bcode_restoreOpt
290B%=P%-bas_litStart%
291A%=O%-B%
292C%=0
293P%=bas_litStart%
294O%=A%
295=FNbas_call(bcode_lit)
296
297DEF FNlitAlign
298LOCAL A%,B%,C%
299A%=bas_savedOpt%
300CALL bas_code%+bcode_restoreOpt
301B%=P%-bas_litStart%
302A%=O%-B%
303C%=1
304P%=bas_litStart%
305O%=A%
306=FNbas_call(bcode_lit)
307
308DEF FNltorg=FNbas_call(bcode_ltorg)
309
310REM ----- Initialising areas ------------------------------------------------
311
312DEF FNalign=FNbas_call(bcode_align)
313DEF FNreserve(A%)=FNbas_call(bcode_reserve)
314
315DEF FNbin(file$)
316LOCAL size%
317IF FNbas_call(bcode_noReloc)
318size%=FNfSize(file$)
319SYS "OS_File",16,file$,O%,0
320O%+=size%
321P%+=size%
322IF FNbas_call(bcode_reloc)
323=0
324
325DEF FNfSize(file$)
326LOCAL size%
327SYS "OS_File",17,file$ TO ,,,,size%
328=size%
329
330REM ----- Laying out storage areas ------------------------------------------
331
332DEF PROCws_start
333bas_R%=0
334ENDPROC
335
336DEF PROCws_base(start%)
337bas_R%=start%
338ENDPROC
339
340DEF FNws(size%)
341bas_R%+=size%
342=bas_R%-size%
343
344DEF PROCws_align
345bas_R%=(bas_R%+3) AND -4
346ENDPROC
347
348DEF FNws_word
349PROCws_align
350=FNws(4)
351
352DEF FNws_byte=FNws(1)
353
354REM ----- Long directives ---------------------------------------------------
355
356DEF FNadrl(r%,adr%)=FNaddccl(14,r%,15,adr%-P%-8)
357DEF FNadrccl(cc%,r%,adr%)=FNaddccl(cc%,r%,15,adr%-P%-8)
358DEF FNaddl(r%,b%,off%)=FNaddccl(14,r%,b%,off%)
359DEF FNaddccl(cc%,r%,b%,off%)
360IF off%>0 THEN
361 [opt 4:addeq r%,b%,#off% AND 255:addeq r%,r%,#off% AND -256:]
362ELSE
363 [opt 4:subeq r%,pc,#(-off%) AND 255:subeq r%,r%,#(-off%) AND -256:]
364ENDIF
365!(O%-8)=!(O%-8) OR (cc%<<28)
366!(O%-4)=!(O%-4) OR (cc%<<28)
367=0
368
369DEF FNldrl(r%,adr%)=FNldrrccl(14,r%,15,adr%-P%-8)
370DEF FNldrccl(cc%,r%,adr%)=FNldrrccl(cc%,r%,15,adr%-P%-8)
371DEF FNldrrl(r%,b%,off%)=FNldrrccl(14,r%,b%,off%)
372DEF FNldrrccl(cc%,r%,b%,off%)
373IF off%>0 THEN
374 [opt 4:addeq r%,b%,#off% AND -256:ldreq r%,[r%,#off% AND 255]:]
375ELSE
376 [opt 4:subeq r%,b%,#(-off%) AND -256:ldreq r%,[r%,#-((-off%) AND 255)]:]
377ENDIF
378!(O%-8)=!(O%-8) OR (cc%<<28)
379!(O%-4)=!(O%-4) OR (cc%<<28)
380=0
381
382REM ----- That's all, folks -------------------------------------------------