1 /*
2    Format conversion handle routines for the HERMES library
3    Copyright (c) 1998 Christian Nentwich (c.nentwich@cs.ucl.ac.uk)
4    This source code is licensed under the GNU LGPL
5 
6    Please refer to the file COPYING.LIB contained in the distribution for
7    licensing conditions
8 */
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include "H_Conv.h"
14 #include "H_Format.h"
15 #include "H_Pal.h"
16 #include "H_Blit.h"
17 #include "Palette.h"
18 #include "Factory.h"
19 #include "Convert.h"
20 #include "HermConf.h"
21 #include "HeadC.h"
22 #include "HeadX86.h"
23 #include "HeadMMX.h"
24 #include "Debug.h"
25 
26 /* ConverterList is a list of HermesConverter* */
27 
28 /* This static array is used by programs that require less than (HERMES_INITIAL) number of handles */
29 /* (Usually programs only require one handle - the static array is used to prevent unnecessary malloc's) */
30 /* If a larger array is required - A new memory block will be allocated */
31 static HermesConverter *StaticConverterList[HERMES_INITIAL];
32 
33 static HermesConverter **ConverterList = 0;	// Points to the converter memory (0 = not initialised)
34 static int LastConverter;	// Array size
35 static int NextHandle;		// The next handle that is possible free (used to optimise searching)
36 static int RefCount;		// Contains the number of used handles
37 
38 HermesJumpTable HJT_NONE[4] = {
39 	{0, 0, "Not Available" },
40 	{0, 0, "Not Available" },
41 	{0, 0, "Not Available" },
42 	{0, 0, "Not Available" }
43 	};
44 
45 static HermesJumpTable Blit_HJT_CC_32[4] = {
46 	{ConvertC_Generic32_C_Generic8_C_Blit, ConvertC_Generic32_C_Generic8_C_S_Blit, "Generic32_C_Generic8_C" },
47 	{ConvertC_Generic32_C_Generic16_C_Blit, ConvertC_Generic32_C_Generic16_C_S_Blit, "Generic32_C_Generic16_C" },
48 	{ConvertC_Generic32_C_Generic24_C_Blit, ConvertC_Generic32_C_Generic24_C_S_Blit, "Generic32_C_Generic24_C" },
49 	{ConvertC_Generic32_C_Generic32_C_Blit, ConvertC_Generic32_C_Generic32_C_S_Blit, "Generic32_C_Generic32_C" }
50 	};
51 
52 static HermesJumpTable Blit_HJT_CC_24[4] = {
53 	{ConvertC_Generic24_C_Generic8_C_Blit, ConvertC_Generic24_C_Generic8_C_S_Blit, "Generic24_C_Generic8_C" },
54 	{ConvertC_Generic24_C_Generic16_C_Blit, ConvertC_Generic24_C_Generic16_C_S_Blit, "Generic24_C_Generic16_C" },
55 	{ConvertC_Generic24_C_Generic24_C_Blit, ConvertC_Generic24_C_Generic24_C_S_Blit, "Generic24_C_Generic24_C" },
56 	{ConvertC_Generic24_C_Generic32_C_Blit, ConvertC_Generic24_C_Generic32_C_S_Blit, "Generic24_C_Generic32_C" }
57 	};
58 
59 static HermesJumpTable Blit_HJT_CC_16[4] = {
60 	{ConvertC_Generic16_C_Generic8_C_Blit, ConvertC_Generic16_C_Generic8_C_S_Blit, "Generic16_C_Generic8_C" },
61 	{ConvertC_Generic16_C_Generic16_C_Blit, ConvertC_Generic16_C_Generic16_C_S_Blit, "Generic16_C_Generic16_C" },
62 	{ConvertC_Generic16_C_Generic24_C_Blit, ConvertC_Generic16_C_Generic24_C_S_Blit, "Generic16_C_Generic24_C" },
63 	{ConvertC_Generic16_C_Generic32_C_Blit, ConvertC_Generic16_C_Generic32_C_S_Blit, "Generic16_C_Generic32_C" }
64 	};
65 
66 
67 static HermesJumpTable Blit_HJT_AO_32[4] = {
68 	{ConvertC_Generic32_A_Generic8_O_Blit, ConvertC_Generic32_A_Generic8_O_S_Blit, "Generic32_A_Generic8_O" },
69 	{ConvertC_Generic32_A_Generic16_O_Blit, ConvertC_Generic32_A_Generic16_O_S_Blit, "Generic32_A_Generic16_O" },
70 	{ConvertC_Generic32_A_Generic24_O_Blit, ConvertC_Generic32_A_Generic24_O_S_Blit, "Generic32_A_Generic24_O" },
71 	{ConvertC_Generic32_A_Generic32_O_Blit, ConvertC_Generic32_A_Generic32_O_S_Blit, "Generic32_A_Generic32_O" }
72 	};
73 
74 static HermesJumpTable Blit_HJT_AO_24[4] = {
75 	{ConvertC_Generic24_A_Generic8_O_Blit, ConvertC_Generic24_A_Generic8_O_S_Blit, "Generic24_A_Generic8_O" },
76 	{ConvertC_Generic24_A_Generic16_O_Blit, ConvertC_Generic24_A_Generic16_O_S_Blit, "Generic24_A_Generic16_O" },
77 	{ConvertC_Generic24_A_Generic24_O_Blit, ConvertC_Generic24_A_Generic24_O_S_Blit, "Generic24_A_Generic24_O" },
78 	{ConvertC_Generic24_A_Generic32_O_Blit, ConvertC_Generic24_A_Generic32_O_S_Blit, "Generic24_A_Generic32_O" }
79 	};
80 
81 static HermesJumpTable Blit_HJT_AO_16[4] = {
82 	{ConvertC_Generic16_A_Generic8_O_Blit, ConvertC_Generic16_A_Generic8_O_S_Blit, "Generic16_A_Generic8_O" },
83 	{ConvertC_Generic16_A_Generic16_O_Blit, ConvertC_Generic16_A_Generic16_O_S_Blit, "Generic16_A_Generic16_O" },
84 	{ConvertC_Generic16_A_Generic24_O_Blit, ConvertC_Generic16_A_Generic24_O_S_Blit, "Generic16_A_Generic24_O" },
85 	{ConvertC_Generic16_A_Generic32_O_Blit, ConvertC_Generic16_A_Generic32_O_S_Blit, "Generic16_A_Generic32_O" }
86 	};
87 
88 static HermesJumpTable Blit_HJT_CO_32[4] = {
89 	{ConvertC_Generic32_C_Generic8_O_Blit, ConvertC_Generic32_C_Generic8_O_S_Blit, "Generic32_C_Generic8_O" },
90 	{ConvertC_Generic32_C_Generic16_O_Blit, ConvertC_Generic32_C_Generic16_O_S_Blit, "Generic32_C_Generic16_O" },
91 	{ConvertC_Generic32_C_Generic24_O_Blit, ConvertC_Generic32_C_Generic24_O_S_Blit, "Generic32_C_Generic24_O" },
92 	{ConvertC_Generic32_C_Generic32_O_Blit, ConvertC_Generic32_C_Generic32_O_S_Blit, "Generic32_C_Generic32_O" }
93 	};
94 
95 static HermesJumpTable Blit_HJT_CO_24[4] = {
96 	{ConvertC_Generic24_C_Generic8_O_Blit, ConvertC_Generic24_C_Generic8_O_S_Blit, "Generic24_C_Generic8_O" },
97 	{ConvertC_Generic24_C_Generic16_O_Blit, ConvertC_Generic24_C_Generic16_O_S_Blit, "Generic24_C_Generic16_O" },
98 	{ConvertC_Generic24_C_Generic24_O_Blit, ConvertC_Generic24_C_Generic24_O_S_Blit, "Generic24_C_Generic24_O" },
99 	{ConvertC_Generic24_C_Generic32_O_Blit, ConvertC_Generic24_C_Generic32_O_S_Blit, "Generic24_C_Generic32_O" }
100 	};
101 
102 static HermesJumpTable Blit_HJT_CO_16[4] = {
103 	{ConvertC_Generic16_C_Generic8_O_Blit, ConvertC_Generic16_C_Generic8_O_S_Blit, "Generic16_C_Generic8_O" },
104 	{ConvertC_Generic16_C_Generic16_O_Blit, ConvertC_Generic16_C_Generic16_O_S_Blit, "Generic16_C_Generic16_O" },
105 	{ConvertC_Generic16_C_Generic24_O_Blit, ConvertC_Generic16_C_Generic24_O_S_Blit, "Generic16_C_Generic24_O" },
106 	{ConvertC_Generic16_C_Generic32_O_Blit, ConvertC_Generic16_C_Generic32_O_S_Blit, "Generic16_C_Generic32_O" }
107 	};
108 
109 static HermesJumpTable Blit_HJT_CopyOnly_32[4] = {
110 	{ConvertC_Generic32_Generic8, ConvertC_Generic32_Generic8_S, "Generic32_Generic8" },
111 	{ConvertC_Generic32_Generic16, ConvertC_Generic32_Generic16_S, "Generic32_Generic16" },
112 	{ConvertC_Generic32_Generic24, ConvertC_Generic32_Generic24_S, "Generic32_Generic24" },
113 	{ConvertC_Generic32_Generic32, ConvertC_Generic32_Generic32_S, "Generic32_Generic32" }
114 	};
115 
116 static HermesJumpTable Blit_HJT_CopyOnly_24[4] = {
117 	{ConvertC_Generic24_Generic8, ConvertC_Generic24_Generic8_S, "Generic24_Generic8" },
118 	{ConvertC_Generic24_Generic16, ConvertC_Generic24_Generic16_S, "Generic24_Generic16" },
119 	{ConvertC_Generic24_Generic24, ConvertC_Generic24_Generic24_S, "Generic24_Generic24" },
120 	{ConvertC_Generic24_Generic32, ConvertC_Generic24_Generic32_S, "Generic24_Generic32" }
121 	};
122 
123 static HermesJumpTable Blit_HJT_CopyOnly_16[4] = {
124 	{ConvertC_Generic16_Generic8, ConvertC_Generic16_Generic8_S, "Generic16_Generic8" },
125 	{ConvertC_Generic16_Generic16, ConvertC_Generic16_Generic16_S, "Generic16_Generic16" },
126 	{ConvertC_Generic16_Generic24, ConvertC_Generic16_Generic24_S, "Generic16_Generic24" },
127 	{ConvertC_Generic16_Generic32, ConvertC_Generic16_Generic32_S, "Generic16_Generic32" }
128 	};
129 static HermesJumpTable *Blit_HJT_CC[4] = { HJT_NONE, Blit_HJT_CC_16, Blit_HJT_CC_24, Blit_HJT_CC_32 };
130 static HermesJumpTable *Blit_HJT_AO[4] = { HJT_NONE, Blit_HJT_AO_16, Blit_HJT_AO_24, Blit_HJT_AO_32 };
131 static HermesJumpTable *Blit_HJT_CO[4] = { HJT_NONE, Blit_HJT_CO_16, Blit_HJT_CO_24, Blit_HJT_CO_32 };
132 static HermesJumpTable *Blit_HJT_CopyOnly[4] = { HJT_NONE, Blit_HJT_CopyOnly_16, Blit_HJT_CopyOnly_24, Blit_HJT_CopyOnly_32 };
133 
134 // *** This table is as of Hermes 1.3.2 - It looks incorrect ***
135 static HermesJumpTableList Blit_HJT = {
136 	Blit_HJT_CC,	NULL,	NULL,	Blit_HJT_AO,	Blit_HJT_AO,	Blit_HJT_CO,	Blit_HJT_CopyOnly };
137 
Hermes_BlitterInstance(unsigned long flags)138 HermesHandle HERMES_API Hermes_BlitterInstance(unsigned long flags)
139 {
140   int i;
141   HermesConverter *newinstance;
142   HermesConverter **newlist;
143   HermesConverter **cptr;
144   int cptr_id;
145   int new_size;
146 
147   DEBUG_PRINT("Hermes_BlitterInstance called\n","");
148   /* Initialising, allocate initial size array of converters */
149 
150   if (!ConverterList) {		// ConverterList not initialised. (Called on the first call to this function)
151     memset(StaticConverterList, 0, sizeof(StaticConverterList));	// Clear the array
152     ConverterList = StaticConverterList;	// Set the ConverterList address to the static array
153     LastConverter=HERMES_INITIAL;	// Size of the StaticConvertList array
154     NextHandle=1;	// Set the handle will be free
155     RefCount=0;		// Number of used handles
156   }
157 
158   cptr = 0;	// Flag the converter pointer has not been found
159   cptr_id = 0;
160 
161   // If the next handle is free use it now (to prevent unnecessary searching)
162   if (NextHandle < LastConverter)	// Valid next handle
163   {
164 	if (!ConverterList[NextHandle])	// Found a free handle
165 	{
166 		cptr = &(ConverterList[NextHandle]);	// The free handle
167 		cptr_id = NextHandle;	// The handle id
168 	}
169   }
170 
171   if (!cptr)	// handle not found - do a full search
172   {
173     // Note, I start searching at one (not zero) this is intentional - since returning zero also denotes an error
174     for (i=1; i<LastConverter; i++)	// For all the converters
175     {
176       if (!ConverterList[i])      // Found an empty slot
177       {
178         cptr = &(ConverterList[i]);	// The free handle
179         cptr_id = i;		// The handle id
180         break;
181       }
182     }
183   }
184 
185   if (!cptr) // No free slot found
186   {
187 
188     /* Uh oh, arrary too small, time for growth */
189     new_size = LastConverter+HERMES_GROWTH;
190     newlist=(HermesConverter **)malloc(sizeof(HermesConverter*) * new_size);
191     if (!newlist) return 0;
192 
193     /* Copy converter pointers */
194 
195     for (i=0;i<LastConverter;i++)	// Copy each existing converters
196     {
197       newlist[i]=ConverterList[i];
198     }
199     for ( ; i < new_size; i++ )	// Clear the new elements of the array
200     {
201       newlist[i]=0;
202     }
203 
204     if (ConverterList != StaticConverterList)	// Do not deallocate the static array
205     {
206       free(ConverterList);
207     }
208 
209     /* Assign new list to old one */
210     ConverterList=newlist;
211 
212     cptr = &(ConverterList[LastConverter]);	// The free handle
213     cptr_id = LastConverter;	// The handle id
214 
215     LastConverter = new_size;
216 
217     DEBUG_PRINT("Growing dynamic array, new size %d\n",LastConverter)
218   }
219 
220   /* Create a HermesConverter */
221 
222   /* Note: allocates and clears the list */
223   newinstance=(HermesConverter *)calloc(1, sizeof(HermesConverter));
224   if (!newinstance) return 0;
225   newinstance->flags=flags;
226 
227   RefCount++;
228 
229   *cptr = newinstance;		// Store the new HermesConverter
230   NextHandle = cptr_id + 1;	// Set the next possible free handle
231   return cptr_id;
232 }
233 
234 
235 
Hermes_BlitterReturn(HermesHandle handle)236 void HERMES_API Hermes_BlitterReturn(HermesHandle handle)
237 {
238   if (!ConverterList) return;	// Return called before Init
239   if (handle<=0 || handle>=LastConverter) return;	// Invalid handle
240   if (!ConverterList[handle]) return;   // Already deallocated
241 
242   free(ConverterList[handle]);	// Free the handle
243   ConverterList[handle]=0;	// Flag handle freed
244 
245   NextHandle = handle;		// Flag where the free handle is located
246 
247   RefCount--;
248   /* No more references, deinitialise */
249   if (!RefCount)
250   {
251     if (ConverterList != StaticConverterList)	// Not using the static array
252     {
253       free(ConverterList); 		// Free the array
254       ConverterList = StaticConverterList;  // Set the ConverterList address to the static array
255       LastConverter=HERMES_INITIAL;       // Size of the StaticConvertList array
256     }
257     NextHandle = 1;	// Where the free handle is located
258   }
259 }
260 
Hermes_BlitterRequest(HermesHandle handle,HermesFormat * source,HermesFormat * dest)261 int HERMES_API Hermes_BlitterRequest(HermesHandle handle, HermesFormat *source, HermesFormat *dest)
262 {
263   // Note - Not using specialised converters as we are blitting
264   return (Hermes_BlitterRequest_V2(handle, source, dest, 0, &Blit_HJT));
265 }
266 
267 // api_flags : 0 = Do not look for the specialised converters
Hermes_BlitterRequest_V2(HermesHandle handle,HermesFormat * source,HermesFormat * dest,int api_flags,HermesJumpTableList * tptr)268 int HERMES_API Hermes_BlitterRequest_V2(HermesHandle handle, HermesFormat *source, HermesFormat *dest, int api_flags, HermesJumpTableList *tptr)
269 {
270   int searchlist;
271   int i;
272   HermesConverter *cnv;
273   int src_bits;
274   int dest_bits;
275   HermesJumpTable *jptr;
276 
277   DEBUG_PRINT("Blitter Request\n","");
278   /* Check array ranges */
279 
280   if (handle<0 || handle>=LastConverter) return 0;
281   if (!ConverterList[handle]) return 0;
282 
283   cnv=ConverterList[handle];
284 
285   /* Cache repeated requests of the same conversion */
286 
287   if (Hermes_FormatEquals(source,&ConverterList[handle]->source) &&
288       Hermes_FormatEquals(dest,&ConverterList[handle]->dest))
289   {
290       DEBUG_PRINT("Cached converter, from bpp %d\n", source->bits);
291       DEBUG_PRINT("To bpp: %d\n", dest->bits);
292       DEBUG_PRINT("\tColorkey source: %d,\n", source->has_colorkey);
293       DEBUG_PRINT("\tColorkey dest: %d,\n", dest->has_colorkey);
294       return 1;
295   }
296 
297   DEBUG_PRINT("\tColorkey source: %d,\n", source->has_colorkey);
298   DEBUG_PRINT("\tColorkey dest: %d,\n", dest->has_colorkey);
299 
300   DEBUG_PRINT("source ->a: %x,\n", (int) source->a);
301   DEBUG_PRINT("dest ->a: %x,\n", (int) dest->a);
302 
303   /* Clear the generic converter flag */
304 
305   cnv->flags&=~HERMES_CONVERT_GENERIC;
306 
307   /* If the source and destination are equal and src no alph, use copy routines */
308 
309   if (Hermes_FormatEquals(source,dest) && !source->a) {
310       DEBUG_PRINT("Source, dest equal! bpp %d\n", source->bits);
311       if ((source->bits&0x7)!=0 || source->bits > 32 || !source->bits) return 0;
312 
313       i=(source->bits>>3)-1;
314 
315       if (!equalConverters[i]) return 0;
316 
317     Hermes_FormatCopy(source,&cnv->source);
318     Hermes_FormatCopy(dest,&cnv->dest);
319 
320     cnv->loopnormal=equalConverters[i]->loopnormal;
321     cnv->loopstretch=equalConverters[i]->loopstretch;
322     cnv->normal=equalConverters[i]->normal;
323     cnv->stretch=equalConverters[i]->stretch;
324 
325     return 1;
326   }
327 
328   if (api_flags)  /* Start looking for specialised converters */
329   {
330     searchlist=0xff;
331 
332     switch (source->bits) {
333       case 32: if (source->r==0xff0000 && source->g==0xff00 && source->b==0xff)
334                searchlist=0;
335                else
336 	     if (source->r==0xff<<20 && source->g==0xff<<10 && source->b==0xff)
337                searchlist=3;
338                break;
339 
340       case 24: if (source->r==0xff0000 && source->g==0xff00 && source->b==0xff)
341                searchlist=1; break;
342 
343       case 16: if (source->r==0xf800 && source->g==0x7e0 && source->b==0x1f)
344                searchlist=2;
345                break;
346 
347        case 8: if (source->indexed)
348                searchlist=4;
349                break;
350     }
351 
352 
353     /* We can use a quicker loop for 8 bit */
354 
355     if (searchlist!=0xff)
356     if (source->bits==8) {
357       for (i=0;i<numConverters[searchlist];i++) {
358         if (standardConverters[searchlist][i])
359         if (dest->bits==standardConverters[searchlist][i]->dest.bits)
360         {
361 	Hermes_FormatCopy(source,&cnv->source);
362           Hermes_FormatCopy(dest,&cnv->dest);
363 
364           cnv->loopnormal=standardConverters[searchlist][i]->loopnormal;
365           cnv->loopstretch=standardConverters[searchlist][i]->loopstretch;
366 
367           cnv->normal=standardConverters[searchlist][i]->normal;
368           cnv->stretch=standardConverters[searchlist][i]->stretch;
369 
370 	cnv->dither=standardConverters[searchlist][i]->dither;
371 	cnv->ditherstretch=standardConverters[searchlist][i]->ditherstretch;
372 
373           return 1;
374         }
375       }
376     }
377     else
378     for (i=0;i<numConverters[searchlist];i++) {
379       if (standardConverters[searchlist][i])
380       if (Hermes_FormatEquals(&standardConverters[searchlist][i]->source,source)&&
381 	Hermes_FormatEquals(&standardConverters[searchlist][i]->dest,dest))
382       { Hermes_FormatCopy(source,&cnv->source);
383         Hermes_FormatCopy(dest,&cnv->dest);
384 
385         cnv->loopnormal=standardConverters[searchlist][i]->loopnormal;
386         cnv->loopstretch=standardConverters[searchlist][i]->loopstretch;
387 
388         cnv->normal=standardConverters[searchlist][i]->normal;
389         cnv->stretch=standardConverters[searchlist][i]->stretch;
390 
391         cnv->dither=standardConverters[searchlist][i]->dither;
392         cnv->ditherstretch=standardConverters[searchlist][i]->ditherstretch;
393 
394         return 1;
395       }
396     }
397   }
398 
399   /* Find a generic converter */
400 
401   cnv->loopnormal=0;
402   cnv->loopstretch=0;
403   cnv->dither=0;
404   cnv->ditherstretch=0;
405   cnv->flags|=HERMES_CONVERT_GENERIC;
406 
407 
408   /* Generic routines implement whole converters not scanline converters,
409      assign placeholders */
410 
411   cnv->normal=NotApplicable;
412   cnv->stretch=NotApplicable;
413 
414   // Calculate the jump table offset;
415   src_bits = (source->bits >> 3);
416   dest_bits = (dest->bits >> 3);
417   // Validate the offset
418   if ((src_bits <= 0) || (src_bits > 4) || (dest_bits <= 0) || (dest_bits > 4) ) return 0;
419   src_bits = src_bits - 1;
420   dest_bits = dest_bits - 1;
421 
422   jptr = NULL;
423   if ((cnv->flags & HERMES_CONVERT_INVERSE_ALPHA) && (dest->a) && (tptr->jt_noalpha_alpha !=NULL))
424   {
425     jptr = tptr->jt_noalpha_alpha[src_bits] + dest_bits;
426   }
427   else if ((source->has_colorkey==1) && (dest->has_colorkey==1) && (tptr->jt_cc != NULL))
428   {
429 	 jptr = tptr->jt_cc[src_bits] + dest_bits;
430   }
431   else if ((source->has_colorkey==1) && dest->a && (tptr->jt_ca != NULL))
432   {
433 	 jptr = tptr->jt_ca[src_bits] + dest_bits;
434   }
435   else if (source->a && (dest->has_colorkey==1) && (tptr->jt_ac != NULL))
436   {
437 	 jptr = tptr->jt_ac[src_bits] + dest_bits;
438   }
439   else if (source->a && dest->a && (tptr->jt_ao != NULL))
440   {
441 	 jptr = tptr->jt_ao[src_bits] + dest_bits;
442   }
443   else if (source->a && (tptr->jt_aa != NULL))
444   {
445 	 jptr = tptr->jt_aa[src_bits] + dest_bits;
446   }
447   else if (source->has_colorkey==1 && (tptr->jt_co != NULL))
448   {
449 	 jptr = tptr->jt_co[src_bits] + dest_bits;
450   }
451   else if ( tptr->jt_copyonly != NULL)
452   {
453 	 jptr = tptr->jt_copyonly[src_bits] + dest_bits;
454   }
455 
456   if (jptr) {
457     cnv->loopnormal = jptr->loopnormal;
458     cnv->loopstretch = jptr->loopstretch;
459     DEBUG_PRINT("Using Converter: %s\n", jptr->converter_name);
460     Hermes_FormatCopy(source,&cnv->source);
461     Hermes_FormatCopy(dest,&cnv->dest);
462     return 1;
463   }
464 
465   /* No converter found, fail */
466 
467   return 0;
468 }
469 
470 
471 
472 
Hermes_BlitterPalette(HermesHandle handle,HermesHandle sourcepal,HermesHandle destpal)473 int HERMES_API Hermes_BlitterPalette(HermesHandle handle,
474 				       HermesHandle sourcepal,
475 				       HermesHandle destpal)
476 {
477   if (handle<0 || handle>=LastConverter) return 0;
478   if (!ConverterList[handle]) return 0;
479 
480   /* Fail silently if not indexed colour format */
481 
482   if (!ConverterList[handle]->source.indexed) {
483     ConverterList[handle]->lookup=0;
484     return 1;
485   }
486 
487   ConverterList[handle]->lookup=
488     Hermes_PaletteGetTable(sourcepal,&ConverterList[handle]->dest);
489 
490   if (!ConverterList[handle]->lookup) return 0;
491 
492   return 1;
493 }
494 
495 
Hermes_BlitterBlit(HermesHandle handle,void * s_pixels,int s_x,int s_y,int s_width,int s_height,int s_pitch,void * d_pixels,int d_x,int d_y,int d_width,int d_height,int d_pitch)496 int HERMES_API Hermes_BlitterBlit(HermesHandle handle,void *s_pixels,int s_x,
497 				    int s_y,int s_width,int s_height,
498 				    int s_pitch,void *d_pixels,int d_x,int d_y,
499 				    int d_width,int d_height,int d_pitch)
500 { HermesConverter *cnv;
501   HermesConverterInterface iface;
502 
503   if (handle<0 || handle>=LastConverter) return 0;
504   cnv=ConverterList[handle];
505   if (!cnv) return 0;
506 
507 
508   /* Returns success if height or width is zero. This is debatable.. ! */
509 
510   if (s_width<=0 || s_height<=0 || d_width<=0 || d_height<=0) return 1;
511 
512   iface.s_pixels=(char8 *)s_pixels;
513   iface.s_width=s_width;
514   iface.s_height=s_height;
515   iface.s_add=s_pitch-s_width*(cnv->source.bits>>3);
516   iface.s_pitch=s_pitch;
517 
518   iface.d_pixels=(char8 *)d_pixels;
519   iface.d_width=d_width;
520   iface.d_height=d_height;
521   iface.d_add=d_pitch-d_width*(cnv->dest.bits>>3);
522   iface.d_pitch=d_pitch;
523 
524   iface.s_pixels+=s_y*s_pitch+s_x*(cnv->source.bits>>3);
525   iface.d_pixels+=d_y*d_pitch+d_x*(cnv->dest.bits>>3);
526 
527   iface.s_has_colorkey = cnv->source.has_colorkey;
528   iface.d_has_colorkey = cnv->dest.has_colorkey;
529   iface.s_colorkey = cnv->source.colorkey;
530   iface.d_colorkey = cnv->dest.colorkey;
531 
532   iface.lookup=cnv->lookup;
533 
534 
535   /* For generic converters, do some extra setup (find shifts, etc.)
536      TODO: Move that out of here and in the request routine ! */
537 
538   if (cnv->flags&HERMES_CONVERT_GENERIC) {
539     Hermes_Calculate_Generic_Info(Hermes_Topbit(cnv->source.r),
540 	  			  Hermes_Topbit(cnv->source.g),
541 		 		  Hermes_Topbit(cnv->source.b),
542 		 		  Hermes_Topbit(cnv->source.a),
543 				  Hermes_Topbit(cnv->dest.r),
544 				  Hermes_Topbit(cnv->dest.g),
545 				  Hermes_Topbit(cnv->dest.b),
546 				  Hermes_Topbit(cnv->dest.a),
547 				  &iface.info);
548     iface.mask_r=cnv->dest.r;
549     iface.mask_g=cnv->dest.g;
550     iface.mask_b=cnv->dest.b;
551 	iface.mask_a=cnv->dest.a;
552     iface.s_mask_a = cnv->source.a;
553   }
554 
555 
556   /* Check for dithering. This should not be in here but in request as well */
557 
558   if (cnv->flags&HERMES_CONVERT_DITHER) {
559 
560     /* If there is a ditherer, use it else fall back to normal */
561 
562     if (cnv->dither)
563     cnv->loopnormal=cnv->dither;
564   }
565 
566 
567   /* Normal conversion */
568 
569   if (s_width==d_width && s_height==d_height) {
570     if (!cnv->normal || !cnv->loopnormal) return 0;
571 
572     /* Optimization
573     if (iface.s_add==0 && iface.d_add==0) {
574       iface.s_width *= s_height;
575       iface.d_width *= d_height;
576       iface.s_height = 1;
577       iface.d_height = 1;
578     }*/
579 
580     iface.func=cnv->normal;
581     cnv->loopnormal(&iface);
582 
583     return 1;
584   }
585   /* Stretch conversion */
586   else {
587     if (!cnv->stretch || !cnv->loopstretch) return 0;
588 
589     iface.func=cnv->stretch;
590     cnv->loopstretch(&iface);
591   }
592 
593   return 1;
594 }
595 
596 
597 
598 
599 
600 
601 
602 
603