Refactored the code for "substr" script function

* fixed the crashing bug and added a new behavior.

Changed the error message due to missing critter frame (again):
* replaced the interruption with printing the error message to in-game
message window.
This commit is contained in:
NovaRain
2019-11-29 11:52:35 +08:00
parent 11fee91f2f
commit 84076a2586
7 changed files with 63 additions and 46 deletions
+5 -1
View File
@@ -262,7 +262,10 @@ 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. 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") - cuts a substring from a string starting at "start" up to "length" characters. The first character position starts with 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
> int strlen(string string) > int strlen(string string)
- returns string length - returns string length
@@ -452,6 +455,7 @@ Some utility/math functions are available:
> array sfall_func2("get_ini_section", string fileName, string section) > array sfall_func2("get_ini_section", string fileName, string section)
- returns an associative array of keys and values for a given INI file and section - returns an associative array of keys and values for a given INI file and section
- NOTE: all keys and their values will be of String type
> int sfall_func0("car_gas_amount") > int sfall_func0("car_gas_amount")
- returns current amount of fuel in player's car (between 0 and 80000) - returns current amount of fuel in player's car (between 0 and 80000)
+10 -7
View File
@@ -321,12 +321,15 @@ artNotExist:
push eax; push eax;
push artDbgMsg; push artDbgMsg;
call fo::funcoffs::debug_printf_; call fo::funcoffs::debug_printf_;
add esp, 8; mov eax, [esp + 0x124 - 0x1C + 12]; // filename
cmp isDebug, 0; push eax;
jz skip; push artDbgMsg;
int 3; // break program lea eax, [esp + 0x124 - 0x124 + 20]; // buf
skip: push eax;
retn; call fo::funcoffs::sprintf_;
add esp, 20;
lea eax, [esp + 4];
jmp fo::funcoffs::display_print_;
} }
} }
@@ -365,7 +368,7 @@ static void DebugModePatch() {
if (iniGetInt("Debugging", "HideObjIsNullMsg", 0, ::sfall::ddrawIni)) { if (iniGetInt("Debugging", "HideObjIsNullMsg", 0, ::sfall::ddrawIni)) {
MakeJump(0x453FD2, dbg_error_hack); MakeJump(0x453FD2, dbg_error_hack);
} }
// prints a debug message about missing art file for critters and interrupts game execution // prints a debug message about missing art file for critters to debug.log and the message window
HookCall(0x419B65, art_data_size_hook); HookCall(0x419B65, art_data_size_hook);
dlogr(" Done", DL_INIT); dlogr(" Done", DL_INIT);
+3 -3
View File
@@ -523,9 +523,9 @@ end:
static void __declspec(naked) DialogHook() { static void __declspec(naked) DialogHook() {
__asm { __asm {
cmp dword ptr [esp + 0x14], 0x45A5C9; // call from op_gsay_end_ test inLoop, DIALOG; // check bit flag
je changeMode; jz changeMode;
jmp fo::funcoffs::gdProcess_; jmp fo::funcoffs::gdProcess_;
changeMode: changeMode:
_InLoop(1, DIALOG); _InLoop(1, DIALOG);
call fo::funcoffs::gdProcess_; call fo::funcoffs::gdProcess_;
+5 -5
View File
@@ -31,7 +31,7 @@ namespace script
void sf_create_array(OpcodeContext& ctx) { void sf_create_array(OpcodeContext& ctx) {
auto arrayId = CreateArray(ctx.arg(0).rawValue(), ctx.arg(1).rawValue()); auto arrayId = CreateArray(ctx.arg(0).rawValue(), ctx.arg(1).rawValue());
ctx.setReturn(arrayId, DataType::INT); ctx.setReturn(arrayId);
} }
void sf_set_array(OpcodeContext& ctx) { void sf_set_array(OpcodeContext& ctx) {
@@ -55,7 +55,7 @@ void sf_get_array(OpcodeContext& ctx) {
); );
} else if (ctx.arg(0).isString()) { } else if (ctx.arg(0).isString()) {
if (ctx.arg(1).isInt()) { if (ctx.arg(1).isInt()) {
auto str = Substring(ctx.arg(0).strValue(), ctx.arg(1).rawValue(), 1); const char* str = Substring(ctx.arg(0).strValue(), ctx.arg(1).rawValue(), 1);
ctx.setReturn(str); // returns char of string ctx.setReturn(str); // returns char of string
} else { } else {
ctx.printOpcodeError("%s() - index must be numeric when used on a string.", ctx.getOpcodeName()); ctx.printOpcodeError("%s() - index must be numeric when used on a string.", ctx.getOpcodeName());
@@ -83,7 +83,7 @@ void sf_resize_array(OpcodeContext& ctx) {
void sf_temp_array(OpcodeContext& ctx) { void sf_temp_array(OpcodeContext& ctx) {
auto arrayId = TempArray(ctx.arg(0).rawValue(), ctx.arg(1).rawValue()); auto arrayId = TempArray(ctx.arg(0).rawValue(), ctx.arg(1).rawValue());
ctx.setReturn(arrayId, DataType::INT); ctx.setReturn(arrayId);
} }
void sf_fix_array(OpcodeContext& ctx) { void sf_fix_array(OpcodeContext& ctx) {
@@ -200,7 +200,7 @@ static DWORD ListAsArray(DWORD type) {
void sf_list_as_array(OpcodeContext& ctx) { void sf_list_as_array(OpcodeContext& ctx) {
auto arrayId = ListAsArray(ctx.arg(0).rawValue()); auto arrayId = ListAsArray(ctx.arg(0).rawValue());
ctx.setReturn(arrayId, DataType::INT); ctx.setReturn(arrayId);
} }
static DWORD ListBegin(DWORD type) { static DWORD ListBegin(DWORD type) {
@@ -212,7 +212,7 @@ static DWORD ListBegin(DWORD type) {
} }
void sf_list_begin(OpcodeContext& ctx) { void sf_list_begin(OpcodeContext& ctx) {
ctx.setReturn(ListBegin(ctx.arg(0).rawValue()), DataType::INT); ctx.setReturn(ListBegin(ctx.arg(0).rawValue()));
} }
static fo::GameObject* ListNext(sList* list) { static fo::GameObject* ListNext(sList* list) {
+1 -1
View File
@@ -92,7 +92,7 @@ void __declspec(naked) op_game_loaded() {
movzx edx, al; movzx edx, al;
mov eax, ebx; mov eax, ebx;
_RET_VAL_INT; _RET_VAL_INT;
pop ecx; pop ecx;
retn; retn;
} }
} }
+38 -28
View File
@@ -190,29 +190,40 @@ void sf_string_split(OpcodeContext& ctx) {
ctx.setReturn(StringSplit(ctx.arg(0).strValue(), ctx.arg(1).strValue())); ctx.setReturn(StringSplit(ctx.arg(0).strValue(), ctx.arg(1).strValue()));
} }
char* Substring(const char* str, int pos, int length) { static char* tempTextBuf = nullptr;
char* newstr;
int srclen; char* Substring(const char* str, int startPos, int length) {
srclen = strlen(str); int len = strlen(str);
if (pos < 0)
pos = srclen + pos; if (startPos < 0) {
if (length < 0) startPos += len; // start from end
length = srclen - pos + length; if (startPos < 0) startPos = 0;
if (pos >= srclen) }
length = 0; if (length < 0) {
else if (length + pos > srclen) length += len - startPos; // cutoff at end
length = srclen - pos; if (length == 0) {
newstr = new char[length + 1]; // memory leak!!! return "";
if (length > 0) } else if (length < 0) {
memcpy(newstr, &str[pos], length); length = -length; // length can't be negative
newstr[length] = '\0'; }
return newstr; }
// check position
if (startPos >= len) return ""; // start position is out of string length, return empty string
if (length == 0 || length + startPos > len) {
length = len - startPos; // set the correct length, the length of characters goes beyond the end of the string
}
if (tempTextBuf) delete[] tempTextBuf;
tempTextBuf = new char[length + 1];
memcpy(tempTextBuf, &str[startPos], length);
tempTextBuf[length] = '\0';
return tempTextBuf;
} }
void sf_substr(OpcodeContext& ctx) { void sf_substr(OpcodeContext& ctx) {
ctx.setReturn( const char* str = ctx.arg(0).strValue();
Substring(ctx.arg(0).strValue(), ctx.arg(1).rawValue(), ctx.arg(2).rawValue()) if (*str != '\0') str = Substring(str, ctx.arg(1).rawValue(), ctx.arg(2).rawValue());
); ctx.setReturn(str);
} }
void sf_string_compare(OpcodeContext& ctx) { void sf_string_compare(OpcodeContext& ctx) {
@@ -225,7 +236,6 @@ void sf_string_compare(OpcodeContext& ctx) {
} }
} }
static char* sprintfbuf = nullptr;
// A safer version of sprintf for using in user scripts. // A safer version of sprintf for using in user scripts.
static char* _stdcall sprintf_lite(const char* format, ScriptValue value) { static char* _stdcall sprintf_lite(const char* format, ScriptValue value) {
int fmtlen = strlen(format); int fmtlen = strlen(format);
@@ -290,18 +300,18 @@ static char* _stdcall sprintf_lite(const char* format, ScriptValue value) {
} else { } else {
buflen = j + 30; // numbers buflen = j + 30; // numbers
} }
if (sprintfbuf) { if (tempTextBuf) {
delete[] sprintfbuf; delete[] tempTextBuf;
} }
sprintfbuf = new char[buflen + 1]; tempTextBuf = new char[buflen + 1];
if (value.isFloat()) { if (value.isFloat()) {
_snprintf(sprintfbuf, buflen, newfmt, value.floatValue()); _snprintf(tempTextBuf, buflen, newfmt, value.floatValue());
} else { } else {
_snprintf(sprintfbuf, buflen, newfmt, value.rawValue()); _snprintf(tempTextBuf, buflen, newfmt, value.rawValue());
} }
sprintfbuf[buflen] = '\0'; // just in case tempTextBuf[buflen] = '\0'; // just in case
delete[] newfmt; delete[] newfmt;
return sprintfbuf; return tempTextBuf;
} }
void sf_sprintf(OpcodeContext& ctx) { void sf_sprintf(OpcodeContext& ctx) {
+1 -1
View File
@@ -23,7 +23,7 @@ namespace sfall
namespace script namespace script
{ {
char* Substring(const char* str, int pos, int length); char* Substring(const char* str, int startPos, int length);
class OpcodeContext; class OpcodeContext;