mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Rewrote get/set_proto_data functions in C++ and added an auto-extend mechanism for proto loading limit (from Mr.Stalin)
Replaced ProtoProcessingLimit with LoadProtoMaxLimit option. Added more definitions to define_extra.h and reformatted sfall.h a bit.
This commit is contained in:
+4
-4
@@ -347,6 +347,10 @@ CorpseLineOfFireFix=0
|
||||
;Set to 1 (or some higher number if needed, the maximum is 127) to prevent 100% CPU use
|
||||
ProcessorIdle=-1
|
||||
|
||||
;Set a number of how many protos of a type can be loaded into memory at once (valid range: 512..4096)
|
||||
;Set to -1 to let set_proto_data script function automatically increase the limit when needed
|
||||
LoadProtoMaxLimit=-1
|
||||
|
||||
;Set to 1 if using the hero appearance mod
|
||||
EnableHeroAppearanceMod=0
|
||||
|
||||
@@ -549,10 +553,6 @@ ExplosionsEmitLight=0
|
||||
;MovieTimer_artimer3=270
|
||||
;MovieTimer_artimer4=360
|
||||
|
||||
;Uncomment the next line to change how many protos the engine can process at once (valid range: 512..16384)
|
||||
;Set to 1024 or some higher number to avoid some glitches with scripts that will process a large number of protos
|
||||
;ProtoProcessingLimit=512
|
||||
|
||||
;Set to 1 to enable the new arrays behavior
|
||||
;Set to 0 for backward compatibility with pre-3.4 scripts
|
||||
arraysBehavior=1
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
#define OBJ_TYPE_MISC (5)
|
||||
#define OBJ_TYPE_SPATIAL (6)
|
||||
|
||||
#define WEAPON_TYPE_NONE (0)
|
||||
#define WEAPON_TYPE_UNARMED (1)
|
||||
#define WEAPON_TYPE_MELEE (2)
|
||||
#define WEAPON_TYPE_THROWN (3)
|
||||
#define WEAPON_TYPE_GUNS (4)
|
||||
|
||||
/* Item Common Flags */
|
||||
#define HIDDEN_ITEM 134217728 // 0x08000000 - Hidden Item
|
||||
|
||||
@@ -21,14 +27,14 @@
|
||||
#define WEAPON_2HAND 512 // 0x00000200 - 2Hnd (weapon is two-handed)
|
||||
|
||||
#define ATKMODE_PRI_NONE 0
|
||||
#define ATKMODE_PRI_PUNCH 1
|
||||
#define ATKMODE_PRI_KICK 2
|
||||
#define ATKMODE_PRI_SWING 3
|
||||
#define ATKMODE_PRI_THRUST 4
|
||||
#define ATKMODE_PRI_THROW 5
|
||||
#define ATKMODE_PRI_SINGLE 6
|
||||
#define ATKMODE_PRI_BURST 7
|
||||
#define ATKMODE_PRI_FLAME 8
|
||||
#define ATKMODE_PRI_PUNCH 1 // 0001
|
||||
#define ATKMODE_PRI_KICK 2 // 0010
|
||||
#define ATKMODE_PRI_SWING 3 // 0011
|
||||
#define ATKMODE_PRI_THRUST 4 // 0100
|
||||
#define ATKMODE_PRI_THROW 5 // 0101
|
||||
#define ATKMODE_PRI_SINGLE 6 // 0110
|
||||
#define ATKMODE_PRI_BURST 7 // 0111
|
||||
#define ATKMODE_PRI_FLAME 8 // 1000
|
||||
#define ATKMODE_SEC_NONE 0
|
||||
#define ATKMODE_SEC_PUNCH 16 // 0x00000010
|
||||
#define ATKMODE_SEC_KICK 32 // 0x00000020
|
||||
@@ -101,15 +107,21 @@
|
||||
// offsets for get_proto_data
|
||||
#define PROTO_PID (1)
|
||||
#define PROTO_TEXTID (4)
|
||||
#define PROTO_FID (8)
|
||||
|
||||
// items
|
||||
#define PROTO_IT_LDIST (12)
|
||||
#define PROTO_IT_LINT (16)
|
||||
#define PROTO_IT_FLAG (20)
|
||||
#define PROTO_IT_FLAGS (24)
|
||||
#define PROTO_IT_SCRIPTID (28)
|
||||
#define PROTO_IT_TYPE (32)
|
||||
#define PROTO_IT_MATERIAL (108)
|
||||
#define PROTO_IT_SIZE (112)
|
||||
#define PROTO_IT_WEIGHT (116)
|
||||
#define PROTO_IT_COST (120)
|
||||
#define PROTO_IT_INV_FID (124)
|
||||
#define PROTO_IT_SOUND (128) // byte
|
||||
|
||||
// weapons
|
||||
#define PROTO_WP_ANIM (36)
|
||||
@@ -187,7 +199,11 @@
|
||||
#define PROTO_DR_ADDICT_DELAY (100)
|
||||
|
||||
// critters
|
||||
#define PROTO_CR_FLAGS (32)
|
||||
#define PROTO_CR_LDIST (20)
|
||||
#define PROTO_CR_LINT (24)
|
||||
#define PROTO_CR_FLAG (28)
|
||||
#define PROTO_CR_FLAGS (32) // Critter Flags
|
||||
#define PROTO_CR_SCRIPTID (36)
|
||||
#define PROTO_CR_HEAD_FID (40)
|
||||
#define PROTO_CR_AI_PACKET (44)
|
||||
#define PROTO_CR_TEAM_NUM (48)
|
||||
|
||||
@@ -221,45 +221,45 @@
|
||||
#define party_member_list_all party_member_list(1)
|
||||
|
||||
|
||||
#define attack_is_aimed sfall_func0("attack_is_aimed")
|
||||
#define car_gas_amount sfall_func0("car_gas_amount")
|
||||
#define create_win(winName, x, y, w, h) sfall_func5("create_win", winName, x, y, w, h)
|
||||
#define create_win_flag(winName, x, y, w, h, flag) sfall_func6("create_win", winName, x, y, w, h, flag)
|
||||
#define critter_inven_obj2(obj, type) sfall_func2("critter_inven_obj2", obj, type)
|
||||
#define dialog_message(text) sfall_func1("dialog_message", text)
|
||||
#define display_stats sfall_func0("display_stats")
|
||||
#define exec_map_update_scripts sfall_func0("exec_map_update_scripts")
|
||||
#define floor2(value) sfall_func1("floor2", value)
|
||||
#define get_can_rest_on_map(map, elev) sfall_func2("get_can_rest_on_map", map, elev)
|
||||
#define get_current_inven_size(obj) sfall_func1("get_current_inven_size", obj)
|
||||
#define get_cursor_mode sfall_func0("get_cursor_mode")
|
||||
#define get_flags(obj) sfall_func1("get_flags", obj)
|
||||
#define get_ini_section(file, sect) sfall_func2("get_ini_section", file, sect)
|
||||
#define get_ini_sections(file) sfall_func1("get_ini_sections", file)
|
||||
#define get_map_enter_position sfall_func0("get_map_enter_position")
|
||||
#define get_outline(obj) sfall_func1("get_outline", obj)
|
||||
#define get_string_pointer(text) sfall_func1("get_string_pointer", text)
|
||||
#define intface_hide sfall_func0("intface_hide")
|
||||
#define intface_is_hidden sfall_func0("intface_is_hidden")
|
||||
#define intface_redraw sfall_func0("intface_redraw")
|
||||
#define intface_show sfall_func0("intface_show")
|
||||
#define inventory_redraw(invSide) sfall_func1("inventory_redraw", invSide)
|
||||
#define item_weight(obj) sfall_func1("item_weight", obj)
|
||||
#define lock_is_jammed(obj) sfall_func1("lock_is_jammed", obj)
|
||||
#define outlined_object sfall_func0("outlined_object")
|
||||
#define real_dude_obj sfall_func0("real_dude_obj")
|
||||
#define set_can_rest_on_map(map, elev, value) sfall_func3("set_can_rest_on_map", map, elev, value)
|
||||
#define set_car_intface_art(artIndex) sfall_func1("set_car_intface_art", artIndex)
|
||||
#define set_cursor_mode(mode) sfall_func1("set_cursor_mode", mode)
|
||||
#define set_dude_obj(critter) sfall_func1("set_dude_obj", critter)
|
||||
#define set_flags(obj, flags) sfall_func2("set_flags", obj, flags)
|
||||
#define set_iface_tag_text(tag, text, color) sfall_func3("set_iface_tag_text", tag, text, color)
|
||||
#define set_ini_setting(setting, value) sfall_func2("set_ini_setting", setting, value)
|
||||
#define set_map_enter_position(tile, elev, rot) sfall_func3("set_map_enter_position", tile, elev, rot)
|
||||
#define set_outline(obj, color) sfall_func2("set_outline", obj, color)
|
||||
#define set_rest_heal_time(time) sfall_func1("set_rest_heal_time", time)
|
||||
#define set_rest_mode(mode) sfall_func1("set_rest_mode", mode)
|
||||
#define set_unjam_locks_time(time) sfall_func1("set_unjam_locks_time", time)
|
||||
#define spatial_radius(obj) sfall_func1("spatial_radius", obj)
|
||||
#define tile_refresh_display sfall_func0("tile_refresh_display")
|
||||
#define unjam_lock(obj) sfall_func1("unjam_lock", obj)
|
||||
#define attack_is_aimed sfall_func0("attack_is_aimed")
|
||||
#define car_gas_amount sfall_func0("car_gas_amount")
|
||||
#define create_win(winName, x, y, w, h) sfall_func5("create_win", winName, x, y, w, h)
|
||||
#define create_win_flag(winName, x, y, w, h, flag) sfall_func6("create_win", winName, x, y, w, h, flag)
|
||||
#define critter_inven_obj2(obj, type) sfall_func2("critter_inven_obj2", obj, type)
|
||||
#define dialog_message(text) sfall_func1("dialog_message", text)
|
||||
#define display_stats sfall_func0("display_stats")
|
||||
#define exec_map_update_scripts sfall_func0("exec_map_update_scripts")
|
||||
#define floor2(value) sfall_func1("floor2", value)
|
||||
#define get_can_rest_on_map(map, elev) sfall_func2("get_can_rest_on_map", map, elev)
|
||||
#define get_current_inven_size(obj) sfall_func1("get_current_inven_size", obj)
|
||||
#define get_cursor_mode sfall_func0("get_cursor_mode")
|
||||
#define get_flags(obj) sfall_func1("get_flags", obj)
|
||||
#define get_ini_section(file, sect) sfall_func2("get_ini_section", file, sect)
|
||||
#define get_ini_sections(file) sfall_func1("get_ini_sections", file)
|
||||
#define get_map_enter_position sfall_func0("get_map_enter_position")
|
||||
#define get_outline(obj) sfall_func1("get_outline", obj)
|
||||
#define get_string_pointer(text) sfall_func1("get_string_pointer", text)
|
||||
#define intface_hide sfall_func0("intface_hide")
|
||||
#define intface_is_hidden sfall_func0("intface_is_hidden")
|
||||
#define intface_redraw sfall_func0("intface_redraw")
|
||||
#define intface_show sfall_func0("intface_show")
|
||||
#define inventory_redraw(invSide) sfall_func1("inventory_redraw", invSide)
|
||||
#define item_weight(obj) sfall_func1("item_weight", obj)
|
||||
#define lock_is_jammed(obj) sfall_func1("lock_is_jammed", obj)
|
||||
#define outlined_object sfall_func0("outlined_object")
|
||||
#define real_dude_obj sfall_func0("real_dude_obj")
|
||||
#define set_can_rest_on_map(map, elev, value) sfall_func3("set_can_rest_on_map", map, elev, value)
|
||||
#define set_car_intface_art(artIndex) sfall_func1("set_car_intface_art", artIndex)
|
||||
#define set_cursor_mode(mode) sfall_func1("set_cursor_mode", mode)
|
||||
#define set_dude_obj(critter) sfall_func1("set_dude_obj", critter)
|
||||
#define set_flags(obj, flags) sfall_func2("set_flags", obj, flags)
|
||||
#define set_iface_tag_text(tag, text, color) sfall_func3("set_iface_tag_text", tag, text, color)
|
||||
#define set_ini_setting(setting, value) sfall_func2("set_ini_setting", setting, value)
|
||||
#define set_map_enter_position(tile, elev, rot) sfall_func3("set_map_enter_position", tile, elev, rot)
|
||||
#define set_outline(obj, color) sfall_func2("set_outline", obj, color)
|
||||
#define set_rest_heal_time(time) sfall_func1("set_rest_heal_time", time)
|
||||
#define set_rest_mode(mode) sfall_func1("set_rest_mode", mode)
|
||||
#define set_unjam_locks_time(time) sfall_func1("set_unjam_locks_time", time)
|
||||
#define spatial_radius(obj) sfall_func1("spatial_radius", obj)
|
||||
#define tile_refresh_display sfall_func0("tile_refresh_display")
|
||||
#define unjam_lock(obj) sfall_func1("unjam_lock", obj)
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace sfall
|
||||
{
|
||||
|
||||
static int unjamTimeState;
|
||||
static int maxCountProto = 512;
|
||||
|
||||
void Objects::SetAutoUnjamLockTime(DWORD time) {
|
||||
if (!unjamTimeState) {
|
||||
@@ -54,10 +55,41 @@ void RestoreObjUnjamAllLocks() {
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) proto_ptr_hack() {
|
||||
__asm {
|
||||
mov ecx, maxCountProto;
|
||||
cmp ecx, 4096;
|
||||
jae skip;
|
||||
cmp eax, ecx;
|
||||
jb end;
|
||||
add ecx, 256;
|
||||
mov maxCountProto, ecx;
|
||||
skip:
|
||||
cmp eax, ecx;
|
||||
end:
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void Objects::LoadProtoAutoMaxLimit() {
|
||||
if (maxCountProto != -1) {
|
||||
MakeCall(0x4A21B2, proto_ptr_hack);
|
||||
}
|
||||
}
|
||||
|
||||
void Objects::init() {
|
||||
LoadGameHook::OnGameReset() += [] () {
|
||||
LoadGameHook::OnGameReset() += []() {
|
||||
RestoreObjUnjamAllLocks();
|
||||
};
|
||||
|
||||
int maxlimit = GetConfigInt("Misc", "LoadProtoMaxLimit", -1);
|
||||
if (maxlimit != -1) {
|
||||
maxCountProto = -1;
|
||||
if (maxlimit > 512) {
|
||||
if (maxlimit > 4096) maxlimit = 4096;
|
||||
SafeWrite32(0x4A21B3, maxlimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ public:
|
||||
void init();
|
||||
|
||||
static void SetAutoUnjamLockTime(DWORD time);
|
||||
static void LoadProtoAutoMaxLimit();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -661,9 +661,6 @@ void ScriptExtender::init() {
|
||||
}
|
||||
modifiedIni = GetConfigInt("Main", "ModifiedIni", 0);
|
||||
|
||||
// increase the processing limit of proto_ptr_ engine function
|
||||
SimplePatch<DWORD>(0x4A21B3, "Misc", "ProtoProcessingLimit", 512, 512, 16384);
|
||||
|
||||
arraysBehavior = GetConfigInt("Misc", "arraysBehavior", 1);
|
||||
if (arraysBehavior > 0) {
|
||||
arraysBehavior = 1; // only 1 and 0 allowed at this time
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "..\..\Knockback.h"
|
||||
#include "..\..\MiscPatches.h"
|
||||
#include "..\..\Movies.h"
|
||||
#include "..\..\Objects.h"
|
||||
#include "..\..\PlayerModel.h"
|
||||
#include "..\..\ScriptExtender.h"
|
||||
#include "..\..\Stats.h"
|
||||
@@ -1145,84 +1146,30 @@ void __declspec(naked) op_nb_create_char() {
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) op_get_proto_data() {
|
||||
__asm {
|
||||
pushad;
|
||||
sub esp, 4;
|
||||
mov ebp, eax;
|
||||
call fo::funcoffs::interpretPopShort_;
|
||||
mov edi, eax;
|
||||
mov eax, ebp;
|
||||
call fo::funcoffs::interpretPopLong_;
|
||||
mov ecx, eax;
|
||||
mov eax, ebp;
|
||||
call fo::funcoffs::interpretPopShort_;
|
||||
mov esi, eax;
|
||||
mov eax, ebp;
|
||||
call fo::funcoffs::interpretPopLong_;
|
||||
cmp di, VAR_TYPE_INT;
|
||||
jnz fail;
|
||||
cmp si, VAR_TYPE_INT;
|
||||
jnz fail;
|
||||
mov edx, esp;
|
||||
call fo::funcoffs::proto_ptr_;
|
||||
mov eax, [esp];
|
||||
test eax, eax;
|
||||
jz fail;
|
||||
mov edx, [eax+ecx/**4*/];
|
||||
jmp end;
|
||||
fail:
|
||||
xor edx, edx;
|
||||
dec edx;
|
||||
end:
|
||||
mov eax, ebp;
|
||||
call fo::funcoffs::interpretPushLong_;
|
||||
mov eax, ebp;
|
||||
mov edx, VAR_TYPE_INT;
|
||||
call fo::funcoffs::interpretPushShort_;
|
||||
add esp, 4;
|
||||
popad;
|
||||
retn;
|
||||
void sf_get_proto_data(OpcodeContext& ctx) {
|
||||
fo::Proto* protoPtr;
|
||||
int pid = ctx.arg(0).rawValue();
|
||||
int result = fo::func::proto_ptr(pid, &protoPtr);
|
||||
if (result != -1) {
|
||||
result = *(long*)((BYTE*)protoPtr + ctx.arg(1).rawValue());
|
||||
} else {
|
||||
ctx.printOpcodeError("get_proto_data() - failed to load a prototype id: %d", pid);
|
||||
}
|
||||
ctx.setReturn(result);
|
||||
}
|
||||
|
||||
void __declspec(naked) op_set_proto_data() {
|
||||
__asm {
|
||||
pushad;
|
||||
sub esp, 4;
|
||||
mov ebp, eax;
|
||||
call fo::funcoffs::interpretPopShort_;
|
||||
mov edi, eax;
|
||||
mov eax, ebp;
|
||||
call fo::funcoffs::interpretPopLong_;
|
||||
mov ecx, eax;
|
||||
mov eax, ebp;
|
||||
call fo::funcoffs::interpretPopShort_;
|
||||
mov esi, eax;
|
||||
mov eax, ebp;
|
||||
call fo::funcoffs::interpretPopLong_;
|
||||
mov ebx, eax;
|
||||
mov eax, ebp;
|
||||
call fo::funcoffs::interpretPopShort_;
|
||||
xchg eax, ebp;
|
||||
call fo::funcoffs::interpretPopLong_;
|
||||
cmp di, VAR_TYPE_INT;
|
||||
jnz end;
|
||||
cmp si, VAR_TYPE_INT;
|
||||
jnz end;
|
||||
cmp bp, VAR_TYPE_INT;
|
||||
jnz end;
|
||||
//mov eax, [eax+0x64];
|
||||
mov edx, esp;
|
||||
call fo::funcoffs::proto_ptr_;
|
||||
mov eax, [esp];
|
||||
test eax, eax;
|
||||
jz end;
|
||||
mov [eax+ebx/**4*/], ecx;
|
||||
end:
|
||||
add esp, 4;
|
||||
popad;
|
||||
retn;
|
||||
static bool protoMaxLimitPatch = false;
|
||||
void sf_set_proto_data(OpcodeContext& ctx) {
|
||||
fo::Proto* protoPtr;
|
||||
int pid = ctx.arg(0).rawValue();
|
||||
if (fo::func::proto_ptr(pid, &protoPtr) != -1) {
|
||||
*(long*)((BYTE*)protoPtr + ctx.arg(1).rawValue()) = ctx.arg(2).rawValue();
|
||||
if (!protoMaxLimitPatch) {
|
||||
Objects::LoadProtoAutoMaxLimit();
|
||||
protoMaxLimitPatch = true;
|
||||
}
|
||||
} else {
|
||||
ctx.printOpcodeError("set_proto_data() - failed to load a prototype id: %d", pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -109,9 +109,9 @@ void __declspec() op_set_palette();
|
||||
//numbers subgame functions
|
||||
void __declspec() op_nb_create_char();
|
||||
|
||||
void __declspec() op_get_proto_data();
|
||||
void sf_get_proto_data(OpcodeContext&);
|
||||
|
||||
void __declspec() op_set_proto_data();
|
||||
void sf_set_proto_data(OpcodeContext&);
|
||||
|
||||
void __declspec() op_hero_select_win() ;
|
||||
|
||||
|
||||
@@ -90,6 +90,8 @@ static SfallOpcodeInfo opcodeInfoArray[] = {
|
||||
{0x201, "fs_pos", sf_fs_pos, 1, true, {ARG_INT}},
|
||||
{0x202, "fs_seek", sf_fs_seek, 2, false, {ARG_INT, ARG_INT}},
|
||||
{0x203, "fs_resize", sf_fs_resize, 2, false, {ARG_INT, ARG_INT}},
|
||||
{0x204, "get_proto_data", sf_get_proto_data, 2, true, {ARG_INT, ARG_INT}},
|
||||
{0x205, "set_proto_data", sf_set_proto_data, 3, false, {ARG_INT, ARG_INT, ARG_INT}},
|
||||
{0x207, "register_hook", sf_register_hook, 1, false, {ARG_INT}},
|
||||
{0x208, "fs_write_bstring", sf_fs_write_bstring, 2, false, {ARG_INT, ARG_STRING}},
|
||||
{0x209, "fs_read_byte", sf_fs_read_byte, 1, true, {ARG_INT}},
|
||||
@@ -188,7 +190,7 @@ void InitOpcodeInfoTable() {
|
||||
|
||||
// Default handler for Sfall Opcodes.
|
||||
// Searches current opcode in Opcode Info table and executes the appropriate handler.
|
||||
void __stdcall defaultOpcodeHandlerStdcall(fo::Program* program, DWORD opcodeOffset) {
|
||||
void __fastcall defaultOpcodeHandlerCall(fo::Program* program, DWORD opcodeOffset) {
|
||||
int opcode = opcodeOffset / 4;
|
||||
auto iter = opcodeInfoMap.find(opcode);
|
||||
if (iter != opcodeInfoMap.end()) {
|
||||
@@ -203,11 +205,14 @@ void __stdcall defaultOpcodeHandlerStdcall(fo::Program* program, DWORD opcodeOff
|
||||
// Default handler for Sfall opcodes (naked function for integration with the engine).
|
||||
void __declspec(naked) defaultOpcodeHandler() {
|
||||
__asm {
|
||||
pushad;
|
||||
push edx;
|
||||
push eax;
|
||||
call defaultOpcodeHandlerStdcall;
|
||||
popad;
|
||||
push ecx;
|
||||
push edx;
|
||||
mov ecx, eax; // ecx - program
|
||||
call defaultOpcodeHandlerCall; // edx - opcodeOffset
|
||||
pop edx;
|
||||
pop ecx;
|
||||
pop eax;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
@@ -365,8 +370,6 @@ void InitNewOpcodes() {
|
||||
opcodes[0x1f4] = op_set_script;
|
||||
|
||||
opcodes[0x1f6] = op_nb_create_char;
|
||||
opcodes[0x204] = op_get_proto_data;
|
||||
opcodes[0x205] = op_set_proto_data;
|
||||
opcodes[0x206] = op_set_self;
|
||||
opcodes[0x213] = op_hero_select_win;
|
||||
opcodes[0x214] = op_set_hero_race;
|
||||
|
||||
Reference in New Issue
Block a user