summaryrefslogtreecommitdiff
path: root/programs/sub-suite/utils.s
blob: 3813a051d22214c0ce97ee5a6d2c8e0e77d4ac65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
; Utility subroutines for SuBAsm.

print_hi:
	and #0		; Reset A.
	sta idx3	; Clear the string index.
	tax		; Reset X.
	lda #'$'	; Print the hex delimiter.
	sta strbuf, x	; Save it in the string buffer.
	lda.q idx0	; Get the masked address.
	ldx #$10	; Set digit count to 16.
	jsr print_hex	; Print the address.
	lda.q hex_str	; Get the lower half of the string.
	sta.q strbuf+1	; Save it in the string buffer.
	lda.q hex_str+8	; Get the upper half of the string.
	sta.q strbuf+9	; Save it in the string buffer.
	ldx #$11	; Add 16 to the index.
	stx idx3	;
	lda.w #': '	; Print a space.
	sta.w strbuf, x	; Save it in the string buffer.
	inc idx3	; Increment the string index twice.
	inc idx3	;
	and #0		; Reset A.
	rts		; End of print_hi.


print_lo:
	and #0		; Reset A.
	sta idx3	; Clear the string index.
@loop:
	ldx #2		; Set digit count to 2.
	pha		; Preserve the nibble offset.
	jsr print_hex	; Print the low nibble offset.
	lda.w (ptr3)	; Get the two digits.
	ldx idx3	; Get the string index.
	sta.w strbuf, x	; Save it in the string buffer.
	inc idx3	; Increment the string index twice.
	inc idx3	;
	ldx idx3	; Get the string index.
	pla		; Get the nibble offset back.
	inc		; Increment the offset.
	cmp #$10	; Are we at the last offset?
	bcs @end	; Yes, so we're done.
@loop1:
	pha		; No, so preserve the nibble offset.
	lda #' '	; Add a space to the string buffer.
	sta strbuf, x	; Save it in the string buffer.
	inc idx3	; Increment the string index.
	pla		; Get the nibble offset back.
	bra @loop	; Keep looping.
@end:
	and #0		; Reset A.
	sta strbuf, x	; Null terminate the string buffer.
	tax		; Reset X.
	lea strbuf	; Print the string buffer.
;	jsr print_str	;
	jsr print_sfast	; Use the faster, but less robust print string routine.
	rts		; End of print_lo.
;@end:
;	lda #0		; Null terminate the string buffer.
;	sta strbuf, x	;
;	tax		; Reset X.
;	lea strbuf	; Print the string buffer.
;	jsr print_str	;
;	rts		; End of print_lo.


print_chunk:
	ldx #0		; Reset X.
	phy.w		; Preserve the screen buffer index.
	txy		; Copy the byte index to it.
@loop:
	and #0		; Reset A.
	ldx #2		; Set the digit count to 2.
	lda (idx0), y	; Get the byte at that address.
	jsr print_hex	; Print the byte.
	lda.w (ptr3)	; Get the two digits.
	ldx idx3	; Get the string index.
	sta.w strbuf, x	; Save it in the string buffer.
	inc idx3	; Increment the string index twice.
	inc idx3	;
	ldx idx3	; Get the string index.
	iny		; Increment the byte index.
	cpy #$10	; Have we read 16 bytes?
	beq @end	; Yes, so we're done.
	lda #' '	; No, so add a soace to the string buffer.
	sta strbuf, x	; Save it in the string buffer.
	inc idx3	; Increment the string index.
	bra @loop	; Keep looping.
@end:
	ply.w		; Get the screen buffer index back.
	inx		; Increment the index by one.
	and #0		; Null terminate the string.
	sta strbuf, x	;
	tax		; Reset X.
	sta idx3	; Clear the string index.
	rts		; End of print_chunk.


print_hex:
	pha.q		; Preserve the hex value.
	and #0		; Reset A.
	ldb #1		; Set the second pointer
	lda.w #hex_char	; to the start of hex character table.
	jsr set_ptr	;
	inb		; Set the third pointer
	lda.d #hex_str	; to the end of hex string buffer.
	clc		; Do a non carrying add.
	adc #$10	;
	jsr set_ptr	;
	ldb #0		; Reset B.
	pla.q		; Get the hex value back.
@loop:
	pha.q		; Preserve the hex value.
	and #$F		; Mask the lowest nibble.
	phy.w		; Preserve the screen buffer position.
	tay		; Get the index for the hex digit.
	lda (ptr2), y	; Get the hex digit.
	dec ptr3	; Decrement the string pointer.
	sta (ptr3)	; Save the hex digit character in the string.
	ply.w		; Get back the screen buffer position.
	pla.q		; Get the hex value back.
