mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
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:
@@ -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
@@ -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);
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user