Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glide64 / TexCache.cpp
CommitLineData
98e75f2d 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
46void LoadTex (int id, int tmu);
47
48wxUint8 tex1[1024*1024*4]; // temporary texture
49wxUint8 tex2[1024*1024*4];
50wxUint8 *texture;
51wxUint8 *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 <koolsmoky@users.sourceforge.net>
62extern int ghq_dmptex_toggle_key;
63#endif
64
65typedef 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
79TEXINFO texinfo[2];
80int tex_found[2][MAX_TMU];
81
82#ifdef TEXTURE_FILTER
83typedef struct HIRESTEX_t {
84 int width, height;
85 wxUint16 format;
86 wxUint8 *data;
87} HIRESTEX;
88#endif
89
90//****************************************************************
91// List functions
92
93typedef struct NODE_t {
94 wxUint32 crc;
95 wxUIntPtr data;
96 int tmu;
97 int number;
98 NODE_t *pNext;
99} NODE;
100
101NODE *cachelut[65536];
102
103void 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
117void DeleteList (NODE **list)
118{
119 while (*list)
120 {
121 NODE *next = (*list)->pNext;
122 delete (*list);
123 *list = next;
124 }
125}
126
127void 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
138void 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//****************************************************************
152uint32_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
174void 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
499int 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
516static 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
524int SwapTextureBuffer();
525void TexCache ()
526{
527 LRDP(" |-+ TexCache called\n");
528
529#ifdef TEXTURE_FILTER /* Hiroshi Morii <koolsmoky@users.sourceforge.net> */ // 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 */
966inline wxUint32 CalculateDXT(wxUint32 txl2words)
967{
968 if( txl2words == 0 ) return 1;
969 else return (2048+txl2words-1)/txl2words;
970}
971
972wxUint32 sizeBytes[4] = {0,1,2,4};
973
974inline 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
982inline 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
1006void 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 <koolsmoky@users.sourceforge.net>
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 <koolsmoky@users.sourceforge.net>
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 <koolsmoky@users.sourceoforge.net>
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 <koolsmoky@users.sourceforge.net>
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 <koolsmoky@users.sourceforge.net> 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}