1 #include "driver.h"
2 #include "artwork.h"
3
4
5 #define VERBOSE 0
6
7
8 static unsigned char *game_palette; /* RGB palette as set by the driver. */
9 static unsigned char *new_palette; /* changes to the palette are stored here before */
10 /* being moved to game_palette by palette_recalc() */
11 static unsigned char *palette_dirty;
12 /* arrays which keep track of colors actually used, to help in the palette shrinking. */
13 unsigned char *palette_used_colors;
14 static unsigned char *old_used_colors;
15 static int *pen_visiblecount,*pen_cachedcount;
16 static unsigned char *just_remapped; /* colors which have been remapped in this frame, */
17 /* returned by palette_recalc() */
18
19 static int use_16bit;
20 #define NO_16BIT 0
21 #define STATIC_16BIT 1
22 #define PALETTIZED_16BIT 2
23
24 static int total_shrinked_pens;
25 unsigned short *shrinked_pens;
26 static unsigned char *shrinked_palette;
27 static unsigned short *palette_map; /* map indexes from game_palette to shrinked_palette */
28 static unsigned short pen_usage_count[DYNAMIC_MAX_PENS];
29
30 unsigned short palette_transparent_pen;
31 int palette_transparent_color;
32
33
34 #define BLACK_PEN 0
35 #define TRANSPARENT_PEN 1
36 #define RESERVED_PENS 2
37
38 #define PALETTE_COLOR_NEEDS_REMAP 0x80
39
40 /* helper macro for 16-bit mode */
41 #define rgbpenindex(r,g,b) ((Machine->scrbitmap->depth==16) ? ((((r)>>3)<<10)+(((g)>>3)<<5)+((b)>>3)) : ((((r)>>5)<<5)+(((g)>>5)<<2)+((b)>>6)))
42
43
44 unsigned short *palette_shadow_table;
45
46 void overlay_remap(void);
47
48
49
palette_start(void)50 int palette_start(void)
51 {
52 int i,num;
53
54
55 game_palette = (unsigned char*)malloc(3 * Machine->drv->total_colors * sizeof(unsigned char));
56 palette_map = (unsigned short*)malloc(Machine->drv->total_colors * sizeof(unsigned short));
57 if (Machine->drv->color_table_len)
58 {
59 Machine->game_colortable = (unsigned short*)malloc(Machine->drv->color_table_len * sizeof(unsigned short));
60 Machine->remapped_colortable = (unsigned short*)malloc(Machine->drv->color_table_len * sizeof(unsigned short));
61 }
62 else Machine->game_colortable = Machine->remapped_colortable = 0;
63
64 if (Machine->color_depth == 16 || (Machine->gamedrv->flags & GAME_REQUIRES_16BIT))
65 {
66 if (Machine->color_depth == 8 || Machine->drv->total_colors > 65532)
67 use_16bit = STATIC_16BIT;
68 else
69 use_16bit = PALETTIZED_16BIT;
70 }
71 else
72 use_16bit = NO_16BIT;
73
74 switch (use_16bit)
75 {
76 case NO_16BIT:
77 if (Machine->drv->video_attributes & VIDEO_MODIFIES_PALETTE)
78 total_shrinked_pens = DYNAMIC_MAX_PENS;
79 else
80 total_shrinked_pens = STATIC_MAX_PENS;
81 break;
82 case STATIC_16BIT:
83 total_shrinked_pens = 32768;
84 break;
85 case PALETTIZED_16BIT:
86 total_shrinked_pens = Machine->drv->total_colors + RESERVED_PENS;
87 break;
88 }
89
90 shrinked_pens = (unsigned short*)malloc(total_shrinked_pens * sizeof(short));
91 shrinked_palette = (unsigned char*)malloc(3 * total_shrinked_pens * sizeof(unsigned char));
92
93 Machine->pens = (unsigned short*)malloc(Machine->drv->total_colors * sizeof(short));
94
95 if ((Machine->drv->video_attributes & VIDEO_MODIFIES_PALETTE))
96 {
97 /* if the palette changes dynamically, */
98 /* we'll need the usage arrays to help in shrinking. */
99 palette_used_colors = (unsigned char*)malloc((1+1+1+3+1) * Machine->drv->total_colors * sizeof(unsigned char));
100 pen_visiblecount = (int*)malloc(2 * Machine->drv->total_colors * sizeof(int));
101
102 if (palette_used_colors == 0 || pen_visiblecount == 0)
103 {
104 palette_stop();
105 return 1;
106 }
107
108 old_used_colors = palette_used_colors + Machine->drv->total_colors * sizeof(unsigned char);
109 just_remapped = old_used_colors + Machine->drv->total_colors * sizeof(unsigned char);
110 new_palette = just_remapped + Machine->drv->total_colors * sizeof(unsigned char);
111 palette_dirty = new_palette + 3*Machine->drv->total_colors * sizeof(unsigned char);
112 memset(palette_used_colors,PALETTE_COLOR_USED,Machine->drv->total_colors * sizeof(unsigned char));
113 memset(old_used_colors,PALETTE_COLOR_UNUSED,Machine->drv->total_colors * sizeof(unsigned char));
114 memset(palette_dirty,0,Machine->drv->total_colors * sizeof(unsigned char));
115 pen_cachedcount = pen_visiblecount + Machine->drv->total_colors;
116 memset(pen_visiblecount,0,Machine->drv->total_colors * sizeof(int));
117 memset(pen_cachedcount,0,Machine->drv->total_colors * sizeof(int));
118 }
119 else palette_used_colors = old_used_colors = just_remapped = new_palette = palette_dirty = 0;
120
121 if (Machine->color_depth == 8) num = 256;
122 else num = 65536;
123 palette_shadow_table = (unsigned short*)malloc(num * sizeof(unsigned short));
124 if (palette_shadow_table == 0)
125 {
126 palette_stop();
127 return 1;
128 }
129 for (i = 0;i < num;i++)
130 palette_shadow_table[i] = i;
131
132 if ((Machine->drv->color_table_len && (Machine->game_colortable == 0 || Machine->remapped_colortable == 0))
133 || game_palette == 0 || palette_map == 0
134 || shrinked_pens == 0 || shrinked_palette == 0 || Machine->pens == 0)
135 {
136 palette_stop();
137 return 1;
138 }
139
140 return 0;
141 }
142
palette_stop(void)143 void palette_stop(void)
144 {
145 free(palette_used_colors);
146 palette_used_colors = old_used_colors = just_remapped = new_palette = palette_dirty = 0;
147 free(pen_visiblecount);
148 pen_visiblecount = 0;
149 free(game_palette);
150 game_palette = 0;
151 free(palette_map);
152 palette_map = 0;
153 free(Machine->game_colortable);
154 Machine->game_colortable = 0;
155 free(Machine->remapped_colortable);
156 Machine->remapped_colortable = 0;
157 free(shrinked_pens);
158 shrinked_pens = 0;
159 free(shrinked_palette);
160 shrinked_palette = 0;
161 free(Machine->pens);
162 Machine->pens = 0;
163 free(palette_shadow_table);
164 palette_shadow_table = 0;
165 }
166
167
168
palette_init(void)169 int palette_init(void)
170 {
171 int i;
172
173
174 /* We initialize the palette and colortable to some default values so that */
175 /* drivers which dynamically change the palette don't need a vh_init_palette() */
176 /* function (provided the default color table fits their needs). */
177
178 for (i = 0;i < Machine->drv->total_colors;i++)
179 {
180 game_palette[3*i + 0] = ((i & 1) >> 0) * 0xff;
181 game_palette[3*i + 1] = ((i & 2) >> 1) * 0xff;
182 game_palette[3*i + 2] = ((i & 4) >> 2) * 0xff;
183 }
184
185 /* Preload the colortable with a default setting, following the same */
186 /* order of the palette. The driver can overwrite this in */
187 /* vh_init_palette() */
188 for (i = 0;i < Machine->drv->color_table_len;i++)
189 Machine->game_colortable[i] = i % Machine->drv->total_colors;
190
191 /* by default we use -1 to identify the transparent color, the driver */
192 /* can modify this. */
193 palette_transparent_color = -1;
194
195 /* now the driver can modify the default values if it wants to. */
196 if (Machine->drv->vh_init_palette)
197 (*Machine->drv->vh_init_palette)(game_palette,Machine->game_colortable,memory_region(REGION_PROMS));
198
199
200 switch (use_16bit)
201 {
202 case NO_16BIT:
203 {
204 /* initialize shrinked palette to all black */
205 for (i = 0;i < total_shrinked_pens;i++)
206 {
207 shrinked_palette[3*i + 0] =
208 shrinked_palette[3*i + 1] =
209 shrinked_palette[3*i + 2] = 0;
210 }
211
212 if (Machine->drv->video_attributes & VIDEO_MODIFIES_PALETTE)
213 {
214 /* initialize pen usage counters */
215 for (i = 0;i < DYNAMIC_MAX_PENS;i++)
216 pen_usage_count[i] = 0;
217
218 /* allocate two fixed pens at the beginning: */
219 /* transparent black */
220 pen_usage_count[TRANSPARENT_PEN] = 1; /* so the pen will not be reused */
221
222 /* non transparent black */
223 pen_usage_count[BLACK_PEN] = 1;
224
225 /* create some defaults associations of game colors to shrinked pens. */
226 /* They will be dynamically modified at run time. */
227 for (i = 0;i < Machine->drv->total_colors;i++)
228 palette_map[i] = (i & 7) + 8;
229
230 if (osd_allocate_colors(total_shrinked_pens,shrinked_palette,shrinked_pens,1))
231 return 1;
232 }
233 else
234 {
235 int j,used;
236
237
238 logerror("shrinking %d colors palette...\n",Machine->drv->total_colors);
239
240 /* shrink palette to fit */
241 used = 0;
242
243 for (i = 0;i < Machine->drv->total_colors;i++)
244 {
245 for (j = 0;j < used;j++)
246 {
247 if ( shrinked_palette[3*j + 0] == game_palette[3*i + 0] &&
248 shrinked_palette[3*j + 1] == game_palette[3*i + 1] &&
249 shrinked_palette[3*j + 2] == game_palette[3*i + 2])
250 break;
251 }
252
253 palette_map[i] = j;
254
255 if (j == used)
256 {
257 used++;
258 if (used > total_shrinked_pens)
259 {
260 used = total_shrinked_pens;
261 palette_map[i] = total_shrinked_pens-1;
262 usrintf_showmessage("cannot shrink static palette");
263 logerror("error: ran out of free pens to shrink the palette.\n");
264 }
265 else
266 {
267 shrinked_palette[3*j + 0] = game_palette[3*i + 0];
268 shrinked_palette[3*j + 1] = game_palette[3*i + 1];
269 shrinked_palette[3*j + 2] = game_palette[3*i + 2];
270 }
271 }
272 }
273
274 logerror("shrinked palette uses %d colors\n",used);
275
276 if (osd_allocate_colors(used,shrinked_palette,shrinked_pens,0))
277 return 1;
278 }
279
280
281 for (i = 0;i < Machine->drv->total_colors;i++)
282 Machine->pens[i] = shrinked_pens[palette_map[i]];
283
284 palette_transparent_pen = shrinked_pens[TRANSPARENT_PEN]; /* for dynamic palette games */
285 }
286 break;
287
288 case STATIC_16BIT:
289 {
290 unsigned char *p = shrinked_palette;
291 int r,g,b;
292
293 if (Machine->scrbitmap->depth == 16)
294 {
295 for (r = 0;r < 32;r++)
296 {
297 for (g = 0;g < 32;g++)
298 {
299 for (b = 0;b < 32;b++)
300 {
301 *p++ = (r << 3) | (r >> 2);
302 *p++ = (g << 3) | (g >> 2);
303 *p++ = (b << 3) | (b >> 2);
304 }
305 }
306 }
307
308 if (osd_allocate_colors(32768,shrinked_palette,shrinked_pens,0))
309 return 1;
310 }
311 else
312 {
313 for (r = 0;r < 8;r++)
314 {
315 for (g = 0;g < 8;g++)
316 {
317 for (b = 0;b < 4;b++)
318 {
319 *p++ = (r << 5) | (r << 2) | (r >> 1);
320 *p++ = (g << 5) | (g << 2) | (g >> 1);
321 *p++ = (b << 6) | (b << 4) | (b << 2) | b;
322 }
323 }
324 }
325
326 if (osd_allocate_colors(256,shrinked_palette,shrinked_pens,0))
327 return 1;
328 }
329
330 for (i = 0;i < Machine->drv->total_colors;i++)
331 {
332 r = game_palette[3*i + 0];
333 g = game_palette[3*i + 1];
334 b = game_palette[3*i + 2];
335
336 Machine->pens[i] = shrinked_pens[rgbpenindex(r,g,b)];
337 }
338
339 palette_transparent_pen = shrinked_pens[0]; /* we are forced to use black for the transparent pen */
340 }
341 break;
342
343 case PALETTIZED_16BIT:
344 {
345 for (i = 0;i < RESERVED_PENS;i++)
346 {
347 shrinked_palette[3*i + 0] =
348 shrinked_palette[3*i + 1] =
349 shrinked_palette[3*i + 2] = 0;
350 }
351
352 for (i = 0;i < Machine->drv->total_colors;i++)
353 {
354 shrinked_palette[3*(i+RESERVED_PENS) + 0] = game_palette[3*i + 0];
355 shrinked_palette[3*(i+RESERVED_PENS) + 1] = game_palette[3*i + 1];
356 shrinked_palette[3*(i+RESERVED_PENS) + 2] = game_palette[3*i + 2];
357 }
358
359 if (osd_allocate_colors(total_shrinked_pens,shrinked_palette,shrinked_pens,(Machine->drv->video_attributes & VIDEO_MODIFIES_PALETTE)))
360 return 1;
361
362 for (i = 0;i < Machine->drv->total_colors;i++)
363 Machine->pens[i] = shrinked_pens[i + RESERVED_PENS];
364
365 palette_transparent_pen = shrinked_pens[TRANSPARENT_PEN]; /* for dynamic palette games */
366 }
367 break;
368 }
369
370 for (i = 0;i < Machine->drv->color_table_len;i++)
371 {
372 int color = Machine->game_colortable[i];
373
374 /* check for invalid colors set by Machine->drv->vh_init_palette */
375 if (color < Machine->drv->total_colors)
376 Machine->remapped_colortable[i] = Machine->pens[color];
377 else
378 usrintf_showmessage("colortable[%d] (=%d) out of range (total_colors = %d)",
379 i,color,Machine->drv->total_colors);
380 }
381
382 return 0;
383 }
384
palette_change_color_16_static(int color,unsigned char red,unsigned char green,unsigned char blue)385 static INLINE void palette_change_color_16_static(int color,unsigned char red,unsigned char green,unsigned char blue)
386 {
387 if (color == palette_transparent_color)
388 {
389 int i;
390
391
392 palette_transparent_pen = shrinked_pens[rgbpenindex(red,green,blue)];
393
394 if (color == -1) return; /* by default, palette_transparent_color is -1 */
395
396 for (i = 0;i < Machine->drv->total_colors;i++)
397 {
398 if ((old_used_colors[i] & (PALETTE_COLOR_VISIBLE | PALETTE_COLOR_TRANSPARENT_FLAG))
399 == (PALETTE_COLOR_VISIBLE | PALETTE_COLOR_TRANSPARENT_FLAG))
400 old_used_colors[i] |= PALETTE_COLOR_NEEDS_REMAP;
401 }
402 }
403
404 if ( game_palette[3*color + 0] == red &&
405 game_palette[3*color + 1] == green &&
406 game_palette[3*color + 2] == blue)
407 return;
408
409 game_palette[3*color + 0] = red;
410 game_palette[3*color + 1] = green;
411 game_palette[3*color + 2] = blue;
412
413 if (old_used_colors[color] & PALETTE_COLOR_VISIBLE)
414 /* we'll have to reassign the color in palette_recalc() */
415 old_used_colors[color] |= PALETTE_COLOR_NEEDS_REMAP;
416 }
417
palette_change_color_16_palettized(int color,unsigned char red,unsigned char green,unsigned char blue)418 static INLINE void palette_change_color_16_palettized(int color,unsigned char red,unsigned char green,unsigned char blue)
419 {
420 if (color == palette_transparent_color)
421 {
422 osd_modify_pen(palette_transparent_pen,red,green,blue);
423
424 if (color == -1) return; /* by default, palette_transparent_color is -1 */
425 }
426
427 if ( game_palette[3*color + 0] == red &&
428 game_palette[3*color + 1] == green &&
429 game_palette[3*color + 2] == blue)
430 return;
431
432 /* Machine->pens[color] might have been remapped to transparent_pen, so I */
433 /* use shrinked_pens[] directly */
434 osd_modify_pen(shrinked_pens[color + RESERVED_PENS],red,green,blue);
435 game_palette[3*color + 0] = red;
436 game_palette[3*color + 1] = green;
437 game_palette[3*color + 2] = blue;
438 }
439
palette_change_color_8(int color,unsigned char red,unsigned char green,unsigned char blue)440 static INLINE void palette_change_color_8(int color,unsigned char red,unsigned char green,unsigned char blue)
441 {
442 int pen;
443
444 if (color == palette_transparent_color)
445 {
446 osd_modify_pen(palette_transparent_pen,red,green,blue);
447
448 if (color == -1) return; /* by default, palette_transparent_color is -1 */
449 }
450
451 if ( game_palette[3*color + 0] == red &&
452 game_palette[3*color + 1] == green &&
453 game_palette[3*color + 2] == blue)
454 {
455 palette_dirty[color] = 0;
456 return;
457 }
458
459 pen = palette_map[color];
460
461 /* if the color was used, mark it as dirty, we'll change it in palette_recalc() */
462 if (old_used_colors[color] & PALETTE_COLOR_VISIBLE)
463 {
464 new_palette[3*color + 0] = red;
465 new_palette[3*color + 1] = green;
466 new_palette[3*color + 2] = blue;
467 palette_dirty[color] = 1;
468 }
469 /* otherwise, just update the array */
470 else
471 {
472 game_palette[3*color + 0] = red;
473 game_palette[3*color + 1] = green;
474 game_palette[3*color + 2] = blue;
475 }
476 }
477
palette_change_color(int color,unsigned char red,unsigned char green,unsigned char blue)478 void palette_change_color(int color,unsigned char red,unsigned char green,unsigned char blue)
479 {
480 if ((Machine->drv->video_attributes & VIDEO_MODIFIES_PALETTE) == 0)
481 {
482 logerror("Error: palette_change_color() called, but VIDEO_MODIFIES_PALETTE not set.\n");
483 return;
484 }
485
486 if (color >= Machine->drv->total_colors)
487 {
488 logerror("error: palette_change_color() called with color %d, but only %d allocated.\n",color,Machine->drv->total_colors);
489 return;
490 }
491
492 switch (use_16bit)
493 {
494 case NO_16BIT:
495 palette_change_color_8(color,red,green,blue);
496 break;
497 case STATIC_16BIT:
498 palette_change_color_16_static(color,red,green,blue);
499 break;
500 case PALETTIZED_16BIT:
501 palette_change_color_16_palettized(color,red,green,blue);
502 break;
503 }
504 }
505
506
507
508
palette_increase_usage_count(int table_offset,unsigned int usage_mask,int color_flags)509 void palette_increase_usage_count(int table_offset,unsigned int usage_mask,int color_flags)
510 {
511 /* if we are not dynamically reducing the palette, return immediately. */
512 if (palette_used_colors == 0) return;
513
514 while (usage_mask)
515 {
516 if (usage_mask & 1)
517 {
518 if (color_flags & PALETTE_COLOR_VISIBLE)
519 pen_visiblecount[Machine->game_colortable[table_offset]]++;
520 if (color_flags & PALETTE_COLOR_CACHED)
521 pen_cachedcount[Machine->game_colortable[table_offset]]++;
522 }
523 table_offset++;
524 usage_mask >>= 1;
525 }
526 }
527
palette_decrease_usage_count(int table_offset,unsigned int usage_mask,int color_flags)528 void palette_decrease_usage_count(int table_offset,unsigned int usage_mask,int color_flags)
529 {
530 /* if we are not dynamically reducing the palette, return immediately. */
531 if (palette_used_colors == 0) return;
532
533 while (usage_mask)
534 {
535 if (usage_mask & 1)
536 {
537 if (color_flags & PALETTE_COLOR_VISIBLE)
538 pen_visiblecount[Machine->game_colortable[table_offset]]--;
539 if (color_flags & PALETTE_COLOR_CACHED)
540 pen_cachedcount[Machine->game_colortable[table_offset]]--;
541 }
542 table_offset++;
543 usage_mask >>= 1;
544 }
545 }
546
palette_increase_usage_countx(int table_offset,int num_pens,const unsigned char * pen_data,int color_flags)547 void palette_increase_usage_countx(int table_offset,int num_pens,const unsigned char *pen_data,int color_flags)
548 {
549 char flag[256];
550 memset(flag,0,256);
551
552 while (num_pens--)
553 {
554 int pen = pen_data[num_pens];
555 if (flag[pen] == 0)
556 {
557 if (color_flags & PALETTE_COLOR_VISIBLE)
558 pen_visiblecount[Machine->game_colortable[table_offset+pen]]++;
559 if (color_flags & PALETTE_COLOR_CACHED)
560 pen_cachedcount[Machine->game_colortable[table_offset+pen]]++;
561 flag[pen] = 1;
562 }
563 }
564 }
565
palette_decrease_usage_countx(int table_offset,int num_pens,const unsigned char * pen_data,int color_flags)566 void palette_decrease_usage_countx(int table_offset, int num_pens, const unsigned char *pen_data,int color_flags)
567 {
568 char flag[256];
569 memset(flag,0,256);
570
571 while (num_pens--)
572 {
573 int pen = pen_data[num_pens];
574 if (flag[pen] == 0)
575 {
576 if (color_flags & PALETTE_COLOR_VISIBLE)
577 pen_visiblecount[Machine->game_colortable[table_offset+pen]]--;
578 if (color_flags & PALETTE_COLOR_CACHED)
579 pen_cachedcount[Machine->game_colortable[table_offset+pen]]--;
580 flag[pen] = 1;
581 }
582 }
583 }
584
palette_init_used_colors(void)585 void palette_init_used_colors(void)
586 {
587 int pen;
588
589
590 /* if we are not dynamically reducing the palette, return immediately. */
591 if (palette_used_colors == 0) return;
592
593 memset(palette_used_colors,PALETTE_COLOR_UNUSED,Machine->drv->total_colors * sizeof(unsigned char));
594
595 for (pen = 0;pen < Machine->drv->total_colors;pen++)
596 {
597 if (pen_visiblecount[pen]) palette_used_colors[pen] |= PALETTE_COLOR_VISIBLE;
598 if (pen_cachedcount[pen]) palette_used_colors[pen] |= PALETTE_COLOR_CACHED;
599 }
600 }
601
602
603
604
605 static unsigned char rgb6_to_pen[64][64][64];
606
build_rgb_to_pen(void)607 static void build_rgb_to_pen(void)
608 {
609 int i,rr,gg,bb;
610
611 memset(rgb6_to_pen,DYNAMIC_MAX_PENS,sizeof(rgb6_to_pen));
612 rgb6_to_pen[0][0][0] = BLACK_PEN;
613
614 for (i = 0;i < DYNAMIC_MAX_PENS;i++)
615 {
616 if (pen_usage_count[i] > 0)
617 {
618 rr = shrinked_palette[3*i + 0] >> 2;
619 gg = shrinked_palette[3*i + 1] >> 2;
620 bb = shrinked_palette[3*i + 2] >> 2;
621
622 if (rgb6_to_pen[rr][gg][bb] == DYNAMIC_MAX_PENS)
623 {
624 int j,max;
625
626 rgb6_to_pen[rr][gg][bb] = i;
627 max = pen_usage_count[i];
628
629 /* to reduce flickering during remaps, find the pen used by most colors */
630 for (j = i+1;j < DYNAMIC_MAX_PENS;j++)
631 {
632 if (pen_usage_count[j] > max &&
633 rr == (shrinked_palette[3*j + 0] >> 2) &&
634 gg == (shrinked_palette[3*j + 1] >> 2) &&
635 bb == (shrinked_palette[3*j + 2] >> 2))
636 {
637 rgb6_to_pen[rr][gg][bb] = j;
638 max = pen_usage_count[j];
639 }
640 }
641 }
642 }
643 }
644 }
645
compress_palette(void)646 static int compress_palette(void)
647 {
648 int i,j,saved,r,g,b;
649
650
651 build_rgb_to_pen();
652
653 saved = 0;
654
655 for (i = 0;i < Machine->drv->total_colors;i++)
656 {
657 /* merge pens of the same color */
658 if ((old_used_colors[i] & PALETTE_COLOR_VISIBLE) &&
659 !(old_used_colors[i] & (PALETTE_COLOR_NEEDS_REMAP|PALETTE_COLOR_TRANSPARENT_FLAG)))
660 {
661 r = game_palette[3*i + 0] >> 2;
662 g = game_palette[3*i + 1] >> 2;
663 b = game_palette[3*i + 2] >> 2;
664
665 j = rgb6_to_pen[r][g][b];
666
667 if (palette_map[i] != j)
668 {
669 just_remapped[i] = 1;
670
671 pen_usage_count[palette_map[i]]--;
672 if (pen_usage_count[palette_map[i]] == 0)
673 saved++;
674 palette_map[i] = j;
675 pen_usage_count[palette_map[i]]++;
676 Machine->pens[i] = shrinked_pens[palette_map[i]];
677 }
678 }
679 }
680
681 #if VERBOSE
682 {
683 int subcount[8];
684
685
686 for (i = 0;i < 8;i++)
687 subcount[i] = 0;
688
689 for (i = 0;i < Machine->drv->total_colors;i++)
690 subcount[palette_used_colors[i]]++;
691
692 logerror("Ran out of pens! %d colors used (%d unused, %d visible %d cached %d visible+cached, %d transparent)\n",
693 subcount[PALETTE_COLOR_VISIBLE]+subcount[PALETTE_COLOR_CACHED]+subcount[PALETTE_COLOR_VISIBLE|PALETTE_COLOR_CACHED]+subcount[PALETTE_COLOR_TRANSPARENT],
694 subcount[PALETTE_COLOR_UNUSED],
695 subcount[PALETTE_COLOR_VISIBLE],
696 subcount[PALETTE_COLOR_CACHED],
697 subcount[PALETTE_COLOR_VISIBLE|PALETTE_COLOR_CACHED],
698 subcount[PALETTE_COLOR_TRANSPARENT]);
699 logerror("Compressed the palette, saving %d pens\n",saved);
700 }
701 #endif
702
703 return saved;
704 }
705
706
palette_recalc_16_static(void)707 static const unsigned char *palette_recalc_16_static(void)
708 {
709 int i,color;
710 int did_remap = 0;
711 int need_refresh = 0;
712
713
714 memset(just_remapped,0,Machine->drv->total_colors * sizeof(unsigned char));
715
716 for (color = 0;color < Machine->drv->total_colors;color++)
717 {
718 /* the comparison between palette_used_colors and old_used_colors also includes */
719 /* PALETTE_COLOR_NEEDS_REMAP which might have been set by palette_change_color() */
720 if ((palette_used_colors[color] & PALETTE_COLOR_VISIBLE) &&
721 palette_used_colors[color] != old_used_colors[color])
722 {
723 int r,g,b;
724
725
726 did_remap = 1;
727 if (old_used_colors[color] & palette_used_colors[color] & PALETTE_COLOR_CACHED)
728 {
729 /* the color was and still is cached, we'll have to redraw everything */
730 need_refresh = 1;
731 just_remapped[color] = 1;
732 }
733
734 if (palette_used_colors[color] & PALETTE_COLOR_TRANSPARENT_FLAG)
735 Machine->pens[color] = palette_transparent_pen;
736 else
737 {
738 r = game_palette[3*color + 0];
739 g = game_palette[3*color + 1];
740 b = game_palette[3*color + 2];
741
742 Machine->pens[color] = shrinked_pens[rgbpenindex(r,g,b)];
743 }
744 }
745
746 old_used_colors[color] = palette_used_colors[color];
747 }
748
749
750 if (did_remap)
751 {
752 /* rebuild the color lookup table */
753 for (i = 0;i < Machine->drv->color_table_len;i++)
754 Machine->remapped_colortable[i] = Machine->pens[Machine->game_colortable[i]];
755 }
756
757 if (need_refresh) return just_remapped;
758 else return 0;
759 }
760
palette_recalc_16_palettized(void)761 static const unsigned char *palette_recalc_16_palettized(void)
762 {
763 int i,color;
764 int did_remap = 0;
765 int need_refresh = 0;
766
767
768 memset(just_remapped,0,Machine->drv->total_colors * sizeof(unsigned char));
769
770 for (color = 0;color < Machine->drv->total_colors;color++)
771 {
772 if ((palette_used_colors[color] & PALETTE_COLOR_TRANSPARENT_FLAG) !=
773 (old_used_colors[color] & PALETTE_COLOR_TRANSPARENT_FLAG))
774 {
775 did_remap = 1;
776 if (old_used_colors[color] & palette_used_colors[color] & PALETTE_COLOR_CACHED)
777 {
778 /* the color was and still is cached, we'll have to redraw everything */
779 need_refresh = 1;
780 just_remapped[color] = 1;
781 }
782
783 if (palette_used_colors[color] & PALETTE_COLOR_TRANSPARENT_FLAG)
784 Machine->pens[color] = palette_transparent_pen;
785 else
786 Machine->pens[color] = shrinked_pens[color + RESERVED_PENS];
787 }
788
789 old_used_colors[color] = palette_used_colors[color];
790 }
791
792
793 if (did_remap)
794 {
795 /* rebuild the color lookup table */
796 for (i = 0;i < Machine->drv->color_table_len;i++)
797 Machine->remapped_colortable[i] = Machine->pens[Machine->game_colortable[i]];
798 }
799
800 if (need_refresh) return just_remapped;
801 else return 0;
802 }
803
palette_recalc_8(void)804 static const unsigned char *palette_recalc_8(void)
805 {
806 int i,color;
807 int did_remap = 0;
808 int need_refresh = 0;
809 int first_free_pen;
810 int ran_out = 0;
811 int reuse_pens = 0;
812 int need,avail;
813
814
815 memset(just_remapped,0,Machine->drv->total_colors * sizeof(unsigned char));
816
817
818 /* first of all, apply the changes to the palette which were */
819 /* requested since last update */
820 for (color = 0;color < Machine->drv->total_colors;color++)
821 {
822 if (palette_dirty[color])
823 {
824 int r,g,b,pen;
825
826
827 pen = palette_map[color];
828 r = new_palette[3*color + 0];
829 g = new_palette[3*color + 1];
830 b = new_palette[3*color + 2];
831
832 /* if the color maps to an exclusive pen, just change it */
833 if (pen_usage_count[pen] == 1)
834 {
835 palette_dirty[color] = 0;
836 game_palette[3*color + 0] = r;
837 game_palette[3*color + 1] = g;
838 game_palette[3*color + 2] = b;
839
840 shrinked_palette[3*pen + 0] = r;
841 shrinked_palette[3*pen + 1] = g;
842 shrinked_palette[3*pen + 2] = b;
843 osd_modify_pen(Machine->pens[color],r,g,b);
844 }
845 else
846 {
847 if (pen < RESERVED_PENS)
848 {
849 /* the color uses a reserved pen, the only thing we can do is remap it */
850 for (i = color;i < Machine->drv->total_colors;i++)
851 {
852 if (palette_dirty[i] != 0 && palette_map[i] == pen)
853 {
854 palette_dirty[i] = 0;
855 game_palette[3*i + 0] = new_palette[3*i + 0];
856 game_palette[3*i + 1] = new_palette[3*i + 1];
857 game_palette[3*i + 2] = new_palette[3*i + 2];
858 old_used_colors[i] |= PALETTE_COLOR_NEEDS_REMAP;
859 }
860 }
861 }
862 else
863 {
864 /* the pen is shared with other colors, let's see if all of them */
865 /* have been changed to the same value */
866 for (i = 0;i < Machine->drv->total_colors;i++)
867 {
868 if ((old_used_colors[i] & PALETTE_COLOR_VISIBLE) &&
869 palette_map[i] == pen)
870 {
871 if (palette_dirty[i] == 0 ||
872 new_palette[3*i + 0] != r ||
873 new_palette[3*i + 1] != g ||
874 new_palette[3*i + 2] != b)
875 break;
876 }
877 }
878
879 if (i == Machine->drv->total_colors)
880 {
881 /* all colors sharing this pen still are the same, so we */
882 /* just change the palette. */
883 shrinked_palette[3*pen + 0] = r;
884 shrinked_palette[3*pen + 1] = g;
885 shrinked_palette[3*pen + 2] = b;
886 osd_modify_pen(Machine->pens[color],r,g,b);
887
888 for (i = color;i < Machine->drv->total_colors;i++)
889 {
890 if (palette_dirty[i] != 0 && palette_map[i] == pen)
891 {
892 palette_dirty[i] = 0;
893 game_palette[3*i + 0] = r;
894 game_palette[3*i + 1] = g;
895 game_palette[3*i + 2] = b;
896 }
897 }
898 }
899 else
900 {
901 /* the colors sharing this pen now are different, we'll */
902 /* have to remap them. */
903 for (i = color;i < Machine->drv->total_colors;i++)
904 {
905 if (palette_dirty[i] != 0 && palette_map[i] == pen)
906 {
907 palette_dirty[i] = 0;
908 game_palette[3*i + 0] = new_palette[3*i + 0];
909 game_palette[3*i + 1] = new_palette[3*i + 1];
910 game_palette[3*i + 2] = new_palette[3*i + 2];
911 old_used_colors[i] |= PALETTE_COLOR_NEEDS_REMAP;
912 }
913 }
914 }
915 }
916 }
917 }
918 }
919
920
921 need = 0;
922 for (i = 0;i < Machine->drv->total_colors;i++)
923 {
924 if ((palette_used_colors[i] & PALETTE_COLOR_VISIBLE) && palette_used_colors[i] != old_used_colors[i])
925 need++;
926 }
927 if (need > 0)
928 {
929 avail = 0;
930 for (i = 0;i < DYNAMIC_MAX_PENS;i++)
931 {
932 if (pen_usage_count[i] == 0)
933 avail++;
934 }
935
936 if (need > avail)
937 {
938 #if VERBOSE
939 logerror("Need %d new pens; %d available. I'll reuse some pens.\n",need,avail);
940 #endif
941 reuse_pens = 1;
942 build_rgb_to_pen();
943 }
944 }
945
946 first_free_pen = RESERVED_PENS;
947 for (color = 0;color < Machine->drv->total_colors;color++)
948 {
949 /* the comparison between palette_used_colors and old_used_colors also includes */
950 /* PALETTE_COLOR_NEEDS_REMAP which might have been set previously */
951 if ((palette_used_colors[color] & PALETTE_COLOR_VISIBLE) &&
952 palette_used_colors[color] != old_used_colors[color])
953 {
954 int r,g,b;
955
956
957 if (old_used_colors[color] & PALETTE_COLOR_VISIBLE)
958 {
959 pen_usage_count[palette_map[color]]--;
960 old_used_colors[color] &= ~PALETTE_COLOR_VISIBLE;
961 }
962
963 r = game_palette[3*color + 0];
964 g = game_palette[3*color + 1];
965 b = game_palette[3*color + 2];
966
967 if (palette_used_colors[color] & PALETTE_COLOR_TRANSPARENT_FLAG)
968 {
969 if (palette_map[color] != TRANSPARENT_PEN)
970 {
971 /* use the fixed transparent black for this */
972 did_remap = 1;
973 if (old_used_colors[color] & palette_used_colors[color] & PALETTE_COLOR_CACHED)
974 {
975 /* the color was and still is cached, we'll have to redraw everything */
976 need_refresh = 1;
977 just_remapped[color] = 1;
978 }
979
980 palette_map[color] = TRANSPARENT_PEN;
981 }
982 pen_usage_count[palette_map[color]]++;
983 Machine->pens[color] = shrinked_pens[palette_map[color]];
984 old_used_colors[color] = palette_used_colors[color];
985 }
986 else
987 {
988 if (reuse_pens)
989 {
990 i = rgb6_to_pen[r >> 2][g >> 2][b >> 2];
991 if (i != DYNAMIC_MAX_PENS)
992 {
993 if (palette_map[color] != i)
994 {
995 did_remap = 1;
996 if (old_used_colors[color] & palette_used_colors[color] & PALETTE_COLOR_CACHED)
997 {
998 /* the color was and still is cached, we'll have to redraw everything */
999 need_refresh = 1;
1000 just_remapped[color] = 1;
1001 }
1002
1003 palette_map[color] = i;
1004 }
1005 pen_usage_count[palette_map[color]]++;
1006 Machine->pens[color] = shrinked_pens[palette_map[color]];
1007 old_used_colors[color] = palette_used_colors[color];
1008 }
1009 }
1010
1011 /* if we still haven't found a pen, choose a new one */
1012 if (old_used_colors[color] != palette_used_colors[color])
1013 {
1014 /* if possible, reuse the last associated pen */
1015 if (pen_usage_count[palette_map[color]] == 0)
1016 {
1017 pen_usage_count[palette_map[color]]++;
1018 }
1019 else /* allocate a new pen */
1020 {
1021 retry:
1022 while (first_free_pen < DYNAMIC_MAX_PENS && pen_usage_count[first_free_pen] > 0)
1023 first_free_pen++;
1024
1025 if (first_free_pen < DYNAMIC_MAX_PENS)
1026 {
1027 did_remap = 1;
1028 if (old_used_colors[color] & palette_used_colors[color] & PALETTE_COLOR_CACHED)
1029 {
1030 /* the color was and still is cached, we'll have to redraw everything */
1031 need_refresh = 1;
1032 just_remapped[color] = 1;
1033 }
1034
1035 palette_map[color] = first_free_pen;
1036 pen_usage_count[palette_map[color]]++;
1037 Machine->pens[color] = shrinked_pens[palette_map[color]];
1038 }
1039 else
1040 {
1041 /* Ran out of pens! Let's see what we can do. */
1042
1043 if (ran_out == 0)
1044 {
1045 ran_out++;
1046
1047 /* from now on, try to reuse already allocated pens */
1048 reuse_pens = 1;
1049 if (compress_palette() > 0)
1050 {
1051 did_remap = 1;
1052 need_refresh = 1; /* we'll have to redraw everything */
1053
1054 first_free_pen = RESERVED_PENS;
1055 goto retry;
1056 }
1057 }
1058
1059 ran_out++;
1060
1061 /* we failed, but go on with the loop, there might */
1062 /* be some transparent pens to remap */
1063
1064 continue;
1065 }
1066 }
1067
1068 {
1069 int rr,gg,bb;
1070
1071 i = palette_map[color];
1072 rr = shrinked_palette[3*i + 0] >> 2;
1073 gg = shrinked_palette[3*i + 1] >> 2;
1074 bb = shrinked_palette[3*i + 2] >> 2;
1075 if (rgb6_to_pen[rr][gg][bb] == i)
1076 rgb6_to_pen[rr][gg][bb] = DYNAMIC_MAX_PENS;
1077
1078 shrinked_palette[3*i + 0] = r;
1079 shrinked_palette[3*i + 1] = g;
1080 shrinked_palette[3*i + 2] = b;
1081 osd_modify_pen(Machine->pens[color],r,g,b);
1082
1083 r >>= 2;
1084 g >>= 2;
1085 b >>= 2;
1086 if (rgb6_to_pen[r][g][b] == DYNAMIC_MAX_PENS)
1087 rgb6_to_pen[r][g][b] = i;
1088 }
1089
1090 old_used_colors[color] = palette_used_colors[color];
1091 }
1092 }
1093 }
1094 }
1095
1096 if (ran_out > 1)
1097 {
1098 logerror("Error: no way to shrink the palette to 256 colors, left out %d colors.\n",ran_out-1);
1099 }
1100
1101 /* Reclaim unused pens; we do this AFTER allocating the new ones, to avoid */
1102 /* using the same pen for two different colors in two consecutive frames, */
1103 /* which might cause flicker. */
1104 for (color = 0;color < Machine->drv->total_colors;color++)
1105 {
1106 if (!(palette_used_colors[color] & PALETTE_COLOR_VISIBLE))
1107 {
1108 if (old_used_colors[color] & PALETTE_COLOR_VISIBLE)
1109 pen_usage_count[palette_map[color]]--;
1110 old_used_colors[color] = palette_used_colors[color];
1111 }
1112 }
1113
1114 #ifdef PEDANTIC
1115 /* invalidate unused pens to make bugs in color allocation evident. */
1116 for (i = 0;i < DYNAMIC_MAX_PENS;i++)
1117 {
1118 if (pen_usage_count[i] == 0)
1119 {
1120 int r,g,b;
1121 r = rand() & 0xff;
1122 g = rand() & 0xff;
1123 b = rand() & 0xff;
1124 shrinked_palette[3*i + 0] = r;
1125 shrinked_palette[3*i + 1] = g;
1126 shrinked_palette[3*i + 2] = b;
1127 osd_modify_pen(shrinked_pens[i],r,g,b);
1128 }
1129 }
1130 #endif
1131
1132 if (did_remap)
1133 {
1134 /* rebuild the color lookup table */
1135 for (i = 0;i < Machine->drv->color_table_len;i++)
1136 Machine->remapped_colortable[i] = Machine->pens[Machine->game_colortable[i]];
1137 }
1138
1139 if (need_refresh)
1140 {
1141 #if VERBOSE
1142 int used;
1143
1144 used = 0;
1145 for (i = 0;i < DYNAMIC_MAX_PENS;i++)
1146 {
1147 if (pen_usage_count[i] > 0)
1148 used++;
1149 }
1150 logerror("Did a palette remap, need a full screen redraw (%d pens used).\n",used);
1151 #endif
1152
1153 return just_remapped;
1154 }
1155 else return 0;
1156 }
1157
1158
palette_recalc(void)1159 const unsigned char *palette_recalc(void)
1160 {
1161 const unsigned char* ret = NULL;
1162
1163 /* if we are not dynamically reducing the palette, return NULL. */
1164 if (palette_used_colors != 0)
1165 {
1166 switch (use_16bit)
1167 {
1168 case NO_16BIT:
1169 default:
1170 ret = palette_recalc_8();
1171 break;
1172 case STATIC_16BIT:
1173 ret = palette_recalc_16_static();
1174 break;
1175 case PALETTIZED_16BIT:
1176 ret = palette_recalc_16_palettized();
1177 break;
1178 }
1179 }
1180
1181 if (ret) overlay_remap();
1182
1183 return ret;
1184 }
1185
1186
1187
1188 /******************************************************************************
1189
1190 Commonly used palette RAM handling functions
1191
1192 ******************************************************************************/
1193
1194 unsigned char *paletteram,*paletteram_2;
1195
READ_HANDLER(paletteram_r)1196 READ_HANDLER( paletteram_r )
1197 {
1198 return paletteram[offset];
1199 }
1200
READ_HANDLER(paletteram_2_r)1201 READ_HANDLER( paletteram_2_r )
1202 {
1203 return paletteram_2[offset];
1204 }
1205
READ_HANDLER(paletteram_word_r)1206 READ_HANDLER( paletteram_word_r )
1207 {
1208 return READ_WORD(&paletteram[offset]);
1209 }
1210
READ_HANDLER(paletteram_2_word_r)1211 READ_HANDLER( paletteram_2_word_r )
1212 {
1213 return READ_WORD(&paletteram_2[offset]);
1214 }
1215
WRITE_HANDLER(paletteram_RRRGGGBB_w)1216 WRITE_HANDLER( paletteram_RRRGGGBB_w )
1217 {
1218 int r,g,b;
1219 int bit0,bit1,bit2;
1220
1221
1222 paletteram[offset] = data;
1223
1224 /* red component */
1225 bit0 = (data >> 5) & 0x01;
1226 bit1 = (data >> 6) & 0x01;
1227 bit2 = (data >> 7) & 0x01;
1228 r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
1229 /* green component */
1230 bit0 = (data >> 2) & 0x01;
1231 bit1 = (data >> 3) & 0x01;
1232 bit2 = (data >> 4) & 0x01;
1233 g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
1234 /* blue component */
1235 bit0 = 0;
1236 bit1 = (data >> 0) & 0x01;
1237 bit2 = (data >> 1) & 0x01;
1238 b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
1239
1240 palette_change_color(offset,r,g,b);
1241 }
1242
1243
WRITE_HANDLER(paletteram_BBGGGRRR_w)1244 WRITE_HANDLER( paletteram_BBGGGRRR_w )
1245 {
1246 int r,g,b;
1247 int bit0,bit1,bit2;
1248
1249
1250 paletteram[offset] = data;
1251
1252 /* red component */
1253 bit0 = (data >> 0) & 0x01;
1254 bit1 = (data >> 1) & 0x01;
1255 bit2 = (data >> 2) & 0x01;
1256 r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
1257 /* green component */
1258 bit0 = (data >> 3) & 0x01;
1259 bit1 = (data >> 4) & 0x01;
1260 bit2 = (data >> 5) & 0x01;
1261 g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
1262 /* blue component */
1263 bit0 = 0;
1264 bit1 = (data >> 6) & 0x01;
1265 bit2 = (data >> 7) & 0x01;
1266 b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
1267
1268 palette_change_color(offset,r,g,b);
1269 }
1270
1271
WRITE_HANDLER(paletteram_IIBBGGRR_w)1272 WRITE_HANDLER( paletteram_IIBBGGRR_w )
1273 {
1274 int r,g,b,i;
1275
1276
1277 paletteram[offset] = data;
1278
1279 i = (data >> 6) & 0x03;
1280 /* red component */
1281 r = (data << 2) & 0x0c;
1282 if (r) r |= i;
1283 r *= 0x11;
1284 /* green component */
1285 g = (data >> 0) & 0x0c;
1286 if (g) g |= i;
1287 g *= 0x11;
1288 /* blue component */
1289 b = (data >> 2) & 0x0c;
1290 if (b) b |= i;
1291 b *= 0x11;
1292
1293 palette_change_color(offset,r,g,b);
1294 }
1295
1296
WRITE_HANDLER(paletteram_BBGGRRII_w)1297 WRITE_HANDLER( paletteram_BBGGRRII_w )
1298 {
1299 int r,g,b,i;
1300
1301
1302 paletteram[offset] = data;
1303
1304 i = (data >> 0) & 0x03;
1305 /* red component */
1306 r = (((data >> 0) & 0x0c) | i) * 0x11;
1307 /* green component */
1308 g = (((data >> 2) & 0x0c) | i) * 0x11;
1309 /* blue component */
1310 b = (((data >> 4) & 0x0c) | i) * 0x11;
1311
1312 palette_change_color(offset,r,g,b);
1313 }
1314
changecolor_xxxxBBBBGGGGRRRR(int color,int data)1315 static INLINE void changecolor_xxxxBBBBGGGGRRRR(int color,int data)
1316 {
1317 int r,g,b;
1318
1319
1320 r = (data >> 0) & 0x0f;
1321 g = (data >> 4) & 0x0f;
1322 b = (data >> 8) & 0x0f;
1323
1324 r = (r << 4) | r;
1325 g = (g << 4) | g;
1326 b = (b << 4) | b;
1327
1328 palette_change_color(color,r,g,b);
1329 }
1330
WRITE_HANDLER(paletteram_xxxxBBBBGGGGRRRR_w)1331 WRITE_HANDLER( paletteram_xxxxBBBBGGGGRRRR_w )
1332 {
1333 paletteram[offset] = data;
1334 changecolor_xxxxBBBBGGGGRRRR(offset / 2,paletteram[offset & ~1] | (paletteram[offset | 1] << 8));
1335 }
1336
WRITE_HANDLER(paletteram_xxxxBBBBGGGGRRRR_swap_w)1337 WRITE_HANDLER( paletteram_xxxxBBBBGGGGRRRR_swap_w )
1338 {
1339 paletteram[offset] = data;
1340 changecolor_xxxxBBBBGGGGRRRR(offset / 2,paletteram[offset | 1] | (paletteram[offset & ~1] << 8));
1341 }
1342
WRITE_HANDLER(paletteram_xxxxBBBBGGGGRRRR_split1_w)1343 WRITE_HANDLER( paletteram_xxxxBBBBGGGGRRRR_split1_w )
1344 {
1345 paletteram[offset] = data;
1346 changecolor_xxxxBBBBGGGGRRRR(offset,paletteram[offset] | (paletteram_2[offset] << 8));
1347 }
1348
WRITE_HANDLER(paletteram_xxxxBBBBGGGGRRRR_split2_w)1349 WRITE_HANDLER( paletteram_xxxxBBBBGGGGRRRR_split2_w )
1350 {
1351 paletteram_2[offset] = data;
1352 changecolor_xxxxBBBBGGGGRRRR(offset,paletteram[offset] | (paletteram_2[offset] << 8));
1353 }
1354
WRITE_HANDLER(paletteram_xxxxBBBBGGGGRRRR_word_w)1355 WRITE_HANDLER( paletteram_xxxxBBBBGGGGRRRR_word_w )
1356 {
1357 int oldword = READ_WORD(&paletteram[offset]);
1358 int newword = COMBINE_WORD(oldword,data);
1359
1360
1361 WRITE_WORD(&paletteram[offset],newword);
1362 changecolor_xxxxBBBBGGGGRRRR(offset / 2,newword);
1363 }
1364
changecolor_xxxxBBBBRRRRGGGG(int color,int data)1365 static INLINE void changecolor_xxxxBBBBRRRRGGGG(int color,int data)
1366 {
1367 int r,g,b;
1368
1369
1370 r = (data >> 4) & 0x0f;
1371 g = (data >> 0) & 0x0f;
1372 b = (data >> 8) & 0x0f;
1373
1374 r = (r << 4) | r;
1375 g = (g << 4) | g;
1376 b = (b << 4) | b;
1377
1378 palette_change_color(color,r,g,b);
1379 }
1380
WRITE_HANDLER(paletteram_xxxxBBBBRRRRGGGG_w)1381 WRITE_HANDLER( paletteram_xxxxBBBBRRRRGGGG_w )
1382 {
1383 paletteram[offset] = data;
1384 changecolor_xxxxBBBBRRRRGGGG(offset / 2,paletteram[offset & ~1] | (paletteram[offset | 1] << 8));
1385 }
1386
WRITE_HANDLER(paletteram_xxxxBBBBRRRRGGGG_swap_w)1387 WRITE_HANDLER( paletteram_xxxxBBBBRRRRGGGG_swap_w )
1388 {
1389 paletteram[offset] = data;
1390 changecolor_xxxxBBBBRRRRGGGG(offset / 2,paletteram[offset | 1] | (paletteram[offset & ~1] << 8));
1391 }
1392
WRITE_HANDLER(paletteram_xxxxBBBBRRRRGGGG_split1_w)1393 WRITE_HANDLER( paletteram_xxxxBBBBRRRRGGGG_split1_w )
1394 {
1395 paletteram[offset] = data;
1396 changecolor_xxxxBBBBRRRRGGGG(offset,paletteram[offset] | (paletteram_2[offset] << 8));
1397 }
1398
WRITE_HANDLER(paletteram_xxxxBBBBRRRRGGGG_split2_w)1399 WRITE_HANDLER( paletteram_xxxxBBBBRRRRGGGG_split2_w )
1400 {
1401 paletteram_2[offset] = data;
1402 changecolor_xxxxBBBBRRRRGGGG(offset,paletteram[offset] | (paletteram_2[offset] << 8));
1403 }
1404
changecolor_xxxxRRRRBBBBGGGG(int color,int data)1405 static INLINE void changecolor_xxxxRRRRBBBBGGGG(int color,int data)
1406 {
1407 int r,g,b;
1408
1409
1410 r = (data >> 8) & 0x0f;
1411 g = (data >> 0) & 0x0f;
1412 b = (data >> 4) & 0x0f;
1413
1414 r = (r << 4) | r;
1415 g = (g << 4) | g;
1416 b = (b << 4) | b;
1417
1418 palette_change_color(color,r,g,b);
1419 }
1420
WRITE_HANDLER(paletteram_xxxxRRRRBBBBGGGG_split1_w)1421 WRITE_HANDLER( paletteram_xxxxRRRRBBBBGGGG_split1_w )
1422 {
1423 paletteram[offset] = data;
1424 changecolor_xxxxRRRRBBBBGGGG(offset,paletteram[offset] | (paletteram_2[offset] << 8));
1425 }
1426
WRITE_HANDLER(paletteram_xxxxRRRRBBBBGGGG_split2_w)1427 WRITE_HANDLER( paletteram_xxxxRRRRBBBBGGGG_split2_w )
1428 {
1429 paletteram_2[offset] = data;
1430 changecolor_xxxxRRRRBBBBGGGG(offset,paletteram[offset] | (paletteram_2[offset] << 8));
1431 }
1432
changecolor_xxxxRRRRGGGGBBBB(int color,int data)1433 static INLINE void changecolor_xxxxRRRRGGGGBBBB(int color,int data)
1434 {
1435 int r,g,b;
1436
1437
1438 r = (data >> 8) & 0x0f;
1439 g = (data >> 4) & 0x0f;
1440 b = (data >> 0) & 0x0f;
1441
1442 r = (r << 4) | r;
1443 g = (g << 4) | g;
1444 b = (b << 4) | b;
1445
1446 palette_change_color(color,r,g,b);
1447 }
1448
WRITE_HANDLER(paletteram_xxxxRRRRGGGGBBBB_w)1449 WRITE_HANDLER( paletteram_xxxxRRRRGGGGBBBB_w )
1450 {
1451 paletteram[offset] = data;
1452 changecolor_xxxxRRRRGGGGBBBB(offset / 2,paletteram[offset & ~1] | (paletteram[offset | 1] << 8));
1453 }
1454
WRITE_HANDLER(paletteram_xxxxRRRRGGGGBBBB_swap_w)1455 WRITE_HANDLER( paletteram_xxxxRRRRGGGGBBBB_swap_w )
1456 {
1457 paletteram[offset] = data;
1458 changecolor_xxxxRRRRGGGGBBBB(offset / 2,paletteram[offset | 1] | (paletteram[offset & ~1] << 8));
1459 }
1460
WRITE_HANDLER(paletteram_xxxxRRRRGGGGBBBB_word_w)1461 WRITE_HANDLER( paletteram_xxxxRRRRGGGGBBBB_word_w )
1462 {
1463 int oldword = READ_WORD(&paletteram[offset]);
1464 int newword = COMBINE_WORD(oldword,data);
1465
1466
1467 WRITE_WORD(&paletteram[offset],newword);
1468 changecolor_xxxxRRRRGGGGBBBB(offset / 2,newword);
1469 }
1470
changecolor_RRRRGGGGBBBBxxxx(int color,int data)1471 static INLINE void changecolor_RRRRGGGGBBBBxxxx(int color,int data)
1472 {
1473 int r,g,b;
1474
1475
1476 r = (data >> 12) & 0x0f;
1477 g = (data >> 8) & 0x0f;
1478 b = (data >> 4) & 0x0f;
1479
1480 r = (r << 4) | r;
1481 g = (g << 4) | g;
1482 b = (b << 4) | b;
1483
1484 palette_change_color(color,r,g,b);
1485 }
1486
WRITE_HANDLER(paletteram_RRRRGGGGBBBBxxxx_swap_w)1487 WRITE_HANDLER( paletteram_RRRRGGGGBBBBxxxx_swap_w )
1488 {
1489 paletteram[offset] = data;
1490 changecolor_RRRRGGGGBBBBxxxx(offset / 2,paletteram[offset | 1] | (paletteram[offset & ~1] << 8));
1491 }
1492
WRITE_HANDLER(paletteram_RRRRGGGGBBBBxxxx_split1_w)1493 WRITE_HANDLER( paletteram_RRRRGGGGBBBBxxxx_split1_w )
1494 {
1495 paletteram[offset] = data;
1496 changecolor_RRRRGGGGBBBBxxxx(offset,paletteram[offset] | (paletteram_2[offset] << 8));
1497 }
1498
WRITE_HANDLER(paletteram_RRRRGGGGBBBBxxxx_split2_w)1499 WRITE_HANDLER( paletteram_RRRRGGGGBBBBxxxx_split2_w )
1500 {
1501 paletteram_2[offset] = data;
1502 changecolor_RRRRGGGGBBBBxxxx(offset,paletteram[offset] | (paletteram_2[offset] << 8));
1503 }
1504
WRITE_HANDLER(paletteram_RRRRGGGGBBBBxxxx_word_w)1505 WRITE_HANDLER( paletteram_RRRRGGGGBBBBxxxx_word_w )
1506 {
1507 int oldword = READ_WORD(&paletteram[offset]);
1508 int newword = COMBINE_WORD(oldword,data);
1509
1510
1511 WRITE_WORD(&paletteram[offset],newword);
1512 changecolor_RRRRGGGGBBBBxxxx(offset / 2,newword);
1513 }
1514
changecolor_BBBBGGGGRRRRxxxx(int color,int data)1515 static INLINE void changecolor_BBBBGGGGRRRRxxxx(int color,int data)
1516 {
1517 int r,g,b;
1518
1519
1520 r = (data >> 4) & 0x0f;
1521 g = (data >> 8) & 0x0f;
1522 b = (data >> 12) & 0x0f;
1523
1524 r = (r << 4) | r;
1525 g = (g << 4) | g;
1526 b = (b << 4) | b;
1527
1528 palette_change_color(color,r,g,b);
1529 }
1530
WRITE_HANDLER(paletteram_BBBBGGGGRRRRxxxx_swap_w)1531 WRITE_HANDLER( paletteram_BBBBGGGGRRRRxxxx_swap_w )
1532 {
1533 paletteram[offset] = data;
1534 changecolor_BBBBGGGGRRRRxxxx(offset / 2,paletteram[offset | 1] | (paletteram[offset & ~1] << 8));
1535 }
1536
WRITE_HANDLER(paletteram_BBBBGGGGRRRRxxxx_split1_w)1537 WRITE_HANDLER( paletteram_BBBBGGGGRRRRxxxx_split1_w )
1538 {
1539 paletteram[offset] = data;
1540 changecolor_BBBBGGGGRRRRxxxx(offset,paletteram[offset] | (paletteram_2[offset] << 8));
1541 }
1542
WRITE_HANDLER(paletteram_BBBBGGGGRRRRxxxx_split2_w)1543 WRITE_HANDLER( paletteram_BBBBGGGGRRRRxxxx_split2_w )
1544 {
1545 paletteram_2[offset] = data;
1546 changecolor_BBBBGGGGRRRRxxxx(offset,paletteram[offset] | (paletteram_2[offset] << 8));
1547 }
1548
WRITE_HANDLER(paletteram_BBBBGGGGRRRRxxxx_word_w)1549 WRITE_HANDLER( paletteram_BBBBGGGGRRRRxxxx_word_w )
1550 {
1551 int oldword = READ_WORD(&paletteram[offset]);
1552 int newword = COMBINE_WORD(oldword,data);
1553
1554
1555 WRITE_WORD(&paletteram[offset],newword);
1556 changecolor_BBBBGGGGRRRRxxxx(offset / 2,newword);
1557 }
1558
changecolor_xBBBBBGGGGGRRRRR(int color,int data)1559 static INLINE void changecolor_xBBBBBGGGGGRRRRR(int color,int data)
1560 {
1561 int r,g,b;
1562
1563
1564 r = (data >> 0) & 0x1f;
1565 g = (data >> 5) & 0x1f;
1566 b = (data >> 10) & 0x1f;
1567
1568 r = (r << 3) | (r >> 2);
1569 g = (g << 3) | (g >> 2);
1570 b = (b << 3) | (b >> 2);
1571
1572 palette_change_color(color,r,g,b);
1573 }
1574
WRITE_HANDLER(paletteram_xBBBBBGGGGGRRRRR_w)1575 WRITE_HANDLER( paletteram_xBBBBBGGGGGRRRRR_w )
1576 {
1577 paletteram[offset] = data;
1578 changecolor_xBBBBBGGGGGRRRRR(offset / 2,paletteram[offset & ~1] | (paletteram[offset | 1] << 8));
1579 }
1580
WRITE_HANDLER(paletteram_xBBBBBGGGGGRRRRR_swap_w)1581 WRITE_HANDLER( paletteram_xBBBBBGGGGGRRRRR_swap_w )
1582 {
1583 paletteram[offset] = data;
1584 changecolor_xBBBBBGGGGGRRRRR(offset / 2,paletteram[offset | 1] | (paletteram[offset & ~1] << 8));
1585 }
1586
WRITE_HANDLER(paletteram_xBBBBBGGGGGRRRRR_word_w)1587 WRITE_HANDLER( paletteram_xBBBBBGGGGGRRRRR_word_w )
1588 {
1589 int oldword = READ_WORD(&paletteram[offset]);
1590 int newword = COMBINE_WORD(oldword,data);
1591
1592
1593 WRITE_WORD(&paletteram[offset],newword);
1594 changecolor_xBBBBBGGGGGRRRRR(offset / 2,newword);
1595 }
1596
changecolor_xRRRRRGGGGGBBBBB(int color,int data)1597 static INLINE void changecolor_xRRRRRGGGGGBBBBB(int color,int data)
1598 {
1599 int r,g,b;
1600
1601
1602 r = (data >> 10) & 0x1f;
1603 g = (data >> 5) & 0x1f;
1604 b = (data >> 0) & 0x1f;
1605
1606 r = (r << 3) | (r >> 2);
1607 g = (g << 3) | (g >> 2);
1608 b = (b << 3) | (b >> 2);
1609
1610 palette_change_color(color,r,g,b);
1611 }
1612
WRITE_HANDLER(paletteram_xRRRRRGGGGGBBBBB_w)1613 WRITE_HANDLER( paletteram_xRRRRRGGGGGBBBBB_w )
1614 {
1615 paletteram[offset] = data;
1616 changecolor_xRRRRRGGGGGBBBBB(offset / 2,paletteram[offset & ~1] | (paletteram[offset | 1] << 8));
1617 }
1618
WRITE_HANDLER(paletteram_xRRRRRGGGGGBBBBB_word_w)1619 WRITE_HANDLER( paletteram_xRRRRRGGGGGBBBBB_word_w )
1620 {
1621 int oldword = READ_WORD(&paletteram[offset]);
1622 int newword = COMBINE_WORD(oldword,data);
1623
1624
1625 WRITE_WORD(&paletteram[offset],newword);
1626 changecolor_xRRRRRGGGGGBBBBB(offset / 2,newword);
1627 }
1628
changecolor_xGGGGGRRRRRBBBBB(int color,int data)1629 static INLINE void changecolor_xGGGGGRRRRRBBBBB(int color,int data)
1630 {
1631 int r,g,b;
1632
1633
1634 r = (data >> 5) & 0x1f;
1635 g = (data >> 10) & 0x1f;
1636 b = (data >> 0) & 0x1f;
1637
1638 r = (r << 3) | (r >> 2);
1639 g = (g << 3) | (g >> 2);
1640 b = (b << 3) | (b >> 2);
1641
1642 palette_change_color(color,r,g,b);
1643 }
1644
WRITE_HANDLER(paletteram_xGGGGGRRRRRBBBBB_word_w)1645 WRITE_HANDLER( paletteram_xGGGGGRRRRRBBBBB_word_w )
1646 {
1647 int oldword = READ_WORD(&paletteram[offset]);
1648 int newword = COMBINE_WORD(oldword,data);
1649
1650
1651 WRITE_WORD(&paletteram[offset],newword);
1652 changecolor_xGGGGGRRRRRBBBBB(offset / 2,newword);
1653 }
1654
changecolor_RRRRRGGGGGBBBBBx(int color,int data)1655 static INLINE void changecolor_RRRRRGGGGGBBBBBx(int color,int data)
1656 {
1657 int r,g,b;
1658
1659
1660 r = (data >> 11) & 0x1f;
1661 g = (data >> 6) & 0x1f;
1662 b = (data >> 1) & 0x1f;
1663
1664 r = (r << 3) | (r >> 2);
1665 g = (g << 3) | (g >> 2);
1666 b = (b << 3) | (b >> 2);
1667
1668 palette_change_color(color,r,g,b);
1669 }
1670
WRITE_HANDLER(paletteram_RRRRRGGGGGBBBBBx_w)1671 WRITE_HANDLER( paletteram_RRRRRGGGGGBBBBBx_w )
1672 {
1673 paletteram[offset] = data;
1674 changecolor_RRRRRGGGGGBBBBBx(offset / 2,paletteram[offset & ~1] | (paletteram[offset | 1] << 8));
1675 }
1676
WRITE_HANDLER(paletteram_RRRRRGGGGGBBBBBx_word_w)1677 WRITE_HANDLER( paletteram_RRRRRGGGGGBBBBBx_word_w )
1678 {
1679 int oldword = READ_WORD(&paletteram[offset]);
1680 int newword = COMBINE_WORD(oldword,data);
1681
1682
1683 WRITE_WORD(&paletteram[offset],newword);
1684 changecolor_RRRRRGGGGGBBBBBx(offset / 2,newword);
1685 }
1686
changecolor_IIIIRRRRGGGGBBBB(int color,int data)1687 static INLINE void changecolor_IIIIRRRRGGGGBBBB(int color,int data)
1688 {
1689 int i,r,g,b;
1690
1691
1692 static const int ztable[16] =
1693 { 0x0, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11 };
1694
1695 i = ztable[(data >> 12) & 15];
1696 r = ((data >> 8) & 15) * i;
1697 g = ((data >> 4) & 15) * i;
1698 b = ((data >> 0) & 15) * i;
1699
1700 palette_change_color(color,r,g,b);
1701 }
1702
WRITE_HANDLER(paletteram_IIIIRRRRGGGGBBBB_word_w)1703 WRITE_HANDLER( paletteram_IIIIRRRRGGGGBBBB_word_w )
1704 {
1705 int oldword = READ_WORD(&paletteram[offset]);
1706 int newword = COMBINE_WORD(oldword,data);
1707
1708
1709 WRITE_WORD(&paletteram[offset],newword);
1710 changecolor_IIIIRRRRGGGGBBBB(offset / 2,newword);
1711 }
1712
changecolor_RRRRGGGGBBBBIIII(int color,int data)1713 static INLINE void changecolor_RRRRGGGGBBBBIIII(int color,int data)
1714 {
1715 int i,r,g,b;
1716
1717
1718 static const int ztable[16] =
1719 { 0x0, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11 };
1720
1721 i = ztable[(data >> 0) & 15];
1722 r = ((data >> 12) & 15) * i;
1723 g = ((data >> 8) & 15) * i;
1724 b = ((data >> 4) & 15) * i;
1725
1726 palette_change_color(color,r,g,b);
1727 }
1728
WRITE_HANDLER(paletteram_RRRRGGGGBBBBIIII_word_w)1729 WRITE_HANDLER( paletteram_RRRRGGGGBBBBIIII_word_w )
1730 {
1731 int oldword = READ_WORD(&paletteram[offset]);
1732 int newword = COMBINE_WORD(oldword,data);
1733
1734
1735 WRITE_WORD(&paletteram[offset],newword);
1736 changecolor_RRRRGGGGBBBBIIII(offset / 2,newword);
1737 }
1738