; _______________________________________________________________________________________
;|                                                                                       |
;| ..::FreshLib::..  Free, open source. Licensed under "Fresh artistic license."         |
;|_______________________________________________________________________________________|
;
;  Description: Dynamic memory management library. Win32 part.
;
;  Target OS: Win32
;
;  Dependencies:
;
;  Notes: Uses Heap functions of Win32 API. Also contains some debug and profiling code,
;         that needs some revision in order to be either removed, or legalized.
;_________________________________________________________________________________________

uglobal
  if used _hHeap
    _hHeap  dd  ?
  end if
endg



if DebugMemory

    struct TMemoryItem
      .pointer dd ?
      .callfrom dd ?
    ends

    uglobal
      ptrMemoryStack dd ?
      flagNoDebug    dd ?
    endg


    proc InitAllocStack
    begin
            mov     [flagNoDebug], 1
            stdcall CreateArray, sizeof.TMemoryItem
            mov     [ptrMemoryStack], eax
            mov     [flagNoDebug], 0
            return
    endp

end if




initialize InitMemoryManager
begin
        invoke  GetProcessHeap
        mov     [_hHeap], eax

if DebugMemory
        call    InitAllocStack
end if
        return
endp



finalize FinalizeMemoryManager
begin
if DebugMemory
        mov     eax, [ptrMemoryStack]

        int3
        xor     eax, eax
        xchg    eax, [ptrMemoryStack]
        stdcall FreeMem, eax
end if
        return
endp



; Allocates memory block with given size.
; Returns: CF=1 if error.
;          if CF=0, eax = pointer to the memory block allocated.
align 16

proc GetMem, .size
begin
        push    ecx edx

        invoke  HeapAlloc, [_hHeap], HEAP_ZERO_MEMORY, [.size]
        test    eax, eax
        jz      .error

if DebugMemory
            cmp     [flagNoDebug], 0
            jne     .exit

            pushad
            push    [flagNoDebug]
            mov     [flagNoDebug], 1

            mov     ecx, eax
            stdcall AddArrayItem, [ptrMemoryStack]
            mov     [ptrMemoryStack], edx
            jnc     @f

            int3
@@:
            mov     [eax+TMemoryItem.pointer], ecx
            mov     ecx, [esp+12*4]
            cmp     ecx, CreateArray.retaddr
            jne     @f
            mov     ecx, [esp+12*4+5*4]
@@:
            mov     [eax+TMemoryItem.callfrom], ecx

            pop     [flagNoDebug]
            popad

    .exit:
end if
        clc
        pop     edx ecx
        return

.error:
        stc
        pop     edx ecx
        return
endp


align 16

proc FreeMem, .ptr
begin
        push    eax ecx edx

if DebugMemory
            cmp     [flagNoDebug], 0
            jne     .exit

            pushad

            mov     esi, [ptrMemoryStack]
            mov     ebx, [esi+TArray.count]
            mov     eax, [.ptr]

            xor     ebx, ebx

    .loop:
            cmp     ebx, [esi+TArray.count]
            jae     .notfound

            cmp     [esi+TArray.array+8*ebx], eax
            je      .found

            inc     ebx
            jmp     .loop

    .notfound:
            int3
            jmp     .exit2

    .found:
            push    [flagNoDebug]
            mov     [flagNoDebug], 1

            stdcall DeleteArrayItem, esi, ebx
            jnc     @f

            int3
@@:
            mov     [ptrMemoryStack], edx

            pop     [flagNoDebug]

    .exit2:
            popad
    .exit:
end if

        invoke  HeapFree, [_hHeap], 0 , [.ptr]
        pop     edx ecx eax
        return
endp




proc ResizeMem, .ptr, .newsize
begin
        push    ecx edx
        invoke  HeapReAlloc, [_hHeap], HEAP_ZERO_MEMORY, [.ptr], [.newsize]
        test    eax, eax
        jz      .error

if DebugMemory
            cmp     [flagNoDebug], 0
            jne     .exit

            pushad

            mov     esi, [ptrMemoryStack]
            mov     ebx, [esi+TArray.count]
            mov     ecx, [.ptr]

            xor     ebx, ebx

    .loop:
            cmp     ebx, [esi+TArray.count]
            jae     .notfound

            cmp     [esi+TArray.array+8*ebx], ecx
            je      .found

            inc     ebx
            jmp     .loop

    .notfound:
            int3
            jmp     .exit2

    .found:
            mov     [esi+TArray.array+8*ebx], eax
            mov     ecx, [esp+11*4]
            cmp     ecx, AddArrayItem.retaddr
            jne     @f
            mov     ecx, [esp+12*4+5*4]
@@:
            mov     [esi+TArray.array+8*ebx+4], ecx

    .exit2:
            popad
    .exit:
end if

        clc
        pop     edx ecx
        return

.error:
        mov     eax, [.ptr]
        stc
        pop     edx ecx
        return
endp



;
;proc GetMemSize, .ptr
;begin
;        push    ecx edx
;        invoke  HeapSize, [_hHeap], 0, [.ptr]
;        cmp     eax, -1
;        je      .error
;        clc
;        pop     edx ecx
;        return
;
;.error:
;        stc
;        pop     edx ecx
;        return
;endp







