hermes.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. {
  2. Free Pascal port of the Hermes C library.
  3. Copyright (C) 2001-2003 Nikolay Nikolov ([email protected])
  4. Original C version by Christian Nentwich ([email protected])
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. }
  17. Unit Hermes;
  18. {$MODE objfpc}
  19. Interface
  20. Const
  21. HERMES_CONVERT_NORMAL = 0;
  22. HERMES_CONVERT_DITHER = 1;
  23. Type
  24. THermesHandle = Integer;
  25. Pint32 = ^int32;
  26. int32 = DWord;
  27. Pshort16 = ^short16;
  28. short16 = Word;
  29. Pchar8 = ^char8;
  30. char8 = Byte;
  31. PHermesFormat = ^THermesFormat;
  32. THermesFormat = Record
  33. r,g,b,a : int32;
  34. bits : Integer;
  35. indexed : Boolean;
  36. has_colorkey : Boolean;
  37. colorkey : int32;
  38. End;
  39. Function Hermes_FormatNewEmpty : PHermesFormat;
  40. { Create a new format structure, returns 0 if failed. }
  41. Function Hermes_FormatNew(bits : Integer; r, g, b, a : int32;
  42. indexed : Boolean) : PHermesFormat;
  43. { Free a format structure }
  44. Procedure Hermes_FormatFree(fmt : PHermesFormat);
  45. { Create a new format structure with colorkey info, returns 0 if failed. }
  46. Function Hermes_FormatNewEx(bits : Integer; r, g, b, a : int32;
  47. indexed, has_colorkey : Boolean;
  48. colorkey : int32) : PHermesFormat;
  49. { Compare two formats. Return true if they are equal, false otherwise }
  50. Function Hermes_FormatEquals(op1, op2 : PHermesFormat) : Boolean;
  51. { Copy the contents of format 'source' to format 'destination' }
  52. Procedure Hermes_FormatCopy(source, dest : PHermesFormat);
  53. {
  54. Get a converter to work with, specifying a combination of the flags
  55. above. Returns 0 if unsuccessful.
  56. }
  57. Function Hermes_ConverterInstance(flags : DWord) : THermesHandle;
  58. {
  59. Return a converter if it is not needed anymore, thus releasing some
  60. memory.
  61. }
  62. Procedure Hermes_ConverterReturn(handle : THermesHandle);
  63. {
  64. Request a format conversion between two formats. This function returns false
  65. if the conversion cannot be provided (which should not occur too often :)
  66. Repeated calls to this function will be cached an terminate almost
  67. immediately, so don't be ashamed of calling it often.
  68. }
  69. Function Hermes_ConverterRequest(handle : THermesHandle;
  70. source, dest : PHermesFormat) : Boolean;
  71. {
  72. Set the palette of the source surface / destination surface for a
  73. subsequent conversion. At the moment, only sourcepal is used.
  74. Returns false if unsuccessful (invalid handle!).
  75. }
  76. Function Hermes_ConverterPalette(handle, sourcepal, destpal : THermesHandle) : Boolean;
  77. {
  78. Do a format conversion after calling the setup routines above. This will
  79. convert (or copy) the pixel data from s_pixels to the data in d_pixels.
  80. Both source and destination areas/origins can be specified as well as
  81. the scanline width in bytes of the source/destination.
  82. Returns false if unsuccessful (invalid handle or request not called before).
  83. }
  84. Function Hermes_ConverterCopy(handle : THermesHandle; s_pixels : Pointer;
  85. s_x, s_y, s_width, s_height, s_pitch : Integer;
  86. d_pixels : Pointer; d_x, d_y, d_width,
  87. d_height, d_pitch : Integer) : Boolean;
  88. (*
  89. {-----------------H_BLIT---------------}
  90. {
  91. Get a blitter to work with, specifying a combination of the flags
  92. in H_Conv. Returns 0 if unsuccessful.
  93. }
  94. Function Hermes_BlitterInstance(flags : DWord) : THermesHandle;
  95. {
  96. Return a blitter if it is not needed anymore, thus releasing some
  97. memory.
  98. }
  99. Procedure Hermes_BlitterReturn(handle : THermesHandle);
  100. {
  101. Request a format blitting between two formats. This function returns false
  102. if the blitting cannot be provided (which should not occur too often :)
  103. Repeated calls to this function will be cached an terminate almost
  104. immediately, so don't be ashamed of calling it often.
  105. }
  106. Function Hermes_BlitterRequest(handle : THermesHandle;
  107. source, dest : PHermesFormat) : Boolean;
  108. {
  109. Set the palette of the source surface / destination surface for a
  110. subsequent blitting. At the moment, only sourcepal is used.
  111. Returns false if unsuccessful (invalid handle!).
  112. }
  113. Function Hermes_BlitterPalette(handle, sourcepal, destpal : THermesHandle) : Boolean;
  114. {
  115. Do a format blitting after calling the setup routines above. This will
  116. blit the pixel data from s_pixels to the data in d_pixels. Both source
  117. and destination areas/origins can be specified as well as the scanline
  118. width in bytes of the source/destination. Returns false if unsuccessful
  119. (invalid handle or request not called before).
  120. }
  121. Function Hermes_BlitterBlit(handle : THermesHandle; s_pixels : Pointer;
  122. s_x, s_y, s_width, s_height, s_pitch : Integer;
  123. d_pixels : Pointer; d_x, d_y, d_width, d_height,
  124. d_pitch : Integer) : Boolean;
  125. *)
  126. {-----------------H_PAL---------------}
  127. { Get a handle for a palette to work with. This allocates memory for an
  128. internal palette. Returns 0 if failed.
  129. }
  130. Function Hermes_PaletteInstance : THermesHandle;
  131. {
  132. Return a handle for a palette if the palette isn't used anymore. The
  133. internal palette will be deallocated.
  134. }
  135. Procedure Hermes_PaletteReturn(handle : THermesHandle);
  136. {
  137. Copy the contents of the palette parameter provided into the internal
  138. palette. The user palette has to be 256*4 bytes long.
  139. }
  140. Procedure Hermes_PaletteSet(handle : THermesHandle; palette : Pointer);
  141. {
  142. Return the pointer to the internal palette. The palette is 256*4 bytes
  143. long.
  144. }
  145. Function Hermes_PaletteGet(handle : THermesHandle) : Pointer;
  146. {
  147. Force invalidation of the palette cache. This will force lookup tables to
  148. be regenerated and has to be done manually after PaletteGet has been used
  149. and the data has been modified without the knowledge of Hermes.
  150. }
  151. Procedure Hermes_PaletteInvalidateCache(handle : THermesHandle);
  152. {-----------------H_CLEAR---------------}
  153. {
  154. Get a handle for a new clearer instance to work with. Returns 0 if failed.
  155. }
  156. Function Hermes_ClearerInstance : THermesHandle;
  157. {
  158. Return the clearer instance if it is no longer needed.
  159. }
  160. Procedure Hermes_ClearerReturn(handle : THermesHandle);
  161. {
  162. Request the clearing routines to be set up for clearing to a specific
  163. format later. Repeated calls to the routine will be cached and terminate
  164. after a short check.
  165. }
  166. Function Hermes_ClearerRequest(handle : THermesHandle; format : PHermesFormat) : Boolean;
  167. {
  168. Clear a surface. pixels points to the pixel data, x1, y1, width, height
  169. specify the area to clear, pitch is the width of a scanline in bytes,
  170. the rest are the colour components.
  171. }
  172. Function Hermes_ClearerClear(handle : THermesHandle; pixels : Pointer;
  173. x1, y1, width, height, pitch : Integer;
  174. r, g, b : int32; index : char8) : Boolean;
  175. { Initialise Hermes, returns false if failed }
  176. Function Hermes_Init : Boolean;
  177. { Deinitialise Hermes, returns false if failed }
  178. Function Hermes_Done : Boolean;
  179. Implementation
  180. {$I hermdef.inc}
  181. Const
  182. PROC_GENERIC = 1;
  183. PROC_X86_PENTIUM = 2;
  184. PROC_MMX_PENTIUM = 4;
  185. HERMES_CONVERT_GENERIC = 65536;
  186. {$I hermconf.inc}
  187. Type
  188. PHermesClearInterface = ^THermesClearInterface;
  189. THermesClearInterface = Record
  190. dest : ^char8;
  191. value : int32;
  192. width, height : Integer;
  193. add : Integer;
  194. End;
  195. THermesClearPtr = Procedure(hci : PHermesClearInterface); CDecl;
  196. PHermesClearer = ^THermesClearer;
  197. THermesClearer = Record
  198. bits : Integer;
  199. func : THermesClearPtr;
  200. End;
  201. { Structure to hold shift amounts for the generic routines }
  202. PHermesGenericInfo = ^THermesGenericInfo;
  203. THermesGenericInfo = Record
  204. r_right, g_right, b_right, a_right : Integer; {Shift amount to the right}
  205. r_left, g_left, b_left, a_left : Integer; {Shift amount to the right}
  206. End;
  207. { Pointer to specialised (one-scanline-only) conversion procedure }
  208. THermesConverterPtr = Procedure(source, dest : Pchar8;
  209. count, inc_source : DWord); CDecl;
  210. { Structure for conversion loop routines, don't be scared, size does NOT
  211. matter in this case :) }
  212. PHermesConverterInterface = ^THermesConverterInterface;
  213. THermesConverterInterface = Record
  214. s_pixels : Pchar8;
  215. s_width,s_height : Integer;
  216. s_add : Integer; { Offset to next line from end of line }
  217. d_pixels : Pchar8;
  218. d_width,d_height : Integer;
  219. d_add : Integer;
  220. func : THermesConverterPtr;
  221. lookup : Pint32; { Palette lookup table ptr, for 8 bit }
  222. s_pitch : Integer; { Source and destination pitch, }
  223. d_pitch : Integer; { only used by C routines }
  224. info : THermesGenericInfo; { Only used by generic converters }
  225. mask_r, mask_g, mask_b, mask_a : int32; { Only used by generic converters }
  226. s_mask_a : int32;
  227. s_has_colorkey : Boolean;
  228. s_colorkey : int32;
  229. d_has_colorkey : Boolean;
  230. d_colorkey : int32;
  231. End;
  232. { Pointer to loop function (C, assembler main loop, generic routines) }
  233. THermesConverterLoopPtr = Procedure(hci : PHermesConverterInterface); CDecl;
  234. PHermesConverter = ^THermesConverter;
  235. THermesConverter = Record
  236. source,dest : THermesFormat; { Source and destination format }
  237. lookup : Pint32; { Pointer to lookup table (8bit) }
  238. flags : DWord; { Defined in H_Conv.h, DITHER,etc}
  239. loopnormal : THermesConverterLoopPtr; { Loop routine for normal conv. }
  240. loopstretch : THermesConverterLoopPtr;
  241. normal : THermesConverterPtr; { One-scanline routine }
  242. stretch : THermesConverterPtr;
  243. dither : THermesConverterLoopPtr; { Dithering routines always }
  244. ditherstretch : THermesConverterLoopPtr; { convert the whole buffer }
  245. End;
  246. PHermesFactoryStruct = ^THermesFactoryStruct;
  247. THermesFactoryStruct = Record
  248. s_bits : Integer;
  249. s_idx : Boolean;
  250. s_r, s_g, s_b, s_a : int32;
  251. d_bits : Integer;
  252. d_idx : Boolean;
  253. d_r, d_g, d_b, d_a : int32;
  254. loopnormal, loopstretch : THermesConverterLoopPtr;
  255. normal, stretch : THermesConverterPtr;
  256. dither, ditherstretch : THermesConverterLoopPtr;
  257. processor : Integer;
  258. End;
  259. {dither types ?}
  260. Const
  261. { p_converters holds a list of formats, for conversion from 32 bit, 24 bit,
  262. 16 bit, muhmu and 8 bit.
  263. The destination formats are listed in the order of frequency they might
  264. occur so common formats can be retrieved faster.
  265. Format of a row:
  266. source bpp, s. indexed, s. r_mask, s. g_mask, s. b_mask, s. alpha ,dest bpp,
  267. d.indexed, d. r_mask, d. g_mask, d. b_mask, d. alpha
  268. }
  269. { I wish I could touch this, but it's used in too many other placed in the code,
  270. ( at least indirectly), and many of the indicies are hardcoded }
  271. p_converters : Array[0..4, 0..11, 0..11] Of DWord =
  272. (
  273. ( {From 32 bit RGB 888}
  274. (32,0,$ff0000,$ff00,$ff,0,16,0,$f800,$7e0,$1f,0), {16RGB565 }
  275. (32,0,$ff0000,$ff00,$ff,0, 8,0,$e0,$1c,$3,0), { 8RGB332 }
  276. (32,0,$ff0000,$ff00,$ff,0,16,0,$7c00,$3e0,$1f,0), { 16RGB555 }
  277. (32,0,$ff0000,$ff00,$ff,0,24,0,$ff0000,$ff00,$ff,0), { 24RGB888 }
  278. (32,0,$ff0000,$ff00,$ff,0,32,0,$ff,$ff00,$ff0000,0), { 32BGR888 }
  279. (32,0,$ff0000,$ff00,$ff,0,16,0,$1f,$7e0,$f800,0), { 16BGR565 }
  280. (32,0,$ff0000,$ff00,$ff,0,16,0,$1f,$3e0,$7c00,0), { 16BGR555 }
  281. (32,0,$ff0000,$ff00,$ff,0,32,0,$ff000000,$ff0000,$ff00,$ff), { 32RGBA888 }
  282. (32,0,$ff0000,$ff00,$ff,0,32,0,$ff00,$ff0000,$ff000000,$ff), { 32BGRA888 }
  283. (32,0,$ff0000,$ff00,$ff,0,24,0,$ff,$ff00,$ff0000,0), { 24BGR888 }
  284. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0)
  285. )
  286. ,
  287. ( {From 24 bit RGB 888}
  288. (24,0,$ff0000,$ff00,$ff,0,32,0,$ff0000,$ff00,$ff,0), { 32RGB888 }
  289. (24,0,$ff0000,$ff00,$ff,0,16,0,$f800,$7e0,$1f,0), { 16RGB565 }
  290. (24,0,$ff0000,$ff00,$ff,0, 8,0,$e0,$1c,$3,0), { 8RGB332 }
  291. (24,0,$ff0000,$ff00,$ff,0,16,0,$7c00,$3e0,$1f,0), { 16RGB555 }
  292. (24,0,$ff0000,$ff00,$ff,0,32,0,$ff,$ff00,$ff0000,0), { 32BGR888 }
  293. (24,0,$ff0000,$ff00,$ff,0,16,0,$1f,$7e0,$f800,0), { 16BGR565 }
  294. (24,0,$ff0000,$ff00,$ff,0,16,0,$1f,$3e0,$7c00,0), { 16BGR555 }
  295. (24,0,$ff0000,$ff00,$ff,0,32,0,$ff000000,$ff0000,$ff00,$ff), { 32RGBA888 }
  296. (24,0,$ff0000,$ff00,$ff,0,32,0,$ff00,$ff0000,$ff000000,$ff), { 32BGRA888 }
  297. (24,0,$ff0000,$ff00,$ff,0,24,0,$ff,$ff00,$ff0000,0), { 24BGR888 }
  298. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0)
  299. )
  300. ,
  301. ( {From 16 bit RGB 565}
  302. (16,0,$f800,$7e0,$1f,0,32,0,$ff0000,$ff00,$ff,0), { 32RGB888 }
  303. (16,0,$f800,$7e0,$1f,0, 8,0,$e0,$1c,$3,0), { 8RGB332 }
  304. (16,0,$f800,$7e0,$1f,0,16,0,$7c00,$3e0,$1f,0), { 16RGB555 }
  305. (16,0,$f800,$7e0,$1f,0,24,0,$ff0000,$ff00,$ff,0), { 24RGB888 }
  306. (16,0,$f800,$7e0,$1f,0,32,0,$ff,$ff00,$ff0000,0), { 32BGR888 }
  307. (16,0,$f800,$7e0,$1f,0,16,0,$1f,$7e0,$f800,0), { 16BGR565 }
  308. (16,0,$f800,$7e0,$1f,0,16,0,$1f,$3e0,$7c00,0), { 16BGR555 }
  309. (16,0,$f800,$7e0,$1f,0,32,0,$ff000000,$ff0000,$ff00,$ff), { 32RGBA888 }
  310. (16,0,$f800,$7e0,$1f,0,32,0,$ff00,$ff0000,$ff000000,$ff), { 32BGRA888 }
  311. (16,0,$f800,$7e0,$1f,0,24,0,$ff,$ff00,$ff0000,0), { 24BGR888 }
  312. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0)
  313. ),
  314. ( {From 32 bit muhmu}
  315. (32,0,$ff00000,$3fc00,$ff,0,32,0,$ff0000,$ff00,$ff,0), { 32RGB888 }
  316. (32,0,$ff00000,$3fc00,$ff,0,16,0,$f800,$7e0,$1f,0), { 16RGB565 }
  317. (32,0,$ff00000,$3fc00,$ff,0, 8,0,$e0,$1c,$3,0), { 8RGB332 }
  318. (32,0,$ff00000,$3fc00,$ff,0,16,0,$7c00,$3e0,$1f,0), { 16RGB555 }
  319. (32,0,$ff00000,$3fc00,$ff,0,24,0,$ff0000,$ff00,$ff,0), { 24RGB888 }
  320. (32,0,$ff00000,$3fc00,$ff,0,32,0,$ff,$ff00,$ff0000,0), { 32BGR888 }
  321. (32,0,$ff00000,$3fc00,$ff,0,16,0,$1f,$7e0,$f800,0), { 16BGR565 }
  322. (32,0,$ff00000,$3fc00,$ff,0,16,0,$1f,$3e0,$7c00,0), { 16BGR555 }
  323. (32,0,$ff00000,$3fc00,$ff,0,32,0,$ff000000,$ff0000,$ff00,$ff), { 32RGBA888 }
  324. (32,0,$ff00000,$3fc00,$ff,0,32,0,$ff00,$ff0000,$ff000000,$ff), { 32BGRA888 }
  325. (32,0,$ff00000,$3fc00,$ff,0,24,0,$ff,$ff00,$ff0000,0), { 24BGR888 }
  326. (0,0,0,0,0,0,0,0,0,0,0,0)
  327. ),
  328. ( {From 8 bit indexed}
  329. (8,1,0,0,0,0,32,0,0,0,0,0),
  330. (8,1,0,0,0,0,24,0,0,0,0,0),
  331. (8,1,0,0,0,0,16,0,0,0,0,0),
  332. (8,1,0,0,0,0,8,0,0,0,0,0),
  333. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0),
  334. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0),
  335. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0),
  336. (0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0)
  337. )
  338. );
  339. numConverters : Array[0..4] Of Integer = (10,10,10,11,4);
  340. refcount : Integer = 0;
  341. Var
  342. Clearers : Array[0..3] Of PHermesClearer;
  343. numClearers : Integer;
  344. standardConverters : Array[0..4] Of ^PHermesConverter;
  345. equalConverters : Array[0..3] Of PHermesConverter;
  346. {$I malloc.inc}
  347. {$I debug.inc}
  348. {$I dither.inc}
  349. {$I headp.inc}
  350. {$IFDEF I386_ASSEMBLER}
  351. {$I i386/headi386.inc}
  352. {$I i386/headmmx.inc}
  353. {$ENDIF I386_ASSEMBLER}
  354. {$I factconv.inc}
  355. {$I list.inc}
  356. {$I utility.inc}
  357. {$I format.inc}
  358. {$I palette.inc}
  359. {$I convert.inc}
  360. {$I clear.inc}
  361. {$I factory.inc}
  362. Function Hermes_Init : Boolean;
  363. Var
  364. i, j : Integer;
  365. source, dest : THermesFormat;
  366. Begin
  367. If refcount > 0 Then
  368. Begin
  369. Inc(refcount);
  370. Hermes_Init := True;
  371. Exit;
  372. End;
  373. { Initialise hermes factory }
  374. Hermes_Factory_Init;
  375. { Instruct the factory to return clearing routines }
  376. Clearers[0] := Hermes_Factory_getClearer(32);
  377. Clearers[1] := Hermes_Factory_getClearer(24);
  378. Clearers[2] := Hermes_Factory_getClearer(16);
  379. Clearers[3] := Hermes_Factory_getClearer(8);
  380. numClearers := 4;
  381. { Use factory to obtain specialised converters }
  382. For j := 0 To 4 Do
  383. Begin
  384. standardConverters[j] := malloc(SizeOf(PHermesConverter)*numConverters[j]);
  385. For i := 0 To numConverters[j] - 1 Do
  386. Begin
  387. // xxx jm color keys not taken into consideration here
  388. FillChar(source, SizeOf(source), 0);
  389. FillChar(dest, SizeOf(dest), 0);
  390. source.bits := p_converters[j, i, 0]; dest.bits := p_converters[j, i, 6];
  391. source.indexed:= p_converters[j,i,1]<>0; dest.indexed:= p_converters[j,i,7]<>0;
  392. source.r := p_converters[j, i, 2]; dest.r := p_converters[j, i, 8];
  393. source.g := p_converters[j, i, 3]; dest.g := p_converters[j, i, 9];
  394. source.b := p_converters[j, i, 4]; dest.b := p_converters[j, i, 10];
  395. source.a := p_converters[j, i, 5]; dest.a := p_converters[j, i, 11];
  396. standardConverters[j][i] := Hermes_Factory_getConverter(@source, @dest);
  397. End;
  398. End;
  399. { Set up converters for equal colour formats }
  400. equalConverters[3] := Hermes_Factory_getEqualConverter(32);
  401. equalConverters[2] := Hermes_Factory_getEqualConverter(24);
  402. equalConverters[1] := Hermes_Factory_getEqualConverter(16);
  403. equalConverters[0] := Hermes_Factory_getEqualConverter(8);
  404. { Initialise dithering tables }
  405. Dither_SetupMatrices;
  406. Inc(refcount);
  407. Hermes_Init := True;
  408. End;
  409. Function Hermes_Done : Boolean;
  410. Var
  411. i, j : Integer;
  412. Begin
  413. Dec(refcount);
  414. If refcount < 0 Then
  415. Begin
  416. refcount := 0;
  417. Hermes_Done := False;
  418. Exit;
  419. End;
  420. If refcount = 0 Then
  421. Begin
  422. For i := 0 To 3 Do
  423. Begin
  424. If Clearers[i] <> Nil Then
  425. Begin
  426. free(Clearers[i]);
  427. Clearers[i] := Nil;
  428. End;
  429. If equalConverters[i] <> Nil Then
  430. Begin
  431. free(equalConverters[i]);
  432. equalConverters[i] := Nil;
  433. End;
  434. End;
  435. For i := 0 To 4 Do
  436. Begin
  437. If standardConverters[i] <> Nil Then
  438. Begin
  439. For j := 0 To numConverters[i] - 1 Do
  440. free(standardConverters[i][j]);
  441. free(standardConverters[i]);
  442. End;
  443. standardConverters[i] := Nil;
  444. End;
  445. End;
  446. Hermes_Done := True;
  447. End;
  448. Begin
  449. DebugInit;
  450. End.