NEW
PREFIX
AUTO 4,1
*--------------------------------------
ZPMemMgrSPtr 	.EQ ZPMEMMGR			Pointer To Slot selected
ZPMemMgrTmp1	.EQ ZPMEMMGR+2
ZPMemMgrSize	.EQ ZPMEMMGR+4
*/--------------------------------------
* # GetMem0
*  Y,A = Size Requested
* ## RETURN VALUE
*  CC : success
*   YA = PTR to Mem (ZERO Initialised)
*	X = hMem
*  CS :
*   A = EC
*\--------------------------------------
MEM.ReqFlags	.BS 1					store requested Flags
MEM.BestSlot	.BS 1
*MEM.BestScore	.BS 2
MEM.BestScore	.EQ ZPMemMgrTmp1
*--------------------------------------
K.GetMem0		ldx #S.MEM.F.INIT0
				.HS 2C					bit abs
*/--------------------------------------
* # GetMem
*  Y,A = Size Requested
* ## RETURN VALUE
*  CC : success
*   YA = PTR to Mem (Uninitialised)
*	X = hMem
*  CS :
*   A = EC
*\--------------------------------------
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
				and #S.MEM.F.ALIGN		is request needs a page align ?
				beq .3
				
				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
				and #S.MEM.F.ALIGN		is request needs a page align ?
				beq .6
				
				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

				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			
				
				phx
				
				ldx #0
				
.11				iny
				bne .12
				inc
				beq .13
				
.12				stz $ffff,x
				inx
				bne .11
				
				inc .12+2
				bra .11
				
.13				plx

.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
				
				ldy #S.PS.PID
				lda (pPs),y
				ldy #S.MEM.OWNERPID
				sta (ZPMemMgrSPtr),y
				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								
*/--------------------------------------
* # FreeMem
*  A = hMem To Free
* ## RETURN VALUE
*  none.
*  (X unmodified)
*\--------------------------------------
K.FreeMem.MSG	.AZ "FreeMem:hMem=$%h,PID=%d\r\n"
*--------------------------------------
K.FreeMem.ERR	phx
				
				phy						hMem n Y
				ldy #S.PS.PID
				lda (pPS),y
				>PUSHA
				
				pla
				>PUSHA
				
				>PUSHBI 2
				>LDYAI K.FreeMem.MSG
				
.1				ldx #SYS.printf
				jsr K.SYSCALL2.BANK
				plx

				sec
				rts
*--------------------------------------
K.FreeMem	    tay
				beq K.FreeMem.ERR		Slot=0, reserved by Kernel
				
				cmp Mem.LastSlot
				bcc .10
				bne K.FreeMem.ERR
				
.10				jsr MEM.GetMemByID		X,Y unmodified
				lda (ZPMemMgrSPtr)		In use ?
				bpl K.FreeMem.ERR

				ldy #S.MEM.REFCNT
				lda (ZPMemMgrSPtr),y
				dec
				sta (ZPMemMgrSPtr),y	only one left ?	
				bne .8					no, must be a code segment loaded several times
				
				lda (ZPMemMgrSPtr)
				and #S.MEM.F.CODE		CS: Any BINPATH to discard ?
				sta (ZPMemMgrSPtr)		Mark as FREE
				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
*--------------------------------------
ZPSListKeyID	.EQ ZPMEMMGR+6
ZPSListDataPtr 	.EQ ZPMEMMGR+8
ZPSListDataLen 	.EQ ZPMEMMGR+10
ZPSListIBlkPtr	.EQ ZPMEMMGR+12
ZPSListDBlkPtr 	.EQ ZPMEMMGR+14			
*/--------------------------------------
* # SListGetData
* ## ASM
* `PUSHW DataOfs`
* `PUSHW DataLen`
* `PUSHW DataPtr`
* `PUSHW KeyID`
* `lda hSList`
* `>SYSCALL SListGetData`
* ## RETURN VALUE
*  Y,A = Byte Count
*  X = hMem (if DataPtr = 0)
*\--------------------------------------
K.SListGetData	pha
				>PULLW ZPSListKeyID
				>PULLW ZPSListDataPtr
				>PULLW ZPSListDataLen
				>PULLW ZPMemMgrSize
				pla
				bra K.SListFree
				pla
*/--------------------------------------
* # SListAddData
* ## ASM
* `PUSHW DataLen`
* `PUSHW DataPtr`
* `PUSHW KeyID`
* `lda hSList`
* `>SYSCALL SListAddData`
* ## RETURN VALUE
*\--------------------------------------
K.SListAddData	
*/--------------------------------------
* # SListSetData
* ## ASM
* `PUSHW DataLen`
* `PUSHW DataPtr`
* `PUSHW KeyID`
* `lda hSList`
* `>SYSCALL SListSetData`
* ## RETURN VALUE
*\--------------------------------------
K.SListSetData	pha
				>PULLW ZPSListKeyID
				>PULLW ZPSListDataPtr
				>PULLW ZPSListDataLen
				pla
				bra K.SListFree
