Skip to content

Commit 1d2120f

Browse files
committed
thecl10: introduce type 'H' for th20 ins_46/ins_47
ZUN's compiler, it seems, treats these arguments as 'D', but the vm behaves as if these were SS/Sf when looking up the bits in the param_mask. Vanilla game never uses variables in those arguments, but mods may wish to do so. The new 'H' type is equivalent to 'D', but a bit in the param_mask is skipped when reading/writing the instruction. param_count is not affected.
1 parent 64cfb81 commit 1d2120f

2 files changed

Lines changed: 14 additions & 6 deletions

File tree

thecl/ecsparse.y

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,7 @@ instr_set_types(
15091509
new_type = *format;
15101510

15111511
if (new_type != param->type &&
1512+
!(param->type == 'D' && new_type == 'H') &&
15121513
!(param->type == 'z' && (new_type == 'm' || new_type == 'x' || new_type == 'N' || new_type == 'n')) &&
15131514
!(param->type == 'S' && (new_type == 's' || new_type == 'U' || new_type == 't'))
15141515
) {
@@ -1890,7 +1891,7 @@ static void instr_create_inline_call(
18901891
/* Still reusing the same param variable as earlier. */
18911892
param = (thecl_param_t*)param_node->data;
18921893
if (param->stack) {
1893-
if (param->type == 'D') {
1894+
if (param->type == 'D' || param->type == 'H') {
18941895
thecl_sub_param_t* D = (thecl_sub_param_t*)param->value.val.m.data;
18951896
if (D->from == 'i') {
18961897
if (D->val.S < sub->arity*4 && D->val.S >= 0) {

thecl/thecl10.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ th10_value_from_data(
9898
{
9999
switch (type) {
100100
case 'D':
101+
case 'H':
101102
return value_from_data(data, sizeof(thecl_sub_param_t), 'm', value);
102103
case 'o':
103104
case 't':
@@ -1080,8 +1081,8 @@ static const id_format_pair_t th19_fmts[] = {
10801081
};
10811082

10821083
static const id_format_pair_t th20_fmts[] = {
1083-
{ 46, "SSSSSSSSS" },
1084-
{ 47, "fSfffffff" },
1084+
{ 46, "SSS*H" },
1085+
{ 47, "fSf*H" },
10851086
{ 341, "" },
10861087
{ 342, "" },
10871088
{ 343, "S" },
@@ -1377,6 +1378,8 @@ th10_open(
13771378
f = format[p];
13781379
}
13791380
thecl_param_t* param = param_new(f);
1381+
if (f == 'H')
1382+
param_mask >>= 1;
13801383
param->stack = param_mask & 1;
13811384
param_mask >>= 1;
13821385
param->value = *value_iter;
@@ -1609,7 +1612,7 @@ th10_stringify_param(
16091612
sprintf(temp, "%s_%d", sub->name, instr->offset + param->value.val.S);
16101613
return strdup(temp);
16111614
}
1612-
case 'D': {
1615+
case 'D': case 'H': {
16131616
value_t new_value;
16141617
thecl_sub_param_t* D = (thecl_sub_param_t*)param->value.val.m.data;
16151618

@@ -2153,6 +2156,7 @@ th10_instr_serialize(
21532156

21542157
unsigned char* param_data = ret->data;
21552158
int param_count = 0;
2159+
int param_mask_shift = 0;
21562160

21572161
seqmap_entry_t* ent = seqmap_get(g_eclmap->ins_names, instr->id);
21582162
char buf[128];
@@ -2219,8 +2223,11 @@ th10_instr_serialize(
22192223
}
22202224

22212225
list_for_each(&instr->params, param) {
2226+
if (param->type == 'H')
2227+
++param_mask_shift;
22222228
if (param->stack)
2223-
ret->param_mask |= 1 << param_count;
2229+
ret->param_mask |= 1 << param_mask_shift;
2230+
++param_mask_shift;
22242231
++param_count;
22252232
if (param->type == 'o') {
22262233
/* This calculates the relative offset from the current instruction. */
@@ -2261,7 +2268,7 @@ th10_instr_serialize(
22612268
++ret->zero;
22622269
} else if (param->type == 'S' && param->value.val.S == -(ret->zero + 1)) {
22632270
++ret->zero;
2264-
} else if (param->type == 'D') {
2271+
} else if (param->type == 'D' || param->type == 'H') {
22652272
thecl_sub_param_t *temp = (thecl_sub_param_t*)param->value.val.m.data;
22662273

22672274
if (temp->from == 'f' && temp->val.f == -(ret->zero + 1.0f))

0 commit comments

Comments
 (0)