1 // license:BSD-3-Clause
2 // copyright-holders:R. Belmont, Ville Linde
3 #include "emu.h"
4 #include "video/rgbutil.h"
5 #include "includes/model3.h"
6 
7 /*
8     TODO:
9     - Tilemap flash effect
10     - Fog
11     - Mipmapping
12     - Mipmap uploads smaller than a tile
13     - Some of the 4-bit and 8-bit textures need their alpha values rechecked
14     - Spotlights
15     - Recheck normal vector transform
16 
17 */
18 
19 #define ENABLE_BILINEAR     1
20 
21 #define TRI_PARAM_TEXTURE_PAGE          0x1
22 #define TRI_PARAM_TEXTURE_MIRROR_U      0x2
23 #define TRI_PARAM_TEXTURE_MIRROR_V      0x4
24 #define TRI_PARAM_TEXTURE_ENABLE        0x8
25 #define TRI_PARAM_ALPHA_TEST            0x10
26 #define TRI_PARAM_COLOR_MOD             0x20
27 
28 #define TRI_BUFFER_SIZE                 50000
29 #define TRI_ALPHA_BUFFER_SIZE           15000
30 
31 struct model3_polydata
32 {
33 	cached_texture *texture;
34 	uint32_t color;
35 	uint32_t texture_param;
36 	int transparency;
37 	int intensity;
38 };
39 
40 class model3_renderer : public poly_manager<float, model3_polydata, 6, 50000>
41 {
42 public:
model3_renderer(model3_state & state,int width,int height)43 	model3_renderer(model3_state &state, int width, int height)
44 		: poly_manager<float, model3_polydata, 6, 50000>(state.machine())
45 	{
46 		m_fb = std::make_unique<bitmap_rgb32>(width, height);
47 		m_zb = std::make_unique<bitmap_ind32>(width, height);
48 	}
49 
50 	void draw(bitmap_rgb32 &bitmap, const rectangle &cliprect);
51 	void draw_opaque_triangles(const m3_triangle* tris, int num_tris);
52 	void draw_alpha_triangles(const m3_triangle* tris, int num_tris);
53 	void clear_fb();
54 	void clear_zb();
55 	void draw_scanline_solid(int32_t scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
56 	void draw_scanline_solid_trans(int32_t scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
57 	void draw_scanline_tex(int32_t scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
58 	void draw_scanline_tex_colormod(int32_t scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
59 	void draw_scanline_tex_contour(int32_t scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
60 	void draw_scanline_tex_trans(int32_t scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
61 	void draw_scanline_tex_alpha(int32_t scanline, const extent_t &extent, const model3_polydata &extradata, int threadid);
62 	void wait_for_polys();
63 
64 private:
65 	std::unique_ptr<bitmap_rgb32> m_fb;
66 	std::unique_ptr<bitmap_ind32> m_zb;
67 };
68 
69 
70 
71 /*****************************************************************************/
72 
73 /* matrix stack */
74 #define MATRIX_STACK_SIZE   256
75 
76 
77 #define BYTE_REVERSE32(x)       (((x >> 24) & 0xff) | \
78 								((x >> 8) & 0xff00) | \
79 								((x << 8) & 0xff0000) | \
80 								((x << 24) & 0xff000000))
81 
82 #define BYTE_REVERSE16(x)       (((x >> 8) & 0xff) | ((x << 8) & 0xff00))
83 
84 
model3_exit()85 void model3_state::model3_exit()
86 {
87 #if 0
88 	FILE* file;
89 	int i;
90 	file = fopen("m3_texture_ram.bin","wb");
91 	for (i=0; i < 0x200000; i++)
92 	{
93 		fputc((uint8_t)(m_texture_ram[0][i] >> 8), file);
94 		fputc((uint8_t)(m_texture_ram[0][i] >> 0), file);
95 	}
96 	for (i=0; i < 0x200000; i++)
97 	{
98 		fputc((uint8_t)(m_texture_ram[1][i] >> 8), file);
99 		fputc((uint8_t)(m_texture_ram[1][i] >> 0), file);
100 	}
101 	fclose(file);
102 
103 	file = fopen("m3_displist.bin","wb");
104 	for (i=0; i < 0x40000; i++)
105 	{
106 		fputc((uint8_t)(m_display_list_ram[i] >> 24), file);
107 		fputc((uint8_t)(m_display_list_ram[i] >> 16), file);
108 		fputc((uint8_t)(m_display_list_ram[i] >> 8), file);
109 		fputc((uint8_t)(m_display_list_ram[i] >> 0), file);
110 	}
111 	fclose(file);
112 
113 	file = fopen("m3_culling_ram.bin","wb");
114 	for (i=0; i < 0x100000; i++)
115 	{
116 		fputc((uint8_t)(m_culling_ram[i] >> 24), file);
117 		fputc((uint8_t)(m_culling_ram[i] >> 16), file);
118 		fputc((uint8_t)(m_culling_ram[i] >> 8), file);
119 		fputc((uint8_t)(m_culling_ram[i] >> 0), file);
120 	}
121 	fclose(file);
122 
123 	file = fopen("m3_polygon_ram.bin","wb");
124 	for (i=0; i < 0x100000; i++)
125 	{
126 		fputc((uint8_t)(m_polygon_ram[i] >> 24), file);
127 		fputc((uint8_t)(m_polygon_ram[i] >> 16), file);
128 		fputc((uint8_t)(m_polygon_ram[i] >> 8), file);
129 		fputc((uint8_t)(m_polygon_ram[i] >> 0), file);
130 	}
131 	fclose(file);
132 
133 	file = fopen("m3_vrom.bin","wb");
134 	for (i=0; i < 0x1000000; i++)
135 	{
136 		fputc((uint8_t)(m_vrom[i] >> 24), file);
137 		fputc((uint8_t)(m_vrom[i] >> 16), file);
138 		fputc((uint8_t)(m_vrom[i] >> 8), file);
139 		fputc((uint8_t)(m_vrom[i] >> 0), file);
140 	}
141 	fclose(file);
142 #endif
143 
144 //  invalidate_texture(0, 0, 0, 6, 5);
145 //  invalidate_texture(1, 0, 0, 6, 5);
146 }
147 
video_start()148 void model3_state::video_start()
149 {
150 	static const gfx_layout char4_layout =
151 	{
152 		8, 8,
153 		31744,
154 		4,
155 		{ 0,1,2,3 },
156 		{ 0*4, 1*4, 2*4, 3*4, 4*4, 5*4, 6*4, 7*4 },
157 		{ 1*32, 0*32, 3*32, 2*32, 5*32, 4*32, 7*32, 6*32 },
158 		4 * 8*8
159 	};
160 
161 	static const gfx_layout char8_layout =
162 	{
163 		8, 8,
164 		15872,
165 		8,
166 		{ 0,1,2,3,4,5,6,7 },
167 		{ 4*8, 5*8, 6*8, 7*8, 0*8, 1*8, 2*8, 3*8 },
168 		{ 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 },
169 		8 * 8*8
170 	};
171 
172 	int width = m_screen->width();
173 	int height = m_screen->height();
174 
175 	m_renderer = auto_alloc(machine(), model3_renderer(*this, width, height));
176 
177 	m_tri_buffer = auto_alloc_array_clear(machine(), m3_triangle, TRI_BUFFER_SIZE);
178 	m_tri_alpha_buffer = auto_alloc_array_clear(machine(), m3_triangle, TRI_ALPHA_BUFFER_SIZE);
179 
180 	machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&model3_state::model3_exit, this));
181 
182 	m_m3_char_ram = make_unique_clear<uint64_t[]>(0x100000/8);
183 	m_m3_tile_ram = make_unique_clear<uint64_t[]>(0x8000/8);
184 
185 	m_texture_fifo = make_unique_clear<uint32_t[]>(0x100000/4);
186 
187 	/* 2x 4MB texture sheets */
188 	m_texture_ram[0] = std::make_unique<uint16_t[]>(0x400000/2);
189 	m_texture_ram[1] = std::make_unique<uint16_t[]>(0x400000/2);
190 
191 	/* 1MB Display List RAM */
192 	m_display_list_ram = make_unique_clear<uint32_t[]>(0x100000/4);
193 	/* 4MB for nodes (< Step 2.0 have only 2MB) */
194 	m_culling_ram = make_unique_clear<uint32_t[]>(0x400000/4);
195 	/* 4MB Polygon RAM */
196 	m_polygon_ram = make_unique_clear<uint32_t[]>(0x400000/4);
197 
198 	m_vid_reg0 = 0;
199 
200 	m_layer4[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(model3_state::tile_info_layer0_4bit)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
201 	m_layer8[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(model3_state::tile_info_layer0_8bit)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
202 	m_layer4[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(model3_state::tile_info_layer1_4bit)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
203 	m_layer8[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(model3_state::tile_info_layer1_8bit)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
204 	m_layer4[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(model3_state::tile_info_layer2_4bit)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
205 	m_layer8[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(model3_state::tile_info_layer2_8bit)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
206 	m_layer4[3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(model3_state::tile_info_layer3_4bit)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
207 	m_layer8[3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(model3_state::tile_info_layer3_8bit)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
208 
209 	// 4-bit tiles
210 	m_gfxdecode->set_gfx(0, std::make_unique<gfx_element>(m_palette, char4_layout, (uint8_t*)m_m3_char_ram.get(), 0, m_palette->entries() / 16, 0));
211 
212 	// 8-bit tiles
213 	m_gfxdecode->set_gfx(1, std::make_unique<gfx_element>(m_palette, char8_layout, (uint8_t*)m_m3_char_ram.get(), 0, m_palette->entries() / 256, 0));
214 
215 	init_matrix_stack();
216 }
217 
218 #define MODEL3_TILE_INFO4(address)  \
219 do { \
220 	uint16_t *tiles = (uint16_t*)&m_m3_tile_ram[address + (tile_index / 4)];    \
221 	uint16_t t = BYTE_REVERSE16(tiles[(tile_index & 3) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0)]); \
222 	int tile = ((t << 1) & 0x7ffe) | ((t >> 15) & 0x1); \
223 	int color = (t & 0x7ff0) >> 4; \
224 	tileinfo.set(0, tile, color, 0); \
225 } while (0)
226 
227 #define MODEL3_TILE_INFO8(address)  \
228 do { \
229 	uint16_t *tiles = (uint16_t*)&m_m3_tile_ram[address + (tile_index / 4)];    \
230 	uint16_t t = BYTE_REVERSE16(tiles[(tile_index & 3) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0)]); \
231 	int tile = ((t << 1) & 0x7ffe) | ((t >> 15) & 0x1); \
232 	int color = (t & 0x7f00) >> 8; \
233 	tileinfo.set(1, tile >> 1, color, 0); \
234 } while (0)
235 
TILE_GET_INFO_MEMBER(model3_state::tile_info_layer0_4bit)236 TILE_GET_INFO_MEMBER(model3_state::tile_info_layer0_4bit) { MODEL3_TILE_INFO4(0x000); }
TILE_GET_INFO_MEMBER(model3_state::tile_info_layer0_8bit)237 TILE_GET_INFO_MEMBER(model3_state::tile_info_layer0_8bit) { MODEL3_TILE_INFO8(0x000); }
TILE_GET_INFO_MEMBER(model3_state::tile_info_layer1_4bit)238 TILE_GET_INFO_MEMBER(model3_state::tile_info_layer1_4bit) { MODEL3_TILE_INFO4(0x400); }
TILE_GET_INFO_MEMBER(model3_state::tile_info_layer1_8bit)239 TILE_GET_INFO_MEMBER(model3_state::tile_info_layer1_8bit) { MODEL3_TILE_INFO8(0x400); }
TILE_GET_INFO_MEMBER(model3_state::tile_info_layer2_4bit)240 TILE_GET_INFO_MEMBER(model3_state::tile_info_layer2_4bit) { MODEL3_TILE_INFO4(0x800); }
TILE_GET_INFO_MEMBER(model3_state::tile_info_layer2_8bit)241 TILE_GET_INFO_MEMBER(model3_state::tile_info_layer2_8bit) { MODEL3_TILE_INFO8(0x800); }
TILE_GET_INFO_MEMBER(model3_state::tile_info_layer3_4bit)242 TILE_GET_INFO_MEMBER(model3_state::tile_info_layer3_4bit) { MODEL3_TILE_INFO4(0xc00); }
TILE_GET_INFO_MEMBER(model3_state::tile_info_layer3_8bit)243 TILE_GET_INFO_MEMBER(model3_state::tile_info_layer3_8bit) { MODEL3_TILE_INFO8(0xc00); }
244 
245 #ifdef UNUSED_FUNCTION
draw_texture_sheet(bitmap_ind16 & bitmap,const rectangle & cliprect)246 void model3_state::draw_texture_sheet(bitmap_ind16 &bitmap, const rectangle &cliprect)
247 {
248 	for(int y = cliprect.min_y; y <= cliprect.max_y; y++)
249 	{
250 		uint16_t *const d = &bitmap.pix(y);
251 		int index = (y*2)*2048;
252 		for(int x = cliprect.min_x; x <= cliprect.max_x; x++) {
253 			uint16_t pix = m_texture_ram[0][index];
254 			index+=4;
255 			if(pix != 0) {
256 				d[x] = pix;
257 			}
258 		}
259 	}
260 }
261 #endif
262 
draw_layer(bitmap_rgb32 & bitmap,const rectangle & cliprect,int layer,int sx,int sy,int prio)263 void model3_state::draw_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect, int layer, int sx, int sy, int prio)
264 {
265 	int bitdepth = (m_layer_priority & (0x10 << layer)) ? 1 : 0;
266 //  int layer_prio = (m_layer_priority & (0x1 << layer)) ? 1 : 0;
267 
268 	tilemap_t *tmap = bitdepth ? m_layer4[layer] : m_layer8[layer];
269 	bitmap_ind16 &pixmap = tmap->pixmap();
270 	const pen_t *pens = m_palette->pens();
271 
272 	uint32_t* palram = (uint32_t*)&m_paletteram64[0];
273 	uint16_t* rowscroll_ram = (uint16_t*)&m_m3_char_ram[0x1ec00];
274 	uint32_t* rowmask_ram = (uint32_t*)&m_m3_char_ram[0x1ee00];
275 
276 	int x1 = cliprect.min_x;
277 	int y1 = cliprect.min_y;
278 	int x2 = cliprect.max_x;
279 	int y2 = cliprect.max_y;
280 
281 	int ix = sx;
282 	int iy = sy;
283 	if (ix < 0)
284 	{
285 		ix = 0 - ix;
286 	}
287 	if (iy < 0)
288 	{
289 		iy = 0 - iy;
290 	}
291 
292 	for (int y = y1; y <= y2; y++)
293 	{
294 		uint32_t *const dst = &bitmap.pix(y);
295 		uint16_t const *const src = &pixmap.pix(iy & 0x1ff);
296 
297 		int rowscroll = BYTE_REVERSE16(rowscroll_ram[((layer * 0x200) + y) ^ NATIVE_ENDIAN_VALUE_LE_BE(3,0)]) & 0x7fff;
298 		if (rowscroll & 0x100)
299 			rowscroll |= ~0x1ff;
300 
301 		uint16_t rowmask;
302 		if (prio && (layer == 1 || layer == 2))
303 			rowmask = BYTE_REVERSE32(rowmask_ram[(y & 0x1ff) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)]) & 0xffff;
304 		else
305 			rowmask = 0xffff;
306 
307 		int iix = ix & 0x1ff;
308 
309 		int rx1 = x1 - (rowscroll * 2);
310 		int rx2 = x2 - (rowscroll * 2);
311 
312 		if (rx1 < 0)
313 		{
314 			iix += (0 - rx1);
315 			rx1 = 0;
316 		}
317 		if (rx2 > cliprect.max_x)
318 			rx2 = cliprect.max_x;
319 
320 		for (int x = rx1; x <= rx2; x++)
321 		{
322 			uint32_t mask = rowmask & (1 << ((iix & 0x1ff) >> 5));
323 
324 			if (mask)
325 			{
326 				uint16_t p0 = src[iix & 0x1ff];
327 				if ((palram[p0^NATIVE_ENDIAN_VALUE_LE_BE(1,0)] & NATIVE_ENDIAN_VALUE_LE_BE(0x00800000,0x00008000)) == 0)
328 				{
329 					dst[x] = pens[p0];
330 				}
331 			}
332 			iix++;
333 		}
334 
335 		iy++;
336 	}
337 }
338 
screen_update_model3(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)339 uint32_t model3_state::screen_update_model3(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
340 {
341 	int layer_scroll_x[4], layer_scroll_y[4];
342 	uint32_t layer_data[4];
343 
344 	layer_data[0] = BYTE_REVERSE32((uint32_t)(m_layer_scroll[0] >> 32));
345 	layer_data[1] = BYTE_REVERSE32((uint32_t)(m_layer_scroll[0] >> 0));
346 	layer_data[2] = BYTE_REVERSE32((uint32_t)(m_layer_scroll[1] >> 32));
347 	layer_data[3] = BYTE_REVERSE32((uint32_t)(m_layer_scroll[1] >> 0));
348 	layer_scroll_x[0] = layer_data[0] & 0x1ff;
349 	layer_scroll_y[0] = (layer_data[0] >> 16) & 0x1ff;
350 	layer_scroll_x[1] = layer_data[1] & 0x1ff;
351 	layer_scroll_y[1] = (layer_data[1] >> 16) & 0x1ff;
352 	layer_scroll_x[2] = layer_data[2] & 0x1ff;
353 	layer_scroll_y[2] = (layer_data[2] >> 16) & 0x1ff;
354 	layer_scroll_x[3] = layer_data[3] & 0x1ff;
355 	layer_scroll_y[3] = (layer_data[3] >> 16) & 0x1ff;
356 
357 	m_screen_clip = (rectangle*)&cliprect;
358 	m_clip3d = cliprect;
359 
360 	bitmap.fill(0, cliprect);
361 
362 	// render enabled layers with priority 0
363 	if ((layer_data[3] & 0x80000000) && (m_layer_priority & 0x8) == 0)
364 		draw_layer(bitmap, cliprect, 3, layer_scroll_x[3], layer_scroll_y[3], 0);
365 	if ((layer_data[2] & 0x80000000) && (m_layer_priority & 0x4) == 0)
366 		draw_layer(bitmap, cliprect, 2, layer_scroll_x[2], layer_scroll_y[2], 0);
367 	if ((layer_data[1] & 0x80000000) && (m_layer_priority & 0x2) == 0)
368 		draw_layer(bitmap, cliprect, 1, layer_scroll_x[1], layer_scroll_y[1], 0);
369 	if ((layer_data[0] & 0x80000000) && (m_layer_priority & 0x1) == 0)
370 		draw_layer(bitmap, cliprect, 0, layer_scroll_x[0], layer_scroll_y[0], 0);
371 
372 	// render 3D
373 	m_renderer->draw(bitmap, cliprect);
374 
375 	// render enabled layers with priority 1
376 	if ((layer_data[3] & 0x80000000) && (m_layer_priority & 0x8) != 0)
377 		draw_layer(bitmap, cliprect, 3, layer_scroll_x[3], layer_scroll_y[3], 1);
378 	if ((layer_data[2] & 0x80000000) && (m_layer_priority & 0x4) != 0)
379 		draw_layer(bitmap, cliprect, 2, layer_scroll_x[2], layer_scroll_y[2], 1);
380 	if ((layer_data[0] & 0x80000000) && (m_layer_priority & 0x1) != 0)
381 		draw_layer(bitmap, cliprect, 0, layer_scroll_x[0], layer_scroll_y[0], 1);
382 	if ((layer_data[1] & 0x80000000) && (m_layer_priority & 0x2) != 0)
383 		draw_layer(bitmap, cliprect, 1, layer_scroll_x[1], layer_scroll_y[1], 1);
384 
385 	return 0;
386 }
387 
388 
389 
model3_char_r(offs_t offset)390 uint64_t model3_state::model3_char_r(offs_t offset)
391 {
392 	return m_m3_char_ram[offset];
393 }
394 
model3_char_w(offs_t offset,uint64_t data,uint64_t mem_mask)395 void model3_state::model3_char_w(offs_t offset, uint64_t data, uint64_t mem_mask)
396 {
397 	COMBINE_DATA(&m_m3_char_ram[offset]);
398 	m_gfxdecode->gfx(0)->mark_dirty(offset / 4);
399 	m_gfxdecode->gfx(1)->mark_dirty(offset / 8);
400 }
401 
model3_tile_r(offs_t offset)402 uint64_t model3_state::model3_tile_r(offs_t offset)
403 {
404 	return m_m3_tile_ram[offset];
405 }
406 
model3_tile_w(offs_t offset,uint64_t data,uint64_t mem_mask)407 void model3_state::model3_tile_w(offs_t offset, uint64_t data, uint64_t mem_mask)
408 {
409 	COMBINE_DATA(&m_m3_tile_ram[offset]);
410 
411 	/*
412 	m_layer4[0]->mark_all_dirty();
413 	m_layer8[0]->mark_all_dirty();
414 	m_layer4[1]->mark_all_dirty();
415 	m_layer8[1]->mark_all_dirty();
416 	m_layer4[2]->mark_all_dirty();
417 	m_layer8[2]->mark_all_dirty();
418 	m_layer4[3]->mark_all_dirty();
419 	m_layer8[3]->mark_all_dirty();
420 	*/
421 
422 	int layer = (offset >> 10) & 0x3;
423 	int tile = (offset & 0x3ff) * 4;
424 	m_layer4[layer]->mark_tile_dirty(tile+0);
425 	m_layer4[layer]->mark_tile_dirty(tile+1);
426 	m_layer4[layer]->mark_tile_dirty(tile+2);
427 	m_layer4[layer]->mark_tile_dirty(tile+3);
428 	m_layer8[layer]->mark_tile_dirty(tile+0);
429 	m_layer8[layer]->mark_tile_dirty(tile+1);
430 	m_layer8[layer]->mark_tile_dirty(tile+2);
431 	m_layer8[layer]->mark_tile_dirty(tile+3);
432 }
433 
434 /*
435     Video registers:
436 
437     0xF1180000:         ?
438     0xF1180004:         ?
439     0xF1180008:         ?                                   lostwsga: writes 0x7f010000
440                                                             lemans24, magtruck, von2, lamachin: writes 0xee000000
441                                                             bass, vs2, harley, scud, skichamp, fvipers2, eca: writes 0xef000000
442                                                             srally2, swtrilgy: writes 0x70010000
443                                                             daytona2: writes 0x4f010000
444 
445     0xF1180010:                                             VBL IRQ acknowledge
446 
447     0xF1180020:         xxxxxxxx -------- -------- -------- ?
448                         -------- x------- -------- -------- Layer 3 bitdepth (0 = 8-bit, 1 = 4-bit)
449                         -------- -x------ -------- -------- Layer 2 bitdepth (0 = 8-bit, 1 = 4-bit)
450                         -------- --x----- -------- -------- Layer 1 bitdepth (0 = 8-bit, 1 = 4-bit)
451                         -------- ---x---- -------- -------- Layer 0 bitdepth (0 = 8-bit, 1 = 4-bit)
452                         -------- ----x--- -------- -------- Layer 3 priority (0 = below 3D, 1 = above 3D)
453                         -------- -----x-- -------- -------- Layer 2 priority (0 = below 3D, 1 = above 3D)
454                         -------- ------x- -------- -------- Layer 1 priority (0 = below 3D, 1 = above 3D)
455                         -------- -------x -------- -------- Layer 0 priority (0 = below 3D, 1 = above 3D)
456 
457     0xF1180040:                                             Foreground layer color modulation?
458                         -------- xxxxxxxx -------- -------- Red component
459                         -------- -------- xxxxxxxx -------- Green component
460                         -------- -------- -------- xxxxxxxx Blue component
461 
462     0xF1180044:                                             Background layer color modulation?
463                         -------- xxxxxxxx -------- -------- Red component
464                         -------- -------- xxxxxxxx -------- Green component
465                         -------- -------- -------- xxxxxxxx Blue component
466 
467     0xF1180060:         x------- -------- -------- -------- Layer 0 enable
468                         -------x xxxxxxxx -------- -------- Layer 0 Y scroll position
469                         -------- -------- -------x xxxxxxxx Layer 0 X scroll position
470 
471     0xF1180064:         x------- -------- -------- -------- Layer 1 enable
472                         -------x xxxxxxxx -------- -------- Layer 1 Y scroll position
473                         -------- -------- -------x xxxxxxxx Layer 1 X scroll position
474 
475     0xF1180068:         x------- -------- -------- -------- Layer 2 enable
476                         -------x xxxxxxxx -------- -------- Layer 2 Y scroll position
477                         -------- -------- -------x xxxxxxxx Layer 2 X scroll position
478 
479     0xF118006C:         x------- -------- -------- -------- Layer 3 enable
480                         -------x xxxxxxxx -------- -------- Layer 3 Y scroll position
481                         -------- -------- -------x xxxxxxxx Layer 3 X scroll position
482 */
483 
484 
model3_vid_reg_r(offs_t offset)485 uint64_t model3_state::model3_vid_reg_r(offs_t offset)
486 {
487 	switch(offset)
488 	{
489 		case 0x00/8:    return m_vid_reg0;
490 		case 0x08/8:    return 0xffffffffffffffffU;     /* ??? */
491 		case 0x20/8:    return (uint64_t)m_layer_priority << 48;
492 		case 0x40/8:    return ((uint64_t)m_layer_modulate1 << 32) | (uint64_t)m_layer_modulate2;
493 		default:        logerror("read reg %02X\n", offset);break;
494 	}
495 	return 0;
496 }
497 
model3_vid_reg_w(offs_t offset,uint64_t data,uint64_t mem_mask)498 void model3_state::model3_vid_reg_w(offs_t offset, uint64_t data, uint64_t mem_mask)
499 {
500 	switch(offset)
501 	{
502 		case 0x00/8:    logerror("vid_reg0: %08X%08X\n", (uint32_t)(data>>32),(uint32_t)(data)); m_vid_reg0 = data; break;
503 		case 0x08/8:    break;      /* ??? */
504 		case 0x10/8:    set_irq_line((data >> 56) & 0x0f, CLEAR_LINE); break;     /* VBL IRQ Ack */
505 
506 		case 0x20/8:    m_layer_priority = (data >> 48); break;
507 
508 		case 0x40/8:    m_layer_modulate1 = (uint32_t)(data >> 32);
509 						m_layer_modulate2 = (uint32_t)(data);
510 						break;
511 		case 0x60/8:    COMBINE_DATA(&m_layer_scroll[0]); break;
512 		case 0x68/8:    COMBINE_DATA(&m_layer_scroll[1]); break;
513 		default:        logerror("model3_vid_reg_w: %02X, %08X%08X\n", offset, (uint32_t)(data >> 32), (uint32_t)(data)); break;
514 	}
515 }
516 
model3_palette_w(offs_t offset,uint64_t data,uint64_t mem_mask)517 void model3_state::model3_palette_w(offs_t offset, uint64_t data, uint64_t mem_mask)
518 {
519 	COMBINE_DATA(&m_paletteram64[offset]);
520 	uint32_t data1 = BYTE_REVERSE32((uint32_t)(m_paletteram64[offset] >> 32));
521 	uint32_t data2 = BYTE_REVERSE32((uint32_t)(m_paletteram64[offset] >> 0));
522 
523 	m_palette->set_pen_color((offset*2)+0, pal5bit(data1 >> 0), pal5bit(data1 >> 5), pal5bit(data1 >> 10));
524 	m_palette->set_pen_color((offset*2)+1, pal5bit(data2 >> 0), pal5bit(data2 >> 5), pal5bit(data2 >> 10));
525 }
526 
model3_palette_r(offs_t offset)527 uint64_t model3_state::model3_palette_r(offs_t offset)
528 {
529 	return m_paletteram64[offset];
530 }
531 
532 
533 /*****************************************************************************/
534 /* texture caching */
535 
536 /*
537     array of cached textures:
538         4 potential textures for 4-bit grayscale
539         2 pages
540         1024 pixels / 32 pixel resolution vertically
541         2048 pixels / 32 pixel resolution horizontally
542 */
invalidate_texture(int page,int texx,int texy,int texwidth,int texheight)543 void model3_state::invalidate_texture(int page, int texx, int texy, int texwidth, int texheight)
544 {
545 	int wtiles = 1 << texwidth;
546 	int htiles = 1 << texheight;
547 
548 	for (int y = 0; y < htiles; y++)
549 		for (int x = 0; x < wtiles; x++)
550 			while (m_texcache[page][texy + y][texx + x] != nullptr)
551 			{
552 				cached_texture *freeme = m_texcache[page][texy + y][texx + x];
553 				m_texcache[page][texy + y][texx + x] = freeme->next;
554 				auto_free(machine(), freeme);
555 			}
556 }
557 
get_texture(int page,int texx,int texy,int texwidth,int texheight,int format)558 cached_texture *model3_state::get_texture(int page, int texx, int texy, int texwidth, int texheight, int format)
559 {
560 	cached_texture *tex = m_texcache[page][texy][texx];
561 	int pixheight = 32 << texheight;
562 	int pixwidth = 32 << texwidth;
563 	uint32_t alpha = ~0;
564 	int x, y;
565 
566 	/* if we have one already, validate it */
567 	for (tex = m_texcache[page][texy][texx]; tex != nullptr; tex = tex->next)
568 		if (tex->width == texwidth && tex->height == texheight && tex->format == format)
569 			return tex;
570 
571 	/* create a new texture */
572 	tex = (cached_texture *)auto_alloc_array(machine(), uint8_t, sizeof(cached_texture) + (2 * pixwidth * 2 * pixheight) * sizeof(rgb_t));
573 	tex->width = texwidth;
574 	tex->height = texheight;
575 	tex->format = format;
576 
577 	/* set the new texture */
578 	tex->next = m_texcache[page][texy][texx];
579 	m_texcache[page][texy][texx] = tex;
580 
581 	/* decode it */
582 	for (y = 0; y < pixheight; y++)
583 	{
584 		const uint16_t *texsrc = &m_texture_ram[page][(texy * 32 + y) * 2048 + texx * 32];
585 		rgb_t *dest = tex->data + 2 * pixwidth * y;
586 
587 		switch (format)
588 		{
589 			case 0:     /* 1-5-5-5 ARGB */
590 				for (x = 0; x < pixwidth; x++)
591 				{
592 					uint16_t pixdata = texsrc[x];
593 					alpha &= dest[x] = rgb_t(pal1bit(~pixdata >> 15), pal5bit(pixdata >> 10), pal5bit(pixdata >> 5), pal5bit(pixdata >> 0));
594 				}
595 				break;
596 
597 			case 1:     /* A4L4 interleaved */
598 				for (x = 0; x < pixwidth; x++)
599 				{
600 					uint8_t grayvalue = pal4bit(texsrc[x] & 0xf);
601 					uint8_t a = pal4bit((texsrc[x] >> 4) & 0xf);
602 					alpha &= dest[x] = rgb_t(a, grayvalue, grayvalue, grayvalue);
603 				}
604 				break;
605 
606 			case 2:     /* A4L4? */
607 				for (x = 0; x < pixwidth; x++)
608 				{
609 					uint8_t grayvalue = pal4bit((texsrc[x] >> 0) & 0xf);
610 					uint8_t a = pal4bit((texsrc[x] >> 4) & 0xf);
611 					alpha &= dest[x] = rgb_t(a, grayvalue, grayvalue, grayvalue);
612 				}
613 				break;
614 
615 			case 3:     /* A4L4 interleaved */
616 				for (x = 0; x < pixwidth; x++)
617 				{
618 					uint8_t grayvalue = pal4bit((texsrc[x] >> 8) & 0xf);
619 					uint8_t a = pal4bit((texsrc[x] >> 12) & 0xf);
620 					alpha &= dest[x] = rgb_t(a, grayvalue, grayvalue, grayvalue);
621 				}
622 				break;
623 
624 			case 4:     /* 8-bit A4L4 */
625 				for (x = 0; x < pixwidth; x++)
626 				{
627 					uint8_t pixdata = texsrc[x] >> 8;
628 					alpha &= dest[x] = rgb_t(pal4bit(pixdata), pal4bit(pixdata >> 4), pal4bit(pixdata >> 4), pal4bit(pixdata >> 4));
629 				}
630 				break;
631 
632 			case 5:     /* L8 */
633 				for (x = 0; x < pixwidth; x++)
634 				{
635 					uint8_t grayvalue = texsrc[x];
636 					alpha &= dest[x] = rgb_t(0xff, grayvalue, grayvalue, grayvalue);
637 				}
638 				break;
639 
640 			case 6:     /* L8 */
641 				for (x = 0; x < pixwidth; x++)
642 				{
643 					uint8_t grayvalue = texsrc[x] >> 8;
644 					alpha &= dest[x] = rgb_t(0xff, grayvalue, grayvalue, grayvalue);
645 				}
646 				break;
647 
648 			case 7:     /* 4-4-4-4 ARGB */
649 				for (x = 0; x < pixwidth; x++)
650 				{
651 					uint16_t pixdata = texsrc[x];
652 					alpha &= dest[x] = rgb_t(pal4bit(pixdata >> 0), pal4bit(pixdata >> 12), pal4bit(pixdata >> 8), pal4bit(pixdata >> 4));
653 				}
654 				break;
655 		}
656 
657 		/* create the horizontal mirror of this line */
658 		for (x = 0; x < pixwidth; x++)
659 			dest[pixwidth * 2 - 1 - x] = dest[x];
660 	}
661 
662 	/* create the vertical mirror of the texture */
663 	for (y = 0; y < pixheight; y++)
664 		memcpy(tex->data + 2 * pixwidth * (pixheight * 2 - 1 - y), tex->data + 2 * pixwidth * y, sizeof(rgb_t) * pixwidth * 2);
665 
666 	/* remember the overall alpha */
667 	tex->alpha = alpha >> 24;
668 
669 	/* return a pointer to the texture */
670 	return tex;
671 }
672 
673 /*****************************************************************************/
674 /* Real3D Graphics stuff */
675 
676 /*
677     Real3D Pro-1000 capabilities:
678 
679     Coordinate sets
680     - 4096 matrices (matrix base pointer in viewport node)
681 
682     Polygons
683     - 32MB max polygon memory. VROM in Model 3, the low 4MB of VROM is overlaid by Polygon RAM for runtime generated content.
684 
685     Texture
686     - 2 texture sheets of 2048x1024
687     - Mipmaps located in the bottom right corner
688     - Texture size 32x32 to 1024x1024
689     - Microtextures (is this featured in Model 3?)
690 
691     LODs
692     - 127 blend types per viewport with 4 sets of min/max angle or range (where is this in the viewport node?)
693 
694     Lighting
695     - Self-luminous lighting (enable and luminosity parameter in polygon structure)
696     - Fixed polygon shading, fixed shading weight per vertex (not found in Model 3, yet)
697     - Flat sun shading (lighting parameters in viewport node) needs a separate enable?
698     - Smooth polygon shading (lighting parameters in viewport, use vertex normals)
699 
700     Gamma table
701     - 256 entry 8-bit table, possibly in Polygon RAM
702 */
703 
704 /*
705     Real3D Memory Structures:
706 
707     Culling Nodes:
708     - Located in Culling RAM (0x8E000000)
709     - Limit of 15 child nodes (nesting), not including polygon nodes
710     - Color table (is this featured in Model 3?)
711 
712     0x00:   xxxxxxxx xxxxxxxx xxxxxx-- -------- Viewport number
713             -------- -------- ------xx -------- Viewport select 0-3
714             -------- -------- -------- x------- Display select
715             -------- -------- -------- -x------ Fix point centroid
716             -------- -------- -------- --x----- Viewport off
717             -------- -------- -------- ---xx--- Viewport priority
718             -------- -------- -------- -----x-- "clr_xlator_tbl_sel"
719             -------- -------- -------- ------xx Node type
720 
721     0x01:   -------x -------- -------- -------- Sibling null
722             -------- xxxxxxxx xxxxxxxx xxxxxxxx Sibling pointer
723 
724     0x02:   -----x-- -------- -------- -------- Child is sibling table
725             -------x -------- -------- -------- Leaf node
726             -------- xxxxxxxx xxxxxxxx xxxxxxxx Child pointer
727 
728     0x03:   "cota" (float) Affected by frustum angles and viewport size
729     0x04:   Sun light vector X-component (float)
730     0x05:   Sun light vector Y-component (float)
731     0x06:   Sun light vector Z-component (float)
732     0x07:   Sun light intensity (float)
733     0x08:   "Cv" ? (float) Affected by left and right angle
734     0x09:   "Cw" ? (float) Affected by top and bottom angle
735     0x0a:   "Io" ? (float) Affected by top and bottom angle
736     0x0b:   "Jo" ? (float) Affected by left and right angle
737     0x0c:   (float) Left clip plane U
738     0x0d:   (float) Left clip plane V
739     0x0e:   (float) Top clip plane U
740     0x0f:   (float) Top clip plane W
741     0x10:   (float) Right clip plane U
742     0x11:   (float) Right clip plane V
743     0x12:   (float) Bottom clip plane U
744     0x13:   (float) Bottom clip plane W
745 
746     0x14:   xxxxxxxx xxxxxxxx -------- -------- Viewport height (14.2 fixed-point)
747             -------- -------- xxxxxxxx xxxxxxxx Viewport width (14.2 fixed-point)
748 
749     0x15:   xxxxxxxx xxxxxxxx -------- -------- "env_to_chan_matrix_index"
750 
751     0x16:   -------- xxxxxxxx xxxxxxxx xxxxxxxx Matrix base pointer
752 
753     0x17:   -------- xxxxxxxx xxxxxxxx xxxxxxxx LOD pointer
754 
755     0x18:   -------- xxxxxxxx xxxxxxxx xxxxxxxx Culling offset
756 
757     0x19:   -------- xxxxxxxx xxxxxxxx xxxxxxxx Polygon offset
758 
759     0x1a:   xxxxxxxx xxxxxxxx -------- -------- Viewport Y coordinate (12.4 fixed-point)
760             -------- -------- xxxxxxxx xxxxxxxx Viewport X coordinate (12.4 fixed-point)
761 
762     0x1b:   Copy of word 0x00
763 
764     0x1c:   xxxxxxxx xxxxxxxx -------- -------- "lj"
765             -------- -------- xxxxxxxx xxxxxxxx "li"
766 
767     0x1d:   -------- xxxxxxxx -------- -------- Spotlight Y size
768             -------- -------- xxxxxxxx xxxxxxxx Spotlight Y position (13.3 fixed-point?)
769 
770     0x1e:   -------- xxxxxxxx -------- -------- Spotlight X size
771             -------- -------- xxxxxxxx xxxxxxxx Spotlight X position (13.3 fixed-point?)
772 
773     0x1f:   Light extent (float)
774 
775     0x20:   xxxxxxxx -------- -------- -------- ?
776             -------- xxxxxxxx -------- -------- ?
777             -------- -------- -x------ -------- Parallel projection
778             -------- -------- --xxx--- -------- Light RGB (RGB111?)
779             -------- -------- -----xxx -------- Light RGB Fog (RGB111?)
780             -------- -------- -------- xxxxxxxx Scroll Fog (0.8 fixed-point?) What is this???
781 
782     0x21:   "inv_light_start_range" (float)
783     0x22:   Fog Color (RGB888)
784     0x23:   Fog Density (float)
785 
786     0x24:   -------- xxxxxxxx -------- -------- Fog attenuation
787             -------- -------- xxxxxxxx -------- Sun light ambient (0.8 fixed-point)
788             -------- -------- -------- xxxxxxxx Scroll attenuation (0.8 fixed-point) What is this???
789 
790     0x25:   -------- xxxxxxxx -------- -------- Ambient fog
791             -------- -------- xxxxxxxx xxxxxxxx Fog offset
792 
793     0x26:   xxxxxxxx xxxxxxxx xxxxxxxx -------- Spot light
794             -------- -------- -------- x------- Clear viewport
795             -------- -------- -------- -x------ New sun parameters
796 
797     0x27:   x------- -------- -------- -------- Valid spot light
798             -x------ -------- -------- -------- Pro 1000 dummy
799             -------- --xxxxxx xxxxxxxx xxxxxxxx "upgrade_wd_10"
800 
801     0x28:   Fog layer altitude (float)
802 
803     0x29:   Top fog density (float)
804 
805     0x2a:   Bottom fog density (float)
806 
807     0x2b:   Near clipping plane (float)
808 
809     0x2c:   Far clipping plane (float)
810 
811     0x2d:   Pfog offset top
812 
813     0x2e:   Pfog offset bottom
814     0x2f:   ?
815 
816 
817     Sub types:
818     LOD Culling Node. Up to 4 LODs.
819 
820     Articulated Part Culling Node (is this used by Model 3?)
821     - An Articulated Part culling node, or six degree?of?freedom node, is used to define
822       geometry that can move relative to the parent coordinate set to which it is attached.
823       Fifteen levels of coordinate set nesting (levels of articulation) are supported.
824 
825     Animation Culling Node
826     - Animation culling nodes are used to build a culling hierarchy for an object with different
827       representations, or animation frames. which can be turned on and off by the
828       application. Each child (culling node or polygon) added to an Animation culling node
829       specifies the frame for which the child is valid.
830 
831     Instance Culling Node
832     - Instance culling nodes define the top of a shared display list segment that can be
833       referenced from other parts of the scene display list.
834 
835     Instance Reference Culling Node
836     - An Instance Reference node is considered a leaf node; its
837       "child" is the shared geometry segment. An Instance Reference may be attached to
838       a parent node and may not have any other children, but may have siblings.
839 
840     Point Light
841     - A Point Light is used to create an instance of a point luminous feature. The size,
842       feature type, and number of sides of the point light model may be customized.
843 
844     Instance Set
845     - An Instance Set is a culling node which defines a set of point features. Each feature
846       is positioned individually. This type of culling node can be used to simulate particles.
847 
848 
849 
850     Instance Node?
851 
852     0x00:   x------- -------- -------- -------- Is UF ref
853             -x------ -------- -------- -------- Is 3D model
854             --x----- -------- -------- -------- Is point
855             ---x---- -------- -------- -------- Is point ref
856             ----x--- -------- -------- -------- Is animation
857             -----x-- -------- -------- -------- Is billboard
858             ------x- -------- -------- -------- Child is billboard
859             -------x -------- -------- -------- Extra child pointer needed
860             -------- -----xxx xxxxxx-- -------- Node ID
861 
862             -------- -------- -------- x------- Reset matrix
863             -------- -------- -------- -x------ Use child pointer
864             -------- -------- -------- --x----- Use sibling pointer
865             -------- -------- -------- ---x---- No matrix
866             -------- -------- -------- ----x--- Indirect child
867             -------- -------- -------- -----x-- Valid color table
868             -------- -------- -------- ------xx Node type (0 = viewport, 1 = root node, 2 = culling node)
869 
870     0x01,0x02 only present on Step 2+
871 
872     0x01:   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Model scale (float)
873     0x02:   -------- -------- x------- -------- Texture replace
874             -------- -------- -x------ -------- Switch bank
875             -------- -------- --xxxxxx x------- X offset
876             -------- -------- -------- -xxxxxxx Y offset
877 
878     0x03:   xxxxxxxx xxxxx--- -------- -------- Color table address 1
879             -------- -----xxx xxxx---- -------- LOD table pointer
880             -------- -------- ----xxxx xxxxxxxx Node matrix
881 
882     0x04:   Translation X coordinate
883     0x05:   Translation Y coordinate
884     0x06:   Translation Z coordinate
885 
886     0x07:   xxxx---- -------- -------- -------- Color table address 2
887             -----x-- -------- -------- -------- Sibling table
888             ------x- -------- -------- -------- Point
889             -------x -------- -------- -------- Leaf node
890             -------- xxxxxxxx xxxxxxxx xxxxxxxx Child pointer
891 
892     0x08:   xxxxxxx- -------- -------- -------- Color table address 3
893             -------x -------- -------- -------- Null sibling
894             -------- xxxxxxxx xxxxxxxx xxxxxxxx Sibling pointer
895 
896     0x09:   xxxxxxxx xxxxxxxx -------- -------- Blend radius
897             -------- -------- xxxxxxxx xxxxxxxx Culling radius
898 
899 
900     Polygon Data
901 
902     0x00:   xxxxxx-- -------- -------- -------- Specular
903             ------x- -------- -------- -------- Clockwise data
904             -------x xxxxxxxx xxxxxx-- -------- Polygon ID
905             -------- -------- ------xx -------- Discard this polygon
906             -------- -------- -------- x------- Specular enable
907             -------- -------- -------- -x------ 0 = Triangle, 1 = Quad
908             -------- -------- -------- --x----- Polygon is points
909             -------- -------- -------- ---x---- Smoothing enable
910             -------- -------- -------- ----x--- Vertex 3 shared from previous polygon
911             -------- -------- -------- -----x-- Vertex 2 shared from previous polygon
912             -------- -------- -------- ------x- Vertex 1 shared from previous polygon
913             -------- -------- -------- -------x Vertex 0 shared from previous polygon
914 
915 
916     0x01:   xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal X coordinate (2.22 fixed point)
917             -------- -------- -------- x------- Edge on translucency
918             -------- -------- -------- -x------ UV format (0 = 13.3, 1 = 16.0)
919             -------- -------- -------- --x----- Enable fixed shading
920             -------- -------- -------- ---x---- Enable double-sided polygon
921             -------- -------- -------- ----x--- Enable smooth shading
922             -------- -------- -------- -----x-- If set, this is the last polygon
923             -------- -------- -------- ------x- Poly color, 1 = RGB, 0 = color table
924             -------- -------- -------- -------x No LOS return
925 
926 
927     0x02:   xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal Y coordinate (2.22 fixed point)
928             -------- -------- -------- xxx----- Microtexture select
929             -------- -------- -------- ---x---- Microtexture enable
930             -------- -------- -------- ----xx-- Microtexture min LOD
931             -------- -------- -------- ------x- Texture U mirror enable
932             -------- -------- -------- -------x Texture V mirror enable
933 
934     0x03:   xxxxxxxx xxxxxxxx xxxxxxxx -------- Polygon normal Z coordinate (2.22 fixed point)
935             -------- -------- -------- x------- X wrap smoothing
936             -------- -------- -------- -x------ Y wrap smoothing
937             -------- -------- -------- --xxx--- Texture width (in 8-pixel tiles)
938             -------- -------- -------- -----xxx Texture height (in 8-pixel tiles)
939 
940     0x04:   xxxxxxxx xxxxxxxx xxxxxxxx -------- Color (RGB888)
941             -------- -------- -------- x------- Translator map select
942             -------- -------- -------- -x------ Texture page
943             -------- -------- -------- --xxxxxx Upper 6 bits of texture U coordinate
944 
945     0x05:   xxxxxxxx xxxxxxxx xxxxxxxx -------- Texture NP scale
946             -------- -------- -------- x------- Low bit of texture U coordinate
947             -------- -------- -------- ---xxxxx Low 5 bits of texture V coordinate
948             -------- -------- -------- -xx----- Top 2 bits of texture V coordinate (unused by Model 3)
949 
950     0x06:   x------- -------- -------- -------- Texture contour enable
951             -xxxxxxx -------- -------- -------- Translator map offset
952             -------- xxxxxx-- -------- -------- Polygon translucency
953             -------- ------x- -------- -------- Translucency pattern select
954             -------- -------x -------- -------- 1 = disable lighting
955             -------- -------- xxxxx--- -------- Polygon light modifier (Amount that a luminous polygon will burn through fog.
956                                                                         Valid range is 0.0 to 1.0. 0.0 is completely fogged;
957                                                                         1.0 has no fog.)
958             -------- -------- -----x-- -------- Texture enable
959             -------- -------- ------xx x------- Texture format
960             -------- -------- -------- -xx----- Shininess
961             -------- -------- -------- ---x---- High priority polygon
962             -------- -------- -------- ----x--- Layered polygon (stencil)
963             -------- -------- -------- -----xxx Translucency mode
964 
965 
966     Vertex entry
967 
968     0x00:   xxxxxxxx xxxxxxxx xxxxxxxx -------- Vertex X coordinate (17.7 fixed-point in Step 1.0, 13.11 otherwise)
969             -------- -------- -------- xxxxxxxx Vertex normal X
970 
971     0x01:   xxxxxxxx xxxxxxxx xxxxxxxx -------- Vertex Y coordinate
972             -------- -------- -------- xxxxxxxx Vertex normal Y
973 
974     0x02:   xxxxxxxx xxxxxxxx xxxxxxxx -------- Vertex Z coordinate
975             -------- -------- -------- xxxxxxxx Vertex normal Z
976 
977     0x03:   xxxxxxxx xxxxxxxx -------- -------- Vertex U coordinate
978             -------- -------- xxxxxxxx xxxxxxxx Vertex V coordinate
979 
980 */
981 
982 
real3d_display_list_w(offs_t offset,uint64_t data,uint64_t mem_mask)983 void model3_state::real3d_display_list_w(offs_t offset, uint64_t data, uint64_t mem_mask)
984 {
985 	if (ACCESSING_BITS_32_63)
986 	{
987 		m_display_list_ram[offset*2] = BYTE_REVERSE32((uint32_t)(data >> 32));
988 	}
989 	if (ACCESSING_BITS_0_31)
990 	{
991 		m_display_list_ram[(offset*2)+1] = BYTE_REVERSE32((uint32_t)(data));
992 	}
993 }
994 
real3d_polygon_ram_w(offs_t offset,uint64_t data,uint64_t mem_mask)995 void model3_state::real3d_polygon_ram_w(offs_t offset, uint64_t data, uint64_t mem_mask)
996 {
997 	if (ACCESSING_BITS_32_63)
998 	{
999 		m_polygon_ram[offset*2] = BYTE_REVERSE32((uint32_t)(data >> 32));
1000 	}
1001 	if (ACCESSING_BITS_0_31)
1002 	{
1003 		m_polygon_ram[(offset*2)+1] = BYTE_REVERSE32((uint32_t)(data));
1004 	}
1005 }
1006 
1007 static const uint8_t texture_decode16[64] =
1008 {
1009 		0,  1,  4,  5,  8,  9, 12, 13,
1010 		2,  3,  6,  7, 10, 11, 14, 15,
1011 	16, 17, 20, 21, 24, 25, 28, 29,
1012 	18, 19, 22, 23, 26, 27, 30, 31,
1013 	32, 33, 36, 37, 40, 41, 44, 45,
1014 	34, 35, 38, 39, 42, 43, 46, 47,
1015 	48, 49, 52, 53, 56, 57, 60, 61,
1016 	50, 51, 54, 55, 58, 59, 62, 63
1017 };
1018 
1019 static const uint8_t texture_decode8[32] =
1020 {
1021 		1,  3,  5,  7,
1022 		0,  2,  4,  6,
1023 		9, 11, 13, 15,
1024 		8, 10, 12, 14,
1025 	17, 19, 21, 23,
1026 	16, 18, 20, 22,
1027 	25, 27, 29, 31,
1028 	24, 26, 28, 30
1029 };
1030 
write_texture16(int xpos,int ypos,int width,int height,int page,uint16_t * data)1031 inline void model3_state::write_texture16(int xpos, int ypos, int width, int height, int page, uint16_t *data)
1032 {
1033 	int x,y,i,j;
1034 
1035 	for(y=ypos; y < ypos+height; y+=8)
1036 	{
1037 		for(x=xpos; x < xpos+width; x+=8)
1038 		{
1039 			uint16_t *texture = &m_texture_ram[page][y*2048+x];
1040 			int b = 0;
1041 			for(j=y; j < y+8; j++) {
1042 				for(i=x; i < x+8; i++) {
1043 					*texture++ = data[texture_decode16[b^1]];
1044 					++b;
1045 				}
1046 				texture += 2048-8;
1047 			}
1048 			data += 64;
1049 		}
1050 	}
1051 }
1052 
write_texture8(int xpos,int ypos,int width,int height,int page,int upper,int lower,uint16_t * data)1053 inline void model3_state::write_texture8(int xpos, int ypos, int width, int height, int page, int upper, int lower, uint16_t *data)
1054 {
1055 	int x,y,i,j;
1056 
1057 	for(y=ypos; y < ypos+height; y+=8)
1058 	{
1059 		for(x=xpos; x < xpos+width; x+=8)
1060 		{
1061 			uint16_t *texture = &m_texture_ram[page][y*2048+x];
1062 			int b = 0;
1063 			for(j=y; j < y+8; j++)
1064 			{
1065 				for(i=x; i < x+8; i+=2)
1066 				{
1067 					uint16_t d = data[texture_decode8[b]];
1068 
1069 					if (upper)
1070 						*texture = (*texture & 0xff) | (d & 0xff00);
1071 					if (lower)
1072 						*texture = (*texture & 0xff00) | ((d >> 8) & 0xff);
1073 					texture++;
1074 
1075 					if (upper)
1076 						*texture = (*texture & 0xff) | ((d & 0xff) << 8);
1077 					if (lower)
1078 						*texture = (*texture & 0xff00) | (d & 0xff);
1079 					texture++;
1080 
1081 					++b;
1082 				}
1083 				texture += 2048-8;
1084 			}
1085 			data += 32;
1086 		}
1087 	}
1088 }
1089 
1090 /*
1091     Texture header:
1092 
1093     -------- -------- -------- --xxxxxx X-position
1094     -------- -------- ----xxxx x------- Y-position
1095     -------- -------x xx------ -------- Width
1096     -------- ----xxx- -------- -------- Height
1097     -------- ---x---- -------- -------- Texture page
1098     -------- --x----- -------- -------- Write 8-bit data to the lower byte of texel
1099     -------- -x------ -------- -------- Write 8-bit data to the upper byte of texel
1100     -------- x------- -------- -------- Bitdepth, 0 = 8-bit, 1 = 16-bit
1101     xxxxxxxx -------- -------- -------- Texture type
1102                                             0x00 = texture with mipmaps
1103                                             0x01 = texture without mipmaps
1104                                             0x02 = only mipmaps
1105                                             0x80 = possibly gamma table
1106 
1107 */
1108 
1109 static const int mipmap_coords[9][2] =
1110 {
1111 	{ 1024,  512 },
1112 	{ 1536,  768 },
1113 	{ 1792,  896 },
1114 	{ 1920,  960 },
1115 	{ 1984,  992 },
1116 	{ 2016, 1008 },
1117 	{ 2032, 1016 },
1118 	{ 2040, 1020 },
1119 	{ 2044, 1022 },
1120 };
1121 
1122 static const int mipmap_divider[9] = { 2, 4, 8, 16, 32, 64, 128, 256, 512 };
1123 
real3d_upload_texture(uint32_t header,uint32_t * data)1124 void model3_state::real3d_upload_texture(uint32_t header, uint32_t *data)
1125 {
1126 	int width   = 32 << ((header >> 14) & 0x7);
1127 	int height  = 32 << ((header >> 17) & 0x7);
1128 	int xpos    = (header & 0x3f) * 32;
1129 	int ypos    = ((header >> 7) & 0x1f) * 32;
1130 	int page    = (header >> 20) & 0x1;
1131 	int bitdepth = (header >> 23) & 0x1;
1132 	int upper_byte = (header >> 22) & 0x1;
1133 	int lower_byte = (header >> 21) & 0x1;
1134 
1135 	//printf("write tex: %08X, w %d, h %d, x %d, y %d, p %d, b %d\n", header, width, height, xpos, ypos, page, bitdepth);
1136 
1137 	switch(header >> 24)
1138 	{
1139 		case 0x00:      /* Texture with mipmaps */
1140 		{
1141 			int x = xpos;
1142 			int y = ypos;
1143 			int w = width;
1144 			int h = height;
1145 
1146 			int mipmap = 0;
1147 
1148 			while (w >= 8 && h >= 8)
1149 			{
1150 				if (bitdepth)
1151 				{
1152 					write_texture16(x, y, w, h, page, (uint16_t*)data);
1153 				}
1154 				else
1155 				{
1156 					//printf("write tex8: %08X, w %d, h %d, x %d, y %d, p %d, b %d\n", header, width, height, xpos, ypos, page, bitdepth);
1157 					write_texture8(x, y, w, h, page, upper_byte, lower_byte, (uint16_t*)data);
1158 				}
1159 
1160 				data += (w * h * (bitdepth ? 2 : 1)) / 4;
1161 				w /= 2;
1162 				h /= 2;
1163 
1164 				x = mipmap_coords[mipmap][0] + (xpos / mipmap_divider[mipmap]);
1165 				y = mipmap_coords[mipmap][1] + (ypos / mipmap_divider[mipmap]);
1166 				mipmap++;
1167 			}
1168 
1169 			invalidate_texture(page, header & 0x3f, (header >> 7) & 0x1f, (header >> 14) & 0x7, (header >> 17) & 0x7);
1170 			break;
1171 		}
1172 		case 0x01:      /* Texture without mipmaps */
1173 		{
1174 			if (bitdepth)
1175 			{
1176 				write_texture16(xpos, ypos, width, height, page, (uint16_t*)data);
1177 			}
1178 			else
1179 			{
1180 				//printf("write tex8: %08X, w %d, h %d, x %d, y %d, p %d, b %d\n", header, width, height, xpos, ypos, page, bitdepth);
1181 				write_texture8(xpos, ypos, width, height, page, upper_byte, lower_byte, (uint16_t*)data);
1182 			}
1183 
1184 			invalidate_texture(page, header & 0x3f, (header >> 7) & 0x1f, (header >> 14) & 0x7, (header >> 17) & 0x7);
1185 			break;
1186 		}
1187 		case 0x02:      /* Only mipmaps */
1188 		{
1189 			int x = mipmap_coords[0][0] + (xpos / mipmap_divider[0]);
1190 			int y = mipmap_coords[0][1] + (ypos / mipmap_divider[0]);
1191 			int w = width / 2;
1192 			int h = height / 2;
1193 
1194 			int mipmap = 1;
1195 
1196 			while (w >= 8 && h >= 8)
1197 			{
1198 				if (bitdepth)
1199 				{
1200 					write_texture16(x, y, w, h, page, (uint16_t*)data);
1201 				}
1202 				else
1203 				{
1204 					//printf("write tex8: %08X, w %d, h %d, x %d, y %d, p %d, b %d\n", header, width, height, xpos, ypos, page, bitdepth);
1205 					write_texture8(x, y, w, h, page, upper_byte, lower_byte, (uint16_t*)data);
1206 				}
1207 
1208 				data += (w * h * (bitdepth ? 2 : 1)) / 4;
1209 				w /= 2;
1210 				h /= 2;
1211 
1212 				x = mipmap_coords[mipmap][0] + (xpos / mipmap_divider[mipmap]);
1213 				y = mipmap_coords[mipmap][1] + (ypos / mipmap_divider[mipmap]);
1214 				mipmap++;
1215 			}
1216 
1217 			invalidate_texture(page, header & 0x3f, (header >> 7) & 0x1f, (header >> 14) & 0x7, (header >> 17) & 0x7);
1218 			break;
1219 		}
1220 		case 0x80:      /* Gamma-table ? */
1221 			break;
1222 		default:
1223 			fatalerror("Unknown texture type: %02X (%08X)\n", header >> 24, header);
1224 			break;
1225 	}
1226 }
1227 
real3d_display_list_end()1228 void model3_state::real3d_display_list_end()
1229 {
1230 	/* upload textures if there are any in the FIFO */
1231 	if (m_texture_fifo_pos > 0)
1232 	{
1233 		int i = 0;
1234 		while (i < m_texture_fifo_pos)
1235 		{
1236 			int length = (m_texture_fifo[i] / 2) + 2;
1237 			uint32_t header = m_texture_fifo[i+1];
1238 			real3d_upload_texture(header, &m_texture_fifo[i+2]);
1239 			i += length;
1240 		};
1241 	}
1242 	m_texture_fifo_pos = 0;
1243 
1244 	m_renderer->clear_fb();
1245 
1246 	reset_triangle_buffers();
1247 	real3d_traverse_display_list();
1248 
1249 	for (int i=0; i < 4; i++)
1250 	{
1251 		int ticount, tiacount;
1252 		int ti = m_viewport_tri_index[i];
1253 		int tia = m_viewport_tri_alpha_index[i];
1254 		if (i < 3)
1255 		{
1256 			ticount = m_viewport_tri_index[i+1] - ti;
1257 			tiacount = m_viewport_tri_alpha_index[i+1] - tia;
1258 		}
1259 		else
1260 		{
1261 			ticount = m_tri_buffer_ptr - ti;
1262 			tiacount = m_tri_alpha_buffer_ptr - tia;
1263 		}
1264 
1265 		if (ticount > 0 || tiacount > 0)
1266 		{
1267 			m_renderer->clear_zb();
1268 			m_renderer->draw_opaque_triangles(&m_tri_buffer[ti], ticount);
1269 			m_renderer->draw_alpha_triangles(&m_tri_alpha_buffer[tia], tiacount);
1270 			m_renderer->wait_for_polys();
1271 		}
1272 	}
1273 }
1274 
real3d_display_list1_dma(uint32_t src,uint32_t dst,int length,int byteswap)1275 void model3_state::real3d_display_list1_dma(uint32_t src, uint32_t dst, int length, int byteswap)
1276 {
1277 	address_space &space = m_maincpu->space(AS_PROGRAM);
1278 	int d = (dst & 0xffffff) / 4;
1279 	for (int i = 0; i < length; i += 4)
1280 	{
1281 		uint32_t w = space.read_dword(src);
1282 
1283 		if (byteswap)
1284 			w = BYTE_REVERSE32(w);
1285 
1286 		m_display_list_ram[d++] = w;
1287 		src += 4;
1288 	}
1289 }
1290 
real3d_display_list2_dma(uint32_t src,uint32_t dst,int length,int byteswap)1291 void model3_state::real3d_display_list2_dma(uint32_t src, uint32_t dst, int length, int byteswap)
1292 {
1293 	address_space &space = m_maincpu->space(AS_PROGRAM);
1294 	int d = (dst & 0xffffff) / 4;
1295 	for (int i = 0; i < length; i += 4)
1296 	{
1297 		uint32_t w = space.read_dword(src);
1298 
1299 		if (byteswap)
1300 			w = BYTE_REVERSE32(w);
1301 
1302 		m_culling_ram[d++] = w;
1303 		src += 4;
1304 	}
1305 }
1306 
real3d_vrom_texture_dma(uint32_t src,uint32_t dst,int length,int byteswap)1307 void model3_state::real3d_vrom_texture_dma(uint32_t src, uint32_t dst, int length, int byteswap)
1308 {
1309 	address_space &space = m_maincpu->space(AS_PROGRAM);
1310 	if ((dst & 0xff) == 0)
1311 	{
1312 		for (int i=0; i < length; i+=12)
1313 		{
1314 			uint32_t address = space.read_dword(src+i+0);
1315 			uint32_t header = space.read_dword(src+i+4);
1316 
1317 			if (byteswap)
1318 			{
1319 				address = BYTE_REVERSE32(address);
1320 				header = BYTE_REVERSE32(header);
1321 			}
1322 
1323 			real3d_upload_texture(header, (uint32_t*)&m_vrom[address]);
1324 		}
1325 	}
1326 }
1327 
real3d_texture_fifo_dma(uint32_t src,int length,int byteswap)1328 void model3_state::real3d_texture_fifo_dma(uint32_t src, int length, int byteswap)
1329 {
1330 	address_space &space = m_maincpu->space(AS_PROGRAM);
1331 	for (int i = 0; i < length; i += 4)
1332 	{
1333 		uint32_t w = space.read_dword(src);
1334 
1335 		if (byteswap)
1336 			w = BYTE_REVERSE32(w);
1337 
1338 		m_texture_fifo[m_texture_fifo_pos] = w;
1339 		m_texture_fifo_pos++;
1340 		src += 4;
1341 	}
1342 }
1343 
real3d_polygon_ram_dma(uint32_t src,uint32_t dst,int length,int byteswap)1344 void model3_state::real3d_polygon_ram_dma(uint32_t src, uint32_t dst, int length, int byteswap)
1345 {
1346 	address_space &space = m_maincpu->space(AS_PROGRAM);
1347 	int d = (dst & 0xffffff) / 4;
1348 	for (int i = 0; i < length; i += 4)
1349 	{
1350 		uint32_t w = space.read_dword(src);
1351 
1352 		if (byteswap)
1353 			w = BYTE_REVERSE32(w);
1354 
1355 		m_polygon_ram[d++] = w;
1356 		src += 4;
1357 	}
1358 }
1359 
real3d_cmd_w(uint64_t data)1360 void model3_state::real3d_cmd_w(uint64_t data)
1361 {
1362 	real3d_display_list_end();
1363 }
1364 
1365 
1366 /*****************************************************************************/
1367 /* matrix and vector operations */
1368 
dot_product3(VECTOR3 a,VECTOR3 b)1369 static inline float dot_product3(VECTOR3 a, VECTOR3 b)
1370 {
1371 	return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
1372 }
1373 
1374 /* multiplies a 4-element vector by a 4x4 matrix */
matrix_multiply_vector(MATRIX matrix,const VECTOR v,VECTOR * p)1375 static void matrix_multiply_vector(MATRIX matrix, const VECTOR v, VECTOR *p)
1376 {
1377 	(*p)[0] = (v[0] * matrix[0][0]) + (v[1] * matrix[1][0]) + (v[2] * matrix[2][0]) + (v[3] * matrix[3][0]);
1378 	(*p)[1] = (v[0] * matrix[0][1]) + (v[1] * matrix[1][1]) + (v[2] * matrix[2][1]) + (v[3] * matrix[3][1]);
1379 	(*p)[2] = (v[0] * matrix[0][2]) + (v[1] * matrix[1][2]) + (v[2] * matrix[2][2]) + (v[3] * matrix[3][2]);
1380 	(*p)[3] = (v[0] * matrix[0][3]) + (v[1] * matrix[1][3]) + (v[2] * matrix[2][3]) + (v[3] * matrix[3][3]);
1381 }
1382 
1383 /* multiplies a 4x4 matrix with another 4x4 matrix */
matrix_multiply(MATRIX a,MATRIX b,MATRIX * out)1384 static void matrix_multiply(MATRIX a, MATRIX b, MATRIX *out)
1385 {
1386 	int i,j;
1387 	MATRIX tmp;
1388 
1389 	for( i=0; i < 4; i++ ) {
1390 		for( j=0; j < 4; j++ ) {
1391 			tmp[i][j] = (a[i][0] * b[0][j]) + (a[i][1] * b[1][j]) + (a[i][2] * b[2][j]) + (a[i][3] * b[3][j]);
1392 		}
1393 	}
1394 	memcpy(out, &tmp, sizeof(MATRIX));
1395 }
1396 
init_matrix_stack()1397 void model3_state::init_matrix_stack()
1398 {
1399 	MATRIX *matrix_stack;
1400 	matrix_stack = m_matrix_stack = auto_alloc_array_clear(machine(), MATRIX, MATRIX_STACK_SIZE);
1401 
1402 	/* initialize the first matrix as identity */
1403 	matrix_stack[0][0][0] = 1.0f;
1404 	matrix_stack[0][0][1] = 0.0f;
1405 	matrix_stack[0][0][2] = 0.0f;
1406 	matrix_stack[0][0][3] = 0.0f;
1407 	matrix_stack[0][1][0] = 0.0f;
1408 	matrix_stack[0][1][1] = 1.0f;
1409 	matrix_stack[0][1][2] = 0.0f;
1410 	matrix_stack[0][1][3] = 0.0f;
1411 	matrix_stack[0][2][0] = 0.0f;
1412 	matrix_stack[0][2][1] = 0.0f;
1413 	matrix_stack[0][2][2] = 1.0f;
1414 	matrix_stack[0][2][3] = 0.0f;
1415 	matrix_stack[0][3][0] = 0.0f;
1416 	matrix_stack[0][3][1] = 0.0f;
1417 	matrix_stack[0][3][2] = 0.0f;
1418 	matrix_stack[0][3][3] = 1.0f;
1419 
1420 	m_matrix_stack_ptr = 0;
1421 }
1422 
get_top_matrix(MATRIX * out)1423 void model3_state::get_top_matrix(MATRIX *out)
1424 {
1425 	memcpy(out, &m_matrix_stack[m_matrix_stack_ptr], sizeof(MATRIX));
1426 }
1427 
push_matrix_stack()1428 void model3_state::push_matrix_stack()
1429 {
1430 	m_matrix_stack_ptr++;
1431 	if (m_matrix_stack_ptr >= MATRIX_STACK_SIZE)
1432 		fatalerror("push_matrix_stack: matrix stack overflow\n");
1433 
1434 	memcpy(&m_matrix_stack[m_matrix_stack_ptr], &m_matrix_stack[m_matrix_stack_ptr - 1], sizeof(MATRIX));
1435 }
1436 
pop_matrix_stack()1437 void model3_state::pop_matrix_stack()
1438 {
1439 	m_matrix_stack_ptr--;
1440 	if (m_matrix_stack_ptr < 0)
1441 		fatalerror("pop_matrix_stack: matrix stack underflow\n");
1442 }
1443 
multiply_matrix_stack(MATRIX matrix)1444 void model3_state::multiply_matrix_stack(MATRIX matrix)
1445 {
1446 	matrix_multiply(matrix, m_matrix_stack[m_matrix_stack_ptr], &m_matrix_stack[m_matrix_stack_ptr]);
1447 }
1448 
translate_matrix_stack(float x,float y,float z)1449 void model3_state::translate_matrix_stack(float x, float y, float z)
1450 {
1451 	MATRIX tm;
1452 
1453 	tm[0][0] = 1.0f;    tm[0][1] = 0.0f;    tm[0][2] = 0.0f;    tm[0][3] = 0.0f;
1454 	tm[1][0] = 0.0f;    tm[1][1] = 1.0f;    tm[1][2] = 0.0f;    tm[1][3] = 0.0f;
1455 	tm[2][0] = 0.0f;    tm[2][1] = 0.0f;    tm[2][2] = 1.0f;    tm[2][3] = 0.0f;
1456 	tm[3][0] = x;       tm[3][1] = y;       tm[3][2] = z;       tm[3][3] = 1.0f;
1457 
1458 	matrix_multiply(tm, m_matrix_stack[m_matrix_stack_ptr], &m_matrix_stack[m_matrix_stack_ptr]);
1459 }
1460 
set_projection(float left,float right,float top,float bottom,float near,float far)1461 void model3_state::set_projection(float left, float right, float top, float bottom, float near, float far)
1462 {
1463 	float l = near * tanf(left * 0.5f);
1464 	float r = near * tanf(right * 0.5f);
1465 	float t = near * tanf(top * 0.5f );
1466 	float b = near * tanf(bottom * 0.5f);
1467 
1468 	m_projection_matrix[0][0] = (2.0f * near) / (l - r);
1469 	m_projection_matrix[0][1] = 0.0f;
1470 	m_projection_matrix[0][2] = (r + l) / (r - l);
1471 	m_projection_matrix[0][3] = 0.0f;
1472 	m_projection_matrix[1][0] = 0.0f;
1473 	m_projection_matrix[1][1] = (2.0f * near) / (t - b);
1474 	m_projection_matrix[1][2] = (t + b) / (t - b);
1475 	m_projection_matrix[1][3] = 0.0f;
1476 	m_projection_matrix[2][0] = 0.0f;
1477 	m_projection_matrix[2][1] = 0.0f;
1478 	m_projection_matrix[2][2] = -(far + near) / (far - near);
1479 	m_projection_matrix[2][3] = -(2.0f * far * near) / (far - near);
1480 	m_projection_matrix[3][0] = 0.0f;
1481 	m_projection_matrix[3][1] = 0.0f;
1482 	m_projection_matrix[3][2] = -1.0f;
1483 	m_projection_matrix[3][3] = 0.0f;
1484 }
1485 
1486 /*****************************************************************************/
1487 /* transformation and rasterizing */
1488 
reset_triangle_buffers()1489 void model3_state::reset_triangle_buffers()
1490 {
1491 	m_tri_buffer_ptr = 0;
1492 	m_tri_alpha_buffer_ptr = 0;
1493 }
1494 
push_triangle(bool alpha)1495 m3_triangle *model3_state::push_triangle(bool alpha)
1496 {
1497 	if (!alpha)
1498 	{
1499 		int i = m_tri_buffer_ptr;
1500 
1501 		if (m_tri_buffer_ptr >= TRI_BUFFER_SIZE)
1502 		{
1503 			return nullptr;
1504 			//fatalerror("push_triangle: tri buffer max exceeded");
1505 		}
1506 
1507 		m_tri_buffer_ptr++;
1508 		return &m_tri_buffer[i];
1509 	}
1510 	else
1511 	{
1512 		int i = m_tri_alpha_buffer_ptr;
1513 
1514 		if (m_tri_alpha_buffer_ptr >= TRI_ALPHA_BUFFER_SIZE)
1515 		{
1516 			return nullptr;
1517 			//fatalerror("push_triangle: tri alpha buffer max exceeded");
1518 		}
1519 
1520 		m_tri_alpha_buffer_ptr++;
1521 		return &m_tri_alpha_buffer[i];
1522 	}
1523 }
1524 
draw_model(uint32_t addr)1525 void model3_state::draw_model(uint32_t addr)
1526 {
1527 	// Polygon RAM is mapped to the low 4MB of VROM
1528 	uint32_t *model = (addr >= 0x100000) ? &m_vrom[addr] :  &m_polygon_ram[addr];
1529 
1530 	uint32_t header[7];
1531 	int index = 0;
1532 	bool last_polygon = false, first_polygon = true, back_face = false;
1533 	int num_vertices;
1534 	int i, v, vi;
1535 	float fixed_point_fraction;
1536 	m3_vertex vertex[4];
1537 	m3_vertex prev_vertex[4];
1538 	m3_clip_vertex clip_vert[10];
1539 
1540 	MATRIX transform_matrix;
1541 	MATRIX vp_matrix;
1542 	MATRIX coord_matrix;
1543 
1544 	memset(&coord_matrix, 0, sizeof(coord_matrix));
1545 	coord_matrix[0][0] = m_coordinate_system[0][1];
1546 	coord_matrix[1][1] = m_coordinate_system[1][2];
1547 	coord_matrix[2][2] = -m_coordinate_system[2][0];
1548 	coord_matrix[3][3] = 1.0f;
1549 
1550 	if (m_step < 0x15)      // position coordinates are 17.7 fixed-point in Step 1.0
1551 		fixed_point_fraction = 1.0f / 128.0f;
1552 	else                    // 13.11 fixed-point in other Steps
1553 		fixed_point_fraction = 1.0f / 2048.0f;
1554 
1555 	get_top_matrix(&transform_matrix);
1556 
1557 	// make view-projection matrix
1558 	matrix_multiply(transform_matrix, coord_matrix, &transform_matrix);
1559 	matrix_multiply(transform_matrix, m_projection_matrix, &vp_matrix);
1560 
1561 	memset(prev_vertex, 0, sizeof(prev_vertex));
1562 
1563 	while (!last_polygon)
1564 	{
1565 		float texture_coord_scale;
1566 		uint32_t color;
1567 		VECTOR3 normal;
1568 		VECTOR3 sn;
1569 		VECTOR p[4];
1570 		int polygon_transparency;
1571 
1572 		for (i = 0; i < 7; i++)
1573 			header[i] = model[index++];
1574 
1575 		if (first_polygon && (header[0] & 0x0f) != 0)
1576 			return;
1577 		first_polygon = false;
1578 
1579 		if (header[6] == 0)
1580 			return;
1581 
1582 		if (header[1] & 0x4)
1583 			last_polygon = true;
1584 
1585 		if ((header[0] & 0x300) == 0x300)       // TODO: broken polygons in srally2 have these bits set
1586 			return;
1587 
1588 		num_vertices = (header[0] & 0x40) ? 4 : 3;
1589 
1590 		/* texture coordinates are 16.0 or 13.3 fixed-point */
1591 		texture_coord_scale = (header[1] & 0x40) ? 1.0f : (1.0f / 8.0f);
1592 
1593 		/* polygon normal (sign + 1.22 fixed-point) */
1594 		normal[0] = (float)((int32_t)header[1] >> 8) * (1.0f / 4194304.0f);
1595 		normal[1] = (float)((int32_t)header[2] >> 8) * (1.0f / 4194304.0f);
1596 		normal[2] = (float)((int32_t)header[3] >> 8) * (1.0f / 4194304.0f);
1597 
1598 		/* load reused vertices */
1599 		vi = 0;
1600 		for (v = 0; v < 4; v++)
1601 			if (header[0] & (1 << v))
1602 				vertex[vi++] = prev_vertex[v];
1603 
1604 		/* load new vertices */
1605 		for ( ; vi < num_vertices; vi++)
1606 		{
1607 			uint32_t xw = model[index++];
1608 			uint32_t yw = model[index++];
1609 			uint32_t zw = model[index++];
1610 
1611 			vertex[vi].x = (float)((int32_t)(xw) >> 8) * fixed_point_fraction;
1612 			vertex[vi].y = (float)((int32_t)(yw) >> 8) * fixed_point_fraction;
1613 			vertex[vi].z = (float)((int32_t)(zw) >> 8) * fixed_point_fraction;
1614 			vertex[vi].u = (uint16_t)(model[index] >> 16);
1615 			vertex[vi].v = (uint16_t)(model[index++]);
1616 //          vertex[vi].nx = normal[0] + ((float)((int8_t)(xw)) / 127.0f);
1617 //          vertex[vi].ny = normal[1] + ((float)((int8_t)(yw)) / 127.0f);
1618 //          vertex[vi].nz = normal[2] + ((float)((int8_t)(zw)) / 127.0f);
1619 
1620 			vertex[vi].nx = ((float)((int8_t)(xw)) / 127.0f);
1621 			vertex[vi].ny = ((float)((int8_t)(yw)) / 127.0f);
1622 			vertex[vi].nz = ((float)((int8_t)(zw)) / 127.0f);
1623 		}
1624 
1625 		/* Copy current vertices as previous vertices */
1626 		memcpy(prev_vertex, vertex, sizeof(m3_vertex) * 4);
1627 
1628 		if (header[1] & 0x2)
1629 		{
1630 			color = (header[4] >> 8) & 0xffffff;
1631 		}
1632 		else
1633 		{
1634 			int ci = (header[4] >> 8) & 0x7ff;
1635 			color = m_polygon_ram[0x400 + ci];
1636 		}
1637 
1638 		polygon_transparency =  (header[6] & 0x800000) ? 32 : ((header[6] >> 18) & 0x1f);
1639 
1640 		/* transform polygon normal to view-space */
1641 		sn[0] = (normal[0] * transform_matrix[0][0]) +
1642 				(normal[1] * transform_matrix[0][1]) +
1643 				(normal[2] * transform_matrix[0][2]);
1644 		sn[1] = (normal[0] * transform_matrix[1][0]) +
1645 				(normal[1] * transform_matrix[1][1]) +
1646 				(normal[2] * transform_matrix[1][2]);
1647 		sn[2] = (normal[0] * transform_matrix[2][0]) +
1648 				(normal[1] * transform_matrix[2][1]) +
1649 				(normal[2] * transform_matrix[2][2]);
1650 
1651 		// TODO: depth bias
1652 		// transform and light vertices
1653 		for (i = 0; i < num_vertices; i++)
1654 		{
1655 			VECTOR vect;
1656 
1657 			vect[0] = vertex[i].x;
1658 			vect[1] = vertex[i].y;
1659 			vect[2] = vertex[i].z;
1660 			vect[3] = 1.0f;
1661 
1662 			// transform to projection space
1663 			matrix_multiply_vector(vp_matrix, vect, &p[i]);
1664 
1665 			clip_vert[i].x = p[i][0];
1666 			clip_vert[i].y = p[i][1];
1667 			clip_vert[i].z = p[i][2];
1668 			clip_vert[i].w = p[i][3];
1669 
1670 			clip_vert[i].p[0] = vertex[i].u * texture_coord_scale * 256.0f;        // 8 bits of subtexel accuracy for bilinear filtering
1671 			clip_vert[i].p[1] = vertex[i].v * texture_coord_scale * 256.0f;
1672 
1673 			// transform vertex normal
1674 			VECTOR3 n;
1675 			n[0] = (vertex[i].nx * transform_matrix[0][0]) +
1676 					(vertex[i].ny * transform_matrix[0][1]) +
1677 					(vertex[i].nz * transform_matrix[0][2]);
1678 			n[1] = (vertex[i].nx * transform_matrix[1][0]) +
1679 					(vertex[i].ny * transform_matrix[1][1]) +
1680 					(vertex[i].nz * transform_matrix[1][2]);
1681 			n[2] = (vertex[i].nx * transform_matrix[2][0]) +
1682 					(vertex[i].ny * transform_matrix[2][1]) +
1683 					(vertex[i].nz * transform_matrix[2][2]);
1684 
1685 			// lighting
1686 			float intensity;
1687 			if ((header[6] & 0x10000) == 0)
1688 			{
1689 				float dot = dot_product3(n, m_parallel_light);
1690 
1691 				if (header[1] & 0x10)
1692 					dot = fabs(dot);
1693 
1694 				intensity = ((dot * m_parallel_light_intensity) + m_ambient_light_intensity) * 255.0f;
1695 				if (intensity > 255.0f)
1696 				{
1697 					intensity = 255.0f;
1698 				}
1699 				if (intensity < 0.0f)
1700 				{
1701 					intensity = 0.0f;
1702 				}
1703 			}
1704 			else
1705 			{
1706 				intensity = 255.0f;
1707 			}
1708 
1709 			clip_vert[i].p[2] = intensity;
1710 		}
1711 
1712 		/* clip against all edges of the view frustum */
1713 		num_vertices = frustum_clip_all<float, 4>(clip_vert, num_vertices, clip_vert);
1714 
1715 		/* divide by W, transform to screen coords */
1716 		for(i=0; i < num_vertices; i++)
1717 		{
1718 			float oow = 1.0f / clip_vert[i].w;
1719 
1720 			clip_vert[i].x *= oow;
1721 			clip_vert[i].y *= oow;
1722 			clip_vert[i].z *= oow;
1723 			clip_vert[i].p[0] *= oow;
1724 			clip_vert[i].p[1] *= oow;
1725 
1726 			clip_vert[i].x = (((clip_vert[i].x * 0.5f) + 0.5f) * m_viewport_width) + m_viewport_x;
1727 			clip_vert[i].y = (((clip_vert[i].y * 0.5f) + 0.5f) * m_viewport_height) + m_viewport_y;
1728 			clip_vert[i].z = (((clip_vert[i].z * 0.5f) + 0.5f) * (m_viewport_far - m_viewport_near)) + m_viewport_near;
1729 		}
1730 
1731 		/* backface culling */
1732 		if( (header[6] & 0x800000) && (!(header[1] & 0x0010)) )
1733 		{
1734 			if (sn[0]*clip_vert[0].x + sn[1]*clip_vert[0].y + sn[2]*clip_vert[0].z > 0)
1735 				back_face = 1;
1736 			else
1737 				back_face = 0;
1738 		}
1739 		else
1740 		{
1741 			back_face = 0;  //no culling for transparent or two-sided polygons
1742 		}
1743 
1744 		back_face = 0;
1745 
1746 		if (!back_face)
1747 		{
1748 			bool colormod = false;
1749 			cached_texture* texture;
1750 
1751 			if (header[6] & 0x0000400)
1752 			{
1753 				int tex_x = ((header[4] & 0x1f) << 1) | ((header[5] >> 7) & 0x1);
1754 				int tex_y = (header[5] & 0x1f);
1755 				int tex_width = ((header[3] >> 3) & 0x7);
1756 				int tex_height = (header[3] & 0x7);
1757 				int tex_format = (header[6] >> 7) & 0x7;
1758 
1759 				if (tex_format != 0 && tex_format != 7)     // enable color modulation if this is not a color texture
1760 					colormod = true;
1761 
1762 				if (tex_width >= 6 || tex_height >= 6)      // srally2 poly ram has degenerate polys with 2k tex size (cpu bug or intended?)
1763 					return;
1764 
1765 				texture = get_texture((header[4] & 0x40) ? 1 : 0, tex_x, tex_y, tex_width, tex_height, tex_format);
1766 			}
1767 			else
1768 			{
1769 				texture = nullptr;
1770 			}
1771 
1772 			for (i=2; i < num_vertices; i++)
1773 			{
1774 				bool alpha = (header[6] & 0x1) || ((header[6] & 0x800000) == 0);        // put to alpha buffer if there's any transparency involved
1775 				m3_triangle* tri = push_triangle(alpha);
1776 
1777 				// bail out if tri buffer is maxed out (happens during harley boot)
1778 				if (!tri)
1779 					return;
1780 
1781 				memcpy(&tri->v[0], &clip_vert[0], sizeof(m3_clip_vertex));
1782 				memcpy(&tri->v[1], &clip_vert[i-1], sizeof(m3_clip_vertex));
1783 				memcpy(&tri->v[2], &clip_vert[i], sizeof(m3_clip_vertex));
1784 
1785 				tri->texture = texture;
1786 				tri->transparency = polygon_transparency;
1787 				tri->color = color;
1788 
1789 				tri->param = 0;
1790 				tri->param |= (header[4] & 0x40) ? TRI_PARAM_TEXTURE_PAGE : 0;
1791 				tri->param |= (header[6] & 0x00000400) ? TRI_PARAM_TEXTURE_ENABLE : 0;
1792 				tri->param |= (header[2] & 0x2) ? TRI_PARAM_TEXTURE_MIRROR_U : 0;
1793 				tri->param |= (header[2] & 0x1) ? TRI_PARAM_TEXTURE_MIRROR_V : 0;
1794 				tri->param |= (header[6] & 0x80000000) ? TRI_PARAM_ALPHA_TEST : 0;
1795 				tri->param |= (colormod) ? TRI_PARAM_COLOR_MOD : 0;
1796 			}
1797 		}
1798 	}
1799 }
1800 
1801 
1802 /*****************************************************************************/
1803 /* display list parser */
1804 
get_memory_pointer(uint32_t address)1805 uint32_t *model3_state::get_memory_pointer(uint32_t address)
1806 {
1807 	if (address & 0x800000)
1808 	{
1809 		if (address >= 0x840000) {
1810 			fatalerror("get_memory_pointer: invalid display list memory address %08X\n", address);
1811 		}
1812 		return &m_display_list_ram[address & 0x7fffff];
1813 	}
1814 	else
1815 	{
1816 		if (address >= 0x100000) {
1817 			fatalerror("get_memory_pointer: invalid node ram address %08X\n", address);
1818 		}
1819 		return &m_culling_ram[address];
1820 	}
1821 }
1822 
load_matrix(int matrix_num,MATRIX * out)1823 void model3_state::load_matrix(int matrix_num, MATRIX *out)
1824 {
1825 	float *matrix = (float *)get_memory_pointer(m_matrix_base_address + matrix_num * 12);
1826 
1827 	(*out)[0][0] = matrix[3];   (*out)[0][1] = matrix[6];   (*out)[0][2] = matrix[9];   (*out)[0][3] = 0.0f;
1828 	(*out)[1][0] = matrix[4];   (*out)[1][1] = matrix[7];   (*out)[1][2] = matrix[10];  (*out)[1][3] = 0.0f;
1829 	(*out)[2][0] = matrix[5];   (*out)[2][1] = matrix[8];   (*out)[2][2] = matrix[11];  (*out)[2][3] = 0.0f;
1830 	(*out)[3][0] = matrix[0];   (*out)[3][1] = matrix[1];   (*out)[3][2] = matrix[2];   (*out)[3][3] = 1.0f;
1831 }
1832 
traverse_list4(int lod_num,uint32_t address)1833 void model3_state::traverse_list4(int lod_num, uint32_t address)
1834 {
1835 	/* does something with the LOD selection */
1836 	uint32_t *list = get_memory_pointer(address);
1837 	uint32_t link = list[0];
1838 
1839 	draw_model(link & 0xffffff);
1840 }
1841 
traverse_list(uint32_t address)1842 void model3_state::traverse_list(uint32_t address)
1843 {
1844 	uint32_t *list = get_memory_pointer(address);
1845 	int list_ptr = 0;
1846 
1847 	if (m_list_depth > 2)
1848 		return;
1849 
1850 	m_list_depth++;
1851 
1852 	/* find the end of the list */
1853 	while (1)
1854 	{
1855 		address = list[list_ptr++];
1856 		if (address & 0x02000000)
1857 			break;
1858 		if (address == 0 || (address >> 24) != 0)
1859 		{
1860 			list_ptr--;
1861 			break;
1862 		}
1863 	}
1864 
1865 	/* walk it backwards */
1866 	while (list_ptr > 0)
1867 	{
1868 		address = list[--list_ptr] & 0xffffff;
1869 		if (address != 0 && address != 0x800800)
1870 		//if (address != 0)
1871 			draw_block(address);
1872 	}
1873 
1874 	m_list_depth--;
1875 }
1876 
process_link(uint32_t address,uint32_t link)1877 inline void model3_state::process_link(uint32_t address, uint32_t link)
1878 {
1879 	if (link != 0 && link != 0x0fffffff && link != 0x00800800 && link != 0x01000000)
1880 	{
1881 		switch (link >> 24)
1882 		{
1883 			case 0x00:      /* link to another node */
1884 				draw_block(link & 0xffffff);
1885 				break;
1886 
1887 			case 0x01:
1888 			case 0x03:      /* both of these link to models, is there any difference ? */
1889 				draw_model(link & 0xffffff);
1890 				break;
1891 
1892 			case 0x04:      /* list of links */
1893 				traverse_list(link & 0xffffff);
1894 				break;
1895 
1896 			default:
1897 				logerror("process_link %08X: link = %08X\n", address, link);
1898 				break;
1899 		}
1900 	}
1901 }
1902 
draw_block(uint32_t address)1903 void model3_state::draw_block(uint32_t address)
1904 {
1905 	const uint32_t *node = get_memory_pointer(address);
1906 	uint32_t link;
1907 	int node_matrix;
1908 	float x, y, z;
1909 	MATRIX matrix;
1910 	int offset;
1911 
1912 	offset = (m_step < 0x15) ? 2 : 0;
1913 	link = node[7 - offset];
1914 
1915 	/* apply matrix and translation */
1916 	node_matrix = node[3 - offset] & 0xfff;
1917 	load_matrix(node_matrix, &matrix);
1918 
1919 	push_matrix_stack();
1920 
1921 	if (node[0] & 0x10)
1922 	{
1923 		x = *(float *)&node[4 - offset];
1924 		y = *(float *)&node[5 - offset];
1925 		z = *(float *)&node[6 - offset];
1926 		translate_matrix_stack(x, y, z);
1927 	}
1928 	else if (node_matrix != 0)
1929 		multiply_matrix_stack(matrix);
1930 
1931 	/* bit 0x08 of word 0 indicates a pointer list */
1932 	if (node[0] & 0x08)
1933 		traverse_list4((node[3 - offset] >> 12) & 0x7f, link & 0xffffff);
1934 	else
1935 		process_link(address, link);
1936 
1937 	pop_matrix_stack();
1938 
1939 	/* handle the second link */
1940 	if ((node[0] & 0x7) != 0x6)
1941 	{
1942 		link = node[8 - offset];
1943 		process_link(address, link);
1944 	}
1945 }
1946 
draw_viewport(int pri,uint32_t address)1947 void model3_state::draw_viewport(int pri, uint32_t address)
1948 {
1949 	const uint32_t *node = get_memory_pointer(address);
1950 	uint32_t link_address;
1951 
1952 	link_address = node[1];
1953 
1954 	/* traverse to the link node before drawing this viewport */
1955 	/* check this is correct as this affects the rendering order */
1956 	if (link_address != 0x01000000 && link_address != 0)
1957 		draw_viewport(pri, link_address);
1958 
1959 	/* skip if this isn't the right priority */
1960 	if (pri != ((node[0] >> 3) & 3))
1961 		return;
1962 
1963 	/* set viewport parameters */
1964 	m_viewport_x      = (float)(node[26] & 0xffff) / 16.0f;         /* 12.4 fixed point */
1965 	m_viewport_y      = (float)((node[26] >> 16) & 0xffff) / 16.0f;
1966 	m_viewport_width  = (float)(node[20] & 0xffff) / 4.0f;          /* 14.2 fixed point */
1967 	m_viewport_height = (float)((node[20] >> 16) & 0xffff) / 4.0f;
1968 
1969 	m_viewport_near = 1.0f;
1970 	m_viewport_far = 100000.0f;
1971 
1972 	/* set up frustum */
1973 	float frustum_left      = atan2(*(float *)&node[12], *(float *)&node[13]);
1974 	float frustum_right     = -atan2(*(float *)&node[16], -*(float *)&node[17]);
1975 	float frustum_top       = atan2(*(float *)&node[14], *(float *)&node[15]);
1976 	float frustum_bottom    = -atan2(*(float *)&node[18], -*(float *)&node[19]);
1977 //  float frustum_1         = atan2(*(float *)&node[9], *(float *)&node[8]);
1978 //  float frustum_2         = atan2(*(float *)&node[11], *(float *)&node[10]);
1979 
1980 	/*
1981 	printf("%f\n", *(float *)&node[3]);
1982 	printf("0: %f, 1: %f, 2: %f, 3: %f\n", *(float *)&node[8], *(float *)&node[9], *(float *)&node[10], *(float *)&node[11]);
1983 	printf("4: %f, 5: %f, 6: %f, 7: %f\n", *(float *)&node[12], *(float *)&node[13], *(float *)&node[14], *(float *)&node[15]);
1984 	printf("8: %f, 9: %f, A: %f, B: %f\n", *(float *)&node[16], *(float *)&node[17], *(float *)&node[18], *(float *)&node[19]);
1985 	printf("fl = %f, fr = %f, ft = %f, fb = %f\n", RADIAN_TO_DEGREE(frustum_left), RADIAN_TO_DEGREE(frustum_right), RADIAN_TO_DEGREE(frustum_top), RADIAN_TO_DEGREE(frustum_bottom));
1986 	printf("f1 = %f, f2 = %f\n", RADIAN_TO_DEGREE(frustum_1), RADIAN_TO_DEGREE(frustum_2));
1987 	*/
1988 
1989 	set_projection(frustum_left, frustum_right, frustum_top, frustum_bottom, m_viewport_near, m_viewport_far);
1990 
1991 
1992 	m_matrix_base_address = node[22];
1993 	/* TODO: where does node[23] point to ? LOD table ? */
1994 
1995 	/* set lighting parameters */
1996 	m_parallel_light[0] = *(float *)&node[5];
1997 	m_parallel_light[1] = *(float *)&node[6];
1998 	m_parallel_light[2] = *(float *)&node[4];
1999 	m_parallel_light_intensity = *(float *)&node[7];
2000 	m_ambient_light_intensity = (uint8_t)(node[36] >> 8) / 256.0f;
2001 
2002 	/* set coordinate system matrix */
2003 	load_matrix(0, &m_coordinate_system);
2004 
2005 	/* process a link */
2006 	process_link(link_address, node[2]);
2007 }
2008 
2009 
real3d_traverse_display_list()2010 void model3_state::real3d_traverse_display_list()
2011 {
2012 	init_matrix_stack();
2013 
2014 	m_list_depth = 0;
2015 
2016 	for (int pri = 0; pri < 4; pri++)
2017 	{
2018 		m_viewport_tri_index[pri] = m_tri_buffer_ptr;
2019 		m_viewport_tri_alpha_index[pri] = m_tri_alpha_buffer_ptr;
2020 		draw_viewport(pri, 0x800000);
2021 	}
2022 }
2023 
draw(bitmap_rgb32 & bitmap,const rectangle & cliprect)2024 void model3_renderer::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect)
2025 {
2026 	for (int j = cliprect.min_y; j <= cliprect.max_y; ++j)
2027 	{
2028 		uint32_t *const dst = &bitmap.pix(j);
2029 		uint32_t const *const src = &m_fb->pix(j);
2030 
2031 		for (int i = cliprect.min_x; i <= cliprect.max_x; ++i)
2032 		{
2033 			if (src[i] & 0xff000000)
2034 			{
2035 				dst[i] = src[i];
2036 			}
2037 		}
2038 	}
2039 }
2040 
clear_fb()2041 void model3_renderer::clear_fb()
2042 {
2043 	rectangle cliprect;
2044 	cliprect.min_x = 0;
2045 	cliprect.min_y = 0;
2046 	cliprect.max_x = 495;
2047 	cliprect.max_y = 383;
2048 
2049 	m_fb->fill(0x00000000, cliprect);
2050 }
2051 
clear_zb()2052 void model3_renderer::clear_zb()
2053 {
2054 	rectangle cliprect;
2055 	cliprect.min_x = 0;
2056 	cliprect.min_y = 0;
2057 	cliprect.max_x = 495;
2058 	cliprect.max_y = 383;
2059 
2060 	float zvalue = 10000000000.0f;
2061 	m_zb->fill(*(int*)&zvalue, cliprect);
2062 }
2063 
wait_for_polys()2064 void model3_renderer::wait_for_polys()
2065 {
2066 	wait();
2067 }
2068 
draw_opaque_triangles(const m3_triangle * tris,int num_tris)2069 void model3_renderer::draw_opaque_triangles(const m3_triangle* tris, int num_tris)
2070 {
2071 	rectangle cliprect;
2072 	cliprect.min_x = 0;
2073 	cliprect.min_y = 0;
2074 	cliprect.max_x = 495;
2075 	cliprect.max_y = 383;
2076 
2077 //  printf("draw opaque: %d\n", num_tris);
2078 
2079 	vertex_t v[3];
2080 
2081 	for (int t=0; t < num_tris; t++)
2082 	{
2083 		const m3_triangle* tri = &tris[t];
2084 
2085 		if (tri->param & TRI_PARAM_TEXTURE_ENABLE)
2086 		{
2087 			for (int i=0; i < 3; i++)
2088 			{
2089 				v[i].x = tri->v[i].x;
2090 				v[i].y = tri->v[i].y;
2091 				v[i].p[0] = tri->v[i].w;
2092 				v[i].p[1] = 1.0f / tri->v[i].w;
2093 				v[i].p[2] = tri->v[i].p[0];
2094 				v[i].p[3] = tri->v[i].p[1];
2095 				v[i].p[4] = tri->v[i].p[2];
2096 			}
2097 
2098 			model3_polydata &extra = object_data_alloc();
2099 			extra.texture = tri->texture;
2100 			extra.transparency = tri->transparency;
2101 			extra.texture_param = tri->param;
2102 			extra.color = tri->color;
2103 
2104 			if (tri->param & TRI_PARAM_ALPHA_TEST)
2105 			{
2106 				render_triangle(cliprect, render_delegate(&model3_renderer::draw_scanline_tex_contour, this), 5, v[0], v[1], v[2]);
2107 			}
2108 			else
2109 			{
2110 				if (tri->param & TRI_PARAM_COLOR_MOD)
2111 					render_triangle(cliprect, render_delegate(&model3_renderer::draw_scanline_tex_colormod, this), 5, v[0], v[1], v[2]);
2112 				else
2113 					render_triangle(cliprect, render_delegate(&model3_renderer::draw_scanline_tex, this), 5, v[0], v[1], v[2]);
2114 			}
2115 		}
2116 		else
2117 		{
2118 			for (int i=0; i < 3; i++)
2119 			{
2120 				v[i].x = tri->v[i].x;
2121 				v[i].y = tri->v[i].y;
2122 				v[i].p[0] = tri->v[i].w;
2123 				v[i].p[1] = tri->v[i].p[2];
2124 			}
2125 
2126 			model3_polydata &extra = object_data_alloc();
2127 			extra.color = tri->color;
2128 
2129 			render_triangle(cliprect, render_delegate(&model3_renderer::draw_scanline_solid, this), 2, v[0], v[1], v[2]);
2130 		}
2131 	}
2132 }
2133 
draw_alpha_triangles(const m3_triangle * tris,int num_tris)2134 void model3_renderer::draw_alpha_triangles(const m3_triangle* tris, int num_tris)
2135 {
2136 	rectangle cliprect;
2137 	cliprect.min_x = 0;
2138 	cliprect.min_y = 0;
2139 	cliprect.max_x = 495;
2140 	cliprect.max_y = 383;
2141 
2142 //  printf("draw alpha: %d\n", num_tris);
2143 
2144 	vertex_t v[3];
2145 
2146 	for (int t=num_tris-1; t >= 0; t--)
2147 	{
2148 		const m3_triangle* tri = &tris[t];
2149 
2150 		if (tri->param & TRI_PARAM_TEXTURE_ENABLE)
2151 		{
2152 			for (int i=0; i < 3; i++)
2153 			{
2154 				v[i].x = tri->v[i].x;
2155 				v[i].y = tri->v[i].y;
2156 				v[i].p[0] = tri->v[i].w;
2157 				v[i].p[1] = 1.0f / tri->v[i].w;
2158 				v[i].p[2] = tri->v[i].p[0];
2159 				v[i].p[3] = tri->v[i].p[1];
2160 				v[i].p[4] = tri->v[i].p[2];
2161 			}
2162 
2163 			model3_polydata &extra = object_data_alloc();
2164 			extra.texture = tri->texture;
2165 			extra.transparency = tri->transparency;
2166 			extra.texture_param = tri->param;
2167 
2168 			render_triangle(cliprect, render_delegate(&model3_renderer::draw_scanline_tex_alpha, this), 5, v[0], v[1], v[2]);
2169 		}
2170 		else
2171 		{
2172 			for (int i=0; i < 3; i++)
2173 			{
2174 				v[i].x = tri->v[i].x;
2175 				v[i].y = tri->v[i].y;
2176 				v[i].p[0] = tri->v[i].w;
2177 				v[i].p[1] = tri->v[i].p[2];
2178 			}
2179 
2180 			model3_polydata &extra = object_data_alloc();
2181 			extra.color = tri->color;
2182 			extra.transparency = tri->transparency;
2183 
2184 			render_triangle(cliprect, render_delegate(&model3_renderer::draw_scanline_solid_trans, this), 2, v[0], v[1], v[2]);
2185 		}
2186 	}
2187 }
2188 
draw_scanline_solid(int32_t scanline,const extent_t & extent,const model3_polydata & polydata,int threadid)2189 void model3_renderer::draw_scanline_solid(int32_t scanline, const extent_t &extent, const model3_polydata &polydata, int threadid)
2190 {
2191 	uint32_t *const fb = &m_fb->pix(scanline);
2192 	float *const zb = (float*)&m_zb->pix(scanline);
2193 
2194 	float z = extent.param[0].start;
2195 	float dz = extent.param[0].dpdx;
2196 
2197 	float in = extent.param[1].start;
2198 	float inz = extent.param[1].dpdx;
2199 
2200 	rgbaint_t color(polydata.color);
2201 
2202 	for (int x = extent.startx; x < extent.stopx; x++)
2203 	{
2204 		if (z <= zb[x])
2205 		{
2206 			rgbaint_t c(color);
2207 
2208 			c.scale_imm_and_clamp((int)in);
2209 
2210 			fb[x] = 0xff000000 | c.to_rgba_clamp();
2211 			zb[x] = z;
2212 		}
2213 
2214 		in += inz;
2215 		z += dz;
2216 	}
2217 }
2218 
draw_scanline_solid_trans(int32_t scanline,const extent_t & extent,const model3_polydata & polydata,int threadid)2219 void model3_renderer::draw_scanline_solid_trans(int32_t scanline, const extent_t &extent, const model3_polydata &polydata, int threadid)
2220 {
2221 	uint32_t *const fb = &m_fb->pix(scanline);
2222 	float *const zb = (float*)&m_zb->pix(scanline);
2223 
2224 	float z = extent.param[0].start;
2225 	float dz = extent.param[0].dpdx;
2226 
2227 	float in = extent.param[1].start;
2228 	float inz = extent.param[1].dpdx;
2229 
2230 	rgbaint_t color(polydata.color);
2231 
2232 	int trans = (polydata.transparency << 3) | (polydata.transparency >> 2);
2233 
2234 	for (int x = extent.startx; x < extent.stopx; x++)
2235 	{
2236 		if (z <= zb[x])
2237 		{
2238 			rgbaint_t c(color);
2239 
2240 			c.scale_imm_and_clamp((int)in);
2241 
2242 			if (trans != 0xff)
2243 			{
2244 				c.blend(rgbaint_t(fb[x]), trans);
2245 			}
2246 
2247 			fb[x] = 0xff000000 | c.to_rgba_clamp();
2248 		}
2249 
2250 		in += inz;
2251 		z += dz;
2252 	}
2253 }
2254 
2255 #define TEX_FETCH_NOFILTER()                                \
2256 do {                                                        \
2257 	float intz = 1.0f / ooz;                                \
2258 	uint32_t u = uoz * intz;                                  \
2259 	uint32_t v = voz * intz;                                  \
2260 	uint32_t u1 = (u >> 8) & umask;                           \
2261 	uint32_t v1 = (v >> 8) & vmask;                           \
2262 	texel = texture->data[(v1 << width) + u1];              \
2263 } while(0);
2264 
2265 #define TEX_FETCH_BILINEAR()                                                    \
2266 do {                                                                            \
2267 	float intz = 1.0f / ooz;                                                    \
2268 	uint32_t u = uoz * intz;                                                      \
2269 	uint32_t v = voz * intz;                                                      \
2270 	uint32_t u1 = (u >> 8) & umask;                                               \
2271 	uint32_t v1 = (v >> 8) & vmask;                                               \
2272 	uint32_t u2 = (u1 + 1) & umask;                                               \
2273 	uint32_t v2 = (v1 + 1) & vmask;                                               \
2274 	uint32_t pix00 = texture->data[(v1 << width) + u1];                           \
2275 	uint32_t pix01 = texture->data[(v1 << width) + u2];                           \
2276 	uint32_t pix10 = texture->data[(v2 << width) + u1];                           \
2277 	uint32_t pix11 = texture->data[(v2 << width) + u2];                           \
2278 	texel = rgbaint_t::bilinear_filter(pix00, pix01, pix10, pix11, u, v);       \
2279 } while(0);
2280 
2281 #if ENABLE_BILINEAR
2282 #define TEX_FETCH() TEX_FETCH_BILINEAR()
2283 #else
2284 #define TEX_FETCH() TEX_FETCH_NOFILTER()
2285 #endif
2286 
draw_scanline_tex(int32_t scanline,const extent_t & extent,const model3_polydata & polydata,int threadid)2287 void model3_renderer::draw_scanline_tex(int32_t scanline, const extent_t &extent, const model3_polydata &polydata, int threadid)
2288 {
2289 	uint32_t *const fb = &m_fb->pix(scanline);
2290 	float *const zb = (float*)&m_zb->pix(scanline);
2291 	const cached_texture *texture = polydata.texture;
2292 
2293 	float z = extent.param[0].start;
2294 	float dz = extent.param[0].dpdx;
2295 	float ooz = extent.param[1].start;
2296 	float dooz = extent.param[1].dpdx;
2297 	float uoz = extent.param[2].start;
2298 	float duoz = extent.param[2].dpdx;
2299 	float voz = extent.param[3].start;
2300 	float dvoz = extent.param[3].dpdx;
2301 	float in = extent.param[4].start;
2302 	float inz = extent.param[4].dpdx;
2303 
2304 	uint32_t umask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1;
2305 	uint32_t vmask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1;
2306 	uint32_t width = 6 + texture->width;
2307 
2308 	for (int x = extent.startx; x < extent.stopx; x++)
2309 	{
2310 		if (z <= zb[x])
2311 		{
2312 			uint32_t texel;
2313 			TEX_FETCH();        // TODO fetch rgbaint_t instead
2314 
2315 			rgbaint_t color(texel);
2316 
2317 			color.scale_imm_and_clamp((int)in);
2318 
2319 			fb[x] = 0xff000000 | color.to_rgba_clamp();
2320 			zb[x] = z;
2321 		}
2322 
2323 		ooz += dooz;
2324 		uoz += duoz;
2325 		voz += dvoz;
2326 		in += inz;
2327 		z += dz;
2328 	}
2329 }
2330 
draw_scanline_tex_colormod(int32_t scanline,const extent_t & extent,const model3_polydata & polydata,int threadid)2331 void model3_renderer::draw_scanline_tex_colormod(int32_t scanline, const extent_t &extent, const model3_polydata &polydata, int threadid)
2332 {
2333 	uint32_t *const fb = &m_fb->pix(scanline);
2334 	float *const zb = (float*)&m_zb->pix(scanline);
2335 	const cached_texture *texture = polydata.texture;
2336 
2337 	float z = extent.param[0].start;
2338 	float dz = extent.param[0].dpdx;
2339 	float ooz = extent.param[1].start;
2340 	float dooz = extent.param[1].dpdx;
2341 	float uoz = extent.param[2].start;
2342 	float duoz = extent.param[2].dpdx;
2343 	float voz = extent.param[3].start;
2344 	float dvoz = extent.param[3].dpdx;
2345 	float in = extent.param[4].start;
2346 	float inz = extent.param[4].dpdx;
2347 
2348 	uint32_t umask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1;
2349 	uint32_t vmask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1;
2350 	uint32_t width = 6 + texture->width;
2351 
2352 	rgbaint_t polycolor(polydata.color);
2353 
2354 	for (int x = extent.startx; x < extent.stopx; x++)
2355 	{
2356 		if (z <= zb[x])
2357 		{
2358 			uint32_t texel;
2359 			TEX_FETCH();        // TODO fetch rgbaint_t instead
2360 
2361 			rgbaint_t color(texel);
2362 
2363 			color.scale_and_clamp(polycolor);
2364 			color.scale_imm_and_clamp((int)in);
2365 
2366 			fb[x] = 0xff000000 | color.to_rgba_clamp();
2367 			zb[x] = z;
2368 		}
2369 
2370 		ooz += dooz;
2371 		uoz += duoz;
2372 		voz += dvoz;
2373 		in += inz;
2374 		z += dz;
2375 	}
2376 }
2377 
draw_scanline_tex_contour(int32_t scanline,const extent_t & extent,const model3_polydata & polydata,int threadid)2378 void model3_renderer::draw_scanline_tex_contour(int32_t scanline, const extent_t &extent, const model3_polydata &polydata, int threadid)
2379 {
2380 	uint32_t *const fb = &m_fb->pix(scanline);
2381 	float *const zb = (float*)&m_zb->pix(scanline);
2382 	const cached_texture *texture = polydata.texture;
2383 
2384 	float z = extent.param[0].start;
2385 	float dz = extent.param[0].dpdx;
2386 	float ooz = extent.param[1].start;
2387 	float dooz = extent.param[1].dpdx;
2388 	float uoz = extent.param[2].start;
2389 	float duoz = extent.param[2].dpdx;
2390 	float voz = extent.param[3].start;
2391 	float dvoz = extent.param[3].dpdx;
2392 	float in = extent.param[4].start;
2393 	float inz = extent.param[4].dpdx;
2394 
2395 	uint32_t umask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1;
2396 	uint32_t vmask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1;
2397 	uint32_t width = 6 + texture->width;
2398 
2399 	rgbaint_t polycolor(polydata.color);
2400 
2401 	for (int x = extent.startx; x < extent.stopx; x++)
2402 	{
2403 		if (z <= zb[x])
2404 		{
2405 			uint32_t texel;
2406 			TEX_FETCH();
2407 
2408 			uint32_t fa = texel >> 24;
2409 			if (fa >= 0xf8)
2410 			{
2411 				rgbaint_t color(texel);
2412 
2413 				color.scale_and_clamp(polycolor);
2414 				color.scale_imm_and_clamp((int)in);
2415 				color.blend(rgbaint_t(fb[x]), fa);
2416 
2417 				fb[x] = 0xff000000 | color.to_rgba_clamp();
2418 				zb[x] = z;
2419 			}
2420 		}
2421 
2422 		ooz += dooz;
2423 		uoz += duoz;
2424 		voz += dvoz;
2425 		in += inz;
2426 		z += dz;
2427 	}
2428 }
2429 
draw_scanline_tex_trans(int32_t scanline,const extent_t & extent,const model3_polydata & polydata,int threadid)2430 void model3_renderer::draw_scanline_tex_trans(int32_t scanline, const extent_t &extent, const model3_polydata &polydata, int threadid)
2431 {
2432 	uint32_t *const fb = &m_fb->pix(scanline);
2433 	float *const zb = (float*)&m_zb->pix(scanline);
2434 	const cached_texture *texture = polydata.texture;
2435 
2436 	float z = extent.param[0].start;
2437 	float dz = extent.param[0].dpdx;
2438 	float ooz = extent.param[1].start;
2439 	float dooz = extent.param[1].dpdx;
2440 	float uoz = extent.param[2].start;
2441 	float duoz = extent.param[2].dpdx;
2442 	float voz = extent.param[3].start;
2443 	float dvoz = extent.param[3].dpdx;
2444 	float in = extent.param[4].start;
2445 	float inz = extent.param[4].dpdx;
2446 
2447 	int trans = (polydata.transparency << 3) | (polydata.transparency >> 2);
2448 
2449 	uint32_t umask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1;
2450 	uint32_t vmask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1;
2451 	uint32_t width = 6 + texture->width;
2452 
2453 	rgbaint_t polycolor(polydata.color);
2454 
2455 	for (int x = extent.startx; x < extent.stopx; x++)
2456 	{
2457 		if (z <= zb[x])
2458 		{
2459 			uint32_t texel;
2460 			TEX_FETCH();
2461 
2462 			rgbaint_t color(texel);
2463 
2464 			color.scale_and_clamp(polycolor);
2465 			color.scale_imm_and_clamp((int)in);
2466 			color.blend(rgbaint_t(fb[x]), trans);
2467 
2468 			fb[x] = 0xff000000 | color.to_rgba_clamp();
2469 		}
2470 
2471 		ooz += dooz;
2472 		uoz += duoz;
2473 		voz += dvoz;
2474 		in += inz;
2475 		z += dz;
2476 	}
2477 }
2478 
draw_scanline_tex_alpha(int32_t scanline,const extent_t & extent,const model3_polydata & polydata,int threadid)2479 void model3_renderer::draw_scanline_tex_alpha(int32_t scanline, const extent_t &extent, const model3_polydata &polydata, int threadid)
2480 {
2481 	uint32_t *const fb = &m_fb->pix(scanline);
2482 	float *const zb = (float*)&m_zb->pix(scanline);
2483 	const cached_texture *texture = polydata.texture;
2484 
2485 	float z = extent.param[0].start;
2486 	float dz = extent.param[0].dpdx;
2487 	float ooz = extent.param[1].start;
2488 	float dooz = extent.param[1].dpdx;
2489 	float uoz = extent.param[2].start;
2490 	float duoz = extent.param[2].dpdx;
2491 	float voz = extent.param[3].start;
2492 	float dvoz = extent.param[3].dpdx;
2493 	float in = extent.param[4].start;
2494 	float inz = extent.param[4].dpdx;
2495 
2496 //  int srctrans = polydata.transparency;
2497 //  int desttrans = 32 - polydata.transparency;
2498 
2499 	uint32_t umask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_U) ? 64 : 32) << texture->width) - 1;
2500 	uint32_t vmask = (((polydata.texture_param & TRI_PARAM_TEXTURE_MIRROR_V) ? 64 : 32) << texture->height) - 1;
2501 	uint32_t width = 6 + texture->width;
2502 
2503 	for (int x = extent.startx; x < extent.stopx; x++)
2504 	{
2505 		if (z <= zb[x])
2506 		{
2507 			uint32_t texel;
2508 			TEX_FETCH();
2509 
2510 			uint32_t fa = texel >> 24;
2511 			if (fa != 0)
2512 			{
2513 				rgbaint_t color(texel);
2514 
2515 				color.scale_imm_and_clamp((int)in);
2516 				color.blend(rgbaint_t(fb[x]), fa);
2517 
2518 				fb[x] = 0xff000000 | color.to_rgba_clamp();
2519 			}
2520 		}
2521 
2522 		ooz += dooz;
2523 		uoz += duoz;
2524 		voz += dvoz;
2525 		in += inz;
2526 		z += dz;
2527 	}
2528 }
2529