@isauto:
	cpx #1		; Is the digit count less than one?
	bcc @auto	; Yes, so don't decrement the digit count.
	dex		; No, but was the digit count zero, when decremented?
	beq @end	; Yes, so we're done.
	bra @next	; No, so get the next nibble.
@auto:
	ldb #1		; Enable auto digit count.
@next:
	lsr #4		; Is the next nibble, a zero?
	beq @isauto1	; Yes, so check if auto digit count is enabled.
	bra @loop	; No, so print the next digit.
@isauto1:
	cpb #1		; Is auto digit count enabled?
	beq @end	; Yes, so we're done.
	bra @loop	; No, so keep printing more digits.
@end:
	rts		; End of print_hex.


charcpy:
	ldx idx3	; Get the string index.
	sta strbuf, x	; Save it in the string buffer.
	inc idx3	; Increment the string index.
	rts		; End of charcpy.


strcmpg:
	ldb.w #strcmp	; Get the address of strcmp.
	phb.q		; Use it for an indirect call.
	ldb.q ptr	; Get the first pointer.
	bra gargs	; Jump to the argument handler.
strcaseg:
	ldb.w #strccmp	; Get the address of strcasecmp.
	phb.q		; Use it for an indirect call.
	ldb.q ptr	; Get the first pointer.
	bra gargs	; Jump to the argument handler.
gargs:
	phb.q		; Use the pointer in B as the first arg.
	pha.q		; Use the value in A as the second arg.
	and #0		; reset a.
	tab		; reset b.
	jsr (sp+17)	; call the pushed routine.
	tab		; Preserve the return value.
	pla.q		; Get the second arg back.
	pla.q		; Get the first arg back.
	pla.q		; Get the pushed routine back.
	tba		; Get the return value back.
	rts		; End of gargs.


strtoullg:
	ldb.q ptr3	; Get the third pointer.
	phb.q		; Push the first arg.
	pha		; Push the second arg.
	and #0		; Reset A.
	tab		; Reset B.
	jsr strtoull	; Call strtoull.
	tab		; Preserve the return value.
	pla		; Get the second arg back.
	pla.q		; Get the first arg back.
	tba		; Get the return value back.
	pha.q		; Preserve the return value.
	and #0		; Reset A.
	tab		; Reset B.
	pla.q		; Get the return value back.
	rts		; End of strtoullg.


isdelm2:
	ldx #0		; Reset X.
@loop:
	ldb dtab2, x	; Get the compare value.
	beq @other	; We hit the end of the table, so check for the others.
	cmp b		; Are they the same?
	beq @r1		; Yes, so return 1.
	inx		; No, so increment the table index.
	bra @loop	; Keep looping.
@other:
	ldx #0		; Reset X.
	cmp #0		; Is this a null terminator?
	beq @r1		; Yes, so return 1.
	cmp #'\t'	; No, but is it a tab?
	beq @r2		; Yes, so return 2.
	cmp #' '	; No, but is it a space?
	beq @r2		; Yes, so also return 2.
@r0:
	lda #0		; Return 0.
	rts		; End of isdelm2.
@r1:
	ldx #0		; Reset X.
	lda #1		; Return 1.
	rts		; End of isdelm2.
@r2:
	lda #2		; Return 2.
	rts		; End of isdelm2.


isdelm:
	ldx #0		; Reset X.
@loop:
	ldb dtab, x	; Get the compare value.
	beq @other	; We hit the end of the table, so check for the others.
	cmp b		; Are they the same?
	beq @rshft	; Yes, so return 1 << index.
	inx		; No, so increment the table index.
	bra @loop	; Keep looping.
@other:
	ldx #0		; Reset X.
	cmp #0		; Is this a null terminator?
	beq @rshft	; Yes, so return 1.
	ldx #4		; No, so set the shift amount to 4.
	cmp #'\t'	; Is this a tab?
	beq @rshft	; Yes, so return 16.
	ldx #0		; No, so reset X.
@r0:
	lda #0		; Return 0.
	rts		; End of isdelm.
@rshft:
	lda #1		; Set up the bitshift.
	phx		; Push the shift value to stack.
	lsl sp+1	; Return 1 << X.
	plx		; Pull the shift value off the stack.
	ldx #0		; Reset X.
	rts		; End of isdelm.


isesc:
	ldy.w idx0	; Get the string index.
	lda (ptr), y	; Get the current character.
	cmp #'\\'	; Is it a backslash?
	bne @false	; No, so return false.
@dec:
	dey		; Decrement the string index.
	lda (ptr), y	; Get the current character.
	iny		; Set the string index back.
	cmp #'\\'	; Is it a backslash?
	beq @false	; Yes, so return false.
	lda #1		; No, so return true.
	rts		; End of isesc.
