mirror of https://github.com/dschmenk/VM02.git
3096 lines
47 KiB
ArmAsm
Executable File
3096 lines
47 KiB
ArmAsm
Executable File
;*
|
|
;* JAVA MEMORY MANAGER FOR 6502
|
|
;*
|
|
;*
|
|
;* HANDLE TABLE IS A TABLE OF POINTERS TO MEMORY BLOCKS
|
|
;*
|
|
;* THE LOW ORDER 3 BITS ARE STATE BITS FOR THE MEMORY BLOCK
|
|
;* 1 (001) = IN USE
|
|
;* 3 (011) = FIXED - HAS TO REMAIN IN PLACE
|
|
;* 5 (101) = CODE
|
|
;* 7 (111) = SWAPPED - NEEDS TO BE RELOADED FROM SOURCE OR SWAP
|
|
;*
|
|
;*
|
|
;* MEMORY BLOCKS ARE ALIGNED ON 64 BIT BOUNDARIES
|
|
;*
|
|
;*
|
|
;* A MEMORY HANDLE IS A POINTER TO THE ENTRY IN THE TABLE
|
|
;*
|
|
;* AN ALLOCATED MEMORY BLOCK IS ORGANIZED AS:
|
|
;* OFFSET SIZE FUNCTION
|
|
;* 0 2 SIZE
|
|
;* 2 2 REF CNT - MSB = ACCESSED BIT
|
|
;* 4 ? DATA
|
|
;* A FREE MEMORY BLOCK IS ORGANIZED AS:
|
|
;* OFFSET SIZE FUNCTION
|
|
;* 0 2 SIZE
|
|
;* 2 2 HNEXT
|
|
.INCLUDE "global.inc"
|
|
.INCLUDE "dvm.inc"
|
|
.IMPORT INIT_START,INIT_END,WARM_INIT
|
|
.IMPORT PRNTAX,COUT,CROUT,PUTS,PUTSLN,PRBYTE,PRSTR,PRSTRLN,MEMCPY,MEMCLR,KBWAIT
|
|
.IMPORT SYSTHROW,THROW_INTERNALERR
|
|
.IFDEF SWAPPING
|
|
.IMPORT PREFIX_GET,DIR_CREATE,FILE_GETINFO,FILE_CREATE,FILE_DESTROY,FILE_OPEN,FILE_CLOSE
|
|
.IMPORT FILE_GETEOF,FILE_READ,FILE_WRITE,FILE_SETBUFFER,FILE_SETAUX,ON_LINE
|
|
.EXPORT HMEM_CLRACCESS,HMEM_SWAP_CLEANUP
|
|
.ENDIF
|
|
.EXPORT HMEM_INIT
|
|
.EXPORT HMEM_ALLOC,HMEM_ALLOC_CODE,HMEM_ALLOC_FIXED,HMEM_FREE
|
|
.EXPORT HMEM_PTR,HMEM_REF_INC,HMEM_REF_DEC,HMEM_CLR
|
|
.EXPORT HMEM_LOCK,HMEM_UNLOCK,HMEM_UNLOCK_CODE,HMEM_GC
|
|
.IFDEF IDLE_GC
|
|
.EXPORT HMEM_GC_IDLE
|
|
.ENDIF
|
|
|
|
.MACRO CHKAUXLC
|
|
.IFDEF DEBUG_MEMMGR
|
|
.IFDEF BIGMEM
|
|
PHA
|
|
LDA $C016
|
|
BPL :+
|
|
AUXZP_ACCESS_OFF
|
|
PERR "AUXZP ENABLED"
|
|
BRK
|
|
: PLA
|
|
.ENDIF
|
|
.ENDIF
|
|
.ENDMACRO
|
|
.MACRO CHKHNDL
|
|
.IFDEF DEBUG
|
|
CPX #>HTBL
|
|
BCS :+
|
|
CPX #>HTBL_END
|
|
BCC :+
|
|
AUXZP_ACCESS_OFF
|
|
PERR "BAD HNDL"
|
|
BRK
|
|
:
|
|
.ENDIF
|
|
.ENDMACRO
|
|
|
|
.SEGMENT "INIT"
|
|
;*
|
|
;* CREATE EXTERNAL LINKEAGE TABLE AT $302
|
|
;*
|
|
HMEM_INIT: LDA #<HMEM_PTR
|
|
STA LINK_HMEMPTR
|
|
LDA #>HMEM_PTR
|
|
STA LINK_HMEMPTR+1
|
|
LDA #<HMEM_ALLOC
|
|
STA LINK_HMEMALLOC
|
|
LDA #>HMEM_ALLOC
|
|
STA LINK_HMEMALLOC+1
|
|
LDA #<HMEM_ALLOC_FIXED
|
|
STA LINK_HMEMALLOCFIXED
|
|
LDA #>HMEM_ALLOC_FIXED
|
|
STA LINK_HMEMALLOCFIXED+1
|
|
LDA #<HMEM_FREE
|
|
STA LINK_HMEMFREE
|
|
LDA #>HMEM_FREE
|
|
STA LINK_HMEMFREE+1
|
|
LDA #<HMEM_LOCK
|
|
STA LINK_HMEMLOCK
|
|
LDA #>HMEM_LOCK
|
|
STA LINK_HMEMLOCK+1
|
|
LDA #<HMEM_UNLOCK
|
|
STA LINK_HMEMUNLOCK
|
|
LDA #>HMEM_UNLOCK
|
|
STA LINK_HMEMUNLOCK+1
|
|
LDA #<HMEM_REF_INC
|
|
STA LINK_HMEMREFINC
|
|
LDA #>HMEM_REF_INC
|
|
STA LINK_HMEMREFINC+1
|
|
LDA #<HMEM_REF_DEC
|
|
STA LINK_HMEMREFDEC
|
|
LDA #>HMEM_REF_DEC
|
|
STA LINK_HMEMREFDEC+1
|
|
LDA #<HMEM_GC
|
|
STA LINK_GC
|
|
LDA #>HMEM_GC
|
|
STA LINK_GC+1
|
|
.IFDEF BIGMEM
|
|
LDA #$00 ; TOP OF FREE MEMORY IN AUX SPACE
|
|
STA CODEHEAPTOP
|
|
LDA #$BF
|
|
STA CODEHEAPTOP+1
|
|
.ENDIF
|
|
|
|
;*
|
|
;* INITIALIZE THE HANDLE TABLE
|
|
;*
|
|
AUXZP_ACCESS_ON
|
|
BIT LCBNK2 ; MAKE SURE LCBANK2 SET UP
|
|
BIT LCBNK2
|
|
LDX #<HTBL
|
|
STX HUNUSED
|
|
LDA #>HTBL
|
|
STA HUNUSED+1
|
|
LINK_UNUSED: STX HNDL
|
|
STA HNDL+1
|
|
LDA HNDL
|
|
CLC ; MAKE UNUSED HANDLE LIST
|
|
ADC #$02
|
|
STA (HNDL),Y
|
|
TAX
|
|
INY
|
|
LDA HNDL+1
|
|
ADC #$00
|
|
STA (HNDL),Y
|
|
DEY
|
|
CMP #>HTBL_END
|
|
BNE LINK_UNUSED
|
|
TYA
|
|
STA (HNDL),Y ; NULL OUT LAST IN LIST
|
|
INY
|
|
STA (HNDL),Y
|
|
JSR HMEM_NEW ; GET NEXT AVAIL HANDLE
|
|
STA HFREE ; MAKE INITAL FREE BLOCK
|
|
STX HFREE+1
|
|
.IFDEF DEBUG_MEMMGR
|
|
STA HFREEBAK ; MAKE INITAL FREE BLOCK
|
|
STX HFREEBAK+1
|
|
.ENDIF
|
|
LDY #$00 ; SET FREE MEM PTR
|
|
LDA #<INIT_START
|
|
CLC
|
|
ADC #$07
|
|
AND #$F8
|
|
STA MPTR
|
|
STA (HFREE),Y
|
|
INY
|
|
LDA #>INIT_START
|
|
ADC #$00
|
|
STA MPTR+1
|
|
STA (HFREE),Y
|
|
DEY ; SET FREE MEM SIZE
|
|
LDA #<TOPOFHEAP
|
|
SEC
|
|
SBC MPTR
|
|
STA (MPTR),Y
|
|
INY
|
|
LDA #>TOPOFHEAP
|
|
SBC MPTR+1
|
|
STA (MPTR),Y
|
|
INY
|
|
LDA #$00 ; NULL OUT NEXT FREE HANDLE
|
|
STA (MPTR),Y
|
|
INY
|
|
STA (MPTR),Y
|
|
AUXZP_ACCESS_OFF
|
|
LDA WARM_INIT
|
|
BNE :+
|
|
LDA #'$'
|
|
JSR COUT
|
|
AUXZP_ACCESS_ON
|
|
LDY #$00
|
|
LDA (MPTR),Y
|
|
INY
|
|
TAX
|
|
LDA (MPTR),Y
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
PSTRLN " bytes available"
|
|
:
|
|
.IFDEF DEBUG
|
|
AUXZP_ACCESS_ON
|
|
LDY #$00
|
|
LDA (MPTR),Y
|
|
INY
|
|
STA RAMAVAIL
|
|
LDA (MPTR),Y
|
|
STA RAMAVAIL+1
|
|
AUXZP_ACCESS_OFF
|
|
.ENDIF
|
|
.IFDEF DEBUG_MEMMGR
|
|
; JSR HMEM_DUMP
|
|
; JSR CROUT
|
|
.ENDIF
|
|
.IFDEF SWAPPING
|
|
;
|
|
; FIND THE MOST APPROPRIATE SWAP VOLUME
|
|
;
|
|
.IFDEF DEBUG_SWAP
|
|
PSTRLN "SWAPPING ENABLED"
|
|
; JSR KBWAIT
|
|
.ENDIF
|
|
LDX #$0F
|
|
FINDBESTVOL: STX VCNT
|
|
TXA
|
|
AND #$07
|
|
BEQ :+
|
|
CMP SKIPSLOT
|
|
BNE :++
|
|
: JMP VOLNXT
|
|
: TXA
|
|
ASL
|
|
ASL
|
|
ASL
|
|
ASL
|
|
TAY
|
|
LDX #>CLASSFILE_IO_BUFF
|
|
JSR ON_LINE
|
|
LDX VCNT
|
|
JSR CPYVOL
|
|
BCC :+
|
|
JMP VOLNXT
|
|
: LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
JSR FILE_GETINFO
|
|
BCC :+
|
|
JSR PUTS
|
|
.ASCIIZ "ERROR GETING VOLUME INFO:"
|
|
LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
JSR PRSTRLN
|
|
BRK
|
|
: STA TMPTR
|
|
STX TMPTR+1
|
|
LDY #$05
|
|
LDA (TMPTR),Y
|
|
LDY #$08
|
|
SEC
|
|
SBC (TMPTR),Y
|
|
STA HBEST
|
|
LDY #$06
|
|
LDA (TMPTR),Y
|
|
LDY #$09
|
|
SBC (TMPTR),Y
|
|
STA HBEST+1
|
|
LDA SWAPFILE+2
|
|
AND #$7F
|
|
CMP #'R'
|
|
BNE CHKFREE
|
|
LDA SWAPFILE+3
|
|
AND #$7F
|
|
CMP #'A'
|
|
BNE CHKFREE
|
|
LDA SWAPFILE+4
|
|
AND #$7F
|
|
CMP #'M'
|
|
BNE CHKFREE
|
|
LDY #$00 ; OFFSET FOR BEST RAM VOL
|
|
BEQ :+
|
|
CHKFREE: LDY #$03 ; OFFSET FOR BEST DEV VOL
|
|
: LDA HBEST+1
|
|
CMP BESTFREE+1,Y
|
|
BCC VOLNXT
|
|
BEQ :+
|
|
BCS SAVEVOL
|
|
: LDA HBEST
|
|
CMP BESTFREE,Y
|
|
BCC VOLNXT
|
|
BEQ VOLNXT
|
|
SAVEVOL: LDA HBEST
|
|
STA BESTFREE,Y
|
|
LDA HBEST+1
|
|
STA BESTFREE+1,Y
|
|
LDA VCNT
|
|
STA BESTVOL,Y
|
|
VOLNXT: LDX VCNT
|
|
DEX
|
|
BEQ :+
|
|
JMP FINDBESTVOL
|
|
: LDX BESTRAMVOL
|
|
LDA BESTRAMFREE+1 ; RAM VOL MUST HAVE AT LEAST 64K FREE
|
|
BNE SAVEBESTVOL
|
|
LDA BESTRAMFREE
|
|
BMI SAVEBESTVOL
|
|
LDX BESTDEVVOL
|
|
BPL SAVEBESTVOL
|
|
LDA SKIPSLOT ; NO WORKABLE DEVICES FOUND, REMOVE SLOT 6 SKIP
|
|
BNE :+ ; AND TRY AGAIN
|
|
PSTRLN "HALT: NO SWAP VOLUME AVAILABLE!"
|
|
BRK
|
|
: LDA #$00
|
|
STA SKIPSLOT
|
|
STA BESTRAMVOL
|
|
STA BESTDEVVOL
|
|
STA BESTRAMFREE
|
|
STA BESTRAMFREE+1
|
|
STA BESTDEVFREE
|
|
STA BESTDEVFREE+1
|
|
LDX #$0F
|
|
JMP FINDBESTVOL
|
|
SAVEBESTVOL: JSR CPYVOL
|
|
INC SWAPFILE
|
|
LDX SWAPFILE
|
|
LDA #'/'
|
|
STA SWAPFILE,X
|
|
LDY #$00
|
|
CPYSWPDIR: LDA SWAPDIR,Y
|
|
BEQ :+
|
|
INX
|
|
STA SWAPFILE,X
|
|
INY
|
|
BNE CPYSWPDIR
|
|
: STX SWAPFILE
|
|
LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
JSR DIR_CREATE
|
|
LDX SWAPFILE
|
|
LDA #'/'
|
|
STA SWAPFILE+1,X
|
|
;.IFDEF DEBUG_SWAP
|
|
INX
|
|
STX SWAPFILE
|
|
LDA WARM_INIT
|
|
BNE :+
|
|
JSR PUTS
|
|
.ASCIIZ "Swap path:"
|
|
LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
JSR PRSTRLN
|
|
: LDX SWAPFILE
|
|
DEX
|
|
;.ENDIF
|
|
TXA
|
|
CLC
|
|
ADC #$05 ; ADD SPACE FOR SWAPFILE NAME
|
|
STA SWAPFILE
|
|
RTS
|
|
CPYVOL: TXA
|
|
ASL
|
|
ASL
|
|
ASL
|
|
ASL
|
|
TAY
|
|
LDA CLASSFILE_IO_BUFF,Y
|
|
AND #$0F
|
|
BNE :+
|
|
SEC
|
|
RTS
|
|
: STA SWAPFILE
|
|
TAX
|
|
TYA
|
|
CLC
|
|
ADC SWAPFILE
|
|
TAY
|
|
INC SWAPFILE
|
|
LDA #'/'
|
|
STA SWAPFILE+1
|
|
: LDA CLASSFILE_IO_BUFF,Y
|
|
STA SWAPFILE+1,X
|
|
DEY
|
|
DEX
|
|
BNE :-
|
|
CLC
|
|
RTS
|
|
;*
|
|
;* CLEANUP SWAP DIRECTORY
|
|
;* CALLED AFTER RELOADING VM02 FOR WARM INIT/RESET
|
|
;*
|
|
HMEM_SWAP_CLEANUP:
|
|
.IFDEF DEBUG_SWAP
|
|
JSR PUTSLN
|
|
.ASCIIZ "CLEAN UP SWAP FILES"
|
|
.ENDIF
|
|
LDX #>HTBL
|
|
LDA #<HTBL
|
|
SWPCLNLP: AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
LDY #$00
|
|
LDA (HNDL), Y
|
|
AND #$07 ; LOOK FOR SWAPPED BLOCKS
|
|
CMP #$07
|
|
BNE SWPCLNNXT
|
|
LDA HNDL
|
|
PHA
|
|
LDA HNDL+1
|
|
PHA
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
JSR SETSWAPFILE
|
|
LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
JSR FILE_DESTROY ; REMOVE ANY EXISTING FILE
|
|
AUXZP_ACCESS_ON
|
|
PLA
|
|
STA HNDL+1
|
|
PLA
|
|
STA HNDL
|
|
SWPCLNNXT: LDA HNDL
|
|
LDX HNDL+1 ; NEXT HANDLE
|
|
AUXZP_ACCESS_OFF
|
|
CLC
|
|
ADC #$02
|
|
BCC :+
|
|
INX
|
|
: CPX #>HTBL_END
|
|
BCC SWPCLNLP
|
|
LDA SWAPFILE
|
|
SEC
|
|
SBC #$05
|
|
STA SWAPFILE
|
|
LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
JMP FILE_DESTROY ; REMOVE SWAP DIRECTORY
|
|
SWAPDIR: .ASCIIZ "SWAP"
|
|
BESTVOL:
|
|
BESTRAMVOL: .BYTE $FF
|
|
BESTFREE:
|
|
BESTRAMFREE: .WORD $0000
|
|
BESTDEVVOL: .BYTE $FF
|
|
BESTDEVFREE: .WORD $0000
|
|
SKIPSLOT: .BYTE $06 ; SKIP SLOT SIX SWAP TEST INITIALLY
|
|
|
|
.DATA
|
|
SWAPHNDL: .WORD $0000
|
|
SWAPREF: .BYTE $00
|
|
SWPAXED: .BYTE $00 ; MASK FOR ACCESSED TEST
|
|
SWPMINSIZE: .BYTE $00
|
|
SWPLEN: .WORD $0000
|
|
.ELSE
|
|
RTS
|
|
.ENDIF
|
|
;*
|
|
;* MEMORY MANAGER
|
|
;*
|
|
|
|
.CODE
|
|
;*
|
|
;* CONVERT HANDLE TO POINTER
|
|
;* ENTRYY: AX = HANDLE
|
|
;* EXIT: AX = POINTER
|
|
;*
|
|
HMEM_PTR: CHKAUXLC
|
|
CHKHNDL
|
|
AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
.IFDEF DEBUG_MEMMGR
|
|
JSR HMEM_VALIDATE
|
|
.ENDIF
|
|
.IFDEF SWAPPING
|
|
LDY #$00
|
|
LDA (HNDL),Y
|
|
.IFDEF DEBUG
|
|
LSR
|
|
BCS :+
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ "HMEM_PTR BEING CALLED ON FREE HANDLE: $"
|
|
AUXZP_ACCESS_ON
|
|
LDA HNDL+1
|
|
LDX HNDL
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
BRK
|
|
; JMP THROW_INTERNALERR
|
|
: ROL
|
|
.ENDIF
|
|
AND #$07
|
|
CMP #$07
|
|
BEQ HMEM_SWAPIN
|
|
LDA (HNDL),Y
|
|
AND #$F8
|
|
STA MPTR
|
|
INY
|
|
LDA (HNDL),Y
|
|
STA MPTR+1
|
|
TAX
|
|
LDY #$03
|
|
LDA (MPTR),Y
|
|
ORA #$80 ; SET ACCESSED FLAG
|
|
STA (MPTR),Y
|
|
LDA MPTR
|
|
.ELSE
|
|
LDY #$01
|
|
LDA (HNDL),Y
|
|
DEY
|
|
TAX
|
|
LDA (HNDL),Y
|
|
AND #$F8
|
|
.ENDIF
|
|
AUXZP_ACCESS_OFF
|
|
ORA #$04 ; RETURN POINTER
|
|
RTS
|
|
.IFDEF SWAPPING
|
|
;*
|
|
;* SWAP IN HANDLE MEMORY FROM FILE
|
|
;* ENTRY: HNDL = HANDLE
|
|
;*
|
|
HMEM_SWAPIN:
|
|
.IFDEF DEBUG_SWAP
|
|
AUXZP_ACCESS_OFF
|
|
JSR CROUT
|
|
JSR PUTS
|
|
.ASCIIZ "SWAPPING IN MEMORY HANDLE: "
|
|
AUXZP_ACCESS_ON
|
|
LDA HNDL+1
|
|
LDX HNDL
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
; JSR KBWAIT
|
|
AUXZP_ACCESS_ON
|
|
.ENDIF
|
|
LDA HNDL
|
|
STA SWAPHNDL
|
|
LDX HNDL+1
|
|
STX SWAPHNDL+1
|
|
LDY #$00 ; PULL BLOCK SIZE FROM HANDLE
|
|
LDA (HNDL),Y
|
|
INY
|
|
AND #$F8
|
|
SEC
|
|
.IFDEF DEBUG_MEMMGR
|
|
STA SWPLENBAK
|
|
LDA (HNDL),Y
|
|
STA SWPLENBAK+1
|
|
LDA SWPLENBAK
|
|
SBC #$06
|
|
.ELSE
|
|
SBC #$04
|
|
.ENDIF
|
|
PHA ; AND PUSH IT FOR LATER
|
|
STA TMP
|
|
LDA (HNDL),Y
|
|
SBC #$00
|
|
TAX
|
|
PHA
|
|
LDA TMP
|
|
|
|
.IFDEF DEBUG_SWAP
|
|
PHA
|
|
TXA
|
|
PHA
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ ", LENGTH: "
|
|
AUXZP_ACCESS_ON
|
|
PLA
|
|
STA TMP+1
|
|
PLA
|
|
STA TMP
|
|
TAX
|
|
LDA TMP+1
|
|
LDX TMP
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
AUXZP_ACCESS_ON
|
|
LDA TMP
|
|
LDX TMP+1
|
|
LDY #$00
|
|
.ENDIF
|
|
AUXZP_ACCESS_OFF
|
|
JSR HMEM_ALLOC ; ALLOCATE MEMORY
|
|
AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
LDY #$00
|
|
LDA (HNDL),Y
|
|
INY
|
|
AND #$F8
|
|
STA MPTR
|
|
LDA (HNDL),Y
|
|
STA MPTR+1 ; SAVE POINTER
|
|
.IFDEF DEBUG_MEMMGR
|
|
LDY #$00
|
|
LDA (MPTR),Y
|
|
CMP SWPLENBAK
|
|
BNE :+
|
|
INY
|
|
LDA (MPTR),Y
|
|
CMP SWPLENBAK+1
|
|
BEQ :++
|
|
: LDX SWPLENBAK
|
|
LDA SWPLENBAK+1
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR PUTS
|
|
.ASCIIZ " SWAPIN SIZE != ALLOC SIZE "
|
|
AUXZP_ACCESS_ON
|
|
LDY #$00
|
|
LDA (MPTR),Y
|
|
INY
|
|
TAX
|
|
LDA (MPTR),Y
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
BRK
|
|
SWPLENBAK: .WORD 0
|
|
:
|
|
.ENDIF
|
|
.IFDEF DEBUG_SWAP
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ ", ADDRESS: "
|
|
AUXZP_ACCESS_ON
|
|
LDA MPTR+1
|
|
LDX MPTR
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
AUXZP_ACCESS_ON
|
|
LDY #$01
|
|
.ENDIF
|
|
LDA HUNUSED+1 ; RETURN HANDLE TO UNUSED LIST
|
|
STA (HNDL),Y
|
|
DEY
|
|
LDA HUNUSED
|
|
STA (HNDL),Y
|
|
LDA HNDL
|
|
STA HUNUSED
|
|
LDA HNDL+1
|
|
STA HUNUSED+1
|
|
LDA SWAPHNDL ; ATTACH MEMORY TO SWAPIN HANDLE
|
|
STA HNDL
|
|
LDX SWAPHNDL+1
|
|
STX HNDL+1
|
|
JSR SETSWAPFILE
|
|
LDY #$00
|
|
LDA MPTR
|
|
STA (HNDL),Y
|
|
INY
|
|
LDA MPTR+1
|
|
STA (HNDL),Y
|
|
AUXZP_ACCESS_OFF
|
|
LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
JSR FILE_GETINFO
|
|
BCS SWAPINERR
|
|
AUXZP_ACCESS_ON
|
|
STA TMPTR
|
|
STX TMPTR+1
|
|
LDY #$04 ; READ FILE TYPE
|
|
LDA (TMPTR),Y
|
|
LDY #$00
|
|
AND #$07 ; RESTORE HANDLE TYPE BITS
|
|
ORA (HNDL),Y
|
|
STA (HNDL),Y
|
|
; LDY #$06 ; RESTORE MEMORY BLOCK REF COUNTS
|
|
; LDA (TMPTR),Y
|
|
; DEY
|
|
; TAX
|
|
; LDA (TMPTR),Y
|
|
; LDY #$02
|
|
; STA (MPTR),Y
|
|
; INY
|
|
; TXA
|
|
; ORA #$80 ; SET ACCESSED FLAG
|
|
; STA (MPTR),Y
|
|
LDY #$03
|
|
LDA (MPTR),Y
|
|
ORA #$80 ; SET ACCESSED FLAG
|
|
STA (MPTR),Y
|
|
AUXZP_ACCESS_OFF
|
|
LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
LDY #>SWAPFILE_IO_BUFF
|
|
JSR FILE_OPEN ; READ SWAPFILE
|
|
BCS SWAPINERR
|
|
STY SWAPREF
|
|
AUXZP_ACCESS_ON
|
|
LDA MPTR
|
|
; ORA #$04
|
|
ORA #$02
|
|
LDX MPTR+1
|
|
JSR FILE_SETBUFFER ; SET DESTINATION FOR READ
|
|
PLA ; PULL SIZE
|
|
TAX
|
|
PLA
|
|
AUXZP_ACCESS_OFF
|
|
CLC
|
|
ADC #$02 ; ADD SIZE OF REF COUNT
|
|
BCC :+
|
|
INX
|
|
: LDY SWAPREF
|
|
JSR FILE_READ ; READ IT!
|
|
BCS SWAPINERR
|
|
LDY SWAPREF
|
|
JSR FILE_CLOSE
|
|
LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
JSR FILE_DESTROY ; REMOVE EXISTING FILE
|
|
.IF 0
|
|
JSR PUTS
|
|
.ASCIIZ "SWAPIN AUX REF COUNT: "
|
|
AUXZP_ACCESS_ON
|
|
LDY #$02
|
|
LDA (MPTR),Y ; GET REFERENCE COUNTS OF MEMORY BLOCK
|
|
INY
|
|
TAX
|
|
LDA (MPTR),Y
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
.ENDIF
|
|
AUXZP_ACCESS_ON
|
|
.IFDEF DEBUG_MEMMGR
|
|
LDA SWAPHNDL
|
|
LDX SWAPHNDL+1
|
|
JSR HMEM_VALIDATE
|
|
.ENDIF
|
|
LDA MPTR
|
|
ORA #$04
|
|
LDX MPTR+1
|
|
AUXZP_ACCESS_OFF
|
|
RTS
|
|
SWAPINERR:
|
|
.IFDEF DEBUG_SWAP
|
|
AUXZP_ACCESS_OFF
|
|
PHA
|
|
JSR PUTS
|
|
.ASCIIZ "ERROR "
|
|
PLA
|
|
JSR PRBYTE
|
|
JSR PUTS
|
|
.ASCIIZ " READING FROM SWAPFILE: "
|
|
LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
JSR PRSTRLN
|
|
.ENDIF
|
|
JMP THROW_INTERNALERR
|
|
;*
|
|
;* SET SWAP FILE NAME BASED ON HANDLE
|
|
;* ENTRY: AX = HANDLE
|
|
;*
|
|
SETSWAPFILE: PHA
|
|
TXA
|
|
JSR BYTE2ASCII
|
|
LDX SWAPFILE ; GET SWAPFILE NAME LENGTH
|
|
STA SWAPFILE-3,X
|
|
TYA
|
|
STA SWAPFILE-2,X
|
|
PLA
|
|
JSR BYTE2ASCII
|
|
STA SWAPFILE-1,X
|
|
TYA
|
|
STA SWAPFILE-0,X
|
|
RTS
|
|
;*
|
|
;* CONVERT BYTE VALUE TO ASCII REPRESENTATION
|
|
;* ENTRY: A = BYTE
|
|
;* EXIT: A = ASCII HI NIBBLE
|
|
;* Y = ASCII LO NIBBLE
|
|
;*
|
|
BYTE2ASCII: PHA
|
|
AND #$0F
|
|
CLC
|
|
ADC #'0'
|
|
CMP #'9'+1
|
|
BCC :+
|
|
ADC #'A'-'9'-2
|
|
: TAY
|
|
PLA
|
|
LSR
|
|
LSR
|
|
LSR
|
|
LSR
|
|
CLC
|
|
ADC #'0'
|
|
CMP #'9'+1
|
|
BCC :+
|
|
ADC #'A'-'9'-2
|
|
: RTS
|
|
.ENDIF
|
|
;*
|
|
;* CLEAR MEMORY BLOCK
|
|
;* ENTRY: AX = HANDLE
|
|
;* EXIT: AX = HANDLE
|
|
;*
|
|
HMEM_CLR: CHKAUXLC
|
|
CHKHNDL
|
|
.IFDEF BIGMEM
|
|
STA HNDL ; THIS IS SAVED TO MAIN ZP, NOT AUX
|
|
STX HNDL+1
|
|
.ENDIF
|
|
JSR HMEM_PTR
|
|
STA DSTADDR
|
|
STX DSTADDR+1
|
|
AND #$F8 ; POINT BACK TO HEADER
|
|
STA MPTR
|
|
STX MPTR+1
|
|
LDY #$01
|
|
LDA (MPTR),Y
|
|
DEY
|
|
TAX
|
|
LDA (MPTR),Y
|
|
SEC
|
|
.IFDEF DEBUG_MEMMGR
|
|
SBC #$06 ; SUBTRACT FENCE+HEADER SIZE
|
|
.ELSE
|
|
SBC #$04 ; SUBTRACT HEADER SIZE
|
|
.ENDIF
|
|
BCS :+
|
|
DEX
|
|
: JSR MEMCLR ; CLEAR BLOCK
|
|
LDA HNDL ; RELOAD HANDLE INTO AX
|
|
LDX HNDL+1
|
|
RTS
|
|
;*
|
|
;* INCREMENT REFERENCE COUNT
|
|
;* ENTRY: AX = HANDLE
|
|
;* EXIT: AX = HANDLE
|
|
;*
|
|
HMEM_REF_INC: CHKAUXLC
|
|
CHKHNDL
|
|
.IFDEF DEBUG_MEMMGR
|
|
AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
JSR HMEM_VALIDATE
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
.ENDIF
|
|
.IF 0
|
|
STA HNDL
|
|
STX HNDL+1
|
|
JSR PUTS
|
|
.ASCIIZ "INC REF: $"
|
|
LDA HNDL+1
|
|
LDX HNDL
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
.ENDIF
|
|
.IFDEF SWAPPING
|
|
JSR HMEM_PTR
|
|
AUXZP_ACCESS_ON
|
|
LDX HNDL+1
|
|
LDY #$02
|
|
.ELSE
|
|
AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
LDY #$00
|
|
LDA (HNDL),Y
|
|
INY
|
|
AND #$F8
|
|
STA MPTR
|
|
LDA (HNDL),Y
|
|
INY
|
|
STA MPTR+1
|
|
.ENDIF
|
|
LDA (MPTR),Y
|
|
CLC
|
|
ADC #$01
|
|
STA (MPTR),Y
|
|
INY
|
|
LDA (MPTR),Y
|
|
ADC #$00
|
|
.IFDEF SWAPPING
|
|
ORA #$80 ; SET ACCESSED FLAG
|
|
.ENDIF
|
|
STA (MPTR),Y
|
|
LDA HNDL
|
|
AUXZP_ACCESS_OFF
|
|
RTS
|
|
;*
|
|
;* DECREMENT REFERENCE COUNT
|
|
;* ENTRY: AX = HANDLE
|
|
;* EXIT: AX = REF COUNT
|
|
;*
|
|
HMEM_REF_DEC: CHKAUXLC
|
|
CHKHNDL
|
|
.IFDEF DEBUG_MEMMGR
|
|
AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
JSR HMEM_VALIDATE
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
.ENDIF
|
|
.IF 0
|
|
STA HNDL
|
|
STX HNDL+1
|
|
JSR PUTS
|
|
.ASCIIZ "DEC REF: $"
|
|
LDA HNDL+1
|
|
LDX HNDL
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
.ENDIF
|
|
.IFDEF SWAPPING
|
|
JSR HMEM_PTR
|
|
LDY #$02
|
|
AUXZP_ACCESS_ON
|
|
.ELSE
|
|
AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
LDY #$00 ; DEREF HANDLE
|
|
LDA (HNDL),Y
|
|
INY
|
|
AND #$F8
|
|
STA MPTR
|
|
LDA (HNDL),Y
|
|
INY
|
|
STA MPTR+1
|
|
.ENDIF
|
|
LDA (MPTR),Y
|
|
SEC ; DEC REF COUNT
|
|
SBC #$01
|
|
STA (MPTR),Y
|
|
INY
|
|
PHA
|
|
LDA (MPTR),Y
|
|
AND #$7F
|
|
SBC #$00
|
|
TAX
|
|
.IFDEF SWAPPING
|
|
ORA #$80 ; SET ACCESSED FLAG
|
|
.ENDIF
|
|
STA (MPTR),Y
|
|
PLA
|
|
AUXZP_ACCESS_OFF
|
|
RTS
|
|
;*
|
|
;* LOCK MEMORY BLOCK IN PLACE
|
|
;* ENTRY: AX = HANDLE
|
|
;* EXIT: AX = POINTER
|
|
;*
|
|
HMEM_LOCK: JSR HMEM_PTR ; MAKE SURE MEM BLOCK PRESENT
|
|
.IF 0
|
|
JSR PUTS
|
|
.ASCIIZ "LOCKING HANDLE: "
|
|
AUXZP_ACCESS_ON
|
|
LDA HNDL+1
|
|
LDX HNDL
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
AUXZP_ACCESS_ON
|
|
LDY #$01
|
|
LDA (HNDL),Y
|
|
DEY
|
|
TAX
|
|
LDA (HNDL),Y
|
|
.ENDIF
|
|
LDY #$00
|
|
AND #$F8
|
|
ORA #$03 ; CHANGE FLAGS TO LOCKED
|
|
AUXZP_ACCESS_ON
|
|
STA (HNDL),Y ; AND SAVE
|
|
AUXZP_ACCESS_OFF
|
|
AND #$F8
|
|
ORA #$04
|
|
RTS
|
|
;*
|
|
;* UNLOCK MEMORY BLOCK
|
|
;* ENTRY: AX = HANDLE
|
|
;*
|
|
HMEM_UNLOCK: CHKHNDL
|
|
AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
.IF 0
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ "UNLOCKING HANDLE: "
|
|
AUXZP_ACCESS_ON
|
|
LDA HNDL+1
|
|
LDX HNDL
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
AUXZP_ACCESS_ON
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
.ENDIF
|
|
.IFDEF DEBUG_MEMMGR
|
|
JSR HMEM_VALIDATE
|
|
.ENDIF
|
|
LDY #$00
|
|
LDA (HNDL),Y
|
|
.IFDEF DEBUG_MEMMGR
|
|
TAX
|
|
AND #$07
|
|
CMP #$03
|
|
BEQ :+
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ "UNLOCKING UNLOCKED HANDLE :"
|
|
AUXZP_ACCESS_ON
|
|
LDA HNDL+1
|
|
LDX HNDL
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
JMP THROW_INTERNALERR
|
|
: TXA
|
|
LDY #$00
|
|
.ENDIF
|
|
AND #$F8
|
|
.IFDEF SWAPPING
|
|
STA MPTR
|
|
.ENDIF
|
|
ORA #$01
|
|
STA (HNDL),Y
|
|
AUXZP_ACCESS_OFF
|
|
RTS
|
|
;*
|
|
;* UNLOCK CODE MEMORY BLOCK
|
|
;* ENTRY: AX = HANDLE
|
|
;*
|
|
HMEM_UNLOCK_CODE: JSR HMEM_UNLOCK
|
|
LDY #$00
|
|
AUXZP_ACCESS_ON
|
|
LDA (HNDL),Y
|
|
ORA #$04
|
|
STA (HNDL),Y
|
|
AUXZP_ACCESS_OFF
|
|
RTS
|
|
;*
|
|
;* GET NEXT AVAILABLE HANDLE
|
|
;*
|
|
HMEM_NEW: LDA HUNUSED
|
|
LDX HUNUSED+1
|
|
BEQ HNEW_GC
|
|
PHA
|
|
LDY #$00
|
|
LDA (HUNUSED),Y
|
|
PHA
|
|
INY
|
|
LDA (HUNUSED),Y
|
|
STA HUNUSED+1
|
|
PLA
|
|
STA HUNUSED
|
|
PLA
|
|
CLC
|
|
RTS
|
|
HNEW_GC: AUXZP_ACCESS_OFF
|
|
JSR HMEM_COALESCE ; ATTEMPT EASY FREE SPACE COMBINE
|
|
AUXZP_ACCESS_ON
|
|
BCC HMEM_NEW
|
|
AUXZP_ACCESS_OFF
|
|
JSR HMEM_COMPACT ; ATTEMPT FREE SPACE COMPACTION
|
|
AUXZP_ACCESS_ON
|
|
BCC HNEW_GC
|
|
AUXZP_ACCESS_OFF
|
|
PERR "OUT OF MEMORY HANDLES"
|
|
; JSR HMEM_DUMP
|
|
; BRK
|
|
JMP THROW_INTERNALERR
|
|
;*
|
|
;* UNLINK FREE BLOCK FROM LIST
|
|
;*
|
|
HFREE_UNLINK: CMP HFREE
|
|
BNE :+
|
|
CPX HFREE+1
|
|
BNE :+
|
|
LDY #$00
|
|
LDA (HFREE),Y
|
|
INY
|
|
TAX
|
|
LDA (HFREE),Y
|
|
INY
|
|
STX HFREE
|
|
STA HFREE+1
|
|
.IFDEF DEBUG_MEMMGR
|
|
STX HFREEBAK ; SAVE BACKUP
|
|
STA HFREEBAK+1
|
|
.ENDIF
|
|
LDA (HFREE),Y ; UNLINK FROM HEAD-OF-LIST
|
|
INY
|
|
TAX
|
|
LDA (HFREE),Y
|
|
STX HFREE
|
|
STA HFREE+1
|
|
.IFDEF DEBUG_MEMMGR
|
|
STX HFREEBAK ; SAVE BACKUP
|
|
STA HFREEBAK+1
|
|
.ENDIF
|
|
RTS
|
|
: STA TMP
|
|
STX TMP+1
|
|
LDA HNDL ; SAVE HANDLE
|
|
PHA
|
|
LDA HNDL+1
|
|
PHA
|
|
LDA HFREE
|
|
LDX HFREE+1
|
|
LOOP_UNLINK: STA HNDL ; STORE HANDLE
|
|
STX HNDL+1
|
|
LDY #$01 ; DEREF HANDLE FOR POINTER
|
|
LDA (HNDL),Y
|
|
DEY
|
|
TAX
|
|
LDA (HNDL),Y
|
|
STA HNDL
|
|
STX HNDL+1
|
|
LDY #$03 ; CHECK NEXT HANDLE
|
|
LDA (HNDL),Y
|
|
.IFDEF DEBUG_MEMMGR
|
|
BNE :+
|
|
AUXZP_ACCESS_OFF
|
|
PERR "UNLINK FREE BLOCK NOT IN LIST"
|
|
JMP THROW_INTERNALERR
|
|
:
|
|
.ENDIF
|
|
DEY
|
|
TAX
|
|
LDA (HNDL),Y
|
|
CMP TMP
|
|
BNE LOOP_UNLINK
|
|
CPX TMP+1
|
|
BNE LOOP_UNLINK
|
|
DEY ; HANDLES EQUAL
|
|
LDA (TMP),Y ; DEREF TMP
|
|
DEY
|
|
TAX
|
|
LDA (TMP),Y
|
|
STA TMPTR
|
|
STX TMPTR+1
|
|
LDY #$03
|
|
LDA (TMPTR),Y ; MOVE NEXT LINK TO PREVIOUS
|
|
STA (HNDL),Y
|
|
DEY
|
|
LDA (TMPTR),Y
|
|
STA (HNDL),Y
|
|
.IFDEF DEBUG_MEMMGR
|
|
JSR HFREE_VALIDATE
|
|
.ENDIF
|
|
PLA ; RESTORE HNDL
|
|
STA HNDL+1
|
|
PLA
|
|
STA HNDL
|
|
RTS
|
|
;*
|
|
;* ALLOCATE A MEMORY BLOCK
|
|
;* ENTRY: AX (LH) = SIZE
|
|
;* Y = INITIAL REF COUNT
|
|
;* EXIT: AX = HANDLE :: C == 0
|
|
;* ERR :: C == 1
|
|
;*
|
|
HMEM_ALLOC: CHKAUXLC
|
|
.IFDEF DEBUG
|
|
CPX #$10
|
|
BCC :+
|
|
STA MLEN
|
|
STX MLEN+1
|
|
PERR "Big alloc: $"
|
|
LDX MLEN
|
|
LDA MLEN+1
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
LDA MLEN
|
|
LDX MLEN+1
|
|
; JMP THROW_INTERNALERR
|
|
:
|
|
.ENDIF
|
|
AUXZP_ACCESS_ON
|
|
STY REFCNT
|
|
CLC ; ADD SIZE OF HEADER (4 + 7)
|
|
.IFDEF DEBUG_MEMMGR
|
|
ADC #$0D ; AND ROUND TO MULTIPLE OF 8 BYTES
|
|
.ELSE
|
|
ADC #$0B ; AND ROUND TO MULTIPLE OF 8 BYTES
|
|
.ENDIF
|
|
BCC :+
|
|
INX
|
|
: AND #$F8
|
|
STA MLEN
|
|
STX MLEN+1
|
|
.IFDEF DEBUG_MEMMGR
|
|
STA MLENBAK
|
|
STX MLENBAK+1
|
|
JMP SEARCH_FREE
|
|
MLENBAK: .WORD $0000
|
|
.ENDIF
|
|
SEARCH_FREE: LDA HFREE ; SEARCH FREE LIST FOR AVAILABLE SPACE
|
|
STA HNDL
|
|
LDA HFREE+1
|
|
STA HNDL+1
|
|
BEQ MAKE_FREE_AVAIL
|
|
LDA #$00 ; CLEAR OUT BEST MATCH
|
|
; STA HBEST
|
|
STA HBEST+1
|
|
LOOP_FREE: AUXZP_ACCESS_ON
|
|
LDY #$01 ; DEREF HANDLE
|
|
LDA (HNDL),Y
|
|
DEY
|
|
STA MPTR+1
|
|
LDA (HNDL),Y
|
|
STA MPTR
|
|
LDA (MPTR),Y
|
|
INY
|
|
SEC
|
|
SBC MLEN
|
|
TAX
|
|
LDA (MPTR),Y
|
|
SBC MLEN+1
|
|
BCC NEXT_FREE
|
|
BNE :+
|
|
CPX #$00
|
|
BNE :+
|
|
JMP MATCH_FREE
|
|
: LDA HBEST+1 ; CHECK FOR EXISTING BEST MATCH
|
|
BEQ SAVE_BEST ; SAVE ONE WITH HIGHEST ADDRESS
|
|
LDA (HNDL),Y ; COMPARE FREE BLOCK ADDRESSES
|
|
CMP (HBEST),Y
|
|
BCC NEXT_FREE
|
|
BNE SAVE_BEST
|
|
DEY
|
|
LDA (HNDL),Y
|
|
CMP (HBEST),Y
|
|
BCC NEXT_FREE
|
|
SAVE_BEST: LDA HNDL
|
|
STA HBEST
|
|
LDA HNDL+1
|
|
STA HBEST+1
|
|
NEXT_FREE: LDY #$02 ; FOLLOW LINKED FREE LIST
|
|
LDA (MPTR),Y
|
|
INY
|
|
STA HNDL
|
|
LDA (MPTR),Y
|
|
STA HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
BNE LOOP_FREE ; CONTINUE UNTIL NULL NEXT
|
|
AUXZP_ACCESS_ON
|
|
LDA HBEST+1
|
|
BEQ :+
|
|
JMP BEST_FREE
|
|
:
|
|
.IFDEF SWAPPING
|
|
LDA #$FF
|
|
LDX MLEN+1
|
|
BNE :+
|
|
LDA MLEN
|
|
: STA SWPMINSIZE
|
|
.ENDIF
|
|
MAKE_FREE_AVAIL: AUXZP_ACCESS_OFF
|
|
JSR HMEM_COALESCE ; ATTEMPT EASY FREE SPACE COMBINE
|
|
AUXZP_ACCESS_ON
|
|
BCS :+
|
|
LDA GCMLEN ; ONLY ATTEMPT SEARCH FREE IF COALESCED
|
|
CMP MLEN ; BLOCK IS GREATER OR EQUAL TO REQUESTED SIZE
|
|
LDA GCMLEN+1
|
|
SBC MLEN+1
|
|
BCC MAKE_FREE_AVAIL
|
|
JMP SEARCH_FREE
|
|
:
|
|
.IFDEF SWAPPING
|
|
SWAPRETRY: AUXZP_ACCESS_OFF
|
|
JSR HMEM_SWAPOUT_UNAXED ; ATTEMPT SWAPPING OUT UNACCESSED BLOCKS
|
|
BCC :++
|
|
: JSR HMEM_COMPACT ; ATTEMPT FREE SPACE COMPACTION
|
|
BCC :-
|
|
JSR HMEM_SWAPOUT_UNLOCKED ; ATTEMPT SWAPPING OUT UNLOCKED BLOCKS
|
|
: AUXZP_ACCESS_ON
|
|
BCS :+
|
|
LDA SWPLEN ; ONLY ATTEMPT SEARCH FREE IF COALESCED
|
|
CMP MLEN ; BLOCK IS GREATER OR EQUAL TO REQUESTED SIZE
|
|
LDA SWPLEN+1
|
|
SBC MLEN+1
|
|
BCC MAKE_FREE_AVAIL
|
|
JMP SEARCH_FREE
|
|
: LSR SWPMINSIZE
|
|
BNE SWAPRETRY
|
|
.ELSE
|
|
AUXZP_ACCESS_OFF
|
|
JSR HMEM_COMPACT ; ATTEMPT FREE SPACE COMPACTION
|
|
AUXZP_ACCESS_ON ; ONLY DO THIS AS A LAST RESORT
|
|
BCC MAKE_FREE_AVAIL
|
|
.ENDIF
|
|
JMP ALLOC_ERR
|
|
MATCH_FREE: LDA HNDL ; EXACT FIT - USE IT
|
|
LDX HNDL+1
|
|
JSR HFREE_UNLINK
|
|
LDY #$00
|
|
LDA (HNDL),Y
|
|
ORA #$01 ; SET ALLOCED FLAG
|
|
STA (HNDL),Y
|
|
LDY #$02 ; SET INITIAL REFERENCE COUNT
|
|
LDA REFCNT
|
|
.IFDEF DEBUG_MEMMGR
|
|
CMP #$02
|
|
BCC :+
|
|
AUXZP_ACCESS_OFF
|
|
PERR "LARGE REFCNT IN MEMALLOC"
|
|
JSR KBWAIT
|
|
AUXZP_ACCESS_ON
|
|
LDY #$02 ; SET INITIAL REFERENCE COUNT
|
|
LDA REFCNT
|
|
:
|
|
.ENDIF
|
|
STA (MPTR),Y
|
|
INY
|
|
.IFDEF SWAPPING
|
|
LDA #$80 ; SET ACCESSED FLAG
|
|
.ELSE
|
|
LDA #$00
|
|
.ENDIF
|
|
STA (MPTR),Y
|
|
.IFDEF DEBUG_MEMMGR
|
|
LDA MLEN ; WRITE FENCE
|
|
LDX MLEN+1
|
|
CMP MLENBAK
|
|
BNE :+
|
|
CPX MLENBAK+1
|
|
BEQ :++
|
|
: AUXZP_ACCESS_OFF
|
|
PERR "BAD MLEN"
|
|
BRK
|
|
: SEC
|
|
SBC #$02
|
|
BCS :+
|
|
DEX
|
|
: CLC
|
|
ADC MPTR
|
|
STA MPTR
|
|
TXA
|
|
ADC MPTR+1
|
|
STA MPTR+1
|
|
LDY #$00
|
|
LDA #$CA
|
|
STA (MPTR),Y
|
|
INY
|
|
LDA #$FE
|
|
STA (MPTR),Y
|
|
JSR HFREE_VALIDATE
|
|
LDA HNDL ; RETURN HANDLE, NO ERR
|
|
LDX HNDL+1
|
|
JSR HMEM_VALIDATE
|
|
.ENDIF
|
|
.IFDEF DEBUG
|
|
LDA RAMAVAIL ; UPDATE AVAILABLE RAM
|
|
SEC
|
|
SBC MLEN
|
|
STA RAMAVAIL
|
|
LDA RAMAVAIL+1
|
|
SBC MLEN+1
|
|
STA RAMAVAIL+1
|
|
JSR PRNTRAM
|
|
.ENDIF
|
|
LDA HNDL ; RETURN HANDLE, NO ERR
|
|
LDX HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
CLC
|
|
RTS
|
|
BEST_FREE: LDY #$00 ; DEREF FREE HANDLE
|
|
LDA (HBEST),Y
|
|
INY
|
|
STA TMPTR
|
|
LDA (HBEST),Y
|
|
DEY
|
|
STA TMPTR+1
|
|
LDA (TMPTR),Y
|
|
SEC ; SUB MLEN FROM FREE SIZE
|
|
SBC MLEN
|
|
STA (TMPTR),Y
|
|
INY
|
|
LDA (TMPTR),Y
|
|
SBC MLEN+1
|
|
STA (TMPTR),Y
|
|
DEY ; CALC ALLOCED POINTER
|
|
CLC
|
|
LDA TMPTR
|
|
ADC (TMPTR),Y
|
|
INY
|
|
STA MPTR
|
|
LDA TMPTR+1
|
|
ADC (TMPTR),Y
|
|
DEY ; SET LENGTH IN ALLOCED BLOCK
|
|
STA MPTR+1
|
|
LDA MLEN
|
|
STA (MPTR),Y
|
|
INY
|
|
LDA MLEN+1
|
|
STA (MPTR),Y
|
|
INY ; SET REFERENCE COUNT
|
|
LDA REFCNT
|
|
.IFDEF DEBUG_MEMMGR
|
|
CMP #$02
|
|
BCC :+
|
|
AUXZP_ACCESS_OFF
|
|
PERR "LARGE REFCNT IN MEMALLOC"
|
|
JSR KBWAIT
|
|
AUXZP_ACCESS_ON
|
|
LDY #$02 ; SET INITIAL REFERENCE COUNT
|
|
LDA REFCNT
|
|
:
|
|
.ENDIF
|
|
STA (MPTR),Y
|
|
INY
|
|
.IFDEF SWAPPING
|
|
LDA #$80 ; SET ACCESSED FLAG
|
|
.ELSE
|
|
LDA #$00
|
|
.ENDIF
|
|
STA (MPTR),Y
|
|
JSR HMEM_NEW ; GET NEW HANDLE
|
|
.IFDEF DEBUG_MEMMGR
|
|
BCC :+
|
|
JMP ALLOC_ERR
|
|
:
|
|
.ELSE
|
|
BCS ALLOC_ERR
|
|
.ENDIF
|
|
STA HNDL
|
|
STX HNDL+1
|
|
LDY #$00 ; UPDATE HANDLE POINTERS
|
|
LDA MPTR
|
|
ORA #$01 ; SET ALLOCED FLAG
|
|
STA (HNDL),Y ; SET POINTER IN HANDLE TABLE
|
|
INY
|
|
LDA MPTR+1
|
|
STA (HNDL),Y
|
|
.IFDEF DEBUG_MEMMGR
|
|
LDA MLEN ; WRITE FENCE
|
|
LDX MLEN+1
|
|
CMP MLENBAK
|
|
BNE :+
|
|
CPX MLENBAK+1
|
|
BEQ :++
|
|
: AUXZP_ACCESS_OFF
|
|
PERR "BAD MLEN"
|
|
BRK
|
|
: SEC
|
|
SBC #$02
|
|
BCS :+
|
|
DEX
|
|
: CLC
|
|
ADC MPTR
|
|
STA MPTR
|
|
TXA
|
|
ADC MPTR+1
|
|
STA MPTR+1
|
|
LDY #$00
|
|
LDA #$CA
|
|
STA (MPTR),Y
|
|
INY
|
|
LDA #$FE
|
|
STA (MPTR),Y
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
JSR HMEM_VALIDATE
|
|
LDX HNDL+1
|
|
.ENDIF
|
|
.IFDEF DEBUG
|
|
LDA RAMAVAIL ; UPDATE AVAILABLE RAM
|
|
SEC
|
|
SBC MLEN
|
|
STA RAMAVAIL
|
|
LDA RAMAVAIL+1
|
|
SBC MLEN+1
|
|
STA RAMAVAIL+1
|
|
JSR PRNTRAM
|
|
.ENDIF
|
|
LDA HNDL ; RETURN HANDLE, NO ERR
|
|
AUXZP_ACCESS_OFF
|
|
CLC
|
|
RTS
|
|
ALLOC_ERR:
|
|
.IFDEF DEBUG_MEMMGR
|
|
AUXZP_ACCESS_OFF
|
|
PERR "CANT ALLOC SIZE:"
|
|
AUXZP_ACCESS_ON
|
|
LDA MLEN+1
|
|
LDX MLEN
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
AUXZP_ACCESS_ON
|
|
JSR HMEM_DUMP
|
|
BRK
|
|
.ENDIF
|
|
AUXZP_ACCESS_OFF
|
|
LDA #4 ; OUT OF MEMORY
|
|
JMP SYSTHROW
|
|
;*
|
|
;* ALLOC CODE MEMORY
|
|
;* ENTRY: AX (LH) = SIZE
|
|
;* Y = INITIAL REF COUNT
|
|
;* EXIT: AX = HANDLE :: C == 0
|
|
;* ERR :: C == 1
|
|
;*
|
|
HMEM_ALLOC_CODE: CHKAUXLC
|
|
JSR HMEM_ALLOC
|
|
BCS :+
|
|
AUXZP_ACCESS_ON
|
|
LDY #$00
|
|
LDA (HNDL),Y
|
|
ORA #$04 ; SET CODE FLAG IN ALLOC BLOCK FLAGS
|
|
STA (HNDL),Y
|
|
LDA HNDL
|
|
AUXZP_ACCESS_OFF
|
|
: RTS
|
|
|
|
;*
|
|
;* ALLOCATE A MEMORY BLOCK AT FIXED ADDRESS
|
|
;* ENTRY: X = PAGE ADDRESS
|
|
;* A = SIZE IN PAGES
|
|
;* Y = INITIAL REF COUNT
|
|
;* EXIT: AX = HANDLE :: C == 0
|
|
;* ERR :: C == 1
|
|
;*
|
|
HMEM_ALLOC_FIXED: CHKAUXLC
|
|
AUXZP_ACCESS_ON
|
|
STY REFCNT
|
|
STA MEND+1
|
|
TXA
|
|
CLC
|
|
ADC MEND+1
|
|
STA MEND+1 ; MEND = END ADDRESS OF BLOCK
|
|
.IFDEF DEBUG_MEMMGR
|
|
LDA #$08 ; LEAVE ROOM FOR DEBUG FENCE
|
|
STA MEND
|
|
.ELSE
|
|
LDA #$00
|
|
STA MEND
|
|
.ENDIF
|
|
LDA #$F8 ; SUBTRACT 8 BYTE MIN ALIGNED HEADER
|
|
DEX
|
|
STA MPTR
|
|
STX MPTR+1
|
|
DVM_BEGIN
|
|
LDZPW MEND
|
|
LDZPW MPTR
|
|
SUBW
|
|
STZPW MLEN
|
|
SEARCH_FIXED: LDZPW HFREE
|
|
LOOP_FIXED: DUPW
|
|
STZPW HNDL
|
|
BRZW ALLOC_FIXED_ERR
|
|
LDZPW MPTR
|
|
LDPW (HNDL),0
|
|
DUPW
|
|
STZPW TMPTR
|
|
BRBW NEXT_FIXED ; SKIP IF REQUESTED RANGE STARTS BELOW FREE
|
|
LDZPW TMPTR ; FIND END OF FREE BLOCK
|
|
LDPW (TMPTR),0
|
|
ADDW
|
|
LDZPW MEND
|
|
SUBW
|
|
DUPW
|
|
BRPOSW FOUND_FIXED ; THIS FREE BLOCK ENCOMPASSES REQUESTED RANGE
|
|
POPW ; RE-ENABLE INTERRUPTS FOR A MOMENT
|
|
NEXT_FIXED: LDPW (TMPTR),2
|
|
BRNCH LOOP_FIXED
|
|
ALLOC_FIXED_ERR: DVM_END
|
|
AUXZP_ACCESS_OFF
|
|
.IFDEF DEBUG_MEMMGR
|
|
; PERR "ALLOC_FIXED PAGES UNAVAILABLE"
|
|
; JSR KBWAIT
|
|
.ENDIF
|
|
SEC ; RETURN WITH ERR
|
|
RTS
|
|
FOUND_FIXED: DUPW
|
|
BRZW FRONT_FREE_FIXED
|
|
END_FREE_FIXED: STPW (MEND),0 ; SET SIZE OF NEW FREE END BLOCK
|
|
LDZPW HFREE
|
|
STPW (MEND),2 ; ADD TO FREE LIST
|
|
DVM_END
|
|
JSR HMEM_NEW ; GET NEW HANDLE FOR END FREE BLOCK
|
|
BCS ALLOC_FIXED_ERR+1
|
|
STA HFREE
|
|
STX HFREE+1
|
|
.IFDEF DEBUG_MEMMGR
|
|
STA HFREEBAK ; SAVE BACKUP
|
|
STX HFREEBAK+1
|
|
.ENDIF
|
|
DVM_BEGIN
|
|
LDZPW MEND
|
|
DUPW
|
|
STPW (HFREE),0
|
|
FRONT_FREE_FIXED: POPW
|
|
LDZPW MPTR
|
|
LDZPW TMPTR
|
|
SUBW
|
|
DUPW
|
|
BRZW FRONT_EQUAL_FIXED ; EQUAL START ADDRESSES
|
|
STPW (TMPTR),0
|
|
DVM_END
|
|
JSR HMEM_NEW ; GET NEW HANDLE FOR ALLOCED BLOCK
|
|
BCS ALLOC_FIXED_ERR+1
|
|
STA HNDL
|
|
STX HNDL+1
|
|
DVM_BEGIN
|
|
LDZPW MPTR
|
|
LD3W
|
|
ORW ; SET FIXED AND ALLOCED FLAGS
|
|
STPW (HNDL),0 ; SAVE POINTER IN NEW HANDLE
|
|
BRNCH SET_ALLOC_FIXED
|
|
FRONT_EQUAL_FIXED: POPW
|
|
DVM_END
|
|
LDA HNDL ; SAME START ADDRESS FOR FREE AND ALLOC BLOCK
|
|
LDX HNDL+1 ; RE-USE FREE BLOCK
|
|
JSR HFREE_UNLINK ; UNLINK FREE BLOCK
|
|
DVM_BEGIN
|
|
LDPB (HNDL),0
|
|
LD3B
|
|
ORB ; SET FIXED AND ALLOCED FLAGS
|
|
STPB (HNDL),0
|
|
SET_ALLOC_FIXED: LDZPW MLEN
|
|
STPW (MPTR),0
|
|
LDB REFCNT
|
|
ZEXTB
|
|
STPW (MPTR),2
|
|
DVM_END
|
|
.IFDEF DEBUG_MEMMGR
|
|
LDA MLEN ; WRITE FENCE
|
|
LDX MLEN+1
|
|
SEC
|
|
SBC #$02
|
|
BCS :+
|
|
DEX
|
|
: CLC
|
|
ADC MPTR
|
|
STA MPTR
|
|
TXA
|
|
ADC MPTR+1
|
|
STA MPTR+1
|
|
LDY #$00
|
|
LDA #$CA
|
|
STA (MPTR),Y
|
|
INY
|
|
LDA #$FE
|
|
STA (MPTR),Y
|
|
LDA HNDL ; RETURN HANDLE, NO ERR
|
|
LDX HNDL+1
|
|
JSR HMEM_VALIDATE
|
|
.ENDIF
|
|
.IFDEF DEBUG
|
|
LDA RAMAVAIL ; UPDATE AVAILABLE RAM
|
|
SEC
|
|
SBC MLEN
|
|
STA RAMAVAIL
|
|
LDA RAMAVAIL+1
|
|
SBC MLEN+1
|
|
STA RAMAVAIL+1
|
|
JSR PRNTRAM
|
|
.ENDIF
|
|
LDA HNDL ; RETURN HANDLE, NO ERR
|
|
LDX HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
CLC
|
|
RTS
|
|
.IFDEF SWAPPING
|
|
;*
|
|
;* INCREMENTALLY CLEAR ACCESSED FLAG ON ALL IN-USE BLOCKS
|
|
;* CALLED FROM THREAD_YEILD
|
|
;*
|
|
CLRACCHNDL: .ADDR HTBL
|
|
HMEM_CLRACCESS: CHKAUXLC
|
|
LDA CLRACCHNDL
|
|
LDX CLRACCHNDL+1
|
|
CLC
|
|
ADC #$02
|
|
BCC :++
|
|
INX
|
|
CPX #>HTBL_END
|
|
BCC :+
|
|
LDA #<HTBL
|
|
LDX #>HTBL
|
|
: STX CLRACCHNDL+1
|
|
: STA CLRACCHNDL
|
|
CHKHNDL
|
|
AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
LDY #$00
|
|
LDA (HNDL),Y
|
|
AND #$03 ; SKIP FREE, FIXED OR SWAPPED BLOCKS
|
|
CMP #$01
|
|
BNE :+
|
|
.IFDEF DEBUG_MEMMGR
|
|
LDA HNDL
|
|
JSR HNDL_VALIDATE
|
|
LDY #$00
|
|
.ENDIF
|
|
LDA (HNDL),Y ; CLEAR ACCESSED FLAG
|
|
INY
|
|
AND #$F8
|
|
STA MPTR
|
|
LDA (HNDL),Y
|
|
STA MPTR+1
|
|
LDY #$03
|
|
LDA (MPTR),Y
|
|
AND #$7F
|
|
STA (MPTR),Y
|
|
: AUXZP_ACCESS_OFF
|
|
RTS
|
|
;*
|
|
;* SWAP OUT UNLOCKED BLOCKS LARGER THAN SWAPMINSIZE
|
|
;*
|
|
SWPBESTHNDL: .WORD HTBL
|
|
HMEM_SWAPOUT_UNLOCKED:
|
|
.IFDEF DEBUG_SWAP
|
|
JSR PUTSLN
|
|
.ASCIIZ "SWAP OUT UNLOCKED BLOCKS"
|
|
.ENDIF
|
|
LDA #$00
|
|
BEQ SWAPOUT_BEST
|
|
;*
|
|
;* SWAP OUT UNACCESSED BLOCKS
|
|
;*
|
|
HMEM_SWAPOUT_UNAXED:
|
|
.IFDEF DEBUG_SWAP
|
|
JSR PUTSLN
|
|
.ASCIIZ "SWAP OUT UNACCESSED BLOCKS"
|
|
.ENDIF
|
|
LDA #$80
|
|
SWAPOUT_BEST: STA SWPAXED
|
|
LDA SWPBESTHNDL
|
|
LDX SWPBESTHNDL+1
|
|
CLC
|
|
ADC #$02
|
|
BCC :++
|
|
INX
|
|
CPX #>HTBL_END
|
|
BCC :+
|
|
LDA #<HTBL
|
|
LDX #>HTBL
|
|
: STX SWPBESTHNDL+1
|
|
: STA SWPBESTHNDL
|
|
SWPBESTLP: AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
LDY #$00
|
|
LDA (HNDL), Y
|
|
AND #$03 ; SKIP FREE, FIXED OR SWAPPED BLOCKS
|
|
CMP #$01
|
|
BNE SWPBESTNXT
|
|
LDA (HNDL),Y
|
|
INY
|
|
AND #$F8
|
|
STA MPTR
|
|
LDA (HNDL),Y
|
|
STA MPTR+1
|
|
LDY #$03 ; CHECK ACCESSED BIT
|
|
LDA (MPTR),Y
|
|
AND SWPAXED ; TEST MASK FOR UNACCESSED VS UNLOCKED
|
|
BMI SWPBESTNXT ; SKIP ACCESSED BLOCKS
|
|
LDY #$01
|
|
LDA (MPTR),Y ; COMPARE BLOCK SIZE FOR > SWAPMINSIZE
|
|
BNE SWPBEST
|
|
DEY
|
|
LDA (MPTR),Y
|
|
CMP SWPMINSIZE
|
|
BCS SWPBEST
|
|
SWPBESTNXT: LDA HNDL
|
|
; LDX HNDL+1 ; NEXT HANDLE
|
|
AUXZP_ACCESS_OFF
|
|
SWPBESTINC: CLC
|
|
ADC #$02
|
|
BCC :+
|
|
INX
|
|
CPX #>HTBL_END
|
|
BCC :+
|
|
LDA #<HTBL
|
|
LDX #>HTBL
|
|
: CMP SWPBESTHNDL ; EXIT AFTER LOOPING ONCE
|
|
BNE SWPBESTLP
|
|
CPX SWPBESTHNDL+1
|
|
BNE SWPBESTLP
|
|
SEC
|
|
RTS
|
|
SWPBEST: LDA HNDL
|
|
STA SWPBESTHNDL
|
|
STX SWPBESTHNDL+1
|
|
; JMP HMEM_SWAPOUT ; SWAP BLOCK OUT
|
|
;*
|
|
;* SWAP OUT MEMORY BLOCK TO FILE
|
|
;* ENTRY: AX = HANDLE
|
|
;*
|
|
HMEM_SWAPOUT: AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
.IFDEF DEBUG_SWAP
|
|
AUXZP_ACCESS_OFF
|
|
JSR CROUT
|
|
JSR PUTS
|
|
.ASCIIZ "SWAPPING OUT MEMORY HANDLE: "
|
|
AUXZP_ACCESS_ON
|
|
LDA HNDL+1
|
|
LDX HNDL
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
; JSR CROUT
|
|
; JSR KBWAIT
|
|
AUXZP_ACCESS_ON
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
.ENDIF
|
|
.IFDEF DEBUG_MEMMGR
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
JSR HMEM_VALIDATE
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
.ENDIF
|
|
; LDY #$FF
|
|
; STY SWAPREF
|
|
; LDA HNDL
|
|
; LDX HNDL+1
|
|
JSR SETSWAPFILE
|
|
; AUXZP_ACCESS_OFF
|
|
; LDA #<SWAPFILE
|
|
; LDX #>SWAPFILE
|
|
; JSR FILE_DESTROY ; REMOVE ANY EXISTING FILE
|
|
; AUXZP_ACCESS_ON
|
|
LDY #$00 ; GET POINTER TO MEMORY BLOCK
|
|
LDA (HNDL),Y
|
|
INY
|
|
PHA
|
|
AND #$F8
|
|
STA MPTR
|
|
LDA (HNDL),Y
|
|
STA MPTR+1
|
|
; LDY #$03
|
|
; LDA (MPTR),Y ; GET REFERENCE COUNTS OF MEMORY BLOCK
|
|
; DEY
|
|
; TAX
|
|
; LDA (MPTR),Y
|
|
; JSR FILE_SETAUX ; SET AUX TYPE FOR FILE
|
|
.IF 0
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ "SWAPOUT AUX REF COUNT: "
|
|
AUXZP_ACCESS_ON
|
|
LDY #$02
|
|
LDA (MPTR),Y ; GET REFERENCE COUNTS OF MEMORY BLOCK
|
|
INY
|
|
TAX
|
|
LDA (MPTR),Y
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
AUXZP_ACCESS_ON
|
|
.ENDIF
|
|
PLA ; GET FILE TYPE BITS FROM BLOCK BITS
|
|
TAY
|
|
AUXZP_ACCESS_OFF
|
|
LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
JSR FILE_CREATE
|
|
; BCS SWAPOUTERR
|
|
LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
LDY #>SWAPFILE_IO_BUFF
|
|
JSR FILE_OPEN ; OPEN NEWLY CREATED FILE
|
|
; DSS BCS SWAPOUTERR
|
|
STY SWAPREF
|
|
AUXZP_ACCESS_ON
|
|
LDX MPTR+1
|
|
TXA
|
|
PHA
|
|
LDA MPTR
|
|
PHA
|
|
; ORA #$04
|
|
ORA #$02
|
|
JSR FILE_SETBUFFER
|
|
LDY #$01 ; GET SIZE OF BLOCK
|
|
LDA (MPTR),Y
|
|
DEY
|
|
TAX
|
|
LDA (MPTR),Y
|
|
STA SWPLEN
|
|
STX SWPLEN+1
|
|
.IFDEF DEBUG_SWAP
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ " LENGTH: "
|
|
AUXZP_ACCESS_ON
|
|
LDA SWPLEN+1
|
|
LDX SWPLEN
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
; JSR KBWAIT
|
|
AUXZP_ACCESS_ON
|
|
LDA SWPLEN
|
|
LDX SWPLEN+1
|
|
.ENDIF
|
|
SEC ; SUBTRACT OFF BLOCK HEADER SIZE
|
|
.IFDEF DEBUG_MEMMGR
|
|
; SBC #$06
|
|
SBC #$04
|
|
.ELSE
|
|
; SBC #$04
|
|
SBC #$02
|
|
.ENDIF
|
|
BCS :+
|
|
DEX
|
|
: AUXZP_ACCESS_OFF
|
|
LDY SWAPREF
|
|
JSR FILE_WRITE
|
|
BCS SWAPOUTERR
|
|
LDY SWAPREF
|
|
JSR FILE_CLOSE
|
|
BCS SWAPOUTERR
|
|
AUXZP_ACCESS_ON
|
|
LDY #$00
|
|
LDA (HNDL),Y
|
|
LDA #$07 ; SET SWAPPED BITS FOR HANDLE
|
|
ORA SWPLEN ; STICK BLOCK SIZE IN HANDLE DATA
|
|
STA (HNDL),Y
|
|
INY
|
|
LDA SWPLEN+1 ; CLEVER, HUH?
|
|
STA (HNDL),Y
|
|
JSR HMEM_NEW ; GET NEW HANDLE TO POINT TO OLD MEMORY
|
|
STA HNDL
|
|
STX HNDL+1
|
|
STA COMPGCHNDL ; FOCUS COMPACTOR HERE
|
|
STX COMPGCHNDL+1
|
|
LDY #$00 ; MOVE BLOCK POINTER TO NEW HANDLE
|
|
PLA
|
|
ORA #$01
|
|
STA (HNDL),Y
|
|
INY
|
|
PLA
|
|
STA (HNDL),Y
|
|
.IFDEF DEBUG
|
|
LDY #$02 ; ZERO OUT REF COUNT
|
|
LDA #$00
|
|
STA (MPTR),Y
|
|
INY
|
|
STA (MPTR),Y
|
|
.ENDIF
|
|
.IF 0
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ "SWAPOUT FREE HANDLE: $"
|
|
AUXZP_ACCESS_ON
|
|
LDX HNDL
|
|
LDA HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
AUXZP_ACCESS_ON
|
|
.ENDIF
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
;JMP HMEM_FREE ; NOW FREE THE OLD BLOCK AND NEW HANDLE
|
|
BNE HMEM_FREE ; NOW FREE THE OLD BLOCK AND NEW HANDLE
|
|
SWAPOUTERR:
|
|
AUXZP_ACCESS_OFF
|
|
.IFDEF DEBUG_SWAP
|
|
PHA
|
|
JSR PUTS
|
|
.ASCIIZ "ERROR "
|
|
PLA
|
|
JSR PRBYTE
|
|
JSR PUTS
|
|
.ASCIIZ " WRITING TO SWAPFILE: "
|
|
LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
JSR PRSTRLN
|
|
.ENDIF
|
|
LDY SWAPREF ; ATTEMPT CLEAN-UP
|
|
BMI :+
|
|
JSR FILE_CLOSE
|
|
: LDA #<SWAPFILE
|
|
LDX #>SWAPFILE
|
|
JSR FILE_DESTROY
|
|
SEC ; SET CARRY AND EXIT - NO ERROR
|
|
RTS
|
|
.ENDIF
|
|
;*
|
|
;* FREE MEMORY BLOCK
|
|
;* ENTRY: AX = HANDLE
|
|
;* EXIT: C = 0 :: NO ERROR
|
|
;*
|
|
HMEM_FREE: CHKAUXLC
|
|
CHKHNDL
|
|
.IF 0
|
|
AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ "FREE HANDLE: "
|
|
AUXZP_ACCESS_ON
|
|
LDA HNDL+1
|
|
LDX HNDL
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
LDA #'-'
|
|
JSR COUT
|
|
LDA #'>'
|
|
JSR COUT
|
|
AUXZP_ACCESS_ON
|
|
LDY #$00
|
|
LDA (HNDL),Y
|
|
INY
|
|
AND #$F8
|
|
TAX
|
|
LDA (HNDL),Y
|
|
STA $71
|
|
STX $70
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR PUTS
|
|
.ASCIIZ ": LEN:"
|
|
AUXZP_ACCESS_ON
|
|
LDY #$00
|
|
LDA ($70),Y
|
|
INY
|
|
TAX
|
|
LDA ($70),Y
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR PUTS
|
|
.ASCIIZ " REF:"
|
|
AUXZP_ACCESS_ON
|
|
LDY #$02
|
|
LDA ($70),Y
|
|
INY
|
|
TAX
|
|
LDA ($70),Y
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
; JSR KBWAIT
|
|
AUXZP_ACCESS_ON
|
|
; LDA HNDL
|
|
; LDX HNDL+1
|
|
; JSR HMEM_VALIDATE
|
|
; JSR HFREE_VALIDATE
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
.ENDIF
|
|
.IFDEF SWAPPING
|
|
JSR HMEM_PTR
|
|
LDY #$01
|
|
STY GCNEEDED
|
|
DEY ; FREE ALLOCED MEMORY BLOCK
|
|
AUXZP_ACCESS_ON
|
|
LDA (HNDL),Y
|
|
AND #$F8
|
|
STA (HNDL),Y ; CLEAR ALLOCED FLAGS
|
|
INY
|
|
.ELSE
|
|
LDY #$01
|
|
STY GCNEEDED
|
|
DEY
|
|
AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
LDA (HNDL),Y
|
|
AND #$F8
|
|
STA (HNDL),Y ; CLEAR ALLOCED FLAG
|
|
INY
|
|
STA MPTR
|
|
LDA (HNDL),Y
|
|
STA MPTR+1
|
|
.ENDIF
|
|
INY
|
|
.IFDEF DEBUG
|
|
LDA (MPTR),Y
|
|
BEQ :+
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ "FREE NON_ZERO REF COUNT. HANDLE/ADDRESS: $"
|
|
AUXZP_ACCESS_ON
|
|
LDA HNDL+1
|
|
LDX HNDL
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
LDA #$80|'/'
|
|
JSR COUT
|
|
LDA #$80|'$'
|
|
JSR COUT
|
|
AUXZP_ACCESS_ON
|
|
LDA MPTR+1
|
|
LDX MPTR
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
; JMP THROW_INTERNALERR
|
|
AUXZP_ACCESS_ON
|
|
:
|
|
.ENDIF
|
|
LDA HFREE ; ADD TO FREE LIST
|
|
STA (MPTR),Y
|
|
INY
|
|
LDA HFREE+1
|
|
STA (MPTR),Y
|
|
LDA HNDL
|
|
LDX HNDL+1
|
|
STA HFREE
|
|
STX HFREE+1
|
|
.IFDEF DEBUG_MEMMGR
|
|
STA HFREEBAK ; SAVE BACKUP
|
|
STX HFREEBAK+1
|
|
.ENDIF
|
|
;.IFDEF DEBUG
|
|
.IF 0
|
|
LDA MPTR ; ZERO OUT MEMORY BLOCK WHEN DEBUGGING
|
|
ORA #$04
|
|
STA DSTADDR
|
|
LDA MPTR+1
|
|
STA DSTADDR+1
|
|
LDY #$01 ; SUBTRACT HEADER SIZE FROM BLOCK SIZE
|
|
LDA (MPTR),Y
|
|
DEY
|
|
TAX
|
|
LDA (MPTR),Y
|
|
SEC
|
|
.IFDEF DEBUG_MEMMGR
|
|
SBC #$06
|
|
.ELSE
|
|
SBC #$04
|
|
.ENDIF
|
|
BCS :+
|
|
DEX
|
|
: JSR MEMCLR
|
|
.ENDIF
|
|
.IFDEF DEBUG_MEMMGR
|
|
JSR HFREE_VALIDATE
|
|
.ENDIF
|
|
.IFDEF DEBUG
|
|
LDY #$00 ; UPDATE AVAILABLE RAM
|
|
LDA (MPTR),Y
|
|
INY
|
|
CLC
|
|
ADC RAMAVAIL
|
|
STA RAMAVAIL
|
|
LDA (MPTR),Y
|
|
ADC RAMAVAIL+1
|
|
STA RAMAVAIL+1
|
|
JSR PRNTRAM
|
|
.ENDIF
|
|
AUXZP_ACCESS_OFF
|
|
CLC
|
|
RTS
|
|
;*******************************
|
|
;*
|
|
;* GARBAGE COLLECTION ROUTINES
|
|
;*
|
|
;*******************************
|
|
;*
|
|
;* GARBAGE COLLECT
|
|
;* ENTRY: AX = MAX ITERATIONS
|
|
;* Y = MIN SWAP SIZE
|
|
;* EXIT: CFLAG=1, NOTHING COLLECTED; CFLAG=0, GARBAGE COLLECTED
|
|
;*
|
|
GCCNT: .WORD $0000
|
|
HMEM_GC: ADC #$01
|
|
INX
|
|
STA GCCNT
|
|
STX GCCNT+1
|
|
.IFDEF DEBUG_GC
|
|
JSR PUTSLN
|
|
.ASCIIZ "STARTING GARBAGE COLLECTION:"
|
|
JSR HMEM_DUMP
|
|
JSR KBWAIT
|
|
.ENDIF
|
|
LDA GCNEEDED
|
|
BNE LOOPGC
|
|
INC GCNEEDED
|
|
LOOPGC: DEC GCCNT
|
|
BNE :+
|
|
DEC GCCNT+1
|
|
BEQ :++
|
|
:
|
|
.IFDEF SWAPPING
|
|
JSR HMEM_CLRACCESS
|
|
.ENDIF
|
|
JSR HMEM_GC_INCR
|
|
BCC LOOPGC
|
|
:
|
|
.IFDEF DEBUG_GC
|
|
JSR PUTSLN
|
|
.ASCIIZ "FINISHED GARBAGE COLLECTION:"
|
|
JSR HMEM_DUMP
|
|
JSR KBWAIT
|
|
.ENDIF
|
|
EXITGC: RTS
|
|
;*
|
|
;* GARBAGE COLLECTION CALLED FROM IDLE LOOP
|
|
;*
|
|
.IFDEF IDLE_GC
|
|
HMEM_GC_IDLE:
|
|
.ENDIF
|
|
;*
|
|
;* GARBAGE COLLECT
|
|
;* ENTRY:
|
|
;* EXIT: CFLAG=1, NOTHING COLLECTED; CFLAG=0, GARBAGE COLLECTED
|
|
;*
|
|
HMEM_GC_INCR: CHKAUXLC
|
|
SEC
|
|
LDA GCNEEDED
|
|
BEQ EXITGC
|
|
CMP #$02
|
|
BEQ :+
|
|
JSR HMEM_COALESCE ; ATTEMPT EASY FREE SPACE COMBINE
|
|
BCC EXITGC
|
|
INC GCNEEDED
|
|
: JSR HMEM_COMPACT ; ATTEMPT FREE SPACE COMPACTION
|
|
.IFDEF SWAPPING
|
|
;*
|
|
;* SWAP OUT MEMORY BLOCKS WHEN IDLE
|
|
;* START FROM BOTTOM AND MOVE TO TOP. THE THEORY BEING IT WILL SWAP OUT OLDER BLOCKS FIRST.
|
|
;*
|
|
LDA SWPGCHNDL
|
|
LDX SWPGCHNDL+1
|
|
CLC
|
|
ADC #$02
|
|
BCC :++
|
|
INX
|
|
CPX #>HTBL_END
|
|
BCC :+
|
|
LDA #<HTBL
|
|
LDX #>HTBL
|
|
: STX SWPGCHNDL+1
|
|
: STA SWPGCHNDL
|
|
CHKHNDL
|
|
AUXZP_ACCESS_ON
|
|
STA HNDL
|
|
STX HNDL+1
|
|
LDY #$00
|
|
LDA (HNDL),Y
|
|
AND #$03 ; SKIP FREE, FIXED OR SWAPPED BLOCKS
|
|
CMP #$01
|
|
CLC
|
|
BNE EXITSWPGC
|
|
.IFDEF DEBUG_MEMMGR
|
|
LDA HNDL
|
|
JSR HNDL_VALIDATE
|
|
LDX HNDL+1
|
|
LDY #$00
|
|
.ENDIF
|
|
LDA (HNDL),Y
|
|
INY
|
|
AND #$F8
|
|
STA MPTR
|
|
LDA (HNDL),Y
|
|
STA MPTR+1
|
|
LDY #$03
|
|
LDA (MPTR),Y
|
|
BMI EXITSWPGC ; LEAVE ACCESSED BLOCKS ALONE
|
|
LDA HNDL
|
|
AUXZP_ACCESS_OFF
|
|
DEC GCNEEDED
|
|
JMP HMEM_SWAPOUT ; SWAP OUT UNACCESSED BLOCK
|
|
SWPGCHNDL: .ADDR HTBL
|
|
EXITSWPGC: AUXZP_ACCESS_OFF
|
|
CLC
|
|
.ELSE
|
|
BCC EXITGC
|
|
LDA #$00 ; AND SWAPPING, SO DON'T DO IT WHEN SWAPPING ENABLED
|
|
STA GCNEEDED
|
|
.ENDIF
|
|
RTS
|
|
;*
|
|
;* COALESCE ADJACENT FREE BLOCKS
|
|
;* ENTRY:
|
|
;* EXIT: CFLAG=1, NOTHING COALESCED; CFLAG=0, FREE MEM COALESCED
|
|
;*
|
|
HMEM_COALESCE:
|
|
.IFDEF DEBUG_GC
|
|
PERR "HMEM_COALESCING..."
|
|
.ENDIF
|
|
AUXZP_ACCESS_ON
|
|
LDA HFREE ; SEARCH FREE LIST FOR BLOCKS TO COMBINE
|
|
STA GCHNDL
|
|
LDA HFREE+1
|
|
STA GCHNDL+1
|
|
BEQ NOTGCED
|
|
SEARCHCOALESCE: LDY #$01 ; DEREF HANDLE
|
|
LDA (GCHNDL),Y
|
|
DEY
|
|
STA GCMPTR+1
|
|
LDA (GCHNDL),Y
|
|
STA GCMPTR
|
|
CLC
|
|
ADC (GCMPTR),Y
|
|
INY
|
|
STA GCMEND
|
|
LDA GCMPTR+1
|
|
ADC (GCMPTR),Y
|
|
STA GCMEND+1
|
|
LDA HFREE
|
|
STA GCTMP
|
|
LDA HFREE+1
|
|
STA GCTMP+1
|
|
LOOPCOALESCE: LDY #$00 ; COMPARE THIS FREE BLOCK ADDRESS
|
|
AUXZP_ACCESS_ON
|
|
LDA (GCTMP),Y ; WITH END OF FREE BLOCK BEING CHECKED
|
|
INY
|
|
TAX
|
|
LDA (GCTMP),Y
|
|
CMP GCMEND+1
|
|
BNE NEXTCOAL
|
|
CPX GCMEND
|
|
BEQ MATCHCOALESCE ; A MATCH, COMBINE BLOCKS
|
|
NEXTCOAL: INY
|
|
STA GCTMP+1 ; GET POINTER TO FREE BLOCK
|
|
STX GCTMP
|
|
LDA (GCTMP),Y ; GET NEXT FREE BLOCK HANDLE
|
|
INY
|
|
TAX
|
|
LDA (GCTMP),Y
|
|
STX GCTMP
|
|
STA GCTMP+1
|
|
AUXZP_ACCESS_OFF
|
|
BNE LOOPCOALESCE ; KEEP CHECKING
|
|
AUXZP_ACCESS_ON
|
|
LDA (GCMPTR),Y ; NEXT FREE BLOCK TO COMPARE WITH
|
|
BEQ NOTGCED
|
|
STA GCHNDL+1
|
|
DEY
|
|
LDA (GCMPTR),Y
|
|
STA GCHNDL
|
|
JMP SEARCHCOALESCE
|
|
NOTGCED: AUXZP_ACCESS_OFF
|
|
SEC
|
|
RTS
|
|
MATCHCOALESCE:
|
|
;.IFDEF DEBUG_GC
|
|
.IF 0
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ "COMBINING "
|
|
AUXZP_ACCESS_ON
|
|
LDA GCHNDL+1
|
|
LDX GCHNDL
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR PUTS
|
|
.ASCIIZ " AND "
|
|
AUXZP_ACCESS_ON
|
|
LDA GCTMP+1
|
|
LDX GCTMP
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
AUXZP_ACCESS_ON
|
|
.ENDIF
|
|
LDA GCTMP ; UNLINK FREE BLOCK FROM LIST
|
|
LDX GCTMP+1
|
|
JSR HFREE_UNLINK
|
|
LDY #$00 ; RETURN UNREFERENCED HANDLE BACK TO UNUSED LIST
|
|
LDA (GCTMP),Y
|
|
PHA ; SAVE MEMORY POINTER FOR LATER
|
|
LDA HUNUSED
|
|
STA (GCTMP),Y
|
|
INY
|
|
LDA (GCTMP),Y
|
|
PHA
|
|
LDA HUNUSED+1
|
|
STA (GCTMP),Y
|
|
DEY
|
|
LDA GCTMP
|
|
STA HUNUSED
|
|
LDA GCTMP+1
|
|
STA HUNUSED+1
|
|
PLA ; RECOVER MEMORY POINTER
|
|
STA GCTMP+1
|
|
PLA
|
|
STA GCTMP
|
|
LDA (GCMPTR),Y ; ADD SIZE OF NEXT FREE BLOCK TO CURRENT
|
|
CLC
|
|
ADC (GCTMP),Y
|
|
STA (GCMPTR),Y
|
|
INY
|
|
STA GCMLEN
|
|
LDA (GCMPTR),Y
|
|
ADC (GCTMP),Y
|
|
STA (GCMPTR),Y
|
|
STA GCMLEN+1
|
|
.IFDEF DEBUG_MEMMGR
|
|
JSR HFREE_VALIDATE
|
|
.ENDIF
|
|
AUXZP_ACCESS_OFF
|
|
CLC
|
|
RTS
|
|
;*
|
|
;* COMPACT MEMORY BY MOVING ALLOCED BLOCKS TO TOP OF HEAP
|
|
;* ENTRY:
|
|
;* EXIT: CFLAG=1, NOTHING COMPACTED; CFLAG=0, MEM COMPACTED
|
|
;*
|
|
COMPGCHNDL: .WORD $0000
|
|
RECOMPACT: LDA HFREE
|
|
LDX HFREE+1 ; CHECK FOR ANY FREE BLOCKS
|
|
STA COMPGCHNDL
|
|
STX COMPGCHNDL+1
|
|
BEQ NOTGCED ; C = 1
|
|
HMEM_COMPACT:
|
|
.IFDEF DEBUG_GC
|
|
AUXZP_ACCESS_OFF
|
|
PERR "HMEM_COMPACTING..."
|
|
.ENDIF
|
|
LDA COMPGCHNDL
|
|
LDX COMPGCHNDL+1
|
|
AUXZP_ACCESS_ON
|
|
BEQ RECOMPACT
|
|
CHKHNDL
|
|
STA GCHNDL
|
|
STX GCHNDL+1
|
|
LDY #$00 ; DEREF HANDLE
|
|
LDA (GCHNDL),Y
|
|
LSR
|
|
BCS RECOMPACT
|
|
ASL
|
|
INY
|
|
STA GCMPTR ; GCMPTR = ADDRESS OF FREE BLOCK
|
|
LDA (GCHNDL),Y
|
|
STA GCMPTR+1
|
|
LDA #<HTBL
|
|
LDX #>HTBL
|
|
STA GCTMP
|
|
STX GCTMP+1
|
|
LOOPCOMPACT: LDY #$00
|
|
LDA (GCTMP),Y
|
|
TAX
|
|
AND #$03
|
|
CMP #$01 ; CHECK IF FREE, LOCKED OR SWAPPED
|
|
BNE NEXTCOMP ; SKIP IF NOT AVAIL
|
|
TXA
|
|
AND #$F8 ; MASK OFF FLAGS
|
|
TAX
|
|
INY
|
|
LDA (GCTMP),Y ; COMPARE FOR LOWER ADDRESS THAN FREE BLOCK
|
|
CMP GCMPTR+1
|
|
BNE :+
|
|
CPX GCMPTR
|
|
: BCS NEXTCOMP
|
|
STA GCMEND+1 ; CALC END ADDRESS OF BLOCK
|
|
STX GCMEND ; IF IT MATCHES START OF FREE BLOCK
|
|
DEY ; THEN IT CAN BE SHIFTED UP
|
|
TXA
|
|
CLC
|
|
ADC (GCMEND),Y
|
|
INY
|
|
TAX
|
|
LDA GCMEND+1
|
|
ADC (GCMEND),Y
|
|
CMP GCMPTR+1
|
|
BNE :+
|
|
CPX GCMPTR
|
|
BNE :+
|
|
LDA GCTMP ; SAVE NEAREST NEIGHBOR
|
|
STA GCNEIGHBOR
|
|
LDA GCTMP+1
|
|
; STA GCNEIGHBOR+1
|
|
; BNE NEXTCOMP
|
|
BNE SHIFTNEIGHBOR ; MOVE NEXT-DOOR NEIGHBOR UP
|
|
: LDA (GCMPTR),Y ; ELSE COMPARE SIZE OF BLOCK TO FREE BLOCK
|
|
CMP (GCMEND),Y ; IT MUST BE EQUAL TO SIZE
|
|
BNE NEXTCOMP ; OF FREE BLOCK
|
|
DEY
|
|
LDA (GCMPTR),Y
|
|
CMP (GCMEND),Y
|
|
BNE NEXTCOMP
|
|
LDA GCTMP
|
|
STA GCBEST
|
|
LDA GCTMP+1
|
|
STA GCBEST+1
|
|
BNE XCHNGBEST
|
|
;CHECKBESTCOMP: LDA GCBEST+1 ; ONLY REPLACE BEST MATCH IF AT A HIGER ADDRESS
|
|
; BEQ :+ ; ASSUMING HIGHER ADDRESSES ARE OLDER AND
|
|
; INY ; WILL BE FREED LAST
|
|
; LDA GCMEND+1
|
|
; CMP (GCBEST),Y
|
|
; BCC NEXTCOMP ; CURRENT BEST IS HIGHER
|
|
; BNE :+
|
|
; DEY
|
|
; LDA GCMEND
|
|
; CMP (GCBEST),Y
|
|
; BCC NEXTCOMP ; CURRENT BEST IS HIGER
|
|
;: LDA GCTMP
|
|
; STA GCBEST
|
|
; LDA GCTMP+1
|
|
; STA GCBEST+1
|
|
NEXTCOMP: LDA GCTMP ; MOVE TO NEXT HANDLE IN TABLE
|
|
AUXZP_ACCESS_OFF
|
|
CLC
|
|
ADC #$02
|
|
AUXZP_ACCESS_ON
|
|
STA GCTMP
|
|
BCC LOOPCOMPACT
|
|
INC GCTMP+1
|
|
LDX GCTMP+1
|
|
CPX #>HTBL_END
|
|
BCC LOOPCOMPACT
|
|
EXITCOMPACT: AUXZP_ACCESS_OFF
|
|
LDY #$02
|
|
LDA (GCMPTR),Y
|
|
INY
|
|
STA COMPGCHNDL
|
|
LDA (GCMPTR),Y
|
|
STA COMPGCHNDL+1
|
|
SEC
|
|
RTS
|
|
SHIFTNEIGHBOR: STA GCBEST+1
|
|
LDA GCNEIGHBOR
|
|
STA GCBEST
|
|
.IF 0
|
|
AUXZP_ACCESS_OFF
|
|
LDA #$80|'<'
|
|
JSR COUT
|
|
AUXZP_ACCESS_ON
|
|
.ENDIF
|
|
.IFDEF DEBUG_GC
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ "SHIFT NGHBR "
|
|
AUXZP_ACCESS_ON
|
|
LDA GCNEIGHBOR+1
|
|
LDX GCNEIGHBOR
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR PUTS
|
|
.ASCIIZ " OVR "
|
|
AUXZP_ACCESS_ON
|
|
LDA GCHNDL+1
|
|
LDX GCHNDL
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
AUXZP_ACCESS_ON
|
|
.ENDIF
|
|
.IFDEF DEBUG_MEMMGR
|
|
LDA GCNEIGHBOR
|
|
LDX GCNEIGHBOR+1
|
|
JSR HMEM_VALIDATE
|
|
LDY #$01
|
|
.ENDIF
|
|
LDY #$00 ; SET COPY POINTERS
|
|
LDA (GCBEST),Y
|
|
AND #$F8
|
|
STA SRCADDR
|
|
CLC ; ADD SIZE OF FREE BLOCK
|
|
ADC (GCMPTR),Y ; FOR DESTINATION
|
|
STA DSTADDR
|
|
INY
|
|
LDA (GCBEST),Y
|
|
STA SRCADDR+1
|
|
ADC (GCMPTR),Y
|
|
STA DSTADDR+1
|
|
BNE MOVEBLOCKS
|
|
XCHNGBEST:
|
|
.IFDEF DEBUG_GC
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTS
|
|
.ASCIIZ "EXCHANGING BEST "
|
|
AUXZP_ACCESS_ON
|
|
LDA GCBEST+1
|
|
LDX GCBEST
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR PUTS
|
|
.ASCIIZ " WITH "
|
|
AUXZP_ACCESS_ON
|
|
LDA GCHNDL+1
|
|
LDX GCHNDL
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
AUXZP_ACCESS_ON
|
|
.ENDIF
|
|
.IFDEF DEBUG_MEMMGR
|
|
LDA GCBEST
|
|
LDX GCBEST+1
|
|
JSR HMEM_VALIDATE
|
|
.ENDIF
|
|
.IF 0
|
|
AUXZP_ACCESS_OFF
|
|
LDA #$80|'^'
|
|
JSR COUT
|
|
AUXZP_ACCESS_ON
|
|
.ENDIF
|
|
LDY #$00 ; SET COPY POINTERS
|
|
LDA (GCBEST),Y
|
|
AND #$F8
|
|
STA SRCADDR
|
|
LDA GCMPTR
|
|
STA DSTADDR
|
|
INY
|
|
LDA (GCBEST),Y
|
|
STA SRCADDR+1
|
|
LDA GCMPTR+1
|
|
STA DSTADDR+1
|
|
MOVEBLOCKS: LDY #$00 ; SAVE FREE BLOCK INFO
|
|
: LDA (GCMPTR),Y
|
|
PHA
|
|
INY
|
|
CPY #$04
|
|
BNE :-
|
|
LDY #$00 ; UPDATE ALLOC BLOCK POINTER
|
|
LDA (GCBEST),Y
|
|
AND #$07 ; COPY ALLOC FLAGS
|
|
ORA DSTADDR
|
|
STA (GCBEST),Y
|
|
LDA SRCADDR
|
|
STA (GCHNDL),Y ; UPDATE FREE BLOCK POINTER
|
|
STA GCMPTR
|
|
INY
|
|
LDA DSTADDR+1
|
|
STA (GCBEST),Y
|
|
LDA SRCADDR+1
|
|
STA (GCHNDL),Y
|
|
STA GCMPTR+1
|
|
LDA (SRCADDR),Y ; SIZE OF ALLOCED BLOCK TO MOVE
|
|
DEY
|
|
TAX
|
|
LDA (SRCADDR),Y
|
|
JSR MEMCPY ; MOVE ALLOCED BLOCK UP
|
|
LDY #$03 ; RESTORE FREE BLOCK INFO
|
|
: PLA
|
|
STA (GCMPTR),Y
|
|
DEY
|
|
BPL :-
|
|
.IFDEF DEBUG_MEMMGR
|
|
LDA GCBEST
|
|
LDX GCBEST+1
|
|
JSR HMEM_VALIDATE
|
|
JSR HFREE_VALIDATE
|
|
.ENDIF
|
|
AUXZP_ACCESS_OFF
|
|
CLC
|
|
RTS
|
|
.IFDEF DEBUG
|
|
;*
|
|
;* PRINT AVAIL RAM TO SCREEN
|
|
;*
|
|
PRNTRAM: LDA RAMAVAIL+1
|
|
LSR
|
|
LSR
|
|
LSR
|
|
LSR
|
|
CLC
|
|
ADC #'0'
|
|
CMP #'9'+1
|
|
BCC :+
|
|
ADC #'A'-'9'-2
|
|
: ORA #$80
|
|
STA $0424
|
|
LDA RAMAVAIL+1
|
|
AND #$0F
|
|
CLC
|
|
ADC #'0'
|
|
CMP #'9'+1
|
|
BCC :+
|
|
ADC #'A'-'9'-2
|
|
: ORA #$80
|
|
STA $0425
|
|
LDA RAMAVAIL
|
|
LSR
|
|
LSR
|
|
LSR
|
|
LSR
|
|
CLC
|
|
ADC #'0'
|
|
CMP #'9'+1
|
|
BCC :+
|
|
ADC #'A'-'9'-2
|
|
: ORA #$80
|
|
STA $0426
|
|
LDA RAMAVAIL
|
|
AND #$0F
|
|
CLC
|
|
ADC #'0'
|
|
CMP #'9'+1
|
|
BCC :+
|
|
ADC #'A'-'9'-2
|
|
: ORA #$80
|
|
STA $0427
|
|
RTS
|
|
.ENDIF
|
|
;*
|
|
;* VALIDATE HANDLE/POINTER
|
|
;*
|
|
.IFDEF DEBUG_MEMMGR
|
|
HNDL_SAVE: .WORD $0000
|
|
HMEM_VALIDATE: PHA
|
|
TXA
|
|
PHA
|
|
TYA
|
|
PHA
|
|
LDA HNDL
|
|
STA HNDL_SAVE
|
|
LDA HNDL+1
|
|
STA HNDL_SAVE+1
|
|
LDX #>HTBL
|
|
LDA #<HTBL
|
|
HTBLVLP: STA HNDL
|
|
STX HNDL+1
|
|
LDY #$00
|
|
LDA (HNDL), Y
|
|
AND #$01
|
|
BEQ :+
|
|
LDA HNDL
|
|
JSR HNDL_VALIDATE
|
|
: LDA HNDL
|
|
LDX HNDL+1
|
|
CLC
|
|
ADC #$02
|
|
BCC :+
|
|
INX
|
|
: CPX #>HTBL_END
|
|
BCC HTBLVLP
|
|
LDA HNDL_SAVE
|
|
STA HNDL
|
|
LDA HNDL_SAVE+1
|
|
STA HNDL+1
|
|
PLA
|
|
TAY
|
|
PLA
|
|
TAX
|
|
PLA
|
|
RTS
|
|
HNDL_VALIDATE:
|
|
STA $70
|
|
STX $71
|
|
CPX #>HTBL
|
|
BCC BADHNDL
|
|
CPX #>HTBL_END
|
|
BCS BADHNDL
|
|
LSR
|
|
BCS BADHNDL
|
|
LDY #$01
|
|
LDA ($70),Y
|
|
DEY
|
|
TAX
|
|
LDA ($70),Y
|
|
TAY
|
|
AND #$07
|
|
CMP #$07
|
|
BNE :+
|
|
RTS ; HANDLE SWAPPED OUT
|
|
: TYA
|
|
AND #$F8
|
|
CPX #>INIT_START
|
|
BCC BADHNDL
|
|
BNE :+
|
|
CMP #<INIT_START
|
|
BCC BADHNDL
|
|
: CPX #>TOPOFHEAP
|
|
BCS BADHNDL
|
|
TYA
|
|
LSR
|
|
BCC BADHNDL
|
|
TYA
|
|
AND #$F8
|
|
STA $72
|
|
STX $73
|
|
LDY #$01 ; CHECK FENCE
|
|
LDA ($72),Y
|
|
DEY
|
|
TAX
|
|
LDA ($72),Y
|
|
AND #$07 ; MAKE SURE NO BITS IN 3 LSBS
|
|
BNE BADSIZE
|
|
LDA ($72),Y
|
|
SEC
|
|
SBC #$02
|
|
BCS :+
|
|
DEX
|
|
: CLC
|
|
ADC $72
|
|
STA $72
|
|
TXA
|
|
ADC $73
|
|
STA $73
|
|
LDA #$CA
|
|
CMP ($72),Y
|
|
BNE BADFENCE
|
|
INY
|
|
LDA #$FE
|
|
CMP ($72),Y
|
|
BNE BADFENCE
|
|
RTS
|
|
BADHNDL: AUXZP_ACCESS_OFF
|
|
PERR "INVALID MEMORY HANDLE/POINTER:"
|
|
JMP PRNTBADHNDL
|
|
BADFENCE: AUXZP_ACCESS_OFF
|
|
PERR "CORRUPTED FENCE:"
|
|
JMP PRNTBADHNDL
|
|
BADSIZE: AUXZP_ACCESS_OFF
|
|
PERR "INVALID SIZE:"
|
|
PRNTBADHNDL: LDA $71
|
|
LDX $70
|
|
JSR PRNTAX
|
|
LDA #'/'
|
|
JSR COUT
|
|
AUXZP_ACCESS_ON
|
|
LDY #$00
|
|
LDA ($70),Y
|
|
INY
|
|
TAX
|
|
LDA ($70),Y
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
JSR CHKDBLALLOC
|
|
JSR KBWAIT
|
|
JSR HMEM_DUMP
|
|
LDA BADHNDLBRK ; STOP RECURSIVE BAD HANDLES
|
|
BEQ :+
|
|
DEC BADHNDLBRK
|
|
JMP THROW_INTERNALERR
|
|
: BRK
|
|
CHKDBLALLOC: LDX #>HTBL ; CHECK FOR DOUBLY LINKED BLOCKS
|
|
LDA #<HTBL
|
|
AUXZP_ACCESS_ON
|
|
CHKDBLALCLP: STA $74
|
|
STX $75
|
|
LDY #$00
|
|
LDA ($74), Y
|
|
LSR
|
|
BCC CHKDBLALCNXT ; SKIP FREE BLOCKS
|
|
AND #$03
|
|
CMP #$03 ;SKIP SWAPPED OUT BLOCKS
|
|
BEQ CHKDBLALCNXT
|
|
LDA ($74), Y ; CHECK FOR SAME BLOCK ADDRESS
|
|
AND #$F8
|
|
CMP $72
|
|
BNE CHKDBLALCNXT
|
|
INY
|
|
LDA ($74), Y
|
|
CMP $73
|
|
BNE CHKDBLALCNXT
|
|
LDA $70 ; POINTER MATCH, MAKE SURE NOT SAME HANDLE
|
|
CMP $74
|
|
BEQ :+
|
|
JMP DBLALCERR
|
|
: LDA $71
|
|
CMP $75
|
|
BEQ CHKDBLALCNXT
|
|
JMP DBLALCERR
|
|
CHKDBLALCNXT: LDA $74
|
|
LDX $75
|
|
CLC
|
|
ADC #$02
|
|
BCC :+
|
|
INX
|
|
: CPX #>HTBL_END
|
|
BCC CHKDBLALCLP
|
|
RTS
|
|
DBLALCERR: LDA $71
|
|
LDX $70
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
PERR " DOUBLEY ALLOCATED WITH "
|
|
AUXZP_ACCESS_ON
|
|
LDA $75
|
|
LDX $74
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
JMP PRNTBADHNDL
|
|
BADHNDLBRK: .BYTE $01
|
|
HFREEBAK: .WORD $0000
|
|
HFREE_VALIDATE: LDA HFREE
|
|
CMP HFREEBAK
|
|
BNE BADFREE
|
|
STA $70
|
|
LDX HFREE+1
|
|
CPX HFREEBAK+1
|
|
BNE BADFREE
|
|
STX $71
|
|
VALFREE: CPX #$00
|
|
BEQ VALFREEDONE
|
|
CPX #>HTBL ; MAKE SURE HANDLE IS IN THE TABLE RANGE
|
|
BCC BADFREE
|
|
CPX #>HTBL_END
|
|
BCS BADFREE
|
|
AND #$01 ; CHECK ALLOCATED BIT (LSB)
|
|
BNE BADFREE
|
|
LDY #$01
|
|
LDA ($70),Y
|
|
DEY
|
|
TAX
|
|
LDA ($70),Y
|
|
AND #$F8
|
|
CPX #>INIT_START ; CHECK MEMORY POINTER IS IN VALID RANGE
|
|
BCC BADFREE
|
|
BNE :+
|
|
CMP #<INIT_START
|
|
BCS :+
|
|
JMP BADFREE
|
|
: CPX #>HTBL
|
|
BCC :+
|
|
BEQ :+
|
|
JMP BADFREE
|
|
CMP #<HTBL
|
|
BCC :+
|
|
JMP BADFREE
|
|
: LDY #$01 ; DEREF NEXT HANDLE IN LIST
|
|
LDA ($70),Y
|
|
DEY
|
|
TAX
|
|
LDA ($70),Y
|
|
STA $72
|
|
STX $73
|
|
LDY #$03
|
|
LDA ($72),Y
|
|
DEY
|
|
TAX
|
|
LDA ($72),Y
|
|
STA $70
|
|
STX $71
|
|
JMP VALFREE
|
|
VALFREEDONE: RTS
|
|
BADFREE: AUXZP_ACCESS_OFF
|
|
PERR "CORRUPTED FREE LIST @:"
|
|
AUXZP_ACCESS_ON
|
|
LDA $71
|
|
LDX $70
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
JSR HMEM_DUMP
|
|
AUXZP_ACCESS_OFF
|
|
JMP THROW_INTERNALERR
|
|
;*
|
|
;* PRINT OUT MEMORY MANAGER DETAILS
|
|
;*
|
|
.EXPORT HMEM_DUMP
|
|
HMEM_DUMP: AUXZP_ACCESS_OFF
|
|
JSR CROUT
|
|
JSR PUTSLN
|
|
.ASCIIZ "MEMORY MANAGER STATE"
|
|
JSR PUTSLN
|
|
.ASCIIZ "===================="
|
|
JSR KBWAIT
|
|
JSR PUTSLN
|
|
.ASCIIZ "FREE LIST"
|
|
JSR PUTSLN
|
|
.ASCIIZ "---------"
|
|
AUXZP_ACCESS_ON
|
|
LDA HFREE
|
|
STA HNDL
|
|
LDA HFREE+1
|
|
STA HNDL+1
|
|
FREE_DUMP: LDX HNDL
|
|
LDA HNDL+1
|
|
BNE :+
|
|
JMP FREE_DONE
|
|
: AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR PUTS
|
|
.ASCIIZ "->"
|
|
AUXZP_ACCESS_ON
|
|
LDY #$00
|
|
LDA (HNDL),Y
|
|
INY
|
|
STA MPTR
|
|
TAX
|
|
LDA (HNDL),Y
|
|
STA MPTR+1
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR PUTS
|
|
.ASCIIZ ": LEN:"
|
|
AUXZP_ACCESS_ON
|
|
LDY #$00
|
|
LDA (MPTR),Y
|
|
INY
|
|
TAX
|
|
LDA (MPTR),Y
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR PUTS
|
|
.ASCIIZ " NEXT:"
|
|
AUXZP_ACCESS_ON
|
|
LDY #$02
|
|
LDA (MPTR),Y
|
|
INY
|
|
TAX
|
|
STA HNDL
|
|
LDA (MPTR),Y
|
|
STA HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
AUXZP_ACCESS_ON
|
|
JMP FREE_DUMP
|
|
FREE_DONE: LDA #<HTBL
|
|
STA HNDL
|
|
LDA #>HTBL
|
|
STA HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
JSR PUTSLN
|
|
.ASCIIZ "ALLOCATED BLOCKS"
|
|
JSR PUTSLN
|
|
.ASCIIZ "----------------"
|
|
AUXZP_ACCESS_ON
|
|
LDA #$00
|
|
STA MLEN ; ZERO TOTAL ALLOCATED
|
|
STA MLEN+1
|
|
ALLOC_DUMP: LDY #$00 ; MAKE UNUSED HANDLE LIST
|
|
LDA (HNDL),Y
|
|
AND #$01
|
|
BNE :+
|
|
JMP NEXT_ADUMP ; NOT ALLOCATED
|
|
: LDX HNDL
|
|
LDA HNDL+1
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR PUTS
|
|
.ASCIIZ "->"
|
|
AUXZP_ACCESS_ON
|
|
LDY #$00
|
|
LDA (HNDL),Y
|
|
AND #$07
|
|
CMP #$07
|
|
BNE :+
|
|
JSR PUTSLN
|
|
.ASCIIZ "SWAPPED OUT"
|
|
JMP NEXT_ADUMP
|
|
: LDA (HNDL),Y
|
|
INY
|
|
TAX
|
|
AND #$F8
|
|
STA MPTR
|
|
LDA (HNDL),Y
|
|
STA MPTR+1
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR PUTS
|
|
.ASCIIZ ": LEN:"
|
|
AUXZP_ACCESS_ON
|
|
LDY #$00
|
|
LDA (MPTR),Y
|
|
INY
|
|
TAX
|
|
CLC ; ADD TO TOTAL
|
|
ADC MLEN
|
|
STA MLEN
|
|
LDA (MPTR),Y
|
|
ADC MLEN+1
|
|
STA MLEN+1
|
|
LDA (MPTR),Y
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR PUTS
|
|
.ASCIIZ " REF:"
|
|
AUXZP_ACCESS_ON
|
|
LDY #$02
|
|
LDA (MPTR),Y
|
|
INY
|
|
TAX
|
|
LDA (MPTR),Y
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
NEXT_ADUMP: AUXZP_ACCESS_ON
|
|
LDA HNDL
|
|
CLC
|
|
ADC #$02
|
|
STA HNDL
|
|
BEQ :+
|
|
JMP ALLOC_DUMP
|
|
: INC HNDL+1
|
|
LDA HNDL+1
|
|
CMP #>HTBL_END
|
|
BEQ :+
|
|
JMP ALLOC_DUMP
|
|
: AUXZP_ACCESS_OFF
|
|
JSR CROUT
|
|
JSR PUTS
|
|
.ASCIIZ "TOTAL ALLOCATED:$"
|
|
AUXZP_ACCESS_ON
|
|
LDA MLEN+1
|
|
LDX MLEN
|
|
AUXZP_ACCESS_OFF
|
|
JSR PRNTAX
|
|
JSR CROUT
|
|
RTS
|
|
.ENDIF |