Update the dcc tools code
This commit is contained in:
parent
c5c9196561
commit
842687726f
@ -27,7 +27,7 @@ enable_testing()
|
|||||||
ENDIF()
|
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(
|
INCLUDE_DIRECTORIES(
|
||||||
3rd_party/libdisasm
|
3rd_party/libdisasm
|
||||||
include
|
include
|
||||||
|
|||||||
@ -1,5 +1,82 @@
|
|||||||
#ifndef PATTERNCOLLECTOR
|
#ifndef PATTERNCOLLECTOR
|
||||||
#define 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
|
#endif // PATTERNCOLLECTOR
|
||||||
|
|
||||||
|
|||||||
@ -211,6 +211,7 @@ struct ComLoader : public DosLoader {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool load(PROG &prog,QFile &fp) {
|
bool load(PROG &prog,QFile &fp) {
|
||||||
|
fp.seek(0);
|
||||||
/* COM file
|
/* COM file
|
||||||
* In this case the load module size is just the file length
|
* In this case the load module size is just the file length
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
PerfectHash g_pattern_hasher;
|
||||||
#define NIL -1 /* Used like NULL, but 0 is valid */
|
#define NIL -1 /* Used like NULL, but 0 is valid */
|
||||||
|
|
||||||
/* Hash table structure */
|
/* Hash table structure */
|
||||||
@ -331,7 +331,7 @@ void SetupLibCheck(void)
|
|||||||
|
|
||||||
/* Initialise the perfhlib stuff. Also allocates T1, T2, g, etc */
|
/* Initialise the perfhlib stuff. Also allocates T1, T2, g, etc */
|
||||||
/* Set the parameters for the hash table */
|
/* Set the parameters for the hash table */
|
||||||
g_pattern_hasher.init(
|
g_pattern_hasher.setHashParams(
|
||||||
numKeys, /* The number of symbols */
|
numKeys, /* The number of symbols */
|
||||||
PatLen, /* The length of the pattern to be hashed */
|
PatLen, /* The length of the pattern to be hashed */
|
||||||
256, /* The character set of the pattern (0-FF) */
|
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");
|
// rec = Records.getDef("CCR");
|
||||||
// if(rec)
|
// if(rec)
|
||||||
// rec->dump();
|
// rec->dump();
|
||||||
for(auto val : Records.getDefs())
|
for(const auto &val : Records.getDefs())
|
||||||
{
|
{
|
||||||
//std::cout<< "Def "<<val.first<<"\n";
|
//std::cout<< "Def "<<val.first<<"\n";
|
||||||
}
|
}
|
||||||
@ -73,43 +73,43 @@ bool TVisitor(raw_ostream &OS, RecordKeeper &Records)
|
|||||||
}
|
}
|
||||||
int testTblGen(int argc, char **argv)
|
int testTblGen(int argc, char **argv)
|
||||||
{
|
{
|
||||||
using namespace llvm;
|
// using namespace llvm;
|
||||||
sys::PrintStackTraceOnErrorSignal();
|
// sys::PrintStackTraceOnErrorSignal();
|
||||||
PrettyStackTraceProgram(argc,argv);
|
// PrettyStackTraceProgram(argc,argv);
|
||||||
cl::ParseCommandLineOptions(argc,argv);
|
// cl::ParseCommandLineOptions(argc,argv);
|
||||||
return llvm::TableGenMain(argv[0],TVisitor);
|
// return llvm::TableGenMain(argv[0],TVisitor);
|
||||||
InitializeNativeTarget();
|
// InitializeNativeTarget();
|
||||||
Triple TheTriple;
|
// Triple TheTriple;
|
||||||
std::string def = sys::getDefaultTargetTriple();
|
// std::string def = sys::getDefaultTargetTriple();
|
||||||
std::string MCPU="i386";
|
// std::string MCPU="i386";
|
||||||
std::string MARCH="x86";
|
// std::string MARCH="x86";
|
||||||
InitializeAllTargetInfos();
|
// InitializeAllTargetInfos();
|
||||||
InitializeAllTargetMCs();
|
// InitializeAllTargetMCs();
|
||||||
InitializeAllAsmPrinters();
|
// InitializeAllAsmPrinters();
|
||||||
InitializeAllAsmParsers();
|
// InitializeAllAsmParsers();
|
||||||
InitializeAllDisassemblers();
|
// InitializeAllDisassemblers();
|
||||||
std::string TargetTriple("i386-pc-linux-gnu");
|
// std::string TargetTriple("i386-pc-linux-gnu");
|
||||||
TheTriple = Triple(Triple::normalize(TargetTriple));
|
// TheTriple = Triple(Triple::normalize(TargetTriple));
|
||||||
MCOperand op=llvm::MCOperand::CreateImm(11);
|
// MCOperand op=llvm::MCOperand::CreateImm(11);
|
||||||
MCAsmInfo info;
|
// MCAsmInfo info;
|
||||||
raw_os_ostream wrap(std::cerr);
|
// raw_os_ostream wrap(std::cerr);
|
||||||
op.print(wrap,&info);
|
// op.print(wrap,&info);
|
||||||
wrap.flush();
|
// wrap.flush();
|
||||||
std::cerr<<"\n";
|
// std::cerr<<"\n";
|
||||||
std::string lookuperr;
|
// std::string lookuperr;
|
||||||
TargetRegistry::printRegisteredTargetsForVersion();
|
// TargetRegistry::printRegisteredTargetsForVersion();
|
||||||
const Target *t = TargetRegistry::lookupTarget(MARCH,TheTriple,lookuperr);
|
// const Target *t = TargetRegistry::lookupTarget(MARCH,TheTriple,lookuperr);
|
||||||
TargetOptions opts;
|
// TargetOptions opts;
|
||||||
std::string Features;
|
// std::string Features;
|
||||||
opts.PrintMachineCode=1;
|
// opts.PrintMachineCode=1;
|
||||||
TargetMachine *tm = t->createTargetMachine(TheTriple.getTriple(),MCPU,Features,opts);
|
// TargetMachine *tm = t->createTargetMachine(TheTriple.getTriple(),MCPU,Features,opts);
|
||||||
std::cerr<<tm->getInstrInfo()->getName(97)<<"\n";
|
// std::cerr<<tm->getInstrInfo()->getName(97)<<"\n";
|
||||||
const MCInstrDesc &ds(tm->getInstrInfo()->get(97));
|
// const MCInstrDesc &ds(tm->getInstrInfo()->get(97));
|
||||||
const MCOperandInfo *op1=ds.OpInfo;
|
// const MCOperandInfo *op1=ds.OpInfo;
|
||||||
uint16_t impl_def = ds.getImplicitDefs()[0];
|
// uint16_t impl_def = ds.getImplicitDefs()[0];
|
||||||
std::cerr<<lookuperr<<"\n";
|
// std::cerr<<lookuperr<<"\n";
|
||||||
|
|
||||||
exit(0);
|
// exit(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
void setupOptions(QCoreApplication &app) {
|
void setupOptions(QCoreApplication &app) {
|
||||||
|
|||||||
@ -1,7 +1,237 @@
|
|||||||
#include "LIB_PatternCollector.h"
|
#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
|
#pragma once
|
||||||
#define LIB_PATTERNCOLLECTOR_H
|
|
||||||
|
|
||||||
|
#include "PatternCollector.h"
|
||||||
|
|
||||||
class LIB_PatternCollector
|
struct LIB_PatternCollector : public PatternCollector
|
||||||
{
|
{
|
||||||
public:
|
protected:
|
||||||
LIB_PatternCollector();
|
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
|
#ifndef TPL_PATTERNCOLLECTOR_H
|
||||||
#define 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
|
#endif // TPL_PATTERNCOLLECTOR_H
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user