summaryrefslogtreecommitdiff
path: root/programs/sub-suite/utils.s
blob: 3621051541b9a88496101ed54dbc0714b177ca78 (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
; Utility subroutines for SuBAsm.

print_hi:
	phb.q			; Preserve B.
	sbs #$10		; Make room for the hex string buffer.
	and #0			; Reset A.
	mov b, d		; Get the string buffer pointer.
	mov (b), #'$'		; Print the hex delimiter to the string buffer.
	inb			; Increment the string buffer pointer.
	lea d, (sp+1)		; Get the address of the hex string buffer.
	mov f, #$10		; Set digit count to 16.
	jsr print_hex		; Print the address.
	mov.q (b), (d)		; Print the lower half of the hex string to the string buffer.
	mov.q (b+8), (d+8)	; Print the upper half of the hex string to the string buffer.
	add b, #$10		; Add 16 to the index.
	mov.w (b), #': '	; Print a colon, and space to the string buffer.
	add b, #2		; Add two to the string buffer pointer.
	tba			; Return the string buffer pointer after the printed string.
	ads #$10		; Cleanup the stack frame.
	plb.q			; Restore B.
	rts			; End of print_hi.


print_lo:
	pha.q			; Preserve A.
	phb.q			; Preserve B.
	phx.q			; Preserve X.
	sbs #$33		; Make room for the hex string buffer, and the normal string buffer.
	and #0			; Reset A.
	tab			; Reset B.
	lea d, (sp+1)		; Get the address of the hex string buffer.
	lea x, (sp+3)		; Get the address of the string buffer.
@loop:
	lea f, 2		; Set the digit count to two.
	mov s, b		; Get the low nibble offset.
	jsr print_hex		; Print the low nibble offset.
	mov.w (x), (d)		; Place the hex digits in the string buffer.
	add x, #2		; Add two to the string buffer pointer.
	inb			; Increment the nibble offset.
	cpb #$10		; Are we at the last offset?
	bcs @end		; Yes, so we're done.
@loop1:
	mov (x), #' '		; No, so add a space to the string buffer.
	inx			; Increment the string buffer pointer.
	bra @loop		; Keep looping.
@end:
	mov (x), #0		; Null terminate the string buffer.
	lea d, (sp+3)		; Get the address of the string buffer.
	lea s, (buffer)+y	; Get the address of the screen buffer, at the current cursor position.
;	jsr print_str		; Print the string buffer.
	jsr print_sfast		; Use the faster, but less robust print string routine.
	ads #$33		; Cleanup the stack frame.
	plx.q			; Restore X.
	plb.q			; Restore B.
	pla.q			; Restore A.
	rts			; End of print_lo.

print_chunk:
	pha.q			; Preserve A.
	phb.q			; Preserve B.
	phx.q			; Preserve X.
	phy.q			; Preserve Y.
	sbs #16			; Make room for the hex string buffer.
	and #0			; Reset A.
	tay			; Reset Y.
	ldy #2			; Set the number of 8 byte chunks to read to 2.
	mov x, d		; Get the address of the string buffer.
	mov b, s		; Get the starting address.
	lea d, (sp+1)		; Get the address of the hex string buffer.
;	xor s, s		; Reset S.
@print_hex:
	lda #16			; Set the hex string index to 16.
	mov f, a		; Set the digit count to 16.
	dey			; Decrement the chunk count.
	bng @end		; The chunk count is negative, so we're done.
	mov.q s, (b)		; Read 8 bytes from that address.
	jsr print_hex		; Print 8 bytes.
	add b, #8		; Add 8 to the address.
@loop:
	sub #2			; Subtract two from the hex string index.
	mov.w (x), (d+a)	; Print the hex string to the string buffer.
	mov (x+2), #' '		; Print a space to the string buffer.
	add x, #3		; Add three to the string buffer pointer.
	cmp #0			; Did we print 8 bytes?
	beq @print_hex		; Yes, so read 8 more bytes.
	bra @loop		; No, so keep looping.
@end:
	mov (x-1), #0		; Null terminate the string.
	ads #16			; Cleanup the stack frame.
	ply.q			; Restore Y.
	plx.q			; Restore X.
	plb.q			; Restore B.
	pla.q			; Restore A.
	rts			; End of print_chunk.


print_hex:
	pha.q		; Preserve A.
	phb.q		; Preserve B.
	phx.q		; Preserve X.
	phy.q		; Preserve Y.
	lea b, hex_char	; Get the address of the hex character table.
	mov a, f	; Get the digit count.
	set x, eq	; Set the auto digit count flag if so.
	lne #16		; Also set the digit count to 16 if so.
	cmp #17		; Is the digit count greater than 16?
	lcs #16		; Set the digit count to 16 if so.
	add d, a	; Add the string pointer with the digit count.
@loop:
	mov y, s	; No, so mask the low nibble of the value.
	and y, #$F	;
	dec d		; Decrement the string pointer.
	mov (d), (b+y)	; Place the hex digit character in the string.
	lsr s, #4	; Get the next nibble.
	bne @loop1	; No, so decrement the digit count.
@isauto:
	cpx #1		; Is the auto digit count flag set?
	beq @end	; Yes, so we're done.
@loop1:
	dec		; Decrement the digit count.
	bne @loop	; The digit count is non zero, so keep looping.
@end:
	ply.q		; Restore Y.
	plx.q		; Restore X.
	plb.q		; Restore B.
	pla.q		; Restore A.
	rts		; End of print_hex.


strcmpg:
	lea strcmp	; Get the address of strcmp.
	mov.q d, ptr	; Get the first pointer.
	bra gargs	; Jump to the argument handler.
strcaseg:
	lea strcasecmp	; Get the address of strcasecmp.
	mov.q d, ptr	; Get the first pointer.
	bra gargs	; Jump to the argument handler.
gargs:
	mov s, a	; Use the value in A as the second arg.
	and #0		; Reset a.
	tab		; Reset b.
	jsr (e)		; Call the pushed routine.
	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:
	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.
	rts		; End of get_ctrlidx.


findramend:
	and #0		; Reset A.
@loop:
	mov a, (d)	; Preserve the value.
	mov (d), #MAGIC	; Write the magic number to the current end of RAM.
	cmp (d), #MAGIC	; 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.
	mov (d), a	; Yes, so restore the previous value.
	add.w d, #$4000	; Increment the end of RAM pointer by 16K.
	bra @loop	; Keep looping.
@moveback:
	dec d		; Decrement the end of RAM pointer.
	mov a, (d)	; Preserve the value.
	mov (d), #MAGIC	; Write the magic number to the current end of RAM.
	cmp (d), #MAGIC	; Is the value in RAM, the same as the magic number we wrote?
	bne @moveback	; No, so keep looping.
	mov (d), a	; Yes, so restore the previous value.
@end:
	mov a, d	; Return the end of RAM pointer.
	rts		; End of findramend.

; get_index: Get the index of a given character from a string.
; Input: D = Pointer to string. S = Character to look for. F = Indexing mode.
; Output: A = Index of the character in the string, if found.
; Caller preserved registers: D, S, F.
; Callee preserved registers: B.
;
; Indexing modes:
; 0 = Increment mode.
; 1 = Boolean mode.
; 2 = Increment mode, plus one.

get_index:
	phb.q		; Preserve B.
	and #0		; Reset A.
	tab		; Reset B.
	cmp f, #2	; Is the index starting at one?
	leq #1		; Set the index to one if so.
	dec		; Decrement the index to account for incrementing at the start.
@loop:
	inc		; Increment the index.
	mov b, (d+a)	; Are we at the end of the string?
	beq @is_bool	; Yes, so check if we're using boolean mode.
@@loop:
	cmp s, b	; Is this character the same as the one we're looking for?
	bne @loop	; No, so keep looping.
@is_bool:
	and f, f	; Are we using boolean mode?
	beq @end	; No, so we're done.
@bool:
	cmp s, b	; Is this character the same as the one we're looking for?
	set a, eq	; Set the index to true if so.
@end:
	plb.q		; Restore B.
	rts		; End of get_index.


print_sfast:
	pha.q			; Preserve A.
	and #0			; Reset A.
@loop:
	cmp (d+a), #0		; Did we hit the end of the string?
	beq @end		; Yes, so we're done.
	mov (s+a), (d+a)	; No, so print the character to the buffer.
	mov scr, (d+a)		; Print the character to the screen.
	inc			; Increment the index.
	bra @loop		; Keep looping.
@end:
	pla.q			; Restore A.
	rts			; End of print_sfast.