NEW
  AUTO 3,1
*--------------------------------------
ZPMemMgrSPtr 	.EQ ZPMEMMGR			Pointer To Slot selected
ZPMemMgrTmp1	.EQ ZPMEMMGR+2
ZPMemMgrSize	.EQ ZPMEMMGR+4
MEM.ReqFlags	.EQ ZPMEMMGR+6			store requested Flags
MEM.BestSlot	.EQ ZPMEMMGR+7
MEM.BestScore	.EQ ZPMemMgrTmp1
*/--------------------------------------
* # Realloc
* ## C
* `void *realloc(short int hMem, int size);`
* ## ASM
* `>PUSHB hMem`
* `>PUSHW size`
* `>SYSCALL realloc`
* ## RETURN VALUE
*  YA = ptr
*  X = hMem
*\--------------------------------------
K.Realloc		>PULLA
				sta .1+1				New Size LO

				>PULLA
				sta .2+1				New Size HI

				>PULLA					Src hMem
				tax
				
				jsr MEM.GetMemByID
				
				ldy #S.MEM.LEN
				lda (ZPMemMgrSPtr),y
				pha
				iny
				lda (ZPMemMgrSPtr),y
				ply

				jsr MEM.MoveToAux		x = Src hMem, YA = Old size
				bcs .99
				
				stx .7+1				Aux hMem
				
.1				ldy #$FF				SELF MODIFIED
.2				lda #$FF				SELF MODIFIED

				>STYA A2L				size for MoveSetupA1A2
				
				jsr K.getmem
				bcs .99
				
				stx .8+1				new main hMem to return
				>STYA A4L				Save MAIN Ptr

				lda .7+1
				sta IO.SETREADAUX
				jsr MEM.SetA1A2			Setup AUX base & End Ptrs
				sta IO.CLRREADAUX
				
				clc						Aux To Main
				jsr XMov
				
.7				lda #$ff				SELF MODIFIED
				>SYSCALL2 FreeStkObj
				
.8				lda #$ff				SELF MODIFIED
				tax						X = new hMem
				jmp k.GetMemPtr			YA = new ptr
				
.99				rts
*/--------------------------------------
* # GetMem
*  Y,A = Size Requested
* ## RETURN VALUE
*  CC : success
*   YA = PTR to Mem (Uninitialised)
*	X = hMem
*  CS :
*   A = EC
*\--------------------------------------
K.GetMem0		ldx #S.MEM.F.INIT0
				.HS 2C					BIT ABS
K.GetMem		ldx #0
MEM.GetMem.YAX	stx MEM.ReqFlags
				sta ZPMemMgrSize+1

				tya
				bit #K.MEM.ALIGN-1		aligned ?
				beq .10					yes, request it	

				and #K.MEM.nALIGNm1		align on boundary
				clc
				adc #K.MEM.ALIGN
				bcc .10

				inc ZPMemMgrSize+1

.10				sta ZPMemMgrSize
				>LDYAI Mem.Table
				>STYA ZPMemMgrSPtr
				stz MEM.BestSlot
				ldx #$ff
				stx MEM.BestScore
				stx MEM.BestScore+1
				ldx #0					Current slot=0
				bra .4					skip slot 0, Check if some free slot to reuse first

.1				inx						move to next slot
				jsr Mem.NextSlot
				lda (ZPMemMgrSPtr)		Get Flags
				bmi .4					in use ?

.2				lda MEM.ReqFlags		Found an empty slot
				bit #S.MEM.F.NOCROSS
				beq .21

				ldy ZPMemMgrSize+1		> 255, not applicable
				bne .22					Align to page if $100
				
				ldy #S.MEM.PTR
				lda (ZPMemMgrSPtr),y	get LO of PTR
				clc
				adc ZPMemMgrSize
				bcs .4					cross page boundary....
				
				lda MEM.ReqFlags		get back flags to test if match
				
.21				bit #S.MEM.F.ALIGN		is request needs a page align ?
				beq .3

.22				ldy #S.MEM.PTR
				lda (ZPMemMgrSPtr),y	get LO of PTR
				bne .4					not page-aligned

.3				ldy #S.MEM.LEN
				sec
				lda (ZPMemMgrSPtr),y	get LEN of this block
				sbc ZPMemMgrSize		compare with requested size
				pha
				iny
				lda (ZPMemMgrSPtr),y
				sbc ZPMemMgrSize+1
				ply						Y,A = SlotLen - ReqSize
				bcc .4					req size > slot size

				cpy MEM.BestScore
				pha
				sbc MEM.BestScore+1
				pla
				bcs	.4					Delta is >= BestScore	
				bne .4					Delta is > 255...

				sty MEM.BestScore
				sta MEM.BestScore+1
				stx MEM.BestSlot