*/--------------------------------------
* # SListGetByID
* ## ASM
* `PUSHW KeyPtr`
* `PUSHW KeyID`
* `lda hSList`
* `>SYSCALL SListGetByID`
* ## RETURN VALUE
*  Y,A = Next KeyID
*\--------------------------------------
K.SListGetByID	pha
				>PULLW ZPSListKeyID
				>PULLW ZPSListDataPtr
				pla
				bra K.SListFree
*/--------------------------------------
* # SListNewKey
* ## ASM
* `PUSHW KeyPtr`
* `lda hSList`
* `>SYSCALL SListNewKey`
* ## RETURN VALUE
*  Y,A = KeyID
*  X = KeyLen
*\--------------------------------------
K.SListNewKey
*/--------------------------------------
* # SListLookup
* ## ASM
* `PUSHW KeyPtr`
* `lda hSList`
* `>SYSCALL SListLookup`
* ## RETURN VALUE
*  Y,A = KeyID
*  X = Key Length
*\--------------------------------------
K.SListLookup	pha
				>PULLW ZPSListDataPtr
				pla
*/--------------------------------------
* # SListNew
* ## ASM
* `>SYSCALL SListNew`
* ## RETURN VALUE
* A=hSList
*\--------------------------------------
K.SListNew
*/--------------------------------------
* # SListFree
* ## ASM
* `lda hSList`
* `>SYSCALL SListFree`
* ## RETURN VALUE
*\--------------------------------------
K.SListFree		sta SETREADAUX
				sta SETWRITEAUX
				
				jsr	X.SLIST
				
				sta CLRREADAUX
				sta CLRWRITEAUX
				rts
*/--------------------------------------
* # NewStkObj
*  Y,A = Size Requested
* ## RETURN VALUE
*  CC : success
*   YA = PTR to Mem (Uninitialised)
*	X = hMem
*  CS :
*   A = EC
*\--------------------------------------
K.NewStkObj		ldx #SYS.GetMem
				.HS 2C					BIT ABS
*/--------------------------------------
* # FreeStkObj
*  A = hMem To Free (AUX Memory)
* ## RETURN VALUE
*  none.
*  (X,Y unmodified)
*\--------------------------------------
K.FreeStkObj	ldx #SYS.FreeMem

				sta SETREADAUX
				sta SETWRITEAUX
				
				jsr	K.SYSCALL.JMP
				
				sta CLRREADAUX
				sta CLRWRITEAUX
				rts
*/--------------------------------------
* # LoadStkObj
* Load a file in AUX memory (Stock Objects)
*  PUSHW = AUXTYPE (Handled by....
*  PUSHB = TYPE  ...
*  PUSHB = MODE  ...
*  LDYA = PATH ...FOpen)
* ## RETURN VALUE
*  Y,A = File Length
*  X = hMem of Loaded Object in AUX mem
*\--------------------------------------
K.LoadStkObj	ldx #SYS.LoadTxtFile	To get ending \0
				jsr K.SYSCALL2.BANK
				bcs .99
				
				sty .81+1
				sta .82+1
				
				stx .8+1				Save MAIN hMem
				iny
				bne .1
				inc						+1 for ending 0
.1				>STYA A2L				Save LEN temporarly
				
				jsr K.NewStkObj
				bcs .9
				stx .80+1
				>STYA A4L				Save Destination Address in AUX
				
				lda .8+1
				jsr K.GetMemPtr
				
				>STYA A1L				Save MAIN base Ptr
				
				pha						Add Allocated LEN
				tya
				clc
				adc A2L
				sta A2L
				pla
				adc A2L+1
				sta A2L+1				to get End address in A2L/H

				sec						Main To Aux
				jsr AuxMove
							
.8				lda #$ff				SELF MODIFIED
				jsr K.FreeMem			release MAIN memory
				
.80				ldx #$ff				Returns AUX hMem
.81				ldy #$ff				and file len in Y,A
.82				lda #$ff
*				clc
				rts
				
.9				pha
				jsr .8
				pla
				sec
.99				rts				
*/--------------------------------------
* # GetStkObjData
* ## ASM
* `PUSHW DataLen`
* `PUSHW DataPtr`
* `lda hStkObj`
* `>SYSCALL GetStkObjData`
* ## RETURN VALUE
*\--------------------------------------
K.GetStkObjData	sta SETREADAUX
				jsr K.GetMemPtr
				>STYA ZPMemMgrTmp1
				
				>PULLW ZPSListDataLen
				>PULLW ZPSListDataPtr
				
				lda (ZPMemMgrTmp1),y
				pha
				iny
				lda (ZPMemMgrTmp1),y
				ply
				
				sta CLRREADAUX
				rts
