;MM_ = MemoryManager
;â®â ¬®¤ã«ì ¯®§¢®«ï¥â ¢ë¤¥«ïâì ¯ ¬ïâì ¬ «¥­ìª¨¬¨ ªãá®çª ¬¨, ®¯â¨¬ «ì­® ¨á¯®«ì§ãï
;áâà ­¨æë ¯ ¬ïâ¨
;«®ª¨ - íâ® ®¤­  ¨«¨ ­¥áª®«ìª® áâà ­¨æ, ª®â®àë¥ ¨¬¥îâ § ¯¨áì
;¢ MM_BlockInfo ¨ ª®â®àë¥ ¢ ª®­æ¥ ¨¬¥îâ á⥪®®¡à §­ãî áâàãªâãàã(¢ á¬ëá«¥
;à áâñâ ª ¬¥­ì訬  ¤à¥á ¬), § ª ­ç¨¢ î饩áï dword 0. ‚ ­ ç «¥ ¡«®ª 
;­ å®¤ïâáï ¤ ­­ë¥. ‚ áâàãªâãॠ­ å®¤ïâáï ¯ àë dword'®¢: ­ ç «®
;ãç á⪮¢, ¨å ª®­¥æ(¯®á«. ¡ ©â+1). â¨ ¯ àë ¢á¥£¤  á®àâ¨àãîâáï ¯®
;à á¯®«®¦¥­¨î ®¯¨á뢠¥¬ëå
;ãç á⪮¢ ¢ ®¡à â­®¬ ¯®à浪¥, â.¥. ¢ á ¬®¬ ª®­æ¥ ¡«®ª  ¡ã¤¥â ¯ à  ¤ ­­ëå
;­  á ¬ë© ¯¥à¢ë© ãç á⮪. „«ï ¢ë¤¥«¥­¨ï ¯ ¬ï⨠­ã¦­® ­ ©â¨ ¡«®ª, ¢ ª®â®à®¬
;¤®áâ â®ç­® ¬¥áâ  (¯à¨çñ¬ ­¥®¡å®¤¨¬®¥ ¬¥áâ® = § ¯à è¨¢ ¥¬ë© ®¡êñ¬ + ¬¥áâ®
;¯®¤ ¯ àã á ¤ ­­ë¬¨ ¢ ª®­æ¥ ¡«®ª ) ¨ ¢áâ ¢¨âì ¯ àã á ­ã¦­ë¬¨ ¤ ­­ë¬¨.
;„«ï 㤠«¥­¨ï ãç á⪠ ­ã¦­® ⮫쪮 ã¡à âì ¨§ ¯ à ¯ àã á ­ã¦­ë¬ ãç á⪮¬
;¨ ¯®¯à ¢¨âì à á¯®«®¦¥­¨¥ ®áâ «ì­ëå ¯ à.
;begData1.....endData1,begData2...endData2,.......0,beg2,end2,beg1,end1


;¢ë¤¥«ï¥â ¯ ¬ïâì
;return eax = 㪠§ â¥«ì ­  ¢ë¤¥«¥­ë© ¡«®ª
;proc MM_AllocMem stdcall,Size:DWORD

;€ƒ ¢ ¢ë¤¥«¥­¨¨ ªà㯭ëå ªã᪮¢: ¢á¥£¤  ¢ë¤¥«ï¥â ­®¢ãî áâà ­¨æã



align 4
MM_AllocMem:
	Size equ ebp+8
	begFree equ ebp-8 ;­ ç «®
	endFree equ ebp-4 ;¨ ª®­¥æ ᢮¡®¤­®£® ¬¥áâ  ®â ª®­æ  ¨­äë ¤®
	endArea equ ebp-12
	push	ebp
	mov	ebp,esp
	add	esp,-4*3
	push	ebx edi esi
;dps 'MEM: '
;dph [Size]
;dps ' '
				;­ ç «  ¯ à § ¯¨á¥©
	mov	edx,[MM_NBlocks]
	cmp	edx,0
	jne	.BegTestBlocks	       ;¥á«¨ ¡«®ª®¢ ­¥â, â® ¤®¡ ¢¨âì ­®¢ë©
	mov	ecx,[Size]
	call	AddBlock
	jmp	.return
align 4
 .BegTestBlocks:


	xor	ebx,ebx
	mov	ecx,edx
