funcs.inc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. /*
  2. Legal:
  3. Version: MPL 1.1
  4. The contents of this file are subject to the Mozilla Public License Version
  5. 1.1 the "License"; you may not use this file except in compliance with
  6. the License. You may obtain a copy of the License at
  7. http://www.mozilla.org/MPL/
  8. Software distributed under the License is distributed on an "AS IS" basis,
  9. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  10. for the specific language governing rights and limitations under the
  11. License.
  12. The Original Code is the YSI framework.
  13. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  14. Portions created by the Initial Developer are Copyright C 2011
  15. the Initial Developer. All Rights Reserved.
  16. Contributors:
  17. Y_Less
  18. koolk
  19. JoeBullet/Google63
  20. g_aSlice/Slice
  21. Misiur
  22. samphunter
  23. tianmeta
  24. maddinat0r
  25. spacemud
  26. Crayder
  27. Dayvison
  28. Ahmad45123
  29. Zeex
  30. irinel1996
  31. Yiin-
  32. Chaprnks
  33. Konstantinos
  34. Masterchen09
  35. Southclaws
  36. PatchwerkQWER
  37. m0k1
  38. paulommu
  39. udan111
  40. Thanks:
  41. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  42. ZeeX - Very productive conversations.
  43. koolk - IsPlayerinAreaEx code.
  44. TheAlpha - Danish translation.
  45. breadfish - German translation.
  46. Fireburn - Dutch translation.
  47. yom - French translation.
  48. 50p - Polish translation.
  49. Zamaroht - Spanish translation.
  50. Los - Portuguese translation.
  51. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes for
  52. me to strive to better.
  53. Pixels^ - Running XScripters where the idea was born.
  54. Matite - Pestering me to release it and using it.
  55. Very special thanks to:
  56. Thiadmer - PAWN, whose limits continue to amaze me!
  57. Kye/Kalcor - SA:MP.
  58. SA:MP Team past, present and future - SA:MP.
  59. Optional plugins:
  60. Gamer_Z - GPS.
  61. Incognito - Streamer.
  62. Me - sscanf2, fixes2, Whirlpool.
  63. */
  64. /*-------------------------------------------------------------------------*//**
  65. * <param name="slot">Allocation unit to get the size of.</param>
  66. * <returns>
  67. * The size.
  68. * </returns>
  69. *//*------------------------------------------------------------------------**/
  70. P:D(Malloc_GetSlotSize(Alloc:slot));
  71. #define Malloc_GetSlotSize(%1) \
  72. (YSI_gMallocMemory[_:(%1) - 1])
  73. /*-------------------------------------------------------------------------*//**
  74. * <param name="slot">Allocation unit to get the size of.</param>
  75. * <returns>
  76. * The size.
  77. * </returns>
  78. *//*------------------------------------------------------------------------**/
  79. #if defined YSI_MALLOC_SECURE
  80. stock Malloc_SlotSize(Alloc:slot)
  81. {
  82. return Malloc_GetSlotSize(slot);
  83. }
  84. #else
  85. P:D(Malloc_SlotSize(Alloc:slot));
  86. #define Malloc_SlotSize(%1) \
  87. Malloc_GetSlotSize(%1)
  88. #endif
  89. /*-------------------------------------------------------------------------*//**
  90. * <param name="string">The string to store.</param>
  91. * <param name="pack">Whether or not the string will be packed.</param>
  92. * <returns>
  93. * 0 on fail or a data handle on sucess.
  94. * </returns>
  95. * <remarks>
  96. * Allocates a new piece of memory with enough space to store the given string.
  97. * </remarks>
  98. *//*------------------------------------------------------------------------**/
  99. stock Alloc:Malloc_NewS(const string[], bool:pack = false) {
  100. new
  101. size = pack ? ((strlen(string) + 1) char) : (strlen(string) + 1),
  102. Alloc:alloc = Malloc_Allocate(size, false);
  103. if (alloc)
  104. {
  105. if (pack)
  106. strpack(YSI_gMallocMemory[_:alloc], string, size);
  107. else
  108. strunpack(YSI_gMallocMemory[_:alloc], string, size);
  109. }
  110. return alloc;
  111. }
  112. /*-------------------------------------------------------------------------*//**
  113. * <param name="slot">The allocation unit to set the size of.</param>
  114. * <param name="size">The size to set it to.</param>
  115. *//*------------------------------------------------------------------------**/
  116. P:D(Malloc_SetSlotSize(slot,size));
  117. #define Malloc_SetSlotSize(%1,%2) \
  118. YSI_gMallocMemory[_:(%1) - 1] = (%2)
  119. /*-------------------------------------------------------------------------*//**
  120. * <param name="slot">The allocation unit to get data from.</param>
  121. * <param name="index">The location in the unit to get.</param>
  122. * <returns>
  123. * The data
  124. * </returns>
  125. * <remarks>
  126. * Basically like <symbolref name="Malloc_Get" /> but used internally.
  127. * </remarks>
  128. *//*------------------------------------------------------------------------**/
  129. P:D(Malloc_GetData(Alloc:slot,index));
  130. #define Malloc_GetData(%1,%2) \
  131. (YSI_gMallocMemory[_:((%1)+Alloc:(%2))])
  132. /*-------------------------------------------------------------------------*//**
  133. * <param name="slot">The allocation unit to set in.</param>
  134. * <param name="index">Where in the unit to set.</param>
  135. * <param name="value">The value to save.</param>
  136. *//*------------------------------------------------------------------------**/
  137. P:D(Malloc_SetData(Alloc:slot,index,value));
  138. #define Malloc_SetData(%1,%2,%3) \
  139. YSI_gMallocMemory[_:((%1)+Alloc:(%2))]=(%3)
  140. /*-------------------------------------------------------------------------*//**
  141. * <param name="slot">The allocation unit to get data from.</param>
  142. * <param name="index">The location in the unit to get.</param>
  143. * <returns>
  144. * The data
  145. * </returns>
  146. * <remarks>
  147. * Shorthand for <symbolref name="Malloc_Get" />.
  148. * </remarks>
  149. *//*------------------------------------------------------------------------**/
  150. P:D(mget(Alloc:slot, index));
  151. #if !defined YSI_MALLOC_NO_SHORT
  152. #define mget(%1) \
  153. Malloc_Get(%1)
  154. #endif
  155. /*-------------------------------------------------------------------------*//**
  156. * <param name="slot">The allocation unit to set in.</param>
  157. * <param name="index">Where in the unit to set.</param>
  158. * <param name="value">The value to save.</param>
  159. * <remarks>
  160. * Shorthand for <symbolref name="Malloc_Set" />.
  161. * </remarks>
  162. *//*------------------------------------------------------------------------**/
  163. P:D(mset(Alloc:slot, index, value));
  164. #if !defined YSI_MALLOC_NO_SHORT
  165. #define mset(%1) \
  166. Malloc_Set(%1)
  167. #endif
  168. /*-------------------------------------------------------------------------*//**
  169. * <param name="target">Target for the string.</param>
  170. * <param name="length">Length of the target.</param>
  171. * <param name="array">Data unit to put information in.</param>
  172. * <param name="index">Index in the unit.</param>
  173. * <param name="pack">Return the string packed?</param>
  174. * <returns>
  175. * The data
  176. * </returns>
  177. * <remarks>
  178. * Displays errors in secure mode. Gets a string.
  179. * Shorthand for <symbolref name="Malloc_GetS" />.
  180. * </remarks>
  181. *//*------------------------------------------------------------------------**/
  182. P:D(mgets(target[], length, Alloc:array, const index, const bool:pack = false));
  183. #if !defined YSI_MALLOC_NO_SHORT
  184. #define mgets(%1) \
  185. Malloc_GetS(%1)
  186. #endif
  187. /*-------------------------------------------------------------------------*//**
  188. * <param name="target">Target for the string.</param>
  189. * <param name="length">Length of the target.</param>
  190. * <param name="array">Data unit to put information in.</param>
  191. * <param name="index">Index in the unit.</param>
  192. * <returns>
  193. * The data
  194. * </returns>
  195. * <remarks>
  196. * Displays errors in secure mode. Gets an array.
  197. * Shorthand for <symbolref name="Malloc_GetA" />.
  198. * </remarks>
  199. *//*------------------------------------------------------------------------**/
  200. P:D(mgeta(target[], length, Alloc:array, index));
  201. #if !defined YSI_MALLOC_NO_SHORT
  202. #define mgeta(%1) \
  203. Malloc_GetA(%1)
  204. #endif
  205. /*-------------------------------------------------------------------------*//**
  206. * <param name="array">Data unit to put information in.</param>
  207. * <param name="index">Index in the unit.</param>
  208. * <param name="str">String to insert</param>
  209. * <param name="pack">Should the string be packed in?</param>
  210. * <remarks>
  211. * Displays errors in secure mode. Inserts a string.
  212. * Shorthand for <symbolref name="Malloc_SetS" />.
  213. * </remarks>
  214. *//*------------------------------------------------------------------------**/
  215. P:D(msets(Alloc:array, const index, const str[], const bool:pack = false));
  216. #if !defined YSI_MALLOC_NO_SHORT
  217. #define msets(%1) \
  218. Malloc_SetS(%1)
  219. #endif
  220. /*-------------------------------------------------------------------------*//**
  221. * <param name="array">Data unit to put information in.</param>
  222. * <param name="index">Index in the unit.</param>
  223. * <param name="str">Array to insert.</param>
  224. * <param name="len">Length of the array.</param>
  225. * <remarks>
  226. * Displays errors in secure mode. Inserts an array.
  227. * Shorthand for <symbolref name="Malloc_SetA" />.
  228. * </remarks>
  229. *//*------------------------------------------------------------------------**/
  230. P:D(mseta(Alloc:array, index, const str[], len));
  231. #if !defined YSI_MALLOC_NO_SHORT
  232. #define mseta(%1) \
  233. Malloc_SetA(%1)
  234. #endif
  235. /*-------------------------------------------------------------------------*//**
  236. * <param name="slot">The unit to get the one after of.</param>
  237. * <remarks>
  238. * Gets the next free block of memory after the current one.
  239. * </remarks>
  240. *//*------------------------------------------------------------------------**/
  241. P:D(Malloc_NextSlot(slot));
  242. #define Malloc_NextSlot(%1) \
  243. (YSI_gMallocMemory[(%1)])
  244. /*-------------------------------------------------------------------------*//**
  245. * <param name="array">Data unit to get information from.</param>
  246. * <param name="index">Index in the unit.</param>
  247. * <returns>
  248. * Data.
  249. * </returns>
  250. * <remarks>
  251. * Displays errors in secure mode.
  252. * </remarks>
  253. *//*------------------------------------------------------------------------**/
  254. #if defined YSI_MALLOC_SECURE
  255. stock Malloc_Get(Alloc:array, index)
  256. {
  257. if (index >= 0 && index < Malloc_GetSlotSize(_:array))
  258. {
  259. return Malloc_GetData(_:array, index);
  260. }
  261. P:C(else P:E("Array read index out of bounds: %d[%d]", _:array, index););
  262. return 0;
  263. }
  264. #else
  265. P:D(Malloc_Get(Alloc:array, index));
  266. #define Malloc_Get(%1,%2) \
  267. Malloc_GetData(%1, %2)
  268. #endif
  269. /*-------------------------------------------------------------------------*//**
  270. * <param name="array">Data unit to put information in.</param>
  271. * <param name="index">Index in the unit.</param>
  272. * <param name="value">Value to insert</param>
  273. * <remarks>
  274. * Displays errors in secure mode.
  275. * </remarks>
  276. *//*------------------------------------------------------------------------**/
  277. #if defined YSI_MALLOC_SECURE
  278. stock Malloc_Set(Alloc:array, index, value)
  279. {
  280. if (index >= 0 && index < Malloc_GetSlotSize(_:array))
  281. {
  282. return Malloc_SetData(_:array, index, value);
  283. }
  284. P:C(else P:E("Array write index out of bounds: %d[%d]", _:array, index););
  285. return 0;
  286. }
  287. #else
  288. P:D(Malloc_Set(Alloc:array,index,value));
  289. #define Malloc_Set(%1,%2,%3) \
  290. Malloc_SetData(%1, %2, %3)
  291. #endif
  292. /*-------------------------------------------------------------------------*//**
  293. * <param name="target">Target for the string.</param>
  294. * <param name="length">Length of the target.</param>
  295. * <param name="array">Data unit to put information in.</param>
  296. * <param name="index">Index in the unit.</param>
  297. * <param name="pack">Return the string packed?</param>
  298. * <remarks>
  299. * Displays errors in secure mode. Gets a string.
  300. * </remarks>
  301. *//*------------------------------------------------------------------------**/
  302. stock Malloc_GetS(target[], length, Alloc:array, const index, const bool:pack = false)
  303. {
  304. P:3("Malloc_GetS: array = %d, index = %d.", _:array, index);
  305. if (0 <= index < Malloc_GetSlotSize(_:array))
  306. {
  307. if (pack)
  308. {
  309. strpack(target, Malloc_GetData(array, index), length);
  310. }
  311. else
  312. {
  313. strunpack(target, Malloc_GetData(array, index), length);
  314. }
  315. }
  316. return 0;
  317. }
  318. /*-------------------------------------------------------------------------*//**
  319. * <param name="array">Data unit to put information in.</param>
  320. * <param name="index">Index in the unit.</param>
  321. * <param name="str">String to insert</param>
  322. * <param name="pack">Should the string be packed in?</param>
  323. * <remarks>
  324. * Displays errors in secure mode. Inserts a string.
  325. * </remarks>
  326. *//*------------------------------------------------------------------------**/
  327. stock Malloc_SetS(Alloc:array, const index, const str[], const bool:pack = false)
  328. {
  329. P:3("Malloc_SetS called: %d, %d, %s", _:array, index, str);
  330. new
  331. len = strlen(str) + 1;
  332. if (0 <= index && index + len <= Malloc_GetSlotSize(_:array))
  333. {
  334. P:5("Malloc_SetS: In check.");
  335. if (pack)
  336. {
  337. strpack(Malloc_GetData(array, index), str, cellmax);
  338. return (len char);
  339. }
  340. else
  341. {
  342. strunpack(Malloc_GetData(array, index), str, cellmax);
  343. return (len);
  344. }
  345. }
  346. else
  347. {
  348. #if defined YSI_MALLOC_SECURE
  349. P:E("String copy failed (%s)", str);
  350. #endif
  351. return 0;
  352. }
  353. }
  354. /*-------------------------------------------------------------------------*//**
  355. * <param name="array">Data unit to put information in.</param>
  356. * <param name="index">Index in the unit.</param>
  357. * <param name="arg">Offset in the stack of the string to store.</param>
  358. * <remarks>
  359. * Inserts a string by stack offset for use in vararg functions.
  360. * </remarks>
  361. *//*------------------------------------------------------------------------**/
  362. stock Malloc_SetVAS(Alloc:array, index, arg)
  363. {
  364. P:3("Malloc_SetVAS called: %d, %d, %d", _:array, index, arg);
  365. new
  366. len;
  367. #emit LOAD.S.pri arg
  368. #emit SMUL.C 4
  369. #emit LOAD.S.alt 0
  370. #emit ADD
  371. #emit ADD.C 12
  372. #emit LOAD.I
  373. // For later reuse.
  374. #emit STOR.S.pri arg
  375. #emit PUSH.pri
  376. #emit PUSH.C 4
  377. #emit SYSREQ.C strlen
  378. #emit STACK 8
  379. #emit STOR.S.pri len
  380. if (index >= 0 && index + (++len) <= Malloc_GetSlotSize(_:array))
  381. {
  382. P:5("Malloc_SetVAS: In check.");
  383. index += _:array;
  384. YSI_gMallocMemory[index] = 0;
  385. // Blank and copy the string.
  386. //#emit LOAD.S.pri arg
  387. //#emit SMUL.C 4
  388. //#emit LOAD.S.alt 0
  389. //#emit ADD
  390. //#emit ADD.C 12
  391. //#emit LOAD.I
  392. // Skip the code above the second time now (store the true source
  393. // address in "arg" the first time).
  394. #emit PUSH.S len
  395. #emit PUSH.S arg
  396. #emit CONST.alt YSI_gMallocMemory
  397. #emit LOAD.S.pri index
  398. #emit IDXADDR
  399. #emit MOVE.alt
  400. #emit CONST.pri 0
  401. #emit STOR.I
  402. #emit PUSH.alt
  403. #emit PUSH.C 12
  404. #emit SYSREQ.C strcat
  405. #emit STACK 16
  406. //strcat(YSI_gMallocMemory[index], str, cellmax);
  407. }
  408. #if defined YSI_MALLOC_SECURE
  409. P:C(else P:E("String copy failed (%s)", str););
  410. #endif
  411. }
  412. /*-------------------------------------------------------------------------*//**
  413. * <param name="target">Target for the array.</param>
  414. * <param name="length">Length of the target.</param>
  415. * <param name="array">Data unit to put information in.</param>
  416. * <param name="index">Index in the unit.</param>
  417. * <remarks>
  418. * Displays errors in secure mode. Gets an array.
  419. * </remarks>
  420. *//*------------------------------------------------------------------------**/
  421. stock Malloc_GetA(target[], length, Alloc:array, index)
  422. {
  423. P:3("Malloc_GetA called: array = %d, index = %d.", _:array, index);
  424. if (index >= 0)
  425. {
  426. new
  427. size = Malloc_GetSlotSize(_:array);
  428. P:5("Malloc_GetA: size = %d.", size);
  429. memcpy(target, YSI_gMallocMemory, index + _:array, size * 4, length);
  430. #if defined YSI_MALLOC_SECURE
  431. P:C(if(length > size)P:E("Out of buffer space."););
  432. #endif
  433. return 1;
  434. }
  435. return 0;
  436. }
  437. /*-------------------------------------------------------------------------*//**
  438. * <param name="array">Data unit to put information in.</param>
  439. * <param name="index">Index in the unit.</param>
  440. * <param name="str">Array to insert.</param>
  441. * <param name="len">Length of the array.</param>
  442. * <remarks>
  443. * Displays errors in secure mode. Inserts an array.
  444. * </remarks>
  445. *//*------------------------------------------------------------------------**/
  446. stock Malloc_SetA(Alloc:array, index, const str[], len)
  447. {
  448. P:3("Malloc_SetA: array = %d, index = %d.", _:array, index);
  449. if (index >= 0)
  450. {
  451. new
  452. size = Malloc_GetSlotSize(_:array);
  453. P:5("Malloc_SetA: size = %d.", size);
  454. memcpy(YSI_gMallocMemory[index + _:array], str, 0, len * 4, size - index);
  455. #if defined YSI_MALLOC_SECURE
  456. P:C(if(len > size - index)P:E("Out of buffer space."););
  457. #endif
  458. }
  459. }
  460. /*-------------------------------------------------------------------------*//**
  461. * <param name="array">Data unit to put information in.</param>
  462. * <param name="index">Index in the unit.</param>
  463. * <param name="arg">Offset in the stack of the array to store.</param>
  464. * <remarks>
  465. * Inserts an array by stack offset for use in vararg functions.
  466. * </remarks>
  467. *//*------------------------------------------------------------------------**/
  468. stock Malloc_SetVAA(Alloc:array, index, arg)
  469. {
  470. P:3("Malloc_SetVAA called: %d, %d, %d", _:array, index, arg);
  471. new
  472. len;
  473. #emit LOAD.S.pri arg
  474. #emit ADD.C 1
  475. #emit SMUL.C 4
  476. #emit LOAD.S.alt 0
  477. #emit ADD
  478. #emit ADD.C 12
  479. #emit LOAD.I
  480. #emit LOAD.I
  481. // For later reuse.
  482. #emit STOR.S.pri len
  483. if (index >= 0 && index + len <= Malloc_GetSlotSize(_:array))
  484. {
  485. P:5("Malloc_SetVAA In check.");
  486. index += _:array;
  487. // Skip the code above the second time now (store the true source
  488. // address in "arg" the first time).
  489. #emit LOAD.S.pri len
  490. #emit PUSH.pri
  491. #emit SMUL.C 4
  492. #emit PUSH.pri
  493. #emit PUSH.C 0
  494. // Source.
  495. #emit LOAD.S.pri arg
  496. #emit SMUL.C 4
  497. #emit LOAD.S.alt 0
  498. #emit ADD
  499. #emit ADD.C 12
  500. #emit LOAD.I
  501. #emit PUSH.pri
  502. // Destination.
  503. #emit CONST.alt YSI_gMallocMemory
  504. #emit LOAD.S.pri index
  505. #emit IDXADDR
  506. #emit MOVE.alt
  507. #emit CONST.pri 0
  508. #emit STOR.I
  509. #emit PUSH.alt
  510. // GO!
  511. #emit PUSH.C 20
  512. #emit SYSREQ.C memcpy
  513. #emit STACK 24
  514. }
  515. #if defined YSI_MALLOC_SECURE
  516. P:C(else P:E("Array copy out of memory."););
  517. #endif
  518. }
  519. /*-------------------------------------------------------------------------*//**
  520. * <param name="size">Size of memory to allocate.</param>
  521. * <returns>
  522. * 0 on fail or a data handle on sucess.
  523. * </returns>
  524. * <remarks>
  525. * Displays errors in secure mode.
  526. * </remarks>
  527. *//*------------------------------------------------------------------------**/
  528. #if defined YSI_MALLOC_SECURE
  529. stock Alloc:malloc(size)
  530. {
  531. new
  532. Alloc:slot = Malloc_Allocate(size);
  533. P:C(if(!slot)P:E("Allocation failed (%d)", size););
  534. return slot;
  535. }
  536. #else
  537. P:D(Alloc:malloc(size));
  538. #define malloc(%1) \
  539. Malloc_Allocate(%1)
  540. #endif
  541. /*-------------------------------------------------------------------------*//**
  542. * <param name="size">Size of memory to allocate.</param>
  543. * <returns>
  544. * 0 on fail or a data handle on sucess.
  545. * </returns>
  546. * <remarks>
  547. * Displays errors in secure mode. Blanks allocated mmeory.
  548. * </remarks>
  549. *//*------------------------------------------------------------------------**/
  550. stock Alloc:calloc(size)
  551. {
  552. new
  553. Alloc:slot = Malloc_Allocate(size);
  554. if (slot)
  555. {
  556. new
  557. temp = _:slot;
  558. while (size--)
  559. {
  560. YSI_gMallocMemory[temp++] = 0;
  561. }
  562. }
  563. #if defined YSI_MALLOC_SECURE
  564. P:C(if(!slot)P:E("Allocation failed (%d)", size););
  565. #endif
  566. return slot;
  567. }
  568. /*-------------------------------------------------------------------------*//**
  569. * <param name="slot">Slot of memory to free up.</param>
  570. * <remarks>
  571. * Displays errors in secure mode.
  572. * </remarks>
  573. *//*------------------------------------------------------------------------**/
  574. #if defined YSI_MALLOC_SECURE
  575. stock free(Alloc:slot)
  576. {
  577. if (!slot || !Malloc_GetSlotSize(_:slot))
  578. {
  579. P:1("Free failed (%d)", _:slot);
  580. return 0;
  581. }
  582. return Malloc_Free(slot);
  583. }
  584. #else
  585. P:D(free(Alloc:slot));
  586. #define free(%1) \
  587. Malloc_Free(%1)
  588. #endif
  589. /*-------------------------------------------------------------------------*//**
  590. * <param name="size">Ammount of memory to allocate IN CELLS.</param>
  591. * <param name="cleat">Blank the memory?</param>
  592. * <returns>
  593. * Memory identifier.
  594. * </returns>
  595. * <remarks>
  596. * The size check should never fail, if there's only 1 cell
  597. * extra somewhere just sneak it onto the end of an array,
  598. * if the user does proper bounds checking it shouldn't
  599. * matter.
  600. *
  601. * Implementation code for <symbolref name="malloc" />.
  602. *
  603. * This code will find an area in memory with sufficient
  604. * space to store the given data and
  605. * </remarks>
  606. *//*------------------------------------------------------------------------**/
  607. #if defined YSI_MALLOC_SECURE
  608. static
  609. #endif
  610. stock Alloc:Malloc_Allocate(size, const bool:clear = true)
  611. {
  612. P:2("Malloc_Allocate called: %d, %d, %d, %d", size, YSI_g_sUnusedStart, YSI_g_sHeapStart, Malloc_GetSlotSize(YSI_g_sUnusedStart));
  613. //P:0("Malloc_Allocate called: %d, %d, %d, %d", size, YSI_g_sUnusedStart, YSI_g_sHeapStart, Malloc_GetSlotSize(YSI_g_sUnusedStart));
  614. new
  615. slot = YSI_g_sUnusedStart,
  616. p = YSI_g_sHeapStart, // Was "0", now an offset to the heap.
  617. cs,
  618. nextSlot = 0;
  619. #if _DEBUG > 3
  620. #emit LCTRL 2
  621. #emit STOR.S.alt cs
  622. printf("Malloc_Allocate: heap = %d", cs);
  623. #endif
  624. while (slot)
  625. {
  626. cs = Malloc_GetSlotSize(slot);
  627. if (!cs)
  628. {
  629. return NO_ALLOC;
  630. }
  631. if (cs >= size)
  632. {
  633. break;
  634. }
  635. p = slot;
  636. slot = Malloc_NextSlot(slot);
  637. }
  638. if (slot)
  639. {
  640. nextSlot = Malloc_NextSlot(slot);
  641. if (cs == size + 1)
  642. {
  643. size++;
  644. }
  645. if (clear)
  646. {
  647. memset(Malloc_GetData(Alloc:slot, 0), 0, size);
  648. }
  649. if (cs == size)
  650. {
  651. if (p == YSI_g_sHeapStart)
  652. {
  653. YSI_g_sUnusedStart = nextSlot;
  654. }
  655. else
  656. {
  657. Malloc_SetData(Alloc:p, 0, nextSlot);
  658. }
  659. }
  660. else
  661. {
  662. Malloc_SetSlotSize(slot, size);
  663. size++;
  664. cs -= size;
  665. size += slot;
  666. if (p == YSI_g_sHeapStart)
  667. {
  668. YSI_g_sUnusedStart = size;
  669. }
  670. else
  671. {
  672. Malloc_SetData(Alloc:p, 0, size);
  673. }
  674. Malloc_SetData(Alloc:size, 0, nextSlot);
  675. Malloc_SetSlotSize(size, cs);
  676. }
  677. return Alloc:slot;
  678. }
  679. return NO_ALLOC;
  680. }
  681. /*-------------------------------------------------------------------------*//**
  682. * <param name="slot">Memory allocation unit to release</param>
  683. * <remarks>
  684. * Implementation code for <symbolref name="free" />.
  685. * </remarks>
  686. *//*------------------------------------------------------------------------**/
  687. #if defined YSI_MALLOC_SECURE
  688. static
  689. #endif
  690. stock Malloc_Free(Alloc:slot)
  691. {
  692. if (slot == NO_ALLOC) return 0;
  693. P:4("Malloc_Free called: %d", _:slot);
  694. new
  695. size = Malloc_GetSlotSize(_:slot),
  696. p = YSI_g_sUnusedStart,
  697. l = YSI_g_sHeapStart; // Was "0", now an offset to the heap.
  698. P:5("Malloc_Free: size = %d", size);
  699. if (p)
  700. {
  701. while (p && p < _:slot)
  702. {
  703. l = p;
  704. p = Malloc_NextSlot(p);
  705. }
  706. if (p)
  707. {
  708. if (l == YSI_g_sHeapStart)
  709. {
  710. YSI_g_sUnusedStart = _:slot;
  711. }
  712. else
  713. {
  714. new
  715. tmp = Malloc_GetSlotSize(l);
  716. if (l + tmp + 1 == _:slot)
  717. {
  718. size += tmp + 1;
  719. Malloc_SetSlotSize(l, size);
  720. slot = Alloc:l;
  721. }
  722. else
  723. {
  724. Malloc_SetData(slot, 0, p);
  725. Malloc_SetData(Alloc:l, 0, _:slot);
  726. }
  727. }
  728. if (_:slot + size + 1 == p)
  729. {
  730. Malloc_SetSlotSize(_:slot, Malloc_GetSlotSize(p) + size + 1);
  731. Malloc_SetData(slot, 0, Malloc_NextSlot(p));
  732. }
  733. else
  734. {
  735. Malloc_SetData(slot, 0, p);
  736. }
  737. }
  738. else
  739. {
  740. p = Malloc_GetSlotSize(l) + 1;
  741. if (l + p == _:slot)
  742. {
  743. Malloc_SetSlotSize(l, size + p);
  744. }
  745. else
  746. {
  747. Malloc_SetData(slot, 0, 0);
  748. Malloc_SetData(Alloc:l, 0, _:slot);
  749. }
  750. }
  751. }
  752. else
  753. {
  754. YSI_g_sUnusedStart = _:slot;
  755. Malloc_SetData(slot, 0, 0);
  756. }
  757. return 1;
  758. }
  759. /*-------------------------------------------------------------------------*//**
  760. * <param name="slot">Memory allocation unit to find</param>
  761. * <remarks>
  762. * Transforms a memory slot in to a memory address.
  763. * </remarks>
  764. *//*------------------------------------------------------------------------**/
  765. stock ResolvedAlloc:Malloc_Resolve(Alloc:slot)
  766. {
  767. #emit CONST.alt YSI_gMallocMemory
  768. #emit LOAD.S.pri slot
  769. #emit IDXADDR
  770. #emit RETN
  771. return ResolvedAlloc:0;
  772. }
  773. /*-------------------------------------------------------------------------*//**
  774. * <param name="addr">Memory address to find</param>
  775. * <remarks>
  776. * Transforms a memory address in to a memory slot.
  777. * </remarks>
  778. *//*------------------------------------------------------------------------**/
  779. stock Alloc:Malloc_Reconcile(ResolvedAlloc:addr)
  780. {
  781. #emit CONST.alt YSI_gMallocMemory
  782. #emit LOAD.S.pri addr
  783. #emit SUB
  784. #emit SHR.C.pri 2
  785. #emit RETN
  786. return Alloc:0;
  787. }