Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-glide64/src/Util.cpp
2 views
1
/*
2
* Glide64 - Glide video plugin for Nintendo 64 emulators.
3
* Copyright (c) 2002 Dave2001
4
*
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public
16
* License along with this program; if not, write to the Free
17
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
* Boston, MA 02110-1301, USA
19
*/
20
21
//****************************************************************
22
//
23
// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
24
// Project started on December 29th, 2001
25
//
26
// To modify Glide64:
27
// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
28
// * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
29
//
30
// Official Glide64 development channel: #Glide64 on EFnet
31
//
32
// Original author: Dave2001 ([email protected])
33
// Other authors: Gonetz, Gugaman
34
//
35
//****************************************************************
36
37
#define M64P_PLUGIN_PROTOTYPES 1
38
#include "m64p_types.h"
39
#include "m64p_plugin.h"
40
#include "m64p_config.h"
41
#include "m64p_vidext.h"
42
#include "Util.h"
43
#include "Combine.h"
44
#include "3dmath.h"
45
#include "Debugger.h"
46
#include "TexCache.h"
47
#include "DepthBufferRender.h"
48
49
#ifndef _WIN32
50
#include <string.h>
51
#include <stdlib.h>
52
#endif // _WIN32
53
54
#define max(a,b) ((a) > (b) ? (a) : (b))
55
#define min(a,b) ((a) < (b) ? (a) : (b))
56
57
#define Vj rdp.vtxbuf2[j]
58
#define Vi rdp.vtxbuf2[i]
59
60
VERTEX *vtx_list1[32]; // vertex indexing
61
VERTEX *vtx_list2[32];
62
63
//
64
// util_init - initialize data for the functions in this file
65
//
66
67
void util_init ()
68
{
69
for (int i=0; i<32; i++)
70
{
71
vtx_list1[i] = &rdp.vtx1[i];
72
vtx_list2[i] = &rdp.vtx2[i];
73
}
74
}
75
76
//software backface culling. Gonetz
77
// mega modifications by Dave2001
78
BOOL cull_tri(VERTEX **v) // type changed to VERTEX** [Dave2001]
79
{
80
int i;
81
82
if (v[0]->scr_off & v[1]->scr_off & v[2]->scr_off)
83
{
84
RDP (" clipped\n");
85
return TRUE;
86
}
87
88
// Triangle can't be culled, if it need clipping
89
BOOL draw = FALSE;
90
91
//fix for sun in zeldas
92
BOOL fix_i_uv = FALSE;
93
if (settings.zelda && rdp.rm == 0x0c184241 && rdp.tiles[rdp.cur_tile].format == 4)
94
fix_i_uv = TRUE;
95
96
for (i=0; i<3; i++)
97
{
98
if (!v[i]->screen_translated)
99
{
100
v[i]->sx = rdp.view_trans[0] + v[i]->x_w * rdp.view_scale[0];
101
v[i]->sy = rdp.view_trans[1] + v[i]->y_w * rdp.view_scale[1];
102
v[i]->sz = rdp.view_trans[2] + v[i]->z_w * rdp.view_scale[2];
103
if ((fix_i_uv) && (v[i]->uv_fixed == 0))
104
{
105
v[i]->uv_fixed = 1;
106
v[i]->ou *= 0.5f;
107
v[i]->ov *= 0.5f;
108
}
109
v[i]->screen_translated = 1;
110
}
111
if (v[i]->w < 0.01f) //need clip_z. can't be culled now
112
draw = 1;
113
}
114
115
if (settings.fix_tex_coord)
116
fix_tex_coord (v);
117
if (draw) return FALSE; // z-clipping, can't be culled by software
118
119
#define SW_CULLING
120
#ifdef SW_CULLING
121
//now we need to check, if triangle's vertices are in clockwise order
122
// Use precalculated x/z and y/z coordinates.
123
float x1 = v[0]->sx - v[1]->sx;
124
float y1 = v[0]->sy - v[1]->sy;
125
float x2 = v[2]->sx - v[1]->sx;
126
float y2 = v[2]->sy - v[1]->sy;
127
128
DWORD mode = (rdp.flags & CULLMASK) >> CULLSHIFT;
129
switch (mode)
130
{
131
case 1: // cull front
132
// if ((x1*y2 - y1*x2) < 0.0f) //counter-clockwise, positive
133
if ((y1*x2-x1*y2) < 0.0f) //counter-clockwise, positive
134
{
135
RDP (" culled!\n");
136
return TRUE;
137
}
138
return FALSE;
139
case 2: // cull back
140
// if ((x1*y2 - y1*x2) >= 0.0f) //clockwise, negative
141
if ((y1*x2-x1*y2) >= 0.0f) //clockwise, negative
142
{
143
RDP (" culled!\n");
144
return TRUE;
145
}
146
return FALSE;
147
}
148
#endif
149
150
return FALSE;
151
}
152
153
154
void apply_shade_mods (VERTEX *v)
155
{
156
float col[4];
157
DWORD cmb;
158
memcpy (col, rdp.col, 16);
159
160
if (rdp.cmb_flags)
161
{
162
cmb = rdp.cmb_flags;
163
if (cmb & CMB_SET)
164
{
165
if (col[0] > 1.0f) col[0] = 1.0f;
166
if (col[1] > 1.0f) col[1] = 1.0f;
167
if (col[2] > 1.0f) col[2] = 1.0f;
168
if (col[0] < 0.0f) col[0] = 0.0f;
169
if (col[1] < 0.0f) col[1] = 0.0f;
170
if (col[2] < 0.0f) col[2] = 0.0f;
171
v->r = (BYTE)(255.0f * col[0]);
172
v->g = (BYTE)(255.0f * col[1]);
173
v->b = (BYTE)(255.0f * col[2]);
174
}
175
if (cmb & CMB_A_SET)
176
{
177
if (col[3] > 1.0f) col[3] = 1.0f;
178
if (col[3] < 0.0f) col[3] = 0.0f;
179
v->a = (BYTE)(255.0f * col[3]);
180
}
181
if (cmb & CMB_SETSHADE_SHADEALPHA)
182
{
183
v->r = v->g = v->b = v->a;
184
}
185
if (cmb & CMB_SUB)
186
{
187
int r = v->r - (int)(255.0f * rdp.coladd[0]);
188
int g = v->g - (int)(255.0f * rdp.coladd[1]);
189
int b = v->b - (int)(255.0f * rdp.coladd[2]);
190
if (r < 0) r = 0;
191
if (g < 0) g = 0;
192
if (b < 0) b = 0;
193
v->r = (BYTE)r;
194
v->g = (BYTE)g;
195
v->b = (BYTE)b;
196
}
197
if (cmb & CMB_A_SUB)
198
{
199
int a = v->a - (int)(255.0f * rdp.coladd[3]);
200
if (a < 0) a = 0;
201
v->a = (BYTE)a;
202
}
203
204
if (cmb & CMB_ADD)
205
{
206
int r = v->r + (int)(255.0f * rdp.coladd[0]);
207
int g = v->g + (int)(255.0f * rdp.coladd[1]);
208
int b = v->b + (int)(255.0f * rdp.coladd[2]);
209
if (r > 255) r = 255;
210
if (g > 255) g = 255;
211
if (b > 255) b = 255;
212
v->r = (BYTE)r;
213
v->g = (BYTE)g;
214
v->b = (BYTE)b;
215
}
216
if (cmb & CMB_A_ADD)
217
{
218
int a = v->a + (int)(255.0f * rdp.coladd[3]);
219
if (a > 255) a = 255;
220
v->a = (BYTE)a;
221
}
222
if (cmb & CMB_COL_SUB_OWN)
223
{
224
int r = (BYTE)(255.0f * rdp.coladd[0]) - v->r;
225
int g = (BYTE)(255.0f * rdp.coladd[1]) - v->g;
226
int b = (BYTE)(255.0f * rdp.coladd[2]) - v->b;
227
if (r < 0) r = 0;
228
if (g < 0) g = 0;
229
if (b < 0) b = 0;
230
v->r = (BYTE)r;
231
v->g = (BYTE)g;
232
v->b = (BYTE)b;
233
}
234
if (cmb & CMB_MULT)
235
{
236
if (col[0] > 1.0f) col[0] = 1.0f;
237
if (col[1] > 1.0f) col[1] = 1.0f;
238
if (col[2] > 1.0f) col[2] = 1.0f;
239
if (col[0] < 0.0f) col[0] = 0.0f;
240
if (col[1] < 0.0f) col[1] = 0.0f;
241
if (col[2] < 0.0f) col[2] = 0.0f;
242
v->r = (BYTE)(v->r * col[0]);
243
v->g = (BYTE)(v->g * col[1]);
244
v->b = (BYTE)(v->b * col[2]);
245
}
246
if (cmb & CMB_A_MULT)
247
{
248
if (col[3] > 1.0f) col[3] = 1.0f;
249
if (col[3] < 0.0f) col[3] = 0.0f;
250
v->a = (BYTE)(v->a * col[3]);
251
}
252
if (cmb & CMB_MULT_OWN_ALPHA)
253
{
254
float percent = v->a / 255.0f;
255
v->r = (BYTE)(v->r * percent);
256
v->g = (BYTE)(v->g * percent);
257
v->b = (BYTE)(v->b * percent);
258
}
259
v->shade_mods_allowed = 0;
260
}
261
cmb = rdp.cmb_flags_2;
262
if (cmb & CMB_INTER)
263
{
264
v->r = (BYTE)(rdp.col_2[0] * rdp.shade_factor * 255.0f + v->r * (1.0f - rdp.shade_factor));
265
v->g = (BYTE)(rdp.col_2[1] * rdp.shade_factor * 255.0f + v->g * (1.0f - rdp.shade_factor));
266
v->b = (BYTE)(rdp.col_2[2] * rdp.shade_factor * 255.0f + v->b * (1.0f - rdp.shade_factor));
267
v->shade_mods_allowed = 0;
268
}
269
}
270
271
272
static long dzdx = 0;
273
274
void DrawTri (VERTEX **vtx, WORD linew)
275
{
276
if (settings.fb_depth_render && linew == 0)
277
{
278
float X0 = vtx[0]->sx / rdp.scale_x;
279
float Y0 = vtx[0]->sy / rdp.scale_y;
280
float X1 = vtx[1]->sx / rdp.scale_x;
281
float Y1 = vtx[1]->sy / rdp.scale_y;
282
float X2 = vtx[2]->sx / rdp.scale_x;
283
float Y2 = vtx[2]->sy / rdp.scale_y;
284
float diff12 = Y1 - Y2;
285
float diff02 = Y0 - Y2;
286
287
288
double denom = ((X0 - X2) * diff12 -
289
(X1 - X2) * diff02);
290
if(denom*denom > 0.0)
291
{
292
dzdx = (long)(((vtx[0]->sz - vtx[2]->sz) * diff12 -
293
(vtx[1]->sz - vtx[2]->sz) * diff02) / denom * 65536.0);
294
}
295
else
296
dzdx = 0;
297
}
298
else
299
dzdx = 0;
300
301
for (int i=0; i<3; i++)
302
{
303
VERTEX *v = vtx[i];
304
305
if (v->uv_calculated != rdp.tex_ctr)
306
{
307
#ifdef EXTREME_LOGGING
308
FRDP(" * CALCULATING VERTEX U/V: %d\n", v->number);
309
#endif
310
v->uv_calculated = rdp.tex_ctr;
311
312
if (!(rdp.geom_mode & 0x00020000))
313
{
314
if (!(rdp.geom_mode & 0x00000200))
315
{
316
if (rdp.geom_mode & 0x00000004) // flat shading
317
{
318
#ifdef EXTREME_LOGGING
319
RDP(" * Flat shaded\n");
320
#endif
321
v->a = vtx[0]->a;
322
v->b = vtx[0]->b;
323
v->g = vtx[0]->g;
324
v->r = vtx[0]->r;
325
}
326
else // prim color
327
{
328
#ifdef EXTREME_LOGGING
329
FRDP(" * Prim shaded %08lx\n", rdp.prim_color);
330
#endif
331
v->a = (BYTE)(rdp.prim_color & 0xFF);
332
v->b = (BYTE)((rdp.prim_color >> 8) & 0xFF);
333
v->g = (BYTE)((rdp.prim_color >> 16) & 0xFF);
334
v->r = (BYTE)((rdp.prim_color >> 24) & 0xFF);
335
}
336
}
337
}
338
339
// Fix texture coordinates
340
v->u1 = v->u0 = v->ou;
341
v->v1 = v->v0 = v->ov;
342
343
if (rdp.tex >= 1 && rdp.cur_cache[0])
344
{
345
if (rdp.hires_tex && rdp.hires_tex->tile == 0)
346
{
347
v->u0 += rdp.hires_tex->u_shift + rdp.hires_tex->tile_uls;
348
v->v0 += rdp.hires_tex->v_shift + rdp.hires_tex->tile_ult;
349
}
350
351
if (rdp.tiles[rdp.cur_tile].shift_s)
352
{
353
if (rdp.tiles[rdp.cur_tile].shift_s > 10)
354
v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s));
355
else
356
v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s);
357
}
358
if (rdp.tiles[rdp.cur_tile].shift_t)
359
{
360
if (rdp.tiles[rdp.cur_tile].shift_t > 10)
361
v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t));
362
else
363
v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t);
364
}
365
366
if (rdp.hires_tex && rdp.hires_tex->tile == 0)
367
{
368
if (rdp.hires_tex->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s)
369
v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;
370
v->u0 *= rdp.hires_tex->u_scale;
371
v->v0 *= rdp.hires_tex->u_scale;
372
v->u0 -= 0.45f;
373
v->v0 -= 0.45f;
374
FRDP("hires_tex t0: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u0, v->v0);
375
}
376
else
377
{
378
v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;
379
v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t;
380
v->u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * v->u0;
381
v->v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * v->v0;
382
}
383
v->u0_w = v->u0 / v->w;
384
v->v0_w = v->v0 / v->w;
385
}
386
387
if (rdp.tex >= 2 && rdp.cur_cache[1])
388
{
389
if (rdp.hires_tex && rdp.hires_tex->tile == 1)
390
{
391
v->u1 += rdp.hires_tex->u_shift + rdp.hires_tex->tile_uls;
392
v->v1 += rdp.hires_tex->v_shift + rdp.hires_tex->tile_ult;
393
}
394
if (rdp.tiles[rdp.cur_tile+1].shift_s)
395
{
396
if (rdp.tiles[rdp.cur_tile+1].shift_s > 10)
397
v->u1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s));
398
else
399
v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s);
400
}
401
if (rdp.tiles[rdp.cur_tile+1].shift_t)
402
{
403
if (rdp.tiles[rdp.cur_tile+1].shift_t > 10)
404
v->v1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t));
405
else
406
v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t);
407
}
408
409
if (rdp.hires_tex && rdp.hires_tex->tile == 1)
410
{
411
if (rdp.hires_tex->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s)
412
v->u1 -= rdp.tiles[rdp.cur_tile].f_ul_s;
413
v->u1 *= rdp.hires_tex->u_scale;
414
v->v1 *= rdp.hires_tex->u_scale;
415
v->u1 -= 0.45f;
416
v->v1 -= 0.45f;
417
FRDP("hires_tex t1: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u0, v->v0);
418
}
419
else
420
{
421
v->u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s;
422
v->v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t;
423
v->u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * v->u1;
424
v->v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * v->v1;
425
}
426
427
v->u1_w = v->u1 / v->w;
428
v->v1_w = v->v1 / v->w;
429
}
430
// FRDP(" * CALCULATING VERTEX U/V: %d u0: %f, v0: %f, u1: %f, v1: %f\n", v->number, v->u0, v->v0, v->u1, v->v1);
431
}
432
if (v->shade_mods_allowed)
433
apply_shade_mods (v);
434
} //for
435
436
rdp.clip = 0;
437
438
if ((vtx[0]->scr_off & 16) ||
439
(vtx[1]->scr_off & 16) ||
440
(vtx[2]->scr_off & 16))
441
rdp.clip |= CLIP_ZMIN;
442
443
vtx[0]->not_zclipped = vtx[1]->not_zclipped = vtx[2]->not_zclipped = 1;
444
445
if (rdp.cur_cache[0] && (rdp.tex & 1) && (rdp.cur_cache[0]->splits > 1) && !rdp.hires_tex && !rdp.clip)
446
{
447
int index,i,j, min_256,max_256, cur_256,left_256,right_256;
448
float percent;
449
450
min_256 = min((int)vtx[0]->u0,(int)vtx[1]->u0); // bah, don't put two mins on one line
451
min_256 = min(min_256,(int)vtx[2]->u0) >> 8; // or it will be calculated twice
452
453
max_256 = max((int)vtx[0]->u0,(int)vtx[1]->u0); // not like it makes much difference
454
max_256 = max(max_256,(int)vtx[2]->u0) >> 8; // anyway :P
455
456
for (cur_256=min_256; cur_256<=max_256; cur_256++)
457
{
458
left_256 = cur_256 << 8;
459
right_256 = (cur_256+1) << 8;
460
461
// Set vertex buffers
462
rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1
463
rdp.vtxbuf2 = rdp.vtx2;
464
rdp.vtx_buffer = 0;
465
rdp.n_global = 3;
466
index = 0;
467
468
// ** Left plane **
469
for (i=0; i<3; i++)
470
{
471
j = i+1;
472
if (j == 3) j = 0;
473
474
VERTEX *v1 = vtx[i];
475
VERTEX *v2 = vtx[j];
476
477
if (v1->u0 >= left_256)
478
{
479
if (v2->u0 >= left_256) // Both are in, save the last one
480
{
481
rdp.vtxbuf[index] = *v2;
482
rdp.vtxbuf[index].u0 -= left_256;
483
rdp.vtxbuf[index++].v0 += rdp.cur_cache[0]->c_scl_y * (cur_256 * rdp.cur_cache[0]->splitheight);
484
}
485
else // First is in, second is out, save intersection
486
{
487
percent = (left_256 - v1->u0) / (v2->u0 - v1->u0);
488
rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent;
489
rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent;
490
rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent;
491
rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent;
492
rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent;
493
rdp.vtxbuf[index].u0 = 0.5f;
494
rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent +
495
rdp.cur_cache[0]->c_scl_y * cur_256 * rdp.cur_cache[0]->splitheight;
496
rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent;
497
rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent;
498
rdp.vtxbuf[index].b = (BYTE)(v1->b + (v2->b - v1->b) * percent);
499
rdp.vtxbuf[index].g = (BYTE)(v1->g + (v2->g - v1->g) * percent);
500
rdp.vtxbuf[index].r = (BYTE)(v1->r + (v2->r - v1->r) * percent);
501
rdp.vtxbuf[index++].a = (BYTE)(v1->a + (v2->a - v1->a) * percent);
502
}
503
}
504
else
505
{
506
//if (v2->u0 < left_256) // Both are out, save nothing
507
if (v2->u0 >= left_256) // First is out, second is in, save intersection & in point
508
{
509
percent = (left_256 - v2->u0) / (v1->u0 - v2->u0);
510
rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent;
511
rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent;
512
rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent;
513
rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent;
514
rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent;
515
rdp.vtxbuf[index].u0 = 0.5f;
516
rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent +
517
rdp.cur_cache[0]->c_scl_y * cur_256 * rdp.cur_cache[0]->splitheight;
518
rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent;
519
rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent;
520
rdp.vtxbuf[index].b = (BYTE)(v2->b + (v1->b - v2->b) * percent);
521
rdp.vtxbuf[index].g = (BYTE)(v2->g + (v1->g - v2->g) * percent);
522
rdp.vtxbuf[index].r = (BYTE)(v2->r + (v1->r - v2->r) * percent);
523
rdp.vtxbuf[index++].a = (BYTE)(v2->a + (v1->a - v2->a) * percent);
524
525
// Save the in point
526
rdp.vtxbuf[index] = *v2;
527
rdp.vtxbuf[index].u0 -= left_256;
528
rdp.vtxbuf[index++].v0 += rdp.cur_cache[0]->c_scl_y * (cur_256 * rdp.cur_cache[0]->splitheight);
529
}
530
}
531
}
532
rdp.n_global = index;
533
534
rdp.vtxbuf = rdp.vtx2; // now vtx1 holds the value, & vtx2 is the destination
535
rdp.vtxbuf2 = rdp.vtx1;
536
rdp.vtx_buffer ^= 1;
537
index = 0;
538
539
for (i=0; i<rdp.n_global; i++)
540
{
541
j = i+1;
542
if (j == rdp.n_global) j = 0;
543
544
VERTEX *v1 = &rdp.vtxbuf2[i];
545
VERTEX *v2 = &rdp.vtxbuf2[j];
546
547
// ** Right plane **
548
if (v1->u0 <= 256.0f)
549
{
550
if (v2->u0 <= 256.0f) // Both are in, save the last one
551
{
552
rdp.vtxbuf[index] = *v2;
553
rdp.vtxbuf[index++].not_zclipped = 0;
554
}
555
else // First is in, second is out, save intersection
556
{
557
percent = (right_256 - v1->u0) / (v2->u0 - v1->u0);
558
rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent;
559
rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent;
560
rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent;
561
rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent;
562
rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent;
563
rdp.vtxbuf[index].u0 = 255.5f;
564
rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent;
565
rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent;
566
rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent;
567
rdp.vtxbuf[index].b = (BYTE)(v1->b + (v2->b - v1->b) * percent);
568
rdp.vtxbuf[index].g = (BYTE)(v1->g + (v2->g - v1->g) * percent);
569
rdp.vtxbuf[index].r = (BYTE)(v1->r + (v2->r - v1->r) * percent);
570
rdp.vtxbuf[index].a = (BYTE)(v1->a + (v2->a - v1->a) * percent);
571
rdp.vtxbuf[index++].not_zclipped = 0;
572
}
573
}
574
else
575
{
576
//if (v2->u0 > 256.0f) // Both are out, save nothing
577
if (v2->u0 <= 256.0f) // First is out, second is in, save intersection & in point
578
{
579
percent = (right_256 - v2->u0) / (v1->u0 - v2->u0);
580
rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent;
581
rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent;
582
rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent;
583
rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent;
584
rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent;
585
rdp.vtxbuf[index].u0 = 255.5f;
586
rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent;
587
rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent;
588
rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent;
589
rdp.vtxbuf[index].b = (BYTE)(v2->b + (v1->b - v2->b) * percent);
590
rdp.vtxbuf[index].g = (BYTE)(v2->g + (v1->g - v2->g) * percent);
591
rdp.vtxbuf[index].r = (BYTE)(v2->r + (v1->r - v2->r) * percent);
592
rdp.vtxbuf[index].a = (BYTE)(v2->a + (v1->a - v2->a) * percent);
593
rdp.vtxbuf[index++].not_zclipped = 0;
594
595
// Save the in point
596
rdp.vtxbuf[index] = *v2;
597
rdp.vtxbuf[index++].not_zclipped = 0;
598
}
599
}
600
}
601
rdp.n_global = index;
602
603
do_triangle_stuff (linew);
604
}
605
}
606
else
607
{
608
// Set vertex buffers
609
rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1
610
rdp.vtxbuf2 = rdp.vtx2;
611
rdp.vtx_buffer = 0;
612
rdp.n_global = 3;
613
614
rdp.vtxbuf[0] = *vtx[0];
615
rdp.vtxbuf[1] = *vtx[1];
616
rdp.vtxbuf[2] = *vtx[2];
617
618
do_triangle_stuff (linew);
619
}
620
}
621
622
void do_triangle_stuff (WORD linew) // what else?? do the triangle stuff :P (to keep from writing code twice)
623
{
624
int i;
625
626
// if (rdp.zsrc != 1)
627
clip_z ();
628
629
for (i=0; i<rdp.n_global; i++)
630
{
631
if (rdp.vtxbuf[i].not_zclipped)// && rdp.zsrc != 1)
632
{
633
#ifdef EXTREME_LOGGING
634
FRDP (" * NOT ZCLIPPPED: %d\n", rdp.vtxbuf[i].number);
635
#endif
636
rdp.vtxbuf[i].x = rdp.vtxbuf[i].sx;
637
rdp.vtxbuf[i].y = rdp.vtxbuf[i].sy;
638
rdp.vtxbuf[i].z = rdp.vtxbuf[i].sz;
639
rdp.vtxbuf[i].q = rdp.vtxbuf[i].oow;
640
rdp.vtxbuf[i].u0 = rdp.vtxbuf[i].u0_w;
641
rdp.vtxbuf[i].v0 = rdp.vtxbuf[i].v0_w;
642
rdp.vtxbuf[i].u1 = rdp.vtxbuf[i].u1_w;
643
rdp.vtxbuf[i].v1 = rdp.vtxbuf[i].v1_w;
644
}
645
else
646
{
647
#ifdef EXTREME_LOGGING
648
FRDP (" * ZCLIPPED: %d\n", rdp.vtxbuf[i].number);
649
#endif
650
rdp.vtxbuf[i].q = 1.0f / rdp.vtxbuf[i].w;
651
rdp.vtxbuf[i].x = rdp.view_trans[0] + rdp.vtxbuf[i].x * rdp.vtxbuf[i].q * rdp.view_scale[0];
652
rdp.vtxbuf[i].y = rdp.view_trans[1] + rdp.vtxbuf[i].y * rdp.vtxbuf[i].q * rdp.view_scale[1];
653
rdp.vtxbuf[i].z = rdp.view_trans[2] + rdp.vtxbuf[i].z * rdp.vtxbuf[i].q * rdp.view_scale[2];
654
if (rdp.tex >= 1)
655
{
656
rdp.vtxbuf[i].u0 *= rdp.vtxbuf[i].q;
657
rdp.vtxbuf[i].v0 *= rdp.vtxbuf[i].q;
658
}
659
if (rdp.tex >= 2)
660
{
661
rdp.vtxbuf[i].u1 *= rdp.vtxbuf[i].q;
662
rdp.vtxbuf[i].v1 *= rdp.vtxbuf[i].q;
663
}
664
}
665
666
if (rdp.zsrc == 1)
667
rdp.vtxbuf[i].z = rdp.prim_depth;
668
669
// Don't remove clipping, or it will freeze
670
if (rdp.vtxbuf[i].x > rdp.scissor.lr_x) rdp.clip |= CLIP_XMAX;
671
if (rdp.vtxbuf[i].x < rdp.scissor.ul_x) rdp.clip |= CLIP_XMIN;
672
if (rdp.vtxbuf[i].y > rdp.scissor.lr_y) rdp.clip |= CLIP_YMAX;
673
if (rdp.vtxbuf[i].y < rdp.scissor.ul_y) rdp.clip |= CLIP_YMIN;
674
}
675
676
clip_tri (linew);
677
}
678
679
void do_triangle_stuff_2 (WORD linew)
680
{
681
rdp.clip = 0;
682
683
for (int i=0; i<rdp.n_global; i++)
684
{
685
// Don't remove clipping, or it will freeze
686
if (rdp.vtxbuf[i].x > rdp.scissor.lr_x) rdp.clip |= CLIP_XMAX;
687
if (rdp.vtxbuf[i].x < rdp.scissor.ul_x) rdp.clip |= CLIP_XMIN;
688
if (rdp.vtxbuf[i].y > rdp.scissor.lr_y) rdp.clip |= CLIP_YMAX;
689
if (rdp.vtxbuf[i].y < rdp.scissor.ul_y) rdp.clip |= CLIP_YMIN;
690
}
691
692
clip_tri (linew);
693
}
694
695
//
696
// clip_z - clips along the z-axis, also copies the vertex buffer for clip_tri
697
// * ALWAYS * processes it, even if it does not need z-clipping. It needs
698
// to copy the buffer anyway.
699
//
700
701
void clip_z ()
702
{
703
int i,j,index,n=rdp.n_global;
704
float percent;
705
706
if (rdp.clip & CLIP_ZMIN)
707
{
708
// Swap vertex buffers
709
VERTEX *tmp = rdp.vtxbuf2;
710
rdp.vtxbuf2 = rdp.vtxbuf;
711
rdp.vtxbuf = tmp;
712
rdp.vtx_buffer ^= 1;
713
index = 0;
714
715
// Check the vertices for clipping
716
for (i=0; i<n; i++)
717
{
718
j = i+1;
719
if (j == n) j = 0;
720
721
if (Vi.w >= 0.01f)
722
{
723
if (Vj.w >= 0.01f) // Both are in, save the last one
724
{
725
rdp.vtxbuf[index] = Vj;
726
rdp.vtxbuf[index++].not_zclipped = 1;
727
}
728
else // First is in, second is out, save intersection
729
{
730
percent = (-Vi.w) / (Vj.w - Vi.w);
731
rdp.vtxbuf[index].not_zclipped = 0;
732
rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
733
rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;
734
rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
735
rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;
736
rdp.vtxbuf[index].w = 0.01f;
737
rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
738
rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
739
rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
740
rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
741
rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);
742
rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);
743
rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);
744
rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);
745
}
746
}
747
else
748
{
749
//if (Vj.w < 0.01f) // Both are out, save nothing
750
if (Vj.w >= 0.01f) // First is out, second is in, save intersection & in point
751
{
752
percent = (-Vj.w) / (Vi.w - Vj.w);
753
rdp.vtxbuf[index].not_zclipped = 0;
754
rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
755
rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;
756
rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
757
rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;
758
rdp.vtxbuf[index].w = 0.01f;
759
rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
760
rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
761
rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
762
rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
763
rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);
764
rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);
765
rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);
766
rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);
767
768
// Save the in point
769
rdp.vtxbuf[index] = Vj;
770
rdp.vtxbuf[index++].not_zclipped = 1;
771
}
772
}
773
}
774
rdp.n_global = index;
775
}
776
}
777
778
static void CalculateLOD(VERTEX **v, int n)
779
{
780
//rdp.update |= UPDATE_TEXTURE;
781
/*
782
if (rdp.lod_calculated)
783
{
784
float detailmax;
785
if (dc0_detailmax < 0.5)
786
detailmax = rdp.lod_fraction;
787
else
788
detailmax = 1.0f - rdp.lod_fraction;
789
grTexDetailControl (GR_TMU0, dc0_lodbias, dc0_detailscale, detailmax);
790
if (num_tmu == 2)
791
grTexDetailControl (GR_TMU1, dc1_lodbias, dc1_detailscale, detailmax);
792
return;
793
}
794
*/
795
float deltaS, deltaT;
796
float deltaX, deltaY;
797
double deltaTexels, deltaPixels, lodFactor = 0;
798
double intptr;
799
float s_scale = rdp.tiles[rdp.cur_tile].width / 255.0f;
800
float t_scale = rdp.tiles[rdp.cur_tile].height / 255.0f;
801
if (settings.lodmode == 1)
802
{
803
deltaS = (v[1]->u0/v[1]->q - v[0]->u0/v[0]->q) * s_scale;
804
deltaT = (v[1]->v0/v[1]->q - v[0]->v0/v[0]->q) * t_scale;
805
deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT );
806
807
deltaX = (v[1]->x - v[0]->x)/rdp.scale_x;
808
deltaY = (v[1]->y - v[0]->y)/rdp.scale_y;
809
deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY );
810
811
lodFactor = deltaTexels / deltaPixels;
812
}
813
else
814
{
815
int i, j;
816
for (i = 0; i < n; i++)
817
{
818
j = (i < n-1) ? i + 1 : 0;
819
820
deltaS = (v[j]->u0/v[j]->q - v[i]->u0/v[i]->q) * s_scale;
821
deltaT = (v[j]->v0/v[j]->q - v[i]->v0/v[i]->q) * t_scale;
822
// deltaS = v[j]->ou - v[i]->ou;
823
// deltaT = v[j]->ov - v[i]->ov;
824
deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT );
825
826
deltaX = (v[j]->x - v[i]->x)/rdp.scale_x;
827
deltaY = (v[j]->y - v[i]->y)/rdp.scale_y;
828
deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY );
829
830
lodFactor += deltaTexels / deltaPixels;
831
}
832
// Divide by n (n edges) to find average
833
lodFactor = lodFactor / n;
834
}
835
long ilod = (long)lodFactor;
836
int lod_tile = min((int)(log((double)ilod)/log(2.0)), rdp.cur_tile + rdp.mipmap_level);
837
float lod_fraction = 1.0f;
838
if (lod_tile < rdp.cur_tile + rdp.mipmap_level)
839
{
840
lod_fraction = max((float)modf(lodFactor / pow(2.0f,lod_tile),&intptr), rdp.prim_lodmin / 255.0f);
841
}
842
float detailmax;
843
if (cmb.dc0_detailmax < 0.5f)
844
detailmax = lod_fraction;
845
else
846
detailmax = 1.0f - lod_fraction;
847
grTexDetailControl (GR_TMU0, cmb.dc0_lodbias, cmb.dc0_detailscale, detailmax);
848
if (num_tmu == 2)
849
grTexDetailControl (GR_TMU1, cmb.dc1_lodbias, cmb.dc1_detailscale, detailmax);
850
FRDP("CalculateLOD factor: %f, tile: %d, lod_fraction: %f\n", (float)lodFactor, lod_tile, lod_fraction);
851
}
852
853
static void DepthBuffer(VERTEX ** vtx, int n)
854
{
855
if (settings.RE2)
856
{
857
for(int i=0; i<n; i++)
858
{
859
int fz = (int)(vtx[i]->z*8.0f+0.5f);
860
if (fz < 0) fz = 0;
861
else if (fz >= 0x40000) fz = 0x40000 - 1;
862
vtx[i]->z = (float)zLUT[fz];
863
}
864
return;
865
}
866
if (settings.fb_depth_render && dzdx && (rdp.flags & ZBUF_UPDATE))
867
{
868
vertexi v[12];
869
870
for(int i=0; i<n; i++)
871
{
872
v[i].x = (long)(vtx[i]->x / rdp.scale_x * 65536.0);
873
v[i].y = (long)(vtx[i]->y / rdp.scale_y * 65536.0);
874
v[i].z = (long)(vtx[i]->z * 65536.0);
875
}
876
Rasterize(v, n, dzdx);
877
}
878
for(int i=0; i<n; i++)
879
vtx[i]->z = ScaleZ(vtx[i]->z);
880
}
881
882
void clip_tri (WORD linew)
883
{
884
int i,j,index,n=rdp.n_global;
885
float percent;
886
887
// rdp.vtxbuf and rdp.vtxbuf2 were set by clip_z
888
889
// Check which clipping is needed
890
if (rdp.clip & CLIP_XMAX) // right of the screen
891
{
892
// Swap vertex buffers
893
VERTEX *tmp = rdp.vtxbuf2;
894
rdp.vtxbuf2 = rdp.vtxbuf;
895
rdp.vtxbuf = tmp;
896
rdp.vtx_buffer ^= 1;
897
index = 0;
898
899
// Check the vertices for clipping
900
for (i=0; i<n; i++)
901
{
902
j = i+1;
903
if (j == n) j = 0;
904
905
if (Vi.x <= rdp.scissor.lr_x)
906
{
907
if (Vj.x <= rdp.scissor.lr_x) // Both are in, save the last one
908
{
909
rdp.vtxbuf[index++] = Vj;
910
}
911
else // First is in, second is out, save intersection
912
{
913
percent = (rdp.scissor.lr_x - Vi.x) / (Vj.x - Vi.x);
914
rdp.vtxbuf[index].x = (float)rdp.scissor.lr_x + 0.001f;
915
rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;
916
rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
917
rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
918
rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;
919
rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
920
rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
921
rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
922
rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
923
rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);
924
rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);
925
rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);
926
rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);
927
}
928
}
929
else
930
{
931
//if (Vj.x > rdp.scissor.lr_x) // Both are out, save nothing
932
if (Vj.x <= rdp.scissor.lr_x) // First is out, second is in, save intersection & in point
933
{
934
percent = (rdp.scissor.lr_x - Vj.x) / (Vi.x - Vj.x);
935
rdp.vtxbuf[index].x = (float)rdp.scissor.lr_x + 0.001f;
936
rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;
937
rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
938
rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
939
rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;
940
rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
941
rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
942
rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
943
rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
944
rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);
945
rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);
946
rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);
947
rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);
948
949
// Save the in point
950
rdp.vtxbuf[index++] = Vj;
951
}
952
}
953
}
954
n = index;
955
}
956
if (rdp.clip & CLIP_XMIN) // left of the screen
957
{
958
// Swap vertex buffers
959
VERTEX *tmp = rdp.vtxbuf2;
960
rdp.vtxbuf2 = rdp.vtxbuf;
961
rdp.vtxbuf = tmp;
962
rdp.vtx_buffer ^= 1;
963
index = 0;
964
965
// Check the vertices for clipping
966
for (i=0; i<n; i++)
967
{
968
j = i+1;
969
if (j == n) j = 0;
970
971
if (Vi.x >= rdp.scissor.ul_x)
972
{
973
if (Vj.x >= rdp.scissor.ul_x) // Both are in, save the last one
974
{
975
rdp.vtxbuf[index++] = Vj;
976
}
977
else // First is in, second is out, save intersection
978
{
979
percent = (rdp.scissor.ul_x - Vi.x) / (Vj.x - Vi.x);
980
rdp.vtxbuf[index].x = (float)rdp.scissor.ul_x + 0.001f;
981
rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;
982
rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
983
rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
984
rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;
985
rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
986
rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
987
rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
988
rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
989
rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);
990
rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);
991
rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);
992
rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);
993
}
994
}
995
else
996
{
997
//if (Vj.x < rdp.scissor.ul_x) // Both are out, save nothing
998
if (Vj.x >= rdp.scissor.ul_x) // First is out, second is in, save intersection & in point
999
{
1000
percent = (rdp.scissor.ul_x - Vj.x) / (Vi.x - Vj.x);
1001
rdp.vtxbuf[index].x = (float)rdp.scissor.ul_x + 0.001f;
1002
rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;
1003
rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
1004
rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
1005
rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;
1006
rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
1007
rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
1008
rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
1009
rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
1010
rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);
1011
rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);
1012
rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);
1013
rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);
1014
1015
// Save the in point
1016
rdp.vtxbuf[index++] = Vj;
1017
}
1018
}
1019
}
1020
n = index;
1021
}
1022
if (rdp.clip & CLIP_YMAX) // top of the screen
1023
{
1024
// Swap vertex buffers
1025
VERTEX *tmp = rdp.vtxbuf2;
1026
rdp.vtxbuf2 = rdp.vtxbuf;
1027
rdp.vtxbuf = tmp;
1028
rdp.vtx_buffer ^= 1;
1029
index = 0;
1030
1031
// Check the vertices for clipping
1032
for (i=0; i<n; i++)
1033
{
1034
j = i+1;
1035
if (j == n) j = 0;
1036
1037
if (Vi.y <= rdp.scissor.lr_y)
1038
{
1039
if (Vj.y <= rdp.scissor.lr_y) // Both are in, save the last one
1040
{
1041
rdp.vtxbuf[index++] = Vj;
1042
}
1043
else // First is in, second is out, save intersection
1044
{
1045
percent = (rdp.scissor.lr_y - Vi.y) / (Vj.y - Vi.y);
1046
rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
1047
rdp.vtxbuf[index].y = (float)rdp.scissor.lr_y + 0.001f;
1048
rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
1049
rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
1050
rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;
1051
rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
1052
rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
1053
rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
1054
rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
1055
rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);
1056
rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);
1057
rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);
1058
rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);
1059
}
1060
}
1061
else
1062
{
1063
//if (Vj.y > rdp.scissor.lr_y) // Both are out, save nothing
1064
if (Vj.y <= rdp.scissor.lr_y) // First is out, second is in, save intersection & in point
1065
{
1066
percent = (rdp.scissor.lr_y - Vj.y) / (Vi.y - Vj.y);
1067
rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
1068
rdp.vtxbuf[index].y = (float)rdp.scissor.lr_y + 0.001f;
1069
rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
1070
rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
1071
rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;
1072
rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
1073
rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
1074
rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
1075
rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
1076
rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);
1077
rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);
1078
rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);
1079
rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);
1080
1081
// Save the in point
1082
rdp.vtxbuf[index++] = Vj;
1083
}
1084
}
1085
}
1086
n = index;
1087
}
1088
if (rdp.clip & CLIP_YMIN) // bottom of the screen
1089
{
1090
// Swap vertex buffers
1091
VERTEX *tmp = rdp.vtxbuf2;
1092
rdp.vtxbuf2 = rdp.vtxbuf;
1093
rdp.vtxbuf = tmp;
1094
rdp.vtx_buffer ^= 1;
1095
index = 0;
1096
1097
// Check the vertices for clipping
1098
for (i=0; i<n; i++)
1099
{
1100
j = i+1;
1101
if (j == n) j = 0;
1102
1103
if (Vi.y >= rdp.scissor.ul_y)
1104
{
1105
if (Vj.y >= rdp.scissor.ul_y) // Both are in, save the last one
1106
{
1107
rdp.vtxbuf[index++] = Vj;
1108
}
1109
else // First is in, second is out, save intersection
1110
{
1111
percent = (rdp.scissor.ul_y - Vi.y) / (Vj.y - Vi.y);
1112
rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
1113
rdp.vtxbuf[index].y = (float)rdp.scissor.ul_y + 0.001f;
1114
rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
1115
rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
1116
rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;
1117
rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
1118
rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
1119
rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
1120
rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
1121
rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);
1122
rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);
1123
rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);
1124
rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);
1125
}
1126
}
1127
else
1128
{
1129
//if (Vj.y < rdp.scissor.ul_y) // Both are out, save nothing
1130
if (Vj.y >= rdp.scissor.ul_y) // First is out, second is in, save intersection & in point
1131
{
1132
percent = (rdp.scissor.ul_y - Vj.y) / (Vi.y - Vj.y);
1133
rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
1134
rdp.vtxbuf[index].y = (float)rdp.scissor.ul_y + 0.001f;
1135
rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
1136
rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
1137
rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;
1138
rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
1139
rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
1140
rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
1141
rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
1142
rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);
1143
rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);
1144
rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);
1145
rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);
1146
1147
// Save the in point
1148
rdp.vtxbuf[index++] = Vj;
1149
}
1150
}
1151
}
1152
n = index;
1153
}
1154
1155
if (n < 3)
1156
{
1157
FRDP (" * clip_tri: n < 3\n");
1158
return;
1159
}
1160
ConvertCoordsConvert (rdp.vtxbuf, n);
1161
if (rdp.fog_coord_enabled)
1162
{
1163
for (i = 0; i < n; i++)
1164
{
1165
rdp.vtxbuf[i].f = 1.0f/max(16.0f,rdp.vtxbuf[i].f);
1166
}
1167
}
1168
1169
if (settings.lodmode > 0 && rdp.cur_tile < rdp.mipmap_level)
1170
CalculateLOD(rdp.vtx_buffer?(vtx_list2):(vtx_list1), n);
1171
1172
cmb.cmb_ext_use = cmb.tex_cmb_ext_use = 0;
1173
1174
/*
1175
if (rdp.hires_tex)
1176
{
1177
for (int k = 0; k < 3; k++)
1178
{
1179
FRDP("v%d %f->%f, width: %d. height: %d, tex_width: %d, tex_height: %d, lr_u: %f, lr_v: %f\n", k, vv0[k], pv[k]->v1, rdp.hires_tex->width, rdp.hires_tex->height, rdp.hires_tex->tex_width, rdp.hires_tex->tex_height, rdp.hires_tex->lr_u, rdp.hires_tex->lr_v);
1180
}
1181
}
1182
*/
1183
if (fullscreen)
1184
{
1185
if (settings.wireframe)
1186
{
1187
SetWireframeCol ();
1188
for (i=0; i<n; i++)
1189
{
1190
j = i+1;
1191
if (j == n) j = 0;
1192
grDrawLine (&rdp.vtxbuf[i], &rdp.vtxbuf[j]);
1193
}
1194
}
1195
else
1196
{
1197
1198
// VERTEX ** pv = rdp.vtx_buffer?(vtx_list2):(vtx_list1);
1199
// for (int k = 0; k < n; k ++)
1200
// FRDP ("DRAW[%d]: v.x = %f, v.y = %f, v.z = %f, v.u = %f, v.v = %f\n", k, pv[k]->x, pv[k]->y, pv[k]->z, pv[k]->coord[rdp.t0<<1], pv[k]->coord[(rdp.t0<<1)+1]);
1201
// pv[k]->y = settings.res_y - pv[k]->y;
1202
1203
if (linew > 0)
1204
{
1205
if (linew == 1)
1206
{
1207
for (i=0; i<n; i++)
1208
{
1209
rdp.vtxbuf[i].z = ScaleZ(rdp.vtxbuf[i].z);
1210
j = i+1;
1211
if (j == n) j = 0;
1212
grDrawLine (&rdp.vtxbuf[i], &rdp.vtxbuf[j]);
1213
}
1214
}
1215
else if (n == 3)
1216
{
1217
rdp.vtxbuf[0].z = ScaleZ(rdp.vtxbuf[0].z);
1218
rdp.vtxbuf[1].z = ScaleZ(rdp.vtxbuf[1].z);
1219
VERTEX v[4];
1220
v[0] = rdp.vtxbuf[0];
1221
v[1] = rdp.vtxbuf[0];
1222
v[2] = rdp.vtxbuf[1];
1223
v[3] = rdp.vtxbuf[1];
1224
float width = (linew-1)*0.25f;
1225
if(rdp.vtxbuf[0].y == rdp.vtxbuf[1].y )
1226
{
1227
v[0].x = v[1].x = rdp.vtxbuf[0].x;
1228
v[2].x = v[3].x = rdp.vtxbuf[1].x;
1229
1230
v[0].y = v[2].y = rdp.vtxbuf[0].y-width*rdp.scale_y+1;
1231
v[1].y = v[3].y = rdp.vtxbuf[0].y+width*rdp.scale_y;
1232
}
1233
else
1234
{
1235
v[0].y = v[1].y = rdp.vtxbuf[0].y;
1236
v[2].y = v[3].y = rdp.vtxbuf[1].y;
1237
1238
v[0].x = v[2].x = rdp.vtxbuf[0].x-width*rdp.scale_x+1;
1239
v[1].x = v[3].x = rdp.vtxbuf[0].x+width*rdp.scale_x;
1240
}
1241
grDrawTriangle(&v[0], &v[1], &v[2]);
1242
grDrawTriangle(&v[1], &v[2], &v[3]);
1243
}
1244
}
1245
else
1246
{
1247
if (settings.ucode == 5)
1248
for (i=0; i<n; i++)
1249
if (rdp.vtxbuf[i].z < -1000.0f) return;//rdp.vtxbuf[i].z = 0.0f;
1250
DepthBuffer(rdp.vtx_buffer?(vtx_list2):(vtx_list1), n);
1251
grDrawVertexArray (GR_TRIANGLE_FAN, n, rdp.vtx_buffer?(&vtx_list2):(&vtx_list1));
1252
}
1253
//grDrawVertexArrayContiguous (GR_TRIANGLE_FAN, n, rdp.vtxbuf, sizeof(VERTEX));
1254
}
1255
}
1256
1257
if (debug.capture) add_tri (rdp.vtxbuf, n, TRI_TRIANGLE);
1258
}
1259
1260
void add_tri (VERTEX *v, int n, int type)
1261
{
1262
//FRDP ("ENTER (%f, %f, %f), (%f, %f, %f), (%f, %f, %f)\n", v[0].x, v[0].y, v[0].w,
1263
// v[1].x, v[1].y, v[1].w, v[2].x, v[2].y, v[2].w);
1264
1265
// Debug capture
1266
if (debug.capture)
1267
{
1268
rdp.debug_n ++;
1269
1270
TRI_INFO *info = new TRI_INFO;
1271
info->nv = n;
1272
info->v = new VERTEX [n];
1273
memcpy (info->v, v, sizeof(VERTEX)*n);
1274
info->cycle_mode = rdp.cycle_mode;
1275
info->cycle1 = rdp.cycle1;
1276
info->cycle2 = rdp.cycle2;
1277
info->uncombined = rdp.uncombined;
1278
info->geom_mode = rdp.geom_mode;
1279
info->othermode_h = rdp.othermode_h;
1280
info->othermode_l = rdp.othermode_l;
1281
info->tri_n = rdp.tri_n;
1282
info->type = type;
1283
1284
for (int i=0; i<2; i++)
1285
{
1286
int j = rdp.cur_tile+i;
1287
if (i == 0)
1288
info->t[i].tmu = rdp.t0;
1289
else
1290
info->t[i].tmu = rdp.t1;
1291
info->t[i].cur_cache[0] = rdp.cur_cache_n[rdp.t0];
1292
info->t[i].cur_cache[1] = rdp.cur_cache_n[rdp.t1];
1293
info->t[i].format = rdp.tiles[j].format;
1294
info->t[i].size = rdp.tiles[j].size;
1295
info->t[i].width = rdp.tiles[j].width;
1296
info->t[i].height = rdp.tiles[j].height;
1297
info->t[i].line = rdp.tiles[j].line;
1298
info->t[i].palette = rdp.tiles[j].palette;
1299
info->t[i].clamp_s = rdp.tiles[j].clamp_s;
1300
info->t[i].clamp_t = rdp.tiles[j].clamp_t;
1301
info->t[i].mirror_s = rdp.tiles[j].mirror_s;
1302
info->t[i].mirror_t = rdp.tiles[j].mirror_t;
1303
info->t[i].shift_s = rdp.tiles[j].shift_s;
1304
info->t[i].shift_t = rdp.tiles[j].shift_t;
1305
info->t[i].mask_s = rdp.tiles[j].mask_s;
1306
info->t[i].mask_t = rdp.tiles[j].mask_t;
1307
info->t[i].ul_s = rdp.tiles[j].ul_s;
1308
info->t[i].ul_t = rdp.tiles[j].ul_t;
1309
info->t[i].lr_s = rdp.tiles[j].lr_s;
1310
info->t[i].lr_t = rdp.tiles[j].lr_t;
1311
info->t[i].t_ul_s = rdp.tiles[7].t_ul_s;
1312
info->t[i].t_ul_t = rdp.tiles[7].t_ul_t;
1313
info->t[i].t_lr_s = rdp.tiles[7].t_lr_s;
1314
info->t[i].t_lr_t = rdp.tiles[7].t_lr_t;
1315
info->t[i].scale_s = rdp.tiles[j].s_scale;
1316
info->t[i].scale_t = rdp.tiles[j].t_scale;
1317
}
1318
1319
info->fog_color = rdp.fog_color;
1320
info->fill_color = rdp.fill_color;
1321
info->prim_color = rdp.prim_color;
1322
info->blend_color = rdp.blend_color;
1323
info->env_color = rdp.env_color;
1324
info->prim_lodmin = rdp.prim_lodmin;
1325
info->prim_lodfrac = rdp.prim_lodfrac;
1326
1327
info->pNext = debug.tri_list;
1328
debug.tri_list = info;
1329
1330
if (debug.tri_last == NULL)
1331
debug.tri_last = debug.tri_list;
1332
}
1333
}
1334
1335
void update_scissor ()
1336
{
1337
if (rdp.update & UPDATE_SCISSOR)
1338
{
1339
rdp.update ^= UPDATE_SCISSOR;
1340
1341
// KILL the floating point error with 0.01f
1342
rdp.scissor.ul_x = (DWORD) max(min((rdp.scissor_o.ul_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0);
1343
rdp.scissor.lr_x = (DWORD) max(min((rdp.scissor_o.lr_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0);
1344
rdp.scissor.ul_y = (DWORD) max(min((rdp.scissor_o.ul_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0);
1345
rdp.scissor.lr_y = (DWORD) max(min((rdp.scissor_o.lr_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0);
1346
FRDP (" |- scissor - (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y,
1347
rdp.scissor.lr_x, rdp.scissor.lr_y);
1348
}
1349
}
1350
1351
//
1352
// update - update states if they need it
1353
//
1354
1355
typedef struct
1356
{
1357
unsigned int c2_m2b:2;
1358
unsigned int c1_m2b:2;
1359
unsigned int c2_m2a:2;
1360
unsigned int c1_m2a:2;
1361
unsigned int c2_m1b:2;
1362
unsigned int c1_m1b:2;
1363
unsigned int c2_m1a:2;
1364
unsigned int c1_m1a:2;
1365
} rdp_blender_setting;
1366
1367
void update ()
1368
{
1369
RDP ("-+ update called\n");
1370
// Check for rendermode changes
1371
// Z buffer
1372
if (rdp.render_mode_changed & 0x00000C30)
1373
{
1374
FRDP (" |- render_mode_changed zbuf - decal: %s, update: %s, compare: %s\n",
1375
str_yn[(rdp.othermode_l&0x00000C00) == 0x00000C00],
1376
str_yn[(rdp.othermode_l&0x00000020)?1:0],
1377
str_yn[(rdp.othermode_l&0x00000010)?1:0]);
1378
1379
rdp.render_mode_changed &= ~0x00000C30;
1380
rdp.update |= UPDATE_ZBUF_ENABLED;
1381
1382
// Decal?
1383
// if ((rdp.othermode_l & 0x00000C00) == 0x00000C00)
1384
if (rdp.othermode_l & 0x00000800)
1385
rdp.flags |= ZBUF_DECAL;
1386
else
1387
rdp.flags &= ~ZBUF_DECAL;
1388
1389
// Update?
1390
if ((rdp.othermode_l & 0x00000020))
1391
rdp.flags |= ZBUF_UPDATE;
1392
else
1393
rdp.flags &= ~ZBUF_UPDATE;
1394
1395
// Compare?
1396
if (rdp.othermode_l & 0x00000010)
1397
rdp.flags |= ZBUF_COMPARE;
1398
else
1399
rdp.flags &= ~ZBUF_COMPARE;
1400
}
1401
1402
// Alpha compare
1403
if (rdp.render_mode_changed & 0x00001000)
1404
{
1405
FRDP (" |- render_mode_changed alpha compare - on: %s\n",
1406
str_yn[(rdp.othermode_l&0x00001000)?1:0]);
1407
rdp.render_mode_changed &= ~0x00001000;
1408
rdp.update |= UPDATE_ALPHA_COMPARE;
1409
1410
if (rdp.othermode_l & 0x00001000)
1411
rdp.flags |= ALPHA_COMPARE;
1412
else
1413
rdp.flags &= ~ALPHA_COMPARE;
1414
}
1415
1416
if (rdp.render_mode_changed & 0x00002000) // alpha cvg sel
1417
{
1418
FRDP (" |- render_mode_changed alpha cvg sel - on: %s\n",
1419
str_yn[(rdp.othermode_l&0x00002000)?1:0]);
1420
rdp.render_mode_changed &= ~0x00002000;
1421
rdp.update |= UPDATE_COMBINE;
1422
}
1423
1424
// Force blend
1425
if (rdp.render_mode_changed & 0xFFFF0000)
1426
{
1427
FRDP (" |- render_mode_changed force_blend - %08lx\n", rdp.othermode_l&0xFFFF0000);
1428
rdp.render_mode_changed &= 0x0000FFFF;
1429
1430
rdp.fbl_a0 = (BYTE)((rdp.othermode_l>>30)&0x3);
1431
rdp.fbl_b0 = (BYTE)((rdp.othermode_l>>26)&0x3);
1432
rdp.fbl_c0 = (BYTE)((rdp.othermode_l>>22)&0x3);
1433
rdp.fbl_d0 = (BYTE)((rdp.othermode_l>>18)&0x3);
1434
rdp.fbl_a1 = (BYTE)((rdp.othermode_l>>28)&0x3);
1435
rdp.fbl_b1 = (BYTE)((rdp.othermode_l>>24)&0x3);
1436
rdp.fbl_c1 = (BYTE)((rdp.othermode_l>>20)&0x3);
1437
rdp.fbl_d1 = (BYTE)((rdp.othermode_l>>16)&0x3);
1438
1439
rdp.update |= UPDATE_COMBINE;
1440
}
1441
1442
//if (fullscreen)
1443
//{
1444
// Combine MUST go before texture
1445
if ((rdp.update & UPDATE_COMBINE) && rdp.allow_combine)
1446
{
1447
RDP (" |-+ update_combine\n");
1448
Combine ();
1449
}
1450
1451
if (rdp.update & UPDATE_TEXTURE) // note: UPDATE_TEXTURE and UPDATE_COMBINE are the same
1452
{
1453
rdp.tex_ctr ++;
1454
if (rdp.tex_ctr == 0xFFFFFFFF)
1455
rdp.tex_ctr = 0;
1456
1457
TexCache ();
1458
if (rdp.noise == noise_none)
1459
rdp.update ^= UPDATE_TEXTURE;
1460
}
1461
1462
if (fullscreen)
1463
{
1464
// Z buffer
1465
if (rdp.update & UPDATE_ZBUF_ENABLED)
1466
{
1467
// already logged above
1468
rdp.update ^= UPDATE_ZBUF_ENABLED;
1469
1470
if (rdp.flags & ZBUF_DECAL)
1471
{
1472
if ((rdp.othermode_l & 0x00000C00) == 0x00000C00)
1473
{
1474
grDepthBiasLevel (settings.depth_bias);//(-32);
1475
FRDP("depth bias: %d\n", settings.depth_bias);
1476
}
1477
else
1478
{
1479
// VP changed that to -1 (was -4)
1480
grDepthBiasLevel (-4);//-16);
1481
RDP("depth bias: -4");
1482
}
1483
}
1484
else
1485
{
1486
grDepthBiasLevel (0);
1487
}
1488
1489
if ((rdp.flags & ZBUF_ENABLED) || (settings.force_depth_compare && rdp.zsrc == 1))
1490
{
1491
if ((rdp.flags & ZBUF_COMPARE))
1492
{
1493
if (settings.soft_depth_compare)
1494
{
1495
grDepthBufferFunction (GR_CMP_LEQUAL);
1496
}
1497
else
1498
{
1499
grDepthBufferFunction (GR_CMP_LESS);
1500
}
1501
}
1502
else
1503
{
1504
grDepthBufferFunction (GR_CMP_ALWAYS);
1505
}
1506
1507
if ((rdp.flags & ZBUF_UPDATE)
1508
// || (rdp.flags & ZBUF_DECAL) // FOR DEBUGGING ONLY
1509
)
1510
{
1511
grDepthMask (FXTRUE);
1512
}
1513
else
1514
{
1515
grDepthMask (FXFALSE);
1516
}
1517
}
1518
else
1519
{
1520
grDepthBufferFunction (GR_CMP_ALWAYS);
1521
grDepthMask (FXFALSE);
1522
}
1523
}
1524
// Alpha compare
1525
if (rdp.update & UPDATE_ALPHA_COMPARE)
1526
{
1527
// already logged above
1528
rdp.update ^= UPDATE_ALPHA_COMPARE;
1529
1530
// if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && !force_full_alpha)
1531
// if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (rdp.blend_color&0xFF))
1532
if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (!(rdp.othermode_l & 0x00004000) || (rdp.blend_color&0xFF)))
1533
{
1534
BYTE reference = (BYTE)(rdp.blend_color&0xFF);
1535
if (reference)
1536
grAlphaTestFunction (GR_CMP_GEQUAL);
1537
else
1538
grAlphaTestFunction (GR_CMP_GREATER);
1539
grAlphaTestReferenceValue (reference);
1540
FRDP (" |- alpha compare: blend: %02lx\n", reference);
1541
}
1542
else
1543
{
1544
if (rdp.flags & ALPHA_COMPARE)
1545
{
1546
if ((rdp.othermode_l & 0x5000) != 0x5000)
1547
{
1548
grAlphaTestFunction (GR_CMP_GEQUAL);
1549
grAlphaTestReferenceValue (0x20);//0xA0);
1550
RDP (" |- alpha compare: 0x20\n");
1551
}
1552
else
1553
{
1554
grAlphaTestFunction (GR_CMP_GREATER);
1555
if (rdp.acmp == 3)
1556
{
1557
grAlphaTestReferenceValue ((BYTE)(rdp.blend_color&0xFF));
1558
FRDP (" |- alpha compare: blend: %02lx\n", rdp.blend_color&0xFF);
1559
}
1560
else
1561
{
1562
grAlphaTestReferenceValue (0x00);
1563
RDP (" |- alpha compare: 0x00\n");
1564
}
1565
}
1566
}
1567
else
1568
{
1569
grAlphaTestFunction (GR_CMP_ALWAYS);
1570
RDP (" |- alpha compare: none\n");
1571
}
1572
}
1573
if (rdp.acmp == 3)
1574
{
1575
if (grStippleModeExt)
1576
{
1577
RDP (" |- alpha compare: dither\n");
1578
grStippleModeExt(settings.stipple_mode);
1579
// grStippleModeExt(GR_STIPPLE_PATTERN);
1580
}
1581
}
1582
else
1583
{
1584
if (grStippleModeExt)
1585
{
1586
//RDP (" |- alpha compare: dither disabled\n");
1587
grStippleModeExt(GR_STIPPLE_DISABLE);
1588
}
1589
}
1590
}
1591
// Cull mode (leave this in for z-clipped triangles)
1592
if (rdp.update & UPDATE_CULL_MODE)
1593
{
1594
rdp.update ^= UPDATE_CULL_MODE;
1595
DWORD mode = (rdp.flags & CULLMASK) >> CULLSHIFT;
1596
FRDP (" |- cull_mode - mode: %s\n", str_cull[mode]);
1597
switch (mode)
1598
{
1599
case 0: // cull none
1600
case 3: // cull both
1601
grCullMode(GR_CULL_DISABLE);
1602
break;
1603
case 1: // cull front
1604
// grCullMode(GR_CULL_POSITIVE);
1605
grCullMode(GR_CULL_NEGATIVE);
1606
break;
1607
case 2: // cull back
1608
// grCullMode (GR_CULL_NEGATIVE);
1609
grCullMode (GR_CULL_POSITIVE);
1610
break;
1611
}
1612
}
1613
1614
//Added by Gonetz.
1615
if (settings.fog && (rdp.update & UPDATE_FOG_ENABLED))
1616
{
1617
rdp.update ^= UPDATE_FOG_ENABLED;
1618
1619
if (rdp.flags & FOG_ENABLED)
1620
{
1621
typedef union { WORD *w; rdp_blender_setting *b; } BLEND;
1622
WORD blword = (WORD) (rdp.othermode_l >> 16);
1623
BLEND bl;
1624
bl.w = &blword;
1625
if((rdp.fog_multiplier > 0) && (bl.b->c1_m1a==3 || bl.b->c1_m2a == 3 || bl.b->c2_m1a == 3 || bl.b->c2_m2a == 3))
1626
{
1627
grFogColorValue(rdp.fog_color);
1628
grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
1629
rdp.fog_coord_enabled = TRUE;
1630
RDP("fog enabled \n");
1631
}
1632
else
1633
{
1634
RDP("fog disabled in blender\n");
1635
rdp.fog_coord_enabled = FALSE;
1636
grFogMode (GR_FOG_DISABLE);
1637
}
1638
}
1639
else
1640
{
1641
RDP("fog disabled\n");
1642
rdp.fog_coord_enabled = FALSE;
1643
grFogMode (GR_FOG_DISABLE);
1644
}
1645
}
1646
}
1647
1648
if (rdp.update & UPDATE_VIEWPORT)
1649
{
1650
rdp.update ^= UPDATE_VIEWPORT;
1651
if (fullscreen)
1652
{
1653
if (settings.RE2)
1654
{
1655
grClipWindow (0, 0, settings.res_x-1, settings.res_y-1);
1656
}
1657
else
1658
{
1659
float scale_x = (float)fabs(rdp.view_scale[0]);
1660
float scale_y = (float)fabs(rdp.view_scale[1]);
1661
//printf("scale_y %g\n", scale_y);
1662
1663
DWORD min_x = (DWORD) max(rdp.view_trans[0] - scale_x, 0);
1664
DWORD min_y = (DWORD) max(rdp.view_trans[1] - scale_y, 0);
1665
DWORD max_x = (DWORD) min(rdp.view_trans[0] + scale_x + 1, settings.res_x);
1666
DWORD max_y = (DWORD) min(rdp.view_trans[1] + scale_y + 1, settings.res_y);
1667
1668
FRDP (" |- viewport - (%d, %d, %d, %d)\n", min_x, min_y, max_x, max_y);
1669
grClipWindow (min_x, min_y, max_x, max_y);
1670
//printf("viewport %d %d %d %d\n", min_x, min_y, max_x, max_y);
1671
}
1672
}
1673
}
1674
1675
if (rdp.update & UPDATE_SCISSOR)
1676
update_scissor ();
1677
1678
RDP (" + update end\n");
1679
}
1680
1681
void set_message_combiner ()
1682
{
1683
grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
1684
GR_COMBINE_FACTOR_ONE,
1685
GR_COMBINE_LOCAL_NONE,
1686
GR_COMBINE_OTHER_TEXTURE,
1687
FXFALSE);
1688
grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
1689
GR_COMBINE_FACTOR_ONE,
1690
GR_COMBINE_LOCAL_NONE,
1691
GR_COMBINE_OTHER_TEXTURE,
1692
FXFALSE);
1693
if (settings.buff_clear && (settings.show_fps & 0x08))
1694
grAlphaBlendFunction (GR_BLEND_SRC_ALPHA,
1695
GR_BLEND_ONE_MINUS_SRC_ALPHA,
1696
GR_BLEND_ZERO,
1697
GR_BLEND_ZERO);
1698
else
1699
grAlphaBlendFunction (GR_BLEND_ONE,
1700
GR_BLEND_ZERO,
1701
GR_BLEND_ZERO,
1702
GR_BLEND_ZERO);
1703
grAlphaTestFunction (GR_CMP_ALWAYS);
1704
if (grStippleModeExt)
1705
{
1706
grStippleModeExt(GR_STIPPLE_DISABLE);
1707
}
1708
grTexCombine (GR_TMU1,
1709
GR_COMBINE_FUNCTION_NONE,
1710
GR_COMBINE_FACTOR_NONE,
1711
GR_COMBINE_FUNCTION_NONE,
1712
GR_COMBINE_FACTOR_NONE,
1713
FXFALSE, FXFALSE);
1714
grTexCombine (GR_TMU0,
1715
GR_COMBINE_FUNCTION_LOCAL,
1716
GR_COMBINE_FACTOR_NONE,
1717
GR_COMBINE_FUNCTION_LOCAL,
1718
GR_COMBINE_FACTOR_NONE,
1719
FXFALSE, FXFALSE);
1720
grTexSource(GR_TMU0,
1721
grTexMinAddress(GR_TMU0) + offset_font,
1722
GR_MIPMAPLEVELMASK_BOTH,
1723
&fontTex);
1724
grFogMode (GR_FOG_DISABLE);
1725
}
1726
1727
/*
1728
1 bit: common
1729
2 bit: I textures, V-Rally 99
1730
3 bit: South Park, Polaris
1731
4 bit: Mace
1732
5 bit: CyberTiger
1733
6 bit: Yoshi Story
1734
*/
1735
void fix_tex_coord (VERTEX **v)
1736
{
1737
BOOL fix = FALSE;
1738
if (settings.fix_tex_coord & 449)
1739
{
1740
// if ( (rdp.tiles[rdp.last_tile_size].format == 2) ||
1741
// ( (rdp.tiles[rdp.last_tile_size].size != 2)) )
1742
if (rdp.tiles[rdp.last_tile_size].size != 2)
1743
{
1744
if (settings.fix_tex_coord & 128)
1745
{
1746
if (v[0]->sz != v[1]->sz || v[0]->sz != v[2]->sz)
1747
return;
1748
}
1749
1750
if (settings.fix_tex_coord & 256) //dr.mario
1751
{
1752
if ((rdp.tiles[rdp.last_tile_size].format == 2) && (rdp.tiles[rdp.last_tile_size].size == 0))
1753
return;
1754
}
1755
1756
// int lu = (rdp.tiles[rdp.last_tile_size].ul_s)<<1;
1757
int ru = (rdp.tiles[rdp.last_tile_size].lr_s+1)<<1;
1758
int rv = (rdp.tiles[rdp.last_tile_size].lr_t+1)<<1;
1759
int diff = (settings.fix_tex_coord & 64) ? 5 : 3;
1760
1761
for (int t = 0; t < 3; t++)
1762
{
1763
if (v[t]->uv_fixed == 0) //&& (((short)v[t]->ou > 0) || ((short)v[t]->ov > 0)))
1764
{
1765
if ( (abs((short)v[t]->ou - ru) < diff) || (abs((short)v[t]->ov - rv) < diff) )
1766
// if ( ((short)v[t]->ou == lu) || (abs((short)v[t]->ou - ru) < 3) )
1767
{
1768
fix = TRUE;
1769
break;
1770
}
1771
}
1772
else
1773
{
1774
fix = TRUE;
1775
break;
1776
}
1777
}
1778
if (fix)
1779
{
1780
for (int t = 0; t < 3; t++)
1781
{
1782
if (v[t]->uv_fixed == 0)
1783
{
1784
v[t]->uv_fixed = 1;
1785
FRDP("v[%d] uv_fixed (%f, %f)->(%f,%f)\n",t, v[t]->ou, v[t]->ov, v[t]->ou*0.5f, v[t]->ov*0.5f);
1786
v[t]->ou *= 0.5f;
1787
v[t]->ov *= 0.5f;
1788
}
1789
}
1790
return;
1791
}
1792
}
1793
}
1794
if (settings.fix_tex_coord & 2)
1795
{
1796
if (rdp.tiles[rdp.last_tile_size].format == 4)
1797
{
1798
for (int t = 0; t < 3; t++)
1799
{
1800
if (v[t]->uv_fixed == 0)
1801
{
1802
v[t]->uv_fixed = 1;
1803
v[t]->ou *= 0.5f;
1804
v[t]->ov *= 0.5f;
1805
}
1806
}
1807
return;
1808
}
1809
}
1810
if (settings.fix_tex_coord & 4)
1811
{
1812
TILE & last_tile = rdp.tiles[rdp.last_tile_size];
1813
if ((last_tile.format == 2) &&
1814
(last_tile.size == 0) &&
1815
(last_tile.line%2 == 0) &&
1816
(last_tile.lr_s >= last_tile.lr_t))
1817
{
1818
int ru = (rdp.tiles[rdp.last_tile_size].lr_s+1);
1819
int rv = (rdp.tiles[rdp.last_tile_size].lr_t+1);
1820
int t;
1821
for (t = 0; t < 3; t++)
1822
{
1823
if (v[t]->uv_fixed == 0)
1824
{
1825
if ( (abs((short)v[t]->ou - ru) < 3) || (abs((short)v[t]->ov - rv) < 3) )
1826
return;
1827
}
1828
}
1829
for (t = 0; t < 3; t++)
1830
{
1831
if (v[t]->uv_fixed == 0)
1832
{
1833
v[t]->uv_fixed = 1;
1834
v[t]->ou *= 0.5f;
1835
v[t]->ov *= 0.5f;
1836
}
1837
}
1838
return;
1839
}
1840
}
1841
if (settings.fix_tex_coord & 8)
1842
{
1843
if (rdp.tiles[rdp.last_tile_size].format == 3 && rdp.tiles[rdp.last_tile_size].size == 1)
1844
{
1845
short width = (rdp.tiles[rdp.last_tile_size].ul_s<<1)+1 ;
1846
for (int t = 0; t < 3; t++)
1847
{
1848
if (v[t]->uv_fixed == 0)
1849
{
1850
if (short(v[t]->ou) == width)
1851
{
1852
fix = TRUE;
1853
break;
1854
}
1855
}
1856
else
1857
{
1858
fix = TRUE;
1859
break;
1860
}
1861
}
1862
if (fix)
1863
{
1864
RDP("texcoord fixed!\n");
1865
for (int t = 0; t < 3; t++)
1866
{
1867
if (v[t]->uv_fixed == 0)
1868
{
1869
v[t]->uv_fixed = 1;
1870
v[t]->ou *= 0.5f;
1871
v[t]->ov *= 0.5f;
1872
}
1873
}
1874
return;
1875
}
1876
}
1877
}
1878
if (settings.fix_tex_coord & 16)
1879
{
1880
if ((rdp.tiles[rdp.last_tile_size].format == 2) && (rdp.tiles[rdp.last_tile_size].size == 0))
1881
{
1882
short width = rdp.tiles[rdp.last_tile_size].lr_s + 1;
1883
short height = rdp.tiles[rdp.last_tile_size].lr_t + 1;
1884
for (int t = 0; t < 3; t++)
1885
{
1886
if (v[t]->uv_fixed == 0)
1887
{
1888
if ((short(v[t]->ou) > width) || (short(v[t]->ov) > height))
1889
{
1890
fix = TRUE;
1891
break;
1892
}
1893
}
1894
else
1895
{
1896
fix = TRUE;
1897
break;
1898
}
1899
}
1900
if (fix)
1901
{
1902
for (int t = 0; t < 3; t++)
1903
{
1904
if (v[t]->uv_fixed == 0)
1905
{
1906
v[t]->uv_fixed = 1;
1907
v[t]->ou *= 0.5f;
1908
v[t]->ov *= 0.5f;
1909
}
1910
}
1911
RDP("texcoord fixed!\n");
1912
return;
1913
}
1914
}
1915
}
1916
if (settings.fix_tex_coord & 32)
1917
{
1918
if (!rdp.vtx[rdp.v0].uv_fixed &&
1919
(rdp.tiles[rdp.last_tile_size].format == 2) &&
1920
(rdp.tiles[rdp.last_tile_size].size == 1) &&
1921
(rdp.tiles[rdp.last_tile_size].lr_s >= 31) &&
1922
(rdp.tiles[rdp.last_tile_size].lr_t >= 31))
1923
{
1924
int ru = (rdp.tiles[rdp.last_tile_size].lr_s+1)<<1;
1925
int rv = (rdp.tiles[rdp.last_tile_size].lr_t+1)<<1;
1926
int top = rdp.v0 + rdp.vn;
1927
for (int t = rdp.v0; t < top; t++)
1928
{
1929
if ( (abs((short)rdp.vtx[t].ou - ru) < 2) || (abs((short)rdp.vtx[t].ov - rv) < 2) )
1930
{
1931
fix = TRUE;
1932
break;
1933
}
1934
}
1935
if (fix)
1936
{
1937
for (int t = rdp.v0; t < top; t++)
1938
{
1939
rdp.vtx[t].uv_fixed = 1;
1940
rdp.vtx[t].ou *= 0.5f;
1941
rdp.vtx[t].ov *= 0.5f;
1942
}
1943
RDP("texcoord fixed!\n");
1944
return;
1945
}
1946
}
1947
}
1948
}
1949
1950
1951