187 lines
4.0 KiB
C++
187 lines
4.0 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <assert.h>
|
|
#include "decompiler.h"
|
|
#include "platform_util.h"
|
|
|
|
sp_decomp_t *Sp_InitDecomp(const char *file, int *err)
|
|
{
|
|
sp_decomp_t *dc;
|
|
sp_file_t *plugin;
|
|
|
|
if ((plugin = Sp_ReadPlugin(file, err)) == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
dc = new sp_decomp_t;
|
|
memset(dc, 0, sizeof(sp_decomp_t));
|
|
dc->plugin = plugin;
|
|
dc->pcode_map = (cell_t *)malloc(dc->plugin->pcode_size);
|
|
memset(dc->pcode_map, 0, dc->plugin->pcode_size);
|
|
|
|
#define OPDEF(num,enm,str,prms) \
|
|
dc->opdef[num].name = str; \
|
|
dc->opdef[num].params = prms;
|
|
#include "opcodes.tbl"
|
|
#undef OPDEF
|
|
|
|
if (plugin->debug.ntv != NULL)
|
|
{
|
|
assert(plugin->debug.ntv->num_entries == plugin->num_natives);
|
|
dc->natives = new FunctionInfo[plugin->num_natives];
|
|
memset(dc->natives, 0, sizeof(FunctionInfo) * plugin->num_natives);
|
|
|
|
/* Unfurl this mess. */
|
|
uint8_t *cursor = (uint8_t *)plugin->debug.ntv;
|
|
|
|
cursor += sizeof(sp_fdbg_ntvtab_t);
|
|
for (uint32_t i = 0; i < plugin->num_natives; i++)
|
|
{
|
|
sp_fdbg_native_t *native = (sp_fdbg_native_t *)cursor;
|
|
|
|
uint32_t idx = native->index;
|
|
|
|
assert(dc->natives[idx].name[0] == '\0');
|
|
|
|
Sp_Format(dc->natives[idx].name,
|
|
sizeof(dc->natives[idx].name),
|
|
"%s",
|
|
plugin->debug.stringbase + native->name);
|
|
dc->natives[idx].tag = Sp_FindTag(plugin, native->tagid);
|
|
dc->natives[idx].num_known_args = native->nargs;
|
|
|
|
cursor += sizeof(sp_fdbg_native_t);
|
|
|
|
for (uint32_t j = 0; j < dc->natives[idx].num_known_args; j++)
|
|
{
|
|
sp_fdbg_ntvarg_t *arg = (sp_fdbg_ntvarg_t *)cursor;
|
|
dc->natives[idx].known_args[j].name =
|
|
plugin->debug.stringbase + arg->name;
|
|
dc->natives[idx].known_args[j].tag =
|
|
Sp_FindTag(plugin, arg->tagid);
|
|
dc->natives[idx].known_args[j].dimcount = arg->dimcount;
|
|
|
|
cursor += sizeof(sp_fdbg_ntvarg_t);
|
|
if (arg->dimcount != 0)
|
|
{
|
|
dc->natives[idx].known_args[j].dims = (sp_fdbg_arraydim_t *)cursor;
|
|
cursor += sizeof(sp_fdbg_arraydim_t) * arg->dimcount;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return dc;
|
|
}
|
|
|
|
void Sp_FreeDecomp(sp_decomp_t *decomp)
|
|
{
|
|
FunctionInfo *info, *info_temp;
|
|
|
|
info = decomp->funcs;
|
|
while (info != NULL)
|
|
{
|
|
info_temp = info->next;
|
|
delete info;
|
|
info = info_temp;
|
|
}
|
|
|
|
Sp_FreePlugin(decomp->plugin);
|
|
free(decomp->pcode_map);
|
|
delete [] decomp->natives;
|
|
delete decomp;
|
|
}
|
|
|
|
PrintBuffer::PrintBuffer() : printbuf(NULL), printbuf_alloc(0), printbuf_pos(0)
|
|
{
|
|
}
|
|
|
|
PrintBuffer::~PrintBuffer()
|
|
{
|
|
free(printbuf);
|
|
}
|
|
|
|
void PrintBuffer::Grow(size_t len)
|
|
{
|
|
if (printbuf_pos + len > printbuf_alloc)
|
|
{
|
|
if (printbuf_alloc == 0)
|
|
{
|
|
printbuf_alloc = len * 8;
|
|
}
|
|
else
|
|
{
|
|
printbuf_alloc += len;
|
|
printbuf_alloc *= 2;
|
|
}
|
|
|
|
printbuf = (char *)realloc(printbuf, printbuf_alloc);
|
|
}
|
|
}
|
|
|
|
void PrintBuffer::Append(const char *fmt, ...)
|
|
{
|
|
size_t len;
|
|
va_list ap;
|
|
char buffer[2048];
|
|
|
|
va_start(ap, fmt);
|
|
len = Sp_FormatArgs(buffer, sizeof(buffer), fmt, ap);
|
|
va_end(ap);
|
|
|
|
Grow(len + 1);
|
|
|
|
strcpy(&printbuf[printbuf_pos], buffer);
|
|
printbuf_pos += len;
|
|
}
|
|
|
|
void PrintBuffer::Set(const char *fmt, ...)
|
|
{
|
|
size_t len;
|
|
va_list ap;
|
|
char buffer[2048];
|
|
|
|
va_start(ap, fmt);
|
|
len = Sp_FormatArgs(buffer, sizeof(buffer), fmt, ap);
|
|
va_end(ap);
|
|
|
|
Reset();
|
|
Grow(len + 1);
|
|
|
|
printbuf = (char *)realloc(printbuf, printbuf_alloc);
|
|
strcpy(&printbuf[printbuf_pos], buffer);
|
|
printbuf_pos += len;
|
|
}
|
|
|
|
void PrintBuffer::Prepend(const char *fmt, ...)
|
|
{
|
|
size_t len;
|
|
va_list ap;
|
|
char buffer[2048];
|
|
|
|
va_start(ap, fmt);
|
|
len = Sp_FormatArgs(buffer, sizeof(buffer), fmt, ap);
|
|
va_end(ap);
|
|
|
|
Grow(len + 1);
|
|
|
|
/* Move old data forward. Move one extra byte for the null terminator. */
|
|
memmove(&printbuf[len], printbuf, printbuf_pos + 1);
|
|
printbuf_pos += len;
|
|
/* Move the new data in. */
|
|
memcpy(printbuf, buffer, len);
|
|
}
|
|
|
|
void PrintBuffer::Reset()
|
|
{
|
|
printbuf_pos = 0;
|
|
}
|
|
|
|
void PrintBuffer::Dump(FILE *fp)
|
|
{
|
|
fprintf(fp, "%s", printbuf);
|
|
}
|