1
88 #include "emu.h"
89 #include "video/segaic24.h"
90 #include "video/poly.h"
91 #include "includes/model2.h"
92
93 #define DEBUG 0
94
95
96 #define pz p[0]
97 #define pu p[1]
98 #define pv p[2]
99
100
101
106
107 struct plane
108 {
109 poly_vertex normal;
110 float distance;
111 };
112
113 struct texture_parameter
114 {
115 float diffuse;
116 float ambient;
117 UINT32 specular_control;
118 float specular_scale;
119 };
120
121 struct triangle
122 {
123 void * next;
124 poly_vertex v[3];
125 UINT16 z;
126 UINT16 texheader[4];
127 UINT8 luma;
128 INT16 viewport[4];
129 INT16 center[2];
130 };
131
132 struct quad_m2
133 {
134 poly_vertex v[4];
135 UINT16 z;
136 UINT16 texheader[4];
137 UINT8 luma;
138 };
139
140 struct poly_extra_data
141 {
142 model2_state * state;
143 UINT32 lumabase;
144 UINT32 colorbase;
145 UINT32 * texsheet;
146 UINT32 texwidth;
147 UINT32 texheight;
148 UINT32 texx, texy;
149 UINT8 texmirrorx;
150 UINT8 texmirrory;
151 };
152
153
154
159
160 INLINE void transform_point( poly_vertex *point, float *matrix )
161 {
162 float tx = (point->x * matrix[0]) + (point->y * matrix[3]) + (point->pz * matrix[6]) + (matrix[9]);
163 float ty = (point->x * matrix[1]) + (point->y * matrix[4]) + (point->pz * matrix[7]) + (matrix[10]);
164 float tz = (point->x * matrix[2]) + (point->y * matrix[5]) + (point->pz * matrix[8]) + (matrix[11]);
165
166 point->x = tx;
167 point->y = ty;
168 point->pz = tz;
169 }
170
171 INLINE void transform_vector( poly_vertex *vector, float *matrix )
172 {
173 float tx = (vector->x * matrix[0]) + (vector->y * matrix[3]) + (vector->pz * matrix[6]);
174 float ty = (vector->x * matrix[1]) + (vector->y * matrix[4]) + (vector->pz * matrix[7]);
175 float tz = (vector->x * matrix[2]) + (vector->y * matrix[5]) + (vector->pz * matrix[8]);
176
177 vector->x = tx;
178 vector->y = ty;
179 vector->pz = tz;
180 }
181
182 INLINE void normalize_vector( poly_vertex *vector )
183 {
184 float n = sqrt( (vector->x * vector->x) + (vector->y * vector->y) + (vector->pz * vector->pz) );
185
186 if ( n )
187 {
188 float oon = 1.0f / n;
189 vector->x *= oon;
190 vector->y *= oon;
191 vector->pz *= oon;
192 }
193 }
194
195 INLINE float dot_product( poly_vertex *v1, poly_vertex *v2 )
196 {
197 return (v1->x * v2->x) + (v1->y * v2->y) + (v1->pz * v2->pz);
198 }
199
200 INLINE void vector_cross3( poly_vertex *dst, poly_vertex *v0, poly_vertex *v1, poly_vertex *v2 )
201 {
202 poly_vertex p1, p2;
203
204 p1.x = v1->x - v0->x; p1.y = v1->y - v0->y; p1.pz = v1->pz - v0->pz;
205 p2.x = v2->x - v0->x; p2.y = v2->y - v0->y; p2.pz = v2->pz - v0->pz;
206
207 dst->x = (p1.y * p2.pz) - (p1.pz * p2.y);
208 dst->y = (p1.pz * p2.x) - (p1.x * p2.pz);
209 dst->pz = (p1.x * p2.y) - (p1.y * p2.x);
210 }
211
212
213 static UINT16 float_to_zval( float floatval )
214 {
215 INT32 fpint = f2u(floatval);
216 INT32 exponent = ((fpint >> 23) & 0xff) - 127;
217 UINT32 mantissa = fpint & 0x7fffff;
218
219
220 mantissa += 0x400;
221 if (mantissa > 0x7fffff) { exponent++; mantissa = (mantissa & 0x7fffff) >> 1; }
222 mantissa >>= 11;
223
224
225 if (fpint < 0)
226 return 0x0000;
227
228
229
230 if ( exponent < -12 )
231 return 0x0000;
232
233
234 else if ( exponent < 0 )
235 return (mantissa | 0x1000) >> -exponent;
236
237
238 else if ( exponent < 15 )
239 return (( exponent + 1 ) << 12) | mantissa;
240
241
242 return 0xffff;
243 }
244
245 static INT32 clip_polygon(poly_vertex *v, INT32 num_vertices, plane *cp, poly_vertex *vout)
246 {
247 poly_vertex *cur, *out;
248 float curdot, nextdot, scale;
249 INT32 i, curin, nextin, nextvert, outcount;
250
251 outcount = 0;
252
253 cur = v;
254 out = vout;
255
256 curdot = dot_product( cur, &cp->normal );
257 curin = (curdot >= cp->distance) ? 1 : 0;
258
259 for( i = 0; i < num_vertices; i++ )
260 {
261 nextvert = (i + 1) % num_vertices;
262
263
264 if ( curin ) memcpy( &out[outcount++], cur, sizeof( poly_vertex ) );
265
266 nextdot = dot_product( &v[nextvert], &cp->normal );
267 nextin = (nextdot >= cp->distance) ? 1 : 0;
268
269
270 if ( curin != nextin )
271 {
272 scale = (cp->distance - curdot) / (nextdot - curdot);
273
274 out[outcount].x = cur->x + ((v[nextvert].x - cur->x) * scale);
275 out[outcount].y = cur->y + ((v[nextvert].y - cur->y) * scale);
276 out[outcount].pz = cur->pz + ((v[nextvert].pz - cur->pz) * scale);
277 out[outcount].pu = (UINT16)((float)cur->pu + (((float)v[nextvert].pu - (float)cur->pu) * scale));
278 out[outcount].pv = (UINT16)((float)cur->pv + (((float)v[nextvert].pv - (float)cur->pv) * scale));
279 outcount++;
280 }
281
282 curdot = nextdot;
283 curin = nextin;
284 cur++;
285 }
286
287 return outcount;
288 }
289
290
291
292
297
298 #define MAX_TRIANGLES 32768
299
300 struct raster_state
301 {
302 UINT32 mode;
303 UINT16 * texture_rom;
304 INT16 viewport[4];
305 INT16 center[4][2];
306 UINT16 center_sel;
307 UINT32 reverse;
308 float z_adjust;
309 float triangle_z;
310 UINT8 master_z_clip;
311 UINT32 cur_command;
312 UINT32 command_buffer[32];
313 UINT32 command_index;
314 triangle tri_list[MAX_TRIANGLES];
315 UINT32 tri_list_index;
316 triangle * tri_sorted_list[0x10000];
317 UINT16 min_z;
318 UINT16 max_z;
319 UINT16 texture_ram[0x10000];
320 UINT8 log_ram[0x40000];
321 };
322
323
324
329
330 static void model2_3d_init( running_machine &machine, UINT16 *texture_rom )
331 {
332 model2_state *state = machine.driver_data<model2_state>();
333
334 state->m_raster = auto_alloc_clear( machine, raster_state );
335
336 state->m_raster->texture_rom = texture_rom;
337 }
338
339
344
345 void model2_3d_set_zclip( running_machine &machine, UINT8 clip )
346 {
347 model2_state *state = machine.driver_data<model2_state>();
348 state->m_raster->master_z_clip = clip;
349 }
350
351
356
357 static void model2_3d_process_quad( raster_state *raster, UINT32 attr )
358 {
359 quad_m2 object;
360 UINT16 *th, *tp;
361 INT32 tho;
362 UINT32 cull, i;
363 float zvalue;
364 float min_z, max_z;
365
366
367 object.v[1].x = u2f( raster->command_buffer[2] << 8 );
368 object.v[1].y = u2f( raster->command_buffer[3] << 8 );
369 object.v[1].pz = u2f( raster->command_buffer[4] << 8 );
370
371
372 object.v[0].x = u2f( raster->command_buffer[5] << 8 );
373 object.v[0].y = u2f( raster->command_buffer[6] << 8 );
374 object.v[0].pz = u2f( raster->command_buffer[7] << 8 );
375
376
377 object.v[2].x = u2f( raster->command_buffer[11] << 8 );
378 object.v[2].y = u2f( raster->command_buffer[12] << 8 );
379 object.v[2].pz = u2f( raster->command_buffer[13] << 8 );
380
381
382 object.v[3].x = u2f( raster->command_buffer[14] << 8 );
383 object.v[3].y = u2f( raster->command_buffer[15] << 8 );
384 object.v[3].pz = u2f( raster->command_buffer[16] << 8 );
385
386
387 min_z = object.v[0].pz;
388 if ( object.v[1].pz < min_z ) min_z = object.v[1].pz;
389 if ( object.v[2].pz < min_z ) min_z = object.v[2].pz;
390 if ( object.v[3].pz < min_z ) min_z = object.v[3].pz;
391
392 max_z = object.v[0].pz;
393 if ( object.v[1].pz > max_z ) max_z = object.v[1].pz;
394 if ( object.v[2].pz > max_z ) max_z = object.v[2].pz;
395 if ( object.v[3].pz > max_z ) max_z = object.v[3].pz;
396
397
398
399
400 if ( raster->command_buffer[0] & 0x800000 )
401 tp = &raster->texture_ram[raster->command_buffer[0] & 0xFFFF];
402 else
403 tp = &raster->texture_rom[raster->command_buffer[0] & 0x7FFFFF];
404
405 object.v[0].pv = *tp++;
406 object.v[0].pu = *tp++;
407 object.v[1].pv = *tp++;
408 object.v[1].pu = *tp++;
409 object.v[2].pv = *tp++;
410 object.v[2].pu = *tp++;
411 object.v[3].pv = *tp++;
412 object.v[3].pu = *tp++;
413
414
415 raster->command_buffer[0] += 8;
416
417
418 if ( raster->command_buffer[1] & 0x800000 )
419 th = &raster->texture_ram[raster->command_buffer[1] & 0xFFFF];
420 else
421 th = &raster->texture_rom[raster->command_buffer[1] & 0x7FFFFF];
422
423 object.texheader[0] = *th++;
424 object.texheader[1] = *th++;
425 object.texheader[2] = *th++;
426 object.texheader[3] = *th++;
427
428
429 tho = (attr >> 12) & 0x1F;
430
431
432 if ( tho & 0x10 )
433 tho |= -16;
434
435
436 raster->command_buffer[1] += tho * 4;
437
438
439 object.luma = (raster->command_buffer[9] >> 15) & 0xFF;
440
441
442 cull = 0;
443
444
445 if ( ((attr >> 17) & 1) == 0 )
446 {
447
448 if ( raster->command_buffer[9] & 0x00800000 )
449 cull = 1;
450 }
451
452
453 if ( ((attr >> 8) & 3) == 0 )
454 cull = 1;
455
456
457 if ( (INT32)(1.0/min_z) > raster->master_z_clip )
458 cull = 1;
459
460
461 if ( max_z < 0 )
462 cull = 1;
463
464
465 zvalue = raster->triangle_z;
466
467
468 if ( (attr >> 10) & 3 )
469 {
470 if ( (attr >> 10) & 1 )
471 {
472 zvalue = min_z;
473 }
474 else if ( (attr >> 10) & 2 )
475 {
476 zvalue = max_z;
477 }
478
479 raster->triangle_z = zvalue;
480 }
481
482 if ( cull == 0 )
483 {
484 INT32 clipped_verts;
485 poly_vertex verts[10];
486 plane clip_plane;
487
488 clip_plane.normal.x = 0;
489 clip_plane.normal.y = 0;
490 clip_plane.normal.pz = 1;
491 clip_plane.distance = 0;
492
493
494 clipped_verts = clip_polygon( object.v, 4, &clip_plane, verts);
495
496 if ( clipped_verts > 2 )
497 {
498 triangle *ztri;
499
500
501 object.z = float_to_zval( zvalue + raster->z_adjust );
502
503
504 ztri = raster->tri_sorted_list[object.z];
505
506 if ( ztri != NULL )
507 {
508 while( ztri->next != NULL )
509 ztri = (triangle *)ztri->next;
510 }
511
512
513 for( i = 2; i < clipped_verts; i++ )
514 {
515 triangle *tri;
516
517 tri = &raster->tri_list[raster->tri_list_index++];
518
519 if ( raster->tri_list_index >= MAX_TRIANGLES )
520 {
521 fatalerror( "SEGA 3D: Max triangle limit exceeded\n" );
522 }
523
524
525 tri->z = object.z;
526 tri->texheader[0] = object.texheader[0];
527 tri->texheader[1] = object.texheader[1];
528 tri->texheader[2] = object.texheader[2];
529 tri->texheader[3] = object.texheader[3];
530 tri->luma = object.luma;
531
532
533 tri->viewport[0] = raster->viewport[0];
534 tri->viewport[1] = raster->viewport[1];
535 tri->viewport[2] = raster->viewport[2];
536 tri->viewport[3] = raster->viewport[3];
537
538
539 tri->center[0] = raster->center[raster->center_sel][0];
540 tri->center[1] = raster->center[raster->center_sel][1];
541
542 memcpy( &tri->v[0], &verts[0], sizeof( poly_vertex ) );
543 memcpy( &tri->v[1], &verts[i-1], sizeof( poly_vertex ) );
544 memcpy( &tri->v[2], &verts[i], sizeof( poly_vertex ) );
545
546
547 tri->next = NULL;
548
549 if ( ztri == NULL )
550 {
551 raster->tri_sorted_list[object.z] = tri;
552 }
553 else
554 {
555 ztri->next = tri;
556 }
557
558 ztri = tri;
559 }
560
561
562 if ( object.z < raster->min_z ) raster->min_z = object.z;
563 if ( object.z > raster->max_z ) raster->max_z = object.z;
564 }
565 }
566
567
568 switch( ((attr >> 8) & 3) )
569 {
570 case 0:
571 case 2:
572 {
573
574 for( i = 0; i < 6; i++ )
575 raster->command_buffer[2+i] = raster->command_buffer[11+i];
576 }
577 break;
578
579 case 1:
580 {
581
582 for( i = 0; i < 3; i++ )
583 raster->command_buffer[5+i] = raster->command_buffer[11+i];
584 }
585 break;
586
587 case 3:
588 {
589
590 for( i = 0; i < 3; i++ )
591 raster->command_buffer[2+i] = raster->command_buffer[14+i];
592 }
593 break;
594 }
595 }
596
597 static void model2_3d_process_triangle( raster_state *raster, UINT32 attr )
598 {
599 triangle object;
600 UINT16 *th, *tp;
601 INT32 tho;
602 UINT32 cull, i;
603 float zvalue;
604 float min_z, max_z;
605
606
607 object.v[1].x = u2f( raster->command_buffer[2] << 8 );
608 object.v[1].y = u2f( raster->command_buffer[3] << 8 );
609 object.v[1].pz = u2f( raster->command_buffer[4] << 8 );
610
611
612 object.v[0].x = u2f( raster->command_buffer[5] << 8 );
613 object.v[0].y = u2f( raster->command_buffer[6] << 8 );
614 object.v[0].pz = u2f( raster->command_buffer[7] << 8 );
615
616
617 object.v[2].x = u2f( raster->command_buffer[11] << 8 );
618 object.v[2].y = u2f( raster->command_buffer[12] << 8 );
619 object.v[2].pz = u2f( raster->command_buffer[13] << 8 );
620
621
622 raster->command_buffer[14] = raster->command_buffer[11];
623 raster->command_buffer[15] = raster->command_buffer[12];
624 raster->command_buffer[16] = raster->command_buffer[13];
625
626
627 min_z = object.v[0].pz;
628 if ( object.v[1].pz < min_z ) min_z = object.v[1].pz;
629 if ( object.v[2].pz < min_z ) min_z = object.v[2].pz;
630
631 max_z = object.v[0].pz;
632 if ( object.v[1].pz > max_z ) max_z = object.v[1].pz;
633 if ( object.v[2].pz > max_z ) max_z = object.v[2].pz;
634
635
636
637
638 if ( raster->command_buffer[0] & 0x800000 )
639 tp = &raster->texture_ram[raster->command_buffer[0] & 0xFFFF];
640 else
641 tp = &raster->texture_rom[raster->command_buffer[0] & 0x7FFFFF];
642
643 object.v[0].pv = *tp++;
644 object.v[0].pu = *tp++;
645 object.v[1].pv = *tp++;
646 object.v[1].pu = *tp++;
647 object.v[2].pv = *tp++;
648 object.v[2].pu = *tp++;
649
650
651 raster->command_buffer[0] += 6;
652
653
654 if ( raster->command_buffer[1] & 0x800000 )
655 th = &raster->texture_ram[raster->command_buffer[1] & 0xFFFF];
656 else
657 th = &raster->texture_rom[raster->command_buffer[1] & 0x7FFFFF];
658
659 object.texheader[0] = *th++;
660 object.texheader[1] = *th++;
661 object.texheader[2] = *th++;
662 object.texheader[3] = *th++;
663
664
665 tho = (attr >> 12) & 0x1F;
666
667
668 if ( tho & 0x10 )
669 tho |= -16;
670
671
672 raster->command_buffer[1] += tho * 4;
673
674
675 object.luma = (raster->command_buffer[9] >> 15) & 0xFF;
676
677
678 cull = 0;
679
680
681 if ( ((attr >> 17) & 1) == 0 )
682 {
683
684 if ( raster->command_buffer[9] & 0x00800000 )
685 cull = 1;
686 }
687
688
689 if ( ((attr >> 8) & 3) == 0 )
690 cull = 1;
691
692
693 if ( (INT32)(1.0/min_z) > raster->master_z_clip )
694 cull = 1;
695
696
697 if ( max_z < 0 )
698 cull = 1;
699
700
701 zvalue = raster->triangle_z;
702
703
704 if ( (attr >> 10) & 3 )
705 {
706 if ( (attr >> 10) & 1 )
707 {
708 zvalue = min_z;
709 }
710 else if ( (attr >> 10) & 2 )
711 {
712 zvalue = max_z;
713 }
714
715 raster->triangle_z = zvalue;
716 }
717
718
719 if ( cull == 0 )
720 {
721 INT32 clipped_verts;
722 poly_vertex verts[10];
723 plane clip_plane;
724
725 clip_plane.normal.x = 0;
726 clip_plane.normal.y = 0;
727 clip_plane.normal.pz = 1;
728 clip_plane.distance = 0;
729
730
731 clipped_verts = clip_polygon( object.v, 3, &clip_plane, verts);
732
733 if ( clipped_verts > 2 )
734 {
735 triangle *ztri;
736
737
738 object.z = float_to_zval( zvalue + raster->z_adjust );
739
740
741 ztri = raster->tri_sorted_list[object.z];
742
743 if ( ztri != NULL )
744 {
745 while( ztri->next != NULL )
746 ztri = (triangle *)ztri->next;
747 }
748
749
750 for( i = 2; i < clipped_verts; i++ )
751 {
752 triangle *tri;
753
754 tri = &raster->tri_list[raster->tri_list_index++];
755
756 if ( raster->tri_list_index >= MAX_TRIANGLES )
757 {
758 fatalerror( "SEGA 3D: Max triangle limit exceeded\n" );
759 }
760
761
762 tri->z = object.z;
763 tri->texheader[0] = object.texheader[0];
764 tri->texheader[1] = object.texheader[1];
765 tri->texheader[2] = object.texheader[2];
766 tri->texheader[3] = object.texheader[3];
767 tri->luma = object.luma;
768
769
770 tri->viewport[0] = raster->viewport[0];
771 tri->viewport[1] = raster->viewport[1];
772 tri->viewport[2] = raster->viewport[2];
773 tri->viewport[3] = raster->viewport[3];
774
775
776 tri->center[0] = raster->center[raster->center_sel][0];
777 tri->center[1] = raster->center[raster->center_sel][1];
778
779 memcpy( &tri->v[0], &verts[0], sizeof( poly_vertex ) );
780 memcpy( &tri->v[1], &verts[i-1], sizeof( poly_vertex ) );
781 memcpy( &tri->v[2], &verts[i], sizeof( poly_vertex ) );
782
783
784 tri->next = NULL;
785
786 if ( ztri == NULL )
787 {
788 raster->tri_sorted_list[object.z] = tri;
789 }
790 else
791 {
792 ztri->next = tri;
793 }
794
795 ztri = tri;
796 }
797
798
799 if ( object.z < raster->min_z ) raster->min_z = object.z;
800 if ( object.z > raster->max_z ) raster->max_z = object.z;
801 }
802 }
803
804
805 switch( ((attr >> 8) & 3) )
806 {
807 case 0:
808 case 2:
809 {
810
811 for( i = 0; i < 6; i++ )
812 raster->command_buffer[2+i] = raster->command_buffer[11+i];
813 }
814 break;
815
816 case 1:
817 {
818
819 for( i = 0; i < 3; i++ )
820 raster->command_buffer[5+i] = raster->command_buffer[11+i];
821 }
822 break;
823
824 case 3:
825 {
826
827 for( i = 0; i < 3; i++ )
828 raster->command_buffer[2+i] = raster->command_buffer[14+i];
829 }
830 break;
831 }
832 }
833
834
835
836 INLINE UINT16 get_texel( UINT32 base_x, UINT32 base_y, int x, int y, UINT32 *sheet )
837 {
838 UINT32 baseoffs = ((base_y/2)*512)+(base_x/2);
839 UINT32 texeloffs = ((y/2)*512)+(x/2);
840 UINT32 offset = baseoffs + texeloffs;
841 UINT32 texel = sheet[offset>>1];
842
843 if ( offset & 1 )
844 texel >>= 16;
845
846 if ( (y & 1) == 0 )
847 texel >>= 8;
848
849 if ( (x & 1) == 0 )
850 texel >>= 4;
851
852 return (texel & 0x0f);
853 }
854
855
856 #define MODEL2_FUNC 0
857 #define MODEL2_FUNC_NAME model2_3d_render_0
858 #include "model2rd.c"
859 #undef MODEL2_FUNC
860 #undef MODEL2_FUNC_NAME
861
862
863 #define MODEL2_FUNC 1
864 #define MODEL2_FUNC_NAME model2_3d_render_1
865 #include "model2rd.c"
866 #undef MODEL2_FUNC
867 #undef MODEL2_FUNC_NAME
868
869
870 #define MODEL2_FUNC 2
871 #define MODEL2_FUNC_NAME model2_3d_render_2
872 #include "model2rd.c"
873 #undef MODEL2_FUNC
874 #undef MODEL2_FUNC_NAME
875
876
877 #define MODEL2_FUNC 3
878 #define MODEL2_FUNC_NAME model2_3d_render_3
879 #include "model2rd.c"
880 #undef MODEL2_FUNC
881 #undef MODEL2_FUNC_NAME
882
883
884 #define MODEL2_FUNC 4
885 #define MODEL2_FUNC_NAME model2_3d_render_4
886 #include "model2rd.c"
887 #undef MODEL2_FUNC
888 #undef MODEL2_FUNC_NAME
889
890
891 #define MODEL2_FUNC 5
892 #define MODEL2_FUNC_NAME model2_3d_render_5
893 #include "model2rd.c"
894 #undef MODEL2_FUNC
895 #undef MODEL2_FUNC_NAME
896
897
898 #define MODEL2_FUNC 6
899 #define MODEL2_FUNC_NAME model2_3d_render_6
900 #include "model2rd.c"
901 #undef MODEL2_FUNC
902 #undef MODEL2_FUNC_NAME
903
904
905 #define MODEL2_FUNC 7
906 #define MODEL2_FUNC_NAME model2_3d_render_7
907 #include "model2rd.c"
908 #undef MODEL2_FUNC
909 #undef MODEL2_FUNC_NAME
910
911
912
913 static const poly_draw_scanline_func render_funcs[8] =
914 {
915 model2_3d_render_0,
916 model2_3d_render_1,
917 model2_3d_render_2,
918 model2_3d_render_3,
919 model2_3d_render_4,
920 model2_3d_render_5,
921 model2_3d_render_6,
922 model2_3d_render_7
923 };
924
925 static void model2_3d_render( model2_state *state, bitmap_rgb32 &bitmap, triangle *tri, const rectangle &cliprect )
926 {
927 poly_manager *poly = state->m_poly;
928 poly_extra_data *extra = (poly_extra_data *)poly_get_extra_data(poly);
929 UINT8 renderer;
930
931
932 renderer = (tri->texheader[0] >> 13) & 7;
933
934
935 rectangle vp(tri->viewport[0] - 8, tri->viewport[2] - 8, (384-tri->viewport[3])+90, (384-tri->viewport[1])+90);
936 vp &= cliprect;
937
938 extra->state = state;
939 extra->lumabase = ((tri->texheader[1] & 0xFF) << 7) + ((tri->luma >> 5) ^ 0x7);
940 extra->colorbase = (tri->texheader[3] >> 6) & 0x3FF;
941
942 if (renderer & 2)
943 {
944 extra->texwidth = 32 << ((tri->texheader[0] >> 0) & 0x7);
945 extra->texheight = 32 << ((tri->texheader[0] >> 3) & 0x7);
946 extra->texx = 32 * ((tri->texheader[2] >> 0) & 0x1f);
947 extra->texy = 32 * (((tri->texheader[2] >> 6) & 0x1f) + ( tri->texheader[2] & 0x20 ));
948 extra->texmirrorx = (tri->texheader[0] >> 9) & 1;
949 extra->texmirrory = (tri->texheader[0] >> 8) & 1;
950 extra->texsheet = (tri->texheader[2] & 0x1000) ? state->m_textureram1 : state->m_textureram0;
951
952 tri->v[0].pz = 1.0f / (1.0f + tri->v[0].pz);
953 tri->v[0].pu = tri->v[0].pu * tri->v[0].pz * (1.0f / 8.0f);
954 tri->v[0].pv = tri->v[0].pv * tri->v[0].pz * (1.0f / 8.0f);
955 tri->v[1].pz = 1.0f / (1.0f + tri->v[1].pz);
956 tri->v[1].pu = tri->v[1].pu * tri->v[1].pz * (1.0f / 8.0f);
957 tri->v[1].pv = tri->v[1].pv * tri->v[1].pz * (1.0f / 8.0f);
958 tri->v[2].pz = 1.0f / (1.0f + tri->v[2].pz);
959 tri->v[2].pu = tri->v[2].pu * tri->v[2].pz * (1.0f / 8.0f);
960 tri->v[2].pv = tri->v[2].pv * tri->v[2].pz * (1.0f / 8.0f);
961
962 poly_render_triangle(poly, &bitmap, vp, render_funcs[renderer], 3, &tri->v[0], &tri->v[1], &tri->v[2]);
963 }
964 else
965 poly_render_triangle(poly, &bitmap, vp, render_funcs[renderer], 0, &tri->v[0], &tri->v[1], &tri->v[2]);
966 }
967
968
986
987
988 static void model2_3d_project( triangle *tri )
989 {
990 UINT16 i;
991
992 for( i = 0; i < 3; i++ )
993 {
994
995 tri->v[i].x = -8 + tri->center[0] + (tri->v[i].x / (1.0f+tri->v[i].pz));
996 tri->v[i].y = ((384 - tri->center[1])+90) - (tri->v[i].y / (1.0f+tri->v[i].pz));
997 }
998 }
999
1000
1001 static void model2_3d_frame_start( model2_state *state )
1002 {
1003 raster_state *raster = state->m_raster;
1004
1005
1006 raster->tri_list_index = 0;
1007
1008
1009 memset( raster->tri_sorted_list, 0, 0x10000 * sizeof( triangle * ) );
1010
1011
1012 raster->min_z = 0xFFFF;
1013 raster->max_z = 0;
1014 }
1015
1016 static void model2_3d_frame_end( model2_state *state, bitmap_rgb32 &bitmap, const rectangle &cliprect )
1017 {
1018 raster_state *raster = state->m_raster;
1019 INT32 z;
1020
1021
1022 if ( raster->tri_list_index == 0 )
1023 return;
1024
1025 #if DEBUG
1026 if (machine.input().code_pressed(KEYCODE_Q))
1027 {
1028 UINT32 i;
1029
1030 FILE *f = fopen( "triangles.txt", "w" );
1031
1032 if ( f )
1033 {
1034 for( i = 0; i < raster->tri_list_index; i++ )
1035 {
1036
1037 fprintf( f, "index: %d\n", i );
1038 fprintf( f, "v0.x = %f, v0.y = %f, v0.z = %f\n", raster->tri_list[i].v[0].x, raster->tri_list[i].v[0].y, raster->tri_list[i].v[0].pz );
1039 fprintf( f, "v1.x = %f, v1.y = %f, v1.z = %f\n", raster->tri_list[i].v[1].x, raster->tri_list[i].v[1].y, raster->tri_list[i].v[1].pz );
1040 fprintf( f, "v2.x = %f, v2.y = %f, v2.z = %f\n", raster->tri_list[i].v[2].x, raster->tri_list[i].v[2].y, raster->tri_list[i].v[2].pz );
1041
1042 fprintf( f, "tri z: %04x\n", raster->tri_list[i].pz );
1043 fprintf( f, "texheader - 0: %04x\n", raster->tri_list[i].texheader[0] );
1044 fprintf( f, "texheader - 1: %04x\n", raster->tri_list[i].texheader[1] );
1045 fprintf( f, "texheader - 2: %04x\n", raster->tri_list[i].texheader[2] );
1046 fprintf( f, "texheader - 3: %04x\n", raster->tri_list[i].texheader[3] );
1047 fprintf( f, "luma: %02x\n", raster->tri_list[i].luma );
1048 fprintf( f, "vp.sx: %04x\n", raster->tri_list[i].viewport[0] );
1049 fprintf( f, "vp.sy: %04x\n", raster->tri_list[i].viewport[1] );
1050 fprintf( f, "vp.ex: %04x\n", raster->tri_list[i].viewport[2] );
1051 fprintf( f, "vp.ey: %04x\n", raster->tri_list[i].viewport[3] );
1052 fprintf( f, "vp.swx: %04x\n", raster->tri_list[i].center[0] );
1053 fprintf( f, "vp.swy: %04x\n", raster->tri_list[i].center[1] );
1054 fprintf( f, "\n---\n\n" );
1055 }
1056
1057 fprintf( f, "min_z = %04x, max_z = %04x\n", raster->min_z, raster->max_z );
1058
1059 fclose( f );
1060 }
1061 }
1062 #endif
1063
1064
1065 for( z = raster->max_z; z >= raster->min_z; z-- )
1066 {
1067
1068 if ( raster->tri_sorted_list[z] != NULL )
1069 {
1070
1071 triangle *tri = raster->tri_sorted_list[z];
1072
1073
1074 while( tri != NULL )
1075 {
1076
1077 model2_3d_project( tri );
1078 model2_3d_render( state, bitmap, tri, cliprect );
1079
1080 tri = (triangle *)tri->next;
1081 }
1082 }
1083 }
1084 poly_wait(state->m_poly, "End of frame");
1085 }
1086
1087
1088 static void model2_3d_push( raster_state *raster, UINT32 input )
1089 {
1090
1091 if ( raster->cur_command != 0 )
1092 {
1093 raster->command_buffer[raster->command_index++] = input;
1094
1095 switch( raster->cur_command )
1096 {
1097 case 0x00:
1098 break;
1099
1100 case 0x01:
1101 {
1102 UINT32 attr;
1103
1104
1105 if ( raster->command_index < 9 )
1106 return;
1107
1108
1109 attr = raster->command_buffer[8];
1110
1111
1112 if ( (attr & 3) == 0 )
1113 {
1114 raster->cur_command = 0;
1115 return;
1116 }
1117
1118
1119 if ( attr & 1 )
1120 {
1121
1122 if ( raster->command_index < 17 )
1123 return;
1124
1125
1126 model2_3d_process_quad( raster, attr );
1127
1128
1129 raster->command_index = 8;
1130 }
1131 else
1132 {
1133
1134 if ( raster->command_index < 14 )
1135 return;
1136
1137
1138 model2_3d_process_triangle( raster, attr );
1139
1140
1141 raster->command_index = 8;
1142 }
1143 }
1144 break;
1145
1146 case 0x03:
1147 {
1148 UINT32 i;
1149
1150
1151 if ( raster->command_index < 6 )
1152 return;
1153
1154
1155
1156
1157 raster->viewport[0] = (raster->command_buffer[0] >> 12) & 0xFFF;
1158
1159 if ( raster->viewport[0] & 0x800 )
1160 raster->viewport[0] = -( 0x800 - (raster->viewport[0] & 0x7FF) );
1161
1162
1163 raster->viewport[1] = raster->command_buffer[0] & 0xFFF;
1164
1165 if ( raster->viewport[1] & 0x800 )
1166 raster->viewport[1] = -( 0x800 - (raster->viewport[1] & 0x7FF) );
1167
1168
1169 raster->viewport[2] = (raster->command_buffer[1] >> 12) & 0xFFF;
1170
1171 if ( raster->viewport[2] & 0x800 )
1172 raster->viewport[2] = -( 0x800 - (raster->viewport[2] & 0x7FF) );
1173
1174
1175 raster->viewport[3] = raster->command_buffer[1] & 0xFFF;
1176
1177 if ( raster->viewport[3] & 0x800 )
1178 raster->viewport[3] = -( 0x800 - (raster->viewport[3] & 0x7FF) );
1179
1180
1181 for( i = 0; i < 4; i++ )
1182 {
1183
1184 raster->center[i][0] = (raster->command_buffer[2+i] >> 12) & 0xFFF;
1185
1186 if ( raster->center[i][0] & 0x800 )
1187 raster->center[i][0] = -( 0x800 - (raster->center[i][0] & 0x7FF) );
1188
1189
1190 raster->center[i][1] = raster->command_buffer[2+i] & 0xFFF;
1191
1192 if ( raster->center[i][1] & 0x800 )
1193 raster->center[i][1] = -( 0x800 - (raster->center[i][1] & 0x7FF) );
1194 }
1195
1196
1197 raster->cur_command = 0;
1198 }
1199 break;
1200
1201 case 0x04:
1202 {
1203
1204 if ( raster->command_index < 2 )
1205 return;
1206
1207
1208 if ( raster->command_buffer[1] > 0 )
1209 {
1210
1211 if ( raster->command_index >= 3 )
1212 {
1213
1214 UINT32 address = raster->command_buffer[0];
1215
1216
1217 if ( address & 0x800000 )
1218 raster->texture_ram[address&0xFFFF] = raster->command_buffer[2];
1219 else
1220 raster->log_ram[address&0xFFFF] = raster->command_buffer[2];
1221
1222
1223 raster->command_buffer[0]++;
1224 raster->command_buffer[1]--;
1225
1226
1227 raster->command_index--;
1228 }
1229 }
1230
1231
1232 if ( raster->command_buffer[1] == 0 )
1233 raster->cur_command = 0;
1234 }
1235 break;
1236
1237 case 0x08:
1238 {
1239
1240 raster->z_adjust = u2f( raster->command_buffer[0] << 8 );
1241
1242
1243 raster->cur_command = 0;
1244 }
1245 break;
1246
1247 default:
1248 {
1249 fatalerror( "SEGA 3D: Unknown rasterizer command %08x\n", raster->cur_command );
1250 }
1251 break;
1252 }
1253 }
1254 else
1255 {
1256
1257 raster->cur_command = input & 0x0F;
1258 raster->command_index = 0;
1259
1260
1261 if ( raster->cur_command == 1 )
1262 {
1263
1264 raster->reverse = (input >> 4) & 1;
1265
1266
1267 raster->center_sel = ( input >> 6 ) & 3;
1268
1269
1270 raster->triangle_z = 0;
1271 }
1272 }
1273 }
1274
1275
1276
1277
1278
1279
1284
1285 struct geo_state
1286 {
1287 raster_state * raster;
1288 UINT32 mode;
1289 UINT32 * polygon_rom;
1290 float matrix[12];
1291 poly_vertex focus;
1292 poly_vertex light;
1293 float lod;
1294 float coef_table[32];
1295 texture_parameter texture_parameters[32];
1296 UINT32 polygon_ram0[0x8000];
1297 UINT32 polygon_ram1[0x8000];
1298 };
1299
1300
1301
1306
1307 static void geo_init( running_machine &machine, UINT32 *polygon_rom )
1308 {
1309 model2_state *state = machine.driver_data<model2_state>();
1310 state->m_geo = auto_alloc_clear(machine, geo_state);
1311
1312 state->m_geo->raster = state->m_raster;
1313 state->m_geo->polygon_rom = polygon_rom;
1314 }
1315
1316
1321
1322
1323 static void geo_parse_np_ns( geo_state *geo, UINT32 *input, UINT32 count )
1324 {
1325 raster_state *raster = geo->raster;
1326 poly_vertex point, normal;
1327 UINT32 attr, i;
1328
1329
1330 point.x = u2f( *input++ );
1331 point.y = u2f( *input++ );
1332 point.pz = u2f( *input++ );
1333
1334
1335 transform_point( &point, geo->matrix );
1336
1337
1338 point.x *= geo->focus.x;
1339 point.y *= geo->focus.y;
1340
1341
1342 model2_3d_push( raster, f2u(point.x) >> 8 );
1343 model2_3d_push( raster, f2u(point.y) >> 8 );
1344 model2_3d_push( raster, f2u(point.pz) >> 8 );
1345
1346
1347 point.x = u2f( *input++ );
1348 point.y = u2f( *input++ );
1349 point.pz = u2f( *input++ );
1350
1351
1352 transform_point( &point, geo->matrix );
1353
1354
1355 point.x *= geo->focus.x;
1356 point.y *= geo->focus.y;
1357
1358
1359 model2_3d_push( raster, f2u(point.x) >> 8 );
1360 model2_3d_push( raster, f2u(point.y) >> 8 );
1361 model2_3d_push( raster, f2u(point.pz) >> 8 );
1362
1363
1364 for( i = 0; i < count; i++ )
1365 {
1366
1367 attr = *input++;
1368
1369
1370 model2_3d_push( raster, attr & 0x0003FFFF );
1371
1372
1373 normal.x = u2f(*input++);
1374 normal.y = u2f(*input++);
1375 normal.pz = u2f(*input++);
1376
1377
1378 transform_vector( &normal, geo->matrix );
1379
1380 if ( (attr & 3) != 0 )
1381 {
1382 float dotl, dotp, luminance, distance;
1383 float coef, face;
1384 INT32 luma;
1385 texture_parameter * texparam;
1386
1387
1388 point.x = u2f( *input++ );
1389 point.y = u2f( *input++ );
1390 point.pz = u2f( *input++ );
1391
1392
1393 transform_point( &point, geo->matrix );
1394
1395
1396 dotl = dot_product( &normal, &geo->light );
1397
1398
1399 dotp = dot_product( &normal, &point );
1400
1401
1402 point.x *= geo->focus.x;
1403 point.y *= geo->focus.y;
1404
1405
1406 face = 0x100;
1407 if ( dotp >= 0 ) face = 0;
1408
1409
1410 texparam = &geo->texture_parameters[(attr>>18) & 0x1f];
1411
1412
1413 if ( (dotl * dotp) < 0 ) luminance = 0;
1414 else luminance = fabs( dotl );
1415
1416 luminance = (luminance * texparam->diffuse) + texparam->ambient;
1417 luma = (INT32)luminance;
1418
1419 if ( luma > 255 ) luma = 255;
1420 if ( luma < 0 ) luma = 0;
1421
1422
1423 luma += face;
1424
1425
1426 coef = geo->coef_table[attr>>27];
1427
1428
1429 distance = coef * fabs( dotp ) * geo->lod;
1430
1431
1432 model2_3d_push( raster, luma << 15 );
1433 model2_3d_push( raster, f2u(distance) >> 8 );
1434 model2_3d_push( raster, f2u(point.x) >> 8 );
1435 model2_3d_push( raster, f2u(point.y) >> 8 );
1436 model2_3d_push( raster, f2u(point.pz) >> 8 );
1437
1438
1439 if ( attr & 1 )
1440 {
1441
1442 point.x = u2f( *input++ );
1443 point.y = u2f( *input++ );
1444 point.pz = u2f( *input++ );
1445
1446
1447 transform_point( &point, geo->matrix );
1448
1449
1450 point.x *= geo->focus.x;
1451 point.y *= geo->focus.y;
1452
1453
1454 model2_3d_push( raster, f2u(point.x) >> 8 );
1455 model2_3d_push( raster, f2u(point.y) >> 8 );
1456 model2_3d_push( raster, f2u(point.pz) >> 8 );
1457 }
1458 else
1459 {
1460
1461 input += 3;
1462 }
1463 }
1464 else
1465 {
1466 break;
1467 }
1468 }
1469
1470
1471 model2_3d_push( raster, 0 );
1472 }
1473
1474
1475 static void geo_parse_np_s( geo_state *geo, UINT32 *input, UINT32 count )
1476 {
1477 raster_state *raster = geo->raster;
1478 poly_vertex point, normal;
1479 UINT32 attr, i;
1480
1481
1482 point.x = u2f( *input++ );
1483 point.y = u2f( *input++ );
1484 point.pz = u2f( *input++ );
1485
1486
1487 transform_point( &point, geo->matrix );
1488
1489
1490 point.x *= geo->focus.x;
1491 point.y *= geo->focus.y;
1492
1493
1494 model2_3d_push( raster, f2u(point.x) >> 8 );
1495 model2_3d_push( raster, f2u(point.y) >> 8 );
1496 model2_3d_push( raster, f2u(point.pz) >> 8 );
1497
1498
1499 point.x = u2f( *input++ );
1500 point.y = u2f( *input++ );
1501 point.pz = u2f( *input++ );
1502
1503
1504 transform_point( &point, geo->matrix );
1505
1506
1507 point.x *= geo->focus.x;
1508 point.y *= geo->focus.y;
1509
1510
1511 model2_3d_push( raster, f2u(point.x) >> 8 );
1512 model2_3d_push( raster, f2u(point.y) >> 8 );
1513 model2_3d_push( raster, f2u(point.pz) >> 8 );
1514
1515
1516 for( i = 0; i < count; i++ )
1517 {
1518
1519 attr = *input++;
1520
1521
1522 model2_3d_push( raster, attr & 0x0003FFFF );
1523
1524
1525 normal.x = u2f(*input++);
1526 normal.y = u2f(*input++);
1527 normal.pz = u2f(*input++);
1528
1529
1530 transform_vector( &normal, geo->matrix );
1531
1532 if ( (attr & 3) != 0 )
1533 {
1534 float dotl, dotp, luminance, distance, specular;
1535 float coef, face;
1536 INT32 luma;
1537 texture_parameter * texparam;
1538
1539
1540 point.x = u2f( *input++ );
1541 point.y = u2f( *input++ );
1542 point.pz = u2f( *input++ );
1543
1544
1545 transform_point( &point, geo->matrix );
1546
1547
1548 dotl = dot_product( &normal, &geo->light );
1549
1550
1551 dotp = dot_product( &normal, &point );
1552
1553
1554 point.x *= geo->focus.x;
1555 point.y *= geo->focus.y;
1556
1557
1558 face = 0x100;
1559 if ( dotp >= 0 ) face = 0;
1560
1561
1562 texparam = &geo->texture_parameters[(attr>>18) & 0x1f];
1563
1564
1565 if ( (dotl * dotp) < 0 ) luminance = 0;
1566 else luminance = fabs( dotl );
1567
1568 specular = ((2*dotl) * normal.pz) - geo->light.pz;
1569 if ( specular < 0 ) specular = 0;
1570 if ( texparam->specular_control == 0 ) specular = 0;
1571 if ( (texparam->specular_control >> 1) != 0 ) specular *= specular;
1572 if ( (texparam->specular_control >> 2) != 0 ) specular *= specular;
1573 if ( ((texparam->specular_control+1) >> 3) != 0 ) specular *= specular;
1574
1575 specular *= texparam->specular_scale;
1576
1577 luminance = (luminance * texparam->diffuse) + texparam->ambient + specular;
1578 luma = (INT32)luminance;
1579
1580 if ( luma > 255 ) luma = 255;
1581 if ( luma < 0 ) luma = 0;
1582
1583
1584 luma += face;
1585
1586
1587 coef = geo->coef_table[attr>>27];
1588
1589
1590 distance = coef * fabs( dotp ) * geo->lod;
1591
1592
1593 model2_3d_push( raster, luma << 15 );
1594 model2_3d_push( raster, f2u(distance) >> 8 );
1595 model2_3d_push( raster, f2u(point.x) >> 8 );
1596 model2_3d_push( raster, f2u(point.y) >> 8 );
1597 model2_3d_push( raster, f2u(point.pz) >> 8 );
1598
1599
1600 if ( attr & 1 )
1601 {
1602
1603 point.x = u2f( *input++ );
1604 point.y = u2f( *input++ );
1605 point.pz = u2f( *input++ );
1606
1607
1608 transform_point( &point, geo->matrix );
1609
1610
1611 point.x *= geo->focus.x;
1612 point.y *= geo->focus.y;
1613
1614
1615 model2_3d_push( raster, f2u(point.x) >> 8 );
1616 model2_3d_push( raster, f2u(point.y) >> 8 );
1617 model2_3d_push( raster, f2u(point.pz) >> 8 );
1618 }
1619 else
1620 {
1621
1622 input += 3;
1623 }
1624 }
1625 else
1626 {
1627 break;
1628 }
1629 }
1630
1631
1632 model2_3d_push( raster, 0 );
1633 }
1634
1635
1636 static void geo_parse_nn_ns( geo_state *geo, UINT32 *input, UINT32 count )
1637 {
1638 raster_state *raster = geo->raster;
1639 poly_vertex point, normal, p0, p1, p2, p3;
1640 UINT32 attr, i;
1641
1642
1643 point.x = u2f( *input++ );
1644 point.y = u2f( *input++ );
1645 point.pz = u2f( *input++ );
1646
1647
1648 transform_point( &point, geo->matrix );
1649
1650
1651 p0.x = point.x; p0.y = point.y; p0.pz = point.pz;
1652
1653
1654 point.x *= geo->focus.x;
1655 point.y *= geo->focus.y;
1656
1657
1658 model2_3d_push( raster, f2u(point.x) >> 8 );
1659 model2_3d_push( raster, f2u(point.y) >> 8 );
1660 model2_3d_push( raster, f2u(point.pz) >> 8 );
1661
1662
1663 point.x = u2f( *input++ );
1664 point.y = u2f( *input++ );
1665 point.pz = u2f( *input++ );
1666
1667
1668 transform_point( &point, geo->matrix );
1669
1670
1671 p1.x = point.x; p1.y = point.y; p1.pz = point.pz;
1672
1673
1674 point.x *= geo->focus.x;
1675 point.y *= geo->focus.y;
1676
1677
1678 model2_3d_push( raster, f2u(point.x) >> 8 );
1679 model2_3d_push( raster, f2u(point.y) >> 8 );
1680 model2_3d_push( raster, f2u(point.pz) >> 8 );
1681
1682
1683 input += 4;
1684
1685
1686 for( i = 0; i < count; i++ )
1687 {
1688
1689 attr = *input++;
1690
1691
1692 model2_3d_push( raster, attr & 0x0003FFFF );
1693
1694 if ( (attr & 3) != 0 )
1695 {
1696 float dotl, dotp, luminance, distance;
1697 float coef, face;
1698 INT32 luma;
1699 texture_parameter * texparam;
1700
1701
1702 point.x = u2f( *input++ );
1703 point.y = u2f( *input++ );
1704 point.pz = u2f( *input++ );
1705
1706
1707 transform_point( &point, geo->matrix );
1708
1709
1710 p2.x = point.x; p2.y = point.y; p2.pz = point.pz;
1711
1712
1713 vector_cross3( &normal, &p0, &p1, &p2 );
1714
1715
1716 normalize_vector( &normal );
1717
1718
1719 dotl = dot_product( &normal, &geo->light );
1720
1721
1722 dotp = dot_product( &normal, &point );
1723
1724
1725 point.x *= geo->focus.x;
1726 point.y *= geo->focus.y;
1727
1728
1729 face = 0x100;
1730 if ( dotp >= 0 ) face = 0;
1731
1732
1733 texparam = &geo->texture_parameters[(attr>>18) & 0x1f];
1734
1735
1736 if ( (dotl * dotp) < 0 ) luminance = 0;
1737 else luminance = fabs( dotl );
1738
1739 luminance = (luminance * texparam->diffuse) + texparam->ambient;
1740 luma = (INT32)luminance;
1741
1742 if ( luma > 255 ) luma = 255;
1743 if ( luma < 0 ) luma = 0;
1744
1745
1746 luma += face;
1747
1748
1749 coef = geo->coef_table[attr>>27];
1750
1751
1752 distance = coef * fabs( dotp ) * geo->lod;
1753
1754
1755 model2_3d_push( raster, luma << 15 );
1756 model2_3d_push( raster, f2u(distance) >> 8 );
1757 model2_3d_push( raster, f2u(point.x) >> 8 );
1758 model2_3d_push( raster, f2u(point.y) >> 8 );
1759 model2_3d_push( raster, f2u(point.pz) >> 8 );
1760
1761
1762 if ( attr & 1 )
1763 {
1764
1765 point.x = u2f( *input++ );
1766 point.y = u2f( *input++ );
1767 point.pz = u2f( *input++ );
1768
1769
1770 transform_point( &point, geo->matrix );
1771
1772
1773 p3.x = point.x; p3.y = point.y; p3.pz = point.pz;
1774
1775
1776 point.x *= geo->focus.x;
1777 point.y *= geo->focus.y;
1778
1779
1780 model2_3d_push( raster, f2u(point.x) >> 8 );
1781 model2_3d_push( raster, f2u(point.y) >> 8 );
1782 model2_3d_push( raster, f2u(point.pz) >> 8 );
1783 }
1784 else
1785 {
1786
1787 input += 3;
1788
1789
1790 p3.x = p2.x; p3.y = p2.y; p3.pz = p2.pz;
1791 }
1792 }
1793 else
1794 {
1795 break;
1796 }
1797
1798
1799 switch( (attr>>8) & 3 )
1800 {
1801 case 0:
1802 case 2:
1803 {
1804
1805 p0.x = p2.x; p0.y = p2.y; p0.pz = p2.pz;
1806 p1.x = p3.x; p1.y = p3.y; p1.pz = p3.pz;
1807 }
1808 break;
1809
1810 case 1:
1811 {
1812
1813 p1.x = p2.x; p1.y = p2.y; p1.pz = p2.pz;
1814 }
1815 break;
1816
1817 case 3:
1818 {
1819
1820 p0.x = p3.x; p0.y = p3.y; p0.pz = p3.pz;
1821 }
1822 break;
1823 }
1824 }
1825
1826
1827 model2_3d_push( raster, 0 );
1828 }
1829
1830
1831 static void geo_parse_nn_s( geo_state *geo, UINT32 *input, UINT32 count )
1832 {
1833 raster_state *raster = geo->raster;
1834 poly_vertex point, normal, p0, p1, p2, p3;
1835 UINT32 attr, i;
1836
1837
1838 point.x = u2f( *input++ );
1839 point.y = u2f( *input++ );
1840 point.pz = u2f( *input++ );
1841
1842
1843 transform_point( &point, geo->matrix );
1844
1845
1846 p0.x = point.x; p0.y = point.y; p0.pz = point.pz;
1847
1848
1849 point.x *= geo->focus.x;
1850 point.y *= geo->focus.y;
1851
1852
1853 model2_3d_push( raster, f2u(point.x) >> 8 );
1854 model2_3d_push( raster, f2u(point.y) >> 8 );
1855 model2_3d_push( raster, f2u(point.pz) >> 8 );
1856
1857
1858 point.x = u2f( *input++ );
1859 point.y = u2f( *input++ );
1860 point.pz = u2f( *input++ );
1861
1862
1863 transform_point( &point, geo->matrix );
1864
1865
1866 p1.x = point.x; p1.y = point.y; p1.pz = point.pz;
1867
1868
1869 point.x *= geo->focus.x;
1870 point.y *= geo->focus.y;
1871
1872
1873 model2_3d_push( raster, f2u(point.x) >> 8 );
1874 model2_3d_push( raster, f2u(point.y) >> 8 );
1875 model2_3d_push( raster, f2u(point.pz) >> 8 );
1876
1877
1878 input += 4;
1879
1880
1881 for( i = 0; i < count; i++ )
1882 {
1883
1884 attr = *input++;
1885
1886
1887 model2_3d_push( raster, attr & 0x0003FFFF );
1888
1889 if ( (attr & 3) != 0 )
1890 {
1891 float dotl, dotp, luminance, distance, specular;
1892 float coef, face;
1893 INT32 luma;
1894 texture_parameter * texparam;
1895
1896
1897 point.x = u2f( *input++ );
1898 point.y = u2f( *input++ );
1899 point.pz = u2f( *input++ );
1900
1901
1902 transform_point( &point, geo->matrix );
1903
1904
1905 p2.x = point.x; p2.y = point.y; p2.pz = point.pz;
1906
1907
1908 vector_cross3( &normal, &p0, &p1, &p2 );
1909
1910
1911 normalize_vector( &normal );
1912
1913
1914 dotl = dot_product( &normal, &geo->light );
1915
1916
1917 dotp = dot_product( &normal, &point );
1918
1919
1920 point.x *= geo->focus.x;
1921 point.y *= geo->focus.y;
1922
1923
1924 face = 0x100;
1925 if ( dotp >= 0 ) face = 0;
1926
1927
1928 texparam = &geo->texture_parameters[(attr>>18) & 0x1f];
1929
1930
1931 if ( (dotl * dotp) < 0 ) luminance = 0;
1932 else luminance = fabs( dotl );
1933
1934 specular = ((2*dotl) * normal.pz) - geo->light.pz;
1935 if ( specular < 0 ) specular = 0;
1936 if ( texparam->specular_control == 0 ) specular = 0;
1937 if ( (texparam->specular_control >> 1) != 0 ) specular *= specular;
1938 if ( (texparam->specular_control >> 2) != 0 ) specular *= specular;
1939 if ( ((texparam->specular_control+1) >> 3) != 0 ) specular *= specular;
1940
1941 specular *= texparam->specular_scale;
1942
1943 luminance = (luminance * texparam->diffuse) + texparam->ambient + specular;
1944 luma = (INT32)luminance;
1945
1946 if ( luma > 255 ) luma = 255;
1947 if ( luma < 0 ) luma = 0;
1948
1949
1950 luma += face;
1951
1952
1953 coef = geo->coef_table[attr>>27];
1954
1955
1956 distance = coef * fabs( dotp ) * geo->lod;
1957
1958
1959 model2_3d_push( raster, luma << 15 );
1960 model2_3d_push( raster, f2u(distance) >> 8 );
1961 model2_3d_push( raster, f2u(point.x) >> 8 );
1962 model2_3d_push( raster, f2u(point.y) >> 8 );
1963 model2_3d_push( raster, f2u(point.pz) >> 8 );
1964
1965
1966 if ( attr & 1 )
1967 {
1968
1969 point.x = u2f( *input++ );
1970 point.y = u2f( *input++ );
1971 point.pz = u2f( *input++ );
1972
1973
1974 transform_point( &point, geo->matrix );
1975
1976
1977 p3.x = point.x; p3.y = point.y; p3.pz = point.pz;
1978
1979
1980 point.x *= geo->focus.x;
1981 point.y *= geo->focus.y;
1982
1983
1984 model2_3d_push( raster, f2u(point.x) >> 8 );
1985 model2_3d_push( raster, f2u(point.y) >> 8 );
1986 model2_3d_push( raster, f2u(point.pz) >> 8 );
1987 }
1988 else
1989 {
1990
1991 input += 3;
1992
1993
1994 p3.x = p2.x; p3.y = p2.y; p3.pz = p2.pz;
1995 }
1996 }
1997 else
1998 {
1999 break;
2000 }
2001
2002
2003 switch( (attr>>8) & 3 )
2004 {
2005 case 0:
2006 case 2:
2007 {
2008
2009 p0.x = p2.x; p0.y = p2.y; p0.pz = p2.pz;
2010 p1.x = p3.x; p1.y = p3.y; p1.pz = p3.pz;
2011 }
2012 break;
2013
2014 case 1:
2015 {
2016
2017 p1.x = p2.x; p1.y = p2.y; p1.pz = p2.pz;
2018 }
2019 break;
2020
2021 case 3:
2022 {
2023
2024 p0.x = p3.x; p0.y = p3.y; p0.pz = p3.pz;
2025 }
2026 break;
2027 }
2028 }
2029
2030
2031 model2_3d_push( raster, 0 );
2032 }
2033
2034
2039
2040
2041 static UINT32 * geo_nop( geo_state *geo, UINT32 opcode, UINT32 *input )
2042 {
2043 raster_state *raster = geo->raster;
2044
2045
2046 model2_3d_push( raster, opcode >> 23 );
2047
2048 return input;
2049 }
2050
2051
2052 static UINT32 * geo_object_data( geo_state *geo, UINT32 opcode, UINT32 *input )
2053 {
2054 raster_state *raster = geo->raster;
2055 UINT32 tpa = *input++;
2056 UINT32 tha = *input++;
2057 UINT32 oba = *input++;
2058 UINT32 obc = *input++;
2059
2060 UINT32 *obp;
2061
2062
2063 model2_3d_push( raster, opcode >> 23 );
2064 model2_3d_push( raster, tpa );
2065 model2_3d_push( raster, tha );
2066
2067
2068 if ( oba & 0x01000000 )
2069 {
2070
2071 obp = &geo->polygon_ram0[oba & 0x7FFF];
2072 }
2073 else if ( oba & 0x00800000 )
2074 {
2075
2076 obp = &geo->polygon_rom[oba & 0x7FFFFF];
2077 }
2078 else
2079 {
2080
2081 obp = &geo->polygon_ram1[oba & 0x7FFF];
2082 }
2083
2084 switch( geo->mode & 3 )
2085 {
2086
2087 case 0: geo_parse_np_ns( geo, obp, obc ); break;
2088
2089
2090 case 1: geo_parse_np_s( geo, obp, obc ); break;
2091
2092
2093 case 2: geo_parse_nn_ns( geo, obp, obc ); break;
2094
2095
2096 case 3: geo_parse_nn_s( geo, obp, obc ); break;
2097 }
2098
2099
2100 return input;
2101 }
2102
2103
2104 static UINT32 * geo_direct_data( geo_state *geo, UINT32 opcode, UINT32 *input )
2105 {
2106 raster_state *raster = geo->raster;
2107 UINT32 tpa = *input++;
2108 UINT32 tha = *input++;
2109 UINT32 attr;
2110
2111
2112 model2_3d_push( raster, (opcode >> 23) - 1 );
2113 model2_3d_push( raster, tpa );
2114 model2_3d_push( raster, tha );
2115
2116
2117 model2_3d_push( raster, (*input++) >> 8 );
2118 model2_3d_push( raster, (*input++) >> 8 );
2119 model2_3d_push( raster, (*input++) >> 8 );
2120
2121 model2_3d_push( raster, (*input++) >> 8 );
2122 model2_3d_push( raster, (*input++) >> 8 );
2123 model2_3d_push( raster, (*input++) >> 8 );
2124
2125 do
2126 {
2127
2128 attr = *input++;
2129
2130 if ( (attr & 3) == 0 )
2131 break;
2132
2133
2134 model2_3d_push( raster, attr & 0x00FFFFFF );
2135
2136
2137 model2_3d_push( raster, (*input++) >> 8 );
2138
2139
2140 model2_3d_push( raster, (*input++) >> 8 );
2141
2142
2143 model2_3d_push( raster, (*input++) >> 8 );
2144 model2_3d_push( raster, (*input++) >> 8 );
2145 model2_3d_push( raster, (*input++) >> 8 );
2146
2147
2148 if ( attr & 1 )
2149 {
2150 model2_3d_push( raster, (*input++) >> 8 );
2151 model2_3d_push( raster, (*input++) >> 8 );
2152 model2_3d_push( raster, (*input++) >> 8 );
2153 }
2154 } while( 1 );
2155
2156
2157 model2_3d_push( raster, 0 );
2158
2159 return input;
2160 }
2161
2162
2163 static UINT32 * geo_window_data( geo_state *geo, UINT32 opcode, UINT32 *input )
2164 {
2165 raster_state *raster = geo->raster;
2166 UINT32 x, y, i;
2167
2168
2169 model2_3d_push( raster, opcode >> 23 );
2170
2171
2180
2181 for( i = 0; i < 6; i++ )
2182 {
2183
2184 y = *input++;
2185
2186
2187 x = ( y & 0x0FFF0000 ) >> 4 ;
2188 y &= 0xFFF;
2189
2190
2191 model2_3d_push( raster, x | y );
2192 }
2193
2194 return input;
2195 }
2196
2197
2198 static UINT32 * geo_texture_data( geo_state *geo, UINT32 opcode, UINT32 *input )
2199 {
2200 raster_state *raster = geo->raster;
2201 UINT32 i, count;
2202
2203
2204 model2_3d_push( raster, opcode >> 23 );
2205
2206
2207 model2_3d_push( raster, *input++ );
2208
2209
2210 count = *input++;
2211
2212
2213 model2_3d_push( raster, count );
2214
2215
2216 for( i = 0; i < count; i++ )
2217 model2_3d_push( raster, *input++ );
2218
2219 return input;
2220 }
2221
2222
2223 static UINT32 * geo_polygon_data( geo_state *geo, UINT32 opcode, UINT32 *input )
2224 {
2225 UINT32 address, count, i;
2226 UINT32 *p;
2227
2228 (void)opcode;
2229
2230
2231 address = *input++;
2232
2233
2234 if ( address & 0x01000000 )
2235 {
2236
2237 p = &geo->polygon_ram0[address & 0x7FFF];
2238 }
2239 else
2240 {
2241
2242 p = &geo->polygon_ram1[address & 0x7FFF];
2243 }
2244
2245
2246 count = *input++;
2247
2248
2249 for( i = 0; i < count; i++ )
2250 *p++ = *input++;
2251
2252 return input;
2253 }
2254
2255
2256 static UINT32 * geo_texture_parameters( geo_state *geo, UINT32 opcode, UINT32 *input )
2257 {
2258 UINT32 index, count, i, param;
2259
2260 (void)opcode;
2261
2262
2263 index = *input++;
2264
2265
2266 count = *input++;
2267
2268 for( i = 0; i < count; i++ )
2269 {
2270
2271 param = *input++;
2272
2273 geo->texture_parameters[index].diffuse = (float)( param & 0xFF );
2274 geo->texture_parameters[index].ambient = (float)( (param >> 8) & 0xFF );
2275 geo->texture_parameters[index].specular_control = (param >> 24) & 0xFF;
2276 geo->texture_parameters[index].specular_scale = (float)( (param >> 16) & 0xFF );
2277
2278
2279 geo->coef_table[index] = u2f(*input++);
2280
2281 index = (index + 1) & 0x1F;
2282 }
2283
2284 return input;
2285 }
2286
2287
2288 static UINT32 * geo_mode( geo_state *geo, UINT32 opcode, UINT32 *input )
2289 {
2290 (void)opcode;
2291
2292
2293 geo->mode = *input++;
2294
2295 return input;
2296 }
2297
2298
2299 static UINT32 * geo_zsort_mode( geo_state *geo, UINT32 opcode, UINT32 *input )
2300 {
2301 raster_state *raster = geo->raster;
2302
2303
2304 model2_3d_push( raster, opcode >> 23 );
2305
2306
2307 model2_3d_push( raster, (*input++) >> 8 );
2308
2309 return input;
2310 }
2311
2312
2313 static UINT32 * geo_focal_distance( geo_state *geo, UINT32 opcode, UINT32 *input )
2314 {
2315 (void)opcode;
2316
2317
2318 geo->focus.x = u2f( *input++ );
2319
2320
2321 geo->focus.y = u2f( *input++ );
2322
2323 return input;
2324 }
2325
2326
2327 static UINT32 * geo_light_source( geo_state *geo, UINT32 opcode, UINT32 *input )
2328 {
2329 (void)opcode;
2330
2331
2332 geo->light.x = u2f( *input++ );
2333
2334
2335 geo->light.y = u2f( *input++ );
2336
2337
2338 geo->light.pz = u2f( *input++ );
2339
2340 return input;
2341 }
2342
2343
2344 static UINT32 * geo_matrix_write( geo_state *geo, UINT32 opcode, UINT32 *input )
2345 {
2346 UINT32 i;
2347
2348 (void)opcode;
2349
2350
2351 for( i = 0; i < 12; i++ )
2352 geo->matrix[i] = u2f( *input++ );
2353
2354 return input;
2355 }
2356
2357
2358 static UINT32 * geo_translate_write( geo_state *geo, UINT32 opcode, UINT32 *input )
2359 {
2360 UINT32 i;
2361
2362 (void)opcode;
2363
2364
2365 for( i = 0; i < 3; i++ )
2366 geo->matrix[i+9] = u2f( *input++ );
2367
2368 return input;
2369 }
2370
2371
2372 static UINT32 * geo_data_mem_push( geo_state *geo, UINT32 opcode, UINT32 *input )
2373 {
2374 UINT32 address, count, i;
2375
2376
2387
2388
2389 (void)opcode;
2390
2391
2392 address = *input++;
2393
2394
2395 count = *input++;
2396
2397 logerror( "SEGA GEO: Executing unsupported geo_data_mem_push (address = %08x, count = %08x)\n", address, count );
2398
2399 (void)i;
2400
2404
2405 return input;
2406 }
2407
2408
2409 static UINT32 * geo_test( geo_state *geo, UINT32 opcode, UINT32 *input )
2410 {
2411 UINT32 data, blocks, address, count, checksum, i;
2412
2413 (void)opcode;
2414
2415
2416 data = 1;
2417
2418 for( i = 0; i < 32; i++ )
2419 {
2420 if ( *input++ != data )
2421 {
2422
2423 logerror( "SEGA GEO: FIFO Test failed\n" );
2424 }
2425
2426 data <<= 1;
2427 }
2428
2429
2430 blocks = *input++;
2431
2432 for( i = 0; i < blocks; i++ )
2433 {
2434 UINT32 sum_even, sum_odd, j;
2435
2436
2437 address = (*input++) & 0x7FFFFF;
2438
2439
2440 count = *input++;
2441
2442
2443 checksum = *input++;
2444
2445
2446 sum_even = 0;
2447 sum_odd = 0;
2448
2449 for( j = 0; j < count; j++ )
2450 {
2451 data = geo->polygon_rom[address++];
2452
2453 address &= 0x7FFFFF;
2454
2455 sum_even += data >> 16;
2456 sum_even &= 0xFFFF;
2457
2458 sum_odd += data & 0xFFFF;
2459 sum_odd &= 0xFFFF;
2460 }
2461
2462 sum_even += checksum >> 16;
2463 sum_even &= 0xFFFF;
2464
2465 sum_odd += checksum & 0xFFFF;
2466 sum_odd &= 0xFFFF;
2467
2468 if ( sum_even != 0 || sum_odd != 0 )
2469 {
2470
2471 logerror( "SEGA GEO: Polygon ROM Test failed\n" );
2472 }
2473 }
2474
2475 return input;
2476 }
2477
2478
2479 static UINT32 * geo_end( geo_state *geo, UINT32 opcode, UINT32 *input )
2480 {
2481 raster_state *raster = geo->raster;
2482
2483 (void)opcode;
2484
2485
2486 model2_3d_push( raster, 0xFF000000 );
2487
2488
2489 return NULL;
2490 }
2491
2492
2493 static UINT32 * geo_dummy( geo_state *geo, UINT32 opcode, UINT32 *input )
2494 {
2495
2496 (void)opcode;
2497
2498
2499
2500 input++;
2501
2502 return input;
2503 }
2504
2505
2506 static UINT32 * geo_log_data( geo_state *geo, UINT32 opcode, UINT32 *input )
2507 {
2508 raster_state *raster = geo->raster;
2509 UINT32 i, count;
2510
2511
2512 model2_3d_push( raster, opcode >> 23 );
2513
2514
2515 model2_3d_push( raster, *input++ );
2516
2517
2518 count = *input++;
2519
2520
2521 model2_3d_push( raster, count << 2 );
2522
2523
2524 for( i = 0; i < count; i++ )
2525 {
2526 UINT32 data = *input++;
2527
2528 model2_3d_push( raster, data & 0xff );
2529 model2_3d_push( raster, (data >> 8) & 0xff );
2530 model2_3d_push( raster, (data >> 16) & 0xff );
2531 model2_3d_push( raster, (data >> 24) & 0xff );
2532 }
2533
2534 return input;
2535 }
2536
2537
2538 static UINT32 * geo_lod( geo_state *geo, UINT32 opcode, UINT32 *input )
2539 {
2540 (void)opcode;
2541
2542
2543 geo->lod = u2f(*input++);
2544
2545 return input;
2546 }
2547
2548
2549 static UINT32 * geo_code_upload( geo_state *geo, UINT32 opcode, UINT32 *input )
2550 {
2551 UINT32 count, i;
2552
2553
2559
2560 logerror( "SEGA GEO: Uploading debug code (unimplemented)\n" );
2561
2562 (void)opcode;
2563
2564
2565
2566 input++;
2567
2568
2569 count = *input++;
2570
2571 for( i = 0; i < count; i++ )
2572 {
2573 UINT64 code;
2574
2575
2576 code = *input++;
2577
2578 code <<= 32;
2579
2580
2581 code |= *input++;
2582 code |= (*input++) << 16;
2583 }
2584
2585
2588
2589
2593
2594 return input;
2595 }
2596
2597
2598 static UINT32 * geo_code_jump( geo_state *geo, UINT32 opcode, UINT32 *input )
2599 {
2600
2601
2602
2609
2610 logerror( "SEGA GEO: Jumping to debug code (unimplemented)\n" );
2611
2612 (void)opcode;
2613
2614
2615 input++;
2616
2617
2620 return input;
2621 }
2622
2623 static UINT32 * geo_process_command( geo_state *geo, UINT32 opcode, UINT32 *input )
2624 {
2625 switch( opcode >> 23 )
2626 {
2627 case 0x00: input = geo_nop( geo, opcode, input ); break;
2628 case 0x01: input = geo_object_data( geo, opcode, input ); break;
2629 case 0x02: input = geo_direct_data( geo, opcode, input ); break;
2630 case 0x03: input = geo_window_data( geo, opcode, input ); break;
2631 case 0x04: input = geo_texture_data( geo, opcode, input ); break;
2632 case 0x05: input = geo_polygon_data( geo, opcode, input ); break;
2633 case 0x06: input = geo_texture_parameters( geo, opcode, input ); break;
2634 case 0x07: input = geo_mode( geo, opcode, input ); break;
2635 case 0x08: input = geo_zsort_mode( geo, opcode, input ); break;
2636 case 0x09: input = geo_focal_distance( geo, opcode, input ); break;
2637 case 0x0A: input = geo_light_source( geo, opcode, input ); break;
2638 case 0x0B: input = geo_matrix_write( geo, opcode, input ); break;
2639 case 0x0C: input = geo_translate_write( geo, opcode, input ); break;
2640 case 0x0D: input = geo_data_mem_push( geo, opcode, input ); break;
2641 case 0x0E: input = geo_test( geo, opcode, input ); break;
2642 case 0x0F: input = geo_end( geo, opcode, input ); break;
2643 case 0x10: input = geo_dummy( geo, opcode, input ); break;
2644 case 0x11: input = geo_object_data( geo, opcode, input ); break;
2645 case 0x12: input = geo_direct_data( geo, opcode, input ); break;
2646 case 0x13: input = geo_window_data( geo, opcode, input ); break;
2647 case 0x14: input = geo_log_data( geo, opcode, input ); break;
2648 case 0x15: input = geo_polygon_data( geo, opcode, input ); break;
2649 case 0x16: input = geo_lod( geo, opcode, input ); break;
2650 case 0x17: input = geo_mode( geo, opcode, input ); break;
2651 case 0x18: input = geo_zsort_mode( geo, opcode, input ); break;
2652 case 0x19: input = geo_focal_distance( geo, opcode, input ); break;
2653 case 0x1A: input = geo_light_source( geo, opcode, input ); break;
2654 case 0x1B: input = geo_matrix_write( geo, opcode, input ); break;
2655 case 0x1C: input = geo_translate_write( geo, opcode, input ); break;
2656 case 0x1D: input = geo_code_upload( geo, opcode, input ); break;
2657 case 0x1E: input = geo_code_jump( geo, opcode, input ); break;
2658 case 0x1F: input = geo_end( geo, opcode, input ); break;
2659 }
2660
2661 return input;
2662 }
2663
2664 static void geo_parse( model2_state *state )
2665 {
2666 UINT32 address = (state->m_geo_read_start_address/4);
2667 UINT32 *input = &state->m_bufferram[address];
2668 UINT32 opcode;
2669
2670 while( input != NULL && (input - state->m_bufferram) < 0x20000 )
2671 {
2672
2673 opcode = *input++;
2674
2675
2676 if ( opcode & 0x80000000 )
2677 {
2678
2679 address = (opcode & 0x7FFFF) / 4;
2680
2681
2682 input = &state->m_bufferram[address];
2683
2684
2685 continue;
2686 }
2687
2688
2689 input = geo_process_command( state->m_geo, opcode, input );
2690 }
2691 }
2692
2693
2694
2695
2696 static void model2_exit(running_machine &machine)
2697 {
2698 model2_state *state = machine.driver_data<model2_state>();
2699 poly_free(state->m_poly);
2700 }
2701
2702 VIDEO_START_MEMBER(model2_state,model2)
2703 {
2704 const rectangle &visarea = machine().primary_screen->visible_area();
2705 int width = visarea.width();
2706 int height = visarea.height();
2707
2708 m_sys24_bitmap.allocate(width, height+4);
2709
2710 m_poly = poly_alloc(machine(), 4000, sizeof(poly_extra_data), 0);
2711 machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(model2_exit), &machine()));
2712
2713
2714 model2_3d_init( machine(), (UINT16*)memregion("user3")->base() );
2715
2716
2717 geo_init( machine(), (UINT32*)memregion("user2")->base() );
2718 }
2719
2720 UINT32 model2_state::screen_update_model2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
2721 {
2722 logerror("--- frame ---\n");
2723
2724 bitmap.fill(machine().pens[0], cliprect);
2725 m_sys24_bitmap.fill(0, cliprect);
2726
2727 segas24_tile *tile = machine().device<segas24_tile>("tile");
2728 tile->draw(m_sys24_bitmap, cliprect, 7, 0, 0);
2729 tile->draw(m_sys24_bitmap, cliprect, 6, 0, 0);
2730 tile->draw(m_sys24_bitmap, cliprect, 5, 0, 0);
2731 tile->draw(m_sys24_bitmap, cliprect, 4, 0, 0);
2732
2733 copybitmap_trans(bitmap, m_sys24_bitmap, 0, 0, 0, 0, cliprect, 0);
2734
2735
2736 model2_3d_frame_start(this);
2737
2738
2739 geo_parse(this);
2740
2741
2742 model2_3d_frame_end( this, bitmap, cliprect );
2743
2744 m_sys24_bitmap.fill(0, cliprect);
2745 tile->draw(m_sys24_bitmap, cliprect, 3, 0, 0);
2746 tile->draw(m_sys24_bitmap, cliprect, 2, 0, 0);
2747 tile->draw(m_sys24_bitmap, cliprect, 1, 0, 0);
2748 tile->draw(m_sys24_bitmap, cliprect, 0, 0, 0);
2749
2750 copybitmap_trans(bitmap, m_sys24_bitmap, 0, 0, 0, 0, cliprect, 0);
2751
2752 return 0;
2753 }
2754