1 #include "driver.h"
2 #include "state.h"
3 #include "vidhrdw/generic.h"
4 #include "vidhrdw/segaic24.h"
5 
6 #include <math.h>
7 
8 
9 #ifndef min
10 #define min(a,b) (a<b?a:b)
11 #endif
12 #ifndef max
13 #define max(a,b) (a>b?a:b)
14 #endif
15 
16 UINT16 *model1_display_list0, *model1_display_list1;
17 UINT16 *model1_color_xlat;
18 static UINT16 listctl[2];
19 static UINT16 *glist;
20 
21 // Model 1 geometrizer TGP and rasterizer simulation
22 enum { FRAC_SHIFT = 16 };
23 
24 static int render_done;
25 static UINT16 *tgp_ram;
26 static float trans_mat[12];
27 
28 static float vxx, vyy, vzz, ayy, ayyc, ayys;
29 
30 struct vector {
31 	float x, y, z;
32 };
33 
34 static struct {
35 	int xc, yc, x1, y1, x2, y2;
36 	float zoomx, zoomy, transx, transy;
37 	float a_bottom, a_top, a_left, a_right;
38 	struct vector light;
39 } view;
40 
41 struct spoint {
42 	INT32 x, y;
43 };
44 
45 struct point {
46 	float x, y, z;
47 	float xx, yy;
48 	struct spoint s;
49 };
50 
51 static struct lightparam
52 {
53 	float a;
54 	float d;
55 	float s;
56 	int p;
57 } lightparams[32];
58 
59 enum { MOIRE = 0x00010000 };
60 
61 struct quad {
62 	struct point *p[4];
63 	float z;
64 	int col;
65 };
66 
67 static struct point *pointdb, *pointpt;
68 static struct quad *quaddb, *quadpt;
69 static struct quad **quadind;
70 
71 static UINT32 *poly_rom,*poly_ram;
72 
u2f(UINT32 v)73 static float u2f(UINT32 v)
74 {
75 	union {
76 		float ff;
77 		UINT32 vv;
78 	} u;
79 	u.vv = v;
80 	return u.ff;
81 }
82 
f2u(float f)83 static UINT32 f2u(float f)
84 {
85 	union {
86 		float ff;
87 		UINT32 vv;
88 	} u;
89 	u.ff = f;
90 	return u.vv;
91 }
92 
readi(const UINT16 * adr)93 static UINT32 readi(const UINT16 *adr)
94 {
95 	return adr[0]|(adr[1] << 16);
96 }
97 
readi16(const UINT16 * adr)98 static INT16 readi16(const UINT16 *adr)
99 {
100 	return adr[0];
101 }
102 
readf(const UINT16 * adr)103 static float readf(const UINT16 *adr)
104 {
105 	return u2f(readi(adr));
106 }
107 
transform_point(struct point * p)108 static void transform_point(struct point *p)
109 {
110 	struct point q = *p;
111 	float xx, zz;
112 	xx = trans_mat[0]*q.x+trans_mat[3]*q.y+trans_mat[6]*q.z+trans_mat[9]+vxx;
113 	p->y = trans_mat[1]*q.x+trans_mat[4]*q.y+trans_mat[7]*q.z+trans_mat[10]+vyy;
114 	zz = trans_mat[2]*q.x+trans_mat[5]*q.y+trans_mat[8]*q.z+trans_mat[11]+vzz;
115 	p->x = ayyc*xx-ayys*zz;
116 	p->z = ayys*xx+ayyc*zz;
117 }
118 
transform_vector(struct vector * p)119 static void transform_vector(struct vector *p)
120 {
121 	struct vector q = *p;
122 	p->x = trans_mat[0]*q.x+trans_mat[3]*q.y+trans_mat[6]*q.z;
123 	p->y = trans_mat[1]*q.x+trans_mat[4]*q.y+trans_mat[7]*q.z;
124 	p->z = trans_mat[2]*q.x+trans_mat[5]*q.y+trans_mat[8]*q.z;
125 }
126 
normalize_vector(struct vector * p)127 static void normalize_vector(struct vector *p)
128 {
129 	float norm = sqrt(p->x*p->x+p->y*p->y+p->z*p->z);
130 	if(norm) {
131 		p->x /= norm;
132 		p->y /= norm;
133 		p->z /= norm;
134 	}
135 }
136 
mult_vector(const struct vector * p,const struct vector * q)137 static float mult_vector(const struct vector *p, const struct vector *q)
138 {
139 	return p->x*q->x+p->y*q->y+p->z*q->z;
140 }
141 
view_determinant(const struct point * p1,const struct point * p2,const struct point * p3)142 static float view_determinant(const struct point *p1, const struct point *p2, const struct point *p3)
143 {
144 	float x1 = p2->x - p1->x;
145 	float y1 = p2->y - p1->y;
146 	float z1 = p2->z - p1->z;
147 	float x2 = p3->x - p1->x;
148 	float y2 = p3->y - p1->y;
149 	float z2 = p3->z - p1->z;
150 
151 	return p1->x*(y1*z2-y2*z1) + p1->y*(z1*x2-z2*x1) + p1->z*(x1*y2-x2*y1);
152 }
153 
154 
project_point(struct point * p)155 static void project_point(struct point *p)
156 {
157 	p->xx = p->x / p->z;
158 	p->yy = p->y / p->z;
159 	p->s.x = view.xc+(p->xx*view.zoomx+view.transx);
160 	p->s.y = view.yc-(p->yy*view.zoomy+view.transy);
161 }
162 
project_point_direct(struct point * p)163 static void project_point_direct(struct point *p)
164 {
165 	p->xx = p->x /*/ p->z*/;
166 	p->yy = p->y /*/ p->z*/;
167 	p->s.x = view.xc+(p->xx);
168 	p->s.y = view.yc-(p->yy);
169 }
170 
171 
draw_hline(struct mame_bitmap * bitmap,int x1,int x2,int y,int color)172 static void draw_hline(struct mame_bitmap *bitmap, int x1, int x2, int y, int color)
173 {
174 	UINT16 *base = (UINT16 *)(bitmap->line[y]);
175 	while(x1 <= x2) {
176 		base[x1] = color;
177 		x1++;
178 	}
179 }
180 
draw_hline_moired(struct mame_bitmap * bitmap,int x1,int x2,int y,int color)181 static void draw_hline_moired(struct mame_bitmap *bitmap, int x1, int x2, int y, int color)
182 {
183 	UINT16 *base = (UINT16 *)(bitmap->line[y]);
184 	while(x1 <= x2) {
185 		if((x1^y)&1)
186 			base[x1] = color;
187 		x1++;
188 	}
189 }
190 
fill_slope(struct mame_bitmap * bitmap,int color,INT32 x1,INT32 x2,INT32 sl1,INT32 sl2,INT32 y1,INT32 y2,INT32 * nx1,INT32 * nx2)191 static void fill_slope(struct mame_bitmap *bitmap, int color, INT32 x1, INT32 x2, INT32 sl1, INT32 sl2, INT32 y1, INT32 y2, INT32 *nx1, INT32 *nx2)
192 {
193 	if(y1 > view.y2)
194 		return;
195 
196 	if(y2 <= view.y1) {
197 		int delta = y2-y1;
198 		*nx1 = x1+delta*sl1;
199 		*nx2 = x2+delta*sl2;
200 		return;
201 	}
202 
203 	if(y2 > view.y2)
204 		y2 = view.y2+1;
205 
206 	if(y1 < view.y1) {
207 		int delta = view.y1 - y1;
208 		x1 += delta*sl1;
209 		x2 += delta*sl2;
210 		y1 = view.y1;
211 	}
212 
213 	if(x1 > x2 || (x1==x2 && sl1 > sl2)) {
214 		INT32 t, *tp;
215 		t = x1;
216 		x1 = x2;
217 		x2 = t;
218 		t = sl1;
219 		sl1 = sl2;
220 		sl2 = t;
221 		tp = nx1;
222 		nx1 = nx2;
223 		nx2 = tp;
224 	}
225 
226 	while(y1 < y2) {
227 		if(y1 >= view.y1) {
228 			int xx1 = x1>>FRAC_SHIFT;
229 			int xx2 = x2>>FRAC_SHIFT;
230 			if(xx1 <= view.x2 || xx2 >= view.x1) {
231 				if(xx1 < view.x1)
232 					xx1 = view.x1;
233 				if(xx2 > view.x2)
234 					xx2 = view.x2;
235 
236 				if(color & MOIRE)
237 					draw_hline_moired(bitmap, xx1, xx2, y1, color);
238 				else
239 					draw_hline(bitmap, xx1, xx2, y1, color);
240 			}
241 		}
242 
243 		x1 += sl1;
244 		x2 += sl2;
245 		y1++;
246 	}
247 	*nx1 = x1;
248 	*nx2 = x2;
249 }
250 
fill_line(struct mame_bitmap * bitmap,int color,INT32 y,INT32 x1,INT32 x2)251 static void fill_line(struct mame_bitmap *bitmap, int color, INT32 y, INT32 x1, INT32 x2)
252 {
253 	int xx1 = x1>>FRAC_SHIFT;
254 	int xx2 = x2>>FRAC_SHIFT;
255 
256 	if(y > view.y2 || y < view.y1)
257 		return;
258 
259 	if(xx1 <= view.x2 || xx2 >= view.x1) {
260 		if(xx1 < view.x1)
261 			xx1 = view.x1;
262 		if(xx2 > view.x2)
263 			xx2 = view.x2;
264 
265 		if(color & MOIRE)
266 			draw_hline_moired(bitmap, xx1, xx2, y, color);
267 		else
268 			draw_hline(bitmap, xx1, xx2, y, color);
269 	}
270 }
271 
fill_quad(struct mame_bitmap * bitmap,const struct quad * q)272 static void fill_quad(struct mame_bitmap *bitmap, const struct quad *q)
273 {
274 	INT32 sl1, sl2, cury, limy, x1, x2;
275 	int pmin, pmax, i, ps1, ps2;
276 	struct spoint p[8];
277 	int color = q->col;
278 
279 	if(color < 0) {
280 		color = -1-color;
281 		logerror("VIDEOD: Q (%d, %d)-(%d, %d)-(%d, %d)-(%d, %d)\n",
282 				 q->p[0]->s.x, q->p[0]->s.y,
283 				 q->p[1]->s.x, q->p[1]->s.y,
284 				 q->p[2]->s.x, q->p[2]->s.y,
285 				 q->p[3]->s.x, q->p[3]->s.y);
286 	}
287 
288 	for(i=0; i<4; i++) {
289 		p[i].x = p[i+4].x = q->p[i]->s.x << FRAC_SHIFT;
290 		p[i].y = p[i+4].y = q->p[i]->s.y;
291 	}
292 
293 	pmin = pmax = 0;
294 	for(i=1; i<4; i++) {
295 		if(p[i].y < p[pmin].y)
296 			pmin = i;
297 		if(p[i].y > p[pmax].y)
298 			pmax = i;
299 	}
300 
301 	cury = p[pmin].y;
302 	limy = p[pmax].y;
303 
304 	if(cury == limy) {
305 		x1 = x2 = p[0].x;
306 		for(i=1; i<4; i++) {
307 			if(p[i].x < x1)
308 				x1 = p[i].x;
309 			if(p[i].x > x2)
310 				x2 = p[i].x;
311 		}
312 		fill_line(bitmap, color, cury, x1, x2);
313 		return;
314 	}
315 
316 	if(cury > view.y2)
317 		return;
318 	if(limy <= view.y1)
319 		return;
320 
321 	if(limy > view.y2)
322 		limy = view.y2;
323 
324 	ps1 = pmin+4;
325 	ps2 = pmin;
326 
327 	goto startup;
328 
329 	for(;;) {
330 		if(p[ps1-1].y == p[ps2+1].y) {
331 			fill_slope(bitmap, color, x1, x2, sl1, sl2, cury, p[ps1-1].y, &x1, &x2);
332 			cury = p[ps1-1].y;
333 			if(cury >= limy)
334 				break;
335 			ps1--;
336 			ps2++;
337 
338 		startup:
339 			while(p[ps1-1].y == cury)
340 				ps1--;
341 			while(p[ps2+1].y == cury)
342 				ps2++;
343 			x1 = p[ps1].x;
344 			x2 = p[ps2].x;
345 			sl1 = (x1-p[ps1-1].x)/(cury-p[ps1-1].y);
346 			sl2 = (x2-p[ps2+1].x)/(cury-p[ps2+1].y);
347 		} else if(p[ps1-1].y < p[ps2+1].y) {
348 			fill_slope(bitmap, color, x1, x2, sl1, sl2, cury, p[ps1-1].y, &x1, &x2);
349 			cury = p[ps1-1].y;
350 			if(cury >= limy)
351 				break;
352 			ps1--;
353 			while(p[ps1-1].y == cury)
354 				ps1--;
355 			x1 = p[ps1].x;
356 			sl1 = (x1-p[ps1-1].x)/(cury-p[ps1-1].y);
357 		} else {
358 			fill_slope(bitmap, color, x1, x2, sl1, sl2, cury, p[ps2+1].y, &x1, &x2);
359 			cury = p[ps2+1].y;
360 			if(cury >= limy)
361 				break;
362 			ps2++;
363 			while(p[ps2+1].y == cury)
364 				ps2++;
365 			x2 = p[ps2].x;
366 			sl2 = (x2-p[ps2+1].x)/(cury-p[ps2+1].y);
367 		}
368 	}
369 	if(cury == limy)
370 		fill_line(bitmap, color, cury, x1, x2);
371 }
372 #if 0
373 static void draw_line(struct mame_bitmap *bitmap, int color, int x1, int y1, int x2, int y2)
374 {
375 	int s1x, s1y, s2x, s2y;
376 	int d1, d2;
377 	int cur;
378 	int x, y;
379 
380 	if((x1 < view.x1 && x2 < view.x1) ||
381 	   (x1 > view.x2 && x2 > view.x2) ||
382 	   (y1 < view.y1 && y2 < view.y1) ||
383 	   (y1 > view.y2 && y2 > view.y2))
384 		return;
385 
386 	x = x1;
387 	y = y1;
388 	s1x = 1;
389 	s1y = 0;
390 	s2x = 0;
391 	s2y = 1;
392 
393 	d1 = x2-x1;
394 	d2 = y2-y1;
395 	if(d1<0) {
396 		s1x = -s1x;
397 		d1 = -d1;
398 	}
399 	if(d2<0) {
400 		s2y = -s2y;
401 		d2 = -d2;
402 	}
403 	if(d1 < d2) {
404 		int t;
405 		t = s1x;
406 		s1x = s2x;
407 		s2x = t;
408 		t = s1y;
409 		s1y = s2y;
410 		s2y = t;
411 		t = d1;
412 		d1 = d2;
413 		d2 = t;
414 	}
415 
416 	if(d1 > 600)
417 		return;
418 
419 	cur = 0;
420 	while(x != x2 || y != y2) {
421 		if(x>=view.x1 && x<=view.x2 && y>=view.y1 && y<=view.y2)
422 			((UINT16 *)(bitmap->line[y]))[x] = color;
423 		x += s1x;
424 		y += s1y;
425 		cur += d2;
426 		if(cur >= d1) {
427 			cur -= d1;
428 			x += s2x;
429 			y += s2y;
430 		}
431 	}
432 	if(x>=view.x1 && x<=view.x2 && y>=view.y1 && y<=view.y2)
433 		((UINT16 *)(bitmap->line[y]))[x] = color;
434 }
435 #endif
comp_quads(const void * q1,const void * q2)436 static int comp_quads(const void *q1, const void *q2)
437 {
438 	float z1 = (*(const struct quad **)q1)->z;
439 	float z2 = (*(const struct quad **)q2)->z;
440 	if(z1<z2)
441 		return +1;
442 	if(z1>z2)
443 		return -1;
444 	return 0;
445 }
446 
sort_quads(void)447 static void sort_quads(void)
448 {
449 	int count = quadpt - quaddb;
450 	int i;
451 	for(i=0; i<count; i++)
452 		quadind[i] = quaddb+i;
453 	qsort(quadind, count, sizeof(struct quad *), comp_quads);
454 }
455 
unsort_quads(void)456 static void unsort_quads(void)
457 {
458 	int count = quadpt - quaddb;
459 	int i;
460 	for(i=0; i<count; i++)
461 		quadind[i] = quaddb+i;
462 }
463 
464 
draw_quads(struct mame_bitmap * bitmap,const struct rectangle * cliprect)465 static void draw_quads(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
466 {
467 	int count = quadpt - quaddb;
468 	int i;
469 	for(i=0; i<count; i++) {
470 		struct quad *q = quadind[i];
471 
472 		fill_quad(bitmap, q);
473 #if 0
474 		draw_line(bitmap, get_black_pen(), q->p[0]->s.x, q->p[0]->s.y, q->p[1]->s.x, q->p[1]->s.y);
475 		draw_line(bitmap, get_black_pen(), q->p[1]->s.x, q->p[1]->s.y, q->p[2]->s.x, q->p[2]->s.y);
476 		draw_line(bitmap, get_black_pen(), q->p[2]->s.x, q->p[2]->s.y, q->p[3]->s.x, q->p[3]->s.y);
477 		draw_line(bitmap, get_black_pen(), q->p[3]->s.x, q->p[3]->s.y, q->p[0]->s.x, q->p[0]->s.y);
478 #endif
479 	}
480 }
481 
scale_color(UINT16 color,float level)482 static UINT16 scale_color(UINT16 color, float level)
483 {
484 	int r, g, b;
485 	r = ((color >> 10) & 31)*level;
486 	g = ((color >> 5) & 31)*level;
487 	b = (color & 31)*level;
488 	return (r<<10)|(g<<5)|b;
489 }
490 
491 // xe = xc + (x/z * zm + tx)
492 // xe < x1 => xc + (x/z * zm + tx) < x1
493 //         => x/z < (x1-xc-tx)/zm
494 //         => x < z*(x1-xc-tx)/zm
495 
496 // ye = yc - (y/z * zm + ty)
497 // ye < y1 => yc - (y/z * zm + ty) < y1
498 //         => -y/z < (y1-yc+ty)/zm
499 //         => y > -z*(y1-yc+ty)/zm
500 
501 // xf = zf*a
502 // xx = x1*t+x2(1-t); zz = z1*t+z2(1-t)
503 // => x1*t+x2(1-t) = z1*t*a+z2*(1-t)*a
504 // => t*(x1-x2+a*(z2-z1) = -x2+a*z2
505 // => t = (z2*a-x2)/((z2-z1)*a-(x2-x1))
506 
recompute_frustrum(void)507 static void recompute_frustrum(void)
508 {
509 	view.a_left   = ( view.x1-view.xc-view.transx)/view.zoomx;
510 	view.a_right  = ( view.x2-view.xc-view.transx)/view.zoomx;
511 	view.a_bottom = (-view.y1+view.yc-view.transy)/view.zoomy;
512 	view.a_top    = (-view.y2+view.yc-view.transy)/view.zoomy;
513 }
514 
fclip_isc_bottom(struct point * p)515 static int fclip_isc_bottom(struct point *p)
516 {
517 	return p->y > p->z*view.a_bottom;
518 }
519 
fclip_clip_bottom(struct point * p1,struct point * p2)520 static struct point *fclip_clip_bottom(struct point *p1, struct point *p2)
521 {
522 	float t = (p2->z*view.a_bottom-p2->y)/((p2->z-p1->z)*view.a_bottom-(p2->y-p1->y));
523 	pointpt->x = p1->x*t + p2->x*(1-t);
524 	pointpt->y = p1->y*t + p2->y*(1-t);
525 	pointpt->z = p1->z*t + p2->z*(1-t);
526 	project_point(pointpt);
527 	return pointpt++;
528 }
529 
fclip_isc_top(struct point * p)530 static int fclip_isc_top(struct point *p)
531 {
532 	return p->y < p->z*view.a_top;
533 }
534 
fclip_clip_top(struct point * p1,struct point * p2)535 static struct point *fclip_clip_top(struct point *p1, struct point *p2)
536 {
537 	float t = (p2->z*view.a_top-p2->y)/((p2->z-p1->z)*view.a_top-(p2->y-p1->y));
538 	pointpt->x = p1->x*t + p2->x*(1-t);
539 	pointpt->y = p1->y*t + p2->y*(1-t);
540 	pointpt->z = p1->z*t + p2->z*(1-t);
541 	project_point(pointpt);
542 	return pointpt++;
543 }
544 
fclip_isc_left(struct point * p)545 static int fclip_isc_left(struct point *p)
546 {
547 	return p->x < p->z*view.a_left;
548 }
549 
fclip_clip_left(struct point * p1,struct point * p2)550 static struct point *fclip_clip_left(struct point *p1, struct point *p2)
551 {
552 	float t = (p2->z*view.a_left-p2->x)/((p2->z-p1->z)*view.a_left-(p2->x-p1->x));
553 	pointpt->x = p1->x*t + p2->x*(1-t);
554 	pointpt->y = p1->y*t + p2->y*(1-t);
555 	pointpt->z = p1->z*t + p2->z*(1-t);
556 	project_point(pointpt);
557 	return pointpt++;
558 }
559 
fclip_isc_right(struct point * p)560 static int fclip_isc_right(struct point *p)
561 {
562 	return p->x > p->z*view.a_right;
563 }
564 
fclip_clip_right(struct point * p1,struct point * p2)565 static struct point *fclip_clip_right(struct point *p1, struct point *p2)
566 {
567 	float t = (p2->z*view.a_right-p2->x)/((p2->z-p1->z)*view.a_right-(p2->x-p1->x));
568 	pointpt->x = p1->x*t + p2->x*(1-t);
569 	pointpt->y = p1->y*t + p2->y*(1-t);
570 	pointpt->z = p1->z*t + p2->z*(1-t);
571 	project_point(pointpt);
572 	return pointpt++;
573 }
574 
575 static struct {
576 	int (*isclipped)(struct point *p);
577 	struct point *(*clip)(struct point *p1, struct point *p2);
578 } clipfn[4] = {
579 	{ fclip_isc_bottom, fclip_clip_bottom },
580 	{ fclip_isc_top,    fclip_clip_top },
581 	{ fclip_isc_left,   fclip_clip_left },
582 	{ fclip_isc_right,  fclip_clip_right },
583 };
584 
585 static void fclip_push_quad(int level, struct quad *q);
586 
fclip_push_quad_next(int level,struct quad * q,struct point * p1,struct point * p2,struct point * p3,struct point * p4)587 static void fclip_push_quad_next(int level, struct quad *q,
588 								 struct point *p1, struct point *p2, struct point *p3, struct point *p4)
589 {
590 	struct quad q2;
591 	q2.col = q->col;
592 	q2.z = q->z;
593 	q2.p[0] = p1;
594 	q2.p[1] = p2;
595 	q2.p[2] = p3;
596 	q2.p[3] = p4;
597 
598 	fclip_push_quad(level+1, &q2);
599 }
600 
fclip_push_quad(int level,struct quad * q)601 static void fclip_push_quad(int level, struct quad *q)
602 {
603 	int i, j;
604 	struct point *pt[4], *pi1, *pi2;
605 	int is_out[4], is_out2[4];
606 	struct point *(*fclip_point)(struct point *p1, struct point *p2);
607 
608 	if(level == 4) {
609 		logerror("VIDEOCQ %d", level);
610 		for(i=0; i<4; i++)
611 			logerror(" (%f, %f, %f)", q->p[i]->x, q->p[i]->y, q->p[i]->z);
612 		logerror("\n");
613 		*quadpt = *q;
614 		quadpt++;
615 		return;
616 	}
617 
618 	for(i=0; i<4; i++)
619 		is_out[i] = clipfn[level].isclipped(q->p[i]);
620 
621 	logerror("VIDEOCQ %d", level);
622 	for(i=0; i<4; i++)
623 		logerror(" (%f, %f, %f, %d)", q->p[i]->x, q->p[i]->y, q->p[i]->z, is_out[i]);
624 	logerror("\n");
625 
626 	// No clipping
627 	if(!is_out[0] && !is_out[1] && !is_out[2] && !is_out[3]) {
628 		fclip_push_quad(level+1, q);
629 		return;
630 	}
631 
632 	fclip_point = clipfn[level].clip;
633 
634 	// Full clipping
635 	if(is_out[0] && is_out[1] && is_out[2] && is_out[3])
636 		return;
637 
638 	// Find n so that point n is clipped and n-1 isn't
639 	for(i=0; i<4; i++)
640 		if(is_out[i] && !is_out[(i-1)&3])
641 			break;
642 
643 	for(j=0; j<4; j++) {
644 		pt[j] = q->p[(i+j)&3];
645 		is_out2[j] = is_out[(i+j)&3];
646 	}
647 
648 	// At this point, pt[0] is clipped out and pt[3] isn't.  Test for the 4 possible cases
649 	if(is_out2[1])
650 		if(is_out2[2]) {
651 			// pt 0,1,2 clipped out, one triangle left
652 			pi1 = fclip_point(pt[2], pt[3]);
653 			pi2 = fclip_point(pt[3], pt[0]);
654 			fclip_push_quad_next(level, q, pi1, pt[3], pi2, pi2);
655 		} else {
656 			// pt 0,1 clipped out, one quad left
657 			pi1 = fclip_point(pt[1], pt[2]);
658 			pi2 = fclip_point(pt[3], pt[0]);
659 			fclip_push_quad_next(level, q, pi1, pt[2], pt[3], pi2);
660 		}
661 	else
662 		if(is_out2[2]) {
663 			// pt 0,2 clipped out, shouldn't happen, two triangles
664 			pi1 = fclip_point(pt[0], pt[1]);
665 			pi2 = fclip_point(pt[1], pt[2]);
666 			fclip_push_quad_next(level, q, pi1, pt[1], pi2, pi2);
667 			pi1 = fclip_point(pt[2], pt[3]);
668 			pi2 = fclip_point(pt[3], pt[0]);
669 			fclip_push_quad_next(level, q, pi1, pt[3], pi2, pi2);
670 		} else {
671 			// pt 0 clipped out, one decagon left, split in quad+tri
672 			pi1 = fclip_point(pt[0], pt[1]);
673 			pi2 = fclip_point(pt[3], pt[0]);
674 			fclip_push_quad_next(level, q, pi1, pt[1], pt[2], pt[3]);
675 			fclip_push_quad_next(level, q, pt[3], pi2, pi1, pi1);
676 		}
677 }
678 
min4f(float a,float b,float c,float d)679 static float min4f(float a, float b, float c, float d)
680 {
681 	float m = a;
682 	if(b<m)
683 		m = b;
684 	if(c<m)
685 		m = c;
686 	if(d<m)
687 		m = d;
688 	return m;
689 }
690 
max4f(float a,float b,float c,float d)691 static float max4f(float a, float b, float c, float d)
692 {
693 	float m = a;
694 	if(b>m)
695 		m = b;
696 	if(c>m)
697 		m = c;
698 	if(d>m)
699 		m = d;
700 	return m;
701 }
702 
703 static const unsigned char times[]={1,1,1,1,2,2,2,3};
compute_specular(struct vector * normal,struct vector * light,float diffuse,int lmode)704 static float compute_specular(struct vector *normal, struct vector *light,float diffuse,int lmode)
705 {
706 #if 0
707 	float s;
708 	int p=lightparams[lmode].p&7;
709 	int i;
710 	float sv=lightparams[lmode].s;
711 
712 	//This is how it should be according to model2 geo program, but doesn't work fine
713 	s=2*(diffuse*normal->z-light->z);
714 	for(i=0;i<times[p];++i)
715 		s*=s;
716 	s*=sv;
717 	if(s<0.0)
718 		return 0.0;
719 	if(s>1.0)
720 		return 1.0;
721 	return s;
722 
723 	return fabs(diffuse)*sv;
724 
725 #endif
726 
727 	return 0;
728 }
729 
push_object(UINT32 tex_adr,UINT32 poly_adr,UINT32 size)730 static void push_object(UINT32 tex_adr, UINT32 poly_adr, UINT32 size)
731 {
732 	int i;
733 	UINT32 flags;
734 	struct point *old_p0, *old_p1, *p0, *p1;
735 	struct vector vn;
736 	int link, type;
737 	int dump;
738 	int lightmode;
739 	float old_z;
740 	struct quad cquad;
741 	float *poly_data;
742 
743 	if(poly_adr & 0x800000)
744 		poly_data=(float *) poly_ram;
745 	else
746 		poly_data=(float *) poly_rom;
747 
748 	poly_adr &= 0x7fffff;
749 	dump = poly_adr == 0x944ea;
750 	dump = 0;
751 
752 #if 0
753 	if(poly_adr < 0x10000 || poly_adr >= 0x80000)
754 		return;
755 
756 	if(poly_adr < 0x40000 || poly_adr >= 0x50000)
757 		return;
758 
759 	if(poly_adr == 0x4c7db || poly_adr == 0x4cdaa || poly_adr == 0x4d3e7)
760 		return;
761 
762 	if(poly_adr != 0x483e5)
763 		return;
764 #endif
765 
766 	if(1) {
767 		logerror("XVIDEO:   draw object (%x, %x, %x)\n", tex_adr, poly_adr, size);
768 	}
769 
770 	if(!size)
771 		size = 0xffffffff;
772 
773 	old_p0 = pointpt++;
774 	old_p1 = pointpt++;
775 
776 	old_p0->x = poly_data[poly_adr+0];
777 	old_p0->y = poly_data[poly_adr+1];
778 	old_p0->z = poly_data[poly_adr+2];
779 	old_p1->x = poly_data[poly_adr+3];
780 	old_p1->y = poly_data[poly_adr+4];
781 	old_p1->z = poly_data[poly_adr+5];
782 	transform_point(old_p0);
783 	transform_point(old_p1);
784 	if(old_p0->z > 0)
785 		project_point(old_p0);
786 	else
787 		old_p0->s.x = old_p0->s.y = 0;
788 	if(old_p1->z > 0)
789 		project_point(old_p1);
790 	else
791 		old_p1->s.x = old_p1->s.y = 0;
792 
793 	old_z = 0;
794 
795 	poly_adr += 6;
796 
797 	for(i=0; i<size; i++) {
798 #if 0
799 		logerror("VIDEO:     %08x (%f, %f, %f) (%f, %f, %f) (%f, %f, %f)\n",
800 				 *(UINT32 *)(poly_data+poly_adr) & ~(0x01800303),
801 				 poly_data[poly_adr+1], poly_data[poly_adr+2], poly_data[poly_adr+3],
802 				 poly_data[poly_adr+4], poly_data[poly_adr+5], poly_data[poly_adr+6],
803 				 poly_data[poly_adr+7], poly_data[poly_adr+8], poly_data[poly_adr+9]);
804 #endif
805 		flags = *(UINT32 *)(poly_data+poly_adr);
806 
807 		type = flags & 3;
808 		if(!type)
809 			break;
810 
811 		if(flags & 0x00001000)
812 			tex_adr ++;
813 		lightmode=(flags>>17)&15;
814 
815 		p0 = pointpt++;
816 		p1 = pointpt++;
817 
818 		vn.x = poly_data[poly_adr+1];
819 		vn.y = poly_data[poly_adr+2];
820 		vn.z = poly_data[poly_adr+3];
821 		p0->x = poly_data[poly_adr+4];
822 		p0->y = poly_data[poly_adr+5];
823 		p0->z = poly_data[poly_adr+6];
824 		p1->x = poly_data[poly_adr+7];
825 		p1->y = poly_data[poly_adr+8];
826 		p1->z = poly_data[poly_adr+9];
827 
828 		link = (flags >> 8) & 3;
829 
830 		transform_vector(&vn);
831 
832 		transform_point(p0);
833 		transform_point(p1);
834 		if(p0->z > 0)
835 			project_point(p0);
836 		else
837 			p0->s.x = p0->s.y = 0;
838 		if(p1->z > 0)
839 			project_point(p1);
840 		else
841 			p1->s.x = p1->s.y = 0;
842 
843 #if 0
844 		if(dump)
845 			logerror("VIDEO:     %08x (%f, %f, %f) (%f, %f, %f)\n",
846 					 *(UINT32 *)(poly_data+poly_adr),
847 					 p0->x, p0->y, p0->z,
848 					 p1->x, p1->y, p1->z);
849 #endif
850 
851 
852 #if 0
853 		if(1 || dump) {
854 			logerror("VIDEO:     %08x (%d, %d) (%d, %d) (%d, %d) (%d, %d)\n",
855 					 *(UINT32 *)(poly_data+poly_adr),
856 					 old_p0->s.x, old_p0->s.y,
857 					 old_p1->s.x, old_p1->s.y,
858 					 p0->s.x, p0->s.y,
859 					 p1->s.x, p1->s.y);
860 		}
861 #endif
862 
863 		if(!link)
864 			goto next;
865 
866 		if(!(flags & 0x00004000) && view_determinant(old_p1, old_p0, p0) > 0)
867 			goto next;
868 
869 		normalize_vector(&vn);
870 
871 		cquad.p[0] = old_p1;
872 		cquad.p[1] = old_p0;
873 		cquad.p[2] = p0;
874 		cquad.p[3] = p1;
875 
876 		switch((flags >> 10) & 3) {
877 		case 0:
878 			cquad.z = old_z;
879 			break;
880 		case 1:
881 			cquad.z = old_z = min4f(old_p1->z, old_p0->z, p0->z, p1->z);
882 			break;
883 		case 2:
884 			cquad.z = old_z = max4f(old_p1->z, old_p0->z, p0->z, p1->z);
885 			break;
886 		case 3:
887 		default:
888 			cquad.z = 0.0;
889 			break;
890 		}
891 
892 		{
893 			/*float dif=mult_vector(&vn, &view.light);
894 			float ln=lightparams[lightmode].a + lightparams[lightmode].d*max(0.0,dif);
895 			cquad.col = scale_color(Machine->pens[0x1000|(tgp_ram[tex_adr-0x40000] & 0x3ff)], min(1.0,ln));
896 			cquad.col = scale_color(Machine->pens[0x1000|(tgp_ram[tex_adr-0x40000] & 0x3ff)], min(1.0,ln));
897 			*/
898 			float dif=mult_vector(&vn, &view.light);
899 			float spec=compute_specular(&vn,&view.light,dif,lightmode);
900 			float ln=lightparams[lightmode].a + lightparams[lightmode].d*max(0.0,dif) + spec;
901 			int lumval=255.0*min(1.0,ln);
902 			int color=paletteram16[0x1000|(tgp_ram[tex_adr-0x40000] & 0x3ff)];
903 			int r=(color>>0x0)&0x1f;
904 			int g=(color>>0x5)&0x1f;
905 			int b=(color>>0xA)&0x1f;
906 			lumval>>=2;	//there must be a luma translation table somewhere
907 			if(lumval>0x3f)
908 				lumval=0x3f;
909 			r=(model1_color_xlat[(r<<8)|lumval|0x0]>>3)&0x1f;
910 			g=(model1_color_xlat[(g<<8)|lumval|0x2000]>>3)&0x1f;
911 			b=(model1_color_xlat[(b<<8)|lumval|0x4000]>>3)&0x1f;
912 			cquad.col=(r<<10)|(g<<5)|(b<<0);
913 		}
914 
915 		if(flags & 0x00002000)
916 			cquad.col |= MOIRE;
917 
918 		fclip_push_quad(0, &cquad);
919 
920 	next:
921 		poly_adr += 10;
922 		switch(link) {
923 		case 0:
924 		case 2:
925 			old_p0 = p0;
926 			old_p1 = p1;
927 			break;
928 		case 1:
929 			old_p1 = p0;
930 			break;
931 		case 3:
932 			old_p0 = p1;
933 			break;
934 		}
935 	}
936 }
937 
push_direct(UINT16 * list)938 static UINT16 *push_direct(UINT16 *list)
939 {
940 	UINT32 flags;
941 	UINT32 tex_adr, lum, v1, v2;
942 	struct point *old_p0, *old_p1, *p0, *p1;
943 	int link, type;
944 	float z;
945 	struct quad cquad;
946 
947 	tex_adr = readi(list);
948 	v1      = readi(list+2);
949 	v2      = readi(list+10);
950 
951 	old_p0 = pointpt++;
952 	old_p1 = pointpt++;
953 
954 	old_p0->x = readf(list+4);
955 	old_p0->y = readf(list+6);
956 	old_p0->z = readf(list+8);
957 	old_p1->x = readf(list+12);
958 	old_p1->y = readf(list+14);
959 	old_p1->z = readf(list+16);
960 
961 	logerror("VIDEOD start direct\n");
962 	logerror("VIDEOD (%f, %f, %f) (%f, %f, %f)\n",
963 			 old_p0->x, old_p0->y, old_p0->z,
964 			 old_p1->x, old_p1->y, old_p1->z);
965 
966 //	transform_point(old_p0);
967 //	transform_point(old_p1);
968 	if(old_p0->z > 0)
969 		project_point_direct(old_p0);
970 	else
971 		old_p0->s.x = old_p0->s.y = 0;
972 	if(old_p1->z > 0)
973 		project_point_direct(old_p1);
974 	else
975 		old_p1->s.x = old_p1->s.y = 0;
976 
977 	list += 18;
978 
979 	for(;;) {
980 		flags = readi(list);
981 
982 		type = flags & 3;
983 		if(!type)
984 			break;
985 
986 		if(flags & 0x00001000)
987 			tex_adr ++;
988 
989 		// list+2 is luminosity
990 		// list+4 is 0?
991 		// list+12 is z?
992 
993 		p0 = pointpt++;
994 		p1 = pointpt++;
995 
996 		lum   = readi(list+2);
997 		v1    = readi(list+4);
998 
999 		if(type == 2) {
1000 			p0->x = readf(list+6);
1001 			p0->y = readf(list+8);
1002 			p0->z = readf(list+10);
1003 			z = p0->z;
1004 			logerror("VIDEOD %08x %08x (%f, %f, %f)\n",
1005 					 flags, lum,
1006 					 p0->x, p0->y, p0->z);
1007 			*p1 = *p0;
1008 			list += 12;
1009 		} else {
1010 			p0->x = readf(list+6);
1011 			p0->y = readf(list+8);
1012 			p0->z = readf(list+10);
1013 			p1->x = readf(list+14);
1014 			p1->y = readf(list+16);
1015 			p1->z = readf(list+18);
1016 			z     = readf(list+12);
1017 			logerror("VIDEOD %08x %08x (%f, %f, %f) (%f, %f, %f)\n",
1018 					 flags, lum,
1019 					 p0->x, p0->y, p0->z,
1020 					 p1->x, p1->y, p1->z);
1021 			list += 20;
1022 		}
1023 
1024 		link = (flags >> 8) & 3;
1025 
1026 //		transform_point(p0);
1027 //		transform_point(p1);
1028 		if(p0->z > 0)
1029 			project_point_direct(p0);
1030 		if(p1->z > 0)
1031 			project_point_direct(p1);
1032 
1033 #if 1
1034 		if(old_p0 && old_p1)
1035 			logerror("VIDEOD:     %08x (%d, %d) (%d, %d) (%d, %d) (%d, %d)\n",
1036 					 flags,
1037 					 old_p0->s.x, old_p0->s.y,
1038 					 old_p1->s.x, old_p1->s.y,
1039 					 p0->s.x, p0->s.y,
1040 					 p1->s.x, p1->s.y);
1041 		else
1042 			logerror("VIDEOD:     %08x (%d, %d) (%d, %d)\n",
1043 					 flags,
1044 					 p0->s.x, p0->s.y,
1045 					 p1->s.x, p1->s.y);
1046 
1047 #endif
1048 
1049 		if(!link)
1050 			goto next;
1051 
1052 		cquad.p[0] = old_p1;
1053 		cquad.p[1] = old_p0;
1054 		cquad.p[2] = p0;
1055 		cquad.p[3] = p1;
1056 		cquad.z    = z;
1057 		{
1058 			int lumval=((float) (lum>>24)) * 2.0;
1059 			int color=paletteram16[0x1000|(tgp_ram[tex_adr-0x40000] & 0x3ff)];
1060 			int r=(color>>0x0)&0x1f;
1061 			int g=(color>>0x5)&0x1f;
1062 			int b=(color>>0xA)&0x1f;
1063 			lumval>>=2;	//there must be a luma translation table somewhere
1064 			if(lumval>0x3f)
1065 				lumval=0x3f;
1066 			r=(model1_color_xlat[(r<<8)|lumval|0x0]>>3)&0x1f;
1067 			g=(model1_color_xlat[(g<<8)|lumval|0x2000]>>3)&0x1f;
1068 			b=(model1_color_xlat[(b<<8)|lumval|0x4000]>>3)&0x1f;
1069 			cquad.col=(r<<10)|(g<<5)|(b<<0);
1070 		}
1071 		//cquad.col  = scale_color(Machine->pens[0x1000|(tgp_ram[tex_adr-0x40000] & 0x3ff)],((float) (lum>>24)) / 128.0);
1072 		if(flags & 0x00002000)
1073 			cquad.col |= MOIRE;
1074 
1075 		fclip_push_quad(0, &cquad);
1076 
1077 	next:
1078 		switch(link) {
1079 		case 0:
1080 		case 2:
1081 			old_p0 = p0;
1082 			old_p1 = p1;
1083 			break;
1084 		case 1:
1085 			old_p1 = p0;
1086 			break;
1087 		case 3:
1088 			old_p0 = p1;
1089 			break;
1090 		}
1091 	}
1092 	return list+2;
1093 }
1094 
skip_direct(UINT16 * list)1095 static UINT16 *skip_direct(UINT16 *list)
1096 {
1097 	UINT32 flags;
1098 	int type;
1099 
1100 	list += 18;
1101 
1102 	for(;;) {
1103 		flags = readi(list);
1104 
1105 		type = flags & 3;
1106 		if(!type)
1107 			break;
1108 
1109 		if(type == 2)
1110 			list += 12;
1111 		else
1112 			list += 20;
1113 	}
1114 	return list+2;
1115 }
1116 
draw_objects(struct mame_bitmap * bitmap,const struct rectangle * cliprect)1117 static void draw_objects(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
1118 {
1119 	if(quadpt != quaddb) {
1120 		logerror("VIDEO: sort&draw\n");
1121 		sort_quads();
1122 		draw_quads(bitmap, cliprect);
1123 	}
1124 
1125 	quadpt = quaddb;
1126 	pointpt = pointdb;
1127 }
1128 
draw_direct(UINT16 * list,struct mame_bitmap * bitmap,const struct rectangle * cliprect)1129 static UINT16 *draw_direct(UINT16 *list, struct mame_bitmap *bitmap, const struct rectangle *cliprect)
1130 {
1131 	UINT16 *res;
1132 
1133 	logerror("VIDEO:   draw direct %x\n", readi(list));
1134 
1135 	draw_objects(bitmap, cliprect);
1136 	res = push_direct(list);
1137 	unsort_quads();
1138 	draw_quads(bitmap, cliprect);
1139 
1140 	quadpt = quaddb;
1141 	pointpt = pointdb;
1142 	return res;
1143 }
1144 
get_list(void)1145 static UINT16 *get_list(void)
1146 {
1147 	if(!(listctl[0] & 4))
1148 		listctl[0] = (listctl[0] & ~0x40) | (listctl[0] & 8 ? 0x40 : 0);
1149 	return listctl[0] & 0x40 ? model1_display_list1 : model1_display_list0;
1150 }
1151 
get_list_number(void)1152 static int get_list_number(void)
1153 {
1154 	if(!(listctl[0] & 4))
1155 		listctl[0] = (listctl[0] & ~0x40) | (listctl[0] & 8 ? 0x40 : 0);
1156 	return listctl[0] & 0x40 ? 0 : 1;
1157 }
1158 
end_frame(void)1159 static void end_frame(void)
1160 {
1161 	if((listctl[0] & 4) && (cpu_getcurrentframe() & 1))
1162 		listctl[0] ^= 0x40;
1163 }
1164 
READ16_HANDLER(model1_listctl_r)1165 READ16_HANDLER( model1_listctl_r )
1166 {
1167 	if(!offset)
1168 		return listctl[0] | 0x30;
1169 	else
1170 		return listctl[1];
1171 }
1172 
WRITE16_HANDLER(model1_listctl_w)1173 WRITE16_HANDLER( model1_listctl_w )
1174 {
1175 	COMBINE_DATA(listctl+offset);
1176 	logerror("VIDEO: control=%08x\n", (listctl[1]<<16)|listctl[0]);
1177 }
1178 
tgp_render(struct mame_bitmap * bitmap,const struct rectangle * cliprect)1179 static void tgp_render(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
1180 {
1181 	render_done = 1;
1182 	if((listctl[1] & 0x1f) == 0x1f) {
1183 		UINT16 *list = get_list();
1184 		int zz = 0;
1185 		logerror("VIDEO: render list %d\n", get_list_number());
1186 
1187 		memset(trans_mat, 0, sizeof(trans_mat));
1188 		trans_mat[0] = 1.0;
1189 		trans_mat[4] = 1.0;
1190 		trans_mat[8] = 1.0;
1191 
1192 		for(;;) {
1193 			int type = (list[1]<<16)|list[0];
1194 			glist=list;
1195 			switch(type & 15) {
1196 			case 0:
1197 				list += 2;
1198 				break;
1199 			case 1:
1200 				// 1 = plane 1
1201 				// 2 = ??  draw object (413d3, 17c4c, e)
1202 				// 3 = plane 2
1203 				// 4 = ??  draw object (408a8, a479, 9)
1204 				// 5 = decor
1205 				// 6 = ??  draw object (57bd4, 387460, 2ad)
1206 
1207 				if(1 || zz >= 666)
1208 					push_object(readi(list+2), readi(list+4), readi(list+6));
1209 				list += 8;
1210 				break;
1211 			case 2:
1212 				list = draw_direct(list+2, bitmap, cliprect);
1213 				break;
1214 			case 3:
1215 				logerror("VIDEO:   viewport (%d, %d, %d, %d, %d, %d, %d)\n",
1216 						 readi(list+2),
1217 						 readi16(list+4), readi16(list+6), readi16(list+8),
1218 						 readi16(list+10), readi16(list+12), readi16(list+14));
1219 
1220 				draw_objects(bitmap, cliprect);
1221 
1222 				view.xc = readi16(list+4);
1223 				view.yc = 383-(readi16(list+6)-39);
1224 				view.x1 = readi16(list+8);
1225 				view.y2 = 383-(readi16(list+10)-39);
1226 				view.x2 = readi16(list+12);
1227 				view.y1 = 383-(readi16(list+14)-39);
1228 
1229 				recompute_frustrum();
1230 
1231 				list += 16;
1232 				break;
1233 			case 4: {
1234 				int adr = readi(list+2);
1235 				int len = readi(list+4)+1;
1236 				int i;
1237 				logerror("ZVIDEO:   color write, adr=%x, len=%x\n", adr, len);
1238 				for(i=0; i<len; i++)
1239 					tgp_ram[adr-0x40000+i] = list[6+2*i];
1240 				list += 6+len*2;
1241 				break;
1242 			}
1243 			case 5:
1244 				{
1245 					int adr = readi(list+2);
1246 					int len = readi(list+4);
1247 					int i;
1248 					for(i=0;i<len;++i)
1249 					{
1250 						poly_ram[adr-0x800000+i]=readi(list+2*i+6);
1251 					}
1252 					list+=6+len*2;
1253 				}
1254 				break;
1255 			case 6: {
1256 				int adr = readi(list+2);
1257 				int len = readi(list+4);
1258 				int i;
1259 				logerror("VIDEO:   upload data, adr=%x, len=%x\n", adr, len);
1260 				for(i=0;i<len;++i)
1261 				{
1262 					int v=readi(list+6+i*2);
1263 					lightparams[i+adr].d=((float) (v&0xff))/255.0;
1264 					lightparams[i+adr].a=((float) ((v>>8)&0xff))/255.0;
1265 					lightparams[i+adr].s=((float) ((v>>16)&0xff))/255.0;
1266 					lightparams[i+adr].p=(v>>24)&0xff;
1267 				}
1268 				list += 6+len*2;
1269 				break;
1270 			}
1271 			case 7:
1272 				logerror("VIDEO:   code 7 (%d)\n", readi(list+2));
1273 				zz++;
1274 				list += 4;
1275 				break;
1276 			case 8:
1277 				logerror("VIDEO:   select mode %08x\n", readi(list+2));
1278 				list += 4;
1279 				break;
1280 			case 9:
1281 				logerror("VIDEO:   zoom (%f, %f)\n", readf(list+2), readf(list+4));
1282 				view.zoomx = readf(list+2)*4;
1283 				view.zoomy = readf(list+4)*4;
1284 
1285 				recompute_frustrum();
1286 
1287 				list += 6;
1288 				break;
1289 			case 0xa:
1290 				logerror("VIDEO:   light vector (%f, %f, %f)\n", readf(list+2), readf(list+4), readf(list+6));
1291 				view.light.x = readf(list+2);
1292 				view.light.y = readf(list+4);
1293 				view.light.z = readf(list+6);
1294 				normalize_vector(&view.light);
1295 				list += 8;
1296 				break;
1297 			case 0xb: {
1298 				int i;
1299 				logerror("VIDEO:   matrix (%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f)\n",
1300 						 readf(list+2), readf(list+4), readf(list+6),
1301 						 readf(list+8), readf(list+10), readf(list+12),
1302 						 readf(list+14), readf(list+16), readf(list+18),
1303 						 readf(list+20), readf(list+22), readf(list+24));
1304 				for(i=0; i<12; i++)
1305 					trans_mat[i] = readf(list+2+2*i);
1306 				list += 26;
1307 				break;
1308 			}
1309 			case 0xc:
1310 				logerror("VIDEO:   trans (%f, %f)\n", readf(list+2), readf(list+4));
1311 				view.transx = readf(list+2);
1312 				view.transy = readf(list+4);
1313 
1314 				recompute_frustrum();
1315 
1316 				list += 6;
1317 				break;
1318 			case 0xf:
1319 			case -1:
1320 				goto end;
1321 			default:
1322 				logerror("VIDEO:   unknown type %d\n", type);
1323 				goto end;
1324 			}
1325 		}
1326 	end:
1327 		draw_objects(bitmap, cliprect);
1328 	}
1329 }
1330 
tgp_scan(void)1331 static void tgp_scan(void)
1332 {
1333 #if 0
1334 	if (code_pressed_memory(KEYCODE_F))
1335         {
1336 			FILE *fp;
1337 			fp=fopen("tgp-ram.bin", "w+b");
1338 			if (fp)
1339                 {
1340 					fwrite(tgp_ram, (0x100000-0x40000)*2, 1, fp);
1341 					fclose(fp);
1342                 }
1343 			exit(0);
1344         }
1345 #endif
1346 	if(!render_done && (listctl[1] & 0x1f) == 0x1f) {
1347 		UINT16 *list = get_list();
1348 		// Skip everything but the data uploads
1349 		logerror("VIDEO: scan list %d\n", get_list_number());
1350 		for(;;) {
1351 			int type = (list[1]<<16)|list[0];
1352 			switch(type) {
1353 			case 0:
1354 				list += 2;
1355 				break;
1356 			case 1:
1357 				list += 8;
1358 				break;
1359 			case 2:
1360 				list = skip_direct(list+2);
1361 				break;
1362 			case 3:
1363 				list += 16;
1364 				break;
1365 			case 4: {
1366 				int adr = readi(list+2);
1367 				int len = readi(list+4)+1;
1368 				int i;
1369 				logerror("ZVIDEO:   scan color write, adr=%x, len=%x\n", adr, len);
1370 				for(i=0; i<len; i++)
1371 					tgp_ram[adr-0x40000+i] = list[6+2*i];
1372 				list += 6+len*2;
1373 				break;
1374 			}
1375 			case 5:
1376 				{
1377 					int adr = readi(list+2);
1378 					int len = readi(list+4);
1379 					int i;
1380 					for(i=0;i<len;++i)
1381 					{
1382 						poly_ram[adr-0x800000+i]=readi(list+2*i+6);
1383 					}
1384 					list+=6+len*2;
1385 				}
1386 				break;
1387 			case 6: {
1388 				int adr = readi(list+2);
1389 				int len = readi(list+4);
1390 				int i;
1391 				//logerror("VIDEO:   upload data, adr=%x, len=%x\n", adr, len);
1392 				for(i=0;i<len;++i)
1393 				{
1394 					int v=readi(list+6+i*2);
1395 					lightparams[i+adr].d=((float) (v&0xff))/255.0;
1396 					lightparams[i+adr].a=((float) ((v>>8)&0xff))/255.0;
1397 					lightparams[i+adr].s=((float) ((v>>16)&0xff))/255.0;
1398 					lightparams[i+adr].p=(v>>24)&0xff;
1399 					//logerror("         %02X\n",v);
1400 				}
1401 				list += 6+len*2;
1402 				break;
1403 			}
1404 			case 7:
1405 				list += 4;
1406 				break;
1407 			case 8:
1408 				list += 4;
1409 				break;
1410 			case 9:
1411 				list += 6;
1412 				break;
1413 			case 0xa:
1414 				list += 8;
1415 				break;
1416 			case 0xb:
1417 				list += 26;
1418 				break;
1419 			case 0xc:
1420 				list += 6;
1421 				break;
1422 			case 0xf:
1423 			case -1:
1424 				goto end;
1425 			default:
1426 				logerror("VIDEO:   unknown type %d\n", type);
1427 				goto end;
1428 			}
1429 		}
1430 	end:
1431 		;
1432 	}
1433 	render_done = 0;
1434 }
1435 
VIDEO_START(model1)1436 VIDEO_START(model1)
1437 {
1438 	vxx=vyy=vzz=0;
1439 	ayy = 0;
1440 
1441 	if(sys24_tile_vh_start(0x3fff))
1442 		return 1;
1443 
1444 	poly_rom = (UINT32 *)memory_region(REGION_USER1);
1445 	poly_ram = auto_malloc(0x400000*4);
1446 	tgp_ram = auto_malloc((0x100000-0x40000)*2);
1447 	pointdb = auto_malloc(1000000*2*sizeof(struct point));
1448 	quaddb  = auto_malloc(1000000*sizeof(struct quad));
1449 	quadind = auto_malloc(1000000*sizeof(struct quad *));
1450 
1451 	if(!tgp_ram || !pointdb || !quaddb || !quadind)
1452 		return 1;
1453 
1454 	pointpt = pointdb;
1455 	quadpt = quaddb;
1456 	listctl[0] = listctl[1] = 0;
1457 
1458 	state_save_register_UINT16("video", 0, "colors",  tgp_ram, 0x100000-0x40000);
1459 	state_save_register_UINT32("video", 0, "polys",  poly_ram, 0x40000);
1460 	state_save_register_UINT16("video", 0, "listctl", listctl, 2);
1461 	return 0;
1462 }
1463 
VIDEO_UPDATE(model1)1464 VIDEO_UPDATE(model1)
1465 {
1466 	sys24_tile_update();
1467 #if 0
1468 	{
1469 		int mod = 0;
1470 		double delta;
1471 		delta = 1;
1472 
1473 		if(code_pressed(KEYCODE_F)) {
1474 			mod = 1;
1475 			vxx -= delta;
1476 		}
1477 		if(code_pressed(KEYCODE_G)) {
1478 			mod = 1;
1479 			vxx += delta;
1480 		}
1481 		if(code_pressed(KEYCODE_H)) {
1482 			mod = 1;
1483 			vyy -= delta;
1484 		}
1485 		if(code_pressed(KEYCODE_J)) {
1486 			mod = 1;
1487 			vyy += delta;
1488 		}
1489 		if(code_pressed(KEYCODE_K)) {
1490 			mod = 1;
1491 			vzz -= delta;
1492 		}
1493 		if(code_pressed(KEYCODE_L)) {
1494 			mod = 1;
1495 			vzz += delta;
1496 		}
1497 		if(code_pressed(KEYCODE_U)) {
1498 			mod = 1;
1499 			ayy -= 0.05;
1500 		}
1501 		if(code_pressed(KEYCODE_I)) {
1502 			mod = 1;
1503 			ayy += 0.05;
1504 		}
1505 		if(mod)
1506 			usrintf_showmessage("%g,%g,%g:%g", vxx, vyy, vzz, ayy);
1507 	}
1508 #endif
1509 
1510 	ayyc = cos(ayy);
1511 	ayys = sin(ayy);
1512 
1513 	fillbitmap(priority_bitmap, 0, 0);
1514 	fillbitmap(bitmap, Machine->pens[0], &Machine->visible_area);
1515 
1516 	sys24_tile_draw(bitmap, cliprect, 7, 0, 0);
1517 	sys24_tile_draw(bitmap, cliprect, 6, 0, 0);
1518 	sys24_tile_draw(bitmap, cliprect, 5, 0, 0);
1519 	sys24_tile_draw(bitmap, cliprect, 4, 0, 0);
1520 
1521 	tgp_render(bitmap, cliprect);
1522 
1523 	sys24_tile_draw(bitmap, cliprect, 3, 0, 0);
1524 	sys24_tile_draw(bitmap, cliprect, 2, 0, 0);
1525 	sys24_tile_draw(bitmap, cliprect, 1, 0, 0);
1526 	sys24_tile_draw(bitmap, cliprect, 0, 0, 0);
1527 }
1528 
VIDEO_EOF(model1)1529 VIDEO_EOF(model1)
1530 {
1531 	tgp_scan();
1532 	end_frame();
1533 	logerror("TGP: vsync\n");
1534 }
1535