Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-glide64/src/TexCache.cpp
2 views
1
/*
2
* Glide64 - Glide video plugin for Nintendo 64 emulators.
3
* Copyright (c) 2002 Dave2001
4
* Copyright (c) 2008 Günther <[email protected]>
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
17
* Licence along with this program; if not, write to the Free
18
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
* Boston, MA 02110-1301, USA
20
*/
21
22
//****************************************************************
23
//
24
// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
25
// Project started on December 29th, 2001
26
//
27
// To modify Glide64:
28
// * 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.
29
// * 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.
30
//
31
// Official Glide64 development channel: #Glide64 on EFnet
32
//
33
// Original author: Dave2001 ([email protected])
34
// Other authors: Gonetz, Gugaman
35
//
36
//****************************************************************
37
38
#define M64P_PLUGIN_PROTOTYPES 1
39
#include "m64p_types.h"
40
#include "m64p_plugin.h"
41
#include "m64p_config.h"
42
#include "m64p_vidext.h"
43
#include "TexCache.h"
44
#include "Combine.h"
45
46
void LoadTex (int id, int tmu);
47
48
BYTE tex1[512*512*4]; // temporary texture
49
BYTE tex2[512*512*4];
50
BYTE *texture;
51
52
#include "TexLoad.h" // texture loading functions, ONLY INCLUDE IN THIS FILE!!!
53
#include "MiClWr16b.h" // Mirror/Clamp/Wrap functions, ONLY INCLUDE IN THIS FILE!!!
54
#include "MiClWr8b.h" // Mirror/Clamp/Wrap functions, ONLY INCLUDE IN THIS FILE!!!
55
#include "TexConv.h" // texture conversions, ONLY INCLUDE IN THIS FILE!!!
56
#include "TexMod.h"
57
#include "TexModCI.h"
58
#include "CRC.h"
59
60
#ifndef _WIN32
61
#include <stdlib.h>
62
#endif // _WIN32
63
64
typedef struct TEXINFO_t {
65
int real_image_width, real_image_height; // FOR ALIGNMENT PURPOSES ONLY!!!
66
int tile_width, tile_height;
67
int mask_width, mask_height;
68
int width, height;
69
int wid_64, line;
70
DWORD crc;
71
DWORD flags;
72
int splits, splitheight;
73
} TEXINFO;
74
75
TEXINFO texinfo[2];
76
int tex_found[2][MAX_TMU];
77
78
//****************************************************************
79
// List functions
80
81
typedef struct NODE_t {
82
DWORD crc;
83
CACHE_LUT* data;
84
int tmu;
85
int number;
86
NODE_t *pNext;
87
} NODE;
88
89
NODE *cachelut[256];
90
91
void AddToList (NODE **list, DWORD crc, CACHE_LUT* data, int tmu, int number)
92
{
93
NODE *node = new NODE;
94
node->crc = crc;
95
node->data = data;
96
node->tmu = tmu;
97
node->number = number;
98
node->pNext = *list;
99
*list = node;
100
}
101
102
void DeleteList (NODE **list)
103
{
104
while (*list)
105
{
106
NODE *next = (*list)->pNext;
107
delete (*list);
108
*list = next;
109
}
110
}
111
112
void TexCacheInit ()
113
{
114
for (int i=0; i<256; i++)
115
{
116
cachelut[i] = NULL;
117
}
118
}
119
120
//****************************************************************
121
// GetTexInfo - gets information for either t0 or t1, checks if in cache & fills tex_found
122
123
void GetTexInfo (int id, int tile)
124
{
125
FRDP (" | |-+ GetTexInfo (id: %d, tile: %d)\n", id, tile);
126
127
TEXINFO *info = &texinfo[id];
128
129
int tile_width, tile_height;
130
int mask_width, mask_height;
131
int width, height;
132
int wid_64, line, bpl;
133
134
// Get width and height
135
tile_width = rdp.tiles[tile].lr_s - rdp.tiles[tile].ul_s + 1;
136
tile_height = rdp.tiles[tile].lr_t - rdp.tiles[tile].ul_t + 1;
137
138
mask_width = (rdp.tiles[tile].mask_s==0)?(tile_width):(1 << rdp.tiles[tile].mask_s);
139
mask_height = (rdp.tiles[tile].mask_t==0)?(tile_height):(1 << rdp.tiles[tile].mask_t);
140
141
if (settings.alt_tex_size)
142
{
143
// ** ALTERNATE TEXTURE SIZE METHOD **
144
// Helps speed in some games that loaded weird-sized textures, but could break other
145
// textures.
146
147
// Get the width/height to load
148
if ((rdp.tiles[tile].clamp_s && tile_width <= 256) || (mask_width > 256))
149
{
150
// loading width
151
width = min(mask_width, tile_width);
152
// actual width
153
rdp.tiles[tile].width = tile_width;
154
}
155
else
156
{
157
// wrap all the way
158
width = min(mask_width, tile_width); // changed from mask_width only
159
rdp.tiles[tile].width = width;
160
}
161
162
if ((rdp.tiles[tile].clamp_t && tile_height <= 256) || (mask_height > 256))
163
{
164
// loading height
165
height = min(mask_height, tile_height);
166
// actual height
167
rdp.tiles[tile].height = tile_height;
168
}
169
else
170
{
171
// wrap all the way
172
height = min(mask_height, tile_height);
173
rdp.tiles[tile].height = height;
174
}
175
}
176
else
177
{
178
// ** NORMAL TEXTURE SIZE METHOD **
179
// This is the 'correct' method for determining texture size, but may cause certain
180
// textures to load too large & make the whole game go slow.
181
182
// Get the width/height to load
183
if ((rdp.tiles[tile].clamp_s && tile_width <= 256) || (mask_width > 256))
184
{
185
// loading width
186
width = min(mask_width, tile_width);
187
// actual width
188
rdp.tiles[tile].width = tile_width;
189
}
190
else
191
{
192
// wrap all the way
193
width = mask_width;
194
rdp.tiles[tile].width = mask_width;
195
}
196
197
if ((rdp.tiles[tile].clamp_t && tile_height <= 256) || (mask_height > 256))
198
{
199
// loading height
200
height = min(mask_height, tile_height);
201
// actual height
202
rdp.tiles[tile].height = tile_height;
203
}
204
else
205
{
206
// wrap all the way
207
height = mask_height;
208
rdp.tiles[tile].height = mask_height;
209
}
210
}
211
212
// without any large texture fixing-up; for alignment
213
int real_image_width = rdp.tiles[tile].width;
214
int real_image_height = rdp.tiles[tile].height;
215
bpl = width << rdp.tiles[tile].size >> 1;
216
217
// ** COMMENT THIS TO DISABLE LARGE TEXTURES
218
#ifdef LARGE_TEXTURE_HANDLING
219
if (width > 256)
220
{
221
info->splits = ((width-1)>>8)+1;
222
info->splitheight = rdp.tiles[tile].height;
223
rdp.tiles[tile].height *= info->splits;
224
rdp.tiles[tile].width = 256;
225
width = 256;
226
}
227
else
228
#endif
229
// **
230
{
231
info->splits = 1;
232
}
233
234
RDP (" | | |-+ Texture approved:\n");
235
FRDP (" | | | |- tmem: %08lx\n", rdp.tiles[tile].t_mem);
236
FRDP (" | | | |- load width: %d\n", width);
237
FRDP (" | | | |- load height: %d\n", height);
238
FRDP (" | | | |- actual width: %d\n", rdp.tiles[tile].width);
239
FRDP (" | | | |- actual height: %d\n", rdp.tiles[tile].height);
240
FRDP (" | | | |- size: %d\n", rdp.tiles[tile].size);
241
FRDP (" | | | +- format: %d\n", rdp.tiles[tile].format);
242
RDP (" | | |- Calculating CRC... ");
243
244
// ** CRC CHECK
245
246
wid_64 = width << (rdp.tiles[tile].size) >> 1;
247
if (rdp.tiles[tile].size == 3)
248
{
249
if (wid_64 & 15) wid_64 += 16;
250
wid_64 &= 0xFFFFFFF0;
251
}
252
else
253
{
254
if (wid_64 & 7) wid_64 += 8; // round up
255
}
256
wid_64 = wid_64>>3;
257
258
// Texture too big for tmem & needs to wrap? (trees in mm)
259
260
if (settings.wrap_big_tex && (rdp.tiles[tile].t_mem + min(height, tile_height) * (rdp.tiles[tile].line<<3) > 4096))
261
{
262
RDP ("TEXTURE WRAPS TMEM!!! ");
263
264
// calculate the y value that intersects at 4096 bytes
265
int y = (4096 - rdp.tiles[tile].t_mem) / (rdp.tiles[tile].line<<3);
266
267
rdp.tiles[tile].clamp_t = 0;
268
rdp.tiles[tile].lr_t = rdp.tiles[tile].ul_t + y - 1;
269
270
// calc mask
271
int shift;
272
for (shift=0; (1<<shift)<y; shift++);
273
rdp.tiles[tile].mask_t = shift;
274
275
// restart the function
276
RDP ("restarting...\n");
277
GetTexInfo (id, tile);
278
return;
279
}
280
281
line = rdp.tiles[tile].line;
282
if (rdp.tiles[tile].size == 3) line <<= 1;
283
DWORD crc = 0;
284
if (settings.fast_crc || bpl < 2 )
285
{
286
line = (line - wid_64) << 3;
287
288
if (wid_64 < 1) wid_64 = 1;
289
unsigned char * addr = rdp.tmem + (rdp.tiles[tile].t_mem<<3);
290
if (height > 0)
291
{
292
293
// Check the CRC
294
#if !defined(__GNUC__) && !defined(NO_ASM)
295
__asm {
296
xor eax,eax // eax is final result
297
mov ebx,dword ptr [line]
298
mov ecx,dword ptr [height] // ecx is height counter
299
mov edi,dword ptr [addr] // edi is ptr to texture memory
300
crc_loop_y:
301
push ecx
302
303
mov ecx,dword ptr [wid_64]
304
crc_loop_x:
305
306
add eax,dword ptr [edi] // MUST be 64-bit aligned, so manually unroll
307
add eax,dword ptr [edi+4]
308
mov edx,ecx
309
mul edx
310
add eax,edx
311
add edi,8
312
313
dec ecx
314
jnz crc_loop_x
315
316
pop ecx
317
318
mov edx,ecx
319
mul edx
320
add eax,edx
321
322
add edi,ebx
323
324
dec ecx
325
jnz crc_loop_y
326
327
mov dword ptr [crc],eax // store the result
328
}
329
#elif !defined(NO_ASM)
330
int i;
331
int tempheight = height;
332
asm volatile (
333
"xor %[crc], %[crc] \n" // eax is final result
334
"crc_loop_y: \n"
335
336
"mov %[wid_64], %[i] \n"
337
"crc_loop_x: \n"
338
339
"add (%[addr]), %[crc] \n" // MUST be 64-bit aligned, so manually unroll
340
"add 4(%[addr]), %[crc] \n"
341
"mov %[i], %%edx \n"
342
"mul %%edx \n" // edx:eax/crc := eax/crc * edx
343
"add %%edx, %[crc] \n"
344
"add $8, %[addr] \n"
345
346
"dec %[i] \n"
347
"jnz crc_loop_x \n"
348
349
"mov %[tempheight], %%edx \n"
350
"mul %%edx \n"
351
"add %%edx, %[crc] \n"
352
353
"add %[line], %[addr] \n"
354
355
"dec %[tempheight] \n"
356
"jnz crc_loop_y \n"
357
: [crc] "=&a"(crc), [i] "=&r" (i), [tempheight] "+r"(tempheight), [addr]"+r"(addr)
358
: [line] "g" ((intptr_t)line), [wid_64] "g" (wid_64)
359
: "memory", "cc", "edx"
360
);
361
#endif
362
// ** END CRC CHECK
363
}
364
}
365
else
366
{
367
crc = 0xFFFFFFFF;
368
// unsigned __int64 * addr = (unsigned __int64 *)&rdp.tmem[rdp.tiles[tile].t_mem];
369
BYTE * addr = rdp.tmem + (rdp.tiles[tile].t_mem<<3);
370
DWORD line2 = max(line,1);
371
line2 <<= 3;
372
for (int y = 0; y < height; y++)
373
{
374
crc = CRC_Calculate( crc, (void*)addr, bpl );
375
addr += line2;
376
}
377
line = (line - wid_64) << 3;
378
if (wid_64 < 1) wid_64 = 1;
379
}
380
if ((rdp.tiles[tile].size < 2) && (rdp.tlut_mode != 0))
381
{
382
if (rdp.tiles[tile].size == 0)
383
crc += rdp.pal_8_crc[rdp.tiles[tile].palette];
384
else
385
crc += rdp.pal_256_crc;
386
}
387
388
389
FRDP ("Done. CRC is: %08lx.\n", crc);
390
391
DWORD flags = (rdp.tiles[tile].clamp_s << 23) | (rdp.tiles[tile].mirror_s << 22) |
392
(rdp.tiles[tile].mask_s << 18) | (rdp.tiles[tile].clamp_t << 17) |
393
(rdp.tiles[tile].mirror_t << 16) | (rdp.tiles[tile].mask_t << 12);
394
395
info->real_image_width = real_image_width;
396
info->real_image_height = real_image_height;
397
info->tile_width = tile_width;
398
info->tile_height = tile_height;
399
info->mask_width = mask_width;
400
info->mask_height = mask_height;
401
info->width = width;
402
info->height = height;
403
info->wid_64 = wid_64;
404
info->line = line;
405
info->crc = crc;
406
info->flags = flags;
407
408
// Search the texture cache for this texture
409
RDP (" | | |-+ Checking cache...\n");
410
411
int t;
412
CACHE_LUT *cache;
413
414
// this is the OLD cache searching, searches ALL textures
415
/* for (t=0; t<num_tmu; t++)
416
{
417
tex_found[id][t] = -1; // default, overwrite if found
418
419
for (i=0; i<rdp.n_cached[t]; i++)
420
{
421
cache = &rdp.cache[t][i];
422
if (crc == cache->crc &&
423
//rdp.timg.addr == cache->addr && // not totally correct, but will help
424
//rdp.addr[rdp.tiles[tile].t_mem] == cache->addr && // more correct
425
rdp.tiles[tile].width == cache->width &&
426
rdp.tiles[tile].height == cache->height &&
427
rdp.tiles[tile].format == cache->format &&
428
rdp.tiles[tile].size == cache->size &&
429
rdp.tiles[tile].palette == cache->palette &&
430
pal_crc == cache->pal_crc &&
431
flags == cache->flags)
432
{
433
FRDP (" | | | |- Texture found in cache (tmu=%d).\n", t);
434
tex_found[id][t] = i;
435
break;
436
}
437
}
438
}
439
for (; t<MAX_TMU; t++)
440
{
441
tex_found[id][t] = -1;
442
}*/
443
444
// this is the NEW cache searching, searches only textures with similar crc's
445
for (t=0; t<MAX_TMU; t++)
446
tex_found[id][t] = -1;
447
448
if (rdp.noise == noise_texture)
449
return;
450
451
DWORD mod, modcolor, modcolor1, modcolor2, modfactor;
452
if (id == 0)
453
{
454
mod = cmb.mod_0;
455
modcolor = cmb.modcolor_0;
456
modcolor1 = cmb.modcolor1_0;
457
modcolor2 = cmb.modcolor2_0;
458
modfactor = cmb.modfactor_0;
459
}
460
else
461
{
462
mod = cmb.mod_1;
463
modcolor = cmb.modcolor_1;
464
modcolor1 = cmb.modcolor1_1;
465
modcolor2 = cmb.modcolor2_1;
466
modfactor = cmb.modfactor_1;
467
}
468
469
NODE *node = cachelut[crc>>24];
470
DWORD mod_mask = (rdp.tiles[tile].format == 2)?0xFFFFFFFF:0xF0F0F0F0;
471
while (node)
472
{
473
if (node->crc == crc)
474
{
475
cache = (CACHE_LUT*)node->data;
476
if (tex_found[id][node->tmu] == -1 &&
477
rdp.tiles[tile].width == cache->width &&
478
rdp.tiles[tile].height == cache->height &&
479
rdp.tiles[tile].format == cache->format &&
480
rdp.tiles[tile].size == cache->size &&
481
rdp.tiles[tile].palette == cache->palette &&
482
flags == cache->flags)
483
{
484
if (cache->mod == mod &&
485
(cache->mod_color&mod_mask) == (modcolor&mod_mask) &&
486
(cache->mod_color1&mod_mask) == (modcolor1&mod_mask) &&
487
(cache->mod_color2&mod_mask) == (modcolor2&mod_mask) &&
488
abs(static_cast<int>(cache->mod_factor - modfactor)) < 8)
489
{
490
FRDP (" | | | |- Texture found in cache (tmu=%d).\n", node->tmu);
491
tex_found[id][node->tmu] = node->number;
492
// if (rdp.addr[rdp.tiles[tile].t_mem] == cache->addr)
493
// return;
494
}
495
}
496
}
497
node = node->pNext;
498
}
499
500
RDP (" | | | +- Done.\n | | +- GetTexInfo end\n");
501
}
502
503
//****************************************************************
504
// ChooseBestTmu - chooses the best TMU to load to (the one with the most memory)
505
506
int ChooseBestTmu (int tmu1, int tmu2)
507
{
508
if (!fullscreen) return tmu1;
509
510
if (tmu1 >= num_tmu) return tmu2;
511
if (tmu2 >= num_tmu) return tmu1;
512
513
if (grTexMaxAddress(tmu1)-rdp.tmem_ptr[tmu1] >
514
grTexMaxAddress(tmu2)-rdp.tmem_ptr[tmu2])
515
return tmu1;
516
else
517
return tmu2;
518
}
519
520
//****************************************************************
521
// SelectHiresTex - select texture from texture buffer
522
523
static void SelectHiresTex()
524
{
525
FRDP ("SelectHiresTex: tex: %d, tmu: %d, tile: %d\n", rdp.tex, rdp.hires_tex->tmu, rdp.hires_tex->tile);
526
grTexSource( rdp.hires_tex->tmu, rdp.hires_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.hires_tex->info) );
527
if (rdp.tex == 3 && rdp.hires_tex->tmu == rdp.hires_tex->tile)
528
return;
529
GrCombineFunction_t color_source =
530
(rdp.hires_tex->info.format == GR_TEXFMT_RGB_565) ? GR_COMBINE_FUNCTION_LOCAL : GR_COMBINE_FUNCTION_LOCAL_ALPHA;
531
if (rdp.hires_tex->tmu == GR_TMU0)
532
{
533
grTexCombine( GR_TMU1,
534
GR_COMBINE_FUNCTION_NONE,
535
GR_COMBINE_FACTOR_NONE,
536
GR_COMBINE_FUNCTION_NONE,
537
GR_COMBINE_FACTOR_NONE,
538
FXFALSE,
539
FXFALSE );
540
grTexCombine( GR_TMU0,
541
color_source,
542
GR_COMBINE_FACTOR_NONE,
543
GR_COMBINE_FUNCTION_LOCAL,
544
GR_COMBINE_FACTOR_NONE,
545
FXFALSE,
546
FXFALSE);
547
}
548
else
549
{
550
grTexCombine( GR_TMU1,
551
color_source,
552
GR_COMBINE_FACTOR_NONE,
553
GR_COMBINE_FUNCTION_LOCAL,
554
GR_COMBINE_FACTOR_NONE,
555
FXFALSE,
556
FXFALSE);
557
grTexCombine( GR_TMU0,
558
GR_COMBINE_FUNCTION_SCALE_OTHER,
559
GR_COMBINE_FACTOR_ONE,
560
GR_COMBINE_FUNCTION_SCALE_OTHER,
561
GR_COMBINE_FACTOR_ONE,
562
FXFALSE,
563
FXFALSE );
564
}
565
}
566
567
//****************************************************************
568
// TexCache - does texture loading after combiner is set
569
570
void TexCache ()
571
{
572
RDP (" |-+ TexCache called\n");
573
574
if (rdp.tex & 1)
575
GetTexInfo (0, rdp.cur_tile);
576
if (rdp.tex & 2)
577
GetTexInfo (1, rdp.cur_tile+1);
578
579
#define TMUMODE_NORMAL 0
580
#define TMUMODE_PASSTHRU 1
581
#define TMUMODE_NONE 2
582
583
int tmu_0, tmu_1;
584
int tmu_0_mode=0, tmu_1_mode=0;
585
586
// Select the best TMUs to use (removed 3 tmu support, unnecessary)
587
if (rdp.tex == 3) // T0 and T1
588
{
589
tmu_0 = 0;
590
tmu_1 = 1;
591
}
592
else if (rdp.tex == 2) // T1
593
{
594
if (tex_found[1][0] != -1) // T1 found in tmu 0
595
tmu_1 = 0;
596
else if (tex_found[1][1] != -1) // T1 found in tmu 1
597
tmu_1 = 1;
598
else // T1 not found
599
tmu_1 = ChooseBestTmu (0, 1);
600
601
tmu_0 = !tmu_1;
602
tmu_0_mode = (tmu_0==1)?TMUMODE_NONE:TMUMODE_PASSTHRU;
603
}
604
else if (rdp.tex == 1) // T0
605
{
606
if (tex_found[0][0] != -1) // T0 found in tmu 0
607
tmu_0 = 0;
608
else if (tex_found[0][1] != -1) // T0 found in tmu 1
609
tmu_0 = 1;
610
else // T0 not found
611
tmu_0 = ChooseBestTmu (0, 1);
612
613
tmu_1 = !tmu_0;
614
tmu_1_mode = (tmu_1==1)?TMUMODE_NONE:TMUMODE_PASSTHRU;
615
}
616
else // no texture
617
{
618
tmu_0 = 0;
619
tmu_0_mode = TMUMODE_NONE;
620
tmu_1 = 0;
621
tmu_1_mode = TMUMODE_NONE;
622
}
623
624
FRDP (" | |-+ Modes set:\n | | |- tmu_0 = %d\n | | |- tmu_1 = %d\n",
625
tmu_0, tmu_1);
626
FRDP (" | | |- tmu_0_mode = %d\n | | |- tmu_1_mode = %d\n",
627
tmu_0_mode, tmu_1_mode);
628
629
if (tmu_0_mode == TMUMODE_PASSTHRU) {
630
cmb.tmu0_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER;
631
cmb.tmu0_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_ONE;
632
if (cmb.tex_cmb_ext_use)
633
{
634
cmb.t0c_ext_a = GR_CMBX_OTHER_TEXTURE_RGB;
635
cmb.t0c_ext_a_mode = GR_FUNC_MODE_X;
636
cmb.t0c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB;
637
cmb.t0c_ext_b_mode = GR_FUNC_MODE_ZERO;
638
cmb.t0c_ext_c = GR_CMBX_ZERO;
639
cmb.t0c_ext_c_invert = 1;
640
cmb.t0c_ext_d = GR_CMBX_ZERO;
641
cmb.t0c_ext_d_invert = 0;
642
cmb.t0a_ext_a = GR_CMBX_OTHER_TEXTURE_ALPHA;
643
cmb.t0a_ext_a_mode = GR_FUNC_MODE_X;
644
cmb.t0a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA;
645
cmb.t0a_ext_b_mode = GR_FUNC_MODE_ZERO;
646
cmb.t0a_ext_c = GR_CMBX_ZERO;
647
cmb.t0a_ext_c_invert = 1;
648
cmb.t0a_ext_d = GR_CMBX_ZERO;
649
cmb.t0a_ext_d_invert = 0;
650
}
651
}
652
else if (tmu_0_mode == TMUMODE_NONE) {
653
cmb.tmu0_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_NONE;
654
cmb.tmu0_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE;
655
if (cmb.tex_cmb_ext_use)
656
{
657
cmb.t0c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB;
658
cmb.t0c_ext_a_mode = GR_FUNC_MODE_ZERO;
659
cmb.t0c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB;
660
cmb.t0c_ext_b_mode = GR_FUNC_MODE_ZERO;
661
cmb.t0c_ext_c = GR_CMBX_ZERO;
662
cmb.t0c_ext_c_invert = 0;
663
cmb.t0c_ext_d = GR_CMBX_ZERO;
664
cmb.t0c_ext_d_invert = 0;
665
cmb.t0a_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA;
666
cmb.t0a_ext_a_mode = GR_FUNC_MODE_ZERO;
667
cmb.t0a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA;
668
cmb.t0a_ext_b_mode = GR_FUNC_MODE_ZERO;
669
cmb.t0a_ext_c = GR_CMBX_ZERO;
670
cmb.t0a_ext_c_invert = 0;
671
cmb.t0a_ext_d = GR_CMBX_ZERO;
672
cmb.t0a_ext_d_invert = 0;
673
}
674
}
675
if (tmu_1_mode == TMUMODE_PASSTHRU) {
676
cmb.tmu1_func = cmb.tmu1_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER;
677
cmb.tmu1_fac = cmb.tmu1_a_fac = GR_COMBINE_FACTOR_ONE;
678
if (cmb.tex_cmb_ext_use)
679
{
680
cmb.t1c_ext_a = GR_CMBX_OTHER_TEXTURE_RGB;
681
cmb.t1c_ext_a_mode = GR_FUNC_MODE_X;
682
cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB;
683
cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO;
684
cmb.t1c_ext_c = GR_CMBX_ZERO;
685
cmb.t1c_ext_c_invert = 1;
686
cmb.t1c_ext_d = GR_CMBX_ZERO;
687
cmb.t1c_ext_d_invert = 0;
688
cmb.t1a_ext_a = GR_CMBX_OTHER_TEXTURE_ALPHA;
689
cmb.t1a_ext_a_mode = GR_FUNC_MODE_X;
690
cmb.t1a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA;
691
cmb.t1a_ext_b_mode = GR_FUNC_MODE_ZERO;
692
cmb.t1a_ext_c = GR_CMBX_ZERO;
693
cmb.t1a_ext_c_invert = 1;
694
cmb.t1a_ext_d = GR_CMBX_ZERO;
695
cmb.t1a_ext_d_invert = 0;
696
}
697
}
698
else if (tmu_1_mode == TMUMODE_NONE) {
699
cmb.tmu1_func = cmb.tmu1_a_func = GR_COMBINE_FUNCTION_NONE;
700
cmb.tmu1_fac = cmb.tmu1_a_fac = GR_COMBINE_FACTOR_NONE;
701
if (cmb.tex_cmb_ext_use)
702
{
703
cmb.t1c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB;
704
cmb.t1c_ext_a_mode = GR_FUNC_MODE_ZERO;
705
cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB;
706
cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO;
707
cmb.t1c_ext_c = GR_CMBX_ZERO;
708
cmb.t1c_ext_c_invert = 0;
709
cmb.t1c_ext_d = GR_CMBX_ZERO;
710
cmb.t1c_ext_d_invert = 0;
711
cmb.t1a_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA;
712
cmb.t1a_ext_a_mode = GR_FUNC_MODE_ZERO;
713
cmb.t1a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA;
714
cmb.t1a_ext_b_mode = GR_FUNC_MODE_ZERO;
715
cmb.t1a_ext_c = GR_CMBX_ZERO;
716
cmb.t1a_ext_c_invert = 0;
717
cmb.t1a_ext_d = GR_CMBX_ZERO;
718
cmb.t1a_ext_d_invert = 0;
719
}
720
}
721
722
// little change to make single-tmu cards look better, use first texture no matter what
723
724
if (num_tmu == 1)
725
{
726
if (rdp.best_tex == 0)
727
{
728
cmb.tmu0_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL;
729
cmb.tmu0_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE;
730
tmu_0 = 0;
731
tmu_1 = 1;
732
}
733
else
734
{
735
cmb.tmu1_func = cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL;
736
cmb.tmu1_fac = cmb.tmu1_a_fac = GR_COMBINE_FACTOR_NONE;
737
tmu_1 = 0;
738
tmu_0 = 1;
739
}
740
}
741
742
743
rdp.t0 = tmu_0;
744
rdp.t1 = tmu_1;
745
746
// SET the combiner
747
if (fullscreen)
748
{
749
if (rdp.allow_combine)
750
{
751
// Now actually combine
752
if (cmb.cmb_ext_use)
753
{
754
RDP (" | | | |- combiner extension\n");
755
if (!(cmb.cmb_ext_use & COMBINE_EXT_COLOR))
756
ColorCombinerToExtension ();
757
if (!(cmb.cmb_ext_use & COMBINE_EXT_ALPHA))
758
AlphaCombinerToExtension ();
759
cmb.grColorCombineExt(cmb.c_ext_a, cmb.c_ext_a_mode,
760
cmb.c_ext_b, cmb.c_ext_b_mode,
761
cmb.c_ext_c, cmb.c_ext_c_invert,
762
cmb.c_ext_d, cmb.c_ext_d_invert, 0, 0);
763
cmb.grAlphaCombineExt(cmb.a_ext_a, cmb.a_ext_a_mode,
764
cmb.a_ext_b, cmb.a_ext_b_mode,
765
cmb.a_ext_c, cmb.a_ext_c_invert,
766
cmb.a_ext_d, cmb.a_ext_d_invert, 0, 0);
767
}
768
else
769
{
770
grColorCombine (cmb.c_fnc, cmb.c_fac, cmb.c_loc, cmb.c_oth, FXFALSE);
771
grAlphaCombine (cmb.a_fnc, cmb.a_fac, cmb.a_loc, cmb.a_oth, FXFALSE);
772
}
773
grConstantColorValue (cmb.ccolor);
774
grAlphaBlendFunction (cmb.abf1, cmb.abf2, GR_BLEND_ZERO, GR_BLEND_ZERO);
775
}
776
777
if (tmu_1 < num_tmu)
778
{
779
if (cmb.tex_cmb_ext_use)
780
{
781
RDP (" | | | |- combiner extension tmu1\n");
782
if (!(cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_COLOR))
783
TexColorCombinerToExtension (GR_TMU1);
784
if (!(cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_ALPHA))
785
TexAlphaCombinerToExtension (GR_TMU1);
786
cmb.grTexColorCombineExt(tmu_1, cmb.t1c_ext_a, cmb.t1c_ext_a_mode,
787
cmb.t1c_ext_b, cmb.t1c_ext_b_mode,
788
cmb.t1c_ext_c, cmb.t1c_ext_c_invert,
789
cmb.t1c_ext_d, cmb.t1c_ext_d_invert, 0, 0);
790
cmb.grTexAlphaCombineExt(tmu_1, cmb.t1a_ext_a, cmb.t1a_ext_a_mode,
791
cmb.t1a_ext_b, cmb.t1a_ext_b_mode,
792
cmb.t1a_ext_c, cmb.t1a_ext_c_invert,
793
cmb.t1a_ext_d, cmb.t1a_ext_d_invert, 0, 0);
794
cmb.grConstantColorValueExt(tmu_1, cmb.tex_ccolor);
795
}
796
else
797
{
798
grTexCombine (tmu_1, cmb.tmu1_func, cmb.tmu1_fac, cmb.tmu1_a_func, cmb.tmu1_a_fac, cmb.tmu1_invert, cmb.tmu1_a_invert);
799
if (cmb.combine_ext)
800
cmb.grConstantColorValueExt(tmu_1, 0);
801
}
802
grTexDetailControl (tmu_1, cmb.dc1_lodbias, cmb.dc1_detailscale, cmb.dc1_detailmax);
803
grTexLodBiasValue (tmu_1, cmb.lodbias1);
804
}
805
if (tmu_0 < num_tmu)
806
{
807
if (cmb.tex_cmb_ext_use)
808
{
809
RDP (" | | | |- combiner extension tmu0\n");
810
if (!(cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_COLOR))
811
TexColorCombinerToExtension (GR_TMU0);
812
if (!(cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_ALPHA))
813
TexAlphaCombinerToExtension (GR_TMU0);
814
cmb.grTexColorCombineExt(tmu_0, cmb.t0c_ext_a, cmb.t0c_ext_a_mode,
815
cmb.t0c_ext_b, cmb.t0c_ext_b_mode,
816
cmb.t0c_ext_c, cmb.t0c_ext_c_invert,
817
cmb.t0c_ext_d, cmb.t0c_ext_d_invert, 0, 0);
818
cmb.grTexAlphaCombineExt(tmu_0, cmb.t0a_ext_a, cmb.t0a_ext_a_mode,
819
cmb.t0a_ext_b, cmb.t0a_ext_b_mode,
820
cmb.t0a_ext_c, cmb.t0a_ext_c_invert,
821
cmb.t0a_ext_d, cmb.t0a_ext_d_invert, 0, 0);
822
cmb.grConstantColorValueExt(tmu_0, cmb.tex_ccolor);
823
}
824
else
825
{
826
grTexCombine (tmu_0, cmb.tmu0_func, cmb.tmu0_fac, cmb.tmu0_a_func, cmb.tmu0_a_fac, cmb.tmu0_invert, cmb.tmu0_a_invert);
827
if (cmb.combine_ext)
828
cmb.grConstantColorValueExt(tmu_0, 0);
829
}
830
grTexDetailControl (tmu_0, cmb.dc0_lodbias, cmb.dc0_detailscale, cmb.dc0_detailmax);
831
grTexLodBiasValue (tmu_0, cmb.lodbias0);
832
}
833
}
834
835
if ((rdp.tex & 1) && tmu_0 < num_tmu)
836
{
837
if (tex_found[0][tmu_0] != -1)
838
{
839
RDP (" | |- T0 found in cache.\n");
840
if (fullscreen)
841
{
842
CACHE_LUT *cache = &rdp.cache[tmu_0][tex_found[0][tmu_0]];
843
rdp.cur_cache_n[0] = tex_found[0][tmu_0];
844
rdp.cur_cache[0] = cache;
845
rdp.cur_cache[0]->last_used = frame_count;
846
rdp.cur_cache[0]->uses = rdp.debug_n;
847
grTexSource (tmu_0,
848
(grTexMinAddress(tmu_0) + cache->tmem_addr),
849
GR_MIPMAPLEVELMASK_BOTH,
850
&cache->t_info);
851
}
852
}
853
else
854
LoadTex (0, tmu_0);
855
}
856
if ((rdp.tex & 2) && tmu_1 < num_tmu)
857
{
858
if (tex_found[1][tmu_1] != -1)
859
{
860
if (fullscreen)
861
{
862
CACHE_LUT *cache = &rdp.cache[tmu_1][tex_found[1][tmu_1]];
863
rdp.cur_cache_n[1] = tex_found[1][tmu_1];
864
rdp.cur_cache[1] = cache;
865
rdp.cur_cache[1]->last_used = frame_count;
866
rdp.cur_cache[1]->uses = rdp.debug_n;
867
grTexSource (tmu_1,
868
(grTexMinAddress(tmu_1) + cache->tmem_addr),
869
GR_MIPMAPLEVELMASK_BOTH,
870
&cache->t_info);
871
}
872
}
873
else
874
LoadTex (1, tmu_1);
875
}
876
877
if (fullscreen)
878
{
879
for (int i=0; i<2; i++)
880
{
881
int tmu;
882
if (i==0) tmu=tmu_0;
883
else tmu=tmu_1;
884
885
if (tmu >= num_tmu) continue;
886
887
int tile = rdp.cur_tile + i;
888
889
if (settings.filtering == 0)
890
{
891
int filter = (rdp.filter_mode!=2)?GR_TEXTUREFILTER_POINT_SAMPLED:GR_TEXTUREFILTER_BILINEAR;
892
grTexFilterMode (tmu, filter, filter);
893
}
894
else
895
{
896
int filter = (settings.filtering==1)?GR_TEXTUREFILTER_BILINEAR:GR_TEXTUREFILTER_POINT_SAMPLED;
897
grTexFilterMode (tmu, filter, filter);
898
}
899
900
DWORD mode_s, mode_t;
901
902
if ((rdp.tiles[tile].clamp_s || rdp.tiles[tile].mask_s == 0) &&
903
rdp.tiles[tile].lr_s-rdp.tiles[tile].ul_s < 256)
904
mode_s = GR_TEXTURECLAMP_CLAMP;
905
else
906
{
907
if (rdp.tiles[tile].mirror_s && sup_mirroring)
908
mode_s = GR_TEXTURECLAMP_MIRROR_EXT;
909
else
910
mode_s = GR_TEXTURECLAMP_WRAP;
911
}
912
913
if ((rdp.tiles[tile].clamp_t || rdp.tiles[tile].mask_t == 0) &&
914
rdp.tiles[tile].lr_t-rdp.tiles[tile].ul_t < 256)
915
mode_t = GR_TEXTURECLAMP_CLAMP;
916
else
917
{
918
if (rdp.tiles[tile].mirror_t && sup_mirroring)
919
mode_t = GR_TEXTURECLAMP_MIRROR_EXT;
920
else
921
mode_t = GR_TEXTURECLAMP_WRAP;
922
}
923
924
grTexClampMode (tmu,
925
mode_s,
926
mode_t);
927
}
928
if (rdp.hires_tex)
929
SelectHiresTex();
930
}
931
932
RDP (" | +- TexCache End\n");
933
}
934
935
//****************************************************************
936
// ClearCache - clear the texture cache for BOTH tmus
937
938
void ClearCache ()
939
{
940
rdp.tmem_ptr[0] = offset_textures;
941
rdp.n_cached[0] = 0;
942
rdp.tmem_ptr[1] = offset_texbuf1;
943
rdp.n_cached[1] = 0;
944
945
for (int i=0; i<256; i++)
946
{
947
DeleteList (&cachelut[i]);
948
}
949
}
950
951
//****************************************************************
952
// LoadTex - does the actual texture loading after everything is prepared
953
954
void LoadTex (int id, int tmu)
955
{
956
FRDP (" | |-+ LoadTex (id: %d, tmu: %d)\n", id, tmu);
957
958
int td = rdp.cur_tile + id;
959
int lod, aspect;
960
CACHE_LUT *cache;
961
962
if (texinfo[id].width < 0 ||
963
texinfo[id].height < 0) return;
964
965
// Clear the cache if it's full
966
if (rdp.n_cached[tmu] >= MAX_CACHE)
967
{
968
RDP ("Cache count reached, clearing...\n");
969
ClearCache ();
970
if (id == 1 && rdp.tex == 3)
971
LoadTex (0, rdp.t0);
972
}
973
974
// Get this cache object
975
cache = &rdp.cache[tmu][rdp.n_cached[tmu]];
976
rdp.cur_cache[id] = cache;
977
rdp.cur_cache_n[id] = rdp.n_cached[tmu];
978
979
// Set the data
980
cache->line = rdp.tiles[td].line;
981
cache->addr = rdp.addr[rdp.tiles[td].t_mem];
982
cache->crc = texinfo[id].crc;
983
cache->palette = rdp.tiles[td].palette;
984
cache->width = rdp.tiles[td].width;
985
cache->height = rdp.tiles[td].height;
986
cache->format = rdp.tiles[td].format;
987
cache->size = rdp.tiles[td].size;
988
cache->tmem_addr = rdp.tmem_ptr[tmu];
989
cache->set_by = rdp.timg.set_by;
990
cache->texrecting = rdp.texrecting;
991
cache->last_used = frame_count;
992
cache->uses = rdp.debug_n;
993
cache->flags = texinfo[id].flags;
994
995
// Add this cache to the list
996
AddToList (&cachelut[cache->crc>>24], cache->crc, cache, tmu, rdp.n_cached[tmu]);
997
998
rdp.n_cached[tmu] ++;
999
1000
// temporary
1001
cache->t_info.format = GR_TEXFMT_ARGB_1555;
1002
1003
// Calculate lod and aspect
1004
DWORD size_x = rdp.tiles[td].width;
1005
DWORD size_y = rdp.tiles[td].height;
1006
1007
// make size_x and size_y both powers of two
1008
if (size_x > 256) size_x = 256;
1009
if (size_y > 256) size_y = 256;
1010
1011
int shift;
1012
for (shift=0; (1<<shift) < (int)size_x; shift++);
1013
size_x = 1 << shift;
1014
for (shift=0; (1<<shift) < (int)size_y; shift++);
1015
size_y = 1 << shift;
1016
1017
// Voodoo 1 support is all here, it will automatically mirror to the full extent.
1018
if (!sup_mirroring)
1019
{
1020
if (rdp.tiles[td].mirror_s && !rdp.tiles[td].clamp_s && size_x <= 128)
1021
size_x <<= 1;
1022
if (rdp.tiles[td].mirror_t && !rdp.tiles[td].clamp_t && size_y <= 128)
1023
size_y <<= 1;
1024
}
1025
1026
// Calculate the maximum size
1027
int size_max = max (size_x, size_y);
1028
DWORD real_x=size_max, real_y=size_max;
1029
switch (size_max)
1030
{
1031
case 1:
1032
lod = GR_LOD_LOG2_1;
1033
cache->scale = 256.0f;
1034
break;
1035
case 2:
1036
lod = GR_LOD_LOG2_2;
1037
cache->scale = 128.0f;
1038
break;
1039
case 4:
1040
lod = GR_LOD_LOG2_4;
1041
cache->scale = 64.0f;
1042
break;
1043
case 8:
1044
lod = GR_LOD_LOG2_8;
1045
cache->scale = 32.0f;
1046
break;
1047
case 16:
1048
lod = GR_LOD_LOG2_16;
1049
cache->scale = 16.0f;
1050
break;
1051
case 32:
1052
lod = GR_LOD_LOG2_32;
1053
cache->scale = 8.0f;
1054
break;
1055
case 64:
1056
lod = GR_LOD_LOG2_64;
1057
cache->scale = 4.0f;
1058
break;
1059
case 128:
1060
lod = GR_LOD_LOG2_128;
1061
cache->scale = 2.0f;
1062
break;
1063
//case 256:
1064
default:
1065
lod = GR_LOD_LOG2_256;
1066
cache->scale = 1.0f;
1067
break;
1068
1069
// No default here, can't be a non-power of two, see above
1070
}
1071
1072
// Calculate the aspect ratio
1073
if (size_x >= size_y)
1074
{
1075
int ratio = size_x / size_y;
1076
switch (ratio)
1077
{
1078
case 1:
1079
aspect = GR_ASPECT_LOG2_1x1;
1080
cache->scale_x = 1.0f;
1081
cache->scale_y = 1.0f;
1082
break;
1083
case 2:
1084
aspect = GR_ASPECT_LOG2_2x1;
1085
cache->scale_x = 1.0f;
1086
cache->scale_y = 0.5f;
1087
real_y >>= 1;
1088
break;
1089
case 4:
1090
aspect = GR_ASPECT_LOG2_4x1;
1091
cache->scale_x = 1.0f;
1092
cache->scale_y = 0.25f;
1093
real_y >>= 2;
1094
break;
1095
//case 8:
1096
default:
1097
aspect = GR_ASPECT_LOG2_8x1;
1098
cache->scale_x = 1.0f;
1099
cache->scale_y = 0.125f;
1100
real_y >>= 3;
1101
break;
1102
}
1103
}
1104
else
1105
{
1106
int ratio = size_y / size_x;
1107
switch (ratio)
1108
{
1109
case 2:
1110
aspect = GR_ASPECT_LOG2_1x2;
1111
cache->scale_x = 0.5f;
1112
cache->scale_y = 1.0f;
1113
real_x >>= 1;
1114
break;
1115
case 4:
1116
aspect = GR_ASPECT_LOG2_1x4;
1117
cache->scale_x = 0.25f;
1118
cache->scale_y = 1.0f;
1119
real_x >>= 2;
1120
break;
1121
//case 8:
1122
default:
1123
aspect = GR_ASPECT_LOG2_1x8;
1124
cache->scale_x = 0.125f;
1125
cache->scale_y = 1.0f;
1126
real_x >>= 3;
1127
break;
1128
}
1129
}
1130
1131
if (real_x != cache->width || real_y != cache->height)
1132
{
1133
cache->scale_x *= (float)cache->width / (float)real_x;
1134
cache->scale_y *= (float)cache->height / (float)real_y;
1135
}
1136
1137
int splits = texinfo[id].splits;
1138
cache->splits = texinfo[id].splits;
1139
cache->splitheight = real_y / cache->splits;
1140
if (cache->splitheight < texinfo[id].splitheight)
1141
cache->splitheight = texinfo[id].splitheight;
1142
1143
// ** Calculate alignment values
1144
int wid = cache->width;
1145
int hei = cache->height;
1146
1147
if (splits > 1)
1148
{
1149
wid = texinfo[id].real_image_width;
1150
hei = texinfo[id].real_image_height;
1151
}
1152
1153
float center_off = cache->scale / 2.0f;
1154
float c_lr_x = (float)real_x*cache->scale - center_off;
1155
float c_lr_y = (float)real_y*cache->scale - center_off;
1156
float c_scl_x;
1157
if (real_x != 1) c_scl_x = (c_lr_x - center_off) / (real_x-1);
1158
else c_scl_x = 0.0f;
1159
float c_scl_y;
1160
if (real_y != 1) c_scl_y = (c_lr_y - center_off) / (real_y-1);
1161
else c_scl_y = 0.0f;
1162
c_lr_x = center_off + c_scl_x * (wid-1);
1163
c_lr_y = center_off + c_scl_y * (hei-1);
1164
cache->c_off = center_off;
1165
if (wid != 1) cache->c_scl_x = (c_lr_x - center_off) / (float)(wid-1);
1166
else cache->c_scl_x = 0.0f;
1167
if (hei != 1) cache->c_scl_y = (c_lr_y - center_off) / (float)(hei-1);
1168
else cache->c_scl_y = 0.0f;
1169
// **
1170
1171
DWORD mod, modcolor, modcolor1, modcolor2, modfactor;
1172
if (id == 0)
1173
{
1174
mod = cmb.mod_0;
1175
modcolor = cmb.modcolor_0;
1176
modcolor1 = cmb.modcolor1_0;
1177
modcolor2 = cmb.modcolor2_0;
1178
modfactor = cmb.modfactor_0;
1179
}
1180
else
1181
{
1182
mod = cmb.mod_1;
1183
modcolor = cmb.modcolor_1;
1184
modcolor1 = cmb.modcolor1_1;
1185
modcolor2 = cmb.modcolor2_1;
1186
modfactor = cmb.modfactor_1;
1187
}
1188
1189
WORD tmp_pal[256];
1190
BOOL modifyPalette = (mod && (cache->format == 2) && (rdp.tlut_mode == 2));
1191
1192
if (modifyPalette)
1193
{
1194
memcpy(tmp_pal, rdp.pal_8, 512);
1195
ModifyPalette(mod, modcolor, modcolor1, modfactor);
1196
}
1197
1198
cache->mod = mod;
1199
cache->mod_color = modcolor;
1200
cache->mod_color1 = modcolor1;
1201
cache->mod_factor = modfactor;
1202
1203
if (rdp.hires_tex && rdp.hires_tex->tile == id) //texture buffer will be used instead of frame buffer texture
1204
{
1205
RDP("hires_tex selected\n");
1206
return;
1207
}
1208
1209
DWORD result = 0; // keep =0 so it doesn't mess up on the first split
1210
1211
texture = tex1;
1212
1213
// ** handle texture splitting **
1214
if (splits > 1)
1215
{
1216
cache->scale_y = 0.125f;
1217
1218
int i;
1219
for (i=0; i<splits; i++)
1220
{
1221
int start_dst = i * cache->splitheight * 256; // start lower
1222
start_dst <<= HIWORD(result); // 1st time, result is set to 0, but start_dst is 0 anyway so it doesn't matter
1223
1224
int start_src = i * 256; // start 256 more to the right
1225
start_src = start_src << (rdp.tiles[td].size) >> 1;
1226
1227
result = load_table[rdp.tiles[td].size][rdp.tiles[td].format]
1228
(texture+start_dst, rdp.tmem+(rdp.tiles[td].t_mem<<3)+start_src,
1229
texinfo[id].wid_64, texinfo[id].height, texinfo[id].line, real_x, td);
1230
1231
DWORD size = HIWORD(result);
1232
// clamp so that it looks somewhat ok when wrapping
1233
if (size == 1)
1234
Clamp16bT (texture+start_dst, texinfo[id].height, real_x, cache->splitheight);
1235
else
1236
Clamp8bT (texture+start_dst, texinfo[id].height, real_x, cache->splitheight);
1237
}
1238
}
1239
// ** end texture splitting **
1240
else
1241
{
1242
result = load_table[rdp.tiles[td].size][rdp.tiles[td].format]
1243
(texture, rdp.tmem+(rdp.tiles[td].t_mem<<3),
1244
texinfo[id].wid_64, texinfo[id].height, texinfo[id].line, real_x, td);
1245
1246
DWORD size = HIWORD(result);
1247
1248
int min_x, min_y;
1249
if (rdp.tiles[td].mask_s != 0)
1250
min_x = min((int)real_x, 1<<rdp.tiles[td].mask_s);
1251
else
1252
min_x = real_x;
1253
if (rdp.tiles[td].mask_t != 0)
1254
min_y = min((int)real_y, 1<<rdp.tiles[td].mask_t);
1255
else
1256
min_y = real_y;
1257
1258
// Load using mirroring/clamping
1259
if (min_x > texinfo[id].width)
1260
{
1261
if (size == 1)
1262
Clamp16bS (texture, texinfo[id].width, min_x, real_x, texinfo[id].height);
1263
else
1264
Clamp8bS (texture, texinfo[id].width, min_x, real_x, texinfo[id].height);
1265
}
1266
1267
if (texinfo[id].width < (int)real_x)
1268
{
1269
if (rdp.tiles[td].mirror_s)
1270
{
1271
if (size == 1)
1272
Mirror16bS (texture, rdp.tiles[td].mask_s,
1273
real_x, real_x, texinfo[id].height);
1274
else
1275
Mirror8bS (texture, rdp.tiles[td].mask_s,
1276
real_x, real_x, texinfo[id].height);
1277
}
1278
else
1279
{
1280
if (size == 1)
1281
Wrap16bS (texture, rdp.tiles[td].mask_s,
1282
real_x, real_x, texinfo[id].height);
1283
else
1284
Wrap8bS (texture, rdp.tiles[td].mask_s,
1285
real_x, real_x, texinfo[id].height);
1286
}
1287
}
1288
1289
if (min_y > texinfo[id].height)
1290
{
1291
if (size == 1)
1292
Clamp16bT (texture, texinfo[id].height, real_x, min_y);
1293
else
1294
Clamp8bT (texture, texinfo[id].height, real_x, min_y);
1295
}
1296
1297
if (texinfo[id].height < (int)real_y)
1298
{
1299
if (rdp.tiles[td].mirror_t)
1300
{
1301
if (size == 1)
1302
Mirror16bT (texture, rdp.tiles[td].mask_t,
1303
real_y, real_x);
1304
else
1305
Mirror8bT (texture, rdp.tiles[td].mask_t,
1306
real_y, real_x);
1307
}
1308
else
1309
{
1310
if (size == 1)
1311
Wrap16bT (texture, rdp.tiles[td].mask_t,
1312
real_y, real_x);
1313
else
1314
Wrap8bT (texture, rdp.tiles[td].mask_t,
1315
real_y, real_x);
1316
}
1317
}
1318
}
1319
1320
if (modifyPalette)
1321
{
1322
memcpy(rdp.pal_8, tmp_pal, 512);
1323
}
1324
1325
if (mod && !modifyPalette)
1326
{
1327
// Convert the texture to ARGB 4444
1328
if (LOWORD(result) == GR_TEXFMT_ARGB_1555)
1329
TexConv_ARGB1555_ARGB4444 (tex1, tex2, real_x, real_y);
1330
if (LOWORD(result) == GR_TEXFMT_ALPHA_INTENSITY_88)
1331
TexConv_AI88_ARGB4444 (tex1, tex2, real_x, real_y);
1332
if (LOWORD(result) == GR_TEXFMT_ALPHA_INTENSITY_44)
1333
TexConv_AI44_ARGB4444 (tex1, tex2, real_x, real_y);
1334
if (LOWORD(result) == GR_TEXFMT_ALPHA_8)
1335
TexConv_A8_ARGB4444 (tex1, tex2, real_x, real_y);
1336
if (LOWORD(result) == GR_TEXFMT_ARGB_4444)
1337
memcpy (tex2, tex1, (real_x*real_y) << 1);
1338
texture = tex2;
1339
result = (1 << 16) | GR_TEXFMT_ARGB_4444;
1340
1341
// Now convert the color to the same
1342
modcolor = ((modcolor & 0xF0000000) >> 16) | ((modcolor & 0x00F00000) >> 12) |
1343
((modcolor & 0x0000F000) >> 8) | ((modcolor & 0x000000F0) >> 4);
1344
modcolor1 = ((modcolor1 & 0xF0000000) >> 16) | ((modcolor1 & 0x00F00000) >> 12) |
1345
((modcolor1 & 0x0000F000) >> 8) | ((modcolor1 & 0x000000F0) >> 4);
1346
modcolor2 = ((modcolor2 & 0xF0000000) >> 16) | ((modcolor2 & 0x00F00000) >> 12) |
1347
((modcolor2 & 0x0000F000) >> 8) | ((modcolor2 & 0x000000F0) >> 4);
1348
1349
int size = (real_x * real_y) << 1;
1350
1351
switch (mod)
1352
{
1353
case TMOD_TEX_INTER_COLOR_USING_FACTOR:
1354
mod_tex_inter_color_using_factor ((WORD*)tex2, size, modcolor, modfactor);
1355
break;
1356
case TMOD_TEX_INTER_COL_USING_COL1:
1357
mod_tex_inter_col_using_col1 ((WORD*)tex2, size, modcolor, modcolor1);
1358
break;
1359
case TMOD_FULL_COLOR_SUB_TEX:
1360
mod_full_color_sub_tex ((WORD*)tex2, size, modcolor);
1361
break;
1362
case TMOD_COL_INTER_COL1_USING_TEX:
1363
mod_col_inter_col1_using_tex ((WORD*)tex2, size, modcolor, modcolor1);
1364
break;
1365
case TMOD_COL_INTER_COL1_USING_TEXA:
1366
mod_col_inter_col1_using_texa ((WORD*)tex2, size, modcolor, modcolor1);
1367
break;
1368
case TMOD_COL_INTER_COL1_USING_TEXA__MUL_TEX:
1369
mod_col_inter_col1_using_texa__mul_tex ((WORD*)tex2, size, modcolor, modcolor1);
1370
break;
1371
case TMOD_COL_INTER_TEX_USING_TEXA:
1372
mod_col_inter_tex_using_texa ((WORD*)tex2, size, modcolor);
1373
break;
1374
case TMOD_COL2_INTER__COL_INTER_COL1_USING_TEX__USING_TEXA:
1375
mod_col2_inter__col_inter_col1_using_tex__using_texa ((WORD*)tex2, size, modcolor, modcolor1, modcolor2);
1376
break;
1377
case TMOD_TEX_SCALE_FAC_ADD_FAC:
1378
mod_tex_scale_fac_add_fac ((WORD*)tex2, size, modfactor);
1379
break;
1380
case TMOD_TEX_SUB_COL_MUL_FAC_ADD_TEX:
1381
mod_tex_sub_col_mul_fac_add_tex ((WORD*)tex2, size, modcolor, modfactor);
1382
break;
1383
case TMOD_TEX_SCALE_COL_ADD_COL:
1384
mod_tex_scale_col_add_col ((WORD*)tex2, size, modcolor, modfactor);
1385
break;
1386
case TMOD_TEX_ADD_COL:
1387
mod_tex_add_col ((WORD*)tex2, size, modcolor);
1388
break;
1389
case TMOD_TEX_SUB_COL:
1390
mod_tex_sub_col ((WORD*)tex2, size, modcolor);
1391
break;
1392
case TMOD_TEX_SUB_COL_MUL_FAC:
1393
mod_tex_sub_col_mul_fac ((WORD*)tex2, size, modcolor, modfactor);
1394
break;
1395
case TMOD_COL_INTER_TEX_USING_COL1:
1396
mod_col_inter_tex_using_col1 ((WORD*)tex2, size, modcolor, modcolor1);
1397
break;
1398
case TMOD_COL_MUL_TEXA_ADD_TEX:
1399
mod_col_mul_texa_add_tex((WORD*)tex2, size, modcolor);
1400
break;
1401
case TMOD_COL_INTER_TEX_USING_TEX:
1402
mod_col_inter_tex_using_tex ((WORD*)tex2, size, modcolor);
1403
break;
1404
case TMOD_TEX_INTER_NOISE_USING_COL:
1405
mod_tex_inter_noise_using_col ((WORD*)tex2, size, modcolor);
1406
break;
1407
case TMOD_TEX_INTER_COL_USING_TEXA:
1408
mod_tex_inter_col_using_texa ((WORD*)tex2, size, modcolor);
1409
break;
1410
case TMOD_TEX_MUL_COL:
1411
mod_tex_mul_col ((WORD*)tex2, size, modcolor);
1412
break;
1413
case TMOD_TEX_SCALE_FAC_ADD_COL:
1414
mod_tex_scale_fac_add_col ((WORD*)tex2, size, modcolor, modfactor);
1415
break;
1416
default:
1417
;
1418
}
1419
}
1420
1421
1422
cache->t_info.format = LOWORD(result);
1423
1424
cache->realwidth = real_x;
1425
cache->realheight = real_y;
1426
cache->lod = lod;
1427
cache->aspect = aspect;
1428
1429
if (fullscreen)
1430
{
1431
// Load the texture into texture memory
1432
GrTexInfo *t_info = &cache->t_info;
1433
t_info->data = texture;
1434
t_info->smallLodLog2 = lod;
1435
t_info->largeLodLog2 = lod;
1436
t_info->aspectRatioLog2 = aspect;
1437
1438
DWORD texture_size = grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, t_info);
1439
1440
// Check for 2mb boundary
1441
if ((rdp.tmem_ptr[tmu] < TEXMEM_2MB_EDGE) && (rdp.tmem_ptr[tmu]+texture_size > TEXMEM_2MB_EDGE))
1442
{
1443
rdp.tmem_ptr[tmu] = TEXMEM_2MB_EDGE;
1444
cache->tmem_addr = rdp.tmem_ptr[tmu];
1445
}
1446
1447
// Check for end of memory (too many textures to fit, clear cache)
1448
if (rdp.tmem_ptr[tmu]+texture_size >= grTexMaxAddress(tmu))
1449
{
1450
RDP ("Cache size reached, clearing...\n");
1451
ClearCache ();
1452
1453
if (id == 1 && rdp.tex == 3)
1454
LoadTex (0, rdp.t0);
1455
1456
LoadTex (id, tmu);
1457
return;
1458
// DON'T CONTINUE (already done)
1459
}
1460
1461
grTexDownloadMipMap (tmu,
1462
grTexMinAddress(tmu) + rdp.tmem_ptr[tmu],
1463
GR_MIPMAPLEVELMASK_BOTH,
1464
t_info);
1465
1466
grTexSource (tmu,
1467
grTexMinAddress(tmu) + rdp.tmem_ptr[tmu],
1468
GR_MIPMAPLEVELMASK_BOTH,
1469
t_info);
1470
rdp.tmem_ptr[tmu] += texture_size;
1471
}
1472
1473
RDP (" | | +- LoadTex end\n");
1474
}
1475
1476
1477