Update the dcc tools code
This commit is contained in:
@@ -1 +1,300 @@
|
||||
#include "TPL_PatternCollector.h"
|
||||
#include <cstring>
|
||||
|
||||
/** \note Fundamental problem: there seems to be no information linking the names
|
||||
in the system unit ("V" category) with their routines, except trial and
|
||||
error. I have entered a few. There is no guarantee that the same pmap
|
||||
offset will map to the same routine in all versions of turbo.tpl. They
|
||||
seem to match so far in version 4 and 5.0 */
|
||||
|
||||
|
||||
#define roundUp(w) ((w + 0x0F) & 0xFFF0)
|
||||
extern void fixWildCards(uint8_t pat[]);
|
||||
void TPL_PatternCollector::enterSym(FILE *f, const char *name, uint16_t pmapOffset)
|
||||
{
|
||||
uint16_t pm, cm, codeOffset, pcode;
|
||||
uint16_t j;
|
||||
|
||||
/* Enter a symbol with given name */
|
||||
allocSym(count);
|
||||
strcpy(keys[count].name, name);
|
||||
pm = pmap + pmapOffset; /* Pointer to the 4 byte pmap structure */
|
||||
fseek(f, unitBase+pm, SEEK_SET);/* Go there */
|
||||
cm = readShort(f); /* CSeg map offset */
|
||||
codeOffset = readShort(f); /* How far into the code segment is our rtn */
|
||||
j = cm / 8; /* Index into the cmap array */
|
||||
pcode = csegBase+csegoffs[j]+codeOffset;
|
||||
fseek(f, unitBase+pcode, SEEK_SET); /* Go there */
|
||||
grab(f,PATLEN); /* Grab the pattern to buf[] */
|
||||
fixWildCards(buf); /* Fix the wild cards */
|
||||
memcpy(keys[count].pat, buf, PATLEN); /* Copy to the key array */
|
||||
count++; /* Done one more */
|
||||
}
|
||||
|
||||
void TPL_PatternCollector::allocSym(int count)
|
||||
{
|
||||
keys.resize(count);
|
||||
}
|
||||
|
||||
void TPL_PatternCollector::readCmapOffsets(FILE *f)
|
||||
{
|
||||
uint16_t cumsize, csize;
|
||||
uint16_t i;
|
||||
|
||||
/* Read the cmap table to find the start address of each segment */
|
||||
fseek(f, unitBase+cmap, SEEK_SET);
|
||||
cumsize = 0;
|
||||
csegIdx = 0;
|
||||
for (i=cmap; i < pmap; i+=8)
|
||||
{
|
||||
readShort(f); /* Always 0 */
|
||||
csize = readShort(f);
|
||||
if (csize == 0xFFFF) continue; /* Ignore the first one... unit init */
|
||||
csegoffs[csegIdx++] = cumsize;
|
||||
cumsize += csize;
|
||||
grab(f,4);
|
||||
}
|
||||
}
|
||||
|
||||
void TPL_PatternCollector::enterSystemUnit(FILE *f)
|
||||
{
|
||||
/* The system unit is special. The association between keywords and
|
||||
pmap entries is not stored in the .tpl file (as far as I can tell).
|
||||
So we hope that they are constant pmap entries.
|
||||
*/
|
||||
|
||||
fseek(f, 0x0C, SEEK_SET);
|
||||
cmap = readShort(f);
|
||||
pmap = readShort(f);
|
||||
fseek(f, offStCseg, SEEK_SET);
|
||||
csegBase = roundUp(readShort(f)); /* Round up to next 16 bdry */
|
||||
printf("CMAP table at %04X\n", cmap);
|
||||
printf("PMAP table at %04X\n", pmap);
|
||||
printf("Code seg base %04X\n", csegBase);
|
||||
|
||||
readCmapOffsets(f);
|
||||
|
||||
enterSym(f,"INITIALISE", 0x04);
|
||||
enterSym(f,"UNKNOWN008", 0x08);
|
||||
enterSym(f,"EXIT", 0x0C);
|
||||
enterSym(f,"BlockMove", 0x10);
|
||||
unknown(f,0x14, 0xC8);
|
||||
enterSym(f,"PostIO", 0xC8);
|
||||
enterSym(f,"UNKNOWN0CC", 0xCC);
|
||||
enterSym(f,"STACKCHK", 0xD0);
|
||||
enterSym(f,"UNKNOWN0D4", 0xD4);
|
||||
enterSym(f,"WriteString", 0xD8);
|
||||
enterSym(f,"WriteInt", 0xDC);
|
||||
enterSym(f,"UNKNOWN0E0", 0xE0);
|
||||
enterSym(f,"UNKNOWN0E4", 0xE4);
|
||||
enterSym(f,"CRLF", 0xE8);
|
||||
enterSym(f,"UNKNOWN0EC", 0xEC);
|
||||
enterSym(f,"UNKNOWN0F0", 0xF0);
|
||||
enterSym(f,"UNKNOWN0F4", 0xF4);
|
||||
enterSym(f,"ReadEOL", 0xF8);
|
||||
enterSym(f,"Read", 0xFC);
|
||||
enterSym(f,"UNKNOWN100", 0x100);
|
||||
enterSym(f,"UNKNOWN104", 0x104);
|
||||
enterSym(f,"PostWrite", 0x108);
|
||||
enterSym(f,"UNKNOWN10C", 0x10C);
|
||||
enterSym(f,"Randomize", 0x110);
|
||||
unknown(f,0x114, 0x174);
|
||||
enterSym(f,"Random", 0x174);
|
||||
unknown(f,0x178, 0x1B8);
|
||||
enterSym(f,"FloatAdd", 0x1B8); /* A guess! */
|
||||
enterSym(f,"FloatSub", 0x1BC); /* disicx - dxbxax -> dxbxax*/
|
||||
enterSym(f,"FloatMult", 0x1C0); /* disicx * dxbxax -> dxbxax*/
|
||||
enterSym(f,"FloatDivide", 0x1C4); /* disicx / dxbxax -> dxbxax*/
|
||||
enterSym(f,"UNKNOWN1C8", 0x1C8);
|
||||
enterSym(f,"DoubleToFloat",0x1CC); /* dxax to dxbxax */
|
||||
enterSym(f,"UNKNOWN1D0", 0x1D0);
|
||||
enterSym(f,"WriteFloat", 0x1DC);
|
||||
unknown(f,0x1E0, 0x200);
|
||||
|
||||
}
|
||||
|
||||
void TPL_PatternCollector::readString(FILE *f)
|
||||
{
|
||||
uint8_t len;
|
||||
|
||||
len = readByte(f);
|
||||
grab(f,len);
|
||||
buf[len] = '\0';
|
||||
}
|
||||
|
||||
void TPL_PatternCollector::unknown(FILE *f, unsigned j, unsigned k)
|
||||
{
|
||||
/* Mark calls j to k (not inclusive) as unknown */
|
||||
unsigned i;
|
||||
|
||||
for (i=j; i < k; i+= 4)
|
||||
{
|
||||
sprintf((char *)buf, "UNKNOWN%03X", i);
|
||||
enterSym(f,(char *)buf, i);
|
||||
}
|
||||
}
|
||||
|
||||
void TPL_PatternCollector::nextUnit(FILE *f)
|
||||
{
|
||||
/* Find the start of the next unit */
|
||||
|
||||
uint16_t dsegBase, sizeSyms, sizeOther1, sizeOther2;
|
||||
|
||||
fseek(f, unitBase+offStCseg, SEEK_SET);
|
||||
dsegBase = roundUp(readShort(f));
|
||||
sizeSyms = roundUp(readShort(f));
|
||||
sizeOther1 = roundUp(readShort(f));
|
||||
sizeOther2 = roundUp(readShort(f));
|
||||
|
||||
unitBase += dsegBase + sizeSyms + sizeOther1 + sizeOther2;
|
||||
|
||||
fseek(f, unitBase, SEEK_SET);
|
||||
if (fread(buf, 1, 4, f) == 4)
|
||||
{
|
||||
buf[4]='\0';
|
||||
printf("Start of unit: found %s\n", buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TPL_PatternCollector::setVersionSpecifics()
|
||||
{
|
||||
|
||||
version = buf[3]; /* The x of TPUx */
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case '0': /* Version 4.0 */
|
||||
offStCseg = 0x14; /* Offset to the LL giving the Cseg start */
|
||||
charProc = 'T'; /* Indicates a proc in the dictionary */
|
||||
charFunc = 'U'; /* Indicates a function in the dictionary */
|
||||
skipPmap = 6; /* Bytes to skip after Func to get pmap offset */
|
||||
break;
|
||||
|
||||
|
||||
case '5': /* Version 5.0 */
|
||||
offStCseg = 0x18; /* Offset to the LL giving the Cseg start */
|
||||
charProc = 'T'; /* Indicates a proc in the dictionary */
|
||||
charFunc = 'U'; /* Indicates a function in the dictionary */
|
||||
skipPmap = 1; /* Bytes to skip after Func to get pmap offset */
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unknown version %c!\n", version);
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TPL_PatternCollector::savePos(FILE *f)
|
||||
{
|
||||
|
||||
if (positionStack.size() >= 20)
|
||||
{
|
||||
printf("Overflowed filePosn array\n");
|
||||
exit(1);
|
||||
}
|
||||
positionStack.push_back(ftell(f));
|
||||
}
|
||||
|
||||
void TPL_PatternCollector::restorePos(FILE *f)
|
||||
{
|
||||
if (positionStack.empty() == 0)
|
||||
{
|
||||
printf("Underflowed filePosn array\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fseek(f, positionStack.back(), SEEK_SET);
|
||||
positionStack.pop_back();
|
||||
}
|
||||
|
||||
void TPL_PatternCollector::enterUnitProcs(FILE *f)
|
||||
{
|
||||
|
||||
uint16_t i, LL;
|
||||
uint16_t hash, hsize, dhdr, pmapOff;
|
||||
char cat;
|
||||
char name[40];
|
||||
|
||||
fseek(f, unitBase+0x0C, SEEK_SET);
|
||||
cmap = readShort(f);
|
||||
pmap = readShort(f);
|
||||
fseek(f, unitBase+offStCseg, SEEK_SET);
|
||||
csegBase = roundUp(readShort(f)); /* Round up to next 16 bdry */
|
||||
printf("CMAP table at %04X\n", cmap);
|
||||
printf("PMAP table at %04X\n", pmap);
|
||||
printf("Code seg base %04X\n", csegBase);
|
||||
|
||||
readCmapOffsets(f);
|
||||
|
||||
fseek(f, unitBase+pmap, SEEK_SET); /* Go to first pmap entry */
|
||||
if (readShort(f) != 0xFFFF) /* FFFF means none */
|
||||
{
|
||||
sprintf(name, "UNIT_INIT_%d", ++unitNum);
|
||||
enterSym(f,name, 0); /* This is the unit init code */
|
||||
}
|
||||
|
||||
fseek(f, unitBase+0x0A, SEEK_SET);
|
||||
hash = readShort(f);
|
||||
//printf("Hash table at %04X\n", hash);
|
||||
fseek(f, unitBase+hash, SEEK_SET);
|
||||
hsize = readShort(f);
|
||||
//printf("Hash table size %04X\n", hsize);
|
||||
for (i=0; i <= hsize; i+= 2)
|
||||
{
|
||||
dhdr = readShort(f);
|
||||
if (dhdr)
|
||||
{
|
||||
savePos(f);
|
||||
fseek(f, unitBase+dhdr, SEEK_SET);
|
||||
do
|
||||
{
|
||||
LL = readShort(f);
|
||||
readString(f);
|
||||
strcpy(name, (char *)buf);
|
||||
cat = readByte(f);
|
||||
if ((cat == charProc) || (cat == charFunc))
|
||||
{
|
||||
grab(f,skipPmap); /* Skip to the pmap */
|
||||
pmapOff = readShort(f); /* pmap offset */
|
||||
printf("pmap offset for %13s: %04X\n", name, pmapOff);
|
||||
enterSym(f,name, pmapOff);
|
||||
}
|
||||
//printf("%13s %c ", name, cat);
|
||||
if (LL)
|
||||
{
|
||||
//printf("LL seek to %04X\n", LL);
|
||||
fseek(f, unitBase+LL, SEEK_SET);
|
||||
}
|
||||
} while (LL);
|
||||
restorePos(f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int TPL_PatternCollector::readSyms(FILE *f)
|
||||
{
|
||||
grab(f,4);
|
||||
if ((strncmp((char *)buf, "TPU0", 4) != 0) && ((strncmp((char *)buf, "TPU5", 4) != 0)))
|
||||
{
|
||||
printf("Not a Turbo Pascal version 4 or 5 library file\n");
|
||||
fclose(f);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
setVersionSpecifics();
|
||||
|
||||
enterSystemUnit(f);
|
||||
unitBase = 0;
|
||||
do
|
||||
{
|
||||
nextUnit(f);
|
||||
if (feof(f)) break;
|
||||
enterUnitProcs(f);
|
||||
} while (1);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user