Update the dcc tools code
This commit is contained in:
parent
c5c9196561
commit
842687726f
@ -27,7 +27,7 @@ enable_testing()
|
||||
ENDIF()
|
||||
|
||||
|
||||
llvm_map_components_to_libnames(REQ_LLVM_LIBRARIES jit native mc support tablegen)
|
||||
llvm_map_components_to_libnames(REQ_LLVM_LIBRARIES native mc support tablegen)
|
||||
INCLUDE_DIRECTORIES(
|
||||
3rd_party/libdisasm
|
||||
include
|
||||
|
||||
@ -1,5 +1,82 @@
|
||||
#ifndef PATTERNCOLLECTOR
|
||||
#define PATTERNCOLLECTOR
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
#define SYMLEN 16 /* Number of chars in the symbol name, incl null */
|
||||
#define PATLEN 23 /* Number of bytes in the pattern part */
|
||||
|
||||
struct HASHENTRY
|
||||
{
|
||||
char name[SYMLEN]; /* The symbol name */
|
||||
uint8_t pat [PATLEN]; /* The pattern */
|
||||
uint16_t offset; /* Offset (needed temporarily) */
|
||||
};
|
||||
|
||||
struct PatternCollector {
|
||||
uint8_t buf[100], bufSave[7]; /* Temp buffer for reading the file */
|
||||
uint16_t readShort(FILE *f)
|
||||
{
|
||||
uint8_t b1, b2;
|
||||
|
||||
if (fread(&b1, 1, 1, f) != 1)
|
||||
{
|
||||
printf("Could not read\n");
|
||||
exit(11);
|
||||
}
|
||||
if (fread(&b2, 1, 1, f) != 1)
|
||||
{
|
||||
printf("Could not read\n");
|
||||
exit(11);
|
||||
}
|
||||
return (b2 << 8) + b1;
|
||||
}
|
||||
|
||||
void grab(FILE *f,int n)
|
||||
{
|
||||
if (fread(buf, 1, n, f) != (size_t)n)
|
||||
{
|
||||
printf("Could not read\n");
|
||||
exit(11);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t readByte(FILE *f)
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
if (fread(&b, 1, 1, f) != 1)
|
||||
{
|
||||
printf("Could not read\n");
|
||||
exit(11);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
uint16_t readWord(FILE *fl)
|
||||
{
|
||||
uint8_t b1, b2;
|
||||
|
||||
b1 = readByte(fl);
|
||||
b2 = readByte(fl);
|
||||
|
||||
return b1 + (b2 << 8);
|
||||
}
|
||||
|
||||
/* Called by map(). Return the i+1th key in *pKeys */
|
||||
uint8_t *getKey(int i)
|
||||
{
|
||||
return keys[i].pat;
|
||||
}
|
||||
/* Display key i */
|
||||
void dispKey(int i)
|
||||
{
|
||||
printf("%s", keys[i].name);
|
||||
}
|
||||
std::vector<HASHENTRY> keys; /* array of keys */
|
||||
virtual int readSyms(FILE *f)=0;
|
||||
};
|
||||
#endif // PATTERNCOLLECTOR
|
||||
|
||||
|
||||
@ -211,6 +211,7 @@ struct ComLoader : public DosLoader {
|
||||
return false;
|
||||
}
|
||||
bool load(PROG &prog,QFile &fp) {
|
||||
fp.seek(0);
|
||||
/* COM file
|
||||
* In this case the load module size is just the file length
|
||||
*/
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
|
||||
PerfectHash g_pattern_hasher;
|
||||
#define NIL -1 /* Used like NULL, but 0 is valid */
|
||||
|
||||
/* Hash table structure */
|
||||
@ -331,7 +331,7 @@ void SetupLibCheck(void)
|
||||
|
||||
/* Initialise the perfhlib stuff. Also allocates T1, T2, g, etc */
|
||||
/* Set the parameters for the hash table */
|
||||
g_pattern_hasher.init(
|
||||
g_pattern_hasher.setHashParams(
|
||||
numKeys, /* The number of symbols */
|
||||
PatLen, /* The length of the pattern to be hashed */
|
||||
256, /* The character set of the pattern (0-FF) */
|
||||
|
||||
74
src/dcc.cpp
74
src/dcc.cpp
@ -65,7 +65,7 @@ bool TVisitor(raw_ostream &OS, RecordKeeper &Records)
|
||||
// rec = Records.getDef("CCR");
|
||||
// if(rec)
|
||||
// rec->dump();
|
||||
for(auto val : Records.getDefs())
|
||||
for(const auto &val : Records.getDefs())
|
||||
{
|
||||
//std::cout<< "Def "<<val.first<<"\n";
|
||||
}
|
||||
@ -73,43 +73,43 @@ bool TVisitor(raw_ostream &OS, RecordKeeper &Records)
|
||||
}
|
||||
int testTblGen(int argc, char **argv)
|
||||
{
|
||||
using namespace llvm;
|
||||
sys::PrintStackTraceOnErrorSignal();
|
||||
PrettyStackTraceProgram(argc,argv);
|
||||
cl::ParseCommandLineOptions(argc,argv);
|
||||
return llvm::TableGenMain(argv[0],TVisitor);
|
||||
InitializeNativeTarget();
|
||||
Triple TheTriple;
|
||||
std::string def = sys::getDefaultTargetTriple();
|
||||
std::string MCPU="i386";
|
||||
std::string MARCH="x86";
|
||||
InitializeAllTargetInfos();
|
||||
InitializeAllTargetMCs();
|
||||
InitializeAllAsmPrinters();
|
||||
InitializeAllAsmParsers();
|
||||
InitializeAllDisassemblers();
|
||||
std::string TargetTriple("i386-pc-linux-gnu");
|
||||
TheTriple = Triple(Triple::normalize(TargetTriple));
|
||||
MCOperand op=llvm::MCOperand::CreateImm(11);
|
||||
MCAsmInfo info;
|
||||
raw_os_ostream wrap(std::cerr);
|
||||
op.print(wrap,&info);
|
||||
wrap.flush();
|
||||
std::cerr<<"\n";
|
||||
std::string lookuperr;
|
||||
TargetRegistry::printRegisteredTargetsForVersion();
|
||||
const Target *t = TargetRegistry::lookupTarget(MARCH,TheTriple,lookuperr);
|
||||
TargetOptions opts;
|
||||
std::string Features;
|
||||
opts.PrintMachineCode=1;
|
||||
TargetMachine *tm = t->createTargetMachine(TheTriple.getTriple(),MCPU,Features,opts);
|
||||
std::cerr<<tm->getInstrInfo()->getName(97)<<"\n";
|
||||
const MCInstrDesc &ds(tm->getInstrInfo()->get(97));
|
||||
const MCOperandInfo *op1=ds.OpInfo;
|
||||
uint16_t impl_def = ds.getImplicitDefs()[0];
|
||||
std::cerr<<lookuperr<<"\n";
|
||||
// using namespace llvm;
|
||||
// sys::PrintStackTraceOnErrorSignal();
|
||||
// PrettyStackTraceProgram(argc,argv);
|
||||
// cl::ParseCommandLineOptions(argc,argv);
|
||||
// return llvm::TableGenMain(argv[0],TVisitor);
|
||||
// InitializeNativeTarget();
|
||||
// Triple TheTriple;
|
||||
// std::string def = sys::getDefaultTargetTriple();
|
||||
// std::string MCPU="i386";
|
||||
// std::string MARCH="x86";
|
||||
// InitializeAllTargetInfos();
|
||||
// InitializeAllTargetMCs();
|
||||
// InitializeAllAsmPrinters();
|
||||
// InitializeAllAsmParsers();
|
||||
// InitializeAllDisassemblers();
|
||||
// std::string TargetTriple("i386-pc-linux-gnu");
|
||||
// TheTriple = Triple(Triple::normalize(TargetTriple));
|
||||
// MCOperand op=llvm::MCOperand::CreateImm(11);
|
||||
// MCAsmInfo info;
|
||||
// raw_os_ostream wrap(std::cerr);
|
||||
// op.print(wrap,&info);
|
||||
// wrap.flush();
|
||||
// std::cerr<<"\n";
|
||||
// std::string lookuperr;
|
||||
// TargetRegistry::printRegisteredTargetsForVersion();
|
||||
// const Target *t = TargetRegistry::lookupTarget(MARCH,TheTriple,lookuperr);
|
||||
// TargetOptions opts;
|
||||
// std::string Features;
|
||||
// opts.PrintMachineCode=1;
|
||||
// TargetMachine *tm = t->createTargetMachine(TheTriple.getTriple(),MCPU,Features,opts);
|
||||
// std::cerr<<tm->getInstrInfo()->getName(97)<<"\n";
|
||||
// const MCInstrDesc &ds(tm->getInstrInfo()->get(97));
|
||||
// const MCOperandInfo *op1=ds.OpInfo;
|
||||
// uint16_t impl_def = ds.getImplicitDefs()[0];
|
||||
// std::cerr<<lookuperr<<"\n";
|
||||
|
||||
exit(0);
|
||||
// exit(0);
|
||||
|
||||
}
|
||||
void setupOptions(QCoreApplication &app) {
|
||||
|
||||
@ -1,7 +1,237 @@
|
||||
#include "LIB_PatternCollector.h"
|
||||
#include <cstring>
|
||||
#include <cstring>
|
||||
/** \note there is an untested assumption that the *first* segment definition
|
||||
with class CODE will be the one containing all useful functions in the
|
||||
LEDATA records. Functions such as _exit() have more than one segment
|
||||
declared with class CODE (MSC8 libraries) */
|
||||
|
||||
LIB_PatternCollector::LIB_PatternCollector()
|
||||
extern void fixWildCards(uint8_t pat[]);
|
||||
void readNN(int n, FILE *fl)
|
||||
{
|
||||
|
||||
if (fseek(fl, (long)n, SEEK_CUR) != 0)
|
||||
{
|
||||
printf("Could not seek file\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
void LIB_PatternCollector::readString(FILE *fl)
|
||||
{
|
||||
uint8_t len;
|
||||
|
||||
len = readByte(fl);
|
||||
if (fread(buf, 1, len, fl) != len)
|
||||
{
|
||||
printf("Could not read string len %d\n", len);
|
||||
exit(2);
|
||||
}
|
||||
buf[len] = '\0';
|
||||
offset += len;
|
||||
}
|
||||
|
||||
int LIB_PatternCollector::readSyms(FILE *fl)
|
||||
{
|
||||
int i;
|
||||
int count = 0;
|
||||
int firstSym = 0; /* First symbol this module */
|
||||
uint8_t b, c, type;
|
||||
uint16_t w, len;
|
||||
|
||||
codeLNAMES = NONE; /* Invalidate indexes for code segment */
|
||||
codeSEGDEF = NONE; /* Else won't be assigned */
|
||||
|
||||
offset = 0; /* For diagnostics, really */
|
||||
|
||||
if ((leData = (uint8_t *)malloc(0xFF80)) == 0)
|
||||
{
|
||||
printf("Could not malloc 64k bytes for LEDATA\n");
|
||||
exit(10);
|
||||
}
|
||||
|
||||
while (!feof(fl))
|
||||
{
|
||||
type = readByte(fl);
|
||||
len = readWord(fl);
|
||||
/* Note: uncommenting the following generates a *lot* of output */
|
||||
/*printf("Offset %05lX: type %02X len %d\n", offset-3, type, len);//*/
|
||||
switch (type)
|
||||
{
|
||||
|
||||
case 0x96: /* LNAMES */
|
||||
while (len > 1)
|
||||
{
|
||||
readString(fl);
|
||||
++lnum;
|
||||
if (strcmp((char *)buf, "CODE") == 0)
|
||||
{
|
||||
/* This is the class name we're looking for */
|
||||
codeLNAMES= lnum;
|
||||
}
|
||||
len -= strlen((char *)buf)+1;
|
||||
}
|
||||
b = readByte(fl); /* Checksum */
|
||||
break;
|
||||
|
||||
case 0x98: /* Segment definition */
|
||||
b = readByte(fl); /* Segment attributes */
|
||||
if ((b & 0xE0) == 0)
|
||||
{
|
||||
/* Alignment field is zero. Frame and offset follow */
|
||||
readWord(fl);
|
||||
readByte(fl);
|
||||
}
|
||||
|
||||
w = readWord(fl); /* Segment length */
|
||||
|
||||
b = readByte(fl); /* Segment name index */
|
||||
++segnum;
|
||||
|
||||
b = readByte(fl); /* Class name index */
|
||||
if ((b == codeLNAMES) && (codeSEGDEF == NONE))
|
||||
{
|
||||
/* This is the segment defining the code class */
|
||||
codeSEGDEF = segnum;
|
||||
}
|
||||
|
||||
b = readByte(fl); /* Overlay index */
|
||||
b = readByte(fl); /* Checksum */
|
||||
break;
|
||||
|
||||
case 0x90: /* PUBDEF: public symbols */
|
||||
b = readByte(fl); /* Base group */
|
||||
c = readByte(fl); /* Base segment */
|
||||
len -= 2;
|
||||
if (c == 0)
|
||||
{
|
||||
w = readWord(fl);
|
||||
len -= 2;
|
||||
}
|
||||
while (len > 1)
|
||||
{
|
||||
readString(fl);
|
||||
w = readWord(fl); /* Offset */
|
||||
b = readByte(fl); /* Type index */
|
||||
if (c == codeSEGDEF)
|
||||
{
|
||||
char *p;
|
||||
HASHENTRY entry;
|
||||
p = (char *)buf;
|
||||
if (buf[0] == '_') /* Leading underscore? */
|
||||
{
|
||||
p++; /* Yes, remove it*/
|
||||
}
|
||||
i = std::min(size_t(SYMLEN-1), strlen(p));
|
||||
memcpy(entry.name, p, i);
|
||||
entry.name[i] = '\0';
|
||||
entry.offset = w;
|
||||
/*printf("%04X: %s is sym #%d\n", w, keys[count].name, count);//*/
|
||||
keys.push_back(entry);
|
||||
count++;
|
||||
}
|
||||
len -= strlen((char *)buf) + 1 + 2 + 1;
|
||||
}
|
||||
b = readByte(fl); /* Checksum */
|
||||
break;
|
||||
|
||||
|
||||
case 0xA0: /* LEDATA */
|
||||
{
|
||||
b = readByte(fl); /* Segment index */
|
||||
w = readWord(fl); /* Offset */
|
||||
len -= 3;
|
||||
/*printf("LEDATA seg %d off %02X len %Xh, looking for %d\n", b, w, len-1, codeSEGDEF);//*/
|
||||
|
||||
if (b != codeSEGDEF)
|
||||
{
|
||||
readNN(len,fl); /* Skip the data */
|
||||
break; /* Next record */
|
||||
}
|
||||
|
||||
|
||||
if (fread(&leData[w], 1, len-1, fl) != len-1)
|
||||
{
|
||||
printf("Could not read LEDATA length %d\n", len-1);
|
||||
exit(2);
|
||||
}
|
||||
offset += len-1;
|
||||
maxLeData = std::max<uint16_t>(maxLeData, w+len-1);
|
||||
|
||||
readByte(fl); /* Checksum */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
readNN(len,fl); /* Just skip the lot */
|
||||
|
||||
if (type == 0x8A) /* Mod end */
|
||||
{
|
||||
/* Now find all the patterns for public code symbols that
|
||||
we have found */
|
||||
for (i=firstSym; i < count; i++)
|
||||
{
|
||||
uint16_t off = keys[i].offset;
|
||||
if (off == (uint16_t)-1)
|
||||
{
|
||||
continue; /* Ignore if already done */
|
||||
}
|
||||
if (keys[i].offset > maxLeData)
|
||||
{
|
||||
printf(
|
||||
"Warning: no LEDATA for symbol #%d %s "
|
||||
"(offset %04X, max %04X)\n",
|
||||
i, keys[i].name, off, maxLeData);
|
||||
/* To make things consistant, we set the pattern for
|
||||
this symbol to nulls */
|
||||
memset(&keys[i].pat, 0, PATLEN);
|
||||
continue;
|
||||
}
|
||||
/* Copy to temp buffer so don't overrun later patterns.
|
||||
(e.g. when chopping a short pattern).
|
||||
Beware of short patterns! */
|
||||
if (off+PATLEN <= maxLeData)
|
||||
{
|
||||
/* Available pattern is >= PATLEN */
|
||||
memcpy(buf, &leData[off], PATLEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Short! Only copy what is available (and malloced!) */
|
||||
memcpy(buf, &leData[off], maxLeData-off);
|
||||
/* Set rest to zeroes */
|
||||
memset(&buf[maxLeData-off], 0, PATLEN-(maxLeData-off));
|
||||
}
|
||||
fixWildCards((uint8_t *)buf);
|
||||
/* Save into the hash entry. */
|
||||
memcpy(keys[i].pat, buf, PATLEN);
|
||||
keys[i].offset = (uint16_t)-1; // Flag it as done
|
||||
//printf("Saved pattern for %s\n", keys[i].name);
|
||||
}
|
||||
|
||||
|
||||
while (readByte(fl) == 0);
|
||||
readNN(-1,fl); /* Unget the last byte (= type) */
|
||||
lnum = 0; /* Reset index into lnames */
|
||||
segnum = 0; /* Reset index into snames */
|
||||
firstSym = count; /* Remember index of first sym this mod */
|
||||
codeLNAMES = NONE; /* Invalidate indexes for code segment */
|
||||
codeSEGDEF = NONE;
|
||||
memset(leData, 0, maxLeData); /* Clear out old junk */
|
||||
maxLeData = 0; /* No data read this module */
|
||||
}
|
||||
|
||||
else if (type == 0xF1)
|
||||
{
|
||||
/* Library end record */
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(leData);
|
||||
keys.clear();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -1,11 +1,25 @@
|
||||
#ifndef LIB_PATTERNCOLLECTOR_H
|
||||
#define LIB_PATTERNCOLLECTOR_H
|
||||
#pragma once
|
||||
|
||||
#include "PatternCollector.h"
|
||||
|
||||
class LIB_PatternCollector
|
||||
struct LIB_PatternCollector : public PatternCollector
|
||||
{
|
||||
public:
|
||||
LIB_PatternCollector();
|
||||
};
|
||||
protected:
|
||||
unsigned long offset;
|
||||
uint8_t lnum = 0; /* Count of LNAMES so far */
|
||||
uint8_t segnum = 0; /* Count of SEGDEFs so far */
|
||||
uint8_t codeLNAMES; /* Index of the LNAMES for "CODE" class */
|
||||
uint8_t codeSEGDEF; /* Index of the first SEGDEF that has class CODE */
|
||||
#define NONE 0xFF /* Improbable segment index */
|
||||
uint8_t *leData; /* Pointer to 64K of alloc'd data. Some .lib files
|
||||
have the symbols (PUBDEFs) *after* the data
|
||||
(LEDATA), so you need to keep the data here */
|
||||
uint16_t maxLeData; /* How much data we have in there */
|
||||
/* read a length then string to buf[]; make it an asciiz string */
|
||||
void readString( FILE *fl);
|
||||
|
||||
#endif // LIB_PATTERNCOLLECTOR_H
|
||||
public:
|
||||
/* Read the .lib file, and put the keys into the array *keys[]. Returns the count */
|
||||
int readSyms(FILE *fl);
|
||||
|
||||
};
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1,5 +1,38 @@
|
||||
#ifndef TPL_PATTERNCOLLECTOR_H
|
||||
#define TPL_PATTERNCOLLECTOR_H
|
||||
#include "PatternCollector.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
struct TPL_PatternCollector : public PatternCollector {
|
||||
protected:
|
||||
uint16_t cmap, pmap, csegBase, unitBase;
|
||||
uint16_t offStCseg, skipPmap;
|
||||
int count = 0;
|
||||
int cAllocSym = 0;
|
||||
int unitNum = 0;
|
||||
char version, charProc, charFunc;
|
||||
uint16_t csegoffs[100];
|
||||
uint16_t csegIdx;
|
||||
std::vector<long int> positionStack;
|
||||
|
||||
void enterSym(FILE *f,const char *name, uint16_t pmapOffset);
|
||||
void allocSym(int count);
|
||||
void readCmapOffsets(FILE *f);
|
||||
void enterSystemUnit(FILE *f);
|
||||
void readString(FILE *f);
|
||||
void unknown(FILE *f,unsigned j, unsigned k);
|
||||
void nextUnit(FILE *f);
|
||||
void setVersionSpecifics(void);
|
||||
void savePos(FILE *f);
|
||||
void restorePos(FILE *f);
|
||||
void enterUnitProcs(FILE *f);
|
||||
public:
|
||||
/* Read the .tpl file, and put the keys into the array *keys[]. Returns the count */
|
||||
int readSyms(FILE *f);
|
||||
};
|
||||
|
||||
#endif // TPL_PATTERNCOLLECTOR_H
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user