AppleIIAsm-Collection/source/d3_arrays/T.SUB.APUT162.ASM
2021-06-05 21:40:51 -04:00

171 lines
7.0 KiB
NASM

*
*``````````````````````````````*
* APUT162 (NATHAN RIGGS) *
* *
* PLACE A VALUE HELD IN ONE *
* ADDRESS INTO THE SPECIFIED *
* ELEMENT IN A 16-BIT, TWO- *
* DIMENSIONAL ARRAY. *
* *
*------------------------------*
* MULTIPLICATION ADAPTED FROM *
* WHITE FLAME'S WORK ON *
* CODEBASE64. LICENSE MAY VARY *
*------------------------------*
* *
* INPUT: *
* *
* ZPW1 = SOURCE ADDRESS *
* ZPW2 = ARRAY ADDRESS *
* ZPW3 = 1ST DIM INDEX *
* ZPW4 = 2ND DIM INDEX *
* *
* DESTROY: NZCIDV *
* ^^^ ^ *
* *
* CYCLES: 378+ *
* SIZE: 220 BYTES *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]ADDRS EQU ZPW1 ; VALUE SOURCE ADDRESS
]ADDRD EQU ZPW2 ; ARRAY ADDRESS
]XIDX EQU ZPW3 ; FIRST DIMENSION INDEX
]YIDX EQU ZPW4 ; SECOND DIMENSION INDEX
*
]ESIZE EQU ZPB1 ; ELEMENT LENGTH
]MCAND EQU ZPW5 ; MULTIPLICAND
]MLIER EQU VARTAB ; MULTIPLIER
]PBAK EQU VARTAB+4 ; PRODUCT BACKUP
]XLEN EQU VARTAB+8 ; X-DIMENSION LENGTH
]YLEN EQU VARTAB+12 ; Y-DIMENSION LENGTH
]PROD EQU VARTAB+16 ; PRODUCT OF MULTIPLICATION
*
APUT162
LDY #4 ; {2C2B} LOAD BYTE 4 OF ARRAY
LDA (]ADDRD),Y ; {6C2B} HEADER TO GET ELEM LENGTH
STA ]ESIZE ; {3C2B}
LDY #0 ; {2C2B} LOAD BYTE 0 TO GET
LDA (]ADDRD),Y ; {6C2B} X-DIMENSION LENGTH LOBYTE
STA ]XLEN ; {3C2B}
LDY #1 ; {2C2B} LOAD BYTE 1 TO GET
LDA (]ADDRD),Y ; {6C2B} X-DIMENSION LENGTH HIBYTE
STA ]XLEN+1 ; {3C2B}
LDY #2 ; {2C2B} LOAD BYTE 2 TO GET THE
LDA (]ADDRD),Y ; {6C2B} Y-DIMENSION LENGTH LOBYTE
STA ]YLEN ; {3C2B}
LDY #3 ; {2C2B} LOAD BYTE 3 TO GET THE
LDA (]ADDRD),Y ; {6C2B} Y-DIMENSION LENGTH HIBYTE
STA ]YLEN+1 ; {3C2B}
LDY #0 ; {2C2B} RESET BYTE INDEX
*
** MULTIPLY Y-INDEX BY Y-LENGTH
*
LDA ]YIDX ; {3C2B} LOAD Y-INDEX LOBYTE
STA ]MLIER ; {3C2B} PUT IN MULTIPLIER LOBYTE
LDA ]YIDX+1 ; {3C2B} DO SAME FOR HIBYTES
STA ]MLIER+1 ; {3C2B}
LDA ]YLEN ; {3C2B} PUT Y-DIM LENGTH LOBYTE
STA ]MCAND ; {3C2B} INTO MULTIPLICAND
LDA ]YLEN+1 ; {3C2B} DO SAME FOR HIBYTE
STA ]MCAND+1 ; {3C2B}
LDA #00 ; {2C2B} CLEAR PRODUCT BYTES
STA ]PROD ; {3C2B}
STA ]PROD+1 ; {3C2B}
STA ]PROD+2 ; {3C2B}
STA ]PROD+3 ; {3C2B}
LDX #$10 ; {2C2B} INIT COUNTER TO #16
:SHIFT_R
LSR ]MLIER+1 ; {6C2B} DIVIDE MULTIPLIER HIBYTE BY 2
ROR ]MLIER ; {6C2B} ADJUST LOBYTE
BCC :ROT_R ; {3C2B} IF 0 PUT IN CARRY, ROTATE PRODUCT
LDA ]PROD+2 ; {3C2B} LOAD PRODUCT 3RD BYTE
CLC ; {2C1B} CLEAR CARRY
ADC ]MCAND ; {4C3B} ADD MULTIPLICAND
STA ]PROD+2 ; {3C2B} STORE 3RD BYTE
LDA ]PROD+3 ; {3C2B} LOAD PRODUCT HIBYTE
ADC ]MCAND+1 ; {4C3B} ADD MULTIPLICAND HIBYTE
:ROT_R
ROR ; {6C2B} ROTATE .A RIGHT
STA ]PROD+3 ; {3C2B} STORE IN PRODUCT HIBYTE
ROR ]PROD+2 ; {6C2B} ROTATE 3RD BYTE
ROR ]PROD+1 ; {6C2B} ROTATE 2ND
ROR ]PROD ; {6C2B} ROTATE LOBYTE
DEX ; {2C1B} DECREASE X COUNTER
BNE :SHIFT_R ; {3C2B} IF NOT ZERO, LOOP AGAIN
*
** NOW MULTIPLY XIDX BY ELEMENT SIZE
*
LDA ]PROD ; {3C2B} BACKUP PREVIOUS
STA ]PBAK ; {3C2B} PRODUCT FOR USE LATER
LDA ]PROD+1 ; {3C2B} DO SAME FOR HIBYTE
STA ]PBAK+1 ; {3C2B}
LDA ]XIDX ; {3C2B} PUT X-INDEX LOBYTE
STA ]MLIER ; {3C2B} INTO MULTIPLIER
LDA ]XIDX+1 ; {3C2B} DO SAME FOR HIBYTE
STA ]MLIER+1 ; {3C2B}
LDA ]ESIZE ; {3C2B} PUT ELEMENT SIZE
STA ]MCAND ; {3C2B} INTO MULTIPLICAND
LDA #0 ; {2C2B} CLEAR MULTIPLICAND HIBYTE
STA ]MCAND+1 ; {3C2B}
*
STA ]PROD ; {3C2B} CLEAR PRODUCT
STA ]PROD+1 ; {3C2B}
STA ]PROD+2 ; {3C2B}
STA ]PROD+3 ; {3C2B}
LDX #$10 ; {2C2B} INIT X COUNTER TO #16
:SHIFTR LSR ]MLIER+1 ; {6C2B} DIVIDE MULTIPLIER BY 2
ROR ]MLIER ; {6C2B} ADJUST LOBYTE
BCC :ROTR ; {3C2B} IF 0 PUT INTO CARRY, ROTATE PROD
LDA ]PROD+2 ; {3C2B} LOAD PRODUCT 3RD BYTE
CLC ; {2C1B} CLEAR CARRY
ADC ]MCAND ; {4C3B} ADD MULTIPLICAND LOBYTE
STA ]PROD+2 ; {3C2B}
LDA ]PROD+3 ; {3C2B} LOAD PRODUCT HIBYTE
ADC ]MCAND+1 ; {4C3B} HAD MULTIPLICAND HIBYTE
:ROTR
ROR ; {6C2B} ROTATE .A RIGHT
STA ]PROD+3 ; {3C2B} STORE PRODUCT HIBYTE
ROR ]PROD+2 ; {6C2B} ROTATE 3RD BYTE
ROR ]PROD+1 ; {6C2B} ROTATE 2ND BYTE
ROR ]PROD ; {6C2B} ROTATE LOBYTE
DEX ; {2C1B} DECREASE X COUNTER
BNE :SHIFTR ; {3C2B} IF NOT 0, KEEP LOOPING
*
** NOW ADD X * ESIZE TO RUNNING PRODUCT
*
CLC ; {2C1B} CLEAR CARRY
LDA ]PROD ; {3C2B} ADD CURRENT PRODUCT
ADC ]PBAK ; {4C3B} TO PREVIOUS PRODUCT
STA ]PROD ; {3C2B} AND STORE BACK IN PRODUCT
LDA ]PROD+1 ; {3C2B}
ADC ]PBAK+1 ; {4C3B}
STA ]PROD+1 ; {3C2B}
CLC ; {2C1B} CLEAR CARRY
LDA ]PROD ; {3C2B} INCREASE LOBYTE BY 5
ADC #5 ; {2C2B} TO ACCOUNT FOR ARRAY
STA ]PROD ; {3C2B} HEADER
LDA ]PROD+1 ; {3C2B}
ADC #0 ; {2C2B} ADJUST HIBYTE
STA ]PROD+1 ; {3C2B}
*
** ADD ARRAY ADDRESS TO GET INDEX
*
CLC ; {2C1B} CLEAR CARRY
LDA ]PROD ; {3C2B} ADD ARRAY ADDRESS
ADC ]ADDRD ; {4C3B} TO PRODUCT TO GET
STA ZPW6 ; {3C2B} ELEMENT ADDRESS; STORE
LDA ]PROD+1 ; {3C2B} ADDRESS ON ZERO PAGE
ADC ]ADDRD+1 ; {4C3B}
STA ZPW6+1 ; {3C2B}
LDY #0 ; {2C2B} RESET BYTE INDEX
:CLP
LDA (]ADDRS),Y ; {6C2B} LOAD BYTE FROM SOURCE
STA (ZPW6),Y ; {6C2B} STORE AT ELEMENT ADDRESS
INY ; {2C1B} INCREASE BYTE INDEX
CPY ]ESIZE ; {4C3B} IF != ELEMENT LENGTH, LOOP
BNE :CLP ; {3C2B}
LDY ZPW6+1 ; {3C2B} .Y = ELEMENT ADDRESS HIBYTE
LDX ZPW6 ; {3C2B} .X = ELEMENT ADDRESS LOBYTE
LDA ]ESIZE ; {3C2B} .A = ELEMENT LENGTH
RTS ; {6C1B}