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 12:13:36 +08:00
parent 3629c90fa9
commit 66c237d297
6 changed files with 70 additions and 104 deletions
+4 -1
View File
@@ -248,7 +248,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))
> 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)
- returns string length
+10 -7
View File
@@ -313,12 +313,15 @@ artNotExist:
push eax;
push artDbgMsg;
call debug_printf_;
add esp, 8;
cmp isDebug, 0;
jz skip;
int 3; // break program
skip:
retn;
mov eax, [esp + 0x124 - 0x1C + 12]; // filename
push eax;
push artDbgMsg;
lea eax, [esp + 0x124 - 0x124 + 20]; // buf
push eax;
call sprintf_;
add esp, 20;
lea eax, [esp + 4];
jmp display_print_;
}
}
@@ -357,7 +360,7 @@ static void DebugModePatch() {
if (iniGetInt("Debugging", "HideObjIsNullMsg", 0, ddrawIniDef)) {
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);
dlogr(" Done", DL_INIT);
+3 -3
View File
@@ -472,9 +472,9 @@ end:
static void __declspec(naked) DialogHook() {
__asm {
cmp dword ptr [esp + 0x14], 0x45A5C9; // call from op_gsay_end_
je changeMode;
jmp gdProcess_;
test inLoop, DIALOG; // check bit flag
jz changeMode;
jmp gdProcess_;
changeMode:
or inLoop, DIALOG;
call gdProcess_;
+1 -1
View File
@@ -94,7 +94,7 @@ void _stdcall AddTimerEventScripts(DWORD script, long time, long param);
void _stdcall RemoveTimerEventScripts(DWORD script, long param);
void _stdcall RemoveTimerEventScripts(DWORD script);
char* _stdcall mysubstr(const char* str, int pos, int length);
char* _stdcall Substring(const char* str, int startPos, int length);
// variables
static char reg_anim_combat_check = 1;
+1 -1
View File
@@ -151,7 +151,7 @@ callsubstr:
push 1;
push edi;
push eax;
call mysubstr;
call Substring;
mov edx, eax; // result substring
mov ebx, VAR_TYPE_STR; // result type
jmp end;
+51 -91
View File
@@ -513,30 +513,40 @@ end:
}
}
char* _stdcall mysubstr(const char* str, int pos, int length) {
char* newstr;
int srclen;
srclen = strlen(str);
if (pos < 0)
pos = srclen + pos;
if (length < 0)
length = srclen - pos + length;
if (pos >= srclen)
length = 0;
else if (length + pos > srclen)
length = srclen - pos;
newstr = new char[length + 1];
if (length > 0)
memcpy(newstr, &str[pos], length);
newstr[length] = '\0';
return newstr;
static char* tempTextBuf = nullptr;
char* _stdcall Substring(const char* str, int startPos, int length) {
int len = strlen(str);
if (startPos < 0) {
startPos += len; // start from end
if (startPos < 0) startPos = 0;
}
if (length < 0) {
length += len - startPos; // cutoff at end
if (length == 0) {
return "";
} else if (length < 0) {
length = -length; // length can't be negative
}
}
// 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;
}
static DWORD _stdcall mystrlen(const char* str) {
return strlen(str);
}
static char* sprintfbuf = nullptr;
static char* _stdcall mysprintf(const char* format, DWORD value, DWORD valueType) {
valueType = valueType & 0xFFFF; // use lower 2 bytes
int fmtlen = strlen(format);
@@ -601,87 +611,37 @@ static char* _stdcall mysprintf(const char* format, DWORD value, DWORD valueType
} else {
buflen = j + 30; // numbers
}
if (sprintfbuf) {
delete[] sprintfbuf;
if (tempTextBuf) {
delete[] tempTextBuf;
}
sprintfbuf = new char[buflen + 1];
tempTextBuf = new char[buflen + 1];
if (valueType == VAR_TYPE_FLOAT) {
_snprintf(sprintfbuf, buflen, newfmt, *(float*)(&value));
_snprintf(tempTextBuf, buflen, newfmt, *(float*)(&value));
} else {
_snprintf(sprintfbuf, buflen, newfmt, value);
_snprintf(tempTextBuf, buflen, newfmt, value);
}
sprintfbuf[buflen] = '\0'; // just in case
tempTextBuf[buflen] = '\0'; // just in case
delete[] newfmt;
return sprintfbuf;
return tempTextBuf;
}
static void _stdcall op_substr2() {
const ScriptValue &strArg = opHandler.arg(0),
&startArg = opHandler.arg(1),
&lenArg = opHandler.arg(2);
if (strArg.isString() && startArg.isInt() && lenArg.isInt()) {
const char* str = strArg.strValue();
if (*str != '\0') str = Substring(str, startArg.rawValue(), lenArg.rawValue());
opHandler.setReturn(str);
} else {
OpcodeInvalidArgs("substr");
opHandler.setReturn(-1);
}
}
static void __declspec(naked) op_substr() {
__asm {
pushad;
mov edi, eax;
call interpretPopShort_;
push eax;
mov eax, edi;
call interpretPopLong_; // length
push eax;
mov eax, edi;
call interpretPopShort_;
push eax;
mov eax, edi;
call interpretPopLong_; // position
push eax;
mov eax, edi;
call interpretPopShort_;
push eax;
mov eax, edi;
call interpretPopLong_; // string
push eax;
movzx eax, word ptr [esp+12];
cmp eax, VAR_TYPE_INT;
jne fail;
movzx eax, word ptr [esp+20];
cmp eax, VAR_TYPE_INT;
jne fail;
movzx eax, word ptr [esp+4];
cmp eax, VAR_TYPE_STR2;
je next1;
cmp eax, VAR_TYPE_STR;
jne fail;
next1:
mov eax, edi;
mov edx, [esp+4];
mov ebx, [esp];
call interpretGetString_;
mov ebx, [esp+16];
mov edx, [esp+8];
push ebx;
push edx;
push eax;
call mysubstr;
mov edx, eax;
mov eax, edi;
call interpretAddString_;
mov edx, eax;
mov eax, edi;
call interpretPushLong_;
mov edx, VAR_TYPE_STR;
mov eax, edi;
call interpretPushShort_;
jmp end;
fail:
xor edx, edx;
dec edx;
mov eax, edi;
call interpretPushLong_;
mov edx, VAR_TYPE_INT;
mov eax, edi;
call interpretPushShort_;
end:
add esp, 24;
popad;
retn;
}
_WRAP_OPCODE(op_substr2, 3, 1)
}
static void __declspec(naked) op_strlen() {