y_amx.inc 37 KB

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