1
0
mirror of synced 2026-01-13 23:25:28 +00:00
2020-09-09 15:11:45 -07:00

177 lines
5.1 KiB
C++

#define _CRT_SECURE_NO_WARNINGS
// cray_ios_disasm.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "utils.h"
#include <map>
#include <boost/filesystem.hpp>
bool IsUpperCaseOrNum(char aC) {
if (aC >= 'A' && aC <= 'Z') return true;
if (aC >= '0' && aC <= '9') return true;
return false;
}
struct ProcessedFileHeader_s {
uint16_t FileSize;
uint16_t Flags;
uint16_t Flags1;
uint16_t Flags2;
char FileName[9];
};
const size_t cFileHeaderSize = 16;
ProcessedFileHeader_s DecodeHeader(uint8_t *aContent, size_t aMaxOffset, size_t aOffset) {
ProcessedFileHeader_s RetVal;
RetVal.FileSize = SwapBytes(*(uint16_t*)(aContent+aOffset)) * 2;
aOffset += 2;
RetVal.FileSize -= cFileHeaderSize;
RetVal.Flags = SwapBytes(*(uint16_t*)(aContent+aOffset));
aOffset += 2;
memcpy(RetVal.FileName,aContent+aOffset,8);
RetVal.FileName[8] = 0;
aOffset += 8;
RetVal.Flags1 = SwapBytes(*(uint16_t*)(aContent+aOffset));
aOffset += 2;
RetVal.Flags2 = SwapBytes(*(uint16_t*)(aContent+aOffset));
aOffset += 2;
return RetVal;
}
bool IsValidHeader(ProcessedFileHeader_s &aHeader, size_t aMaxOffset, size_t aOffset) {
if (aHeader.FileSize > aMaxOffset - aOffset) return false;
// if (aHeader.FileSize > 65536) return false;
// if (aHeader.FileSize == -(int16_t)cFileHeaderSize) return false;
if (aHeader.Flags != 0) return false;
if (aHeader.Flags1 == 0) return false;
if ((aHeader.Flags1 & 0xf000) != 0x0000 && (aHeader.Flags1 & 0xf000) != 0x8000) return false;
if (!IsUpperCaseOrNum(aHeader.FileName[0])) return false;
bool InStr = true;
for(int i=1;i<8;++i) {
if (InStr) {
if (aHeader.FileName[i] == 0) {
InStr = false;
} else {
if (!IsUpperCaseOrNum(aHeader.FileName[i])) return false;
}
} else {
if (aHeader.FileName[i] != 0) return false;
}
}
return true;
}
bool IsValidHeader(uint8_t *aContent, size_t aMaxOffset, size_t aOffset) {
ProcessedFileHeader_s Header = DecodeHeader(aContent,aMaxOffset,aOffset);
return IsValidHeader(Header, aMaxOffset, aOffset);
}
bool FindNextHeader(uint8_t *aContent, size_t aMaxOffset, size_t &aOffset) {
while (aOffset < aMaxOffset-16) {
if (IsValidHeader(aContent, aMaxOffset, aOffset)) return true;
++aOffset;
}
return false;
}
typedef std::map<size_t, std::string> FileDirectory_t;
void ParseOvlNum(FileDirectory_t &aFileNames, std::vector<uint8_t> &aFile, size_t aFileCnt) {
char Desc[255];
for(size_t FileIdx=0;FileIdx<aFileCnt;++FileIdx) {
uint16_t StartOffs = SwapBytes(*(uint16_t*)&aFile[FileIdx*8+4]) * 8 - 12;
uint16_t Size = SwapBytes(*(uint16_t*)&aFile[FileIdx*8+6]);
if (Size >= 255) break;
memcpy(Desc,&aFile[StartOffs],Size);
Desc[Size] = 0;
std::cout << aFileNames[FileIdx] << ": " << Desc << std::endl;
}
}
int main(int argc, char* argv[])
{
if (argc != 2) {
printf("Usage: %s <image file>\n",argv[0]);
return 1;
}
const char *InFileName = argv[1];
FILE *Input = fopen(InFileName,"rb");
if (Input == nullptr) {
printf("Can't open input file: %s\n", InFileName);
return 1;
}
uint64_t TotalFileSize = boost::filesystem::file_size(InFileName);
const size_t MaxFileSize = 256*1024*1024;
if (TotalFileSize > MaxFileSize) {
printf("Can't use files larger than %uMB\n",unsigned(MaxFileSize/1024/1024));
fclose(Input);
return 1;
}
uint8_t *File = new uint8_t[(size_t)TotalFileSize+1];
if (File == nullptr) {
printf("Not enough memory to allocate buffer for image\n");
fclose(Input);
return 1;
}
size_t Read = fread(File,1,(size_t)TotalFileSize,Input);
fclose(Input);
if (Read != TotalFileSize) {
printf("Can't read file.\n");
return 1;
}
{
size_t FileCnt = SwapBytes(*((uint16_t *)(File)));
size_t Offset = 4;
size_t FileIdx = 0;
FileDirectory_t FileNames;
std::vector<uint8_t> OvlNum;
size_t MaxFileId = 0;
while (FileIdx < FileCnt) {
ProcessedFileHeader_s Header = DecodeHeader(File,(size_t)TotalFileSize,Offset);
if (!IsValidHeader(Header,(size_t)TotalFileSize,Offset)) {
printf("Lost track at offset 0x%08x\n",unsigned(Offset));
break;
}
Offset += cFileHeaderSize;
printf("0x%08x-0x%08x flags:0x%04x 0x%04x size:%8d %s\n",unsigned(Offset-cFileHeaderSize) , unsigned(Offset+Header.FileSize) ,Header.Flags1, Header.Flags2, Header.FileSize, Header.FileName);
char OutFileName[255];
size_t FileId = Header.Flags1 & 0x7fff;
if (FileId > MaxFileId) MaxFileId = FileId;
FileNames[FileId] = Header.FileName;
if (strcmp(Header.FileName, "OVLNUM") == 0) {
OvlNum.resize(Header.FileSize);
memcpy(&OvlNum[0],File+Offset,Header.FileSize);
}
sprintf(OutFileName,"%04u_%s.%s",unsigned(FileIdx),Header.FileName,((Header.Flags1 & 0x8000) == 0) ? "cod":"dat");
FILE *OutFile = fopen(OutFileName,"wb");
if (OutFile != nullptr) {
fwrite(File+Offset,1,Header.FileSize,OutFile);
fclose(OutFile);
}
Offset += Header.FileSize;
++FileIdx;
}
if (OvlNum.size() > 0) {
std::cout << "Overlay file explanations" << std::endl;
std::cout << "========================================" << std::endl;
ParseOvlNum(FileNames,OvlNum,MaxFileId+1);
}
}
delete[] File;
return 0;
}