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 | |
46 | void LoadTex (int id, int tmu); |
47 | |
48 | wxUint8 tex1[1024*1024*4]; // temporary texture |
49 | wxUint8 tex2[1024*1024*4]; |
50 | wxUint8 *texture; |
51 | wxUint8 *texture_buffer = tex1; |
52 | |
53 | #include "TexLoad.h" // texture loading functions, ONLY INCLUDE IN THIS FILE!!! |
54 | #include "MiClWr32b.h" |
55 | #include "MiClWr16b.h" // Mirror/Clamp/Wrap functions, ONLY INCLUDE IN THIS FILE!!! |
56 | #include "MiClWr8b.h" // Mirror/Clamp/Wrap functions, ONLY INCLUDE IN THIS FILE!!! |
57 | #include "TexConv.h" // texture conversions, ONLY INCLUDE IN THIS FILE!!! |
58 | #include "TexMod.h" |
59 | #include "TexModCI.h" |
60 | #include "CRC.h" |
61 | #ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net> |
62 | extern int ghq_dmptex_toggle_key; |
63 | #endif |
64 | |
65 | typedef struct TEXINFO_t { |
66 | int real_image_width, real_image_height; // FOR ALIGNMENT PURPOSES ONLY!!! |
67 | int tile_width, tile_height; |
68 | int mask_width, mask_height; |
69 | int width, height; |
70 | int wid_64, line; |
71 | wxUint32 crc; |
72 | wxUint32 flags; |
73 | int splits, splitheight; |
74 | #ifdef TEXTURE_FILTER |
75 | uint64 ricecrc; |
76 | #endif |
77 | } TEXINFO; |
78 | |
79 | TEXINFO texinfo[2]; |
80 | int tex_found[2][MAX_TMU]; |
81 | |
82 | #ifdef TEXTURE_FILTER |
83 | typedef struct HIRESTEX_t { |
84 | int width, height; |
85 | wxUint16 format; |
86 | wxUint8 *data; |
87 | } HIRESTEX; |
88 | #endif |
89 | |
90 | //**************************************************************** |
91 | // List functions |
92 | |
93 | typedef struct NODE_t { |
94 | wxUint32 crc; |
95 | wxUIntPtr data; |
96 | int tmu; |
97 | int number; |
98 | NODE_t *pNext; |
99 | } NODE; |
100 | |
101 | NODE *cachelut[65536]; |
102 | |
103 | void AddToList (NODE **list, wxUint32 crc, wxUIntPtr data, int tmu, int number) |
104 | { |
105 | NODE *node = new NODE; |
106 | node->crc = crc; |
107 | node->data = data; |
108 | node->tmu = tmu; |
109 | node->number = number; |
110 | node->pNext = *list; |
111 | *list = node; |
112 | rdp.n_cached[tmu] ++; |
113 | if (voodoo.tex_UMA) |
114 | rdp.n_cached[tmu^1] = rdp.n_cached[tmu]; |
115 | } |
116 | |
117 | void DeleteList (NODE **list) |
118 | { |
119 | while (*list) |
120 | { |
121 | NODE *next = (*list)->pNext; |
122 | delete (*list); |
123 | *list = next; |
124 | } |
125 | } |
126 | |
127 | void TexCacheInit () |
128 | { |
129 | for (int i=0; i<65536; i++) |
130 | { |
131 | cachelut[i] = NULL; |
132 | } |
133 | } |
134 | |
135 | //**************************************************************** |
136 | // ClearCache - clear the texture cache for BOTH tmus |
137 | |
138 | void ClearCache () |
139 | { |
140 | voodoo.tmem_ptr[0] = offset_textures; |
141 | rdp.n_cached[0] = 0; |
142 | voodoo.tmem_ptr[1] = voodoo.tex_UMA ? offset_textures : offset_texbuf1; |
143 | rdp.n_cached[1] = 0; |
144 | |
145 | for (int i=0; i<65536; i++) |
146 | { |
147 | DeleteList (&cachelut[i]); |
148 | } |
149 | } |
150 | |
151 | //**************************************************************** |
152 | uint32_t textureCRC(uint8_t *addr, int width, int height, int line) |
153 | { |
154 | uint32_t crc = 0; |
155 | uint32_t *pixelpos; |
156 | unsigned int i; |
157 | uint64_t twopixel_crc; |
158 | |
159 | pixelpos = (uint32_t*)addr; |
160 | for (; height; height--) { |
161 | for (i = width; i; --i) { |
162 | twopixel_crc = i * (uint64_t)(pixelpos[1] + pixelpos[0] + crc); |
163 | crc = (uint32_t) ((twopixel_crc >> 32) + twopixel_crc); |
164 | pixelpos += 2; |
165 | } |
166 | crc = ((unsigned int)height * (uint64_t)crc >> 32) + height * crc; |
167 | pixelpos = (uint32_t *)((char *)pixelpos + line); |
168 | } |
169 | |
170 | return crc; |
171 | } |
172 | // GetTexInfo - gets information for either t0 or t1, checks if in cache & fills tex_found |
173 | |
174 | void GetTexInfo (int id, int tile) |
175 | { |
176 | FRDP (" | |-+ GetTexInfo (id: %d, tile: %d)\n", id, tile); |
177 | |
178 | // this is the NEW cache searching, searches only textures with similar crc's |
179 | int t; |
180 | for (t=0; t<MAX_TMU; t++) |
181 | tex_found[id][t] = -1; |
182 | |
183 | TBUFF_COLOR_IMAGE * pFBTex = 0; |
184 | if (rdp.aTBuffTex[0] && rdp.aTBuffTex[0]->tile == id) |
185 | pFBTex = rdp.aTBuffTex[0]; |
186 | else if (rdp.aTBuffTex[1] && rdp.aTBuffTex[1]->tile == id) |
187 | pFBTex = rdp.aTBuffTex[1]; |
188 | if (pFBTex && pFBTex->cache) |
189 | return; |
190 | |
191 | TEXINFO *info = &texinfo[id]; |
192 | |
193 | int tile_width, tile_height; |
194 | int mask_width, mask_height; |
195 | int width, height; |
196 | int wid_64, line, bpl; |
197 | |
198 | // Get width and height |
199 | tile_width = rdp.tiles[tile].lr_s - rdp.tiles[tile].ul_s + 1; |
200 | tile_height = rdp.tiles[tile].lr_t - rdp.tiles[tile].ul_t + 1; |
201 | |
202 | mask_width = (rdp.tiles[tile].mask_s==0)?(tile_width):(1 << rdp.tiles[tile].mask_s); |
203 | mask_height = (rdp.tiles[tile].mask_t==0)?(tile_height):(1 << rdp.tiles[tile].mask_t); |
204 | |
205 | if (settings.alt_tex_size) |
206 | { |
207 | // ** ALTERNATE TEXTURE SIZE METHOD ** |
208 | // Helps speed in some games that loaded weird-sized textures, but could break other |
209 | // textures. |
210 | |
211 | // Get the width/height to load |
212 | if ((rdp.tiles[tile].clamp_s && tile_width <= 256) || (mask_width > 256)) |
213 | { |
214 | // loading width |
215 | width = min(mask_width, tile_width); |
216 | // actual width |
217 | rdp.tiles[tile].width = tile_width; |
218 | } |
219 | else |
220 | { |
221 | // wrap all the way |
222 | width = min(mask_width, tile_width); // changed from mask_width only |
223 | rdp.tiles[tile].width = width; |
224 | } |
225 | |
226 | if ((rdp.tiles[tile].clamp_t && tile_height <= 256) || (mask_height > 256)) |
227 | { |
228 | // loading height |
229 | height = min(mask_height, tile_height); |
230 | // actual height |
231 | rdp.tiles[tile].height = tile_height; |
232 | } |
233 | else |
234 | { |
235 | // wrap all the way |
236 | height = min(mask_height, tile_height); |
237 | rdp.tiles[tile].height = height; |
238 | } |
239 | } |
240 | else |
241 | { |
242 | // ** NORMAL TEXTURE SIZE METHOD ** |
243 | // This is the 'correct' method for determining texture size, but may cause certain |
244 | // textures to load too large & make the whole game go slow. |
245 | |
246 | if (mask_width > 256 && mask_height > 256) |
247 | { |
248 | mask_width = tile_width; |
249 | mask_height = tile_height; |
250 | } |
251 | |
252 | // Get the width/height to load |
253 | if ((rdp.tiles[tile].clamp_s && tile_width <= 256) )//|| (mask_width > 256)) |
254 | { |
255 | // loading width |
256 | width = min(mask_width, tile_width); |
257 | // actual width |
258 | rdp.tiles[tile].width = tile_width; |
259 | } |
260 | else |
261 | { |
262 | // wrap all the way |
263 | width = mask_width; |
264 | rdp.tiles[tile].width = mask_width; |
265 | } |
266 | |
267 | if ((rdp.tiles[tile].clamp_t && tile_height <= 256) || (mask_height > 256)) |
268 | { |
269 | // loading height |
270 | height = min(mask_height, tile_height); |
271 | // actual height |
272 | rdp.tiles[tile].height = tile_height; |
273 | } |
274 | else |
275 | { |
276 | // wrap all the way |
277 | height = mask_height; |
278 | rdp.tiles[tile].height = mask_height; |
279 | } |
280 | } |
281 | |
282 | // without any large texture fixing-up; for alignment |
283 | int real_image_width = rdp.tiles[tile].width; |
284 | int real_image_height = rdp.tiles[tile].height; |
285 | int crc_height = height; |
286 | if (rdp.timg.set_by == 1) |
287 | crc_height = tile_height; |
288 | |
289 | bpl = width << rdp.tiles[tile].size >> 1; |
290 | |
291 | // ** COMMENT THIS TO DISABLE LARGE TEXTURES |
292 | #ifdef LARGE_TEXTURE_HANDLING |
293 | if (!voodoo.sup_large_tex && width > 256) |
294 | { |
295 | info->splits = ((width-1)>>8)+1; |
296 | info->splitheight = rdp.tiles[tile].height; |
297 | rdp.tiles[tile].height *= info->splits; |
298 | rdp.tiles[tile].width = 256; |
299 | width = 256; |
300 | } |
301 | else |
302 | #endif |
303 | // ** |
304 | { |
305 | info->splits = 1; |
306 | } |
307 | |
308 | LRDP(" | | |-+ Texture approved:\n"); |
309 | FRDP (" | | | |- tmem: %08lx\n", rdp.tiles[tile].t_mem); |
310 | FRDP (" | | | |- load width: %d\n", width); |
311 | FRDP (" | | | |- load height: %d\n", height); |
312 | FRDP (" | | | |- actual width: %d\n", rdp.tiles[tile].width); |
313 | FRDP (" | | | |- actual height: %d\n", rdp.tiles[tile].height); |
314 | FRDP (" | | | |- size: %d\n", rdp.tiles[tile].size); |
315 | FRDP (" | | | +- format: %d\n", rdp.tiles[tile].format); |
316 | LRDP(" | | |- Calculating CRC... "); |
317 | |
318 | // ** CRC CHECK |
319 | |
320 | wid_64 = width << (rdp.tiles[tile].size) >> 1; |
321 | if (rdp.tiles[tile].size == 3) |
322 | { |
323 | if (wid_64 & 15) wid_64 += 16; |
324 | wid_64 &= 0xFFFFFFF0; |
325 | } |
326 | else |
327 | { |
328 | if (wid_64 & 7) wid_64 += 8; // round up |
329 | } |
330 | wid_64 = wid_64>>3; |
331 | |
332 | // Texture too big for tmem & needs to wrap? (trees in mm) |
333 | if (rdp.tiles[tile].t_mem + min(height, tile_height) * (rdp.tiles[tile].line<<3) > 4096) |
334 | { |
335 | LRDP("TEXTURE WRAPS TMEM!!! "); |
336 | |
337 | // calculate the y value that intersects at 4096 bytes |
338 | int y = (4096 - rdp.tiles[tile].t_mem) / (rdp.tiles[tile].line<<3); |
339 | |
340 | rdp.tiles[tile].clamp_t = 0; |
341 | rdp.tiles[tile].lr_t = rdp.tiles[tile].ul_t + y - 1; |
342 | |
343 | // calc mask |
344 | int shift; |
345 | for (shift=0; (1<<shift)<y; shift++); |
346 | rdp.tiles[tile].mask_t = shift; |
347 | |
348 | // restart the function |
349 | LRDP("restarting...\n"); |
350 | GetTexInfo (id, tile); |
351 | return; |
352 | } |
353 | |
354 | line = rdp.tiles[tile].line; |
355 | if (rdp.tiles[tile].size == 3) |
356 | line <<= 1; |
357 | wxUint32 crc = 0; |
358 | if (settings.fast_crc) |
359 | { |
360 | line = (line - wid_64) << 3; |
361 | if (wid_64 < 1) wid_64 = 1; |
362 | uint8_t * addr = (((uint8_t*)rdp.tmem) + (rdp.tiles[tile].t_mem<<3)); |
363 | if (crc_height > 0) // Check the CRC |
364 | { |
365 | if (rdp.tiles[tile].size < 3) |
366 | crc = textureCRC(addr, wid_64, crc_height, line); |
367 | else //32b texture |
368 | { |
369 | int line_2 = line >> 1; |
370 | int wid_64_2 = max(1, wid_64 >> 1); |
371 | crc = textureCRC(addr, wid_64_2, crc_height, line_2); |
372 | crc += textureCRC(addr+0x800, wid_64_2, crc_height, line_2); |
373 | } |
374 | } |
375 | } |
376 | else |
377 | { |
378 | crc = 0xFFFFFFFF; |
379 | wxUIntPtr addr = wxPtrToUInt(rdp.tmem) + (rdp.tiles[tile].t_mem<<3); |
380 | wxUint32 line2 = max(line,1); |
381 | if (rdp.tiles[tile].size < 3) |
382 | { |
383 | line2 <<= 3; |
384 | for (int y = 0; y < crc_height; y++) |
385 | { |
386 | crc = CRC32( crc, reinterpret_cast<void*>(addr), bpl ); |
387 | addr += line2; |
388 | } |
389 | } |
390 | else //32b texture |
391 | { |
392 | line2 <<= 2; |
393 | //32b texel is split in two 16b parts, so bpl/2 and line/2. |
394 | //Min value for bpl is 4, because when width==1 first 2 bytes of tmem will not be used. |
395 | bpl = max(bpl >> 1, 4); |
396 | for (int y = 0; y < crc_height; y++) |
397 | { |
398 | crc = CRC32( crc, reinterpret_cast<void*>(addr), bpl); |
399 | crc = CRC32( crc, reinterpret_cast<void*>(addr + 0x800), bpl); |
400 | addr += line2; |
401 | } |
402 | } |
403 | line = (line - wid_64) << 3; |
404 | if (wid_64 < 1) wid_64 = 1; |
405 | } |
406 | if ((rdp.tiles[tile].size < 2) && (rdp.tlut_mode || rdp.tiles[tile].format == 2)) |
407 | { |
408 | if (rdp.tiles[tile].size == 0) |
409 | crc += rdp.pal_8_crc[rdp.tiles[tile].palette]; |
410 | else |
411 | crc += rdp.pal_256_crc; |
412 | } |
413 | |
414 | FRDP ("Done. CRC is: %08lx.\n", crc); |
415 | |
416 | wxUint32 flags = (rdp.tiles[tile].clamp_s << 23) | (rdp.tiles[tile].mirror_s << 22) | |
417 | (rdp.tiles[tile].mask_s << 18) | (rdp.tiles[tile].clamp_t << 17) | |
418 | (rdp.tiles[tile].mirror_t << 16) | (rdp.tiles[tile].mask_t << 12); |
419 | |
420 | info->real_image_width = real_image_width; |
421 | info->real_image_height = real_image_height; |
422 | info->tile_width = tile_width; |
423 | info->tile_height = tile_height; |
424 | info->mask_width = mask_width; |
425 | info->mask_height = mask_height; |
426 | info->width = width; |
427 | info->height = height; |
428 | info->wid_64 = wid_64; |
429 | info->line = line; |
430 | info->crc = crc; |
431 | info->flags = flags; |
432 | |
433 | // Search the texture cache for this texture |
434 | LRDP(" | | |-+ Checking cache...\n"); |
435 | |
436 | CACHE_LUT *cache; |
437 | |
438 | if (rdp.noise == RDP::noise_texture) |
439 | return; |
440 | |
441 | wxUint32 mod, modcolor, modcolor1, modcolor2, modfactor; |
442 | if (id == 0) |
443 | { |
444 | mod = cmb.mod_0; |
445 | modcolor = cmb.modcolor_0; |
446 | modcolor1 = cmb.modcolor1_0; |
447 | modcolor2 = cmb.modcolor2_0; |
448 | modfactor = cmb.modfactor_0; |
449 | } |
450 | else |
451 | { |
452 | mod = cmb.mod_1; |
453 | modcolor = cmb.modcolor_1; |
454 | modcolor1 = cmb.modcolor1_1; |
455 | modcolor2 = cmb.modcolor2_1; |
456 | modfactor = cmb.modfactor_1; |
457 | } |
458 | |
459 | NODE *node = cachelut[crc>>16]; |
460 | wxUint32 mod_mask = (rdp.tiles[tile].format == 2)?0xFFFFFFFF:0xF0F0F0F0; |
461 | while (node) |
462 | { |
463 | if (node->crc == crc) |
464 | { |
465 | cache = (CACHE_LUT*)node->data; |
466 | if (/*tex_found[id][node->tmu] == -1 && |
467 | rdp.tiles[tile].palette == cache->palette && |
468 | rdp.tiles[tile].format == cache->format && |
469 | rdp.tiles[tile].size == cache->size &&*/ |
470 | rdp.tiles[tile].width == cache->width && |
471 | rdp.tiles[tile].height == cache->height && |
472 | flags == cache->flags) |
473 | { |
474 | if (!(mod+cache->mod) || (cache->mod == mod && |
475 | (cache->mod_color&mod_mask) == (modcolor&mod_mask) && |
476 | (cache->mod_color1&mod_mask) == (modcolor1&mod_mask) && |
477 | (cache->mod_color2&mod_mask) == (modcolor2&mod_mask) && |
478 | abs((int)(cache->mod_factor - modfactor)) < 8)) |
479 | { |
480 | FRDP (" | | | |- Texture found in cache (tmu=%d).\n", node->tmu); |
481 | tex_found[id][node->tmu] = node->number; |
482 | if (voodoo.tex_UMA) |
483 | { |
484 | tex_found[id][node->tmu^1] = node->number; |
485 | return; |
486 | } |
487 | } |
488 | } |
489 | } |
490 | node = node->pNext; |
491 | } |
492 | |
493 | LRDP(" | | | +- Done.\n | | +- GetTexInfo end\n"); |
494 | } |
495 | |
496 | //**************************************************************** |
497 | // ChooseBestTmu - chooses the best TMU to load to (the one with the most memory) |
498 | |
499 | int ChooseBestTmu (int tmu1, int tmu2) |
500 | { |
501 | if (!fullscreen) return tmu1; |
502 | if (voodoo.tex_UMA) return 0; |
503 | |
504 | if (tmu1 >= voodoo.num_tmu) return tmu2; |
505 | if (tmu2 >= voodoo.num_tmu) return tmu1; |
506 | |
507 | if (voodoo.tex_max_addr[tmu1]-voodoo.tmem_ptr[tmu1] > |
508 | voodoo.tex_max_addr[tmu2]-voodoo.tmem_ptr[tmu2]) |
509 | return tmu1; |
510 | else |
511 | return tmu2; |
512 | } |
513 | |
514 | //**************************************************************** |
515 | // SelectTBuffTex - select texture from texture buffer |
516 | static void SelectTBuffTex(TBUFF_COLOR_IMAGE * pTBuffTex) |
517 | { |
518 | FRDP ("SelectTBuffTex: tex: %d, tmu: %d, tile: %d\n", rdp.tex, pTBuffTex->tmu, pTBuffTex->tile); |
519 | grTexSource(pTBuffTex->tile, pTBuffTex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(pTBuffTex->info) ); |
520 | } |
521 | |
522 | //**************************************************************** |
523 | // TexCache - does texture loading after combiner is set |
524 | int SwapTextureBuffer(); |
525 | void TexCache () |
526 | { |
527 | LRDP(" |-+ TexCache called\n"); |
528 | |
529 | #ifdef TEXTURE_FILTER /* Hiroshi Morii <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 */ |
966 | inline wxUint32 CalculateDXT(wxUint32 txl2words) |
967 | { |
968 | if( txl2words == 0 ) return 1; |
969 | else return (2048+txl2words-1)/txl2words; |
970 | } |
971 | |
972 | wxUint32 sizeBytes[4] = {0,1,2,4}; |
973 | |
974 | inline wxUint32 Txl2Words(wxUint32 width, wxUint32 size) |
975 | { |
976 | if( size == 0 ) |
977 | return max(1, width/16); |
978 | else |
979 | return max(1, width*sizeBytes[size]/8); |
980 | } |
981 | |
982 | inline wxUint32 ReverseDXT(wxUint32 val, wxUint32 lrs, wxUint32 width, wxUint32 size) |
983 | { |
984 | if( val == 0x800 ) return 1; |
985 | |
986 | int low = 2047/val; |
987 | if( CalculateDXT(low) > val ) low++; |
988 | int high = 2047/(val-1); |
989 | |
990 | if( low == high ) return low; |
991 | |
992 | for( int i=low; i<=high; i++ ) |
993 | { |
994 | if( Txl2Words(width, size) == (wxUint32)i ) |
995 | return i; |
996 | } |
997 | |
998 | return (low+high)/2; |
999 | } |
1000 | /** end RiceVideo cite */ |
1001 | #endif |
1002 | |
1003 | //**************************************************************** |
1004 | // LoadTex - does the actual texture loading after everything is prepared |
1005 | |
1006 | void LoadTex (int id, int tmu) |
1007 | { |
1008 | FRDP (" | |-+ LoadTex (id: %d, tmu: %d)\n", id, tmu); |
1009 | |
1010 | int td = rdp.cur_tile + id; |
1011 | int lod, aspect; |
1012 | CACHE_LUT *cache; |
1013 | |
1014 | if (texinfo[id].width < 0 || texinfo[id].height < 0) |
1015 | return; |
1016 | |
1017 | // Clear the cache if it's full |
1018 | if (rdp.n_cached[tmu] >= MAX_CACHE) |
1019 | { |
1020 | LRDP("Cache count reached, clearing...\n"); |
1021 | ClearCache (); |
1022 | if (id == 1 && rdp.tex == 3) |
1023 | LoadTex (0, rdp.t0); |
1024 | } |
1025 | |
1026 | // Get this cache object |
1027 | cache = voodoo.tex_UMA?&rdp.cache[0][rdp.n_cached[0]]:&rdp.cache[tmu][rdp.n_cached[tmu]]; |
1028 | rdp.cur_cache[id] = cache; |
1029 | rdp.cur_cache_n[id] = rdp.n_cached[tmu]; |
1030 | |
1031 | //!Hackalert |
1032 | //GoldenEye water texture. It has CI format in fact, but the game set it to RGBA |
1033 | if ((settings.hacks&hack_GoldenEye) && rdp.tiles[td].format == 0 && rdp.tlut_mode == 2 && rdp.tiles[td].size == 2) |
1034 | { |
1035 | rdp.tiles[td].format = 2; |
1036 | rdp.tiles[td].size = 1; |
1037 | } |
1038 | |
1039 | // Set the data |
1040 | cache->line = rdp.tiles[td].line; |
1041 | cache->addr = rdp.addr[rdp.tiles[td].t_mem]; |
1042 | cache->crc = texinfo[id].crc; |
1043 | cache->palette = rdp.tiles[td].palette; |
1044 | cache->width = rdp.tiles[td].width; |
1045 | cache->height = rdp.tiles[td].height; |
1046 | cache->format = rdp.tiles[td].format; |
1047 | cache->size = rdp.tiles[td].size; |
1048 | cache->tmem_addr = voodoo.tmem_ptr[tmu]; |
1049 | cache->set_by = rdp.timg.set_by; |
1050 | cache->texrecting = rdp.texrecting; |
1051 | cache->last_used = frame_count; |
1052 | cache->uses = rdp.debug_n; |
1053 | cache->flags = texinfo[id].flags; |
1054 | cache->f_mirror_s = FALSE; |
1055 | cache->f_mirror_t = FALSE; |
1056 | cache->f_wrap_s = FALSE; |
1057 | cache->f_wrap_t = FALSE; |
1058 | #ifdef TEXTURE_FILTER |
1059 | cache->is_hires_tex = FALSE; |
1060 | cache->ricecrc = texinfo[id].ricecrc; |
1061 | #endif |
1062 | |
1063 | // Add this cache to the list |
1064 | AddToList (&cachelut[cache->crc>>16], cache->crc, wxPtrToUInt(cache), tmu, rdp.n_cached[tmu]); |
1065 | |
1066 | // temporary |
1067 | cache->t_info.format = GR_TEXFMT_ARGB_1555; |
1068 | |
1069 | // Calculate lod and aspect |
1070 | wxUint32 size_x = rdp.tiles[td].width; |
1071 | wxUint32 size_y = rdp.tiles[td].height; |
1072 | |
1073 | // make size_x and size_y both powers of two |
1074 | if (!voodoo.sup_large_tex) |
1075 | { |
1076 | if (size_x > 256) size_x = 256; |
1077 | if (size_y > 256) size_y = 256; |
1078 | } |
1079 | |
1080 | int shift; |
1081 | for (shift=0; (1<<shift) < (int)size_x; shift++); |
1082 | size_x = 1 << shift; |
1083 | for (shift=0; (1<<shift) < (int)size_y; shift++); |
1084 | size_y = 1 << shift; |
1085 | |
1086 | // Voodoo 1 support is all here, it will automatically mirror to the full extent. |
1087 | if (!voodoo.sup_mirroring) |
1088 | { |
1089 | if (rdp.tiles[td].mirror_s && !rdp.tiles[td].clamp_s && (voodoo.sup_large_tex || size_x <= 128)) |
1090 | size_x <<= 1; |
1091 | if (rdp.tiles[td].mirror_t && !rdp.tiles[td].clamp_t && (voodoo.sup_large_tex || size_y <= 128)) |
1092 | size_y <<= 1; |
1093 | } |
1094 | |
1095 | // Calculate the maximum size |
1096 | int size_max = max (size_x, size_y); |
1097 | wxUint32 real_x=size_max, real_y=size_max; |
1098 | switch (size_max) |
1099 | { |
1100 | case 1: |
1101 | lod = GR_LOD_LOG2_1; |
1102 | cache->scale = 256.0f; |
1103 | break; |
1104 | case 2: |
1105 | lod = GR_LOD_LOG2_2; |
1106 | cache->scale = 128.0f; |
1107 | break; |
1108 | case 4: |
1109 | lod = GR_LOD_LOG2_4; |
1110 | cache->scale = 64.0f; |
1111 | break; |
1112 | case 8: |
1113 | lod = GR_LOD_LOG2_8; |
1114 | cache->scale = 32.0f; |
1115 | break; |
1116 | case 16: |
1117 | lod = GR_LOD_LOG2_16; |
1118 | cache->scale = 16.0f; |
1119 | break; |
1120 | case 32: |
1121 | lod = GR_LOD_LOG2_32; |
1122 | cache->scale = 8.0f; |
1123 | break; |
1124 | case 64: |
1125 | lod = GR_LOD_LOG2_64; |
1126 | cache->scale = 4.0f; |
1127 | break; |
1128 | case 128: |
1129 | lod = GR_LOD_LOG2_128; |
1130 | cache->scale = 2.0f; |
1131 | break; |
1132 | case 256: |
1133 | lod = GR_LOD_LOG2_256; |
1134 | cache->scale = 1.0f; |
1135 | break; |
1136 | case 512: |
1137 | lod = GR_LOD_LOG2_512; |
1138 | cache->scale = 0.5f; |
1139 | break; |
1140 | default: |
1141 | lod = GR_LOD_LOG2_1024; |
1142 | cache->scale = 0.25f; |
1143 | break; |
1144 | } |
1145 | |
1146 | // Calculate the aspect ratio |
1147 | if (size_x >= size_y) |
1148 | { |
1149 | int ratio = size_x / size_y; |
1150 | switch (ratio) |
1151 | { |
1152 | case 1: |
1153 | aspect = GR_ASPECT_LOG2_1x1; |
1154 | cache->scale_x = 1.0f; |
1155 | cache->scale_y = 1.0f; |
1156 | break; |
1157 | case 2: |
1158 | aspect = GR_ASPECT_LOG2_2x1; |
1159 | cache->scale_x = 1.0f; |
1160 | cache->scale_y = 0.5f; |
1161 | real_y >>= 1; |
1162 | break; |
1163 | case 4: |
1164 | aspect = GR_ASPECT_LOG2_4x1; |
1165 | cache->scale_x = 1.0f; |
1166 | cache->scale_y = 0.25f; |
1167 | real_y >>= 2; |
1168 | break; |
1169 | default: |
1170 | aspect = GR_ASPECT_LOG2_8x1; |
1171 | cache->scale_x = 1.0f; |
1172 | cache->scale_y = 0.125f; |
1173 | real_y >>= 3; |
1174 | break; |
1175 | } |
1176 | } |
1177 | else |
1178 | { |
1179 | int ratio = size_y / size_x; |
1180 | switch (ratio) |
1181 | { |
1182 | case 2: |
1183 | aspect = GR_ASPECT_LOG2_1x2; |
1184 | cache->scale_x = 0.5f; |
1185 | cache->scale_y = 1.0f; |
1186 | real_x >>= 1; |
1187 | break; |
1188 | case 4: |
1189 | aspect = GR_ASPECT_LOG2_1x4; |
1190 | cache->scale_x = 0.25f; |
1191 | cache->scale_y = 1.0f; |
1192 | real_x >>= 2; |
1193 | break; |
1194 | default: |
1195 | aspect = GR_ASPECT_LOG2_1x8; |
1196 | cache->scale_x = 0.125f; |
1197 | cache->scale_y = 1.0f; |
1198 | real_x >>= 3; |
1199 | break; |
1200 | } |
1201 | } |
1202 | |
1203 | if (real_x != cache->width || real_y != cache->height) |
1204 | { |
1205 | cache->scale_x *= (float)cache->width / (float)real_x; |
1206 | cache->scale_y *= (float)cache->height / (float)real_y; |
1207 | } |
1208 | |
1209 | int splits = texinfo[id].splits; |
1210 | cache->splits = texinfo[id].splits; |
1211 | cache->splitheight = real_y / cache->splits; |
1212 | if (cache->splitheight < texinfo[id].splitheight) |
1213 | cache->splitheight = texinfo[id].splitheight; |
1214 | |
1215 | // ** Calculate alignment values |
1216 | int wid = cache->width; |
1217 | int hei = cache->height; |
1218 | |
1219 | if (splits > 1) |
1220 | { |
1221 | wid = texinfo[id].real_image_width; |
1222 | hei = texinfo[id].real_image_height; |
1223 | } |
1224 | |
1225 | cache->c_off = cache->scale * 0.5f; |
1226 | if (wid != 1) cache->c_scl_x = cache->scale; |
1227 | else cache->c_scl_x = 0.0f; |
1228 | if (hei != 1) cache->c_scl_y = cache->scale; |
1229 | else cache->c_scl_y = 0.0f; |
1230 | // ** |
1231 | |
1232 | wxUint32 mod, modcolor, modcolor1, modcolor2, modfactor; |
1233 | if (id == 0) |
1234 | { |
1235 | mod = cmb.mod_0; |
1236 | modcolor = cmb.modcolor_0; |
1237 | modcolor1 = cmb.modcolor1_0; |
1238 | modcolor2 = cmb.modcolor2_0; |
1239 | modfactor = cmb.modfactor_0; |
1240 | } |
1241 | else |
1242 | { |
1243 | mod = cmb.mod_1; |
1244 | modcolor = cmb.modcolor_1; |
1245 | modcolor1 = cmb.modcolor1_1; |
1246 | modcolor2 = cmb.modcolor2_1; |
1247 | modfactor = cmb.modfactor_1; |
1248 | } |
1249 | |
1250 | wxUint16 tmp_pal[256]; |
1251 | int modifyPalette = (mod && (cache->format == 2) && (rdp.tlut_mode == 2)); |
1252 | |
1253 | if (modifyPalette) |
1254 | { |
1255 | memcpy(tmp_pal, rdp.pal_8, 512); |
1256 | ModifyPalette(mod, modcolor, modcolor1, modfactor); |
1257 | } |
1258 | |
1259 | cache->mod = mod; |
1260 | cache->mod_color = modcolor; |
1261 | cache->mod_color1 = modcolor1; |
1262 | cache->mod_factor = modfactor; |
1263 | |
1264 | for (int t = 0; t < 2; t++) { |
1265 | if (rdp.aTBuffTex[t] && rdp.aTBuffTex[t]->tile == id) //texture buffer will be used instead of frame buffer texture |
1266 | { |
1267 | rdp.aTBuffTex[t]->cache = cache; |
1268 | FRDP("tbuff_tex selected: %d, tile=%d\n", t, id); |
1269 | return; |
1270 | } |
1271 | } |
1272 | |
1273 | wxUint32 result = 0; // keep =0 so it doesn't mess up on the first split |
1274 | |
1275 | texture = tex1; |
1276 | |
1277 | // Hiroshi Morii <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 | } |