; Memory managment for NXDOS - 2006 Chris Evans
; Portions based on work from DIGITAL RESEARCH and CALDERA


FIRST_FIT_LOW EQU 0000h      ; Search Conventional memory for available
                             ; block having the lowest address, default.
BEST_FIT_LOW  EQU 0001h      ; Search conventional RAM for a available
                             ; block that most closly matches the
                             ; requested size.
LAST_FIT_LOW  EQU 0002h      ; Search Conventional RAM from highest
                             ; address fr available block. (Top-Down)
BEST_FIT      equ     01h             ; allocate BEST match memory block
LAST_FIT      equ     02h             ; allocate LAST matching memory block
FIRST_FIT     equ     04h             ; we use this internally...
; DOS 5.0+ ------------------------------------------------------------------
FIRST_FIT_HIGH      EQU 0080h      ; Ditto, but with CONV+UMBs address space
BEST_FIT_HIGH       EQU 0081h      ; Ditto, but with CONV+UMBs address space
LAST_FIT_HIGH       EQU 0082h      ; Ditto, but with CONV+UMBs address space
FIRST_FIT_HIGHONLY  EQU 0040h      ; Ditto, but with CONV+UMBs address space
BEST_FIT_HIGHONLY   EQU 0041h      ; Ditto, but with UMBs address space
LAST_FIT_HIGHONLY   EQU 0042h      ; Ditto, but with UMBs address space
; ---------------------------------------------------------------------------
UPPER_FIT	equ	80h		; preferably allocate from upper memory
UPPER_ONLY_FIT	equ	40h		; only allocate from upper memory

allocate_minimum EQU 16
DEFAULTMEMSTART EQU 0090h

;        extrn   error_exit:near         ; Standard Error Handler
;        extrn   return_AX_CLC:near
;        extrn   return_BX:near
;        extrn   reload_ES:near
;        extrn   toupper:near

; ===========================================================================
MINIT  proc far
; BX = Allocation strategy (see above)
; dx = NZ = user specified segment
; ===========================================================================
       mov  ax, word ptr firstaddr
       cmp  ax, 0
       jne  MINIT_NOSETUP
       mov  ax, dx
       cmp  ax, 0
       je   MINIT_NOUSERSEG
       mov  word ptr firstaddr, ax
       jmp  short MINIT_2
MINIT_NOUSERSEG:
       mov  ax, DEFAULTMEMSTART
MINIT_2:
       mov  word ptr firstaddr, ax
       int  12h
       mov  memorypool, ax
MINIT_NOSETUP:
       mov  MEMSTRATEGY, bx
       ret
MINIT  endp

MFREE  proc far
; AX = memory block to free

       ret
MFREE  endp


MALLOC proc far
;         CX = SIZE
; Output: ES:SI = Pointer to block
;         AX    = Memory Block ID NZ if okay
       ; if size <= allocate_minimum size = allocate_minimum


       ret
MALLOC endp

MADDR  proc far
;         AX = mem block ID or AX = FF then find first free that matches <=size
;         if AX = FF then BX = size 
; Output: ES:BX = Address of mem block
;         CX    = Size
;         AX    = Memory Block ID
       push ds
       push si
       ;
       push cs
       pop  ds
       lea  si, HEAPSTRUCT
       cmp  ax, 0ffh
       jne  MADDR_getentry
       xor  ax, ax
MADDR_SEARCH:
       mov  bp, ax
      ; mov  cx, word ptr ds:[si+bp*6+2]
       cmp  bx, cx
       jle  MADDR_FOUNDMATCH
       ; No, continue searching!
       inc  ax
       cmp  ax, 128
       jle  MADDR_SEARCH
MADDR_FOUNDMATCH:
      ; mov  dx, word ptr ds:[si+bp*6]
      ; mov  bx, word ptr ds:[si+bp*6+2]
      ; mov  cx, word ptr ds:[si+bp*6+4]
       push dx
       pop  es
       ; AX = Memory block ID 
       jmp  MADDR_X
MADDR_getentry:
       mov  bp, ax
      ; mov  dx, word ptr ds:[si+bp*6]
      ; mov  bx, word ptr ds:[si+bp*6+2]
      ; mov  cx, word ptr ds:[si+bp*6+4]
       push dx
       pop  es
       ;
MADDR_X:
       pop  si
       pop  ds
       ret
MADDR  endp

HEAPCOUNT  db 0
HEAPSTRUCT db 128 dup(6 dup(0))

;SEG  dw 0
;OFS  dw 0
;SIZE dw 0
;nextfree = ofs + size+1

; ===========================================================================
MEMCOPY proc far
; DS:DI <- Source
; ES:SI -> Destination
;    CX Size
; ===========================================================================
memcopy_loop:
        mov  al, byte ptr ds:[di]
        mov  byte ptr es:[si], al
        inc  di
        inc  si
        loop memcopy_loop
        ret
MEMCOPY endp

; Heap managers work by request a large block of memory from the operating
; system. They create a free list of pointers to storage blocks. When an
; allocation request is received, the heap manager marks an appropriately
; sized block of memory as reserved and returns a pointer to the block. Later,
; when a delete request for the same block is received, the heap frees up the
; block, returning it to the free list. Whenever a new allocation request is
; received, the heap manager scans the free list, looking for the first
; available block large enough to grant the request.

;        extrn   lock_tables:dword
;        extrn   unlock_tables:dword

dmd_address    dw 0        ; don't free DMD's with segment under this value
dmd_owner      dw 0        ; don't free DMD's with owner under this value
dmd_upper_root dw 0
dmd_upper_link dw 0
current_psp    dw 0
dmd_root       dw 0

locus           db 0
DMD_ID          db      ?               ; id code ('M' or 'Z')
DMD_PSP         dw      ?               ; owner of memory block
DMD_LEN         dw      ?               ; length of memory block
DMD_IDLE_FLAGS  dw      ?               ; idle flags live here
DMD_NAME_LEN	equ	8		;  8 Bytes long
DMD_NAME        db DMD_NAME_LEN dup(0)  ; ASCIIZ name field
mem_strategy db FIRST_FIT_LOW
MEMSTRATEGY  dw FIRST_FIT_LOW
firstaddr    dd ?
memorypool   dw 0000h  ; In KB! set to whatever is received from int 12h 
umb_root     dw 0
umb_link     dw 0
ma_handles   dw 0