.4				cpx Mem.LastSlot		any other slot to check?
				bne .1					last one, create a new slot

				lda MEM.BestSlot
				beq .5
				tax
				jsr MEM.GetMemByID
				bra .7
*-------------- Create a New SLOT

.5				lda MEM.ReqFlags
				bit #S.MEM.F.NOCROSS
				beq .51

				lda ZPMemMgrSize+1		> 255, not applicable
				bne .52					Align to page if $100

				lda Mem.Free			target PTR will be in same page ?
				beq .6					Memfree is xx00, will be in same page
				cmp ZPMemMgrSize
				bcs .6					yes, allocate

				tay						no, reserve a free slot to fill gap
				lda #0
				jsr Mem.AddSlot			X = new slot
				bcs .9

				lda #S.MEM.F.NOCROSS	Make sure marked FREE
				sta (ZPMemMgrSPtr)
				bra .6
				
.51				bit #S.MEM.F.ALIGN		is request needs a page align ?
				beq .6

.52				lda Mem.Free			target PTR will be page aligned ?
				sec
				sbc ZPMemMgrSize
				beq .6					yes, allocate

				tay						no, reserve a free slot to fill gap
				lda #0
				jsr Mem.AddSlot			X = new slot
				bcs .9

				lda #S.MEM.F.ALIGN		Make sure marked FREE
				sta (ZPMemMgrSPtr)

.6				>LDYA ZPMemMgrSize
				jsr Mem.AddSlot			X = new slot
				bcs .9
*-------------- Reuse this SLOT

.7				lda MEM.ReqFlags		get requested flags
				ora #S.MEM.F.INUSE		mark as in use
				sta (ZPMemMgrSPtr)
				and #S.MEM.F.INIT0
				beq .8

				jsr MEM.Init0
				
.8				lda #0
				ldy #S.MEM.BIN
				sta (ZPMemMgrSPtr),y
				inc						Mark this slot used by one process
				ldy #S.MEM.REFCNT
				sta (ZPMemMgrSPtr),y

				lda IO.RDREADAUX
				pha
				
				sta IO.CLRREADAUX

				ldy #S.PS.PID
				lda (pPS),y
				
				ldy #S.MEM.OWNERPID
				sta (ZPMemMgrSPtr),y
				
				pla
				bpl .80
				
				sta IO.SETREADAUX

.80				clc

				jmp MEM.GetMEMPTR
* A = HI PTR,Y = LO PTR,X = Current hMem
.9				rts
*--------------------------------------
* Mem.AddSlot
*  In:
*   Y,A = Requested size
*  Out: 
*--------------------------------------
Mem.AddSlot  	>STYA ZPMemMgrTmp1		save req size
				ldx Mem.LastSlot
				inx
				beq .99					> 255 ERR:OUT OF SLOT

				lda Mem.Free			Compute base PTR=FREE-REQ size
				sec
				sbc ZPMemMgrTmp1
				tay						save new Mem.Free LO
				lda Mem.Free+1
				sbc ZPMemMgrTmp1+1
				pha						save new Mem.Free HI
				cpy Mem.LoMem
				sbc Mem.LoMem+1
				bcc .98					ERR out of mem

				jsr Mem.NextSlot		X,Y unmodified
				tya						get back Mem.Free LO
				ldy #S.MEM.PTR
				sta Mem.Free			set as system Mem.Free value
				sta (ZPMemMgrSPtr),y	store it as base address of new slot
				iny
				pla						get back Mem.Free HI
				sta Mem.Free+1
				sta (ZPMemMgrSPtr),y

				iny
				lda ZPMemMgrTmp1		get requested size
				sta (ZPMemMgrSPtr),y	setup slot LEN
				iny	
				lda ZPMemMgrTmp1+1
				sta (ZPMemMgrSPtr),y

				stx Mem.LastSlot		mark this slot allocated
				clc
				rts
.98				pla						discard new Mem.Free HI

.99				lda #E.OOM
				sec
				rts	
*--------------------------------------
MEM.NextSlot	lda ZPMemMgrSPtr
				clc
				adc #S.MEM
				sta ZPMemMgrSPtr
				bcc .8

				inc ZPMemMgrSPtr+1

.8				rts
*--------------------------------------
MEM.Init0		phx
				ldy #S.MEM.PTR
				lda (ZPMemMgrSPtr),y	ZPMemMgrSPtr already set
				sta .12+1
				iny
				lda (ZPMemMgrSPtr),y
				sta .12+2
				lda ZPMemMgrSize
				eor #$ff
				tay						y=not lo count
				lda ZPMemMgrSize+1
				eor #$ff				a=not hi count			

				ldx #0

.11				iny
				bne .12

				inc
				beq .13

.12				stz $ffff,x
				inx
				bne .11

				inc .12+2
				bra .11

.13				plx
				rts
*--------------------------------------
DEV.FreeFD.8	clc
				rts
				
