Update the dcc tools code
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user