Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/TexBuffer.cpp
2 views
1
/*
2
* Glide64 - Glide video plugin for Nintendo 64 emulators.
3
* Copyright (c) 2002 Dave2001
4
* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
*/
20
21
//****************************************************************
22
//
23
// Glide64 - Glide Plugin for Nintendo 64 emulators
24
// Project started on December 29th, 2001
25
//
26
// Authors:
27
// Dave2001, original author, founded the project in 2001, left it in 2002
28
// Gugaman, joined the project in 2002, left it in 2002
29
// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
30
// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
31
//
32
//****************************************************************
33
//
34
// To modify Glide64:
35
// * 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.
36
// * 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.
37
//
38
//****************************************************************
39
//
40
// Hardware frame buffer emulation
41
// Dec 2003 created by Gonetz
42
//
43
//****************************************************************
44
45
#include "Gfx_1.3.h"
46
#include "TexBuffer.h"
47
#include "CRC.h"
48
49
static TBUFF_COLOR_IMAGE * AllocateTextureBuffer(COLOR_IMAGE & cimage)
50
{
51
TBUFF_COLOR_IMAGE texbuf;
52
texbuf.addr = cimage.addr;
53
texbuf.end_addr = cimage.addr + ((cimage.width*cimage.height)<<cimage.size>>1);
54
texbuf.width = cimage.width;
55
texbuf.height = cimage.height;
56
texbuf.format = cimage.format;
57
texbuf.size = cimage.size;
58
texbuf.scr_width = min(cimage.width * rdp.scale_x, settings.scr_res_x);
59
float height = min(rdp.vi_height,cimage.height);
60
if (cimage.status == ci_copy_self || (cimage.status == ci_copy && cimage.width == rdp.frame_buffers[rdp.main_ci_index].width))
61
height = rdp.vi_height;
62
texbuf.scr_height = height * rdp.scale_y;
63
// texbuf.scr_height = texbuf.height * rdp.scale_y;
64
65
wxUint16 max_size = max((wxUint16)texbuf.scr_width, (wxUint16)texbuf.scr_height);
66
if (max_size > voodoo.max_tex_size) //texture size is too large
67
return 0;
68
wxUint32 tex_size;
69
//calculate LOD
70
switch ((max_size-1) >> 6)
71
{
72
case 0:
73
texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_64;
74
tex_size = 64;
75
break;
76
case 1:
77
texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_128;
78
tex_size = 128;
79
break;
80
case 2:
81
case 3:
82
texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_256;
83
tex_size = 256;
84
break;
85
case 4:
86
case 5:
87
case 6:
88
case 7:
89
texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_512;
90
tex_size = 512;
91
break;
92
case 8:
93
case 9:
94
case 10:
95
case 11:
96
case 12:
97
case 13:
98
case 14:
99
case 15:
100
texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_1024;
101
tex_size = 1024;
102
break;
103
default:
104
texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_2048;
105
tex_size = 2048;
106
}
107
//calculate aspect
108
if (texbuf.scr_width >= texbuf.scr_height)
109
{
110
if ((texbuf.scr_width/texbuf.scr_height) >= 2)
111
{
112
texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_2x1;
113
texbuf.tex_width = tex_size;
114
texbuf.tex_height = tex_size >> 1;
115
}
116
else
117
{
118
texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
119
texbuf.tex_width = texbuf.tex_height = tex_size;
120
}
121
}
122
else
123
{
124
if ((texbuf.scr_height/texbuf.scr_width) >= 2)
125
{
126
texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x2;
127
texbuf.tex_width = tex_size >> 1;
128
texbuf.tex_height = tex_size;
129
}
130
else
131
{
132
texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
133
texbuf.tex_width = texbuf.tex_height = tex_size;
134
}
135
}
136
if ((cimage.format != 0))// && (cimage.width <= 64))
137
texbuf.info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
138
else
139
texbuf.info.format = GR_TEXFMT_RGB_565;
140
141
texbuf.lr_u = 256.0f * texbuf.scr_width / (float)tex_size;// + 1.0f;
142
texbuf.lr_v = 256.0f * texbuf.scr_height / (float)tex_size;// + 1.0f;
143
texbuf.tile = 0;
144
texbuf.tile_uls = 0;
145
texbuf.tile_ult = 0;
146
texbuf.u_shift = 0;
147
texbuf.v_shift = 0;
148
texbuf.drawn = FALSE;
149
texbuf.u_scale = texbuf.lr_u / (float)(texbuf.width);
150
texbuf.v_scale = texbuf.lr_v / (float)(texbuf.height);
151
texbuf.cache = 0;
152
texbuf.crc = 0;
153
texbuf.t_mem = 0;
154
155
FRDP("\nAllocateTextureBuffer. width: %d, height: %d, scr_width: %f, scr_height: %f, vi_width: %f, vi_height:%f, scale_x: %f, scale_y: %f, lr_u: %f, lr_v: %f, u_scale: %f, v_scale: %f\n", texbuf.width, texbuf.height, texbuf.scr_width, texbuf.scr_height, rdp.vi_width, rdp.vi_height, rdp.scale_x, rdp.scale_y, texbuf.lr_u, texbuf.lr_v, texbuf.u_scale, texbuf.v_scale);
156
157
wxUint32 required = grTexCalcMemRequired(texbuf.info.smallLodLog2, texbuf.info.largeLodLog2,
158
texbuf.info.aspectRatioLog2, texbuf.info.format);
159
//find free space
160
for (int i = 0; i < voodoo.num_tmu; i++)
161
{
162
wxUint32 available = 0;
163
wxUint32 top = 0;
164
if (rdp.texbufs[i].count)
165
{
166
TBUFF_COLOR_IMAGE & t = rdp.texbufs[i].images[rdp.texbufs[i].count - 1];
167
if (rdp.read_whole_frame || rdp.motionblur)
168
{
169
if ((cimage.status == ci_aux) && (rdp.cur_tex_buf == i))
170
{
171
top = t.tex_addr + t.tex_width * (int)(t.scr_height+1) * 2;
172
if (rdp.texbufs[i].end - top < required)
173
return 0;
174
}
175
else
176
top = rdp.texbufs[i].end;
177
}
178
else
179
top = t.tex_addr + t.tex_width * t.tex_height * 2;
180
available = rdp.texbufs[i].end - top;
181
}
182
else
183
{
184
available = rdp.texbufs[i].end - rdp.texbufs[i].begin;
185
top = rdp.texbufs[i].begin;
186
}
187
if (available >= required)
188
{
189
rdp.texbufs[i].count++;
190
rdp.texbufs[i].clear_allowed = FALSE;
191
texbuf.tex_addr = top;
192
rdp.cur_tex_buf = i;
193
texbuf.tmu = rdp.texbufs[i].tmu;
194
rdp.texbufs[i].images[rdp.texbufs[i].count - 1] = texbuf;
195
return &(rdp.texbufs[i].images[rdp.texbufs[i].count - 1]);
196
}
197
}
198
//not found. keep recently accessed bank, clear second one
199
if (!rdp.texbufs[rdp.cur_tex_buf^1].clear_allowed) //can't clear => can't allocate
200
return 0;
201
rdp.cur_tex_buf ^= 1;
202
rdp.texbufs[rdp.cur_tex_buf].count = 1;
203
rdp.texbufs[rdp.cur_tex_buf].clear_allowed = FALSE;
204
texbuf.tmu = rdp.texbufs[rdp.cur_tex_buf].tmu;
205
texbuf.tex_addr = rdp.texbufs[rdp.cur_tex_buf].begin;
206
rdp.texbufs[rdp.cur_tex_buf].images[0] = texbuf;
207
return &(rdp.texbufs[rdp.cur_tex_buf].images[0]);
208
}
209
210
int OpenTextureBuffer(COLOR_IMAGE & cimage)
211
{
212
FRDP("OpenTextureBuffer. cur_tex_buf: %d, addr: %08lx, width: %d, height: %d", rdp.cur_tex_buf, cimage.addr, cimage.width, cimage.height);
213
if (!fullscreen) return FALSE;
214
215
int found = FALSE, search = TRUE;
216
TBUFF_COLOR_IMAGE *texbuf = 0;
217
wxUint32 addr = cimage.addr;
218
if ((settings.hacks&hack_Banjo2) && cimage.status == ci_copy_self)
219
addr = rdp.frame_buffers[rdp.copy_ci_index].addr;
220
wxUint32 end_addr = addr + ((cimage.width*cimage.height)<<cimage.size>>1);
221
if (rdp.motionblur)
222
{
223
// if (cimage.format != 0)
224
// return FALSE;
225
search = FALSE;
226
}
227
if (rdp.read_whole_frame)
228
{
229
if (settings.hacks&hack_PMario) //motion blur effects in Paper Mario
230
{
231
rdp.cur_tex_buf = rdp.acc_tex_buf;
232
FRDP("\nread_whole_frame. last allocated bank: %d\n", rdp.acc_tex_buf);
233
}
234
else
235
{
236
if (!rdp.texbufs[0].clear_allowed || !rdp.texbufs[1].clear_allowed)
237
{
238
if (cimage.status == ci_main)
239
{
240
texbuf = &(rdp.texbufs[rdp.cur_tex_buf].images[0]);
241
found = TRUE;
242
}
243
else
244
{
245
for (int t = 0; (t < rdp.texbufs[rdp.cur_tex_buf].count) && !found; t++)
246
{
247
texbuf = &(rdp.texbufs[rdp.cur_tex_buf].images[t]);
248
if (addr == texbuf->addr && cimage.width == texbuf->width)
249
{
250
texbuf->drawn = FALSE;
251
found = TRUE;
252
}
253
}
254
}
255
}
256
search = FALSE;
257
}
258
}
259
if (search)
260
{
261
for (int i = 0; (i < voodoo.num_tmu) && !found; i++)
262
{
263
for (int j = 0; (j < rdp.texbufs[i].count) && !found; j++)
264
{
265
texbuf = &(rdp.texbufs[i].images[j]);
266
if (addr == texbuf->addr && cimage.width == texbuf->width)
267
{
268
//texbuf->height = cimage.height;
269
//texbuf->end_addr = end_addr;
270
texbuf->drawn = FALSE;
271
texbuf->format = (wxUint16)cimage.format;
272
if ((cimage.format != 0))
273
texbuf->info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
274
else
275
texbuf->info.format = GR_TEXFMT_RGB_565;
276
texbuf->crc = 0;
277
texbuf->t_mem = 0;
278
texbuf->tile = 0;
279
found = TRUE;
280
rdp.cur_tex_buf = i;
281
rdp.texbufs[i].clear_allowed = FALSE;
282
}
283
else //check intersection
284
{
285
if (!((end_addr <= texbuf->addr) || (addr >= texbuf->end_addr))) //intersected, remove
286
{
287
grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
288
grTextureBufferExt( texbuf->tmu, texbuf->tex_addr, texbuf->info.smallLodLog2, texbuf->info.largeLodLog2,
289
texbuf->info.aspectRatioLog2, texbuf->info.format, GR_MIPMAPLEVELMASK_BOTH );
290
grDepthMask (FXFALSE);
291
grBufferClear (0, 0, 0xFFFF);
292
grDepthMask (FXTRUE);
293
grRenderBuffer( GR_BUFFER_BACKBUFFER );
294
rdp.texbufs[i].count--;
295
if (j < rdp.texbufs[i].count)
296
memcpy(&(rdp.texbufs[i].images[j]), &(rdp.texbufs[i].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[i].count-j));
297
}
298
}
299
}
300
}
301
}
302
else
303
{
304
LRDP(" not searched");
305
}
306
307
if (!found)
308
{
309
LRDP(" not found");
310
texbuf = AllocateTextureBuffer(cimage);
311
}
312
else
313
{
314
LRDP(" found");
315
}
316
317
if (!texbuf)
318
{
319
LRDP(" KO\n");
320
return FALSE;
321
}
322
323
rdp.acc_tex_buf = rdp.cur_tex_buf;
324
rdp.cur_image = texbuf;
325
grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
326
grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2,
327
rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH );
328
///*
329
if (rdp.cur_image->clear && (settings.frame_buffer&fb_hwfbe_buf_clear) && cimage.changed)
330
{
331
rdp.cur_image->clear = FALSE;
332
grDepthMask (FXFALSE);
333
grBufferClear (0, 0, 0xFFFF);
334
grDepthMask (FXTRUE);
335
}
336
//*/
337
// memset(gfx.RDRAM+cimage.addr, 0, cimage.width*cimage.height*cimage.size);
338
FRDP(" texaddr: %08lx, tex_width: %d, tex_height: %d, cur_tex_buf: %d, texformat: %d, motionblur: %d\n", rdp.cur_image->tex_addr, rdp.cur_image->tex_width, rdp.cur_image->tex_height, rdp.cur_tex_buf, rdp.cur_image->info.format, rdp.motionblur);
339
if (!rdp.offset_x_bak)
340
{
341
rdp.offset_x_bak = rdp.offset_x;
342
rdp.offset_x = 0;
343
}
344
if (!rdp.offset_y_bak)
345
{
346
rdp.offset_y_bak = rdp.offset_y;
347
rdp.offset_y = 0;
348
}
349
rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
350
return TRUE;
351
}
352
353
static GrTextureFormat_t TexBufSetupCombiner(int force_rgb = FALSE)
354
{
355
grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
356
GR_COMBINE_FACTOR_ONE,
357
GR_COMBINE_LOCAL_NONE,
358
GR_COMBINE_OTHER_TEXTURE,
359
// GR_COMBINE_OTHER_CONSTANT,
360
FXFALSE);
361
grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
362
GR_COMBINE_FACTOR_ONE,
363
GR_COMBINE_LOCAL_NONE,
364
GR_COMBINE_OTHER_TEXTURE,
365
FXFALSE);
366
// grConstantColorValue (0xFFFFFFFF);
367
grAlphaBlendFunction (GR_BLEND_ONE, // use alpha compare, but not T0 alpha
368
GR_BLEND_ZERO,
369
GR_BLEND_ONE,
370
GR_BLEND_ZERO);
371
grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);
372
grDepthBufferFunction (GR_CMP_ALWAYS);
373
grDepthMask (FXFALSE);
374
grCullMode (GR_CULL_DISABLE);
375
grFogMode (GR_FOG_DISABLE);
376
GrTextureFormat_t buf_format = (rdp.tbuff_tex) ? rdp.tbuff_tex->info.format : GR_TEXFMT_RGB_565;
377
GrCombineFunction_t color_source = GR_COMBINE_FUNCTION_LOCAL;
378
if (!force_rgb && rdp.black_ci_index > 0 && rdp.black_ci_index <= rdp.copy_ci_index)
379
{
380
color_source = GR_COMBINE_FUNCTION_LOCAL_ALPHA;
381
buf_format = GR_TEXFMT_ALPHA_INTENSITY_88;
382
}
383
if (rdp.tbuff_tex->tmu == GR_TMU0)
384
{
385
grTexCombine( GR_TMU1,
386
GR_COMBINE_FUNCTION_NONE,
387
GR_COMBINE_FACTOR_NONE,
388
GR_COMBINE_FUNCTION_NONE,
389
GR_COMBINE_FACTOR_NONE,
390
FXFALSE,
391
FXFALSE );
392
grTexCombine( GR_TMU0,
393
color_source,
394
GR_COMBINE_FACTOR_NONE,
395
GR_COMBINE_FUNCTION_ZERO,
396
GR_COMBINE_FACTOR_NONE,
397
FXFALSE,
398
FXTRUE );
399
}
400
else
401
{
402
grTexCombine( GR_TMU1,
403
color_source,
404
GR_COMBINE_FACTOR_NONE,
405
GR_COMBINE_FUNCTION_ZERO,
406
GR_COMBINE_FACTOR_NONE,
407
FXFALSE,
408
FXTRUE );
409
grTexCombine( GR_TMU0,
410
GR_COMBINE_FUNCTION_SCALE_OTHER,
411
GR_COMBINE_FACTOR_ONE,
412
GR_COMBINE_FUNCTION_SCALE_OTHER,
413
GR_COMBINE_FACTOR_ONE,
414
FXFALSE,
415
FXFALSE );
416
}
417
return buf_format;
418
}
419
420
int CloseTextureBuffer(int draw)
421
{
422
if (!fullscreen || !rdp.cur_image)
423
{
424
LRDP("CloseTextureBuffer KO\n");
425
return FALSE;
426
}
427
grRenderBuffer( GR_BUFFER_BACKBUFFER );
428
rdp.offset_x = rdp.offset_x_bak;
429
rdp.offset_y = rdp.offset_y_bak;
430
rdp.offset_x_bak = rdp.offset_y_bak = 0;
431
rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
432
if (!draw)
433
{
434
LRDP("CloseTextureBuffer no draw, OK\n");
435
rdp.cur_image = 0;
436
return TRUE;
437
}
438
rdp.tbuff_tex = rdp.cur_image;
439
rdp.cur_image = 0;
440
rdp.tbuff_tex->info.format = TexBufSetupCombiner();
441
float zero = 0.0f;
442
float ul_x = rdp.offset_x;
443
float ul_y = rdp.offset_y;
444
float lr_x = rdp.tbuff_tex->scr_width + rdp.offset_x;
445
float lr_y = rdp.tbuff_tex->scr_height + rdp.offset_y;
446
float lr_u = rdp.tbuff_tex->lr_u;
447
float lr_v = rdp.tbuff_tex->lr_v;
448
FRDP("lr_x: %f, lr_y: %f, lr_u: %f, lr_v: %f\n", lr_x, lr_y, lr_u, lr_v);
449
450
451
// Make the vertices
452
VERTEX v[4] = {
453
{ ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
454
{ lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
455
{ ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
456
{ lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
457
};
458
459
grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
460
grClipWindow (0, 0, settings.res_x, settings.res_y);
461
grDrawTriangle (&v[0], &v[2], &v[1]);
462
grDrawTriangle (&v[2], &v[3], &v[1]);
463
rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
464
if (settings.fog && (rdp.flags & FOG_ENABLED))
465
{
466
grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
467
}
468
LRDP("CloseTextureBuffer draw, OK\n");
469
rdp.tbuff_tex = 0;
470
return TRUE;
471
}
472
473
int CopyTextureBuffer(COLOR_IMAGE & fb_from, COLOR_IMAGE & fb_to)
474
{
475
if (!fullscreen)
476
return FALSE;
477
FRDP("CopyTextureBuffer from %08x to %08x\n", fb_from.addr, fb_to.addr);
478
if (rdp.cur_image)
479
{
480
rdp.cur_image->crc = 0;
481
if (rdp.cur_image->addr == fb_to.addr)
482
return CloseTextureBuffer(TRUE);
483
rdp.tbuff_tex = rdp.cur_image;
484
}
485
else if (!FindTextureBuffer(fb_from.addr, (wxUint16)fb_from.width))
486
{
487
LRDP("Can't find 'from' buffer.\n");
488
return FALSE;
489
}
490
if (!OpenTextureBuffer(fb_to))
491
{
492
LRDP("Can't open new buffer.\n");
493
return CloseTextureBuffer(TRUE);
494
}
495
rdp.tbuff_tex->crc = 0;
496
GrTextureFormat_t buf_format = rdp.tbuff_tex->info.format;
497
rdp.tbuff_tex->info.format = GR_TEXFMT_RGB_565;
498
TexBufSetupCombiner(TRUE);
499
float ul_x = 0.0f;
500
float ul_y = 0.0f;
501
float lr_x = rdp.tbuff_tex->scr_width;
502
float lr_y = rdp.tbuff_tex->scr_height;
503
float zero = 0.0f;
504
float lr_u = rdp.tbuff_tex->lr_u;
505
float lr_v = rdp.tbuff_tex->lr_v;
506
FRDP("lr_x: %f, lr_y: %f\n", lr_x, lr_y);
507
508
509
// Make the vertices
510
VERTEX v[4] = {
511
{ ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
512
{ lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
513
{ ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
514
{ lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
515
};
516
517
grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
518
grDrawTriangle (&v[0], &v[2], &v[1]);
519
grDrawTriangle (&v[2], &v[3], &v[1]);
520
grRenderBuffer( GR_BUFFER_BACKBUFFER );
521
rdp.offset_x = rdp.offset_x_bak;
522
rdp.offset_y = rdp.offset_y_bak;
523
rdp.offset_x_bak = rdp.offset_y_bak = 0;
524
AddOffset(v, 4);
525
grClipWindow (0, 0, settings.res_x, settings.res_y);
526
grDrawTriangle (&v[0], &v[2], &v[1]);
527
grDrawTriangle (&v[2], &v[3], &v[1]);
528
rdp.tbuff_tex->info.format = buf_format;
529
530
rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
531
rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
532
if (settings.fog && (rdp.flags & FOG_ENABLED))
533
grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
534
LRDP("CopyTextureBuffer draw, OK\n");
535
rdp.tbuff_tex = 0;
536
rdp.cur_image = 0;
537
return TRUE;
538
}
539
540
int CopyDepthBuffer()
541
{
542
if (!fullscreen)
543
return FALSE;
544
LRDP("CopyDepthBuffer. ");
545
float bound = 1024.0f;
546
GrLOD_t LOD = GR_LOD_LOG2_1024;
547
if (settings.scr_res_x > 1024)
548
{
549
bound = 2048.0f;
550
LOD = GR_LOD_LOG2_2048;
551
}
552
rdp.tbuff_tex = &(rdp.texbufs[0].images[0]);
553
rdp.tbuff_tex->tmu = rdp.texbufs[0].tmu;
554
rdp.tbuff_tex->info.format = GR_TEXFMT_RGB_565;
555
rdp.tbuff_tex->info.smallLodLog2 = rdp.tbuff_tex->info.largeLodLog2 = LOD;
556
rdp.tbuff_tex->info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
557
TexBufSetupCombiner(TRUE);
558
float ul_x = 0.0f;
559
float ul_y = 0.0f;
560
float lr_x = bound;
561
float lr_y = bound;
562
float zero = 0.0f;
563
float lr_u = 255.5f;
564
float lr_v = 255.5f;
565
FRDP("lr_x: %f, lr_y: %f\n", lr_x, lr_y);
566
567
568
// Make the vertices
569
VERTEX v[4] = {
570
{ ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
571
{ lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
572
{ ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
573
{ lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
574
};
575
576
grAuxBufferExt( GR_BUFFER_AUXBUFFER );
577
grTexSource( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
578
grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
579
grTextureBufferExt( rdp.texbufs[1].tmu, rdp.texbufs[1].begin, LOD, LOD,
580
GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
581
grDrawTriangle (&v[0], &v[2], &v[1]);
582
grDrawTriangle (&v[2], &v[3], &v[1]);
583
grRenderBuffer( GR_BUFFER_BACKBUFFER );
584
grTextureAuxBufferExt( rdp.texbufs[1].tmu, rdp.texbufs[1].begin, LOD, LOD,
585
GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
586
grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT );
587
588
rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
589
if (settings.fog && (rdp.flags & FOG_ENABLED))
590
grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
591
LRDP("CopyDepthBuffer draw, OK\n");
592
rdp.tbuff_tex = 0;
593
return TRUE;
594
}
595
596
int SwapTextureBuffer()
597
{
598
if (!fullscreen || !rdp.tbuff_tex)
599
return FALSE;
600
LRDP("SwapTextureBuffer.");
601
COLOR_IMAGE ci;
602
ci.addr = rdp.tbuff_tex->addr;
603
ci.format = rdp.tbuff_tex->format;
604
ci.width = rdp.tbuff_tex->width;
605
ci.height = rdp.tbuff_tex->height;
606
ci.size = 2;
607
ci.status = ci_main;
608
ci.changed = FALSE;
609
TBUFF_COLOR_IMAGE * texbuf = AllocateTextureBuffer(ci);
610
if (!texbuf)
611
{
612
LRDP("Failed!\n");
613
return FALSE;
614
}
615
TexBufSetupCombiner();
616
617
float ul_x = 0.0f;
618
float ul_y = 0.0f;
619
float lr_x = rdp.tbuff_tex->scr_width;
620
float lr_y = rdp.tbuff_tex->scr_height;
621
float zero = 0.0f;
622
float lr_u = rdp.tbuff_tex->lr_u;
623
float lr_v = rdp.tbuff_tex->lr_v;
624
625
// Make the vertices
626
VERTEX v[4] = {
627
{ ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
628
{ lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
629
{ ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
630
{ lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
631
};
632
633
grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
634
texbuf->tile_uls = rdp.tbuff_tex->tile_uls;
635
texbuf->tile_ult = rdp.tbuff_tex->tile_ult;
636
texbuf->v_shift = rdp.tbuff_tex->v_shift;
637
grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
638
grTextureBufferExt( texbuf->tmu, texbuf->tex_addr, texbuf->info.smallLodLog2, texbuf->info.largeLodLog2,
639
texbuf->info.aspectRatioLog2, texbuf->info.format, GR_MIPMAPLEVELMASK_BOTH );
640
grDrawTriangle (&v[0], &v[2], &v[1]);
641
grDrawTriangle (&v[2], &v[3], &v[1]);
642
rdp.texbufs[rdp.tbuff_tex->tmu].clear_allowed = TRUE;
643
rdp.texbufs[rdp.tbuff_tex->tmu].count = 0;
644
texbuf->tile_uls = rdp.tbuff_tex->tile_uls;
645
texbuf->tile_ult = rdp.tbuff_tex->tile_ult;
646
texbuf->u_shift = rdp.tbuff_tex->u_shift;
647
texbuf->v_shift = rdp.tbuff_tex->v_shift;
648
rdp.tbuff_tex = texbuf;
649
if (rdp.cur_image)
650
{
651
grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2,
652
rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH );
653
}
654
else
655
{
656
grRenderBuffer( GR_BUFFER_BACKBUFFER );
657
rdp.offset_x = rdp.offset_x_bak;
658
rdp.offset_y = rdp.offset_y_bak;
659
rdp.offset_x_bak = rdp.offset_y_bak = 0;
660
rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
661
}
662
rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
663
if (settings.fog && (rdp.flags & FOG_ENABLED))
664
{
665
grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
666
}
667
LRDP("SwapTextureBuffer draw, OK\n");
668
return TRUE;
669
}
670
671
static wxUint32 CalcCRC(TBUFF_COLOR_IMAGE * pTCI)
672
{
673
wxUint32 result = 0;
674
if ((settings.frame_buffer&fb_ref) > 0)
675
pTCI->crc = 0; //Since fb content changes each frame, crc check is meaningless.
676
else if (settings.fb_crc_mode == SETTINGS::fbcrcFast)
677
result = *((wxUint32*)(gfx.RDRAM + pTCI->addr + (pTCI->end_addr-pTCI->addr)/2));
678
else if (settings.fb_crc_mode == SETTINGS::fbcrcSafe)
679
{
680
wxUint8 * pSrc = gfx.RDRAM + pTCI->addr;
681
const wxUint32 nSize = pTCI->end_addr-pTCI->addr;
682
result = CRC32(0xFFFFFFFF, pSrc, 32);
683
result = CRC32(result, pSrc + (nSize>>1), 32);
684
result = CRC32(result, pSrc + nSize - 32, 32);
685
}
686
return result;
687
}
688
689
int FindTextureBuffer(wxUint32 addr, wxUint16 width)
690
{
691
if (rdp.skip_drawing)
692
return FALSE;
693
FRDP("FindTextureBuffer. addr: %08lx, width: %d, scale_x: %f\n", addr, width, rdp.scale_x);
694
int found = FALSE;
695
wxUint32 shift = 0;
696
for (int i = 0; i < voodoo.num_tmu && !found; i++)
697
{
698
wxUint8 index = rdp.cur_tex_buf^i;
699
for (int j = 0; j < rdp.texbufs[index].count && !found; j++)
700
{
701
rdp.tbuff_tex = &(rdp.texbufs[index].images[j]);
702
if(addr >= rdp.tbuff_tex->addr && addr < rdp.tbuff_tex->end_addr)// && rdp.timg.format == 0)
703
{
704
bool bCorrect;
705
if (rdp.tbuff_tex->crc == 0)
706
{
707
rdp.tbuff_tex->crc = CalcCRC(rdp.tbuff_tex);
708
bCorrect = width == 1 || rdp.tbuff_tex->width == width || (rdp.tbuff_tex->width > 320 && rdp.tbuff_tex->width == width*2);
709
}
710
else
711
bCorrect = rdp.tbuff_tex->crc == CalcCRC(rdp.tbuff_tex);
712
if (bCorrect)
713
{
714
shift = addr - rdp.tbuff_tex->addr;
715
// if (!rdp.motionblur)
716
if (!rdp.cur_image)
717
rdp.cur_tex_buf = index;
718
found = TRUE;
719
// FRDP("FindTextureBuffer, found in TMU%d buffer: %d\n", rdp.tbuff_tex->tmu, j);
720
}
721
else //new texture is loaded into this place, texture buffer is not valid anymore
722
{
723
rdp.texbufs[index].count--;
724
if (j < rdp.texbufs[index].count)
725
memcpy(&(rdp.texbufs[index].images[j]), &(rdp.texbufs[index].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[index].count-j));
726
}
727
}
728
}
729
}
730
if (found)
731
{
732
rdp.tbuff_tex->tile_uls = 0;
733
rdp.tbuff_tex->tile_ult = 0;
734
if (shift > 0)
735
{
736
shift >>= 1;
737
rdp.tbuff_tex->v_shift = shift / rdp.tbuff_tex->width;
738
rdp.tbuff_tex->u_shift = shift % rdp.tbuff_tex->width;
739
}
740
else
741
{
742
rdp.tbuff_tex->v_shift = 0;
743
rdp.tbuff_tex->u_shift = 0;
744
}
745
FRDP("FindTextureBuffer, found, u_shift: %d, v_shift: %d, format: %s\n", rdp.tbuff_tex->u_shift, rdp.tbuff_tex->v_shift, str_format[rdp.tbuff_tex->format]);
746
//FRDP("Buffer, addr=%08lx, end_addr=%08lx, width: %d, height: %d\n", rdp.tbuff_tex->addr, rdp.tbuff_tex->end_addr, rdp.tbuff_tex->width, rdp.tbuff_tex->height);
747
return TRUE;
748
}
749
rdp.tbuff_tex = 0;
750
LRDP("FindTextureBuffer, not found\n");
751
return FALSE;
752
}
753
754