DEV.FreeFD		ldx IO.hFD
				lda FDs.pHI-1,x
				cmp #$C0
				bcs DEV.FreeFD.8

				stz FDs.pHI-1,x	

				ldy FDs.pLO-1,x
*/--------------------------------------
* # Free
*  Y,A = Ptr To Free
* ## RETURN VALUE
*  none.
*  (X unmodified)
*\--------------------------------------
K.Free			>STYA ZPMemMgrTmp1
				
				ldx Mem.LastSlot

.1				txa
				jsr MEM.GetMemByID
				
				ldy #S.MEM.PTR
				lda (ZPMemMgrSPtr),y
				cmp ZPMemMgrTmp1
				bne .2
				
				iny
				lda (ZPMemMgrSPtr),y
				cmp ZPMemMgrTmp1+1
				beq MEM.FreeMem

.2				dex
				bne .1
				
				sec
				rts
*/--------------------------------------
* # FreeMem
*  A = hMem To Free
* ## RETURN VALUE
*  none.
*  (X unmodified)
*\--------------------------------------
K.FreeMem.ERR	>PUSHWI .1
				
				tya						hMem n Y
				>PUSHA
	
				ldy #S.PS.PID
				lda (pPS),y
				>PUSHA
				>PUSHBI 2
				
				>SYSCALL2 PrintF
*			>DEBUG
				lda #E.INVH
				sec
				rts

.1				.CZ "Free(%h),PID=%d\r\n"
*--------------------------------------
K.FreeMem	    tay
				beq K.FreeMem.ERR		Slot=0, reserved by Kernel

				cmp Mem.LastSlot
				bcc .1
				
				bne K.FreeMem.ERR

.1				jsr MEM.GetMemByID		X,Y unmodified
*--------------------------------------
MEM.FreeMem		lda (ZPMemMgrSPtr)		In use ?
				bpl K.FreeMem.ERR
				
				ldy #S.MEM.REFCNT
				lda (ZPMemMgrSPtr),y
				dec						only one left ?	
				sta (ZPMemMgrSPtr),y
				bne .8					no, must be a code segment loaded several times

				lda (ZPMemMgrSPtr)
				and #$7f				keep flags for memdump
				sta (ZPMemMgrSPtr)		Mark as FREE
				and #S.MEM.F.CODE		CS: Any BINPATH to discard ?
				beq .1

				ldy #S.MEM.BIN
				lda (ZPMemMgrSPtr),y
				jsr MEM.GetMemByID		X unmodified
*				lda (ZPMemMgrSPtr)
*				bpl *					***MUST BE ALLOCATED***
				lda #0					mark BINPATH slot as free
				sta (ZPMemMgrSPtr)
				
.1				lda Mem.LastSlot
				beq .8

				jsr MEM.GetMemByID		X unmodified
				lda (ZPMemMgrSPtr)
				bmi .8					used, exit

.2				dec	Mem.LastSlot		free! get previous....
				beq .80					empty list: go set Mem.Free=Mem.HiMem

				lda Mem.LastSlot
				jsr MEM.GetMemByID		X unmodified
				lda (ZPMemMgrSPtr)
				bpl .2					free again! loop

				ldy #S.MEM.PTR
				lda (ZPMemMgrSPtr),y	set Mem.Free... 
				sta Mem.Free
				iny
				lda (ZPMemMgrSPtr),y
				sta Mem.Free+1

.8				clc
				rts

.80				>LDYA Mem.HiMem
				>STYA Mem.Free
				clc
				rts
*/--------------------------------------
* # GetMemPtr
* A = hMem
* ## RETURN VALUE
* Y,A = PTR to MemBlock
* (X unmodified)
*\--------------------------------------
* Optimized for :
* Mem.Table is page aligned at $800
* S.MEM is 8 bytes
*--------------------------------------
				.DO Mem.Table=$800
				.ELSE
				!!!!!WARNING!!!!!
				.FIN
				.DO S.MEM=8
				.ELSE
				!!!!!WARNING!!!!!
				.FIN
*--------------------------------------
K.GetMemPtr		jsr MEM.GetMemByID
MEM.GetMEMPTR	ldy #S.MEM.PTR
				lda (ZPMemMgrSPtr),y
				pha
				iny
				lda (ZPMemMgrSPtr),y
				ply
				rts
*--------------------------------------
MEM.GetMemByID	sta ZPMemMgrSPtr
				lda /Mem.Table/8
				asl ZPMemMgrSPtr
				rol
				asl ZPMemMgrSPtr
				rol
				asl ZPMemMgrSPtr
				rol
				sta ZPMemMgrSPtr+1
				rts
*--------------------------------------
Mem.SetOwner	lda CORE.LastPSID
				.HS 2C					BIT ABS
