amx_header.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. // Copyright (C) 2012 Zeex
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a
  4. // copy of this software and associated documentation files (the "Software"),
  5. // to deal in the Software without restriction, including without limitation
  6. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  7. // and/or sell copies of the Software, and to permit persons to whom the
  8. // Software is furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  14. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  19. // DEALINGS IN THE SOFTWARE.
  20. #if defined AMX_HEADER_INC
  21. #endinput
  22. #endif
  23. #define AMX_HEADER_INC
  24. #tryinclude <console>
  25. #include "amx_memory"
  26. #define AMX_HDR_BYTES (60)
  27. #define AMX_HDR_CELLS (AMX_HDR_BYTES / 4)
  28. #define AMX_TAG_MASK (0x80000000)
  29. #define AMX_TAG_STRONG (0x40000000)
  30. enum AMX_HDR {
  31. AMX_HDR_SIZE,
  32. AMX_HDR_MAGIC,
  33. AMX_HDR_FILE_VERSION,
  34. AMX_HDR_AMX_VERSION,
  35. AMX_HDR_FLAGS,
  36. AMX_HDR_DEFSIZE,
  37. AMX_HDR_COD,
  38. AMX_HDR_DAT,
  39. AMX_HDR_HEA,
  40. AMX_HDR_STP,
  41. AMX_HDR_CIP,
  42. AMX_HDR_PUBLICS,
  43. AMX_HDR_NATIVES,
  44. AMX_HDR_LIBRARIES,
  45. AMX_HDR_PUBVARS,
  46. AMX_HDR_TAGS,
  47. AMX_HDR_NAMETABLE
  48. }
  49. const AMX_HDR_OFFSET_SIZE = 0;
  50. const AMX_HDR_OFFSET_MAGIC = 4;
  51. const AMX_HDR_OFFSET_FILE_VERSION = 6;
  52. const AMX_HDR_OFFSET_AMX_VERSION = 7;
  53. const AMX_HDR_OFFSET_FLAGS = 8;
  54. const AMX_HDR_OFFSET_DEFSIZE = 10;
  55. const AMX_HDR_OFFSET_COD = 12;
  56. const AMX_HDR_OFFSET_DAT = 16;
  57. const AMX_HDR_OFFSET_HEA = 20;
  58. const AMX_HDR_OFFSET_STP = 24;
  59. const AMX_HDR_OFFSET_CIP = 28;
  60. const AMX_HDR_OFFSET_PUBLICS = 32;
  61. const AMX_HDR_OFFSET_NATIVES = 36;
  62. const AMX_HDR_OFFSET_LIBRARIES = 40;
  63. const AMX_HDR_OFFSET_PUBVARS = 44;
  64. const AMX_HDR_OFFSET_TAGS = 48;
  65. const AMX_HDR_OFFSET_NAMETABLE = 52;
  66. enum AMX_FUNCSTUBNT {
  67. AMX_FUNCSTUBNT_ADDRESS,
  68. AMX_FUNCSTUBNT_NAMEOFS
  69. }
  70. #define AMX_FUNCSTUBNT_ID AMX_FUNCSTUBNT_ADDRESS
  71. // Publics
  72. forward bool:GetPublicInfo(index, info[AMX_FUNCSTUBNT]);
  73. forward GetPublicIndexFromAddress(address);
  74. forward GetPublicIndexFromName(const name[]);
  75. forward GetPublicAddressFromName(const name[]);
  76. forward GetPublicAddressFromIndex(index);
  77. forward bool:GetPublicNameFromIndex(index, name[], size = sizeof(name));
  78. forward bool:GetPublicNameFromAddress(address, name[], size = sizeof(name));
  79. forward HookPublic(index, address);
  80. // Tags
  81. forward bool:GetTagInfo(index, info[AMX_FUNCSTUBNT]);
  82. forward GetTagIndexFromID(id);
  83. forward GetTagIndexFromName(const name[]);
  84. forward GetTagIDFromName(const name[]);
  85. forward GetTagIDFromIndex(index);
  86. forward bool:GetTagNameFromIndex(index, name[], size = sizeof(name));
  87. forward bool:GetTagNameFromID(id, name[], size = sizeof(name));
  88. // Natives
  89. forward bool:GetNativeInfo(index, info[AMX_FUNCSTUBNT]);
  90. forward GetNativeIndexFromAddress(address);
  91. forward GetNativeIndexFromName(const name[]);
  92. forward GetNativeAddressFromName(const name[]);
  93. forward GetNativeAddressFromIndex(index);
  94. forward bool:GetNativeNameFromIndex(index, name[], size = sizeof(name));
  95. forward bool:GetNativeNameFromAddress(address, name[], size = sizeof(name));
  96. forward HookNative(index, address);
  97. // Public Variables
  98. forward bool:GetPubVarInfo(index, info[AMX_FUNCSTUBNT]);
  99. forward GetPubVarIndexFromName(const name[]);
  100. forward GetPubVarIndexFromAddress(address);
  101. forward GetPubVarAddressFromName(const name[]);
  102. forward GetPubVarAddressFromIndex(index);
  103. forward bool:GetPubVarNameFromIndex(index, name[], size = sizeof(name));
  104. forward bool:GetPubVarNameFromAddress(address, name[], size = sizeof(name));
  105. // General
  106. forward GetRawAmxHeader(plain_amxhdr[AMX_HDR_CELLS]);
  107. forward GetAmxHeaderNow(amxhdr[AMX_HDR]);
  108. forward GetAmxHeader(amxhdr[AMX_HDR]);
  109. forward GetAmxHeaderComponent(AMX_HDR:comp);
  110. forward PrintAmxHeader();
  111. stock GetRawAmxHeader(plain_amxhdr[AMX_HDR_CELLS]) {
  112. new address;
  113. #emit lctrl 1 // DAT
  114. #emit neg // -DAT
  115. #emit stor.s.pri address
  116. for (new i = 0; i < AMX_HDR_CELLS; i++) {
  117. plain_amxhdr[i] = ReadAmxMemory(address);
  118. address += 4;
  119. }
  120. }
  121. static stock copy_1(&dest, const source[], start) {
  122. #emit load.s.pri source
  123. #emit load.s.alt start
  124. #emit add
  125. #emit load.s.alt dest
  126. #emit movs 1
  127. }
  128. static stock copy_2(&dest, const source[], start) {
  129. #emit load.s.pri source
  130. #emit load.s.alt start
  131. #emit add
  132. #emit load.s.alt dest
  133. #emit movs 2
  134. }
  135. static stock copy_4(&dest, const source[], start) {
  136. #emit load.s.pri source
  137. #emit load.s.alt start
  138. #emit add
  139. #emit load.s.alt dest
  140. #emit movs 4
  141. }
  142. stock GetAmxHeaderNow(amxhdr[AMX_HDR]) {
  143. new plain_amxhdr[AMX_HDR_CELLS];
  144. GetRawAmxHeader(plain_amxhdr);
  145. copy_4(amxhdr[AMX_HDR_SIZE], plain_amxhdr, AMX_HDR_OFFSET_SIZE);
  146. copy_2(amxhdr[AMX_HDR_MAGIC], plain_amxhdr, AMX_HDR_OFFSET_MAGIC);
  147. copy_1(amxhdr[AMX_HDR_FILE_VERSION], plain_amxhdr, AMX_HDR_OFFSET_FILE_VERSION);
  148. copy_1(amxhdr[AMX_HDR_AMX_VERSION], plain_amxhdr, AMX_HDR_OFFSET_AMX_VERSION);
  149. copy_2(amxhdr[AMX_HDR_FLAGS], plain_amxhdr, AMX_HDR_OFFSET_FLAGS);
  150. copy_2(amxhdr[AMX_HDR_DEFSIZE], plain_amxhdr, AMX_HDR_OFFSET_DEFSIZE);
  151. copy_4(amxhdr[AMX_HDR_COD], plain_amxhdr, AMX_HDR_OFFSET_COD);
  152. copy_4(amxhdr[AMX_HDR_DAT], plain_amxhdr, AMX_HDR_OFFSET_DAT);
  153. copy_4(amxhdr[AMX_HDR_HEA], plain_amxhdr, AMX_HDR_OFFSET_HEA);
  154. copy_4(amxhdr[AMX_HDR_STP], plain_amxhdr, AMX_HDR_OFFSET_STP);
  155. copy_4(amxhdr[AMX_HDR_CIP], plain_amxhdr, AMX_HDR_OFFSET_CIP);
  156. copy_4(amxhdr[AMX_HDR_PUBLICS], plain_amxhdr, AMX_HDR_OFFSET_PUBLICS);
  157. copy_4(amxhdr[AMX_HDR_NATIVES], plain_amxhdr, AMX_HDR_OFFSET_NATIVES);
  158. copy_4(amxhdr[AMX_HDR_LIBRARIES], plain_amxhdr, AMX_HDR_OFFSET_LIBRARIES);
  159. copy_4(amxhdr[AMX_HDR_PUBVARS], plain_amxhdr, AMX_HDR_OFFSET_PUBVARS);
  160. copy_4(amxhdr[AMX_HDR_TAGS], plain_amxhdr, AMX_HDR_OFFSET_TAGS);
  161. copy_4(amxhdr[AMX_HDR_NAMETABLE], plain_amxhdr, AMX_HDR_OFFSET_NAMETABLE);
  162. }
  163. static gHdr[AMX_HDR];
  164. static bool:gInitialized = false;
  165. stock ResetStaticAmxHeader() {
  166. GetAmxHeaderNow(gHdr);
  167. gInitialized = true;
  168. }
  169. #define InitStaticAmxHeader() \
  170. if (!gInitialized) \
  171. ResetStaticAmxHeader()
  172. stock GetAmxHeader(amxhdr[AMX_HDR]) {
  173. InitStaticAmxHeader();
  174. amxhdr = gHdr;
  175. }
  176. stock GetAmxHeaderComponent(AMX_HDR:comp) {
  177. InitStaticAmxHeader();
  178. return gHdr[comp];
  179. }
  180. stock PrintAmxHeader() {
  181. InitStaticAmxHeader();
  182. printf("------------------------");
  183. printf("AMX Header:");
  184. printf("------------------------");
  185. printf("size %d", gHdr[AMX_HDR_SIZE]);
  186. printf("magic %x", gHdr[AMX_HDR_MAGIC]);
  187. printf("file_version %d", gHdr[AMX_HDR_FILE_VERSION]);
  188. printf("amx_version %d", gHdr[AMX_HDR_AMX_VERSION]);
  189. printf("flags %d", gHdr[AMX_HDR_FLAGS]);
  190. printf("defsize %d", gHdr[AMX_HDR_DEFSIZE]);
  191. printf("cod 0x%08x", gHdr[AMX_HDR_COD]);
  192. printf("dat 0x%08x", gHdr[AMX_HDR_DAT]);
  193. printf("hea 0x%08x", gHdr[AMX_HDR_HEA]);
  194. printf("stp 0x%08x", gHdr[AMX_HDR_STP]);
  195. printf("cip 0x%08x", gHdr[AMX_HDR_CIP]);
  196. printf("publics 0x%08x", gHdr[AMX_HDR_PUBLICS]);
  197. printf("natives 0x%08x", gHdr[AMX_HDR_NATIVES]);
  198. printf("libraries 0x%08x", gHdr[AMX_HDR_LIBRARIES]);
  199. printf("pubvars 0x%08x", gHdr[AMX_HDR_PUBVARS]);
  200. printf("tags 0x%08x", gHdr[AMX_HDR_TAGS]);
  201. printf("nametable 0x%08x", gHdr[AMX_HDR_NAMETABLE]);
  202. printf("------------------------");
  203. }
  204. // Compares a string stored in the name table starting at "s1" (packed)
  205. // with another string "s2" (unpacked).
  206. static stock NtCompare(s1, const s2[]) {
  207. new index;
  208. new c1, c2;
  209. new diff;
  210. do {
  211. c1 = ReadAmxMemory(s1++) & 0xFF;
  212. c2 = s2[index++];
  213. diff = c1 - c2;
  214. if (diff != 0) {
  215. break;
  216. }
  217. } while (!(c1 & c2 == 0));
  218. return diff;
  219. }
  220. // Copies a name from the name table to a string. Returns the number
  221. // of characters copied.
  222. static stock NtCopy(src, dest[], size = sizeof(dest)) {
  223. new i = 0;
  224. new c;
  225. do {
  226. c = ReadAmxMemory(src++) & 0xFF;
  227. dest[i++] = c;
  228. } while (c != '\0' && i <= size);
  229. dest[i] = '\0'; // terminator
  230. return i;
  231. }
  232. stock GetNumPublics(amxhdr[AMX_HDR]) {
  233. new num_publics = (amxhdr[AMX_HDR_NATIVES] - amxhdr[AMX_HDR_PUBLICS]) / amxhdr[AMX_HDR_DEFSIZE];
  234. return num_publics;
  235. }
  236. stock GetPublicIndexFromAddress(address) {
  237. InitStaticAmxHeader();
  238. new num_publics = GetNumPublics(gHdr);
  239. new off = gHdr[AMX_HDR_PUBLICS] - gHdr[AMX_HDR_DAT];
  240. // Linear search
  241. for (new i = 0; i < num_publics; i++) {
  242. if (ReadAmxMemory(off) == address) {
  243. return i;
  244. }
  245. off += gHdr[AMX_HDR_DEFSIZE];
  246. }
  247. return -1;
  248. }
  249. stock bool:GetPublicInfo(index, info[AMX_FUNCSTUBNT]) {
  250. InitStaticAmxHeader();
  251. new num_publics = GetNumPublics(gHdr);
  252. if (index < 0 || index >= num_publics) {
  253. return false;
  254. }
  255. new off = gHdr[AMX_HDR_PUBLICS] - gHdr[AMX_HDR_DAT] + index * gHdr[AMX_HDR_DEFSIZE];
  256. info[AMX_FUNCSTUBNT_ADDRESS] = ReadAmxMemory(off);
  257. info[AMX_FUNCSTUBNT_NAMEOFS] = ReadAmxMemory(off + 4);
  258. return true;
  259. }
  260. stock GetPublicIndexFromName(const name[]) {
  261. InitStaticAmxHeader();
  262. new num_publics = GetNumPublics(gHdr);
  263. // Binary search
  264. new first = 0;
  265. new last = num_publics - 1;
  266. new mid;
  267. while (first <= last) {
  268. mid = (first + last) / 2;
  269. new off = gHdr[AMX_HDR_PUBLICS] - gHdr[AMX_HDR_DAT] + mid * gHdr[AMX_HDR_DEFSIZE];
  270. new nameofs = ReadAmxMemory(off + 4) - gHdr[AMX_HDR_DAT];
  271. new diff = NtCompare(nameofs, name);
  272. if (diff < 0) {
  273. first = mid + 1;
  274. } else if (diff > 0) {
  275. last = mid - 1;
  276. } else {
  277. return mid;
  278. }
  279. }
  280. return -1;
  281. }
  282. stock GetPublicAddressFromIndex(index) {
  283. new info[AMX_FUNCSTUBNT];
  284. GetPublicInfo(index, info);
  285. return info[AMX_FUNCSTUBNT_ADDRESS];
  286. }
  287. stock GetPublicAddressFromName(const name[]) {
  288. return GetPublicAddressFromIndex(GetPublicIndexFromName(name));
  289. }
  290. stock bool:GetPublicNameFromIndex(index, name[], size = sizeof(name)) {
  291. new info[AMX_FUNCSTUBNT];
  292. if (!GetPublicInfo(index, info)) {
  293. return false;
  294. }
  295. return (NtCopy(info[AMX_FUNCSTUBNT_NAMEOFS]
  296. - GetAmxHeaderComponent(AMX_HDR_DAT), name, size) > 0);
  297. }
  298. stock bool:GetPublicNameFromAddress(address, name[], size = sizeof(name)) {
  299. return GetPublicNameFromIndex(GetPublicIndexFromAddress(address), name, size);
  300. }
  301. stock HookPublic(index, address) {
  302. InitStaticAmxHeader();
  303. new num_publics = GetNumPublics(gHdr);
  304. if (index < 0 || index >= num_publics) {
  305. return 0;
  306. }
  307. new off = gHdr[AMX_HDR_PUBLICS] - gHdr[AMX_HDR_DAT] + index * gHdr[AMX_HDR_DEFSIZE];
  308. new old_address = ReadAmxMemory(off);
  309. WriteAmxMemory(off, address);
  310. return old_address;
  311. }
  312. stock GetNumNatives(amxhdr[AMX_HDR]) {
  313. return (amxhdr[AMX_HDR_LIBRARIES] - amxhdr[AMX_HDR_NATIVES]) / amxhdr[AMX_HDR_DEFSIZE];
  314. }
  315. stock GetNativeIndexFromAddress(address) {
  316. InitStaticAmxHeader();
  317. new num_natives = GetNumNatives(gHdr);
  318. new off = gHdr[AMX_HDR_NATIVES] - gHdr[AMX_HDR_DAT];
  319. // Linear search
  320. for (new i = 0; i < num_natives; i++) {
  321. if (ReadAmxMemory(off) == address) {
  322. return i;
  323. }
  324. off += gHdr[AMX_HDR_DEFSIZE];
  325. }
  326. return -1;
  327. }
  328. stock bool:GetNativeInfo(index, info[AMX_FUNCSTUBNT]) {
  329. InitStaticAmxHeader();
  330. // For when "index" is not valid
  331. info[AMX_FUNCSTUBNT_ADDRESS] = -1;
  332. new num_natives = GetNumNatives(gHdr);
  333. if (index < 0 || index >= num_natives) {
  334. return false;
  335. }
  336. new off = gHdr[AMX_HDR_NATIVES] - gHdr[AMX_HDR_DAT] + index * gHdr[AMX_HDR_DEFSIZE];
  337. info[AMX_FUNCSTUBNT_ADDRESS] = ReadAmxMemory(off);
  338. info[AMX_FUNCSTUBNT_NAMEOFS] = ReadAmxMemory(off + 4);
  339. return true;
  340. }
  341. stock GetNativeIndexFromName(const name[]) {
  342. InitStaticAmxHeader();
  343. new num_natives = GetNumNatives(gHdr);
  344. new off = gHdr[AMX_HDR_NATIVES] - gHdr[AMX_HDR_DAT];
  345. // Linear search
  346. for (new i = 0; i < num_natives; i++) {
  347. new nameofs = ReadAmxMemory(off + 4) - gHdr[AMX_HDR_DAT];
  348. new diff = NtCompare(nameofs, name);
  349. if (diff == 0) {
  350. return i;
  351. }
  352. off += gHdr[AMX_HDR_DEFSIZE];
  353. }
  354. return -1;
  355. }
  356. stock GetNativeAddressFromIndex(index) {
  357. new info[AMX_FUNCSTUBNT];
  358. GetNativeInfo(index, info);
  359. return info[AMX_FUNCSTUBNT_ADDRESS];
  360. }
  361. stock GetNativeAddressFromName(const name[]) {
  362. return GetNativeAddressFromIndex(GetNativeIndexFromName(name));
  363. }
  364. stock bool:GetNativeNameFromIndex(index, name[], size = sizeof(name)) {
  365. new info[AMX_FUNCSTUBNT];
  366. if (!GetNativeInfo(index, info)) {
  367. return false;
  368. }
  369. return (NtCopy(info[AMX_FUNCSTUBNT_NAMEOFS]
  370. - GetAmxHeaderComponent(AMX_HDR_DAT), name, size) > 0);
  371. }
  372. stock bool:GetNativeNameFromAddress(address, name[], size = sizeof(name)) {
  373. return GetNativeNameFromIndex(GetNativeIndexFromAddress(address), name, size);
  374. }
  375. stock HookNative(index, address) {
  376. InitStaticAmxHeader();
  377. new num_natives = GetNumNatives(gHdr);
  378. if (index < 0 || index >= num_natives) {
  379. return 0;
  380. }
  381. new off = gHdr[AMX_HDR_NATIVES] - gHdr[AMX_HDR_DAT] + index * gHdr[AMX_HDR_DEFSIZE];
  382. new old_address = ReadAmxMemory(off);
  383. WriteAmxMemory(off, address);
  384. return old_address;
  385. }
  386. stock GetNumPubVars(amxhdr[AMX_HDR]) {
  387. return (amxhdr[AMX_HDR_TAGS] - amxhdr[AMX_HDR_PUBVARS]) / amxhdr[AMX_HDR_DEFSIZE];
  388. }
  389. stock bool:GetPubVarInfo(index, info[AMX_FUNCSTUBNT]) {
  390. InitStaticAmxHeader();
  391. new num_pubvars = GetNumPubVars(gHdr);
  392. if (index < 0 || index >= num_pubvars) {
  393. return false;
  394. }
  395. new off = gHdr[AMX_HDR_PUBVARS] - gHdr[AMX_HDR_DAT] + index * gHdr[AMX_HDR_DEFSIZE];
  396. info[AMX_FUNCSTUBNT_ADDRESS] = ReadAmxMemory(off);
  397. info[AMX_FUNCSTUBNT_NAMEOFS] = ReadAmxMemory(off + 4);
  398. return true;
  399. }
  400. stock GetPubVarIndexFromName(const name[]) {
  401. InitStaticAmxHeader();
  402. new num_pubvars = GetNumPubVars(gHdr);
  403. // Binary search
  404. new first = 0;
  405. new last = num_pubvars - 1;
  406. new mid;
  407. while (first <= last) {
  408. mid = (first + last) / 2;
  409. new off = gHdr[AMX_HDR_PUBVARS] - gHdr[AMX_HDR_DAT] + mid * gHdr[AMX_HDR_DEFSIZE];
  410. new nameofs = ReadAmxMemory(off + 4) - gHdr[AMX_HDR_DAT];
  411. new diff = NtCompare(nameofs, name);
  412. if (diff < 0) {
  413. first = mid + 1;
  414. } else if (diff > 0) {
  415. last = mid - 1;
  416. } else {
  417. return mid;
  418. }
  419. }
  420. return -1;
  421. }
  422. stock GetPubVarIndexFromAddress(address) {
  423. InitStaticAmxHeader();
  424. new num_pubvars = GetNumPubVars(gHdr);
  425. new off = gHdr[AMX_HDR_PUBVARS] - gHdr[AMX_HDR_DAT];
  426. // Linear search
  427. for (new i = 0; i < num_pubvars; i++) {
  428. if (ReadAmxMemory(off) == address) {
  429. return i;
  430. }
  431. off += gHdr[AMX_HDR_DEFSIZE];
  432. }
  433. return -1;
  434. }
  435. stock GetPubVarAddressFromIndex(index) {
  436. new info[AMX_FUNCSTUBNT];
  437. GetPubVarInfo(index, info);
  438. return info[AMX_FUNCSTUBNT_ADDRESS];
  439. }
  440. stock GetPubVarAddressFromName(const name[]) {
  441. return GetPubVarAddressFromIndex(GetPubVarIndexFromName(name));
  442. }
  443. stock bool:GetPubVarNameFromIndex(index, name[], size = sizeof(name)) {
  444. new info[AMX_FUNCSTUBNT];
  445. if (!GetPubVarInfo(index, info)) {
  446. return false;
  447. }
  448. return (NtCopy(info[AMX_FUNCSTUBNT_NAMEOFS]
  449. - GetAmxHeaderComponent(AMX_HDR_DAT), name, size) > 0);
  450. }
  451. stock bool:GetPubVarNameFromAddress(address, name[], size = sizeof(name)) {
  452. return GetPubVarNameFromIndex(GetPubVarIndexFromAddress(address), name, size);
  453. }
  454. static stock GetNumTagsInternal(amxhdr[AMX_HDR]) {
  455. return (amxhdr[AMX_HDR_NAMETABLE] - amxhdr[AMX_HDR_TAGS]) / amxhdr[AMX_HDR_DEFSIZE];
  456. }
  457. stock GetNumTags(amxhdr[AMX_HDR]) {
  458. return GetNumTagsInternal(amxhdr) + 1;
  459. }
  460. stock bool:GetTagInfo(index, info[AMX_FUNCSTUBNT]) {
  461. if (index == 0) {
  462. info[AMX_FUNCSTUBNT_ID] = AMX_TAG_MASK;
  463. info[AMX_FUNCSTUBNT_NAMEOFS] = 0;
  464. return true;
  465. }
  466. InitStaticAmxHeader();
  467. new num_tags = GetNumTagsInternal(gHdr);
  468. if (index < 0 || index >= num_tags) {
  469. return false;
  470. }
  471. new off = gHdr[AMX_HDR_TAGS] - gHdr[AMX_HDR_DAT] + index * gHdr[AMX_HDR_DEFSIZE];
  472. info[AMX_FUNCSTUBNT_ID] = ReadAmxMemory(off) | AMX_TAG_MASK;
  473. info[AMX_FUNCSTUBNT_NAMEOFS] = ReadAmxMemory(off + 4);
  474. return true;
  475. }
  476. stock GetTagIndexFromName(const name[]) {
  477. if (name[0] == '_' && name[1] == '\0')
  478. return 0;
  479. InitStaticAmxHeader();
  480. new num_tags = GetNumTagsInternal(gHdr);
  481. // Binary search
  482. new first = 0;
  483. new last = num_tags - 1;
  484. new mid;
  485. while (first <= last) {
  486. mid = (first + last) / 2;
  487. new off = gHdr[AMX_HDR_TAGS] - gHdr[AMX_HDR_DAT] + mid * gHdr[AMX_HDR_DEFSIZE];
  488. new nameofs = ReadAmxMemory(off + 4) - gHdr[AMX_HDR_DAT];
  489. new diff = NtCompare(nameofs, name);
  490. if (diff < 0) {
  491. first = mid + 1;
  492. } else if (diff > 0) {
  493. last = mid - 1;
  494. } else {
  495. return mid;
  496. }
  497. }
  498. return -1;
  499. }
  500. stock GetTagIndexFromID(id) {
  501. id &= ~AMX_TAG_MASK;
  502. if (id == 0)
  503. return 0;
  504. InitStaticAmxHeader();
  505. new num_tags = GetNumTagsInternal(gHdr);
  506. new off = gHdr[AMX_HDR_TAGS] - gHdr[AMX_HDR_DAT];
  507. // Linear search
  508. for (new i = 0; i < num_tags; i++) {
  509. if (ReadAmxMemory(off) == id) {
  510. return i;
  511. }
  512. off += gHdr[AMX_HDR_DEFSIZE];
  513. }
  514. return -1;
  515. }
  516. stock GetTagIDFromIndex(index) {
  517. if (index == 0)
  518. return AMX_TAG_MASK;
  519. new info[AMX_FUNCSTUBNT];
  520. GetTagInfo(index, info);
  521. return info[AMX_FUNCSTUBNT_ID];
  522. }
  523. stock GetTagIDFromName(const name[]) {
  524. if (name[0] == '_' && name[1] == '\0')
  525. return AMX_TAG_MASK;
  526. return GetTagIDFromIndex(GetTagIndexFromName(name));
  527. }
  528. stock bool:GetTagNameFromIndex(index, name[], size = sizeof(name)) {
  529. if (index == 0)
  530. {
  531. name[0] = '_';
  532. name[1] = '\0';
  533. return true;
  534. }
  535. new info[AMX_FUNCSTUBNT];
  536. if (!GetTagInfo(index, info)) {
  537. return false;
  538. }
  539. return (NtCopy(info[AMX_FUNCSTUBNT_NAMEOFS]
  540. - GetAmxHeaderComponent(AMX_HDR_DAT), name, size) > 0);
  541. }
  542. stock bool:GetTagNameFromID(id, name[], size = sizeof(name)) {
  543. if (id == 0)
  544. {
  545. name[0] = '_';
  546. name[1] = '\0';
  547. return true;
  548. }
  549. return GetTagNameFromIndex(GetTagIndexFromID(id), name, size);
  550. }
  551. stock bool:IsTagIDStrong(tag) {
  552. return !!(tag & AMX_TAG_STRONG);
  553. }
  554. stock bool:IsTagIDWeak(tag) {
  555. return !(tag & AMX_TAG_STRONG);
  556. }
  557. stock bool:IsTagIDEmpty(tag) {
  558. return !(tag & ~AMX_TAG_MASK);
  559. }
  560. stock bool:IsTagNameStrong(tag[]) {
  561. return ('A' <= tag[0] <= 'Z');
  562. }
  563. stock bool:IsTagNameWeak(tag[]) {
  564. return !('A' <= tag[0] <= 'Z');
  565. }
  566. stock bool:IsTagNameEmpty(tag[]) {
  567. return (tag[0] == '_' && tag[1] == '\0');
  568. }
  569. stock bool:IsTagIndexStrong(tag) {
  570. new info[AMX_FUNCSTUBNT];
  571. return (GetTagInfo(tag, info) && IsTagIDStrong(info[AMX_FUNCSTUBNT_ID]));
  572. }
  573. stock bool:IsTagIndexWeak(tag) {
  574. new info[AMX_FUNCSTUBNT];
  575. return (GetTagInfo(tag, info) && IsTagIDWeak(info[AMX_FUNCSTUBNT_ID]));
  576. }
  577. stock bool:IsTagIndexEmpty(tag) {
  578. return (tag == 0);
  579. }
  580. #undef InitStaticAmxHeader