home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 5
/
ctrom5b.zip
/
ctrom5b
/
DOS
/
UTILITY
/
GEHEUGEN
/
MAP20
/
MAP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-27
|
34KB
|
1,152 lines
// --------------------------------------------------------------------------
//
// File: MAP.C
// Author: Sulyok Peter (C) 1992,1994.
// Compiler: Borland C++ 3.1 (COMPACT model with byte alignment)
// Notes: Memory map.
//
// --------------------------------------------------------------------------
// Include files ------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <mem.h>
#include <string.h>
// Constants ----------------------------------------------------------------
#define uchar unsigned char
#define ushort unsigned int
#define ulong unsigned long
#define FALSE 0
#define TRUE 1
#define MAX_ITEM 150
#define MAX_VEC 100
#define MAX_DRIVE 20
#define MAX_HANDLE 255
#define MT_NONE 0
#define MT_SYSCODE 1
#define MT_SYSDATA 2
#define MT_PROGRAM 3
#define MT_DEVICE 4
#define MT_ENV 5
#define MT_DATA 6
#define MT_FREE 7
#define MT_MAP 8
#define NORMAL 0
#define UPPER 1
#define USAGE "MAP 2.0, memory map utility, Sulyok Peter (C) 1992,1994.\n" \
"Usage: MAP [-option ...]\n" \
"Options:\n" \
" -n list of programs in normal memory (default)\n" \
" -u list of programs in normal and upper memory\n" \
" -f full list of memory blocks\n" \
" -d list of device drivers\n" \
" -x XMS report\n" \
" -e EMS report\n" \
" -h,? this text"
// Types --------------------------------------------------------------------
// Structure of device driver header.
typedef struct device_header {
struct device_header *next;
ushort attr;
ushort strategy_rutin;
ushort interrupt_rutin;
uchar name[8];
} DEVICE_HEADER;
// Structure of device driver information.
typedef struct {
struct device_header *addr;
uchar devname[9];
uchar progname[9];
ushort attr;
uchar drive_num;
uchar drives[MAX_DRIVE];
} DINFO;
// Structure of DOS DPB.
typedef struct dpb {
uchar drive_num;
uchar unit_number;
ushort bytes_in_sector;
uchar lsec_num;
uchar log_base;
ushort reserved_num;
uchar FAT_num;
ushort rootentry_num;
ushort first_sector;
ushort largest_cluster;
ushort sectors_in_FAT;
ushort root_firstsector;
DEVICE_HEADER *device_addr;
uchar media_desc;
uchar block_flag;
struct dpb *next_dpb;
} DPB;
// Internal structure of DOS DATA blocks.
typedef struct {
uchar type;
ushort start;
ushort size;
uchar unused[3];
uchar name[8];
} SD_HEADER;
// Stucture of MCB header.
typedef struct {
uchar type;
ushort owner;
ushort size;
uchar unused[3];
uchar name[8];
} MCB;
// Structure of programs, device drivers, memory blocks information.
typedef struct {
uchar type;
ushort seg;
ushort owner;
ushort environment;
uchar name[10];
ulong size;
uchar vecnum;
uchar vectors[MAX_VEC];
} MINFO;
// Structure of allocated EMS handles.
typedef struct {
ushort handle;
ushort pages;
} EMS_HANDLE;
// Structure of allocated XMS handles.
typedef struct {
ushort handle;
ulong size;
ushort locks;
} XMS_HANDLE;
// Local variables ----------------------------------------------------------
static uchar copyright[]=
"Sulyok Péter (C) 1992,1994.";
static MCB *first_mcb=NULL;
static MINFO mlist[MAX_ITEM];
static ushort mlistnum=0;
static DEVICE_HEADER *first_dev=NULL;
static DPB *first_dpb=NULL;
static DINFO dlist[MAX_ITEM];
static ushort dlistnum=0;
static uchar *typenames[]=
{
" ",
"system code ",
"system data ",
"program ",
"device driver",
"environment ",
"data area ",
"free ",
};
static uchar ems_installed=FALSE;
static uchar ems_name[]="EMMXXXX0";
static ushort ems_frame=0;
static uchar ems_vermajor=0;
static uchar ems_verminor=0;
static ulong ems_size=0L;
static ulong ems_free=0L;
static ushort ems_totalhandle=0;
static ushort ems_freehandle=0;
static ushort ems_usehandle=0;
static EMS_HANDLE ems_handles[MAX_HANDLE];
static uchar xms_installed=FALSE;
static void far (*xms_drv)(void);
static ulong xms_free=0L;
static ulong xms_largest=0L;
static uchar xms_vermajor=0;
static uchar xms_verminor=0;
static uchar xms_hma=0;
static uchar xms_a20=0;
static XMS_HANDLE xms_handles[MAX_HANDLE];
static ushort xms_usehandle=0;
static ushort xms_freehandle=0;
static uchar upper_installed=FALSE;
static ulong upper_free=0L;
static ulong upper_large=0L;
static ushort upper_index=0;
// Local functions ----------------------------------------------------------
static void check_ems(void);
static void check_xms(void);
static void check_upper(void);
static void check_memory(void);
static uchar get_upperlink(void);
static int set_upperlink(uchar);
static void search_vectors(MINFO *);
static void search_sd(MCB *);
static void register_mcb(MCB *);
static int is_psp(MCB *);
static ushort env_seg(MCB *);
static void make_mcb_list(void);
static void make_dev_list(void);
static void normal_list(uchar type);
static void full_list(void);
static void device_list(void);
static void ems_list(void);
static void xms_list(void);
// --------------------------------------------------------------------------
// Name: check_ems
// Input: -
// Output: -
// Notes: Checks EMS memory and gets EMS parameters.
// --------------------------------------------------------------------------
static void check_ems(void)
{
void far *int67;
int67=(void *)getvect(0x67);
if (int67 == NULL)
return;
asm push ds
asm push si
asm push di
asm les di,int67
asm mov di,10
asm lea si,ems_name
asm mov cx,8
asm cld
asm repe cmpsb
asm pop di
asm pop si
asm pop ds
asm jz _found
return;
_found:
ems_installed=TRUE;
asm mov ah,41h
asm int 67h
asm or ah,ah
asm jnz _error
asm mov ems_frame,bx
asm mov ah,46h
asm int 67h
asm or ah,ah
asm jnz _error
asm mov bl,al
asm and al,0fh
asm and bl,0f0h
asm mov cl,4
asm shr bl,cl
asm mov ems_vermajor,bl
asm mov ems_verminor,al
asm mov ah,42h
asm int 67h
asm or ah,ah
asm jnz _error
asm mov word ptr ems_size,dx
asm mov word ptr ems_size[2],0
asm mov word ptr ems_free,bx
asm mov word ptr ems_free[2],0
ems_size*=16384L;
ems_free*=16384L;
asm push di
_ES=FP_SEG(&ems_handles);
_DI=FP_OFF(&ems_handles);
asm mov ah,4Dh
asm int 67h
asm pop di
asm or ah,ah
asm jnz _error
asm mov ems_usehandle,bx
if (ems_vermajor >= 4) {
asm mov ax,5402h
asm int 67h
asm or ah,ah
asm jnz _error
asm mov ems_totalhandle,bx
} else {
ems_totalhandle=ems_usehandle;
}
ems_freehandle=ems_totalhandle - ems_usehandle;
return;
_error:
puts("EMS INTERNAL ERROR.");
exit(1);
}
// --------------------------------------------------------------------------
// Name: check_xms
// Input: -
// Output: -
// Notes: Checks XMS memory and gets XMS parameters.
// --------------------------------------------------------------------------
static void check_xms(void)
{
asm mov ax,4300h
asm int 2fh
asm cmp al,80h
asm je _found
return;
_found:
xms_installed=TRUE;
asm mov ax,4310h
asm int 2fh
asm mov word ptr xms_drv,bx
asm mov word ptr xms_drv[2],es
asm mov ah,0
(*xms_drv)();
asm mov xms_vermajor,ah
asm mov xms_verminor,al
asm mov xms_hma,dl
asm mov ah,8
(*xms_drv)();
asm mov word ptr xms_free,ax
asm mov word ptr xms_free[2],0
asm mov word ptr xms_largest,dx
asm mov word ptr xms_largest[2],0
xms_free*=1024L;
xms_largest*=1024L;
asm mov ah,7
(*xms_drv)();
asm or bl,bl
asm jnz _error
asm mov xms_a20,al
return;
_error:
puts("XMS INTERNAL ERROR.");
exit(1);
}
// --------------------------------------------------------------------------
// Name: get_upperlink
// Input: -
// Output: uchar 0 separated upper and normal blocks
// 1 linked upper and normal blocks
// Notes: Checks the connection of normal and upper memory blocks.
// --------------------------------------------------------------------------
static uchar get_upperlink(void)
{
asm mov ax,5802h
asm int 21h
return(_AL);
}
// --------------------------------------------------------------------------
// Name: set_upperlink
// Input: uchar link 0 separate it
// 1 link it
// Output: int 1 successful
// 0 there is no upper memory
// -1 system memory is trashed
// Notes: Set the connection between upper and normal memory
// blocks.
// --------------------------------------------------------------------------
static int set_upperlink(uchar link)
{
asm mov ax,5803h
asm xor bh,bh
asm mov bl,link
asm int 21h
asm jc _noumb
return(1);
_noumb:
asm cmp ax,1
asm jne _trash
return(0);
_trash:
return(-1);
}
// --------------------------------------------------------------------------
// Name: check_upper
// Input: -
// Output: -
// Notes: Checks upper memory.
// --------------------------------------------------------------------------
static void check_upper(void)
{
uchar origlink;
origlink=get_upperlink();
switch(set_upperlink(1)) {
case 1:
upper_installed=TRUE;
break;
case 0:
upper_installed=FALSE;
break;
case -1:
puts("SYSTEM MEMORY TRASHED!");
exit(1);
break;
}
set_upperlink(origlink);
}
// --------------------------------------------------------------------------
// Name: check_memory
// Input: -
// Output: -
// Notes: Checks EMS, XMS, upper memory.
// --------------------------------------------------------------------------
static void check_memory(void)
{
check_ems();
check_xms();
check_upper();
}
// --------------------------------------------------------------------------
// Name: is_psp
// Input: MCB *mcb address of the MSC structure
// Output: int TRUE it is a program
// FALSE it is a simple MCB block
// Notes: Checks the PSP of given MCB block.
// --------------------------------------------------------------------------
static int is_psp(MCB *mcb)
{
asm les bx,mcb
asm mov ax,es
asm inc ax
asm mov es,ax
asm mov ax,TRUE
asm cmp word ptr es:[bx],20CDh
asm je __exit
asm mov ax,FALSE
__exit:
return(_AX);
}
// --------------------------------------------------------------------------
// Name: env_seg
// Input: MCB *mcb address of MCB block
// Output: ushort segment of enviroment
// Notes: Returns the segment of the given MCB block.
// --------------------------------------------------------------------------
static ushort env_seg(MCB *mcb)
{
MCB *env;
asm les bx,mcb
asm mov ax,es
asm inc ax
asm mov es,ax
asm mov bx,ax
asm mov ax,es:[2Ch]
asm dec ax
asm mov es,ax
asm inc ax
asm cmp es:[1],bx
asm je __exit
asm mov ax,0
__exit:
return(_AX);
}
// --------------------------------------------------------------------------
// Name: search_vectors
// Input: MINFO *m address of a memory block
// Output: -
// Notes: Searches interrupt vectors of the given memory block.
// --------------------------------------------------------------------------
static void search_vectors(MINFO *m)
{
ushort i;
ulong begin, end, iv;
uchar far *ivp;
begin=(ulong)(m->seg + 1) << 4;
end=begin + m->size;
for(i=0; i<256; i++) {
memcpy(&ivp, MK_FP(0, i*4), 4);
iv=((ulong)(FP_SEG(ivp) + 1) << 4) + (ulong)FP_OFF(ivp);
if ((iv > begin) && (iv < end) && (m->vecnum < MAX_VEC))
m->vectors[m->vecnum++]=(uchar)i;
}
}
// --------------------------------------------------------------------------
// Name: search_sd
// Input: MCB *mcb address of MCB block
// Output: -
// Notes: Searches the internal parts of a DOS data block.
// --------------------------------------------------------------------------
static void search_sd(MCB *mcb)
{
ushort begin, end;
SD_HEADER *sd;
sd=MK_FP(FP_SEG(mcb) + 1, 0);
begin=FP_SEG(mcb);
end=FP_SEG(mcb) + mcb->size;
while((FP_SEG(sd) > begin) &&
(FP_SEG(sd) < end) &&
(mlistnum < MAX_ITEM)) {
mlistnum++;
mlist[mlistnum].seg=sd->start;
mlist[mlistnum].size=(ulong)sd->size << 4;
switch(sd->type) {
case 'D':
case 'I':
mlist[mlistnum].name[0]=' ';
strncpy(&mlist[mlistnum].name[1], sd->name, 8);
strupr(mlist[mlistnum].name);
mlist[mlistnum].type=MT_DEVICE;
break;
case 'F':
strcpy(mlist[mlistnum].name, " FILES");
mlist[mlistnum].type=MT_DATA;
break;
case 'X':
strcpy(mlist[mlistnum].name, " FCBS");
mlist[mlistnum].type=MT_DATA;
break;
case 'C':
case 'B':
strcpy(mlist[mlistnum].name, " BUFFERS");
mlist[mlistnum].type=MT_DATA;
break;
case 'L':
strcpy(mlist[mlistnum].name, " LASTDRV");
mlist[mlistnum].type=MT_DATA;
break;
case 'S':
strcpy(mlist[mlistnum].name, " STACKS");
mlist[mlistnum].type=MT_DATA;
break;
default:
strcpy(mlist[mlistnum].name, " ??????");
mlist[mlistnum].type=MT_DATA;
break;
}
sd=MK_FP(sd->start + sd->size, 0);
}
}
// --------------------------------------------------------------------------
// Name: check_name
// Input: uchar *name name of MCB or device driver
// Output: -
// Notes: Filters name of MCBs and device drivers.
// --------------------------------------------------------------------------
void check_name(uchar *name)
{
ushort i;
for(i=0; name[i]; i++)
if ( name[i] < ' ' ) {
name[i] = '\0';
break;
} // if
}
// --------------------------------------------------------------------------
// Name: register_mcb
// Input: MCB *mcb address of MCB block
// Output: -
// Notes: Registers parameters of the given MCB block.
// --------------------------------------------------------------------------
static void register_mcb(MCB *mcb)
{
mlist[mlistnum].seg=FP_SEG(mcb);
mlist[mlistnum].owner=mcb->owner;
mlist[mlistnum].size=(ulong)mcb->size << 4;
if (mlist[mlistnum].seg <= 0x9FFF) {
if (is_psp(mcb)) {
strncpy(mlist[mlistnum].name, mcb->name, 8);
check_name(mlist[mlistnum].name);
strupr(mlist[mlistnum].name);
mlist[mlistnum].environment=env_seg(mcb);
mlist[mlistnum].type=MT_PROGRAM;
}
if (!mcb->owner) {
mlist[mlistnum].type=MT_FREE;
} else if (mcb->owner <= 0x0008) {
strcpy(mlist[mlistnum].name, "DOS");
if (!strncmp(mcb->name, "SD", 2)) {
mlist[mlistnum].type=MT_SYSDATA;
search_sd(mcb);
} else if (!strncmp(mcb->name, "SC", 2)) {
mlist[mlistnum].type=MT_SYSCODE;
}
else
mlist[mlistnum].type=MT_SYSCODE;
}
} else {
if (!mcb->owner) {
mlist[mlistnum].type=MT_FREE;
} else if (mcb->owner <= 0x0008) {
strcpy(mlist[mlistnum].name, "DOS");
if (!strncmp(mcb->name, "SD", 2)) {
mlist[mlistnum].type=MT_SYSDATA;
search_sd(mcb);
} else if (!strncmp(mcb->name, "SC", 2)) {
mlist[mlistnum].type=MT_SYSCODE;
}
} else if (mcb->owner > 0x0008) {
mlist[mlistnum].environment=env_seg(mcb);
mlist[mlistnum].type=MT_PROGRAM;
strncpy(mlist[mlistnum].name, mcb->name, 8);
strupr(mlist[mlistnum].name);
}
}
}
// --------------------------------------------------------------------------
// Name: make_mcb_list
// Input: -
// Output: -
// Notes: Makes the list of MCBs.
// --------------------------------------------------------------------------
static void make_mcb_list(void)
{
ushort i, j;
MCB *cur_mcb;
uchar origlink;
memset(mlist, 0, sizeof(mlist));
check_memory();
asm mov ah,52h
asm int 21h
asm mov ax,es:[bx-2]
asm mov word ptr first_mcb[2],ax
asm mov word ptr first_mcb,0
if (upper_installed) {
origlink=get_upperlink();
set_upperlink(1);
}
cur_mcb=(MCB *)MK_FP(first_mcb, 0);
while((mlistnum < MAX_ITEM) && (cur_mcb->type != 'Z')) {
register_mcb(cur_mcb);
cur_mcb=(MCB *)MK_FP(FP_SEG(cur_mcb) + cur_mcb->size + 1, 0);
++mlistnum;
}
register_mcb(cur_mcb);
cur_mcb=(MCB *)MK_FP(FP_SEG(cur_mcb) + cur_mcb->size + 1, 0);
++mlistnum;
if (upper_installed)
set_upperlink(origlink);
for(i=0; i<mlistnum; i++)
if ( (mlist[i].seg >= 0x9000) && (mlist[i].seg <= 0xB000) &&
(mlist[i].type == MT_SYSCODE) ) {
upper_index=i;
break;
}
for(i=upper_index; i<mlistnum; i++)
if (mlist[i].type == MT_FREE) {
upper_free+=mlist[i].size;
if (mlist[i].size > upper_large)
upper_large=mlist[i].size;
}
for(i=0; i<mlistnum; i++) {
if (mlist[i].type == MT_PROGRAM)
for(j=0; j<mlistnum; j++)
if ((mlist[i].seg != mlist[j].seg) &&
(mlist[j].owner == mlist[i].seg+1)) {
strcpy(mlist[j].name, mlist[i].name);
mlist[j].type=(mlist[i].environment == mlist[j].seg+1) ? MT_ENV : MT_DATA;
}
if (mlist[i].type != MT_SYSDATA)
search_vectors(&mlist[i]);
}
for(i=0; i<mlistnum; i++)
if (mlist[i].seg+1 == _psp) {
mlist[i+1].size+=mlist[i].size + 16;
mlist[i].type=MT_MAP;
for(j=0; j<mlistnum; j++)
if (mlist[j].seg+1 == mlist[i].environment) {
if (j == i-1) {
mlist[j].type=MT_MAP;
} else {
mlist[j].type=MT_FREE;
mlist[j].name[0]='\0';
}
break;
}
break;
}
}
// --------------------------------------------------------------------------
// Name: make_dev_list
// Input: -
// Output: -
// Notes: Makes list of device drivers.
// --------------------------------------------------------------------------
static void make_dev_list(void)
{
ushort i, j;
DEVICE_HEADER *cur_dev;
DPB *cur_dpb;
memset(dlist, 0, sizeof(dlist));
make_mcb_list();
asm mov ah,52h
asm int 21h
asm add bx,22h
asm mov word ptr first_dev[2],es
asm mov word ptr first_dev,bx
cur_dev=first_dev;
while((FP_OFF(cur_dev) != 0xFFFF) &&
(dlistnum < MAX_ITEM)) {
dlist[dlistnum].addr=cur_dev;
dlist[dlistnum].attr=cur_dev->attr;
strncpy(dlist[dlistnum].devname, cur_dev->name, 8);
check_name(dlist[dlistnum].devname);
strupr(dlist[dlistnum].devname);
cur_dev=cur_dev->next;
++dlistnum;
}
for(i=0; i<dlistnum; i++)
for(j=0; j<mlistnum; j++)
if (mlist[j].seg == FP_SEG(dlist[i].addr))
strcpy(dlist[i].progname, (mlist[j].name[0] == ' ') ?
&mlist[j].name[1] : mlist[j].name);
asm mov ah,52h
asm int 21h
asm les bx,es:[bx]
asm mov word ptr first_dpb[2],es
asm mov word ptr first_dpb,bx
cur_dpb=first_dpb;
while(FP_OFF(cur_dpb) != 0xFFFF) {
for(i=0; i<dlistnum; i++)
if (dlist[i].addr == cur_dpb->device_addr) {
dlist[i].drives[dlist[i].drive_num++]=cur_dpb->drive_num+'A';
break;
}
cur_dpb=cur_dpb->next_dpb;
}
for(i=0; i<dlistnum; i++) {
if ((dlist[i].attr & 0x8000) == 0)
dlist[i].devname[0]='\0';
if (dlist[i].drive_num) {
if (dlist[i].drive_num == 1)
sprintf(dlist[i].devname, "%c:", dlist[i].drives[0]);
else
sprintf(dlist[i].devname, "%c: - %c:", dlist[i].drives[0],
dlist[i].drives[dlist[i].drive_num-1]);
}
}
}
// --------------------------------------------------------------------------
// Name: normal_list
// Input: uchar type type of list
// Output: -
// Notes: Displays the normal list of programs.
// --------------------------------------------------------------------------
static void normal_list(uchar type)
{
ushort i, num;
make_mcb_list();
puts("┌───────────────────────────────────────────┐");
puts("│ mcb size name type │");
puts("├──────┬────────┬───────────┬───────────────┤");
num=(upper_installed && (type == NORMAL)) ? upper_index : mlistnum;
for(i=0; i<num; i++)
if ((mlist[i].type == MT_SYSCODE) ||
(mlist[i].type == MT_SYSDATA) ||
(mlist[i].type == MT_FREE) ||
(mlist[i].type == MT_PROGRAM) ||
(mlist[i].type == MT_DEVICE))
printf("│ %04x │ %6lu │ %-9s │ %-13s │\n",
mlist[i].seg, mlist[i].size, mlist[i].name,
typenames[mlist[i].type]);
if (!ems_installed && !xms_installed && !upper_installed) {
puts("└──────┴────────┴───────────┴───────────────┘");
return;
}
puts("├──────┴────────┴───────────┴───────────────┤");
if (ems_installed)
printf("│ %8lu bytes free EMS memory │\n", ems_free);
if (xms_installed)
printf("│ %8lu bytes free XMS memory │\n", xms_free);
if (upper_installed)
printf("│ %8lu bytes free upper memory │\n", upper_free);
puts("└───────────────────────────────────────────┘");
}
// --------------------------------------------------------------------------
// Name: full_list
// Input: -
// Output: -
// Notes: Displays full list of memory blocks.
// --------------------------------------------------------------------------
static void full_list(void)
{
ushort i, j, pos;
uchar line[81];
make_mcb_list();
puts("┌────────────────────────────────────────────────────────────────────────┐");
puts("│ mcb size name type interrupt vectors │");
puts("├──────┬────────┬───────────┬───────────────┬────────────────────────────┤");
for(i=0; i<mlistnum; i++)
if (mlist[i].type != MT_MAP) {
sprintf(line, "│ %04x │ %6lu │ %-9s │ %-4s │ │",
mlist[i].seg, mlist[i].size, mlist[i].name,
typenames[mlist[i].type]);
for(j=1, pos=46; j<=mlist[i].vecnum; j++) {
sprintf(&line[pos], "%02x", (int)mlist[i].vectors[j-1]);
line[pos+2]=' ';
if (!(j % 9) && ((j+1) <= mlist[i].vecnum)) {
puts(line);
strcpy(line, "│ │ │ │ │ │");
pos=46;
} else {
pos+=3;
}
}
puts(line);
}
puts("└──────┴────────┴───────────┴───────────────┴────────────────────────────┘");
}
// --------------------------------------------------------------------------
// Name: device_list
// Input: -
// Output: -
// Notes: Display the list of device drivers.
// --------------------------------------------------------------------------
static void device_list(void)
{
ushort i, num;
make_dev_list();
puts("┌────────────────────────────────────────┐");
puts("│ address attr name program │");
puts("├───────────┬──────┬──────────┬──────────┤");
// XXXX:XXXX XXXX XXXXXXXX XXXXXXXX
for(i=0; i<dlistnum; i++)
printf("│ %Fp │ %04x │ %-8s │ %-8s │\n",
dlist[i].addr, dlist[i].attr, dlist[i].devname,
dlist[i].progname);
puts("└───────────┴──────┴──────────┴──────────┘");
}
// --------------------------------------------------------------------------
// Name: ems_list
// Input: -
// Output: -
// Notes: Displays the EMS report.
// --------------------------------------------------------------------------
static void ems_list(void)
{
ushort i;
uchar *line, numstr[20];
uchar handlename[9];
check_ems();
puts("┌─────────────────────────────────────┐");
if (!ems_installed) {
puts("│ EMS driver not installed in system. │");
} else {
line="│ EMS driver version │";
sprintf(numstr, "%1i.%1i", (int)ems_vermajor, (int)ems_verminor);
strncpy(&line[22], numstr, strlen(numstr));
puts(line);
line="│ EMS page frame │";
sprintf(numstr, "%04X", ems_frame);
strncpy(&line[22], numstr, strlen(numstr));
puts(line);
line="│ Total EMS memory │";
sprintf(numstr, "%lu bytes", ems_size);
strncpy(&line[22], numstr, strlen(numstr));
puts(line);
line="│ Free EMS memory │";
sprintf(numstr, "%lu bytes", ems_free);
strncpy(&line[22], numstr, strlen(numstr));
puts(line);
line="│ Total handles │";
sprintf(numstr, "%u", ems_totalhandle);
strncpy(&line[22], numstr, strlen(numstr));
puts(line);
line="│ Free handles │";
sprintf(numstr, "%u", ems_freehandle);
strncpy(&line[22], numstr, strlen(numstr));
puts(line);
puts("│ │");
puts("│ Handle Pages Size Name │");
puts("│ ─────────────────────────────────── │");
for(i=0; i<ems_usehandle; i++) {
memset(handlename, 0, sizeof(handlename));
if (ems_vermajor >= 4) {
if (ems_handles[i].handle == 0) {
strcpy(handlename, "SYSTEM");
} else {
asm push di
_DX=ems_handles[i].handle;
_ES=FP_SEG(&handlename);
_DI=FP_OFF(&handlename);
asm mov ax,5300h
asm int 67h
asm pop di
}
strupr(handlename);
}
printf("│ %-7u %-6u %-9lu %-9s │\n",
ems_handles[i].handle, ems_handles[i].pages,
(ulong)ems_handles[i].pages * 16384L, handlename);
}
}
puts("└─────────────────────────────────────┘");
}
// --------------------------------------------------------------------------
// Name: xms_list
// Input: -
// Output: -
// Notes: Displays the XMS report.
// --------------------------------------------------------------------------
static void xms_list(void)
{
ushort i;
uchar *line, numstr[20];
make_mcb_list();
if (xms_installed) {
printf("Testing XMS memory ...");
memset(xms_handles, 0, sizeof(xms_handles));
xms_usehandle=0;
for(i=0; i<65535; i++) {
asm mov ah,0Eh
_DX=i;
(*xms_drv)();
asm or ax,ax
asm jnz _found
continue;
_found:
asm mov byte ptr xms_freehandle,bl
if (xms_usehandle < MAX_HANDLE) {
asm push di
_ES=FP_SEG(&xms_handles);
_DI=FP_OFF(&xms_handles);
asm mov ax,xms_usehandle // xms_handles[xms_usehandle].handle=i;
asm mov cl,3
asm shl ax,cl
asm add di,ax
asm mov ax,i
asm mov es:[di],ax
asm mov es:[di+2],dx // xms_handles[xms_usehandle].size=_DX;
asm mov es:[di+6],bh // xms_handles[xms_usehandle].locks=_BH;
asm pop di
xms_handles[xms_usehandle].size*=1024L;
xms_usehandle++;
}
}
printf("\r");
}
puts("┌────────────────────────────────────────┐");
if (!xms_installed) {
puts("│ XMS driver not installed in system. │");
} else {
line="│ XMS driver version │";
sprintf(numstr, "%i.%i", (ushort)xms_vermajor, (ushort)xms_verminor);
strncpy(&line[26], numstr, strlen(numstr));
puts(line);
line="│ HMA state │";
sprintf(numstr, "%s", (xms_hma) ? "exists" : "not exists");
strncpy(&line[26], numstr, strlen(numstr));
puts(line);
line="│ A20 line state │";
sprintf(numstr, "%s", (xms_a20) ? "enabled" : "disabled");
strncpy(&line[26], numstr, strlen(numstr));
puts(line);
line="│ Free XMS memory │";
sprintf(numstr, "%lu bytes", xms_free);
strncpy(&line[26], numstr, strlen(numstr));
puts(line);
line="│ Largest free XMS block │";
sprintf(numstr, "%lu bytes", xms_largest);
strncpy(&line[26], numstr, strlen(numstr));
puts(line);
line="│ Free handles │";
sprintf(numstr, "%u", xms_freehandle);
strncpy(&line[26], numstr, strlen(numstr));
puts(line);
if (xms_usehandle) {
puts("│ │");
puts("│ Block Handle Size Locks │");
puts("│ ────────────────────────────────────── │");
for(i=0; i<xms_usehandle; i++)
printf("│ %-6u %-7u %-9lu %-12u │\n",
i, xms_handles[i].handle, xms_handles[i].size,
xms_handles[i].locks);
}
puts("│ │");
if (upper_installed) {
line="│ Free upper memory │";
sprintf(numstr, "%lu bytes", upper_free);
strncpy(&line[26], numstr, strlen(numstr));
puts(line);
line="│ Largest upper block │";
sprintf(numstr, "%lu bytes", upper_large);
strncpy(&line[26], numstr, strlen(numstr));
puts(line);
} else {
puts("│ Upper memory not available │");
}
}
puts("└────────────────────────────────────────┘");
}
// Main ---------------------------------------------------------------------
int main(int argc, char *argv[])
{
ushort i;
if ( (_osmajor != 5) && (_osmajor != 6 ) ) {
puts("This program runs under DOS 5.x or 6.x versions.");
return 1;
}
if (argc > 1) {
for(i=1; i<argc; i++) {
if ((argv[i][0] == '-') || (argv[i][0] == '/'))
switch( argv[i][1] ) {
case 'n':
case 'N':
normal_list(NORMAL);
break;
case 'u':
case 'U':
normal_list(UPPER);
break;
case 'f':
case 'F':
full_list();
break;
case 'd':
case 'D':
device_list();
break;
case 'e':
case 'E':
ems_list();
break;
case 'x':
case 'X':
xms_list();
break;
case 'h':
case 'H':
case '?':
puts(USAGE);
return 0;
default:
printf("Invalid option %s (use -h for help).\n", argv[i]);
return 1;
}
else {
printf("Invalid option %s (use -h for help).\n", argv[i]);
return 1;
}
}
} else {
normal_list(NORMAL);
}
return 0;
}
// End ----------------------------------------------------------------------