align 4
  .TestBlock:	 ;¯à®¢¥àª  ¡«®ª 
		   ;¯à®¢¥àª : ¥áâì «¨ ¬¥áâ® ¤«ï ¥éñ ®¤­®© ¯ àë
	mov	edi,[MM_BlocksInfo+ebx]
	add	edi,[MM_BlocksInfo+ebx+4]
	mov	[endArea], edi
	sub	edi,4

	cmp	dword[edi],0	 ;¥á«¨ ¢ ¡«®ª¥ ­¥â ­¨ ®¤­®© § ¯¨á¨
	jne	.NoEmptyBlock
	mov	eax,[MM_BlocksInfo+ebx]
	mov	dword[edi-4],eax
	mov	dword[edi],eax
	mov	edx,[Size]
	add	dword[edi],edx
	mov	dword[edi-8],0
	jmp	.return
align 4
 .NoEmptyBlock:
	xor	eax,eax
	push	ecx
	or	ecx,-1
	std
	repne	scasd
	cld
	pop	ecx
	mov	eax,[edi+12] ;ª®­¥æ ¯®á« ãç á⪠
	add	eax,4
	cmp	eax,edi
	jb	@f

	add	ebx,8
	dec	ecx
	jnz	.TestBlock

	mov	ecx,[Size]
	call	AddBlock
	jmp	.return
     @@:


	mov	[begFree],eax  ;eax = ª®­¥æ ¯®á«. ãç á⪠ + 4
	mov	[endFree],edi  ;edi = 㪠§ â¥«ì ­  ª®­¥æ ¯®á« ãç á⪠ - 12
	sub	dword[begFree],4
	add	dword[endFree],12

   ;¯à®¢¥àª  ¯¥à¥¤ ¢á¥¬¨ ãç á⪠¬¨
	mov	edi,[MM_BlocksInfo+ebx]
	mov	eax,[endArea]
	mov	eax,[eax-8]
	sub	eax,[MM_BlocksInfo+ebx]
	cmp	eax,[Size]
	ja	.AddInBegBlock

   ;¯à®¢¥àª  ¬¥¦¤ã ãç á⪠¬¨
	mov	eax,[endArea]
	cmp	dword[eax-12],0
	je	.EndTest ;¥á«¨ ¢ ¡«®ª¥ ⮫쪮 1 ãç á⮪

	sub	eax,4
     @@:
	mov	edi,[eax-12]
	sub	edi,[eax]
	cmp	edi,[Size]
	jae	.AddInMiddle
	sub	eax,8
	cmp	dword[eax-8],0
	jne	@b

   .EndTest:

   ;¯à®¢¥àª  ¯®á«¥ ¢á¥å ¡«®ª®¢
	mov	eax,[begFree]
	mov	edi,[endFree]
	lea	esi,[edi-8]    ;8 - ¬¥áâ® ¯®¤ § ¯¨áì
	sub	esi,eax

	cmp	esi,[Size]
	ja	.AddInEnd

	add	ebx,8
	dec	ecx
	jnz	.TestBlock

	mov	ecx,[Size]
	call	AddBlock

	jmp	.return
align 4
  .AddInBegBlock: ;„®¡ ¢¨âì ¢ ­ ç «®. ‚ edi ­ ç «® ¡«®ª 
	;pop     eax

	mov	eax,edi
	add	eax,[MM_BlocksInfo+ebx+4]
	sub	eax,4
	push	eax
	call	MoveRecordsLeft
	pop	eax
	mov	[eax-4],edi
	push	edi
	add	edi,[Size]
	mov	[eax],edi
	pop	eax

	jmp	.return
align 4
  .AddInMiddle:  ;„®¡ ¢¨âì ¬¥¦¤ã ãç á⪠¬¨, ¥ å=ª®­¥æ ãç á⪠ ¯¥à¥¤ ᢮¡®¤­ë¬ ¬¥á⮬

	;pop     ecx   ;add     esp,4
	push	eax
	sub	eax,8
	call	MoveRecordsLeft
	pop	eax

	mov	edx,[eax]
	mov	[eax-12],edx
	add	edx,[Size]
	mov	[eax-8],edx
	mov	eax,[eax]
	jmp	.return
