/*
Phantasy Star Online Blue Burst Quest Disassembler
Copyright (C) 2022 Terry Chatman
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License version 3
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
#include
#include
#include "stdafx.h"
#include "prs.h"
#define DUMP_STR
//#define NO_ARGS
unsigned short questNum = 0;
#ifdef DUMP_STR
FILE *sf;
#endif
typedef struct {
long val;
wchar_t name[256];
wchar_t mask[256];
} psoOpcode;
int numOpcodes = 0;
#ifdef NO_ARGS
int vaStarted = 1;
#else
int vaStarted = 0;
#endif
long* strFunctions;
long* hexFunctions;
long numStrFunctions = 0;
long numHexFunctions = 0;
wchar_t asmFileName[4096] = { 0 };
wchar_t replaceBuf[4096];
wchar_t maskBuf[4096] = { 0 };
unsigned numArgs = 0;
wchar_t* argptrs[256] = { 0 };
wchar_t argbuf[4096];
int argreg[256] = { 0 };
int argidx = 0;
psoOpcode* opcode_list[1024];
typedef struct {
const wchar_t* arg;
unsigned size;
} psoOpcodeArg;
psoOpcodeArg opcodeSizes[] =
{{ L"T_NONE", 0x00 },
{ L"T_IMED", 0x00 },
{ L"T_ARGS", 0x30000 },
{ L"T_VASTART", 0x30001 },
{ L"T_VAEND", 0x030002 },
{ L"T_STR", 0x20001 },
{ L"T_SWITCH", 0x20002 },
{ L"T_SWITCH2B", 0x20003 },
{ L"T_PUSH", 0x10000 },
{ L"T_REG", 0x01 },
{ L"T_BREG", 0x01 },
{ L"T_BYTE", 0x01 },
{ L"T_WORD", 0x02 },
{ L"T_FUNC", 0x02 },
{ L"T_FUNC2", 0x02 },
{ L"T_PFLAG", 0x02 },
{ L"T_DATA", 0x02 },
{ L"T_STRDATA", 0x02 },
{ L"T_DWORD", 0x04 },
{ L"T_FLOAT", 0x04 },
{ L"T_DC", 0x00 },
{ L"T_V2", 0x00 },
{ L"T_V3", 0x00 },
{ L"T_V4", 0x00 },
};
long getMaskSize(unsigned char* opArgs, const wchar_t* mask)
{
unsigned maskSize = 0;
wchar_t* t = NULL;
wchar_t* nt1 = NULL;
unsigned ch;
psoOpcodeArg* a;
wchar_t maskproc[4096];
if (mask == NULL)
return -1;
swprintf(maskproc, 4096, mask);
t = wcstok(maskproc, L", ", &nt1);
while (t != NULL)
{
for (ch = 0; ch < sizeof(opcodeSizes) / sizeof(psoOpcodeArg); ch++)
{
a = &opcodeSizes[ch];
if (wcscmp(t, a->arg) == 0)
{
switch (a->size)
{
case 0x10000: // T_PUSH
maskSize |= 0x10000;
break;
case 0x20001: // T_STR
maskSize += (wcslen((wchar_t*)& opArgs[maskSize & 0xFFFF]) * 2) + 2;
break;
case 0x20002: // T_SWITCH
maskSize += *(unsigned char*)& opArgs[maskSize & 0xFFFF] * 2;
maskSize++;
break;
case 0x20003: // T_SWITCH2B
maskSize += *(unsigned char*)& opArgs[maskSize & 0xFFFF];
maskSize++;
break;
case 0x30000: // T_ARGS
case 0x30001: // T_VASTART
case 0x30002: // T_VAEND
return 0;
break;
default:
maskSize += a->size;
break;
}
}
}
t = wcstok(NULL, L", ", &nt1);
}
return maskSize;
}
void parseOpcodeList()
{
FILE* of;
char opCodeData[1024];
unsigned ch;
char* t;
unsigned ch2, ch3;
psoOpcode* o;
psoOpcodeArg* a;
int Dreamcast;
int functionOK;
wchar_t wcsbuf[256];
wchar_t* w;
of = _wfopen(asmFileName, L"r");
if (!of)
{
printf("FATAL: asm.txt is missing!");
exit(1);
}
else
{
while (fgets(opCodeData, 1024, of) != NULL)
{
if (strlen(opCodeData) > 1)
{
for (ch = 1; ch < strlen(opCodeData); ch++)
{
if (opCodeData[ch] == 0x7D)
opCodeData[ch] = 0x00;
}
t = strtok(&opCodeData[1], ", ");
Dreamcast = 0;
if (t != NULL)
{
ch2 = 0;
o = calloc(1, sizeof(psoOpcode));
if (!o)
{
wprintf(L"Out of memory!");
exit(1);
}
while (t != NULL)
{
wcsbuf[0] = 0;
w = &wcsbuf[0];
for (ch3 = 0; ch3 < strlen(t); ch3++)
{
if (t[ch3] != 0x22)
* w++ = t[ch3];
}
*w++ = 0;
w = &wcsbuf[0];
switch (ch2)
{
case 0: // opcode value
o->val = (long)wcstoll(w, NULL, 0);
break;
case 1:
swprintf_s(o->name, 256, w);
break;
default:
if (wcslen(o->mask))
wcscat(o->mask, L", ");
wcscat(o->mask, w);
if ((wcscmp(w, L"T_DC") == 0) || (wcscmp(w, L"T_DREG") == 0))
Dreamcast = 1;
else
{
functionOK = 0;
for (ch3 = 0; ch3 < sizeof(opcodeSizes) / sizeof(psoOpcodeArg); ch3++)
{
a = &opcodeSizes[ch3];
if (wcscmp(a->arg, w) == 0)
{
functionOK = 1;
break;
}
}
if (!functionOK)
{
wprintf(L"FATAL: Processing asm.txt, I don't understand \"%s\"!", w);
exit(1);
}
}
break;
}
t = strtok(NULL, ", ");
ch2++;
}
if (!Dreamcast)
{
if (numOpcodes > 1024)
{
wprintf(L"FATAL: Processing asm.txt, too many opcodes in file!");
exit(1);
}
opcode_list[numOpcodes++] = o;
}
else
free(o);
}
}
}
wprintf(L"%u opcodes loaded from asm.txt\n", numOpcodes);
fclose(of);
}
}
wchar_t* replaceStr(const wchar_t *s)
{
int c = 0, d = 0;
replaceBuf[0] = 0;
while (s[c] != 0)
{
switch (s[c])
{
case 0x25:
swprintf(&replaceBuf[d], 4, L"%%%%");
d += 2;
break;
case 0x09:
swprintf(&replaceBuf[d], 5, L"");
d += 3;
break;
case 0x0A:
swprintf(&replaceBuf[d], 10, L"");
d += 4;
break;
default:
replaceBuf[d++] = s[c];
break;
}
c++;
}
replaceBuf[d++] = 0;
#ifdef DUMP_STR
fputws(replaceBuf, sf);
fputws(L"\n", sf);
#endif
return replaceBuf;
}
wchar_t* putMask(psoOpcode* opcode, unsigned char* opArgs, wchar_t* mask)
{
unsigned c, c2 = 0;
long argOfs = 0;
wchar_t* t;
wchar_t* nt1 = NULL;
wchar_t argcheck[7];
wchar_t maskproc[4096];
unsigned arg;
maskBuf[0] = 0;
if (mask == NULL)
return NULL;
if (!wcslen(mask))
return NULL;
memcpy(argcheck, mask, 6 * sizeof(wchar_t));
argcheck[6] = 0;
if (wcscmp(argcheck, L"T_ARGS") == 0)
{
#ifdef NO_ARGS
#else
swprintf(maskproc, 4096, opcode->mask);
t = wcstok(maskproc, L", ", &nt1);
c2 = 0;
while (t != NULL)
{
for (c = 0; c < sizeof(opcodeSizes) / sizeof(psoOpcodeArg); c++)
{
if ((wcscmp(t, opcodeSizes[c].arg) == 0) && (opcodeSizes[c].size & 0xFFFF))
{
if (wcslen(maskBuf))
wcscat(maskBuf, L", ");
if (argptrs[c2])
{
if (argreg[c2])
wcscat(maskBuf, argptrs[c2]);
else
{
if ((wcscmp(t, L"T_DATA") == 0) || (wcscmp(t, L"T_STRDATA") == 0) || (wcscmp(t, L"T_FUNC") == 0) || (wcscmp(t, L"T_FUNC2") == 0))
{
if (wcscmp(t, L"T_DATA") == 0)
hexFunctions[numHexFunctions++] = (unsigned)wcstoll(argptrs[c2], NULL, 16);
else
if (wcscmp(t, L"T_STRDATA") == 0)
strFunctions[numHexFunctions++] = (unsigned)wcstoll(argptrs[c2], NULL, 16);
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%u", (unsigned)wcstoll(argptrs[c2], NULL, 16));
}
else
if (wcscmp(t, L"T_FLOAT") == 0)
{
arg = (unsigned)wcstoll(argptrs[c2], NULL, 16);
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%f", *(float*)& arg);
}
else
wcscat(maskBuf, argptrs[c2]);
}
c2++;
}
}
}
t = wcstok(NULL, L", ", &nt1);
}
for (c = 0; c < numArgs; c++)
argptrs[c] = NULL;
numArgs = 0;
argidx = 0;
argbuf[0] = 0;
#endif
return &maskBuf[0];
}
swprintf(maskproc, 4096, mask);
t = wcstok(maskproc, L", ", &nt1);
while (t != NULL)
{
for (c = 0; c < sizeof(opcodeSizes) / sizeof(psoOpcodeArg); c++)
{
if ((wcscmp(t, opcodeSizes[c].arg) == 0) && (opcodeSizes[c].size & 0xFFFF))
{
if (argOfs)
wcscat(maskBuf, L", ");
#ifndef NO_ARGS
if (wcscmp(t, L"T_VASTART") == 0)
vaStarted = 1;
else
if (wcscmp(t, L"T_VAEND") == 0)
{
vaStarted = 0;
argbuf[0] = 0;
}
else
#endif
if (wcscmp(t, L"T_STR") == 0)
{
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"\'%s\'", replaceStr((wchar_t*)& opArgs[argOfs]));
argOfs += (wcslen((wchar_t*)& opArgs[argOfs]) * 2) + 2;
}
else
if (wcscmp(t, L"T_SWITCH") == 0)
{
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%u:", opArgs[argOfs]);
c2 = opArgs[argOfs++];
while (c2)
{
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%u", *(unsigned short*)& opArgs[argOfs]);
if (c2 > 1)
wcscat(maskBuf, L":");
argOfs += 2;
c2--;
}
}
else
if (wcscmp(t, L"T_SWITCH2B") == 0)
{
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%u:", opArgs[argOfs]);
c2 = opArgs[argOfs++];
while (c2)
{
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%u", opArgs[argOfs]);
if (c2 > 1)
wcscat(maskBuf, L":");
argOfs++;
c2--;
}
}
else
if (wcscmp(t, L"T_DATA") == 0)
{
hexFunctions[numHexFunctions++] = *(unsigned short*)& opArgs[argOfs];
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%u", *(unsigned short*)& opArgs[argOfs]);
argOfs += 2;
}
else
if (wcscmp(t, L"T_STRDATA") == 0)
{
strFunctions[numStrFunctions++] = *(unsigned short*)& opArgs[argOfs];
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%u", *(unsigned short*)& opArgs[argOfs]);
argOfs += 2;
}
else
if ((wcscmp(t, L"T_REG") == 0) || (wcscmp(t, L"T_BREG") == 0))
{
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"R%u", opArgs[argOfs]);
argOfs += 1;
}
else
if (wcscmp(t, L"T_BYTE") == 0)
{
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%02X", opArgs[argOfs]);
argOfs += 1;
}
else
if ((wcscmp(t, L"T_WORD") == 0) || (wcscmp(t, L"T_PFLAG") == 0))
{
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%04X", *(unsigned short*)& opArgs[argOfs]);
argOfs += 2;
}
else
if (wcscmp(t, L"T_DWORD") == 0)
{
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%08X", *(unsigned long*)& opArgs[argOfs]);
argOfs += 4;
}
else
if (wcscmp(t, L"T_FLOAT") == 0)
{
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%f", *(float*)& opArgs[argOfs]);
argOfs += 4;
}
else
if ((wcscmp(t, L"T_FUNC") == 0) || (wcscmp(t, L"T_FUNC2") == 0))
{
swprintf(&maskBuf[wcslen(maskBuf)], 4096 - wcslen(maskBuf), L"%u", *(unsigned short*)& opArgs[argOfs]);
argOfs += 2;
}
}
}
t = wcstok(NULL, L", ", &nt1);
}
return &maskBuf[0];
}
int _tmain(int argc, _TCHAR* argv[])
{
FILE *qf;
long thisFunction = -1;
long binSize;
long datSize;
unsigned char* binData = NULL;
unsigned char* datData = NULL;
long numFunctions;
long binOfs;
long* functionPointers;
long* functionOrder;
long functOrderOffset = 0;
int functOrder = 0;
int isFunction;
int isStrFunction;
int isHexFunction;
long hexEnd;
long scriptOffset;
long c, c2;
long eos;
//long scriptCheck;
long opOfs;
long argSize;
long scriptSize;
unsigned opcode;
unsigned char* prsbuf;
unsigned char* qstbuf;
int decompressed = 0;
int goodOp = 0;
long prsSize, qstSize;
wchar_t quest_filename[32];
FILE *df;
wchar_t filebuf[4096];
psoOpcode* o;
wprintf(L"\nPhantasy Star Online Blue Burst Quest Disassembler version 2.4 by Sodaboy\n");
wprintf(L"-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
GetModuleFileName(NULL, asmFileName, 4096);
c2 = 0;
for (c = 0; c < (long)wcslen(asmFileName); c++)
{
if (asmFileName[c] == 92)
c2 = c;
}
if (c2 < 4090)
swprintf_s(&asmFileName[c2 + 1], 4096 - c2, L"asm.txt");
c = c2 = 0;
parseOpcodeList();
if (argc > 1)
{
qf = _wfopen(argv[1], L"rb");
if (!qf)
{
wprintf(L"Couldn't open %s\n", argv[1]);
return 1;
}
_wcslwr(argv[1]);
if (wcsstr(argv[1], L".qst"))
{
fseek(qf, 0, SEEK_END);
qstSize = ftell(qf);
fseek(qf, 0, SEEK_SET);
qstbuf = (unsigned char*)malloc(qstSize);
if (!qstbuf)
{
fclose(qf);
wprintf(L"Failed to allocate memory\n");
return 1;
}
fread((void*)qstbuf, 1, qstSize, qf);
fclose(qf);
prsbuf = (unsigned char*)malloc(qstSize);
if (!prsbuf)
{
fclose(qf);
wprintf(L"Failed to allocate memory\n");
return 1;
}
c = 0;
prsSize = 0;
while (c < qstSize)
{
if (((*(unsigned short*)& qstbuf[c + 0x02]) == 0x13) && (strstr((char*)& qstbuf[c + 0x08], ".dat")))
{
memcpy((void*)& prsbuf[prsSize], (void*)& qstbuf[c + 0x18], *(long*)& qstbuf[c + 0x418]);
prsSize += *(long*)& qstbuf[c + 0x418];
}
c2 = *(unsigned short*)& qstbuf[0];
if (c2 % 8)
c2 += (8 - (c2 % 8));
c += c2;
}
datSize = prs_decompress_buf(prsbuf, &datData, prsSize);
if ((int)datSize < 0)
{
wprintf(L"Failed to allocate memory\n");
return 1;
}
c = 0;
prsSize = 0;
while (c < qstSize)
{
if (((*(unsigned short*)&qstbuf[c + 0x02]) == 0x13) && (strstr((char*)&qstbuf[c + 0x08], ".bin")))
{
memcpy((void*)&prsbuf[prsSize], (void*)&qstbuf[c + 0x18], *(long*)&qstbuf[c + 0x418]);
prsSize += *(long*)&qstbuf[c + 0x418];
}
c2 = *(unsigned short*)&qstbuf[0];
if (c2 % 8)
c2 += (8 - (c2 % 8));
c += c2;
}
free(qstbuf);
binSize = prs_decompress_buf(prsbuf, &binData, prsSize);
if ((int)binSize < 0)
{
wprintf(L"Failed to allocate memory\n");
return 1;
}
free(prsbuf);
decompressed = 1;
}
}
else
{
qf = fopen("quest.bin", "rb");
if (!qf)
{
wprintf(L"Couldn't open quest.bin\n\nUsage: quest_disasm [file.bin]\n");
return 1;
}
}
if (!decompressed)
{
fseek(qf, 0, SEEK_END);
binSize = ftell(qf);
fseek(qf, 0, SEEK_SET);
binData = (unsigned char*)malloc(binSize);
if (!binData)
{
fclose(qf);
wprintf(L"Failed to allocate memory\n");
return 1;
}
fread((void*)binData, 1, binSize, qf);
fclose(qf);
}
questNum = *(unsigned short*)&binData[0x10];
swprintf(quest_filename, 32, L"quest%u.pasm.strings", questNum);
#ifdef DUMP_STR
wprintf(L"Writing strings to %s ...\n", quest_filename);
_wfopen_s(&sf, quest_filename, L"w, ccs=UTF-16LE");
if (!sf)
{
wprintf(L"Failed to open %s for writing!\n", quest_filename);
return 1;
}
#endif
if (datData)
{
swprintf(quest_filename, 32, L"quest%u.dat", questNum);
wprintf(L"Extracting object data as %s...\n", quest_filename);
_wfopen_s(&df, quest_filename, L"wb");
if (df)
{
fwrite(datData, datSize, 1, df);
fclose(df);
df = NULL;
}
else
{
wprintf(L"Could not write to %s!\n", quest_filename);
exit(1);
}
}
swprintf(quest_filename, 32, L"quest%u.pasm.header", questNum);
wprintf(L"Writing header information to %s ...\n", quest_filename);
_wfopen_s(&df, quest_filename, L"w, ccs=UTF-16LE");
if (!df)
{
wprintf(L"Failed to open %s for writing!\n", quest_filename);
return 1;
}
swprintf(filebuf, 4096, L"%s\n", replaceStr((wchar_t*)& binData[0x18]));
fputws(filebuf, df);
swprintf(filebuf, 4096, L"%u\n", *(unsigned short*)& binData[0x10]);
fputws(filebuf, df);
swprintf(filebuf, 4096, L"%s\n", replaceStr((wchar_t*)& binData[0x58]));
fputws(filebuf, df);
swprintf(filebuf, 4096, L"%s\n", replaceStr((wchar_t*)& binData[0x158]));
fputws(filebuf, df);
fclose(df);
swprintf(quest_filename, 32, L"quest%u.pasm", questNum);
wprintf(L"Disassembling quest \"%s\" to %s ...\n", (wchar_t*)& binData[0x18], quest_filename);
_wfopen_s(&df, quest_filename, L"w, ccs=UTF-16LE");
if (!df)
{
wprintf(L"Failed to open %s for writing!\n", quest_filename);
return 1;
}
filebuf[0] = 0;
numFunctions = (*(long*)&binData[0x08] - *(long*)&binData[0x04]) / 4L;
functionPointers = (long*)malloc(numFunctions * 4L);
functionOrder = (long*)malloc(numFunctions * 8L + 8);
if (!functionPointers)
{
fclose(qf);
wprintf(L"Failed to allocate memory\n");
return 1;
}
hexFunctions = (long*)malloc(65536 * 4L);
if (!hexFunctions)
{
fclose(qf);
wprintf(L"Failed to allocate memory\n");
return 1;
}
numHexFunctions = 0;
strFunctions = (long*)malloc(65536 * 4L);
if (!strFunctions)
{
fclose(qf);
wprintf(L"Failed to allocate memory\n");
return 1;
}
numStrFunctions = 0;
scriptOffset = *(long*)&binData[0x00];
binOfs = *(long*)&binData[0x04];
for (c = 0; c < numFunctions; c++)
{
functionPointers[c] = *(long*)&binData[binOfs];
binOfs += 4;
}
scriptSize = *(long*)&binData[0x04] - *(long*)&binData[0x00];
//wprintf(L"[Script Size: %i bytes]\n\n", scriptSize);
binOfs = *(long*)&binData[0x00];
eos = binOfs + scriptSize;
functOrderOffset = binOfs;
while (binOfs < eos)
{
isHexFunction = 0;
isStrFunction = 0;
isFunction = 0;
for (c = 0; c < numFunctions; c++)
{
if ((functionPointers[c] + scriptOffset) == binOfs)
{
functionOrder[functOrder * 2] = c;
functionOrder[((functOrder++) * 2) + 1] = binOfs;
thisFunction = c;
isFunction = 1;
if (wcslen(filebuf))
{
filebuf[8] = 0;
fputws(filebuf, df);
fputws(L"\n", df);
filebuf[0] = 0;
}
swprintf(filebuf, 4096, L"%u:", c);
if (wcslen(filebuf) < 8)
for (c2 = wcslen(filebuf); c2 < 8; c2++)
filebuf[c2] = 0x20;
for (c2 = 0; c2 < numHexFunctions; c2++)
{
if (hexFunctions[c2] == c)
{
isHexFunction = 1;
break;
}
}
for (c2 = 0; c2 < numStrFunctions; c2++)
{
if (strFunctions[c2] == c)
{
isStrFunction = 1;
break;
}
}
}
}
if ((binData[binOfs] != 0xF8) &&
(binData[binOfs] != 0xF9))
opcode = binData[binOfs];
else
opcode = ((unsigned)binData[binOfs] << 8) + (unsigned)binData[binOfs + 1];
goodOp = 0;
for (c = 0; c < numOpcodes; c++)
{
if (opcode_list[c]->val == opcode)
{
goodOp = 1;
o = opcode_list[c];
break;
}
}
if ((!goodOp) && (!isFunction))
{
wprintf(L"FATAL: Don't know how to handle opcode %04X!", opcode);
exit(1);
}
if ((goodOp == 0) &&
(isFunction) &&
(!isHexFunction) &&
(!isStrFunction))
{
wprintf(L"WARNING: Couldn't disassemble function %u properly! Function was dumped as HEX. (%04X)\n", thisFunction, opcode);
isHexFunction = 1;
}
if (isStrFunction)
{
hexEnd = eos;
for (c = binOfs + 1; c < eos; c++)
{
for (c2 = 0; c2 < numFunctions; c2++)
{
if ((functionPointers[c2] + scriptOffset) == c)
{
hexEnd = c;
break;
}
}
if (hexEnd != eos)
break;
}
swprintf(&filebuf[8], 4088, L"STR: %s\n", replaceStr((wchar_t*)& binData[binOfs]));
fputws(filebuf, df);
binOfs += (hexEnd - binOfs);
filebuf[0] = 0;
}
else
if (isHexFunction)
{
hexEnd = eos;
for (c = binOfs + 1; c < eos; c++)
{
for (c2 = 0; c2 < numFunctions; c2++)
{
if ((functionPointers[c2] + scriptOffset) == c)
{
hexEnd = c;
break;
}
}
if (hexEnd != eos)
break;
}
swprintf(&filebuf[8], 4088, L"HEX:");
c2 = 0;
for (c = binOfs; c < hexEnd; c++)
{
swprintf(&filebuf[wcslen(filebuf)], 4096 - wcslen(filebuf), L" %02X", binData[binOfs++]);
c2++;
if ((c2 == 17) && ((c + 1) < hexEnd))
{
swprintf(&filebuf[wcslen(filebuf)], 4096 - wcslen(filebuf), L"\n HEX:");
c2 = 0;
}
}
wcscat(filebuf, L"\n");
fputws(filebuf, df);
filebuf[0] = 0;
}
else
{
// Check the opcode
opOfs = binOfs;
if (opcode >= 0xF800)
binOfs += 2;
else
binOfs++;
argSize = getMaskSize(&binData[binOfs], o->mask);
/*fputws(o->name, df);
fputws(L"\n", df);*/
if ((argSize & 0x10000) && (!vaStarted))
{
if ((o->val == 0x48) || (o->val == 0x4A) || (o->val == 0x4C))
argreg[numArgs] = 1;
else
argreg[numArgs] = 0;
argptrs[numArgs++] = &argbuf[argidx];
swprintf(&argbuf[argidx], 4096 - argidx, putMask(o, &binData[binOfs], o->mask));
argidx += wcslen(&argbuf[argidx]) + 4;
if ((argidx > 4096) || (numArgs > 255))
{
wprintf(L"Out of argument space! %u %u\n", argidx, numArgs);
exit(1);
}
}
else
{
if (argSize == -1)
{
wprintf(L"Can't finish disassembly!\n\nNo opcode mask data for opcode (%u) %s at %u (Function %u)", opcode, o->name, opOfs, thisFunction);
return 1;
}
if (wcslen(filebuf) < 8)
for (c = wcslen(filebuf); c < 8; c++)
filebuf[c] = 0x20;
swprintf(&filebuf[8], 4088, L"%s ", o->name);
if (putMask(o, &binData[binOfs], o->mask))
wcscat(filebuf, maskBuf);
wcscat(filebuf, L"\n");
fputws(filebuf, df);
filebuf[0] = 0;
}
binOfs += argSize & 0xFFFF;
}
}
/*
scriptCheck = 0;
for (c = 0; c < functOrder; c++)
{
thisFunction = functionOrder[c * 2];
printf("Function %08X (file offset %i, pointer %i)\n",
thisFunction,
functionOrder[(c * 2) + 1],
functionPointers[thisFunction]);
if (c > 0)
scriptCheck += functionOrder[(c * 2) + 1] - functionOrder[((c - 1) * 2) + 1];
}
if (functOrder)
scriptCheck += eos - functionOrder[((functOrder - 1) * 2) + 1];
printf("Original script size: %i bytes (%i bytes check)\n", scriptSize, scriptCheck);
*/
free(strFunctions);
free(hexFunctions);
free(functionOrder);
free(functionPointers);
free(binData);
fclose(df);
#ifdef DUMP_STR
fclose(sf);
#endif
wprintf(L"Disassembly complete!\n");
return 0;
}