Mem.SetOwnerPS0	lda #0	
				ldy #S.MEM.OWNERPID
				sta (ZPMemMgrSPtr),y
				rts
*--------------------------------------
Mem.IncRefCnt	ldy #S.MEM.REFCNT
				lda (ZPMemMgrSPtr),y
				inc
				sta (ZPMemMgrSPtr),y
				rts
*/--------------------------------------
* # NewStkObj
*  Y,A = Size Requested
* ## RETURN VALUE
*  CC : success
*   YA = PTR to Mem (Uninitialised)
*	X = hMem
*  CS :
*   A = EC
*\--------------------------------------
*/--------------------------------------
* # GetStkObjPtr
* ## ASM
* `lda hStkObj`
* `>SYSCALL GetStkObjPtr`
* ## RETURN VALUE
*\--------------------------------------
*/--------------------------------------
* # FreeStkObj
*  A = hMem To Free (AUX Memory)
* ## RETURN VALUE
*  none.
*  (X,Y unmodified)
*\--------------------------------------
*--------------------------------------
MEM.DupX		sta IO.SETREADAUX
				sta IO.SETWRITEAUX
				jsr MEM.Dup
				sta IO.CLRREADAUX
				sta IO.CLRWRITEAUX
				rts
*--------------------------------------
MEM.Dup			jsr K.GetMemPtr
				>STYA A1L
				
				ldy #S.MEM.LEN
				lda (ZPMemMgrSPtr),y
				pha
				eor #$ff
				sta A4L
				iny
				lda (ZPMemMgrSPtr),y
				eor #$ff
				sta A4L+1
				eor #$ff
				ply

MEM.DupA1LnA4L	jsr K.GetMem
				bcs MEM.Dup.RTS
				
				>STYA A2L
				
				ldy #0
				
.1				inc A4L
				bne .2
				inc A4L+1
				beq .8
	
.2				lda (A1L),y
				sta (A2L),y
				iny
				bne .1
				
				inc A1L+1
				inc A2L+1
				bra .1
				
.8				txa
*				clc
MEM.Dup.RTS		rts				
*--------------------------------------
MEM.CopyToMain	clc
				.HS B0					BCS
MEM.MoveToMain	sec
				ror .1+1
				stx .2+1				Save AUX hMem
				>STYA A2L				Save LEN to copy/move

				sta IO.CLRREADAUX			Make sure MAIN !!!!
				sta IO.CLRWRITEAUX
				jsr K.GetMem
				bcs MEM.Dup.RTS

				stx .8+1				Save MAIN hMem
				>STYA A4L				Save MAIN Ptr

				lda .2+1				Get AUX mem Ptr
				sta IO.SETREADAUX
				jsr MEM.SetA1A2			Setup AUX base & End Ptrs
				sta IO.CLRREADAUX

				clc						Aux To Main
				jsr XMov

.1				lda #$ff				SELF MODIFIED
				bpl .8					Copy : dont discard AUX mem

.2				lda #$ff				SELF MODIFIED
				>SYSCALL2 FreeStkObj	release AUX mem

.8				ldx #$ff				Returns MAIN hMem
				txa
				jmp K.GetMemPtr			Y,A = Ptr
*--------------------------------------
MEM.MoveToAux	stx .1+1				Save MAIN hMem
				>STYA A2L				Save LEN to move

				>SYSCALL2 NewStkObj
				bcs .9

				stx .8+1				Save AUX hMem
				>STYA A4L				Save AUX Ptr

				lda .1+1
				jsr MEM.SetA1A2			Setup MAIN base & End Ptrs

				sec						Main To Aux
				jsr XMov

.1				lda #$ff				SELF MODIFIED
				jsr K.FreeMem			release MAIN memory

.8				ldx #$ff				Returns AUX hMem
*				clc

.9				rts
*--------------------------------------
MEM.SetA1A2		jsr K.GetMemPtr

				>STYA A1L				Start Address
				pha
				tya
				clc
				adc A2L
				tay

				pla
				adc A2L+1
				sta A2L+1

				tya
				bne .1
				
				dec A2L+1
				
.1				dey
				sty A2L
				
				rts
*--------------------------------------
MEM.GetKBuf		pha
				tya
				clc
				adc DevMgr.Free
				tax
				pla
				adc DevMgr.Free+1
				bcs .99					we crossed $FFFF, out of mem

				cpx #DevMgr.HiMem
				pha
				sbc /DevMgr.HiMem
				pla
				bcs .99					No More Room...

				ldy DevMgr.Free
				stx DevMgr.Free
				ldx DevMgr.Free+1
				sta DevMgr.Free+1
				txa
*				clc
				rts

.99				lda #E.OOM
*				sec
				rts
*--------------------------------------
MAN
SAVE usr/src/sys/kernel.s.mem
LOAD usr/src/sys/kernel.s
ASM
