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(&params);
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