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