y_amx.inc 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366
  1. /**--------------------------------------------------------------------------**\
  2. ===============================
  3. y_scripting - Access amx data
  4. ===============================
  5. Description:
  6. Allows a script access to information about itself, such as function names.
  7. This can be used for a range of things, including automatic callback hooking
  8. and testing.
  9. Legal:
  10. Version: MPL 1.1
  11. The contents of this file are subject to the Mozilla Public License Version
  12. 1.1 (the "License"); you may not use this file except in compliance with
  13. the License. You may obtain a copy of the License at
  14. http://www.mozilla.org/MPL/
  15. Software distributed under the License is distributed on an "AS IS" basis,
  16. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  17. for the specific language governing rights and limitations under the
  18. License.
  19. The Original Code is the YSI AMX include.
  20. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  21. Portions created by the Initial Developer are Copyright (C) 2011
  22. the Initial Developer. All Rights Reserved.
  23. Contributors:
  24. ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
  25. Thanks:
  26. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  27. ZeeX - Very productive conversations.
  28. koolk - IsPlayerinAreaEx code.
  29. TheAlpha - Danish translation.
  30. breadfish - German translation.
  31. Fireburn - Dutch translation.
  32. yom - French translation.
  33. 50p - Polish translation.
  34. Zamaroht - Spanish translation.
  35. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  36. for me to strive to better.
  37. Pixels^ - Running XScripters where the idea was born.
  38. Matite - Pestering me to release it and using it.
  39. Very special thanks to:
  40. Thiadmer - PAWN, whose limits continue to amaze me!
  41. Kye/Kalcor - SA:MP.
  42. SA:MP Team past, present and future - SA:MP.
  43. Version:
  44. 1.0
  45. Changelog:
  46. 13/11/13:
  47. Simplified the main macros to work across multiple lines.
  48. 06/08/10:
  49. First version
  50. \**--------------------------------------------------------------------------**/
  51. #if defined _INC_y_amx
  52. #endinput
  53. #endif
  54. #define _INC_y_amx
  55. // I debated porting this over to use ZeeX's advanced AMX system, but there's no
  56. // point - this is stable and works well. Doing so would mean testing that all
  57. // the code that uses this file still operates corectly given how differently
  58. // the two systems do things. I fully admit that his is FAR more general but
  59. // there are legacy libraries to consider.
  60. #include "..\YSI_Internal\y_version"
  61. #include "..\YSI_Server\y_scriptinit"
  62. #include "..\YSI_Core\y_debug"
  63. #include "..\YSI_Internal\y_natives"
  64. #include "..\YSI_Internal\amx_assembly"
  65. #define AMX_FastString(%1,%2,%3,%4) \
  66. (((%1) << 0) | ((%2) << 8) | ((%3) << 16) | ((%4) << 24))
  67. #define AMX_MEMORY_TRACE_0 0xAABBCCDD
  68. #define AMX_MEMORY_TRACE_1 0xDDCCBBAA
  69. #define AMX_MEMORY_TRACE_2 0x12345678
  70. #define AMX_MEMORY_TRACE_3 0x87654321
  71. stock
  72. AMX_HEADER_SIZE,
  73. AMX_HEADER_MAGIC,
  74. AMX_HEADER_FILE_VERSION,
  75. AMX_HEADER_AMX_VERSION,
  76. AMX_HEADER_FLAGS,
  77. AMX_HEADER_DEFSIZE,
  78. // These are not as they appear in the AMX - they are relative to the dat
  79. // pointer so that they can be directly manipulated.
  80. AMX_HEADER_COD,
  81. AMX_HEADER_DAT,
  82. AMX_HEADER_HEA,
  83. AMX_HEADER_STP,
  84. AMX_HEADER_CIP,
  85. AMX_HEADER_PUBLICS,
  86. AMX_HEADER_NATIVES,
  87. AMX_HEADER_LIBRARIES,
  88. AMX_HEADER_PUBVARS,
  89. AMX_HEADER_TAGS,
  90. AMX_HEADER_NAMETABLE,
  91. //E_AMX_HEADER_OVERLAYS,
  92. AMX_REAL_ADDRESS,
  93. AMX_BASE_ADDRESS,
  94. AMX_REAL_DATA;
  95. enum E_AMX_TABLE
  96. {
  97. AMX_TABLE_PUBLICS,
  98. AMX_TABLE_NATIVES,
  99. AMX_TABLE_LIBRARIES,
  100. AMX_TABLE_PUBVARS,
  101. AMX_TABLE_TAGS
  102. }
  103. // This is based on the AMX version used in SA:MP - it DOES NOT match the code
  104. // found in the PAWN documentation as that's for a later version.
  105. public OnScriptInit()
  106. {
  107. new
  108. addr,
  109. data;
  110. #emit LCTRL 1
  111. #emit STOR.S.pri addr
  112. // Invert to get the prefix offset relative to the data.
  113. // Get all the script data.
  114. addr = -addr;
  115. // Now read in all the data.
  116. #emit LREF.S.pri addr
  117. #emit STOR.S.pri data
  118. AMX_HEADER_SIZE = data;
  119. addr += 4;
  120. #emit LREF.S.pri addr
  121. #emit STOR.S.pri data
  122. AMX_HEADER_MAGIC = data & 0xFFFF;
  123. AMX_HEADER_FILE_VERSION = data >>> 16 & 0xFF;
  124. AMX_HEADER_AMX_VERSION = data >>> 24;
  125. addr += 4;
  126. #emit LREF.S.pri addr
  127. #emit STOR.S.pri data
  128. AMX_HEADER_FLAGS = data & 0xFFFF;
  129. AMX_HEADER_DEFSIZE = data >>> 16;
  130. addr += 4;
  131. #emit LREF.S.pri addr
  132. #emit STOR.S.pri data
  133. AMX_HEADER_COD = data;
  134. addr += 4;
  135. #emit LREF.S.pri addr
  136. #emit STOR.S.pri data
  137. //dat = data;
  138. AMX_HEADER_DAT = 0;
  139. AMX_BASE_ADDRESS = -data;
  140. AMX_HEADER_COD += AMX_BASE_ADDRESS;
  141. addr += 4;
  142. #emit LREF.S.pri addr
  143. #emit STOR.S.pri data
  144. AMX_HEADER_HEA = data + AMX_BASE_ADDRESS;
  145. addr += 4;
  146. #emit LREF.S.pri addr
  147. #emit STOR.S.pri data
  148. AMX_HEADER_STP = data + AMX_BASE_ADDRESS;
  149. addr += 4;
  150. #emit LREF.S.pri addr
  151. #emit STOR.S.pri data
  152. AMX_HEADER_CIP = data + AMX_BASE_ADDRESS;
  153. addr += 4;
  154. #emit LREF.S.pri addr
  155. #emit STOR.S.pri data
  156. AMX_HEADER_PUBLICS = data + AMX_BASE_ADDRESS;
  157. addr += 4;
  158. #emit LREF.S.pri addr
  159. #emit STOR.S.pri data
  160. AMX_HEADER_NATIVES = data + AMX_BASE_ADDRESS;
  161. addr += 4;
  162. #emit LREF.S.pri addr
  163. #emit STOR.S.pri data
  164. AMX_HEADER_LIBRARIES = data + AMX_BASE_ADDRESS;
  165. addr += 4;
  166. #emit LREF.S.pri addr
  167. #emit STOR.S.pri data
  168. AMX_HEADER_PUBVARS = data + AMX_BASE_ADDRESS;
  169. addr += 4;
  170. #emit LREF.S.pri addr
  171. #emit STOR.S.pri data
  172. AMX_HEADER_TAGS = data + AMX_BASE_ADDRESS;
  173. addr += 4;
  174. #emit LREF.S.pri addr
  175. #emit STOR.S.pri data
  176. AMX_HEADER_NAMETABLE = data + AMX_BASE_ADDRESS;
  177. // Now find the AMX's base address in global memory. This is VERY handy to
  178. // have for more advanced functionality (none of which actually exists yet).
  179. AMX_REAL_ADDRESS = AMX_GetGlobal();
  180. AMX_REAL_DATA = AMX_REAL_ADDRESS - AMX_BASE_ADDRESS;
  181. // Call next ALS callback.
  182. #if defined YSI_LOCK_MODE
  183. GetServerVarAsString(YSI_gLockData, YSI_gLockData[5], sizeof (YSI_gLockData) - 5);
  184. #endif
  185. #if defined AMX_OnScriptInit
  186. AMX_OnScriptInit();
  187. #endif
  188. return 1;
  189. }
  190. #undef OnScriptInit
  191. #define OnScriptInit AMX_OnScriptInit
  192. #if defined AMX_OnScriptInit
  193. forward AMX_OnScriptInit();
  194. #endif
  195. stock AMX_GetGlobalAddress(...)
  196. {
  197. new
  198. addr;
  199. // addr = numargs();
  200. #emit LOAD.S.pri 8
  201. #emit STOR.S.pri addr
  202. if (addr >= 4)
  203. {
  204. // getargptr(0);
  205. #emit LOAD.S.pri 12
  206. #emit LOAD.alt AMX_REAL_DATA
  207. #emit ADD
  208. #emit STACK 4
  209. #emit RETN
  210. }
  211. return 0;
  212. }
  213. stock AMX_GetRelativeAddress(...)
  214. {
  215. new
  216. addr;
  217. // addr = numargs();
  218. #emit LOAD.S.pri 8
  219. #emit STOR.S.pri addr
  220. if (addr >= 4)
  221. {
  222. // getargptr(0);
  223. #emit LOAD.S.pri 12
  224. #emit STACK 4
  225. #emit RETN
  226. }
  227. return 0;
  228. }
  229. static AMX_DoNothing()
  230. {
  231. return 0;
  232. }
  233. static AMX_GetGlobal()
  234. {
  235. new
  236. addr = -1;
  237. // Call dummy function and read its (absolute) address from code.
  238. AMX_DoNothing();
  239. #emit LCTRL 6
  240. #emit CONST.alt 12
  241. #emit SUB
  242. #emit LOAD.alt AMX_HEADER_COD
  243. #emit ADD
  244. #emit STOR.S.pri addr
  245. #emit LREF.S.pri addr
  246. // Get difference between absolute and relative addresses.
  247. #emit SUB
  248. #emit CONST.alt AMX_DoNothing
  249. #emit SUB
  250. #emit MOVE.alt
  251. #emit LCTRL 1
  252. #emit XCHG
  253. #emit SUB
  254. // Return
  255. #emit STACK 4
  256. #emit RETN
  257. return 0;
  258. }
  259. stock AMX_TraceCode(pattern[], &addrRet, &dataRet, size = sizeof (pattern))
  260. {
  261. new
  262. addr = AMX_HEADER_COD + addrRet,
  263. data,
  264. i;
  265. while (addr < AMX_HEADER_DAT)
  266. {
  267. #emit LREF.S.pri addr
  268. #emit STOR.S.pri data
  269. if (data == pattern[i])
  270. {
  271. ++i;
  272. addr += 4;
  273. if (i == size)
  274. {
  275. addrRet = addr - i * 4 - AMX_HEADER_COD;
  276. #emit LREF.S.pri addr
  277. #emit STOR.S.pri data
  278. dataRet = data;
  279. return 1;
  280. }
  281. }
  282. else if (i)
  283. {
  284. addr -= i * 4 - 4;
  285. i = 0;
  286. }
  287. else
  288. {
  289. addr += 4;
  290. }
  291. }
  292. return 0;
  293. }
  294. stock AMX_TraceMemory(pattern[], &addrRet, &dataRet, size = sizeof (pattern))
  295. {
  296. new
  297. addr = AMX_HEADER_DAT + addrRet,
  298. data,
  299. i;
  300. while (addr < AMX_HEADER_HEA)
  301. {
  302. #emit LREF.S.pri addr
  303. #emit STOR.S.pri data
  304. if (data == pattern[i])
  305. {
  306. ++i;
  307. addr += 4;
  308. if (i == size)
  309. {
  310. addrRet = addr - i * 4 - AMX_HEADER_DAT;
  311. #emit LREF.S.pri addr
  312. #emit STOR.S.pri data
  313. dataRet = data;
  314. return 1;
  315. }
  316. }
  317. else if (i)
  318. {
  319. addr -= i * 4 - 4;
  320. i = 0;
  321. }
  322. else
  323. {
  324. addr += 4;
  325. }
  326. }
  327. return 0;
  328. }
  329. stock AMX_GetBaseCount(E_AMX_TABLE:table, &base, &count)
  330. {
  331. P:7("AMX_GetBaseCount called: %i, %i, %i", _:table, base, count);
  332. switch (table)
  333. {
  334. case AMX_TABLE_PUBLICS:
  335. {
  336. base = AMX_HEADER_PUBLICS;
  337. count = (AMX_HEADER_NATIVES - AMX_HEADER_PUBLICS) / 8;
  338. }
  339. case AMX_TABLE_NATIVES:
  340. {
  341. base = AMX_HEADER_NATIVES;
  342. count = (AMX_HEADER_LIBRARIES - AMX_HEADER_NATIVES) / 8;
  343. }
  344. case AMX_TABLE_LIBRARIES:
  345. {
  346. base = AMX_HEADER_LIBRARIES;
  347. count = (AMX_HEADER_PUBVARS - AMX_HEADER_LIBRARIES) / 8;
  348. }
  349. case AMX_TABLE_PUBVARS:
  350. {
  351. base = AMX_HEADER_PUBVARS;
  352. count = (AMX_HEADER_TAGS - AMX_HEADER_PUBVARS) / 8;
  353. }
  354. case AMX_TABLE_TAGS:
  355. {
  356. base = AMX_HEADER_TAGS;
  357. count = (AMX_HEADER_NAMETABLE - AMX_HEADER_TAGS) / 8;
  358. }
  359. default:
  360. {
  361. base = 0;
  362. count = 0;
  363. }
  364. }
  365. }
  366. #define AMX_GetPublicEntry( AMX_GetEntry(AMX_TABLE_PUBLICS,
  367. #define AMX_GetNativeEntry( AMX_GetEntry(AMX_TABLE_NATIVES,
  368. #define AMX_GetLibraryEntry( AMX_GetEntry(AMX_TABLE_LIBRARIES,
  369. #define AMX_GetPubvarEntry( AMX_GetEntry(AMX_TABLE_PUBVARS,
  370. #define AMX_GetTagEntry( AMX_GetEntry(AMX_TABLE_TAGS,
  371. stock AMX_GetEntry(E_AMX_TABLE:table, idx, &buffer, const pattern[] = "", const bool:exact = false)
  372. {
  373. P:7("AMX_GetEntry called: %i, %i, %i, \"%s\", %i", _:table, idx, buffer, pattern, exact);
  374. new
  375. base,
  376. count;
  377. AMX_GetBaseCount(table, base, count);
  378. if (idx < count)
  379. {
  380. if (pattern[0] == '\0')
  381. {
  382. buffer = idx * 8 + base;
  383. return idx + 1;
  384. }
  385. else
  386. {
  387. new
  388. addr,
  389. pos = idx * 8 + base + 4,
  390. str[32];
  391. do
  392. {
  393. #emit LREF.S.pri pos
  394. #emit STOR.S.pri addr
  395. AMX_ReadString(AMX_BASE_ADDRESS + addr, str);
  396. ++idx;
  397. if (exact ? (str{0} && !strcmp(str, pattern)) : (strfind(str, pattern) != -1))
  398. {
  399. buffer = pos - 4;
  400. return idx;
  401. }
  402. pos += 8;
  403. }
  404. while (idx < count);
  405. }
  406. }
  407. return 0;
  408. }
  409. #define AMX_GetPublicEntryPrefix( AMX_GetEntryPrefix(AMX_TABLE_PUBLICS,
  410. #define AMX_GetNativeEntryPrefix( AMX_GetEntryPrefix(AMX_TABLE_NATIVES,
  411. #define AMX_GetLibraryEntryPrefix( AMX_GetEntryPrefix(AMX_TABLE_LIBRARIES,
  412. #define AMX_GetPubvarEntryPrefix( AMX_GetEntryPrefix(AMX_TABLE_PUBVARS,
  413. #define AMX_GetTagEntryPrefix( AMX_GetEntryPrefix(AMX_TABLE_TAGS,
  414. stock AMX_GetEntryPrefix(E_AMX_TABLE:table, idx, &buffer, pattern)
  415. {
  416. P:7("AMX_GetEntryPrefix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
  417. new
  418. base,
  419. count;
  420. AMX_GetBaseCount(table, base, count);
  421. if (idx < count)
  422. {
  423. new
  424. addr,
  425. pos = idx * 8 + base + 4;
  426. do
  427. {
  428. // Get the address of the string.
  429. #emit LREF.S.pri pos
  430. #emit STOR.S.pri addr
  431. // Get the 4 bytes 5 bytes before this position.
  432. addr += AMX_BASE_ADDRESS;
  433. #emit LREF.S.pri addr
  434. #emit STOR.S.pri addr
  435. ++idx;
  436. if (addr == pattern)
  437. {
  438. buffer = pos - 4;
  439. return idx;
  440. }
  441. pos += 8;
  442. }
  443. while (idx < count);
  444. }
  445. return 0;
  446. }
  447. #define AMX_GetPublicEntrySuffix( AMX_GetEntrySuffix(AMX_TABLE_PUBLICS,
  448. #define AMX_GetNativeEntrySuffix( AMX_GetEntrySuffix(AMX_TABLE_NATIVES,
  449. #define AMX_GetLibraryEntrySuffix( AMX_GetEntrySuffix(AMX_TABLE_LIBRARIES,
  450. #define AMX_GetPubvarEntrySuffix( AMX_GetEntrySuffix(AMX_TABLE_PUBVARS,
  451. #define AMX_GetTagEntrySuffix( AMX_GetEntrySuffix(AMX_TABLE_TAGS,
  452. stock AMX_GetEntrySuffix(E_AMX_TABLE:table, idx, &buffer, pattern)
  453. {
  454. P:7("AMX_GetEntrySuffix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
  455. new
  456. base,
  457. count;
  458. AMX_GetBaseCount(table, base, count);
  459. if (idx < --count)
  460. {
  461. new
  462. addr,
  463. pos = idx * 8 + base + 12;
  464. do
  465. {
  466. // Get the address of the string.
  467. #emit LREF.S.pri pos
  468. #emit STOR.S.pri addr
  469. // Get the 4 bytes 5 bytes before this position.
  470. addr += AMX_BASE_ADDRESS - 5;
  471. #emit LREF.S.pri addr
  472. #emit STOR.S.pri addr
  473. ++idx;
  474. if (addr == pattern)
  475. {
  476. buffer = pos - 12;
  477. return idx;
  478. }
  479. pos += 8;
  480. }
  481. while (idx < count);
  482. }
  483. if (idx == count)
  484. {
  485. // Do the final one, this is more of an issue!
  486. new
  487. addr,
  488. ch,
  489. pos = idx * 8 + base + 4;
  490. // Get the address of the string.
  491. #emit LREF.S.pri pos
  492. #emit STOR.S.pri addr
  493. addr += AMX_BASE_ADDRESS;
  494. for ( ; ; )
  495. {
  496. // Find the end of the string.
  497. #emit LREF.S.pri addr
  498. #emit STOR.S.pri ch
  499. if (ch & 0x000000FF)
  500. {
  501. if (ch & 0x0000FF00)
  502. {
  503. if (ch & 0x00FF0000)
  504. {
  505. if (ch & 0xFF000000)
  506. {
  507. addr += 4;
  508. continue;
  509. }
  510. else addr -= 1;
  511. }
  512. else addr -= 2;
  513. }
  514. else addr -= 3;
  515. }
  516. else addr -= 4;
  517. break;
  518. }
  519. #emit LREF.S.pri addr
  520. #emit STOR.S.pri ch
  521. ++idx;
  522. if (ch == pattern)
  523. {
  524. buffer = pos - 4;
  525. return idx;
  526. }
  527. }
  528. return 0;
  529. }
  530. #define AMX_GetPublicName( AMX_GetName(AMX_TABLE_PUBLICS,
  531. #define AMX_GetNativeName( AMX_GetName(AMX_TABLE_NATIVES,
  532. #define AMX_GetLibraryName( AMX_GetName(AMX_TABLE_LIBRARIES,
  533. #define AMX_GetPubvarName( AMX_GetName(AMX_TABLE_PUBVARS,
  534. #define AMX_GetTagName( AMX_GetName(AMX_TABLE_TAGS,
  535. stock AMX_GetName(E_AMX_TABLE:table, idx, buffer[32], const pattern[] = "", const bool:exact = false)
  536. {
  537. P:7("AMX_GetName called: %i, %i, \"%s\", \"%s\"", _:table, idx, buffer, pattern);
  538. new
  539. base,
  540. count;
  541. AMX_GetBaseCount(table, base, count);
  542. if (idx < count)
  543. {
  544. if (pattern[0] == '\0')
  545. {
  546. new
  547. addr,
  548. pos = idx * 8 + base + 4;
  549. #emit LREF.S.pri pos
  550. #emit STOR.S.pri addr
  551. AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
  552. ++idx;
  553. //buffer = idx * 8 + base;
  554. return idx;
  555. }
  556. else
  557. {
  558. new
  559. addr,
  560. pos = idx * 8 + base + 4;
  561. do
  562. {
  563. #emit LREF.S.pri pos
  564. #emit STOR.S.pri addr
  565. AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
  566. ++idx;
  567. if (exact ? (!strcmp(buffer, pattern)) : (strfind(buffer, pattern) != -1))//if (strfind(buffer, pattern) != -1)
  568. {
  569. //buffer = idx * 8 + base;
  570. return idx;
  571. }
  572. pos += 8;
  573. }
  574. while (idx < count);
  575. }
  576. }
  577. return 0;
  578. }
  579. #define AMX_GetPublicNamePrefix( AMX_GetNamePrefix(AMX_TABLE_PUBLICS,
  580. #define AMX_GetNativeNamePrefix( AMX_GetNamePrefix(AMX_TABLE_NATIVES,
  581. #define AMX_GetLibraryNamePrefix( AMX_GetNamePrefix(AMX_TABLE_LIBRARIES,
  582. #define AMX_GetPubvarNamePrefix( AMX_GetNamePrefix(AMX_TABLE_PUBVARS,
  583. #define AMX_GetTagNamePrefix( AMX_GetNamePrefix(AMX_TABLE_TAGS,
  584. stock AMX_GetNamePrefix(E_AMX_TABLE:table, idx, buffer[32], pattern)
  585. {
  586. P:7("AMX_GetNamePrefix called: %i, %i, \"%s\", %i", _:table, idx, buffer, pattern);
  587. new
  588. base,
  589. count;
  590. AMX_GetBaseCount(table, base, count);
  591. if (idx < count)
  592. {
  593. new
  594. addr,
  595. pos = idx * 8 + base + 4;
  596. do
  597. {
  598. // Get the address of the string.
  599. #emit LREF.S.pri pos
  600. #emit STOR.S.pri addr
  601. // Get the 4 bytes 5 bytes before this position.
  602. addr += AMX_BASE_ADDRESS;
  603. #emit LREF.S.pri addr
  604. #emit STOR.S.pri addr
  605. ++idx;
  606. if (addr == pattern)
  607. {
  608. #emit LREF.S.pri pos
  609. #emit STOR.S.pri addr
  610. AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
  611. return idx;
  612. }
  613. pos += 8;
  614. }
  615. while (idx < count);
  616. }
  617. return 0;
  618. }
  619. #define AMX_GetPublicNameSuffix( AMX_GetNameSuffix(AMX_TABLE_PUBLICS,
  620. #define AMX_GetNativeNameSuffix( AMX_GetNameSuffix(AMX_TABLE_NATIVES,
  621. #define AMX_GetLibraryNameSuffix( AMX_GetNameSuffix(AMX_TABLE_LIBRARIES,
  622. #define AMX_GetPubvarNameSuffix( AMX_GetNameSuffix(AMX_TABLE_PUBVARS,
  623. #define AMX_GetTagNameSuffix( AMX_GetNameSuffix(AMX_TABLE_TAGS,
  624. stock AMX_GetNameSuffix(E_AMX_TABLE:table, idx, buffer[32], pattern)
  625. {
  626. P:7("AMX_GetNameSuffix called: %i, %i, \"%s\", %i", _:table, idx, buffer, pattern);
  627. new
  628. base,
  629. count;
  630. AMX_GetBaseCount(table, base, count);
  631. if (idx < --count)
  632. {
  633. new
  634. addr,
  635. pos = idx * 8 + base + 12;
  636. do
  637. {
  638. // Get the address of the string.
  639. #emit LREF.S.pri pos
  640. #emit STOR.S.pri addr
  641. // Get the 4 bytes 5 bytes before this position.
  642. addr += AMX_BASE_ADDRESS - 5;
  643. #emit LREF.S.pri addr
  644. #emit STOR.S.pri addr
  645. ++idx;
  646. if (addr == pattern)
  647. {
  648. //buffer = pos - 12;
  649. pos -= 8;
  650. #emit LREF.S.pri pos
  651. #emit STOR.S.pri addr
  652. //addr += AMX_BASE_ADDRESS;
  653. AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
  654. return idx;
  655. }
  656. pos += 8;
  657. }
  658. while (idx < count);
  659. }
  660. if (idx == count)
  661. {
  662. // Do the final one, this is more of an issue!
  663. new
  664. addr,
  665. ch,
  666. pos = idx * 8 + base + 4;
  667. // Get the address of the string.
  668. #emit LREF.S.pri pos
  669. #emit STOR.S.pri addr
  670. addr += AMX_BASE_ADDRESS;
  671. for ( ; ; )
  672. {
  673. // Find the end of the string.
  674. #emit LREF.S.pri addr
  675. #emit STOR.S.pri ch
  676. if (ch & 0x000000FF)
  677. {
  678. if (ch & 0x0000FF00)
  679. {
  680. if (ch & 0x00FF0000)
  681. {
  682. if (ch & 0xFF000000)
  683. {
  684. addr += 4;
  685. continue;
  686. }
  687. else addr -= 1;
  688. }
  689. else addr -= 2;
  690. }
  691. else addr -= 3;
  692. }
  693. else addr -= 4;
  694. break;
  695. }
  696. #emit LREF.S.pri addr
  697. #emit STOR.S.pri ch
  698. ++idx;
  699. if (ch == pattern)
  700. {
  701. #emit LREF.S.pri pos
  702. #emit STOR.S.pri addr
  703. AMX_ReadString(AMX_BASE_ADDRESS + addr, buffer);
  704. return idx;
  705. }
  706. }
  707. return 0;
  708. }
  709. #define AMX_GetPublicPointer( AMX_GetPointer(AMX_TABLE_PUBLICS,
  710. #define AMX_GetNativePointer( AMX_GetPointer(AMX_TABLE_NATIVES,
  711. #define AMX_GetLibraryPointer( AMX_GetPointer(AMX_TABLE_LIBRARIES,
  712. #define AMX_GetPubvarPointer( AMX_GetPointer(AMX_TABLE_PUBVARS,
  713. #define AMX_GetTagPointer( AMX_GetPointer(AMX_TABLE_TAGS,
  714. stock AMX_GetPointer(E_AMX_TABLE:table, idx, &buffer, const pattern[] = "", const bool:exact = false)
  715. {
  716. P:7("AMX_GetPointer called: %i, %i, %i, \"%s\", %i", _:table, idx, buffer, pattern, exact);
  717. new
  718. pointer;
  719. idx = AMX_GetEntry(table, idx, pointer, pattern, exact);
  720. if (idx)
  721. {
  722. #emit LREF.S.pri pointer
  723. #emit SREF.S.pri buffer
  724. }
  725. return idx;
  726. }
  727. #define AMX_GetPublicPointerPrefix( AMX_GetPointerPrefix(AMX_TABLE_PUBLICS,
  728. #define AMX_GetNativePointerPrefix( AMX_GetPointerPrefix(AMX_TABLE_NATIVES,
  729. #define AMX_GetLibraryPointerPrefix( AMX_GetPointerPrefix(AMX_TABLE_LIBRARIES,
  730. #define AMX_GetPubvarPointerPrefix( AMX_GetPointerPrefix(AMX_TABLE_PUBVARS,
  731. #define AMX_GetTagPointerPrefix( AMX_GetPointerPrefix(AMX_TABLE_TAGS,
  732. stock AMX_GetPointerPrefix(E_AMX_TABLE:table, idx, &buffer, pattern)
  733. {
  734. P:7("AMX_GetPointerPrefix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
  735. new
  736. pointer;
  737. idx = AMX_GetEntryPrefix(table, idx, pointer, pattern);
  738. if (idx)
  739. {
  740. #emit LREF.S.pri pointer
  741. #emit SREF.S.pri buffer
  742. }
  743. return idx;
  744. }
  745. #define AMX_GetPublicPointerSuffix( AMX_GetPointerSuffix(AMX_TABLE_PUBLICS,
  746. #define AMX_GetNativePointerSuffix( AMX_GetPointerSuffix(AMX_TABLE_NATIVES,
  747. #define AMX_GetLibraryPointerSuffix( AMX_GetPointerSuffix(AMX_TABLE_LIBRARIES,
  748. #define AMX_GetPubvarPointerSuffix( AMX_GetPointerSuffix(AMX_TABLE_PUBVARS,
  749. #define AMX_GetTagPointerSuffix( AMX_GetPointerSuffix(AMX_TABLE_TAGS,
  750. stock AMX_GetPointerSuffix(E_AMX_TABLE:table, idx, &buffer, pattern)
  751. {
  752. P:7("AMX_GetPointerSuffix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
  753. new
  754. pointer;
  755. idx = AMX_GetEntrySuffix(table, idx, pointer, pattern);
  756. if (idx)
  757. {
  758. #emit LREF.S.pri pointer
  759. #emit SREF.S.pri buffer
  760. }
  761. return idx;
  762. }
  763. #define AMX_GetPublicValue( AMX_GetValue(AMX_TABLE_PUBLICS,
  764. #define AMX_GetNativeValue( AMX_GetValue(AMX_TABLE_NATIVES,
  765. #define AMX_GetLibraryValue( AMX_GetValue(AMX_TABLE_LIBRARIES,
  766. #define AMX_GetPubvarValue( AMX_GetValue(AMX_TABLE_PUBVARS,
  767. #define AMX_GetTagValue( AMX_GetValue(AMX_TABLE_TAGS,
  768. stock AMX_GetValue(E_AMX_TABLE:table, idx, &buffer, const pattern[] = "", const bool:exact = false)
  769. {
  770. P:7("AMX_GetValue called: %i, %i, %i, \"%s\", %i", _:table, idx, buffer, pattern, exact);
  771. new
  772. pointer;
  773. idx = AMX_GetPointer(table, idx, pointer, pattern, exact);
  774. if (idx)
  775. {
  776. #emit LREF.S.pri pointer
  777. #emit SREF.S.pri buffer
  778. }
  779. return idx;
  780. }
  781. #define AMX_GetPublicValuePrefix( AMX_GetValuePrefix(AMX_TABLE_PUBLICS,
  782. #define AMX_GetNativeValuePrefix( AMX_GetValuePrefix(AMX_TABLE_NATIVES,
  783. #define AMX_GetLibraryValuePrefix( AMX_GetValuePrefix(AMX_TABLE_LIBRARIES,
  784. #define AMX_GetPubvarValuePrefix( AMX_GetValuePrefix(AMX_TABLE_PUBVARS,
  785. #define AMX_GetTagValuePrefix( AMX_GetValuePrefix(AMX_TABLE_TAGS,
  786. stock AMX_GetValuePrefix(E_AMX_TABLE:table, idx, &buffer, pattern)
  787. {
  788. P:7("AMX_GetValuePrefix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
  789. new
  790. pointer;
  791. idx = AMX_GetPointerPrefix(table, idx, pointer, pattern);
  792. if (idx)
  793. {
  794. #emit LREF.S.pri pointer
  795. #emit SREF.S.pri buffer
  796. }
  797. return idx;
  798. }
  799. #define AMX_GetPublicValueSuffix( AMX_GetValueSuffix(AMX_TABLE_PUBLICS,
  800. #define AMX_GetNativeValueSuffix( AMX_GetValueSuffix(AMX_TABLE_NATIVES,
  801. #define AMX_GetLibraryValueSuffix( AMX_GetValueSuffix(AMX_TABLE_LIBRARIES,
  802. #define AMX_GetPubvarValueSuffix( AMX_GetValueSuffix(AMX_TABLE_PUBVARS,
  803. #define AMX_GetTagValueSuffix( AMX_GetValueSuffix(AMX_TABLE_TAGS,
  804. stock AMX_GetValueSuffix(E_AMX_TABLE:table, idx, &buffer, pattern)
  805. {
  806. P:7("AMX_GetValueSuffix called: %i, %i, %i, %i", _:table, idx, buffer, pattern);
  807. new
  808. pointer;
  809. idx = AMX_GetPointerSuffix(table, idx, pointer, pattern);
  810. if (idx)
  811. {
  812. #emit LREF.S.pri pointer
  813. #emit SREF.S.pri buffer
  814. }
  815. return idx;
  816. }
  817. /*enum e_AMX_HEADER_TYPE (<<= 1)
  818. {
  819. e_AMX_HEADER_TYPE_NONE = 0,
  820. e_AMX_HEADER_TYPE_PUBLIC = 1,
  821. e_AMX_HEADER_TYPE_NATIVE,
  822. e_AMX_HEADER_TYPE_LIBRARY,
  823. e_AMX_HEADER_TYPE_PUBVAR,
  824. e_AMX_HEADER_TYPE_TAG
  825. }
  826. enum E_AMX_HEADER
  827. {
  828. e_AMX_HEADER_TYPE:E_AMX_HEADER_TYPE, // Public, native, tag, etc.
  829. E_AMX_HEADER_ENTRY,
  830. E_AMX_HEADER_PTR,
  831. // For variables, this is their value. For publics and natives, this is
  832. // their table index (used by "funcidx" and "SYSREQ.C" respectively).
  833. E_AMX_HEADER_VALUE,
  834. E_AMX_HEADER_NAME[32 char]
  835. }
  836. stock AMX_GetEntryData(entry, ret[E_AMX_HEADER])
  837. {
  838. if ((ret[e_AMX_HEADER_TYPE] = AMX_GetEntryType(entry)))
  839. {
  840. }
  841. }*/
  842. stock AMX_GetEntryPointer(entry)
  843. {
  844. #emit LREF.S.pri entry
  845. #emit RETN
  846. return 0; // Make the compiler happy.
  847. }
  848. /*stock bool:AMX_GetData(const name[], ret[E_AMX_HEADER], e_AMX_HEADER_TYPE:type = e_AMX_HEADER_TYPE_NONE)
  849. {
  850. new
  851. entry;
  852. switch (type)
  853. {
  854. case e_AMX_HEADER_TYPE_NONE :
  855. {
  856. if (AMX_GetEntry(AMX_TABLE_PUBLICS, 0, entry, name)) type |= e_AMX_HEADER_TYPE_PUBLIC ;
  857. if (AMX_GetEntry(AMX_TABLE_NATIVES, 0, entry, name)) type |= e_AMX_HEADER_TYPE_NATIVE ;
  858. if (AMX_GetEntry(AMX_TABLE_LIBRARIES, 0, entry, name)) type |= e_AMX_HEADER_TYPE_LIBRARY;
  859. if (AMX_GetEntry(AMX_TABLE_PUBVARS, 0, entry, name)) type |= e_AMX_HEADER_TYPE_PUBVAR ;
  860. if (AMX_GetEntry(AMX_TABLE_TAGS, 0, entry, name)) type |= e_AMX_HEADER_TYPE_TAG ;
  861. }
  862. case e_AMX_HEADER_TYPE_PUBLIC : AMX_GetEntry(AMX_TABLE_PUBLICS, 0, entry, name);
  863. case e_AMX_HEADER_TYPE_NATIVE : AMX_GetEntry(AMX_TABLE_NATIVES, 0, entry, name);
  864. case e_AMX_HEADER_TYPE_LIBRARY: AMX_GetEntry(AMX_TABLE_LIBRARIES, 0, entry, name);
  865. case e_AMX_HEADER_TYPE_PUBVAR : AMX_GetEntry(AMX_TABLE_PUBVARS, 0, entry, name);
  866. case e_AMX_HEADER_TYPE_TAG : AMX_GetEntry(AMX_TABLE_TAGS, 0, entry, name);
  867. }
  868. strpack(ret[E_AMX_HEADER_NAME], name),
  869. ret[E_AMX_HEADER_TYPE] = type;
  870. new
  871. ptr;
  872. #emit LREF.S.pri entry
  873. #emit SREF.S.pri ptr
  874. switch (type)
  875. {
  876. case e_AMX_HEADER_TYPE_PUBLIC :
  877. {
  878. // Has a pointer.
  879. return
  880. ret[E_AMX_HEADER_ENTRY] = entry,
  881. ret[E_AMX_HEADER_PTR] = ptr,
  882. ret[E_AMX_HEADER_VALUE] = AMX_GetPublicIndexFromEntry(entry);
  883. }
  884. case e_AMX_HEADER_TYPE_NATIVE :
  885. {
  886. // Has a pointer.
  887. return
  888. ret[E_AMX_HEADER_ENTRY] = entry,
  889. ret[E_AMX_HEADER_PTR] = ptr,
  890. ret[E_AMX_HEADER_VALUE] = AMX_GetNativeIndexFromEntry(entry);
  891. }
  892. case e_AMX_HEADER_TYPE_LIBRARY:
  893. {
  894. }
  895. case e_AMX_HEADER_TYPE_PUBVAR :
  896. {
  897. }
  898. case e_AMX_HEADER_TYPE_TAG :
  899. {
  900. }
  901. }
  902. // Multiple matches found, or none.
  903. return
  904. ret[E_AMX_HEADER_INDEX] = -1,
  905. ret[E_AMX_HEADER_PTR] = 0,
  906. ret[E_AMX_HEADER_VALUE] = cellmin;
  907. }*/
  908. stock AMX_GetEntryFromNativeIndex(index)
  909. {
  910. return (index * 8) + AMX_HEADER_NATIVES;
  911. }
  912. stock AMX_GetEntryFromPublicIndex(index)
  913. {
  914. // An index is an offset in to their own table.
  915. return (index * 8) + AMX_HEADER_PUBLICS;
  916. }
  917. stock AMX_GetNativeIndexFromEntry(entry)
  918. {
  919. return (entry - AMX_HEADER_NATIVES) / 8;
  920. }
  921. stock AMX_GetPublicIndexFromEntry(entry)
  922. {
  923. return (entry - AMX_HEADER_PUBLICS) / 8;
  924. }
  925. /*stock AMX_GetEntryType(entry)
  926. {
  927. if (AMX_HEADER_PUBLICS <= entry < AMX_HEADER_NATIVES) return e_AMX_HEADER_TYPE_PUBLIC;
  928. else if (AMX_HEADER_NATIVES <= entry < AMX_HEADER_LIBRARIES) return e_AMX_HEADER_TYPE_NATIVE;
  929. else if (AMX_HEADER_LIBRARIES <= entry < AMX_HEADER_PUBVARS) return e_AMX_HEADER_TYPE_LIBRARY;
  930. else if (AMX_HEADER_PUBVARS <= entry < AMX_HEADER_TAGS) return e_AMX_HEADER_TYPE_PUBVAR;
  931. else if (AMX_HEADER_TAGS <= entry < AMX_HEADER_NAMETABLE) return e_AMX_HEADER_TYPE_TAG;
  932. return e_AMX_HEADER_TYPE_NONE;
  933. }
  934. stock e_AMX_HEADER_TYPE:AMX_GetType(const name[])
  935. {
  936. new
  937. e_AMX_HEADER_TYPE:type = e_AMX_HEADER_TYPE_NONE,
  938. entry;
  939. if (AMX_GetEntry(AMX_TABLE_PUBLICS, 0, entry, name)) type |= e_AMX_HEADER_TYPE_PUBLIC ;
  940. if (AMX_GetEntry(AMX_TABLE_NATIVES, 0, entry, name)) type |= e_AMX_HEADER_TYPE_NATIVE ;
  941. if (AMX_GetEntry(AMX_TABLE_LIBRARIES, 0, entry, name)) type |= e_AMX_HEADER_TYPE_LIBRARY;
  942. if (AMX_GetEntry(AMX_TABLE_PUBVARS, 0, entry, name)) type |= e_AMX_HEADER_TYPE_PUBVAR ;
  943. if (AMX_GetEntry(AMX_TABLE_TAGS, 0, entry, name)) type |= e_AMX_HEADER_TYPE_TAG ;
  944. return type;
  945. }*/
  946. stock AMX_ReadString(addr, str[], len = sizeof (str))
  947. {
  948. new
  949. buffer,
  950. idx;
  951. do
  952. {
  953. // Read 4 bytes.
  954. #emit LREF.S.pri addr
  955. #emit STOR.S.pri buffer
  956. // Write PACKED strings.
  957. buffer = (buffer >>> 24) | (buffer >> 8 & 0x0000FF00) | (buffer << 8 & 0x00FF0000) | (buffer << 24);
  958. str[idx] = buffer;
  959. if (!(buffer & 0x000000FF && buffer & 0x0000FF00 && buffer & 0x00FF0000 && buffer & 0xFF000000))
  960. {
  961. return;
  962. }
  963. addr += 4;
  964. }
  965. while (++idx < len);
  966. }
  967. stock AMX_ReadUnpackedString(addr, str[], len = sizeof (str))
  968. {
  969. new
  970. buffer = 1;
  971. while (buffer && len--);
  972. {
  973. // Read 4 bytes.
  974. #emit LREF.S.pri addr
  975. #emit STOR.S.pri buffer
  976. #emit SREF.S.pri str
  977. #emit LOAD.S.pri str
  978. #emit ADD.C 4
  979. #emit STOR.S.pri str
  980. addr += 4;
  981. }
  982. }
  983. stock AMX_WriteString(addr, const str[], len = sizeof (str))
  984. {
  985. new
  986. old,
  987. buffer,
  988. idx;
  989. do
  990. {
  991. buffer = str[idx];
  992. P:7("AMX_WriteString: Writing %04x%04x", buffer >>> 16, buffer & 0xFFFF);
  993. if (!(buffer & 0xFF000000))
  994. {
  995. #emit LREF.S.pri addr
  996. #emit CONST.alt 0xFFFFFF00
  997. #emit AND
  998. #emit SREF.S.pri addr
  999. return;
  1000. }
  1001. else if (!(buffer & 0x00FF0000))
  1002. {
  1003. // This:
  1004. // '\0', '1'.
  1005. // Becomes:
  1006. // '1', '\0', ???, ???.
  1007. #emit LREF.S.pri addr
  1008. #emit STOR.S.pri old
  1009. buffer = (old & 0xFFFF0000) | (buffer >>> 24);
  1010. #emit LOAD.S.pri buffer
  1011. #emit SREF.S.pri addr
  1012. return;
  1013. }
  1014. else if (!(buffer & 0x0000FF00))
  1015. {
  1016. // This:
  1017. // '\0', '2', '1'.
  1018. // Becomes:
  1019. // '1', '2', '\0', ???.
  1020. #emit LREF.S.pri addr
  1021. #emit STOR.S.pri old
  1022. buffer = (old & 0xFF000000) | (buffer >>> 24) | (buffer >> 8 & 0x0000FF00);
  1023. #emit LOAD.S.pri buffer
  1024. #emit SREF.S.pri addr
  1025. return;
  1026. }
  1027. else if (!(buffer & 0x000000FF))
  1028. {
  1029. // This:
  1030. // '\0', '3', '2', '1'.
  1031. // Becomes:
  1032. // '1', '2', '3', '\0'.
  1033. // Write 3 bytes.
  1034. buffer = (buffer >>> 24) | (buffer >> 8 & 0x0000FF00) | (buffer << 8 & 0x00FF0000);
  1035. #emit LOAD.S.pri buffer
  1036. #emit SREF.S.pri addr
  1037. return;
  1038. }
  1039. else
  1040. {
  1041. // Write 4 bytes.
  1042. buffer = (buffer >>> 24) | (buffer >> 8 & 0x0000FF00) | (buffer << 8 & 0x00FF0000) | (buffer << 24);
  1043. #emit LOAD.S.pri buffer
  1044. #emit SREF.S.pri addr
  1045. addr += 4;
  1046. }
  1047. }
  1048. while (++idx < len);
  1049. }
  1050. stock AMX_Read(addr)
  1051. {
  1052. // This is now, AFAIK, the first ever self-inlining function!
  1053. static
  1054. sFrame;
  1055. // Get the current stack pointer.
  1056. #emit LCTRL 4
  1057. #emit ADD.C 12
  1058. // Get the previous frame pointer.
  1059. #emit LOAD.S.alt 0
  1060. #emit SUB
  1061. #emit STOR.pri sFrame
  1062. P:7("AMX_Read called: %i %d", addr, sFrame);
  1063. new
  1064. start = GetCurrentFrameReturn() - 16,
  1065. ctx2[DisasmContext];
  1066. DisasmInit(ctx2, start, start + 16);
  1067. if (!DisasmDecodeInsn(ctx2) || DisasmGetOpcode(ctx2) != OP_PUSH_C || DisasmGetOperand(ctx2) != 4)
  1068. {
  1069. P:W("Couldn't rewrite \"AMX_Read\" call");
  1070. return AMX_RawRead(addr);
  1071. }
  1072. new
  1073. ctx[AsmContext];
  1074. AsmInitPtr(ctx, start + AMX_HEADER_COD, 16);
  1075. // This is the actual code. The standard function call puts the variable to
  1076. // read from on to the stack, so use that as a frame offset and call "LREF"
  1077. // on that stack value. Then remove it from the stack and skip the next
  1078. // cell - since we are replacing 4 cells with just 3.
  1079. @emit LREF.S.pri sFrame
  1080. @emit POP.alt
  1081. @emit NOP
  1082. return AMX_RawRead(addr);
  1083. }
  1084. stock AMX_Write(addr, value)
  1085. {
  1086. P:7("AMX_Write called: %i, %i", addr, value);
  1087. #emit LOAD.S.pri value
  1088. #emit SREF.S.pri addr
  1089. }
  1090. stock AMX_RawRead(addr)
  1091. {
  1092. P:7("AMX_RawRead called: %i", addr);
  1093. #emit LREF.S.pri addr
  1094. #emit RETN
  1095. return 0;
  1096. }
  1097. stock AMX_RawWrite(addr, value)
  1098. {
  1099. P:7("AMX_RawWrite called: %i, %i", addr, value);
  1100. #emit LOAD.S.pri value
  1101. #emit SREF.S.pri addr
  1102. }
  1103. stock AMX_ReadArray(addr, dest[], len = sizeof (dest))
  1104. {
  1105. // I tried to use memcpy, I couldn't get it to work, even when exactly
  1106. // replicating compiler generated code...
  1107. while (len--)
  1108. {
  1109. // Load the address possibly outside "dat". Can't be done using only
  1110. // "pri"/"alt" as it relies on "LREF.S" explicitly.
  1111. #emit LREF.S.pri addr
  1112. #emit SREF.S.pri dest
  1113. #emit LOAD.S.pri addr
  1114. #emit ADD.C 4
  1115. #emit STOR.S.pri addr
  1116. #emit LOAD.S.pri dest
  1117. #emit ADD.C 4
  1118. #emit STOR.S.pri dest
  1119. }
  1120. }
  1121. stock AMX_WriteArray(addr, const src[], len = sizeof (src))
  1122. {
  1123. while (len--)
  1124. {
  1125. #emit DEC.pri
  1126. // Read the data.
  1127. #emit LREF.S.pri dest
  1128. #emit SREF.S.pri addr
  1129. #emit LOAD.S.pri addr
  1130. #emit ADD.C 4
  1131. #emit STOR.S.pri addr
  1132. #emit LOAD.S.pri dest
  1133. #emit ADD.C 4
  1134. #emit STOR.S.pri dest
  1135. }
  1136. }
  1137. stock AMX_CodToDat(ptr)
  1138. {
  1139. // Convert a pointer in to the code segment in to a data offset.
  1140. return ptr + AMX_HEADER_COD;
  1141. }
  1142. #define _A<%0> (_:H_Re(%0,0))
  1143. // Do the next character test as this one failed.
  1144. #define H_Se(%0,%1,%3) H_Ne%1(%0,%3)
  1145. // End of string test failed.
  1146. #define H_Ee(%0,%3) @E_:H_Se(%0,_,%3)
  1147. // Do the single addition.
  1148. #define H_De(%0,%1,%3) (_:H_Re(%0,%3+8))|%1<<%3
  1149. // Recurse through the string.
  1150. #define H_Re(%0,%3) he:H_Ee(%0,%3)
  1151. // Test for the end of a string (4 characters only).
  1152. #define he:H_Ee(%0,0+8+8+8+8) 0
  1153. // Test for the current character.
  1154. #define @E_:H_Se(_%0,%1,%3) H_De(%0,95,%3)
  1155. #define @E@:H_Se(@%0,%1,%3) H_De(%0,64,%3)
  1156. #define @Ey:H_Se(y%0,%1,%3) H_De(%0,121,%3)
  1157. #define @Ea:H_Se(a%0,%1,%3) H_De(%0,97,%3)
  1158. #define @Eb:H_Se(b%0,%1,%3) H_De(%0,98,%3)
  1159. #define @Ec:H_Se(c%0,%1,%3) H_De(%0,99,%3)
  1160. #define @Ed:H_Se(d%0,%1,%3) H_De(%0,100,%3)
  1161. #define @Ee:H_Se(e%0,%1,%3) H_De(%0,101,%3)
  1162. #define @Ef:H_Se(f%0,%1,%3) H_De(%0,102,%3)
  1163. #define @Eg:H_Se(g%0,%1,%3) H_De(%0,103,%3)
  1164. #define @Eh:H_Se(h%0,%1,%3) H_De(%0,104,%3)
  1165. #define @Ei:H_Se(i%0,%1,%3) H_De(%0,105,%3)
  1166. #define @Ej:H_Se(j%0,%1,%3) H_De(%0,106,%3)
  1167. #define @Ek:H_Se(k%0,%1,%3) H_De(%0,107,%3)
  1168. #define @El:H_Se(l%0,%1,%3) H_De(%0,108,%3)
  1169. #define @Em:H_Se(m%0,%1,%3) H_De(%0,109,%3)
  1170. #define @En:H_Se(n%0,%1,%3) H_De(%0,110,%3)
  1171. #define @Eo:H_Se(o%0,%1,%3) H_De(%0,111,%3)
  1172. #define @Ep:H_Se(p%0,%1,%3) H_De(%0,112,%3)
  1173. #define @Eq:H_Se(q%0,%1,%3) H_De(%0,113,%3)
  1174. #define @Er:H_Se(r%0,%1,%3) H_De(%0,114,%3)
  1175. #define @Es:H_Se(s%0,%1,%3) H_De(%0,115,%3)
  1176. #define @Et:H_Se(t%0,%1,%3) H_De(%0,116,%3)
  1177. #define @Eu:H_Se(u%0,%1,%3) H_De(%0,117,%3)
  1178. #define @Ev:H_Se(v%0,%1,%3) H_De(%0,118,%3)
  1179. #define @Ew:H_Se(w%0,%1,%3) H_De(%0,119,%3)
  1180. #define @Ex:H_Se(x%0,%1,%3) H_De(%0,120,%3)
  1181. #define @Ez:H_Se(z%0,%1,%3) H_De(%0,122,%3)
  1182. #define @EA:H_Se(A%0,%1,%3) H_De(%0,65,%3)
  1183. #define @EB:H_Se(B%0,%1,%3) H_De(%0,66,%3)
  1184. #define @EC:H_Se(C%0,%1,%3) H_De(%0,67,%3)
  1185. #define @ED:H_Se(D%0,%1,%3) H_De(%0,68,%3)
  1186. #define @EE:H_Se(E%0,%1,%3) H_De(%0,69,%3)
  1187. #define @EF:H_Se(F%0,%1,%3) H_De(%0,70,%3)
  1188. #define @EG:H_Se(G%0,%1,%3) H_De(%0,71,%3)
  1189. #define @EH:H_Se(H%0,%1,%3) H_De(%0,72,%3)
  1190. #define @EI:H_Se(I%0,%1,%3) H_De(%0,73,%3)
  1191. #define @EJ:H_Se(J%0,%1,%3) H_De(%0,74,%3)
  1192. #define @EK:H_Se(K%0,%1,%3) H_De(%0,75,%3)
  1193. #define @EL:H_Se(L%0,%1,%3) H_De(%0,76,%3)
  1194. #define @EM:H_Se(M%0,%1,%3) H_De(%0,77,%3)
  1195. #define @EN:H_Se(N%0,%1,%3) H_De(%0,78,%3)
  1196. #define @EO:H_Se(O%0,%1,%3) H_De(%0,79,%3)
  1197. #define @EP:H_Se(P%0,%1,%3) H_De(%0,80,%3)
  1198. #define @EQ:H_Se(Q%0,%1,%3) H_De(%0,81,%3)
  1199. #define @ER:H_Se(R%0,%1,%3) H_De(%0,82,%3)
  1200. #define @ES:H_Se(S%0,%1,%3) H_De(%0,83,%3)
  1201. #define @ET:H_Se(T%0,%1,%3) H_De(%0,84,%3)
  1202. #define @EU:H_Se(U%0,%1,%3) H_De(%0,85,%3)
  1203. #define @EV:H_Se(V%0,%1,%3) H_De(%0,86,%3)
  1204. #define @EW:H_Se(W%0,%1,%3) H_De(%0,87,%3)
  1205. #define @EX:H_Se(X%0,%1,%3) H_De(%0,88,%3)
  1206. #define @EY:H_Se(Y%0,%1,%3) H_De(%0,89,%3)
  1207. #define @EZ:H_Se(Z%0,%1,%3) H_De(%0,90,%3)
  1208. #define @E0:H_Se(0%0,%1,%3) H_De(%0,48,%3)
  1209. #define @E1:H_Se(1%0,%1,%3) H_De(%0,49,%3)
  1210. #define @E2:H_Se(2%0,%1,%3) H_De(%0,50,%3)
  1211. #define @E3:H_Se(3%0,%1,%3) H_De(%0,51,%3)
  1212. #define @E4:H_Se(4%0,%1,%3) H_De(%0,52,%3)
  1213. #define @E5:H_Se(5%0,%1,%3) H_De(%0,53,%3)
  1214. #define @E6:H_Se(6%0,%1,%3) H_De(%0,54,%3)
  1215. #define @E7:H_Se(7%0,%1,%3) H_De(%0,55,%3)
  1216. #define @E8:H_Se(8%0,%1,%3) H_De(%0,56,%3)
  1217. #define @E9:H_Se(9%0,%1,%3) H_De(%0,57,%3)
  1218. // Find the next character to test.
  1219. #define H_Ne_(%0,%3) @E@:H_Se(%0,@,%3)
  1220. #define H_Ne@(%0,%3) @Ey:H_Se(%0,y,%3)
  1221. #define H_Ney(%0,%3) @Ea:H_Se(%0,a,%3)
  1222. #define H_Nea(%0,%3) @Eb:H_Se(%0,b,%3)
  1223. #define H_Neb(%0,%3) @Ec:H_Se(%0,c,%3)
  1224. #define H_Nec(%0,%3) @Ed:H_Se(%0,d,%3)
  1225. #define H_Ned(%0,%3) @Ee:H_Se(%0,e,%3)
  1226. #define H_Nee(%0,%3) @Ef:H_Se(%0,f,%3)
  1227. #define H_Nef(%0,%3) @Eg:H_Se(%0,g,%3)
  1228. #define H_Neg(%0,%3) @Eh:H_Se(%0,h,%3)
  1229. #define H_Neh(%0,%3) @Ei:H_Se(%0,i,%3)
  1230. #define H_Nei(%0,%3) @Ej:H_Se(%0,j,%3)
  1231. #define H_Nej(%0,%3) @Ek:H_Se(%0,k,%3)
  1232. #define H_Nek(%0,%3) @El:H_Se(%0,l,%3)
  1233. #define H_Nel(%0,%3) @Em:H_Se(%0,m,%3)
  1234. #define H_Nem(%0,%3) @En:H_Se(%0,n,%3)
  1235. #define H_Nen(%0,%3) @Eo:H_Se(%0,o,%3)
  1236. #define H_Neo(%0,%3) @Ep:H_Se(%0,p,%3)
  1237. #define H_Nep(%0,%3) @Eq:H_Se(%0,q,%3)
  1238. #define H_Neq(%0,%3) @Er:H_Se(%0,r,%3)
  1239. #define H_Ner(%0,%3) @Es:H_Se(%0,s,%3)
  1240. #define H_Nes(%0,%3) @Et:H_Se(%0,t,%3)
  1241. #define H_Net(%0,%3) @Eu:H_Se(%0,u,%3)
  1242. #define H_Neu(%0,%3) @Ev:H_Se(%0,v,%3)
  1243. #define H_Nev(%0,%3) @Ew:H_Se(%0,w,%3)
  1244. #define H_New(%0,%3) @Ex:H_Se(%0,x,%3)
  1245. #define H_Nex(%0,%3) @Ez:H_Se(%0,z,%3)
  1246. #define H_Nez(%0,%3) @EA:H_Se(%0,A,%3)
  1247. #define H_NeA(%0,%3) @EB:H_Se(%0,B,%3)
  1248. #define H_NeB(%0,%3) @EC:H_Se(%0,C,%3)
  1249. #define H_NeC(%0,%3) @ED:H_Se(%0,D,%3)
  1250. #define H_NeD(%0,%3) @EE:H_Se(%0,E,%3)
  1251. #define H_NeE(%0,%3) @EF:H_Se(%0,F,%3)
  1252. #define H_NeF(%0,%3) @EG:H_Se(%0,G,%3)
  1253. #define H_NeG(%0,%3) @EH:H_Se(%0,H,%3)
  1254. #define H_NeH(%0,%3) @EI:H_Se(%0,I,%3)
  1255. #define H_NeI(%0,%3) @EJ:H_Se(%0,J,%3)
  1256. #define H_NeJ(%0,%3) @EK:H_Se(%0,K,%3)
  1257. #define H_NeK(%0,%3) @EL:H_Se(%0,L,%3)
  1258. #define H_NeL(%0,%3) @EM:H_Se(%0,M,%3)
  1259. #define H_NeM(%0,%3) @EN:H_Se(%0,N,%3)
  1260. #define H_NeN(%0,%3) @EO:H_Se(%0,O,%3)
  1261. #define H_NeO(%0,%3) @EP:H_Se(%0,P,%3)
  1262. #define H_NeP(%0,%3) @EQ:H_Se(%0,Q,%3)
  1263. #define H_NeQ(%0,%3) @ER:H_Se(%0,R,%3)
  1264. #define H_NeR(%0,%3) @ES:H_Se(%0,S,%3)
  1265. #define H_NeS(%0,%3) @ET:H_Se(%0,T,%3)
  1266. #define H_NeT(%0,%3) @EU:H_Se(%0,U,%3)
  1267. #define H_NeU(%0,%3) @EV:H_Se(%0,V,%3)
  1268. #define H_NeV(%0,%3) @EW:H_Se(%0,W,%3)
  1269. #define H_NeW(%0,%3) @EX:H_Se(%0,X,%3)
  1270. #define H_NeX(%0,%3) @EY:H_Se(%0,Y,%3)
  1271. #define H_NeY(%0,%3) @EZ:H_Se(%0,Z,%3)
  1272. #define H_NeZ(%0,%3) @E0:H_Se(%0,0,%3)
  1273. #define H_Ne0(%0,%3) @E1:H_Se(%0,1,%3)
  1274. #define H_Ne1(%0,%3) @E2:H_Se(%0,2,%3)
  1275. #define H_Ne2(%0,%3) @E3:H_Se(%0,3,%3)
  1276. #define H_Ne3(%0,%3) @E4:H_Se(%0,4,%3)
  1277. #define H_Ne4(%0,%3) @E5:H_Se(%0,5,%3)
  1278. #define H_Ne5(%0,%3) @E6:H_Se(%0,6,%3)
  1279. #define H_Ne6(%0,%3) @E7:H_Se(%0,7,%3)
  1280. #define H_Ne7(%0,%3) @E8:H_Se(%0,8,%3)
  1281. #define H_Ne8(%0,%3) @E9:H_Se(%0,9,%3)
  1282. #define H_Ne9(%0,%3) ()