font2png, iffexplore: Misc. cleanup

This commit is contained in:
2015-04-17 15:39:19 +02:00
parent 6726488dda
commit ff7f5b2a0a
2 changed files with 49 additions and 56 deletions

View File

@@ -31,49 +31,28 @@ struct Font {
struct FontHeader { // little endian struct FontHeader { // little endian
uint32_t unknown1; // (always)? "1.\0\0" uint32_t unknown1; // (always)? "1.\0\0"
uint32_t entries; uint32_t entries;
uint32_t charWidth; uint32_t charHeight;
uint8_t bgColor; uint8_t bgColor;
char unknown3[3]; char unknown3[3];
} __attribute__((__packed__)); } __attribute__((__packed__));
Font parseFont(FILE* file, size_t length) Font parseFont(FILE* file, size_t length)
{ {
// if (fseeko(file, 16, SEEK_SET) != 0) { if (length < sizeof(FontHeader))
// throw POSIXException(errno, "Could not seek"); throw FormatException{"File smaller than header"};
// }
// uint32_t data, last_data = 0;
// int last_diff = -1, count = 0;
// size_t pos = 16;
// while (pos < length) {
// if (fread(&data, 4, 1, file) != 1) {
// if (feof(file))
// throw Exception{"Unexpected EOF"};
// throw POSIXException{errno, "Could not read"};
// }
// if ((last_diff == -1) ||
// (data-last_data == last_diff)) {
// ++count;
// last_diff = data-last_data;
// // printf("%.8x\n", data);
// } else {
// if ((count > 1) && last_diff )
// printf("%d times diff %d\n", count, last_diff);
// count = 0;
// last_diff = -1;
// }
// last_data = data;
// pos += 4;
// }
FontHeader header; FontHeader header;
if (fread(&header, sizeof(FontHeader), 1, file) != 1) if (fread(&header, sizeof(FontHeader), 1, file) != 1)
throw POSIXException{errno, "Could not read"}; throw POSIXException{errno, "Could not read"};
if (header.unknown1 != 0x00002E31)
throw FormatException{"Not a font?"};
const unsigned index_start = sizeof(FontHeader); const unsigned index_start = sizeof(FontHeader);
const unsigned index_end = index_start+4*header.entries; const unsigned index_end = index_start+4*header.entries;
const unsigned char_width = header.charWidth;
if (index_end > length)
throw Exception{"Index table exceeds file length"};
std::vector<uint32_t> indices; std::vector<uint32_t> indices;
for (unsigned i = index_start;i < index_end;i+=4) { for (unsigned i = index_start;i < index_end;i+=4) {
@@ -87,9 +66,12 @@ Font parseFont(FILE* file, size_t length)
printf("Index range %u .. %u\n", printf("Index range %u .. %u\n",
*minmax.first, *minmax.second); *minmax.first, *minmax.second);
if (*minmax.second > length)
throw FormatException{"Index exceeds file length"};
Font ret; Font ret;
ret.numChars = header.entries; ret.numChars = header.entries;
ret.charHeight = char_width; ret.charHeight = header.charHeight;
ret.maxCharWidth = 0; ret.maxCharWidth = 0;
ret.bgColor = header.bgColor; ret.bgColor = header.bgColor;
for (auto const& index : indices) { for (auto const& index : indices) {
@@ -101,19 +83,22 @@ Font parseFont(FILE* file, size_t length)
throw POSIXException{errno, "Could not read"}; throw POSIXException{errno, "Could not read"};
if (!len) { if (!len) {
ret.chars.push_back(Image{}); ret.chars.push_back(Image{0, 0, {}});
continue; continue;
} }
if (index+4+len*header.charHeight > length)
throw FormatException{"Glyph data exceeds file length"};
Image chr; Image chr;
chr.height = char_width; chr.height = header.charHeight;
chr.width = len; chr.width = len;
chr.data.resize(char_width*len); chr.data.resize(chr.height*chr.width);
if (chr.width > ret.maxCharWidth) if (chr.width > ret.maxCharWidth)
ret.maxCharWidth = chr.width; ret.maxCharWidth = chr.width;
if (fread(chr.data.data(), len*char_width, 1, file) != 1) if (fread(chr.data.data(), chr.height*chr.width, 1, file) != 1)
throw POSIXException{errno, "Could not read"}; throw POSIXException{errno, "Could not read"};
ret.chars.push_back(chr); ret.chars.push_back(chr);

View File

@@ -13,10 +13,10 @@
struct ChunkHeader { struct ChunkHeader {
char typeID[4]; char typeID[4];
uint32_t length; uint32_t length; // big endian!!
}; } __attribute__((__packed__));
void parseBlob(FILE *iffFile, off_t start, off_t length, char name[4], unsigned level) void parseBlob(FILE *iffFile, off_t start, off_t length, char name[4], unsigned level, bool dump = false)
{ {
static unsigned count = 0; static unsigned count = 0;
@@ -74,6 +74,7 @@ void parseBlob(FILE *iffFile, off_t start, off_t length, char name[4], unsigned
filename.append(std::to_string(count) + "-"); filename.append(std::to_string(count) + "-");
filename.append(name, 4); filename.append(name, 4);
if (dump) {
FILEUPtr outFile{fopen(filename.c_str(), "wb")}; FILEUPtr outFile{fopen(filename.c_str(), "wb")};
if (!outFile) if (!outFile)
throw POSIXException{errno, "Could not open " + filename}; throw POSIXException{errno, "Could not open " + filename};
@@ -84,6 +85,11 @@ void parseBlob(FILE *iffFile, off_t start, off_t length, char name[4], unsigned
if (fwrite(buf.data(), length, 1, outFile.get()) != 1) if (fwrite(buf.data(), length, 1, outFile.get()) != 1)
throw POSIXException{errno, "Could not write data"}; throw POSIXException{errno, "Could not write data"};
} else {
for (unsigned i = 0;i < level;++i)
putchar('\t');
printf("BLOB of length %ld (0x%lx)\n", length, length);
}
++count; ++count;
} }
@@ -97,6 +103,10 @@ void parseChunk(FILE* iffFile, off_t start, off_t length, unsigned level = 0)
throw POSIXException(errno, "Could not seek"); throw POSIXException(errno, "Could not seek");
} }
// pos < length due to loop condition, cast of difference to unsigned is OK
if (static_cast<unsigned>(length-pos) < sizeof(ChunkHeader))
throw FormatException{"Remaining size < header size"};
ChunkHeader header; ChunkHeader header;
if (fread(&header, sizeof(ChunkHeader), 1, iffFile) != 1) { if (fread(&header, sizeof(ChunkHeader), 1, iffFile) != 1) {
@@ -109,11 +119,10 @@ void parseChunk(FILE* iffFile, off_t start, off_t length, unsigned level = 0)
for (unsigned i = 0;i < level;++i) for (unsigned i = 0;i < level;++i)
putchar('\t'); putchar('\t');
printf("Type: %.4s, Length: %u (0x%x)", header.typeID, header.length, header.length); printf("Type: %.4s, Length: %u (0x%x)", header.typeID, header.length, header.length);
if (memcmp(header.typeID, "FORM", 4) == 0) { if (header.length > (length-(pos+8)))
if (header.length > (length-(pos+8))) {
throw FormatException{"Length in header > remaining parent size"}; throw FormatException{"Length in header > remaining parent size"};
}
if (memcmp(header.typeID, "FORM", 4) == 0) {
char subType[4]; char subType[4];
if (fread(&subType, 4, 1, iffFile) != 1) { if (fread(&subType, 4, 1, iffFile) != 1) {
throw POSIXException(errno, "Could not read form subtype"); throw POSIXException(errno, "Could not read form subtype");
@@ -126,10 +135,9 @@ void parseChunk(FILE* iffFile, off_t start, off_t length, unsigned level = 0)
parseBlob(iffFile, start+pos+8, header.length, header.typeID, level+1); parseBlob(iffFile, start+pos+8, header.length, header.typeID, level+1);
} }
if (header.length%2 != 0)
pos += 1;
pos += header.length+8; pos += header.length+8;
if (pos%2 != 0)
++pos;
} }
} }