Skip to content

Commit

Permalink
thanm: fix negative script id recompiling
Browse files Browse the repository at this point in the history
Turns out that instructions don't refer to scripts by their ID, but by their index in the file, which is not always the same.

Why.
  • Loading branch information
Priw8 committed Aug 20, 2020
1 parent 7e80046 commit 2b2710b
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 20 deletions.
3 changes: 2 additions & 1 deletion thanm/anmparse.y
Original file line number Diff line number Diff line change
Expand Up @@ -434,9 +434,10 @@ Script:
reg_reset(state->current_version);
script->offset = malloc(sizeof(*script->offset));
script->offset->id = state->script_id++;
script->real_index = state->script_real_index++;

symbol_id_pair_t* symbol = (symbol_id_pair_t*)malloc(sizeof(symbol_id_pair_t));
symbol->id = script->offset->id;
symbol->id = script->real_index;
symbol->name = $name;
list_append_new(&state->script_names, symbol);
if (state->symbolfp != NULL)
Expand Down
62 changes: 44 additions & 18 deletions thanm/thanm.c
Original file line number Diff line number Diff line change
Expand Up @@ -657,34 +657,55 @@ replace_minus(
}
}

static int
anm_is_valid_script_index(
const anm_archive_t* anm,
int32_t index
) {
anm_entry_t* entry;
anm_script_t* script;
list_for_each(&anm->entries, entry) {
list_for_each(&entry->scripts, script) {
if (script->real_index == index)
return 1;
}
}
return 0;
}

static void
anm_stringify_param(
FILE* stream,
thanm_param_t* param,
thanm_instr_t* instr,
int scriptn
const anm_archive_t* anm,
int32_t scriptn
) {
char* disp = NULL;
char* dest = NULL;
char buf[256];

switch(param->type) {
case 'o':
sprintf(buf, "offset%u", param->val->val.S);
sprintf(buf, "offset%d", param->val->val.S);
replace_minus(buf);
dest = buf;
break;
case 'n':
/* Sprite -1 is used as an empty sprite. */
if (param->val->val.S == -1)
/* Sprite -1 is actually sometimes used to indicate no sprite. */
if (param->val->val.S < 0)
sprintf(buf, "%d", param->val->val.S);
else
sprintf(buf, "sprite%d", param->val->val.S);
dest = buf;
break;
case 'N':
sprintf(buf, "script%d", param->val->val.S);
replace_minus(buf);
if (anm_is_valid_script_index(anm, param->val->val.S)) {
sprintf(buf, "script%d", param->val->val.S);
replace_minus(buf);
} else {
sprintf(buf, "%d", param->val->val.S);
}
dest = buf;
break;
default:
Expand Down Expand Up @@ -811,7 +832,7 @@ thanm_instr_free(
static void
anm_insert_labels(
anm_script_t* script,
int scriptn
int32_t scriptn
) {
thanm_instr_t* instr;
list_for_each(&script->instrs, instr) {
Expand Down Expand Up @@ -870,7 +891,7 @@ anm_read_file(
archive->map = map_base = file_mmap(in, file_size);
map = map_base;

int scriptn = 0;
int32_t scriptn = 0;
for (;;) {
anm_entry_t* entry = malloc(sizeof(*entry));
anm_header06_t* header = (anm_header06_t*)map;
Expand Down Expand Up @@ -927,6 +948,7 @@ anm_read_file(
(anm_offset_t*)(map + sizeof(*header) + header->sprites * sizeof(uint32_t));
for (uint32_t s = 0; s < header->scripts; ++s) {
anm_script_t* script = anm_script_new();
script->real_index = scriptn;
script->offset = &(script_offsets[s]);

unsigned char* limit = map;
Expand Down Expand Up @@ -1106,7 +1128,8 @@ static void
anm_stringify_instr(
FILE* stream,
thanm_instr_t* instr,
int scriptn
const anm_archive_t* anm,
int32_t scriptn
) {
seqmap_entry_t* ent = seqmap_get(g_anmmap->ins_names, instr->id);

Expand All @@ -1117,7 +1140,7 @@ anm_stringify_instr(

thanm_param_t* param;
list_for_each(&instr->params, param) {
anm_stringify_param(stream, param, instr, scriptn);
anm_stringify_param(stream, param, instr, anm, scriptn);
if (!list_is_last_iteration()) {
fprintf(stream, ", ");
}
Expand All @@ -1135,7 +1158,6 @@ anm_dump(
unsigned int entry_num = 0;
anm_entry_t* entry;

int scriptn = 0;
int prev_sprite_id = -1;
int prev_script_id = -1;
list_for_each(&anm->entries, entry) {
Expand Down Expand Up @@ -1198,13 +1220,17 @@ anm_dump(

anm_script_t* script;
list_for_each(&entry->scripts, script) {

sprintf(buf, "script%d", script->offset->id);
replace_minus(buf);
/* We need to use the index of the script in file for the name, because that's
* what instructions that refer to scripts use. I'm unsure what's the actual purpose of the ID field.
* However! I still don't really know how old versions work, and maybe instructions refer to the
* ID field there? If that's the case, it should be enough to just do a check earlier that sets
* real_index to offset->id in old versions (and re-add the replace_minus calls).
* I honestly doubt that this is the case, but I want to leave a note how to change it anyway in case
* it's needed... */
if (script->offset->id - 1 != prev_script_id) {
fprintf(stream, "script %d %s {\n", script->offset->id, buf);
fprintf(stream, "script %d script%d {\n", script->offset->id, script->real_index);
} else {
fprintf(stream, "script %s {\n", buf);
fprintf(stream, "script script%d {\n", script->real_index);
}
prev_script_id = script->offset->id;

Expand All @@ -1215,7 +1241,7 @@ anm_dump(
switch(instr->type) {
case THANM_INSTR_INSTR:
fprintf(stream, " ");
anm_stringify_instr(stream, instr, scriptn);
anm_stringify_instr(stream, instr, anm, script->real_index);
break;
case THANM_INSTR_TIME:
if (instr->time < 0)
Expand All @@ -1240,7 +1266,6 @@ anm_dump(
}

fprintf(stream, "}\n\n");
++scriptn;
}

fprintf(stream, "\n");
Expand Down Expand Up @@ -1755,6 +1780,7 @@ anm_create(
state.current_version = -1;
state.sprite_id = 0;
state.script_id = 0;
state.script_real_index = 0;
list_init(&state.entries);
list_init(&state.globals);
list_init(&state.script_names);
Expand Down
5 changes: 4 additions & 1 deletion thanm/thanm.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ extern unsigned int option_force;
const id_format_pair_t* anm_get_formats(uint32_t version);

typedef struct {
/* The id in the offset struct may not be the real index. */
int32_t real_index;
anm_offset_t* offset;
/* instrs of thanm_instr_t format */
list_t instrs;
Expand Down Expand Up @@ -125,7 +127,8 @@ typedef struct parser_state_t {
int32_t current_version;
uint32_t offset;
uint32_t sprite_id;
uint32_t script_id;
int32_t script_id;
int32_t script_real_index;
/* List of anm_entry_t */
list_t entries;
anm_entry_t* current_entry;
Expand Down

0 comments on commit 2b2710b

Please sign in to comment.