home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************
- ** 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]);
- }
- }