Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/TexCache.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
#include <SDL.h>
41
#include "Gfx_1.3.h"
42
#include "TexCache.h"
43
#include "Combine.h"
44
#include "Util.h"
45
46
void LoadTex (int id, int tmu);
47
48
wxUint8 tex1[1024*1024*4]; // temporary texture
49
wxUint8 tex2[1024*1024*4];
50
wxUint8 *texture;
51
wxUint8 *texture_buffer = tex1;
52
53
#include "TexLoad.h" // texture loading functions, ONLY INCLUDE IN THIS FILE!!!
54
#include "MiClWr32b.h"
55
#include "MiClWr16b.h" // Mirror/Clamp/Wrap functions, ONLY INCLUDE IN THIS FILE!!!
56
#include "MiClWr8b.h" // Mirror/Clamp/Wrap functions, ONLY INCLUDE IN THIS FILE!!!
57
#include "TexConv.h" // texture conversions, ONLY INCLUDE IN THIS FILE!!!
58
#include "TexMod.h"
59
#include "TexModCI.h"
60
#include "CRC.h"
61
#ifdef TEXTURE_FILTER // Hiroshi Morii <[email protected]>
62
extern int ghq_dmptex_toggle_key;
63
#endif
64
65
typedef struct TEXINFO_t {
66
int real_image_width, real_image_height; // FOR ALIGNMENT PURPOSES ONLY!!!
67
int tile_width, tile_height;
68
int mask_width, mask_height;
69
int width, height;
70
int wid_64, line;
71
wxUint32 crc;
72
wxUint32 flags;
73
int splits, splitheight;
74
#ifdef TEXTURE_FILTER
75
uint64 ricecrc;
76
#endif
77
} TEXINFO;
78
79
TEXINFO texinfo[2];
80
int tex_found[2][MAX_TMU];
81
82
#ifdef TEXTURE_FILTER
83
typedef struct HIRESTEX_t {
84
int width, height;
85
wxUint16 format;
86
wxUint8 *data;
87
} HIRESTEX;
88
#endif
89
90
//****************************************************************
91
// List functions
92
93
typedef struct NODE_t {
94
wxUint32 crc;
95
wxUIntPtr data;
96
int tmu;
97
int number;
98
NODE_t *pNext;
99
} NODE;
100
101
NODE *cachelut[65536];
102
103
void AddToList (NODE **list, wxUint32 crc, wxUIntPtr data, int tmu, int number)
104
{
105
NODE *node = new NODE;
106
node->crc = crc;
107
node->data = data;
108
node->tmu = tmu;
109
node->number = number;
110
node->pNext = *list;
111
*list = node;
112
rdp.n_cached[tmu] ++;
113
if (voodoo.tex_UMA)
114
rdp.n_cached[tmu^1] = rdp.n_cached[tmu];
115
}
116
117
void DeleteList (NODE **list)
118
{
119
while (*list)
120
{
121
NODE *next = (*list)->pNext;
122
delete (*list);
123
*list = next;
124
}
125
}
126
127
void TexCacheInit ()
128
{
129
for (int i=0; i<65536; i++)
130
{
131
cachelut[i] = NULL;
132
}
133
}
134
135
//****************************************************************
136
// ClearCache - clear the texture cache for BOTH tmus
137
138
void ClearCache ()
139
{
140
voodoo.tmem_ptr[0] = offset_textures;
141
rdp.n_cached[0] = 0;
142
voodoo.tmem_ptr[1] = voodoo.tex_UMA ? offset_textures : offset_texbuf1;
143
rdp.n_cached[1] = 0;
144
145
for (int i=0; i<65536; i++)
146
{
147
DeleteList (&cachelut[i]);
148
}
149
}
150
151
//****************************************************************
152
uint32_t textureCRC(uint8_t *addr, int width, int height, int line)
153
{
154
uint32_t crc = 0;
155
uint32_t *pixelpos;
156
unsigned int i;
157
uint64_t twopixel_crc;
158
159
pixelpos = (uint32_t*)addr;
160
for (; height; height--) {
161
for (i = width; i; --i) {
162
twopixel_crc = i * (uint64_t)(pixelpos[1] + pixelpos[0] + crc);
163
crc = (uint32_t) ((twopixel_crc >> 32) + twopixel_crc);
164
pixelpos += 2;
165
}
166
crc = ((unsigned int)height * (uint64_t)crc >> 32) + height * crc;
167
pixelpos = (uint32_t *)((char *)pixelpos + line);
168
}
169
170
return crc;
171
}
172
// GetTexInfo - gets information for either t0 or t1, checks if in cache & fills tex_found
173
174
void GetTexInfo (int id, int tile)
175
{
176
FRDP (" | |-+ GetTexInfo (id: %d, tile: %d)\n", id, tile);
177
178
// this is the NEW cache searching, searches only textures with similar crc's
179
int t;
180
for (t=0; t<MAX_TMU; t++)
181
tex_found[id][t] = -1;
182
183
TBUFF_COLOR_IMAGE * pFBTex = 0;
184
if (rdp.aTBuffTex[0] && rdp.aTBuffTex[0]->tile == id)
185
pFBTex = rdp.aTBuffTex[0];
186
else if (rdp.aTBuffTex[1] && rdp.aTBuffTex[1]->tile == id)
187
pFBTex = rdp.aTBuffTex[1];
188
if (pFBTex && pFBTex->cache)
189
return;
190
191
TEXINFO *info = &texinfo[id];
192
193
int tile_width, tile_height;
194
int mask_width, mask_height;
195
int width, height;
196
int wid_64, line, bpl;
197
198
// Get width and height
199
tile_width = rdp.tiles[tile].lr_s - rdp.tiles[tile].ul_s + 1;
200
tile_height = rdp.tiles[tile].lr_t - rdp.tiles[tile].ul_t + 1;
201
202
mask_width = (rdp.tiles[tile].mask_s==0)?(tile_width):(1 << rdp.tiles[tile].mask_s);
203
mask_height = (rdp.tiles[tile].mask_t==0)?(tile_height):(1 << rdp.tiles[tile].mask_t);
204
205
if (settings.alt_tex_size)
206
{
207
// ** ALTERNATE TEXTURE SIZE METHOD **
208
// Helps speed in some games that loaded weird-sized textures, but could break other
209
// textures.
210
211
// Get the width/height to load
212
if ((rdp.tiles[tile].clamp_s && tile_width <= 256) || (mask_width > 256))
213
{
214
// loading width
215
width = min(mask_width, tile_width);
216
// actual width
217
rdp.tiles[tile].width = tile_width;
218
}
219
else
220
{
221
// wrap all the way
222
width = min(mask_width, tile_width); // changed from mask_width only
223
rdp.tiles[tile].width = width;
224
}
225
226
if ((rdp.tiles[tile].clamp_t && tile_height <= 256) || (mask_height > 256))
227
{
228
// loading height
229
height = min(mask_height, tile_height);
230
// actual height
231
rdp.tiles[tile].height = tile_height;
232
}
233
else
234
{
235
// wrap all the way
236
height = min(mask_height, tile_height);
237
rdp.tiles[tile].height = height;
238
}
239
}
240
else
241
{
242
// ** NORMAL TEXTURE SIZE METHOD **
243
// This is the 'correct' method for determining texture size, but may cause certain
244
// textures to load too large & make the whole game go slow.
245
246
if (mask_width > 256 && mask_height > 256)
247
{
248
mask_width = tile_width;
249
mask_height = tile_height;
250
}
251
252
// Get the width/height to load
253
if ((rdp.tiles[tile].clamp_s && tile_width <= 256) )//|| (mask_width > 256))
254
{
255
// loading width
256
width = min(mask_width, tile_width);
257
// actual width
258
rdp.tiles[tile].width = tile_width;
259
}
260
else
261
{
262
// wrap all the way
263
width = mask_width;
264
rdp.tiles[tile].width = mask_width;
265
}
266
267
if ((rdp.tiles[tile].clamp_t && tile_height <= 256) || (mask_height > 256))
268
{
269
// loading height
270
height = min(mask_height, tile_height);
271
// actual height
272
rdp.tiles[tile].height = tile_height;
273
}
274
else
275
{
276
// wrap all the way
277
height = mask_height;
278
rdp.tiles[tile].height = mask_height;
279
}
280
}
281
282
// without any large texture fixing-up; for alignment
283
int real_image_width = rdp.tiles[tile].width;
284
int real_image_height = rdp.tiles[tile].height;
285
int crc_height = height;
286
if (rdp.timg.set_by == 1)
287
crc_height = tile_height;
288
289
bpl = width << rdp.tiles[tile].size >> 1;
290
291
// ** COMMENT THIS TO DISABLE LARGE TEXTURES
292
#ifdef LARGE_TEXTURE_HANDLING
293
if (!voodoo.sup_large_tex && width > 256)
294
{
295
info->splits = ((width-1)>>8)+1;
296
info->splitheight = rdp.tiles[tile].height;
297
rdp.tiles[tile].height *= info->splits;
298
rdp.tiles[tile].width = 256;
299
width = 256;
300
}
301
else
302
#endif
303
// **
304
{
305
info->splits = 1;
306
}
307
308
LRDP(" | | |-+ Texture approved:\n");
309
FRDP (" | | | |- tmem: %08lx\n", rdp.tiles[tile].t_mem);
310
FRDP (" | | | |- load width: %d\n", width);
311
FRDP (" | | | |- load height: %d\n", height);
312
FRDP (" | | | |- actual width: %d\n", rdp.tiles[tile].width);
313
FRDP (" | | | |- actual height: %d\n", rdp.tiles[tile].height);
314
FRDP (" | | | |- size: %d\n", rdp.tiles[tile].size);
315
FRDP (" | | | +- format: %d\n", rdp.tiles[tile].format);
316
LRDP(" | | |- Calculating CRC... ");
317
318
// ** CRC CHECK
319
320
wid_64 = width << (rdp.tiles[tile].size) >> 1;
321
if (rdp.tiles[tile].size == 3)
322
{
323
if (wid_64 & 15) wid_64 += 16;
324
wid_64 &= 0xFFFFFFF0;
325
}
326
else
327
{
328
if (wid_64 & 7) wid_64 += 8; // round up
329
}
330
wid_64 = wid_64>>3;
331
332
// Texture too big for tmem & needs to wrap? (trees in mm)
333
if (rdp.tiles[tile].t_mem + min(height, tile_height) * (rdp.tiles[tile].line<<3) > 4096)
334
{
335
LRDP("TEXTURE WRAPS TMEM!!! ");
336
337
// calculate the y value that intersects at 4096 bytes
338
int y = (4096 - rdp.tiles[tile].t_mem) / (rdp.tiles[tile].line<<3);
339
340
rdp.tiles[tile].clamp_t = 0;
341
rdp.tiles[tile].lr_t = rdp.tiles[tile].ul_t + y - 1;
342
343
// calc mask
344
int shift;
345
for (shift=0; (1<<shift)<y; shift++);
346
rdp.tiles[tile].mask_t = shift;
347
348
// restart the function
349
LRDP("restarting...\n");
350
GetTexInfo (id, tile);
351
return;
352
}
353
354
line = rdp.tiles[tile].line;
355
if (rdp.tiles[tile].size == 3)
356
line <<= 1;
357
wxUint32 crc = 0;
358
if (settings.fast_crc)
359
{
360
line = (line - wid_64) << 3;
361
if (wid_64 < 1) wid_64 = 1;
362
uint8_t * addr = (((uint8_t*)rdp.tmem) + (rdp.tiles[tile].t_mem<<3));
363
if (crc_height > 0) // Check the CRC
364
{
365
if (rdp.tiles[tile].size < 3)
366
crc = textureCRC(addr, wid_64, crc_height, line);
367
else //32b texture
368
{
369
int line_2 = line >> 1;
370
int wid_64_2 = max(1, wid_64 >> 1);
371
crc = textureCRC(addr, wid_64_2, crc_height, line_2);
372
crc += textureCRC(addr+0x800, wid_64_2, crc_height, line_2);
373
}
374
}
375
}
376
else
377
{
378
crc = 0xFFFFFFFF;
379
wxUIntPtr addr = wxPtrToUInt(rdp.tmem) + (rdp.tiles[tile].t_mem<<3);
380
wxUint32 line2 = max(line,1);
381
if (rdp.tiles[tile].size < 3)
382
{
383
line2 <<= 3;
384
for (int y = 0; y < crc_height; y++)
385
{
386
crc = CRC32( crc, reinterpret_cast<void*>(addr), bpl );
387
addr += line2;
388
}
389
}
390
else //32b texture
391
{
392
line2 <<= 2;
393
//32b texel is split in two 16b parts, so bpl/2 and line/2.
394
//Min value for bpl is 4, because when width==1 first 2 bytes of tmem will not be used.
395
bpl = max(bpl >> 1, 4);
396
for (int y = 0; y < crc_height; y++)
397
{
398
crc = CRC32( crc, reinterpret_cast<void*>(addr), bpl);
399
crc = CRC32( crc, reinterpret_cast<void*>(addr + 0x800), bpl);
400
addr += line2;
401
}
402
}
403
line = (line - wid_64) << 3;
404
if (wid_64 < 1) wid_64 = 1;
405
}
406
if ((rdp.tiles[tile].size < 2) && (rdp.tlut_mode || rdp.tiles[tile].format == 2))
407
{
408
if (rdp.tiles[tile].size == 0)
409
crc += rdp.pal_8_crc[rdp.tiles[tile].palette];
410
else
411
crc += rdp.pal_256_crc;
412
}
413
414
FRDP ("Done. CRC is: %08lx.\n", crc);
415
416
wxUint32 flags = (rdp.tiles[tile].clamp_s << 23) | (rdp.tiles[tile].mirror_s << 22) |
417
(rdp.tiles[tile].mask_s << 18) | (rdp.tiles[tile].clamp_t << 17) |
418
(rdp.tiles[tile].mirror_t << 16) | (rdp.tiles[tile].mask_t << 12);
419
420
info->real_image_width = real_image_width;
421
info->real_image_height = real_image_height;
422
info->tile_width = tile_width;
423
info->tile_height = tile_height;
424
info->mask_width = mask_width;
425
info->mask_height = mask_height;
426
info->width = width;
427
info->height = height;
428
info->wid_64 = wid_64;
429
info->line = line;
430
info->crc = crc;
431
info->flags = flags;
432
433
// Search the texture cache for this texture
434
LRDP(" | | |-+ Checking cache...\n");
435
436
CACHE_LUT *cache;
437
438
if (rdp.noise == RDP::noise_texture)
439
return;
440
441
wxUint32 mod, modcolor, modcolor1, modcolor2, modfactor;
442
if (id == 0)
443
{
444
mod = cmb.mod_0;
445
modcolor = cmb.modcolor_0;
446
modcolor1 = cmb.modcolor1_0;
447
modcolor2 = cmb.modcolor2_0;
448
modfactor = cmb.modfactor_0;
449
}
450
else
451
{
452
mod = cmb.mod_1;
453
modcolor = cmb.modcolor_1;
454
modcolor1 = cmb.modcolor1_1;
455
modcolor2 = cmb.modcolor2_1;
456
modfactor = cmb.modfactor_1;
457
}
458
459
NODE *node = cachelut[crc>>16];
460
wxUint32 mod_mask = (rdp.tiles[tile].format == 2)?0xFFFFFFFF:0xF0F0F0F0;
461
while (node)
462
{
463
if (node->crc == crc)
464
{
465
cache = (CACHE_LUT*)node->data;
466
if (/*tex_found[id][node->tmu] == -1 &&
467
rdp.tiles[tile].palette == cache->palette &&
468
rdp.tiles[tile].format == cache->format &&
469
rdp.tiles[tile].size == cache->size &&*/
470
rdp.tiles[tile].width == cache->width &&
471
rdp.tiles[tile].height == cache->height &&
472
flags == cache->flags)
473
{
474
if (!(mod+cache->mod) || (cache->mod == mod &&
475
(cache->mod_color&mod_mask) == (modcolor&mod_mask) &&
476
(cache->mod_color1&mod_mask) == (modcolor1&mod_mask) &&
477
(cache->mod_color2&mod_mask) == (modcolor2&mod_mask) &&
478
abs((int)(cache->mod_factor - modfactor)) < 8))
479
{
480
FRDP (" | | | |- Texture found in cache (tmu=%d).\n", node->tmu);
481
tex_found[id][node->tmu] = node->number;
482
if (voodoo.tex_UMA)
483
{
484
tex_found[id][node->tmu^1] = node->number;
485
return;
486
}
487
}
488
}
489
}
490
node = node->pNext;
491
}
492
493
LRDP(" | | | +- Done.\n | | +- GetTexInfo end\n");
494
}
495
496
//****************************************************************
497
// ChooseBestTmu - chooses the best TMU to load to (the one with the most memory)
498
499
int ChooseBestTmu (int tmu1, int tmu2)
500
{
501
if (!fullscreen) return tmu1;
502
if (voodoo.tex_UMA) return 0;
503
504
if (tmu1 >= voodoo.num_tmu) return tmu2;
505
if (tmu2 >= voodoo.num_tmu) return tmu1;
506
507
if (voodoo.tex_max_addr[tmu1]-voodoo.tmem_ptr[tmu1] >
508
voodoo.tex_max_addr[tmu2]-voodoo.tmem_ptr[tmu2])
509
return tmu1;
510
else
511
return tmu2;
512
}
513
514
//****************************************************************
515
// SelectTBuffTex - select texture from texture buffer
516
static void SelectTBuffTex(TBUFF_COLOR_IMAGE * pTBuffTex)
517
{
518
FRDP ("SelectTBuffTex: tex: %d, tmu: %d, tile: %d\n", rdp.tex, pTBuffTex->tmu, pTBuffTex->tile);
519
grTexSource(pTBuffTex->tile, pTBuffTex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(pTBuffTex->info) );
520
}
521
522
//****************************************************************
523
// TexCache - does texture loading after combiner is set
524
int SwapTextureBuffer();
525
void TexCache ()
526
{
527
LRDP(" |-+ TexCache called\n");
528
529
#ifdef TEXTURE_FILTER /* Hiroshi Morii <[email protected]> */ // POSTNAPALM
530
if (settings.ghq_use && settings.ghq_hirs_dump) {
531
/* Force reload hi-res textures. Useful for texture artists */
532
if (CheckKeyPressed(G64_VK_R, 0x0001)) {
533
if (ext_ghq_reloadhirestex()) ClearCache();
534
}
535
/* Turn on texture dump */
536
else if (CheckKeyPressed(G64_VK_D, 0x0001)) {
537
extern void DisplayLoadProgress(const wchar_t *format, ...);
538
ghq_dmptex_toggle_key = !ghq_dmptex_toggle_key;
539
if (ghq_dmptex_toggle_key) {
540
DisplayLoadProgress(L"Texture dump - ON\n");
541
ClearCache();
542
SDL_Delay(1000);
543
} else {
544
DisplayLoadProgress(L"Texture dump - OFF\n");
545
SDL_Delay(1000);
546
}
547
}
548
}
549
#endif
550
551
if (rdp.tex & 1)
552
GetTexInfo (0, rdp.cur_tile);
553
if (rdp.tex & 2)
554
GetTexInfo (1, rdp.cur_tile+1);
555
556
TBUFF_COLOR_IMAGE * aTBuff[2] = {0, 0};
557
if (rdp.aTBuffTex[0])
558
aTBuff[rdp.aTBuffTex[0]->tile] = rdp.aTBuffTex[0];
559
if (rdp.aTBuffTex[1])
560
aTBuff[rdp.aTBuffTex[1]->tile] = rdp.aTBuffTex[1];
561
562
#define TMUMODE_NORMAL 0
563
#define TMUMODE_PASSTHRU 1
564
#define TMUMODE_NONE 2
565
566
int tmu_0, tmu_1;
567
int tmu_0_mode=0, tmu_1_mode=0;
568
569
// Select the best TMUs to use (removed 3 tmu support, unnecessary)
570
if (rdp.tex == 3) // T0 and T1
571
{
572
tmu_0 = 0;
573
tmu_1 = 1;
574
}
575
else if (rdp.tex == 2) // T1
576
{
577
if (tex_found[1][0] != -1) // T1 found in tmu 0
578
tmu_1 = 0;
579
else if (tex_found[1][1] != -1) // T1 found in tmu 1
580
tmu_1 = 1;
581
else // T1 not found
582
tmu_1 = ChooseBestTmu (0, 1);
583
584
tmu_0 = !tmu_1;
585
tmu_0_mode = (tmu_0==1)?TMUMODE_NONE:TMUMODE_PASSTHRU;
586
}
587
else if (rdp.tex == 1) // T0
588
{
589
if (tex_found[0][0] != -1) // T0 found in tmu 0
590
tmu_0 = 0;
591
else if (tex_found[0][1] != -1) // T0 found in tmu 1
592
tmu_0 = 1;
593
else // T0 not found
594
tmu_0 = ChooseBestTmu (0, 1);
595
596
tmu_1 = !tmu_0;
597
tmu_1_mode = (tmu_1==1)?TMUMODE_NONE:TMUMODE_PASSTHRU;
598
}
599
else // no texture
600
{
601
tmu_0 = 0;
602
tmu_0_mode = TMUMODE_NONE;
603
tmu_1 = 0;
604
tmu_1_mode = TMUMODE_NONE;
605
}
606
607
FRDP (" | |-+ Modes set:\n | | |- tmu_0 = %d\n | | |- tmu_1 = %d\n",
608
tmu_0, tmu_1);
609
FRDP (" | | |- tmu_0_mode = %d\n | | |- tmu_1_mode = %d\n",
610
tmu_0_mode, tmu_1_mode);
611
612
if (tmu_0_mode == TMUMODE_PASSTHRU) {
613
cmb.tmu0_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER;
614
cmb.tmu0_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_ONE;
615
if (cmb.tex_cmb_ext_use)
616
{
617
cmb.t0c_ext_a = GR_CMBX_OTHER_TEXTURE_RGB;
618
cmb.t0c_ext_a_mode = GR_FUNC_MODE_X;
619
cmb.t0c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB;
620
cmb.t0c_ext_b_mode = GR_FUNC_MODE_ZERO;
621
cmb.t0c_ext_c = GR_CMBX_ZERO;
622
cmb.t0c_ext_c_invert = 1;
623
cmb.t0c_ext_d = GR_CMBX_ZERO;
624
cmb.t0c_ext_d_invert = 0;
625
cmb.t0a_ext_a = GR_CMBX_OTHER_TEXTURE_ALPHA;
626
cmb.t0a_ext_a_mode = GR_FUNC_MODE_X;
627
cmb.t0a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA;
628
cmb.t0a_ext_b_mode = GR_FUNC_MODE_ZERO;
629
cmb.t0a_ext_c = GR_CMBX_ZERO;
630
cmb.t0a_ext_c_invert = 1;
631
cmb.t0a_ext_d = GR_CMBX_ZERO;
632
cmb.t0a_ext_d_invert = 0;
633
}
634
}
635
else if (tmu_0_mode == TMUMODE_NONE) {
636
cmb.tmu0_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_NONE;
637
cmb.tmu0_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE;
638
if (cmb.tex_cmb_ext_use)
639
{
640
cmb.t0c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB;
641
cmb.t0c_ext_a_mode = GR_FUNC_MODE_ZERO;
642
cmb.t0c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB;
643
cmb.t0c_ext_b_mode = GR_FUNC_MODE_ZERO;
644
cmb.t0c_ext_c = GR_CMBX_ZERO;
645
cmb.t0c_ext_c_invert = 0;
646
cmb.t0c_ext_d = GR_CMBX_ZERO;
647
cmb.t0c_ext_d_invert = 0;
648
cmb.t0a_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA;
649
cmb.t0a_ext_a_mode = GR_FUNC_MODE_ZERO;
650
cmb.t0a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA;
651
cmb.t0a_ext_b_mode = GR_FUNC_MODE_ZERO;
652
cmb.t0a_ext_c = GR_CMBX_ZERO;
653
cmb.t0a_ext_c_invert = 0;
654
cmb.t0a_ext_d = GR_CMBX_ZERO;
655
cmb.t0a_ext_d_invert = 0;
656
}
657
}
658
if (tmu_1_mode == TMUMODE_PASSTHRU) {
659
cmb.tmu1_func = cmb.tmu1_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER;
660
cmb.tmu1_fac = cmb.tmu1_a_fac = GR_COMBINE_FACTOR_ONE;
661
if (cmb.tex_cmb_ext_use)
662
{
663
cmb.t1c_ext_a = GR_CMBX_OTHER_TEXTURE_RGB;
664
cmb.t1c_ext_a_mode = GR_FUNC_MODE_X;
665
cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB;
666
cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO;
667
cmb.t1c_ext_c = GR_CMBX_ZERO;
668
cmb.t1c_ext_c_invert = 1;
669
cmb.t1c_ext_d = GR_CMBX_ZERO;
670
cmb.t1c_ext_d_invert = 0;
671
cmb.t1a_ext_a = GR_CMBX_OTHER_TEXTURE_ALPHA;
672
cmb.t1a_ext_a_mode = GR_FUNC_MODE_X;
673
cmb.t1a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA;
674
cmb.t1a_ext_b_mode = GR_FUNC_MODE_ZERO;
675
cmb.t1a_ext_c = GR_CMBX_ZERO;
676
cmb.t1a_ext_c_invert = 1;
677
cmb.t1a_ext_d = GR_CMBX_ZERO;
678
cmb.t1a_ext_d_invert = 0;
679
}
680
}
681
else if (tmu_1_mode == TMUMODE_NONE) {
682
cmb.tmu1_func = cmb.tmu1_a_func = GR_COMBINE_FUNCTION_NONE;
683
cmb.tmu1_fac = cmb.tmu1_a_fac = GR_COMBINE_FACTOR_NONE;
684
if (cmb.tex_cmb_ext_use)
685
{
686
cmb.t1c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB;
687
cmb.t1c_ext_a_mode = GR_FUNC_MODE_ZERO;
688
cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB;
689
cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO;
690
cmb.t1c_ext_c = GR_CMBX_ZERO;
691
cmb.t1c_ext_c_invert = 0;
692
cmb.t1c_ext_d = GR_CMBX_ZERO;
693
cmb.t1c_ext_d_invert = 0;
694
cmb.t1a_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA;
695
cmb.t1a_ext_a_mode = GR_FUNC_MODE_ZERO;
696
cmb.t1a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA;
697
cmb.t1a_ext_b_mode = GR_FUNC_MODE_ZERO;
698
cmb.t1a_ext_c = GR_CMBX_ZERO;
699
cmb.t1a_ext_c_invert = 0;
700
cmb.t1a_ext_d = GR_CMBX_ZERO;
701
cmb.t1a_ext_d_invert = 0;
702
}
703
}
704
705
// little change to make single-tmu cards look better, use first texture no matter what
706
707
if (voodoo.num_tmu == 1)
708
{
709
if (rdp.best_tex == 0)
710
{
711
cmb.tmu0_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL;
712
cmb.tmu0_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE;
713
tmu_0 = 0;
714
tmu_1 = 1;
715
}
716
else
717
{
718
cmb.tmu1_func = cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL;
719
cmb.tmu1_fac = cmb.tmu1_a_fac = GR_COMBINE_FACTOR_NONE;
720
tmu_1 = 0;
721
tmu_0 = 1;
722
}
723
}
724
725
726
rdp.t0 = tmu_0;
727
rdp.t1 = tmu_1;
728
729
// SET the combiner
730
if (fullscreen)
731
{
732
if (rdp.allow_combine)
733
{
734
// Now actually combine
735
if (cmb.cmb_ext_use)
736
{
737
LRDP(" | | | |- combiner extension\n");
738
if (!(cmb.cmb_ext_use & COMBINE_EXT_COLOR))
739
ColorCombinerToExtension ();
740
if (!(cmb.cmb_ext_use & COMBINE_EXT_ALPHA))
741
AlphaCombinerToExtension ();
742
cmb.grColorCombineExt(cmb.c_ext_a, cmb.c_ext_a_mode,
743
cmb.c_ext_b, cmb.c_ext_b_mode,
744
cmb.c_ext_c, cmb.c_ext_c_invert,
745
cmb.c_ext_d, cmb.c_ext_d_invert, 0, 0);
746
cmb.grAlphaCombineExt(cmb.a_ext_a, cmb.a_ext_a_mode,
747
cmb.a_ext_b, cmb.a_ext_b_mode,
748
cmb.a_ext_c, cmb.a_ext_c_invert,
749
cmb.a_ext_d, cmb.a_ext_d_invert, 0, 0);
750
}
751
else
752
{
753
grColorCombine (cmb.c_fnc, cmb.c_fac, cmb.c_loc, cmb.c_oth, FXFALSE);
754
grAlphaCombine (cmb.a_fnc, cmb.a_fac, cmb.a_loc, cmb.a_oth, FXFALSE);
755
}
756
grConstantColorValue (cmb.ccolor);
757
grAlphaBlendFunction (cmb.abf1, cmb.abf2, GR_BLEND_ZERO, GR_BLEND_ZERO);
758
if (!rdp.tex) //nothing more to do
759
return;
760
}
761
762
if (tmu_1 < voodoo.num_tmu)
763
{
764
if (cmb.tex_cmb_ext_use)
765
{
766
LRDP(" | | | |- combiner extension tmu1\n");
767
if (!(cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_COLOR))
768
TexColorCombinerToExtension (GR_TMU1);
769
if (!(cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_ALPHA))
770
TexAlphaCombinerToExtension (GR_TMU1);
771
cmb.grTexColorCombineExt(tmu_1, cmb.t1c_ext_a, cmb.t1c_ext_a_mode,
772
cmb.t1c_ext_b, cmb.t1c_ext_b_mode,
773
cmb.t1c_ext_c, cmb.t1c_ext_c_invert,
774
cmb.t1c_ext_d, cmb.t1c_ext_d_invert, 0, 0);
775
cmb.grTexAlphaCombineExt(tmu_1, cmb.t1a_ext_a, cmb.t1a_ext_a_mode,
776
cmb.t1a_ext_b, cmb.t1a_ext_b_mode,
777
cmb.t1a_ext_c, cmb.t1a_ext_c_invert,
778
cmb.t1a_ext_d, cmb.t1a_ext_d_invert, 0, 0);
779
cmb.grConstantColorValueExt(tmu_1, cmb.tex_ccolor);
780
}
781
else
782
{
783
grTexCombine (tmu_1, cmb.tmu1_func, cmb.tmu1_fac, cmb.tmu1_a_func, cmb.tmu1_a_fac, cmb.tmu1_invert, cmb.tmu1_a_invert);
784
if (cmb.combine_ext)
785
cmb.grConstantColorValueExt(tmu_1, 0);
786
}
787
grTexDetailControl (tmu_1, cmb.dc1_lodbias, cmb.dc1_detailscale, cmb.dc1_detailmax);
788
grTexLodBiasValue (tmu_1, cmb.lodbias1);
789
}
790
if (tmu_0 < voodoo.num_tmu)
791
{
792
if (cmb.tex_cmb_ext_use)
793
{
794
LRDP(" | | | |- combiner extension tmu0\n");
795
if (!(cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_COLOR))
796
TexColorCombinerToExtension (GR_TMU0);
797
if (!(cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_ALPHA))
798
TexAlphaCombinerToExtension (GR_TMU0);
799
cmb.grTexColorCombineExt(tmu_0, cmb.t0c_ext_a, cmb.t0c_ext_a_mode,
800
cmb.t0c_ext_b, cmb.t0c_ext_b_mode,
801
cmb.t0c_ext_c, cmb.t0c_ext_c_invert,
802
cmb.t0c_ext_d, cmb.t0c_ext_d_invert, 0, 0);
803
cmb.grTexAlphaCombineExt(tmu_0, cmb.t0a_ext_a, cmb.t0a_ext_a_mode,
804
cmb.t0a_ext_b, cmb.t0a_ext_b_mode,
805
cmb.t0a_ext_c, cmb.t0a_ext_c_invert,
806
cmb.t0a_ext_d, cmb.t0a_ext_d_invert, 0, 0);
807
cmb.grConstantColorValueExt(tmu_0, cmb.tex_ccolor);
808
}
809
else
810
{
811
grTexCombine (tmu_0, cmb.tmu0_func, cmb.tmu0_fac, cmb.tmu0_a_func, cmb.tmu0_a_fac, cmb.tmu0_invert, cmb.tmu0_a_invert);
812
if (cmb.combine_ext)
813
cmb.grConstantColorValueExt(tmu_0, 0);
814
}
815
grTexDetailControl (tmu_0, cmb.dc0_lodbias, cmb.dc0_detailscale, cmb.dc0_detailmax);
816
grTexLodBiasValue (tmu_0, cmb.lodbias0);
817
}
818
}
819
820
if ((rdp.tex & 1) && tmu_0 < voodoo.num_tmu)
821
{
822
if (aTBuff[0] && aTBuff[0]->cache)
823
{
824
LRDP(" | |- Hires tex T0 found in cache.\n");
825
if (fullscreen)
826
{
827
rdp.cur_cache[0] = aTBuff[0]->cache;
828
rdp.cur_cache[0]->last_used = frame_count;
829
rdp.cur_cache[0]->uses = rdp.debug_n;
830
}
831
}
832
else if (tex_found[0][tmu_0] != -1)
833
{
834
LRDP(" | |- T0 found in cache.\n");
835
if (fullscreen)
836
{
837
CACHE_LUT *cache = voodoo.tex_UMA?&rdp.cache[0][tex_found[0][0]]:&rdp.cache[tmu_0][tex_found[0][tmu_0]];
838
rdp.cur_cache_n[0] = tex_found[0][tmu_0];
839
rdp.cur_cache[0] = cache;
840
rdp.cur_cache[0]->last_used = frame_count;
841
rdp.cur_cache[0]->uses = rdp.debug_n;
842
grTexSource (tmu_0,
843
(voodoo.tex_min_addr[tmu_0] + cache->tmem_addr),
844
GR_MIPMAPLEVELMASK_BOTH,
845
&cache->t_info);
846
}
847
}
848
else
849
LoadTex (0, tmu_0);
850
}
851
if ((rdp.tex & 2) && tmu_1 < voodoo.num_tmu)
852
{
853
if (aTBuff[1] && aTBuff[1]->cache)
854
{
855
LRDP(" | |- Hires tex T1 found in cache.\n");
856
if (fullscreen)
857
{
858
rdp.cur_cache[1] = aTBuff[1]->cache;
859
rdp.cur_cache[1]->last_used = frame_count;
860
rdp.cur_cache[1]->uses = rdp.debug_n;
861
}
862
}
863
else if (tex_found[1][tmu_1] != -1)
864
{
865
LRDP(" | |- T1 found in cache.\n");
866
if (fullscreen)
867
{
868
CACHE_LUT *cache = voodoo.tex_UMA?&rdp.cache[0][tex_found[1][0]]:&rdp.cache[tmu_1][tex_found[1][tmu_1]];
869
rdp.cur_cache_n[1] = tex_found[1][tmu_1];
870
rdp.cur_cache[1] = cache;
871
rdp.cur_cache[1]->last_used = frame_count;
872
rdp.cur_cache[1]->uses = rdp.debug_n;
873
grTexSource (tmu_1,
874
(voodoo.tex_min_addr[tmu_1] + cache->tmem_addr),
875
GR_MIPMAPLEVELMASK_BOTH,
876
&cache->t_info);
877
}
878
}
879
else
880
LoadTex (1, tmu_1);
881
}
882
883
if (fullscreen)
884
{
885
for (int i=0; i<2; i++)
886
{
887
int tmu;
888
if (i==0) tmu=tmu_0;
889
else if (i==1) tmu=tmu_1;
890
891
if (tmu >= voodoo.num_tmu) continue;
892
893
int tile = rdp.cur_tile + i;
894
895
if (settings.filtering == 0)
896
{
897
int filter = (rdp.filter_mode!=2)?GR_TEXTUREFILTER_POINT_SAMPLED:GR_TEXTUREFILTER_BILINEAR;
898
grTexFilterMode (tmu, filter, filter);
899
}
900
else
901
{
902
int filter = (settings.filtering==1)?GR_TEXTUREFILTER_BILINEAR:GR_TEXTUREFILTER_POINT_SAMPLED;
903
grTexFilterMode (tmu, filter, filter);
904
}
905
906
if (rdp.cur_cache[i])
907
{
908
wxUint32 mode_s, mode_t;
909
int clamp_s, clamp_t;
910
if (rdp.force_wrap && !rdp.texrecting)
911
{
912
clamp_s = rdp.tiles[tile].clamp_s && rdp.tiles[tile].lr_s-rdp.tiles[tile].ul_s < 256;
913
clamp_t = rdp.tiles[tile].clamp_t && rdp.tiles[tile].lr_t-rdp.tiles[tile].ul_t < 256;
914
}
915
else
916
{
917
clamp_s = (rdp.tiles[tile].clamp_s || rdp.tiles[tile].mask_s == 0) &&
918
rdp.tiles[tile].lr_s-rdp.tiles[tile].ul_s < 256;
919
clamp_t = (rdp.tiles[tile].clamp_t || rdp.tiles[tile].mask_t == 0) &&
920
rdp.tiles[tile].lr_t-rdp.tiles[tile].ul_t < 256;
921
}
922
923
if (rdp.cur_cache[i]->f_mirror_s)
924
mode_s = GR_TEXTURECLAMP_MIRROR_EXT;
925
else if (rdp.cur_cache[i]->f_wrap_s)
926
mode_s = GR_TEXTURECLAMP_WRAP;
927
else if (clamp_s)
928
mode_s = GR_TEXTURECLAMP_CLAMP;
929
else
930
{
931
if (rdp.tiles[tile].mirror_s && voodoo.sup_mirroring)
932
mode_s = GR_TEXTURECLAMP_MIRROR_EXT;
933
else
934
mode_s = GR_TEXTURECLAMP_WRAP;
935
}
936
937
if (rdp.cur_cache[i]->f_mirror_t)
938
mode_t = GR_TEXTURECLAMP_MIRROR_EXT;
939
else if (rdp.cur_cache[i]->f_wrap_t)
940
mode_t = GR_TEXTURECLAMP_WRAP;
941
else if (clamp_t)
942
mode_t = GR_TEXTURECLAMP_CLAMP;
943
else
944
{
945
if (rdp.tiles[tile].mirror_t && voodoo.sup_mirroring)
946
mode_t = GR_TEXTURECLAMP_MIRROR_EXT;
947
else
948
mode_t = GR_TEXTURECLAMP_WRAP;
949
}
950
951
grTexClampMode (tmu,
952
mode_s,
953
mode_t);
954
}
955
if (aTBuff[i] && (rdp.tex&(i+1)))
956
SelectTBuffTex(aTBuff[i]);
957
}
958
}
959
960
LRDP(" | +- TexCache End\n");
961
}
962
963
964
#ifdef TEXTURE_FILTER
965
/** cite from RiceVideo */
966
inline wxUint32 CalculateDXT(wxUint32 txl2words)
967
{
968
if( txl2words == 0 ) return 1;
969
else return (2048+txl2words-1)/txl2words;
970
}
971
972
wxUint32 sizeBytes[4] = {0,1,2,4};
973
974
inline wxUint32 Txl2Words(wxUint32 width, wxUint32 size)
975
{
976
if( size == 0 )
977
return max(1, width/16);
978
else
979
return max(1, width*sizeBytes[size]/8);
980
}
981
982
inline wxUint32 ReverseDXT(wxUint32 val, wxUint32 lrs, wxUint32 width, wxUint32 size)
983
{
984
if( val == 0x800 ) return 1;
985
986
int low = 2047/val;
987
if( CalculateDXT(low) > val ) low++;
988
int high = 2047/(val-1);
989
990
if( low == high ) return low;
991
992
for( int i=low; i<=high; i++ )
993
{
994
if( Txl2Words(width, size) == (wxUint32)i )
995
return i;
996
}
997
998
return (low+high)/2;
999
}
1000
/** end RiceVideo cite */
1001
#endif
1002
1003
//****************************************************************
1004
// LoadTex - does the actual texture loading after everything is prepared
1005
1006
void LoadTex (int id, int tmu)
1007
{
1008
FRDP (" | |-+ LoadTex (id: %d, tmu: %d)\n", id, tmu);
1009
1010
int td = rdp.cur_tile + id;
1011
int lod, aspect;
1012
CACHE_LUT *cache;
1013
1014
if (texinfo[id].width < 0 || texinfo[id].height < 0)
1015
return;
1016
1017
// Clear the cache if it's full
1018
if (rdp.n_cached[tmu] >= MAX_CACHE)
1019
{
1020
LRDP("Cache count reached, clearing...\n");
1021
ClearCache ();
1022
if (id == 1 && rdp.tex == 3)
1023
LoadTex (0, rdp.t0);
1024
}
1025
1026
// Get this cache object
1027
cache = voodoo.tex_UMA?&rdp.cache[0][rdp.n_cached[0]]:&rdp.cache[tmu][rdp.n_cached[tmu]];
1028
rdp.cur_cache[id] = cache;
1029
rdp.cur_cache_n[id] = rdp.n_cached[tmu];
1030
1031
//!Hackalert
1032
//GoldenEye water texture. It has CI format in fact, but the game set it to RGBA
1033
if ((settings.hacks&hack_GoldenEye) && rdp.tiles[td].format == 0 && rdp.tlut_mode == 2 && rdp.tiles[td].size == 2)
1034
{
1035
rdp.tiles[td].format = 2;
1036
rdp.tiles[td].size = 1;
1037
}
1038
1039
// Set the data
1040
cache->line = rdp.tiles[td].line;
1041
cache->addr = rdp.addr[rdp.tiles[td].t_mem];
1042
cache->crc = texinfo[id].crc;
1043
cache->palette = rdp.tiles[td].palette;
1044
cache->width = rdp.tiles[td].width;
1045
cache->height = rdp.tiles[td].height;
1046
cache->format = rdp.tiles[td].format;
1047
cache->size = rdp.tiles[td].size;
1048
cache->tmem_addr = voodoo.tmem_ptr[tmu];
1049
cache->set_by = rdp.timg.set_by;
1050
cache->texrecting = rdp.texrecting;
1051
cache->last_used = frame_count;
1052
cache->uses = rdp.debug_n;
1053
cache->flags = texinfo[id].flags;
1054
cache->f_mirror_s = FALSE;
1055
cache->f_mirror_t = FALSE;
1056
cache->f_wrap_s = FALSE;
1057
cache->f_wrap_t = FALSE;
1058
#ifdef TEXTURE_FILTER
1059
cache->is_hires_tex = FALSE;
1060
cache->ricecrc = texinfo[id].ricecrc;
1061
#endif
1062
1063
// Add this cache to the list
1064
AddToList (&cachelut[cache->crc>>16], cache->crc, wxPtrToUInt(cache), tmu, rdp.n_cached[tmu]);
1065
1066
// temporary
1067
cache->t_info.format = GR_TEXFMT_ARGB_1555;
1068
1069
// Calculate lod and aspect
1070
wxUint32 size_x = rdp.tiles[td].width;
1071
wxUint32 size_y = rdp.tiles[td].height;
1072
1073
// make size_x and size_y both powers of two
1074
if (!voodoo.sup_large_tex)
1075
{
1076
if (size_x > 256) size_x = 256;
1077
if (size_y > 256) size_y = 256;
1078
}
1079
1080
int shift;
1081
for (shift=0; (1<<shift) < (int)size_x; shift++);
1082
size_x = 1 << shift;
1083
for (shift=0; (1<<shift) < (int)size_y; shift++);
1084
size_y = 1 << shift;
1085
1086
// Voodoo 1 support is all here, it will automatically mirror to the full extent.
1087
if (!voodoo.sup_mirroring)
1088
{
1089
if (rdp.tiles[td].mirror_s && !rdp.tiles[td].clamp_s && (voodoo.sup_large_tex || size_x <= 128))
1090
size_x <<= 1;
1091
if (rdp.tiles[td].mirror_t && !rdp.tiles[td].clamp_t && (voodoo.sup_large_tex || size_y <= 128))
1092
size_y <<= 1;
1093
}
1094
1095
// Calculate the maximum size
1096
int size_max = max (size_x, size_y);
1097
wxUint32 real_x=size_max, real_y=size_max;
1098
switch (size_max)
1099
{
1100
case 1:
1101
lod = GR_LOD_LOG2_1;
1102
cache->scale = 256.0f;
1103
break;
1104
case 2:
1105
lod = GR_LOD_LOG2_2;
1106
cache->scale = 128.0f;
1107
break;
1108
case 4:
1109
lod = GR_LOD_LOG2_4;
1110
cache->scale = 64.0f;
1111
break;
1112
case 8:
1113
lod = GR_LOD_LOG2_8;
1114
cache->scale = 32.0f;
1115
break;
1116
case 16:
1117
lod = GR_LOD_LOG2_16;
1118
cache->scale = 16.0f;
1119
break;
1120
case 32:
1121
lod = GR_LOD_LOG2_32;
1122
cache->scale = 8.0f;
1123
break;
1124
case 64:
1125
lod = GR_LOD_LOG2_64;
1126
cache->scale = 4.0f;
1127
break;
1128
case 128:
1129
lod = GR_LOD_LOG2_128;
1130
cache->scale = 2.0f;
1131
break;
1132
case 256:
1133
lod = GR_LOD_LOG2_256;
1134
cache->scale = 1.0f;
1135
break;
1136
case 512:
1137
lod = GR_LOD_LOG2_512;
1138
cache->scale = 0.5f;
1139
break;
1140
default:
1141
lod = GR_LOD_LOG2_1024;
1142
cache->scale = 0.25f;
1143
break;
1144
}
1145
1146
// Calculate the aspect ratio
1147
if (size_x >= size_y)
1148
{
1149
int ratio = size_x / size_y;
1150
switch (ratio)
1151
{
1152
case 1:
1153
aspect = GR_ASPECT_LOG2_1x1;
1154
cache->scale_x = 1.0f;
1155
cache->scale_y = 1.0f;
1156
break;
1157
case 2:
1158
aspect = GR_ASPECT_LOG2_2x1;
1159
cache->scale_x = 1.0f;
1160
cache->scale_y = 0.5f;
1161
real_y >>= 1;
1162
break;
1163
case 4:
1164
aspect = GR_ASPECT_LOG2_4x1;
1165
cache->scale_x = 1.0f;
1166
cache->scale_y = 0.25f;
1167
real_y >>= 2;
1168
break;
1169
default:
1170
aspect = GR_ASPECT_LOG2_8x1;
1171
cache->scale_x = 1.0f;
1172
cache->scale_y = 0.125f;
1173
real_y >>= 3;
1174
break;
1175
}
1176
}
1177
else
1178
{
1179
int ratio = size_y / size_x;
1180
switch (ratio)
1181
{
1182
case 2:
1183
aspect = GR_ASPECT_LOG2_1x2;
1184
cache->scale_x = 0.5f;
1185
cache->scale_y = 1.0f;
1186
real_x >>= 1;
1187
break;
1188
case 4:
1189
aspect = GR_ASPECT_LOG2_1x4;
1190
cache->scale_x = 0.25f;
1191
cache->scale_y = 1.0f;
1192
real_x >>= 2;
1193
break;
1194
default:
1195
aspect = GR_ASPECT_LOG2_1x8;
1196
cache->scale_x = 0.125f;
1197
cache->scale_y = 1.0f;
1198
real_x >>= 3;
1199
break;
1200
}
1201
}
1202
1203
if (real_x != cache->width || real_y != cache->height)
1204
{
1205
cache->scale_x *= (float)cache->width / (float)real_x;
1206
cache->scale_y *= (float)cache->height / (float)real_y;
1207
}
1208
1209
int splits = texinfo[id].splits;
1210
cache->splits = texinfo[id].splits;
1211
cache->splitheight = real_y / cache->splits;
1212
if (cache->splitheight < texinfo[id].splitheight)
1213
cache->splitheight = texinfo[id].splitheight;
1214
1215
// ** Calculate alignment values
1216
int wid = cache->width;
1217
int hei = cache->height;
1218
1219
if (splits > 1)
1220
{
1221
wid = texinfo[id].real_image_width;
1222
hei = texinfo[id].real_image_height;
1223
}
1224
1225
cache->c_off = cache->scale * 0.5f;
1226
if (wid != 1) cache->c_scl_x = cache->scale;
1227
else cache->c_scl_x = 0.0f;
1228
if (hei != 1) cache->c_scl_y = cache->scale;
1229
else cache->c_scl_y = 0.0f;
1230
// **
1231
1232
wxUint32 mod, modcolor, modcolor1, modcolor2, modfactor;
1233
if (id == 0)
1234
{
1235
mod = cmb.mod_0;
1236
modcolor = cmb.modcolor_0;
1237
modcolor1 = cmb.modcolor1_0;
1238
modcolor2 = cmb.modcolor2_0;
1239
modfactor = cmb.modfactor_0;
1240
}
1241
else
1242
{
1243
mod = cmb.mod_1;
1244
modcolor = cmb.modcolor_1;
1245
modcolor1 = cmb.modcolor1_1;
1246
modcolor2 = cmb.modcolor2_1;
1247
modfactor = cmb.modfactor_1;
1248
}
1249
1250
wxUint16 tmp_pal[256];
1251
int modifyPalette = (mod && (cache->format == 2) && (rdp.tlut_mode == 2));
1252
1253
if (modifyPalette)
1254
{
1255
memcpy(tmp_pal, rdp.pal_8, 512);
1256
ModifyPalette(mod, modcolor, modcolor1, modfactor);
1257
}
1258
1259
cache->mod = mod;
1260
cache->mod_color = modcolor;
1261
cache->mod_color1 = modcolor1;
1262
cache->mod_factor = modfactor;
1263
1264
for (int t = 0; t < 2; t++) {
1265
if (rdp.aTBuffTex[t] && rdp.aTBuffTex[t]->tile == id) //texture buffer will be used instead of frame buffer texture
1266
{
1267
rdp.aTBuffTex[t]->cache = cache;
1268
FRDP("tbuff_tex selected: %d, tile=%d\n", t, id);
1269
return;
1270
}
1271
}
1272
1273
wxUint32 result = 0; // keep =0 so it doesn't mess up on the first split
1274
1275
texture = tex1;
1276
1277
// Hiroshi Morii <[email protected]>
1278
// NOTE: Loading Hi-res texture packs and filtering should be done
1279
// before the texture is modified with color palettes, etc.
1280
//
1281
// Since the internal texture identification needs Glide64CRC, (RiceCRC
1282
// doesn't always return unique values) it seems reasonable that the
1283
// extra CRC calculation for hires textures should be executed only
1284
// when we get passed the texture ram cache and texture buffers for
1285
// minimal calculation overhead.
1286
//
1287
#ifdef TEXTURE_FILTER // Hiroshi Morii <[email protected]>
1288
GHQTexInfo ghqTexInfo;
1289
memset(&ghqTexInfo, 0, sizeof(GHQTexInfo));
1290
wxUint32 g64_crc = cache->crc;
1291
if (settings.ghq_use)
1292
{
1293
int bpl;
1294
wxUint8* addr = (wxUint8*)(gfx.RDRAM+rdp.addr[rdp.tiles[td].t_mem]);
1295
int tile_width = texinfo[id].width;
1296
int tile_height = texinfo[id].height;
1297
LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[td].t_mem];
1298
if (rdp.timg.set_by == 1)
1299
{
1300
bpl = info.tex_width << info.tex_size >> 1;
1301
addr += (info.tile_ul_t * bpl) + (((info.tile_ul_s<<info.tex_size)+1)>>1);
1302
1303
tile_width = min(info.tile_width, info.tex_width);
1304
if (info.tex_size > rdp.tiles[td].size)
1305
tile_width <<= info.tex_size - rdp.tiles[td].size;
1306
1307
if (rdp.tiles[td].lr_t > rdp.bg_image_height)
1308
tile_height = rdp.bg_image_height - rdp.tiles[td].ul_t;
1309
else
1310
tile_height = info.tile_height;
1311
}
1312
else
1313
{
1314
if (rdp.tiles[td].size == 3)
1315
bpl = rdp.tiles[td].line << 4;
1316
else if (info.dxt == 0)
1317
bpl = rdp.tiles[td].line << 3;
1318
else {
1319
wxUint32 dxt = info.dxt;
1320
if (dxt > 1)
1321
dxt = ReverseDXT(dxt, info.tile_width, texinfo[id].width, rdp.tiles[td].size);
1322
bpl = dxt << 3;
1323
}
1324
}
1325
1326
// wxUint8* addr = (wxUint8*)(gfx.RDRAM+rdp.addr[rdp.tiles[td].t_mem] + (rdp.tiles[td].ul_t * bpl) + (((rdp.tiles[td].ul_s<<rdp.tiles[td].size)+1)>>1));
1327
wxUint8 * paladdr = 0;
1328
wxUint16 * palette = 0;
1329
if ((rdp.tiles[td].size < 2) && (rdp.tlut_mode || rdp.tiles[td].format == 2))
1330
{
1331
if (rdp.tiles[td].size == 1)
1332
paladdr = (wxUint8*)(rdp.pal_8_rice);
1333
else if (settings.ghq_hirs_altcrc)
1334
paladdr = (wxUint8*)(rdp.pal_8_rice + (rdp.tiles[td].palette << 5));
1335
else
1336
paladdr = (wxUint8*)(rdp.pal_8_rice + (rdp.tiles[td].palette << 4));
1337
palette = (rdp.pal_8 + (rdp.tiles[td].palette << 4));
1338
}
1339
1340
// XXX: Special combiner modes are ignored for hires textures
1341
// for now. Come back to this later!! The following is needed
1342
// for (2xSai, hq4x, etc) enhanced/filtered textures.
1343
g64_crc = CRC32( g64_crc, &cache->mod, 4 );
1344
g64_crc = CRC32( g64_crc, &cache->mod_color, 4 );
1345
g64_crc = CRC32( g64_crc, &cache->mod_color1, 4 );
1346
//g64_crc = CRC32( g64_crc, &cache->mod_color2, 4 ); // not used?
1347
g64_crc = CRC32( g64_crc, &cache->mod_factor, 4 );
1348
1349
cache->ricecrc = ext_ghq_checksum(addr, tile_width, tile_height, (unsigned short)(rdp.tiles[td].format << 8 | rdp.tiles[td].size), bpl, paladdr);
1350
FRDP("CI RICE CRC. format: %d, size: %d, CRC: %08lx, PalCRC: %08lx\n", rdp.tiles[td].format, rdp.tiles[td].size, (wxUint32)(cache->ricecrc&0xFFFFFFFF), (wxUint32)(cache->ricecrc>>32));
1351
if (ext_ghq_hirestex((uint64)g64_crc, cache->ricecrc, palette, &ghqTexInfo))
1352
{
1353
cache->is_hires_tex = ghqTexInfo.is_hires_tex;
1354
if (!ghqTexInfo.is_hires_tex && aspect != ghqTexInfo.aspectRatioLog2)
1355
ghqTexInfo.data = 0; //if aspects of current texture and found filtered texture are different, texture must be filtered again.
1356
}
1357
}
1358
1359
1360
// ** handle texture splitting **
1361
if (ghqTexInfo.data)
1362
;//do nothing
1363
else
1364
#endif
1365
if (splits > 1)
1366
{
1367
cache->scale_y = 0.125f;
1368
1369
int i;
1370
for (i=0; i<splits; i++)
1371
{
1372
int start_dst = i * cache->splitheight * 256; // start lower
1373
start_dst <<= HIWORD(result); // 1st time, result is set to 0, but start_dst is 0 anyway so it doesn't matter
1374
1375
int start_src = i * 256; // start 256 more to the right
1376
start_src = start_src << (rdp.tiles[td].size) >> 1;
1377
if (rdp.tiles[td].size == 3)
1378
start_src >>= 1;
1379
1380
result = load_table[rdp.tiles[td].size][rdp.tiles[td].format]
1381
(wxPtrToUInt(texture)+start_dst, wxPtrToUInt(rdp.tmem)+(rdp.tiles[td].t_mem<<3)+start_src,
1382
texinfo[id].wid_64, texinfo[id].height, texinfo[id].line, real_x, td);
1383
1384
wxUint32 size = HIWORD(result);
1385
// clamp so that it looks somewhat ok when wrapping
1386
if (size == 1)
1387
Clamp16bT ((texture)+start_dst, texinfo[id].height, real_x, cache->splitheight);
1388
else if (size != 2)
1389
Clamp8bT ((texture)+start_dst, texinfo[id].height, real_x, cache->splitheight);
1390
else
1391
Clamp32bT ((texture)+start_dst, texinfo[id].height, real_x, cache->splitheight);
1392
}
1393
}
1394
// ** end texture splitting **
1395
else
1396
{
1397
result = load_table[rdp.tiles[td].size][rdp.tiles[td].format]
1398
(wxPtrToUInt(texture), wxPtrToUInt(rdp.tmem)+(rdp.tiles[td].t_mem<<3),
1399
texinfo[id].wid_64, texinfo[id].height, texinfo[id].line, real_x, td);
1400
1401
wxUint32 size = HIWORD(result);
1402
1403
int min_x, min_y;
1404
if (rdp.tiles[td].mask_s != 0)
1405
min_x = min((int)real_x, 1<<rdp.tiles[td].mask_s);
1406
else
1407
min_x = real_x;
1408
if (rdp.tiles[td].mask_t != 0)
1409
min_y = min((int)real_y, 1<<rdp.tiles[td].mask_t);
1410
else
1411
min_y = real_y;
1412
1413
// Load using mirroring/clamping
1414
if (min_x > texinfo[id].width)
1415
{
1416
if (size == 1)
1417
Clamp16bS ((texture), texinfo[id].width, min_x, real_x, texinfo[id].height);
1418
else if (size != 2)
1419
Clamp8bS ((texture), texinfo[id].width, min_x, real_x, texinfo[id].height);
1420
else
1421
Clamp32bS ((texture), texinfo[id].width, min_x, real_x, texinfo[id].height);
1422
}
1423
1424
if (texinfo[id].width < (int)real_x)
1425
{
1426
if (rdp.tiles[td].mirror_s)
1427
{
1428
if (size == 1)
1429
Mirror16bS ((texture), rdp.tiles[td].mask_s,
1430
real_x, real_x, texinfo[id].height);
1431
else if (size != 2)
1432
Mirror8bS ((texture), rdp.tiles[td].mask_s,
1433
real_x, real_x, texinfo[id].height);
1434
else
1435
Mirror32bS ((texture), rdp.tiles[td].mask_s,
1436
real_x, real_x, texinfo[id].height);
1437
}
1438
else
1439
{
1440
if (size == 1)
1441
Wrap16bS ((texture), rdp.tiles[td].mask_s,
1442
real_x, real_x, texinfo[id].height);
1443
else if (size != 2)
1444
Wrap8bS ((texture), rdp.tiles[td].mask_s,
1445
real_x, real_x, texinfo[id].height);
1446
else
1447
Wrap32bS ((texture), rdp.tiles[td].mask_s,
1448
real_x, real_x, texinfo[id].height);
1449
}
1450
}
1451
1452
if (min_y > texinfo[id].height)
1453
{
1454
if (size == 1)
1455
Clamp16bT ((texture), texinfo[id].height, real_x, min_y);
1456
else if (size != 2)
1457
Clamp8bT ((texture), texinfo[id].height, real_x, min_y);
1458
else
1459
Clamp32bT ((texture), texinfo[id].height, real_x, min_y);
1460
}
1461
1462
if (texinfo[id].height < (int)real_y)
1463
{
1464
if (rdp.tiles[td].mirror_t)
1465
{
1466
if (size == 1)
1467
Mirror16bT ((texture), rdp.tiles[td].mask_t,
1468
real_y, real_x);
1469
else if (size != 2)
1470
Mirror8bT ((texture), rdp.tiles[td].mask_t,
1471
real_y, real_x);
1472
else
1473
Mirror32bT ((texture), rdp.tiles[td].mask_t,
1474
real_y, real_x);
1475
}
1476
else
1477
{
1478
if (size == 1)
1479
Wrap16bT ((texture), rdp.tiles[td].mask_t,
1480
real_y, real_x);
1481
else if (size != 2)
1482
Wrap8bT ((texture), rdp.tiles[td].mask_t,
1483
real_y, real_x);
1484
else
1485
Wrap32bT ((texture), rdp.tiles[td].mask_t,
1486
real_y, real_x);
1487
}
1488
}
1489
}
1490
1491
if (modifyPalette)
1492
{
1493
memcpy(rdp.pal_8, tmp_pal, 512);
1494
}
1495
1496
#ifdef TEXTURE_FILTER
1497
if (mod && !modifyPalette && !ghqTexInfo.data)
1498
#else
1499
if (mod && !modifyPalette)
1500
#endif
1501
{
1502
// Convert the texture to ARGB 4444
1503
if (LOWORD(result) == GR_TEXFMT_ARGB_1555)
1504
{
1505
TexConv_ARGB1555_ARGB4444 ((texture), (tex2), real_x, real_y);
1506
texture = tex2;
1507
}
1508
else if (LOWORD(result) == GR_TEXFMT_ALPHA_INTENSITY_88)
1509
{
1510
TexConv_AI88_ARGB4444 ((texture), (tex2), real_x, real_y);
1511
texture = tex2;
1512
}
1513
else if (LOWORD(result) == GR_TEXFMT_ALPHA_INTENSITY_44)
1514
{
1515
TexConv_AI44_ARGB4444 ((texture), (tex2), real_x, real_y);
1516
texture = tex2;
1517
}
1518
else if (LOWORD(result) == GR_TEXFMT_ALPHA_8)
1519
{
1520
TexConv_A8_ARGB4444 ((texture), (tex2), real_x, real_y);
1521
texture = tex2;
1522
}
1523
/*else if (LOWORD(result) == GR_TEXFMT_ARGB_4444)
1524
{
1525
memcpy (tex2, texture, (real_x*real_y) << 1);
1526
texture = tex2;
1527
}*/ // we can skip memcpy since "texture" won't be swapped between "tex1" and "tex2" after this.
1528
// Hiroshi Morii <[email protected]>
1529
1530
result = (1 << 16) | GR_TEXFMT_ARGB_4444;
1531
1532
// Now convert the color to the same
1533
modcolor = ((modcolor & 0xF0000000) >> 16) | ((modcolor & 0x00F00000) >> 12) |
1534
((modcolor & 0x0000F000) >> 8) | ((modcolor & 0x000000F0) >> 4);
1535
modcolor1 = ((modcolor1 & 0xF0000000) >> 16) | ((modcolor1 & 0x00F00000) >> 12) |
1536
((modcolor1 & 0x0000F000) >> 8) | ((modcolor1 & 0x000000F0) >> 4);
1537
modcolor2 = ((modcolor2 & 0xF0000000) >> 16) | ((modcolor2 & 0x00F00000) >> 12) |
1538
((modcolor2 & 0x0000F000) >> 8) | ((modcolor2 & 0x000000F0) >> 4);
1539
1540
int size = (real_x * real_y) << 1;
1541
1542
switch (mod)
1543
{
1544
case TMOD_TEX_INTER_COLOR_USING_FACTOR:
1545
mod_tex_inter_color_using_factor ((wxUint16*)texture, size, modcolor, modfactor);
1546
break;
1547
case TMOD_TEX_INTER_COL_USING_COL1:
1548
mod_tex_inter_col_using_col1 ((wxUint16*)texture, size, modcolor, modcolor1);
1549
break;
1550
case TMOD_FULL_COLOR_SUB_TEX:
1551
mod_full_color_sub_tex ((wxUint16*)texture, size, modcolor);
1552
break;
1553
case TMOD_COL_INTER_COL1_USING_TEX:
1554
mod_col_inter_col1_using_tex ((wxUint16*)texture, size, modcolor, modcolor1);
1555
break;
1556
case TMOD_COL_INTER_COL1_USING_TEXA:
1557
mod_col_inter_col1_using_texa ((wxUint16*)texture, size, modcolor, modcolor1);
1558
break;
1559
case TMOD_COL_INTER_COL1_USING_TEXA__MUL_TEX:
1560
mod_col_inter_col1_using_texa__mul_tex ((wxUint16*)texture, size, modcolor, modcolor1);
1561
break;
1562
case TMOD_COL_INTER_TEX_USING_TEXA:
1563
mod_col_inter_tex_using_texa ((wxUint16*)texture, size, modcolor);
1564
break;
1565
case TMOD_COL2_INTER__COL_INTER_COL1_USING_TEX__USING_TEXA:
1566
mod_col2_inter__col_inter_col1_using_tex__using_texa ((wxUint16*)texture, size, modcolor, modcolor1, modcolor2);
1567
break;
1568
case TMOD_TEX_SCALE_FAC_ADD_FAC:
1569
mod_tex_scale_fac_add_fac ((wxUint16*)texture, size, modfactor);
1570
break;
1571
case TMOD_TEX_SUB_COL_MUL_FAC_ADD_TEX:
1572
mod_tex_sub_col_mul_fac_add_tex ((wxUint16*)texture, size, modcolor, modfactor);
1573
break;
1574
case TMOD_TEX_SCALE_COL_ADD_COL:
1575
mod_tex_scale_col_add_col ((wxUint16*)texture, size, modcolor, modcolor1);
1576
break;
1577
case TMOD_TEX_ADD_COL:
1578
mod_tex_add_col ((wxUint16*)texture, size, modcolor);
1579
break;
1580
case TMOD_TEX_SUB_COL:
1581
mod_tex_sub_col ((wxUint16*)texture, size, modcolor);
1582
break;
1583
case TMOD_TEX_SUB_COL_MUL_FAC:
1584
mod_tex_sub_col_mul_fac ((wxUint16*)texture, size, modcolor, modfactor);
1585
break;
1586
case TMOD_COL_INTER_TEX_USING_COL1:
1587
mod_col_inter_tex_using_col1 ((wxUint16*)texture, size, modcolor, modcolor1);
1588
break;
1589
case TMOD_COL_MUL_TEXA_ADD_TEX:
1590
mod_col_mul_texa_add_tex((wxUint16*)texture, size, modcolor);
1591
break;
1592
case TMOD_COL_INTER_TEX_USING_TEX:
1593
mod_col_inter_tex_using_tex ((wxUint16*)texture, size, modcolor);
1594
break;
1595
case TMOD_TEX_INTER_NOISE_USING_COL:
1596
mod_tex_inter_noise_using_col ((wxUint16*)texture, size, modcolor);
1597
break;
1598
case TMOD_TEX_INTER_COL_USING_TEXA:
1599
mod_tex_inter_col_using_texa ((wxUint16*)texture, size, modcolor);
1600
break;
1601
case TMOD_TEX_MUL_COL:
1602
mod_tex_mul_col ((wxUint16*)texture, size, modcolor);
1603
break;
1604
case TMOD_TEX_SCALE_FAC_ADD_COL:
1605
mod_tex_scale_fac_add_col ((wxUint16*)texture, size, modcolor, modfactor);
1606
break;
1607
default:
1608
;
1609
}
1610
}
1611
1612
1613
cache->t_info.format = LOWORD(result);
1614
1615
cache->realwidth = real_x;
1616
cache->realheight = real_y;
1617
cache->lod = lod;
1618
cache->aspect = aspect;
1619
1620
if (fullscreen)
1621
{
1622
#ifdef TEXTURE_FILTER // Hiroshi Morii <[email protected]>
1623
if (settings.ghq_use)
1624
{
1625
if (!ghqTexInfo.data && ghq_dmptex_toggle_key) {
1626
unsigned char *tmpbuf = (unsigned char*)texture;
1627
int tmpwidth = real_x;
1628
if (texinfo[id].splits > 1) {
1629
int dstpixoffset, srcpixoffset;
1630
int shift;
1631
switch (LOWORD(result) & 0x7fff) { // XXX is there a better way of determining the pixel color depth?
1632
case GR_TEXFMT_ARGB_8888:
1633
shift = 3;
1634
break;
1635
case GR_TEXFMT_ALPHA_INTENSITY_44:
1636
case GR_TEXFMT_ALPHA_8:
1637
shift = 0;
1638
break;
1639
default:
1640
shift = 1;
1641
}
1642
tmpwidth = texinfo[id].real_image_width;
1643
tmpbuf = (unsigned char*)malloc((256*256)<<3); // XXX performance overhead
1644
for (int i = 0; i < cache->splitheight; i++) {
1645
dstpixoffset = texinfo[id].real_image_width * i;
1646
srcpixoffset = 256 * i;
1647
for (int k = 0; k < texinfo[id].splits; k++) {
1648
memcpy(tmpbuf + (dstpixoffset << shift), texture + (srcpixoffset << shift), (256 << shift));
1649
dstpixoffset += 256;
1650
srcpixoffset += (256 * cache->splitheight);
1651
}
1652
}
1653
}
1654
ext_ghq_dmptx(tmpbuf, (int)texinfo[id].real_image_width, (int)texinfo[id].real_image_height, (int)tmpwidth, (unsigned short)LOWORD(result), (unsigned short)((cache->format << 8) | (cache->size)), cache->ricecrc);
1655
if (tmpbuf != texture && tmpbuf) {
1656
free(tmpbuf);
1657
}
1658
}
1659
1660
if (!ghqTexInfo.data)
1661
if (!settings.ghq_enht_nobg || !rdp.texrecting || (texinfo[id].splits == 1 && texinfo[id].width <= 256))
1662
ext_ghq_txfilter((unsigned char*)texture, (int)real_x, (int)real_y, LOWORD(result), (uint64)g64_crc, &ghqTexInfo);
1663
1664
if (ghqTexInfo.data)
1665
{
1666
if (ghqTexInfo.aspectRatioLog2 < GR_ASPECT_LOG2_1x8 ||
1667
ghqTexInfo.aspectRatioLog2 > GR_ASPECT_LOG2_8x1 ||
1668
ghqTexInfo.largeLodLog2 > GR_LOD_LOG2_2048 ||
1669
ghqTexInfo.largeLodLog2 < GR_LOD_LOG2_1)
1670
{
1671
/* invalid dimensions */
1672
}
1673
else
1674
{
1675
texture = (wxUint8 *)ghqTexInfo.data;
1676
lod = ghqTexInfo.largeLodLog2;
1677
int splits = cache->splits;
1678
if (ghqTexInfo.is_hires_tex)
1679
{
1680
if (ghqTexInfo.tiles/*ghqTexInfo.untiled_width > max_tex_size*/)
1681
{
1682
cache->scale = 1.0f;
1683
cache->c_off = 0.5f;
1684
cache->splits = ghqTexInfo.tiles;//((hirestex.width-1)>>8)+1;
1685
cache->splitheight = ghqTexInfo.untiled_height;
1686
cache->scale_x = 1.0f;
1687
cache->scale_y = float(ghqTexInfo.untiled_height*ghqTexInfo.tiles)/float(ghqTexInfo.width);//*sy;
1688
if (splits == 1)
1689
{
1690
int shift;
1691
for (shift=9; (1<<shift) < ghqTexInfo.untiled_width; shift++);
1692
float mult = float(1 << shift >> 8);
1693
cache->c_scl_x *= mult;
1694
cache->c_scl_y *= mult;
1695
}
1696
else
1697
{
1698
int tile_width = rdp.tiles[td].width;
1699
if (rdp.timg.set_by == 1)
1700
tile_width = rdp.load_info[rdp.tiles[td].t_mem].tex_width;
1701
float mult = float(ghqTexInfo.untiled_width/tile_width);
1702
cache->c_scl_x *= mult;
1703
cache->c_scl_y *= mult;
1704
}
1705
}
1706
else
1707
{
1708
cache->scale = 256.0f / float(1<<lod);
1709
cache->c_off = cache->scale * 0.5f;
1710
cache->splits = 1;
1711
if (aspect != ghqTexInfo.aspectRatioLog2)
1712
{
1713
float mscale = float(1<<abs(aspect - ghqTexInfo.aspectRatioLog2));
1714
if (abs(aspect) > abs(ghqTexInfo.aspectRatioLog2))
1715
{
1716
cache->c_scl_y *= mscale;
1717
cache->c_scl_x *= mscale;
1718
}
1719
/*
1720
else
1721
{
1722
if (rdp.tiles[td].mirror_s && sup_mirroring)
1723
cache->f_mirror_s = TRUE;
1724
if (rdp.tiles[td].mirror_t && sup_mirroring)
1725
cache->f_mirror_t = TRUE;
1726
//cache->c_scl_y /= mscale;
1727
//cache->c_scl_x /= mscale;
1728
}
1729
*/
1730
if (ghqTexInfo.aspectRatioLog2 >= 0)
1731
{
1732
cache->scale_x = 1.0f;
1733
cache->scale_y = 1.0f/float(1<<ghqTexInfo.aspectRatioLog2);
1734
}
1735
else
1736
{
1737
cache->scale_y = 1.0f;
1738
cache->scale_x = 1.0f/float(1<<(-ghqTexInfo.aspectRatioLog2));
1739
}
1740
}
1741
else if (splits > 1)
1742
{
1743
cache->c_scl_x /= splits;
1744
cache->c_scl_y /= splits;
1745
}
1746
}
1747
if (voodoo.sup_mirroring)
1748
{
1749
if (rdp.tiles[td].mirror_s && texinfo[id].tile_width == 2*texinfo[id].width)
1750
cache->f_mirror_s = TRUE;
1751
else if (texinfo[id].tile_width >= 2*texinfo[id].width)
1752
cache->f_wrap_s = TRUE;
1753
if (rdp.tiles[td].mirror_t && texinfo[id].tile_height == 2*texinfo[id].height)
1754
cache->f_mirror_t = TRUE;
1755
else if (texinfo[id].tile_height >= 2*texinfo[id].height)
1756
cache->f_wrap_t = TRUE;
1757
if (cache->f_mirror_s && cache->f_mirror_t)
1758
{
1759
cache->c_scl_x *= 2.0f;
1760
cache->c_scl_y *= 2.0f;
1761
}
1762
}
1763
aspect = ghqTexInfo.aspectRatioLog2;
1764
cache->lod = lod;
1765
cache->aspect = aspect;
1766
}
1767
else
1768
{
1769
//cache->scale = 256.0f / float(1<<lod);
1770
cache->c_off = 128.0f / float(1<<lod);
1771
}
1772
real_x = ghqTexInfo.width;
1773
real_y = ghqTexInfo.height;
1774
result = (1 << 16) | ghqTexInfo.format;
1775
cache->t_info.format = ghqTexInfo.format;
1776
cache->realwidth = real_x;
1777
cache->realheight = real_y;
1778
}
1779
}
1780
}
1781
#endif
1782
1783
// Load the texture into texture memory
1784
GrTexInfo *t_info = &cache->t_info;
1785
t_info->data = texture;
1786
t_info->smallLodLog2 = lod;
1787
t_info->largeLodLog2 = lod;
1788
t_info->aspectRatioLog2 = aspect;
1789
1790
wxUint32 texture_size = grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, t_info);
1791
1792
// Check for 2mb boundary
1793
// Hiroshi Morii <[email protected]> required only for V1,Rush, and V2
1794
if (voodoo.has_2mb_tex_boundary &&
1795
(voodoo.tmem_ptr[tmu] < TEXMEM_2MB_EDGE) && (voodoo.tmem_ptr[tmu]+texture_size > TEXMEM_2MB_EDGE))
1796
{
1797
voodoo.tmem_ptr[tmu] = TEXMEM_2MB_EDGE;
1798
cache->tmem_addr = voodoo.tmem_ptr[tmu];
1799
}
1800
1801
// Check for end of memory (too many textures to fit, clear cache)
1802
if (voodoo.tmem_ptr[tmu]+texture_size >= voodoo.tex_max_addr[tmu])
1803
{
1804
LRDP("Cache size reached, clearing...\n");
1805
ClearCache ();
1806
1807
if (id == 1 && rdp.tex == 3)
1808
LoadTex (0, rdp.t0);
1809
1810
LoadTex (id, tmu);
1811
return;
1812
// DON'T CONTINUE (already done)
1813
}
1814
1815
wxUint32 tex_addr = GetTexAddr(tmu, texture_size);
1816
grTexDownloadMipMap (tmu,
1817
tex_addr,
1818
GR_MIPMAPLEVELMASK_BOTH,
1819
t_info);
1820
1821
grTexSource (tmu,
1822
tex_addr,
1823
GR_MIPMAPLEVELMASK_BOTH,
1824
t_info);
1825
}
1826
1827
LRDP(" | | +- LoadTex end\n");
1828
}
1829
1830