Added hitasm

This commit is contained in:
Fatbag 2013-01-23 15:58:58 -06:00
parent 5488883991
commit 0ec39fd968
15 changed files with 12469 additions and 368 deletions

View file

@ -21,326 +21,20 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#ifndef min
#define min(x,y) ((x) < (y) ? (x) : (y))
#endif
#ifndef max
#define max(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifndef read_int32
#define read_uint32(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#define read_uint16(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
#endif
static void Shutdown_M(const char * Message, ...);
#include "hitutils.h"
enum {
hsm, hot, evt, hit, out, filecount
};
enum {
VERSION_TS1 = 1, VERSION_TSO
};
#define OPERAND_BYTES(x) (x)
#define OPERAND(x, y) ((y)<<((x)*4+4))
#define UNIMPLEMENTED ((uint32_t)~0)
enum operand_t {
o_byte = 1,
o_dword,
o_address,
o_variable,
o_jump
};
typedef struct {
const char * Name;
uint32_t Operands;
} instruction_t;
typedef struct {
const char * Name;
uint32_t Value;
} global_t;
static const uint8_t HITHeader[] = {'H','I','T','!',0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,'T','R','A','X'};
static const instruction_t Instructions[] = {
{"note", UNIMPLEMENTED},
{"note_on", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"note_off", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"loadb", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_byte)},
{"loadl", OPERAND_BYTES(5) | OPERAND(0, o_variable) | OPERAND(1, o_dword)},
{"set", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"call", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"return", OPERAND_BYTES(0)},
{"wait", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"callentrypoint", UNIMPLEMENTED},
{"wait_samp", OPERAND_BYTES(0)},
{"end", OPERAND_BYTES(0)},
{"jump", OPERAND_BYTES(1) | OPERAND(0, o_jump)},
{"test", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"nop", OPERAND_BYTES(0)},
{"add", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"sub", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"div", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"mul", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"cmp", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"less", UNIMPLEMENTED},
{"greater", UNIMPLEMENTED},
{"not", UNIMPLEMENTED},
{"rand", OPERAND_BYTES(3) | OPERAND(0, o_variable) | OPERAND(1, o_variable) | OPERAND(2, o_variable)},
{"abs", UNIMPLEMENTED},
{"limit", UNIMPLEMENTED},
{"error", UNIMPLEMENTED},
{"assert", UNIMPLEMENTED},
{"add_to_group", UNIMPLEMENTED},
{"remove_from_group", UNIMPLEMENTED},
{"get_var", UNIMPLEMENTED},
{"loop", OPERAND_BYTES(0)},
{"set_loop", OPERAND_BYTES(0)},
{"callback", UNIMPLEMENTED},
{"smart_add", UNIMPLEMENTED},
{"smart_remove", UNIMPLEMENTED},
{"smart_removeall", UNIMPLEMENTED},
{"smart_setcrit", UNIMPLEMENTED},
{"smart_choose", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"and", UNIMPLEMENTED},
{"nand", UNIMPLEMENTED},
{"or", UNIMPLEMENTED},
{"nor", UNIMPLEMENTED},
{"xor", UNIMPLEMENTED},
{"max", OPERAND_BYTES(5) | OPERAND(0, o_variable) | OPERAND(1, o_dword)},
{"min", OPERAND_BYTES(5) | OPERAND(0, o_variable) | OPERAND(1, o_dword)},
{"inc", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"dec", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"printreg", UNIMPLEMENTED},
{"play_trk", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"kill_trk", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"push", UNIMPLEMENTED},
{"push_mask", UNIMPLEMENTED},
{"push_vars", UNIMPLEMENTED},
{"call_mask", UNIMPLEMENTED},
{"call_push", UNIMPLEMENTED},
{"pop", UNIMPLEMENTED},
{"test1", OPERAND_BYTES(0)},
{"test2", OPERAND_BYTES(0)},
{"test3", OPERAND_BYTES(0)},
{"test4", OPERAND_BYTES(0)},
{"ifeq", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"ifne", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"ifgt", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"iflt", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"ifge", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"ifle", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"smart_setlist", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"seqgroup_kill", OPERAND_BYTES(1) | OPERAND(0, o_byte)},
{"seqgroup_wait", UNIMPLEMENTED},
{"seqgroup_return", OPERAND_BYTES(1) | OPERAND(0, o_byte)},
{"getsrcdatafield", OPERAND_BYTES(3) | OPERAND(0, o_variable) | OPERAND(1, o_variable) | OPERAND(2, o_variable)},
{"seqgroup_trkid", OPERAND_BYTES(2) | OPERAND(0, o_byte) | OPERAND(1, o_byte)},
{"setll", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"setlt", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"settl", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"waiteq", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"waitne", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"waitgt", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"waitlt", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"waitge", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"waitle", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"duck", OPERAND_BYTES(0)},
{"unduck", OPERAND_BYTES(0)},
{"testx", UNIMPLEMENTED},
{"setlg", OPERAND_BYTES(5) | OPERAND(0, o_variable) | OPERAND(1, o_dword)},
{"setgl", OPERAND_BYTES(5) | OPERAND(0, o_variable) | OPERAND(1, o_dword)},
{"throw", UNIMPLEMENTED},
{"setsrcdatafield", OPERAND_BYTES(3) | OPERAND(0, o_variable) | OPERAND(1, o_variable) | OPERAND(2, o_variable)},
{"stop_trk", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"setchanreg", UNIMPLEMENTED},
{"play_note", UNIMPLEMENTED},
{"stop_note", UNIMPLEMENTED},
{"kill_note", UNIMPLEMENTED},
{"smart_index", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"note_on_loop", OPERAND_BYTES(1) | OPERAND(0, o_variable)}
};
static const char *Registers[] = {
"arg0",
"arg1",
"arg2",
"arg3",
"arg4",
"v1",
"v2",
"v3",
"v4",
"v5",
"v6",
"v7",
"v8",
"h1",
"h2",
"h3",
"h4"
};
#define TSOGlobalCount 66
static const global_t TSOGlobals[] = {
{"argstype", 0x10},
{"trackdatasource", 0x11},
{"patch", 0x12},
{"priority", 0x13},
{"vol", 0x14},
{"extvol", 0x15},
{"pan", 0x16},
{"pitch", 0x17},
{"paused", 0x18},
{"fxtype", 0x19},
{"fxlevel", 0x1a},
{"duckpri", 0x1b},
{"Is3d", 0x1c},
{"IsHeadRelative", 0x1d},
{"MinDistance", 0x1e},
{"MaxDistance", 0x1f},
{"X", 0x20},
{"Y", 0x21},
{"Z", 0x22},
{"attack", 0x23},
{"decay", 0x24},
{"IsStreamed", 0x25},
{"bufsizemult", 0x26},
{"fade_dest", 0x27},
{"fade_var", 0x28},
{"fade_speed", 0x29},
{"fade_on", 0x2a},
{"Preload", 0x2b},
{"isplaying", 0x2c},
{"whattodowithupdate", 0x2d},
{"tempo", 0x2e},
{"target", 0x2f},
{"ctrlgroup", 0x30},
{"interrupt", 0x31},
{"ispositioned", 0x32},
{"AppObjectId", 0x34},
{"callbackarg", 0x35},
{"pitchrandmin", 0x36},
{"pitchrandmax", 0x37},
{"spl", 0x38},
{"sem", 0x39},
{"starttrackid", 0x3a},
{"endtrackid", 0x3b},
{"startdelay", 0x3c},
{"fadeinspeed", 0x3d},
{"fadeoutspeed", 0x3e},
{"hitlist", 0x3f},
{"SimSpeed", 0x64},
{"test_g1", 0x65},
{"test_g2", 0x66},
{"test_g3", 0x67},
{"test_g4", 0x68},
{"test_g5", 0x69},
{"test_g6", 0x6a},
{"test_g7", 0x6b},
{"test_g8", 0x6c},
{"test_g9", 0x6d},
{"main_songnum", 0x6e},
{"main_musichitlistid", 0x6f},
{"campfire_nexttrack", 0x70},
{"campfire_busy", 0x71},
{"main_duckpri", 0x7b},
{"main_vol", 0x7c},
{"main_fxtype", 0x7d},
{"main_fxlevel", 0x7e},
{"main_pause", 0x7f}
};
#define TS1GlobalCount 71
static const global_t TS1Globals[] = {
{"priority", 0x11},
{"vol", 0x12},
{"extvol", 0x13},
{"pan", 0x14},
{"pitch", 0x15},
{"paused", 0x16},
{"fxtype", 0x17},
{"fxlevel", 0x18},
{"duckpri", 0x19},
{"Is3d", 0x1a},
{"IsHeadRelative", 0x1b},
{"MinDistance", 0x1c},
{"MaxDistance", 0x1d},
{"X", 0x1e},
{"Y", 0x1f},
{"Z", 0x20},
{"filter_type", 0x21},
{"filter_cutoff", 0x22},
{"filter_level", 0x23},
{"attack", 0x24},
{"decay", 0x25},
{"IsStreamed", 0x26},
{"BufSizeMult", 0x27},
{"fade_dest", 0x28},
{"fade_var", 0x29},
{"fade_speed", 0x2a},
{"Preload", 0x2b},
{"IsLooped", 0x2c},
{"fade_on", 0x2d},
{"isplaying", 0x2e},
{"source", 0x2f},
{"patch", 0x32},
{"WhatToDoWithUpdate", 0x33},
{"tempo", 0x34},
{"target", 0x35},
{"mutegroup", 0x36},
{"interrupt", 0x37},
{"IsPositioned", 0x38},
{"Spl", 0x39},
{"MultipleInstances", 0x3a},
{"AssociatedTrack1", 0x3b},
{"AssociatedTrack2", 0x3c},
{"AssociatedTrack3", 0x3d},
{"AssociatedTrack4", 0x3e},
{"AssociatedTrack5", 0x3f},
{"AssociatedTrack6", 0x40},
{"AssociatedTrack7", 0x41},
{"AssociatedTrack8", 0x42},
{"SimSpeed", 0x64},
{"test_g1", 0x65},
{"test_g2", 0x66},
{"test_g3", 0x67},
{"test_g4", 0x68},
{"test_g5", 0x69},
{"test_g6", 0x6a},
{"test_g7", 0x6b},
{"test_g8", 0x6c},
{"test_g9", 0x6d},
{"main_songnum", 0x6e},
{"main_musichitlistid", 0x6f},
{"campfire_nexttrack", 0x70},
{"campfire_busy", 0x71},
{"main_duckpri", 0x7b},
{"main_vol", 0x7c},
{"main_fxtype", 0x7d},
{"main_fxlevel", 0x7e},
{"main_pause", 0x7f},
};
static __inline const char * find_global(uint32_t x, const global_t * Globals, size_t GlobalCount){
static __inline const char * find_variable(uint32_t x, const variable_t * Variables, size_t VariableCount){
size_t i;
for(i=0; i<GlobalCount; i++)
if(Globals[i].Value == x)
return Globals[i].Name;
for(i=0; i<VariableCount; i++)
if(Variables[i].Value == x)
return Variables[i].Name;
return NULL;
}
typedef struct {
uint8_t * Data;
size_t Size;
} ByteReaderContext;
enum TokenizeType {
TK_STRING,
TK_ID
@ -531,7 +225,7 @@ static __inline void read_hot_trackdata(uint8_t * Data, size_t Size, addresslist
while(1){
address_t * Address;
uint32_t SoundID, LogicalAddress;
if(!brc.Size || *brc.Data == '\n' || *brc.Data == '[') return;
if(!brc.Size || *brc.Data == '\r' || *brc.Data == '\n' || *brc.Data == '[') return;
if(!parser_find(&brc,
"=", &SoundID, TK_ID,
"\n", &LogicalAddress, TK_ID,
@ -559,7 +253,7 @@ static __inline void read_hot_track(uint8_t * Data, size_t Size, addresslist_t *
address_t * Address;
char * Name;
uint32_t TrackID;
if(!brc.Size || *brc.Data == '\n' || *brc.Data == '[') return;
if(!brc.Size || *brc.Data == '\r' || *brc.Data == '\n' || *brc.Data == '[') return;
if(!parser_find(&brc,
"=", &TrackID, TK_ID,
",", NULL,
@ -604,25 +298,15 @@ static void Shutdown(){
fclose(hFile);
}
static void Shutdown_M(const char * Message, ...){
va_list args;
va_start(args, Message);
vfprintf(stderr, Message, args);
va_end(args);
Shutdown();
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[]){
unsigned i, j, addr;
unsigned i, addr;
int SimsVersion = 0;
int overwrite = 0;
int ShowAddresses = 0;
int length;
size_t filesize[filecount-1];
const global_t * Globals;
size_t GlobalCount;
const variable_t * Variables;
size_t VariableCount;
uint32_t SymbolTable = 0;
uint32_t BaseSoundID = 0, BaseSoundIDSet = 0;
@ -661,19 +345,19 @@ int main(int argc, char *argv[]){
else break;
}
path[hit] = argv[i];
for(j=0; j<filecount; j++)
if(path[j])
path[j] = strdup(path[j]); /* necessary for free(path[i]) in Shutdown_M */
for(i=0; i<filecount; i++)
if(path[i])
path[i] = strdup(path[i]); /* necessary for free(path[i]) in Shutdown_M */
if(!SimsVersion)
Shutdown_M("%sSims version not specified. (Use -ts1 or -tso.)\n", "hitdump: Error: ");
if(SimsVersion == VERSION_TS1){
Globals = TS1Globals;
GlobalCount = TS1GlobalCount;
Variables = TS1Variables;
VariableCount = TS1VariableCount;
}else{
Globals = TSOGlobals;
GlobalCount = TSOGlobalCount;
Variables = TSOVariables;
VariableCount = TSOVariableCount;
}
length = strlen(path[hit]);
@ -813,7 +497,7 @@ int main(int argc, char *argv[]){
"; tkd_GenericHitList 3\r\n"
"\r\n"
"INCLUDE defaultsyms.txt\r\n"
"INCLUDE SimsGlobals.txt\r\n"
"INCLUDE SimsVariables.txt\r\n"
"\r\n"
"LIST [Options] Version=1\r\n"
"LIST [Options] LoadPriority=2\r\n"
@ -878,7 +562,7 @@ int main(int argc, char *argv[]){
}
opcode = data[hit][addr];
if(opcode == 0 || opcode > 96)
if(opcode == 0 || opcode > InstructionCount)
Shutdown_M("%sIllegal opcode 0x%02X at address 0x%08X.\n", "hitdump: Error: ", opcode, addr);
instruction = Instructions + opcode - 1;
@ -910,14 +594,12 @@ int main(int argc, char *argv[]){
else fprintf(hFile, " #%u", LogicalAddress);
addr += 4;
}else if(type == o_variable){
int x = data[hit][addr];
if(x > 16){
const char * Global = find_global(x, Globals, GlobalCount);
if(Global == NULL)
Shutdown_M("%sInvalid %s operand 0x%02X for '%s' instruction at address 0x%08X (expected %s).\n",
"hitdump: Error: ", position[i], x, instruction->Name, addr, "argument, register, or global");
fprintf(hFile, " %s", Global);
} else fprintf(hFile, " %s", Registers[x]);
unsigned x = data[hit][addr];
const char * Variable = find_variable(x, Variables, VariableCount);
if(Variable == NULL)
Shutdown_M("%sInvalid %s operand 0x%02X for '%s' instruction at address 0x%08X (expected variable).\n",
"hitdump: Error: ", position[i], x, instruction->Name, addr);
fprintf(hFile, " %s", Variable);
addr += 1;
}else if(type == o_jump){
unsigned x = 0;
@ -934,14 +616,13 @@ int main(int argc, char *argv[]){
else fprintf(hFile, " #%u", x);
addr += 4;
}else{
const char * Variable;
x = data[hit][addr];
if(x > 16){
const char * Global = find_global(x, Globals, GlobalCount);
if(Global == NULL)
Shutdown_M("%sInvalid %s operand 0x%02X for '%s' instruction at address 0x%08X (expected %s).\n",
"hitdump: Error: ", position[i], x, instruction->Name, addr, "argument, register, or global");
fprintf(hFile, " %s", Global);
} else fprintf(hFile, " %s", Registers[x]);
Variable = find_variable(x, Variables, VariableCount);
if(Variable == NULL)
Shutdown_M("%sInvalid %s operand 0x%02X for '%s' instruction at address 0x%08X (expected variable).\n",
"hitdump: Error: ", position[i], x, instruction->Name, addr);
fprintf(hFile, " %s", Variable);
addr += (data[hit][addr] != 0x05 && data[hit][addr] != 0x06) ? 4 : 1;
}
}