PAGE SBTTL "--- TIME-STAMP PAGING ROUTINE ---" ; ------------------------- ; FETCH NEXT BYTE OF Z-CODE ; ------------------------- ; EXIT: BYTE AT [ZPC] IN [A] & [Y]; FLAGS SET ; EXPANDED TO USE ALL AVAILABLE MEMORY ; ASSUMPTION: PAGING STARTS IN LOW MAIN MEMORY NEXTPC: LDA ZPCFLG ; IS [ZPCPNT] VALID? BEQ NPC0 ; NO, GO GET NEW Z-PAGE ;SAME PAGE LDA ZPNTH ; CHECK ABS ADDR TO SEE IF AUX OR MAIN RAM BEQ NPC4 ; MAIN LDA ZPNTM ; SET UP FOR AUX READ LDY ZPCL ; ABS PAGE AND BYTE OFFSET JMP NPC2 ; Z-PAGE HAS CHANGED! NPC0: LDA ZPCM ; GET TOP LDY ZPCH ; 9 BITS OF [ZPC] CPY ZPURE+HI ; CHECK IF BELOW PAGING BCC NPC3 ; YES BEQ NPC1 ; MAYBE, CHECK LOW BCS NPCPG ; ABOVE, PAGE IT IN NPC1: CMP ZPURE+LO BCC NPC3 ; BELOW NPCPG: LDX #0 ; INVALIDATE MPC FLAG STX MPCFLG JSR PAGE ; ABOVE, GET PAGE INTO Y/A STA ZPNTM ; SAVE POINTER STY ZPNTH LDY #$FF ; VALIDATE [ZPCPNT] STY ZPCFLG INY ; = 0 STY ZPNTL ; 1ST BYTE ON A NEW PAGE LDY ZPNTH ; IF CLEAR BEQ NPC4 ; PAGE IS IN MAIN MEMORY LDY ZPCL ; GET BYTE WANTED NOW FROM AUX MEM NPC2: JSR BUFBYT ; GET [Y] BYTE IN BUFFER [A] INTO [A] JMP NPC5 ; GOT IT NPC3: CLC ; MAKE PAGE ABSOLUTE ADC ZCODE ; BY ADDING IT TO START OF GAME SPACE STA ZPNTM ; SAVE HERE FOR USE LDX #$FF STX ZPCFLG ; VALIDATE [ZPCPNT] INX ; = 0 STX ZPNTL ; CLEAR LSB OF POINTER STX ZPNTH ; AND MSB, MAIN MEMORY ; JSR ALIGN ; GET ABS ADDR. (Y/A = ZPCH/ZPCM) ; BCS NPC2 ; AUX MEM. ; ELSE DROP THRU TO MAIN MEM RTN NPC4: LDY ZPCL ; FETCH PAGE INDEX LDA ZPNTM ; CHECK IF LOW OR HIGH MEMORY CMP #$C0 BCC NPC7 ; LOW JSR HIBYT ; HIGH JMP NPC5 NPC7: LDA (ZPCPNT),Y ; GET Z-BYTE (FROM MAIN MEMORY) NPC5: INC ZPCL ; END OF PAGE YET? BNE NPC6 ; NO, EXIT LDY #0 STY ZPCFLG ; ELSE INVALIDATE [ZPCPNT] INC ZPCM ; POINT [ZPC] TO BNE NPC6 ; THE NEXT INC ZPCH ; Z-PAGE NPC6: TAY ; SET FLAGS RTS ; AND RETURN ; ------------------------------- ; GET NEXT BYTE OF VIRTUAL MEMORY ; ------------------------------- ; EXIT: BYTE AT [MPC] IN [A] & [Y]; FLAGS SET ; (ALL DIFFERENT FOR EXPANDED MEMORY USE - TAKEN FROM EZIP) GETBYT: LDA MPCFLG ; IS [ZPCPNT] VALID? BEQ GTBT0 ; NO, GO GET NEW Z-PAGE LDA MPNTH ; CHECK IF AUX OR MAIN RAM BEQ GTBT4 ; MAIN LDA MPNTM ; SET UP FOR AUX READ LDY MPCL JMP GTBT2 ; Z-PAGE HAS CHANGED! GTBT0: LDA MPCM ; GET TOP LDY MPCH ; 9 BITS OF [MPC] PATCH1: EQU $+1 ; PATCH POINT FOR "VERIFY" CPY ZPURE+HI ; CHECK IF BELOW PAGING BCC GTBT3 ; YES BEQ GTBT1 ; MAYBE, CHECK LOW BCS GETPG ; ABOVE, PAGE IT IN PATCH2: EQU $+1 ; PATCH POINT FOR "VERIFY" GTBT1 CMP ZPURE+LO BCC GTBT3 ; BELOW GETPG: LDX #0 STX ZPCFLG JSR PAGE ; ABOVE, GET PAGE INTO Y/A STA MPNTM ; SAVE POINTER STY MPNTH LDY #$FF ; VALIDATE [MPCPNT] STY MPCFLG INY ; = 0 STY MPNTL ; 1ST BYTE ON A NEW PAGE LDY MPNTH ; IF CLEAR BEQ GTBT4 ; PAGE IS IN MAIN MEMORY LDY MPCL ; BYTE WE WANT GTBT2: JSR BUFBYT ; GET [Y] BYTE IN BUFFER [A] INTO [A] JMP GTBT5 ; GOT IT GTBT3: CLC ; MAKE PAGE ABSOLUTE ADC ZCODE ; BY ADDING IT TO START OF GAME SPACE STA MPNTM ; SAVE HERE FOR USE LDX #$FF STX MPCFLG ; VALIDATE [MPCPNT] INX ; = 0 STX MPNTL ; CLEAR LSB OF POINTER STX MPNTH ; MARK AS MAIN MEMORY ; JSR ALIGNM ; GET ABS ADDR. (Y/A = ZPCH/ZPCM) ; BCS GTBT2 ; AUX MEM. ; ELSE DROP THRU TO MAIN MEM RTN GTBT4: LDY MPCL ; FETCH PAGE INDEX LDA MPNTM ; CHECK IF LOW OR HIGH MEM CMP #$C0 BCC GTBT7 ; LOW JSR HIBYT ; HIGH JMP GTBT5 GTBT7: LDA (MPCPNT),Y ; GET Z-BYTE (FROM MAIN MEMORY) GTBT5: INC MPCL ; END OF PAGE YET? BNE GTBT6 ; NO, EXIT LDY #0 STY MPCFLG ; ELSE INVALIDATE [MPCPNT] INC MPCM ; POINT [MPC] TO BNE GTBT6 ; THE NEXT INC MPCH ; Z-PAGE GTBT6: TAY ; SET FLAGS RTS ; AND RETURN ; ------------------------ ; LOCATE A SWAPABLE Z-PAGE ; ------------------------ ; ENTRY: TARGET Z-PAGE IN [A/Y] (9 BITS) ; EXIT: ABSOLUTE PAGE IN [A] ; DIFF FOR EXPANDED MEMORY USE PAGE: STA TARGET+LO ; SAVE THE STY TARGET+HI ; TARGET Z-PAGE HERE ; IS THIS Z-PAGE ALREADY PAGED IN? LDA PMAX+LO STA ZPAGE+LO ; MOVE PMAX IN FOR COUNT STA PR1+LO LDA PMAX+HI STA ZPAGE+HI STA PR1+HI LDA PR1+LO ; ADD TO PAGTBL ADDR ; SEC ; PMAX ACTUALLY 1 GREATER THAN MAX ; SBC #2 ; SO COME DOWN TO REAL LAST ENTRY ; BCS PG13 ; DEC PR1+HI PG13: CLC ADC #LOW PTABL STA PR1+LO LDA PR1+HI ADC #HIGH PTABL STA PR1+HI ; SO PR1 = TOP OF PGING SPACE ; LDX #HI LDY #0 PG1: LDA TARGET+LO ; CHECK IF TARGET PAGE CMP (PR1),Y ; ALREADY IN RESIDENCE BNE PG2 ; NO LDA TARGET+HI ; CHECK HIGH BYTE INY CMP (PR1),Y BEQ PG4 ; ALREADY THERE DEY ; RESET FOR NEXT COMPARE PG2: LDA PR1+LO ; MOVE DOWN TO NEXT ENTRY SEC SBC #2 STA PR1+LO BCS PG3 DEC PR1+HI PG3: LDA ZPAGE+LO ; DECREMENT COUNTER SEC SBC #2 STA ZPAGE+LO BEQ PG12 BCS PG1 ; NOT DONE YET PG12: DEC ZPAGE+HI BPL PG1 ; KEEP LOOKING ; LDX #0 ; STX ZPAGE ; START AT BUFFER #0 ; ;PG1: CMP PTABL,X ; LSB MATCHED? ; BNE PG2 ; NO, TRY NEXT BUFFER ; TYA ; ELSE CHECK ; CMP PTABH,X ; MSB ; BEQ PG5 ; MATCHED! BUFFER IN [ZPAGE] ; LDA TARGET+LO ; ELSE RESTORE LSB ;PG2: INC ZPAGE ; UPDATE TALLY ; INX ; CPX PMAX ; OUT OF BUFFERS YET? ; BCC PG1 ; NO, KEEP SEARCHING ; SWAP IN THE TARGET PAGE JSR EARLY ; GET EARLIEST PAGE LDA SWAP+LO ; INTO [SWAP] STA ZPAGE+LO ; SAVE FOR LATER CLC ADC #LOW PTABL ; ALIGN AT EARLIEST BUFFER STA PR1+LO LDA SWAP+HI STA ZPAGE+HI ADC #HIGH PTABL STA PR1+HI LDY #LO ; PLACE PAGE IN BUFFER LDA TARGET+LO STA (PR1),Y STA DBLOCK+LO ; AND GIVE IT TO ZDOS LDY #HI LDA TARGET+HI STA (PR1),Y STA DBLOCK+HI ; LDX SWAP ; INTO [SWAP] & [X] ; STX ZPAGE ; SAVE FOR LATER ; ; LDA TARGET+LO ; ASSIGN THE TARGET PAGE ; STA PTABL,X ; TO THE EARLIEST BUFFER ; STA DBLOCK+LO ; ALSO GIVE IT TO ZDOS ; ; LDA TARGET+HI ; SAME FOR TOP BIT ; AND #%00000011 ; USE ONLY BIT 0 (& 1 - EZIP) ; STA PTABH,X ; STA DBLOCK+HI JSR GETBUF ; GET BUFFER FROM DISK INTO CORRECT PAGE BCC PG4 ; OK JMP DKERR ; OOPS ; UPDATE THE TIMESTAMP PG4: LDA ZPAGE+LO ; ADD BUFFER INDEX TO LRUMAP CLC ADC #LOW LRUMAP STA PR1+LO LDA ZPAGE+HI ADC #HIGH LRUMAP STA PR1+HI LDY #LO ; CHECK IF SAME AS LDA (PR1),Y ; CURRENT STAMP CMP STAMP+LO BNE PG5 ; NO, GO GET THIS PG A NEW STAMP LDY #HI LDA (PR1),Y CMP STAMP+HI BEQ PG11 ; YES, EXIT PG5: INC STAMP+LO ; UPDATE STAMP BNE PG10 ; CONTINUE IF NO OVERFLOW LDA STAMP+HI BNE PG6 ; HANDLE OVERFLOW INC STAMP+HI ; SET FOR 2ND 256 STAMPS JMP PG10 ; (512 IN ALL) ;PG5: LDY ZPAGE ; GET THE BUFFER INDEX ; LDA LRUMAP,Y ; GET THIS BUFFER'S STAMP ; CMP STAMP ; SAME AS CURRENT STAMP? ; BEQ PG8 ; YES, EXIT ; ; INC STAMP ; UPDATE STAMP ; BNE PG7 ; CONTINUE IF NO OVERFLOW ; HANDLE STAMP OVERFLOW PG6: JSR EARLY2 ; GET EARLIEST STAMP INTO [LRU] LDA #LOW LRUMAP ; SET PR2 TO LRUMAP SO STA PR2+LO ; CAN HANDLE WHOLE 1K EASILY LDA #HIGH LRUMAP STA PR2+HI ; LDX #HI PG7: LDY #0 ; LOW BYTE LDA (PR2),Y INY ; HIGH BYTE ORA (PR2),Y BEQ PG8 ; SKIP IT IF ALREADY ZERO DEY ; RESET LDA (PR2),Y ; ELSE SUBTRACT OFF SEC SBC LRU+LO ; THE EARLIEST TIMESTAMP STA (PR2),Y ; AND REPLACE THE STAMP INY ; HI BYTE LDA (PR2),Y ; (AND THE HIGH BYTE) SBC LRU+HI STA (PR2),Y DEY ; RESET FOR NEXT ENTRY PG8: CLC ; INC PR2 TO NEXT ENTRY LDA PR2+LO ADC #2 STA PR2+LO BCC PG9 INC PR2+HI PG9: LDA PR2+HI ; GET OFFSET TO WHERE WE ARE SEC SBC #HIGH LRUMAP CMP PMAX+HI ; HAVE WE CHECKED ALL THE ENTRIES? BCC PG7 ; NO, KEEP LOOKING LDA PR2+LO ; CHECK LOW BYTE SBC #LOW LRUMAP CMP PMAX+LO BCC PG7 ; LESS, KEEP LOOKING ; LDX #0 ; INIT INDEX ;PG9: LDA LRUMAP,X ; GET A STAMP READING ; BEQ PG6 ; EXIT IF ALREADY ZERO ; SEC ; ELSE SUBTRACT OFF ; SBC LRU ; THE EARLIEST TIMESTAMP ; STA LRUMAP,X ; AND REPLACE THE STAMP ;PG6: INX ; CPX PMAX ; END OF SWAPPING SPACE? ; BCC PG9 ; LOOP TILL ALL STAMPS FIXED LDA LRU+HI ; TURN BACK THE CLOCK EOR #$FF ; TO REFLECT NEW STA LRU+HI ; STAMP READING LDA LRU+LO EOR #$FF STA LRU+LO INC LRU+LO ; LDA #0 ; TURN BACK THE CLOCK ; SEC ; TO REFLECT NEW ; SBC LRU ; STAMP READING ; STA STAMP PG10: LDY #LO ; STAMP TARGET PAGE LDA STAMP+LO ; WITH NEW STAMP STA (PR1),Y ; [PR1] STILL SET AT PROPER LOCATION LDY #HI LDA STAMP+HI STA (PR1),Y ;PG7: LDA STAMP ; FETCH STAMP ; STA LRUMAP,Y ; STAMP TARGET PAGE WITH IT PG11: LSR ZPAGE+HI ; DIVIDE BY 2 ROR ZPAGE+LO ; WORD ALIGNED LDA ZPAGE+LO ; GET ABS.PAGE CLC ADC PAGE0+LO ; (PAGE # + 1ST PG) PHA LDA ZPAGE+HI ADC PAGE0+HI ; PICK UP CARRY TAY PLA RTS ; Y/A (HI/LO) = PAGE TO USE ;PG8: LDA ZPAGE ; GET ABS. PAGE (EZIP) ; CLC ; ADC PAGE0 ; (PAGE # + 1ST PAGE) ; LDY #1 ; MARK IT AUX MEMORY ; RTS ; AND RETURN IT IN [A] AND [Y] ; *** ERROR #14: DRIVE ACCESS *** DKERR: LDA #14 JMP ZERROR ; ------------------------- ; LOCATE EARLIEST TIMESTAMP ; ------------------------- ; EXIT: [LRU] - EARLIEST TIMESTAMP ; [SWAP] = WORD ALIGNED INDEX TO EARLIEST BUFFER EARLY: LDA #LOW LRUMAP ; SET PR3 & PR2 TO LRUMAP STA PR3+LO CLC ADC #2 ; MOVE PR2 TO NEXT ENTRY STA PR2+LO LDA #HIGH LRUMAP STA PR3+HI ADC #0 ; PICK UP CARRY IF ANY STA PR2+HI LDY #1 ; Y TO HIGH EAR0: LDA (PR3),Y ; CHECK IF PR2 LOCATION CMP (PR2),Y ; IS EARLIER THAN PR3 BCC EAR1 ; NO BNE EAR3 ; GREATER DEY LDA (PR3),Y ; EQUAL, CHECK LOW BYTE CMP (PR2),Y INY ; RESET FOR NEXT ENTRY BCC EAR1 ; NO, NOT EARLIER EAR3: LDA PR2+LO ; YES, PICK UP EARLIER STA PR3+LO LDA PR2+HI STA PR3+HI EAR1: CLC ; INC PR2 TO NEXT ENTRY LDA PR2+LO ADC #2 STA PR2+LO BCC EAR2 INC PR2+HI EAR2: LDA PR2+HI ; GET OFFSET TO WHERE WE ARE SEC SBC #HIGH LRUMAP CMP PMAX+HI ; HAVE WE CHECKED ALL THE ENTRIES? BCC EAR0 ; NO, KEEP LOOKING LDA PR2+LO ; CHECK LOW BYTE SBC #LOW LRUMAP CMP PMAX+LO BCC EAR0 ; LESS, KEEP LOOKING LDA PR3+LO ; GET INDEX OF PG TO USE SEC SBC #LOW LRUMAP STA SWAP+LO ; SAVE IT IN SWAP FOR LATER LDA PR3+HI SBC #HIGH LRUMAP STA SWAP+HI LDA (PR3),Y ; GET LRU # TO USE STA LRU+HI DEY LDA (PR3),Y STA LRU+LO RTS ; THIS IS FOR OVERFLOW, IGNORES 0 ENTRIES EARLY2: LDA #LOW LRUMAP ; SET PR3 & PR2 TO LRUMAP STA PR3+LO CLC ADC #2 ; MOVE PR2 TO NEXT ENTRY STA PR2+LO LDA #HIGH LRUMAP STA PR3+HI ADC #0 ; PICK UP CARRY IF ANY STA PR2+HI EAR20: LDY #0 LDA (PR3),Y ; CHECK IF PR2 LOCATION INY ORA (PR3),Y ; IS VALUE 0 BEQ EAR23 ; YES, SO PICK THE OTHER LDA (PR3),Y CMP (PR2),Y ; IS EARLIER THAN PR3 BCC EAR21 ; NO BNE EAR23 ; GREATER DEY LDA (PR3),Y ; EQUAL, CHECK LOW BYTE CMP (PR2),Y BCC EAR21 ; NO, NOT EARLIER INY EAR23: LDA (PR2),Y ; MAKE SURE PR2 ISN'T 0 DEY ORA (PR2),Y BEQ EAR21 ; DON'T USE 0 ENTRY LDA PR2+LO ; PR2 EARLIER, PICK IT UP STA PR3+LO LDA PR2+HI STA PR3+HI EAR21: CLC ; INC PR2 TO NEXT ENTRY LDA PR2+LO ADC #2 STA PR2+LO BCC EAR22 INC PR2+HI EAR22: LDA PR2+HI ; GET OFFSET TO WHERE WE ARE SEC SBC #HIGH LRUMAP CMP PMAX+HI ; HAVE WE CHECKED ALL THE ENTRIES? BCC EAR20 ; NO, KEEP LOOKING LDA PR2+LO ; CHECK LOW BYTE SBC #LOW LRUMAP CMP PMAX+LO BCC EAR20 ; LESS, KEEP LOOKING LDA PR3+LO ; GET INDEX OF PG TO USE SEC SBC #LOW LRUMAP STA SWAP+LO ; SAVE IT IN SWAP FOR LATER LDA PR3+HI SBC #HIGH LRUMAP STA SWAP+HI LDY #1 LDA (PR3),Y ; GET LRU # TO USE STA LRU+HI DEY LDA (PR3),Y STA LRU+LO RTS ; ------------------------- ; POINT [MPC] TO V-ADDR [I] ; ------------------------- SETWRD: LDA I+LO STA MPCL LDA I+HI STA MPCM LDA #0 STA MPCH ; ZERO TOP BIT STA MPCFLG ; INVALIDATE [MPC] RTS ; ---------------------------- ; GET Z-WORD AT [MPC] INTO [I] ; ---------------------------- ;GETWRD: JSR GETBYT ; STA I+HI ; JSR GETBYT ; STA I+LO ; RTS END