mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Small optimization for receiving/passing script arguments
* combined related engine interpreter functions into a single function for aligning the compiled ASM code better. Minor changes to some other code and documents.
This commit is contained in:
@@ -87,7 +87,7 @@
|
||||
#define FLAG_SEEN (0x40000000)
|
||||
#define FLAG_SHOOTTHRU (0x80000000)
|
||||
|
||||
/* Critter Flags */
|
||||
/* Critter flags */
|
||||
#define CFLG_BARTER 2 // 0x00000002 - Barter (can trade with)
|
||||
#define CFLG_NOSTEAL 32 // 0x00000020 - Steal (cannot steal from)
|
||||
#define CFLG_NODROP 64 // 0x00000040 - Drop (doesn't drop items)
|
||||
@@ -100,12 +100,20 @@
|
||||
#define CFLG_RANGED 8192 // 0x00002000 - Range (melee attack is possible at a distance)
|
||||
#define CFLG_NOKNOCKDOWN 16384 // 0x00004000 - Knock (cannot be knocked down)
|
||||
|
||||
/* Window Flags */
|
||||
/* Window flags */
|
||||
#define WIN_FLAG_MOVEONTOP (0x4)
|
||||
#define WIN_FLAG_HIDDEN (0x8)
|
||||
#define WIN_FLAG_EXCLUSIVE (0x10)
|
||||
#define WIN_FLAG_TRANSPARENT (0x20)
|
||||
|
||||
/* Message window flags */
|
||||
#define MSGBOX_AUTOSIZE (0x0)
|
||||
#define MSGBOX_NORMAL (0x1)
|
||||
#define MSGBOX_SMALL (0x2)
|
||||
#define MSGBOX_ALIGN_LEFT (0x4) // text aligned to left
|
||||
#define MSGBOX_ALIGN_TOP (0x8) // text aligned to top
|
||||
#define MSGBOX_YESNO (0x10) // uses YES/NO buttons instead of DONE
|
||||
#define MSGBOX_CLEAN (0x20) // no buttons
|
||||
|
||||
//remove inven obj defines
|
||||
#define RMOBJ_CONSUME_DRUG 4666772
|
||||
|
||||
@@ -718,11 +718,11 @@ optional argument:
|
||||
- areaID: the ID number of the town from city.txt
|
||||
|
||||
> int sfall_func4("message_box", string message, int flags, int color1, int color2)
|
||||
- creates a dialog box with text and returns the result of pressing the button: 0 - No, 1 - Yes/Done
|
||||
- creates a dialog box with text and returns the result of pressing the button: 0 - No (Escape), 1 - Yes/Done (Enter)
|
||||
- returns -1 if for some reason the dialog box cannot be created
|
||||
- message: the text in the dialog box. Use the \n control character to move text to a new line (example: "Hello\nWorld!")
|
||||
optional arguments:
|
||||
- flags: mode flags (see DIALOGOUT_* constants in define_extra.h). Pass -1 to skip setting the flags (default flags are DIALOGOUT_NORMAL|DIALOGOUT_YESNO)
|
||||
- flags: mode flags (see MSGBOX_* constants in define_extra.h). Pass -1 to skip setting the flags (default flags are NORMAL and YESNO)
|
||||
- color1/2: the color index in Fallout palette. color1 sets the text color for the first line, and color2 for all subsequent lines of text (default color is 145)
|
||||
|
||||
------------------------
|
||||
|
||||
@@ -795,7 +795,7 @@ enum DialogOutFlags : long
|
||||
DIALOGOUT_SMALL = 0x02, // uses smaller graphic
|
||||
DIALOGOUT_ALIGN_LEFT = 0x04, // text aligned to left
|
||||
DIALOGOUT_ALIGN_TOP = 0x08, // text aligned to top
|
||||
DIALOGOUT_YESNO = 0x10, // DONE button replaced by YES/NO buttons - WIP: currently useless in scripts
|
||||
DIALOGOUT_YESNO = 0x10, // DONE button replaced by YES/NO buttons
|
||||
DIALOGOUT_CLEAN = 0x20 // no buttons
|
||||
};
|
||||
|
||||
|
||||
@@ -228,24 +228,48 @@ DWORD __stdcall interpretPopLong(Program* scriptPtr) {
|
||||
WRAP_WATCOM_CALL1(interpretPopLong_, scriptPtr)
|
||||
}
|
||||
|
||||
// pushes value to Data stack (must be followed by InterpretPushShort)
|
||||
void __stdcall interpretPushLong(Program* scriptPtr, DWORD val) {
|
||||
WRAP_WATCOM_CALL2(interpretPushLong_, scriptPtr, val)
|
||||
}
|
||||
|
||||
// pushes value type to Data stack (must be preceded by InterpretPushLong)
|
||||
void __stdcall interpretPushShort(Program* scriptPtr, DWORD valType) {
|
||||
WRAP_WATCOM_CALL2(interpretPushShort_, scriptPtr, valType)
|
||||
}
|
||||
|
||||
DWORD __stdcall interpretAddString(Program* scriptPtr, const char* strval) {
|
||||
WRAP_WATCOM_CALL2(interpretAddString_, scriptPtr, strval)
|
||||
}
|
||||
|
||||
const char* __fastcall interpretGetString(Program* scriptPtr, DWORD dataType, DWORD strId) {
|
||||
WRAP_WATCOM_FCALL3(interpretGetString_, scriptPtr, dataType, strId)
|
||||
}
|
||||
|
||||
void interpretReturnValue(Program* scriptPtr, DWORD val, DWORD valType) {
|
||||
__asm {
|
||||
mov esi, scriptPtr;
|
||||
mov edx, val;
|
||||
cmp valType, VAR_TYPE_STR;
|
||||
jne isNotStr;
|
||||
mov eax, esi;
|
||||
call fo::funcoffs::interpretAddString_;
|
||||
mov edx, eax;
|
||||
isNotStr:
|
||||
mov eax, esi;
|
||||
call fo::funcoffs::interpretPushLong_; // pushes value to Data stack (must be followed by InterpretPushShort)
|
||||
mov edx, valType;
|
||||
mov eax, esi;
|
||||
call fo::funcoffs::interpretPushShort_; // pushes value type to Data stack (must be preceded by InterpretPushLong)
|
||||
}
|
||||
}
|
||||
|
||||
DWORD __fastcall interpretGetValue(Program* scriptPtr, DWORD &outType) {
|
||||
__asm {
|
||||
mov eax, ecx;
|
||||
call fo::funcoffs::interpretPopShort_; // pops value type from Data stack (must be followed by InterpretPopLong)
|
||||
mov [edx], eax; // out type
|
||||
mov edx, eax;
|
||||
mov eax, ecx;
|
||||
call fo::funcoffs::interpretPopLong_; // pops value from Data stack (must be preceded by InterpretPopShort)
|
||||
cmp dx, VAR_TYPE_STR2;
|
||||
je getStr;
|
||||
cmp dx, VAR_TYPE_STR;
|
||||
jne isNotStr;
|
||||
getStr:
|
||||
mov ebx, eax;
|
||||
mov eax, ecx;
|
||||
call fo::funcoffs::interpretGetString_; // retrieve string argument
|
||||
isNotStr:
|
||||
}
|
||||
}
|
||||
|
||||
// prints scripting error in debug.log and stops current script execution by performing longjmp
|
||||
// USE WITH CAUTION
|
||||
void __declspec(naked) interpretError(const char* fmt, ...) {
|
||||
@@ -402,37 +426,44 @@ long __stdcall win_register_button(DWORD winRef, long xPos, long yPos, long widt
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall DialogOut(const char* text, const char** textEx, long lines) {
|
||||
void __stdcall DialogOut(const char* text) {
|
||||
__asm {
|
||||
push 1; // DIALOGOUT_NORMAL flag
|
||||
xor eax, eax;
|
||||
mov al, byte ptr ds:[0x6AB718];
|
||||
push eax; // ColorMsg
|
||||
push 0; // DisplayMsg (unknown)
|
||||
push eax; // ColorIndex
|
||||
mov eax, ecx; // DisplayText
|
||||
push 116; // y
|
||||
xor edx, edx;
|
||||
push edx;
|
||||
push edx;
|
||||
mov dl, byte ptr ds:[0x6AB718];
|
||||
push edx; // ColorMsg
|
||||
mov ecx, 192; // x
|
||||
mov ebx, lines; // count text lines 0-5
|
||||
push 116; // y
|
||||
mov eax, text; // DisplayText
|
||||
xor ebx, ebx;
|
||||
call fo::funcoffs::dialog_out_;
|
||||
}
|
||||
}
|
||||
|
||||
long __fastcall DialogOutEx(const char* text, const char** textEx, long lines, long flags, long colors) {
|
||||
__asm {
|
||||
mov ebx, colors; // Color index
|
||||
xor eax, eax;
|
||||
mov ebx, colors;// Color index
|
||||
push flags;
|
||||
test ebx, ebx;
|
||||
jnz cColor;
|
||||
mov al, byte ptr ds:[0x6AB718];
|
||||
mov bl, al;
|
||||
jmp skip;
|
||||
cColor:
|
||||
mov al, bh;
|
||||
push flags; // flag
|
||||
and ebx, 0xFF
|
||||
skip:
|
||||
push eax; // ColorMsg2
|
||||
push 0; // DisplayMsg (unknown)
|
||||
mov eax, ecx; // DisplayText first line
|
||||
mov eax, ecx; // DisplayText (first line)
|
||||
push ebx; // ColorMsg1
|
||||
mov ecx, 192; // x
|
||||
push 116; // y
|
||||
mov ebx, lines; // count text lines 0-5
|
||||
call fo::funcoffs::dialog_out_; // edx - DisplayText second and later lines
|
||||
mov ebx, lines; // count second lines
|
||||
call fo::funcoffs::dialog_out_; // edx - DisplayText (seconds lines)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -120,15 +120,11 @@ DWORD __stdcall interpretPopShort(Program* scriptPtr);
|
||||
// pops value from Data stack (must be preceded by InterpretPopShort)
|
||||
DWORD __stdcall interpretPopLong(Program* scriptPtr);
|
||||
|
||||
// pushes value to Data stack (must be followed by InterpretPushShort)
|
||||
void __stdcall interpretPushLong(Program* scriptPtr, DWORD val);
|
||||
|
||||
// pushes value type to Data stack (must be preceded by InterpretPushLong)
|
||||
void __stdcall interpretPushShort(Program* scriptPtr, DWORD valType);
|
||||
|
||||
const char* __fastcall interpretGetString(Program* scriptPtr, DWORD dataType, DWORD strId);
|
||||
|
||||
DWORD __stdcall interpretAddString(Program* scriptPtr, const char* str);
|
||||
void interpretReturnValue(Program* scriptPtr, DWORD val, DWORD valType);
|
||||
|
||||
DWORD __fastcall interpretGetValue(Program* scriptPtr, DWORD &outType);
|
||||
|
||||
// prints scripting error in debug.log and stops current script execution by performing longjmp
|
||||
// USE WITH CAUTION
|
||||
@@ -206,9 +202,9 @@ long __stdcall stat_level(GameObject* critter, long statId);
|
||||
// pictureUp/pictureDown - pointers to a surface
|
||||
long __stdcall win_register_button(DWORD winRef, long xPos, long yPos, long width, long height, long hoverOn, long hoverOff, long buttonDown, long buttonUp, BYTE* pictureUp, BYTE* pictureDown, long arg12, long buttonType);
|
||||
|
||||
void __fastcall DialogOut(const char* text, const char** textEx, long lines);
|
||||
void __stdcall DialogOut(const char* text);
|
||||
|
||||
long __fastcall DialogOutEx(const char* text, const char** textEx, long lines, long flags, long colors);
|
||||
long __fastcall DialogOutEx(const char* text, const char** textEx, long lines, long flags, long colors = 0);
|
||||
|
||||
// draws an image to the buffer without scaling and with transparency display toggle
|
||||
void __fastcall windowDisplayBuf(long x, long width, long y, long height, void* data, long noTrans);
|
||||
|
||||
@@ -130,14 +130,14 @@ void __declspec(naked) op_resume_game() {
|
||||
// copy and split
|
||||
static void SplitToBuffer(const char* str, const char** str_ptr, long &lines) {
|
||||
size_t i = 0;
|
||||
do {
|
||||
while (str[i]) {
|
||||
if (str[i] == '\n' && lines < 4) {
|
||||
ScriptExtender::gTextBuffer[i] = '\0';
|
||||
str_ptr[lines++] = &ScriptExtender::gTextBuffer[++i];
|
||||
} else {
|
||||
ScriptExtender::gTextBuffer[i] = str[i++];
|
||||
}
|
||||
} while (str[i]);
|
||||
};
|
||||
ScriptExtender::gTextBuffer[i] = '\0';
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ void sf_create_message_window(OpcodeContext &ctx) {
|
||||
SplitToBuffer(str, str_ptr, lines);
|
||||
|
||||
dialogShow = true;
|
||||
fo::func::DialogOut(ScriptExtender::gTextBuffer, str_ptr, lines);
|
||||
fo::func::DialogOutEx(ScriptExtender::gTextBuffer, str_ptr, lines, fo::DIALOGOUT_NORMAL);
|
||||
dialogShow = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -163,12 +163,8 @@ static void sf_metarule_exist(OpcodeContext& ctx) {
|
||||
bool result = false;
|
||||
auto funcXName = ctx.arg(0).asString();
|
||||
if (funcXName[0] != '\0') {
|
||||
for (auto it = metaruleTable.begin(); it != metaruleTable.end(); it++) {
|
||||
if (it->first == funcXName) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const auto &it = metaruleTable.find(funcXName);
|
||||
if (it != metaruleTable.cend()) result = true;
|
||||
}
|
||||
ctx.setReturn(result);
|
||||
}
|
||||
|
||||
@@ -228,16 +228,9 @@ void OpcodeContext::_popArguments() {
|
||||
// process arguments on stack (reverse order)
|
||||
for (int i = _numArgs - 1; i >= 0; i--) {
|
||||
// get argument from stack
|
||||
DWORD rawValueType = fo::func::interpretPopShort(_program);
|
||||
DWORD rawValue = fo::func::interpretPopLong(_program);
|
||||
DataType type = getSfallTypeByScriptType(rawValueType);
|
||||
|
||||
// retrieve string argument
|
||||
if (type == DataType::STR) {
|
||||
_args[i] = fo::func::interpretGetString(_program, rawValueType, rawValue);
|
||||
} else {
|
||||
_args[i] = ScriptValue(type, rawValue);
|
||||
}
|
||||
DWORD rawValueType;
|
||||
DWORD rawValue = fo::func::interpretGetValue(_program, rawValueType);
|
||||
_args[i] = ScriptValue(getSfallTypeByScriptType(rawValueType), rawValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,12 +238,7 @@ void OpcodeContext::_pushReturnValue() {
|
||||
if (_ret.type() == DataType::NONE) {
|
||||
_ret = ScriptValue(0); // if no value was set in handler, force return 0 to avoid stack error
|
||||
}
|
||||
DWORD rawResult = _ret.rawValue();
|
||||
if (_ret.type() == DataType::STR) {
|
||||
rawResult = fo::func::interpretAddString(_program, _ret.strValue());
|
||||
}
|
||||
fo::func::interpretPushLong(_program, rawResult);
|
||||
fo::func::interpretPushShort(_program, getScriptTypeBySfallType(_ret.type()));
|
||||
fo::func::interpretReturnValue(_program, _ret.rawValue(), getScriptTypeBySfallType(_ret.type()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-16
@@ -43,7 +43,7 @@ struct levelRest {
|
||||
std::unordered_map<int, levelRest> mapRestInfo;
|
||||
|
||||
std::vector<std::pair<long, std::string>> wmTerrainTypeNames; // pair first: x + y * number of horizontal sub-tiles
|
||||
std::vector<std::pair<long, std::string>> wmAreaHotSpotTitle;
|
||||
std::unordered_map<long, std::string> wmAreaHotSpotTitle;
|
||||
|
||||
static bool restMap;
|
||||
static bool restMode;
|
||||
@@ -616,14 +616,13 @@ void Worldmap::SetTerrainTypeName(long x, long y, const char* name) {
|
||||
long subTileID = x + y * (fo::var::wmNumHorizontalTiles * 7);
|
||||
wmTerrainTypeNames.push_back(std::make_pair(subTileID, name));
|
||||
}
|
||||
/*
|
||||
|
||||
// TODO: someone might need to know the name of a terrain type?
|
||||
const char* Worldmap::GetTerrainTypeName(long x, long y) {
|
||||
//const char* name = GetOverrideTerrainName(x, y);
|
||||
//return (name) ? name : fo::GetMessageStr(&fo::var::wmMsgFile, 1000 + fo::wmGetTerrainType(x, y));
|
||||
return nullptr;
|
||||
}
|
||||
*/
|
||||
/*const char* Worldmap::GetTerrainTypeName(long x, long y) {
|
||||
const char* name = GetOverrideTerrainName(x, y);
|
||||
return (name) ? name : fo::GetMessageStr(&fo::var::wmMsgFile, 1000 + fo::wmGetTerrainType(x, y));
|
||||
}*/
|
||||
|
||||
// Returns the name of the terrain type in the position of the player's marker on the world map
|
||||
const char* Worldmap::GetCurrentTerrainName() {
|
||||
const char* name = GetOverrideTerrainName(fo::var::world_xpos / 50, fo::var::world_ypos / 50);
|
||||
@@ -635,17 +634,13 @@ bool Worldmap::AreaTitlesIsEmpty() {
|
||||
}
|
||||
|
||||
void Worldmap::SetCustomAreaTitle(long areaID, const char* msg) {
|
||||
wmAreaHotSpotTitle.push_back(std::make_pair(areaID, msg));
|
||||
wmAreaHotSpotTitle[areaID] = msg;
|
||||
}
|
||||
|
||||
const char* Worldmap::GetCustomAreaTitle(long areaID) {
|
||||
if (wmAreaHotSpotTitle.empty()) return nullptr;
|
||||
|
||||
auto it = std::find_if(wmAreaHotSpotTitle.crbegin(), wmAreaHotSpotTitle.crend(),
|
||||
[=](const std::pair<long, std::string> &el)
|
||||
{ return el.first == areaID; }
|
||||
);
|
||||
return (it != wmAreaHotSpotTitle.crend()) ? it->second.c_str() : nullptr;
|
||||
if (AreaTitlesIsEmpty()) return nullptr;
|
||||
const auto &it = wmAreaHotSpotTitle.find(areaID);
|
||||
return (it != wmAreaHotSpotTitle.cend()) ? it->second.c_str() : nullptr;
|
||||
}
|
||||
|
||||
void Worldmap::init() {
|
||||
|
||||
Reference in New Issue
Block a user