Y_Less

ALS2

Jun 30th, 2012
235
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 13.06 KB | None | 0 0
  1. // Hooks version three.  This code HIGHLY optimises for return calls, and
  2. // slightly optimises for other calls.  Fake function calls are inserted in to
  3. // the code to pad out space, then replaced at run-time.
  4.  
  5. #if !defined ALS_PREFIX
  6.     #define ALS_PREFIX
  7. #endif
  8.  
  9. #if defined ALS_CALL
  10.     #undef ALS_CALL
  11. #endif
  12.  
  13. #if defined ALS_GET
  14.     #undef ALS_GET
  15. #endif
  16.  
  17. #define string:
  18.  
  19. #define ALS_CALL<%0> return _:_ALS_WITH_ON:_ALS_NO_ON:_ALS_NO_P:ALS_Chain(%0)
  20.  
  21. #define ALS_GET<%0> _:_ALS_WITH_ON:_ALS_NO_ON:ALS_Call(%0)
  22.  
  23. #define _ALS_WITH_ON:_ALS_NO_ON:%3(%0_On%1) _ALS_P_%1(%3)(#%0"_On"#%1, _ALS_R_%1)
  24. #define _ALS_NO_ON:%3(%0_%1) _ALS_P_%1(%3)(#%0"_On"#%1, _ALS_R_%1)
  25.  
  26. #define _ALS_NO_P:%3ALS_%0_%1( %3ALS_%0(
  27.  
  28. //#define _ALS_CALL ALS_Call
  29. //#define _ALS_CHAIN _ALS_ONLY_2:ALS_Chain
  30.  
  31. //#define _ALS_ONLY_2:ALS_Chain(%0,%1,%2) ALS_Chain(%0,%1)
  32.  
  33. // Define the default return values for every callback.
  34. #define _ALS_R_GameModeInit 1
  35. #define _ALS_R_GameModeExit 1
  36. #define _ALS_R_FilterScriptInit 1
  37. #define _ALS_R_FilterScriptExit 1
  38. #define _ALS_R_PlayerConnect 1
  39. #define _ALS_R_PlayerDisconnect 1
  40. #define _ALS_R_PlayerSpawn 1
  41. #define _ALS_R_PlayerDeath 1
  42. #define _ALS_R_VehicleSpawn 1
  43. #define _ALS_R_VehicleDeath 1
  44. #define _ALS_R_PlayerText 1
  45. #define _ALS_R_PlayerCommandText 0
  46. #define _ALS_R_PlayerRequestClass 1
  47. #define _ALS_R_PlayerEnterVehicle 1
  48. #define _ALS_R_PlayerExitVehicle 1
  49. #define _ALS_R_PlayerStateChange 1
  50. #define _ALS_R_PlayerEnterCheckpoint 1
  51. #define _ALS_R_PlayerLeaveCheckpoint 1
  52. #define _ALS_R_PlayerEnterRaceCP 1
  53. #define _ALS_R_PlayerLeaveRaceCP 1
  54. #define _ALS_R_RconCommand 1
  55. #define _ALS_R_PlayerRequestSpawn 1
  56. #define _ALS_R_ObjectMoved 1
  57. #define _ALS_R_PlayerObjectMoved 1
  58. #define _ALS_R_PlayerPickUpPickup 1
  59. #define _ALS_R_VehicleMod 1
  60. #define _ALS_R_EnterExitModShop 1
  61. #define _ALS_R_VehiclePaintjob 1
  62. #define _ALS_R_VehicleRespray 1
  63. #define _ALS_R_VehicleDamageStatusUp 1
  64. #define _ALS_R_PlayerSelectedMenuRow 1
  65. #define _ALS_R_PlayerExitedMenu 1
  66. #define _ALS_R_PlayerInteriorChange 1
  67. #define _ALS_R_PlayerKeyStateChange 1
  68. #define _ALS_R_RconLoginAttempt 1
  69. #define _ALS_R_PlayerUpdate 1
  70. #define _ALS_R_PlayerStreamIn 1
  71. #define _ALS_R_PlayerStreamOut 1
  72. #define _ALS_R_VehicleStreamIn 1
  73. #define _ALS_R_VehicleStreamOut 1
  74. #define _ALS_R_DialogResponse 1
  75. #define _ALS_R_PlayerClickPlayer 1
  76. #define _ALS_R_PlayerClickMap 1
  77. #define _ALS_R_PlayerClickTextDraw 1
  78. #define _ALS_R_PlayerClickPlayerTD 1
  79. #define _ALS_R_PlayerEditObject 1
  80. #define _ALS_R_PlayerEditAttachedObj 1
  81. #define _ALS_R_PlayerSelectObject 1
  82. #define _ALS_R_PlayerTakeDamage 1
  83. #define _ALS_R_PlayerGiveDamage 1
  84.  
  85. // Define the number of parameter for every callback.
  86. #define _ALS_P_GameModeInit(%0) %0_0
  87. #define _ALS_P_GameModeExit(%0) %0_0
  88. #define _ALS_P_FilterScriptInit(%0) %0_0
  89. #define _ALS_P_FilterScriptExit(%0) %0_0
  90. #define _ALS_P_PlayerConnect(%0) %0_1
  91. #define _ALS_P_PlayerDisconnect(%0) %0_2
  92. #define _ALS_P_PlayerSpawn(%0) %0_1
  93. #define _ALS_P_PlayerDeath(%0) %0_3
  94. #define _ALS_P_VehicleSpawn(%0) %0_1
  95. #define _ALS_P_VehicleDeath(%0) %0_2
  96. #define _ALS_P_PlayerText(%0) %0_2
  97. #define _ALS_P_PlayerCommandText(%0) %0_2
  98. #define _ALS_P_PlayerRequestClass(%0) %0_2
  99. #define _ALS_P_PlayerEnterVehicle(%0) %0_3
  100. #define _ALS_P_PlayerExitVehicle(%0) %0_2
  101. #define _ALS_P_PlayerStateChange(%0) %0_3
  102. #define _ALS_P_PlayerEnterCheckpoint(%0) %0_1
  103. #define _ALS_P_PlayerLeaveCheckpoint(%0) %0_1
  104. #define _ALS_P_PlayerEnterRaceCP(%0) %0_1
  105. #define _ALS_P_PlayerLeaveRaceCP(%0) %0_1
  106. #define _ALS_P_RconCommand(%0) %0_1
  107. #define _ALS_P_PlayerRequestSpawn(%0) %0_1
  108. #define _ALS_P_ObjectMoved(%0) %0_1
  109. #define _ALS_P_PlayerObjectMoved(%0) %0_2
  110. #define _ALS_P_PlayerPickUpPickup(%0) %0_2
  111. #define _ALS_P_VehicleMod(%0) %0_3
  112. #define _ALS_P_EnterExitModShop(%0) %0_3
  113. #define _ALS_P_VehiclePaintjob(%0) %0_3
  114. #define _ALS_P_VehicleRespray(%0) %0_4
  115. #define _ALS_P_VehicleDamageStatusUp(%0) %0_2
  116. #define _ALS_P_PlayerSelectedMenuRow(%0) %0_2
  117. #define _ALS_P_PlayerExitedMenu(%0) %0_1
  118. #define _ALS_P_PlayerInteriorChange(%0) %0_3
  119. #define _ALS_P_PlayerKeyStateChange(%0) %0_3
  120. #define _ALS_P_RconLoginAttempt(%0) %0_3
  121. #define _ALS_P_PlayerUpdate(%0) %0_1
  122. #define _ALS_P_PlayerStreamIn(%0) %0_2
  123. #define _ALS_P_PlayerStreamOut(%0) %0_2
  124. #define _ALS_P_VehicleStreamIn(%0) %0_2
  125. #define _ALS_P_VehicleStreamOut(%0) %0_2
  126. #define _ALS_P_DialogResponse(%0) %0_5
  127. #define _ALS_P_PlayerClickPlayer(%0) %0_3
  128. #define _ALS_P_PlayerClickMap(%0) %0_4
  129. #define _ALS_P_PlayerClickTextDraw(%0) %0_2
  130. #define _ALS_P_PlayerClickPlayerTD(%0) %0_3
  131. #define _ALS_P_PlayerEditObject(%0) %0_10
  132. #define _ALS_P_PlayerEditAttachedObj(%0) %0_14
  133. #define _ALS_P_PlayerSelectObject(%0) %0_7
  134. #define _ALS_P_PlayerTakeDamage(%0) %0_4
  135. #define _ALS_P_PlayerGiveDamage(%0) %0_4
  136.  
  137. static
  138.     ALS_gsWriteOffset = -1,
  139.     ALS_gsJumpOffset = -1,
  140.     ALS_gsPublicOffset = -1;
  141.  
  142. stock ALS_Call_0(const string:func[], ret)
  143. {
  144.     // We need to write the code this horrible way to avoid having parameters
  145.     // being allocated on the heap instead of the stack (as happens with "...").
  146.     return ALS_Call(func, ret, 0);
  147. }
  148.  
  149. stock ALS_Call_1(const string:func[], ret)
  150. {
  151.     return ALS_Call(func, ret, 1);
  152. }
  153.  
  154. stock ALS_Call_2(const string:func[], ret)
  155. {
  156.     return ALS_Call(func, ret, 2);
  157. }
  158.  
  159. stock ALS_Call_3(const string:func[], ret, _p0 = 0)
  160. {
  161.     // The fake parameters are just there to ensure we reserve enough code space
  162.     // to do all the pushing required.
  163.     #pragma unused _p0
  164.     return ALS_Call(func, ret, 3);
  165. }
  166.  
  167. stock ALS_Call_4(const string:func[], ret, _p0 = 0, _p1 = 0)
  168. {
  169.     #pragma unused _p0, _p1
  170.     return ALS_Call(func, ret, 4);
  171. }
  172.  
  173. stock ALS_Call_5(const string:func[], ret, _p0 = 0, _p1 = 0, _p2 = 0)
  174. {
  175.     #pragma unused _p0, _p1, _p2
  176.     return ALS_Call(func, ret, 5);
  177. }
  178.  
  179. stock ALS_Call_6(const string:func[], ret, _p0 = 0, _p1 = 0, _p2 = 0, _p3 = 0)
  180. {
  181.     #pragma unused _p0, _p1, _p2, _p3
  182.     return ALS_Call(func, ret, 6);
  183. }
  184.  
  185. stock ALS_Call_7(const string:func[], ret, _p0 = 0, _p1 = 0, _p2 = 0, _p3 = 0, _p4 = 0)
  186. {
  187.     #pragma unused _p0, _p1, _p2, _p3, _p4
  188.     return ALS_Call(func, ret, 7);
  189. }
  190.  
  191. stock ALS_Call_8(const string:func[], ret, _p0 = 0, _p1 = 0, _p2 = 0, _p3 = 0, _p4 = 0, _p5 = 0)
  192. {
  193.     #pragma unused _p0, _p1, _p2, _p3, _p4, _p5
  194.     return ALS_Call(func, ret, 8);
  195. }
  196.  
  197. stock ALS_Call_9(const string:func[], ret, _p0 = 0, _p1 = 0, _p2 = 0, _p3 = 0, _p4 = 0, _p5 = 0, _p6 = 0)
  198. {
  199.     #pragma unused _p0, _p1, _p2, _p3, _p4, _p5, _p6
  200.     return ALS_Call(func, ret, 9);
  201. }
  202.  
  203. stock ALS_Call_10(const string:func[], ret, _p0 = 0, _p1 = 0, _p2 = 0, _p3 = 0, _p4 = 0, _p5 = 0, _p6 = 0, _p7 = 0)
  204. {
  205.     #pragma unused _p0, _p1, _p2, _p3, _p4, _p5, _p6, _p7
  206.     return ALS_Call(func, ret, 10);
  207. }
  208.  
  209. stock ALS_Call_11(const string:func[], ret, _p0 = 0, _p1 = 0, _p2 = 0, _p3 = 0, _p4 = 0, _p5 = 0, _p6 = 0, _p7 = 0, _p8 = 0)
  210. {
  211.     #pragma unused _p0, _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8
  212.     return ALS_Call(func, ret, 11);
  213. }
  214.  
  215. stock ALS_Call_12(const string:func[], ret, _p0 = 0, _p1 = 0, _p2 = 0, _p3 = 0, _p4 = 0, _p5 = 0, _p6 = 0, _p7 = 0, _p8 = 0, _p9 = 0)
  216. {
  217.     #pragma unused _p0, _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9
  218.     return ALS_Call(func, ret, 12);
  219. }
  220.  
  221. stock ALS_Call_13(const string:func[], ret, _p0 = 0, _p1 = 0, _p2 = 0, _p3 = 0, _p4 = 0, _p5 = 0, _p6 = 0, _p7 = 0, _p8 = 0, _p9 = 0, _p10 = 0)
  222. {
  223.     #pragma unused _p0, _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9, _p10
  224.     return ALS_Call(func, ret, 13);
  225. }
  226.  
  227. stock ALS_Call_14(const string:func[], ret, _p0 = 0, _p1 = 0, _p2 = 0, _p3 = 0, _p4 = 0, _p5 = 0, _p6 = 0, _p7 = 0, _p8 = 0, _p9 = 0, _p10 = 0, _p11 = 0)
  228. {
  229.     #pragma unused _p0, _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9, _p10, _p11
  230.     return ALS_Call(func, ret, 14);
  231. }
  232.  
  233. static stock ALS_DoNothing()
  234. {
  235.     // New global base address code based on code by Zeex in YSI.  See:
  236.     // https://github.com/Y-Less/YSI/pull/14
  237.     return 0;
  238. }
  239.  
  240. static stock ALS_GetGlobal()
  241. {
  242.     new
  243.         addr;
  244.     // Get the offset from "DAT" to "COD" for writing new code.
  245.     #emit LCTRL          0
  246.     #emit MOVE.alt
  247.     #emit LCTRL          1
  248.     #emit SUB.alt
  249.     #emit STOR.pri       ALS_gsWriteOffset
  250.     // Call dummy function and read its (absolute) address from code.
  251.     ALS_DoNothing();
  252.     #emit LCTRL          6
  253.     #emit ADD.C          0xFFFFFFF4
  254.     #emit LOAD.alt       ALS_gsWriteOffset
  255.     #emit ADD
  256.     #emit STOR.S.pri     addr
  257.     #emit LREF.S.pri     addr
  258.     // Get difference between absolute and relative addresses.
  259.     #emit CONST.alt      ALS_DoNothing
  260.     #emit SUB
  261.     #emit STOR.pri       ALS_gsJumpOffset
  262.     // Get the relative offset to the start of the publics table.
  263.     #emit LCTRL          1
  264.     #emit NEG
  265.     #emit MOVE.alt
  266.     #emit ADD.C          32
  267.     #emit STOR.S.pri     addr
  268.     #emit LREF.S.pri     addr
  269.     #emit ADD
  270.     #emit STOR.pri       ALS_gsPublicOffset
  271. }
  272.  
  273. stock ALS_Call(const string:func[], ret, count)
  274. {
  275.     //printf("ret = %d", ret);
  276.     if (ALS_gsWriteOffset == -1)
  277.     {
  278.         ALS_GetGlobal();
  279.     }
  280.     // Put the address offset in to "addr".  Need code to handle the case where
  281.     // the callback has less parameters than this function.
  282.     new
  283.         clamped = ((count <= 2) ? (2) : (count)),
  284.         addr = clamped * 8 + 16,
  285.         idx = funcidx(func) * 8;
  286.     // Get the write address MANY bytes before the PREVIOUS function call.
  287.     #emit LOAD.S.pri         0
  288.     #emit ADD.C              4
  289.     #emit LOAD.I
  290.     #emit LOAD.S.alt         addr
  291.     #emit SUB
  292.     #emit MOVE.alt
  293.     // Store the new return to the previous function's stack.
  294.     #emit LOAD.S.pri         0
  295.     #emit ADD.C              4
  296.     #emit XCHG
  297.     #emit STOR.I
  298.     // Get the write offset to the function address.
  299.     #emit LOAD.alt           ALS_gsWriteOffset
  300.     #emit ADD
  301.     #emit STOR.S.pri         addr
  302.     // This version basically replaces itself with call to the next item in the
  303.     // chain if needed, or a CONST.pri if not to get the default return.
  304.     // Change "count" to an instruction length offset.
  305.     if (idx == -8)
  306.     {
  307.         // This writes code to return the value given in "ret" back in the
  308.         // calling function, then jumps to that new code.
  309.         #emit CONST.pri      11
  310.         #emit SREF.S.pri     addr
  311.         addr += 4;
  312.         #emit LOAD.S.pri     ret
  313.         #emit SREF.S.pri     addr
  314.         addr += 4;
  315.         // Now we need to jump over at least 4 cells.  Here the extra "2" in
  316.         // "clamped" account for the parameter count "push" and "call" opcodes.
  317.         #emit CONST.pri  51
  318.         #emit SREF.S.pri addr
  319.         addr += 4;
  320.         // Calculate the absolute address.
  321.         #emit LOAD.S.pri     0
  322.         #emit ADD.C          4
  323.         #emit LOAD.I
  324.         #emit LOAD.alt       ALS_gsJumpOffset
  325.         #emit ADD
  326.         // Add on enough offsets to jump past the function call.
  327.         #emit ADD.C          16
  328.         #emit LOAD.S.alt     clamped
  329.         #emit XCHG
  330.         #emit SMUL.C         8
  331.         #emit ADD
  332.         #emit SREF.S.pri     addr
  333.         return 0;
  334.     }
  335.     else
  336.     {
  337.         while (clamped > count)
  338.         {
  339.             // NOP NOP
  340.             #emit CONST.pri  134
  341.             #emit SREF.S.pri addr
  342.             addr += 4;
  343.             #emit CONST.pri  134
  344.             #emit SREF.S.pri addr
  345.             addr += 4;
  346.             --clamped;
  347.         }
  348.         // Start writing code to push all the parameters.
  349.         clamped = clamped * 4 + 8;
  350.         while (clamped > 8)
  351.         {
  352.             // PUSH.S <clamped>
  353.             #emit CONST.pri  41
  354.             #emit SREF.S.pri addr
  355.             addr += 4;
  356.             #emit LOAD.S.pri clamped
  357.             #emit SREF.S.pri addr
  358.             addr += 4;
  359.             // clamped -= 4;
  360.             #emit ADD.C      0xFFFFFFFC
  361.             #emit STOR.S.pri clamped
  362.         }
  363.         // PUSH.C <count * 4>
  364.         #emit CONST.pri  39
  365.         #emit SREF.S.pri addr
  366.         addr += 4;
  367.         #emit LOAD.S.pri count
  368.         #emit SMUL.C     4
  369.         #emit SREF.S.pri addr
  370.         addr += 4;
  371.         // Get the absolute address of the function to call.
  372.         idx += ALS_gsPublicOffset;
  373.         #emit LREF.S.pri     idx
  374.         #emit LOAD.alt       ALS_gsJumpOffset
  375.         #emit ADD
  376.         #emit STOR.S.pri     idx
  377.         // Write the new call code.
  378.         // CALL
  379.         #emit CONST.pri      49
  380.         #emit SREF.S.pri     addr
  381.         addr += 4;
  382.         #emit LOAD.S.pri     idx
  383.         #emit SREF.S.pri     addr
  384.         return 0;
  385.     }
  386. }
  387.  
  388. stock ALS_Chain(const string:func[], ret)
  389. {
  390.     if (ALS_gsWriteOffset == -1)
  391.     {
  392.         ALS_GetGlobal();
  393.     }
  394.     new
  395.         addr,
  396.         idx = funcidx(func) * 8;
  397.     // Get the write address 32 bytes before this function call.
  398.     #emit LOAD.S.pri         4
  399.     #emit ADD.C              0xFFFFFFE0
  400.     // Store the new return.
  401.     #emit STOR.S.pri         4
  402.     #emit LOAD.alt           ALS_gsWriteOffset
  403.     #emit ADD
  404.     #emit STOR.S.pri         addr
  405.     if (idx == -8)
  406.     {
  407.         // This writes code to return the value given in "ret" back in the
  408.         // calling function, then jumps to that new code.
  409.         #emit CONST.pri  11
  410.         #emit SREF.S.pri addr
  411.         addr += 4;
  412.         #emit LOAD.S.pri ret
  413.         #emit SREF.S.pri addr
  414.         addr += 4;
  415.         #emit CONST.pri  48
  416.         #emit SREF.S.pri addr
  417.         return 0;
  418.     }
  419.     else
  420.     {
  421.         // Get the absolute address of the function to jump in to.
  422.         idx += ALS_gsPublicOffset;
  423.         #emit LREF.S.pri     idx
  424.         #emit LOAD.alt       ALS_gsJumpOffset
  425.         #emit ADD
  426.         #emit ADD.C          4
  427.         #emit STOR.S.pri     idx
  428.         // Write the new call code.
  429.         // LCTRL 5
  430.         #emit CONST.pri      31
  431.         #emit SREF.S.pri     addr
  432.         addr += 4;
  433.         #emit CONST.pri      5
  434.         #emit SREF.S.pri     addr
  435.         addr += 4;
  436.         // SCTRL 4
  437.         #emit CONST.pri      32
  438.         #emit SREF.S.pri     addr
  439.         addr += 4;
  440.         #emit CONST.pri      4
  441.         #emit SREF.S.pri     addr
  442.         addr += 4;
  443.         // JUMP
  444.         #emit CONST.pri      51
  445.         #emit SREF.S.pri     addr
  446.         addr += 4;
  447.         #emit LOAD.S.pri     idx
  448.         #emit SREF.S.pri     addr
  449.         return 0;
  450.     }
  451. }
Advertisement
Add Comment
Please, Sign In to add comment