1 // license:BSD-3-Clause
2 // copyright-holders:Nathan Woods, Raphael Nabet, R. Belmont
3 /***************************************************************************
4 
5     video/mac.c
6 
7     Macintosh video hardware
8 
9     Emulates the video hardware for compact Macintosh series (original
10     Macintosh (128k, 512k, 512ke), Macintosh Plus, Macintosh SE, Macintosh
11     Classic)
12 
13     Also emulates on-board video for systems with the
14     RBV, V8, Eagle, Sonora, and DAFB chips.
15 
16     ----------------------------------------------------------------------
17     Monitor sense codes
18 
19     Apple assigns 3 pins for monitor IDs.  These allow 8 possible codes:
20 
21     000 - color 2-Page Display (21")
22     001 - monochrome Full Page display (15")
23     010 - color 512x384 (12")
24     011 - monochrome 2 Page display (21")
25     100 - NTSC
26     101 - color Full Page display (15")
27     110 - High-Resolution Color (13" 640x480) or use "type 6" extended codes
28     111 - No monitor connected or use "type 7" extended codes
29 
30     For extended codes, you drive one of the 3 pins at a time and read the 2
31     undriven pins.  See http://support.apple.com/kb/TA21618?viewlocale=en_US
32     for details.
33 
34 Extended codes:
35 
36                     Sense 2 Low  Sense 1 Low   Sense 0 Low
37                     1 & 0        2 & 0         2 & 1
38 
39 Multiple Scan 14"    00           00           11
40 Multiple Scan 16"    00           10           11
41 Multiple Scan 21"    10           00           11
42 PAL Encoder          00           00           00
43 NTSC Encoder         01           01           00
44 VGA/Super VGA        01           01           11
45 RGB 16"              10           11           01
46 PAL Monitor          11           00           00
47 RGB 19"              11           10           10
48 Radius color TPD     11           00           01   (TPD = Two Page Display)
49 Radius mono TPD      11           01           00
50 Apple TPD            11           01           01
51 Apple color FPD      01           11           10   (FPD = Full Page Display)
52 
53 ***************************************************************************/
54 
55 
56 #include "emu.h"
57 #include "sound/asc.h"
58 #include "includes/mac.h"
59 #include "machine/ram.h"
60 #include "render.h"
61 
VIDEO_START_MEMBER(mac_state,mac)62 VIDEO_START_MEMBER(mac_state,mac)
63 {
64 }
65 
66 #define MAC_MAIN_SCREEN_BUF_OFFSET  0x5900
67 #define MAC_ALT_SCREEN_BUF_OFFSET   0xD900
68 
screen_update_mac(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)69 uint32_t mac_state::screen_update_mac(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
70 {
71 	uint32_t const video_base = m_ram->size() - (m_screen_buffer ? MAC_MAIN_SCREEN_BUF_OFFSET : MAC_ALT_SCREEN_BUF_OFFSET);
72 	uint16_t const *video_ram = (const uint16_t *) (m_ram->pointer() + video_base);
73 
74 	for (int y = 0; y < MAC_V_VIS; y++)
75 	{
76 		uint16_t *const line = &bitmap.pix(y);
77 
78 		for (int x = 0; x < MAC_H_VIS; x += 16)
79 		{
80 			uint16_t const word = *(video_ram++);
81 			for (int b = 0; b < 16; b++)
82 			{
83 				line[x + b] = (word >> (15 - b)) & 0x0001;
84 			}
85 		}
86 	}
87 	return 0;
88 }
89 
screen_update_macse30(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)90 uint32_t mac_state::screen_update_macse30(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
91 {
92 	uint32_t const video_base = (m_screen_buffer ? 0x8000 : 0) + (MAC_H_VIS/8);
93 	uint16_t const *const video_ram = (const uint16_t *) &m_vram[video_base/4];
94 
95 	for (int y = 0; y < MAC_V_VIS; y++)
96 	{
97 		uint16_t *const line = &bitmap.pix(y);
98 
99 		for (int x = 0; x < MAC_H_VIS; x += 16)
100 		{
101 			uint16_t const word = video_ram[((y * MAC_H_VIS)/16) + ((x/16)^1)];
102 			for (int b = 0; b < 16; b++)
103 			{
104 				line[x + b] = (word >> (15 - b)) & 0x0001;
105 			}
106 		}
107 	}
108 	return 0;
109 }
110 
111 // IIci/IIsi RAM-Based Video (RBV) and children: V8, Eagle, Spice, VASP, Sonora
112 
VIDEO_START_MEMBER(mac_state,macrbv)113 VIDEO_START_MEMBER(mac_state,macrbv)
114 {
115 }
116 
VIDEO_RESET_MEMBER(mac_state,maceagle)117 VIDEO_RESET_MEMBER(mac_state,maceagle)
118 {
119 	m_rbv_montype = 32;
120 	m_rbv_palette[0xfe] = 0xffffff;
121 	m_rbv_palette[0xff] = 0;
122 }
123 
VIDEO_RESET_MEMBER(mac_state,macrbv)124 VIDEO_RESET_MEMBER(mac_state,macrbv)
125 {
126 	int htotal, vtotal;
127 	double framerate;
128 	int view;
129 
130 	memset(m_rbv_regs, 0, sizeof(m_rbv_regs));
131 
132 	m_rbv_count = 0;
133 	m_rbv_clutoffs = 0;
134 	m_rbv_immed10wr = 0;
135 
136 	m_rbv_regs[2] = 0x7f;
137 	m_rbv_regs[3] = 0;
138 
139 	m_rbv_type = RBV_TYPE_RBV;
140 
141 	view = 0;
142 
143 	m_rbv_montype = m_montype.read_safe(2);
144 	rectangle visarea;
145 	switch (m_rbv_montype)
146 	{
147 		case 1: // 15" portrait display
148 			visarea.set(0, 640-1, 0, 870-1);
149 			htotal = 832;
150 			vtotal = 918;
151 			framerate = 75.0;
152 			view = 1;
153 			break;
154 
155 		case 2: // 12" RGB
156 			visarea.set(0, 512-1, 0, 384-1);
157 			htotal = 640;
158 			vtotal = 407;
159 			framerate = 60.15;
160 			break;
161 
162 		case 6: // 13" RGB
163 		default:
164 			visarea.set(0, 640-1, 0, 480-1);
165 			htotal = 800;
166 			vtotal = 525;
167 			framerate = 59.94;
168 			break;
169 	}
170 
171 //    logerror("RBV reset: monitor is %dx%d @ %f Hz\n", visarea.width(), visarea.height(), framerate);
172 	m_screen->configure(htotal, vtotal, visarea, HZ_TO_ATTOSECONDS(framerate));
173 	render_target *target = machine().render().first_target();
174 	target->set_view(view);
175 }
176 
VIDEO_RESET_MEMBER(mac_state,macsonora)177 VIDEO_RESET_MEMBER(mac_state,macsonora)
178 {
179 	int htotal, vtotal;
180 	double framerate;
181 	int view = 0;
182 
183 	memset(m_rbv_regs, 0, sizeof(m_rbv_regs));
184 
185 	m_rbv_count = 0;
186 	m_rbv_clutoffs = 0;
187 	m_rbv_immed10wr = 0;
188 
189 	m_rbv_regs[2] = 0x7f;
190 	m_rbv_regs[3] = 0;
191 
192 	m_rbv_type = RBV_TYPE_SONORA;
193 
194 	m_rbv_montype = m_montype.read_safe(2);
195 	rectangle visarea;
196 	switch (m_rbv_montype)
197 	{
198 		case 1: // 15" portrait display
199 			visarea.set(0, 640-1, 0, 870-1);
200 			htotal = 832;
201 			vtotal = 918;
202 			framerate = 75.0;
203 			view = 1;
204 			break;
205 
206 		case 2: // 12" RGB
207 			visarea.set(0, 512-1, 0, 384-1);
208 			htotal = 640;
209 			vtotal = 407;
210 			framerate = 60.15;
211 			break;
212 
213 		case 6: // 13" RGB
214 		default:
215 			visarea.set(0, 640-1, 0, 480-1);
216 			htotal = 800;
217 			vtotal = 525;
218 			framerate = 59.94;
219 			break;
220 	}
221 
222 //    logerror("Sonora reset: monitor is %dx%d @ %f Hz\n", visarea.width(), visarea.height(), framerate);
223 	m_screen->configure(htotal, vtotal, visarea, HZ_TO_ATTOSECONDS(framerate));
224 	render_target *target = machine().render().first_target();
225 	target->set_view(view);
226 }
227 
VIDEO_START_MEMBER(mac_state,macsonora)228 VIDEO_START_MEMBER(mac_state,macsonora)
229 {
230 	memset(m_rbv_regs, 0, sizeof(m_rbv_regs));
231 
232 	m_rbv_count = 0;
233 	m_rbv_clutoffs = 0;
234 	m_rbv_immed10wr = 0;
235 
236 	m_rbv_regs[2] = 0x7f;
237 	m_rbv_regs[3] = 0;
238 	m_rbv_regs[4] = 0x6;
239 	m_rbv_regs[5] = 0x3;
240 
241 	m_sonora_vctl[0] = 0x9f;
242 	m_sonora_vctl[1] = 0;
243 	m_sonora_vctl[2] = 0;
244 
245 	m_rbv_type = RBV_TYPE_SONORA;
246 }
247 
VIDEO_START_MEMBER(mac_state,macv8)248 VIDEO_START_MEMBER(mac_state,macv8)
249 {
250 	memset(m_rbv_regs, 0, sizeof(m_rbv_regs));
251 
252 	m_rbv_count = 0;
253 	m_rbv_clutoffs = 0;
254 	m_rbv_immed10wr = 0;
255 
256 	m_rbv_regs[0] = 0x4f;
257 	m_rbv_regs[1] = 0x06;
258 	m_rbv_regs[2] = 0x7f;
259 
260 	m_rbv_type = RBV_TYPE_V8;
261 }
262 
screen_update_macrbv(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)263 uint32_t mac_state::screen_update_macrbv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
264 {
265 	uint8_t const *vram8 = (uint8_t *)m_ram->pointer();
266 	int hres, vres;
267 
268 	switch (m_rbv_montype)
269 	{
270 		case 32: // classic II built-in display
271 			hres = MAC_H_VIS;
272 			vres = MAC_V_VIS;
273 			vram8 += 0x1f9a80;  // Classic II apparently doesn't use VRAM?
274 			break;
275 
276 		case 1: // 15" portrait display
277 			hres = 640;
278 			vres = 870;
279 			break;
280 
281 		case 2: // 12" RGB
282 			hres = 512;
283 			vres = 384;
284 			break;
285 
286 		case 6: // 13" RGB
287 		default:
288 			hres = 640;
289 			vres = 480;
290 			break;
291 	}
292 
293 	switch (m_rbv_regs[0x10] & 7)
294 	{
295 		case 0: // 1bpp
296 		{
297 			for (int y = 0; y < vres; y++)
298 			{
299 				uint32_t *scanline = &bitmap.pix(y);
300 				for (int x = 0; x < hres; x+=8)
301 				{
302 					uint8_t const pixels = vram8[(y * (hres/8)) + ((x/8)^3)];
303 
304 					*scanline++ = m_rbv_palette[0xfe|(pixels>>7)];
305 					*scanline++ = m_rbv_palette[0xfe|((pixels>>6)&1)];
306 					*scanline++ = m_rbv_palette[0xfe|((pixels>>5)&1)];
307 					*scanline++ = m_rbv_palette[0xfe|((pixels>>4)&1)];
308 					*scanline++ = m_rbv_palette[0xfe|((pixels>>3)&1)];
309 					*scanline++ = m_rbv_palette[0xfe|((pixels>>2)&1)];
310 					*scanline++ = m_rbv_palette[0xfe|((pixels>>1)&1)];
311 					*scanline++ = m_rbv_palette[0xfe|(pixels&1)];
312 				}
313 			}
314 		}
315 		break;
316 
317 		case 1: // 2bpp
318 		{
319 			for (int y = 0; y < vres; y++)
320 			{
321 				uint32_t *scanline = &bitmap.pix(y);
322 				for (int x = 0; x < hres/4; x++)
323 				{
324 					uint8_t const pixels = vram8[(y * (hres/4)) + (BYTE4_XOR_BE(x))];
325 
326 					*scanline++ = m_rbv_palette[0xfc|((pixels>>6)&3)];
327 					*scanline++ = m_rbv_palette[0xfc|((pixels>>4)&3)];
328 					*scanline++ = m_rbv_palette[0xfc|((pixels>>2)&3)];
329 					*scanline++ = m_rbv_palette[0xfc|(pixels&3)];
330 				}
331 			}
332 		}
333 		break;
334 
335 		case 2: // 4bpp
336 		{
337 			for (int y = 0; y < vres; y++)
338 			{
339 				uint32_t *scanline = &bitmap.pix(y);
340 
341 				for (int x = 0; x < hres/2; x++)
342 				{
343 					uint8_t const pixels = vram8[(y * (hres/2)) + (BYTE4_XOR_BE(x))];
344 
345 					*scanline++ = m_rbv_palette[0xf0|(pixels>>4)];
346 					*scanline++ = m_rbv_palette[0xf0|(pixels&0xf)];
347 				}
348 			}
349 		}
350 		break;
351 
352 		case 3: // 8bpp
353 		{
354 			for (int y = 0; y < vres; y++)
355 			{
356 				uint32_t *scanline = &bitmap.pix(y);
357 
358 				for (int x = 0; x < hres; x++)
359 				{
360 					uint8_t const pixels = vram8[(y * hres) + (BYTE4_XOR_BE(x))];
361 					*scanline++ = m_rbv_palette[pixels];
362 				}
363 			}
364 		}
365 	}
366 
367 	return 0;
368 }
369 
screen_update_macrbvvram(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)370 uint32_t mac_state::screen_update_macrbvvram(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
371 {
372 	int hres, vres;
373 	switch (m_rbv_montype)
374 	{
375 		case 1: // 15" portrait display
376 			hres = 640;
377 			vres = 870;
378 			break;
379 
380 		case 2: // 12" RGB
381 			hres = 512;
382 			vres = 384;
383 			break;
384 
385 		case 6: // 13" RGB
386 		default:
387 			hres = 640;
388 			vres = 480;
389 			break;
390 	}
391 
392 	switch (m_rbv_regs[0x10] & 7)
393 	{
394 		case 0: // 1bpp
395 		{
396 			uint8_t const *const vram8 = (uint8_t *)m_vram.target();
397 
398 			for (int y = 0; y < vres; y++)
399 			{
400 				uint32_t *scanline = &bitmap.pix(y);
401 				for (int x = 0; x < hres; x+=8)
402 				{
403 					uint8_t const pixels = vram8[(y * 0x400) + ((x/8)^3)];
404 
405 					*scanline++ = m_rbv_palette[0x7f|(pixels&0x80)];
406 					*scanline++ = m_rbv_palette[0x7f|((pixels<<1)&0x80)];
407 					*scanline++ = m_rbv_palette[0x7f|((pixels<<2)&0x80)];
408 					*scanline++ = m_rbv_palette[0x7f|((pixels<<3)&0x80)];
409 					*scanline++ = m_rbv_palette[0x7f|((pixels<<4)&0x80)];
410 					*scanline++ = m_rbv_palette[0x7f|((pixels<<5)&0x80)];
411 					*scanline++ = m_rbv_palette[0x7f|((pixels<<6)&0x80)];
412 					*scanline++ = m_rbv_palette[0x7f|((pixels<<7)&0x80)];
413 				}
414 			}
415 		}
416 		break;
417 
418 		case 1: // 2bpp
419 		{
420 			uint8_t const *const vram8 = (uint8_t *)m_vram.target();
421 
422 			for (int y = 0; y < vres; y++)
423 			{
424 				uint32_t *scanline = &bitmap.pix(y);
425 				for (int x = 0; x < hres/4; x++)
426 				{
427 					uint8_t const pixels = vram8[(y * (hres/4)) + (BYTE4_XOR_BE(x))];
428 
429 					*scanline++ = m_rbv_palette[0xfc|((pixels>>6)&3)];
430 					*scanline++ = m_rbv_palette[0xfc|((pixels>>4)&3)];
431 					*scanline++ = m_rbv_palette[0xfc|((pixels>>2)&3)];
432 					*scanline++ = m_rbv_palette[0xfc|(pixels&3)];
433 				}
434 			}
435 		}
436 		break;
437 
438 		case 2: // 4bpp
439 		{
440 			uint8_t const *const vram8 = (uint8_t *)m_vram.target();
441 
442 			for (int y = 0; y < vres; y++)
443 			{
444 				uint32_t *scanline = &bitmap.pix(y);
445 
446 				for (int x = 0; x < hres/2; x++)
447 				{
448 					uint8_t const pixels = vram8[(y * (hres/2)) + (BYTE4_XOR_BE(x))];
449 
450 					*scanline++ = m_rbv_palette[0xf0|(pixels>>4)];
451 					*scanline++ = m_rbv_palette[0xf0|(pixels&0xf)];
452 				}
453 			}
454 		}
455 		break;
456 
457 		case 3: // 8bpp
458 		{
459 			uint8_t const *const vram8 = (uint8_t *)m_vram.target();
460 
461 			for (int y = 0; y < vres; y++)
462 			{
463 				uint32_t *scanline = &bitmap.pix(y);
464 
465 				for (int x = 0; x < hres; x++)
466 				{
467 					uint8_t const pixels = vram8[(y * 2048) + (BYTE4_XOR_BE(x))];
468 					*scanline++ = m_rbv_palette[pixels];
469 				}
470 			}
471 		}
472 	}
473 
474 	return 0;
475 }
476 
screen_update_macv8(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)477 uint32_t mac_state::screen_update_macv8(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
478 {
479 	int hres, vres;
480 	switch (m_rbv_montype)
481 	{
482 		case 1: // 15" portrait display
483 			hres = 640;
484 			vres = 870;
485 			break;
486 
487 		case 2: // 12" RGB
488 			hres = 512;
489 			vres = 384;
490 			break;
491 
492 		case 6: // 13" RGB
493 		default:
494 			hres = 640;
495 			vres = 480;
496 			break;
497 	}
498 
499 	switch (m_rbv_regs[0x10] & 7)
500 	{
501 		case 0: // 1bpp
502 		{
503 			uint8_t const *const vram8 = (uint8_t *)m_vram.target();
504 
505 			for (int y = 0; y < vres; y++)
506 			{
507 				uint32_t *scanline = &bitmap.pix(y);
508 				for (int x = 0; x < hres; x+=8)
509 				{
510 					uint8_t const pixels = vram8[(y * 1024) + ((x/8)^3)];
511 
512 					*scanline++ = m_rbv_palette[0x7f|(pixels&0x80)];
513 					*scanline++ = m_rbv_palette[0x7f|((pixels<<1)&0x80)];
514 					*scanline++ = m_rbv_palette[0x7f|((pixels<<2)&0x80)];
515 					*scanline++ = m_rbv_palette[0x7f|((pixels<<3)&0x80)];
516 					*scanline++ = m_rbv_palette[0x7f|((pixels<<4)&0x80)];
517 					*scanline++ = m_rbv_palette[0x7f|((pixels<<5)&0x80)];
518 					*scanline++ = m_rbv_palette[0x7f|((pixels<<6)&0x80)];
519 					*scanline++ = m_rbv_palette[0x7f|((pixels<<7)&0x80)];
520 				}
521 			}
522 		}
523 		break;
524 
525 		case 1: // 2bpp
526 		{
527 			uint8_t const *const vram8 = (uint8_t *)m_vram.target();
528 
529 			for (int y = 0; y < vres; y++)
530 			{
531 				uint32_t *scanline = &bitmap.pix(y);
532 				for (int x = 0; x < hres/4; x++)
533 				{
534 					uint8_t const pixels = vram8[(y * 1024) + (BYTE4_XOR_BE(x))];
535 
536 					*scanline++ = m_rbv_palette[0x3f|(pixels&0xc0)];
537 					*scanline++ = m_rbv_palette[0x3f|((pixels<<2)&0xc0)];
538 					*scanline++ = m_rbv_palette[0x3f|((pixels<<4)&0xc0)];
539 					*scanline++ = m_rbv_palette[0x3f|((pixels<<6)&0xc0)];
540 				}
541 			}
542 		}
543 		break;
544 
545 		case 2: // 4bpp
546 		{
547 			uint8_t const *const vram8 = (uint8_t *)m_vram.target();
548 
549 			for (int y = 0; y < vres; y++)
550 			{
551 				uint32_t *scanline = &bitmap.pix(y);
552 
553 				for (int x = 0; x < hres/2; x++)
554 				{
555 					uint8_t const pixels = vram8[(y * 1024) + (BYTE4_XOR_BE(x))];
556 
557 					*scanline++ = m_rbv_palette[(pixels&0xf0) | 0xf];
558 					*scanline++ = m_rbv_palette[((pixels&0x0f)<<4) | 0xf];
559 				}
560 			}
561 		}
562 		break;
563 
564 		case 3: // 8bpp
565 		{
566 			uint8_t const *const vram8 = (uint8_t *)m_vram.target();
567 
568 			for (int y = 0; y < vres; y++)
569 			{
570 				uint32_t *scanline = &bitmap.pix(y);
571 
572 				for (int x = 0; x < hres; x++)
573 				{
574 					uint8_t const pixels = vram8[(y * 1024) + (BYTE4_XOR_BE(x))];
575 					*scanline++ = m_rbv_palette[pixels];
576 				}
577 			}
578 		}
579 		break;
580 	}
581 
582 	return 0;
583 }
584 
screen_update_macsonora(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)585 uint32_t mac_state::screen_update_macsonora(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
586 {
587 	int hres, vres, stride;
588 	switch (m_rbv_montype)
589 	{
590 		case 1: // 15" portrait display
591 			stride = hres = 640;
592 			vres = 870;
593 			break;
594 
595 		case 2: // 12" RGB
596 			stride = hres = 512;
597 			vres = 384;
598 			break;
599 
600 		case 6: // 13" RGB
601 		default:
602 			stride = hres = 640;
603 			vres = 480;
604 			break;
605 	}
606 
607 	// forced blank?
608 	if (m_sonora_vctl[0] & 0x80)
609 	{
610 		return 0;
611 	}
612 
613 	switch (m_sonora_vctl[1] & 7)
614 	{
615 		case 0: // 1bpp
616 		{
617 			uint8_t const *const vram8 = (uint8_t *)m_vram.target();
618 
619 			for (int y = 0; y < vres; y++)
620 			{
621 				uint32_t *scanline = &bitmap.pix(y);
622 				for (int x = 0; x < hres; x+=8)
623 				{
624 					uint8_t const pixels = vram8[(y * (stride/8)) + ((x/8)^3)];
625 
626 					*scanline++ = m_rbv_palette[0x7f|(pixels&0x80)];
627 					*scanline++ = m_rbv_palette[0x7f|((pixels<<1)&0x80)];
628 					*scanline++ = m_rbv_palette[0x7f|((pixels<<2)&0x80)];
629 					*scanline++ = m_rbv_palette[0x7f|((pixels<<3)&0x80)];
630 					*scanline++ = m_rbv_palette[0x7f|((pixels<<4)&0x80)];
631 					*scanline++ = m_rbv_palette[0x7f|((pixels<<5)&0x80)];
632 					*scanline++ = m_rbv_palette[0x7f|((pixels<<6)&0x80)];
633 					*scanline++ = m_rbv_palette[0x7f|((pixels<<7)&0x80)];
634 				}
635 			}
636 		}
637 		break;
638 
639 		case 1: // 2bpp
640 		{
641 			uint8_t const *const vram8 = (uint8_t *)m_vram.target();
642 
643 			for (int y = 0; y < vres; y++)
644 			{
645 				uint32_t *scanline = &bitmap.pix(y);
646 				for (int x = 0; x < hres/4; x++)
647 				{
648 					uint8_t const pixels = vram8[(y * (stride/4)) + (BYTE4_XOR_BE(x))];
649 
650 					*scanline++ = m_rbv_palette[0x3f|(pixels&0xc0)];
651 					*scanline++ = m_rbv_palette[0x3f|((pixels<<2)&0xc0)];
652 					*scanline++ = m_rbv_palette[0x3f|((pixels<<4)&0xc0)];
653 					*scanline++ = m_rbv_palette[0x3f|((pixels<<6)&0xc0)];
654 				}
655 			}
656 		}
657 		break;
658 
659 		case 2: // 4bpp
660 		{
661 			uint8_t const *const vram8 = (uint8_t *)m_vram.target();
662 
663 			for (int y = 0; y < vres; y++)
664 			{
665 				uint32_t *scanline = &bitmap.pix(y);
666 				for (int x = 0; x < hres/2; x++)
667 				{
668 					uint8_t const pixels = vram8[(y * (stride/2)) + (BYTE4_XOR_BE(x))];
669 
670 					*scanline++ = m_rbv_palette[(pixels&0xf0) | 0xf];
671 					*scanline++ = m_rbv_palette[((pixels&0x0f)<<4) | 0xf];
672 				}
673 			}
674 		}
675 		break;
676 
677 		case 3: // 8bpp
678 		{
679 			uint8_t const *const vram8 = (uint8_t *)m_vram.target();
680 
681 			for (int y = 0; y < vres; y++)
682 			{
683 				uint32_t *scanline = &bitmap.pix(y);
684 				for (int x = 0; x < hres; x++)
685 				{
686 					uint8_t const pixels = vram8[(y * stride) + (BYTE4_XOR_BE(x))];
687 					*scanline++ = m_rbv_palette[pixels];
688 				}
689 			}
690 		}
691 		break;
692 
693 		case 4: // 16bpp
694 		{
695 			uint16_t const *const vram16 = (uint16_t *)m_vram.target();
696 
697 			for (int y = 0; y < vres; y++)
698 			{
699 				uint32_t *scanline = &bitmap.pix(y);
700 				for (int x = 0; x < hres; x++)
701 				{
702 					uint16_t const pixels = vram16[(y * stride) + (x^1)];
703 					*scanline++ = rgb_t(((pixels>>10) & 0x1f)<<3, ((pixels>>5) & 0x1f)<<3, (pixels & 0x1f)<<3);
704 				}
705 			}
706 		}
707 		break;
708 	}
709 
710 	return 0;
711 }
712 
713