Files
2026-07-14 19:31:07 +02:00

2405 lines
40 KiB
NASM

; Hovertank 3-D Source Code
; Copyright (C) 1993-2014 Flat Rock Software
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License along
; with this program; if not, write to the Free Software Foundation, Inc.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ifndef ??version
?debug macro
endm
publicdll macro name
public name
endm
$comm macro name,dist,size,count
comm dist name:BYTE:count*size
endm
else
$comm macro name,dist,size,count
comm dist name[size]:BYTE:count
endm
endif
?debug S "memmgr.c"
?debug C E90E549D16086D656D6D67722E63
?debug C E9D03A9E160749444C49422E48
?debug C E9AE10A3160A4752415048484F562E48
?debug C E92592951609534E4453484F562E48
?debug C E900104D1616433A5C42435C494E434C5544455C7374646172672E+
?debug C 68
?debug C E900104D1613433A5C42435C494E434C5544455C646F732E68
?debug C E900104D1613433A5C42435C494E434C5544455C6D656D2E68
?debug C E900104D1618433A5C42435C494E434C5544455C7379735C737461+
?debug C 742E68
?debug C E900104D1615433A5C42435C494E434C5544455C66636E746C2E68
?debug C E900104D1616433A5C42435C494E434C5544455C7374646C69622E+
?debug C 68
?debug C E900104D1615433A5C42435C494E434C5544455C616C6C6F632E68
?debug C E900104D1612433A5C42435C494E434C5544455C696F2E68
_TEXT segment byte public 'CODE'
_TEXT ends
DGROUP group _DATA,_BSS
assume cs:_TEXT,ds:DGROUP
_DATA segment word public 'DATA'
d@ label byte
d@w label word
_DATA ends
_BSS segment word public 'BSS'
b@ label byte
b@w label word
_BSS ends
_DATA segment word public 'DATA'
db 69
db 77
db 77
db 88
db 88
db 88
db 88
db 48
db 1 dup (0)
_DATA ends
_TEXT segment byte public 'CODE'
;
; void CheckForEMS (void)
;
assume cs:_TEXT
_CheckForEMS proc near
push bp
mov bp,sp
sub sp,10
push ss
lea ax,word ptr [bp-10]
push ax
push ds
mov ax,offset DGROUP:d@+0
push ax
mov cx,9
call near ptr N_SCOPY@
;
; {
; char emmname[9] = "EMMXXXX0";
;
; asm mov dx,OFFSET emmname
;
mov dx,OFFSET [bp-10]
;
; asm mov ax,0x3d00
;
mov ax,03d00H
;
; asm int 0x21 // try to open EMMXXXX0 device
;
int 021H
;
; asm jc error
;
jc short @1@506
;
;
; asm mov bx,ax
;
mov bx,ax
;
; asm mov ax,0x4400
;
mov ax,04400H
;
;
; asm int 0x21 // get device info
;
int 021H
;
; asm jc error
;
jc short @1@506
;
;
; asm and dx,0x80
;
and dx,080H
;
; asm jz error
;
je short @1@506
;
;
; asm mov ax,0x4407
;
mov ax,04407H
;
;
; asm int 0x21 // get status
;
int 021H
;
; asm jc error
;
jc short @1@506
;
; asm or al,al
;
or al,al
;
; asm jz error
;
je short @1@506
;
;
; asm mov ah,0x3e
;
mov ah,03eH
;
; asm int 0x21 // close handle
;
int 021H
;
; asm jc error
;
jc short @1@506
;
;
; //
; // EMS is good
; //
;
;
; return;
;
jmp short @1@530
@1@506:
;
;
; error:
; //
; // EMS is bad
; //
; EMSpresent = 0;
;
mov word ptr DGROUP:_EMSpresent,0
@1@530:
;
;
; }
;
mov sp,bp
pop bp
ret
_CheckForEMS endp
;
; int FindBlock (memptr *ptr)
;
assume cs:_TEXT
_FindBlock proc near
push bp
mov bp,sp
push si
;
; {
; int i;
; for (i=1;i<numblocks;i++)
;
mov si,1
jmp short @2@122
@2@50:
;
; if (blocks[i].useptr == ptr)
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx+6]
cmp ax,word ptr [bp+4]
jne short @2@98
;
; return i;
;
mov ax,si
jmp short @2@170
@2@98:
inc si
@2@122:
cmp si,word ptr DGROUP:_numblocks
jl short @2@50
;
;
; Quit ("Memory manager error: Block not found!");
;
mov ax,offset DGROUP:s@
push ax
call near ptr _Quit
pop cx
;
; return -1;
;
mov ax,65535
jmp short @2@170
@2@170:
;
; }
;
pop si
pop bp
ret
_FindBlock endp
;
; void RemoveBlock (int block)
;
assume cs:_TEXT
_RemoveBlock proc near
push bp
mov bp,sp
sub sp,10
push si
mov si,word ptr [bp+4]
;
; {
; void far *source, far *dest;
; unsigned length;
;
; *blocks[block].useptr = NULL;
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov bx,word ptr DGROUP:_blocks[bx+6]
mov word ptr [bx],0
;
; if (block!=numblocks-1)
;
mov ax,word ptr DGROUP:_numblocks
dec ax
cmp ax,si
je short @3@74
;
; {
; source = &blocks[block+1];
;
mov ax,si
shl ax,1
shl ax,1
shl ax,1
add ax,offset DGROUP:_blocks+8
mov word ptr [bp-2],ds
mov word ptr [bp-4],ax
;
; dest = &blocks[block];
;
mov ax,si
shl ax,1
shl ax,1
shl ax,1
add ax,offset DGROUP:_blocks
mov word ptr [bp-6],ds
mov word ptr [bp-8],ax
;
; length = (numblocks-1-block)*sizeof(blocks[0]);
;
mov ax,word ptr DGROUP:_numblocks
dec ax
sub ax,si
shl ax,1
shl ax,1
shl ax,1
mov word ptr [bp-10],ax
;
; movedata (FP_SEG(source),FP_OFF(source),FP_SEG(dest),FP_OFF(dest),length);
;
push word ptr [bp-10]
push word ptr [bp-8]
push word ptr [bp-6]
push word ptr [bp-4]
push word ptr [bp-2]
call near ptr _movedata
add sp,10
@3@74:
;
; }
; numblocks--;
;
dec word ptr DGROUP:_numblocks
;
; }
;
pop si
mov sp,bp
pop bp
ret
_RemoveBlock endp
;
; void InsertBlock (int block)
;
assume cs:_TEXT
_InsertBlock proc near
push bp
mov bp,sp
sub sp,6
push si
push di
;
; {
; unsigned source,dest,length;
;
; if (block!=numblocks-1)
;
mov ax,word ptr DGROUP:_numblocks
dec ax
cmp ax,word ptr [bp+4]
je short @4@266
;
; {
; source = ((unsigned)&blocks[numblocks])-2;
;
mov ax,word ptr DGROUP:_numblocks
shl ax,1
shl ax,1
shl ax,1
add ax,offset DGROUP:_blocks
dec ax
dec ax
mov word ptr [bp-2],ax
;
; dest = ((unsigned)&blocks[numblocks+1])-2;
;
mov ax,word ptr DGROUP:_numblocks
shl ax,1
shl ax,1
shl ax,1
add ax,offset DGROUP:_blocks+8
dec ax
dec ax
mov word ptr [bp-4],ax
;
; length = (numblocks-1-block)*sizeof(blocks[0])/2;
;
mov ax,word ptr DGROUP:_numblocks
dec ax
sub ax,word ptr [bp+4]
shl ax,1
shl ax,1
shl ax,1
shr ax,1
mov word ptr [bp-6],ax
;
; asm mov cx,length
;
mov cx,[bp-6]
;
; asm mov si,source
;
mov si,[bp-2]
;
; asm mov di,dest
;
mov di,[bp-4]
;
; asm mov ax,ds
;
mov ax,ds
;
; asm mov es,ax
;
mov es,ax
;
; asm std
;
std
;
; asm rep movsw
;
rep movsw
;
; asm cld
;
cld
@4@266:
;
; }
; if (++numblocks>=MAXBLOCKS)
;
inc word ptr DGROUP:_numblocks
mov ax,word ptr DGROUP:_numblocks
cmp ax,1500
jl short @4@314
;
; Quit ("Memory manager error: Too many blocks!");
;
mov ax,offset DGROUP:s@+39
push ax
call near ptr _Quit
pop cx
@4@314:
;
; }
;
pop di
pop si
mov sp,bp
pop bp
ret
_InsertBlock endp
;
; void MMStartup (void)
;
assume cs:_TEXT
_MMStartup proc near
push bp
mov bp,sp
sub sp,14
push si
push di
;
; {
; unsigned long length;
; void far *start;
; unsigned nearstart,farstart,EMSstart,seg;
; unsigned nearlength,farlength,emslength,xmslength;
;
; //
; // get all available near conventional memory
; //
; length=coreleft();
;
call near ptr _coreleft
mov word ptr [bp-2],0
mov word ptr [bp-4],ax
;
; start = (void far *)(nearheap = malloc(length));
;
push word ptr [bp-4]
call near ptr _malloc
pop cx
mov word ptr DGROUP:_nearheap,ax
mov word ptr [bp-6],ds
mov word ptr [bp-8],ax
;
;
; //
; // paragraph align it and figure size
; //
; length -= 16-(FP_OFF(start)&15);
;
mov ax,word ptr [bp-8]
and ax,15
mov dx,16
sub dx,ax
sub word ptr [bp-4],dx
sbb word ptr [bp-2],0
;
; length -= EXTRASTACKSIZE;
;
sub word ptr [bp-4],4096
sbb word ptr [bp-2],0
;
; nearlength = length / 16; // now in paragraphs
;
mov dx,word ptr [bp-2]
mov ax,word ptr [bp-4]
mov cl,4
call near ptr N_LXURSH@
mov word ptr [bp-12],ax
;
; nearstart = FP_SEG(start)+(FP_OFF(start)+15)/16;
;
mov ax,word ptr [bp-8]
add ax,15
mov cl,4
shr ax,cl
mov dx,word ptr [bp-6]
add dx,ax
mov si,dx
;
;
; //
; // get all available far conventional memory
; //
; length=farcoreleft();
;
call near ptr _farcoreleft
mov word ptr [bp-2],dx
mov word ptr [bp-4],ax
;
; start = farheap = farmalloc(length);
;
push word ptr [bp-2]
push word ptr [bp-4]
call near ptr _farmalloc
pop cx
pop cx
mov word ptr DGROUP:_farheap+2,dx
mov word ptr DGROUP:_farheap,ax
mov word ptr [bp-6],dx
mov word ptr [bp-8],ax
;
;
; //
; // paragraph align it and figure size
; //
; if (FP_OFF(start))
;
cmp word ptr [bp-8],0
je short @5@74
;
; {
; length -= 16-FP_OFF(start);
;
mov ax,16
sub ax,word ptr [bp-8]
sub word ptr [bp-4],ax
sbb word ptr [bp-2],0
;
; start = (void far *)MK_FP(FP_SEG(start)+1,0);
;
mov ax,word ptr [bp-6]
inc ax
mov word ptr [bp-6],ax
mov word ptr [bp-8],0
@5@74:
;
; }
; farlength = length / 16; // now in paragraphs
;
mov dx,word ptr [bp-2]
mov ax,word ptr [bp-4]
mov cl,4
call near ptr N_LXURSH@
mov word ptr [bp-14],ax
;
; farstart = FP_SEG(start);
;
mov di,word ptr [bp-6]
;
;
; totalmem = nearlength + farlength;
;
mov ax,word ptr [bp-12]
add ax,word ptr [bp-14]
mov word ptr DGROUP:_totalmem,ax
;
;
; //
; // detect EMS and allocate 64K at page frame
; //
; CheckForEMS();
;
call near ptr _CheckForEMS
;
; if (EMSpresent)
;
cmp word ptr DGROUP:_EMSpresent,0
je short @5@122
;
; {
; EMSstart = 0xffff;
;
mov word ptr [bp-10],65535
;
; totalmem += 0x1000; // 64k of EMS
;
add word ptr DGROUP:_totalmem,4096
;
; MMMapEMS(); // map in used pages
;
call near ptr _MMMapEMS
;
; }
;
jmp short @5@146
@5@122:
;
; else
; {
; EMSstart = 0xffff;
;
mov word ptr [bp-10],65535
@5@146:
;
; }
;
; //
; // set up locked blocks
; //
; numblocks = 0;
;
mov word ptr DGROUP:_numblocks,0
;
;
; blocks[numblocks].start = 0;
;
mov bx,word ptr DGROUP:_numblocks
shl bx,1
shl bx,1
shl bx,1
mov word ptr DGROUP:_blocks[bx],0
;
; blocks[numblocks].length = nearstart;
;
mov bx,word ptr DGROUP:_numblocks
shl bx,1
shl bx,1
shl bx,1
mov word ptr DGROUP:_blocks[bx+2],si
;
; blocks[numblocks].attributes = LOCKBIT;
;
mov bx,word ptr DGROUP:_numblocks
shl bx,1
shl bx,1
shl bx,1
mov word ptr DGROUP:_blocks[bx+4],32768
;
;
; numblocks++;
;
inc word ptr DGROUP:_numblocks
;
;
; blocks[numblocks].start = nearstart+nearlength;
;
mov bx,word ptr DGROUP:_numblocks
shl bx,1
shl bx,1
shl bx,1
mov ax,si
add ax,word ptr [bp-12]
mov word ptr DGROUP:_blocks[bx],ax
;
; blocks[numblocks].length = farstart-(nearstart+nearlength);
;
mov bx,word ptr DGROUP:_numblocks
shl bx,1
shl bx,1
shl bx,1
mov ax,si
add ax,word ptr [bp-12]
mov dx,di
sub dx,ax
mov word ptr DGROUP:_blocks[bx+2],dx
;
; blocks[numblocks].attributes = LOCKBIT;
;
mov bx,word ptr DGROUP:_numblocks
shl bx,1
shl bx,1
shl bx,1
mov word ptr DGROUP:_blocks[bx+4],32768
;
;
; numblocks++;
;
inc word ptr DGROUP:_numblocks
;
;
; blocks[numblocks].start = farstart+farlength;
;
mov bx,word ptr DGROUP:_numblocks
shl bx,1
shl bx,1
shl bx,1
mov ax,di
add ax,word ptr [bp-14]
mov word ptr DGROUP:_blocks[bx],ax
;
; blocks[numblocks].length = EMSstart-(farstart+farlength);
;
mov bx,word ptr DGROUP:_numblocks
shl bx,1
shl bx,1
shl bx,1
mov ax,di
add ax,word ptr [bp-14]
mov dx,word ptr [bp-10]
sub dx,ax
mov word ptr DGROUP:_blocks[bx+2],dx
;
; blocks[numblocks].attributes = LOCKBIT;
;
mov bx,word ptr DGROUP:_numblocks
shl bx,1
shl bx,1
shl bx,1
mov word ptr DGROUP:_blocks[bx+4],32768
;
;
; numblocks++;
;
inc word ptr DGROUP:_numblocks
;
;
;
; }
;
pop di
pop si
mov sp,bp
pop bp
ret
_MMStartup endp
;
; void MMShutdown (void)
;
assume cs:_TEXT
_MMShutdown proc near
push bp
mov bp,sp
;
; {
; farfree (farheap);
;
push word ptr DGROUP:_farheap+2
push word ptr DGROUP:_farheap
call near ptr _farfree
pop cx
pop cx
;
; free (nearheap);
;
push word ptr DGROUP:_nearheap
call near ptr _free
pop cx
;
;
; }
;
pop bp
ret
_MMShutdown endp
;
; void MMMapEMS (void)
;
assume cs:_TEXT
_MMMapEMS proc near
push bp
mov bp,sp
;
; {
;
; }
;
pop bp
ret
_MMMapEMS endp
;
; void MMGetPtr (memptr *baseptr,long size)
;
assume cs:_TEXT
_MMGetPtr proc near
push bp
mov bp,sp
sub sp,8
push si
push di
;
; {
; int i,j,k,try;
; unsigned start,end;
;
; //
; // change size from bytes to paragraphs
; //
; size = (size+15)/16;
;
xor ax,ax
mov dx,16
push ax
push dx
mov ax,word ptr [bp+8]
mov dx,word ptr [bp+6]
add dx,15
adc ax,0
push ax
push dx
call near ptr N_LDIV@
mov word ptr [bp+8],dx
mov word ptr [bp+6],ax
;
;
; //
; // try a normal scan, then compress if not found
; //
; for (try=0;try<2;try++)
;
mov word ptr [bp-4],0
jmp @8@482
@8@50:
;
; {
; for (i=0;i<numblocks-1;i++)
;
xor si,si
jmp @8@386
@8@74:
;
; {
; if (blocks[i].attributes & PURGEBITS )
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
test word ptr DGROUP:_blocks[bx+4],3
je short @8@122
;
; continue;
;
jmp @8@362
@8@122:
;
; //
; // blocks[i] cannot be written over, so try to allocate the
; // new block right after it
; //
; start = blocks[i].start + blocks[i].length;
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
add ax,word ptr DGROUP:_blocks[bx+2]
mov word ptr [bp-6],ax
;
; end = start + size;
;
mov ax,word ptr [bp-6]
add ax,word ptr [bp+6]
mov word ptr [bp-8],ax
;
; j=i+1;
;
mov ax,si
inc ax
mov di,ax
jmp short @8@218
@8@146:
;
; while (blocks[j].start < end)
; {
; if (!(blocks[j].attributes & PURGEBITS))
;
mov bx,di
shl bx,1
shl bx,1
shl bx,1
test word ptr DGROUP:_blocks[bx+4],3
jne short @8@194
;
; {
; i = j-1;
;
mov ax,di
dec ax
mov si,ax
;
; goto lookmore; // a non purgable block is in the way
;
jmp @8@362
@8@194:
;
; }
; j++;
;
inc di
@8@218:
mov bx,di
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx]
cmp ax,word ptr [bp-8]
jb short @8@146
;
; }
; //
; // purge the blocks in the way
; //
; for (k=i+1;k<j;j--)
;
mov ax,si
inc ax
mov word ptr [bp-2],ax
jmp short @8@314
@8@266:
;
; RemoveBlock(k);
;
push word ptr [bp-2]
call near ptr _RemoveBlock
pop cx
dec di
@8@314:
cmp word ptr [bp-2],di
jl short @8@266
;
; //
; // allocate the new block
; //
; InsertBlock(i);
;
push si
call near ptr _InsertBlock
pop cx
;
; *(unsigned *)baseptr = start;
;
mov bx,word ptr [bp+4]
mov ax,word ptr [bp-6]
mov word ptr [bx],ax
;
; blocks[i+1].start = start;
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr [bp-6]
mov word ptr DGROUP:_blocks[bx+8],ax
;
; blocks[i+1].length = size;
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr [bp+6]
mov word ptr DGROUP:_blocks[bx+10],ax
;
; blocks[i+1].useptr = baseptr;
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr [bp+4]
mov word ptr DGROUP:_blocks[bx+14],ax
;
; blocks[i+1].attributes = BASEATTRIBUTES;
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov word ptr DGROUP:_blocks[bx+12],0
;
; return;
;
jmp short @8@530
@8@362:
inc si
@8@386:
mov ax,word ptr DGROUP:_numblocks
dec ax
cmp ax,si
jle @@84
jmp @8@74
@@84:
;
; lookmore:;
; }
; //
; // didn't find any space, so compress and try again
; //
; if (try==0)
;
cmp word ptr [bp-4],0
jne short @8@458
;
; MMSortMem();
;
call near ptr _MMSortMem
@8@458:
inc word ptr [bp-4]
@8@482:
cmp word ptr [bp-4],2
jge @@85
jmp @8@50
@@85:
;
; }
;
; //puts("");
; //MMBlockDump(); // DEBUG
; Quit ("Memory manager error: Out of memory!");
;
mov ax,offset DGROUP:s@+78
push ax
call near ptr _Quit
pop cx
@8@530:
;
; }
;
pop di
pop si
mov sp,bp
pop bp
ret
_MMGetPtr endp
;
; void MMFreePtr (memptr *baseptr)
;
assume cs:_TEXT
_MMFreePtr proc near
push bp
mov bp,sp
;
; {
; RemoveBlock(FindBlock (baseptr));
;
push word ptr [bp+4]
call near ptr _FindBlock
pop cx
push ax
call near ptr _RemoveBlock
pop cx
;
; }
;
pop bp
ret
_MMFreePtr endp
;
; void MMSetPurge (memptr *baseptr, int purge)
;
assume cs:_TEXT
_MMSetPurge proc near
push bp
mov bp,sp
push si
push di
;
; {
; int block;
; unsigned attr;
;
; block = FindBlock (baseptr);
;
push word ptr [bp+4]
call near ptr _FindBlock
pop cx
mov di,ax
;
;
; attr = blocks[block].attributes;
;
mov bx,di
shl bx,1
shl bx,1
shl bx,1
mov si,word ptr DGROUP:_blocks[bx+4]
;
; attr &= 0xffff - PURGEBITS;
;
and si,65532
;
; attr |= purge; // set bits in attributes
;
or si,word ptr [bp+6]
;
; blocks[block].attributes = attr;
;
mov bx,di
shl bx,1
shl bx,1
shl bx,1
mov word ptr DGROUP:_blocks[bx+4],si
;
; }
;
pop di
pop si
pop bp
ret
_MMSetPurge endp
;
; void MoveParaBase (unsigned source, unsigned dest, unsigned words)
;
assume cs:_TEXT
_MoveParaBase proc near
push bp
mov bp,sp
push si
push di
;
; {
; asm mov cx,words
;
mov cx,[bp+8]
;
; asm xor si,si
;
xor si,si
;
; asm xor di,di
;
xor di,di
;
; asm mov ax,source
;
mov ax,[bp+4]
;
; asm mov bx,dest
;
mov bx,[bp+6]
;
; asm mov ds,source
;
mov ds,[bp+4]
;
; asm mov es,dest
;
mov es,[bp+6]
;
; asm rep movsw
;
rep movsw
;
; asm mov ax,ss
;
mov ax,ss
;
; asm mov ds,ax
;
mov ds,ax
;
; }
;
pop di
pop si
pop bp
ret
_MoveParaBase endp
;
; void MoveParaBaseUp (unsigned source, unsigned dest, unsigned words)
;
assume cs:_TEXT
_MoveParaBaseUp proc near
push bp
mov bp,sp
push si
push di
;
; {
; asm mov cx,words
;
mov cx,[bp+8]
;
; asm mov si,cx
;
mov si,cx
;
; asm dec si
;
dec si
;
; asm shl si,1
;
shl si,1
;
; asm mov di,si
;
mov di,si
;
; asm mov ax,source
;
mov ax,[bp+4]
;
; asm mov bx,dest
;
mov bx,[bp+6]
;
; asm mov ds,source
;
mov ds,[bp+4]
;
; asm mov es,dest
;
mov es,[bp+6]
;
; asm rep movsw
;
rep movsw
;
; asm mov ax,ss
;
mov ax,ss
;
; asm mov ds,ax
;
mov ds,ax
;
; }
;
pop di
pop si
pop bp
ret
_MoveParaBaseUp endp
;
; void MoveParas (unsigned source, unsigned dest, unsigned paragraphs)
;
assume cs:_TEXT
_MoveParas proc near
push bp
mov bp,sp
push si
push di
mov si,word ptr [bp+4]
mov di,word ptr [bp+6]
;
; {
; if (source>dest)
;
cmp si,di
jbe short @13@170
;
; {
; asm cld
;
cld
jmp short @13@122
@13@98:
;
; while (paragraphs>0xfff)
; {
; MoveParaBase (source,dest,0xfff*8);
;
mov ax,32760
push ax
push di
push si
call near ptr _MoveParaBase
add sp,6
;
; source += 0xfff*8;
;
add si,32760
;
; dest += 0xfff*8;
;
add di,32760
;
; paragraphs -= 0xfff;
;
sub word ptr [bp+8],4095
@13@122:
cmp word ptr [bp+8],4095
ja short @13@98
;
; }
; MoveParaBase (source,dest,paragraphs*8);
;
mov ax,word ptr [bp+8]
shl ax,1
shl ax,1
shl ax,1
push ax
push di
push si
call near ptr _MoveParaBase
add sp,6
;
; }
;
jmp short @13@314
@13@170:
;
; else
; {
; asm std
;
std
;
; source+=paragraphs;
;
add si,word ptr [bp+8]
;
; dest+=paragraphs;
;
add di,word ptr [bp+8]
jmp short @13@242
@13@218:
;
; while (paragraphs>0xfff)
; {
; source-=0xfff;
;
sub si,4095
;
; dest-=0xfff;
;
sub di,4095
;
; MoveParaBaseUp (source,dest,0xfff*8);
;
mov ax,32760
push ax
push di
push si
call near ptr _MoveParaBaseUp
add sp,6
;
; paragraphs -= 0xfff;
;
sub word ptr [bp+8],4095
@13@242:
cmp word ptr [bp+8],4095
ja short @13@218
;
; }
; source-=paragraphs;
;
sub si,word ptr [bp+8]
;
; dest-=paragraphs;
;
sub di,word ptr [bp+8]
;
; MoveParaBaseUp (source,dest,paragraphs*8);
;
mov ax,word ptr [bp+8]
shl ax,1
shl ax,1
shl ax,1
push ax
push di
push si
call near ptr _MoveParaBaseUp
add sp,6
;
; asm cld
;
cld
@13@314:
;
; }
; }
;
pop di
pop si
pop bp
ret
_MoveParas endp
;
; void PushUp (int move)
;
assume cs:_TEXT
_PushUp proc near
push bp
mov bp,sp
sub sp,6
push si
push di
mov di,word ptr [bp+4]
;
; {
; unsigned source,dest,size;
; int i;
;
; size = blocks[move].length;
;
mov bx,di
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx+2]
mov word ptr [bp-6],ax
;
; source = blocks[move].start;
;
mov bx,di
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx]
mov word ptr [bp-2],ax
;
;
; for (i=numblocks-1;i>keyblock;i--)
;
mov ax,word ptr DGROUP:_numblocks
dec ax
mov si,ax
jmp @14@122
@14@50:
;
; {
; //
; // if the block can fit under this block, move it
; //
; dest = blocks[i].start - size;
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx]
sub ax,word ptr [bp-6]
mov word ptr [bp-4],ax
;
; if (blocks[i-1].start+blocks[i-1].length <= dest)
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx-8]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
add ax,word ptr DGROUP:_blocks[bx-6]
cmp ax,word ptr [bp-4]
ja short @14@98
;
; {
; //
; // make a copy of block 'move' under block 'i'
; //
; InsertBlock (i-1);
;
mov ax,si
dec ax
push ax
call near ptr _InsertBlock
pop cx
;
; blocks[i] = blocks[move];
;
mov ax,si
shl ax,1
shl ax,1
shl ax,1
add ax,offset DGROUP:_blocks
push ds
push ax
mov ax,di
shl ax,1
shl ax,1
shl ax,1
add ax,offset DGROUP:_blocks
push ds
push ax
mov cx,8
call near ptr N_SCOPY@
;
; blocks[i].start = dest;
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr [bp-4]
mov word ptr DGROUP:_blocks[bx],ax
;
; *(blocks[i].useptr) = (void _seg *)dest; // modify the pointer to the new spot
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov bx,word ptr DGROUP:_blocks[bx+6]
mov ax,word ptr [bp-4]
mov word ptr [bx],ax
;
; MoveParas (source,dest,size);
;
push word ptr [bp-6]
push word ptr [bp-4]
push word ptr [bp-2]
call near ptr _MoveParas
add sp,6
;
; break;
;
jmp short @14@146
@14@98:
dec si
@14@122:
cmp si,word ptr DGROUP:_keyblock
jle @@86
jmp @14@50
@@86:
@14@146:
;
; }
; }
;
; //
; // erase original position
; //
; RemoveBlock (move);
;
push di
call near ptr _RemoveBlock
pop cx
;
; keyblock--; // because a block below it was removed
;
dec word ptr DGROUP:_keyblock
;
; }
;
pop di
pop si
mov sp,bp
pop bp
ret
_PushUp endp
;
; void PushDown (void)
;
assume cs:_TEXT
_PushDown proc near
push bp
mov bp,sp
sub sp,10
push si
push di
;
; {
; unsigned source,dest,size,end,lowblock,checkblock,i;
;
; size = blocks[keyblock].length;
;
mov bx,word ptr DGROUP:_keyblock
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx+2]
mov word ptr [bp-4],ax
;
; source = blocks[keyblock].start;
;
mov bx,word ptr DGROUP:_keyblock
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx]
mov word ptr [bp-2],ax
;
;
; //
; // find the lowest space it can be moved into
; //
; for (lowblock = 0;lowblock<keyblock;lowblock++)
;
xor si,si
jmp @15@458
@15@50:
;
; if (!(blocks[lowblock].attributes & PURGEBITS) ||
;
;
; blocks[lowblock].attributes & LOCKBIT)
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
test word ptr DGROUP:_blocks[bx+4],3
je short @15@98
mov bx,si
shl bx,1
shl bx,1
shl bx,1
test word ptr DGROUP:_blocks[bx+4],32768
jne @@87
jmp @15@434
@@87:
@15@98:
;
; {
; //
; // found a locked or nonpurgable block below keyblock
; //
; // see if there is enough space to move block
; //
; dest = blocks[lowblock].start + blocks[lowblock].length;
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
add ax,word ptr DGROUP:_blocks[bx+2]
mov di,ax
;
; end = dest+size;
;
mov ax,di
add ax,word ptr [bp-4]
mov word ptr [bp-6],ax
;
;
; //
; // see if any of the blocks in the middle can be moved away
; //
; checkblock = lowblock+1;
;
mov ax,si
inc ax
mov word ptr [bp-8],ax
jmp short @15@194
@15@122:
;
; while (checkblock < keyblock && blocks[checkblock].start<end)
; {
; if (!(blocks[checkblock].attributes & PURGEBITS) )
;
mov bx,word ptr [bp-8]
shl bx,1
shl bx,1
shl bx,1
test word ptr DGROUP:_blocks[bx+4],3
jne short @15@170
;
; goto nofit; // can't fit between two locked blocks
;
jmp @15@434
@15@170:
;
; //
; // push the block up or remove it, in either case dropping
; // keyblock and changing blocks[checkblock]
; //
; PushUp (checkblock);
;
push word ptr [bp-8]
call near ptr _PushUp
pop cx
@15@194:
mov ax,word ptr [bp-8]
cmp ax,word ptr DGROUP:_keyblock
jae short @15@242
mov bx,word ptr [bp-8]
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx]
cmp ax,word ptr [bp-6]
jb short @15@122
@15@242:
;
; }
; //
; // move it!
; //
; if (dest != source)
;
cmp di,word ptr [bp-2]
jne @@88
jmp @15@410
@@88:
;
; {
; MoveParas (source,dest,size);
;
push word ptr [bp-4]
push di
push word ptr [bp-2]
call near ptr _MoveParas
add sp,6
;
; blocks[keyblock].start = dest;
;
mov bx,word ptr DGROUP:_keyblock
shl bx,1
shl bx,1
shl bx,1
mov word ptr DGROUP:_blocks[bx],di
;
; *(blocks[keyblock].useptr) = (void _seg *)dest; // modify the pointer to the new spot
;
mov bx,word ptr DGROUP:_keyblock
shl bx,1
shl bx,1
shl bx,1
mov bx,word ptr DGROUP:_blocks[bx+6]
mov word ptr [bx],di
;
; if (lowblock<keyblock-1)
;
mov ax,word ptr DGROUP:_keyblock
dec ax
cmp ax,si
ja @@89
jmp @15@410
@@89:
;
; {
; //
; // reorder the block records
; //
; tempblock = blocks[keyblock];
;
mov ax,offset DGROUP:_tempblock
push ds
push ax
mov ax,word ptr DGROUP:_keyblock
shl ax,1
shl ax,1
shl ax,1
add ax,offset DGROUP:_blocks
push ds
push ax
mov cx,8
call near ptr N_SCOPY@
;
; for (i=keyblock;i>lowblock+1;i--)
;
mov ax,word ptr DGROUP:_keyblock
mov word ptr [bp-10],ax
jmp short @15@362
@15@314:
;
; blocks[i]=blocks[i-1];
;
mov ax,word ptr [bp-10]
shl ax,1
shl ax,1
shl ax,1
add ax,offset DGROUP:_blocks
push ds
push ax
mov ax,word ptr [bp-10]
dec ax
shl ax,1
shl ax,1
shl ax,1
add ax,offset DGROUP:_blocks
push ds
push ax
mov cx,8
call near ptr N_SCOPY@
dec word ptr [bp-10]
@15@362:
mov ax,si
inc ax
cmp ax,word ptr [bp-10]
jb short @15@314
;
; blocks[lowblock+1] = tempblock;
;
mov ax,si
inc ax
shl ax,1
shl ax,1
shl ax,1
add ax,offset DGROUP:_blocks
push ds
push ax
mov ax,offset DGROUP:_tempblock
push ds
push ax
mov cx,8
call near ptr N_SCOPY@
@15@410:
;
; }
;
; //MMBlockDump(); // DEBUG
; }
; return;
;
jmp short @15@482
@15@434:
inc si
@15@458:
cmp si,word ptr DGROUP:_keyblock
jae @@90
jmp @15@50
@@90:
@15@482:
;
;
; nofit:; // keep looking...
;
; }
; }
;
pop di
pop si
mov sp,bp
pop bp
ret
_PushDown endp
;
; void MMSortMem (void)
;
assume cs:_TEXT
_MMSortMem proc near
push bp
mov bp,sp
dec sp
dec sp
push si
push di
;
; {
; unsigned i,source,dest;
;
; keyblock = 0;
;
mov word ptr DGROUP:_keyblock,0
@16@50:
;
;
; do
; {
; keyblock++;
;
inc word ptr DGROUP:_keyblock
;
;
; //
; // non-purgable, unlocked blocks will be pushed low in memory
; //
; if ( !(blocks[keyblock].attributes & PURGEBITS) &&
;
;
; !(blocks[keyblock].attributes & LOCKBIT) )
;
mov bx,word ptr DGROUP:_keyblock
shl bx,1
shl bx,1
shl bx,1
test word ptr DGROUP:_blocks[bx+4],3
jne short @16@122
mov bx,word ptr DGROUP:_keyblock
shl bx,1
shl bx,1
shl bx,1
test word ptr DGROUP:_blocks[bx+4],32768
jne short @16@122
;
; PushDown ();
;
call near ptr _PushDown
@16@122:
;
;
; } while (keyblock<numblocks-1);
;
mov ax,word ptr DGROUP:_numblocks
dec ax
cmp ax,word ptr DGROUP:_keyblock
jg short @16@50
;
;
;
; for (i=numblocks-2;i>0;i--)
;
mov ax,word ptr DGROUP:_numblocks
add ax,65534
mov si,ax
jmp @16@266
@16@170:
;
; {
; //
; // push all purgable blocks as high as possible
; // Currently they are NOT moved around locked blocks!
; //
; if ( blocks[i].attributes & PURGEBITS )
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
test word ptr DGROUP:_blocks[bx+4],3
jne @@91
jmp @16@242
@@91:
;
; {
; source= blocks[i].start;
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx]
mov word ptr [bp-2],ax
;
; dest= blocks[i+1].start-blocks[i].length;
;
mov bx,si
inc bx
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
sub ax,word ptr DGROUP:_blocks[bx+2]
mov di,ax
;
; if (source!=dest)
;
cmp word ptr [bp-2],di
je short @16@242
;
; {
; MoveParas (source,dest,blocks[i].length);
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
push word ptr DGROUP:_blocks[bx+2]
push di
push word ptr [bp-2]
call near ptr _MoveParas
add sp,6
;
; blocks[i].start = dest;
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov word ptr DGROUP:_blocks[bx],di
;
; *(blocks[i].useptr) = (void _seg *)dest; // modify the pointer to the new spot
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov bx,word ptr DGROUP:_blocks[bx+6]
mov word ptr [bx],di
@16@242:
dec si
@16@266:
or si,si
jbe @@92
jmp @16@170
@@92:
;
; }
; }
; }
;
; PatchPointers(); // let the main program fix up any
;
call near ptr _PatchPointers
;
; // internal references
; }
;
pop di
pop si
mov sp,bp
pop bp
ret
_MMSortMem endp
?debug C E900104D1615433A5C42435C494E434C5544455C535444494F2E48
;
; void MMBlockDump (void)
;
assume cs:_TEXT
_MMBlockDump proc near
push bp
mov bp,sp
push si
push di
;
; {
; int i;
; unsigned free;
;
; fprintf (stdprn,"-------------\n");
;
mov ax,offset DGROUP:s@+115
push ax
mov ax,offset DGROUP:__streams+64
push ax
call near ptr _fprintf
pop cx
pop cx
;
; for (i=0;i<numblocks;i++)
;
xor si,si
jmp @17@146
@17@50:
;
; {
; fprintf (stdprn,"Start:%4X\tLength:%4X\tAttr:%4X\tPtr:%p\n"
;
;
; ,blocks[i].start,blocks[i].length,blocks[i].attributes,blocks[i].useptr);
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
push word ptr DGROUP:_blocks[bx+6]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
push word ptr DGROUP:_blocks[bx+4]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
push word ptr DGROUP:_blocks[bx+2]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
push word ptr DGROUP:_blocks[bx]
mov ax,offset DGROUP:s@+130
push ax
mov ax,offset DGROUP:__streams+64
push ax
call near ptr _fprintf
add sp,12
;
; if (i<numblocks-1)
;
mov ax,word ptr DGROUP:_numblocks
dec ax
cmp ax,si
jle short @17@122
;
; {
; free = blocks[i+1].start - (blocks[i].start+blocks[i].length);
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
add ax,word ptr DGROUP:_blocks[bx+2]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov dx,word ptr DGROUP:_blocks[bx+8]
sub dx,ax
mov di,dx
;
; if (free)
;
or di,di
je short @17@122
;
; fprintf (stdprn,"### Free:%X\n",free);
;
push di
mov ax,offset DGROUP:s@+168
push ax
mov ax,offset DGROUP:__streams+64
push ax
call near ptr _fprintf
add sp,6
@17@122:
inc si
@17@146:
cmp si,word ptr DGROUP:_numblocks
jge @@93
jmp @17@50
@@93:
;
; }
; }
; puts("");
;
mov ax,offset DGROUP:s@+181
push ax
call near ptr _puts
pop cx
;
; }
;
pop di
pop si
pop bp
ret
_MMBlockDump endp
;
; unsigned MMUnusedMemory (void)
;
assume cs:_TEXT
_MMUnusedMemory proc near
push bp
mov bp,sp
push si
push di
;
; {
; int i;
; unsigned free;
;
; free = 0;
;
xor di,di
;
;
; for (i=0;i<numblocks;i++)
;
xor si,si
jmp short @18@122
@18@50:
;
; {
; if (i<numblocks-1)
;
mov ax,word ptr DGROUP:_numblocks
dec ax
cmp ax,si
jle short @18@98
;
; free += blocks[i+1].start - (blocks[i].start+blocks[i].length);
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
add ax,word ptr DGROUP:_blocks[bx+2]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov dx,word ptr DGROUP:_blocks[bx+8]
sub dx,ax
add di,dx
@18@98:
inc si
@18@122:
cmp si,word ptr DGROUP:_numblocks
jl short @18@50
;
; }
;
; return free;
;
mov ax,di
jmp short @18@170
@18@170:
;
; }
;
pop di
pop si
pop bp
ret
_MMUnusedMemory endp
;
; unsigned MMTotalFree (void)
;
assume cs:_TEXT
_MMTotalFree proc near
push bp
mov bp,sp
push si
push di
;
; {
; int i;
; unsigned free;
;
; free = 0;
;
xor di,di
;
;
; for (i=0;i<numblocks;i++)
;
xor si,si
jmp short @19@170
@19@50:
;
; {
; if (blocks[i].attributes & PURGEBITS)
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
test word ptr DGROUP:_blocks[bx+4],3
je short @19@98
;
; free += blocks[i].length;
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
add di,word ptr DGROUP:_blocks[bx+2]
@19@98:
;
; if (i<numblocks-1)
;
mov ax,word ptr DGROUP:_numblocks
dec ax
cmp ax,si
jle short @19@146
;
; free += blocks[i+1].start - (blocks[i].start+blocks[i].length);
;
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov ax,word ptr DGROUP:_blocks[bx]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
add ax,word ptr DGROUP:_blocks[bx+2]
mov bx,si
shl bx,1
shl bx,1
shl bx,1
mov dx,word ptr DGROUP:_blocks[bx+8]
sub dx,ax
add di,dx
@19@146:
inc si
@19@170:
cmp si,word ptr DGROUP:_numblocks
jl short @19@50
;
; }
;
; return free;
;
mov ax,di
jmp short @19@218
@19@218:
;
; }
;
pop di
pop si
pop bp
ret
_MMTotalFree endp
_TEXT ends
_BSS segment word public 'BSS'
_totalmem label word
db 2 dup (?)
_blocks label word
db 12000 dup (?)
_farheap label dword
db 4 dup (?)
_nearheap label word
db 2 dup (?)
_keyblock label word
db 2 dup (?)
_tempblock label word
db 8 dup (?)
_numblocks label word
db 2 dup (?)
_EMSpresent label word
db 2 dup (?)
_XMSpresent label word
db 2 dup (?)
?debug C E9
_BSS ends
_DATA segment word public 'DATA'
s@ label byte
db 'Memory manager error: Block not found!'
db 0
db 'Memory manager error: Too many blocks!'
db 0
db 'Memory manager error: Out of memory!'
db 0
db '-------------'
db 10
db 0
db 'Start:%4X'
db 9
db 'Length:%4X'
db 9
db 'Attr:%4X'
db 9
db 'Ptr:%p'
db 10
db 0
db '### Free:%X'
db 10
db 0
db 0
_DATA ends
_TEXT segment byte public 'CODE'
_TEXT ends
public _MMShutdown
public _MMBlockDump
extrn _farcoreleft:near
public _XMSpresent
public _MMTotalFree
public _MMStartup
public _EMSpresent
public _MMFreePtr
public _RemoveBlock
extrn _farmalloc:near
public _PushDown
public _numblocks
public _MMSetPurge
public _MMGetPtr
public _tempblock
public _MMSortMem
public _FindBlock
extrn _free:near
public _keyblock
public _nearheap
extrn _malloc:near
extrn _farfree:near
public _farheap
extrn _puts:near
public _MoveParaBase
extrn _fprintf:near
public _MMMapEMS
extrn _Quit:near
public _PushUp
public _MoveParaBaseUp
public _CheckForEMS
public _blocks
extrn N_SCOPY@:far
extrn _movedata:near
extrn N_LXURSH@:far
extrn __streams:word
extrn N_LDIV@:far
public _totalmem
public _MoveParas
extrn _coreleft:near
public _MMUnusedMemory
public _InsertBlock
extrn _PatchPointers:near
end