1 #include <stdint.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5
6 #include <retro_miscellaneous.h>
7
8 #include "Common.h"
9 #include "gles2N64.h"
10 #include "N64.h"
11 #include "GBI.h"
12 #include "RSP.h"
13 #include "RDP.h"
14 #include "gDP.h"
15 #include "gSP.h"
16 #include "Debug.h"
17 #include "convert.h"
18 #include "OpenGL.h"
19 #include "CRC.h"
20 #include "FrameBuffer.h"
21 #include "DepthBuffer.h"
22 #include "VI.h"
23 #include "Config.h"
24 #include "ShaderCombiner.h"
25
26 #include "../../Graphics/RDP/gDP_state.h"
27 #include "../../Graphics/RDP/RDP_state.h"
28 #include "../../Graphics/RSP/gSP_state.h"
29
gln64gDPSetOtherMode(uint32_t mode0,uint32_t mode1)30 void gln64gDPSetOtherMode( uint32_t mode0, uint32_t mode1 )
31 {
32 gDP.otherMode.h = mode0;
33 gDP.otherMode.l = mode1;
34
35 gDP.changed |= CHANGED_RENDERMODE | CHANGED_CYCLETYPE;
36 }
37
gln64gDPSetPrimDepth(uint16_t z,uint16_t dz)38 void gln64gDPSetPrimDepth( uint16_t z, uint16_t dz )
39 {
40 if (gSP.viewport.vscale[2] == 0)
41 gDP.primDepth.z = _FIXED2FLOAT(_SHIFTR(z, 0, 15), 15);
42 else
43 gDP.primDepth.z = MIN(1.0f, MAX(-1.0f, (_FIXED2FLOAT(_SHIFTR(z, 0, 15), 15) - gSP.viewport.vtrans[2]) / gSP.viewport.vscale[2]));
44 gDP.primDepth.deltaZ = _FIXED2FLOAT(_SHIFTR(dz, 0, 15), 15);
45 }
46
gln64gDPPipelineMode(uint32_t mode)47 void gln64gDPPipelineMode( uint32_t mode )
48 {
49 gDP.otherMode.pipelineMode = mode;
50 }
51
gln64gDPSetTexturePersp(uint32_t enable)52 void gln64gDPSetTexturePersp( uint32_t enable )
53 {
54 gDP.otherMode.texturePersp = enable & 1;
55 }
56
gln64gDPSetCycleType(uint32_t type)57 void gln64gDPSetCycleType( uint32_t type )
58 {
59 gDP.otherMode.cycleType = type;
60
61 gDP.changed |= CHANGED_CYCLETYPE;
62 }
63
gln64gDPSetTextureDetail(uint32_t type)64 void gln64gDPSetTextureDetail( uint32_t type )
65 {
66 gDP.otherMode.textureDetail = type;
67 }
68
gln64gDPSetTextureLOD(uint32_t mode)69 void gln64gDPSetTextureLOD( uint32_t mode )
70 {
71 gDP.otherMode.textureLOD = mode;
72 }
73
gln64gDPSetTextureLUT(uint32_t mode)74 void gln64gDPSetTextureLUT( uint32_t mode )
75 {
76 gDP.otherMode.textureLUT = mode & 3;
77 }
78
gln64gDPSetTextureFilter(uint32_t type)79 void gln64gDPSetTextureFilter( uint32_t type )
80 {
81 gDP.otherMode.textureFilter = type;
82 }
83
gln64gDPSetTextureConvert(uint32_t type)84 void gln64gDPSetTextureConvert( uint32_t type )
85 {
86 gDP.otherMode.textureConvert = type;
87 }
88
gln64gDPSetCombineKey(uint32_t type)89 void gln64gDPSetCombineKey( uint32_t type )
90 {
91 gDP.otherMode.combineKey = type;
92 }
93
gln64gDPSetColorDither(uint32_t type)94 void gln64gDPSetColorDither( uint32_t type )
95 {
96 gDP.otherMode.colorDither = type;
97 }
98
gln64gDPSetAlphaDither(uint32_t type)99 void gln64gDPSetAlphaDither( uint32_t type )
100 {
101 gDP.otherMode.alphaDither = type;
102 }
103
gln64gDPSetAlphaCompare(uint32_t mode)104 void gln64gDPSetAlphaCompare( uint32_t mode )
105 {
106 gDP.otherMode.alphaCompare = mode;
107
108 gDP.changed |= CHANGED_ALPHACOMPARE;
109 }
110
gln64gDPSetDepthSource(uint32_t source)111 void gln64gDPSetDepthSource( uint32_t source )
112 {
113 gDP.otherMode.depthSource = source;
114 }
115
gln64gDPSetRenderMode(uint32_t mode1,uint32_t mode2)116 void gln64gDPSetRenderMode( uint32_t mode1, uint32_t mode2 )
117 {
118 gDP.otherMode.l &= 0x00000007;
119 gDP.otherMode.l |= mode1 | mode2;
120
121 gDP.changed |= CHANGED_RENDERMODE;
122 }
123
gln64gDPSetCombine(int32_t muxs0,int32_t muxs1)124 void gln64gDPSetCombine( int32_t muxs0, int32_t muxs1 )
125 {
126 gDP.combine.muxs0 = muxs0;
127 gDP.combine.muxs1 = muxs1;
128
129 gDP.changed |= CHANGED_COMBINE;
130 }
131
gln64gDPUpdateColorImage(void)132 void gln64gDPUpdateColorImage(void)
133 {
134 }
135
gln64gDPSetColorImage(uint32_t format,uint32_t size,uint32_t width,uint32_t address)136 void gln64gDPSetColorImage( uint32_t format, uint32_t size, uint32_t width, uint32_t address )
137 {
138 uint32_t addr = RSP_SegmentToPhysical( address );
139
140 if (gDP.colorImage.address != address || gDP.colorImage.width != width || gDP.colorImage.size != size)
141 {
142 uint32_t height = 1;
143
144 if (width == VI.width)
145 height = VI.height;
146 #if 0
147 else if (!__RSP.bLLE && width == gDP.scissor.lrx && width == gSP.viewport.width)
148 #else
149 else if (width == gDP.scissor.lrx && width == gSP.viewport.width)
150 #endif
151 {
152 height = MAX(gDP.scissor.lry, gSP.viewport.height);
153 height = MIN(height, VI.height);
154 } else if (width == gDP.scissor.lrx)
155 height = gDP.scissor.lry;
156 else if (width <= 64)
157 height = width;
158 else if (gSP.viewport.height > 0)
159 height = gSP.viewport.height;
160 #if 0
161 else if (!__RSP.bLLE && gSP.viewport.height > 0)
162 height = gSP.viewport.height;
163 #endif
164 else
165 height = gDP.scissor.lry;
166
167 if (config.frameBufferEmulation.enable)
168 {
169 FrameBuffer_SaveBuffer(address, (uint16_t)format, (uint16_t)size, (uint16_t)width, height, false);
170 gDP.colorImage.height = 0;
171 }
172 else
173 gDP.colorImage.height = height;
174 }
175
176 gDP.colorImage.format = format;
177 gDP.colorImage.size = size;
178 gDP.colorImage.width = width;
179 gDP.colorImage.address = RSP_SegmentToPhysical(addr);
180 }
181
gln64gDPSetTextureImage(uint32_t format,uint32_t size,uint32_t width,uint32_t address)182 void gln64gDPSetTextureImage( uint32_t format, uint32_t size, uint32_t width, uint32_t address )
183 {
184 gDP.textureImage.format = format;
185 gDP.textureImage.size = size;
186 gDP.textureImage.width = width;
187 gDP.textureImage.address = RSP_SegmentToPhysical( address );
188 gDP.textureImage.bpl = gDP.textureImage.width << gDP.textureImage.size >> 1;
189
190 if (gSP.DMAOffsets.tex_offset != 0)
191 {
192 if (format == G_IM_FMT_RGBA)
193 {
194 uint16_t * t = (uint16_t*)(gfx_info.RDRAM + gSP.DMAOffsets.tex_offset);
195 gSP.DMAOffsets.tex_shift = t[gSP.DMAOffsets.tex_count ^ 1];
196 gDP.textureImage.address += gSP.DMAOffsets.tex_shift;
197 }
198 else
199 {
200 gSP.DMAOffsets.tex_offset = 0;
201 gSP.DMAOffsets.tex_shift = 0;
202 gSP.DMAOffsets.tex_count = 0;
203 }
204 }
205 }
206
207 /* TODO/FIXME - update */
gln64gDPSetDepthImage(uint32_t address)208 void gln64gDPSetDepthImage( uint32_t address )
209 {
210 #if 0
211 depthBufferList().saveBuffer(address);
212 #else
213 DepthBuffer_SetBuffer(RSP_SegmentToPhysical(address));
214
215 if (depthBuffer.current->cleared)
216 OGL_ClearDepthBuffer(false);
217 #endif
218 gDP.depthImageAddress = RSP_SegmentToPhysical(address);
219 }
220
gln64gDPSetEnvColor(uint32_t r,uint32_t g,uint32_t b,uint32_t a)221 void gln64gDPSetEnvColor( uint32_t r, uint32_t g, uint32_t b, uint32_t a )
222 {
223 gDP.envColor.r = r * 0.0039215689f;
224 gDP.envColor.g = g * 0.0039215689f;
225 gDP.envColor.b = b * 0.0039215689f;
226 gDP.envColor.a = a * 0.0039215689f;
227
228 gDP.changed |= CHANGED_COMBINE_COLORS;
229
230 ShaderCombiner_UpdateEnvColor();
231 }
232
gln64gDPSetBlendColor(uint32_t r,uint32_t g,uint32_t b,uint32_t a)233 void gln64gDPSetBlendColor( uint32_t r, uint32_t g, uint32_t b, uint32_t a )
234 {
235 gDP.blendColor.r = r * 0.0039215689f;
236 gDP.blendColor.g = g * 0.0039215689f;
237 gDP.blendColor.b = b * 0.0039215689f;
238 gDP.blendColor.a = a * 0.0039215689f;
239
240 ShaderCombiner_UpdateBlendColor();
241 }
242
gln64gDPSetFogColor(uint32_t r,uint32_t g,uint32_t b,uint32_t a)243 void gln64gDPSetFogColor( uint32_t r, uint32_t g, uint32_t b, uint32_t a )
244 {
245 gDP.fogColor.r = r * 0.0039215689f;
246 gDP.fogColor.g = g * 0.0039215689f;
247 gDP.fogColor.b = b * 0.0039215689f;
248 gDP.fogColor.a = a * 0.0039215689f;
249
250 ShaderCombiner_UpdateFogColor();
251
252 gDP.changed |= CHANGED_FOGCOLOR;
253 }
254
gln64gDPSetFillColor(uint32_t c)255 void gln64gDPSetFillColor( uint32_t c )
256 {
257 gDP.fillColor.color = c;
258 gDP.fillColor.z = (float)_SHIFTR( c, 2, 14 );
259 gDP.fillColor.dz = (float)_SHIFTR( c, 0, 2 );
260 }
261
gln64gDPSetPrimColor(uint32_t m,uint32_t l,uint32_t r,uint32_t g,uint32_t b,uint32_t a)262 void gln64gDPSetPrimColor( uint32_t m, uint32_t l, uint32_t r, uint32_t g, uint32_t b, uint32_t a )
263 {
264 gDP.primColor.m = m * 0.0312500000;
265 gDP.primColor.l = l * 0.0039215689f;
266 gDP.primColor.r = r * 0.0039215689f;
267 gDP.primColor.g = g * 0.0039215689f;
268 gDP.primColor.b = b * 0.0039215689f;
269 gDP.primColor.a = a * 0.0039215689f;
270
271 ShaderCombiner_UpdatePrimColor();
272
273 gDP.changed |= CHANGED_COMBINE_COLORS;
274 }
275
gln64gDPSetTile(uint32_t format,uint32_t size,uint32_t line,uint32_t tmem,uint32_t tile,uint32_t palette,uint32_t cmt,uint32_t cms,uint32_t maskt,uint32_t masks,uint32_t shiftt,uint32_t shifts)276 void gln64gDPSetTile( uint32_t format, uint32_t size, uint32_t line, uint32_t tmem, uint32_t tile,
277 uint32_t palette, uint32_t cmt, uint32_t cms, uint32_t maskt, uint32_t masks, uint32_t shiftt, uint32_t shifts )
278 {
279 if (((size == G_IM_SIZ_4b) || (size == G_IM_SIZ_8b)) && (format == G_IM_FMT_RGBA))
280 format = G_IM_FMT_CI;
281
282 gDP.tiles[tile].format = format;
283 gDP.tiles[tile].size = size;
284 gDP.tiles[tile].line = line;
285 gDP.tiles[tile].tmem = tmem;
286 gDP.tiles[tile].palette = palette;
287 gDP.tiles[tile].cmt = cmt;
288 gDP.tiles[tile].cms = cms;
289 gDP.tiles[tile].maskt = maskt;
290 gDP.tiles[tile].masks = masks;
291 gDP.tiles[tile].shiftt = shiftt;
292 gDP.tiles[tile].shifts = shifts;
293
294 if (!gDP.tiles[tile].masks) gDP.tiles[tile].clamps = 1;
295 if (!gDP.tiles[tile].maskt) gDP.tiles[tile].clampt = 1;
296
297 if (tile == gSP.texture.tile || tile == gSP.texture.tile + 1)
298 {
299 uint32_t nTile = 7;
300 while(gDP.tiles[nTile].tmem != tmem && nTile > gSP.texture.tile + 1)
301 --nTile;
302 if (nTile > gSP.texture.tile + 1)
303 {
304 gDP.tiles[tile].textureMode = gDP.tiles[nTile].textureMode;
305 gDP.tiles[tile].loadType = gDP.tiles[nTile].loadType;
306 gDP.tiles[tile].frameBuffer = gDP.tiles[nTile].frameBuffer;
307 gDP.tiles[tile].imageAddress = gDP.tiles[nTile].imageAddress;
308 }
309 }
310
311 gDP.changed |= CHANGED_TILE;
312 }
313
gln64gDPGetFillColor(float _fillColor[4])314 void gln64gDPGetFillColor(float _fillColor[4])
315 {
316 const uint32_t c = gDP.fillColor.color;
317
318 if (gDP.colorImage.size < 3) {
319 _fillColor[0] = _SHIFTR( c, 11, 5 ) * 0.032258064f;
320 _fillColor[1] = _SHIFTR( c, 6, 5 ) * 0.032258064f;
321 _fillColor[2] = _SHIFTR( c, 1, 5 ) * 0.032258064f;
322 _fillColor[3] = (float)_SHIFTR( c, 0, 1 );
323 } else {
324 _fillColor[0] = _SHIFTR( c, 24, 8 ) * 0.0039215686f;
325 _fillColor[1] = _SHIFTR( c, 16, 8 ) * 0.0039215686f;
326 _fillColor[2] = _SHIFTR( c, 8, 8 ) * 0.0039215686f;
327 _fillColor[3] = _SHIFTR( c, 0, 8 ) * 0.0039215686f;
328 }
329 }
330
gln64gDPSetTileSize(uint32_t tile,uint32_t uls,uint32_t ult,uint32_t lrs,uint32_t lrt)331 void gln64gDPSetTileSize( uint32_t tile, uint32_t uls, uint32_t ult, uint32_t lrs, uint32_t lrt )
332 {
333 gDP.tiles[tile].uls = _SHIFTR( uls, 2, 10 );
334 gDP.tiles[tile].ult = _SHIFTR( ult, 2, 10 );
335 gDP.tiles[tile].lrs = _SHIFTR( lrs, 2, 10 );
336 gDP.tiles[tile].lrt = _SHIFTR( lrt, 2, 10 );
337
338 gDP.tiles[tile].fuls = _FIXED2FLOAT( uls, 2 );
339 gDP.tiles[tile].fult = _FIXED2FLOAT( ult, 2 );
340 gDP.tiles[tile].flrs = _FIXED2FLOAT( lrs, 2 );
341 gDP.tiles[tile].flrt = _FIXED2FLOAT( lrt, 2 );
342
343 gDP.changed |= CHANGED_TILE;
344 }
345
CheckForFrameBufferTexture(uint32_t _address,uint32_t _bytes)346 static bool CheckForFrameBufferTexture(uint32_t _address, uint32_t _bytes)
347 {
348 struct FrameBuffer *pBuffer;
349 int nTile;
350 bool bRes = false;
351
352 gDP.loadTile->textureMode = TEXTUREMODE_NORMAL;
353 gDP.loadTile->frameBuffer = NULL;
354 gDP.changed |= CHANGED_TMEM;
355 if (!config.frameBufferEmulation.enable)
356 return false;
357
358 pBuffer = (struct FrameBuffer*)FrameBuffer_FindBuffer(_address);
359 #if 0
360 FrameBuffer *pBuffer = fbList.findBuffer(_address);
361 #endif
362 bRes = pBuffer != NULL;
363 if (bRes)
364 {
365 uint32_t texEndAddress;
366 if ((config.generalEmulation.hacks & hack_blurPauseScreen) != 0)
367 {
368 #ifdef NEW
369 if (gDP.colorImage.address == gDP.depthImageAddress && pBuffer->m_RdramCrc != 0)
370 {
371 memcpy(RDRAM + gDP.depthImageAddress, RDRAM + pBuffer->m_startAddress, (pBuffer->m_width* pBuffer->m_height) << pBuffer->m_size >> 1);
372 pBuffer->m_RdramCrc = 0;
373 frameBufferList().getCurrent()->m_isPauseScreen = true;
374 }
375 if (pBuffer->m_isPauseScreen)
376 bRes = false;
377 #endif
378 }
379
380 #ifdef NEW
381 if (pBuffer->m_cfb)
382 {
383 FrameBuffer_RemoveBuffer(pBuffer->m_startAddress);
384 bRes = false;
385 }
386 #endif
387
388 #if 0
389 if ((config.generalEmulation.hacks & hack_noDepthFrameBuffers) != 0 && pBuffer->m_isDepthBuffer)
390 #else
391 if ((config.generalEmulation.hacks & hack_noDepthFrameBuffers) != 0 /* && pBuffer->m_isDepthBuffer */)
392 #endif
393 {
394 FrameBuffer_RemoveBuffer(pBuffer->m_startAddress);
395 bRes = false;
396 }
397
398 texEndAddress = _address + _bytes - 1;
399 if (_address > pBuffer->m_startAddress && texEndAddress > (pBuffer->m_endAddress + (pBuffer->m_width << pBuffer->m_size >> 1)))
400 bRes = false;
401
402 if (bRes && gDP.loadTile->loadType == LOADTYPE_TILE && gDP.textureImage.width != pBuffer->m_width && gDP.textureImage.size != pBuffer->m_size)
403 bRes = false;
404
405
406 #ifdef NEW
407 if (bRes && pBuffer->m_validityChecked != __RSP.DList)
408 {
409 if (pBuffer->m_cleared)
410 {
411 const uint32_t color = pBuffer->m_fillcolor & 0xFFFEFFFE;
412 uint32_t wrongPixels = 0;
413 for (uint32_t i = pBuffer->m_startAddress + 4; i < pBuffer->m_endAddress; i += 4) {
414 if (((*(uint32_t*)&RDRAM[i]) & 0xFFFEFFFE) != color)
415 ++wrongPixels;
416 }
417 bRes = wrongPixels < (pBuffer->m_endAddress - pBuffer->m_startAddress)/100; // treshold level 1%
418 if (bRes)
419 pBuffer->m_validityChecked = __RSP.DList;
420 else
421 frameBufferList().removeBuffer(pBuffer->m_startAddress);
422 }
423 else if (pBuffer->m_RdramCrc != 0)
424 {
425 const uint32_t crc = textureCRC(RDRAM + pBuffer->m_startAddress, pBuffer->m_height, pBuffer->m_width << pBuffer->m_size >> 1);
426 bRes = (pBuffer->m_RdramCrc == crc);
427 if (bRes)
428 pBuffer->m_validityChecked = __RSP.DList;
429 else
430 frameBufferList().removeBuffer(pBuffer->m_startAddress);
431 }
432 }
433 #endif
434
435 if (bRes)
436 {
437 #ifdef NEW
438 pBuffer->m_pLoadTile = gDP.loadTile;
439 #endif
440 gDP.loadTile->frameBuffer = pBuffer;
441 gDP.loadTile->textureMode = TEXTUREMODE_FRAMEBUFFER;
442 }
443 }
444
445 for (nTile = gSP.texture.tile; nTile < 6; ++nTile)
446 {
447 if (gDP.tiles[nTile].tmem == gDP.loadTile->tmem)
448 {
449 struct gDPTile *curTile = (struct gDPTile*)&gDP.tiles[nTile];
450 curTile->textureMode = gDP.loadTile->textureMode;
451 curTile->loadType = gDP.loadTile->loadType;
452 curTile->imageAddress = gDP.loadTile->imageAddress;
453 curTile->frameBuffer = gDP.loadTile->frameBuffer;
454 }
455 }
456 return bRes;
457 }
458
459 //****************************************************************
460 // LoadTile for 32bit RGBA texture
461 // Based on sources of angrylion's software plugin.
462 //
gln64gDPLoadTile32b(uint32_t uls,uint32_t ult,uint32_t lrs,uint32_t lrt)463 void gln64gDPLoadTile32b(uint32_t uls, uint32_t ult, uint32_t lrs, uint32_t lrt)
464 {
465 uint32_t i, j;
466 const uint32_t width = lrs - uls + 1;
467 const uint32_t height = lrt - ult + 1;
468 const uint32_t line = gDP.loadTile->line << 2;
469 const uint32_t tbase = gDP.loadTile->tmem << 2;
470 const uint32_t addr = gDP.textureImage.address >> 2;
471 const uint32_t * src = (const uint32_t*)gfx_info.RDRAM;
472 uint16_t * tmem16 = (uint16_t*)TMEM;
473 uint32_t c, ptr, tline, s, xorval;
474
475 for (j = 0; j < height; ++j)
476 {
477 tline = tbase + line * j;
478 s = ((j + ult) * gDP.textureImage.width) + uls;
479 xorval = (j & 1) ? 3 : 1;
480
481 for (i = 0; i < width; ++i)
482 {
483 c = src[addr + s + i];
484 ptr = ((tline + i) ^ xorval) & 0x3ff;
485 tmem16[ptr] = c >> 16;
486 tmem16[ptr | 0x400] = c & 0xffff;
487 }
488 }
489 }
490
gln64gDPLoadTile(uint32_t tile,uint32_t uls,uint32_t ult,uint32_t lrs,uint32_t lrt)491 void gln64gDPLoadTile(uint32_t tile, uint32_t uls, uint32_t ult, uint32_t lrs, uint32_t lrt)
492 {
493 uint32_t width, height, address, bpl, bpl2, height2;
494 struct gDPLoadTileInfo *info;
495
496 gln64gDPSetTileSize( tile, uls, ult, lrs, lrt );
497 gDP.loadTile = &gDP.tiles[tile];
498 gDP.loadTile->loadType = LOADTYPE_TILE;
499 gDP.loadTile->imageAddress = gDP.textureImage.address;
500
501 width = (gDP.loadTile->lrs - gDP.loadTile->uls + 1) & 0x03FF;
502 height = (gDP.loadTile->lrt - gDP.loadTile->ult + 1) & 0x03FF;
503
504 info = (struct gDPLoadTileInfo*)&gDP.loadInfo[gDP.loadTile->tmem];
505 info->texAddress = gDP.loadTile->imageAddress;
506 info->uls = gDP.loadTile->uls;
507 info->ult = gDP.loadTile->ult;
508 info->width = gDP.loadTile->masks != 0 ? (uint16_t)MIN(width, 1U<<gDP.loadTile->masks) : (uint16_t)width;
509 info->height = gDP.loadTile->maskt != 0 ? (uint16_t)MIN(height, 1U<<gDP.loadTile->maskt) : (uint16_t)height;
510 info->texWidth = gDP.textureImage.width;
511 info->size = gDP.textureImage.size;
512 info->loadType = LOADTYPE_TILE;
513
514 if (gDP.loadTile->line == 0)
515 return;
516
517 address = gDP.textureImage.address + gDP.loadTile->ult * gDP.textureImage.bpl + (gDP.loadTile->uls << gDP.textureImage.size >> 1);
518 if ((address + height * gDP.textureImage.bpl) > RDRAMSize)
519 return;
520
521 bpl = gDP.loadTile->line << 3;
522 bpl2 = bpl;
523 if (gDP.loadTile->lrs > gDP.textureImage.width)
524 bpl2 = (gDP.textureImage.width - gDP.loadTile->uls);
525 height2 = height;
526 if (gDP.loadTile->lrt > gDP.scissor.lry)
527 height2 = gDP.scissor.lry - gDP.loadTile->ult;
528 if (CheckForFrameBufferTexture(address, bpl2*height2))
529 return;
530
531 if (gDP.loadTile->size == G_IM_SIZ_32b)
532 gln64gDPLoadTile32b(gDP.loadTile->uls, gDP.loadTile->ult, gDP.loadTile->lrs, gDP.loadTile->lrt);
533 else
534 {
535 uint32_t y;
536 uint32_t tmemAddr = gDP.loadTile->tmem;
537
538 const uint32_t line = gDP.loadTile->line;
539 for (y = 0; y < height; ++y)
540 {
541 UnswapCopyWrap(gfx_info.RDRAM, address, (uint8_t*)TMEM, tmemAddr << 3, 0xFFF, bpl);
542 if (y & 1)
543 DWordInterleaveWrap((uint32_t*)TMEM, tmemAddr << 1, 0x3FF, line);
544
545 address += gDP.textureImage.bpl;
546 tmemAddr += line;
547 }
548 }
549 }
550
551 //****************************************************************
552 // LoadBlock for 32bit RGBA texture
553 // Based on sources of angrylion's software plugin.
554 //
gln64gDPLoadBlock32(uint32_t uls,uint32_t lrs,uint32_t dxt)555 void gln64gDPLoadBlock32(uint32_t uls,uint32_t lrs, uint32_t dxt)
556 {
557 const uint32_t * src = (const uint32_t*)gfx_info.RDRAM;
558 const uint32_t tb = gDP.loadTile->tmem << 2;
559 const uint32_t line = gDP.loadTile->line << 2;
560
561 uint16_t *tmem16 = (uint16_t*)TMEM;
562 uint32_t addr = gDP.loadTile->imageAddress >> 2;
563 uint32_t width = (lrs - uls + 1) << 2;
564 if (width == 4) // lr_s == 0, 1x1 texture
565 width = 1;
566 else if (width & 7)
567 width = (width & (~7)) + 8;
568
569 if (dxt != 0)
570 {
571 uint32_t i;
572 uint32_t j = 0;
573 uint32_t t = 0;
574 uint32_t oldt = 0;
575 uint32_t ptr;
576
577 uint32_t c = 0;
578 for (i = 0; i < width; i += 2)
579 {
580 oldt = t;
581 t = ((j >> 11) & 1) ? 3 : 1;
582 if (t != oldt)
583 i += line;
584 ptr = ((tb + i) ^ t) & 0x3ff;
585 c = src[addr + i];
586 tmem16[ptr] = c >> 16;
587 tmem16[ptr | 0x400] = c & 0xffff;
588 ptr = ((tb + i + 1) ^ t) & 0x3ff;
589 c = src[addr + i + 1];
590 tmem16[ptr] = c >> 16;
591 tmem16[ptr | 0x400] = c & 0xffff;
592 j += dxt;
593 }
594 }
595 else
596 {
597 uint32_t c, ptr, i;
598 for (i = 0; i < width; i++)
599 {
600 ptr = ((tb + i) ^ 1) & 0x3ff;
601 c = src[addr + i];
602 tmem16[ptr] = c >> 16;
603 tmem16[ptr | 0x400] = c & 0xffff;
604 }
605 }
606 }
607
gln64gDPLoadBlock(uint32_t tile,uint32_t uls,uint32_t ult,uint32_t lrs,uint32_t dxt)608 void gln64gDPLoadBlock(uint32_t tile, uint32_t uls, uint32_t ult, uint32_t lrs, uint32_t dxt)
609 {
610 uint32_t bytes, address;
611 struct gDPLoadTileInfo *info;
612
613 gln64gDPSetTileSize( tile, uls, ult, lrs, dxt );
614 gDP.loadTile = &gDP.tiles[tile];
615 gDP.loadTile->loadType = LOADTYPE_BLOCK;
616
617 if (gSP.DMAOffsets.tex_offset != 0) {
618 if (gSP.DMAOffsets.tex_shift % (((lrs>>2) + 1) << 3)) {
619 gDP.textureImage.address -= gSP.DMAOffsets.tex_shift;
620 gSP.DMAOffsets.tex_offset = 0;
621 gSP.DMAOffsets.tex_shift = 0;
622 gSP.DMAOffsets.tex_count = 0;
623 } else
624 ++gSP.DMAOffsets.tex_count;
625 }
626 gDP.loadTile->imageAddress = gDP.textureImage.address;
627
628 info = (struct gDPLoadTileInfo*)&gDP.loadInfo[gDP.loadTile->tmem];
629 info->texAddress = gDP.loadTile->imageAddress;
630 info->width = gDP.loadTile->lrs;
631 info->dxt = dxt;
632 info->size = gDP.textureImage.size;
633 info->loadType = LOADTYPE_BLOCK;
634
635 bytes = (lrs - uls + 1) << gDP.loadTile->size >> 1;
636
637 if ((bytes & 7) != 0)
638 bytes = (bytes & (~7)) + 8;
639 address = gDP.textureImage.address + ult * gDP.textureImage.bpl + (uls << gDP.textureImage.size >> 1);
640
641 if (bytes == 0 || (address + bytes) > RDRAMSize)
642 return;
643
644 gDP.loadTile->textureMode = TEXTUREMODE_NORMAL;
645 gDP.loadTile->frameBuffer = NULL;
646 CheckForFrameBufferTexture(address, bytes); // Load data to TMEM even if FB texture is found. See comment to texturedRectDepthBufferCopy
647
648 if (gDP.loadTile->size == G_IM_SIZ_32b)
649 gln64gDPLoadBlock32(gDP.loadTile->uls, gDP.loadTile->lrs, dxt);
650 else if (gDP.loadTile->format == G_IM_FMT_YUV)
651 memcpy(TMEM, &gfx_info.RDRAM[address], bytes); // HACK!
652 else {
653 uint32_t tmemAddr = gDP.loadTile->tmem;
654
655 if (dxt > 0)
656 {
657 uint32_t y;
658 uint32_t line = (2047 + dxt) / dxt;
659 uint32_t bpl = line << 3;
660 uint32_t height = bytes / bpl;
661
662 for (y = 0; y < height; ++y)
663 {
664 UnswapCopyWrap(gfx_info.RDRAM, address, (uint8_t*)TMEM, tmemAddr << 3, 0xFFF, bpl);
665 if (y & 1)
666 DWordInterleaveWrap((uint32_t*)TMEM, tmemAddr << 1, 0x3FF, line);
667
668 address += bpl;
669 tmemAddr += line;
670 }
671 } else
672 UnswapCopyWrap(gfx_info.RDRAM, address, (uint8_t*)TMEM, tmemAddr << 3, 0xFFF, bytes);
673 }
674 }
675
gln64gDPLoadTLUT(uint32_t tile,uint32_t uls,uint32_t ult,uint32_t lrs,uint32_t lrt)676 void gln64gDPLoadTLUT( uint32_t tile, uint32_t uls, uint32_t ult, uint32_t lrs, uint32_t lrt )
677 {
678 int i;
679 uint32_t address;
680 uint16_t count, pal, *dest, j;
681
682 gln64gDPSetTileSize( tile, uls, ult, lrs, lrt );
683 if (gDP.tiles[tile].tmem < 256)
684 return;
685 count = (uint16_t)((gDP.tiles[tile].lrs - gDP.tiles[tile].uls + 1) * (gDP.tiles[tile].lrt - gDP.tiles[tile].ult + 1));
686 address = gDP.textureImage.address + gDP.tiles[tile].ult * gDP.textureImage.bpl + (gDP.tiles[tile].uls << gDP.textureImage.size >> 1);
687 pal = (uint16_t)((gDP.tiles[tile].tmem - 256) >> 4);
688 dest = (uint16_t*)&TMEM[gDP.tiles[tile].tmem];
689
690 i = 0;
691 while (i < count)
692 {
693 for (j = 0; (j < 16) && (i < count); ++j, ++i)
694 {
695 *dest = swapword(*(uint16_t*)(gfx_info.RDRAM + (address ^ 2)));
696 address += 2;
697 dest += 4;
698 }
699
700 /* TODO/FIXME - should be CRC_CalculatePalette here instead */
701 gDP.paletteCRC16[pal] = Hash_Calculate(0xFFFFFFFF, &TMEM[256 + (pal << 4)], 16);
702 ++pal;
703 }
704
705 gDP.paletteCRC256 = Hash_Calculate(0xFFFFFFFF, gDP.paletteCRC16, 64);
706
707 #ifdef TEXTURE_FILTER
708 if (TFH.isInited())
709 {
710 const uint16_t start = gDP.tiles[tile].tmem - 256; // starting location in the palettes
711 uint16_t *spal = (uint16_t*)(gfx_info.RDRAM + gDP.textureImage.address);
712 memcpy((uint8_t*)(gDP.TexFilterPalette + start), spal, count<<1);
713 }
714 #endif
715
716 gDP.changed |= CHANGED_TMEM;
717 }
718
gln64gDPSetScissor(uint32_t mode,float ulx,float uly,float lrx,float lry)719 void gln64gDPSetScissor( uint32_t mode, float ulx, float uly, float lrx, float lry )
720 {
721 gDP.scissor.mode = mode;
722 gDP.scissor.ulx = ulx;
723 gDP.scissor.uly = uly;
724 gDP.scissor.lrx = lrx;
725 gDP.scissor.lry = lry;
726
727 gDP.changed |= CHANGED_SCISSOR;
728
729 #if 0
730 frameBufferList().correctHeight();
731 #endif
732 }
733
gln64gDPFillRDRAM(uint32_t address,int32_t ulx,int32_t uly,int32_t lrx,int32_t lry,uint32_t width,uint32_t size,uint32_t color,bool scissor)734 void gln64gDPFillRDRAM(uint32_t address, int32_t ulx, int32_t uly, int32_t lrx, int32_t lry, uint32_t width, uint32_t size, uint32_t color, bool scissor)
735 {
736 uint32_t y, x, stride, lowerBound, ci_width_in_dwords, *dst;
737 struct FrameBuffer *pCurrentBuffer;
738
739 pCurrentBuffer = (struct FrameBuffer*)FrameBuffer_GetCurrent();
740
741 if (pCurrentBuffer != NULL)
742 {
743 #ifdef NEW
744 pCurrentBuffer->m_cleared = true;
745 pCurrentBuffer->m_fillcolor = color;
746 #endif
747 }
748 if (scissor)
749 {
750 ulx = MIN(MAX((float)ulx, gDP.scissor.ulx), gDP.scissor.lrx);
751 lrx = MIN(MAX((float)lrx, gDP.scissor.ulx), gDP.scissor.lrx);
752 uly = MIN(MAX((float)uly, gDP.scissor.uly), gDP.scissor.lry);
753 lry = MIN(MAX((float)lry, gDP.scissor.uly), gDP.scissor.lry);
754 }
755 stride = width << size >> 1;
756 lowerBound = address + lry*stride;
757 if (lowerBound > RDRAMSize)
758 lry -= (lowerBound - RDRAMSize) / stride;
759 ci_width_in_dwords = width >> (3 - size);
760 ulx >>= (3 - size);
761 lrx >>= (3 - size);
762 dst = (uint32_t*)(gfx_info.RDRAM + address);
763 dst += uly * ci_width_in_dwords;
764
765 for (y = uly; y < lry; ++y)
766 {
767 for (x = ulx; x < lrx; ++x)
768 dst[x] = color;
769 dst += ci_width_in_dwords;
770 }
771 }
772
gln64gDPFillRectangle(int32_t ulx,int32_t uly,int32_t lrx,int32_t lry)773 void gln64gDPFillRectangle( int32_t ulx, int32_t uly, int32_t lrx, int32_t lry )
774 {
775 float fillColor[4];
776 DepthBuffer *buffer = NULL;
777
778 if (gDP.otherMode.cycleType == G_CYC_FILL)
779 {
780 ++lrx;
781 ++lry;
782 }
783 else if (lry == uly)
784 ++lry;
785
786 buffer = (DepthBuffer*)DepthBuffer_FindBuffer( gDP.colorImage.address );
787 if (buffer)
788 buffer->cleared = true;
789
790 if (gDP.depthImageAddress == gDP.colorImage.address)
791 {
792 /* Game may use depth texture as auxilary color texture. Example: Mario Tennis
793 * If color is not depth clear color, that is most likely the case */
794 if (gDP.fillColor.color == DepthClearColor)
795 {
796 gln64gDPFillRDRAM(gDP.colorImage.address, ulx, uly, lrx, lry,
797 gDP.colorImage.width, gDP.colorImage.size, gDP.fillColor.color, true);
798 OGL_ClearDepthBuffer(lrx - ulx >= gDP.scissor.lrx - gDP.scissor.ulx && lry - uly >= gDP.scissor.lry - gDP.scissor.uly);
799 return;
800 }
801 }
802 else if (gDP.fillColor.color == DepthClearColor && gDP.otherMode.cycleType == G_CYC_FILL)
803 {
804 #ifdef NEW
805 depthBufferList().saveBuffer(gDP.colorImage.address);
806 #endif
807 gln64gDPFillRDRAM(gDP.colorImage.address, ulx, uly, lrx, lry, gDP.colorImage.width, gDP.colorImage.size, gDP.fillColor.color, true);
808 OGL_ClearDepthBuffer(lrx - ulx == gDP.scissor.lrx - gDP.scissor.ulx && lry - uly == gDP.scissor.lry - gDP.scissor.uly);
809 return;
810 }
811
812 #ifdef NEW
813 frameBufferList().setBufferChanged();
814 #endif
815
816 gln64gDPGetFillColor(fillColor);
817
818 if (gDP.otherMode.cycleType == G_CYC_FILL)
819 {
820 if ((ulx == 0) && (uly == 0) && (lrx == gDP.scissor.lrx) && (lry == gDP.scissor.lry))
821 {
822 gln64gDPFillRDRAM(gDP.colorImage.address, ulx, uly, lrx, lry,
823 gDP.colorImage.width, gDP.colorImage.size, gDP.fillColor.color, true);
824
825 if ((*gfx_info.VI_STATUS_REG & 8) != 0)
826 {
827 fillColor[0] = sqrtf(fillColor[0]);
828 fillColor[1] = sqrtf(fillColor[1]);
829 fillColor[2] = sqrtf(fillColor[2]);
830 }
831 OGL_ClearColorBuffer(&fillColor[0]);
832 return;
833 }
834 }
835
836 OGL_DrawRect( ulx, uly, lrx, lry, fillColor);
837
838 /* TODO/FIXME - remove? */
839 if (depthBuffer.current)
840 depthBuffer.current->cleared = false;
841
842 if (gDP.otherMode.cycleType == G_CYC_FILL)
843 {
844 if (lry > (uint32_t)gDP.scissor.lry)
845 gDP.colorImage.height = (uint32_t)MAX( gDP.colorImage.height, (unsigned int)gDP.scissor.lry );
846 else
847 gDP.colorImage.height = (uint32_t)MAX((int32_t)gDP.colorImage.height, lry);
848 }
849 else
850 gDP.colorImage.height = MAX( gDP.colorImage.height, (unsigned int)lry );
851 }
852
gln64gDPSetConvert(int32_t k0,int32_t k1,int32_t k2,int32_t k3,int32_t k4,int32_t k5)853 void gln64gDPSetConvert( int32_t k0, int32_t k1, int32_t k2, int32_t k3, int32_t k4, int32_t k5 )
854 {
855 gDP.convert.k0 = SIGN(k0, 9);
856 gDP.convert.k1 = SIGN(k1, 9);
857 gDP.convert.k2 = SIGN(k2, 9);
858 gDP.convert.k3 = SIGN(k3, 9);
859 gDP.convert.k4 = SIGN(k4, 9);
860 gDP.convert.k5 = SIGN(k5, 9);
861
862 ShaderCombiner_UpdateConvertColor();
863 }
864
gln64gDPSetKeyR(uint32_t cR,uint32_t sR,uint32_t wR)865 void gln64gDPSetKeyR( uint32_t cR, uint32_t sR, uint32_t wR )
866 {
867 gDP.key.center.r = cR * 0.0039215689f;;
868 gDP.key.scale.r = sR * 0.0039215689f;;
869 gDP.key.width.r = wR * 0.0039215689f;;
870
871 }
872
gln64gDPSetKeyGB(uint32_t cG,uint32_t sG,uint32_t wG,uint32_t cB,uint32_t sB,uint32_t wB)873 void gln64gDPSetKeyGB(uint32_t cG, uint32_t sG, uint32_t wG, uint32_t cB, uint32_t sB, uint32_t wB )
874 {
875 gDP.key.center.g = cG * 0.0039215689f;;
876 gDP.key.scale.g = sG * 0.0039215689f;;
877 gDP.key.width.g = wG * 0.0039215689f;;
878 gDP.key.center.b = cB * 0.0039215689f;;
879 gDP.key.scale.b = sB * 0.0039215689f;;
880 gDP.key.width.b = wB * 0.0039215689f;;
881
882 ShaderCombiner_UpdateKeyColor();
883 }
884
gln64gDPTextureRectangle(float ulx,float uly,float lrx,float lry,int32_t tile,float s,float t,float dsdx,float dtdy)885 void gln64gDPTextureRectangle( float ulx, float uly, float lrx, float lry, int32_t tile, float s, float t, float dsdx, float dtdy )
886 {
887 struct TexturedRectParams params;
888 float lrs, lrt;
889 float tmp;
890 struct gDPTile *textureTileOrg[2];
891
892 if (gDP.otherMode.cycleType == G_CYC_COPY)
893 {
894 dsdx = 1.0f;
895 lrx += 1.0f;
896 lry += 1.0f;
897 }
898 lry = MAX(lry, uly + 1.0f);
899
900 textureTileOrg[0] = gSP.textureTile[0];
901 textureTileOrg[1] = gSP.textureTile[1];
902 gSP.textureTile[0] = &gDP.tiles[tile];
903 gSP.textureTile[1] = &gDP.tiles[(tile + 1) & 7];
904
905 if (gDP.loadTile->textureMode == TEXTUREMODE_NORMAL)
906 gDP.loadTile->textureMode = TEXTUREMODE_TEXRECT;
907
908 if (gSP.textureTile[1]->textureMode == TEXTUREMODE_NORMAL)
909 gSP.textureTile[1]->textureMode = TEXTUREMODE_TEXRECT;
910
911 // HACK ALERT!
912 if (((int)(s) == 512) && (gDP.colorImage.width + gSP.textureTile[0]->uls < 512))
913 s = 0.0f;
914
915 if (__RSP.cmd == G_TEXRECTFLIP)
916 {
917 lrs = s + (lry - uly - 1) * dtdy;
918 lrt = t + (lrx - ulx - 1) * dsdx;
919 }
920 else
921 {
922 lrs = s + (lrx - ulx - 1) * dsdx;
923 lrt = t + (lry - uly - 1) * dtdy;
924 }
925
926 gDP.texRect.width = (unsigned int)(MAX( lrs, s ) + dsdx);
927 gDP.texRect.height = (unsigned int)(MAX( lrt, t ) + dtdy);
928
929 params.ulx = ulx;
930 params.uly = uly;
931 params.lrx = lrx;
932 params.lry = lry;
933 params.uls = s;
934 params.ult = t;
935 params.lrs = lrs;
936 params.lrt = lrt;
937 params.flip = (__RSP.cmd == G_TEXRECTFLIP);
938 OGL_DrawTexturedRect(¶ms);
939
940 gSP.textureTile[0] = textureTileOrg[0];
941 gSP.textureTile[1] = textureTileOrg[1];
942
943 #if 1
944 if (depthBuffer.current)
945 depthBuffer.current->cleared = false;
946 gDP.colorImage.changed = true;
947 #else
948 frameBufferList().setBufferChanged();
949 #endif
950 if (gDP.colorImage.width < 64)
951 gDP.colorImage.height = (uint32_t)MAX( (float)gDP.colorImage.height, lry );
952 else
953 gDP.colorImage.height = (unsigned int)(MAX( gDP.colorImage.height, gDP.scissor.lry ));
954 }
955
gln64gDPTextureRectangleFlip(float ulx,float uly,float lrx,float lry,int32_t tile,float s,float t,float dsdx,float dtdy)956 void gln64gDPTextureRectangleFlip( float ulx, float uly, float lrx, float lry, int32_t tile, float s, float t, float dsdx, float dtdy )
957 {
958 gln64gDPTextureRectangle( ulx, uly, lrx, lry, tile, s, t, dsdx, dtdy );
959 }
960
gln64gDPFullSync(void)961 void gln64gDPFullSync(void)
962 {
963 #if 0
964 if (config.frameBufferEmulation.copyAuxToRDRAM != 0) {
965 frameBufferList().copyAux();
966 frameBufferList().removeAux();
967 }
968
969 const bool sync = config.frameBufferEmulation.copyToRDRAM == Config::ctSync;
970 if (config.frameBufferEmulation.copyToRDRAM != Config::ctDisable)
971 FrameBuffer_CopyToRDRAM(gDP.colorImage.address, sync);
972
973 if (__RSP.bLLE)
974 {
975 if (config.frameBufferEmulation.copyDepthToRDRAM != Config::ctDisable)
976 FrameBuffer_CopyDepthBuffer(gDP.colorImage.address);
977 }
978 #endif
979
980 *gfx_info.MI_INTR_REG |= MI_INTR_DP;
981
982 if (gfx_info.CheckInterrupts)
983 gfx_info.CheckInterrupts();
984 }
985
gln64gDPTileSync(void)986 void gln64gDPTileSync(void)
987 {
988 }
989
gln64gDPPipeSync(void)990 void gln64gDPPipeSync(void)
991 {
992 }
993
gln64gDPLoadSync(void)994 void gln64gDPLoadSync(void)
995 {
996 }
997
gln64gDPNoOp(void)998 void gln64gDPNoOp(void)
999 {
1000 }
1001
1002 /*******************************************
1003 * Low level triangle *
1004 *******************************************
1005 * based on sources of ziggy's z64 *
1006 *******************************************/
1007
1008 #define XSCALE(x) ((float)(x)/(1<<18))
1009 #define YSCALE(y) ((float)(y)/(1<<2))
1010 #define ZSCALE(z) ((gDP.otherMode.depthSource == G_ZS_PRIM) ? (gDP.primDepth.z) : ((float)((uint32_t)((z))) / 0xffff0000))
1011 #define PERSP_EN (gDP.otherMode.texturePersp != 0)
1012 #define WSCALE(z) 1.0f/(PERSP_EN? ((float)((uint32_t)(z) + 0x10000)/0xffff0000) : 1.0f)
1013 #define CSCALE(c) ((((c)>0x3ff0000? 0x3ff0000:((c)<0? 0 : (c)))>>18)*0.0039215689f)
1014 #define _PERSP(w) ( w )
1015 #define PERSP(s, w) ( ((int64_t)(s) << 20) / (_PERSP(w)? _PERSP(w):1) )
1016 #define SSCALE(s, _w) (PERSP_EN? (float)(PERSP(s, _w))/(1 << 10) : (float)(s)/(1<<21))
1017 #define TSCALE(s, w) (PERSP_EN? (float)(PERSP(s, w))/(1 << 10) : (float)(s)/(1<<21))
1018
gln64gDPLLETriangle(uint32_t _w1,uint32_t _w2,int _shade,int _texture,int _zbuffer,uint32_t * _pRdpCmd)1019 void gln64gDPLLETriangle(uint32_t _w1, uint32_t _w2, int _shade, int _texture, int _zbuffer, uint32_t * _pRdpCmd)
1020 {
1021 int32_t yl, ym, yh;
1022 int32_t xl, xm, xh;
1023 int32_t dxldy, dxhdy, dxmdy;
1024 uint32_t w3, w4, w5, w6, w7, w8;
1025 struct SPVertex *vtx0, *vtx;
1026 int j;
1027 int xleft, xright, xleft_inc, xright_inc;
1028 int r, g, b, a, z, s, t, w;
1029 int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0, dzdx = 0, dsdx = 0, dtdx = 0, dwdx = 0;
1030 int drde = 0, dgde = 0, dbde = 0, dade = 0, dzde = 0, dsde = 0, dtde = 0, dwde = 0;
1031 int flip = (_w1 & 0x8000000) ? 1 : 0;
1032 uint32_t * shade_base = _pRdpCmd + 8;
1033 uint32_t * texture_base = _pRdpCmd + 8;
1034 uint32_t * zbuffer_base = _pRdpCmd + 8;
1035 const uint32_t tile = _SHIFTR(_w1, 16, 3);
1036 struct gDPTile *textureTileOrg[2];
1037 textureTileOrg[0] = gSP.textureTile[0];
1038 textureTileOrg[1] = gSP.textureTile[1];
1039 gSP.textureTile[0] = &gDP.tiles[tile];
1040 gSP.textureTile[1] = &gDP.tiles[(tile + 1) & 7];
1041
1042 if (_shade != 0) {
1043 texture_base += 16;
1044 zbuffer_base += 16;
1045 }
1046 if (_texture != 0) {
1047 zbuffer_base += 16;
1048 }
1049
1050 w3 = _pRdpCmd[2];
1051 w4 = _pRdpCmd[3];
1052 w5 = _pRdpCmd[4];
1053 w6 = _pRdpCmd[5];
1054 w7 = _pRdpCmd[6];
1055 w8 = _pRdpCmd[7];
1056
1057 yl = (_w1 & 0x3fff);
1058 ym = ((_w2 >> 16) & 0x3fff);
1059 yh = ((_w2 >> 0) & 0x3fff);
1060 xl = (int32_t)(w3);
1061 xh = (int32_t)(w5);
1062 xm = (int32_t)(w7);
1063 dxldy = (int32_t)(w4);
1064 dxhdy = (int32_t)(w6);
1065 dxmdy = (int32_t)(w8);
1066
1067 if (yl & (0x800<<2)) yl |= 0xfffff000<<2;
1068 if (ym & (0x800<<2)) ym |= 0xfffff000<<2;
1069 if (yh & (0x800<<2)) yh |= 0xfffff000<<2;
1070
1071 yh &= ~3;
1072
1073 r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0xffff0000; s = 0; t = 0; w = 0x30000;
1074
1075 if (_shade != 0) {
1076 r = (shade_base[0] & 0xffff0000) | ((shade_base[+4 ] >> 16) & 0x0000ffff);
1077 g = ((shade_base[0 ] << 16) & 0xffff0000) | (shade_base[4 ] & 0x0000ffff);
1078 b = (shade_base[1 ] & 0xffff0000) | ((shade_base[5 ] >> 16) & 0x0000ffff);
1079 a = ((shade_base[1 ] << 16) & 0xffff0000) | (shade_base[5 ] & 0x0000ffff);
1080 drdx = (shade_base[2 ] & 0xffff0000) | ((shade_base[6 ] >> 16) & 0x0000ffff);
1081 dgdx = ((shade_base[2 ] << 16) & 0xffff0000) | (shade_base[6 ] & 0x0000ffff);
1082 dbdx = (shade_base[3 ] & 0xffff0000) | ((shade_base[7 ] >> 16) & 0x0000ffff);
1083 dadx = ((shade_base[3 ] << 16) & 0xffff0000) | (shade_base[7 ] & 0x0000ffff);
1084 drde = (shade_base[8 ] & 0xffff0000) | ((shade_base[12] >> 16) & 0x0000ffff);
1085 dgde = ((shade_base[8 ] << 16) & 0xffff0000) | (shade_base[12] & 0x0000ffff);
1086 dbde = (shade_base[9 ] & 0xffff0000) | ((shade_base[13] >> 16) & 0x0000ffff);
1087 dade = ((shade_base[9 ] << 16) & 0xffff0000) | (shade_base[13] & 0x0000ffff);
1088 }
1089 if (_texture != 0) {
1090 s = (texture_base[0 ] & 0xffff0000) | ((texture_base[4 ] >> 16) & 0x0000ffff);
1091 t = ((texture_base[0 ] << 16) & 0xffff0000) | (texture_base[4 ] & 0x0000ffff);
1092 w = (texture_base[1 ] & 0xffff0000) | ((texture_base[5 ] >> 16) & 0x0000ffff);
1093 // w = abs(w);
1094 dsdx = (texture_base[2 ] & 0xffff0000) | ((texture_base[6 ] >> 16) & 0x0000ffff);
1095 dtdx = ((texture_base[2 ] << 16) & 0xffff0000) | (texture_base[6 ] & 0x0000ffff);
1096 dwdx = (texture_base[3 ] & 0xffff0000) | ((texture_base[7 ] >> 16) & 0x0000ffff);
1097 dsde = (texture_base[8 ] & 0xffff0000) | ((texture_base[12] >> 16) & 0x0000ffff);
1098 dtde = ((texture_base[8 ] << 16) & 0xffff0000) | (texture_base[12] & 0x0000ffff);
1099 dwde = (texture_base[9 ] & 0xffff0000) | ((texture_base[13] >> 16) & 0x0000ffff);
1100 }
1101 if (_zbuffer != 0) {
1102 z = zbuffer_base[0];
1103 dzdx = zbuffer_base[1];
1104 dzde = zbuffer_base[2];
1105 }
1106
1107 xh <<= 2; xm <<= 2; xl <<= 2;
1108 r <<= 2; g <<= 2; b <<= 2; a <<= 2;
1109 dsde >>= 2; dtde >>= 2; dsdx >>= 2; dtdx >>= 2;
1110 dzdx >>= 2; dzde >>= 2;
1111 dwdx >>= 2; dwde >>= 2;
1112
1113 vtx0 = (struct SPVertex*)&OGL.triangles.vertices[0];
1114 vtx = (struct SPVertex*)vtx0;
1115
1116 xleft = xm;
1117 xright = xh;
1118 xleft_inc = dxmdy;
1119 xright_inc = dxhdy;
1120
1121 while (yh<ym &&
1122 !((!flip && xleft < xright+0x10000) ||
1123 (flip && xleft > xright-0x10000))) {
1124 xleft += xleft_inc;
1125 xright += xright_inc;
1126 s += dsde; t += dtde; w += dwde;
1127 r += drde; g += dgde; b += dbde; a += dade;
1128 z += dzde;
1129 yh++;
1130 }
1131
1132 j = ym-yh;
1133 if (j > 0) {
1134 int dx = (xleft-xright)>>16;
1135 if ((!flip && xleft < xright) ||
1136 (flip/* && xleft > xright*/))
1137 {
1138 if (_shade != 0) {
1139 vtx->r = CSCALE(r+drdx*dx);
1140 vtx->g = CSCALE(g+dgdx*dx);
1141 vtx->b = CSCALE(b+dbdx*dx);
1142 vtx->a = CSCALE(a+dadx*dx);
1143 }
1144 if (_texture != 0) {
1145 vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx);
1146 vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx);
1147 }
1148 vtx->x = XSCALE(xleft);
1149 vtx->y = YSCALE(yh);
1150 vtx->z = ZSCALE(z+dzdx*dx);
1151 vtx->w = WSCALE(w+dwdx*dx);
1152 ++vtx;
1153 }
1154 if ((!flip/* && xleft < xright*/) ||
1155 (flip && xleft > xright))
1156 {
1157 if (_shade != 0) {
1158 vtx->r = CSCALE(r);
1159 vtx->g = CSCALE(g);
1160 vtx->b = CSCALE(b);
1161 vtx->a = CSCALE(a);
1162 }
1163 if (_texture != 0) {
1164 vtx->s = SSCALE(s, w);
1165 vtx->t = TSCALE(t, w);
1166 }
1167 vtx->x = XSCALE(xright);
1168 vtx->y = YSCALE(yh);
1169 vtx->z = ZSCALE(z);
1170 vtx->w = WSCALE(w);
1171 ++vtx;
1172 }
1173 xleft += xleft_inc*j; xright += xright_inc*j;
1174 s += dsde*j; t += dtde*j;
1175 if (w + dwde*j) w += dwde*j;
1176 else w += dwde*(j-1);
1177 r += drde*j; g += dgde*j; b += dbde*j; a += dade*j;
1178 z += dzde*j;
1179 // render ...
1180 }
1181
1182 if (xl != xh)
1183 xleft = xl;
1184
1185 //if (yl-ym > 0)
1186 {
1187 int dx = (xleft-xright)>>16;
1188 if ((!flip && xleft <= xright) ||
1189 (flip/* && xleft >= xright*/))
1190 {
1191 if (_shade != 0) {
1192 vtx->r = CSCALE(r+drdx*dx);
1193 vtx->g = CSCALE(g+dgdx*dx);
1194 vtx->b = CSCALE(b+dbdx*dx);
1195 vtx->a = CSCALE(a+dadx*dx);
1196 }
1197 if (_texture != 0) {
1198 vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx);
1199 vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx);
1200 }
1201 vtx->x = XSCALE(xleft);
1202 vtx->y = YSCALE(ym);
1203 vtx->z = ZSCALE(z+dzdx*dx);
1204 vtx->w = WSCALE(w+dwdx*dx);
1205 ++vtx;
1206 }
1207 if ((!flip/* && xleft <= xright*/) ||
1208 (flip && xleft >= xright))
1209 {
1210 if (_shade != 0) {
1211 vtx->r = CSCALE(r);
1212 vtx->g = CSCALE(g);
1213 vtx->b = CSCALE(b);
1214 vtx->a = CSCALE(a);
1215 }
1216 if (_texture != 0) {
1217 vtx->s = SSCALE(s, w);
1218 vtx->t = TSCALE(t, w);
1219 }
1220 vtx->x = XSCALE(xright);
1221 vtx->y = YSCALE(ym);
1222 vtx->z = ZSCALE(z);
1223 vtx->w = WSCALE(w);
1224 ++vtx;
1225 }
1226 }
1227 xleft_inc = dxldy;
1228 xright_inc = dxhdy;
1229
1230 j = yl-ym;
1231 //j--; // ?
1232 xleft += xleft_inc*j; xright += xright_inc*j;
1233 s += dsde*j; t += dtde*j; w += dwde*j;
1234 r += drde*j; g += dgde*j; b += dbde*j; a += dade*j;
1235 z += dzde*j;
1236
1237 while (yl>ym &&
1238 !((!flip && xleft < xright+0x10000) ||
1239 (flip && xleft > xright-0x10000))) {
1240 xleft -= xleft_inc; xright -= xright_inc;
1241 s -= dsde; t -= dtde; w -= dwde;
1242 r -= drde; g -= dgde; b -= dbde; a -= dade;
1243 z -= dzde;
1244 --j;
1245 --yl;
1246 }
1247
1248 // render ...
1249 if (j >= 0) {
1250 int dx = (xleft-xright)>>16;
1251 if ((!flip && xleft <= xright) ||
1252 (flip/* && xleft >= xright*/))
1253 {
1254 if (_shade != 0) {
1255 vtx->r = CSCALE(r+drdx*dx);
1256 vtx->g = CSCALE(g+dgdx*dx);
1257 vtx->b = CSCALE(b+dbdx*dx);
1258 vtx->a = CSCALE(a+dadx*dx);
1259 }
1260 if (_texture != 0) {
1261 vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx);
1262 vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx);
1263 }
1264 vtx->x = XSCALE(xleft);
1265 vtx->y = YSCALE(yl);
1266 vtx->z = ZSCALE(z+dzdx*dx);
1267 vtx->w = WSCALE(w+dwdx*dx);
1268 ++vtx;
1269 }
1270 if ((!flip/* && xleft <= xright*/) ||
1271 (flip && xleft >= xright))
1272 {
1273 if (_shade != 0) {
1274 vtx->r = CSCALE(r);
1275 vtx->g = CSCALE(g);
1276 vtx->b = CSCALE(b);
1277 vtx->a = CSCALE(a);
1278 }
1279 if (_texture != 0) {
1280 vtx->s = SSCALE(s, w);
1281 vtx->t = TSCALE(t, w);
1282 }
1283 vtx->x = XSCALE(xright);
1284 vtx->y = YSCALE(yl);
1285 vtx->z = ZSCALE(z);
1286 vtx->w = WSCALE(w);
1287 ++vtx;
1288 }
1289 }
1290
1291 if (_texture != 0)
1292 gSP.changed |= CHANGED_TEXTURE;
1293 if (_zbuffer != 0)
1294 gSP.geometryMode |= G_ZBUFFER;
1295
1296 OGL_DrawLLETriangle(vtx - vtx0);
1297 gSP.textureTile[0] = textureTileOrg[0];
1298 gSP.textureTile[1] = textureTileOrg[1];
1299 }
1300
gln64gDPTriangle(uint32_t _w1,uint32_t _w2,int shade,int texture,int zbuffer)1301 static void gln64gDPTriangle(uint32_t _w1, uint32_t _w2, int shade, int texture, int zbuffer)
1302 {
1303 gln64gDPLLETriangle(_w1, _w2, shade, texture, zbuffer, __RDP.cmd_data + __RDP.cmd_cur);
1304 }
1305
gln64gDPTriFill(uint32_t w0,uint32_t w1)1306 void gln64gDPTriFill(uint32_t w0, uint32_t w1)
1307 {
1308 gln64gDPTriangle(w0, w1, 0, 0, 0);
1309 }
1310
gln64gDPTriShade(uint32_t w0,uint32_t w1)1311 void gln64gDPTriShade(uint32_t w0, uint32_t w1)
1312 {
1313 gln64gDPTriangle(w0, w1, 1, 0, 0);
1314 }
1315
gln64gDPTriTxtr(uint32_t w0,uint32_t w1)1316 void gln64gDPTriTxtr(uint32_t w0, uint32_t w1)
1317 {
1318 gln64gDPTriangle(w0, w1, 0, 1, 0);
1319 }
1320
gln64gDPTriShadeTxtr(uint32_t w0,uint32_t w1)1321 void gln64gDPTriShadeTxtr(uint32_t w0, uint32_t w1)
1322 {
1323 gln64gDPTriangle(w0, w1, 1, 1, 0);
1324 }
1325
gln64gDPTriFillZ(uint32_t w0,uint32_t w1)1326 void gln64gDPTriFillZ(uint32_t w0, uint32_t w1)
1327 {
1328 gln64gDPTriangle(w0, w1, 0, 0, 1);
1329 }
1330
gln64gDPTriShadeZ(uint32_t w0,uint32_t w1)1331 void gln64gDPTriShadeZ(uint32_t w0, uint32_t w1)
1332 {
1333 gln64gDPTriangle(w0, w1, 1, 0, 1);
1334 }
1335
gln64gDPTriTxtrZ(uint32_t w0,uint32_t w1)1336 void gln64gDPTriTxtrZ(uint32_t w0, uint32_t w1)
1337 {
1338 gln64gDPTriangle(w0, w1, 0, 1, 1);
1339 }
1340
gln64gDPTriShadeTxtrZ(uint32_t w0,uint32_t w1)1341 void gln64gDPTriShadeTxtrZ(uint32_t w0, uint32_t w1)
1342 {
1343 gln64gDPTriangle(w0, w1, 1, 1, 1);
1344 }
1345