Added "string_format" script function

Rewrote ASM code of opcode handlers in MemoryOp.hpp.
This commit is contained in:
NovaRain
2019-12-03 10:52:56 +08:00
parent eeb97a4299
commit 7016690f99
10 changed files with 247 additions and 230 deletions
+1
View File
@@ -277,6 +277,7 @@
#define spatial_radius(obj) sfall_func1("spatial_radius", obj) #define spatial_radius(obj) sfall_func1("spatial_radius", obj)
#define string_compare(str1, str2) sfall_func2("string_compare", str1, str2) #define string_compare(str1, str2) sfall_func2("string_compare", str1, str2)
#define string_compare_locale(str1, str2, codePage) sfall_func3("string_compare", str1, str2, codePage) #define string_compare_locale(str1, str2, codePage) sfall_func3("string_compare", str1, str2, codePage)
#define string_format(format, a1, a2) sfall_func3("string_format", format, a1, a2)
#define tile_refresh_display sfall_func0("tile_refresh_display") #define tile_refresh_display sfall_func0("tile_refresh_display")
#define unjam_lock(obj) sfall_func1("unjam_lock", obj) #define unjam_lock(obj) sfall_func1("unjam_lock", obj)
#define unset_unique_id(obj) sfall_func2("set_unique_id", obj, -1) #define unset_unique_id(obj) sfall_func2("set_unique_id", obj, -1)
+5 -1
View File
@@ -248,7 +248,7 @@ Some utility/math functions are available:
- you can use this to search for a substring in a string like this: strlen(get_array(string_split(haystack, needle), 0)) - you can use this to search for a substring in a string like this: strlen(get_array(string_split(haystack, needle), 0))
> string substr(string, start, length) > string substr(string, start, length)
- cuts a substring from a string starting at "start" up to "length" characters. The first character position starts with 0 (zero). - cuts a substring from a string starting at "start" up to "length" characters. The first character position is 0 (zero).
- If start is negative - it indicates starting position from the end of the string (for example substr("test", -2, 2) will return last 2 charactes: "st"). - If start is negative - it indicates starting position from the end of the string (for example substr("test", -2, 2) will return last 2 charactes: "st").
- If length is negative - it means so many characters will be omitted from the end of string (example: substr("test", 0, -2) will return string without last 2 characters: "te"). - If length is negative - it means so many characters will be omitted from the end of string (example: substr("test", 0, -2) will return string without last 2 characters: "te").
- If length is zero - it will return a string from the starting position to the end of the string **New behavior** for sfall 4.2.2/3.8.22 - If length is zero - it will return a string from the starting position to the end of the string **New behavior** for sfall 4.2.2/3.8.22
@@ -588,6 +588,10 @@ optional arguments:
- codePage: code page number to properly compare national characters in the range 128-255 of the ASCII code table - codePage: code page number to properly compare national characters in the range 128-255 of the ASCII code table
available encodings: 1250-1252, 866 available encodings: 1250-1252, 866
> string sfall_func3("string_format", string format, any val1, any val2, ...)
- formats given value using standard syntax of C printf function (google "printf" for format details). However it is limited to formatting up to 4 values
- formatting is only supported for %s and %d. The format string is limited to 1024 characters
------------------------ ------------------------
------ MORE INFO ------- ------ MORE INFO -------
------------------------ ------------------------
+2 -3
View File
@@ -979,11 +979,10 @@ DWORD __stdcall InterpretAddString(TProgram* scriptPtr, const char* strval) {
} }
} }
const char* __stdcall InterpretGetString(TProgram* scriptPtr, DWORD strId, DWORD dataType) { const char* __fastcall InterpretGetString(TProgram* scriptPtr, DWORD dataType, DWORD strId) {
__asm { __asm {
mov edx, dataType;
mov ebx, strId; mov ebx, strId;
mov eax, scriptPtr; mov eax, ecx;
call interpretGetString_; call interpretGetString_;
} }
} }
+1 -1
View File
@@ -1084,7 +1084,7 @@ void __stdcall InterpretPushLong(TProgram* scriptPtr, DWORD val);
// pushes value type to Data stack (must be preceded by InterpretPushLong) // pushes value type to Data stack (must be preceded by InterpretPushLong)
void __stdcall InterpretPushShort(TProgram* scriptPtr, DWORD valType); void __stdcall InterpretPushShort(TProgram* scriptPtr, DWORD valType);
const char* __stdcall InterpretGetString(TProgram* scriptPtr, DWORD strId, DWORD dataType); const char* __fastcall InterpretGetString(TProgram* scriptPtr, DWORD dataType, DWORD strId);
DWORD __stdcall InterpretAddString(TProgram* scriptPtr, const char* str); DWORD __stdcall InterpretAddString(TProgram* scriptPtr, const char* str);
+1 -1
View File
@@ -337,7 +337,7 @@ public:
// retrieve string argument // retrieve string argument
if (type == DATATYPE_STR) { if (type == DATATYPE_STR) {
_args[i] = InterpretGetString(program, rawValue, rawValueType); _args[i] = InterpretGetString(program, rawValueType, rawValue);
} else { } else {
_args[i] = ScriptValue(type, rawValue); _args[i] = ScriptValue(type, rawValue);
} }
+8
View File
@@ -42,6 +42,7 @@
Gets argument from stack to eax and puts its type to edx register Gets argument from stack to eax and puts its type to edx register
eax register must contain the script_ptr eax register must contain the script_ptr
jlabel - name of the jump label in case the value type is not INT jlabel - name of the jump label in case the value type is not INT
return: eax - arg value
*/ */
#define _GET_ARG_INT(jlabel) __asm { \ #define _GET_ARG_INT(jlabel) __asm { \
__asm mov edx, eax \ __asm mov edx, eax \
@@ -131,6 +132,13 @@ notstring##num:
__asm call interpretPushShort_ \ __asm call interpretPushShort_ \
} }
#define _J_RET_VAL_TYPE(type) __asm { \
__asm call interpretPushLong_ \
__asm mov edx, type \
__asm mov eax, ebx \
__asm jmp interpretPushShort_ \
}
/* /*
handle return value which may be of any type handle return value which may be of any type
num - any unique number num - any unique number
File diff suppressed because it is too large Load Diff
+1
View File
@@ -169,6 +169,7 @@ static const SfallMetarule metaruleArray[] = {
{"show_window", sf_show_window, 0, 1}, {"show_window", sf_show_window, 0, 1},
{"spatial_radius", sf_spatial_radius, 1, 1}, {"spatial_radius", sf_spatial_radius, 1, 1},
{"string_compare", sf_string_compare, 2, 3}, {"string_compare", sf_string_compare, 2, 3},
{"string_format", sf_string_format, 2, 5},
{"tile_refresh_display", sf_tile_refresh_display, 0, 0}, {"tile_refresh_display", sf_tile_refresh_display, 0, 0},
{"unjam_lock", sf_unjam_lock, 1, 1}, {"unjam_lock", sf_unjam_lock, 1, 1},
{"unwield_slot", sf_unwield_slot, 2, 2}, {"unwield_slot", sf_unwield_slot, 2, 2},
+71 -1
View File
@@ -591,7 +591,7 @@ char* _stdcall Substring(const char* str, int startPos, int length) {
if (length < 0) { if (length < 0) {
length += len - startPos; // cutoff at end length += len - startPos; // cutoff at end
if (length == 0) return ""; if (length == 0) return "";
abs(length); // length can't be negative length = abs(length); // length can't be negative
} }
// check position // check position
if (startPos >= len) return ""; // start position is out of string length, return empty string if (startPos >= len) return ""; // start position is out of string length, return empty string
@@ -782,6 +782,76 @@ fail:
} }
} }
static void sf_string_format() {
const ScriptValue &fmtArg = opHandler.arg(0);
if (!fmtArg.isString()) {
OpcodeInvalidArgs("string_format");
opHandler.setReturn(0);
return;
}
const char* format = fmtArg.strValue();
int fmtLen = strlen(format);
if (fmtLen == 0) {
opHandler.setReturn(format);
return;
}
if (fmtLen > 1024) {
opHandler.printOpcodeError("string_format() - the format string exceeds maximum length of 1024 characters.");
opHandler.setReturn("Error");
} else {
char* newFmt = new char[fmtLen + 1];
newFmt[fmtLen] = '\0';
// parse format to make it safe
int i = 0, arg = 0, totalArg = opHandler.numArgs(); // total passed args
do {
char c = format[i];
if (c == '%') {
char cf = format[i + 1];
if (cf != '%') {
if (arg >= 0) {
arg++;
if (arg == totalArg) arg = -1; // format '%' prefixes in the format string exceed the number of passed value args
}
if (arg < 0) { // have % more than passed value args
c = '^'; // delete %
}
// check string is valid or replace unsupported format
else if ((cf == 's' && (arg > 0 && !opHandler.arg(arg).isString())) || (cf != 's' && cf != 'd')) {
newFmt[i++] = c;
c = 'd'; // replace with %d
}
} else {
newFmt[i++] = cf; // skip %%
}
}
newFmt[i] = c;
} while (++i < fmtLen);
const long bufMaxLen = GlblTextBufferSize() - 1;
switch (totalArg) {
case 2 :
_snprintf(gTextBuffer, bufMaxLen, newFmt, opHandler.arg(1).rawValue());
break;
case 3 :
_snprintf(gTextBuffer, bufMaxLen, newFmt, opHandler.arg(1).rawValue(), opHandler.arg(2).rawValue());
break;
case 4 :
_snprintf(gTextBuffer, bufMaxLen, newFmt, opHandler.arg(1).rawValue(), opHandler.arg(2).rawValue(), opHandler.arg(3).rawValue());
break;
case 5 :
_snprintf(gTextBuffer, bufMaxLen, newFmt, opHandler.arg(1).rawValue(), opHandler.arg(2).rawValue(), opHandler.arg(3).rawValue(), opHandler.arg(4).rawValue());
}
gTextBuffer[bufMaxLen] = '\0'; // just in case
delete[] newFmt;
opHandler.setReturn(gTextBuffer);
}
}
static void funcPow2() { static void funcPow2() {
const ScriptValue &base = opHandler.arg(0), const ScriptValue &base = opHandler.arg(0),
&power = opHandler.arg(1); &power = opHandler.arg(1);
+1
View File
@@ -268,6 +268,7 @@ end:
retn; retn;
} }
} }
static void __declspec(naked) get_critter_skill_points() { static void __declspec(naked) get_critter_skill_points() {
__asm { __asm {
pushad; pushad;