6
/* !!! I'm sure this isn't right !!! */
7
UINT32 hng64_dls[2][0x81] ;
9
static int frameCount = 0 ;
11
UINT32* hng64_videoram;
12
tilemap *hng64_tilemap0;
13
tilemap *hng64_tilemap1;
14
tilemap *hng64_tilemap2;
15
tilemap *hng64_tilemap3;
17
UINT32 *hng64_spriteram;
18
UINT32 *hng64_videoregs;
22
/* HAAAACK to make the floor 'work' */
23
UINT32 hackTilemap3, hackTm3Count, rowScrollOffset ;
26
static void matmul4( float *product, const float *a, const float *b ) ;
27
static void vecmatmul4( float *product, const float *a, const float *b) ;
28
static float vecDotProduct( const float *a, const float *b) ;
29
static void normalize(float* x) ;
32
static float uToF(UINT16 input) ;
33
static void SetIdentity(float *matrix) ;
36
static void plot(INT32 x, INT32 y, INT32 color, mame_bitmap *bitmap) ;
37
static void drawline2d(INT32 x0, INT32 y0, INT32 x1, INT32 y1, INT32 color, mame_bitmap *bitmap) ;
39
static float *depthBuffer ;
40
static struct polygon *polys ;
42
/*static int tilemap2Offset = 0x10000 ; */
45
#define WORD_AT(BUFFER,OFFSET) ( (BUFFER[OFFSET] << 8) | BUFFER[OFFSET+1] )
52
* UINT32 | Bytes | Use
53
* -------+-76543210-+----------------
54
* 0 | xxxx---- | y position
55
* 0 | ----xxxx | x position
56
* 1 | xxxx---- | y zoom
57
* 1 | ----xxxx | x zoom
58
* 2 | ------x- | x chain
59
* 2 | -------x | y chain
60
* 2 | xxxx---- | end of sprite list - though it surely contains more info !
61
* 2 | ----oo-- | not used ??
62
* 3 | --xx---- | palette entry
63
* 3 | --x----- | (bit 0x8) - maybe a graphics bank selector
64
* 3 | oo--oooo | not used ?
65
* 4 | --xxxxxx | tile number
66
* 4 | --x----- | (bit 0x2) - x flip
67
* 4 | --x----- | (bit 0x1) - y flip
68
* 4 | oo------ | not used ??
69
* 5 | oooooooo | not used ??
70
* 6 | oooooooo | not used ??
71
* 7 | oooooooo | not used ??
74
/* xxxx---- | I think this part of UINT32 2 is interesting as more than just a list end marker (AJG)
77
static void hng64_drawsprites( mame_bitmap *bitmap, const rectangle *cliprect )
79
const gfx_element *gfx;
80
UINT32 *source = hng64_spriteram;
81
UINT32 *finish = hng64_spriteram + 0xb000/4;
83
/* find end of list? */
88
endlist=(source[2]&0xffff0000)>>16;
89
if (endlist == 0x07ff) break;
93
/* for (int iii = 0; iii < 0x0f; iii++) */
94
/* printf("%.8x ", hng64_videoregs[iii]) ; */
98
finish = hng64_spriteram;
100
/* draw backwards .. */
101
while( source>finish )
103
int xpos, ypos, tileno,chainx,chainy,xflip;
104
int xdrw,ydrw,pal,xinc,yinc,yflip;
109
ypos = (source[0]&0xffff0000)>>16;
110
xpos = (source[0]&0x0000ffff)>>0;
111
tileno=(source[4]&0x00ffffff);
112
chainx=(source[2]&0x000000f0)>>4;
113
chainy=(source[2]&0x0000000f);
115
zoomy = (source[1]&0xffff0000)>>16;
116
zoomx = (source[1]&0x0000ffff)>>0;
118
pal =(source[3]&0x00ff0000)>>16;
119
xflip=(source[4]&0x02000000)>>25;
120
yflip=(source[4]&0x01000000)>>24;
122
if(xpos&0x8000) xpos -=0x10000;
123
if(ypos&0x8000) ypos -=0x10000;
126
/* if (!(source[4] == 0x00000000 || source[4] == 0x000000aa)) */
127
/* printf("unknown : %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x \n", source[0], source[1], source[2], source[3], */
128
/* source[4], source[5], source[6], source[7]) ; */
130
/* Calculate the zoom */
131
/* First, prevent any possible divide by zero errors */
132
if(!zoomx) zoomx=0x1000;
133
if(!zoomy) zoomy=0x1000;
135
foomX = (float)(0x1000) / (float)zoomx ;
136
foomY = (float)(0x1000) / (float)zoomy ;
138
zoomx = ((int)foomX) << 16 ;
139
zoomy = ((int)foomY) << 16 ;
141
zoomx += (int)((foomX - floor(foomX)) * (float)0x10000) ;
142
zoomy += (int)((foomY - floor(foomY)) * (float)0x10000) ;
145
if (source[3]&0x00800000) /* maybe .. */
147
gfx= Machine->gfx[4];
151
gfx= Machine->gfx[5];
154
/* Just a big hack to make the top and bottom tiles in the intro not crash (a pal value of 0x70 is bad) */
155
/* Is there a problem with drawsprites? Doubtful... */
156
if (source[2] == 0x00080000)
160
/* Accomodate for chaining and flipping */
163
xinc=-(int)(16.0f*foomX);
168
xinc=(int)(16.0f*foomX);
173
yinc=-(int)(16.0f*foomY);
178
yinc=(int)(16.0f*foomY);
182
/* if (((source[2] & 0xffff0000) >> 16) == 0x0001) */
184
/* usrintf_showmessage("T %.8x %.8x %.8x %.8x %.8x", source[0], source[1], source[2], source[3], source[4]) ; */
185
/* // usrintf_showmessage("T %.8x %.8x %.8x %.8x %.8x", source[0], source[1], source[2], source[3], source[4]) ; */
188
for(ydrw=0;ydrw<=chainy;ydrw++)
190
for(xdrw=0;xdrw<=chainx;xdrw++)
192
drawgfxzoom(bitmap,gfx,tileno,pal,xflip,yflip,xpos+(xinc*xdrw),ypos+(yinc*ydrw),cliprect,TRANSPARENCY_PEN,0,zoomx,zoomy/*0x10000*/);
200
/* Transition_Control Memory Region Map
201
* ------------------------------
203
* UINT32 | Bytes | Use
204
* -------+-76543210-+----------
211
* 6 | --xxxxxx | I popped into Buriki and saw some of these values changing to the same as 7. hmmmm...
212
* 7 | --xxxxxx | Almost certainly RGB darkening
215
* 10 | --xxxxxx | Almost certainly RGB brightening
216
* 11 | xxxxxxxx | Unknown - looks like an ARGB value - it seems to change when the scene changes
222
* Various bits change depending on what is happening in the scene.
223
* These bits may set which 'layer' is affected by the blending.
224
* Or maybe they adjust the scale of the lightening and darkening...
225
* Or maybe it switches from fading by scaling to fading using absolute addition and subtraction...
226
* Or maybe they set transition type (there seems to be a cute scaling-squares transition in there somewhere)...
228
static void hng64_transition_control(mame_bitmap *bitmap)
232
/* float colorScaleR, colorScaleG, colorScaleB ; */
233
/* float finR, finG, finB ; */
234
INT32 finR, finG, finB ;
236
INT32 darkR, darkG, darkB ;
237
INT32 brigR, brigG, brigB ;
239
/* If either of the fading memory regions is non-zero... */
240
if (hng64_tcram[0x00000007] != 0x00000000 || hng64_tcram[0x0000000a] != 0x00000000)
242
darkR = (INT32)( hng64_tcram[0x00000007] & 0xff) ;
243
darkG = (INT32)((hng64_tcram[0x00000007] >> 8) & 0xff) ;
244
darkB = (INT32)((hng64_tcram[0x00000007] >> 16) & 0xff) ;
246
brigR = (INT32)( hng64_tcram[0x0000000a] & 0xff) ;
247
brigG = (INT32)((hng64_tcram[0x0000000a] >> 8) & 0xff) ;
248
brigB = (INT32)((hng64_tcram[0x0000000a] >> 16) & 0xff) ;
250
for (i = Machine->visible_area.min_x; i < Machine->visible_area.max_x; i++)
252
for (j = Machine->visible_area.min_y; j < Machine->visible_area.max_y; j++)
254
UINT32* thePixel = &((UINT32 *)(bitmap->line[j]))[i] ;
256
finR = (INT32)RGB_RED(*thePixel) ;
257
finG = (INT32)RGB_GREEN(*thePixel) ;
258
finB = (INT32)RGB_BLUE(*thePixel) ;
261
// Apply the darkening pass (0x07)...
262
colorScaleR = 1.0f - (float)( hng64_tcram[0x00000007] & 0xff) / 255.0f ;
263
colorScaleG = 1.0f - (float)((hng64_tcram[0x00000007] >> 8) & 0xff) / 255.0f ;
264
colorScaleB = 1.0f - (float)((hng64_tcram[0x00000007] >> 16) & 0xff) / 255.0f ;
266
finR = ((float)RGB_RED(*thePixel) * colorScaleR) ;
267
finG = ((float)RGB_GREEN(*thePixel) * colorScaleG) ;
268
finB = ((float)RGB_BLUE(*thePixel) * colorScaleB) ;
271
// Apply the lightening pass (0x0a)...
272
colorScaleR = 1.0f + (float)( hng64_tcram[0x0000000a] & 0xff) / 255.0f ;
273
colorScaleG = 1.0f + (float)((hng64_tcram[0x0000000a] >> 8) & 0xff) / 255.0f ;
274
colorScaleB = 1.0f + (float)((hng64_tcram[0x0000000a] >> 16) & 0xff) / 255.0f ;
276
finR *= colorScaleR ;
277
finG *= colorScaleG ;
278
finB *= colorScaleB ;
282
if (finR > 255.0f) finR = 255.0f ;
283
if (finG > 255.0f) finG = 255.0f ;
284
if (finB > 255.0f) finB = 255.0f ;
288
/* Subtractive fading */
289
if (hng64_tcram[0x00000007] != 0x00000000)
296
/* Additive fading */
297
if (hng64_tcram[0x0000000a] != 0x00000000)
304
/* Clamp the high end */
305
if (finR > 255) finR = 255 ;
306
if (finG > 255) finG = 255 ;
307
if (finB > 255) finB = 255 ;
309
/* Clamp the low end */
310
if (finR < 0) finR = 0 ;
311
if (finG < 0) finG = 0 ;
312
if (finB < 0) finB = 0 ;
314
*thePixel = MAKE_ARGB(255, (UINT8)finR, (UINT8)finG, (UINT8)finB) ;
329
#define MAX_ONSCREEN_POLYS (10000)
333
float worldCoords[4] ; /* World space coordinates (X Y Z 1.0) */
335
float texCoords[4] ; /* Texture coordinates (U V 0 1.0) -> OpenGL style... */
337
float normal[4] ; /* Normal (X Y Z 1.0) */
338
float clipCoords[4] ; /* Homogeneous screen space coordinates (X Y Z W) */
340
float light[3] ; /* The intensity of the illumination at this point */
345
int n ; /* Number of sides */
346
struct polyVert vert[10] ; /* Vertices (maximum number per polygon is 10 -> 3+6) */
348
float faceNormal[4] ; /* Normal of the face overall - for calculating visibility and flat-shading... */
349
int visible ; /* Polygon visibility in scene */
351
INT8 texIndex ; /* Which texture to draw from (0x00-0x0f) */
352
INT8 texType ; /* How to index into the texture */
353
UINT8 palIndex ; /* Which palette to use when rasterizing */
357
static void PerformFrustumClip(struct polygon *p) ;
359
static void DrawWireframe(struct polygon *p, mame_bitmap *bitmap) ;
360
static void DrawShaded(struct polygon *p, mame_bitmap *bitmap) ;
363
static void hng64_draw3d( mame_bitmap *bitmap, const rectangle *cliprect )
367
float projectionMatrix[16] ;
368
float modelViewMatrix[16] ;
369
float cameraMatrix[16] ;
370
float objectMatrix[16] ;
372
int paletteState = 0x00 ;
374
UINT32 numPolys = 0 ;
376
struct polygon lastPoly = { 0 } ;
378
/* Set some matrices to the identity... */
379
SetIdentity(projectionMatrix) ;
380
SetIdentity(modelViewMatrix) ;
381
SetIdentity(cameraMatrix) ;
382
SetIdentity(objectMatrix) ;
384
/* Display list 2 comes after display list 1. Go figure. */
385
for (j = 1; j >= 0; j--)
387
UINT32 *workingList = hng64_dls[j] ;
389
for (i = 0; i < 0x80; i += 0x08)
391
float left, right, top, bottom, near_, far_ ;
393
UINT8 *threeDPointer ;
394
UINT32 threeDOffset ;
398
float eyeCoords[4] ; /* objectCoords transformed by the modelViewMatrix */
399
/* float clipCoords[4] ; // eyeCoords transformed by the projectionMatrix */
400
float ndCoords[4] ; /* normalized device coordinates/clipCoordinates (x/w, y/w, z/w) */
401
float windowCoords[4] ; /* mapped ndCoordinates to screen space */
405
/* printf("Element %.2d (%d) : %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", i/0x08, j, */
406
/* (UINT32)hng64_dls[j][i+0], (UINT32)hng64_dls[j][i+1], (UINT32)hng64_dls[j][i+2], (UINT32)hng64_dls[j][i+3], */
407
/* (UINT32)hng64_dls[j][i+4], (UINT32)hng64_dls[j][i+5], (UINT32)hng64_dls[j][i+6], (UINT32)hng64_dls[j][i+7]) ; */
409
/* Depending on what the initial flags are, do sumthin'... */
410
switch((workingList[i+0] & 0xffff0000) >> 16)
413
/* UNKNOWN - seems an awful lot parameters for a projection matrix though... */
417
/* It changes when 'How to play' is on the screen... not too much, but if this is right, the aspect */
418
/* ratio is different... */
420
/* Heisted from GLFrustum - 6 parameters... */
421
left = uToF( workingList[i+5] & 0x0000ffff) ;
422
right = uToF((workingList[i+5] & 0xffff0000) >> 16) ;
423
top = uToF((workingList[i+6] & 0xffff0000) >> 16) ;
424
bottom = uToF( workingList[i+6] & 0x0000ffff) ;
425
near_ = uToF((workingList[i+3] & 0xffff0000) >> 16) ;
426
far_ = uToF( workingList[i+3] & 0x0000ffff) ;
428
/* It's almost .always. these values in fatfurwa... */
429
/* 0.070313 0.000000 [0] (scaled by 128) */
430
/* 0.000000 10.000000 [1] */
431
/* 0.000000 0.500000 [2] */
432
/* 2.000000 11.062500 [3] */
433
/* 10.000000 11.000000 [4] */
434
/* 1.000000 -1.000000 [5] */
435
/* 0.875000 -0.875000 [6] */
436
/* 0.000000 0.000000 [7] */
438
projectionMatrix[0] = (2.0f*near_)/(right-left) ;
439
projectionMatrix[1] = 0.0f ;
440
projectionMatrix[2] = 0.0f ;
441
projectionMatrix[3] = 0.0f ;
443
projectionMatrix[4] = 0.0f ;
444
projectionMatrix[5] = (2.0f*near_)/(top-bottom) ;
445
projectionMatrix[6] = 0.0f ;
446
projectionMatrix[7] = 0.0f ;
448
projectionMatrix[8] = (right+left)/(right-left) ;
449
projectionMatrix[9] = (top+bottom)/(top-bottom) ;
450
projectionMatrix[10] = -((far_+near_)/(far_-near_)) ;
451
projectionMatrix[11] = -1.0f ;
453
projectionMatrix[12] = 0.0f ;
454
projectionMatrix[13] = 0.0f ;
455
projectionMatrix[14] = -((2.0f*far_*near_)/(far_-near_)) ;
456
projectionMatrix[15] = 0.0f ;
460
for (xxx = 0; xxx < 16; xxx++)
461
printf("%f ", projectionMatrix[xxx]) ;
464
printf("Vars : %f %f %f %f %f %f\n", left, right, top, bottom, near, far) ;
465
printf("Camera : %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n",
466
uToF((workingList[i+0] & 0xffff0000) >> 16)*128, uToF( workingList[i+0] & 0x0000ffff)*128,
467
uToF((workingList[i+1] & 0xffff0000) >> 16)*128, uToF( workingList[i+1] & 0x0000ffff)*128,
469
uToF((workingList[i+2] & 0xffff0000) >> 16)*128, uToF( workingList[i+2] & 0x0000ffff)*128,
470
uToF((workingList[i+3] & 0xffff0000) >> 16)*128, uToF( workingList[i+3] & 0x0000ffff)*128,
472
uToF((workingList[i+4] & 0xffff0000) >> 16)*128, uToF( workingList[i+4] & 0x0000ffff)*128,
473
uToF((workingList[i+5] & 0xffff0000) >> 16)*128, uToF( workingList[i+5] & 0x0000ffff)*128,
475
uToF((workingList[i+6] & 0xffff0000) >> 16)*128, uToF( workingList[i+6] & 0x0000ffff)*128,
476
uToF((workingList[i+7] & 0xffff0000) >> 16)*128, uToF( workingList[i+7] & 0x0000ffff)*128) ;
482
/* CAMERA TRANSFORMATION MATRIX */
483
cameraMatrix[0] = uToF( workingList[i+0] & 0x0000ffff) ;
484
cameraMatrix[4] = uToF((workingList[i+1] & 0xffff0000) >> 16) ;
485
cameraMatrix[8] = uToF( workingList[i+1] & 0x0000ffff) ;
486
cameraMatrix[3] = 0.0f ;
488
cameraMatrix[1] = uToF((workingList[i+2] & 0xffff0000) >> 16) ;
489
cameraMatrix[5] = uToF( workingList[i+2] & 0x0000ffff) ;
490
cameraMatrix[9] = uToF((workingList[i+3] & 0xffff0000) >> 16) ;
491
cameraMatrix[7] = 0.0f ;
493
cameraMatrix[2] = uToF( workingList[i+3] & 0x0000ffff) ;
494
cameraMatrix[6] = uToF((workingList[i+4] & 0xffff0000) >> 16) ;
495
cameraMatrix[10] = uToF( workingList[i+4] & 0x0000ffff) ;
496
cameraMatrix[11] = 0.0f ;
498
cameraMatrix[12] = uToF((workingList[i+5] & 0xffff0000) >> 16) ;
499
cameraMatrix[13] = uToF( workingList[i+5] & 0x0000ffff) ;
500
cameraMatrix[14] = uToF((workingList[i+6] & 0xffff0000) >> 16) ;
501
cameraMatrix[15] = 1.0f ;
505
/* UNKNOWN - light maybe */
510
/* 00110000 00000000 00000100 01000100 0400-0000 00007fff 00000000 00000020 */
511
/* ---- pal ---- -------- -------- -------- not used (known) */
512
paletteState = (workingList[i+4] & 0xff000000) >> 24 ;
520
threeDRoms = memory_region(REGION_GFX4) ;
522
/*/////////////////////// */
523
/* GET THE HEADER INFO // */
524
/*/////////////////////// */
527
/* !!! This might be more than just 20 bits... */
528
threeDOffset = workingList[i+1] & 0x000fffff ;
529
threeDOffset = (threeDOffset<<1) * 3 ;
531
threeDPointer = &threeDRoms[threeDOffset] ;
534
/* 66 byte versus 48 byte chunk flag */
535
/* WRONG ! I think it's something to do with lighting... */
536
/* it's 0 for the 66-byte lit globe in the character select and 0 for something in terry's hand... */
537
/* if (workingList[i+0] & 0x00000010) */
540
/*//////////////////////////////////////// */
541
/* GET THE OBJECT TRANSFORMATION MATRIX // */
542
/*//////////////////////////////////////// */
544
objectMatrix[8 ] = uToF( workingList[i+3] & 0x0000ffff) ;
545
objectMatrix[4 ] = uToF((workingList[i+4] & 0xffff0000) >> 16) ;
546
objectMatrix[0 ] = uToF( workingList[i+4] & 0x0000ffff) ;
547
objectMatrix[3] = 0.0f ;
549
objectMatrix[9 ] = uToF((workingList[i+5] & 0xffff0000) >> 16) ;
550
objectMatrix[5 ] = uToF( workingList[i+5] & 0x0000ffff) ;
551
objectMatrix[1 ] = uToF((workingList[i+6] & 0xffff0000) >> 16) ;
552
objectMatrix[7] = 0.0f ;
554
objectMatrix[10] = uToF( workingList[i+6] & 0x0000ffff) ;
555
objectMatrix[6 ] = uToF((workingList[i+7] & 0xffff0000) >> 16) ;
556
objectMatrix[2 ] = uToF( workingList[i+7] & 0x0000ffff) ;
557
objectMatrix[11] = 0.0f ;
559
objectMatrix[12] = uToF((workingList[i+2] & 0xffff0000) >> 16) ;
560
objectMatrix[13] = uToF( workingList[i+2] & 0x0000ffff) ;
561
objectMatrix[14] = uToF((workingList[i+3] & 0xffff0000) >> 16) ;
562
objectMatrix[15] = 1.0f ;
566
/*//////////////////////////////////////////////////////// */
567
/* EXTRACT DATA FROM THE ADDRESS POINTED TO IN THE FILE // */
568
/*//////////////////////////////////////////////////////// */
570
/* Okay, there are 4 hunks per address. They all seem good too... */
572
/* First tell me how many 'chunks' are at each address... */
573
size[0] = WORD_AT( threeDPointer, ( 6<<1) ) ;
574
size[1] = WORD_AT( threeDPointer, ( 7<<1) ) ;
575
size[2] = WORD_AT( threeDPointer, ( 9<<1) ) ;
576
size[3] = WORD_AT( threeDPointer, (10<<1) ) ;
578
megaOffset = ( WORD_AT(threeDRoms, (threeDOffset + 4)) ) << 16 ;
579
address[0] = megaOffset | WORD_AT(threeDPointer, (0<<1)) ;
580
address[1] = megaOffset | WORD_AT(threeDPointer, (1<<1)) ;
581
address[2] = megaOffset | WORD_AT(threeDPointer, (3<<1)) ;
582
address[3] = megaOffset | WORD_AT(threeDPointer, (4<<1)) ;
585
/* printf("%.5x %.3x %.5x %.3x %.5x %.3x %.5x %.3x\n", address[0], size[0], address[1], size[1], address[2], size[2], address[3], size[3]) ; */
586
/* !! END DEBUG !! */
590
/*////////////////////////////////// */
591
/* A FEW 'GLOBAL' TRANSFORMATIONS // */
592
/*////////////////////////////////// */
594
/* Now perform the world transformations... */
595
/* !! Can eliminate this step with a matrix stack (maybe necessary?) !! */
596
SetIdentity(modelViewMatrix) ;
597
matmul4(modelViewMatrix, modelViewMatrix, cameraMatrix) ;
598
matmul4(modelViewMatrix, modelViewMatrix, objectMatrix) ;
600
for (k = 0; k < 4; k++) /* For all 4 chunks */
602
threeDPointer = &threeDRoms[(address[k]<<1) * 3] ;
604
for (l = 0; l < size[k]; l++)
606
/*////////////////////////////////////////// */
607
/* GATHER A SINGLE TRIANGLE'S INFORMATION // */
608
/*////////////////////////////////////////// */
610
UINT8 triangleType = threeDPointer[1] ;
612
UINT8 numVertices = 3 ;
613
UINT8 chunkLength = 0 ;
615
/* Some chunks only have 1 vertex (they act as a vertex fan) */
616
if (triangleType == 0x97 ||
617
triangleType == 0x87 ||
618
triangleType == 0xd7 ||
619
triangleType == 0x96)
622
/* Get which texture this polygon refers to... */
623
/* In fatfur it's 0xc for the smooth-shaded earth - maybe this is for all things with alpha - check the hair at some point... */
624
/* 0x9 for the untextured buildings */
625
/* 0xd for the 'explosion' of the HNG64 */
626
/* and 0x8 everywhere else... */
627
/* they're 0x8 in the buriki intro too (those are 66-byte chunks!) */
628
polys[numPolys].texType = ((threeDPointer[2] & 0xf0) >> 4);
630
if (polys[numPolys].texType == 0x8 || polys[numPolys].texType == 0xc) /* || polys[numPolys].texType == 0x9 */
631
polys[numPolys].texIndex = threeDPointer[3] & 0x0f ;
633
polys[numPolys].texIndex = -1 ;
635
/* Set the polygon's palette */
636
polys[numPolys].palIndex = paletteState ;
638
for (m = 0; m < numVertices; m++) /* For all vertices of the chunk */
645
polys[numPolys].vert[m].worldCoords[0] = uToF(WORD_AT(threeDPointer, ((3<<1) + (6<<1)*m)) ) ;
646
polys[numPolys].vert[m].worldCoords[1] = uToF(WORD_AT(threeDPointer, ((4<<1) + (6<<1)*m)) ) ;
647
polys[numPolys].vert[m].worldCoords[2] = uToF(WORD_AT(threeDPointer, ((5<<1) + (6<<1)*m)) ) ;
648
polys[numPolys].vert[m].worldCoords[3] = 1.0f ;
649
polys[numPolys].n = 3 ;
651
/* !! What is the first coordinate here (6) - maybe denotes size of chunk? !! */
652
polys[numPolys].vert[m].texCoords[0] = uToF(WORD_AT(threeDPointer, ((7<<1) + (6<<1)*m)) ) ;
653
polys[numPolys].vert[m].texCoords[1] = uToF(WORD_AT(threeDPointer, ((8<<1) + (6<<1)*m)) ) ;
654
polys[numPolys].vert[m].texCoords[2] = 0.0f ;
655
polys[numPolys].vert[m].texCoords[3] = 1.0f ;
657
polys[numPolys].vert[m].normal[0] = uToF(WORD_AT(threeDPointer, (21<<1) )) ;
658
polys[numPolys].vert[m].normal[1] = uToF(WORD_AT(threeDPointer, (22<<1) )) ;
659
polys[numPolys].vert[m].normal[2] = uToF(WORD_AT(threeDPointer, (23<<1) )) ;
660
polys[numPolys].vert[m].normal[3] = 0.0f ;
663
polys[numPolys].vert[m].light[0] = polys[numPolys].vert[m].texCoords[0] * 255.0f ;
664
polys[numPolys].vert[m].light[1] = polys[numPolys].vert[m].texCoords[1] * 255.0f ;
665
polys[numPolys].vert[m].light[2] = polys[numPolys].vert[m].texCoords[2] * 255.0f ;
667
/* Redundantly called, but it works... */
668
polys[numPolys].faceNormal[0] = polys[numPolys].vert[m].normal[0] ;
669
polys[numPolys].faceNormal[1] = polys[numPolys].vert[m].normal[1] ;
670
polys[numPolys].faceNormal[2] = polys[numPolys].vert[m].normal[2] ;
671
polys[numPolys].faceNormal[3] = 0.0f ;
673
chunkLength = (24<<1) ;
679
polys[numPolys].vert[m].worldCoords[0] = uToF(WORD_AT(threeDPointer, ((3<<1) + (9<<1)*m)) ) ;
680
polys[numPolys].vert[m].worldCoords[1] = uToF(WORD_AT(threeDPointer, ((4<<1) + (9<<1)*m)) ) ;
681
polys[numPolys].vert[m].worldCoords[2] = uToF(WORD_AT(threeDPointer, ((5<<1) + (9<<1)*m)) ) ;
682
polys[numPolys].vert[m].worldCoords[3] = 1.0f ;
683
polys[numPolys].n = 3 ;
685
/* !! See above - (6) - why? !! */
686
polys[numPolys].vert[m].texCoords[0] = uToF(WORD_AT(threeDPointer, ((7<<1) + (9<<1)*m)) ) ;
687
polys[numPolys].vert[m].texCoords[1] = uToF(WORD_AT(threeDPointer, ((8<<1) + (9<<1)*m)) ) ;
688
polys[numPolys].vert[m].texCoords[2] = 0.0f ;
689
polys[numPolys].vert[m].texCoords[3] = 1.0f ;
691
polys[numPolys].vert[m].normal[0] = uToF(WORD_AT(threeDPointer, ((9<<1) + (9<<1)*m)) ) ;
692
polys[numPolys].vert[m].normal[1] = uToF(WORD_AT(threeDPointer, ((10<<1) + (9<<1)*m)) ) ;
693
polys[numPolys].vert[m].normal[2] = uToF(WORD_AT(threeDPointer, ((11<<1) + (9<<1)*m)) ) ;
694
polys[numPolys].vert[m].normal[3] = 0.0f ;
697
polys[numPolys].vert[m].light[0] = polys[numPolys].vert[m].texCoords[0] * 255.0f ;
698
polys[numPolys].vert[m].light[1] = polys[numPolys].vert[m].texCoords[1] * 255.0f ;
699
polys[numPolys].vert[m].light[2] = polys[numPolys].vert[m].texCoords[2] * 255.0f ;
701
/* Redundantly called, but it works... */
702
polys[numPolys].faceNormal[0] = uToF(WORD_AT(threeDPointer, (30<<1) )) ;
703
polys[numPolys].faceNormal[1] = uToF(WORD_AT(threeDPointer, (31<<1) )) ;
704
polys[numPolys].faceNormal[2] = uToF(WORD_AT(threeDPointer, (32<<1) )) ;
705
polys[numPolys].faceNormal[3] = 0.0f ;
707
chunkLength = (33<<1) ;
715
/* Copy over the proper vertices from the previous triangle... */
716
memcpy(&polys[numPolys].vert[1], &lastPoly.vert[0], sizeof(struct polyVert)) ;
717
memcpy(&polys[numPolys].vert[2], &lastPoly.vert[2], sizeof(struct polyVert)) ;
719
/* Fill in the appropriate data... */
720
polys[numPolys].vert[0].worldCoords[0] = uToF(WORD_AT(threeDPointer, (3<<1) )) ;
721
polys[numPolys].vert[0].worldCoords[1] = uToF(WORD_AT(threeDPointer, (4<<1) )) ;
722
polys[numPolys].vert[0].worldCoords[2] = uToF(WORD_AT(threeDPointer, (5<<1) )) ;
723
polys[numPolys].vert[0].worldCoords[3] = 1.0f ;
724
polys[numPolys].n = 3 ;
726
/* !! See above - (6) - why? !! */
727
polys[numPolys].vert[0].texCoords[0] = uToF(WORD_AT(threeDPointer, (7<<1) )) ;
728
polys[numPolys].vert[0].texCoords[1] = uToF(WORD_AT(threeDPointer, (8<<1) )) ;
729
polys[numPolys].vert[0].texCoords[2] = 0.0f ;
730
polys[numPolys].vert[0].texCoords[3] = 1.0f ;
732
polys[numPolys].vert[0].normal[0] = uToF(WORD_AT(threeDPointer, (9<<1) )) ;
733
polys[numPolys].vert[0].normal[1] = uToF(WORD_AT(threeDPointer, (10<<1) )) ;
734
polys[numPolys].vert[0].normal[2] = uToF(WORD_AT(threeDPointer, (11<<1) )) ;
735
polys[numPolys].vert[0].normal[3] = 0.0f ;
737
polys[numPolys].vert[0].light[0] = polys[numPolys].vert[0].texCoords[0] * 255.0f ;
738
polys[numPolys].vert[0].light[1] = polys[numPolys].vert[0].texCoords[1] * 255.0f ;
739
polys[numPolys].vert[0].light[2] = polys[numPolys].vert[0].texCoords[2] * 255.0f ;
741
polys[numPolys].faceNormal[0] = uToF(WORD_AT(threeDPointer, (12<<1) )) ;
742
polys[numPolys].faceNormal[1] = uToF(WORD_AT(threeDPointer, (13<<1) )) ;
743
polys[numPolys].faceNormal[2] = uToF(WORD_AT(threeDPointer, (14<<1) )) ;
744
polys[numPolys].faceNormal[3] = 0.0f ;
746
chunkLength = (15<<1) ;
752
/* Copy over the proper vertices from the previous triangle... */
753
memcpy(&polys[numPolys].vert[1], &lastPoly.vert[0], sizeof(struct polyVert)) ;
754
memcpy(&polys[numPolys].vert[2], &lastPoly.vert[2], sizeof(struct polyVert)) ;
756
/* !!! Too lazy to have finished this yet !!! */
758
polys[numPolys].vert[0].worldCoords[0] = uToF(WORD_AT(threeDPointer, (3<<1))) ;
759
polys[numPolys].vert[0].worldCoords[1] = uToF(WORD_AT(threeDPointer, (4<<1))) ;
760
polys[numPolys].vert[0].worldCoords[2] = uToF(WORD_AT(threeDPointer, (5<<1))) ;
761
polys[numPolys].vert[0].worldCoords[3] = 1.0f ;
762
polys[numPolys].n = 3 ;
764
/* !! See above - (6) - why? !! */
765
polys[numPolys].vert[0].texCoords[0] = uToF(WORD_AT(threeDPointer, (7<<1))) ;
766
polys[numPolys].vert[0].texCoords[1] = uToF(WORD_AT(threeDPointer, (8<<1))) ;
767
polys[numPolys].vert[0].texCoords[2] = 0.0f ;
768
polys[numPolys].vert[0].texCoords[3] = 1.0f ;
771
polys[numPolys].vert[0].light[0] = polys[numPolys].vert[0].texCoords[0] * 255.0f ;
772
polys[numPolys].vert[0].light[1] = polys[numPolys].vert[0].texCoords[1] * 255.0f ;
773
polys[numPolys].vert[0].light[2] = polys[numPolys].vert[0].texCoords[2] * 255.0f ;
775
/* This normal could be right, but I'm not entirely sure - there is no normal in the 18 bytes! */
776
polys[numPolys].vert[0].normal[0] = lastPoly.faceNormal[0] ;
777
polys[numPolys].vert[0].normal[1] = lastPoly.faceNormal[1] ;
778
polys[numPolys].vert[0].normal[2] = lastPoly.faceNormal[2] ;
779
polys[numPolys].vert[0].normal[3] = lastPoly.faceNormal[3] ;
781
polys[numPolys].faceNormal[0] = lastPoly.faceNormal[0] ;
782
polys[numPolys].faceNormal[1] = lastPoly.faceNormal[1] ;
783
polys[numPolys].faceNormal[2] = lastPoly.faceNormal[2] ;
784
polys[numPolys].faceNormal[3] = lastPoly.faceNormal[3] ;
786
chunkLength = (9<<1) ;
790
printf("UNKNOWN geometry CHUNK TYPE : %x\n", triangleType) ;
795
polys[numPolys].visible = 1 ;
797
memcpy(&lastPoly, &polys[numPolys], sizeof(struct polygon)) ;
802
/* THE HNG64 HARDWARE DOES NOT SEEM TO BACKFACE CULL // */
804
/*///////////////// */
805
/* BACKFACE CULL // */
806
/*///////////////// */
811
// Cast a ray out of the camera towards the polygon's point in eyespace.
812
vecmatmul4(cullRay, modelViewMatrix, polys[numPolys].vert[0].worldCoords) ;
814
// Dot product that with the normal to see if you're negative...
815
vecmatmul4(cullNorm, modelViewMatrix, polys[numPolys].faceNormal) ;
817
float result = vecDotProduct(cullRay, cullNorm) ;
820
polys[numPolys].visible = 1 ;
822
polys[numPolys].visible = 0 ;
825
/*////////////////////////// */
826
/* BEHIND-THE-CAMERA CULL // */
827
/*////////////////////////// */
828
vecmatmul4(cullRay, modelViewMatrix, polys[numPolys].vert[0].worldCoords) ;
830
if (cullRay[2] > 0.0f) /* Camera is pointing down -Z */
832
polys[numPolys].visible = 0 ;
836
/*//////////////////////////////////////////////////////// */
837
/* TRANSFORM THE TRIANGLE INTO HOMOGENEOUS SCREEN SPACE // */
838
/*//////////////////////////////////////////////////////// */
840
if (polys[numPolys].visible)
842
for (m = 0; m < polys[numPolys].n; m++)
844
/* Transform and project the vertex into pre-divided homogeneous coordinates... */
845
vecmatmul4(eyeCoords, modelViewMatrix, polys[numPolys].vert[m].worldCoords) ;
846
vecmatmul4(polys[numPolys].vert[m].clipCoords, projectionMatrix, eyeCoords) ;
849
if (polys[numPolys].visible)
851
/* Clip the triangles to the view frustum... */
852
PerformFrustumClip(&polys[numPolys]) ;
854
for (m = 0; m < polys[numPolys].n; m++)
856
/* Convert into normalized device coordinates... */
857
ndCoords[0] = polys[numPolys].vert[m].clipCoords[0] / polys[numPolys].vert[m].clipCoords[3] ;
858
ndCoords[1] = polys[numPolys].vert[m].clipCoords[1] / polys[numPolys].vert[m].clipCoords[3] ;
859
ndCoords[2] = polys[numPolys].vert[m].clipCoords[2] / polys[numPolys].vert[m].clipCoords[3] ;
860
ndCoords[3] = polys[numPolys].vert[m].clipCoords[3] ;
862
/* Final pixel values are garnered here : */
863
windowCoords[0] = (ndCoords[0]+1.0f) * ((float)(Machine->visible_area.max_x) / 2.0f) + 0.0f ;
864
windowCoords[1] = (ndCoords[1]+1.0f) * ((float)(Machine->visible_area.max_y) / 2.0f) + 0.0f ;
865
windowCoords[2] = (ndCoords[2]+1.0f) * 0.5f ;
867
windowCoords[1] = (float)Machine->visible_area.max_y - windowCoords[1] ; /* Flip Y */
869
/* Store the points in a list for later use... */
870
polys[numPolys].vert[m].clipCoords[0] = windowCoords[0] ;
871
polys[numPolys].vert[m].clipCoords[1] = windowCoords[1] ;
872
polys[numPolys].vert[m].clipCoords[2] = windowCoords[2] ;
873
polys[numPolys].vert[m].clipCoords[3] = ndCoords[3] ;
881
if (chunkLength == (9 << 1))
884
for (int ajg = 0; ajg < chunkLength; ajg+=2)
885
printf("%.2x%.2x ", threeDPointer[ajg], threeDPointer[ajg+1]) ;
891
/* Advance to the next polygon chunk... */
892
threeDPointer += chunkLength ;
894
numPolys++ ; /* Add one more to the display list... */
905
/* Don't forget about this !!! */
906
/*printf(" %.8x\n\n", (UINT32)hng64_dls[j][0x80]) ; */
911
/*/////////////////////////////////////////////// */
912
/* FINALLY RENDER THE TRIANGLES INTO THE FRAME // */
913
/*/////////////////////////////////////////////// */
915
/* Reset the depth buffer... */
916
for (i = 0; i < (Machine->visible_area.max_x)*(Machine->visible_area.max_y); i++)
917
depthBuffer[i] = 100.0f ;
919
for (i = 0; i < numPolys; i++)
921
if (polys[i].visible)
923
/*DrawWireframe(&polys[i], bitmap) ; */
924
DrawShaded(&polys[i], bitmap) ;
928
/* usrintf_showmessage("%d", numPolys) ; */
930
/* Clear each of the display list buffers after drawing... */
931
for (i = 0; i < 0x81; i++)
933
hng64_dls[0][i] = 0 ;
934
hng64_dls[1][i] = 0 ;
939
/* 8x8 tiles, 4bpp layer */
940
static void get_hng64_tile0_info(int tile_index)
943
tileno = hng64_videoram[tile_index];
944
pal = hng64_videoram[tile_index]>>24;
945
SET_TILE_INFO((tileno&1)?0:1,(tileno&0x3fffff)>>1,pal,TILE_FLIPYX((tileno&0xc00000)>>22))
948
/* 16x16 tiles, 8bpp layer */
949
static void get_hng64_tile1_info(int tile_index)
952
tileno = hng64_videoram[tile_index+(0x10000/4)];
953
pal = hng64_videoram[tile_index+(0x10000/4)]>>24;
955
SET_TILE_INFO(3,(tileno&0x3fffff)>>3,pal>>4, TILE_FLIPYX((tileno&0xc00000)>>22) )
958
/* 16x16 tiles, 8bpp layer */
959
static void get_hng64_tile2_info(int tile_index)
962
tileno = hng64_videoram[tile_index+(0x20000/4)];
963
pal = hng64_videoram[tile_index+(0x20000/4)]>>24;
964
SET_TILE_INFO(3,(tileno&0x3fffff)>>3,pal>>4,TILE_FLIPYX((tileno&0xc00000)>>22))
967
/* 16x16 tiles, 8bpp layer */
968
static void get_hng64_tile3_info(int tile_index)
971
tileno = hng64_videoram[tile_index+(0x30000/4)];
972
pal = hng64_videoram[tile_index+(0x30000/4)]>>24;
973
SET_TILE_INFO(3,(tileno&0x3fffff)>>3,pal>>4,TILE_FLIPYX((tileno&0xc00000)>>22))
978
/* Tilemaps zoom, and probably rotate.. they can have linescroll/lineselect,
979
looks like the zoom center can move too..
980
not sure how these features are enabled up yet */
982
static int gatherPixelsForLine(mame_bitmap *tilemapBitmap,
983
INT32 startX, INT32 startY, INT32 endX, INT32 endY,
988
/* !! BRESENHAM'S AGAIN - I REALLY SHOULD GENERALIZE THIS !! */
990
#define SWAP(a,b) tmpswap = a; a = b; b = tmpswap;
994
INT32 sx, sy; /* step positive or negative (1 or -1) */
995
INT32 dx, dy; /* delta (difference in X and Y between points) */
999
* inline swap. On some architectures, the XOR trick may be faster
1004
* optimize for vertical and horizontal lines here
1007
dx = abs(endX - startX);
1008
sx = ((endX - startX) > 0) ? 1 : -1;
1009
dy = abs(endY - startY);
1010
sy = ((endY - startY) > 0) ? 1 : -1;
1015
SWAP(startX, startY);
1022
for (i = 0; i < dx; i++)
1026
penList[retVal] = ((UINT16*)tilemapBitmap->line[startY])[startX] ;
1031
penList[retVal] = ((UINT16*)tilemapBitmap->line[startX])[startY] ;
1049
static void plotTilemap3Line(mame_bitmap *tilemapBitmap,
1050
INT32 startX, INT32 startY, INT32 endX, INT32 endY,
1051
INT32 screenY, mame_bitmap *bitmap)
1057
UINT16 penList[0x1000] ; /* 4k of pixels to be safe */
1059
float pixStride, pixOffset ;
1061
/* printf("(%d,%d) (%d,%d)\n", startX, startY, endX, endY) ; */
1063
/* CLAMP - BUT I'M PRETTY SURE THIS ISN'T QUITE RIGHT !!! ??? */
1064
startX += 1024 ; if (startX < 0) startX = 0 ; else if (startX > 2048) startX = 2048 ;
1065
startY += 1024 ; if (startY < 0) startY = 0 ; else if (startY > 2048) startY = 2048 ;
1066
endX += 1024 ; if (endX < 0) endX = 0 ; else if (endX > 2048) endX = 2048 ;
1067
endY += 1024 ; if (endY < 0) endY = 0 ; else if (endY > 2048) endY = 2048 ;
1069
numPix = gatherPixelsForLine(tilemapBitmap, startX, startY, endX, endY, penList) ;
1071
pixStride = (float)numPix / (float)(Machine->visible_area.max_x-1) ;
1075
penList[0] = ((UINT16*)tilemapBitmap->line[1024])[1024] ;
1077
/* printf("numpix %d ps %f po %f s(%d,%d) e(%d,%d)\n", numPix, pixStride, pixOffset, startX, startY, endX, endY) ; */
1079
/* Draw out the screen's line... */
1080
for (i = Machine->visible_area.min_x; i < Machine->visible_area.max_x; i++)
1082
/* Nearest-neighbor interpolation for now (but i doubt it does linear) */
1083
UINT16 tmPen = penList[(int)pixOffset] ;
1084
palette_get_color(tmPen, &r, &g, &b);
1086
((UINT32 *)(bitmap->line[screenY]))[i] = MAKE_ARGB((UINT8)255, (UINT8)r, (UINT8)g, (UINT8)b) ;
1088
pixOffset += pixStride ;
1092
static void hng64_drawtilemap3( mame_bitmap *bitmap, const rectangle *cliprect )
1096
mame_bitmap *srcbitmap = tilemap_get_pixmap( hng64_tilemap3 );
1098
/* usrintf_showmessage("%d", hackTm3Count) ; */
1100
if (hackTm3Count/4 < Machine->visible_area.max_y)
1102
for (i = 0; i < hackTm3Count/4; i++)
1104
UINT32 address = rowScrollOffset + 0xbf0 ;
1105
address -= (i * 0x10) ;
1107
/*printf("nums : %.4x %.4x %.4x %.4x\n", (INT16)((hng64_videoram[address+0x0]&0xffff0000) >> 16), */
1108
/* (INT16)((hng64_videoram[address+0x1]&0xffff0000) >> 16), */
1109
/* (INT16)((hng64_videoram[address+0x2]&0xffff0000) >> 16), */
1110
/* (INT16)((hng64_videoram[address+0x3]&0xffff0000) >> 16)) ; */
1112
plotTilemap3Line(srcbitmap,
1113
(INT16)((hng64_videoram[address+0x0]&0xffff0000) >> 16),
1114
(INT16)((hng64_videoram[address+0x2]&0xffff0000) >> 16),
1115
(INT16)((hng64_videoram[address+0x1]&0xffff0000) >> 16),
1116
(INT16)((hng64_videoram[address+0x3]&0xffff0000) >> 16),
1117
(Machine->visible_area.max_y-1)-i,
1122
/* Maybe the scrollbase should be used instead of my hacky rowScrollOffset :)? */
1123
/* scrollbase = (hng64_videoregs[0x05]&0x00003fff)>>0; */
1125
/* xscroll = hng64_videoram[(0x40000+(scrollbase<<4))/4]>>16; */
1126
/* yscroll = hng64_videoram[(0x40008+(scrollbase<<4))/4]>>16; */
1127
/* xzoom = hng64_videoram[(0x40010+(scrollbase<<4))/4]>>16; */
1128
/* yzoom = hng64_videoram[(0x4000c+(scrollbase<<4))/4]>>16; */
1129
/* xzoom = xzoom-xscroll; */
1130
/* yzoom = yzoom-yscroll; */
1131
/* xzoom &=0xffff; */
1132
/* yzoom &=0xffff; */
1134
/* xscroll <<=16; */
1135
/* yscroll <<=16; */
1139
/* tilemap_set_scrollx(hng64_tilemap3,0, xscroll); */
1140
/* tilemap_set_scrolly(hng64_tilemap3,0, yscroll); */
1142
/* tilemap_draw(bitmap,cliprect,hng64_tilemap3,0,0); */
1144
/* tilemap_draw_roz(bitmap,cliprect,hng64_tilemap3,xscroll,yscroll, */
1145
/* xzoom,0,0,yzoom, */
1150
static void hng64_drawtilemap2( mame_bitmap *bitmap, const rectangle *cliprect )
1152
int scrollbase,xscroll,yscroll,xzoom,yzoom;
1154
scrollbase = (hng64_videoregs[0x05]&0x3fff0000)>>16;
1155
xscroll = (INT16)(hng64_videoram[(0x40000+(scrollbase<<4))/4]>>16);
1156
/* ??? = (INT16)(hng64_videoram[(0x40004+(scrollbase<<4))/4]>>16); */
1157
yscroll = (INT16)(hng64_videoram[(0x40008+(scrollbase<<4))/4]>>16);
1158
yzoom = (INT16)(hng64_videoram[(0x4000c+(scrollbase<<4))/4]>>16);
1159
xzoom = (INT16)(hng64_videoram[(0x40010+(scrollbase<<4))/4]>>16);
1160
/* ??? = (INT16)(hng64_videoram[(0x40014+(scrollbase<<4))/4]>>16); */
1161
/* ??? = (INT16)(hng64_videoram[(0x40018+(scrollbase<<4))/4]>>16); */
1162
/* ??? = (INT16)(hng64_videoram[(0x4001c+(scrollbase<<4))/4]>>16); */
1163
xzoom = xzoom-xscroll;
1164
yzoom = yzoom-yscroll;
1173
tilemap_draw_roz(bitmap,cliprect,hng64_tilemap2,xscroll,yscroll,
1179
static void hng64_drawtilemap1( mame_bitmap *bitmap, const rectangle *cliprect )
1181
int scrollbase,xscroll,yscroll,xzoom,yzoom;
1183
scrollbase = (hng64_videoregs[0x04]&0x00003fff)>>0;
1184
xscroll = (INT16)(hng64_videoram[(0x40000+(scrollbase<<4))/4]>>16);
1185
/* ??? = (INT16)(hng64_videoram[(0x40004+(scrollbase<<4))/4]>>16); */
1186
yscroll = (INT16)(hng64_videoram[(0x40008+(scrollbase<<4))/4]>>16);
1187
xzoom = (INT16)(hng64_videoram[(0x40010+(scrollbase<<4))/4]>>16);
1188
yzoom = (INT16)(hng64_videoram[(0x4000c+(scrollbase<<4))/4]>>16);
1189
/* ??? = (INT16)(hng64_videoram[(0x40014+(scrollbase<<4))/4]>>16); */
1190
/* ??? = (INT16)(hng64_videoram[(0x40018+(scrollbase<<4))/4]>>16); */
1191
/* ??? = (INT16)(hng64_videoram[(0x4001c+(scrollbase<<4))/4]>>16); */
1192
xzoom = xzoom-xscroll;
1193
yzoom = yzoom-yscroll;
1202
tilemap_draw_roz(bitmap,cliprect,hng64_tilemap1,xscroll,yscroll,
1212
* ------------------
1214
* UINT32 | Bytes | Use
1215
* -------+-76543210-+----------------
1216
* 0 | oooooooo | unknown - always seems to be 04060000 (fatfurwa) and 00060000 (buriki)
1217
* 1 | xxxx---- | looks like it's 0001 most (all) of the time - turns off in buriki intro
1218
* 1 | ----oooo | unknown - always seems to be 0000 (fatfurwa)
1219
* 2 | oooooooo | unknown - likes to change sometimes though... (looks like bit-flags)
1220
* 3 | oooooooo | unknown - change a lot - maybe mixer flags?
1221
* 4 | xxxx---- | tilemap0 offset into tilemap RAM?
1222
* 4 | ----xxxx | tilemap1 offset into tilemap RAM
1223
* 5 | xxxx---- | tilemap3 offset into tilemap RAM
1224
* 5 | ----xxxx | tilemap4 offset into tilemap RAM?
1225
* 6 | oooooooo | unknown - always seems to be 000001ff (fatfurwa)
1226
* 7 | oooooooo | unknown - always seems to be 000001ff (fatfurwa)
1227
* 8 | oooooooo | unknown - always seems to be 80008000 (fatfurwa)
1228
* 9 | oooooooo | unknown - always seems to be 00000000 (fatfurwa)
1229
* a | oooooooo | unknown - always seems to be 00000000 (fatfurwa)
1230
* b | oooooooo | unknown - 00000000 in intro - 00007ff8 when fight is going on (looks like &'ing it with 0x3fff is a good thing to do - tilemap stuff?)
1231
* c | xxxxxxxx | I'm almost positive this is some form of offset to produce animations in Tilemap1 - or maybe all tilemaps?
1232
* - 00xxx000 are used in fatfurwa during fights
1233
* - 00000?xx are used in buriki during the intro
1234
* d | oooooooo | not used ??
1235
* e | oooooooo | not used ??
1239
VIDEO_UPDATE( hng64 )
1241
fillbitmap(bitmap, get_black_pen(), 0);
1244
/* for (int iii = 0; iii < 0x0f; iii++) */
1245
/* printf("%.8x ", hng64_videoregs[iii]) ; */
1246
/* printf("\n") ; */
1247
/* usrintf_showmessage("%.8x %.8x %.8x %.8x", hng64_videoregs[0x1], hng64_videoregs[0x3], hng64_videoregs[0xb], hng64_videoregs[0xc]) ; */
1249
/* I think there's something to this, but I'm not doing it right... */
1250
/* Interestingly enough, this turns the bootup screen blue :) */
1252
if (hng64_videoregs[0xc] != tilemap2Offset)
1254
tilemap2Offset = hng64_videoregs[0xc] ;
1256
tilemap_dispose(hng64_tilemap1) ;
1257
hng64_tilemap1 = tilemap_create(get_hng64_tile2_info,tilemap_scan_rows,TILEMAP_TRANSPARENT, 16, 16, 128,128); // 128x128x4 = 0x10000
1261
/* Rowscroll variables... */
1262
/* usrintf_showmessage("%.8x %.8x x %.8x %.8x", hng64_videoram[0x00057bf0/4], hng64_videoram[0x00057bf4/4], hng64_videoram[0x00057bf8/4], hng64_videoram[0x00057bfc/4]) ; */
1264
/* All of this priority stuff is probably done with some funky layer mixing chip - */
1265
/* (there are neato alpha effects on a real board, etc) */
1266
hng64_drawtilemap2(bitmap,cliprect);
1267
hng64_drawtilemap1(bitmap,cliprect);
1268
hng64_drawtilemap3(bitmap,cliprect); /* Draw the ground last... */
1270
/* !!! This tilemap has the same flags as the 'previous' three, but they're not used in fatfurwa !!! */
1271
/* (in other words, we should make a similar hng64_drawtilemap0() function for this tilemap) */
1272
tilemap_draw(bitmap,cliprect,hng64_tilemap0,0,0);
1274
hng64_drawsprites(bitmap,cliprect);
1276
/* 3d really shouldn't be last, but you don't see some cool stuff right now if it's put before sprites :)... */
1277
hng64_draw3d(bitmap, cliprect);
1279
/* hack to enable 2nd cpu when key is pressed */
1280
if ( code_pressed_memory(KEYCODE_L) )
1282
cpunum_set_input_line(1, INPUT_LINE_HALT, CLEAR_LINE);
1283
cpunum_set_input_line(1, INPUT_LINE_RESET, CLEAR_LINE);
1287
/* if(code_pressed(KEYCODE_D)) */
1289
hng64_transition_control(bitmap) ;
1291
/* printf("FRAME DONE %d\n", frameCount) ; */
1294
hackTilemap3 = rowScrollOffset = hackTm3Count = 0 ;
1297
VIDEO_START( hng64 )
1299
hng64_tilemap0 = tilemap_create(get_hng64_tile0_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 8, 8, 128,128); /* 128x128x4 = 0x10000 */
1300
hng64_tilemap1 = tilemap_create(get_hng64_tile1_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 16, 16, 128,128); /* 128x128x4 = 0x10000 */
1301
hng64_tilemap2 = tilemap_create(get_hng64_tile2_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 16, 16, 128,128); /* 128x128x4 = 0x10000 */
1302
hng64_tilemap3 = tilemap_create(get_hng64_tile3_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 16, 16, 128,128); /* 128x128x4 = 0x10000 */
1303
tilemap_set_transparent_pen(hng64_tilemap0,0);
1304
tilemap_set_transparent_pen(hng64_tilemap1,0);
1305
tilemap_set_transparent_pen(hng64_tilemap2,0);
1306
tilemap_set_transparent_pen(hng64_tilemap3,0);
1308
/* 3d Buffer Allocation */
1309
depthBuffer = (float*)auto_malloc((Machine->visible_area.max_x)*(Machine->visible_area.max_y)*sizeof(float)) ;
1311
/* The general display list of polygons in the scene... */
1312
/* !! This really should be a dynamic array !! */
1313
polys = auto_malloc(MAX_ONSCREEN_POLYS * sizeof(struct polygon)) ;
1322
/* 4x4 matrix multiplication */
1323
static void matmul4( float *product, const float *a, const float *b )
1326
for (i = 0; i < 4; i++)
1328
const float ai0 = a[0 + i] ;
1329
const float ai1 = a[4 + i] ;
1330
const float ai2 = a[8 + i] ;
1331
const float ai3 = a[12 + i] ;
1333
product[0 + i] = ai0 * b[0 ] + ai1 * b[1 ] + ai2 * b[2 ] + ai3 * b[3 ] ;
1334
product[4 + i] = ai0 * b[4 ] + ai1 * b[5 ] + ai2 * b[6 ] + ai3 * b[7 ] ;
1335
product[8 + i] = ai0 * b[8 ] + ai1 * b[9 ] + ai2 * b[10] + ai3 * b[11] ;
1336
product[12 + i] = ai0 * b[12] + ai1 * b[13] + ai2 * b[14] + ai3 * b[15] ;
1340
/* vector by 4x4 matrix multiply */
1341
static void vecmatmul4( float *product, const float *a, const float *b)
1343
const float bi0 = b[0] ;
1344
const float bi1 = b[1] ;
1345
const float bi2 = b[2] ;
1346
const float bi3 = b[3] ;
1348
product[0] = bi0 * a[0] + bi1 * a[4] + bi2 * a[8 ] + bi3 * a[12];
1349
product[1] = bi0 * a[1] + bi1 * a[5] + bi2 * a[9 ] + bi3 * a[13];
1350
product[2] = bi0 * a[2] + bi1 * a[6] + bi2 * a[10] + bi3 * a[14];
1351
product[3] = bi0 * a[3] + bi1 * a[7] + bi2 * a[11] + bi3 * a[15];
1354
static float vecDotProduct( const float *a, const float *b)
1356
return ((a[0]*b[0]) + (a[1]*b[1]) + (a[2]*b[2])) ;
1359
static void SetIdentity(float *matrix)
1363
for (i = 0; i < 16; i++)
1368
matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.0f ;
1371
static float uToF(UINT16 input)
1375
retVal = (float)((INT16)input) / 32768.0f ;
1378
if ((INT16)input < 0)
1379
retVal = (float)((INT16)input) / 32768.0f ;
1381
retVal = (float)((INT16)input) / 32767.0f ;
1387
static void normalize(float* x)
1389
double l2 = (x[0]*x[0]) + (x[1]*x[1]) + (x[2]*x[2]);
1392
x[0] = (float)(x[0] / l) ;
1393
x[1] = (float)(x[1] / l) ;
1394
x[2] = (float)(x[2] / l) ;
1399
/*///////////////////////// */
1400
/* POLYGON CLIPPING CODE // */
1401
/*///////////////////////// */
1403
/*///////////////////////////////////////////////////////////////////////////////// */
1404
/* The remainder of the code in this file is heavily // */
1405
/* influenced by, and sometimes copied verbatim from Andrew Zaferakis' SoftGL // */
1406
/* rasterizing system. http://www.cs.unc.edu/~andrewz/comp236/ // */
1408
/* Andrew granted permission for its use in MAME in October of 2004. // */
1409
/*///////////////////////////////////////////////////////////////////////////////// */
1411
/* Refer to the clipping planes as numbers */
1412
#define HNG64_LEFT 0
1413
#define HNG64_RIGHT 1
1415
#define HNG64_BOTTOM 3
1416
#define HNG64_NEAR 4
1420
static int Inside(struct polyVert *v, int plane)
1425
return (v->clipCoords[0] >= -v->clipCoords[3]) ? 1 : 0 ;
1427
return (v->clipCoords[0] <= v->clipCoords[3]) ? 1 : 0 ;
1430
return (v->clipCoords[1] <= v->clipCoords[3]) ? 1 : 0 ;
1432
return (v->clipCoords[1] >= -v->clipCoords[3]) ? 1 : 0 ;
1435
return (v->clipCoords[2] <= v->clipCoords[3]) ? 1 : 0;
1438
return (v->clipCoords[2] >= -v->clipCoords[3]) ? 1 : 0;
1445
static void Intersect(struct polyVert *input0, struct polyVert *input1, struct polyVert *output, int plane)
1449
float *Iv0 = input0->clipCoords ;
1450
float *Iv1 = input1->clipCoords ;
1451
float *Ov = output->clipCoords ;
1453
float *It0 = input0->texCoords ;
1454
float *It1 = input1->texCoords ;
1455
float *Ot = output->texCoords ;
1457
float *Il0 = input0->light ;
1458
float *Il1 = input1->light ;
1459
float *Ol = output->light ;
1464
t = (Iv0[0]+Iv0[3]) / (-Iv1[3]+Iv0[3]-Iv1[0]+Iv0[0]);
1467
t = (Iv0[0]-Iv0[3]) / (Iv1[3]-Iv0[3]-Iv1[0]+Iv0[0]);
1470
t = (Iv0[1]-Iv0[3]) / (Iv1[3]-Iv0[3]-Iv1[1]+Iv0[1]);
1473
t = (Iv0[1]+Iv0[3]) / (-Iv1[3]+Iv0[3]-Iv1[1]+Iv0[1]);
1476
t = (Iv0[2]-Iv0[3]) / (Iv1[3]-Iv0[3]-Iv1[2]+Iv0[2]);
1479
t = (Iv0[2]+Iv0[3]) / (-Iv1[3]+Iv0[3]-Iv1[2]+Iv0[2]);
1483
Ov[0] = Iv0[0] + (Iv1[0] - Iv0[0]) * t ;
1484
Ov[1] = Iv0[1] + (Iv1[1] - Iv0[1]) * t ;
1485
Ov[2] = Iv0[2] + (Iv1[2] - Iv0[2]) * t ;
1486
Ov[3] = Iv0[3] + (Iv1[3] - Iv0[3]) * t ;
1488
Ot[0] = It0[0] + (It1[0] - It0[0]) * t ;
1489
Ot[1] = It0[1] + (It1[1] - It0[1]) * t ;
1490
Ot[2] = It0[2] + (It1[2] - It0[2]) * t ;
1491
Ot[3] = It0[3] + (It1[3] - It0[3]) * t ;
1493
Ol[0] = Il0[0] + (Il1[0] - Il0[0]) * t ;
1494
Ol[1] = Il0[1] + (Il1[1] - Il0[1]) * t ;
1495
Ol[2] = Il0[2] + (Il1[2] - Il0[2]) * t ;
1500
static void PerformFrustumClip(struct polygon *p)
1505
/*//////////////////////////////////////////////////////////////////////// */
1506
/* Clip against the volumes defined by the homogeneous clip coordinates // */
1507
/*//////////////////////////////////////////////////////////////////////// */
1509
struct polygon temp ;
1511
struct polyVert *v0 ;
1512
struct polyVert *v1 ;
1513
struct polyVert *tv ;
1517
/* Skip near and far clipping planes ? */
1518
for (j = 0; j <= HNG64_BOTTOM; j++)
1520
for (i = 0; i < p->n; i++)
1522
k = (i+1) % p->n; /* Index of next vertex */
1527
tv = &temp.vert[temp.n] ;
1529
if (Inside(v0, j) && Inside(v1, j)) /* Edge is completely inside the volume... */
1531
memcpy(tv, v1, sizeof(struct polyVert)) ;
1535
else if (Inside(v0, j) && !Inside(v1, j)) /* Edge goes from in to out... */
1537
Intersect(v0, v1, tv, j) ;
1541
else if (!Inside(v0, j) && Inside(v1, j)) /* Edge goes from out to in... */
1543
Intersect(v0, v1, tv, j) ;
1544
memcpy(&temp.vert[temp.n+1], v1, sizeof(struct polyVert)) ;
1551
for (i = 0; i < temp.n; i++)
1553
memcpy(&p->vert[i], &temp.vert[i], sizeof(struct polyVert)) ;
1561
/*//////////////////////////// */
1562
/* POLYGON RASTERIZING CODE // */
1563
/*//////////////////////////// */
1565
/*/////////////////////// */
1566
/* wireframe rendering // */
1567
/*/////////////////////// */
1569
static void plot(INT32 x, INT32 y, INT32 color, mame_bitmap *bitmap)
1571
((UINT32 *)(bitmap->line[y]))[x] = MAKE_ARGB((UINT8)255, (UINT8)color, (UINT8)color, (UINT8)color) ;
1574
/* Stolen from http://en.wikipedia.org/wiki/Bresenham's_line_algorithm (no copyright denoted) - the non-optimized version */
1575
static void drawline2d(INT32 x0, INT32 y0, INT32 x1, INT32 y1, INT32 color, mame_bitmap *bitmap)
1577
#define SWAP(a,b) tmpswap = a; a = b; b = tmpswap;
1581
INT32 sx, sy; /* step positive or negative (1 or -1) */
1582
INT32 dx, dy; /* delta (difference in X and Y between points) */
1586
* inline swap. On some architectures, the XOR trick may be faster
1591
* optimize for vertical and horizontal lines here
1595
sx = ((x1 - x0) > 0) ? 1 : -1;
1597
sy = ((y1 - y0) > 0) ? 1 : -1;
1609
for (i = 0; i < dx; i++)
1613
plot(x0,y0,color, bitmap);
1617
plot(y0,x0,color, bitmap);
1632
static void DrawWireframe(struct polygon *p, mame_bitmap *bitmap)
1635
for (j = 0; j < p->n; j++)
1637
/* printf("now drawing : %f %f %f, %f %f %f\n", p->vert[j].clipCoords[0], p->vert[j].clipCoords[1], p->vert[j].clipCoords[2], p->vert[(j+1)%p->n].clipCoords[0], p->vert[(j+1)%p->n].clipCoords[1], p->vert[(j+1)%p->n].clipCoords[2]) ; */
1638
/* printf("%f %f %f %f\n", p->vert[j].clipCoords[0], p->vert[j].clipCoords[1], p->vert[(j+1)%p->n].clipCoords[0], p->vert[(j+1)%p->n].clipCoords[1]) ; */
1639
drawline2d(p->vert[j].clipCoords[0], p->vert[j].clipCoords[1], p->vert[(j+1)%p->n].clipCoords[0], p->vert[(j+1)%p->n].clipCoords[1], 255, bitmap) ;
1642
/* SHOWS THE CLIPPING // */
1644
for (int j = 1; j < p->n-1; j++)
1646
drawline2d(p->vert[0].clipCoords[0], p->vert[0].clipCoords[1], p->vert[j].clipCoords[0], p->vert[j].clipCoords[1], 255, bitmap) ;
1647
drawline2d(p->vert[j].clipCoords[0], p->vert[j].clipCoords[1], p->vert[j+1].clipCoords[0], p->vert[j+1].clipCoords[1], 255, bitmap) ;
1648
drawline2d(p->vert[j+1].clipCoords[0], p->vert[j+1].clipCoords[1], p->vert[0].clipCoords[0], p->vert[0].clipCoords[1], 255, bitmap) ;
1654
/*///////////////////// */
1655
/* polygon rendering // */
1656
/*///////////////////// */
1658
void RasterizeTriangle_SMOOTH_TEX_PC(mame_bitmap *Color,
1659
float A[4], float B[4], float C[4],
1660
float Ca[3], float Cb[3], float Cc[3], /* PER-VERTEX RGB COLORS */
1661
float Ta[2], float Tb[2], float Tc[2], /* PER-VERTEX (S,T) TEX-COORDS */
1662
int Wrapping, int Filtering, int Function) ;
1664
static void DrawShaded(struct polygon *p, mame_bitmap *bitmap)
1666
/* The perspective-correct texture divide... */
1667
/* !!! There is a very good chance the HNG64 hardware does not do perspective-correct texture-mapping !!! */
1669
for (j = 0; j < p->n; j++)
1671
p->vert[j].clipCoords[3] = 1.0f / p->vert[j].clipCoords[3] ;
1672
p->vert[j].light[0] = p->vert[j].light[0] * p->vert[j].clipCoords[3] ;
1673
p->vert[j].light[1] = p->vert[j].light[1] * p->vert[j].clipCoords[3] ;
1674
p->vert[j].light[2] = p->vert[j].light[2] * p->vert[j].clipCoords[3] ;
1675
p->vert[j].texCoords[0] = p->vert[j].texCoords[0] * p->vert[j].clipCoords[3] ;
1676
p->vert[j].texCoords[1] = p->vert[j].texCoords[1] * p->vert[j].clipCoords[3] ;
1679
for (j = 1; j < p->n-1; j++)
1681
RasterizeTriangle_SMOOTH_TEX_PC(bitmap,
1682
p->vert[0].clipCoords, p->vert[j].clipCoords, p->vert[j+1].clipCoords,
1683
p->vert[0].light, p->vert[j].light, p->vert[j+1].light,
1684
p->vert[0].texCoords, p->vert[j].texCoords, p->vert[j+1].texCoords,
1685
p->texType, p->palIndex, p->texIndex) ;
1691
/*********************************************************************/
1692
/** FillSmoothTexPCHorizontalLine **/
1693
/** Input: Color Buffer (framebuffer), depth buffer, width and **/
1694
/** height of framebuffer, starting, and ending values **/
1695
/** for x and y, constant y. Fills horizontally with **/
1696
/** z,r,g,b interpolation. **/
1698
/** Output: none **/
1699
/*********************************************************************/
1700
INLINE void FillSmoothTexPCHorizontalLine(mame_bitmap *Color,
1701
int Wrapping, int Filtering, int Function,
1702
int x_start, int x_end, int y, float z_start, float z_delta,
1703
float w_start, float w_delta, float r_start, float r_delta,
1704
float g_start, float g_delta, float b_start, float b_delta,
1705
float s_start, float s_delta, float t_start, float t_delta)
1707
float *dp = &(depthBuffer[y*Machine->visible_area.max_x+x_start]);
1709
const UINT8 *gfx = memory_region(REGION_GFX3);
1710
const UINT8 *textureOffset ;
1711
UINT8 paletteEntry ;
1712
float t_coord, s_coord ;
1714
if (Function >= 0) textureOffset = &gfx[Function * 1024 * 1024] ;
1715
else textureOffset = 0x00 ;
1718
for ( ; x_start <= x_end; x_start++)
1720
if (z_start < (*dp))
1722
/* MULTIPLY BACK THROUGH BY W */
1723
t_coord = t_start / w_start;
1724
s_coord = s_start / w_start;
1726
/* GET THE TEXTURE INDEX */
1729
if (Wrapping == 0x8 || Wrapping == 0xc)
1730
paletteEntry = textureOffset[(((int)(s_coord*1024.0f))*1024 + (int)(t_coord*1024.0f))] ;
1732
paletteEntry = textureOffset[(((int)(s_coord*512.0f))*1024 + (int)(t_coord*512.0f))] ;
1734
/* Naieve Alpha Implementation (?) - don't draw if you're at texture index 0... */
1735
if (paletteEntry != 0)
1737
/* Greyscale texture - for Buriki... */
1738
/* ((UINT32 *)(Color->line[y]))[x_start] = MAKE_ARGB(255, (UINT8)paletteEntry, (UINT8)paletteEntry, (UINT8)paletteEntry) ; */
1740
((UINT32 *)(Color->line[y]))[x_start] = Machine->pens[(128*(Filtering))+paletteEntry] ;
1746
((UINT32 *)(Color->line[y]))[x_start] = MAKE_ARGB(255, (UINT8)(r_start/w_start), (UINT8)(g_start/w_start), (UINT8)(b_start/w_start)) ;
1761
/*---------------------------------------------------------------------------- */
1762
/* Given 3D triangle ABC in screen space with clipped coordinates within the following */
1763
/* bounds: x in [0,W], y in [0,H], z in [0,1]. The origin for (x,y) is in the bottom */
1764
/* left corner of the pixel grid. z=0 is the near plane and z=1 is the far plane, */
1765
/* so lesser values are closer. The coordinates of the pixels are evenly spaced */
1766
/* in x and y 1 units apart starting at the bottom-left pixel with coords */
1767
/* (0.5,0.5). In other words, the pixel sample point is in the center of the */
1768
/* rectangular grid cell containing the pixel sample. The framebuffer has */
1769
/* dimensions width x height (WxH). The Color buffer is a 1D array (row-major */
1770
/* order) with 3 unsigned chars per pixel (24-bit color). The Depth buffer is */
1771
/* a 1D array (also row-major order) with a float value per pixel */
1772
/* For a pixel location (x,y) we can obtain */
1773
/* the Color and Depth array locations as: Color[(((int)y)*W+((int)x))*3] */
1774
/* (for the red value, green is offset +1, and blue is offset +2 and */
1775
/* Depth[((int)y)*W+((int)x)]. Fills the pixels contained in the triangle */
1776
/* with the global current color and the properly linearly interpolated depth */
1777
/* value (performs Z-buffer depth test before writing new pixel). */
1778
/* Pixel samples that lie inside the triangle edges are filled with */
1779
/* a bias towards the minimum values (samples that lie exactly on a triangle */
1780
/* edge are filled only for minimum x values along a horizontal span and for */
1781
/* minimum y values, samples lying on max values are not filled). */
1782
/* Per-vertex colors are RGB floating point triplets in [0.0,255.0]. The vertices */
1783
/* include their w-components for use in linearly interpolating perspectively */
1784
/* correct color (RGB) and texture-coords (st) across the face of the triangle. */
1785
/* A texture image of RGB floating point triplets of size TWxWH is also given. */
1786
/* Texture colors are normalized RGB values in [0,1]. */
1787
/* clamp and repeat wrapping modes : Wrapping={0,1} */
1788
/* nearest and bilinear filtering: Filtering={0,1} */
1789
/* replace and modulate application modes: Function={0,1} */
1790
/*--------------------------------------------------------------------------- */
1791
void RasterizeTriangle_SMOOTH_TEX_PC(mame_bitmap *Color,
1792
float A[4], float B[4], float C[4],
1793
float Ca[3], float Cb[3], float Cc[3], /* PER-VERTEX RGB COLORS */
1794
float Ta[2], float Tb[2], float Tc[2], /* PER-VERTEX (S,T) TEX-COORDS */
1795
int Wrapping, int Filtering, int Function)
1797
/* Get our order of points by increasing y-coord */
1798
float *p_min = ((A[1] <= B[1]) && (A[1] <= C[1])) ? A : ((B[1] <= A[1]) && (B[1] <= C[1])) ? B : C;
1799
float *p_max = ((A[1] >= B[1]) && (A[1] >= C[1])) ? A : ((B[1] >= A[1]) && (B[1] >= C[1])) ? B : C;
1800
float *p_mid = ((A != p_min) && (A != p_max)) ? A : ((B != p_min) && (B != p_max)) ? B : C;
1802
/* Perspectively correct color interpolation, interpolate r/w, g/w, b/w, then divide by 1/w at each pixel (A[3] = 1/w) */
1803
float ca[3], cb[3], cc[3];
1804
float ta[2], tb[2], tc[2];
1810
/* We must keep the tex coords straight with the point ordering */
1815
/* Find out control points for y, this divides the triangle into upper and lower */
1820
/* Compute the slopes of each line, and color this is used to determine the interpolation */
1838
/* Compute the t values used in the equation Ax = Ax + (Bx - Ax)*t */
1839
/* We only need one t, because it is only used to compute the start. */
1840
/* Create storage for the interpolated x and z values for both lines */
1841
/* also for the RGB interpolation */
1861
/* Create storage for the horizontal interpolation of z and RGB color and its starting points */
1862
/* This is used to fill the triangle horizontally */
1864
float z_interp_x, z_delta_x;
1865
float w_interp_x, w_delta_x;
1866
float r_interp_x, r_delta_x;
1867
float g_interp_x, g_delta_x;
1868
float b_interp_x, b_delta_x;
1869
float s_interp_x, s_delta_x;
1870
float t_interp_x, t_delta_x;
1872
ca[0] = Ca[0]; ca[1] = Ca[1]; ca[2] = Ca[2];
1873
cb[0] = Cb[0]; cb[1] = Cb[1]; cb[2] = Cb[2];
1874
cc[0] = Cc[0]; cc[1] = Cc[1]; cc[2] = Cc[2];
1876
/* Perspectively correct tex interpolation, interpolate s/w, t/w, then divide by 1/w at each pixel (A[3] = 1/w) */
1877
ta[0] = Ta[0]; ta[1] = Ta[1];
1878
tb[0] = Tb[0]; tb[1] = Tb[1];
1879
tc[0] = Tc[0]; tc[1] = Tc[1];
1881
/* We must keep the colors straight with the point ordering */
1882
c_min = (p_min == A) ? ca : (p_min == B) ? cb : cc;
1883
c_mid = (p_mid == A) ? ca : (p_mid == B) ? cb : cc;
1884
c_max = (p_max == A) ? ca : (p_max == B) ? cb : cc;
1886
/* We must keep the tex coords straight with the point ordering */
1887
t_min = (p_min == A) ? ta : (p_min == B) ? tb : tc;
1888
t_mid = (p_mid == A) ? ta : (p_mid == B) ? tb : tc;
1889
t_max = (p_max == A) ? ta : (p_max == B) ? tb : tc;
1891
/* Find out control points for y, this divides the triangle into upper and lower */
1892
y_min = (((int)p_min[1]) + 0.5 >= p_min[1]) ? p_min[1] : ((int)p_min[1]) + 1;
1893
y_max = (((int)p_max[1]) + 0.5 < p_max[1]) ? p_max[1] : ((int)p_max[1]) - 1;
1894
y_mid = (((int)p_mid[1]) + 0.5 >= p_mid[1]) ? p_mid[1] : ((int)p_mid[1]) + 1;
1896
/* Compute the slopes of each line, and color this is used to determine the interpolation */
1897
x1_slope = (p_max[0] - p_min[0]) / (p_max[1] - p_min[1]);
1898
x2_slope = (p_mid[0] - p_min[0]) / (p_mid[1] - p_min[1]);
1899
z1_slope = (p_max[2] - p_min[2]) / (p_max[1] - p_min[1]);
1900
z2_slope = (p_mid[2] - p_min[2]) / (p_mid[1] - p_min[1]);
1901
w1_slope = (p_max[3] - p_min[3]) / (p_max[1] - p_min[1]);
1902
w2_slope = (p_mid[3] - p_min[3]) / (p_mid[1] - p_min[1]);
1903
r1_slope = (c_max[0] - c_min[0]) / (p_max[1] - p_min[1]);
1904
r2_slope = (c_mid[0] - c_min[0]) / (p_mid[1] - p_min[1]);
1905
g1_slope = (c_max[1] - c_min[1]) / (p_max[1] - p_min[1]);
1906
g2_slope = (c_mid[1] - c_min[1]) / (p_mid[1] - p_min[1]);
1907
b1_slope = (c_max[2] - c_min[2]) / (p_max[1] - p_min[1]);
1908
b2_slope = (c_mid[2] - c_min[2]) / (p_mid[1] - p_min[1]);
1909
s1_slope = (t_max[0] - t_min[0]) / (p_max[1] - p_min[1]);
1910
s2_slope = (t_mid[0] - t_min[0]) / (p_mid[1] - p_min[1]);
1911
t1_slope = (t_max[1] - t_min[1]) / (p_max[1] - p_min[1]);
1912
t2_slope = (t_mid[1] - t_min[1]) / (p_mid[1] - p_min[1]);
1914
/* Compute the t values used in the equation Ax = Ax + (Bx - Ax)*t */
1915
/* We only need one t, because it is only used to compute the start. */
1916
/* Create storage for the interpolated x and z values for both lines */
1917
/* also for the RGB interpolation */
1918
t = (((float)y_min) + 0.5 - p_min[1]) / (p_max[1] - p_min[1]);
1919
x1_interp = p_min[0] + (p_max[0] - p_min[0]) * t;
1920
z1_interp = p_min[2] + (p_max[2] - p_min[2]) * t;
1921
w1_interp = p_min[3] + (p_max[3] - p_min[3]) * t;
1922
r1_interp = c_min[0] + (c_max[0] - c_min[0]) * t;
1923
g1_interp = c_min[1] + (c_max[1] - c_min[1]) * t;
1924
b1_interp = c_min[2] + (c_max[2] - c_min[2]) * t;
1925
s1_interp = t_min[0] + (t_max[0] - t_min[0]) * t;
1926
t1_interp = t_min[1] + (t_max[1] - t_min[1]) * t;
1928
t = (((float)y_min) + 0.5 - p_min[1]) / (p_mid[1] - p_min[1]);
1929
x2_interp = p_min[0] + (p_mid[0] - p_min[0]) * t;
1930
z2_interp = p_min[2] + (p_mid[2] - p_min[2]) * t;
1931
w2_interp = p_min[3] + (p_mid[3] - p_min[3]) * t;
1932
r2_interp = c_min[0] + (c_mid[0] - c_min[0]) * t;
1933
g2_interp = c_min[1] + (c_mid[1] - c_min[1]) * t;
1934
b2_interp = c_min[2] + (c_mid[2] - c_min[2]) * t;
1935
s2_interp = t_min[0] + (t_mid[0] - t_min[0]) * t;
1936
t2_interp = t_min[1] + (t_mid[1] - t_min[1]) * t;
1938
/* First work on the bottom half of the triangle */
1939
/* I'm using y_min as the incrementer because it saves space and we don't need it anymore */
1940
for ( ; y_min < y_mid; y_min++) {
1942
/* We always want to fill left to right, so we have 2 main cases */
1943
/* Compute the integer starting and ending points and the appropriate z by */
1944
/* interpolating. Remember the pixels are in the middle of the grid, i.e. (0.5,0.5,0.5) */
1945
if (x1_interp < x2_interp) {
1946
x_start = ((((int)x1_interp) + 0.5) >= x1_interp) ? x1_interp : ((int)x1_interp) + 1;
1947
x_end = ((((int)x2_interp) + 0.5) < x2_interp) ? x2_interp : ((int)x2_interp) - 1;
1948
z_delta_x = (z2_interp - z1_interp) / (x2_interp - x1_interp);
1949
w_delta_x = (w2_interp - w1_interp) / (x2_interp - x1_interp);
1950
r_delta_x = (r2_interp - r1_interp) / (x2_interp - x1_interp);
1951
g_delta_x = (g2_interp - g1_interp) / (x2_interp - x1_interp);
1952
b_delta_x = (b2_interp - b1_interp) / (x2_interp - x1_interp);
1953
s_delta_x = (s2_interp - s1_interp) / (x2_interp - x1_interp);
1954
t_delta_x = (t2_interp - t1_interp) / (x2_interp - x1_interp);
1955
t = (x_start + 0.5 - x1_interp) / (x2_interp - x1_interp);
1956
z_interp_x = z1_interp + (z2_interp - z1_interp) * t;
1957
w_interp_x = w1_interp + (w2_interp - w1_interp) * t;
1958
r_interp_x = r1_interp + (r2_interp - r1_interp) * t;
1959
g_interp_x = g1_interp + (g2_interp - g1_interp) * t;
1960
b_interp_x = b1_interp + (b2_interp - b1_interp) * t;
1961
s_interp_x = s1_interp + (s2_interp - s1_interp) * t;
1962
t_interp_x = t1_interp + (t2_interp - t1_interp) * t;
1965
x_start = ((((int)x2_interp) + 0.5) >= x2_interp) ? x2_interp : ((int)x2_interp) + 1;
1966
x_end = ((((int)x1_interp) + 0.5) < x1_interp) ? x1_interp : ((int)x1_interp) - 1;
1967
z_delta_x = (z1_interp - z2_interp) / (x1_interp - x2_interp);
1968
w_delta_x = (w1_interp - w2_interp) / (x1_interp - x2_interp);
1969
r_delta_x = (r1_interp - r2_interp) / (x1_interp - x2_interp);
1970
g_delta_x = (g1_interp - g2_interp) / (x1_interp - x2_interp);
1971
b_delta_x = (b1_interp - b2_interp) / (x1_interp - x2_interp);
1972
s_delta_x = (s1_interp - s2_interp) / (x1_interp - x2_interp);
1973
t_delta_x = (t1_interp - t2_interp) / (x1_interp - x2_interp);
1974
t = (x_start + 0.5 - x2_interp) / (x1_interp - x2_interp);
1975
z_interp_x = z2_interp + (z1_interp - z2_interp) * t;
1976
w_interp_x = w2_interp + (w1_interp - w2_interp) * t;
1977
r_interp_x = r2_interp + (r1_interp - r2_interp) * t;
1978
g_interp_x = g2_interp + (g1_interp - g2_interp) * t;
1979
b_interp_x = b2_interp + (b1_interp - b2_interp) * t;
1980
s_interp_x = s2_interp + (s1_interp - s2_interp) * t;
1981
t_interp_x = t2_interp + (t1_interp - t2_interp) * t;
1984
/* Pass the horizontal line to the filler, this could be put in the routine */
1985
/* then interpolate for the next values of x and z */
1986
FillSmoothTexPCHorizontalLine(Color, Wrapping, Filtering, Function,
1987
x_start, x_end, y_min, z_interp_x, z_delta_x, w_interp_x, w_delta_x,
1988
r_interp_x, r_delta_x, g_interp_x, g_delta_x, b_interp_x, b_delta_x,
1989
s_interp_x, s_delta_x, t_interp_x, t_delta_x);
1990
x1_interp += x1_slope; z1_interp += z1_slope;
1991
x2_interp += x2_slope; z2_interp += z2_slope;
1992
r1_interp += r1_slope; r2_interp += r2_slope;
1993
g1_interp += g1_slope; g2_interp += g2_slope;
1994
b1_interp += b1_slope; b2_interp += b2_slope;
1995
w1_interp += w1_slope; w2_interp += w2_slope;
1996
s1_interp += s1_slope; s2_interp += s2_slope;
1997
t1_interp += t1_slope; t2_interp += t2_slope;
2000
/* Now do the same thing for the top half of the triangle. */
2001
/* We only need to recompute the x2 line because it changes at the midpoint */
2002
x2_slope = (p_max[0] - p_mid[0]) / (p_max[1] - p_mid[1]);
2003
z2_slope = (p_max[2] - p_mid[2]) / (p_max[1] - p_mid[1]);
2004
w2_slope = (p_max[3] - p_mid[3]) / (p_max[1] - p_mid[1]);
2005
r2_slope = (c_max[0] - c_mid[0]) / (p_max[1] - p_mid[1]);
2006
g2_slope = (c_max[1] - c_mid[1]) / (p_max[1] - p_mid[1]);
2007
b2_slope = (c_max[2] - c_mid[2]) / (p_max[1] - p_mid[1]);
2008
s2_slope = (t_max[0] - t_mid[0]) / (p_max[1] - p_mid[1]);
2009
t2_slope = (t_max[1] - t_mid[1]) / (p_max[1] - p_mid[1]);
2011
t = (((float)y_mid) + 0.5 - p_mid[1]) / (p_max[1] - p_mid[1]);
2012
x2_interp = p_mid[0] + (p_max[0] - p_mid[0]) * t;
2013
z2_interp = p_mid[2] + (p_max[2] - p_mid[2]) * t;
2014
w2_interp = p_mid[3] + (p_max[3] - p_mid[3]) * t;
2015
r2_interp = c_mid[0] + (c_max[0] - c_mid[0]) * t;
2016
g2_interp = c_mid[1] + (c_max[1] - c_mid[1]) * t;
2017
b2_interp = c_mid[2] + (c_max[2] - c_mid[2]) * t;
2018
s2_interp = t_mid[0] + (t_max[0] - t_mid[0]) * t;
2019
t2_interp = t_mid[1] + (t_max[1] - t_mid[1]) * t;
2021
/* We've seen this loop before haven't we? */
2022
/* I'm using y_mid as the incrementer because it saves space and we don't need it anymore */
2023
for ( ; y_mid <= y_max; y_mid++) {
2025
if (x1_interp < x2_interp) {
2026
x_start = ((((int)x1_interp) + 0.5) >= x1_interp) ? x1_interp : ((int)x1_interp) + 1;
2027
x_end = ((((int)x2_interp) + 0.5) < x2_interp) ? x2_interp : ((int)x2_interp) - 1;
2028
z_delta_x = (z2_interp - z1_interp) / (x2_interp - x1_interp);
2029
w_delta_x = (w2_interp - w1_interp) / (x2_interp - x1_interp);
2030
r_delta_x = (r2_interp - r1_interp) / (x2_interp - x1_interp);
2031
g_delta_x = (g2_interp - g1_interp) / (x2_interp - x1_interp);
2032
b_delta_x = (b2_interp - b1_interp) / (x2_interp - x1_interp);
2033
s_delta_x = (s2_interp - s1_interp) / (x2_interp - x1_interp);
2034
t_delta_x = (t2_interp - t1_interp) / (x2_interp - x1_interp);
2035
t = (x_start + 0.5 - x1_interp) / (x2_interp - x1_interp);
2036
z_interp_x = z1_interp + (z2_interp - z1_interp) * t;
2037
w_interp_x = w1_interp + (w2_interp - w1_interp) * t;
2038
r_interp_x = r1_interp + (r2_interp - r1_interp) * t;
2039
g_interp_x = g1_interp + (g2_interp - g1_interp) * t;
2040
b_interp_x = b1_interp + (b2_interp - b1_interp) * t;
2041
s_interp_x = s1_interp + (s2_interp - s1_interp) * t;
2042
t_interp_x = t1_interp + (t2_interp - t1_interp) * t;
2045
x_start = ((((int)x2_interp) + 0.5) >= x2_interp) ? x2_interp : ((int)x2_interp) + 1;
2046
x_end = ((((int)x1_interp) + 0.5) < x1_interp) ? x1_interp : ((int)x1_interp) - 1;
2047
z_delta_x = (z1_interp - z2_interp) / (x1_interp - x2_interp);
2048
w_delta_x = (w1_interp - w2_interp) / (x1_interp - x2_interp);
2049
r_delta_x = (r1_interp - r2_interp) / (x1_interp - x2_interp);
2050
g_delta_x = (g1_interp - g2_interp) / (x1_interp - x2_interp);
2051
b_delta_x = (b1_interp - b2_interp) / (x1_interp - x2_interp);
2052
s_delta_x = (s1_interp - s2_interp) / (x1_interp - x2_interp);
2053
t_delta_x = (t1_interp - t2_interp) / (x1_interp - x2_interp);
2054
t = (x_start + 0.5 - x2_interp) / (x1_interp - x2_interp);
2055
z_interp_x = z2_interp + (z1_interp - z2_interp) * t;
2056
w_interp_x = w2_interp + (w1_interp - w2_interp) * t;
2057
r_interp_x = r2_interp + (r1_interp - r2_interp) * t;
2058
g_interp_x = g2_interp + (g1_interp - g2_interp) * t;
2059
b_interp_x = b2_interp + (b1_interp - b2_interp) * t;
2060
s_interp_x = s2_interp + (s1_interp - s2_interp) * t;
2061
t_interp_x = t2_interp + (t1_interp - t2_interp) * t;
2064
/* Pass the horizontal line to the filler, this could be put in the routine */
2065
/* then interpolate for the next values of x and z */
2066
FillSmoothTexPCHorizontalLine(Color, Wrapping, Filtering, Function,
2067
x_start, x_end, y_mid, z_interp_x, z_delta_x, w_interp_x, w_delta_x,
2068
r_interp_x, r_delta_x, g_interp_x, g_delta_x, b_interp_x, b_delta_x,
2069
s_interp_x, s_delta_x, t_interp_x, t_delta_x);
2070
x1_interp += x1_slope; z1_interp += z1_slope;
2071
x2_interp += x2_slope; z2_interp += z2_slope;
2072
r1_interp += r1_slope; r2_interp += r2_slope;
2073
g1_interp += g1_slope; g2_interp += g2_slope;
2074
b1_interp += b1_slope; b2_interp += b2_slope;
2075
w1_interp += w1_slope; w2_interp += w2_slope;
2076
s1_interp += s1_slope; s2_interp += s2_slope;
2077
t1_interp += t1_slope; t2_interp += t2_slope;