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 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_format(format, a1, a2) sfall_func3("string_format", format, a1, a2)
#define tile_refresh_display sfall_func0("tile_refresh_display")
#define unjam_lock(obj) sfall_func1("unjam_lock", obj)
#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))
> 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 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
@@ -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
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 -------
------------------------
+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 {
mov edx, dataType;
mov ebx, strId;
mov eax, scriptPtr;
mov eax, ecx;
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)
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);
+1 -1
View File
@@ -337,7 +337,7 @@ public:
// retrieve string argument
if (type == DATATYPE_STR) {
_args[i] = InterpretGetString(program, rawValue, rawValueType);
_args[i] = InterpretGetString(program, rawValueType, rawValue);
} else {
_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
eax register must contain the script_ptr
jlabel - name of the jump label in case the value type is not INT
return: eax - arg value
*/
#define _GET_ARG_INT(jlabel) __asm { \
__asm mov edx, eax \
@@ -131,6 +132,13 @@ notstring##num:
__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
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},
{"spatial_radius", sf_spatial_radius, 1, 1},
{"string_compare", sf_string_compare, 2, 3},
{"string_format", sf_string_format, 2, 5},
{"tile_refresh_display", sf_tile_refresh_display, 0, 0},
{"unjam_lock", sf_unjam_lock, 1, 1},
{"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) {
length += len - startPos; // cutoff at end
if (length == 0) return "";
abs(length); // length can't be negative
length = abs(length); // length can't be negative
}
// check position
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() {
const ScriptValue &base = opHandler.arg(0),
&power = opHandler.arg(1);
+1
View File
@@ -268,6 +268,7 @@ end:
retn;
}
}
static void __declspec(naked) get_critter_skill_points() {
__asm {
pushad;