; 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.