1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3 #include "emu.h"
4 #include "k001005.h"
5
6 /*****************************************************************************/
7 /* Konami K001005 Polygon Renderer (KS10071) */
8
9 /***************************************************************************/
10 /* */
11 /* 001005 */
12 /* */
13 /***************************************************************************/
14
15 /*
16 TODO:
17 - Fog equation and parameters are probably not accurate.
18 - Winding Heat (and maybe others) have slight Z-fighting problems.
19 - 3D in Solar Assault title isn't properly turned off (the SHARC keeps rendering 3D).
20
21 */
22
23 #define LOG_POLY_FIFO 0
24
25
k001005_renderer(device_t & parent,screen_device & screen,device_t * k001006)26 k001005_renderer::k001005_renderer(device_t &parent, screen_device &screen, device_t *k001006)
27 : poly_manager<float, k001005_polydata, 8, 50000>(screen)
28 {
29 m_k001006 = k001006;
30
31 int width = screen.width();
32 int height = screen.height();
33
34 m_fb[0] = std::make_unique<bitmap_rgb32>( width, height);
35 m_fb[1] = std::make_unique<bitmap_rgb32>( width, height);
36
37 m_zb = std::make_unique<bitmap_ind32>(width, height);
38
39 m_3dfifo = std::make_unique<uint32_t[]>(0x10000);
40 m_3dfifo_ptr = 0;
41 m_fb_page = 0;
42
43 m_cliprect = screen.cliprect();
44
45 for (int k=0; k < 8; k++)
46 {
47 m_tex_mirror_table[0][k] = std::make_unique<int[]>(128);
48 m_tex_mirror_table[1][k] = std::make_unique<int[]>(128);
49
50 int size = (k+1)*8;
51
52 for (int i=0; i < 128; i++)
53 {
54 m_tex_mirror_table[0][k][i] = i % size;
55 m_tex_mirror_table[1][k][i] = (i % (size*2)) >= size ? ((size - 1) - (i % size)) : (i % size);
56 }
57 }
58
59 // save state
60 parent.save_pointer(NAME(m_3dfifo), 0x10000);
61 parent.save_item(NAME(m_3dfifo_ptr));
62 parent.save_item(NAME(*m_fb[0]));
63 parent.save_item(NAME(*m_fb[1]));
64 parent.save_item(NAME(*m_zb));
65 parent.save_item(NAME(m_fb_page));
66 parent.save_item(NAME(m_light_r));
67 parent.save_item(NAME(m_light_g));
68 parent.save_item(NAME(m_light_b));
69 parent.save_item(NAME(m_ambient_r));
70 parent.save_item(NAME(m_ambient_g));
71 parent.save_item(NAME(m_ambient_b));
72 parent.save_item(NAME(m_fog_r));
73 parent.save_item(NAME(m_fog_g));
74 parent.save_item(NAME(m_fog_b));
75 parent.save_item(NAME(m_far_z));
76
77 }
78
reset()79 void k001005_renderer::reset()
80 {
81 m_3dfifo_ptr = 0;
82 }
83
push_data(uint32_t data)84 void k001005_renderer::push_data(uint32_t data)
85 {
86 // process the current vertex data if a sync command is being sent (usually means the global registers are being changed)
87 if (data == 0x80000000)
88 {
89 render_polygons();
90 }
91
92 m_3dfifo[m_3dfifo_ptr++] = data;
93 }
94
swap_buffers()95 void k001005_renderer::swap_buffers()
96 {
97 m_fb_page ^= 1;
98
99 m_fb[m_fb_page]->fill(0, m_cliprect);
100
101 float zvalue = 10000000000.0f;
102 m_zb->fill(*(int*)&zvalue, m_cliprect);
103 }
104
fifo_filled()105 bool k001005_renderer::fifo_filled()
106 {
107 return m_3dfifo_ptr > 0;
108 }
109
set_param(k001005_param param,uint32_t value)110 void k001005_renderer::set_param(k001005_param param, uint32_t value)
111 {
112 switch (param)
113 {
114 case K001005_LIGHT_R: m_light_r = value; break;
115 case K001005_LIGHT_G: m_light_g = value; break;
116 case K001005_LIGHT_B: m_light_b = value; break;
117 case K001005_AMBIENT_R: m_ambient_r = value; break;
118 case K001005_AMBIENT_G: m_ambient_g = value; break;
119 case K001005_AMBIENT_B: m_ambient_b = value; break;
120 case K001005_FOG_R: m_fog_r = value; break;
121 case K001005_FOG_G: m_fog_g = value; break;
122 case K001005_FOG_B: m_fog_b = value; break;
123 case K001005_FAR_Z:
124 {
125 uint32_t fz = value << 11;
126 m_far_z = *(float*)&fz;
127 if (m_far_z == 0.0f) // just in case...
128 m_far_z = 1.0f;
129 break;
130 }
131 }
132 }
133
render_polygons()134 void k001005_renderer::render_polygons()
135 {
136 vertex_t v[4];
137 int poly_type;
138 int brightness;
139
140 vertex_t *vertex1;
141 vertex_t *vertex2;
142 vertex_t *vertex3;
143 vertex_t *vertex4;
144
145 uint32_t *fifo = m_3dfifo.get();
146
147 const rectangle& visarea = screen().visible_area();
148
149 int index = 0;
150
151 float fog_density = 1.5f;
152
153 render_delegate rd_scan_2d = render_delegate(&k001005_renderer::draw_scanline_2d, this);
154 render_delegate rd_scan_tex2d = render_delegate(&k001005_renderer::draw_scanline_2d_tex, this);
155 render_delegate rd_scan = render_delegate(&k001005_renderer::draw_scanline, this);
156 render_delegate rd_scan_tex = render_delegate(&k001005_renderer::draw_scanline_tex, this);
157 render_delegate rd_scan_gour_blend = render_delegate(&k001005_renderer::draw_scanline_gouraud_blend, this);
158
159 do
160 {
161 uint32_t cmd = fifo[index++];
162
163 // Current guesswork on the command word bits:
164 // 0x01: Z-buffer disable?
165 // 0x02: Almost always set (only exception is 0x80000020 in Thunder Hurricane attract mode)
166 // 0x04:
167 // 0x08:
168 // 0x10: Texture mirror enable
169 // 0x20: Gouraud shading enable?
170 // 0x40: Unused?
171 // 0x80: Used by textured polygons.
172 // 0x100: Alpha blending? Only used by Winding Heat car selection so far.
173
174 if (cmd == 0x800000ae || cmd == 0x8000008e || cmd == 0x80000096 || cmd == 0x800000b6 ||
175 cmd == 0x8000002e || cmd == 0x8000000e || cmd == 0x80000016 || cmd == 0x80000036 ||
176 cmd == 0x800000aa || cmd == 0x800000a8 || cmd == 0x800000b2 || cmd == 0x8000009e ||
177 cmd == 0x80000092 || cmd == 0x8000008a || cmd == 0x80000094 || cmd == 0x8000009a ||
178 cmd == 0x8000009c || cmd == 0x8000008c || cmd == 0x800000ac || cmd == 0x800000b4)
179 {
180 // 0x00: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Command
181 //
182 // 0x01: xxxx---- -------- -------- -------- Texture palette
183 // 0x01: ----xx-- -------- -------- -------- Unknown flags, set by commands 0x7b...0x7e
184 // 0x01: ------xx x------- -------- -------- Texture width / 8 - 1
185 // 0x01: -------- -xxx---- -------- -------- Texture height / 8 - 1
186 // 0x01: -------- -------x xxxx---- -------- Texture page
187 // 0x01: -------- -------- ----x-x- x-x-x-x- Texture X / 8
188 // 0x01: -------- -------- -----x-x -x-x-x-x Texture Y / 8
189
190 // texture, Z
191
192 int tex_x, tex_y;
193 uint32_t color = 0;
194 k001005_polydata &extra = object_data_alloc();
195
196 uint32_t header = fifo[index++];
197
198 int last_vertex = 0;
199 int vert_num = 0;
200 do
201 {
202 int x, y, z;
203 int16_t tu, tv;
204
205 x = (fifo[index] >> 0) & 0x3fff;
206 y = (fifo[index] >> 16) & 0x1fff;
207 x |= ((x & 0x2000) ? 0xffffc000 : 0);
208 y |= ((y & 0x1000) ? 0xffffe000 : 0);
209
210 poly_type = fifo[index] & 0x4000; // 0 = triangle, 1 = quad
211 last_vertex = fifo[index] & 0x8000;
212 index++;
213
214 z = fifo[index] & 0xffffff00;
215 brightness = fifo[index] & 0xff;
216 index++;
217
218 if (last_vertex)
219 {
220 color = fifo[index++];
221 }
222
223 tu = (fifo[index] >> 16) & 0xffff;
224 tv = (fifo[index] & 0xffff);
225 index++;
226
227 v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
228 v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
229 v[vert_num].p[POLY_Z] = *(float*)(&z);
230 v[vert_num].p[POLY_W] = 1.0f / v[vert_num].p[POLY_Z];
231 v[vert_num].p[POLY_U] = tu * v[vert_num].p[POLY_W];
232 v[vert_num].p[POLY_V] = tv * v[vert_num].p[POLY_W];
233 v[vert_num].p[POLY_BRI] = brightness;
234 v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) * ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) ))) * 65536.0f;
235 //v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / far_z) ))) * 65536.0f;
236 if (v[vert_num].p[POLY_FOG] < 0.0f) v[vert_num].p[POLY_FOG] = 0.0f;
237 if (v[vert_num].p[POLY_FOG] > 65536.0f) v[vert_num].p[POLY_FOG] = 65536.0f;
238 vert_num++;
239 }
240 while (!last_vertex);
241
242 tex_y = ((header & 0x400) >> 5) |
243 ((header & 0x100) >> 4) |
244 ((header & 0x040) >> 3) |
245 ((header & 0x010) >> 2) |
246 ((header & 0x004) >> 1) |
247 ((header & 0x001) >> 0);
248
249 tex_x = ((header & 0x800) >> 6) |
250 ((header & 0x200) >> 5) |
251 ((header & 0x080) >> 4) |
252 ((header & 0x020) >> 3) |
253 ((header & 0x008) >> 2) |
254 ((header & 0x002) >> 1);
255
256 extra.texture_x = tex_x * 8;
257 extra.texture_y = tex_y * 8;
258 extra.texture_width = (header >> 23) & 0x7;
259 extra.texture_height = (header >> 20) & 0x7;
260 extra.texture_page = (header >> 12) & 0x1f;
261 extra.texture_palette = (header >> 28) & 0xf;
262 extra.texture_mirror_x = ((cmd & 0x10) ? 0x1 : 0);
263 extra.texture_mirror_y = ((cmd & 0x10) ? 0x1 : 0);
264 extra.color = color;
265 extra.light_r = m_light_r; extra.light_g = m_light_g; extra.light_b = m_light_b;
266 extra.ambient_r = m_ambient_r; extra.ambient_g = m_ambient_g; extra.ambient_b = m_ambient_b;
267 extra.fog_r = m_fog_r; extra.fog_g = m_fog_g; extra.fog_b = m_fog_b;
268 extra.flags = cmd;
269
270 if ((cmd & 0x20) == 0) // possibly enable flag for gouraud shading (fixes some shading errors)
271 {
272 v[0].p[POLY_BRI] = brightness;
273 v[1].p[POLY_BRI] = brightness;
274 }
275
276 if (poly_type == 0) // triangle
277 {
278 if (vert_num == 1)
279 {
280 vertex1 = &m_prev_v[2];
281 vertex2 = &m_prev_v[3];
282 vertex3 = &v[0];
283 }
284 else if (vert_num == 2)
285 {
286 vertex1 = &m_prev_v[3];
287 vertex2 = &v[0];
288 vertex3 = &v[1];
289 }
290 else
291 {
292 vertex1 = &v[0];
293 vertex2 = &v[1];
294 vertex3 = &v[2];
295 }
296
297 render_triangle(m_cliprect, rd_scan_tex, 6, *vertex1, *vertex2, *vertex3);
298
299 memcpy(&m_prev_v[1], vertex1, sizeof(vertex_t));
300 memcpy(&m_prev_v[2], vertex2, sizeof(vertex_t));
301 memcpy(&m_prev_v[3], vertex3, sizeof(vertex_t));
302 }
303 else // quad
304 {
305 if (vert_num == 1)
306 {
307 vertex1 = &m_prev_v[1];
308 vertex2 = &m_prev_v[2];
309 vertex3 = &m_prev_v[3];
310 vertex4 = &v[0];
311 }
312 else if (vert_num == 2)
313 {
314 vertex1 = &m_prev_v[2];
315 vertex2 = &m_prev_v[3];
316 vertex3 = &v[0];
317 vertex4 = &v[1];
318 }
319 else if (vert_num == 3)
320 {
321 vertex1 = &m_prev_v[3];
322 vertex2 = &v[0];
323 vertex3 = &v[1];
324 vertex4 = &v[2];
325 }
326 else
327 {
328 vertex1 = &v[0];
329 vertex2 = &v[1];
330 vertex3 = &v[2];
331 vertex4 = &v[3];
332 }
333
334 render_triangle(visarea, rd_scan_tex, 6, *vertex1, *vertex2, *vertex3);
335 render_triangle(visarea, rd_scan_tex, 6, *vertex3, *vertex4, *vertex1);
336
337 memcpy(&m_prev_v[0], vertex1, sizeof(vertex_t));
338 memcpy(&m_prev_v[1], vertex2, sizeof(vertex_t));
339 memcpy(&m_prev_v[2], vertex3, sizeof(vertex_t));
340 memcpy(&m_prev_v[3], vertex4, sizeof(vertex_t));
341 }
342
343 while ((fifo[index] & 0xffffff00) != 0x80000000 && index < m_3dfifo_ptr)
344 {
345 k001005_polydata &extra = object_data_alloc();
346 int new_verts = 0;
347
348 memcpy(&v[0], &m_prev_v[2], sizeof(vertex_t));
349 memcpy(&v[1], &m_prev_v[3], sizeof(vertex_t));
350
351 last_vertex = 0;
352 vert_num = 2;
353 do
354 {
355 int x, y, z;
356 int16_t tu, tv;
357
358 x = ((fifo[index] >> 0) & 0x3fff);
359 y = ((fifo[index] >> 16) & 0x1fff);
360 x |= ((x & 0x2000) ? 0xffffc000 : 0);
361 y |= ((y & 0x1000) ? 0xffffe000 : 0);
362
363 poly_type = fifo[index] & 0x4000;
364 last_vertex = fifo[index] & 0x8000;
365 index++;
366
367 z = fifo[index] & 0xffffff00;
368 brightness = fifo[index] & 0xff;
369 index++;
370
371 if (last_vertex)
372 {
373 color = fifo[index++];
374 }
375
376 tu = (fifo[index] >> 16) & 0xffff;
377 tv = (fifo[index] >> 0) & 0xffff;
378 index++;
379
380 v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
381 v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
382 v[vert_num].p[POLY_Z] = *(float*)(&z);
383 v[vert_num].p[POLY_W] = 1.0f / v[vert_num].p[POLY_Z];
384 v[vert_num].p[POLY_U] = tu * v[vert_num].p[POLY_W];
385 v[vert_num].p[POLY_V] = tv * v[vert_num].p[POLY_W];
386 v[vert_num].p[POLY_BRI] = brightness;
387 v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) * ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) ))) * 65536.0f;
388 //v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / far_z) ))) * 65536.0f;
389 if (v[vert_num].p[POLY_FOG] < 0.0f) v[vert_num].p[POLY_FOG] = 0.0f;
390 if (v[vert_num].p[POLY_FOG] > 65536.0f) v[vert_num].p[POLY_FOG] = 65536.0f;
391
392 vert_num++;
393 new_verts++;
394 }
395 while (!last_vertex);
396
397 extra.texture_x = tex_x * 8;
398 extra.texture_y = tex_y * 8;
399 extra.texture_width = (header >> 23) & 0x7;
400 extra.texture_height = (header >> 20) & 0x7;
401
402 extra.texture_page = (header >> 12) & 0x1f;
403 extra.texture_palette = (header >> 28) & 0xf;
404
405 extra.texture_mirror_x = ((cmd & 0x10) ? 0x1 : 0);// & ((header & 0x00400000) ? 0x1 : 0);
406 extra.texture_mirror_y = ((cmd & 0x10) ? 0x1 : 0);// & ((header & 0x00400000) ? 0x1 : 0);
407
408 extra.color = color;
409 extra.light_r = m_light_r; extra.light_g = m_light_g; extra.light_b = m_light_b;
410 extra.ambient_r = m_ambient_r; extra.ambient_g = m_ambient_g; extra.ambient_b = m_ambient_b;
411 extra.fog_r = m_fog_r; extra.fog_g = m_fog_g; extra.fog_b = m_fog_b;
412 extra.flags = cmd;
413
414 if ((cmd & 0x20) == 0) // possibly enable flag for gouraud shading (fixes some shading errors)
415 {
416 v[0].p[POLY_BRI] = brightness;
417 v[1].p[POLY_BRI] = brightness;
418 }
419
420 if (new_verts == 1)
421 {
422 render_triangle(visarea, rd_scan_tex, 6, v[0], v[1], v[2]);
423
424 memcpy(&m_prev_v[1], &v[0], sizeof(vertex_t));
425 memcpy(&m_prev_v[2], &v[1], sizeof(vertex_t));
426 memcpy(&m_prev_v[3], &v[2], sizeof(vertex_t));
427 }
428 else if (new_verts == 2)
429 {
430 render_triangle(visarea, rd_scan_tex, 6, v[0], v[1], v[2]);
431 render_triangle(visarea, rd_scan_tex, 6, v[2], v[3], v[0]);
432
433 memcpy(&m_prev_v[0], &v[0], sizeof(vertex_t));
434 memcpy(&m_prev_v[1], &v[1], sizeof(vertex_t));
435 memcpy(&m_prev_v[2], &v[2], sizeof(vertex_t));
436 memcpy(&m_prev_v[3], &v[3], sizeof(vertex_t));
437 }
438 };
439 }
440 else if (cmd == 0x80000006 || cmd == 0x80000026 || cmd == 0x80000002 || cmd == 0x80000020 || cmd == 0x80000022)
441 {
442 // no texture, Z
443
444 k001005_polydata &extra = object_data_alloc();
445 uint32_t color;
446 int r, g, b, a;
447
448 int last_vertex = 0;
449 int vert_num = 0;
450 do
451 {
452 int x, y, z;
453
454 x = (fifo[index] >> 0) & 0x3fff;
455 y = (fifo[index] >> 16) & 0x1fff;
456 x |= ((x & 0x2000) ? 0xffffc000 : 0);
457 y |= ((y & 0x1000) ? 0xffffe000 : 0);
458
459 poly_type = fifo[index] & 0x4000; // 0 = triangle, 1 = quad
460 last_vertex = fifo[index] & 0x8000;
461 index++;
462
463 z = fifo[index] & 0xffffff00;
464 brightness = fifo[index] & 0xff;
465 index++;
466
467 v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
468 v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
469 v[vert_num].p[POLY_Z] = *(float*)(&z);
470 v[vert_num].p[POLY_BRI] = brightness;
471 v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) * ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) ))) * 65536.0f;
472 //v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / far_z) ))) * 65536.0f;
473 if (v[vert_num].p[POLY_FOG] < 0.0f) v[vert_num].p[POLY_FOG] = 0.0f;
474 if (v[vert_num].p[POLY_FOG] > 65536.0f) v[vert_num].p[POLY_FOG] = 65536.0f;
475 vert_num++;
476 }
477 while (!last_vertex);
478
479 r = (fifo[index] >> 0) & 0xff;
480 g = (fifo[index] >> 8) & 0xff;
481 b = (fifo[index] >> 16) & 0xff;
482 a = (fifo[index] >> 24) & 0xff;
483 color = (a << 24) | (r << 16) | (g << 8) | (b);
484 index++;
485
486 extra.color = color;
487 extra.light_r = m_light_r; extra.light_g = m_light_g; extra.light_b = m_light_b;
488 extra.ambient_r = m_ambient_r; extra.ambient_g = m_ambient_g; extra.ambient_b = m_ambient_b;
489 extra.fog_r = m_fog_r; extra.fog_g = m_fog_g; extra.fog_b = m_fog_b;
490 extra.flags = cmd;
491
492 if ((cmd & 0x20) == 0) // possibly enable flag for gouraud shading (fixes some shading errors)
493 {
494 v[0].p[POLY_BRI] = brightness;
495 v[1].p[POLY_BRI] = brightness;
496 }
497
498 if (poly_type == 0) // triangle
499 {
500 if (vert_num == 1)
501 {
502 vertex1 = &m_prev_v[2];
503 vertex2 = &m_prev_v[3];
504 vertex3 = &v[0];
505 }
506 else if (vert_num == 2)
507 {
508 vertex1 = &m_prev_v[3];
509 vertex2 = &v[0];
510 vertex3 = &v[1];
511 }
512 else
513 {
514 vertex1 = &v[0];
515 vertex2 = &v[1];
516 vertex3 = &v[2];
517 }
518
519 render_triangle(visarea, rd_scan, 3, *vertex1, *vertex2, *vertex3);
520
521 memcpy(&m_prev_v[1], vertex1, sizeof(vertex_t));
522 memcpy(&m_prev_v[2], vertex2, sizeof(vertex_t));
523 memcpy(&m_prev_v[3], vertex3, sizeof(vertex_t));
524 }
525 else // quad
526 {
527 if (vert_num == 1)
528 {
529 vertex1 = &m_prev_v[1];
530 vertex2 = &m_prev_v[2];
531 vertex3 = &m_prev_v[3];
532 vertex4 = &v[0];
533 }
534 else if (vert_num == 2)
535 {
536 vertex1 = &m_prev_v[2];
537 vertex2 = &m_prev_v[3];
538 vertex3 = &v[0];
539 vertex4 = &v[1];
540 }
541 else if (vert_num == 3)
542 {
543 vertex1 = &m_prev_v[3];
544 vertex2 = &v[0];
545 vertex3 = &v[1];
546 vertex4 = &v[2];
547 }
548 else
549 {
550 vertex1 = &v[0];
551 vertex2 = &v[1];
552 vertex3 = &v[2];
553 vertex4 = &v[3];
554 }
555
556 render_triangle(visarea, rd_scan, 3, *vertex1, *vertex2, *vertex3);
557 render_triangle(visarea, rd_scan, 3, *vertex3, *vertex4, *vertex1);
558
559 memcpy(&m_prev_v[0], vertex1, sizeof(vertex_t));
560 memcpy(&m_prev_v[1], vertex2, sizeof(vertex_t));
561 memcpy(&m_prev_v[2], vertex3, sizeof(vertex_t));
562 memcpy(&m_prev_v[3], vertex4, sizeof(vertex_t));
563 }
564
565 while ((fifo[index] & 0xffffff00) != 0x80000000 && index < m_3dfifo_ptr)
566 {
567 int new_verts = 0;
568
569 memcpy(&v[0], &m_prev_v[2], sizeof(vertex_t));
570 memcpy(&v[1], &m_prev_v[3], sizeof(vertex_t));
571
572 last_vertex = 0;
573 vert_num = 2;
574 do
575 {
576 int x, y, z;
577
578 x = ((fifo[index] >> 0) & 0x3fff);
579 y = ((fifo[index] >> 16) & 0x1fff);
580 x |= ((x & 0x2000) ? 0xffffc000 : 0);
581 y |= ((y & 0x1000) ? 0xffffe000 : 0);
582
583 poly_type = fifo[index] & 0x4000;
584 last_vertex = fifo[index] & 0x8000;
585 index++;
586
587 z = fifo[index] & 0xffffff00;
588 brightness = fifo[index] & 0xff;
589 index++;
590
591 v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
592 v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
593 v[vert_num].p[POLY_Z] = *(float*)(&z);
594 v[vert_num].p[POLY_BRI] = brightness;
595 v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) * ((v[vert_num].p[POLY_Z] * fog_density) / m_far_z) ))) * 65536.0f;
596 //v[vert_num].p[POLY_FOG] = (1.0f / (exp( ((v[vert_num].p[POLY_Z] * fog_density) / far_z) ))) * 65536.0f;
597 if (v[vert_num].p[POLY_FOG] < 0.0f) v[vert_num].p[POLY_FOG] = 0.0f;
598 if (v[vert_num].p[POLY_FOG] > 65536.0f) v[vert_num].p[POLY_FOG] = 65536.0f;
599
600 vert_num++;
601 new_verts++;
602 }
603 while (!last_vertex);
604
605 r = (fifo[index] >> 0) & 0xff;
606 g = (fifo[index] >> 8) & 0xff;
607 b = (fifo[index] >> 16) & 0xff;
608 a = (fifo[index] >> 24) & 0xff;
609 color = (a << 24) | (r << 16) | (g << 8) | (b);
610 index++;
611
612 extra.color = color;
613 extra.light_r = m_light_r; extra.light_g = m_light_g; extra.light_b = m_light_b;
614 extra.ambient_r = m_ambient_r; extra.ambient_g = m_ambient_g; extra.ambient_b = m_ambient_b;
615 extra.fog_r = m_fog_r; extra.fog_g = m_fog_g; extra.fog_b = m_fog_b;
616 extra.flags = cmd;
617
618 if ((cmd & 0x20) == 0) // possibly enable flag for gouraud shading (fixes some shading errors)
619 {
620 v[0].p[POLY_BRI] = brightness;
621 v[1].p[POLY_BRI] = brightness;
622 }
623
624 if (new_verts == 1)
625 {
626 render_triangle(visarea, rd_scan, 3, v[0], v[1], v[2]);
627
628 memcpy(&m_prev_v[1], &v[0], sizeof(vertex_t));
629 memcpy(&m_prev_v[2], &v[1], sizeof(vertex_t));
630 memcpy(&m_prev_v[3], &v[2], sizeof(vertex_t));
631 }
632 else if (new_verts == 2)
633 {
634 render_triangle(visarea, rd_scan, 3, v[0], v[1], v[2]);
635 render_triangle(visarea, rd_scan, 3, v[2], v[3], v[0]);
636
637 memcpy(&m_prev_v[0], &v[0], sizeof(vertex_t));
638 memcpy(&m_prev_v[1], &v[1], sizeof(vertex_t));
639 memcpy(&m_prev_v[2], &v[2], sizeof(vertex_t));
640 memcpy(&m_prev_v[3], &v[3], sizeof(vertex_t));
641 }
642 }
643 }
644 else if (cmd == 0x80000003 || cmd == 0x80000001)
645 {
646 // no texture, no Z
647
648 k001005_polydata &extra = object_data_alloc();
649 int r, g, b, a;
650 uint32_t color;
651
652 int last_vertex = 0;
653 int vert_num = 0;
654 do
655 {
656 int x, y;
657
658 x = ((fifo[index] >> 0) & 0x3fff);
659 y = ((fifo[index] >> 16) & 0x1fff);
660 x |= ((x & 0x2000) ? 0xffffc000 : 0);
661 y |= ((y & 0x1000) ? 0xffffe000 : 0);
662
663 poly_type = fifo[index] & 0x4000;
664 last_vertex = fifo[index] & 0x8000;
665 index++;
666
667 v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
668 v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
669 vert_num++;
670 }
671 while (!last_vertex);
672
673 // unknown word
674 index++;
675
676 r = (fifo[index] >> 0) & 0xff;
677 g = (fifo[index] >> 8) & 0xff;
678 b = (fifo[index] >> 16) & 0xff;
679 a = (fifo[index] >> 24) & 0xff;
680 color = (a << 24) | (r << 16) | (g << 8) | (b);
681 index++;
682
683 extra.color = color;
684 extra.flags = cmd;
685
686 if (poly_type == 0)
687 {
688 render_triangle(visarea, rd_scan_2d, 0, v[0], v[1], v[2]);
689 }
690 else
691 {
692 render_triangle(visarea, rd_scan_2d, 0, v[0], v[1], v[2]);
693 render_triangle(visarea, rd_scan_2d, 0, v[2], v[3], v[0]);
694 }
695 }
696 else if (cmd == 0x8000008b)
697 {
698 // texture, no Z
699
700 int tex_x, tex_y;
701 k001005_polydata &extra = object_data_alloc();
702 int r, g, b, a;
703 uint32_t color = 0;
704
705 uint32_t header = fifo[index++];
706
707 int last_vertex = 0;
708 int vert_num = 0;
709 do
710 {
711 int x, y;
712 int16_t tu, tv;
713
714 x = ((fifo[index] >> 0) & 0x3fff);
715 y = ((fifo[index] >> 16) & 0x1fff);
716 x |= ((x & 0x2000) ? 0xffffc000 : 0);
717 y |= ((y & 0x1000) ? 0xffffe000 : 0);
718
719 poly_type = fifo[index] & 0x4000;
720 last_vertex = fifo[index] & 0x8000;
721 index++;
722
723 if (last_vertex)
724 {
725 // unknown word
726 index++;
727
728 color = fifo[index++];
729 }
730
731 tu = (fifo[index] >> 16) & 0xffff;
732 tv = (fifo[index] & 0xffff);
733 index++;
734
735 v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
736 v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
737 v[vert_num].p[POLY_U] = tu;
738 v[vert_num].p[POLY_V] = tv;
739 vert_num++;
740 }
741 while (!last_vertex);
742
743 r = (color >> 0) & 0xff;
744 g = (color >> 8) & 0xff;
745 b = (color >> 16) & 0xff;
746 a = (color >> 24) & 0xff;
747 extra.color = (a << 24) | (r << 16) | (g << 8) | (b);
748 extra.flags = cmd;
749
750 tex_y = ((header & 0x400) >> 5) |
751 ((header & 0x100) >> 4) |
752 ((header & 0x040) >> 3) |
753 ((header & 0x010) >> 2) |
754 ((header & 0x004) >> 1) |
755 ((header & 0x001) >> 0);
756
757 tex_x = ((header & 0x800) >> 6) |
758 ((header & 0x200) >> 5) |
759 ((header & 0x080) >> 4) |
760 ((header & 0x020) >> 3) |
761 ((header & 0x008) >> 2) |
762 ((header & 0x002) >> 1);
763
764 extra.texture_x = tex_x * 8;
765 extra.texture_y = tex_y * 8;
766 extra.texture_width = (header >> 23) & 0x7;
767 extra.texture_height = (header >> 20) & 0x7;
768
769 extra.texture_page = (header >> 12) & 0x1f;
770 extra.texture_palette = (header >> 28) & 0xf;
771
772 extra.texture_mirror_x = ((cmd & 0x10) ? 0x1 : 0);
773 extra.texture_mirror_y = ((cmd & 0x10) ? 0x1 : 0);
774
775 if (poly_type == 0)
776 {
777 render_triangle(visarea, rd_scan_tex2d, 5, v[0], v[1], v[2]);
778 }
779 else
780 {
781 render_triangle(visarea, rd_scan_tex2d, 5, v[0], v[1], v[2]);
782 render_triangle(visarea, rd_scan_tex2d, 5, v[2], v[3], v[0]);
783 }
784 }
785 else if (cmd == 0x80000106 || cmd == 0x80000121 || cmd == 0x80000126)
786 {
787 // no texture, color gouraud, Z
788
789 k001005_polydata &extra = object_data_alloc();
790 uint32_t color;
791
792 int last_vertex = 0;
793 int vert_num = 0;
794 do
795 {
796 int x, y, z;
797
798 x = ((fifo[index] >> 0) & 0x3fff);
799 y = ((fifo[index] >> 16) & 0x1fff);
800 x |= ((x & 0x2000) ? 0xffffc000 : 0);
801 y |= ((y & 0x1000) ? 0xffffe000 : 0);
802
803 poly_type = fifo[index] & 0x4000;
804 last_vertex = fifo[index] & 0x8000;
805 index++;
806
807 z = fifo[index] & 0xffffff00;
808 brightness = fifo[index] & 0xff;
809 index++;
810
811 color = fifo[index];
812 index++;
813
814 v[vert_num].x = ((float)(x) / 16.0f) + 256.0f;
815 v[vert_num].y = ((float)(-y) / 16.0f) + 192.0f + 8;
816 v[vert_num].p[POLY_Z] = *(float*)(&z);
817 v[vert_num].p[POLY_R] = (color >> 16) & 0xff;
818 v[vert_num].p[POLY_G] = (color >> 8) & 0xff;
819 v[vert_num].p[POLY_B] = color & 0xff;
820 v[vert_num].p[POLY_A] = (color >> 24) & 0xff;
821 vert_num++;
822 }
823 while (!last_vertex);
824
825 extra.color = color;
826 extra.flags = cmd;
827
828 if (poly_type == 0)
829 {
830 render_triangle(visarea, rd_scan_gour_blend, 6, v[0], v[1], v[2]);
831 }
832 else
833 {
834 render_triangle(visarea, rd_scan_gour_blend, 6, v[0], v[1], v[2]);
835 render_triangle(visarea, rd_scan_gour_blend, 6, v[2], v[3], v[0]);
836 }
837
838 // TODO: can this poly type form strips?
839 }
840 else if (cmd == 0x80000000)
841 {
842 }
843 else if (cmd == 0x80000018)
844 {
845 }
846 else if ((cmd & 0xffff0000) == 0x80000000)
847 {
848 /*
849 osd_printf_debug("Unknown polygon type %08X:\n", fifo[index-1]);
850 for (int i=0; i < 0x20; i++)
851 {
852 osd_printf_debug(" %02X: %08X\n", i, fifo[index+i]);
853 }
854 osd_printf_debug("\n");
855 */
856
857 printf("Unknown polygon type %08X:\n", fifo[index-1]);
858 for (int i=0; i < 0x20; i++)
859 {
860 printf(" %02X: %08X\n", i, fifo[index+i]);
861 }
862 printf("\n");
863 }
864 else
865 {
866 }
867 }
868 while (index < m_3dfifo_ptr);
869
870 #if LOG_POLY_FIFO
871 printf("\nrender %d\n", K001005_3d_fifo_ptr);
872 printf("------------------------------------\n");
873 #endif
874
875 m_3dfifo_ptr = 0;
876
877 wait();
878 }
879
880
draw_scanline_2d(int32_t scanline,const extent_t & extent,const k001005_polydata & extradata,int threadid)881 void k001005_renderer::draw_scanline_2d(int32_t scanline, const extent_t &extent, const k001005_polydata &extradata, int threadid)
882 {
883 uint32_t *const fb = &m_fb[m_fb_page]->pix(scanline);
884 float *const zb = (float*)&m_zb->pix(scanline);
885 uint32_t color = extradata.color;
886
887 for (int x = extent.startx; x < extent.stopx; x++)
888 {
889 if (color & 0xff000000)
890 {
891 fb[x] = color;
892 zb[x] = FLT_MAX; // FIXME
893 }
894 }
895 }
896
draw_scanline_2d_tex(int32_t scanline,const extent_t & extent,const k001005_polydata & extradata,int threadid)897 void k001005_renderer::draw_scanline_2d_tex(int32_t scanline, const extent_t &extent, const k001005_polydata &extradata, int threadid)
898 {
899 // int pal_chip = (extradata.texture_palette & 0x8) ? 1 : 0;
900 k001006_device *k001006 = downcast<k001006_device*>(m_k001006);
901
902 int tex_page = extradata.texture_page * 0x40000;
903 int palette_index = (extradata.texture_palette & 0x7) * 256;
904 float u = extent.param[POLY_U].start;
905 float v = extent.param[POLY_V].start;
906 float du = extent.param[POLY_U].dpdx;
907 float dv = extent.param[POLY_V].dpdx;
908 uint32_t *const fb = &m_fb[m_fb_page]->pix(scanline);
909 float *const zb = (float*)&m_zb->pix(scanline);
910 uint32_t color = extradata.color;
911 int texture_mirror_x = extradata.texture_mirror_x;
912 int texture_mirror_y = extradata.texture_mirror_y;
913 int texture_x = extradata.texture_x;
914 int texture_y = extradata.texture_y;
915 int texture_width = extradata.texture_width;
916 int texture_height = extradata.texture_height;
917
918 int *x_mirror_table = m_tex_mirror_table[texture_mirror_x][texture_width].get();
919 int *y_mirror_table = m_tex_mirror_table[texture_mirror_y][texture_height].get();
920
921 for (int x = extent.startx; x < extent.stopx; x++)
922 {
923 int iu = (int)(u * 0.0625f);
924 int iv = (int)(v * 0.0625f);
925 int iiv, iiu;
926
927 iiu = texture_x + x_mirror_table[iu & 0x7f];
928 iiv = texture_y + y_mirror_table[iv & 0x7f];
929
930 color = k001006->fetch_texel(tex_page, palette_index, iiu, iiv);
931
932 if (color & 0xff000000)
933 {
934 fb[x] = color;
935 zb[x] = FLT_MAX; // FIXME
936 }
937
938 u += du;
939 v += dv;
940 }
941 }
942
draw_scanline(int32_t scanline,const extent_t & extent,const k001005_polydata & extradata,int threadid)943 void k001005_renderer::draw_scanline(int32_t scanline, const extent_t &extent, const k001005_polydata &extradata, int threadid)
944 {
945 float z = extent.param[POLY_Z].start;
946 float dz = extent.param[POLY_Z].dpdx;
947 float bri = extent.param[POLY_BRI].start;
948 float dbri = extent.param[POLY_BRI].dpdx;
949 float fog = extent.param[POLY_FOG].start;
950 float dfog = extent.param[POLY_FOG].dpdx;
951 uint32_t *const fb = &m_fb[m_fb_page]->pix(scanline);
952 float *const zb = (float*)&m_zb->pix(scanline);
953 uint32_t color = extradata.color;
954
955 int poly_light_r = extradata.light_r + extradata.ambient_r;
956 int poly_light_g = extradata.light_g + extradata.ambient_g;
957 int poly_light_b = extradata.light_b + extradata.ambient_b;
958 if (poly_light_r > 255) poly_light_r = 255;
959 if (poly_light_g > 255) poly_light_g = 255;
960 if (poly_light_b > 255) poly_light_b = 255;
961 int poly_fog_r = extradata.fog_r;
962 int poly_fog_g = extradata.fog_g;
963 int poly_fog_b = extradata.fog_b;
964
965 for (int x = extent.startx; x < extent.stopx; x++)
966 {
967 int ibri = (int)(bri);
968 int ifog = (int)(fog);
969
970 if (ibri < 0) ibri = 0;
971 if (ibri > 255) ibri = 255;
972 if (ifog < 0) ifog = 0;
973 if (ifog > 65536) ifog = 65536;
974
975 if (z <= zb[x])
976 {
977 if (color & 0xff000000)
978 {
979 int r = (color >> 16) & 0xff;
980 int g = (color >> 8) & 0xff;
981 int b = color & 0xff;
982
983 r = ((((r * poly_light_r * ibri) >> 16) * ifog) + (poly_fog_r * (65536 - ifog))) >> 16;
984 g = ((((g * poly_light_g * ibri) >> 16) * ifog) + (poly_fog_g * (65536 - ifog))) >> 16;
985 b = ((((b * poly_light_b * ibri) >> 16) * ifog) + (poly_fog_b * (65536 - ifog))) >> 16;
986
987 if (r < 0) r = 0;
988 if (r > 255) r = 255;
989 if (g < 0) g = 0;
990 if (g > 255) g = 255;
991 if (b < 0) b = 0;
992 if (b > 255) b = 255;
993
994 fb[x] = (color & 0xff000000) | (r << 16) | (g << 8) | b;
995 zb[x] = z;
996 }
997 }
998
999 z += dz;
1000 bri += dbri;
1001 fog += dfog;
1002 }
1003 }
1004
draw_scanline_tex(int32_t scanline,const extent_t & extent,const k001005_polydata & extradata,int threadid)1005 void k001005_renderer::draw_scanline_tex(int32_t scanline, const extent_t &extent, const k001005_polydata &extradata, int threadid)
1006 {
1007 // int pal_chip = (extradata.texture_palette & 0x8) ? 1 : 0;
1008 k001006_device *k001006 = downcast<k001006_device*>(m_k001006);
1009
1010 int tex_page = extradata.texture_page * 0x40000;
1011 int palette_index = (extradata.texture_palette & 0x7) * 256;
1012 float z = extent.param[POLY_Z].start;
1013 float u = extent.param[POLY_U].start;
1014 float v = extent.param[POLY_V].start;
1015 float w = extent.param[POLY_W].start;
1016 float dz = extent.param[POLY_Z].dpdx;
1017 float du = extent.param[POLY_U].dpdx;
1018 float dv = extent.param[POLY_V].dpdx;
1019 float dw = extent.param[POLY_W].dpdx;
1020 float bri = extent.param[POLY_BRI].start;
1021 float dbri = extent.param[POLY_BRI].dpdx;
1022 float fog = extent.param[POLY_FOG].start;
1023 float dfog = extent.param[POLY_FOG].dpdx;
1024 int texture_mirror_x = extradata.texture_mirror_x;
1025 int texture_mirror_y = extradata.texture_mirror_y;
1026 int texture_x = extradata.texture_x;
1027 int texture_y = extradata.texture_y;
1028 int texture_width = extradata.texture_width;
1029 int texture_height = extradata.texture_height;
1030
1031 int poly_light_r = extradata.light_r + extradata.ambient_r;
1032 int poly_light_g = extradata.light_g + extradata.ambient_g;
1033 int poly_light_b = extradata.light_b + extradata.ambient_b;
1034 if (poly_light_r > 255) poly_light_r = 255;
1035 if (poly_light_g > 255) poly_light_g = 255;
1036 if (poly_light_b > 255) poly_light_b = 255;
1037 int poly_fog_r = extradata.fog_r;
1038 int poly_fog_g = extradata.fog_g;
1039 int poly_fog_b = extradata.fog_b;
1040
1041 uint32_t *const fb = &m_fb[m_fb_page]->pix(scanline);
1042 float *const zb = (float*)&m_zb->pix(scanline);
1043
1044 int *x_mirror_table = m_tex_mirror_table[texture_mirror_x][texture_width].get();
1045 int *y_mirror_table = m_tex_mirror_table[texture_mirror_y][texture_height].get();
1046
1047 for (int x = extent.startx; x < extent.stopx; x++)
1048 {
1049 int ibri = (int)(bri);
1050 int ifog = (int)(fog);
1051
1052 if (ibri < 0) ibri = 0;
1053 if (ibri > 255) ibri = 255;
1054 if (ifog < 0) ifog = 0;
1055 if (ifog > 65536) ifog = 65536;
1056
1057 if (z <= zb[x])
1058 {
1059 float oow = 1.0f / w;
1060 uint32_t color;
1061 int iu, iv;
1062 int iiv, iiu;
1063
1064 iu = u * oow * 0.0625f;
1065 iv = v * oow * 0.0625f;
1066
1067 iiu = texture_x + x_mirror_table[iu & 0x7f];
1068 iiv = texture_y + y_mirror_table[iv & 0x7f];
1069
1070 color = k001006->fetch_texel(tex_page, palette_index, iiu, iiv);
1071
1072 if (color & 0xff000000)
1073 {
1074 int r = (color >> 16) & 0xff;
1075 int g = (color >> 8) & 0xff;
1076 int b = color & 0xff;
1077
1078 r = ((((r * poly_light_r * ibri) >> 16) * ifog) + (poly_fog_r * (65536 - ifog))) >> 16;
1079 g = ((((g * poly_light_g * ibri) >> 16) * ifog) + (poly_fog_g * (65536 - ifog))) >> 16;
1080 b = ((((b * poly_light_b * ibri) >> 16) * ifog) + (poly_fog_b * (65536 - ifog))) >> 16;
1081
1082 if (r < 0) r = 0;
1083 if (r > 255) r = 255;
1084 if (g < 0) g = 0;
1085 if (g > 255) g = 255;
1086 if (b < 0) b = 0;
1087 if (b > 255) b = 255;
1088
1089 fb[x] = 0xff000000 | (r << 16) | (g << 8) | b;
1090 zb[x] = z;
1091 }
1092 }
1093
1094 u += du;
1095 v += dv;
1096 z += dz;
1097 w += dw;
1098 bri += dbri;
1099 fog += dfog;
1100 }
1101 }
1102
draw_scanline_gouraud_blend(int32_t scanline,const extent_t & extent,const k001005_polydata & extradata,int threadid)1103 void k001005_renderer::draw_scanline_gouraud_blend(int32_t scanline, const extent_t &extent, const k001005_polydata &extradata, int threadid)
1104 {
1105 float z = extent.param[POLY_Z].start;
1106 float dz = extent.param[POLY_Z].dpdx;
1107 float r = extent.param[POLY_R].start;
1108 float dr = extent.param[POLY_R].dpdx;
1109 float g = extent.param[POLY_G].start;
1110 float dg = extent.param[POLY_G].dpdx;
1111 float b = extent.param[POLY_B].start;
1112 float db = extent.param[POLY_B].dpdx;
1113 float a = extent.param[POLY_A].start;
1114 float da = extent.param[POLY_A].dpdx;
1115 uint32_t *const fb = &m_fb[m_fb_page]->pix(scanline);
1116 float *const zb = (float*)&m_zb->pix(scanline);
1117
1118 for (int x = extent.startx; x < extent.stopx; x++)
1119 {
1120 if (z <= zb[x])
1121 {
1122 int ir = (int)(r);
1123 int ig = (int)(g);
1124 int ib = (int)(b);
1125 int ia = (int)(a);
1126
1127 if (ia > 0)
1128 {
1129 if (ia != 0xff)
1130 {
1131 int sr = (fb[x] >> 16) & 0xff;
1132 int sg = (fb[x] >> 8) & 0xff;
1133 int sb = fb[x] & 0xff;
1134
1135 ir = ((ir * ia) >> 8) + ((sr * (0xff-ia)) >> 8);
1136 ig = ((ig * ia) >> 8) + ((sg * (0xff-ia)) >> 8);
1137 ib = ((ib * ia) >> 8) + ((sb * (0xff-ia)) >> 8);
1138 }
1139
1140 if (ir < 0) ir = 0;
1141 if (ir > 255) ir = 255;
1142 if (ig < 0) ig = 0;
1143 if (ig > 255) ig = 255;
1144 if (ib < 0) ib = 0;
1145 if (ib > 255) ib = 255;
1146
1147 fb[x] = 0xff000000 | (ir << 16) | (ig << 8) | ib;
1148 zb[x] = z;
1149 }
1150 }
1151
1152 z += dz;
1153 r += dr;
1154 g += dg;
1155 b += db;
1156 a += da;
1157 }
1158 }
1159
1160
draw(bitmap_rgb32 & bitmap,const rectangle & cliprect)1161 void k001005_renderer::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect)
1162 {
1163 for (int j = cliprect.min_y; j <= cliprect.max_y; j++)
1164 {
1165 uint32_t *const bmp = &bitmap.pix(j);
1166 uint32_t const *const src = &m_fb[m_fb_page^1]->pix(j);
1167
1168 for (int i = cliprect.min_x; i <= cliprect.max_x; i++)
1169 {
1170 if (src[i] & 0xff000000)
1171 {
1172 bmp[i] = src[i];
1173 }
1174 }
1175 }
1176 }
1177
1178
1179
1180 DEFINE_DEVICE_TYPE(K001005, k001005_device, "k001005", "K001005 Polygon Renderer")
1181
k001005_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1182 k001005_device::k001005_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1183 : device_t(mconfig, K001005, tag, owner, clock)
1184 , device_video_interface(mconfig, *this)
1185 , m_k001006(*this, finder_base::DUMMY_TAG)
1186 , m_fifo(nullptr)
1187 , m_status(0)
1188 , m_ram_ptr(0)
1189 , m_fifo_read_ptr(0)
1190 , m_fifo_write_ptr(0)
1191 , m_reg_far_z(0)
1192 {
1193 m_ram[0] = nullptr;
1194 m_ram[1] = nullptr;
1195 }
1196
1197 //-------------------------------------------------
1198 // device_start - device-specific startup
1199 //-------------------------------------------------
1200
device_start()1201 void k001005_device::device_start()
1202 {
1203 m_ram[0] = std::make_unique<uint16_t[]>(0x140000);
1204 m_ram[1] = std::make_unique<uint16_t[]>(0x140000);
1205
1206 m_fifo = std::make_unique<uint32_t[]>(0x800);
1207
1208 m_renderer = auto_alloc(machine(), k001005_renderer(*this, screen(), m_k001006));
1209
1210 save_pointer(NAME(m_ram[0]), 0x140000);
1211 save_pointer(NAME(m_ram[1]), 0x140000);
1212 save_pointer(NAME(m_fifo), 0x800);
1213 save_item(NAME(m_status));
1214 save_item(NAME(m_ram_ptr));
1215 save_item(NAME(m_fifo_read_ptr));
1216 save_item(NAME(m_fifo_write_ptr));
1217 save_item(NAME(m_reg_far_z));
1218 }
1219
1220 //-------------------------------------------------
1221 // device_reset - device-specific reset
1222 //-------------------------------------------------
1223
device_reset()1224 void k001005_device::device_reset()
1225 {
1226 m_status = 0;
1227 m_ram_ptr = 0;
1228 m_fifo_read_ptr = 0;
1229 m_fifo_write_ptr = 0;
1230
1231 m_renderer->reset();
1232 }
1233
1234 //-------------------------------------------------
1235 // device_stop - device-specific stop
1236 //-------------------------------------------------
1237
device_stop()1238 void k001005_device::device_stop()
1239 {
1240 }
1241
1242
1243 /*****************************************************************************
1244 DEVICE HANDLERS
1245 *****************************************************************************/
1246
swap_buffers()1247 void k001005_device::swap_buffers( )
1248 {
1249 m_renderer->swap_buffers();
1250 }
1251
read(address_space & space,offs_t offset,uint32_t mem_mask)1252 uint32_t k001005_device::read(address_space &space, offs_t offset, uint32_t mem_mask)
1253 {
1254 adsp21062_device *dsp = downcast<adsp21062_device*>(&space.device());
1255
1256 switch(offset)
1257 {
1258 case 0x000: // FIFO read, high 16 bits
1259 {
1260 //osd_printf_debug("FIFO_r0: %08X\n", m_fifo_read_ptr);
1261 uint16_t value = m_fifo[m_fifo_read_ptr] >> 16;
1262 return value;
1263 }
1264
1265 case 0x001: // FIFO read, low 16 bits
1266 {
1267 //osd_printf_debug("FIFO_r1: %08X\n", m_fifo_read_ptr);
1268 uint16_t value = m_fifo[m_fifo_read_ptr] & 0xffff;
1269
1270 if (m_status != 1 && m_status != 2)
1271 {
1272 if (m_fifo_read_ptr < 0x3ff)
1273 {
1274 dsp->set_flag_input(1, CLEAR_LINE);
1275 }
1276 else
1277 {
1278 dsp->set_flag_input(1, ASSERT_LINE);
1279 }
1280 }
1281 else
1282 {
1283 dsp->set_flag_input(1, ASSERT_LINE);
1284 }
1285
1286 m_fifo_read_ptr++;
1287 m_fifo_read_ptr &= 0x7ff;
1288 return value;
1289 }
1290
1291 case 0x11b: // status ?
1292 return 0x8002;
1293
1294 case 0x11c: // slave status ?
1295 return 0x8000;
1296
1297 case 0x11f:
1298 if (m_ram_ptr >= 0x400000)
1299 {
1300 return m_ram[1][(m_ram_ptr++) & 0x3fffff];
1301 }
1302 else
1303 {
1304 return m_ram[0][(m_ram_ptr++) & 0x3fffff];
1305 }
1306
1307 default:
1308 //osd_printf_debug("%s m_r: %08X, %08X\n", machine().describe_context(), offset, mem_mask);
1309 break;
1310 }
1311 return 0;
1312 }
1313
write(address_space & space,offs_t offset,uint32_t data,uint32_t mem_mask)1314 void k001005_device::write(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask)
1315 {
1316 adsp21062_device *dsp = downcast<adsp21062_device*>(&space.device());
1317
1318 switch (offset)
1319 {
1320 case 0x000: // FIFO write
1321 {
1322 //osd_printf_debug("%s K001005 FIFO write: %08X\n", machine().describe_context(), data);
1323 if (m_status != 1 && m_status != 2)
1324 {
1325 if (m_fifo_write_ptr < 0x400)
1326 {
1327 dsp->set_flag_input(1, ASSERT_LINE);
1328 }
1329 else
1330 {
1331 dsp->set_flag_input(1, CLEAR_LINE);
1332 }
1333 }
1334 else
1335 {
1336 dsp->set_flag_input(1, ASSERT_LINE);
1337 }
1338
1339 // osd_printf_debug("%s K001005 FIFO write: %08X\n", machine().describe_context(), data);
1340 m_fifo[m_fifo_write_ptr] = data;
1341 m_fifo_write_ptr++;
1342 m_fifo_write_ptr &= 0x7ff;
1343
1344 m_renderer->push_data(data);
1345
1346 #if LOG_POLY_FIFO
1347 printf("0x%08X, ", data);
1348 count++;
1349 if (count >= 8)
1350 {
1351 count = 0;
1352 printf("\n");
1353 }
1354 #endif
1355
1356 // !!! HACK to get past the FIFO B test (GTI Club & Thunder Hurricane) !!!
1357 if (dsp->pc() == 0x201ee)
1358 {
1359 // This is used to make the SHARC timeout
1360 dsp->spin_until_trigger(10000);
1361 }
1362 // !!! HACK to get past the FIFO B test (Winding Heat & Midnight Run) !!!
1363 if (dsp->pc() == 0x201e6)
1364 {
1365 // This is used to make the SHARC timeout
1366 dsp->spin_until_trigger(10000);
1367 }
1368
1369 break;
1370 }
1371
1372 case 0x100: break;
1373
1374 case 0x101: break; // viewport x and width?
1375 case 0x102: break; // viewport y and height?
1376
1377 case 0x104: break; // viewport center x? (usually 0xff)
1378 case 0x105: break; // viewport center y? (usually 0xbf)
1379
1380 case 0x108: // far Z value, 4 exponent bits?
1381 {
1382 // this register seems to hold the 4 missing exponent bits...
1383 m_reg_far_z = (m_reg_far_z & 0x0000ffff) | ((data & 0xf) << 16);
1384 m_renderer->set_param(K001005_FAR_Z, m_reg_far_z);
1385 break;
1386 }
1387
1388 case 0x109: // far Z value
1389 {
1390 // the SHARC code throws away the bottom 11 bits of mantissa and the top 5 bits (to fit in a 16-bit register?)
1391 m_reg_far_z = (m_reg_far_z & 0xffff0000) | (data & 0xffff);
1392 m_renderer->set_param(K001005_FAR_Z, m_reg_far_z);
1393 break;
1394 }
1395
1396 case 0x10a: m_renderer->set_param(K001005_LIGHT_R, data & 0xff); break;
1397 case 0x10b: m_renderer->set_param(K001005_LIGHT_G, data & 0xff); break;
1398 case 0x10c: m_renderer->set_param(K001005_LIGHT_B, data & 0xff); break;
1399
1400 case 0x10d: m_renderer->set_param(K001005_AMBIENT_R, data & 0xff); break;
1401 case 0x10e: m_renderer->set_param(K001005_AMBIENT_G, data & 0xff); break;
1402 case 0x10f: m_renderer->set_param(K001005_AMBIENT_B, data & 0xff); break;
1403
1404 case 0x110: m_renderer->set_param(K001005_FOG_R, data & 0xff); break;
1405 case 0x111: m_renderer->set_param(K001005_FOG_G, data & 0xff); break;
1406 case 0x112: m_renderer->set_param(K001005_FOG_B, data & 0xff); break;
1407
1408
1409 case 0x11a:
1410 m_status = data;
1411 m_fifo_write_ptr = 0;
1412 m_fifo_read_ptr = 0;
1413
1414 if (data == 2)
1415 {
1416 if (m_renderer->fifo_filled())
1417 {
1418 m_renderer->render_polygons();
1419 }
1420
1421 m_renderer->swap_buffers();
1422 }
1423 break;
1424
1425 case 0x11d:
1426 m_fifo_write_ptr = 0;
1427 m_fifo_read_ptr = 0;
1428 break;
1429
1430 case 0x11e:
1431 m_ram_ptr = data;
1432 break;
1433
1434 case 0x11f:
1435 if (m_ram_ptr >= 0x400000)
1436 {
1437 m_ram[1][(m_ram_ptr++) & 0x3fffff] = data & 0xffff;
1438 }
1439 else
1440 {
1441 m_ram[0][(m_ram_ptr++) & 0x3fffff] = data & 0xffff;
1442 }
1443 break;
1444
1445 default:
1446 //osd_printf_debug("%s m_w: %08X, %08X, %08X\n", machine().describe_context(), data, offset, mem_mask);
1447 break;
1448 }
1449
1450 }
1451
draw(bitmap_rgb32 & bitmap,const rectangle & cliprect)1452 void k001005_device::draw( bitmap_rgb32 &bitmap, const rectangle &cliprect )
1453 {
1454 m_renderer->draw(bitmap, cliprect);
1455 }
1456