home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
CPM3
/
RSXMAP.LBR
/
RSXMAP.CZ
/
RSXMAP.C
Wrap
Text File
|
2000-06-30
|
8KB
|
281 lines
/*************************************************************************
** RSXMAP RSXMAP RSXMAP RSXMAP RSXMAP RSXMAP RSXMAP RSXMAP **
** **
** This little program is used to display the current dynamic **
** memory map of a CP/M Plus (3.x) system. It shows the amount **
** of Transient Program Area (TPA) memory that is available. **
** Next, each each installed RSX is shown by displaying its **
** load address, name and size in pages. **
** **
** There is currently a problem when using RSXMAP as a command **
** in a multiple command line, i.e.: **
** A>rsxmap ! dir **
** In this example the "dir" command is stored by the CCP as a **
** quick & dirty RSX while the RSXMAP is being run. The 1k size **
** of the RSX is correct BUT the name is GARBAGE!! **
** Jim Lopushinsky of the Meadowlark RCPM expects to have a fix **
** for this in the next release of his CCP+. **
** **
** This program was developed under Manx Aztec C version 1.06D **
** **
** Developed by Sparrow Software Version 1.00 **
** Released into the Public Domain 10 Feb 1986 **
** **
** Jim Dunn **
** Sparrow Software **
** 30 Birch Lane **
** Fairport, NY 14450 **
** **
** Sparrow RCPM: (716) 377-1113 [300/1200/2400 bps] **
** Voice: (716) 377-7036 **
** CompuServe: 70245,170 **
*************************************************************************/
#include <stdio.h>
#define SML_STR 20 /* bytes in a small string */
#define MAX_RSX 20 /* maximum expected amount of RSXes */
int
i,j,k, /* my favorite 3 little worker ints */
ver, /* CP/M version variable */
lhv, /* last high value, used in RSX size calc */
rsxct, /* RSX counter variable */
oc, /* output counter (inverse of above) */
*nextp, /* pointer to next RSX header - initial */
*nrsxp, /* pointer to next RSX header - result */
*biosp, /* BIOS pointer */
*bdosp; /* BDOS pointer */
long
li; /* long integer needed for TPA size */
char
gof[SML_STR], /* gofer char array */
str[SML_STR], /* another char array */
*cp; /* general purpose char pointer */
/* Let's make a new data type to hold RSX info */
typedef struct {
char
addr[4+1], /* RSX address */
name[8+1]; /* RSX name */
} RSXREC;
RSXREC /* array of pointers to RSX records */
*rsxary[MAX_RSX];
int
bdos(), /* returns an int */
isrsx(); /* returns an int */
char
*strncpy(), /* returns a pointer to a char */
*malloc(); /* returns a pointer to a char */
void
exit(), /* returns nothing */
storrsx(); /* returns absolutely nothing (like my dog) */
main()
{
/****************************************************************/
/********** Let's see what version of CP/M we are riding on */
/***** BDOS function 12 */
i = bdos(12, 0);
/***** Quick and Dirty hex to decimal conversion */
sprintf(str, "%04x", i);
sscanf(str, "%d", &ver);
/***** Split tens and ones to insert decimal point */
i = ver / 10;
j = ver - (i * 10);
/***** Exit if not running under CP/M Plus */
if (i != 3) {
printf("This will only work under CP/M Plus\n");
exit(1);
}
/****************************************************************/
/********** Now let's display the TPA size */
/********** This BDOS pointer will point to the begining of */
/********** any and all installed RSXes, so it will show the */
/********** current TPA, not the "ideal" TPA */
/***** Get value at 0006H, subtract 3 words (6 bytes) */
/***** Assign to BDOS pointer */
bdosp = (int *) (*(int *)6) - 3;
/***** Subtract the CP/M base page from the TPA */
li = ((long)bdosp) - (long)256;
/***** Now its time to display these values */
printf("CP/M Version %d.%d", i,j);
printf(" TPA is %ld bytes\n", li);
printf("==================================================\n");
/****************************************************************/
/********** Where is the BIOS entry table */
/***** Get value at 0001H, assign to BIOS pointer */
biosp = (int *) (*(int *)1);
/***** Subtract 3 bytes to get to page boundary */
biosp = (int *) (((char *) biosp) - 3);
/***** Last high value (lvh) holds the current high map address */
/***** it is used to calculate the difference between it and */
/***** bottom (begining) of the next RSX. */
lhv = (int) biosp;
/***** Convert to upper case hex value and display it */
sprintf(gof, "%04x", biosp);
for (cp = gof; *cp != '\0'; ++cp) {
*cp = (char)toupper(*cp);
}
printf("BIOS entry at %s\n", gof);
/****************************************************************/
/********** Let's find the lowest (last) RSX */
/***** Get value at 0006H, subtract 3 words (6 bytes) */
/***** Assign to BDOS pointer */
bdosp = (int *) (*(int *)6) - 3;
/***** Move from the serial entry point to the start entry */
/***** point by adding 3 words (6 bytes) */
nextp = bdosp + 3;
/***** cycle through the RSXes till we hit the BDOS */
/***** each RSX has its information stored via storrsx() */
while ((nrsxp = (int *) isrsx(nextp)) != 0) {
storrsx(nextp, rsxct);
++rsxct;
nextp = nrsxp;
}
/****************************************************************/
/***** This must now be the real BDOS entry */
/***** Get some heap storage for the BDOS record */
/***** Backup by 6 bytes for the top of the page (xx00H) */
/***** Convert first 2 charcters to upper case */
if ((rsxary[rsxct] = malloc(sizeof(RSXREC))) == NULL) {
printf("malloc says:: out of memory!\n");
exit(1);
}
else {
sprintf(rsxary[rsxct]->addr, "%04x", ((int)nextp) - 6);
rsxary[rsxct]->addr[0] = (char)toupper(rsxary[rsxct]->addr[0]);
rsxary[rsxct]->addr[1] = (char)toupper(rsxary[rsxct]->addr[1]);
}
/****************************************************************/
/***** time to display the upside down rsx table */
for (i = rsxct, oc = 0; i >= 0; --i, ++oc) {
/* Convert hex addr string into integer k */
sscanf(rsxary[i]->addr, "%4x", &k);
/* Subtract this current RSX address from last */
/* high value and covert into 256 byte pages */
j = (lhv - k) / 256;
/*Iif (i == rsxct) then we are at BDOS entry */
if (i == rsxct)
printf("BDOS entry at %s and is %2d pages\n",
rsxary[i]->addr, j);
else {
printf("RSX %2d) is at %s and is %2d pages named %s\n",
oc, rsxary[i]->addr, j, rsxary[i]->name);
}
/* Move current RSX address into last high value */
/* for next cycle. */
lhv = k;
}
printf("==================================================\n");
return(0);
}
int
isrsx(upp)
int
*upp;
{
/***** We try to decide if this is an RSX by looking 9 bytes */
/***** past the start entry point. If in an RSX this is the */
/***** non-bank flag which will either be 00H or FFH. If we */
/***** made it all the way to the BDOS, this byte will be a */
/***** C3H jump command to whatever. */
if (((char *)upp)[9] == 0xc3)
return (0);
else
/***** return with an integer value which is actually a pointer */
/***** to the next RSX. This value is obtained by moving */
/***** 4 bytes up from the start entry point. */
return (upp[2]);
}
void
storrsx(upp, ct)
int
*upp, /* pointer to next high RSX */
ct; /* RSX count */
{
/***** get someheap storage and store RSX record */
/***** Backup by 6 bytes for the top of the page (xx00H) */
/***** Move address hex value into RSX record */
/***** Move name into RSX record and delimit end of string */
/***** Convert first 2 charcters to upper case */
if ((rsxary[ct] = malloc(sizeof(RSXREC))) == NULL) {
printf("malloc says:: out of memory!\n");
exit(1);
}
else {
sprintf(rsxary[ct]->addr, "%04x", (int)upp - 6);
strncpy(rsxary[ct]->name, (char *)upp + 10, 8);
rsxary[ct]->name[8] = '\0';
rsxary[ct]->addr[0] = (char)toupper(rsxary[ct]->addr[0]);
rsxary[ct]->addr[1] = (char)toupper(rsxary[ct]->addr[1]);
}
}