Files
erkyrath.infocom-zcode-terps/apple/xzip/xpaging.asm
Andrew Plotkin b642da811e Initial commit.
2023-11-16 18:19:54 -05:00

481 lines
8.0 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
STTL "--- TIME-STAMP PAGING ROUTINE ---"
PAGE
; -------------------------
; POINT [MPC] TO V-ADDR [I]
; -------------------------
SETWRD: LDA I+LO
STA MPCL
LDA I+HI
STA MPCM
LDA #0
STA MPCH ; ZERO TOP BIT
JMP VLDMPC
; THE FIRST 98.5K (SIDE1) MUST
; BE RAM RESIDENT (394=$18A PAGES)
; 98.5K = $18A PAGES (V$0 TO V$189)
;
; PAGES V$13A TO V$189 ARE IN RAMDISK
; PAGES V$0 TO ($BF-VBEGIN) ARE IN MAIN
; PAGES ($C0-VBEGIN) TO V$139 ARE IN AUX
; PAGING BUFFERS ARE IN AUX FROM
; V$13A-($C0-VBEGIN)+$08 TO $BF
;
DSKBNK: DB 00
RAMSEC: DB 00
;
WANTED: DB 00,00
;
CURRENT: DB 00
NEXT: DB 00
NSUBA: DB 00
PSUBA: DB 00
NSUBCUR: DB 00
;
YTEMP: DB 00
ATEMP: DB 00
NSUBY: DB 00
NOSIDE2: DB 00 ; is there a side 2?
;
;
; GET SIDE 1 LOADS ALL CODE FROM
; DISK SIDE 1 INTO ITS CORRECT
; PLACE
; THE FIRST VPAGE MUST ALREADY BE
; RESIDENT AT [ZBEGIN]
GETSIDE1:
LDA ZBEGIN+ZENDLD ; check to see if game is all
CMP ZBEGIN+ZLENTH ; on side one
BCC GS1 ; nope
BNE GS2 ; yup
LDA ZBEGIN+ZENDLD+1 ; so we don't ask for side 2
CMP ZBEGIN+ZLENTH+1 ; is it all on side 1?
BCC GS1
GS2:
LDA #1 ; set flag
STA NOSIDE2 ; okay
GS1:
LDA ZBEGIN+ZLENTH+1 ; get length back
STA J+LO
LDA ZBEGIN+ZLENTH+0
LDY #5
SLP:
LSR A ;CONVERT QUADS TO PAGES WITH /64
ROR J+LO
DEY
BPL SLP
STA J+HI
; [J] HAS # PAGES IN GAME ROUNDED
; DOWN, BUT PAGE 0 IS IN ALREADY
; SO WE NEED ONLY LOAD [J] MORE
; PAGES OR FILL MEM WITH SIDE 1
; IF THE GAME IS LARGER THAN SIDE 1
; FILL MAIN AND AUX (NOT RAMDSK)
; # GETDSK ASSUMED TO BE POINTING
; # AT V-PAGE 1 AND RAM PAGE ZBEGIN+1
; # ALSO, GETDSK SHOULD ROLL INTO
; # AUX RAM WHEN INCMNTING DBUFF
FLP: JSR DECJ ;C=0 IF [J] GOES >0
BCC FIN
JSR GETDSK
LDA DSKBNK ;IS IT FILLING AUX ?
CMP #AUX
BNE FLP ;NO
LDA DBUFF+HI
CMP #PBEGIN ;FILLED TO PAGING BUFFERS YET?
BNE FLP ;NO, NOT YET
; NOW PUT STUFF IN RAMDSK
LDA #MAIN
STA DSKBNK ;POINT BACK TO MAIN MEM
LDA #0
STA RAMSEC ;POINT TO FIRST SECTOR
LP2:
LDA #>IOBUFF
STA DBUFF+HI ;MAKE GETDSK LEAVE CODE AT [IOBUFF]
JSR DECJ
BCC FIN
JSR GETDSK
LDY #>IOBUFF ;SET UP RAMDSK PARMS
LDA RAMSEC
LDX #WRITE
STA RDBNK+MAIN ;SO WE REALLY JSR RAMDSK
JSR RAMDSK ;CALL RAMDSK
INC RAMSEC
LDA RAMSEC
CMP #RMDSIZE
BCC LP2
JSR CLS ; CLEAR THE SCREEN FOR NEATNESS
LDA #2
STA CVT
LDA NOSIDE2 ; is there a side 2?
BNE FIN ; nope
JMP SIDE2 ; CODE EXISTS ON SIDE2 AND WE HAVE SIDE 1
FIN:
RTS
;DECJ RETURNS C=0 WHEN J=$FFFF
DECJ: LDA J+LO
SEC
SBC #1
STA J+LO
LDA J+HI
SBC #0
STA J+HI
RTS
; MAKE [MPCPNT],[MPCBNK] POINT TO
; THE RAM PAGE AND BANK THAT HOLDS
; THE V-PAGE MPCH,M
;
VLDMPC:
LDA MPCH
BNE VLD1 ;NOT IN FIRST V-64K
LDA MPCM
CMP #VAUX ;IS IT A PAGE IN MAIN
BCS VLD2 ;NO, IT IS IN AUX
ADC #>ZBEGIN ;ADD OFFSET TO GET RAM PAGE
LDY #MAIN
BEQ VLDEXI ;BRA
VLD2: SBC #VAUX-AUXSTART ;FIX TO OFFST INTO AUX RAM
LDY #AUX
BNE VLDEXI
VLD1: CMP #1 ;BETWEEN 64K AND 128K ?
BNE VLD3 ;NO, ABOVE 128K
LDA MPCM
CMP #<VRAMDSK
BCS VLD3 ;ABOVE AUX
ADC #V64PG
LDY #AUX
VLDEXI: STY MPCBNK
STA MPCPNT+HI
NOMUCK: RTS
VLD3: ;MUST BE PAGED
LDA MPCH
LDY MPCM
JSR PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y
CLC
ADC #PBEGIN
STA MPCPNT+HI
LDY #AUX
STY MPCBNK
;TEST FOR MUCK
LDA MUCKFLG
BEQ NOMUCK
JMP VLDZPC ;MAY HAVE MUCKED ZPC SO GO FIX
;SAME IDEA AS VLDMPC
VLDZPC: LDA ZPCH
BNE VLDZ1 ;NOT IN FIRST V-64K
LDA ZPCM
CMP #VAUX ;IS IT A PAGE IN MAIN
BCS VLDZ2 ;NO, IT IS IN AUX
ADC #>ZBEGIN ;ADD OFFSET TO GET RAM PAGE
LDY #MAIN
BEQ VLDZEXI ;BRA
VLDZ2: SBC #VAUX-AUXSTART ;FIX TO OFFST INTO AUX RAM
LDY #AUX
BNE VLDZEXI
VLDZ1: CMP #1 ;BETWEEN 64K AND 128K ?
BNE VLDZ3 ;NO, ABOVE 128K
LDA ZPCM
CMP #<VRAMDSK
BCS VLDZ3 ;ABOVE AUX
ADC #V64PG
LDY #AUX
VLDZEXI:
STY ZPCBNK
STA ZPCPNT+HI
NOZMUCK: RTS
VLDZ3: ;MUST BE PAGED
LDA ZPCH
LDY ZPCM
JSR PAGE ;RETURN BUFFER IN A THAT HAS VPAGE A,Y
CLC
ADC #PBEGIN
STA ZPCPNT+HI
LDY #AUX
STY ZPCBNK
;TEST MUCKING
LDA MUCKFLG
BEQ NOZMUCK
JMP VLDMPC ;MAY HAVE MUCKED MPC SO GO FIX
; FIND V-PAGE A,Y IF IT IS IN MEM
; AND RETURN WITH LINKED LIST
; PROPERLY MAINTAINED
; IF V-PAGE A,Y NOT IN MEM
; GET FROM DISK AND PUT IN RIGHT
; PLACE
MUCKFLG: DB 00 ;00 IF PAGENG BUFFERS NOT MUCKED
PAGE: STA WANTED+HI
STY WANTED+LO
; CLEAR MUCK FLAG
LDX #0
STX MUCKFLG
JSR WHERE
BCC TOUGH ;PAGE IS RESIDENT IN PAGENG SPACE
; PAGE MUST BE BROUGHT IN FROM DISK
LDX CURRENT ;GET BUFFER TO PUT PAGE INTO
LDA NEXTPNT,X ;BY LOOKING AT NEXT POINTER
STA CURRENT ;MAKE IT THE CURRENT BUFFER
TAX
LDA WANTED+HI ;LET BUFFER MAP KNOW
STA VPAGEH,X ;WHICH PAGE
LDA WANTED+LO ;IS GOING TO
STA VPAGEL,X ;BE THERE
TAY
TXA
PHA ;SAVE BUFFER
LDA WANTED+HI
; Y = WANTED+LO
; X = BUFFER
JSR GETVPAGE ;PUT V-PAGE A,Y INTO PAGENG BUFFER X
;INDICATE A MUCKING
DEC MUCKFLG
PLA ;RESTOR BUFFER NUMBER
RTS
; THIS IS WHERE THINGS GET WEIRD
TOUGH: STA NEXT
CMP CURRENT ;GETS REALY FUCKED IF CURRENT=NEXT
BNE T1
RTS ;DO NOT CHANGE POINTERS IF IT DOES, ALL IS WELL
; Y=NEXT(CURRENT)
; DO THE RIGHT THING TO THE POINTERS
; ASK LIM TO EXPLAIN ,HA HA.
T1: LDY CURRENT
LDA NEXTPNT,Y
STA NSUBCUR
LDA NEXT
JSR DETATCH
LDY CURRENT
LDA NEXT
JSR INSERT
LDA NEXT
STA CURRENT
RTS
GETVPAGE:
CMP #>PSIDE1 ;CHECK IF IN RAMDSK
BCC GETYES
BNE GETNO
CPY #<PSIDE1 ;NOT SHURE
BCC GETYES
GETNO: STA DBLOCK+HI
STY DBLOCK+LO
TXA ;OFFSET INTO CORRECT RAM PAGE
CLC
ADC #PBEGIN
STA DBUFF+HI
LDX #AUX
STX DSKBNK
JMP GETDSK
GETYES: TYA
SEC
SBC #<VRAMDSK ; ZERO LIGN INTO RAMDSK
PHA ; SAVE RAMDSK SECTOR
TXA
CLC ; OFFSET TO CORRECT RAM PAGE
ADC #PBEGIN
TAY ; DESTINATION
STA RDBNK+MAIN ;FOR SAFTY
LDX #AUX ; SELECT AUX TO WRITE TO
STX RMDBNK
LDX #READ ; COMMAND
PLA ; SECTOR
JMP RAMDSK
; PREV(A)=Y
; PREV(NEXT(Y))=A
; NEXT(A)=NEXT(Y)
; NEXT(Y)=A
; INSERT A BEFORE Y
INSERT: STA ATEMP
STY YTEMP
TAX
TYA
STA PREVPNT,X
LDA NEXTPNT,Y
STA NSUBY
TXA
LDX NSUBY
STA PREVPNT,X
TXA
LDX ATEMP
STA NEXTPNT,X
LDA ATEMP
STA NEXTPNT,Y
RTS
; DETATCH BUFFER >A<
; NEXT(PREV(A))=NEXT(A)
; PREV(NEXT(A))=PREV(A)
DETATCH: TAX
LDA NEXTPNT,X
STA NSUBA
LDA PREVPNT,X
STA PSUBA
TAX
LDA NSUBA
STA NEXTPNT,X
LDA PSUBA
LDX NSUBA
STA PREVPNT,X
RTS
; RETURN BUFFER OF PAGE [WANTED]
; IN >A< ELSE SEC (Y=WANTED+LO)
WHERE: LDX #NUMBUFS-1
WHLOOP:
LDA WANTED+HI
CMP VPAGEH,X ;>SAME
BEQ WHGOT
WHNOGOT:
DEX
BPL WHLOOP
SEC
RTS
WHGOT:
TYA
CMP VPAGEL,X
BNE WHNOGOT
TXA
CLC
RTS
INITPAG: LDX #NUMBUFS-1
STX CURRENT
LDA #$FF
INILP:
STA VPAGEH,X
DEX
BPL INILP
LDX #0
LDY #1
INILP2:
TYA
STA PREVPNT,X
INX
INY
CPX #NUMBUFS
BCC INILP2
LDA #00
DEX
STA PREVPNT,X
LDX #0
LDY #$FF
LDA #NUMBUFS-1
INILP3:
STA NEXTPNT,X
INX
INY
TYA
CPX #NUMBUFS
BCC INILP3
JMP GETSIDE1
; TAKE CARE OF CROSSING A PAGE
CRSMPC:
PHA
INC MPCM
BNE CRS1
INC MPCH
CRS1: JSR VLDMPC
PLA
RTS
;SAME AS CRSMPC
CRSZPC:
PHA
INC ZPCM
BNE CRSZ1
INC ZPCH
CRSZ1: JSR VLDZPC
PLA
RTS
GETBYT:
LDY MPCBNK ;SELECT CURRENT BANK
STA RDBNK,Y ;ENABLE READ
LDY MPCL
LDA (MPCPNT),Y ;GET THE BYTE
STA RDBNK+MAIN ;KILL (FOR SAFTY)
INC MPCL ;POINT TO NEXT BYTE
BNE GETGOT ;IF NO CROSS WE ARE STILL VALID
JSR CRSMPC
GETGOT: TAY ;SET FLAGS
RTS ;RED SLIPPER TIME
; LIKE GETBYT
NEXTPC: LDY ZPCBNK
STA RDBNK,Y
LDY ZPCL
LDA (ZPCPNT),Y
STA RDBNK+MAIN ;KILL
INC ZPCL
BNE NXTGOT
JSR CRSZPC
NXTGOT:
TAY
RTS
PAGE
END