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:
NovaRain
2020-01-31 00:24:58 +08:00
parent 90b547a472
commit 19f4901328
9 changed files with 97 additions and 83 deletions
+10 -2
View File
@@ -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
+2 -2
View File
@@ -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)
------------------------
+1 -1
View File
@@ -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
};
+59 -28
View File
@@ -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)
}
}
+5 -9
View File
@@ -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);
}
+4 -16
View File
@@ -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
View File
@@ -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() {