From bfd41bb40cbe45bae5c97417bd4922fff4ae8c19 Mon Sep 17 00:00:00 2001 From: Mike Klaas Date: Mon, 22 Jun 2026 20:44:36 -0700 Subject: [PATCH] opcode registration --- src/options.cc | 2 ++ src/sfall_metarules.cc | 78 ++++++++++++++++++++++++++++++++++++------ src/sfall_opcodes.cc | 7 ++++ 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/src/options.cc b/src/options.cc index 08b458a6..92bad66f 100644 --- a/src/options.cc +++ b/src/options.cc @@ -74,6 +74,8 @@ static bool gOptionsWindowGameMouseObjectsWasVisible; // 0x663900 optnwin static int gOptionsWindow; +static int gPauseWindow = -1; + // 0x663908 winbuf static unsigned char* gOptionsWindowBuffer; diff --git a/src/sfall_metarules.cc b/src/sfall_metarules.cc index 5d124ba0..1c90412b 100644 --- a/src/sfall_metarules.cc +++ b/src/sfall_metarules.cc @@ -6,10 +6,13 @@ #include #include +#include "automap.h" #include "art.h" +#include "character_editor.h" #include "color.h" #include "combat.h" #include "config.h" // For Config, configInit, configFree +#include "datafile.h" #include "dbox.h" #include "debug.h" #include "game.h" @@ -24,9 +27,12 @@ #include "message.h" #include "object.h" #include "opcode_context.h" +#include "options.h" #include "platform_compat.h" +#include "pipboy.h" #include "proto_instance.h" #include "scripts.h" +#include "skilldex.h" #include "sfall_animation.h" #include "sfall_arrays.h" // For CreateTempArray, SetArray #include "sfall_ini.h" @@ -35,6 +41,7 @@ #include "text_font.h" #include "tile.h" #include "window.h" +#include "window_manager.h" #include "worldmap.h" #include @@ -44,8 +51,11 @@ namespace fallout { static void mf_attack_is_aimed(OpcodeContext& ctx); static void mf_car_gas_amount(OpcodeContext& ctx); static void mf_combat_data(OpcodeContext& ctx); +static void mf_create_win(OpcodeContext& ctx); static void mf_critter_inven_obj2(OpcodeContext& ctx); static void mf_dialog_obj(OpcodeContext& ctx); +static void mf_dialog_message(OpcodeContext& ctx); +static void mf_display_stats(OpcodeContext& ctx); static void mf_get_combat_free_move(OpcodeContext& ctx); static void mf_get_cursor_mode(OpcodeContext& ctx); static void mf_get_flags(OpcodeContext& ctx); @@ -54,12 +64,17 @@ static void mf_get_object_data(OpcodeContext& ctx); static void mf_get_outline(OpcodeContext& ctx); static void mf_get_sfall_arg_at(OpcodeContext& ctx); static void mf_get_text_width(OpcodeContext& ctx); +static void mf_get_window_attribute(OpcodeContext& ctx); +static void mf_hide_window(OpcodeContext& ctx); +static void mf_interface_art_draw(OpcodeContext& ctx); static void mf_intface_redraw(OpcodeContext& ctx); +static void mf_inventory_redraw(OpcodeContext& ctx); static void mf_item_weight(OpcodeContext& ctx); static void mf_loot_obj(OpcodeContext& ctx); static void mf_message_box(OpcodeContext& ctx); static void mf_add_extra_msg_file(OpcodeContext& ctx); static void mf_add_iface_tag(OpcodeContext& ctx); +static void mf_art_frame_data(OpcodeContext& ctx); static void mf_art_cache_flush(OpcodeContext& ctx); static void mf_metarule_exist(OpcodeContext& ctx); static void mf_obj_is_openable(OpcodeContext& ctx); @@ -72,12 +87,14 @@ static void mf_set_cursor_mode(OpcodeContext& ctx); static void mf_set_flags(OpcodeContext& ctx); static void mf_set_iface_tag_text(OpcodeContext& ctx); static void mf_set_outline(OpcodeContext& ctx); +static void mf_set_window_flag(OpcodeContext& ctx); static void mf_set_unique_id(OpcodeContext& ctx); static void mf_show_window(OpcodeContext& ctx); static void mf_signal_close_game(OpcodeContext& ctx); static void mf_tile_by_position(OpcodeContext& ctx); static void mf_tile_refresh_display(OpcodeContext& ctx); static void mf_unwield_slot(OpcodeContext& ctx); +static void mf_win_fill_color(OpcodeContext& ctx); static void mf_string_compare(OpcodeContext& ctx); static void mf_string_find(OpcodeContext& ctx); static void mf_string_to_case(OpcodeContext& ctx); @@ -93,22 +110,21 @@ const MetaruleInfo kMetarules[] = { // {"add_g_timer_event", mf_add_g_timer_event, 2, 2, -1, {ARG_INT, ARG_INT}}, // {"add_trait", mf_add_trait, 1, 1, -1, {ARG_INT}}, { "art_cache_clear", mf_art_cache_flush, 0, 0 }, - // {"art_frame_data", mf_art_frame_data, 1, 3, 0, {ARG_INTSTR, ARG_INT, ARG_INT}}, + { "art_frame_data", mf_art_frame_data, 1, 3, 0, { ARG_INTSTR, ARG_INT, ARG_INT } }, { "attack_is_aimed", mf_attack_is_aimed, 0, 0 }, { "car_gas_amount", mf_car_gas_amount, 0, 0 }, { "combat_data", mf_combat_data, 0, 0 }, - // {"create_win", mf_create_win, 5, 6, -1, {ARG_STRING, ARG_INT, ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, + { "create_win", mf_create_win, 5, 6, -1, { ARG_STRING, ARG_INT, ARG_INT, ARG_INT, ARG_INT, ARG_INT } }, { "critter_inven_obj2", mf_critter_inven_obj2, 2, 2, 0, { ARG_OBJECT, ARG_INT } }, - // {"dialog_message", mf_dialog_message, 1, 1, -1, {ARG_STRING}}, + { "dialog_message", mf_dialog_message, 1, 1, -1, { ARG_STRING } }, { "dialog_obj", mf_dialog_obj, 0, 0 }, - // {"display_stats", mf_display_stats, 0, 0}, // refresh + { "display_stats", mf_display_stats, 0, 0 }, // refresh // {"draw_image", mf_draw_image, 1, 5, -1, {ARG_INTSTR, ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, // {"draw_image_scaled", mf_draw_image_scaled, 1, 6, -1, {ARG_INTSTR, ARG_INT, ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, // {"exec_map_update_scripts", mf_exec_map_update_scripts, 0, 0}, { "floor2", mf_floor2, 1, 1, 0, { ARG_NUMBER } }, // {"get_can_rest_on_map", mf_get_rest_on_map, 2, 2, -1, {ARG_INT, ARG_INT}}, { "get_combat_free_move", mf_get_combat_free_move, 0, 0 }, - // {"get_current_inven_size", mf_get_current_inven_size, 1, 1, 0, {ARG_OBJECT}}, { "get_cursor_mode", mf_get_cursor_mode, 0, 0 }, { "get_flags", mf_get_flags, 1, 1, 0, { ARG_OBJECT } }, { "get_ini_config", mf_get_ini_config, 2, 2, 0, { ARG_STRING, ARG_INT } }, @@ -126,18 +142,18 @@ const MetaruleInfo kMetarules[] = { // {"get_string_pointer", mf_get_string_pointer, 1, 1, 0, {ARG_STRING}}, // note: deprecated; do not implement // {"get_terrain_name", mf_get_terrain_name, 0, 2, -1, {ARG_INT, ARG_INT}}, { "get_text_width", mf_get_text_width, 1, 1, 0, { ARG_STRING } }, - // {"get_window_attribute", mf_get_window_attribute, 1, 2, -1, {ARG_INT, ARG_INT}}, + { "get_window_attribute", mf_get_window_attribute, 1, 2, -1, { ARG_INT, ARG_INT } }, // {"has_fake_perk_npc", mf_has_fake_perk_npc, 2, 2, 0, {ARG_OBJECT, ARG_STRING}}, // {"has_fake_trait_npc", mf_has_fake_trait_npc, 2, 2, 0, {ARG_OBJECT, ARG_STRING}}, - // {"hide_window", mf_hide_window, 0, 1, -1, {ARG_STRING}}, - // {"interface_art_draw", mf_interface_art_draw, 4, 6, -1, {ARG_INT, ARG_INTSTR, ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, + { "hide_window", mf_hide_window, 0, 1, -1, { ARG_STRING } }, + { "interface_art_draw", mf_interface_art_draw, 4, 6, -1, { ARG_INT, ARG_INTSTR, ARG_INT, ARG_INT, ARG_INT, ARG_INT } }, // {"interface_overlay", mf_interface_overlay, 2, 6, -1, {ARG_INT, ARG_INT, ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, // {"interface_print", mf_interface_print, 5, 6, -1, {ARG_STRING, ARG_INT, ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, // {"intface_hide", mf_intface_hide, 0, 0}, // {"intface_is_hidden", mf_intface_is_hidden, 0, 0}, { "intface_redraw", mf_intface_redraw, 0, 1 }, // {"intface_show", mf_intface_show, 0, 0}, - // {"inventory_redraw", mf_inventory_redraw, 0, 1, -1, {ARG_INT}}, + { "inventory_redraw", mf_inventory_redraw, 0, 1, -1, { ARG_INT } }, // {"item_make_explosive", mf_item_make_explosive, 3, 4, -1, {ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, { "item_weight", mf_item_weight, 1, 1, 0, { ARG_OBJECT } }, // {"lock_is_jammed", mf_lock_is_jammed, 1, 1, 0, {ARG_OBJECT}}, @@ -177,7 +193,7 @@ const MetaruleInfo kMetarules[] = { // {"set_town_title", mf_set_town_title, 2, 2, -1, {ARG_INT, ARG_STRING}}, { "set_unique_id", mf_set_unique_id, 1, 2, -1, { ARG_OBJECT, ARG_INT } }, // {"set_unjam_locks_time", mf_set_unjam_locks_time, 1, 1, -1, {ARG_INT}}, - // {"set_window_flag", mf_set_window_flag, 3, 3, -1, {ARG_INTSTR, ARG_INT, ARG_INT}}, + { "set_window_flag", mf_set_window_flag, 3, 3, -1, { ARG_INTSTR, ARG_INT, ARG_INT } }, { "show_window", mf_show_window, 0, 1, -1, { ARG_STRING } }, { "signal_close_game", mf_signal_close_game, 0, 0 }, // {"spatial_radius", mf_spatial_radius, 1, 1, 0, {ARG_OBJECT}}, @@ -236,6 +252,35 @@ void mf_combat_data(OpcodeContext& ctx) } } +void mf_create_win(OpcodeContext& ctx) +{ + int flags = ctx.numArgs() > 5 + ? ctx.arg(5).asInt() + : WINDOW_MOVE_ON_TOP; + + int color = (flags & WINDOW_TRANSPARENT) != 0 ? 0 : 256; + if (scriptWindowCreate(ctx.stringArg(0), + ctx.arg(1).asInt(), + ctx.arg(2).asInt(), + ctx.arg(3).asInt(), + ctx.arg(4).asInt(), + color, + flags) + == -1) { + ctx.printError("%s() - couldn't create window.", ctx.name()); + ctx.setReturn(-1); + } +} + +void mf_display_stats(OpcodeContext& ctx) +{ + if (GameMode::isInGameMode(GameMode::kInventory)) { + inventoryDisplayStats(); + } else if (GameMode::isInGameMode(GameMode::kEditor)) { + characterEditorDisplayStats(); + } +} + void mf_critter_inven_obj2(OpcodeContext& ctx) { Object* obj = ctx.arg(0).asObject(); @@ -268,6 +313,14 @@ void mf_dialog_obj(OpcodeContext& ctx) } } +void mf_dialog_message(OpcodeContext& ctx) +{ + if (GameMode::isInGameMode(GameMode::kDialog) + && !GameMode::isInGameMode(GameMode::kDialogReview)) { + gameDialogRenderSupplementaryMessage(ctx.stringArg(0)); + } +} + void mf_get_combat_free_move(OpcodeContext& ctx) { ctx.setReturn(_combat_free_move); @@ -341,6 +394,11 @@ void mf_intface_redraw(OpcodeContext& ctx) } } +void mf_inventory_redraw(OpcodeContext& ctx) +{ + inventoryRedraw(ctx.numArgs() > 0 ? ctx.arg(0).asInt() : -1); +} + void mf_item_weight(OpcodeContext& ctx) { Object* object = ctx.arg(0).asObject(); diff --git a/src/sfall_opcodes.cc b/src/sfall_opcodes.cc index 4f6eaf99..3fe16f44 100644 --- a/src/sfall_opcodes.cc +++ b/src/sfall_opcodes.cc @@ -42,6 +42,7 @@ #include "stat.h" #include "svga.h" #include "tile.h" +#include "window_manager.h" #include "worldmap.h" namespace fallout { @@ -899,6 +900,11 @@ static void op_get_mouse_buttons(Program* program) programStackPushInteger(program, mouse_get_last_buttons()); } +static void op_get_window_under_mouse(Program* program) +{ + programStackPushInteger(program, _win_last_button_winID()); +} + // get_screen_width static void op_get_screen_width(Program* program) { @@ -1873,6 +1879,7 @@ void sfallOpcodesInit() // 0x821e - int get_mouse_buttons() interpreterRegisterOpcode(0x821E, op_get_mouse_buttons); // 0x821f - int get_window_under_mouse() + interpreterRegisterOpcode(0x821F, op_get_window_under_mouse); // 0x8163 - int get_year() interpreterRegisterOpcode(0x8163, op_get_year);