1 // license:BSD-3-Clause
2 // copyright-holders:Ville Linde
3
4 // Konami 0000057714 "GCU" 2D Graphics Chip
5
6 #include "emu.h"
7 #include "k057714.h"
8 #include "screen.h"
9
10
11 #define DUMP_VRAM 0
12 #define PRINT_GCU 0
13 #define PRINT_CMD_EXEC 0
14
15
16 DEFINE_DEVICE_TYPE(K057714, k057714_device, "k057714", "k057714_device GCU")
17
k057714_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)18 k057714_device::k057714_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
19 : device_t(mconfig, K057714, tag, owner, clock)
20 , m_irq(*this)
21 {
22 }
23
device_start()24 void k057714_device::device_start()
25 {
26 m_irq.resolve_safe();
27
28 m_vram = std::make_unique<uint32_t[]>(0x2000000/4);
29 memset(m_vram.get(), 0, 0x2000000);
30 }
31
device_reset()32 void k057714_device::device_reset()
33 {
34 m_vram_read_addr = 0;
35 m_command_fifo0_ptr = 0;
36 m_command_fifo1_ptr = 0;
37 m_vram_fifo0_addr = 0;
38 m_vram_fifo1_addr = 0;
39
40 m_fb_origin_x = 0;
41 m_fb_origin_y = 0;
42
43 m_reg_6c = 0;
44
45 for (auto & elem : m_frame)
46 {
47 elem.base = 0;
48 elem.width = 0;
49 elem.height = 0;
50 }
51 }
52
device_stop()53 void k057714_device::device_stop()
54 {
55 #if DUMP_VRAM
56 char filename[200];
57 sprintf(filename, "%s_vram.bin", basetag());
58 printf("dumping %s\n", filename);
59 FILE *file = fopen(filename, "wb");
60 int i;
61
62 for (i=0; i < 0x2000000/4; i++)
63 {
64 fputc((m_vram[i] >> 24) & 0xff, file);
65 fputc((m_vram[i] >> 16) & 0xff, file);
66 fputc((m_vram[i] >> 8) & 0xff, file);
67 fputc((m_vram[i] >> 0) & 0xff, file);
68 }
69
70 fclose(file);
71 #endif
72 }
73
74
read(offs_t offset)75 uint32_t k057714_device::read(offs_t offset)
76 {
77 int reg = offset * 4;
78
79 // VRAM Read
80 if (reg >= 0x80 && reg < 0x100)
81 {
82 return m_vram[m_vram_read_addr + offset - 0x20];
83 }
84
85 switch (reg)
86 {
87 case 0x78: // GCU Status
88 /* ppd checks bits 0x0041 of the upper halfword on interrupt */
89 return 0xffff0005;
90
91 default:
92 break;
93 }
94
95 return 0xffffffff;
96 }
97
write(offs_t offset,uint32_t data,uint32_t mem_mask)98 void k057714_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
99 {
100 int reg = offset * 4;
101
102 switch (reg)
103 {
104 case 0x10:
105 /* IRQ clear/enable; ppd writes bit off then on in response to interrupt */
106 /* it enables bits 0x41, but 0x01 seems to be the one it cares about */
107 if (ACCESSING_BITS_16_31 && (data & 0x00010000) == 0)
108 {
109 if (!m_irq.isnull())
110 {
111 m_irq(CLEAR_LINE);
112 }
113 }
114 if (ACCESSING_BITS_0_15)
115 {
116 m_layer_select = data;
117 #if PRINT_GCU
118 printf("%s_w: %02X, %08X, %08X\n", basetag(), reg, data, mem_mask);
119 #endif
120 }
121 break;
122
123 case 0x14: // ?
124 break;
125
126 case 0x18: // ?
127 break;
128
129 case 0x1c: // set to 1 on "media bus" access
130 if ((data >> 16) == 1)
131 {
132 m_ext_fifo_count = 0;
133 m_ext_fifo_line = 0;
134 }
135 break;
136
137 case 0x20: // Framebuffer 0 Origin(?)
138 if (ACCESSING_BITS_16_31)
139 m_frame[0].y = (data >> 16) & 0xffff;
140 if (ACCESSING_BITS_0_15)
141 m_frame[0].x = data & 0xffff;
142 break;
143
144 case 0x24: // Framebuffer 1 Origin(?)
145 if (ACCESSING_BITS_16_31)
146 m_frame[1].y = (data >> 16) & 0xffff;
147 if (ACCESSING_BITS_0_15)
148 m_frame[1].x = data & 0xffff;
149 break;
150
151 case 0x28: // Framebuffer 2 Origin(?)
152 if (ACCESSING_BITS_16_31)
153 m_frame[2].y = (data >> 16) & 0xffff;
154 if (ACCESSING_BITS_0_15)
155 m_frame[2].x = data & 0xffff;
156 break;
157
158 case 0x2c: // Framebuffer 3 Origin(?)
159 if (ACCESSING_BITS_16_31)
160 m_frame[3].y = (data >> 16) & 0xffff;
161 if (ACCESSING_BITS_0_15)
162 m_frame[3].x = data & 0xffff;
163 break;
164
165 case 0x30: // Framebuffer 0 Dimensions
166 if (ACCESSING_BITS_16_31)
167 m_frame[0].height = (data >> 16) & 0xffff;
168 if (ACCESSING_BITS_0_15)
169 m_frame[0].width = data & 0xffff;
170 #if PRINT_GCU
171 printf("%s FB0 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
172 #endif
173 break;
174
175 case 0x34: // Framebuffer 1 Dimensions
176 if (ACCESSING_BITS_16_31)
177 m_frame[1].height = (data >> 16) & 0xffff;
178 if (ACCESSING_BITS_0_15)
179 m_frame[1].width = data & 0xffff;
180 #if PRINT_GCU
181 printf("%s FB1 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
182 #endif
183 break;
184
185 case 0x38: // Framebuffer 2 Dimensions
186 if (ACCESSING_BITS_16_31)
187 m_frame[2].height = (data >> 16) & 0xffff;
188 if (ACCESSING_BITS_0_15)
189 m_frame[2].width = data & 0xffff;
190 #if PRINT_GCU
191 printf("%s FB2 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
192 #endif
193 break;
194
195 case 0x3c: // Framebuffer 3 Dimensions
196 if (ACCESSING_BITS_16_31)
197 m_frame[3].height = (data >> 16) & 0xffff;
198 if (ACCESSING_BITS_0_15)
199 m_frame[3].width = data & 0xffff;
200 #if PRINT_GCU
201 printf("%s FB3 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
202 #endif
203 break;
204
205 case 0x40: // Framebuffer 0 Base
206 m_frame[0].base = data;
207 #if PRINT_GCU
208 printf("%s FB0 Base: %08X\n", basetag(), data);
209 #endif
210 break;
211
212 case 0x44: // Framebuffer 1 Base
213 m_frame[1].base = data;
214 #if PRINT_GCU
215 printf("%s FB1 Base: %08X\n", basetag(), data);
216 #endif
217 break;
218
219 case 0x48: // Framebuffer 2 Base
220 m_frame[2].base = data;
221 #if PRINT_GCU
222 printf("%s FB2 Base: %08X\n", basetag(), data);
223 #endif
224 break;
225
226 case 0x4c: // Framebuffer 3 Base
227 m_frame[3].base = data;
228 #if PRINT_GCU
229 printf("%s FB3 Base: %08X\n", basetag(), data);
230 #endif
231 break;
232
233 case 0x54:
234 if (ACCESSING_BITS_16_31)
235 m_ext_fifo_num_lines = data >> 16;
236 if (ACCESSING_BITS_0_15)
237 m_ext_fifo_width = data & 0xffff;
238 break;
239
240 case 0x58:
241 m_ext_fifo_addr = (data & 0xffffff);
242 break;
243
244 case 0x5c: // VRAM Read Address
245 m_vram_read_addr = (data & 0xffffff) / 2;
246 break;
247
248 case 0x60: // VRAM Port 0 Write Address
249 m_vram_fifo0_addr = (data & 0xffffff) / 2;
250 break;
251
252 case 0x68: // VRAM Port 0/1 Mode
253 if (ACCESSING_BITS_16_31)
254 m_vram_fifo0_mode = data >> 16;
255 if (ACCESSING_BITS_0_15)
256 m_vram_fifo1_mode = data & 0xffff;
257 break;
258
259 case 0x70: // VRAM Port 0 Write FIFO
260 if (m_vram_fifo0_mode & 0x100)
261 {
262 // write to command fifo
263 m_command_fifo0[m_command_fifo0_ptr] = data;
264 m_command_fifo0_ptr++;
265
266 // execute when filled
267 if (m_command_fifo0_ptr >= 4)
268 {
269 //printf("GCU FIFO0 exec: %08X %08X %08X %08X\n", m_command_fifo0[0], m_command_fifo0[1], m_command_fifo0[2], m_command_fifo0[3]);
270 execute_command(m_command_fifo0);
271 m_command_fifo0_ptr = 0;
272 }
273 }
274 else
275 {
276 // write to VRAM fifo
277 m_vram[m_vram_fifo0_addr] = data;
278 m_vram_fifo0_addr++;
279 }
280 break;
281
282 case 0x64: // VRAM Port 1 Write Address
283 m_vram_fifo1_addr = (data & 0xffffff) / 2;
284 break;
285
286 case 0x74: // VRAM Port 1 Write FIFO
287 if (m_vram_fifo1_mode & 0x100)
288 {
289 // write to command fifo
290 m_command_fifo1[m_command_fifo1_ptr] = data;
291 m_command_fifo1_ptr++;
292
293 // execute when filled
294 if (m_command_fifo1_ptr >= 4)
295 {
296 //printf("GCU FIFO1 exec: %08X %08X %08X %08X\n", m_command_fifo1[0], m_command_fifo1[1], m_command_fifo1[2], m_command_fifo1[3]);
297 execute_command(m_command_fifo1);
298 m_command_fifo1_ptr = 0;
299 }
300 }
301 else
302 {
303 // write to VRAM fifo
304 m_vram[m_vram_fifo1_addr] = data;
305 m_vram_fifo1_addr++;
306 }
307 break;
308
309 case 0x6c:
310 if (ACCESSING_BITS_0_15)
311 {
312 m_reg_6c = data & 0xffff;
313 }
314 break;
315
316 default:
317 //printf("%s_w: %02X, %08X, %08X\n", basetag(), reg, data, mem_mask);
318 break;
319 }
320 }
321
fifo_w(offs_t offset,uint32_t data,uint32_t mem_mask)322 void k057714_device::fifo_w(offs_t offset, uint32_t data, uint32_t mem_mask)
323 {
324 if (ACCESSING_BITS_16_31)
325 {
326 if (m_ext_fifo_count != 0) // first access is a dummy write
327 {
328 int count = m_ext_fifo_count - 1;
329 uint32_t addr = (((m_ext_fifo_addr >> 10) + m_ext_fifo_line) * 1024) + count;
330
331 if ((count & 1) == 0)
332 {
333 m_vram[addr >> 1] &= 0x0000ffff;
334 m_vram[addr >> 1] |= (data & 0xffff0000);
335 }
336 else
337 {
338 m_vram[addr >> 1] &= 0xffff0000;
339 m_vram[addr >> 1] |= (data >> 16);
340 }
341 }
342 m_ext_fifo_count++;
343
344 if (m_ext_fifo_count > m_ext_fifo_width+1)
345 {
346 m_ext_fifo_line++;
347 m_ext_fifo_count = 0;
348 }
349 }
350 }
351
draw_frame(int frame,bitmap_ind16 & bitmap,const rectangle & cliprect,bool inverse_trans)352 void k057714_device::draw_frame(int frame, bitmap_ind16 &bitmap, const rectangle &cliprect, bool inverse_trans)
353 {
354 int height = m_frame[frame].height;
355 int width = m_frame[frame].width;
356
357 if (width == 0 || height == 0)
358 return;
359
360 uint16_t *vram16 = (uint16_t*)m_vram.get();
361
362 int fb_pitch = 1024;
363
364 uint16_t trans_value = inverse_trans ? 0x8000 : 0x0000;
365
366 if (m_frame[frame].y + height > cliprect.max_y)
367 height = cliprect.max_y - m_frame[frame].y;
368 if (m_frame[frame].x + width > cliprect.max_x)
369 width = cliprect.max_x - m_frame[frame].x;
370
371 for (int j = 0; j < height; j++)
372 {
373 uint16_t *const d = &bitmap.pix(j + m_frame[frame].y, m_frame[frame].x);
374 int li = (j * fb_pitch);
375 for (int i = 0; i < width; i++)
376 {
377 uint16_t pix = vram16[(m_frame[frame].base + li + i) ^ NATIVE_ENDIAN_VALUE_LE_BE(1, 0)];
378 if ((pix & 0x8000) != trans_value) {
379 d[i] = pix & 0x7fff;
380 }
381 }
382 }
383 }
384
draw(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)385 int k057714_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
386 {
387 int width = m_frame[0].width;
388 int height = m_frame[0].height;
389
390 if (width != 0 && height != 0)
391 {
392 rectangle visarea = screen.visible_area();
393 if ((visarea.max_x+1) != width || (visarea.max_y+1) != height)
394 {
395 visarea.max_x = width-1;
396 visarea.max_y = height-1;
397 screen.configure(width, height, visarea, screen.frame_period().attoseconds());
398 }
399 }
400
401 bitmap.fill(0, cliprect);
402
403 bool inverse_trans = false;
404
405 // most likely wrong, inverse transparency is only used by kbm
406 if ((m_reg_6c & 0xf) != 0)
407 inverse_trans = true;
408
409 draw_frame((m_layer_select >> 8) & 3, bitmap, cliprect, inverse_trans);
410 draw_frame((m_layer_select >> 10) & 3, bitmap, cliprect, inverse_trans);
411 draw_frame((m_layer_select >> 12) & 3, bitmap, cliprect, inverse_trans);
412 draw_frame((m_layer_select >> 14) & 3, bitmap, cliprect, inverse_trans);
413
414 return 0;
415 }
416
draw_object(uint32_t * cmd)417 void k057714_device::draw_object(uint32_t *cmd)
418 {
419 // 0x00: xxx----- -------- -------- -------- command (5)
420 // 0x00: ---x---- -------- -------- -------- 0: absolute coordinates
421 // 1: relative coordinates from framebuffer origin
422 // 0x00: ----xx-- -------- -------- -------- ?
423 // 0x00: -------- xxxxxxxx xxxxxxxx xxxxxxxx object data address in vram
424
425 // 0x01: -------- -------- ------xx xxxxxxxx object x
426 // 0x01: -------- xxxxxxxx xxxxxx-- -------- object y
427 // 0x01: -----x-- -------- -------- -------- object x flip
428 // 0x01: ----x--- -------- -------- -------- object y flip
429 // 0x01: --xx---- -------- -------- -------- object alpha enable (different blend modes?)
430 // 0x01: -x------ -------- -------- -------- object transparency enable (?)
431 // 0x01: x------- -------- -------- -------- inverse transparency? (used by kbm)
432
433 // 0x02: -------- -------- ------xx xxxxxxxx object width
434 // 0x02: -------- -----xxx xxxxxx-- -------- object x scale
435 // 0x02: xxxxx--- -------- -------- -------- ?
436 // 0x02: -----xxx xx------ -------- -------- translucency
437 // 0x02: -------- --xxx--- -------- -------- ?
438
439 // 0x03: -------- -------- ------xx xxxxxxxx object height
440 // 0x03: -------- -----xxx xxxxxx-- -------- object y scale
441 // 0x03: xxxxx--- -------- -------- -------- ?
442 // 0x03: -----xxx xx------ -------- -------- ?
443 // 0x03: -------- --xxx--- -------- -------- ?
444
445 int x = cmd[1] & 0x3ff;
446 int y = (cmd[1] >> 10) & 0x3fff;
447 int width = (cmd[2] & 0x3ff) + 1;
448 int height = (cmd[3] & 0x3ff) + 1;
449 int xscale = (cmd[2] >> 10) & 0x1ff;
450 int yscale = (cmd[3] >> 10) & 0x1ff;
451 bool xflip = (cmd[1] & 0x04000000) ? true : false;
452 bool yflip = (cmd[1] & 0x08000000) ? true : false;
453 bool alpha_enable = (cmd[1] & 0x30000000) ? true : false;
454 bool trans_enable = (cmd[1] & 0xc0000000) ? true : false;
455 uint32_t address = cmd[0] & 0xffffff;
456 int alpha_level = (cmd[2] >> 22) & 0x1f;
457 bool relative_coords = (cmd[0] & 0x10000000) ? true : false;
458
459 uint16_t trans_value = (cmd[1] & 0x80000000) ? 0x0000 : 0x8000;
460
461 if (relative_coords)
462 {
463 x += m_fb_origin_x;
464 y += m_fb_origin_y;
465 }
466
467 uint16_t *vram16 = (uint16_t*)m_vram.get();
468
469 if (xscale == 0 || yscale == 0)
470 {
471 return;
472 }
473
474 #if PRINT_CMD_EXEC
475 printf("%s Draw Object %08X, x %d, y %d, w %d, h %d, sx: %f, sy: %f [%08X %08X %08X %08X]\n", basetag(), address, x, y, width, height, (float)(xscale) / 64.0f, (float)(yscale) / 64.0f, cmd[0], cmd[1], cmd[2], cmd[3]);
476 #endif
477
478 width = (((width * 65536) / xscale) * 64) / 65536;
479 height = (((height * 65536) / yscale) * 64) / 65536;
480
481 int fb_width = m_frame[0].width;
482 int fb_height = m_frame[0].height;
483
484 if (width > fb_width)
485 width = fb_width;
486 if (height > fb_height)
487 height = fb_height;
488
489 int fb_pitch = 1024;
490
491 int v = 0;
492 for (int j=0; j < height; j++)
493 {
494 int index;
495 int xinc;
496 uint32_t fbaddr = ((j+y) * fb_pitch) + x;
497
498 if (yflip)
499 {
500 index = address + ((height - 1 - (v >> 6)) * 1024);
501 }
502 else
503 {
504 index = address + ((v >> 6) * 1024);
505 }
506
507 if (xflip)
508 {
509 fbaddr += width;
510 xinc = -1;
511 }
512 else
513 {
514 xinc = 1;
515 }
516
517 int u = 0;
518 for (int i=0; i < width; i++)
519 {
520 uint16_t pix = vram16[((index + (u >> 6)) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)) & 0xffffff];
521 bool draw = !trans_enable || (trans_enable && ((pix & 0x8000) == trans_value));
522 if (alpha_enable)
523 {
524 if (draw)
525 {
526 if ((pix & 0x7fff) != 0)
527 {
528 uint16_t srcpix = vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
529
530 uint32_t sr = (srcpix >> 10) & 0x1f;
531 uint32_t sg = (srcpix >> 5) & 0x1f;
532 uint32_t sb = (srcpix >> 0) & 0x1f;
533 uint32_t r = (pix >> 10) & 0x1f;
534 uint32_t g = (pix >> 5) & 0x1f;
535 uint32_t b = (pix >> 0) & 0x1f;
536
537 sr += (r * alpha_level) >> 4;
538 sg += (g * alpha_level) >> 4;
539 sb += (b * alpha_level) >> 4;
540
541 if (sr > 0x1f) sr = 0x1f;
542 if (sg > 0x1f) sg = 0x1f;
543 if (sb > 0x1f) sb = 0x1f;
544
545 vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = (sr << 10) | (sg << 5) | sb | (pix & 0x8000);
546 }
547 }
548 }
549 else
550 {
551 if (draw)
552 {
553 vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = (pix & 0xffff);
554 }
555 }
556
557 fbaddr += xinc;
558 u += xscale;
559 }
560
561 v += yscale;
562 }
563 }
564
fill_rect(uint32_t * cmd)565 void k057714_device::fill_rect(uint32_t *cmd)
566 {
567 // 0x00: xxx----- -------- -------- -------- command (4)
568 // 0x00: ---x---- -------- -------- -------- 0: absolute coordinates
569 // 1: relative coordinates from framebuffer origin
570 // 0x00: ----xx-- -------- -------- -------- ?
571 // 0x00: -------- -------- ------xx xxxxxxxx width
572 // 0x00: -------- ----xxxx xxxxxx-- -------- height
573
574 // 0x01: -------- -------- ------xx xxxxxxxx x
575 // 0x01: -------- xxxxxxxx xxxxxx-- -------- y
576 // 0x01: ---x---- -------- -------- -------- ?
577
578 // 0x02: xxxxxxxx xxxxxxxx -------- -------- fill pattern pixel 0
579 // 0x02: -------- -------- xxxxxxxx xxxxxxxx fill pattern pixel 1
580
581 // 0x03: xxxxxxxx xxxxxxxx -------- -------- fill pattern pixel 2
582 // 0x03: -------- -------- xxxxxxxx xxxxxxxx fill pattern pixel 3
583
584 int x = cmd[1] & 0x3ff;
585 int y = (cmd[1] >> 10) & 0x3fff;
586 int width = (cmd[0] & 0x3ff) + 1;
587 int height = ((cmd[0] >> 10) & 0x3ff) + 1;
588 bool relative_coords = (cmd[0] & 0x10000000) ? true : false;
589
590 if (relative_coords)
591 {
592 x += m_fb_origin_x;
593 y += m_fb_origin_y;
594 }
595
596 uint16_t color[4];
597 color[0] = (cmd[2] >> 16);
598 color[1] = (cmd[2] & 0xffff);
599 color[2] = (cmd[3] >> 16);
600 color[3] = (cmd[3] & 0xffff);
601
602 #if PRINT_CMD_EXEC
603 printf("%s Fill Rect x %d, y %d, w %d, h %d, %08X %08X [%08X %08X %08X %08X]\n", basetag(), x, y, width, height, cmd[2], cmd[3], cmd[0], cmd[1], cmd[2], cmd[3]);
604 #endif
605
606 int x1 = x;
607 int x2 = x + width;
608 int y1 = y;
609 int y2 = y + height;
610
611 uint16_t *vram16 = (uint16_t*)m_vram.get();
612
613 int fb_pitch = 1024;
614
615 for (int j=y1; j < y2; j++)
616 {
617 uint32_t fbaddr = j * fb_pitch;
618 for (int i=x1; i < x2; i++)
619 {
620 vram16[(fbaddr+i) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = color[i&3];
621 }
622 }
623 }
624
draw_character(uint32_t * cmd)625 void k057714_device::draw_character(uint32_t *cmd)
626 {
627 // 0x00: xxx----- -------- -------- -------- command (7)
628 // 0x00: ---x---- -------- -------- -------- 0: absolute coordinates
629 // 1: relative coordinates from framebuffer base (unverified, should be same as other operations)
630 // 0x00: -------- xxxxxxxx xxxxxxxx xxxxxxxx character data address in vram
631
632 // 0x01: -------- -------- ------xx xxxxxxxx character x
633 // 0x01: -------- xxxxxxxx xxxxxx-- -------- character y
634 // 0x01: -------x -------- -------- -------- double height
635 // 0x01: --x----- -------- -------- -------- ?
636 // 0x01: -x------ -------- -------- -------- transparency enable
637
638 // 0x02: xxxxxxxx xxxxxxxx -------- -------- color 0
639 // 0x02: -------- -------- xxxxxxxx xxxxxxxx color 1
640
641 // 0x03: xxxxxxxx xxxxxxxx -------- -------- color 2
642 // 0x03: -------- -------- xxxxxxxx xxxxxxxx color 3
643
644 int x = cmd[1] & 0x3ff;
645 int y = (cmd[1] >> 10) & 0x3fff;
646 uint32_t address = cmd[0] & 0xffffff;
647 uint16_t color[4];
648 bool relative_coords = (cmd[0] & 0x10000000) ? true : false;
649 bool double_height = (cmd[1] & 0x01000000) ? true : false;
650 bool trans_enable = (cmd[1] & 0x40000000) ? true : false;
651
652 if (relative_coords)
653 {
654 x += m_fb_origin_x;
655 y += m_fb_origin_y;
656 }
657
658 color[0] = cmd[2] >> 16;
659 color[1] = cmd[2] & 0xffff;
660 color[2] = cmd[3] >> 16;
661 color[3] = cmd[3] & 0xffff;
662
663 #if PRINT_CMD_EXEC
664 printf("%s Draw Char %08X, x %d, y %d [%08X %08X %08X %08X]\n", basetag(), address, x, y, cmd[0], cmd[1], cmd[2], cmd[3]);
665 #endif
666
667 uint16_t *vram16 = (uint16_t*)m_vram.get();
668 int fb_pitch = 1024;
669 int height = double_height ? 16 : 8;
670
671 for (int j=0; j < height; j++)
672 {
673 uint32_t fbaddr = (y+j) * fb_pitch;
674 uint16_t line = vram16[address ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
675
676 address += 4;
677
678 for (int i=0; i < 8; i++)
679 {
680 int p = (line >> ((7-i) * 2)) & 3;
681 bool draw = !trans_enable || (trans_enable && (color[p] & 0x8000));
682 if (draw)
683 vram16[(fbaddr+x+i) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = color[p];
684 }
685 }
686 }
687
fb_config(uint32_t * cmd)688 void k057714_device::fb_config(uint32_t *cmd)
689 {
690 // 0x00: xxx----- -------- -------- -------- command (3)
691
692 // 0x01: -------- -------- -------- -------- unused?
693
694 // 0x02: -------- -------- ------xx xxxxxxxx Framebuffer Origin X
695
696 // 0x03: -------- -------- --xxxxxx xxxxxxxx Framebuffer Origin Y
697
698 #if PRINT_CMD_EXEC
699 printf("%s FB Config %08X %08X %08X %08X\n", basetag(), cmd[0], cmd[1], cmd[2], cmd[3]);
700 #endif
701
702 m_fb_origin_x = cmd[2] & 0x3ff;
703 m_fb_origin_y = cmd[3] & 0x3fff;
704 }
705
execute_display_list(uint32_t addr)706 void k057714_device::execute_display_list(uint32_t addr)
707 {
708 bool end = false;
709
710 int counter = 0;
711
712 #if PRINT_CMD_EXEC
713 printf("%s Exec Display List %08X\n", basetag(), addr);
714 #endif
715
716 addr /= 2;
717 while (!end && counter < 0x1000 && addr < (0x2000000/4))
718 {
719 uint32_t *cmd = &m_vram[addr];
720 addr += 4;
721
722 int command = (cmd[0] >> 29) & 0x7;
723
724 switch (command)
725 {
726 case 0: // NOP?
727 break;
728
729 case 1: // Execute display list
730 execute_display_list(cmd[0] & 0xffffff);
731 break;
732
733 case 2: // End of display list
734 end = true;
735 break;
736
737 case 3: // Framebuffer config
738 fb_config(cmd);
739 break;
740
741 case 4: // Fill rectangle
742 fill_rect(cmd);
743 break;
744
745 case 5: // Draw object
746 draw_object(cmd);
747 break;
748
749 case 6:
750 case 7: // Draw 8x8 character (2 bits per pixel)
751 draw_character(cmd);
752 break;
753
754 default:
755 printf("GCU Unknown command %08X %08X %08X %08X\n", cmd[0], cmd[1], cmd[2], cmd[3]);
756 break;
757 }
758 counter++;
759 };
760 }
761
execute_command(uint32_t * cmd)762 void k057714_device::execute_command(uint32_t* cmd)
763 {
764 int command = (cmd[0] >> 29) & 0x7;
765
766 #if PRINT_CMD_EXEC
767 printf("%s Exec Command %08X, %08X, %08X, %08X\n", basetag(), cmd[0], cmd[1], cmd[2], cmd[3]);
768 #endif
769
770 switch (command)
771 {
772 case 0: // NOP?
773 break;
774
775 case 1: // Execute display list
776 execute_display_list(cmd[0] & 0xffffff);
777 break;
778
779 case 2: // End of display list
780 break;
781
782 case 3: // Framebuffer config
783 fb_config(cmd);
784 break;
785
786 case 4: // Fill rectangle
787 fill_rect(cmd);
788 break;
789
790 case 5: // Draw object
791 draw_object(cmd);
792 break;
793
794 case 6:
795 case 7: // Draw 8x8 character (2 bits per pixel)
796 draw_character(cmd);
797 break;
798
799 default:
800 printf("GCU Unknown command %08X %08X %08X %08X\n", cmd[0], cmd[1], cmd[2], cmd[3]);
801 break;
802 }
803 }
804