mirror of
https://github.com/nathanriggs/AppleIIAsm-Collection.git
synced 2024-11-27 12:49:27 +00:00
9b12b6fd9b
- getting ready for major changes for 0.6.0. - be sure to download the 0.5.0 release to ensure proper functionality, as these rountines will not work together in the SRC or BIN folder during the transition - Beginning to significantly alter documentation
504 lines
18 KiB
NASM
504 lines
18 KiB
NASM
*
|
|
*``````````````````````````````*
|
|
* LIB.REQUIRED *
|
|
* *
|
|
* LIBRARY OF REQUIRED ROUTINES *
|
|
* AS PART OF THE APPLEIIASM *
|
|
* MACRO AND SUBROUTINE LIBRARY *
|
|
* *
|
|
* AUTHOR: NATHAN RIGGS *
|
|
* CONTACT: NATHAN.RIGGS@ *
|
|
* OUTLOOK.COM *
|
|
* *
|
|
* DATE: 28-NOV-2019 *
|
|
* ASSEMBLER: MERLIN 8 PRO *
|
|
* LICENSE: APACHE 2.0 *
|
|
* OS: DOS 3.3 *
|
|
* *
|
|
* SUBROUTINES: *
|
|
* *
|
|
* __DUMP : DUMP MEMORY *
|
|
* __ERRH : HANDLE ERRORS *
|
|
* __GETRET : GET RETURN VAL *
|
|
* __P : PRINT *
|
|
* DELAYMS : DELAY MLSECS *
|
|
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
|
|
*
|
|
** LIBRARY-SPECIFIC VARIABLES
|
|
*
|
|
]RIGHT DS 1
|
|
]LEFT DS 1
|
|
]LENGTH DS 1
|
|
]A DS 1 ; REGISTER .A BACKUP
|
|
]X DS 1 ; REGISTER .X BACKUP
|
|
]Y DS 1 ; REGISTER .Y BACKUP
|
|
]C DS 1 ; CARRY FLAG BACKUP
|
|
]Z DS 1 ; ZERO FLAG BACKUP
|
|
]N DS 1 ; NEGATIVE FLAG BACKUP
|
|
]O DS 1 ; OVERFLOW FLAG BACKUP
|
|
]HEXTAB ASC "0123456789ABCDEF"
|
|
*
|
|
** LIBRARY-SPECIFIC HOOKS
|
|
*
|
|
]COUT EQU $FDF0 ; SCREEN OUTPUT ROUTINE
|
|
]KYBD EQU $C000 ; KEYBOARD INPUT
|
|
]STROBE EQU $C010 ; KEYBOARD STROBE
|
|
*
|
|
*
|
|
*``````````````````````````````*
|
|
* __DUMP: (NATHAN RIGGS) *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* .A = ADDRESS LOBYTE *
|
|
* .X = ADDRESS HIBYTE *
|
|
* .Y = NUMBER OF BYTES *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* OUTPUTS DATA LOCATED AT THE *
|
|
* SPECIFIED ADDRESS IN HEX *
|
|
* FORMAT FOR SPECIFIED NUMBER *
|
|
* OF BYTES. *
|
|
* *
|
|
* DESTROYS: NZCIDV *
|
|
* ^^^ *
|
|
* *
|
|
* CYCLES: 787+ *
|
|
* SIZE: 111 BYTES *
|
|
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
|
|
*
|
|
__DUMP
|
|
STY ]LENGTH ; ++<4C3B> LENGTH PASSED IN .Y
|
|
STA ADDR1 ; ++<3C2B> ADDRESS LOBYTE IN .A
|
|
STX ADDR1+1 ; ++<3C2B> ADDRESS HIBYTE IN .X
|
|
LDA #$8D ; ++<2C2B> LOAD CARRIAGE RETURN
|
|
JSR ]COUT ; ++<6C3B[83C]> SEND TO COUT
|
|
LDA ADDR1+1 ; ++<2C2B> GET ADDRESS HIBYTE
|
|
CLRHI ; ++<6C3B[16C]> CLEAR HIBITS
|
|
TAX ; ++<2C1B> TRANSFER TO .X
|
|
LDA ]HEXTAB,X ; ++<5C3B> LOAD HEX CHAR FROM TABLE AT .X
|
|
JSR ]COUT ; ++<6C3B[83C]> SEND TO COUT
|
|
LDA ADDR1+1 ; ++<2C2B> LOAD ADDRESS HIBYTE AGAIN
|
|
AND #$0F ; ++<2C2B> CLEAR LOBITS
|
|
TAX ; ++<2C1B> TRANSER TO .X
|
|
LDA ]HEXTAB,X ; ++<5C3B> LOAD HEX CHAR FROM TABLE AT .X
|
|
JSR ]COUT ; ++<6C3B[83C]> SENT TO COUT
|
|
LDA ADDR1 ; ++<4C3B> LOAD LOBYTE
|
|
CLRHI ; ++<[16C10B]> CLEAR HIBITS
|
|
TAX ; ++<2C1B> TRANSFER TO .X
|
|
LDA ]HEXTAB,X ; ++<5C3B> LOAD HEXCHAR AT .X
|
|
JSR ]COUT ; ++<6C3B[83C]> SEND TO COUT
|
|
LDA ADDR1 ; ++<3C2B> LOAD LOBYTE AGAIN
|
|
AND #$0F ; ++<2C2B> CLEAR LOBITS
|
|
TAX ; ++<2C1B> TRANSFER T .X
|
|
LDA ]HEXTAB,X ; ++<[16C]> LOAD HEXCHAR AT .X
|
|
JSR ]COUT ; ++<6C3B[83C]> SEND TO COUT
|
|
LDA #":" ; ++<2C2B>
|
|
JSR ]COUT ; ++<6C3B[83C]>SEND COLON TO COUT
|
|
LDA "#" ; ++<2C2B>
|
|
JSR ]COUT ; ++<6C3B[83C]> SEND SPACE TO COUT
|
|
LDY #0 ; ++<2C2B> RESET COUNTER
|
|
:LP
|
|
LDA (ADDR1),Y ; ++<6C2B> LOAD BYTE FROM ADDRESS
|
|
CLRHI ; ++<[16C10B] AT COUNTER OFFSET; CLEAR HIBITS
|
|
STA ]LEFT ; ++<4C3B> SAVE LEFT INDEX
|
|
LDA (ADDR1),Y ; ++<6C2B> RELOAD
|
|
AND #$0F ; ++<2C2B> CLEAR LOBITS
|
|
STA ]RIGHT ; ++<4C3B> SAVE RIGHT INDEX
|
|
LDX ]LEFT ; ++<4C3B> LOAD LEFT INDEX
|
|
LDA ]HEXTAB,X ; ++<5C3B> GET NIBBLE CHAR
|
|
JSR ]COUT ; ++<6C3B[83C]> SEND TO COUT
|
|
LDX ]RIGHT ; ++<4C3B> LOAD RIGHT INDEX
|
|
LDA ]HEXTAB,X ; ++<5C3B> GET NIBBLE CHAR
|
|
JSR ]COUT ; ++<6C3B[83C]> SEND TO COUT
|
|
LDA #160 ; ++<4C3B> LOAD SPACE
|
|
JSR ]COUT ; ++<6C3B[83C]> SEND TO COUT
|
|
INY ; ++<2C1B> INCREASE COUNTER
|
|
CPY ]LENGTH ; ++<4C3B> IF COUNTER < LENGTH
|
|
BNE :LP ; ++<4C2B> CONTINUE LOOP
|
|
RTS ; ++<6C1B> ELSE, EXIT
|
|
*
|
|
*``````````````````````````````*
|
|
* __ERRH (NATHAN RIGGS) *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* .A = ADDRESS LOBYTE *
|
|
* .X = ADDRESS HIBYTE *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* SETS NEW ADDRESS FOR THE *
|
|
* APPLSOFT ERROR HANDLING *
|
|
* ROUTINE. *
|
|
* *
|
|
* DESTROYS: NZCIDV *
|
|
* ^^^ *
|
|
* *
|
|
* CYCLES: 53 *
|
|
* SIZE: 32 BYTES *
|
|
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
|
|
*
|
|
__ERRH
|
|
LDA #1 ; ++<2C2B> TRICK DOS INTO THINKING
|
|
STA $AAB6 ; ++<4C3B> IT'S IN APPLESOFT MODE
|
|
STA $75+1 ; ++<3C2B> APPLESOFT LINE NUMBER POINTER
|
|
STA $33 ; ++<3C2B> APPLESOFT PROMPT CHARACTER
|
|
STA ADDR1 ; ++<3C2B> ADDRESS LOBYTE IN .A
|
|
STX ADDR1+1 ; ++<3C2B> ADDRESS HIBYTE IN .X
|
|
LDA #$FF ; ++<2C2B> TURN ON ERROR HANDLING
|
|
STA $D8 ; ++<3C3B> BYTE HERE
|
|
LDY #0 ; ++<2C2B> CLEAR OFFSET
|
|
LDA (ADDR1),Y ; ++<6C2B> LOAD ADDRESS LOBYTE
|
|
STA $9D5A ; ++<4C3B> SET AS ERROR HANDLING LO
|
|
INY ; ++<2C1B> INCREASE OFFSET
|
|
LDA (ADDR1),Y ; ++<6C2B> LOAD ADDRESS HIBYTE
|
|
STA $9D5B ; ++<4C3B> SET AS ERROR HANDLING HI
|
|
RTS ; ++<6C1B> EXIT SUBROUTINE
|
|
*
|
|
*``````````````````````````````*
|
|
* __P: (NATHAN RIGGS) *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* ASC STRING FOLLOWING CALL *
|
|
* TERMINATED WITH A 00 BYTE *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* CONTENTS OF STRING. *
|
|
* *
|
|
* DESTROYS: NZCIDV *
|
|
* ^^^ ^ *
|
|
* *
|
|
* CYCLES: 72+(155+ WITH COUT) *
|
|
* SIZE: 35 BYTES *
|
|
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
|
|
*
|
|
__P
|
|
PLA ; ++<4C1B> PULL RETURN LOBYTE
|
|
STA ADDR1 ; ++<3C2B> STORE TO ZERO PAGE
|
|
PLA ; ++<4C1B> PULL RETURN HIBYTE
|
|
STA ADDR1+1 ; ++<3C2B> STORE TO ZERO PAGE --3C,2B
|
|
LDY #1 ; ++<2C2B> SET OFFSET TO PLUS ONE
|
|
:LP LDA (ADDR1),Y ; ++<6C2B> LOAD BYTE AT OFFSET .Y
|
|
BEQ :DONE ; ++<4C2B> IF BYTE = 0, QUIT
|
|
JSR ]COUT ; ++<6C3B[83C]> OTHERWISE, PRINT BYTE
|
|
INY ; ++<2C1B> INCREASE OFFSET
|
|
BNE :LP ; ++<4C2B> IF .Y <> 0, CONTINUE LOOP
|
|
:DONE CLC ; ++<2C1B> CLEAR CARRY FLAG
|
|
TYA ; ++<2C1B> TRANSFER OFFSET TO .A
|
|
ADC ADDR1 ; ++<3C2B> ADD OFFSET TO RETURN ADDRESS
|
|
STA ADDR1 ; ++<4C2B> STORE TO RETURN ADDRESS LOBYTE
|
|
LDA ADDR1+1 ; ++<4C2B> DO THE SAME WITH THE HIBYTE
|
|
ADC #0 ; ++<3C2B> CARRY NOT RESET, SO INC HIBYTE
|
|
PHA ; ++<3C1B> IF NEEDED; THEN, PUSH HIBYTE
|
|
LDA ADDR1 ; ++<4C2B> LOAD LOBYTE
|
|
PHA ; ++<3C1B> PUSH LOBYTE
|
|
RTS ; ++<6C1B> EXIT
|
|
*
|
|
*``````````````````````````````*
|
|
* DELAYMS (LEVENTHAL/SEVILLE) *
|
|
* *
|
|
* ADAPTED FROM LEVANTHAL AND *
|
|
* SEVILLE'S /6502 ASSEMBLY *
|
|
* LANGUAGE ROUTINES/. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* .Y = NUMBER OF MILLISECS *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* DELAYS FOR X NUMBER OF *
|
|
* MILLISECONDS BY LOOPING *
|
|
* THROUGH A PRECISE NUMBER *
|
|
* OF CYCLES. *
|
|
* *
|
|
* DESTROYS: AXYNVBDIZCMS *
|
|
* ^^^^ ^^^ *
|
|
* *
|
|
* CYCLES: 39+ *
|
|
* SIZE: 29 BYTES *
|
|
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
|
|
*
|
|
DELAYMS
|
|
*
|
|
]MSCNT EQU $0CA ; LOOP 202 TIMES THROUGH DELAY1
|
|
; SPECIFIC TO 1.23 MHZ
|
|
; SPEED OF APPLE II
|
|
:DELAY
|
|
CPY #0 ; ++<2C2B> IF Y = 0, THEN EXIT
|
|
BEQ :EXIT ; ++<2C|3C2B>
|
|
NOP ; ++<2C1B> (MAKE OVERHEAD=25C)
|
|
*
|
|
** IF DELAY IS 1MS THEN GOTO LAST1
|
|
** THIS LOGIC IS DESIGNED TO BE
|
|
** 5 CYCLES THROUGH EITHER ATH
|
|
*
|
|
CPY #1 ; ++<2C2B> USE 2 CYCLES
|
|
BNE :DELAYA ; ++<2C|3C2B> 3C IF TAKEN, ELSE 2C
|
|
JMP :LAST1 ; ++<3C3B>
|
|
*
|
|
** DELAY 1 MILLISENCOND TIMES (Y-1)
|
|
*
|
|
:DELAYA
|
|
DEY ; ++<2C1B> (PREDEC Y)
|
|
:DELAY0
|
|
LDX #]MSCNT ; ++<2C2B>
|
|
:DELAY1
|
|
DEX ; ++<2C1B>
|
|
BNE :DELAY1 ; ++<3C2B>
|
|
NOP ; ++<2C1B>
|
|
NOP ; ++<2C1B>
|
|
DEY ; ++<2C1B>
|
|
BNE :DELAY0 ; ++<3C2B>
|
|
:LAST1
|
|
*
|
|
** DELAY THE LAST TIME 25 CYCLES
|
|
** LESS TO TAKE THE CALL, RETURN,
|
|
** AND ROUTINE OVERHEAD INTO
|
|
** ACCOUNT.
|
|
*
|
|
LDX #]MSCNT-3 ; ++<2C2B>
|
|
:DELAY2
|
|
DEX ; ++<2C1B>
|
|
BNE :DELAY2 ; ++<3C2B>
|
|
:EXIT
|
|
RTS ; ++<6C1B>
|
|
*
|
|
*``````````````````````````````*
|
|
* MEMFILL (LEVENTHAL/SAVILLE) *
|
|
* *
|
|
* ADAPTED FROM LEVANTHAL AND *
|
|
* SAVILLE'S /6502 ASSEMBLY *
|
|
* LANGUAGE ROUTINES/. FILLS A *
|
|
* SPECIFIED RANGE OF MEMORY *
|
|
* WITH A FILL VALUE. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* BPAR1 = FILL VALUE *
|
|
* WPAR2 = FILL LENGTH *
|
|
* WPAR3 = STARTING ADDRESS *
|
|
* *
|
|
* DESTROYS: NZCIDV *
|
|
* ^^ *
|
|
* *
|
|
* CYCLES: 59+ *
|
|
* SIZE: 31 BYTES *
|
|
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
|
|
*
|
|
]FILL EQU BPAR1 ; FILL VALUE
|
|
]SIZE EQU WPAR2 ; RANGE LENGTH IN BYTES
|
|
]ADDR EQU WPAR1 ; RANGE STARTING ADDRESS
|
|
*
|
|
MEMFILL
|
|
*
|
|
** FILL WHOLE PAGES FIRST
|
|
*
|
|
LDA ]FILL ; ++<3C2B> GET VAL FOR FILL
|
|
LDX ]SIZE+1 ; ++<3C2B> X=# OF PAGES TO DO
|
|
BEQ :PARTPG ; ++<3C2B> BRANCH IF HIGHBYTE OF SZ = 0
|
|
LDY #0 ; ++<2C2B> RESET INDEX
|
|
:FULLPG
|
|
STA (]ADDR),Y ; ++<6C2B> FILL CURRENT BYTE
|
|
INY ; ++<2C1B> INCREMENT INDEX
|
|
BNE :FULLPG ; ++<3C2B> BRANCH IF NOT DONE W/ PAGE
|
|
INC ]ADDR+1 ; ++<5C2B> ADVANCE TO NEXT PAGE
|
|
DEX ; ++<2C1B> DECREMENT COUNTER
|
|
BNE :FULLPG ; ++<3C2B> BRANCH IF NOT DONE W/ PAGES
|
|
*
|
|
** DO THE REMAINING PARTIAL PAGE
|
|
** REGISTER A STILL CONTAINS VALUE
|
|
*
|
|
:PARTPG
|
|
LDX ]SIZE ; ++<3C2B> GET # OF BYTES IN LAST PAGE
|
|
BEQ :EXIT ; ++<3C2B> BRANCH IF LOW BYTE = 0
|
|
LDY #0 ; ++<2C2B> RESET INDEX
|
|
:PARTLP
|
|
STA (]ADDR),Y ; ++<6C2B> STORE VAL
|
|
INY ; ++<2C1B> INCREMENT INDEX
|
|
DEX ; ++<2C1B> DECREMENT COUNTER
|
|
BNE :PARTLP ; ++<3C2B> BRANCH IF NOT DONE
|
|
:EXIT
|
|
RTS ; ++<6C1B>
|
|
*``````````````````````````````*
|
|
* MEMMOVE (LEVENTHAL/SEVILLE) *
|
|
* *
|
|
* ADAPTED FROM LEVANTHAL AND *
|
|
* SEVILLE'S /6502 ASSEMBLY *
|
|
* LANGUAGE ROUTINES/. COPIES *
|
|
* SERIES OF BYTES FROM SRCLOC *
|
|
* TO DESTLOC. *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* WPAR3 = LENGTH IN BYTES *
|
|
* WPAR1 = SOURCE ADDRESS *
|
|
* WPAR2 = DESTINATION ADDRESS *
|
|
* *
|
|
* DESTROY: NZCIDV *
|
|
* *
|
|
* *
|
|
* CYCLES: 207+ *
|
|
* BYTES: 117 *
|
|
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
|
|
*
|
|
]SIZE EQU WPAR3 ; LENGTH TO COPY (BYTES)
|
|
]ADDR1 EQU WPAR1 ; SOURCE ADDRESS
|
|
]ADDR2 EQU WPAR2 ; DESTINATION ADDRESS
|
|
*
|
|
MEMMOVE
|
|
*
|
|
** DETERMINE IF DEST AREA IS
|
|
** ABOVE SRC AREA BUT OVERLAPS
|
|
** IT. REMEMBER, OVERLAP CAN BE
|
|
** MOD 64K. OVERLAP OCCURS IF
|
|
** STARTING DEST ADDRESS MINUS
|
|
** STARTING SRC ADDRESS (MOD
|
|
** 64K) IS LESS THAN NUMBER
|
|
** OF BYTES TO MOVE.
|
|
*
|
|
LDA ]ADDR2 ; ++<3C2B> CALC DEST-SRC
|
|
SEC ; ++<2C1B> SET CARRY
|
|
SBC ]ADDR1 ; ++<3C2B> SUBTRACT SOURCE ADDRESS
|
|
TAX ; ++<2C1B> HOLD VAL IN .X
|
|
LDA ]ADDR2+1 ; ++<3C2B>
|
|
SBC ]ADDR1+1 ; ++<3C2B> MOD 64K AUTOMATIC
|
|
; -- DISCARD CARRY
|
|
TAY ; ++<2C1B> HOLD HIBYTE IN .Y
|
|
TXA ; ++<2C1B> CMP LOBYTE WITH # TO MOVE
|
|
CMP ]SIZE ; ++<3C2B>
|
|
TYA ; ++<2C1B>
|
|
SBC ]SIZE+1 ; ++<3C2B> SUBTRACT SIZE+1 FROM HIBYTE
|
|
BCS :DOLEFT ; ++<3C2B> BRANCH IF NO OVERLAP
|
|
*
|
|
** DEST AREA IS ABOVE SRC AREA
|
|
** BUT OVERLAPS IT.
|
|
** MOVE FROM HIGHEST ADDR TO
|
|
** AVOID DESTROYING DATA
|
|
*
|
|
JSR :MVERHT ; ++<3C6B>
|
|
JMP :MREXIT ; ++<3C3B>
|
|
*
|
|
** NO PROB DOING ORDINARY MOVE
|
|
** STARTING AT LOWEST ADDR
|
|
*
|
|
:DOLEFT
|
|
JSR :MVELEFT ; ++<6C3B>
|
|
:EXIT
|
|
JMP :MREXIT ; ++<3C3B>
|
|
:MVELEFT
|
|
LDY #0 ; ++<2C2B> ZERO INDEX
|
|
LDX ]SIZE+1 ; ++<3C2B> X=# OF FULL PP TO MOVE
|
|
BEQ :MLPART ; ++<3C2B> IF X=0, DO PARTIAL PAGE
|
|
:MLPAGE
|
|
LDA (]ADDR1),Y ; ++<6C2B> LOAD BYTE FROM SOURCE
|
|
STA (]ADDR2),Y ; ++<6C2B> MOVE BYTE TO DESTINATION
|
|
INY ; ++<2C1B> NEXT BYTE
|
|
BNE :MLPAGE ; ++<3C2B> CONT UNTIL 256B MOVED
|
|
INC ]ADDR1+1 ; ++<5C2B> ADV TO NEXT SRC PAGE
|
|
INC ]ADDR2+1 ; ++<5C2B> ADV NEXT DEST PAGE
|
|
DEX ; ++<2C1B> DEC PAGE COUNT
|
|
BNE :MLPAGE ; ++<3C2B> CONT UNTIL ALL FULL
|
|
; PAGES ARE MOVED
|
|
:MLPART
|
|
LDX ]SIZE ; ++<3C2B> GET LENGTH OF LAST PAGE
|
|
BEQ :MLEXIT ; ++<3C2B> BR IF LENGTH OF LAST
|
|
; PAGE = 0
|
|
; REG Y IS 0
|
|
:MLLAST
|
|
LDA (]ADDR1),Y ; ++<6C2B> LOAD BYTE FROM SOURCE
|
|
STA (]ADDR2),Y ; ++<6C2B> MOVE BYTE TO DESTINATION
|
|
INY ; ++<2C1B> NEXT BYTE
|
|
DEX ; ++<2C1B> DEC COUNTER
|
|
BNE :MLLAST ; ++<3C2B> CONT UNTIL LAST P DONE
|
|
:MLEXIT
|
|
JMP :MREXIT ; ++<3C3B>
|
|
*
|
|
********************************
|
|
*
|
|
:MVERHT
|
|
*
|
|
** -- MOVE THE PARTIAL PAGE FIRST
|
|
*
|
|
LDA ]SIZE+1 ; ++<3C2B> GET SIZE HIBYTE
|
|
CLC ; ++<2C1B> CLEAR CARRY
|
|
ADC ]ADDR1+1 ; ++<3C2B> ADD SOURCE ADDRESS HIBYTE
|
|
STA ]ADDR1+1 ; ++<3C2B> POINT TO LAST PAGE OF SRC
|
|
LDA ]SIZE+1 ; ++<3C2B> GET SIZE HIBYTE
|
|
CLC ; ++<2C1B> CLEAR CARRY
|
|
ADC ]ADDR2+1 ; ++<3C2B> ADD DESTINATION HIBYTE
|
|
STA ]ADDR2+1 ; ++<3C2B> POINT TO LAST P OF DEST
|
|
*
|
|
** MOVE THE LAST PARTIAL PAGE FIRST
|
|
*
|
|
LDY ]SIZE ; ++<3C2B> GET LENGTH OF LAST PAGE
|
|
BEQ :MRPAGE ; ++<3C2B> IF Y=0 DO THE FULL PAGES
|
|
:MR0
|
|
DEY ; ++<2C1B> BACK UP Y TO NEXT BYTE
|
|
LDA (]ADDR1),Y ; ++<6C2B> LOAD CURRENT SOURCE BYTE
|
|
STA (]ADDR2),Y ; ++<6C2B> STORE IN CURRENT DESTINATION
|
|
CPY #0 ; ++<2C2B> BRANCH IF NOT DONE
|
|
BNE :MR0 ; ++<3C2B> WITH THE LAST PAGE
|
|
:MRPAGE
|
|
LDX ]SIZE+1 ; ++<3C2B> GET SIZE HIBYTE
|
|
BEQ :MREXIT ; ++<3C2B> BR IF HYBYTE = 0 (NO FULL P)
|
|
:MR1
|
|
DEC ]ADDR1+1 ; ++<5C2B> BACK UP TO PREV SRC PAGE
|
|
DEC ]ADDR2+1 ; ++<5C2B> TO DEST
|
|
:MR2
|
|
DEY ; ++<2C1B> BACK UP Y TO NEXT BYTE
|
|
LDA (]ADDR1),Y ; ++<6C2B> LOAD SOURCE CURRENT BYTE
|
|
STA (]ADDR2),Y ; ++<6C2B> STORE BYTE IN DESTINATION
|
|
CPY #0 ; ++<2C2B> IF NOT DONE WITH PAGE
|
|
BNE :MR2 ; ++<3C2B> THEN BRANCH OUT
|
|
DEX ; ++<2C1B> DECREASE BYTE COUNTER
|
|
BNE :MR1 ; ++<3C2B> BR IF NOT ALL PAGES MOVED
|
|
:MREXIT
|
|
RTS ; ++<6C1B>
|
|
*
|
|
*``````````````````````````````*
|
|
* MEMSWAP (NATHAN RIGGS) *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* BPAR1 = SWAP LENGTH *
|
|
* WPAR1 = 1ST ADDRESS *
|
|
* WPAR2 = 2ND ADDRESS *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* SWAPS THE VALUES IN THE *
|
|
* MEMORY LOCATIONS GIVEN *
|
|
* FOR THE SPECIFIED LENGTH. *
|
|
* *
|
|
* DESTROYS: NZCIDV *
|
|
* ^^^ *
|
|
* *
|
|
* CYCLES: 46+ *
|
|
* SIZE: 18 BYTES *
|
|
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
|
|
*
|
|
]SIZE EQU BPAR1 ; SIZE OF RANGE TO SWAP
|
|
]ADDR1 EQU WPAR1 ; SOURCE ADDRESS 1
|
|
]ADDR2 EQU WPAR2 ; SOURCE ADDRESS 2
|
|
*
|
|
MEMSWAP
|
|
LDY #255 ; ++<2C2B> RESET BYTE INDEX
|
|
:LP
|
|
INY ; ++<2C1B> INCREASE BYTE INDEX
|
|
LDA (]ADDR1),Y ; ++<6C2B> LOAD BYTE FROM FIRST ADDRESS
|
|
TAX ; ++<2C1B> TRANSFER TO .X
|
|
LDA (]ADDR2),Y ; ++<6C2B> LOAD BYTE FROM SECOND ADDRESS
|
|
STA (]ADDR1),Y ; ++<6C2B> STORE IN FIRST ADDRESS
|
|
TXA ; ++<2C1B> TRANSFER FIRST BYTE VAL TO .A
|
|
STA (]ADDR2),Y ; ++<6C2B> NOW STORE THAT IN SECOND ADDRESS
|
|
CPY ]SIZE ; ++<3C2B> IF BYTE INDEX < LENGTH,
|
|
BNE :LP ; ++<3C2B> CONTINUE LOOPING
|
|
RTS ; ++<6C1B> OTHERWISE, EXIT
|
|
*
|
|
RTS ; ++<6C1B>
|