/*----------------------------------------------------------------------------*- =============================== y_scripting - Access amx data =============================== Description: Allows a script access to information about itself, such as function names. This can be used for a range of things, including automatic callback hooking and testing. Legal: Version: MPL 1.1 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is the SA:MP script information include. The Initial Developer of the Original Code is Alex "Y_Less" Cole. Portions created by the Initial Developer are Copyright (C) 2008 the Initial Developer. All Rights Reserved. Contributors: ZeeX, koolk Thanks: Peter, Cam - Support. ZeeX - Very productive conversations. koolk - IsPlayerinAreaEx code. TheAlpha - Danish translation. breadfish - German translation. Fireburn - Dutch translation. yom - French translation. 50p - Polish translation. Zamaroht - Spanish translation. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes for me to strive to better. Pixels^ - Running XScripters where the idea was born. Matite - Pestering me to release it and using it. Very special thanks to: Thiadmer - PAWN. Kye/Kalcor - SA:MP. SA:MP Team past, present and future - SA:MP. Version: 1.0 Changelog: 06/08/10: First version -*----------------------------------------------------------------------------*/ #include #include #define Scripting_FastString(%1,%2,%3,%4) \ (((%1) << 0) | ((%2) << 8) | ((%3) << 16) | ((%4) << 24)) static stock Scripting_GetBase() { static s_addr; if (!s_addr) { // Get the data offset. #emit LCTRL 1 #emit STOR.pri s_addr // Invert to get the prefix offset relative to the data. s_addr = -s_addr; } return s_addr; } static stock Scripting_GetPublics() { static s_addr; if (!s_addr) { new addr;// = Scripting_GetBase(); // Get the data offset. #emit LCTRL 1 #emit STOR.S.pri addr // Invert to get the prefix offset relative to the data. addr = -addr; // Get the pointer to the publics. addr += 32; #emit LREF.S.pri addr #emit STOR.pri s_addr // Adjust to get the relative offset. s_addr = s_addr + addr - 32; } return s_addr; } static stock Scripting_GetNatives() { static s_addr; if (!s_addr) { new addr;// = Scripting_GetBase(); // Get the data offset. #emit LCTRL 1 #emit STOR.S.pri addr // Invert to get the prefix offset relative to the data. addr = -addr; // Get the pointer to the publics. addr += 36; #emit LREF.S.pri addr #emit STOR.pri s_addr // Adjust to get the relative offset. s_addr = s_addr + addr - 36; } return s_addr; } static stock Scripting_GetLibraries() { static s_addr; if (!s_addr) { new addr;// = Scripting_GetBase(); // Get the data offset. #emit LCTRL 1 #emit STOR.S.pri addr // Invert to get the prefix offset relative to the data. addr = -addr; // Get the pointer to the publics. addr += 40; #emit LREF.S.pri addr #emit STOR.pri s_addr // Adjust to get the relative offset. s_addr = s_addr + addr - 40; } return s_addr; } static stock Scripting_GetString(addr) { new str[32], buffer, ch, idx; do { // Read 4 bytes. #emit LREF.S.pri addr #emit STOR.S.pri buffer // Write a character to the buffer. ch = buffer & 0xFF; str[idx++] = ch; // Check for the end of the string. if (!ch) break; // Write a character to the buffer. ch = buffer >> 8 & 0xFF; str[idx++] = ch; // Check for the end of the string. if (!ch) break; // Write a character to the buffer. ch = buffer >> 16 & 0xFF; str[idx++] = ch; // Check for the end of the string. if (!ch) break; // Write a character to the buffer. ch = buffer >>> 24; str[idx++] = ch; // Check for the end of the string. if (!ch) break; // Get the next address. addr += 4; } while (idx < 32); return str; } static stock Scripting_GetStringFast(addr, buffer) { new str[32], ch, idx; do { // Write a character to the buffer. ch = buffer & 0xFF; str[idx++] = ch; // Check for the end of the string. if (!ch) break; // Write a character to the buffer. ch = buffer >> 8 & 0xFF; str[idx++] = ch; // Check for the end of the string. if (!ch) break; // Write a character to the buffer. ch = buffer >> 16 & 0xFF; str[idx++] = ch; // Check for the end of the string. if (!ch) break; // Write a character to the buffer. ch = buffer >>> 24; str[idx++] = ch; // Check for the end of the string. if (!ch) break; // Get the next address. addr += 4; // Read 4 bytes. #emit LREF.S.pri addr #emit STOR.S.pri buffer } while (idx < 32); return str; } /*----------------------------------------------------------------------------*- Function: Scripting_GetPublicsCount Params: - Return: Number of public functions in a script. Notes: - native Scripting_GetPublicsCount(); -*----------------------------------------------------------------------------*/ stock Scripting_GetPublicsCount() { static s_count; if (!s_count) { // Get the difference in pointers. s_count = (Scripting_GetNatives() - Scripting_GetPublics()) / 8; } return s_count; } /*----------------------------------------------------------------------------*- Function: Scripting_GetNativesCount Params: - Return: Number of native functions in a script. Notes: - native Scripting_GetNativesCount(); -*----------------------------------------------------------------------------*/ stock Scripting_GetNativesCount() { static s_count; if (!s_count) { // Get the difference in pointers. s_count = (Scripting_GetLibraries() - Scripting_GetNatives()) / 8; } return s_count; } /*----------------------------------------------------------------------------*- Function: Scripting_GetPublicFast Params: idx - Index of the public to start at. buffer[32] - Buffer to store the name in. search - Pattern matching parameter. Return: Index of next public. Notes: Gets a string starting with a known 4 character sequence. native Scripting_GetPublicFast(idx, buffer[32], search); -*----------------------------------------------------------------------------*/ stock Scripting_GetPublicFast(idx, buffer[32], search) { new count = Scripting_GetPublicsCount(), base = Scripting_GetBase(), pos = idx * 8 + 4 + Scripting_GetPublics(), addr; while (idx < count) { // Get the offset in the public records. // Get the pointer to the string. //pos += publics; // Get the address of the string. #emit LREF.S.pri pos #emit STOR.S.pri addr //printf("%s", Scripting_GetString(Scripting_GetBase() + pos)); //new // str[32] = Scripting_GetString(base + pos)); ++idx; addr += base; new chars; #emit LREF.S.pri addr #emit STOR.S.pri chars if (chars == search) { buffer = Scripting_GetStringFast(addr, chars); return idx; } pos += 8; } buffer[0] = '\0'; return 0; } /*----------------------------------------------------------------------------*- Function: Scripting_GetPublicSuffix Params: idx - Index of the public to start at. buffer[32] - Buffer to store the name in. search - Pattern matching parameter. Return: Index of next public. Notes: Gets a string ending with a known 4 character sequence. native Scripting_GetPublicFast(idx, buffer[32], search); -*----------------------------------------------------------------------------*/ stock Scripting_GetPublicSuffix(idx, buffer[32], search) { new count = Scripting_GetPublicsCount(), base = Scripting_GetBase(), // Add 12 to get the pointer to the next string. pos = idx * 8 + 12 + Scripting_GetPublics(), addr; // This code will actually spill in to the natives record, but that's fine. while (idx < count) { // Get the address of the string. #emit LREF.S.pri pos #emit STOR.S.pri addr ++idx; addr = addr + base - 5; //addr #emit LREF.S.pri addr #emit STOR.S.pri addr if (addr == search) { pos -= 8; #emit LREF.S.pri pos #emit STOR.S.pri addr addr += base; buffer = Scripting_GetString(addr); return idx; } pos += 8; } buffer[0] = '\0'; return 0; } /*----------------------------------------------------------------------------*- Function: Scripting_GetNativeFast Params: idx - Index of the native to get. buffer[32] - Buffer to store the name in. search - Pattern matching parameter. Return: Index of next native. Notes: - native Scripting_GetNativeFast(idx, buffer[32], search); -*----------------------------------------------------------------------------*/ stock Scripting_GetNativeFast(idx, buffer[32], search) { new count = Scripting_GetNativesCount(), base = Scripting_GetBase(), pos = idx * 8 + 4 + Scripting_GetNatives() addr; while (idx < count) { // Get the offset in the public records. new // Get the pointer to the string. //pos += publics; // Get the address of the string. #emit LREF.S.pri pos #emit STOR.S.pri addr //printf("%s", Scripting_GetString(Scripting_GetBase() + pos)); //new // str[32] = Scripting_GetString(base + pos)); ++idx; addr += base; new chars; #emit LREF.S.pri addr #emit STOR.S.pri chars if (chars == search) { buffer = Scripting_GetStringFast(addr, chars); return idx; } pos += 8; } buffer[0] = '\0'; return 0; } /*----------------------------------------------------------------------------*- Function: Scripting_GetPublic Params: idx - Index of the public to get. buffer[32] - Buffer to store the name in. search[] - Optional pattern matching parameter. Return: Index of next public. Notes: - native Scripting_GetPublic(idx, buffer[32], search[] = ""); -*----------------------------------------------------------------------------*/ stock Scripting_GetPublic(idx, buffer[32], search[] = "") { new count = Scripting_GetPublicsCount(), base = Scripting_GetBase(), pos = idx * 8 + 4 + Scripting_GetPublics(), addr; while (idx < count) { // Get the offset in the public records. // Get the pointer to the string. //pos += publics; // Get the address of the string. #emit LREF.S.pri pos #emit STOR.S.pri addr //printf("%s", Scripting_GetString(Scripting_GetBase() + pos)); //new // str[32] = Scripting_GetString(base + pos)); ++idx; buffer = Scripting_GetString(base + addr); if (search[0] == '\0' || strfind(buffer, search) != -1) { return idx; } pos += 8; } buffer[0] = '\0'; return 0; } /*----------------------------------------------------------------------------*- Function: Scripting_GetNative Params: idx - Index of the native to get. buffer[32] - Buffer to store the name in. search[] - Optional pattern matching parameter. Return: Index of next native. Notes: - native Scripting_GetNative(idx, buffer[32], search[] = ""); -*----------------------------------------------------------------------------*/ stock Scripting_GetNative(idx, buffer[32], search[] = "") { new count = Scripting_GetNativesCount(), base = Scripting_GetBase(), pos = idx * 8 + 4 + Scripting_GetNatives(), addr; while (idx < count) { // Get the offset in the public records. // Get the pointer to the string. //pos += publics; // Get the address of the string. #emit LREF.S.pri pos #emit STOR.S.pri addr //printf("%s", Scripting_GetString(Scripting_GetBase() + pos)); //new // str[32] = Scripting_GetString(base + pos)); ++idx; buffer = Scripting_GetString(base + addr); if (search[0] == '\0' || strfind(buffer, search) != -1) { return idx; } pos += 8; } buffer[0] = '\0'; return 0; } static stock Scripting_CompareString(str[], addr) { new buffer, ch, idx; do { // Read 4 bytes. #emit LREF.S.pri addr #emit STOR.S.pri buffer ch = buffer & 0xFF; if (ch != str[idx++]) return false; if (!ch) break; ch = buffer >> 8 & 0xFF; if (ch != str[idx++]) return false; if (!ch) break; ch = buffer >> 16 & 0xFF; if (ch != str[idx++]) return false; if (!ch) break; ch = buffer >>> 24; if (ch != str[idx++]) return false; if (!ch) break; addr += 4; } while (idx < 32); return true; } /*----------------------------------------------------------------------------*- Function: Scripting_GetPublicPointer Params: name[] - Name of the function to get the pointer for. Return: Pointer or -1. Notes: - native Scripting_GetPublicPointer(name[]); -*----------------------------------------------------------------------------*/ stock Scripting_GetPublicPointer(name[]) { new count = Scripting_GetPublicsCount(), base = Scripting_GetBase(), pos = 4 + Scripting_GetPublics(), addr; while (count--) { // Get the offset in the public records. // Get the pointer to the string. //pos += publics; // Get the address of the string. #emit LREF.S.pri pos #emit STOR.S.pri addr //printf("%s", Scripting_GetString(Scripting_GetBase() + pos)); //new // str[32] = Scripting_GetString(base + pos)); if (Scripting_CompareString(name, base + addr)) { //pos = idx * 8 + publics; pos -= 4; // Get the pointer to the string. //pos += publics; // Get the address of the string. #emit LREF.S.pri pos #emit STOR.S.pri addr // It doesn't really matter what this is relative to, as long as the // usage in code is consistent. return addr; } pos += 8; } return -1; } /*----------------------------------------------------------------------------*- Function: Scripting_RedirectPublic Params: name[] - Name of the function to move. pointer - Where to move it to. Return: - Notes: - native Scripting_RedirectPublic(name[], pointer); -*----------------------------------------------------------------------------*/ stock Scripting_RedirectPublic(name[], pointer) { new count = Scripting_GetPublicsCount(), base = Scripting_GetBase(), pos = 4 + Scripting_GetPublics(), addr; while (count--) { // Get the offset in the public records. // Get the pointer to the string. //pos += publics; // Get the address of the string. #emit LREF.S.pri pos #emit STOR.S.pri addr //printf("%s", Scripting_GetString(Scripting_GetBase() + pos)); //new // str[32] = Scripting_GetString(base + pos)); if (Scripting_CompareString(name, base + addr)) { //pos = idx * 8 + publics; pos -= 4; // Get the pointer to the string. //pos += publics; // Get the address of the string. #emit LOAD.S.pri pointer #emit SREF.S.pri pos // It doesn't really matter what this is relative to, as long as the // usage in code is consistent. return; } pos += 8; } }