*--------------------------------------
* in Y,A = buf size
*--------------------------------------
MEM.GetMainBuf	sta CLRREADAUX
				sta CLRWRITEAUX
				jsr	K.GetMem
				sta SETREADAUX
				sta SETWRITEAUX
				rts
*--------------------------------------
MEM.GetKrnlBuf	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
				bcs .98					No More Room...
				
				ldy DevMgr.Free
				stx DevMgr.Free
				ldx DevMgr.Free+1
				pla
				sta DevMgr.Free+1
				txa
				
*				clc
				rts

.98				pla
.99				lda #E.OOM
*				sec
				rts				
*--------------------------------------
MEM.GetKeyCharY	sta CLRREADAUX
				lda (ZPSListDataPtr),y
				sta SETREADAUX
				beq MEM.IsDigit.9
				
MEM.IsIDValid	cmp #'.'
				beq MEM.IsDigit.8

				cmp #'_'
				beq MEM.IsDigit.8
				
MEM.IsDigitOrL	cmp #'z'+1
				bcs MEM.IsDigit.RTS
				cmp #'a'
				bcs MEM.IsDigit.8
				
MEM.IsDigitOrUC	cmp #'Z'+1
				bcs MEM.IsDigit.RTS
				cmp #'A'
				bcs MEM.IsDigit.8

MEM.IsDigit		cmp #'9'+1
				bcs MEM.IsDigit.RTS
				cmp #'0'
				bcs MEM.IsDigit.8

MEM.IsDigit.9	sec
				
MEM.IsDigit.RTS	rts
				
MEM.IsDigit.8	clc
				rts
*--------------------------------------
MEM.IsHexDigit	jsr MEM.IsDigit
				bcc .8
				
				cmp #'A'
				bcc MEM.IsDigit.9
				cmp #'F'+1
				bcc .1
				
				cmp #'a'
				bcc MEM.IsDigit.9
				cmp #'f'+1
				bcs MEM.IsDigit.RTS

				eor #$20			
.1					
*				clc
				sbc #'A'-11			cc so A->10 (11-CC)
				clc
				
.8				and #$0F					
				rts
*--------------------------------------
MEM.SetKeyCharY	sta CLRWRITEAUX
				sta (ZPSListDataPtr),y
				sta SETWRITEAUX
				rts
*--------------------------------------
MEM.GetDataByte	sta CLRREADAUX
				lda (ZPSListDataPtr)
				sta SETREADAUX
				bra MEM.SetDataByte.1
*--------------------------------------
MEM.SetDataByte	sta CLRWRITEAUX
				sta (ZPSListDataPtr)
				sta SETWRITEAUX
MEM.SetDataByte.1				
				inc ZPSListDataPtr
				bne .8
				inc ZPSListDataPtr+1
.8				rts
*--------------------------------------
MEM.TXTPTR.GetY	sta CLRREADAUX
				lda (TXTPTR),y
				sta SETREADAUX
				rts
*--------------------------------------
MEM.TXTPTR.GetNext
				sta CLRREADAUX
				lda (TXTPTR)
				sta SETREADAUX
				beq .9
				inc TXTPTR
				bne .9
				inc TXTPTR+1
.9				rts				
*--------------------------------------
MEM.SPtr1PPtr2	>STYA ZPPtr1
				>PULLW ZPPtr2
				rts
*--------------------------------------
MEM.SPtr2PPtr1	>STYA ZPPtr2
				>PULLW ZPPtr1
				rts
*--------------------------------------
MEM.GetCharPtr1	lda (ZPPtr1)
				beq MEM.GetCharPtr1.8
MEM.NextCharPtr1				
				inc ZPPtr1
				bne MEM.GetCharPtr1.8
				inc ZPPtr1+1			never Z
MEM.GetCharPtr1.8
				rts
*--------------------------------------
MEM.AddYp1ToPtr1
				sec	
				.HS 90					BCC
MEM.AddYToPtr1	clc
				tya
				adc ZPPtr1
				sta ZPPtr1
				bcc .8
				inc ZPPtr1+1
.8				rts
*--------------------------------------
MEM.PutCharPtr2	sta (ZPPtr2)
MEM.NextCharPtr2
				inc ZPPtr2
				bne .8
				inc ZPPtr2+1
.8				rts
*--------------------------------------
DevMgr.Stat		.DA DevMgr.FreeMem
DevMgr.Free		.DA DevMgr.FreeMem
				.DA DevMgr.HiMem
DevMgr.DevIdx	.DA #1
*--------------------------------------
MAN
SAVE USR/SRC/SYS/KERNEL.S.MEM
LOAD USR/SRC/SYS/KERNEL.S
ASM
