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