align 4
  .AddInEnd:  ;„®¡ ¢¨âì ¯®á«¥ ãç á⪮¢. ¥di=㪠§ â¥«ì ­  2®© í«¥¬ ¯ àë á ¨­ä®© ® ¯®á« ãç á⪥

	;add     esp,4
	mov	eax,[edi]
	mov	[edi-12],eax
	push	eax
	add	eax,[Size]
	mov	[edi-8],eax
	pop	eax

.return:

	pop	esi edi ebx
	leave
	ret 4

restore Xren
restore Size
restore begFree
restore endFree



;eax - ¯¥à¢ë© ᤢ¨£ ¥¬ë© dword
;ᤢ¨£ ¥â ¯ àë dword'®¢ ­  8B ­ § ¤ ¢ª«îç ï dword 0
align 4
proc MoveRecordsLeft
local	var1:DWORD,\
	var2:DWORD

	p2p	[var1],[eax]
	p2p	[var2],[eax-4]

     @@:
	sub	eax,8
	cmp	dword[var1],0
	je	@f

	push	dword[eax]
	p2p	[eax],[var1]
	pop	dword[var1]

	push	dword[eax-4]
	p2p	[eax-4],[var2]
	pop	dword[var2]
	jmp	@b
      @@:

	mov	dword[eax],0
	ret
endp

;ecx = à §¬¥à âॡ㥬®£® ãç á⪠
;¤®¡ ¢«ï¥â ¡«®ª ¨ ᮧ¤ ñâ ¢ ­ñ¬ ãç á⮪ à §¬¥à®¬ ecx
align 4
proc AddBlock
	mov	edx,[MM_NBlocks]
	inc	edx
	cmp	edx,MM_MAX_BLOCKS
	ja	.ErrAlloc

	push	ecx
	add	ecx,12

	test	ecx,0FFFh	   ;®ªà㣫塞 ¤® ¡®«ì襩 £à ­¨æë áâà ­¨æë
	jz	@f
	add	ecx,1000h
	and	ecx,0FFFFF000h
      @@:

	mcall	68,12,ecx
	mov	[MM_NBlocks],edx     ;§ ¯®«­¥­¨¥ ¤ ­­ëå ® ¡«®ª¥
	mov	[edx*4*2-4*2+MM_BlocksInfo],eax  ;begin
	mov	[edx*4*2-4+MM_BlocksInfo],ecx	 ;size
;dps 'Block '
;dph eax
;dps ' '
;dph ecx
;dnl
	mov	edx,eax
	add	edx,ecx
	mov	[edx-8],eax
	pop	dword[edx-4]
	add	[edx-4],eax
	mov	dword[edx-12],0
	ret

 .ErrAlloc:
	pop	ecx
	xor	eax,eax
	ret
endp
;-------------------------------------------------------------------------------


;㤠«ï¥â  ¯ ¬ïâì
;proc MM_DelMem Pointer:DWORD
align 4
MM_DelMem:
	Pointer equ ebp+8
	push	ebp
	mov	ebp,esp
; int3
	push	ebx
	mov	ecx,[MM_NBlocks]
	test	ecx,ecx
	jnz	@f
	xor	eax,eax
	pop	ebx
	leave
	ret 4
      @@:

	mov	eax,[Pointer]
	xor	ebx,ebx ;ebx - (­®¬¥à ¡«®ª )*8
   .TestBlocks:
	mov	edx,[MM_BlocksInfo+ebx]
	add	edx,[MM_BlocksInfo+ebx+4]
	sub	edx,8	      ;edx - 㪠§ â¥«ì ­  1ãî ¯ àã

     .TestMems:
	cmp	[edx],eax
	je	.FoundMem

	sub	edx,8
	cmp	dword[edx+4],0
	jne	.TestMems

	add	ebx,4
	loop	.TestBlocks

	xor	eax,eax
	pop	ebx
	leave
	ret 4

   .FoundMem:
	cmp	dword[edx-4],0
	jz	.EndDelMem

   .NextMoveMem:
	p2p    [edx+4],[edx-4]
	p2p    [edx],[edx-8]
	sub	edx,8
	cmp	dword[edx-4],0
	jnz	.NextMoveMem

    .EndDelMem:
	mov	dword[edx+4],0
	mov	dword[edx],0

	mov	eax,1
	pop	ebx
	leave
	ret 4

restore Pointer