y_amx.inc 41 KB

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