mirror of
https://github.com/erkyrath/infocom-zcode-terps.git
synced 2026-01-11 23:43:24 +00:00
314 lines
6.9 KiB
Plaintext
314 lines
6.9 KiB
Plaintext
PAGE
|
|
SBTTL "--- PAGING ROUTINES ---"
|
|
|
|
; -----------------------
|
|
; GET NEXT BYTE OF G-CODE
|
|
; -----------------------
|
|
|
|
; EXIT: BYTE IN [A] & [Y], FLAGS SET
|
|
|
|
NEXTPC: LDA GPCFLG ; IS [GPOINT] VALID?
|
|
BNE NPC2 ; YES, CONTINUE
|
|
|
|
LDX GPCH ; GET TARGET V-PAGE
|
|
LDA MEMMAP,X ; IS IT ALREADY RESIDENT?
|
|
BEQ NPC0 ; NO, PAGE IT IN
|
|
CMP PAGE0 ; IS IT IN PRELOAD?
|
|
BCC NPC1 ; YES, CONTINUE
|
|
|
|
; HANDLE A RESIDENT "PURE" PAGE
|
|
|
|
JSR UPTIME ; UPDATE STAMP
|
|
JMP NPC1 ; CONTINUE W/PAGE ADDR IN [A]
|
|
|
|
; FETCH A NON-RESIDENT "PURE" PAGE
|
|
|
|
NPC0: STA VPCFLG ; ([A]=0) INVALIDATE [VPC]
|
|
JSR PAGE ; GET ABS PAGE OF V-BLOCK [X] IN [A]
|
|
JMP NEXTPC
|
|
;THIS JUMP SHOULD NOT BE NEEDED BUT SEEMS TO HELP
|
|
|
|
|
|
; [A] HAS ABS ADDR OF TARGET PAGE (FIRST RAM PAGE OF TWO PAGES)
|
|
|
|
NPC1: STA GPOINT+HI ; FORM MSB OF G-POINTER
|
|
LDA GPCL ; IF BIT 7 SET
|
|
BPL NPC1A
|
|
INC GPOINT+HI ; POINT [GPOINT] AT NEXT RAM PAGE
|
|
NPC1A: LDA #$FF
|
|
STA GPCFLG ; VALIDATE [GPC]
|
|
|
|
; [GPOINT] HAS POINTER TO ABS PAGE ADDR
|
|
|
|
; PUT BITS 0 THRU 7 OF GPC INTO <Y>
|
|
|
|
NPC2: LDA GPC0 ; PUT BIT 0 INTO <C>
|
|
LSR A
|
|
LDA GPCL ; GET BITS 1-8
|
|
ROL A ; DON'T WORRY ABOUT BIT 8
|
|
TAY
|
|
|
|
LDA (GPOINT),Y ; GET A G-BYTE
|
|
|
|
; INCREMENT [GPC]
|
|
; IF CROSSING A !RAM! PAGE ADJUST [GPOINT]
|
|
; IF CROSSING A V-PAGE INVALIDATE FLAG
|
|
|
|
PHA ; SAVE THE BYTE
|
|
|
|
LDA GPC0 ; EFFECTIVLY ADD 1
|
|
EOR #$01
|
|
STA GPC0
|
|
BNE NPC3 ; BRANCH NO CARRY
|
|
|
|
INC GPCL
|
|
BEQ NPC4 ; BRANCH CROSSED V-PAGE
|
|
|
|
LDA GPCL ; TEST FOR CROSS !RAM! PAGE
|
|
AND #$7F
|
|
BNE NPC3 ; BRANCH NO CROSS
|
|
|
|
INC GPOINT+HI ; ADJUST RAM POINTER
|
|
JMP NPC3
|
|
|
|
NPC4: INC GPCH ; CROSS V-PAGE
|
|
LDA #00
|
|
STA GPCFLG ; INVALIDATE FLAG
|
|
|
|
NPC3: PLA ; RESTORE BYTE
|
|
TAY ; SET FLAGS
|
|
RTS
|
|
|
|
; ----------------------------
|
|
; GET A BYTE OF VIRTUAL MEMORY
|
|
; ----------------------------
|
|
|
|
; EXIT: SAME AS "NEXTPC"
|
|
|
|
GETBYT: LDA VPCFLG ; [VPC] VALID?
|
|
BNE GTBT2 ; YES, CONTINUE
|
|
|
|
LDX VPCH ; GET TARGET V-PAGE
|
|
LDA MEMMAP,X ; ALREADY IN RAM?
|
|
BEQ GTBT0 ; NO, PAGE IT IN
|
|
CMP PAGE0 ; IS IT PRELOADED?
|
|
BCC GTBT1 ; YES, CONTINUE
|
|
|
|
; HANDLE A RESIDENT PAGE
|
|
|
|
JSR UPTIME ; STAMP PAGE & UPDATE STAMP
|
|
JMP GTBT1 ; CONTINUE W/BUFFER ADDR IN [A]
|
|
|
|
; HANDLE A NON-RESIDENT PAGE
|
|
|
|
GTBT0: STA GPCFLG ; ([A]=0) INVALIDATE [GPC]
|
|
JSR PAGE ; GET ABS PAGE OF V-BLOCK [X] INTO [A]
|
|
JMP GETBYT
|
|
;THIS JMP SHOULD NOT BE NEEDED BUT SEEMS TO HELP
|
|
|
|
|
|
; [A] HAS ABS PAGE # OF TARGET PAGE
|
|
|
|
GTBT1: STA VPOINT+HI ; SET MSB OF POINTER
|
|
LDA VPCL ; IF BIT 7 SET
|
|
BPL GTBT1A
|
|
INC VPOINT+HI ; POINT AT NEXT RAM PAGE
|
|
GTBT1A: LDA #$FF
|
|
STA VPCFLG ; VALIDATE [VPC]
|
|
|
|
; [VPOINT] POINTS TO ABS ADDR OF TARGET V-PAGE
|
|
|
|
; PUT BITS 0 THRU 7 OF GPC INTO <Y>
|
|
|
|
GTBT2: LDA VPC0 ; PUT BIT 0 INTO <C>
|
|
LSR A
|
|
LDA VPCL ; GET BITS 1-8
|
|
ROL A ; DON'T WORRY ABOUT BIT 8
|
|
TAY
|
|
|
|
LDA (VPOINT),Y ; GET A V-BYTE
|
|
|
|
; INCREMENT [VPC]
|
|
; IF CROSSING A !RAM! PAGE ADJUST [GPOINT]
|
|
; IF CROSSING A V-PAGE INVALIDATE FLAG
|
|
|
|
PHA ; SAVE THE BYTE
|
|
|
|
LDA VPC0 ; EFFECTIVLY ADD 1
|
|
EOR #$01
|
|
STA VPC0
|
|
BNE GTBT3 ; BRANCH NO CARRY
|
|
|
|
INC VPCL
|
|
BEQ GTBT4 ; BRANCH CROSSED V-PAGE
|
|
|
|
LDA VPCL ; TEST FOR CROSS !RAM! PAGE
|
|
AND #$7F
|
|
BNE GTBT3 ; BRANCH NO CROSS
|
|
|
|
INC VPOINT+HI ; ADJUST RAM POINTER
|
|
JMP GTBT3
|
|
|
|
GTBT4: INC VPCH ; CROSS V-PAGE
|
|
LDA #00
|
|
STA VPCFLG ; INVALIDATE FLAG
|
|
|
|
GTBT3: PLA ; RESTORE BYTE
|
|
TAY ; SET FLAGS
|
|
RTS
|
|
|
|
; -------------------------------
|
|
; LOCATE A PAGE OF VIRTUAL MEMORY
|
|
; -------------------------------
|
|
|
|
;-----------------------------------------------------------------
|
|
; A VIRTUAL PAGE IS 512 BYTES OF VIRTUAL MEMORY.
|
|
; WHEN PAGED INTO MACHINE RAM IT MUST OCCUPY TWO CONSECUTIVE
|
|
; 256 BYTE !RAM! PAGES.
|
|
;
|
|
; [PAGMAP],BUFFER RETURN THE V-PAGE IN THAT BUFFFER
|
|
; (A BUFFER IS TWO CONSECUTIVE RAM PAGES)
|
|
; [MEMMAP],VPAGE RETURNS RAM PAGE LOWER HALF OF VPAGE IS IN
|
|
;
|
|
; [PAGE0] - RAM PAGE WHERE BUFFER(0) STARTS
|
|
;-----------------------------------------------------------------
|
|
|
|
; ENTRY: V-BLOCK TO SEARCH FOR IN [X]
|
|
; EXIT: ABSOLUTE PAGE ADDRESS IN [A]
|
|
|
|
PAGE: STX DBLOCK ; GIVE TARGET V-PAGE TO GROS
|
|
|
|
; DE-ALLOCATE THE EARLIEST V-PAGE
|
|
|
|
PGE1: JSR EARLY ; GET INDEX OF EARLIEST BUFFER INTO [SWAP]
|
|
|
|
LDY SWAP
|
|
LDX PAGMAP,Y ; GET V-PAGE OF EARLIEST BUFFER
|
|
BEQ PGE2 ; 0 = NO PAGE IN BUFFER
|
|
LDA #0
|
|
STA MEMMAP,X ; ZERO THE [MEMMAP] ENTRY
|
|
|
|
; SPLICE THE TARGET PAGE INTO THE BUFFER MAP
|
|
|
|
PGE2: LDA DBLOCK ; TARGET V-PAGE
|
|
STA PAGMAP,Y ; ADD IT TO BUFFER MAP
|
|
TAX ; USE LATER FOR INDEX INTO [MEMMAP]
|
|
|
|
TYA ; CALC THE ABSOLUTE ADDRESS
|
|
ASL A ; * 2 FOR 512 BYTE VPAGES
|
|
CLC ; OF THE
|
|
ADC PAGE0 ; CORRESPONDING BUFFER
|
|
STA MEMMAP,X ; TELL [MEMMAP] WHERE TO FIND THE PAGE
|
|
STA DBUFF+HI ; TELL GROS WHERE THE BUFFER IS
|
|
|
|
STA TARGET ; SAVE HERE
|
|
JSR GETDSK ; GET PAGE [DBLOCK] INTO [DBUFF]
|
|
LDA TARGET ; RESTORE BUFFER PAGE
|
|
|
|
; FALL THROUGH ...
|
|
|
|
; ----------------
|
|
; UPDATE TIMESTAMP
|
|
; ----------------
|
|
|
|
; ENTRY: ABS BUFFER PAGE OF V-BLOCK
|
|
|
|
UPTIME: STA TARGET ; SAVE FOR LATER
|
|
SEC ; FORM A ZERO-ALIGNED
|
|
SBC PAGE0 ; INDEX
|
|
;***
|
|
LSR A ; / 2 FOR 512 BYTE PAGES
|
|
;***
|
|
TAY ; INTO [LRUMAP]
|
|
LDA LRUMAP,Y ; CHECK THIS PAGE'S STAMP
|
|
CMP STAMP ; SAME AS CURRENT STAMP?
|
|
BEQ UT3 ; EXIT NOW IF SO
|
|
|
|
INC STAMP ; ELSE UPDATE STAMP
|
|
BNE UT2 ; CONTINUE IF NO OVERFLOW
|
|
|
|
; HANDLE STAMP OVERFLOW
|
|
|
|
JSR EARLY2 ; GET EARLIEST STAMP INTO [LRU]
|
|
LDX #0 ; INIT INDEX
|
|
UT0: LDA LRUMAP,X ; ELSE GET A STAMP READING
|
|
BEQ UT1 ; EXIT IF ZERO
|
|
SEC ; SUBTRACT OFF
|
|
SBC LRU ; EARLIEST STAMP READING
|
|
STA LRUMAP,X ; REPLACE IN MAP
|
|
UT1: INX
|
|
CPX PMAX ; LOOP TILL
|
|
BCC UT0 ; ALL STAMPS FIXED
|
|
|
|
LDA #0 ; TURN BACK
|
|
SEC ; THE CLOCK
|
|
SBC LRU ; TO REFLECT STAMP FUDGING
|
|
STA STAMP
|
|
|
|
UT2: LDA STAMP ; STAMP BUFFER [Y]
|
|
STA LRUMAP,Y ; WITH THE NEW STAMP
|
|
|
|
UT3: LDA TARGET ; RESTORE BUFFER ADDR
|
|
RTS
|
|
|
|
; --------------------------------
|
|
; LOCATE EARLIEST ACTIVE TIMESTAMP
|
|
; --------------------------------
|
|
|
|
; EXIT: [LRU] = EARLIEST TIMESTAMP
|
|
; [SWAP] = INDEX TO EARLIEST BUFFER
|
|
|
|
EARLY: LDX #0 ; INIT INDEX
|
|
STX SWAP
|
|
LDA LRUMAP ; GET TIMESTAMP OF BUFFER #0
|
|
INX ; START COMPARE WITH BUFFER #1
|
|
|
|
EAR0: CMP LRUMAP,X ; IS THIS STAMP EARLIER THAN [A]?
|
|
BCC EAR1 ; IF STILL SMALLER, TRY NEXT STAMP
|
|
|
|
LDA LRUMAP,X ; ELSE CHANGE EARLIEST ENTRY
|
|
STX SWAP ; AND UPDATE BUFFER INDEX
|
|
|
|
EAR1: INX
|
|
CPX PMAX ; OUT OF BUFFERS?
|
|
BCC EAR0 ; LOOP TILL EMPTY
|
|
RTS ; [SWAP] HAS INDEX TO EARLIEST BUFFER
|
|
|
|
; THIS IS FOR OVERFLOW, IGNORES 0 ENTRIES
|
|
|
|
SAVEY: DB 0
|
|
|
|
EARLY2: LDX #0 ; INIT INDEX
|
|
STX SWAP
|
|
STY SAVEY
|
|
EAR23: LDA LRUMAP,X ; GET TIMESTAMP OF BUFFER #0
|
|
CMP #0 ; DON'T USE A ZERO VALUE
|
|
BNE EAR22 ; OK, NOT 0
|
|
INX
|
|
CPX PMAX ; OUT OF BUFFERS?
|
|
BCC EAR23 ; NO, KEEP LOOKING
|
|
BCS EAR24 ; YUP, SO WILL HAVE TO USE 0
|
|
|
|
EAR22: INX ; START COMPARE WITH NEXT BUFFER
|
|
|
|
EAR20: CMP LRUMAP,X ; IS THIS STAMP EARLIER THAN [A]?
|
|
BCC EAR21 ; IF STILL SMALLER, TRY NEXT STAMP
|
|
|
|
LDY LRUMAP,X
|
|
BEQ EAR21
|
|
TYA
|
|
STX SWAP
|
|
|
|
EAR21: INX
|
|
CPX PMAX ; OUT OF BUFFERS?
|
|
BCC EAR20 ; LOOP TILL EMPTY
|
|
|
|
EAR24: STA LRU ; [A] HAS EARLIEST STAMP
|
|
; CMP #2 ; DON'T MAKE IT 0
|
|
; BCC EAR25
|
|
DEC LRU ; MAKE SO END RESULT NOT 0
|
|
EAR25: LDY SAVEY
|
|
RTS ; [SWAP] HAS INDEX TO EARLIEST BUFFER
|
|
END
|
|
|