mirror of
https://github.com/nathanriggs/AppleIIAsm-Collection.git
synced 2024-06-08 01:29:28 +00:00
278 lines
12 KiB
NASM
278 lines
12 KiB
NASM
*
|
|
*``````````````````````````````*
|
|
* TXTMORE (NATHAN RIGGS) *
|
|
* THIS SUBROUTINE PRINTS A *
|
|
* NULL-TERMINATED STRING TO *
|
|
* THE SCREEN, WRAPPING THE *
|
|
* TEXT FOR A GIVEN LENGTH OF *
|
|
* EACH LINE. AFTER A GIVEN *
|
|
* NUMBER OF LINES ARE *
|
|
* PRINTED, SCROLLING PAUSES *
|
|
* WHILE THE READER CATCHES *
|
|
* UP. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* ZPW1 = STRING ADDRESS (2B) *
|
|
* ZPW2 = LINE LENGTH *
|
|
* ZPB1 = VERTICAL SCROLL *
|
|
* LENGTH TO PAUSE *
|
|
* *
|
|
* DESTROYS: NZCIDV *
|
|
* ^^^ ^ *
|
|
* *
|
|
* CYCLES: 466+ *
|
|
* SIZE: 452 BYTES *
|
|
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
|
|
*
|
|
]ADDR EQU ZPW1 ; STRING ADDRESS
|
|
]LEN EQU ZPW2 ; MAXIMUM LENGTH OF STRING
|
|
]SCROLL EQU ZPB1 ; MAXIMUM LINES BEFORE PAUSING
|
|
*
|
|
]START EQU ZPW3 ; STARTING POINT OF CURRENT LINE
|
|
]END EQU ZPW4 ; ENDING OF CURRENT LINE
|
|
]PTR EQU ZPW5 ; POINTER BETWEEN START AND END
|
|
]LAST EQU ZPW6 ; LOCATION OF NULL TERMINATION
|
|
]LINES EQU VARTAB ; LINE COUNTER
|
|
]LSPACE EQU VARTAB+2 ; LAST SPACE FOUND
|
|
*
|
|
TXTMORE
|
|
*
|
|
** INIT
|
|
*
|
|
LDA ]ADDR ; {2C2B} GET STRING ADDRESS LOW BYTE
|
|
STA ]START ; {3C2B} STORE AS START ADDRESS LOW BYTE
|
|
LDA ]ADDR+1 ; {2C2B} GET STRING ADDRESS HIGH BYTE
|
|
STA ]START+1 ; {3C2B} STORE AS START ADDRESS HIGH BYTE
|
|
*
|
|
LDA ]ADDR ; {2C2B} LOAD STRING ADDRESS LOW BYTE
|
|
CLC ; {2C1B} CLEAR CARRY
|
|
ADC ]LEN ; {2C2B} ADD LINE LENGTH
|
|
STA ]END ; {3C2B} STORE AS LINE END ADDR LOW BYTE
|
|
LDA ]ADDR+1 ; {2C2B} LOAD ADDRESS HIGH BYTE
|
|
ADC #0 ; {2C2B} ADD ZERO FOR CARRY
|
|
STA ]END+1 ; {2C3B} STORE AS LINE END ADDR HIGH BYTE
|
|
*
|
|
LDA #0 ; {2C2B} CLEAR REGISTERS
|
|
TAY ; {2C1B}
|
|
TAX ; {2C1B}
|
|
*
|
|
** FIRST, CHECK LINE FOR NULL TERMINATION
|
|
*
|
|
:ENTER
|
|
LDA ]START ; {2C2B} FIRST, COPY START INTO
|
|
STA ]PTR ; {3C32} OUR POINTER ADDRESS
|
|
LDA ]START+1 ; {2C2B} BOTH LOW BYTE AND HIGH BYTE
|
|
STA ]PTR+1 ; {3C2B}
|
|
*
|
|
** CHECK FOR NULL VALUE IN STRING
|
|
**
|
|
** LOOP WILL EXIT ONLY IF #$00 IS FOUND AT POINTER
|
|
** POSITION OR THE POINTER ADDRESS EQUALS THE ENDING ADDRESS
|
|
*
|
|
:NULCHK
|
|
LDY #0 ; {2C2B}
|
|
LDA (]PTR),Y ; {6C2B} LOAD CHAR AT CURRENT POINTER
|
|
CMP #0 ; {2C2B} COMPARE TO NULL
|
|
BEQ :FNDNULL ; {3C2B} IF NULL THEN GOTO :FNDNULL
|
|
LDA ]PTR+1 ; {2C2B} CHECK IF HIGH BYTE OF POINTER IS
|
|
CMP ]END+1 ; {2C2B} EQUAL TO HIGH BYTE OF ENDING
|
|
BNE :CNTLP1 ; {3C2B} IF NOT, CONTINUE LOOP
|
|
LDA ]PTR ; {2C2B} IF SO, CHECK LOW BYTE OF POINTER
|
|
CMP ]END ; {2C2B} TO SEE IF IT MATCHES END LOW BYTE
|
|
BEQ :NULCHKX ; {3C2B} IF IT DOES, THEN EXIT NULL FINDER
|
|
:CNTLP1
|
|
LDA ]PTR ; {2C2B} NULL NOT FOUND AND LOOP NOT DONE
|
|
CLC ; {2C1B} SO ADD ONE TO THE POINTER
|
|
ADC #1 ; {2C2B} LOW BYTE
|
|
STA ]PTR ; {3C2B}
|
|
LDA ]PTR+1 ; {2C2B} AND ADD CARRY TO THE HIGH BYTE
|
|
ADC #0 ; {2C2B} IF NEEDED
|
|
STA ]PTR+1 ; {3C2B}
|
|
JMP :NULCHK ; {3C3B} AND CONTINUE LOOP
|
|
*
|
|
** NULL VALUE HAS BEEN FOUND, SO STORE POINTER AND
|
|
** GO TO PRINTING LAST LINE OF THE STRING
|
|
*
|
|
:FNDNULL
|
|
LDA ]PTR ; {2C2B} COPY POINTER ADDRESS LOW BYTE
|
|
STA ]LAST ; {3C2B} TO THE ]LAST VAR FOR FINAL PRINT
|
|
LDA ]PTR+1 ; {2C2B} DO THE SAME WITH THE HIGH BYTE
|
|
STA ]LAST+1 ; {3C2B}
|
|
JMP :PRNLAST ; {3C3B} JUMP TO FINAL PRINTING
|
|
*
|
|
** END OF CHECKING FOR NULL. NO NULL WAS FOUND
|
|
*
|
|
:NULCHKX
|
|
*
|
|
** NOW FIND THE LAST SPACE BETWEEN ]START POSITION
|
|
** AND THE ]END POSITION BY COUNTING BACKWARDS UNTIL
|
|
** A SPACE IS FOUND
|
|
*
|
|
LDA ]END ; {2C2B} LOAD LAST ADDRESS LOW BYTE
|
|
STA ]PTR ; {3C2B} STORE IN POINTER
|
|
LDA ]END+1 ; {2C2B} LOAD THE HIGH BYTE AND
|
|
STA ]PTR+1 ; {3C2B} STORE POINTER HIGH BYTE
|
|
*
|
|
:SPCLOOP
|
|
LDY #0 ; {2C2B} CLEAR .Y INDEX
|
|
LDA (]PTR),Y ; {6C2B} LOAD CHAR AT CURRENT POINTER
|
|
CMP #" " ; {2C2B} COMPARE CHAR TO SPACE
|
|
BEQ :FNDSPC ; {3C2B} IF EQUAL, THEN GOTO :FNDSPC
|
|
LDA ]PTR ; {2C2B} OTHERWISE LOAD POINTER LOW BYTE
|
|
SEC ; {2C1B} SET CARRY
|
|
SBC #1 ; {2C2B} SUBTRACT 1 FROM ADDRESS
|
|
STA ]PTR ; {3C2B} STORE BACK IN LOW BYTE
|
|
LDA ]PTR+1 ; {2C2B} LOAD POINTER HIGH BYTE
|
|
SBC #0 ; {2C2B} SUBTRACT CARRY, IF NEEDED
|
|
STA ]PTR+1 ; {3C2B} STORE BACK IN HIGH BYTE
|
|
JMP :SPCLOOP ; {3C3B} LOOP UNTIL A SPACE IS FOUND
|
|
*
|
|
** THE LAST SPACE BETWEEN ]START AND ]END HAS BEEN FOUND!
|
|
*
|
|
:FNDSPC
|
|
LDA ]PTR ; {2C2B} LOAD LOW BYTE OF CURRENT PTR
|
|
STA ]LSPACE ; {3C2B} AND STORE INTO LAST SPACE VAR
|
|
STA ]END ; {3C2B}
|
|
LDA ]PTR+1 ; {2C2B} AND THEN DO THE SAME FOR THE
|
|
STA ]LSPACE+1 ; {3C2B} HIGH BYTE
|
|
STA ]END+1 ; {3C2B}
|
|
*
|
|
** RESET POINTER AGAIN
|
|
*
|
|
LDA ]START ; {2C2B} LOAD STARTING POINT
|
|
STA ]PTR ; {3C2B} PACK INTO POINTER ADDRESS
|
|
LDA ]START+1 ; {2C2B} BOTH LOW BYTE AND
|
|
STA ]PTR+1 ; {3C2B} HIGH BYTE
|
|
*
|
|
** NOW PRINT THE LINE
|
|
*
|
|
:PRNLP ; PRINTING LOOP
|
|
LDA ]PTR+1 ; {2C2B} LOAD HIGH BYTE OF POINTER
|
|
CMP ]LSPACE+1 ; {2C2B} COMPARE TO HIGH BYTE OF LAST SPACE
|
|
BNE :PRNLP0 ; {3C2B} IF !=, THEN SKIP TO INNER LOOP
|
|
LDA ]PTR ; {2C2B} IF =, THEN COMPARE LOW BYTES
|
|
CMP ]LSPACE ; {2C2B}
|
|
BNE :PRNLP0 ; {3C2B} IF !=, GOTO INNER LOOP
|
|
LDA ]LINES ; {2C2B} OTHERWISE, LOAD CURRENT # OF LINES
|
|
CLC ; {2C1B} CLEAR CARRY
|
|
ADC #1 ; {3C2B} ADD A LINE
|
|
STA ]LINES ; {3C2B} STORE BACK INTO LINES
|
|
LDA ]LINES+1 ; {2C2B} LOAD HIGH BYTE OF LINES
|
|
ADC #0 ; {3C2B} ADD CARRY
|
|
STA ]LINES+1 ; {3C2B} STORE BACK INTO HIGH BYTE
|
|
LDA #$8D ; {2C2B} LOAD A LINE FEED CHARACTER
|
|
JSR COUT ; {6+C3B} SEND TO COUT (PRESS RETURN)
|
|
JMP :XXX ; {3C3B} SKIP REPRINTING SPACE
|
|
:PRNLP0 ; INNER PRINT LOOP
|
|
LDY #0 ; {2C2B} RESET .Y (JUST IN CASE?)
|
|
LDA (]PTR),Y ; {6C2B} LOAD CHARACTER AT POINTER
|
|
JSR COUT ; {6+C2B} PRINT CHARACTER
|
|
LDA (]PTR),Y ; {2C2B} LOAD AGAIN, JUST IN CASE
|
|
CMP #$8D ; {2C2B} IF CHAR != LINE FEED
|
|
BNE :XXX ; {3C2B} SKIP LINE ADDING
|
|
LDA ]LINES ; {2C2B} ELSE LOAD LINES COUNTER
|
|
CLC ; {2C1B} CLEAR CARRY
|
|
ADC #1 ; {3C2B} ADD A LINE
|
|
STA ]LINES ; {3C2B} STORE BACK INTO LOW BYTE
|
|
LDA ]LINES+1 ; {2C2B} LOAD HIGH BYTE OF LINES
|
|
ADC #0 ; {3C2B} ADD CARRY
|
|
STA ]LINES+1 ; {3C2B} STORE BACK INTO HIGH BYTE
|
|
LDA ]SCROLL ; {2C2B} LOAD MAX NUMBER OF LINES
|
|
CMP #0 ; {2C2B} COMPARE TO 0
|
|
BNE :XXX ; {3C2B} IF MAX != 0, SKIP PAUSING
|
|
:WLP LDA ]KYBD ; {2C2B} CHECK FOR KEYSTROKE
|
|
BPL :WLP ; {3C2B} IF .A HAS CLEAR HIGH BYTE
|
|
AND #$7F ; {2C2B} THEN NOT PRESSED; LOOP UNTIL
|
|
STA ]STROBE ; {3C2B} CLEAR THE KEYBOARD STROBE
|
|
LDA #0 ; {2C2B} CLEAR .A
|
|
STA ]LINES ; {3C2B} RESET LINE COUNTER
|
|
STA ]LINES+1 ; {3C2B} RESET LINE COUNTER HIGH BYTE
|
|
*
|
|
:XXX
|
|
LDA ]PTR+1 ; {2C2B} LOAD POINTER HIGH BYTE
|
|
CMP ]END+1 ; {2C2B} COMPARE TO ENDING HIGH BYTE
|
|
BNE :CNTPRN ; {3C2B} IF !=, CONTINUE PRINTING
|
|
LDA ]PTR ; {2C2B} ELSE LOAD POINTER LOW BYTE
|
|
CMP ]END ; {2C2B} COMPARE TO ENDING LOW BYTE
|
|
BEQ :PRNLPX ; {3C2B} IF EQUAL, EXIT PRINTING
|
|
:CNTPRN
|
|
LDA ]PTR ; {2C2B} LOAD POINTER LOW BYTE
|
|
CLC ; {2C1B} CLEAR CARRY
|
|
ADC #1 ; {3C2B} INCREASE ADDRESS BY ONE
|
|
STA ]PTR ; {3C2B} STORE BACK INTO LOW BYTE
|
|
LDA ]PTR+1 ; {2C2B} LOAD POINTER HIGH BYTE
|
|
ADC #0 ; {3C2B} ADD THE CARRY
|
|
STA ]PTR+1 ; {3C2B} STORE BACK INTO HIGH BYTE
|
|
JMP :PRNLP ; {3C3B} RESTART THE PRINTING LOOP
|
|
*
|
|
** FINISHED PRINTING LINE, SO NOW SWAP POINTER VARIABLES
|
|
** TO MOVE ON TO THE NEXT SECTION
|
|
*
|
|
:PRNLPX ; END PRINTING
|
|
LDA ]SCROLL ; {2C2B} LOAD MAX LINES
|
|
CMP ]LINES ; {2C2B} COMPARE TO CURRENT LINES
|
|
BNE :SWAPPP ; {3C2B} IF !=, SKIP WAIT
|
|
:WLP3 LDA ]KYBD ; {2C2B} WAIT FOR A KEYPRESS
|
|
BPL :WLP3 ; {3C2B}
|
|
AND #$7F ; {2C2B}
|
|
STA ]STROBE ; {3C2B} RESET KEYBOARD STROBE
|
|
LDA #0 ; {2C2B} RESET .A
|
|
STA ]LINES ; {3C2B} RESET LINE COUNTER LOW BYTE
|
|
STA ]LINES+1 ; {3C2B} RESET LINE COUNTER HIGH BYTE
|
|
:SWAPPP
|
|
LDA ]END ; {2C2B} LOAD ENDING ADDRESS LOW BYTE
|
|
CLC ; {2C1B} CLEAR CARRY
|
|
ADC #1 ; {3C2B} INCREASE ADDRESS BY ONE
|
|
STA ]END ; {3C2B} STORE BACK INTO LOW BYTE
|
|
LDA ]END+1 ; {2C2B} LOAD ENDING HIGH BYTE
|
|
ADC #0 ; {3C2B} ADD THE CARRY
|
|
STA ]END+1 ; {3C2B} STORE BACK INTO HIGH BYTE
|
|
*
|
|
LDA ]END ; {2C2B} RELOAD ENDING LOW BYTE
|
|
STA ]START ; {3C2B} STORE IN STARTING LOW BYTE
|
|
LDA ]END+1 ; {2C2B} RELOAD ENDING HIGH BYTE
|
|
STA ]START+1 ; {3C2B} STORE IN STARTING HIGH BYTE
|
|
LDA ]END ; {2C2B} RELOAD ENDING LOW BYTE
|
|
CLC ; {2C1B} CLEAR CARRY
|
|
ADC ]LEN ; {3C2B} ADD MAX LENGTH TO ENDING
|
|
STA ]END ; {3C2B} STORE BACK INTO LOW BYTE
|
|
LDA ]END+1 ; {2C2B} LOAD ENDING HIGH BYTE
|
|
ADC #0 ; {3C2B} ADD THE CARRY
|
|
STA ]END+1 ; {3C2B} STORE BACK INTO HIGH BYTE
|
|
JMP :ENTER ; {3C3B} BACK TO BEGINNING OF SUBROUTINE!
|
|
:PRNLAST
|
|
LDA ]START ; {2C2B} LOAD STARTING ADDRESS
|
|
STA ]PTR ; {3C2B} STORE LOW BYTE INTO POINTER LOW
|
|
LDA ]START+1 ; {2C2B} LOAD STARTING HIGH BYTE
|
|
STA ]PTR+1 ; {3C2B} STORE IN POINTER HIGH BYTE
|
|
:LASTLP
|
|
LDY #0 ; {2C2B} CLEAR .Y JUST IN CASE
|
|
LDA (]PTR),Y ; {6C2B} LOAD CHARACTER
|
|
JSR COUT ; {6+C3B} SEND CHARACTER TO COUT
|
|
LDA ]PTR+1 ; {2C2B} LOAD POINTER HIGH BYTE
|
|
CMP ]LAST+1 ; {2C2B} COMPARE IT TO NULL POINTER POS
|
|
BNE :LASTCNT ; {3C2B} IF !=, THEN LOOP
|
|
LDA ]PTR ; {2C2B} LOAD POINTER LOW BYTE AGAIN
|
|
CMP ]LAST ; {2C2B} COMPARE IT TO NULL POSITION LOW
|
|
BEQ :EXIT ; {3C2B} IF EQUAL, THEN EXIT
|
|
:LASTCNT
|
|
LDA ]PTR ; {2C2B} OTHERWISE, LOAD POINTER LOW BYTE
|
|
CLC ; {2C1B} CLEAR CARRY
|
|
ADC #1 ; {3C2B} ADD ONE TO ADDRESS
|
|
STA ]PTR ; {3C2B} STORE LOW BYTE AGAIN
|
|
LDA ]PTR+1 ; {2C2B} LOAD POINTER HIGH BYTE
|
|
ADC #0 ; {3C2B} ADD THE CARRY
|
|
STA ]PTR+1 ; {3C2B} STORE BACK IN POINTER HIGH BYTE
|
|
JMP :LASTLP ; {3C3B} LOOP AGAIN UNTIL LAST IS REACHED
|
|
:EXIT
|
|
LDA ]SCROLL ; {2C2B} LOAD MAX LINES
|
|
CMP #0 ; {2C2B} IF = 0, THEN JUST EXIT
|
|
BEQ :EXIT2 ; {3C2B}
|
|
:WLPZ LDA ]KYBD ; {2C2B} OTHERWISE, PAUSE FOR KEYPRESS
|
|
BPL :WLPZ ; {3C2B} BEFORE LEAVING SUBROUTINE
|
|
AND #$7F ; {2C1B}
|
|
STA ]STROBE ; {3C2B} CLEAR KEYBOARD STROBE
|
|
:EXIT2
|
|
RTS ; {6C1B}
|