mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-07 03:13:49 +00:00
![Sergey Lipskiy](/assets/img/avatar_default.png)
Replays works only if depth buffer FBO is NOT used as texture because CPU copies color frame buffer for replays into depth buffer area. Pause screen in Zelda OOT is copied into depth buffer area and it works only id depth buffer FBO IS used as texture. Thus it is impossible to write general code for both situations.
1443 lines
41 KiB
C++
1443 lines
41 KiB
C++
#include <assert.h>
|
|
#include <algorithm>
|
|
#include "GLideN64.h"
|
|
#include "N64.h"
|
|
#include "GBI.h"
|
|
#include "RSP.h"
|
|
#include "RDP.h"
|
|
#include "gDP.h"
|
|
#include "gSP.h"
|
|
#include "Types.h"
|
|
#include "Debug.h"
|
|
#include "convert.h"
|
|
#include "OpenGL.h"
|
|
#include "CRC.h"
|
|
#include "FrameBuffer.h"
|
|
#include "DepthBuffer.h"
|
|
#include "VI.h"
|
|
#include "Config.h"
|
|
#include "Combiner.h"
|
|
|
|
#define DEPTH_CLEAR_COLOR 0xfffcfffc // The value usually used to clear depth buffer
|
|
|
|
using namespace std;
|
|
|
|
gDPInfo gDP;
|
|
|
|
void gDPSetOtherMode( u32 mode0, u32 mode1 )
|
|
{
|
|
gDP.otherMode.h = mode0;
|
|
gDP.otherMode.l = mode1;
|
|
|
|
gDP.changed |= CHANGED_RENDERMODE | CHANGED_CYCLETYPE | CHANGED_ALPHACOMPARE;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetOtherMode( %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s, %s | %s | %s%s%s%s%s | %s | %s%s%s );\n",
|
|
AlphaDitherText[gDP.otherMode.alphaDither],
|
|
ColorDitherText[gDP.otherMode.colorDither],
|
|
CombineKeyText[gDP.otherMode.combineKey],
|
|
TextureConvertText[gDP.otherMode.textureConvert],
|
|
TextureFilterText[gDP.otherMode.textureFilter],
|
|
TextureLUTText[gDP.otherMode.textureLUT],
|
|
TextureLODText[gDP.otherMode.textureLOD],
|
|
TextureDetailText[gDP.otherMode.textureDetail],
|
|
TexturePerspText[gDP.otherMode.texturePersp],
|
|
CycleTypeText[gDP.otherMode.cycleType],
|
|
PipelineModeText[gDP.otherMode.pipelineMode],
|
|
AlphaCompareText[gDP.otherMode.alphaCompare],
|
|
DepthSourceText[gDP.otherMode.depthSource],
|
|
gDP.otherMode.AAEnable ? "AA_EN | " : "",
|
|
gDP.otherMode.depthCompare ? "Z_CMP | " : "",
|
|
gDP.otherMode.depthUpdate ? "Z_UPD | " : "",
|
|
gDP.otherMode.imageRead ? "IM_RD | " : "",
|
|
CvgDestText[gDP.otherMode.cvgDest],
|
|
DepthModeText[gDP.otherMode.depthMode],
|
|
gDP.otherMode.cvgXAlpha ? "CVG_X_ALPHA | " : "",
|
|
gDP.otherMode.alphaCvgSel ? "ALPHA_CVG_SEL | " : "",
|
|
gDP.otherMode.forceBlender ? "FORCE_BL" : "" );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetPrimDepth( u16 z, u16 dz )
|
|
{
|
|
if (gSP.viewport.vscale[2] == 0)
|
|
gDP.primDepth.z = _FIXED2FLOAT(_SHIFTR(z, 0, 15), 15);
|
|
else
|
|
gDP.primDepth.z = min(1.0f, max(-1.0f, (_FIXED2FLOAT(_SHIFTR(z, 0, 15), 15) - gSP.viewport.vtrans[2]) / gSP.viewport.vscale[2]));
|
|
gDP.primDepth.deltaZ = _FIXED2FLOAT(_SHIFTR(dz, 0, 15), 15);
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetPrimDepth( %f, %f );\n",
|
|
gDP.primDepth.z,
|
|
gDP.primDepth.deltaZ);
|
|
#endif
|
|
}
|
|
|
|
void gDPPipelineMode( u32 mode )
|
|
{
|
|
gDP.otherMode.pipelineMode = mode;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPPipelineMode( %s );\n",
|
|
PipelineModeText[gDP.otherMode.pipelineMode] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetCycleType( u32 type )
|
|
{
|
|
gDP.otherMode.cycleType = type & 3;
|
|
|
|
gDP.changed |= CHANGED_CYCLETYPE;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetCycleType( %s );\n",
|
|
CycleTypeText[gDP.otherMode.cycleType] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetTexturePersp( u32 enable )
|
|
{
|
|
gDP.otherMode.texturePersp = enable & 1;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTexturePersp( %s );\n",
|
|
TexturePerspText[gDP.otherMode.texturePersp] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetTextureDetail( u32 type )
|
|
{
|
|
gDP.otherMode.textureDetail = type & 3;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureDetail( %s );\n",
|
|
TextureDetailText[gDP.otherMode.textureDetail] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetTextureLOD( u32 mode )
|
|
{
|
|
gDP.otherMode.textureLOD = mode & 1;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureLOD( %s );\n",
|
|
TextureLODText[gDP.otherMode.textureLOD] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetTextureLUT( u32 mode )
|
|
{
|
|
gDP.otherMode.textureLUT = mode & 3;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureLUT( %s );\n",
|
|
TextureLUTText[gDP.otherMode.textureLUT] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetTextureFilter( u32 type )
|
|
{
|
|
gDP.otherMode.textureFilter = type & 3;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureFilter( %s );\n",
|
|
TextureFilterText[gDP.otherMode.textureFilter] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetTextureConvert( u32 type )
|
|
{
|
|
gDP.otherMode.textureConvert = type & 7;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureConvert( %s );\n",
|
|
TextureConvertText[gDP.otherMode.textureConvert] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetCombineKey( u32 type )
|
|
{
|
|
gDP.otherMode.combineKey = type & 1;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, "gDPSetCombineKey( %s );\n",
|
|
CombineKeyText[gDP.otherMode.combineKey] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetColorDither( u32 type )
|
|
{
|
|
gDP.otherMode.colorDither = type & 3;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetColorDither( %s );\n",
|
|
ColorDitherText[gDP.otherMode.colorDither] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetAlphaDither( u32 type )
|
|
{
|
|
gDP.otherMode.alphaDither = type & 3;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetAlphaDither( %s );\n",
|
|
AlphaDitherText[gDP.otherMode.alphaDither] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetAlphaCompare( u32 mode )
|
|
{
|
|
gDP.otherMode.alphaCompare = mode & 3;
|
|
|
|
gDP.changed |= CHANGED_ALPHACOMPARE;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetAlphaCompare( %s );\n",
|
|
AlphaCompareText[gDP.otherMode.alphaCompare] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetDepthSource( u32 source )
|
|
{
|
|
gDP.otherMode.depthSource = source & 1;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetDepthSource( %s );\n",
|
|
DepthSourceText[gDP.otherMode.depthSource] );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetRenderMode( u32 mode1, u32 mode2 )
|
|
{
|
|
gDP.otherMode.l &= 0x00000007;
|
|
gDP.otherMode.l |= mode1 | mode2;
|
|
|
|
gDP.changed |= CHANGED_RENDERMODE;
|
|
|
|
#ifdef DEBUG
|
|
// THIS IS INCOMPLETE!!!
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetRenderMode( %s%s%s%s%s | %s | %s%s%s );\n",
|
|
gDP.otherMode.AAEnable ? "AA_EN | " : "",
|
|
gDP.otherMode.depthCompare ? "Z_CMP | " : "",
|
|
gDP.otherMode.depthUpdate ? "Z_UPD | " : "",
|
|
gDP.otherMode.imageRead ? "IM_RD | " : "",
|
|
CvgDestText[gDP.otherMode.cvgDest],
|
|
DepthModeText[gDP.otherMode.depthMode],
|
|
gDP.otherMode.cvgXAlpha ? "CVG_X_ALPHA | " : "",
|
|
gDP.otherMode.alphaCvgSel ? "ALPHA_CVG_SEL | " : "",
|
|
gDP.otherMode.forceBlender ? "FORCE_BL" : "" );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetCombine( s32 muxs0, s32 muxs1 )
|
|
{
|
|
gDP.combine.muxs0 = muxs0;
|
|
gDP.combine.muxs1 = muxs1;
|
|
|
|
gDP.changed |= CHANGED_COMBINE;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, "gDPSetCombine( %s, %s, %s, %s, %s, %s, %s, %s,\n",
|
|
saRGBText[gDP.combine.saRGB0],
|
|
sbRGBText[gDP.combine.sbRGB0],
|
|
mRGBText[gDP.combine.mRGB0],
|
|
aRGBText[gDP.combine.aRGB0],
|
|
saAText[gDP.combine.saA0],
|
|
sbAText[gDP.combine.sbA0],
|
|
mAText[gDP.combine.mA0],
|
|
aAText[gDP.combine.aA0] );
|
|
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, " %s, %s, %s, %s, %s, %s, %s, %s );\n",
|
|
saRGBText[gDP.combine.saRGB1],
|
|
sbRGBText[gDP.combine.sbRGB1],
|
|
mRGBText[gDP.combine.mRGB1],
|
|
aRGBText[gDP.combine.aRGB1],
|
|
saAText[gDP.combine.saA1],
|
|
sbAText[gDP.combine.sbA1],
|
|
mAText[gDP.combine.mA1],
|
|
aAText[gDP.combine.aA1] );
|
|
|
|
#endif
|
|
}
|
|
|
|
void gDPSetColorImage( u32 format, u32 size, u32 width, u32 address )
|
|
{
|
|
address = RSP_SegmentToPhysical( address );
|
|
|
|
if (gDP.colorImage.address != address || gDP.colorImage.width != width || gDP.colorImage.size != size) {
|
|
u32 height = 1;
|
|
if (width == VI.width)
|
|
height = VI.height;
|
|
else if (width == gDP.scissor.lrx && width == gSP.viewport.width) {
|
|
height = max(gDP.scissor.lry, gSP.viewport.height);
|
|
height = min(height, VI.height);
|
|
} else if (width == gDP.scissor.lrx)
|
|
height = gDP.scissor.lry;
|
|
else if (width <= 64)
|
|
height = width;
|
|
else
|
|
height = gSP.viewport.height;
|
|
|
|
if (config.frameBufferEmulation.enable) // && address != gDP.depthImageAddress)
|
|
{
|
|
frameBufferList().saveBuffer(address, (u16)format, (u16)size, (u16)width, height, false);
|
|
gDP.colorImage.height = 0;
|
|
} else
|
|
gDP.colorImage.height = height;
|
|
}
|
|
|
|
gDP.colorImage.format = format;
|
|
gDP.colorImage.size = size;
|
|
gDP.colorImage.width = width;
|
|
gDP.colorImage.address = address;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetColorImage( %s, %s, %i, 0x%08X );\n",
|
|
ImageFormatText[gDP.colorImage.format],
|
|
ImageSizeText[gDP.colorImage.size],
|
|
gDP.colorImage.width,
|
|
gDP.colorImage.address );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetTextureImage(u32 format, u32 size, u32 width, u32 address)
|
|
{
|
|
gDP.textureImage.format = format;
|
|
gDP.textureImage.size = size;
|
|
gDP.textureImage.width = width;
|
|
gDP.textureImage.address = RSP_SegmentToPhysical(address);
|
|
gDP.textureImage.bpl = gDP.textureImage.width << gDP.textureImage.size >> 1;
|
|
if (gSP.DMAOffsets.tex_offset != 0) {
|
|
if (format == G_IM_FMT_RGBA) {
|
|
u16 * t = (u16*)(RDRAM + gSP.DMAOffsets.tex_offset);
|
|
gSP.DMAOffsets.tex_shift = t[gSP.DMAOffsets.tex_count ^ 1];
|
|
gDP.textureImage.address += gSP.DMAOffsets.tex_shift;
|
|
} else {
|
|
gSP.DMAOffsets.tex_offset = 0;
|
|
gSP.DMAOffsets.tex_shift = 0;
|
|
gSP.DMAOffsets.tex_count = 0;
|
|
}
|
|
}
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureImage( %s, %s, %i, 0x%08X );\n",
|
|
ImageFormatText[gDP.textureImage.format],
|
|
ImageSizeText[gDP.textureImage.size],
|
|
gDP.textureImage.width,
|
|
gDP.textureImage.address );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetDepthImage( u32 address )
|
|
{
|
|
address = RSP_SegmentToPhysical( address );
|
|
depthBufferList().saveBuffer(address);
|
|
gDP.depthImageAddress = address;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetDepthImage( 0x%08X );\n", gDP.depthImageAddress );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetEnvColor( u32 r, u32 g, u32 b, u32 a )
|
|
{
|
|
gDP.envColor.r = r * 0.0039215689f;
|
|
gDP.envColor.g = g * 0.0039215689f;
|
|
gDP.envColor.b = b * 0.0039215689f;
|
|
gDP.envColor.a = a * 0.0039215689f;
|
|
|
|
gDP.changed |= CHANGED_COMBINE_COLORS;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, "gDPSetEnvColor( %i, %i, %i, %i );\n",
|
|
r, g, b, a );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetBlendColor( u32 r, u32 g, u32 b, u32 a )
|
|
{
|
|
gDP.blendColor.r = r * 0.0039215689f;
|
|
gDP.blendColor.g = g * 0.0039215689f;
|
|
gDP.blendColor.b = b * 0.0039215689f;
|
|
gDP.blendColor.a = a * 0.0039215689f;
|
|
|
|
gDP.changed |= CHANGED_BLENDCOLOR;
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetBlendColor( %i, %i, %i, %i );\n",
|
|
r, g, b, a );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetFogColor( u32 r, u32 g, u32 b, u32 a )
|
|
{
|
|
gDP.fogColor.r = r * 0.0039215689f;
|
|
gDP.fogColor.g = g * 0.0039215689f;
|
|
gDP.fogColor.b = b * 0.0039215689f;
|
|
gDP.fogColor.a = a * 0.0039215689f;
|
|
|
|
gDP.changed |= CHANGED_FOGCOLOR;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetFogColor( %i, %i, %i, %i );\n",
|
|
r, g, b, a );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetFillColor( u32 c )
|
|
{
|
|
gDP.fillColor.color = c;
|
|
gDP.fillColor.z = (f32)_SHIFTR( c, 2, 14 );
|
|
gDP.fillColor.dz = (f32)_SHIFTR( c, 0, 2 );
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetFillColor( 0x%08X );\n", c );
|
|
#endif
|
|
}
|
|
|
|
void gDPGetFillColor(f32 _fillColor[4])
|
|
{
|
|
const u32 c = gDP.fillColor.color;
|
|
if (gDP.colorImage.size < 3) {
|
|
_fillColor[0] = _SHIFTR( c, 11, 5 ) * 0.032258064f;
|
|
_fillColor[1] = _SHIFTR( c, 6, 5 ) * 0.032258064f;
|
|
_fillColor[2] = _SHIFTR( c, 1, 5 ) * 0.032258064f;
|
|
_fillColor[3] = (f32)_SHIFTR( c, 0, 1 );
|
|
} else {
|
|
_fillColor[0] = _SHIFTR( c, 24, 8 ) * 0.0039215686f;
|
|
_fillColor[1] = _SHIFTR( c, 16, 8 ) * 0.0039215686f;
|
|
_fillColor[2] = _SHIFTR( c, 8, 8 ) * 0.0039215686f;
|
|
_fillColor[3] = _SHIFTR( c, 0, 8 ) * 0.0039215686f;
|
|
}
|
|
}
|
|
|
|
void gDPSetPrimColor( u32 m, u32 l, u32 r, u32 g, u32 b, u32 a )
|
|
{
|
|
gDP.primColor.m = m * 0.0039215689f;
|
|
gDP.primColor.l = l * 0.0039215689f;
|
|
gDP.primColor.r = r * 0.0039215689f;
|
|
gDP.primColor.g = g * 0.0039215689f;
|
|
gDP.primColor.b = b * 0.0039215689f;
|
|
gDP.primColor.a = a * 0.0039215689f;
|
|
|
|
gDP.changed |= CHANGED_COMBINE_COLORS;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, "gDPSetPrimColor( %i, %i, %i, %i, %i, %i );\n",
|
|
m, l, r, g, b, a );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetTile( u32 format, u32 size, u32 line, u32 tmem, u32 tile, u32 palette, u32 cmt, u32 cms, u32 maskt, u32 masks, u32 shiftt, u32 shifts )
|
|
{
|
|
if (((size == G_IM_SIZ_4b) || (size == G_IM_SIZ_8b)) && (format == G_IM_FMT_RGBA))
|
|
format = G_IM_FMT_CI;
|
|
|
|
gDP.tiles[tile].format = format;
|
|
gDP.tiles[tile].size = size;
|
|
gDP.tiles[tile].line = line;
|
|
gDP.tiles[tile].tmem = tmem;
|
|
gDP.tiles[tile].palette = palette;
|
|
gDP.tiles[tile].cmt = cmt;
|
|
gDP.tiles[tile].cms = cms;
|
|
gDP.tiles[tile].maskt = maskt;
|
|
gDP.tiles[tile].masks = masks;
|
|
gDP.tiles[tile].shiftt = shiftt;
|
|
gDP.tiles[tile].shifts = shifts;
|
|
|
|
if (!gDP.tiles[tile].masks) gDP.tiles[tile].clamps = 1;
|
|
if (!gDP.tiles[tile].maskt) gDP.tiles[tile].clampt = 1;
|
|
|
|
if (tile == gSP.texture.tile || tile == gSP.texture.tile + 1) {
|
|
u32 nTile = 7;
|
|
while(gDP.tiles[nTile].tmem != tmem && nTile > gSP.texture.tile + 1)
|
|
--nTile;
|
|
if (nTile > gSP.texture.tile + 1) {
|
|
gDP.tiles[tile].textureMode = gDP.tiles[nTile].textureMode;
|
|
gDP.tiles[tile].loadType = gDP.tiles[nTile].loadType;
|
|
gDP.tiles[tile].frameBuffer = gDP.tiles[nTile].frameBuffer;
|
|
gDP.tiles[tile].imageAddress = gDP.tiles[nTile].imageAddress;
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTile( %s, %s, %i, %i, %i, %i, %s%s, %s%s, %i, %i, %i, %i );\n",
|
|
ImageFormatText[format],
|
|
ImageSizeText[size],
|
|
line,
|
|
tmem,
|
|
tile,
|
|
palette,
|
|
cmt & G_TX_MIRROR ? "G_TX_MIRROR" : "G_TX_NOMIRROR",
|
|
cmt & G_TX_CLAMP ? " | G_TX_CLAMP" : "",
|
|
cms & G_TX_MIRROR ? "G_TX_MIRROR" : "G_TX_NOMIRROR",
|
|
cms & G_TX_CLAMP ? " | G_TX_CLAMP" : "",
|
|
maskt,
|
|
masks,
|
|
shiftt,
|
|
shifts );
|
|
#endif
|
|
}
|
|
|
|
|
|
void gDPSetTileSize( u32 tile, u32 uls, u32 ult, u32 lrs, u32 lrt )
|
|
{
|
|
gDP.tiles[tile].uls = _SHIFTR( uls, 2, 10 );
|
|
gDP.tiles[tile].ult = _SHIFTR( ult, 2, 10 );
|
|
gDP.tiles[tile].lrs = _SHIFTR( lrs, 2, 10 );
|
|
gDP.tiles[tile].lrt = _SHIFTR( lrt, 2, 10 );
|
|
|
|
gDP.tiles[tile].fuls = _FIXED2FLOAT( uls, 2 );
|
|
gDP.tiles[tile].fult = _FIXED2FLOAT( ult, 2 );
|
|
gDP.tiles[tile].flrs = _FIXED2FLOAT( lrs, 2 );
|
|
gDP.tiles[tile].flrt = _FIXED2FLOAT( lrt, 2 );
|
|
|
|
gDP.changed |= CHANGED_TILE;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTileSize( %i, %.2f, %.2f, %.2f, %.2f );\n",
|
|
tile,
|
|
gDP.tiles[tile].fuls,
|
|
gDP.tiles[tile].fult,
|
|
gDP.tiles[tile].flrs,
|
|
gDP.tiles[tile].flrt );
|
|
#endif
|
|
}
|
|
|
|
static
|
|
bool CheckForFrameBufferTexture(u32 _address, u32 _bytes)
|
|
{
|
|
gDP.loadTile->textureMode = TEXTUREMODE_NORMAL;
|
|
gDP.loadTile->frameBuffer = NULL;
|
|
gDP.changed |= CHANGED_TMEM;
|
|
if (!config.frameBufferEmulation.enable)
|
|
return false;
|
|
|
|
FrameBuffer *pBuffer = frameBufferList().findBuffer(_address);
|
|
bool bRes = pBuffer != NULL && ((config.generalEmulation.hacks & hack_MarioGolf) == 0 || !pBuffer->m_isDepthBuffer);
|
|
if ((bRes)
|
|
//&& ((*(u32*)&RDRAM[pBuffer->startAddress] & 0xFFFEFFFE) == (pBuffer->startAddress & 0xFFFEFFFE)) // Does not work for Jet Force Gemini
|
|
)
|
|
{
|
|
const u32 texEndAddress = _address + _bytes - 1;
|
|
u32 height = (int)gDP.scissor.lry;
|
|
if (height % 2 != 0)
|
|
++height;
|
|
const u32 bufEndAddress = pBuffer->m_startAddress + (((pBuffer->m_width * height) << pBuffer->m_size >> 1) - 1);
|
|
if (_address > pBuffer->m_startAddress && texEndAddress > bufEndAddress) {
|
|
// FrameBuffer_RemoveBuffer(pBuffer->startAddress);
|
|
bRes = false;
|
|
}
|
|
|
|
if (bRes && gDP.loadTile->loadType == LOADTYPE_TILE && gDP.textureImage.width != pBuffer->m_width && gDP.textureImage.size != pBuffer->m_size) {
|
|
//FrameBuffer_RemoveBuffer(pBuffer->startAddress); // Does not work with Zelda MM
|
|
bRes = false;
|
|
}
|
|
|
|
if (bRes && pBuffer->m_cleared && pBuffer->m_size == 2
|
|
&& !config.frameBufferEmulation.copyToRDRAM
|
|
&& (!config.frameBufferEmulation.copyDepthToRDRAM || pBuffer->m_fillcolor != DEPTH_CLEAR_COLOR)
|
|
) {
|
|
const u32 endAddress = min(texEndAddress, pBuffer->m_endAddress);
|
|
const u32 color = pBuffer->m_fillcolor&0xFFFEFFFE;
|
|
for (u32 i = _address + 4; i < endAddress; i+=4) {
|
|
if (((*(u32*)&RDRAM[i])&0xFFFEFFFE) != color) {
|
|
frameBufferList().removeBuffer(pBuffer->m_startAddress);
|
|
bRes = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bRes) {
|
|
pBuffer->m_pLoadTile = gDP.loadTile;
|
|
gDP.loadTile->frameBuffer = pBuffer;
|
|
gDP.loadTile->textureMode = TEXTUREMODE_FRAMEBUFFER;
|
|
}
|
|
}
|
|
|
|
for (int nTile = gSP.texture.tile; nTile < 6; ++nTile) {
|
|
if (gDP.tiles[nTile].tmem == gDP.loadTile->tmem) {
|
|
gDPTile & curTile = gDP.tiles[nTile];
|
|
curTile.textureMode = gDP.loadTile->textureMode;
|
|
curTile.loadType = gDP.loadTile->loadType;
|
|
curTile.frameBuffer = gDP.loadTile->frameBuffer;
|
|
curTile.imageAddress = gDP.loadTile->imageAddress;
|
|
}
|
|
}
|
|
return bRes;
|
|
}
|
|
|
|
//****************************************************************
|
|
// LoadTile for 32bit RGBA texture
|
|
// Based on sources of angrylion's software plugin.
|
|
//
|
|
void gDPLoadTile32b(u32 uls, u32 ult, u32 lrs, u32 lrt)
|
|
{
|
|
const u32 width = lrs - uls + 1;
|
|
const u32 height = lrt - ult + 1;
|
|
const u32 line = gDP.loadTile->line << 2;
|
|
const u32 tbase = gDP.loadTile->tmem << 2;
|
|
const u32 addr = gDP.textureImage.address >> 2;
|
|
const u32 * src = (const u32*)RDRAM;
|
|
u16 * tmem16 = (u16*)TMEM;
|
|
u32 c, ptr, tline, s, xorval;
|
|
|
|
for (u32 j = 0; j < height; ++j) {
|
|
tline = tbase + line * j;
|
|
s = ((j + ult) * gDP.textureImage.width) + uls;
|
|
xorval = (j & 1) ? 3 : 1;
|
|
for (u32 i = 0; i < width; ++i) {
|
|
c = src[addr + s + i];
|
|
ptr = ((tline + i) ^ xorval) & 0x3ff;
|
|
tmem16[ptr] = c >> 16;
|
|
tmem16[ptr | 0x400] = c & 0xffff;
|
|
}
|
|
}
|
|
}
|
|
|
|
void gDPLoadTile(u32 tile, u32 uls, u32 ult, u32 lrs, u32 lrt)
|
|
{
|
|
gDPSetTileSize( tile, uls, ult, lrs, lrt );
|
|
gDP.loadTile = &gDP.tiles[tile];
|
|
gDP.loadTile->loadType = LOADTYPE_TILE;
|
|
gDP.loadTile->imageAddress = gDP.textureImage.address;
|
|
|
|
const u32 width = (gDP.loadTile->lrs - gDP.loadTile->uls + 1) & 0x03FF;
|
|
const u32 height = (gDP.loadTile->lrt - gDP.loadTile->ult + 1) & 0x03FF;
|
|
|
|
gDPLoadTileInfo &info = gDP.loadInfo[gDP.loadTile->tmem];
|
|
info.texAddress = gDP.loadTile->imageAddress;
|
|
info.uls = gDP.loadTile->uls;
|
|
info.ult = gDP.loadTile->ult;
|
|
info.width = gDP.loadTile->masks != 0 ? (u16)min(width, 1U<<gDP.loadTile->masks) : (u16)width;
|
|
info.height = gDP.loadTile->maskt != 0 ? (u16)min(height, 1U<<gDP.loadTile->maskt) : (u16)height;
|
|
info.texWidth = gDP.textureImage.width;
|
|
info.size = gDP.textureImage.size;
|
|
info.loadType = LOADTYPE_TILE;
|
|
|
|
if (gDP.loadTile->line == 0)
|
|
return;
|
|
|
|
const u32 address = gDP.textureImage.address + gDP.loadTile->ult * gDP.textureImage.bpl + (gDP.loadTile->uls << gDP.textureImage.size >> 1);
|
|
const u32 bpl = gDP.loadTile->line << 3;
|
|
u32 bytes = height * bpl;
|
|
|
|
if (((address + bytes) > RDRAMSize) ||
|
|
(((gDP.loadTile->tmem << 3) + bytes) > 4096)) // Stay within TMEM
|
|
{
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_ERROR | DEBUG_TEXTURE, "// Attempting to load texture tile out of range\n" );
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadTile( %i, %i, %i, %i, %i );\n",
|
|
tile, gDP.loadTile->uls, gDP.loadTile->ult, gDP.loadTile->lrs, gDP.loadTile->lrt );
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
u32 bpl2 = bpl;
|
|
if (gDP.loadTile->lrs > gDP.textureImage.width)
|
|
bpl2 = (gDP.textureImage.width - gDP.loadTile->uls);
|
|
u32 height2 = height;
|
|
if (gDP.loadTile->lrt > gDP.scissor.lry)
|
|
height2 = gDP.scissor.lry - gDP.loadTile->ult;
|
|
if (CheckForFrameBufferTexture(address, bpl2*height2))
|
|
return;
|
|
|
|
if (gDP.loadTile->size == G_IM_SIZ_32b)
|
|
gDPLoadTile32b(gDP.loadTile->uls, gDP.loadTile->ult, gDP.loadTile->lrs, gDP.loadTile->lrt);
|
|
else {
|
|
u64 * dest = &TMEM[gDP.loadTile->tmem];
|
|
u8 * src = &RDRAM[address];
|
|
const u32 line = gDP.loadTile->line;
|
|
for (u32 y = 0; y < height; ++y) {
|
|
UnswapCopy(src, dest, bpl);
|
|
if (y & 1) DWordInterleave(dest, line);
|
|
|
|
src += gDP.textureImage.bpl;
|
|
dest += line;
|
|
}
|
|
}
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadTile( %i, %i, %i, %i, %i );\n",
|
|
tile, gDP.loadTile->uls, gDP.loadTile->ult, gDP.loadTile->lrs, gDP.loadTile->lrt );
|
|
#endif
|
|
}
|
|
|
|
//****************************************************************
|
|
// LoadBlock for 32bit RGBA texture
|
|
// Based on sources of angrylion's software plugin.
|
|
//
|
|
void gDPLoadBlock32(u32 uls,u32 lrs, u32 dxt)
|
|
{
|
|
const u32 * src = (const u32*)RDRAM;
|
|
const u32 tb = gDP.loadTile->tmem << 2;
|
|
const u32 line = gDP.loadTile->line << 2;
|
|
|
|
u16 *tmem16 = (u16*)TMEM;
|
|
u32 addr = gDP.loadTile->imageAddress >> 2;
|
|
u32 width = (lrs - uls + 1) << 2;
|
|
if (width == 4) // lr_s == 0, 1x1 texture
|
|
width = 1;
|
|
else if (width & 7)
|
|
width = (width & (~7)) + 8;
|
|
|
|
if (dxt != 0) {
|
|
u32 j = 0;
|
|
u32 t = 0;
|
|
u32 oldt = 0;
|
|
u32 ptr;
|
|
|
|
u32 c = 0;
|
|
for (u32 i = 0; i < width; i += 2) {
|
|
oldt = t;
|
|
t = ((j >> 11) & 1) ? 3 : 1;
|
|
if (t != oldt)
|
|
i += line;
|
|
ptr = ((tb + i) ^ t) & 0x3ff;
|
|
c = src[addr + i];
|
|
tmem16[ptr] = c >> 16;
|
|
tmem16[ptr | 0x400] = c & 0xffff;
|
|
ptr = ((tb + i + 1) ^ t) & 0x3ff;
|
|
c = src[addr + i + 1];
|
|
tmem16[ptr] = c >> 16;
|
|
tmem16[ptr | 0x400] = c & 0xffff;
|
|
j += dxt;
|
|
}
|
|
} else {
|
|
u32 c, ptr;
|
|
for (u32 i = 0; i < width; i++) {
|
|
ptr = ((tb + i) ^ 1) & 0x3ff;
|
|
c = src[addr + i];
|
|
tmem16[ptr] = c >> 16;
|
|
tmem16[ptr | 0x400] = c & 0xffff;
|
|
}
|
|
}
|
|
}
|
|
|
|
void gDPLoadBlock(u32 tile, u32 uls, u32 ult, u32 lrs, u32 dxt)
|
|
{
|
|
gDPSetTileSize( tile, uls, ult, lrs, dxt );
|
|
gDP.loadTile = &gDP.tiles[tile];
|
|
gDP.loadTile->loadType = LOADTYPE_BLOCK;
|
|
|
|
if (gSP.DMAOffsets.tex_offset != 0) {
|
|
if (gSP.DMAOffsets.tex_shift % (((lrs>>2) + 1) << 3)) {
|
|
gDP.textureImage.address -= gSP.DMAOffsets.tex_shift;
|
|
gSP.DMAOffsets.tex_offset = 0;
|
|
gSP.DMAOffsets.tex_shift = 0;
|
|
gSP.DMAOffsets.tex_count = 0;
|
|
} else
|
|
++gSP.DMAOffsets.tex_count;
|
|
}
|
|
gDP.loadTile->imageAddress = gDP.textureImage.address;
|
|
|
|
gDPLoadTileInfo &info = gDP.loadInfo[gDP.loadTile->tmem];
|
|
info.texAddress = gDP.loadTile->imageAddress;
|
|
info.width = gDP.loadTile->lrs;
|
|
info.dxt = dxt;
|
|
info.size = gDP.textureImage.size;
|
|
info.loadType = LOADTYPE_BLOCK;
|
|
|
|
u32 bytes = (lrs - uls + 1) << gDP.loadTile->size >> 1;
|
|
if ((bytes & 7) != 0)
|
|
bytes = (bytes & (~7)) + 8;
|
|
u32 address = gDP.textureImage.address + ult * gDP.textureImage.bpl + (uls << gDP.textureImage.size >> 1);
|
|
|
|
if ((bytes == 0) ||
|
|
((address + bytes) > RDRAMSize) ||
|
|
(((gDP.loadTile->tmem << 3) + bytes) > 4096))
|
|
{
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_ERROR | DEBUG_TEXTURE, "// Attempting to load texture block out of range\n" );
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadBlock( %i, %i, %i, %i, %i );\n",
|
|
tile, uls, ult, lrs, dxt );
|
|
#endif
|
|
// bytes = min( bytes, min( RDRAMSize - gDP.textureImage.address, 4096 - (gDP.loadTile->tmem << 3) ) );
|
|
return;
|
|
}
|
|
|
|
gDP.loadTile->textureMode = TEXTUREMODE_NORMAL;
|
|
gDP.loadTile->frameBuffer = NULL;
|
|
gDP.changed |= CHANGED_TMEM;
|
|
CheckForFrameBufferTexture(address, bytes); // Load data to TMEM even if FB texture is found. See comment to texturedRectDepthBufferCopy
|
|
|
|
if (gDP.loadTile->size == G_IM_SIZ_32b)
|
|
gDPLoadBlock32(gDP.loadTile->uls, gDP.loadTile->lrs, dxt);
|
|
else if (gDP.loadTile->format == G_IM_FMT_YUV)
|
|
memcpy(TMEM, &RDRAM[address], bytes); // HACK!
|
|
else {
|
|
u64* src = (u64*)&RDRAM[address];
|
|
u64* dest = &TMEM[gDP.loadTile->tmem];
|
|
|
|
if (dxt > 0) {
|
|
u32 line = (2047 + dxt) / dxt;
|
|
u32 bpl = line << 3;
|
|
u32 height = bytes / bpl;
|
|
|
|
for (u32 y = 0; y < height; ++y) {
|
|
UnswapCopy(src, dest, bpl);
|
|
if (y & 1) DWordInterleave(dest, line);
|
|
|
|
src += line;
|
|
dest += line;
|
|
}
|
|
} else
|
|
UnswapCopy(src, dest, bytes);
|
|
}
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadBlock( %i, %i, %i, %i, %i );\n",
|
|
tile, uls, ult, lrs, dxt );
|
|
#endif
|
|
}
|
|
|
|
void gDPLoadTLUT( u32 tile, u32 uls, u32 ult, u32 lrs, u32 lrt )
|
|
{
|
|
gDPSetTileSize( tile, uls, ult, lrs, lrt );
|
|
if (gDP.tiles[tile].tmem < 256)
|
|
return;
|
|
const u16 count = (u16)((gDP.tiles[tile].lrs - gDP.tiles[tile].uls + 1) * (gDP.tiles[tile].lrt - gDP.tiles[tile].ult + 1));
|
|
u32 address = gDP.textureImage.address + gDP.tiles[tile].ult * gDP.textureImage.bpl + (gDP.tiles[tile].uls << gDP.textureImage.size >> 1);
|
|
u16 pal = (u16)((gDP.tiles[tile].tmem - 256) >> 4);
|
|
u16 *dest = (u16*)&TMEM[gDP.tiles[tile].tmem];
|
|
|
|
int i = 0;
|
|
while (i < count) {
|
|
for (u16 j = 0; (j < 16) && (i < count); ++j, ++i) {
|
|
*dest = swapword(*(u16*)(RDRAM + (address ^ 2)));
|
|
address += 2;
|
|
dest += 4;
|
|
}
|
|
|
|
gDP.paletteCRC16[pal] = CRC_CalculatePalette(0xFFFFFFFF, &TMEM[256 + (pal << 4)], 16);
|
|
++pal;
|
|
}
|
|
|
|
gDP.paletteCRC256 = CRC_Calculate(0xFFFFFFFF, gDP.paletteCRC16, 64);
|
|
|
|
if (TFH.isInited()) {
|
|
const u16 start = gDP.tiles[tile].tmem - 256; // starting location in the palettes
|
|
u16 *spal = (u16*)(RDRAM + gDP.textureImage.address);
|
|
memcpy((u8*)(gDP.TexFilterPalette + start), spal, count<<1);
|
|
}
|
|
|
|
gDP.changed |= CHANGED_TMEM;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadTLUT( %i, %i, %i, %i, %i );\n",
|
|
tile, gDP.tiles[tile].uls, gDP.tiles[tile].ult, gDP.tiles[tile].lrs, gDP.tiles[tile].lrt );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetScissor( u32 mode, f32 ulx, f32 uly, f32 lrx, f32 lry )
|
|
{
|
|
gDP.scissor.mode = mode;
|
|
gDP.scissor.ulx = ulx;
|
|
gDP.scissor.uly = uly;
|
|
gDP.scissor.lrx = lrx;
|
|
gDP.scissor.lry = lry;
|
|
|
|
gDP.changed |= CHANGED_SCISSOR;
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPSetScissor( %s, %.2f, %.2f, %.2f, %.2f );\n",
|
|
ScissorModeText[gDP.scissor.mode],
|
|
gDP.scissor.ulx,
|
|
gDP.scissor.uly,
|
|
gDP.scissor.lrx,
|
|
gDP.scissor.lry );
|
|
#endif
|
|
}
|
|
|
|
const bool g_bDepthClearOnly = false;
|
|
void gDPFillRDRAM(u32 address, s32 ulx, s32 uly, s32 lrx, s32 lry, u32 width, u32 size, u32 color, bool scissor)
|
|
{
|
|
if (g_bDepthClearOnly && color != DEPTH_CLEAR_COLOR)
|
|
return;
|
|
FrameBufferList & fbList = frameBufferList();
|
|
if (fbList.isFboMode()) {
|
|
fbList.getCurrent()->m_cleared = true;
|
|
fbList.getCurrent()->m_fillcolor = color;
|
|
}
|
|
if (scissor) {
|
|
ulx = min(max((float)ulx, gDP.scissor.ulx), gDP.scissor.lrx);
|
|
lrx = min(max((float)lrx, gDP.scissor.ulx), gDP.scissor.lrx);
|
|
uly = min(max((float)uly, gDP.scissor.uly), gDP.scissor.lry);
|
|
lry = min(max((float)lry, gDP.scissor.uly), gDP.scissor.lry);
|
|
}
|
|
const u32 stride = width << size >> 1;
|
|
const u32 lowerBound = address + lry*stride;
|
|
if (lowerBound > RDRAMSize)
|
|
lry -= (lowerBound - RDRAMSize) / stride;
|
|
u32 ci_width_in_dwords = width >> (3 - size);
|
|
ulx >>= (3 - size);
|
|
lrx >>= (3 - size);
|
|
u32 * dst = (u32*)(RDRAM + address);
|
|
dst += uly * ci_width_in_dwords;
|
|
for (u32 y = uly; y < lry; ++y) {
|
|
for (u32 x = ulx; x < lrx; ++x)
|
|
dst[x] = color;
|
|
dst += ci_width_in_dwords;
|
|
}
|
|
*(u32*)&RDRAM[address] = address;
|
|
}
|
|
|
|
void gDPFillRectangle( s32 ulx, s32 uly, s32 lrx, s32 lry )
|
|
{
|
|
OGLRender & render = video().getRender();
|
|
if (gDP.otherMode.cycleType == G_CYC_FILL) {
|
|
++lrx;
|
|
++lry;
|
|
} else if (lry == uly)
|
|
++lry;
|
|
if (gDP.depthImageAddress == gDP.colorImage.address) {
|
|
// Game may use depth texture as auxilary color texture. Example: Mario Tennis
|
|
// If color is not depth clear color, that is most likely the case
|
|
if (gDP.fillColor.color == DEPTH_CLEAR_COLOR ||
|
|
(((gDP.fillColor.color & 0xFFFF) == (gDP.fillColor.color >> 16)) && abs((int)(DEPTH_CLEAR_COLOR & 0xFFFF) - (int)(gDP.fillColor.color & 0xFFFF)) < 100)) {
|
|
gDPFillRDRAM(gDP.colorImage.address, ulx, uly, lrx, lry, gDP.colorImage.width, gDP.colorImage.size, gDP.fillColor.color);
|
|
render.clearDepthBuffer();
|
|
return;
|
|
}
|
|
} else if (gDP.fillColor.color == DEPTH_CLEAR_COLOR && gDP.otherMode.cycleType == G_CYC_FILL) {
|
|
depthBufferList().saveBuffer(gDP.colorImage.address);
|
|
gDPFillRDRAM(gDP.colorImage.address, ulx, uly, lrx, lry, gDP.colorImage.width, gDP.colorImage.size, gDP.fillColor.color);
|
|
render.clearDepthBuffer();
|
|
return;
|
|
}
|
|
|
|
f32 fillColor[4];
|
|
gDPGetFillColor(fillColor);
|
|
if (gDP.otherMode.cycleType == G_CYC_FILL) {
|
|
if ((ulx == 0) && (uly == 0) && (lrx == gDP.scissor.lrx) && (lry == gDP.scissor.lry)) {
|
|
gDPFillRDRAM(gDP.colorImage.address, ulx, uly, lrx, lry, gDP.colorImage.width, gDP.colorImage.size, gDP.fillColor.color);
|
|
if ((*REG.VI_STATUS & 8) != 0) {
|
|
fillColor[0] = sqrtf(fillColor[0]);
|
|
fillColor[1] = sqrtf(fillColor[1]);
|
|
fillColor[2] = sqrtf(fillColor[2]);
|
|
}
|
|
render.clearColorBuffer(fillColor);
|
|
return;
|
|
}
|
|
}
|
|
|
|
f32 * pColor = fillColor;
|
|
if (gDP.otherMode.cycleType != G_CYC_FILL) {
|
|
if (gDP.combine.mux == EncodeCombineMode(0, 0, 0, SHADE, 0, 0, 0, SHADE, 0, 0, 0, SHADE, 0, 0, 0, SHADE))
|
|
memset(pColor, 0, sizeof(f32)* 4);
|
|
else
|
|
pColor = &gDP.blendColor.r;
|
|
}
|
|
render.drawRect(ulx, uly, lrx, lry, pColor);
|
|
|
|
gDP.colorImage.changed = TRUE;
|
|
if (gDP.otherMode.cycleType == G_CYC_FILL) {
|
|
if (lry > (u32)gDP.scissor.lry)
|
|
gDP.colorImage.height = (u32)max(gDP.colorImage.height, (u32)gDP.scissor.lry);
|
|
else
|
|
gDP.colorImage.height = (u32)max((s32)gDP.colorImage.height, lry);
|
|
} else
|
|
gDP.colorImage.height = max( gDP.colorImage.height, (u32)gDP.scissor.lry );
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPFillRectangle( %i, %i, %i, %i );\n",
|
|
ulx, uly, lrx, lry );
|
|
#endif
|
|
}
|
|
|
|
void gDPSetConvert( s32 k0, s32 k1, s32 k2, s32 k3, s32 k4, s32 k5 )
|
|
{
|
|
// angrylion's macro
|
|
#define SRA(exp, sa) ((signed)(exp) >> (sa))
|
|
#define SIGN(i, b) SRA((i) << (32 - (b)), (32 - (b)))
|
|
|
|
gDP.convert.k0 = SIGN(k0, 9);
|
|
gDP.convert.k1 = SIGN(k1, 9);
|
|
gDP.convert.k2 = SIGN(k2, 9);
|
|
gDP.convert.k3 = SIGN(k3, 9);
|
|
gDP.convert.k4 = SIGN(k4, 9);
|
|
gDP.convert.k5 = SIGN(k5, 9);
|
|
}
|
|
|
|
void gDPSetKeyR( u32 cR, u32 sR, u32 wR )
|
|
{
|
|
gDP.key.center.r = cR * 0.0039215689f;;
|
|
gDP.key.scale.r = sR * 0.0039215689f;;
|
|
gDP.key.width.r = wR * 0.0039215689f;;
|
|
}
|
|
|
|
void gDPSetKeyGB(u32 cG, u32 sG, u32 wG, u32 cB, u32 sB, u32 wB )
|
|
{
|
|
gDP.key.center.g = cG * 0.0039215689f;;
|
|
gDP.key.scale.g = sG * 0.0039215689f;;
|
|
gDP.key.width.g = wG * 0.0039215689f;;
|
|
gDP.key.center.b = cB * 0.0039215689f;;
|
|
gDP.key.scale.b = sB * 0.0039215689f;;
|
|
gDP.key.width.b = wB * 0.0039215689f;;
|
|
}
|
|
|
|
void gDPTextureRectangle( f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, f32 s, f32 t, f32 dsdx, f32 dtdy )
|
|
{
|
|
if (gDP.otherMode.cycleType == G_CYC_COPY) {
|
|
dsdx = 1.0f;
|
|
lrx += 1.0f;
|
|
lry += 1.0f;
|
|
}
|
|
lry = max(lry, uly + 1.0f);
|
|
|
|
gDPTile *textureTileOrg[2];
|
|
textureTileOrg[0] = gSP.textureTile[0];
|
|
textureTileOrg[1] = gSP.textureTile[1];
|
|
gSP.textureTile[0] = &gDP.tiles[tile];
|
|
gSP.textureTile[1] = &gDP.tiles[(tile + 1) & 7];
|
|
|
|
if (gSP.textureTile[0]->textureMode == TEXTUREMODE_NORMAL)
|
|
gSP.textureTile[0]->textureMode = TEXTUREMODE_TEXRECT;
|
|
if (gSP.textureTile[1]->textureMode == TEXTUREMODE_NORMAL)
|
|
gSP.textureTile[1]->textureMode = TEXTUREMODE_TEXRECT;
|
|
|
|
// HACK ALERT!
|
|
if ((int(s) == 512) && (gDP.colorImage.width < 512))
|
|
s = 0.0f;
|
|
|
|
f32 lrs, lrt;
|
|
if (RSP.cmd == G_TEXRECTFLIP) {
|
|
lrs = s + (lry - uly - 1) * dsdx;
|
|
lrt = t + (lrx - ulx - 1) * dtdy;
|
|
} else {
|
|
lrs = s + (lrx - ulx - 1) * dsdx;
|
|
lrt = t + (lry - uly - 1) * dtdy;
|
|
}
|
|
|
|
gDP.texRect.width = (u32)(max( lrs, s ) + dsdx);
|
|
gDP.texRect.height = (u32)(max( lrt, t ) + dtdy);
|
|
|
|
float tmp;
|
|
if (lrs < s) {
|
|
tmp = ulx; ulx = lrx; lrx = tmp;
|
|
tmp = s; s = lrs; lrs = tmp;
|
|
}
|
|
if (lrt < t) {
|
|
tmp = uly; uly = lry; lry = tmp;
|
|
tmp = t; t = lrt; lrt = tmp;
|
|
}
|
|
|
|
OGLRender::TexturedRectParams params(ulx, uly, lrx, lry, s, t, lrs, lrt, (RSP.cmd == G_TEXRECTFLIP));
|
|
video().getRender().drawTexturedRect(params);
|
|
|
|
gSP.textureTile[0] = textureTileOrg[0];
|
|
gSP.textureTile[1] = textureTileOrg[1];
|
|
|
|
gDP.colorImage.changed = TRUE;
|
|
if (gDP.colorImage.width < 64)
|
|
gDP.colorImage.height = (u32)max( (f32)gDP.colorImage.height, lry );
|
|
else
|
|
gDP.colorImage.height = max( gDP.colorImage.height, (u32)gDP.scissor.lry );
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPTextureRectangle( %f, %f, %f, %f, %i, %i, %f, %f, %f, %f );\n",
|
|
ulx, uly, lrx, lry, tile, s, t, dsdx, dtdy );
|
|
#endif
|
|
}
|
|
|
|
void gDPTextureRectangleFlip( f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, f32 s, f32 t, f32 dsdx, f32 dtdy )
|
|
{
|
|
gDPTextureRectangle( ulx, uly, lrx, lry, tile, s, t, dsdx, dtdy );
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPTextureRectangleFlip( %f, %f, %f, %f, %i, %f, %f, %f, %f);\n",
|
|
ulx, uly, lrx, lry, tile, s, t, dsdx, dtdy );
|
|
#endif
|
|
}
|
|
|
|
void gDPFullSync()
|
|
{
|
|
*REG.MI_INTR |= MI_INTR_DP;
|
|
|
|
CheckInterrupts();
|
|
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPFullSync();\n" );
|
|
#endif
|
|
}
|
|
|
|
void gDPTileSync()
|
|
{
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_IGNORED | DEBUG_TEXTURE, "gDPTileSync();\n" );
|
|
#endif
|
|
}
|
|
|
|
void gDPPipeSync()
|
|
{
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPPipeSync();\n" );
|
|
#endif
|
|
}
|
|
|
|
void gDPLoadSync()
|
|
{
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPLoadSync();\n" );
|
|
#endif
|
|
}
|
|
|
|
void gDPNoOp()
|
|
{
|
|
#ifdef DEBUG
|
|
DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPNoOp();\n" );
|
|
#endif
|
|
}
|
|
|
|
/*******************************************
|
|
* Low level triangle *
|
|
*******************************************
|
|
* based on sources of ziggy's z64 *
|
|
*******************************************/
|
|
|
|
void gDPLLETriangle(u32 _w1, u32 _w2, int _shade, int _texture, int _zbuffer, u32 * _pRdpCmd)
|
|
{
|
|
const u32 tile = _SHIFTR(_w1, 16, 3);
|
|
gDPTile *textureTileOrg[2];
|
|
textureTileOrg[0] = gSP.textureTile[0];
|
|
textureTileOrg[1] = gSP.textureTile[1];
|
|
gSP.textureTile[0] = &gDP.tiles[tile];
|
|
gSP.textureTile[1] = &gDP.tiles[(tile + 1) & 7];
|
|
|
|
int j;
|
|
int xleft, xright, xleft_inc, xright_inc;
|
|
int r, g, b, a, z, s, t, w;
|
|
int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0, dzdx = 0, dsdx = 0, dtdx = 0, dwdx = 0;
|
|
int drde = 0, dgde = 0, dbde = 0, dade = 0, dzde = 0, dsde = 0, dtde = 0, dwde = 0;
|
|
int flip = (_w1 & 0x800000) ? 1 : 0;
|
|
|
|
s32 yl, ym, yh;
|
|
s32 xl, xm, xh;
|
|
s32 dxldy, dxhdy, dxmdy;
|
|
u32 w3, w4, w5, w6, w7, w8;
|
|
|
|
u32 * shade_base = _pRdpCmd + 8;
|
|
u32 * texture_base = _pRdpCmd + 8;
|
|
u32 * zbuffer_base = _pRdpCmd + 8;
|
|
|
|
if (_shade != 0) {
|
|
texture_base += 16;
|
|
zbuffer_base += 16;
|
|
}
|
|
if (_texture != 0) {
|
|
zbuffer_base += 16;
|
|
}
|
|
|
|
w3 = _pRdpCmd[2];
|
|
w4 = _pRdpCmd[3];
|
|
w5 = _pRdpCmd[4];
|
|
w6 = _pRdpCmd[5];
|
|
w7 = _pRdpCmd[6];
|
|
w8 = _pRdpCmd[7];
|
|
|
|
yl = (_w1 & 0x3fff);
|
|
ym = ((_w2 >> 16) & 0x3fff);
|
|
yh = ((_w2 >> 0) & 0x3fff);
|
|
xl = (s32)(w3);
|
|
xh = (s32)(w5);
|
|
xm = (s32)(w7);
|
|
dxldy = (s32)(w4);
|
|
dxhdy = (s32)(w6);
|
|
dxmdy = (s32)(w8);
|
|
|
|
if (yl & (0x800<<2)) yl |= 0xfffff000<<2;
|
|
if (ym & (0x800<<2)) ym |= 0xfffff000<<2;
|
|
if (yh & (0x800<<2)) yh |= 0xfffff000<<2;
|
|
|
|
yh &= ~3;
|
|
|
|
r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0xffff0000; s = 0; t = 0; w = 0x30000;
|
|
|
|
if (_shade != 0) {
|
|
r = (shade_base[0] & 0xffff0000) | ((shade_base[+4 ] >> 16) & 0x0000ffff);
|
|
g = ((shade_base[0 ] << 16) & 0xffff0000) | (shade_base[4 ] & 0x0000ffff);
|
|
b = (shade_base[1 ] & 0xffff0000) | ((shade_base[5 ] >> 16) & 0x0000ffff);
|
|
a = ((shade_base[1 ] << 16) & 0xffff0000) | (shade_base[5 ] & 0x0000ffff);
|
|
drdx = (shade_base[2 ] & 0xffff0000) | ((shade_base[6 ] >> 16) & 0x0000ffff);
|
|
dgdx = ((shade_base[2 ] << 16) & 0xffff0000) | (shade_base[6 ] & 0x0000ffff);
|
|
dbdx = (shade_base[3 ] & 0xffff0000) | ((shade_base[7 ] >> 16) & 0x0000ffff);
|
|
dadx = ((shade_base[3 ] << 16) & 0xffff0000) | (shade_base[7 ] & 0x0000ffff);
|
|
drde = (shade_base[8 ] & 0xffff0000) | ((shade_base[12] >> 16) & 0x0000ffff);
|
|
dgde = ((shade_base[8 ] << 16) & 0xffff0000) | (shade_base[12] & 0x0000ffff);
|
|
dbde = (shade_base[9 ] & 0xffff0000) | ((shade_base[13] >> 16) & 0x0000ffff);
|
|
dade = ((shade_base[9 ] << 16) & 0xffff0000) | (shade_base[13] & 0x0000ffff);
|
|
}
|
|
if (_texture != 0) {
|
|
s = (texture_base[0 ] & 0xffff0000) | ((texture_base[4 ] >> 16) & 0x0000ffff);
|
|
t = ((texture_base[0 ] << 16) & 0xffff0000) | (texture_base[4 ] & 0x0000ffff);
|
|
w = (texture_base[1 ] & 0xffff0000) | ((texture_base[5 ] >> 16) & 0x0000ffff);
|
|
// w = abs(w);
|
|
dsdx = (texture_base[2 ] & 0xffff0000) | ((texture_base[6 ] >> 16) & 0x0000ffff);
|
|
dtdx = ((texture_base[2 ] << 16) & 0xffff0000) | (texture_base[6 ] & 0x0000ffff);
|
|
dwdx = (texture_base[3 ] & 0xffff0000) | ((texture_base[7 ] >> 16) & 0x0000ffff);
|
|
dsde = (texture_base[8 ] & 0xffff0000) | ((texture_base[12] >> 16) & 0x0000ffff);
|
|
dtde = ((texture_base[8 ] << 16) & 0xffff0000) | (texture_base[12] & 0x0000ffff);
|
|
dwde = (texture_base[9 ] & 0xffff0000) | ((texture_base[13] >> 16) & 0x0000ffff);
|
|
}
|
|
if (_zbuffer != 0) {
|
|
z = zbuffer_base[0];
|
|
dzdx = zbuffer_base[1];
|
|
dzde = zbuffer_base[2];
|
|
}
|
|
|
|
xh <<= 2; xm <<= 2; xl <<= 2;
|
|
r <<= 2; g <<= 2; b <<= 2; a <<= 2;
|
|
dsde >>= 2; dtde >>= 2; dsdx >>= 2; dtdx >>= 2;
|
|
dzdx >>= 2; dzde >>= 2;
|
|
dwdx >>= 2; dwde >>= 2;
|
|
|
|
#define XSCALE(x) (float(x)/(1<<18))
|
|
#define YSCALE(y) (float(y)/(1<<2))
|
|
#define ZSCALE(z) ((gDP.otherMode.depthSource == G_ZS_PRIM)? gDP.primDepth.z : float(u32(z))/0xffff0000)
|
|
#define PERSP_EN (gDP.otherMode.texturePersp != 0)
|
|
#define WSCALE(z) 1.0f/(PERSP_EN? (float(u32(z) + 0x10000)/0xffff0000) : 1.0f)
|
|
#define CSCALE(c) ((((c)>0x3ff0000? 0x3ff0000:((c)<0? 0 : (c)))>>18)*0.0039215689f)
|
|
#define _PERSP(w) ( w )
|
|
#define PERSP(s, w) ( ((s64)(s) << 20) / (_PERSP(w)? _PERSP(w):1) )
|
|
#define SSCALE(s, _w) (PERSP_EN? float(PERSP(s, _w))/(1 << 10) : float(s)/(1<<21))
|
|
#define TSCALE(s, w) (PERSP_EN? float(PERSP(s, w))/(1 << 10) : float(s)/(1<<21))
|
|
|
|
OGLRender & render = video().getRender();
|
|
SPVertex * vtx0 = &render.getVertex(0);
|
|
SPVertex * vtx = vtx0;
|
|
|
|
xleft = xm;
|
|
xright = xh;
|
|
xleft_inc = dxmdy;
|
|
xright_inc = dxhdy;
|
|
|
|
while (yh<ym &&
|
|
!((!flip && xleft < xright+0x10000) ||
|
|
(flip && xleft > xright-0x10000))) {
|
|
xleft += xleft_inc;
|
|
xright += xright_inc;
|
|
s += dsde; t += dtde; w += dwde;
|
|
r += drde; g += dgde; b += dbde; a += dade;
|
|
z += dzde;
|
|
yh++;
|
|
}
|
|
|
|
j = ym-yh;
|
|
if (j > 0) {
|
|
int dx = (xleft-xright)>>16;
|
|
if ((!flip && xleft < xright) ||
|
|
(flip/* && xleft > xright*/))
|
|
{
|
|
if (_shade != 0) {
|
|
vtx->r = CSCALE(r+drdx*dx);
|
|
vtx->g = CSCALE(g+dgdx*dx);
|
|
vtx->b = CSCALE(b+dbdx*dx);
|
|
vtx->a = CSCALE(a+dadx*dx);
|
|
}
|
|
if (_texture != 0) {
|
|
vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx);
|
|
vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx);
|
|
}
|
|
vtx->x = XSCALE(xleft);
|
|
vtx->y = YSCALE(yh);
|
|
vtx->z = ZSCALE(z+dzdx*dx);
|
|
vtx->w = WSCALE(w+dwdx*dx);
|
|
++vtx;
|
|
}
|
|
if ((!flip/* && xleft < xright*/) ||
|
|
(flip && xleft > xright))
|
|
{
|
|
if (_shade != 0) {
|
|
vtx->r = CSCALE(r);
|
|
vtx->g = CSCALE(g);
|
|
vtx->b = CSCALE(b);
|
|
vtx->a = CSCALE(a);
|
|
}
|
|
if (_texture != 0) {
|
|
vtx->s = SSCALE(s, w);
|
|
vtx->t = TSCALE(t, w);
|
|
}
|
|
vtx->x = XSCALE(xright);
|
|
vtx->y = YSCALE(yh);
|
|
vtx->z = ZSCALE(z);
|
|
vtx->w = WSCALE(w);
|
|
++vtx;
|
|
}
|
|
xleft += xleft_inc*j; xright += xright_inc*j;
|
|
s += dsde*j; t += dtde*j;
|
|
if (w + dwde*j) w += dwde*j;
|
|
else w += dwde*(j-1);
|
|
r += drde*j; g += dgde*j; b += dbde*j; a += dade*j;
|
|
z += dzde*j;
|
|
// render ...
|
|
}
|
|
|
|
if (xl != xh)
|
|
xleft = xl;
|
|
|
|
//if (yl-ym > 0)
|
|
{
|
|
int dx = (xleft-xright)>>16;
|
|
if ((!flip && xleft <= xright) ||
|
|
(flip/* && xleft >= xright*/))
|
|
{
|
|
if (_shade != 0) {
|
|
vtx->r = CSCALE(r+drdx*dx);
|
|
vtx->g = CSCALE(g+dgdx*dx);
|
|
vtx->b = CSCALE(b+dbdx*dx);
|
|
vtx->a = CSCALE(a+dadx*dx);
|
|
}
|
|
if (_texture != 0) {
|
|
vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx);
|
|
vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx);
|
|
}
|
|
vtx->x = XSCALE(xleft);
|
|
vtx->y = YSCALE(ym);
|
|
vtx->z = ZSCALE(z+dzdx*dx);
|
|
vtx->w = WSCALE(w+dwdx*dx);
|
|
++vtx;
|
|
}
|
|
if ((!flip/* && xleft <= xright*/) ||
|
|
(flip && xleft >= xright))
|
|
{
|
|
if (_shade != 0) {
|
|
vtx->r = CSCALE(r);
|
|
vtx->g = CSCALE(g);
|
|
vtx->b = CSCALE(b);
|
|
vtx->a = CSCALE(a);
|
|
}
|
|
if (_texture != 0) {
|
|
vtx->s = SSCALE(s, w);
|
|
vtx->t = TSCALE(t, w);
|
|
}
|
|
vtx->x = XSCALE(xright);
|
|
vtx->y = YSCALE(ym);
|
|
vtx->z = ZSCALE(z);
|
|
vtx->w = WSCALE(w);
|
|
++vtx;
|
|
}
|
|
}
|
|
xleft_inc = dxldy;
|
|
xright_inc = dxhdy;
|
|
|
|
j = yl-ym;
|
|
//j--; // ?
|
|
xleft += xleft_inc*j; xright += xright_inc*j;
|
|
s += dsde*j; t += dtde*j; w += dwde*j;
|
|
r += drde*j; g += dgde*j; b += dbde*j; a += dade*j;
|
|
z += dzde*j;
|
|
|
|
while (yl>ym &&
|
|
!((!flip && xleft < xright+0x10000) ||
|
|
(flip && xleft > xright-0x10000))) {
|
|
xleft -= xleft_inc; xright -= xright_inc;
|
|
s -= dsde; t -= dtde; w -= dwde;
|
|
r -= drde; g -= dgde; b -= dbde; a -= dade;
|
|
z -= dzde;
|
|
--j;
|
|
--yl;
|
|
}
|
|
|
|
// render ...
|
|
if (j >= 0) {
|
|
int dx = (xleft-xright)>>16;
|
|
if ((!flip && xleft <= xright) ||
|
|
(flip/* && xleft >= xright*/))
|
|
{
|
|
if (_shade != 0) {
|
|
vtx->r = CSCALE(r+drdx*dx);
|
|
vtx->g = CSCALE(g+dgdx*dx);
|
|
vtx->b = CSCALE(b+dbdx*dx);
|
|
vtx->a = CSCALE(a+dadx*dx);
|
|
}
|
|
if (_texture != 0) {
|
|
vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx);
|
|
vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx);
|
|
}
|
|
vtx->x = XSCALE(xleft);
|
|
vtx->y = YSCALE(yl);
|
|
vtx->z = ZSCALE(z+dzdx*dx);
|
|
vtx->w = WSCALE(w+dwdx*dx);
|
|
++vtx;
|
|
}
|
|
if ((!flip/* && xleft <= xright*/) ||
|
|
(flip && xleft >= xright))
|
|
{
|
|
if (_shade != 0) {
|
|
vtx->r = CSCALE(r);
|
|
vtx->g = CSCALE(g);
|
|
vtx->b = CSCALE(b);
|
|
vtx->a = CSCALE(a);
|
|
}
|
|
if (_texture != 0) {
|
|
vtx->s = SSCALE(s, w);
|
|
vtx->t = TSCALE(t, w);
|
|
}
|
|
vtx->x = XSCALE(xright);
|
|
vtx->y = YSCALE(yl);
|
|
vtx->z = ZSCALE(z);
|
|
vtx->w = WSCALE(w);
|
|
++vtx;
|
|
}
|
|
}
|
|
|
|
if (_texture != 0)
|
|
gSP.changed |= CHANGED_TEXTURE;
|
|
if (_zbuffer != 0)
|
|
gSP.geometryMode |= G_ZBUFFER;
|
|
|
|
render.drawLLETriangle(vtx - vtx0);
|
|
gSP.textureTile[0] = textureTileOrg[0];
|
|
gSP.textureTile[1] = textureTileOrg[1];
|
|
}
|
|
|
|
static void gDPTriangle(u32 _w1, u32 _w2, int shade, int texture, int zbuffer)
|
|
{
|
|
gDPLLETriangle(_w1, _w2, shade, texture, zbuffer, RDP.cmd_data + RDP.cmd_cur);
|
|
}
|
|
|
|
void gDPTriFill(u32 w0, u32 w1)
|
|
{
|
|
gDPTriangle(w0, w1, 0, 0, 0);
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "trifill\n");
|
|
}
|
|
|
|
void gDPTriShade(u32 w0, u32 w1)
|
|
{
|
|
gDPTriangle(w0, w1, 1, 0, 0);
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "trishade\n");
|
|
}
|
|
|
|
void gDPTriTxtr(u32 w0, u32 w1)
|
|
{
|
|
gDPTriangle(w0, w1, 0, 1, 0);
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "tritxtr\n");
|
|
}
|
|
|
|
void gDPTriShadeTxtr(u32 w0, u32 w1)
|
|
{
|
|
gDPTriangle(w0, w1, 1, 1, 0);
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "trishadetxtr\n");
|
|
}
|
|
|
|
void gDPTriFillZ(u32 w0, u32 w1)
|
|
{
|
|
gDPTriangle(w0, w1, 0, 0, 1);
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "trifillz\n");
|
|
}
|
|
|
|
void gDPTriShadeZ(u32 w0, u32 w1)
|
|
{
|
|
gDPTriangle(w0, w1, 1, 0, 1);
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "trishadez\n");
|
|
}
|
|
|
|
void gDPTriTxtrZ(u32 w0, u32 w1)
|
|
{
|
|
gDPTriangle(w0, w1, 0, 1, 1);
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "tritxtrz\n");
|
|
}
|
|
|
|
void gDPTriShadeTxtrZ(u32 w0, u32 w1)
|
|
{
|
|
gDPTriangle(w0, w1, 1, 1, 1);
|
|
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "trishadetxtrz\n");
|
|
}
|