y_amx.inc 32 KB

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