@false:
	and #0		; Return false.
	rts		; End of isesc.


is_altok:
	sec		; Do a non borrowing subtract.
	sbc #12		; Subtract 12 from the token.
	and #$FF	; Make sure the value is 8 bits.
	cmp #4		; Is the token in between PTOK_B, and PTOK_P?
	bcc @r1		; Yes, so return 1.
	beq @r1		;
@r0:
	lda #0		; Return 0.
	rts		; End of is_altok.
@r1:
	lda #1		; Return 1.
	rts		; End of is_altok.


get_ptok:
	ldx #0		; Reset X.
	jsr tolower	; Conver the character to lowercase.
@loop:
	ldb ptok_tab, x	; Get the compare value.
	beq @other	; We hit the end of the table, so check for the others.
	cmp b		; Are they the same?
	beq @rtab	; Yes, so return X.
	inx		; No, so increment the table index.
	bra @loop	; Keep looping.
@rtab:
	txa		; Return X.
	rts		; End of get_ptok.
@other:
	tab		; Preserve the character.
	jsr isdigit	; Is this character a digit?
	bne @rnum	; Yes, so return PTOK_NUM.
	tba		; No, so get the character back.
	jsr islower	; Is it an alphabetical character?
	bne @ralph	; Yes, so return PTOK_ALPH.
	lda #PTOK_OTHR	; No, so return PTOK_OTHR.
	rts		; End of get_ptok.
@rnum:
	lda #PTOK_NUM	; Return PTOK_NUM.
	rts		; End of get_ptok.
@ralph:
	lda #PTOK_ALPH	; Return PTOK_ALPH.
	rts		; End of get_ptok.


get_ctrlidx:
;	phe.q		; Preserve E.
;	cmp #$7F	; Is this a delete character?
;	beq @del	; Yes, so return the same value as backspace.
;	sec		; Do a non borrowing subtract.
;	sbc #8		; Subtract 8 from the character, to get the index.
	sub #8		; Subtract 8 from the character, to get the index.
	tax		; Copy the index to X.
	and #0		; Reset A.
	cpx #19		; Are we within the range of the table?
	lea ct_rtb, x	; Get the address of the value to return.
	lcc (e)		; Read from the table if we're within the range of the table.
	leq (e)		;
	cmp #$7F	; Is this a delete character?
	leq #2		; Return 2 if this is the delete character.
;	bcc @get_rtval	; Yes, so get the return value from the table.
;	beq @get_rtval	;
;	ple.q		; Restore E.
	rts		; End of get_ctrlidx.
;@get_rtval:
;	lda ct_rtb, x	; Get the return value from the table.
;	rts		; End of get_ctrlidx.
;@del:
;	lda #2		; Return 2.
;	rts		; End of get_ctrlidx.


findramend:
	phx.q		; Preserve X.
	and #0		; Reset A.
	lda #MAGIC	; Set A to a magic number.
@loop:
	ldx (e)		; Preserve the value.
	sta (e)		; Write the magic number to the current end of RAM.
	cmp (e)		; Is the value in RAM, the same as the magic number we wrote?
	bne @moveback	; No, so move back until we find the last writable memory location.
	stx (e)		; Yes, so restore the previous value.
	ade.w #$4000	; Increment the end of RAM pointer by 16K.
	bra @loop	; Keep looping.
@moveback:
	dee		; Decrement the end of RAM pointer.
	ldx (e)		; Preserve the value.
	sta (e)		; Write the magic number to the current end of RAM.
	cmp (e)		; Is the value in RAM, the same as the magic number we wrote?
	bne @moveback	; No, so keep looping.
	stx (e)		; Yes, so restore the previous value.
@end:
	phe.q		; Return the end of RAM pointer.
	pla.q		;
	plx.q		; Restore X.
	rts		; End of findramend.


print_sfast:
;	inc step	;
	pea (buffer), y	; Push the address of the cursor's postion in the screen buffer to the stack.
@loop:
	lda (e)		; Get the character.
	beq @end	; We've hit the end of the string, so we're done.
	cmp #'\n'	; Did we get a newline?
	beq @nl		; Yes, so move the cursor to the next line.
	sta (sp+1)	; Print the character to the screen buffer.
	sta scr		; Print the character to the screen.
	inc scr_col	; Move the cursor left by one character.
	ine		; Increment the string pointer.
	inc.q sp+1	; Increment the screen buffer pointer.
	bra @loop	; Keep looping.
@nl:
	stz scr_col	; Move the cursor to the start of the line.
	inc scr_row	; Move the cursor down by one line.
	bra @loop	; Keep looping.
@end:
	ads #8		; Cleanup the stack frame.
	rts		; End of print_sfast.