diff --git a/saco/exceptions.cpp b/saco/exceptions.cpp index c00a610..91ea6f3 100644 --- a/saco/exceptions.cpp +++ b/saco/exceptions.cpp @@ -231,7 +231,7 @@ LONG WINAPI exc_handler(_EXCEPTION_POINTERS* exc_inf) //---------------------------------------------------- -int exc_filter(unsigned int code, struct _EXCEPTION_POINTERS *ep, char *what) +int WINAPI exc_filter(unsigned int code, struct _EXCEPTION_POINTERS *ep, char *what) { if(pChatWindow) { diff --git a/saco/game/scripting.cpp b/saco/game/scripting.cpp index 5cf888d..949bb2c 100644 --- a/saco/game/scripting.cpp +++ b/saco/game/scripting.cpp @@ -4,10 +4,13 @@ GAME_SCRIPT_THREAD* gst; FARPROC ProcessOneCommand = (FARPROC)0x469EB0; BYTE ScriptBuf[255]; +DWORD* pdwParamVars[18]; DWORD dwScmOpcodeDebug=0; BOOL bScmLocalDebug=FALSE; +int WINAPI exc_filter(unsigned int code, struct _EXCEPTION_POINTERS *ep, char *what); + int __declspec(naked) ExecuteScriptBuf() { __asm @@ -32,8 +35,101 @@ int __declspec(naked) ExecuteScriptBuf() int ScriptCommand(const SCRIPT_COMMAND* pScriptCommand, ...) { - // TODO: ScriptCommand - return 0; + va_list ap; + const char* p = pScriptCommand->Params; // Get parameter string. + va_start(ap, pScriptCommand); // Initialize varargs. + memcpy(&ScriptBuf, &pScriptCommand->OpCode, 2); // Copy opcode to script buf. + int buf_pos = 2; // Position in buffer after opcode. + WORD var_pos = 0; // Init var_pos. + + for(int i=0; i<18; i++) + gst->dwLocalVar[i] = 0; + + dwScmOpcodeDebug = pScriptCommand->OpCode; + + while(*p) // While we've not ran out of parameters... + { + switch(*p) // Switch current parameter. + { + case 'i': // If integer... + { + int i = va_arg(ap, int); // Grab an int off the stack. + ScriptBuf[buf_pos] = 0x01; // Variable data type = 0x01 (4b int). + buf_pos++;; // Increment buffer position. + memcpy(&ScriptBuf[buf_pos], &i, 4); // Insert the int. + buf_pos += 4; // Increment buffer by 4b. + break; + } + case 'f': // If float... + { + /* Take note, MSVC++ puts a double on the stack + even if you typecase as a float. <3 Microsoft. */ + float f = (float)va_arg(ap, double); // Get float off the stack. + ScriptBuf[buf_pos] = 0x06; // Variable data type = 0x06 (float). + buf_pos++; // Increment buffer position. + memcpy(&ScriptBuf[buf_pos], &f, 4); // Copy float into script buf. + buf_pos += 4; // Increment buffer by 4b. + break; + } + case 'v': // If variable... + { + DWORD* v = va_arg(ap, DWORD*); // Get the pointer to the passed variable. + ScriptBuf[buf_pos] = 0x03; // Variable data type = 0x03 (Local Var). + buf_pos++; // Increment buffer position. + pdwParamVars[var_pos] = v; // Save pointer to passed variable. + gst->dwLocalVar[var_pos] = *v; // Put value of passed variable into local. + memcpy(&ScriptBuf[buf_pos], &var_pos, 2); // Copy the offset into the script. + buf_pos += 2; // Increment buffer by 2b. + var_pos++; // Increment the variable position. + break; + } + case 's': // If string... Updated 13th Jan 06.. (kyeman) SA string support + { + char* sz = va_arg(ap, char*); + unsigned char aLen = strlen(sz); + ScriptBuf[buf_pos] = 0x0E; + buf_pos++; + ScriptBuf[buf_pos] = aLen; + buf_pos++; + memcpy(&ScriptBuf[buf_pos],sz,aLen); + buf_pos += aLen; + break; + } + case 'z': // If the params need zero-terminating... + { + ScriptBuf[buf_pos] = 0x00; + buf_pos++; + break; + } + default: + { + return 0; + } + } + ++p; // Next parameter + } + va_end(ap); // End varargs. + + // Execute script stub. + int result =0; + + __try + { + result = ExecuteScriptBuf(); + if (var_pos) // if we've used a variable... + { + for (int i=0; idwLocalVar[i]; // Retrieve variable from local var. + } + } + } + __except(exc_filter(GetExceptionCode(), GetExceptionInformation(), "opcode")) + { + // nothing? + } + + return result; } void InitScripting() diff --git a/saco/game/scripting.h b/saco/game/scripting.h index 6ecb917..e6a60bb 100644 --- a/saco/game/scripting.h +++ b/saco/game/scripting.h @@ -6,7 +6,17 @@ // Super Simplified SA Version struct GAME_SCRIPT_THREAD // 0xE0 bytes total. { - BYTE _gap0[224]; + //BYTE _gap0[224]; + BYTE Pad1[0x14]; // 0x00 [0x14] + DWORD dwScriptIP; // 0x14 [0x04] + BYTE Pad2[0x24]; // 0x18 [0x24] + DWORD dwLocalVar[18]; // 0x3C [0x48] + BYTE Pad3[0x41]; // 0x84 [0x41] + DWORD dwIfFlag; // 0xC5 [0x04] + BYTE Pad4[0xF]; // 0xC9 [0x0F] + DWORD dwIndexSomething; // 0xD8 [0x04] (indexes into 0xA49960) + BYTE bHasLocalCopy; // 0xDC [0x01] (has local copy of something, if 1, then uses .data:00A48960 CTheScripts_LocalCopy instead of var0) + BYTE Pad5[0x3]; // 0xDD [0x03] }; struct SCRIPT_COMMAND // Params