Skip to content

Commit

Permalink
TSA: ANM: Support script instruction time changes via JSON. [V]
Browse files Browse the repository at this point in the history
Funded by GhostPhanom.
  • Loading branch information
nmlgc committed Oct 7, 2018
1 parent 5ee2cb9 commit 6b6f275
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 6 deletions.
36 changes: 31 additions & 5 deletions thcrap_tsa/src/anm.cpp
Expand Up @@ -384,7 +384,9 @@ script_mods_t entry_mods_t::script_mods(uint8_t *in, anm_offset_t &offset, uint3
}

#define CHECK_LINE_NUMBER_AFTER_DELETIONS(context, ...) \
if(line_i >= (ret.script.num_instrs - deletions_count)) { \
if(deletions_count == 0) { \
CHECK_LINE_NUMBER(context, ##__VA_ARGS__); \
} else if(line_i >= (ret.script.num_instrs - deletions_count)) { \
FAIL( \
context, \
"Line number %u out of range, script only has %u instructions after %u deletions.", \
Expand Down Expand Up @@ -450,7 +452,9 @@ script_mods_t entry_mods_t::script_mods(uint8_t *in, anm_offset_t &offset, uint3
auto fail_key_syntax = [&]() {
FAIL(
": {\"changes\": {\"%s\"}",
"Invalid key syntax, must be \"<line>#<parameter address>\".",
"Invalid key syntax, must be one of:\n"
"\xE2\x80\xA2 \"<line>#<parameter address>\" (to change instruction parameters)\n"
"\xE2\x80\xA2 \"<line>#time\" (to change the frame an instruction is executed on)\n",
key
);
};
Expand All @@ -468,7 +472,18 @@ script_mods_t entry_mods_t::script_mods(uint8_t *in, anm_offset_t &offset, uint3
unsigned int line_i = line;
CHECK_LINE_NUMBER_AFTER_DELETIONS(": {\"changes\": {\"%s\"}", key);

{
if(!strcmp(key_sep + 1, "time")) {
auto time = json_integer_value(val_j);
if(!json_is_integer(val_j) || (time < INT16_MIN) | (time > INT16_MAX)) {
FAIL(
": {\"changes\": {\"%s\"}", "Time must be a signed 16-bit integer, between %d and %d.",
key, INT16_MIN, INT16_MAX
);
}
ret.time_changes.emplace_back(script_time_change_t{
line_i - deletions_count, (uint16_t)time
});
} else {
auto addr = strtol(key_sep + 1, &endptr, 10);
if(endptr == (key_sep + 1) || endptr[0] != '\0' || addr < 0) {
return fail_key_syntax();
Expand All @@ -487,8 +502,8 @@ script_mods_t entry_mods_t::script_mods(uint8_t *in, anm_offset_t &offset, uint3
if((size_t)addr >= (param_length - code_size)) {
FAIL(
": {\"changes\": {\"%s\"}",
"Address %u + binary hack of length %u exceeds the parameter length of line %u.",
key, addr, code_size, param_length
"Address %u + binary hack of length %u exceeds the parameter length of line %u (%u).",
key, addr, code_size, line, param_length
);
}

Expand Down Expand Up @@ -530,6 +545,10 @@ void script_mods_t::apply_orig()
);
VLA_FREE(code);
}
for(const auto &tc : time_changes) {
LOG("Changing time on line %u", deletions.size() + tc.line);
((script).*(script.apply_time_change))(tc);
}

#undef LOG
}
Expand Down Expand Up @@ -806,6 +825,12 @@ template <typename T> void script_t::_delete_line(unsigned int line)
num_instrs--;
}

template <typename T> void script_t::_apply_time_change(script_time_change_t change)
{
auto instr = _instr_at_line<T>(change.line);
instr->time = change.time;
}

template <typename T> void script_t::_apply_param_change(
unsigned int line, uint16_t param_addr,
const uint8_t *code, size_t code_size
Expand All @@ -826,6 +851,7 @@ template <typename T> void script_t::init(T *first)
after_last = (uint8_t *)instr_next(instr);
param_length_of = &script_t::_param_length_of<T>;
delete_line = &script_t::_delete_line<T>;
apply_time_change = &script_t::_apply_time_change<T>;
apply_param_change = &script_t::_apply_param_change<T>;
}

Expand Down
9 changes: 9 additions & 0 deletions thcrap_tsa/src/anm.hpp
Expand Up @@ -146,6 +146,7 @@ void format_from_bgra(png_bytep data, unsigned int pixels, format_t format);
*
* "changes": {
* "<line>#<parameter address>": "<binary hack>",
* "<line>#time": <frame as a JSON integer"
* ...
*
* Applies the given binary hack to the parameter at the given address,
Expand Down Expand Up @@ -194,13 +195,19 @@ struct script_param_change_t {
size_t code_size;
};

struct script_time_change_t {
unsigned int line;
int16_t time;
};

class script_t {
uint8_t *first_instr;
uint8_t *after_last;

template <typename T> T* _instr_at_line(unsigned int line);
template <typename T> uint16_t _param_length_of(unsigned int line);
template <typename T> void _delete_line(unsigned int line);
template <typename T> void _apply_time_change(script_time_change_t change);
template <typename T> void _apply_param_change(
unsigned int line, uint16_t param_addr,
const uint8_t *code, size_t code_size
Expand All @@ -213,6 +220,7 @@ class script_t {
// Version-dependent operations
uint16_t (script_t::*param_length_of)(unsigned int line);
void (script_t::*delete_line)(unsigned int line);
void (script_t::*apply_time_change)(script_time_change_t change);
void (script_t::*apply_param_change)(
unsigned int line, uint16_t param_addr,
const uint8_t *code, size_t code_size
Expand All @@ -227,6 +235,7 @@ struct script_mods_t {
script_t script;

std::vector<unsigned int> deletions;
std::vector<script_time_change_t> time_changes;
std::vector<script_param_change_t> param_changes;
void apply_orig();
};
Expand Down
2 changes: 1 addition & 1 deletion thtypes

0 comments on commit 6b6f275

Please sign in to comment.