2019-02-05 02:44:07 +02:00
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
/* "bpatch" : Keeps track of, and finally acts on, backpatch markers, */
|
|
|
|
/* correcting symbol values not known at compilation time */
|
|
|
|
/* */
|
2024-02-27 00:51:15 +02:00
|
|
|
/* Part of Inform 6.43 */
|
2024-02-12 01:08:33 +02:00
|
|
|
/* copyright (c) Graham Nelson 1993 - 2024 */
|
2019-02-05 02:44:07 +02:00
|
|
|
/* */
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
#include "header.h"
|
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
uchar *staticarray_backpatch_table; /* Allocated to staticarray_backpatch_size */
|
|
|
|
memory_list staticarray_backpatch_table_memlist;
|
|
|
|
uchar *zmachine_backpatch_table; /* Allocated to zmachine_backpatch_size */
|
|
|
|
memory_list zmachine_backpatch_table_memlist;
|
|
|
|
uchar *zcode_backpatch_table; /* Allocated to zcode_backpatch_size */
|
|
|
|
memory_list zcode_backpatch_table_memlist;
|
2020-06-01 20:29:12 +03:00
|
|
|
int32 zcode_backpatch_size, staticarray_backpatch_size,
|
|
|
|
zmachine_backpatch_size;
|
2019-02-05 02:44:07 +02:00
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
/* Marker values */
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
extern char *describe_mv(int mval)
|
|
|
|
{ switch(mval)
|
|
|
|
{ case NULL_MV: return("null");
|
|
|
|
|
|
|
|
/* Marker values used in ordinary story file backpatching */
|
|
|
|
|
|
|
|
case DWORD_MV: return("dictionary word");
|
|
|
|
case STRING_MV: return("string literal");
|
|
|
|
case INCON_MV: return("system constant");
|
|
|
|
case IROUTINE_MV: return("routine");
|
|
|
|
case VROUTINE_MV: return("veneer routine");
|
|
|
|
case ARRAY_MV: return("internal array");
|
2024-02-12 01:08:33 +02:00
|
|
|
case STATIC_ARRAY_MV: return("internal static array");
|
2022-07-24 13:10:45 +03:00
|
|
|
case NO_OBJS_MV: return("the number of objects");
|
|
|
|
case INHERIT_MV: return("inherited common p value");
|
|
|
|
case INDIVPT_MV: return("indiv prop table address");
|
|
|
|
case INHERIT_INDIV_MV: return("inherited indiv p value");
|
|
|
|
case MAIN_MV: return("ref to Main");
|
|
|
|
case SYMBOL_MV: return("ref to symbol value");
|
|
|
|
|
|
|
|
/* Additional marker values used in Glulx backpatching
|
|
|
|
(IDENT_MV is not really used at all any more) */
|
|
|
|
|
|
|
|
case VARIABLE_MV: return("global variable");
|
|
|
|
case IDENT_MV: return("prop identifier number");
|
|
|
|
case ACTION_MV: return("action");
|
|
|
|
case OBJECT_MV: return("internal object");
|
|
|
|
|
2024-02-12 01:08:33 +02:00
|
|
|
/* Only occurs secondary to another reported error */
|
|
|
|
case ERROR_MV: return("error");
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
}
|
|
|
|
return("** No such MV **");
|
|
|
|
}
|
|
|
|
|
2024-02-12 01:08:33 +02:00
|
|
|
extern char *describe_mv_short(int mval)
|
|
|
|
{ switch(mval)
|
|
|
|
{ case NULL_MV: return("");
|
|
|
|
|
|
|
|
/* Marker values used in ordinary story file backpatching */
|
|
|
|
|
|
|
|
case DWORD_MV: return("dict");
|
|
|
|
case STRING_MV: return("str");
|
|
|
|
case INCON_MV: return("syscon");
|
|
|
|
case IROUTINE_MV: return("rtn");
|
|
|
|
case VROUTINE_MV: return("vrtn");
|
|
|
|
case ARRAY_MV: return("arr");
|
|
|
|
case STATIC_ARRAY_MV: return("stat-arr");
|
|
|
|
case NO_OBJS_MV: return("obj-count");
|
|
|
|
case INHERIT_MV: return("inh-com");
|
|
|
|
case INDIVPT_MV: return("indiv-ptab");
|
|
|
|
case INHERIT_INDIV_MV: return("inh-indiv");
|
|
|
|
case MAIN_MV: return("main");
|
|
|
|
case SYMBOL_MV: return("sym");
|
|
|
|
|
|
|
|
/* Additional marker values used in Glulx backpatching
|
|
|
|
(IDENT_MV is not really used at all any more) */
|
|
|
|
|
|
|
|
case VARIABLE_MV: return("glob");
|
|
|
|
case IDENT_MV: return("prop");
|
|
|
|
case ACTION_MV: return("action");
|
|
|
|
case OBJECT_MV: return("obj");
|
|
|
|
|
|
|
|
case LABEL_MV: return("lbl");
|
|
|
|
case DELETED_MV: return("del");
|
|
|
|
|
|
|
|
/* Only occurs secondary to another reported error */
|
|
|
|
case ERROR_MV: return("err");
|
|
|
|
|
|
|
|
}
|
|
|
|
if (mval >= BRANCH_MV && mval < BRANCHMAX_MV) return "br";
|
|
|
|
|
|
|
|
return("???");
|
|
|
|
}
|
|
|
|
|
2019-02-05 02:44:07 +02:00
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
/* The mending operation */
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
int backpatch_marker, backpatch_size, backpatch_error_flag;
|
|
|
|
|
|
|
|
static int32 backpatch_value_z(int32 value)
|
|
|
|
{ /* Corrects the quantity "value" according to backpatch_marker */
|
|
|
|
|
|
|
|
ASSERT_ZCODE();
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
if (bpatch_trace_setting)
|
2019-02-05 02:44:07 +02:00
|
|
|
printf("BP %s applied to %04x giving ",
|
|
|
|
describe_mv(backpatch_marker), value);
|
|
|
|
|
|
|
|
switch(backpatch_marker)
|
|
|
|
{ case STRING_MV:
|
|
|
|
value += strings_offset/scale_factor; break;
|
|
|
|
case ARRAY_MV:
|
|
|
|
value += variables_offset; break;
|
2020-06-01 20:29:12 +03:00
|
|
|
case STATIC_ARRAY_MV:
|
|
|
|
value += static_arrays_offset; break;
|
2019-02-05 02:44:07 +02:00
|
|
|
case IROUTINE_MV:
|
|
|
|
if (OMIT_UNUSED_ROUTINES)
|
|
|
|
value = df_stripped_address_for_address(value);
|
|
|
|
value += code_offset/scale_factor;
|
|
|
|
break;
|
|
|
|
case VROUTINE_MV:
|
|
|
|
if ((value<0) || (value>=VENEER_ROUTINES))
|
2022-07-24 13:10:45 +03:00
|
|
|
{
|
2019-02-05 02:44:07 +02:00
|
|
|
if (compiler_error
|
|
|
|
("Backpatch veneer routine number out of range"))
|
|
|
|
{ printf("Illegal BP veneer routine number: %d\n", value);
|
|
|
|
backpatch_error_flag = TRUE;
|
|
|
|
}
|
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
value = veneer_routine_address[value];
|
|
|
|
if (OMIT_UNUSED_ROUTINES)
|
|
|
|
value = df_stripped_address_for_address(value);
|
|
|
|
value += code_offset/scale_factor;
|
|
|
|
break;
|
|
|
|
case NO_OBJS_MV:
|
|
|
|
value = no_objects; break;
|
|
|
|
case INCON_MV:
|
|
|
|
if ((value<0) || (value>=NO_SYSTEM_CONSTANTS))
|
2022-07-24 13:10:45 +03:00
|
|
|
{
|
2019-02-05 02:44:07 +02:00
|
|
|
if (compiler_error
|
|
|
|
("Backpatch system constant number out of range"))
|
|
|
|
{ printf("Illegal BP system constant number: %d\n", value);
|
|
|
|
backpatch_error_flag = TRUE;
|
|
|
|
}
|
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
value = value_of_system_constant(value); break;
|
|
|
|
case DWORD_MV:
|
|
|
|
value = dictionary_offset + 7 +
|
2022-03-03 02:10:25 +02:00
|
|
|
final_dict_order[value]*(DICT_ENTRY_BYTE_LENGTH);
|
2019-02-05 02:44:07 +02:00
|
|
|
break;
|
|
|
|
case ACTION_MV:
|
|
|
|
break;
|
|
|
|
case INHERIT_MV:
|
|
|
|
value = 256*zmachine_paged_memory[value + prop_values_offset]
|
|
|
|
+ zmachine_paged_memory[value + prop_values_offset + 1];
|
|
|
|
break;
|
|
|
|
case INHERIT_INDIV_MV:
|
|
|
|
value = 256*zmachine_paged_memory[value
|
|
|
|
+ individuals_offset]
|
|
|
|
+ zmachine_paged_memory[value
|
|
|
|
+ individuals_offset + 1];
|
|
|
|
break;
|
|
|
|
case INDIVPT_MV:
|
|
|
|
value += individuals_offset;
|
|
|
|
break;
|
|
|
|
case MAIN_MV:
|
2024-02-12 01:08:33 +02:00
|
|
|
value = get_symbol_index("Main");
|
|
|
|
if (value < 0 || (symbols[value].flags & UNKNOWN_SFLAG)) {
|
2019-02-05 02:44:07 +02:00
|
|
|
error("No 'Main' routine has been defined");
|
2024-02-12 01:08:33 +02:00
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (symbols[value].type != ROUTINE_T) {
|
|
|
|
ebf_symbol_error("'Main' routine", symbols[value].name, typename(symbols[value].type), symbols[value].line);
|
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
}
|
2022-03-03 02:10:25 +02:00
|
|
|
symbols[value].flags |= USED_SFLAG;
|
|
|
|
value = symbols[value].value;
|
2019-02-05 02:44:07 +02:00
|
|
|
if (OMIT_UNUSED_ROUTINES)
|
|
|
|
value = df_stripped_address_for_address(value);
|
|
|
|
value += code_offset/scale_factor;
|
|
|
|
break;
|
|
|
|
case SYMBOL_MV:
|
|
|
|
if ((value<0) || (value>=no_symbols))
|
2022-07-24 13:10:45 +03:00
|
|
|
{
|
2019-02-05 02:44:07 +02:00
|
|
|
if (compiler_error("Backpatch symbol number out of range"))
|
|
|
|
{ printf("Illegal BP symbol number: %d\n", value);
|
|
|
|
backpatch_error_flag = TRUE;
|
|
|
|
}
|
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
}
|
2022-03-03 02:10:25 +02:00
|
|
|
if (symbols[value].flags & UNKNOWN_SFLAG)
|
|
|
|
{ if (!(symbols[value].flags & UERROR_SFLAG))
|
|
|
|
{ symbols[value].flags |= UERROR_SFLAG;
|
2019-02-05 02:44:07 +02:00
|
|
|
error_named_at("No such constant as",
|
2022-03-03 02:10:25 +02:00
|
|
|
symbols[value].name, symbols[value].line);
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2022-03-03 02:10:25 +02:00
|
|
|
if (symbols[value].flags & CHANGE_SFLAG)
|
|
|
|
{ symbols[value].flags &= (~(CHANGE_SFLAG));
|
|
|
|
backpatch_marker = (symbols[value].marker);
|
2019-02-05 02:44:07 +02:00
|
|
|
if ((backpatch_marker < 0)
|
|
|
|
|| (backpatch_marker > LARGEST_BPATCH_MV))
|
|
|
|
{
|
2022-07-24 13:10:45 +03:00
|
|
|
compiler_error_named(
|
2019-02-05 02:44:07 +02:00
|
|
|
"Illegal backpatch marker attached to symbol",
|
2022-03-03 02:10:25 +02:00
|
|
|
symbols[value].name);
|
2022-07-24 13:10:45 +03:00
|
|
|
backpatch_error_flag = TRUE;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
else
|
2022-03-03 02:10:25 +02:00
|
|
|
symbols[value].value = backpatch_value_z((symbols[value].value) % 0x10000);
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
symbols[value].flags |= USED_SFLAG;
|
|
|
|
{ int t = symbols[value].type;
|
|
|
|
value = symbols[value].value;
|
2019-02-05 02:44:07 +02:00
|
|
|
switch(t)
|
|
|
|
{ case ROUTINE_T:
|
|
|
|
if (OMIT_UNUSED_ROUTINES)
|
|
|
|
value = df_stripped_address_for_address(value);
|
|
|
|
value += code_offset/scale_factor;
|
|
|
|
break;
|
|
|
|
case ARRAY_T: value += variables_offset; break;
|
2020-06-01 20:29:12 +03:00
|
|
|
case STATIC_ARRAY_T: value += static_arrays_offset; break;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (compiler_error("Illegal backpatch marker"))
|
|
|
|
{ printf("Illegal backpatch marker %d value %04x\n",
|
|
|
|
backpatch_marker, value);
|
|
|
|
backpatch_error_flag = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
if (bpatch_trace_setting) printf(" %04x\n", value);
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
return(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32 backpatch_value_g(int32 value)
|
|
|
|
{ /* Corrects the quantity "value" according to backpatch_marker */
|
|
|
|
int32 valaddr;
|
|
|
|
|
|
|
|
ASSERT_GLULX();
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
if (bpatch_trace_setting)
|
2019-02-05 02:44:07 +02:00
|
|
|
printf("BP %s applied to %04x giving ",
|
|
|
|
describe_mv(backpatch_marker), value);
|
|
|
|
|
|
|
|
switch(backpatch_marker)
|
|
|
|
{
|
|
|
|
case STRING_MV:
|
|
|
|
if (value <= 0 || value > no_strings)
|
|
|
|
compiler_error("Illegal string marker.");
|
|
|
|
value = strings_offset + compressed_offsets[value-1]; break;
|
|
|
|
case IROUTINE_MV:
|
|
|
|
if (OMIT_UNUSED_ROUTINES)
|
|
|
|
value = df_stripped_address_for_address(value);
|
|
|
|
value += code_offset;
|
|
|
|
break;
|
|
|
|
case ARRAY_MV:
|
|
|
|
value += arrays_offset; break;
|
2020-06-01 20:29:12 +03:00
|
|
|
case STATIC_ARRAY_MV:
|
|
|
|
value += static_arrays_offset; break;
|
2019-02-05 02:44:07 +02:00
|
|
|
case VARIABLE_MV:
|
|
|
|
value = variables_offset + (4*value); break;
|
|
|
|
case OBJECT_MV:
|
|
|
|
value = object_tree_offset + (OBJECT_BYTE_LENGTH*(value-1));
|
|
|
|
break;
|
|
|
|
case VROUTINE_MV:
|
|
|
|
if ((value<0) || (value>=VENEER_ROUTINES))
|
2022-07-24 13:10:45 +03:00
|
|
|
{
|
2019-02-05 02:44:07 +02:00
|
|
|
if (compiler_error
|
|
|
|
("Backpatch veneer routine number out of range"))
|
|
|
|
{ printf("Illegal BP veneer routine number: %d\n", value);
|
|
|
|
backpatch_error_flag = TRUE;
|
|
|
|
}
|
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
value = veneer_routine_address[value];
|
|
|
|
if (OMIT_UNUSED_ROUTINES)
|
|
|
|
value = df_stripped_address_for_address(value);
|
|
|
|
value += code_offset;
|
|
|
|
break;
|
|
|
|
case NO_OBJS_MV:
|
|
|
|
value = no_objects; break;
|
|
|
|
case INCON_MV:
|
|
|
|
if ((value<0) || (value>=NO_SYSTEM_CONSTANTS))
|
2022-07-24 13:10:45 +03:00
|
|
|
{
|
2019-02-05 02:44:07 +02:00
|
|
|
if (compiler_error
|
|
|
|
("Backpatch system constant number out of range"))
|
|
|
|
{ printf("Illegal BP system constant number: %d\n", value);
|
|
|
|
backpatch_error_flag = TRUE;
|
|
|
|
}
|
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
value = value_of_system_constant(value); break;
|
|
|
|
case DWORD_MV:
|
|
|
|
value = dictionary_offset + 4
|
|
|
|
+ final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
|
|
|
|
break;
|
|
|
|
case ACTION_MV:
|
|
|
|
break;
|
|
|
|
case INHERIT_MV:
|
|
|
|
valaddr = (prop_values_offset - Write_RAM_At) + value;
|
|
|
|
value = ReadInt32(zmachine_paged_memory + valaddr);
|
|
|
|
break;
|
|
|
|
case INHERIT_INDIV_MV:
|
|
|
|
error("*** No individual property storage in Glulx ***");
|
|
|
|
break;
|
|
|
|
case INDIVPT_MV:
|
|
|
|
value += individuals_offset;
|
|
|
|
break;
|
|
|
|
case MAIN_MV:
|
2024-02-12 01:08:33 +02:00
|
|
|
value = get_symbol_index("Main");
|
|
|
|
if (value < 0 || (symbols[value].flags & UNKNOWN_SFLAG)) {
|
2019-02-05 02:44:07 +02:00
|
|
|
error("No 'Main' routine has been defined");
|
2024-02-12 01:08:33 +02:00
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (symbols[value].type != ROUTINE_T) {
|
|
|
|
ebf_symbol_error("'Main' routine", symbols[value].name, typename(symbols[value].type), symbols[value].line);
|
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
}
|
2022-03-03 02:10:25 +02:00
|
|
|
symbols[value].flags |= USED_SFLAG;
|
|
|
|
value = symbols[value].value;
|
2019-02-05 02:44:07 +02:00
|
|
|
if (OMIT_UNUSED_ROUTINES)
|
|
|
|
value = df_stripped_address_for_address(value);
|
|
|
|
value += code_offset;
|
|
|
|
break;
|
|
|
|
case SYMBOL_MV:
|
|
|
|
if ((value<0) || (value>=no_symbols))
|
2022-07-24 13:10:45 +03:00
|
|
|
{
|
2019-02-05 02:44:07 +02:00
|
|
|
if (compiler_error("Backpatch symbol number out of range"))
|
|
|
|
{ printf("Illegal BP symbol number: %d\n", value);
|
|
|
|
backpatch_error_flag = TRUE;
|
|
|
|
}
|
|
|
|
value = 0;
|
|
|
|
break;
|
|
|
|
}
|
2022-03-03 02:10:25 +02:00
|
|
|
if (symbols[value].flags & UNKNOWN_SFLAG)
|
|
|
|
{ if (!(symbols[value].flags & UERROR_SFLAG))
|
|
|
|
{ symbols[value].flags |= UERROR_SFLAG;
|
2019-02-05 02:44:07 +02:00
|
|
|
error_named_at("No such constant as",
|
2022-03-03 02:10:25 +02:00
|
|
|
symbols[value].name, symbols[value].line);
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2022-03-03 02:10:25 +02:00
|
|
|
if (symbols[value].flags & CHANGE_SFLAG)
|
|
|
|
{ symbols[value].flags &= (~(CHANGE_SFLAG));
|
|
|
|
backpatch_marker = symbols[value].marker;
|
2019-02-05 02:44:07 +02:00
|
|
|
if ((backpatch_marker < 0)
|
|
|
|
|| (backpatch_marker > LARGEST_BPATCH_MV))
|
|
|
|
{
|
2022-07-24 13:10:45 +03:00
|
|
|
compiler_error_named(
|
2019-02-05 02:44:07 +02:00
|
|
|
"Illegal backpatch marker attached to symbol",
|
2022-03-03 02:10:25 +02:00
|
|
|
symbols[value].name);
|
2022-07-24 13:10:45 +03:00
|
|
|
backpatch_error_flag = TRUE;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
else
|
2022-03-03 02:10:25 +02:00
|
|
|
symbols[value].value = backpatch_value_g(symbols[value].value);
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
symbols[value].flags |= USED_SFLAG;
|
|
|
|
{ int t = symbols[value].type;
|
|
|
|
value = symbols[value].value;
|
2019-02-05 02:44:07 +02:00
|
|
|
switch(t)
|
|
|
|
{
|
|
|
|
case ROUTINE_T:
|
|
|
|
if (OMIT_UNUSED_ROUTINES)
|
|
|
|
value = df_stripped_address_for_address(value);
|
|
|
|
value += code_offset;
|
|
|
|
break;
|
|
|
|
case ARRAY_T: value += arrays_offset; break;
|
2020-06-01 20:29:12 +03:00
|
|
|
case STATIC_ARRAY_T: value += static_arrays_offset; break;
|
2019-02-05 02:44:07 +02:00
|
|
|
case OBJECT_T:
|
|
|
|
case CLASS_T:
|
|
|
|
value = object_tree_offset +
|
|
|
|
(OBJECT_BYTE_LENGTH*(value-1));
|
|
|
|
break;
|
|
|
|
case ATTRIBUTE_T:
|
|
|
|
/* value is unchanged */
|
|
|
|
break;
|
|
|
|
case CONSTANT_T:
|
|
|
|
case INDIVIDUAL_PROPERTY_T:
|
2022-03-03 02:10:25 +02:00
|
|
|
case PROPERTY_T:
|
2019-02-05 02:44:07 +02:00
|
|
|
/* value is unchanged */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error("*** Illegal backpatch marker in forward-declared \
|
|
|
|
symbol");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (compiler_error("Illegal backpatch marker"))
|
|
|
|
{ printf("Illegal backpatch marker %d value %04x\n",
|
|
|
|
backpatch_marker, value);
|
|
|
|
backpatch_error_flag = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
if (bpatch_trace_setting) printf(" %04x\n", value);
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
return(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern int32 backpatch_value(int32 value)
|
|
|
|
{
|
|
|
|
if (!glulx_mode)
|
|
|
|
return backpatch_value_z(value);
|
|
|
|
else
|
|
|
|
return backpatch_value_g(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void backpatch_zmachine_z(int mv, int zmachine_area, int32 offset)
|
2022-07-24 13:10:45 +03:00
|
|
|
{
|
|
|
|
if (mv == OBJECT_MV) return;
|
|
|
|
if (mv == IDENT_MV) return;
|
|
|
|
if (mv == ACTION_MV) return;
|
2019-02-05 02:44:07 +02:00
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
if (bpatch_trace_setting >= 2)
|
|
|
|
printf("BP added: MV %d ZA %d Off %04x\n", mv, zmachine_area, offset);
|
2019-02-05 02:44:07 +02:00
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
ensure_memory_list_available(&zmachine_backpatch_table_memlist, zmachine_backpatch_size+4);
|
|
|
|
zmachine_backpatch_table[zmachine_backpatch_size++] = mv;
|
|
|
|
zmachine_backpatch_table[zmachine_backpatch_size++] = zmachine_area;
|
|
|
|
zmachine_backpatch_table[zmachine_backpatch_size++] = offset/256;
|
|
|
|
zmachine_backpatch_table[zmachine_backpatch_size++] = offset%256;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void backpatch_zmachine_g(int mv, int zmachine_area, int32 offset)
|
2022-07-24 13:10:45 +03:00
|
|
|
{
|
|
|
|
if (mv == IDENT_MV) return;
|
|
|
|
if (mv == ACTION_MV) return;
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
/* The backpatch table format for Glulx:
|
|
|
|
First, the marker byte.
|
|
|
|
Then, the zmachine area being patched.
|
|
|
|
Then the four-byte address.
|
|
|
|
*/
|
|
|
|
|
2022-07-24 13:10:45 +03:00
|
|
|
if (bpatch_trace_setting >= 2)
|
|
|
|
printf("BP added: MV %d ZA %d Off %06x\n", mv, zmachine_area, offset);
|
2019-02-05 02:44:07 +02:00
|
|
|
|
2022-03-03 02:10:25 +02:00
|
|
|
ensure_memory_list_available(&zmachine_backpatch_table_memlist, zmachine_backpatch_size+6);
|
|
|
|
zmachine_backpatch_table[zmachine_backpatch_size++] = mv;
|
|
|
|
zmachine_backpatch_table[zmachine_backpatch_size++] = zmachine_area;
|
|
|
|
zmachine_backpatch_table[zmachine_backpatch_size++] = (offset >> 24) & 0xFF;
|
|
|
|
zmachine_backpatch_table[zmachine_backpatch_size++] = (offset >> 16) & 0xFF;
|
|
|
|
zmachine_backpatch_table[zmachine_backpatch_size++] = (offset >> 8) & 0xFF;
|
|
|
|
zmachine_backpatch_table[zmachine_backpatch_size++] = (offset) & 0xFF;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
extern void backpatch_zmachine(int mv, int zmachine_area, int32 offset)
|
|
|
|
{
|
|
|
|
if (!glulx_mode)
|
|
|
|
backpatch_zmachine_z(mv, zmachine_area, offset);
|
|
|
|
else
|
|
|
|
backpatch_zmachine_g(mv, zmachine_area, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void backpatch_zmachine_image_z(void)
|
|
|
|
{ int bm = 0, zmachine_area; int32 offset, value, addr = 0;
|
|
|
|
ASSERT_ZCODE();
|
|
|
|
backpatch_error_flag = FALSE;
|
|
|
|
while (bm < zmachine_backpatch_size)
|
|
|
|
{ backpatch_marker
|
2022-03-03 02:10:25 +02:00
|
|
|
= zmachine_backpatch_table[bm];
|
2019-02-05 02:44:07 +02:00
|
|
|
zmachine_area
|
2022-03-03 02:10:25 +02:00
|
|
|
= zmachine_backpatch_table[bm+1];
|
2019-02-05 02:44:07 +02:00
|
|
|
offset
|
2022-03-03 02:10:25 +02:00
|
|
|
= 256*zmachine_backpatch_table[bm+2]
|
|
|
|
+ zmachine_backpatch_table[bm+3];
|
2019-02-05 02:44:07 +02:00
|
|
|
bm += 4;
|
|
|
|
|
|
|
|
switch(zmachine_area)
|
|
|
|
{ case PROP_DEFAULTS_ZA: addr = prop_defaults_offset; break;
|
|
|
|
case PROP_ZA: addr = prop_values_offset; break;
|
|
|
|
case INDIVIDUAL_PROP_ZA: addr = individuals_offset; break;
|
|
|
|
case DYNAMIC_ARRAY_ZA: addr = variables_offset; break;
|
2020-06-01 20:29:12 +03:00
|
|
|
case STATIC_ARRAY_ZA: addr = static_arrays_offset; break;
|
2019-02-05 02:44:07 +02:00
|
|
|
default:
|
2022-07-24 13:10:45 +03:00
|
|
|
if (compiler_error("Illegal area to backpatch"))
|
|
|
|
backpatch_error_flag = TRUE;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
addr += offset;
|
|
|
|
|
|
|
|
value = 256*zmachine_paged_memory[addr]
|
|
|
|
+ zmachine_paged_memory[addr+1];
|
|
|
|
value = backpatch_value_z(value);
|
|
|
|
zmachine_paged_memory[addr] = value/256;
|
|
|
|
zmachine_paged_memory[addr+1] = value%256;
|
|
|
|
|
|
|
|
if (backpatch_error_flag)
|
|
|
|
{ backpatch_error_flag = FALSE;
|
2022-07-24 13:10:45 +03:00
|
|
|
printf("*** MV %d ZA %d Off %04x ***\n",
|
|
|
|
backpatch_marker, zmachine_area, offset);
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void backpatch_zmachine_image_g(void)
|
|
|
|
{ int bm = 0, zmachine_area; int32 offset, value, addr = 0;
|
|
|
|
ASSERT_GLULX();
|
|
|
|
backpatch_error_flag = FALSE;
|
|
|
|
while (bm < zmachine_backpatch_size)
|
|
|
|
{ backpatch_marker
|
2022-03-03 02:10:25 +02:00
|
|
|
= zmachine_backpatch_table[bm];
|
2019-02-05 02:44:07 +02:00
|
|
|
zmachine_area
|
2022-03-03 02:10:25 +02:00
|
|
|
= zmachine_backpatch_table[bm+1];
|
|
|
|
offset = zmachine_backpatch_table[bm+2];
|
2019-02-05 02:44:07 +02:00
|
|
|
offset = (offset << 8) |
|
2022-03-03 02:10:25 +02:00
|
|
|
zmachine_backpatch_table[bm+3];
|
2019-02-05 02:44:07 +02:00
|
|
|
offset = (offset << 8) |
|
2022-03-03 02:10:25 +02:00
|
|
|
zmachine_backpatch_table[bm+4];
|
2019-02-05 02:44:07 +02:00
|
|
|
offset = (offset << 8) |
|
2022-03-03 02:10:25 +02:00
|
|
|
zmachine_backpatch_table[bm+5];
|
2022-07-24 13:10:45 +03:00
|
|
|
bm += 6;
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
switch(zmachine_area) {
|
|
|
|
case PROP_DEFAULTS_ZA: addr = prop_defaults_offset+4; break;
|
|
|
|
case PROP_ZA: addr = prop_values_offset; break;
|
|
|
|
case INDIVIDUAL_PROP_ZA: addr = individuals_offset; break;
|
2020-06-01 20:29:12 +03:00
|
|
|
case DYNAMIC_ARRAY_ZA: addr = arrays_offset; break;
|
2019-02-05 02:44:07 +02:00
|
|
|
case GLOBALVAR_ZA: addr = variables_offset; break;
|
2020-06-01 20:29:12 +03:00
|
|
|
/* STATIC_ARRAY_ZA is in ROM and therefore not handled here */
|
2019-02-05 02:44:07 +02:00
|
|
|
default:
|
|
|
|
if (compiler_error("Illegal area to backpatch"))
|
|
|
|
backpatch_error_flag = TRUE;
|
|
|
|
}
|
|
|
|
addr = addr + offset - Write_RAM_At;
|
|
|
|
|
|
|
|
value = (zmachine_paged_memory[addr] << 24)
|
|
|
|
| (zmachine_paged_memory[addr+1] << 16)
|
|
|
|
| (zmachine_paged_memory[addr+2] << 8)
|
|
|
|
| (zmachine_paged_memory[addr+3]);
|
|
|
|
value = backpatch_value_g(value);
|
|
|
|
zmachine_paged_memory[addr] = (value >> 24) & 0xFF;
|
|
|
|
zmachine_paged_memory[addr+1] = (value >> 16) & 0xFF;
|
|
|
|
zmachine_paged_memory[addr+2] = (value >> 8) & 0xFF;
|
|
|
|
zmachine_paged_memory[addr+3] = (value) & 0xFF;
|
|
|
|
|
|
|
|
if (backpatch_error_flag)
|
|
|
|
{ backpatch_error_flag = FALSE;
|
2022-07-24 13:10:45 +03:00
|
|
|
printf("*** MV %d ZA %d Off %04x ***\n",
|
|
|
|
backpatch_marker, zmachine_area, offset);
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ========================================================================= */
|
|
|
|
/* Data structure management routines */
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
extern void init_bpatch_vars(void)
|
2022-03-03 02:10:25 +02:00
|
|
|
{ zcode_backpatch_table = NULL;
|
|
|
|
staticarray_backpatch_table = NULL;
|
|
|
|
zmachine_backpatch_table = NULL;
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
extern void bpatch_begin_pass(void)
|
|
|
|
{ zcode_backpatch_size = 0;
|
2020-06-01 20:29:12 +03:00
|
|
|
staticarray_backpatch_size = 0;
|
2019-02-05 02:44:07 +02:00
|
|
|
zmachine_backpatch_size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void bpatch_allocate_arrays(void)
|
|
|
|
{
|
2022-03-03 02:10:25 +02:00
|
|
|
initialise_memory_list(&zcode_backpatch_table_memlist,
|
|
|
|
sizeof(uchar), 128, (void**)&zcode_backpatch_table,
|
|
|
|
"code backpatch table");
|
|
|
|
initialise_memory_list(&staticarray_backpatch_table_memlist,
|
|
|
|
sizeof(uchar), 128, (void**)&staticarray_backpatch_table,
|
|
|
|
"static array backpatch table");
|
|
|
|
initialise_memory_list(&zmachine_backpatch_table_memlist,
|
|
|
|
sizeof(uchar), 128, (void**)&zmachine_backpatch_table,
|
|
|
|
"machine backpatch table");
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
extern void bpatch_free_arrays(void)
|
2022-03-03 02:10:25 +02:00
|
|
|
{ deallocate_memory_list(&zcode_backpatch_table_memlist);
|
|
|
|
deallocate_memory_list(&staticarray_backpatch_table_memlist);
|
|
|
|
deallocate_memory_list(&zmachine_backpatch_table_memlist);
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ========================================================================= */
|