2013-06-15 13:46:48 +00:00
|
|
|
#include <assert.h>
|
2014-09-01 16:19:20 +00:00
|
|
|
#include <algorithm>
|
2016-05-10 07:54:19 +00:00
|
|
|
#include <cmath>
|
2013-04-21 14:28:50 +00:00
|
|
|
#include "GLideN64.h"
|
2013-04-05 06:13:26 +00:00
|
|
|
#include "N64.h"
|
|
|
|
#include "GBI.h"
|
|
|
|
#include "RSP.h"
|
2014-10-07 10:59:54 +00:00
|
|
|
#include "RDP.h"
|
2013-04-05 06:13:26 +00:00
|
|
|
#include "gDP.h"
|
|
|
|
#include "gSP.h"
|
|
|
|
#include "Types.h"
|
2017-05-25 08:54:30 +00:00
|
|
|
#include "DebugDump.h"
|
2013-04-05 06:13:26 +00:00
|
|
|
#include "convert.h"
|
|
|
|
#include "CRC.h"
|
|
|
|
#include "FrameBuffer.h"
|
|
|
|
#include "DepthBuffer.h"
|
2016-02-03 16:18:40 +00:00
|
|
|
#include "FrameBufferInfo.h"
|
2016-06-10 11:58:47 +00:00
|
|
|
#include "TextureFilterHandler.h"
|
2013-04-05 06:13:26 +00:00
|
|
|
#include "VI.h"
|
2014-04-05 02:57:00 +00:00
|
|
|
#include "Config.h"
|
2014-10-24 11:00:42 +00:00
|
|
|
#include "Combiner.h"
|
2016-09-25 13:21:54 +00:00
|
|
|
#include "Performance.h"
|
2017-01-15 07:57:25 +00:00
|
|
|
#include "DisplayWindow.h"
|
2017-02-07 17:23:12 +00:00
|
|
|
#include <Graphics/Context.h>
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
#ifdef NATIVE
|
|
|
|
#define RDRAM ((u8*)0)
|
|
|
|
#endif
|
|
|
|
|
2014-09-01 16:19:20 +00:00
|
|
|
using namespace std;
|
|
|
|
|
2013-04-05 06:13:26 +00:00
|
|
|
gDPInfo gDP;
|
|
|
|
|
2020-02-02 12:50:00 +00:00
|
|
|
// angrylion's macro
|
|
|
|
#define SIGN(x, numb) (((x) & ((1 << numb) - 1)) | -((x) & (1 << (numb - 1))))
|
|
|
|
|
2018-09-24 14:39:42 +00:00
|
|
|
bool isCurrentColorImageDepthImage()
|
|
|
|
{
|
|
|
|
return (gDP.colorImage.address == gDP.depthImageAddress) ||
|
|
|
|
(gDP.fillColor.color == DepthClearColor && gDP.otherMode.cycleType == G_CYC_FILL);
|
|
|
|
}
|
|
|
|
|
2019-02-03 11:01:01 +00:00
|
|
|
bool isDepthCompareEnabled()
|
|
|
|
{
|
|
|
|
return gDP.otherMode.cycleType <= G_CYC_2CYCLE &&
|
|
|
|
gDP.otherMode.depthCompare != 0 &&
|
|
|
|
((gSP.geometryMode & G_ZBUFFER) || gDP.otherMode.depthSource == G_ZS_PRIM);
|
|
|
|
}
|
|
|
|
|
2021-11-06 09:57:36 +00:00
|
|
|
f32 calcShiftScaleS(const gDPTile & _tile, s16 * _s)
|
|
|
|
{
|
|
|
|
if (_tile.shifts > 10) {
|
|
|
|
const u32 shifts = 16 - _tile.shifts;
|
|
|
|
if (_s != nullptr)
|
|
|
|
*_s = static_cast<s16>(*_s << shifts);
|
|
|
|
return static_cast<f32>(1 << shifts);
|
|
|
|
} else if (_tile.shifts > 0) {
|
|
|
|
const u32 shifts = _tile.shifts;
|
|
|
|
if (_s != nullptr)
|
|
|
|
*_s = static_cast<s16>(*_s >> shifts);
|
|
|
|
return 1.0f / static_cast<f32>(1 << shifts);
|
|
|
|
}
|
|
|
|
return 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
f32 calcShiftScaleT(const gDPTile & _tile, s16 * _t)
|
|
|
|
{
|
|
|
|
if (_tile.shiftt > 10) {
|
|
|
|
const u32 shiftt = 16 - _tile.shiftt;
|
|
|
|
if (_t != nullptr)
|
|
|
|
*_t = static_cast<s16>(*_t << shiftt);
|
|
|
|
return static_cast<f32>(1 << shiftt);
|
|
|
|
} else if (_tile.shiftt > 0) {
|
|
|
|
const u32 shiftt = _tile.shiftt;
|
|
|
|
if (_t != nullptr)
|
|
|
|
*_t = static_cast<s16>(*_t >> shiftt);
|
|
|
|
return 1.0f / static_cast<f32>(1 << shiftt);
|
|
|
|
}
|
|
|
|
return 1.0f;
|
|
|
|
}
|
|
|
|
|
2013-04-05 06:13:26 +00:00
|
|
|
void gDPSetOtherMode( u32 mode0, u32 mode1 )
|
|
|
|
{
|
|
|
|
gDP.otherMode.h = mode0;
|
|
|
|
gDP.otherMode.l = mode1;
|
|
|
|
|
|
|
|
gDP.changed |= CHANGED_RENDERMODE | CHANGED_CYCLETYPE | CHANGED_ALPHACOMPARE;
|
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
#ifdef DEBUG_DUMP
|
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetOtherMode( %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s, %s | %s | %s%s%s%s%s | %s | %s%s%s );\n",
|
2013-04-05 06:13:26 +00:00
|
|
|
AlphaDitherText[gDP.otherMode.alphaDither],
|
|
|
|
ColorDitherText[gDP.otherMode.colorDither],
|
|
|
|
CombineKeyText[gDP.otherMode.combineKey],
|
2017-10-19 04:48:28 +00:00
|
|
|
TextureConvertText[gDP.otherMode.convert_one | (gDP.otherMode.bi_lerp1 << 1) | (gDP.otherMode.bi_lerp0 << 2)],
|
2013-04-05 06:13:26 +00:00
|
|
|
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 )
|
|
|
|
{
|
2018-10-01 15:37:03 +00:00
|
|
|
gDP.primDepth.z = _FIXED2FLOAT(_SHIFTR(z, 0, 15), 15);
|
2015-01-20 09:50:22 +00:00
|
|
|
gDP.primDepth.deltaZ = _FIXED2FLOAT(_SHIFTR(dz, 0, 15), 15);
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetPrimDepth( %f, %f );\n", gDP.primDepth.z, gDP.primDepth.deltaZ);
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDPSetTexturePersp( u32 enable )
|
|
|
|
{
|
2014-12-20 14:29:17 +00:00
|
|
|
gDP.otherMode.texturePersp = enable & 1;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
#ifdef DEBUG_DUMP
|
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetTexturePersp( %s );\n", TexturePerspText[gDP.otherMode.texturePersp] );
|
2013-04-05 06:13:26 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void gDPSetTextureLUT( u32 mode )
|
|
|
|
{
|
2014-12-20 14:29:17 +00:00
|
|
|
gDP.otherMode.textureLUT = mode & 3;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
#ifdef DEBUG_DUMP
|
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetTextureLUT( %s );\n", TextureLUTText[gDP.otherMode.textureLUT] );
|
2013-04-05 06:13:26 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-11-11 05:17:20 +00:00
|
|
|
void gDPSetCombine( u32 muxs0, u32 muxs1 )
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
|
|
|
gDP.combine.muxs0 = muxs0;
|
|
|
|
gDP.combine.muxs1 = muxs1;
|
|
|
|
|
|
|
|
gDP.changed |= CHANGED_COMBINE;
|
|
|
|
|
2017-05-21 09:00:01 +00:00
|
|
|
DebugMsg(DEBUG_NORMAL, "gDPSetCombine\n");
|
2017-05-25 08:54:30 +00:00
|
|
|
#ifdef DEBUG_DUMP
|
2017-05-21 09:00:01 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, " %s, %s, %s, %s, %s, %s, %s, %s,\n",
|
2013-04-05 06:13:26 +00:00
|
|
|
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] );
|
|
|
|
|
2017-05-21 09:00:01 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, " %s, %s, %s, %s, %s, %s, %s, %s );\n",
|
2013-04-05 06:13:26 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPSetColorImage( u32 format, u32 size, u32 width, word address )
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
|
|
|
address = RSP_SegmentToPhysical( address );
|
|
|
|
|
|
|
|
gDP.colorImage.format = format;
|
|
|
|
gDP.colorImage.size = size;
|
|
|
|
gDP.colorImage.width = width;
|
2017-03-02 15:09:08 +00:00
|
|
|
gDP.colorImage.height = 0;
|
2013-06-01 13:10:30 +00:00
|
|
|
gDP.colorImage.address = address;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2020-11-14 09:54:28 +00:00
|
|
|
frameBufferList().saveBuffer(address, static_cast<u16>(format), static_cast<u16>(size), static_cast<u16>(width), false);
|
2018-09-29 16:21:21 +00:00
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
#ifdef DEBUG_DUMP
|
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetColorImage( %s, %s, %i, 0x%08X );\n",
|
2013-04-05 06:13:26 +00:00
|
|
|
ImageFormatText[gDP.colorImage.format],
|
|
|
|
ImageSizeText[gDP.colorImage.size],
|
|
|
|
gDP.colorImage.width,
|
|
|
|
gDP.colorImage.address );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPSetTextureImage(u32 format, u32 size, u32 width, word address)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
|
|
|
gDP.textureImage.format = format;
|
|
|
|
gDP.textureImage.size = size;
|
|
|
|
gDP.textureImage.width = width;
|
2014-10-10 15:04:08 +00:00
|
|
|
gDP.textureImage.address = RSP_SegmentToPhysical(address);
|
2013-04-05 06:13:26 +00:00
|
|
|
gDP.textureImage.bpl = gDP.textureImage.width << gDP.textureImage.size >> 1;
|
2014-10-10 15:04:08 +00:00
|
|
|
if (gSP.DMAOffsets.tex_offset != 0) {
|
|
|
|
if (format == G_IM_FMT_RGBA) {
|
2020-11-14 09:54:28 +00:00
|
|
|
u16 * t = reinterpret_cast<u16*>(RDRAM + gSP.DMAOffsets.tex_offset);
|
2014-10-10 15:04:08 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2017-05-25 08:54:30 +00:00
|
|
|
#ifdef DEBUG_DUMP
|
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetTextureImage( %s, %s, %i, 0x%08X );\n",
|
2013-04-05 06:13:26 +00:00
|
|
|
ImageFormatText[gDP.textureImage.format],
|
|
|
|
ImageSizeText[gDP.textureImage.size],
|
|
|
|
gDP.textureImage.width,
|
|
|
|
gDP.textureImage.address );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPSetDepthImage( word address )
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2013-06-04 16:00:03 +00:00
|
|
|
address = RSP_SegmentToPhysical( address );
|
|
|
|
gDP.depthImageAddress = address;
|
2015-04-08 17:06:17 +00:00
|
|
|
depthBufferList().saveBuffer(address);
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetDepthImage( 0x%08X );\n", gDP.depthImageAddress );
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDPSetEnvColor( u32 r, u32 g, u32 b, u32 a )
|
|
|
|
{
|
2018-05-31 09:59:44 +00:00
|
|
|
gDP.envColor.r = _FIXED2FLOATCOLOR( r, 8 );
|
|
|
|
gDP.envColor.g = _FIXED2FLOATCOLOR( g, 8 );
|
|
|
|
gDP.envColor.b = _FIXED2FLOATCOLOR( b, 8 );
|
|
|
|
gDP.envColor.a = _FIXED2FLOATCOLOR( a, 8 );
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetEnvColor( %i, %i, %i, %i );\n", r, g, b, a );
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDPSetBlendColor( u32 r, u32 g, u32 b, u32 a )
|
|
|
|
{
|
2018-05-31 09:59:44 +00:00
|
|
|
gDP.blendColor.r = _FIXED2FLOATCOLOR( r, 8 );
|
|
|
|
gDP.blendColor.g = _FIXED2FLOATCOLOR( g, 8 );
|
|
|
|
gDP.blendColor.b = _FIXED2FLOATCOLOR( b, 8 );
|
|
|
|
gDP.blendColor.a = _FIXED2FLOATCOLOR( a, 8 );
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-05-01 17:35:16 +00:00
|
|
|
gDP.changed |= CHANGED_BLENDCOLOR;
|
2017-05-25 08:54:30 +00:00
|
|
|
|
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetBlendColor( %i, %i, %i, %i );\n", r, g, b, a );
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDPSetFogColor( u32 r, u32 g, u32 b, u32 a )
|
|
|
|
{
|
2018-05-31 09:59:44 +00:00
|
|
|
gDP.fogColor.r = _FIXED2FLOATCOLOR( r, 8 );
|
|
|
|
gDP.fogColor.g = _FIXED2FLOATCOLOR( g, 8 );
|
|
|
|
gDP.fogColor.b = _FIXED2FLOATCOLOR( b, 8 );
|
|
|
|
gDP.fogColor.a = _FIXED2FLOATCOLOR( a, 8 );
|
2013-04-05 06:13:26 +00:00
|
|
|
|
|
|
|
gDP.changed |= CHANGED_FOGCOLOR;
|
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetFogColor( %i, %i, %i, %i );\n", r, g, b, a );
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDPSetFillColor( u32 c )
|
|
|
|
{
|
2013-06-04 15:41:56 +00:00
|
|
|
gDP.fillColor.color = c;
|
2020-11-14 09:54:28 +00:00
|
|
|
gDP.fillColor.z = static_cast<f32>(_SHIFTR( c, 2, 14 ));
|
|
|
|
gDP.fillColor.dz = static_cast<f32>(_SHIFTR( c, 0, 2 ));
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetFillColor( 0x%08X );\n", c );
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2013-06-04 15:41:56 +00:00
|
|
|
void gDPGetFillColor(f32 _fillColor[4])
|
|
|
|
{
|
|
|
|
const u32 c = gDP.fillColor.color;
|
|
|
|
if (gDP.colorImage.size < 3) {
|
2018-05-31 09:59:44 +00:00
|
|
|
_fillColor[0] = _FIXED2FLOATCOLOR( _SHIFTR( c, 11, 5 ), 5 );
|
|
|
|
_fillColor[1] = _FIXED2FLOATCOLOR( _SHIFTR( c, 6, 5 ), 5 );
|
|
|
|
_fillColor[2] = _FIXED2FLOATCOLOR( _SHIFTR( c, 1, 5 ), 5 );
|
2020-11-14 09:54:28 +00:00
|
|
|
_fillColor[3] = static_cast<f32>(_SHIFTR( c, 0, 1 ));
|
2013-06-04 15:41:56 +00:00
|
|
|
} else {
|
2018-05-31 09:59:44 +00:00
|
|
|
_fillColor[0] = _FIXED2FLOATCOLOR( _SHIFTR( c, 24, 8 ), 8 );
|
|
|
|
_fillColor[1] = _FIXED2FLOATCOLOR( _SHIFTR( c, 16, 8 ), 8 );
|
|
|
|
_fillColor[2] = _FIXED2FLOATCOLOR( _SHIFTR( c, 8, 8 ), 8 );
|
|
|
|
_fillColor[3] = _FIXED2FLOATCOLOR( _SHIFTR( c, 0, 8 ), 8 );
|
2013-06-04 15:41:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-05 06:13:26 +00:00
|
|
|
void gDPSetPrimColor( u32 m, u32 l, u32 r, u32 g, u32 b, u32 a )
|
|
|
|
{
|
2018-05-31 09:59:44 +00:00
|
|
|
gDP.primColor.m = _FIXED2FLOAT( m, 5 );
|
|
|
|
gDP.primColor.l = _FIXED2FLOATCOLOR( l, 8 );
|
|
|
|
gDP.primColor.r = _FIXED2FLOATCOLOR( r, 8 );
|
|
|
|
gDP.primColor.g = _FIXED2FLOATCOLOR( g, 8 );
|
|
|
|
gDP.primColor.b = _FIXED2FLOATCOLOR( b, 8 );
|
|
|
|
gDP.primColor.a = _FIXED2FLOATCOLOR( a, 8 );
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetPrimColor( %i, %i, %i, %i, %i, %i );\n", m, l, r, g, b, a );
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 )
|
|
|
|
{
|
|
|
|
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;
|
2018-09-20 02:46:13 +00:00
|
|
|
gDP.tiles[tile].maskt = gDP.tiles[tile].originalMaskT = maskt;
|
|
|
|
gDP.tiles[tile].masks = gDP.tiles[tile].originalMaskS = masks;
|
2013-04-05 06:13:26 +00:00
|
|
|
gDP.tiles[tile].shiftt = shiftt;
|
|
|
|
gDP.tiles[tile].shifts = shifts;
|
|
|
|
|
|
|
|
if (!gDP.tiles[tile].masks) gDP.tiles[tile].clamps = 1;
|
2014-09-01 16:21:40 +00:00
|
|
|
if (!gDP.tiles[tile].maskt) gDP.tiles[tile].clampt = 1;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-06-08 08:05:04 +00:00
|
|
|
if (tile == gSP.texture.tile || tile == gSP.texture.tile + 1) {
|
2016-03-05 11:55:30 +00:00
|
|
|
u32 nTile = gDP.loadTileIdx;
|
2013-06-15 13:46:48 +00:00
|
|
|
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;
|
2017-09-29 15:24:30 +00:00
|
|
|
gDP.tiles[tile].frameBufferAddress = gDP.tiles[nTile].frameBufferAddress;
|
2013-06-15 13:46:48 +00:00
|
|
|
gDP.tiles[tile].imageAddress = gDP.tiles[nTile].imageAddress;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-07 12:47:41 +00:00
|
|
|
gDP.changed |= CHANGED_TILE;
|
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
#ifdef DEBUG_DUMP
|
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetTile( %s, %s, %i, %i, %i, %i, %s%s, %s%s, %i, %i, %i, %i );\n",
|
2013-04-05 06:13:26 +00:00
|
|
|
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 );
|
2022-03-29 21:42:02 +00:00
|
|
|
gDP.tiles[tile].lrs = _SHIFTR( lrs, 2, 15 );
|
2013-04-05 06:13:26 +00:00
|
|
|
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;
|
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetTileSize( %i, %.2f, %.2f, %.2f, %.2f );\n",
|
2013-04-05 06:13:26 +00:00
|
|
|
tile,
|
|
|
|
gDP.tiles[tile].fuls,
|
|
|
|
gDP.tiles[tile].fult,
|
|
|
|
gDP.tiles[tile].flrs,
|
|
|
|
gDP.tiles[tile].flrt );
|
|
|
|
}
|
|
|
|
|
2013-06-15 13:46:48 +00:00
|
|
|
static
|
2018-09-16 15:15:28 +00:00
|
|
|
bool CheckForFrameBufferTexture(u32 _address, u32 _width, u32 _bytes)
|
2013-06-15 13:46:48 +00:00
|
|
|
{
|
2013-08-10 11:10:44 +00:00
|
|
|
gDP.loadTile->textureMode = TEXTUREMODE_NORMAL;
|
2017-09-29 15:24:30 +00:00
|
|
|
gDP.loadTile->frameBufferAddress = 0U;
|
2013-08-10 11:10:44 +00:00
|
|
|
gDP.changed |= CHANGED_TMEM;
|
2014-04-05 15:36:20 +00:00
|
|
|
if (!config.frameBufferEmulation.enable)
|
2013-08-10 11:10:44 +00:00
|
|
|
return false;
|
|
|
|
|
2015-09-26 15:09:31 +00:00
|
|
|
FrameBufferList & fbList = frameBufferList();
|
|
|
|
FrameBuffer *pBuffer = fbList.findBuffer(_address);
|
2016-10-29 16:46:39 +00:00
|
|
|
bool bRes = pBuffer != nullptr && pBuffer->m_readable;
|
2018-11-09 16:10:02 +00:00
|
|
|
while (bRes) {
|
2015-03-09 14:24:23 +00:00
|
|
|
if ((config.generalEmulation.hacks & hack_blurPauseScreen) != 0) {
|
2015-04-29 13:58:06 +00:00
|
|
|
if (gDP.colorImage.address == gDP.depthImageAddress && pBuffer->m_copiedToRdram) {
|
2018-11-09 16:10:02 +00:00
|
|
|
memcpy(RDRAM + gDP.depthImageAddress,
|
|
|
|
RDRAM + pBuffer->m_startAddress,
|
|
|
|
(pBuffer->m_width*pBuffer->m_height) << pBuffer->m_size >> 1);
|
2015-04-29 13:58:06 +00:00
|
|
|
pBuffer->m_copiedToRdram = false;
|
2015-09-26 15:09:31 +00:00
|
|
|
fbList.getCurrent()->m_isPauseScreen = true;
|
2015-03-09 11:52:11 +00:00
|
|
|
}
|
2018-11-09 16:10:02 +00:00
|
|
|
if (pBuffer->m_isPauseScreen) {
|
2015-03-09 11:52:11 +00:00
|
|
|
bRes = false;
|
2018-11-09 16:10:02 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-02-27 13:51:53 +00:00
|
|
|
}
|
|
|
|
|
2019-03-23 05:33:04 +00:00
|
|
|
if (gDP.otherMode.textureLUT == G_TT_RGBA16 && (config.generalEmulation.hacks & hack_StarCraftBackgrounds) != 0) {
|
2018-12-01 16:03:20 +00:00
|
|
|
bRes = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-04-03 13:48:38 +00:00
|
|
|
if (pBuffer->m_cfb) {
|
2015-09-26 15:09:31 +00:00
|
|
|
fbList.removeBuffer(pBuffer->m_startAddress);
|
2015-04-03 13:48:38 +00:00
|
|
|
bRes = false;
|
2018-11-09 16:10:02 +00:00
|
|
|
break;
|
2015-04-03 13:48:38 +00:00
|
|
|
}
|
|
|
|
|
2017-11-16 11:32:05 +00:00
|
|
|
if ((config.generalEmulation.hacks & hack_noDepthFrameBuffers) != 0 && pBuffer->m_isDepthBuffer) {
|
2015-09-26 15:09:31 +00:00
|
|
|
fbList.removeBuffer(pBuffer->m_startAddress);
|
2015-03-09 14:24:23 +00:00
|
|
|
bRes = false;
|
2018-11-09 16:10:02 +00:00
|
|
|
break;
|
2015-03-09 14:24:23 +00:00
|
|
|
}
|
|
|
|
|
2013-08-10 11:10:44 +00:00
|
|
|
const u32 texEndAddress = _address + _bytes - 1;
|
2018-09-16 15:15:28 +00:00
|
|
|
if (_address > pBuffer->m_startAddress &&
|
2020-11-14 09:54:28 +00:00
|
|
|
std::abs(static_cast<s32>(pBuffer->m_width) - static_cast<s32>(_width)) > 1 &&
|
2018-09-16 15:15:28 +00:00
|
|
|
texEndAddress > (pBuffer->m_endAddress + (pBuffer->m_width << pBuffer->m_size >> 1))) {
|
2015-09-26 15:09:31 +00:00
|
|
|
//fbList.removeBuffer(pBuffer->m_startAddress);
|
2013-08-10 11:10:44 +00:00
|
|
|
bRes = false;
|
2018-11-09 16:10:02 +00:00
|
|
|
break;
|
2013-08-10 11:10:44 +00:00
|
|
|
}
|
|
|
|
|
2018-11-09 16:10:02 +00:00
|
|
|
if (gDP.loadTile->loadType == LOADTYPE_TILE &&
|
|
|
|
gDP.textureImage.width != pBuffer->m_width &&
|
|
|
|
gDP.textureImage.size != pBuffer->m_size) {
|
2015-09-26 15:09:31 +00:00
|
|
|
//fbList.removeBuffer(pBuffer->m_startAddress); // Does not work with Zelda MM
|
2013-08-10 11:10:44 +00:00
|
|
|
bRes = false;
|
2018-11-09 16:10:02 +00:00
|
|
|
break;
|
2013-08-10 11:10:44 +00:00
|
|
|
}
|
|
|
|
|
2018-11-09 16:10:02 +00:00
|
|
|
bRes = pBuffer->isValid(false);
|
|
|
|
if (!bRes && pBuffer != fbList.getCurrent()) {
|
|
|
|
fbList.removeBuffer(pBuffer->m_startAddress);
|
|
|
|
break;
|
2013-08-10 11:10:44 +00:00
|
|
|
}
|
|
|
|
|
2018-11-09 16:10:02 +00:00
|
|
|
pBuffer->m_loadType = gDP.loadTile->loadType;
|
|
|
|
pBuffer->m_loadTileOrigin.uls = gDP.loadTile->uls;
|
|
|
|
pBuffer->m_loadTileOrigin.ult = gDP.loadTile->ult;
|
|
|
|
gDP.loadTile->frameBufferAddress = pBuffer->m_startAddress;
|
|
|
|
gDP.loadTile->textureMode = TEXTUREMODE_FRAMEBUFFER;
|
|
|
|
break;
|
2013-08-10 11:10:44 +00:00
|
|
|
}
|
2013-06-15 13:46:48 +00:00
|
|
|
|
2020-11-14 09:54:28 +00:00
|
|
|
for (u32 nTile = gSP.texture.tile; nTile < 6; ++nTile) {
|
2013-08-10 11:10:44 +00:00
|
|
|
if (gDP.tiles[nTile].tmem == gDP.loadTile->tmem) {
|
|
|
|
gDPTile & curTile = gDP.tiles[nTile];
|
|
|
|
curTile.textureMode = gDP.loadTile->textureMode;
|
|
|
|
curTile.loadType = gDP.loadTile->loadType;
|
2017-09-29 15:24:30 +00:00
|
|
|
curTile.frameBufferAddress = gDP.loadTile->frameBufferAddress;
|
2013-08-10 11:10:44 +00:00
|
|
|
curTile.imageAddress = gDP.loadTile->imageAddress;
|
2013-06-15 13:46:48 +00:00
|
|
|
}
|
|
|
|
}
|
2013-08-10 11:10:44 +00:00
|
|
|
return bRes;
|
2013-06-15 13:46:48 +00:00
|
|
|
}
|
|
|
|
|
2014-10-28 05:26:45 +00:00
|
|
|
//****************************************************************
|
|
|
|
// 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;
|
2022-01-16 17:27:17 +00:00
|
|
|
const word addr = gDP.textureImage.address >> 2;
|
2020-11-14 09:54:28 +00:00
|
|
|
const u32 * src = reinterpret_cast<const u32*>(RDRAM);
|
|
|
|
u16 * tmem16 = reinterpret_cast<u16*>(TMEM);
|
2014-10-28 05:26:45 +00:00
|
|
|
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];
|
2022-03-29 21:42:02 +00:00
|
|
|
ptr = ((tline + i) ^ xorval) & LOAD_BLOCK32_MASK;
|
2022-01-16 17:27:17 +00:00
|
|
|
#ifdef NATIVE
|
2022-03-29 21:42:02 +00:00
|
|
|
tmem16[ptr | LOAD_BLOCK32_MAX] = c >> 16;
|
2022-01-16 17:27:17 +00:00
|
|
|
tmem16[ptr] = c & 0xffff;
|
|
|
|
#else
|
2014-10-28 05:26:45 +00:00
|
|
|
tmem16[ptr] = c >> 16;
|
2022-03-29 21:42:02 +00:00
|
|
|
tmem16[ptr | LOAD_BLOCK32_MAX] = c & 0xffff;
|
2022-01-16 17:27:17 +00:00
|
|
|
#endif
|
2014-10-28 05:26:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-10-28 05:26:45 +00:00
|
|
|
void gDPLoadTile(u32 tile, u32 uls, u32 ult, u32 lrs, u32 lrt)
|
|
|
|
{
|
2013-04-05 06:13:26 +00:00
|
|
|
gDPSetTileSize( tile, uls, ult, lrs, lrt );
|
2016-03-05 11:55:30 +00:00
|
|
|
gDP.loadTileIdx = tile;
|
2013-04-05 06:13:26 +00:00
|
|
|
gDP.loadTile = &gDP.tiles[tile];
|
2013-06-15 13:46:48 +00:00
|
|
|
gDP.loadTile->loadType = LOADTYPE_TILE;
|
|
|
|
gDP.loadTile->imageAddress = gDP.textureImage.address;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2016-05-04 16:41:49 +00:00
|
|
|
if (gDP.loadTile->lrs < gDP.loadTile->uls || gDP.loadTile->lrt < gDP.loadTile->ult)
|
|
|
|
return;
|
|
|
|
|
2022-03-29 21:42:02 +00:00
|
|
|
const u32 width = (gDP.loadTile->lrs - gDP.loadTile->uls + 1) & LOAD_BLOCK32_MASK;
|
|
|
|
const u32 height = (gDP.loadTile->lrt - gDP.loadTile->ult + 1) & LOAD_BLOCK32_MASK;
|
2016-07-02 18:09:26 +00:00
|
|
|
const u32 bpl = gDP.loadTile->line << 3;
|
2014-11-11 11:28:08 +00:00
|
|
|
|
2018-10-17 12:29:00 +00:00
|
|
|
u32 alignedWidth = width;
|
|
|
|
u32 wmask = 0;
|
|
|
|
switch (gDP.textureImage.size) {
|
|
|
|
case G_IM_SIZ_8b:
|
|
|
|
wmask = 7;
|
|
|
|
break;
|
|
|
|
case G_IM_SIZ_16b:
|
|
|
|
wmask = 3;
|
|
|
|
break;
|
|
|
|
case G_IM_SIZ_32b:
|
|
|
|
wmask = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((width & wmask) != 0)
|
|
|
|
alignedWidth = (width & (~wmask)) + wmask + 1;
|
|
|
|
const u32 bpr = alignedWidth << gDP.loadTile->size >> 1;
|
|
|
|
|
2014-11-11 11:28:08 +00:00
|
|
|
gDPLoadTileInfo &info = gDP.loadInfo[gDP.loadTile->tmem];
|
|
|
|
info.texAddress = gDP.loadTile->imageAddress;
|
2020-11-14 09:54:28 +00:00
|
|
|
info.uls = static_cast<u16>(gDP.loadTile->uls);
|
|
|
|
info.ult = static_cast<u16>(gDP.loadTile->ult);
|
|
|
|
info.lrs = static_cast<u16>(gDP.loadTile->lrs);
|
|
|
|
info.lrt = static_cast<u16>(gDP.loadTile->lrt);
|
|
|
|
info.width = static_cast<u16>(gDP.loadTile->masks != 0 ? min(width, 1U << gDP.loadTile->masks) : width);
|
|
|
|
info.height = static_cast<u16>(gDP.loadTile->maskt != 0 ? min(height, 1U << gDP.loadTile->maskt) : height);
|
|
|
|
info.texWidth = static_cast<u16>(gDP.textureImage.width);
|
|
|
|
info.size = static_cast<u8>(gDP.textureImage.size);
|
2014-11-11 11:28:08 +00:00
|
|
|
info.loadType = LOADTYPE_TILE;
|
2016-07-02 18:09:26 +00:00
|
|
|
info.bytes = bpl * height;
|
2018-09-05 10:22:13 +00:00
|
|
|
if (gDP.loadTile->size == G_IM_SIZ_32b)
|
|
|
|
// 32 bit texture loaded into lower and upper half of TMEM, thus actual bytes doubled.
|
|
|
|
info.bytes *= 2;
|
2014-11-11 11:28:08 +00:00
|
|
|
|
2013-04-05 06:13:26 +00:00
|
|
|
if (gDP.loadTile->line == 0)
|
|
|
|
return;
|
|
|
|
|
2018-10-17 12:29:00 +00:00
|
|
|
if (gDP.loadTile->masks == 0)
|
|
|
|
gDP.loadTile->loadWidth = max(gDP.loadTile->loadWidth, info.width);
|
2019-11-30 15:48:00 +00:00
|
|
|
if (gDP.loadTile->maskt == 0) {
|
|
|
|
if (gDP.otherMode.cycleType != G_CYC_2CYCLE && gDP.loadTile->tmem % gDP.loadTile->line == 0) {
|
2020-11-14 09:54:28 +00:00
|
|
|
u16 theight = static_cast<u16>(info.height + gDP.loadTile->tmem / gDP.loadTile->line);
|
2019-10-12 13:14:58 +00:00
|
|
|
gDP.loadTile->loadHeight = max(gDP.loadTile->loadHeight, theight);
|
2019-11-30 15:48:00 +00:00
|
|
|
} else
|
|
|
|
gDP.loadTile->loadHeight = max(gDP.loadTile->loadHeight, info.height);
|
2018-10-17 12:29:00 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
word address = gDP.textureImage.address + gDP.loadTile->ult * gDP.textureImage.bpl + (gDP.loadTile->uls << gDP.textureImage.size >> 1);
|
2014-12-25 16:55:16 +00:00
|
|
|
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)
|
2020-11-14 09:54:28 +00:00
|
|
|
height2 = static_cast<u32>(gDP.scissor.lry) - gDP.loadTile->ult;
|
2016-05-19 16:50:43 +00:00
|
|
|
|
2018-09-16 15:15:28 +00:00
|
|
|
if (CheckForFrameBufferTexture(address, info.width, bpl2*height2))
|
2013-06-15 13:46:48 +00:00
|
|
|
return;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-10-28 05:26:45 +00:00
|
|
|
if (gDP.loadTile->size == G_IM_SIZ_32b)
|
|
|
|
gDPLoadTile32b(gDP.loadTile->uls, gDP.loadTile->ult, gDP.loadTile->lrs, gDP.loadTile->lrt);
|
|
|
|
else {
|
2022-01-16 17:27:17 +00:00
|
|
|
word tmemAddr = gDP.loadTile->tmem;
|
|
|
|
const word line = gDP.loadTile->line;
|
|
|
|
const word qwpr = bpr >> 3;
|
2014-12-24 05:36:07 +00:00
|
|
|
for (u32 y = 0; y < height; ++y) {
|
2018-09-07 14:07:48 +00:00
|
|
|
if (address + bpl > RDRAMSize)
|
2020-11-14 09:54:28 +00:00
|
|
|
UnswapCopyWrap(RDRAM, address, reinterpret_cast<u8*>(TMEM), tmemAddr << 3, 0xFFF, RDRAMSize - address);
|
2018-09-07 14:07:48 +00:00
|
|
|
else
|
2022-03-29 21:42:02 +00:00
|
|
|
UnswapCopyWrap(RDRAM, address, reinterpret_cast<u8*>(TMEM), tmemAddr << 3, (0x1000 * 8 - 1), bpr);
|
2015-06-17 07:22:21 +00:00
|
|
|
if (y & 1)
|
2022-03-29 21:42:02 +00:00
|
|
|
DWordInterleaveWrap(reinterpret_cast<u32*>(TMEM), tmemAddr << 1, LOAD_BLOCK32_MASK, qwpr);
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2015-06-17 07:22:21 +00:00
|
|
|
address += gDP.textureImage.bpl;
|
2018-09-07 14:07:48 +00:00
|
|
|
if (address >= RDRAMSize)
|
|
|
|
break;
|
2015-06-17 07:22:21 +00:00
|
|
|
tmemAddr += line;
|
2014-10-28 05:26:45 +00:00
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
2017-05-25 08:54:30 +00:00
|
|
|
|
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPLoadTile( %i, %i, %i, %i, %i );\n",
|
2013-04-05 06:13:26 +00:00
|
|
|
tile, gDP.loadTile->uls, gDP.loadTile->ult, gDP.loadTile->lrs, gDP.loadTile->lrt );
|
|
|
|
}
|
|
|
|
|
2014-10-28 05:26:45 +00:00
|
|
|
//****************************************************************
|
|
|
|
// LoadBlock for 32bit RGBA texture
|
|
|
|
// Based on sources of angrylion's software plugin.
|
|
|
|
//
|
2014-11-10 15:22:58 +00:00
|
|
|
void gDPLoadBlock32(u32 uls,u32 lrs, u32 dxt)
|
2014-10-28 05:26:45 +00:00
|
|
|
{
|
2020-11-14 09:54:28 +00:00
|
|
|
const u32 * src = reinterpret_cast<const u32*>(RDRAM);
|
2014-10-28 05:26:45 +00:00
|
|
|
const u32 tb = gDP.loadTile->tmem << 2;
|
|
|
|
const u32 line = gDP.loadTile->line << 2;
|
|
|
|
|
2020-11-14 09:54:28 +00:00
|
|
|
u16 *tmem16 = reinterpret_cast<u16*>(TMEM);
|
2022-01-16 17:27:17 +00:00
|
|
|
word addr = gDP.loadTile->imageAddress >> 2;
|
2014-10-28 05:26:45 +00:00
|
|
|
u32 width = (lrs - uls + 1) << 2;
|
2014-11-04 12:59:53 +00:00
|
|
|
if (width == 4) // lr_s == 0, 1x1 texture
|
|
|
|
width = 1;
|
2022-03-29 21:42:02 +00:00
|
|
|
else if(width & 7)
|
|
|
|
{
|
|
|
|
//width = (width & (~7U)) + 8;
|
|
|
|
}
|
2014-10-28 05:26:45 +00:00
|
|
|
|
|
|
|
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;
|
2022-03-29 21:42:02 +00:00
|
|
|
ptr = ((tb + i) ^ t) & LOAD_BLOCK32_MASK;
|
2014-10-28 05:26:45 +00:00
|
|
|
c = src[addr + i];
|
2022-01-16 17:27:17 +00:00
|
|
|
#ifdef NATIVE
|
2022-03-29 21:42:02 +00:00
|
|
|
tmem16[ptr | LOAD_BLOCK32_MAX] = c >> 16;
|
2022-01-16 17:27:17 +00:00
|
|
|
tmem16[ptr] = c & 0xffff;
|
2022-03-29 21:42:02 +00:00
|
|
|
ptr = ((tb + i + 1) ^ t) & LOAD_BLOCK32_MASK;
|
2022-01-16 17:27:17 +00:00
|
|
|
c = src[addr + i + 1];
|
2022-03-29 21:42:02 +00:00
|
|
|
tmem16[ptr | LOAD_BLOCK32_MAX] = c >> 16;
|
2022-01-16 17:27:17 +00:00
|
|
|
tmem16[ptr] = c & 0xffff;
|
|
|
|
#else
|
2014-10-28 05:26:45 +00:00
|
|
|
tmem16[ptr] = c >> 16;
|
2022-03-29 21:42:02 +00:00
|
|
|
tmem16[ptr | LOAD_BLOCK32_MAX] = c & 0xffff;
|
|
|
|
ptr = ((tb + i + 1) ^ t) & LOAD_BLOCK32_MASK;
|
2014-10-28 05:26:45 +00:00
|
|
|
c = src[addr + i + 1];
|
|
|
|
tmem16[ptr] = c >> 16;
|
2022-03-29 21:42:02 +00:00
|
|
|
tmem16[ptr | LOAD_BLOCK32_MAX] = c & 0xffff;
|
2022-01-16 17:27:17 +00:00
|
|
|
#endif
|
2014-10-28 05:26:45 +00:00
|
|
|
j += dxt;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
u32 c, ptr;
|
|
|
|
for (u32 i = 0; i < width; i++) {
|
2022-03-29 21:42:02 +00:00
|
|
|
ptr = ((tb + i) ^ 1) & LOAD_BLOCK32_MASK;
|
2014-10-28 05:26:45 +00:00
|
|
|
c = src[addr + i];
|
2022-01-16 17:27:17 +00:00
|
|
|
#ifdef NATIVE
|
2022-03-29 21:42:02 +00:00
|
|
|
tmem16[ptr | LOAD_BLOCK32_MAX] = c >> 16;
|
2022-01-16 17:27:17 +00:00
|
|
|
tmem16[ptr] = c & 0xffff;
|
|
|
|
#else
|
2014-10-28 05:26:45 +00:00
|
|
|
tmem16[ptr] = c >> 16;
|
2022-03-29 21:42:02 +00:00
|
|
|
tmem16[ptr | LOAD_BLOCK32_MAX] = c & 0xffff;
|
2022-01-16 17:27:17 +00:00
|
|
|
#endif
|
2014-10-28 05:26:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void gDPLoadBlock(u32 tile, u32 uls, u32 ult, u32 lrs, u32 dxt)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
|
|
|
gDPSetTileSize( tile, uls, ult, lrs, dxt );
|
2016-03-05 11:55:30 +00:00
|
|
|
gDP.loadTileIdx = tile;
|
2013-04-05 06:13:26 +00:00
|
|
|
gDP.loadTile = &gDP.tiles[tile];
|
2013-06-15 13:46:48 +00:00
|
|
|
gDP.loadTile->loadType = LOADTYPE_BLOCK;
|
2014-10-10 15:04:08 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2013-06-15 13:46:48 +00:00
|
|
|
gDP.loadTile->imageAddress = gDP.textureImage.address;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-11-11 11:28:08 +00:00
|
|
|
gDPLoadTileInfo &info = gDP.loadInfo[gDP.loadTile->tmem];
|
|
|
|
info.texAddress = gDP.loadTile->imageAddress;
|
2020-11-14 09:54:28 +00:00
|
|
|
info.uls = static_cast<u16>(gDP.loadTile->uls);
|
|
|
|
info.ult = static_cast<u16>(gDP.loadTile->ult);
|
|
|
|
info.lrs = static_cast<u16>(gDP.loadTile->lrs);
|
|
|
|
info.lrt = static_cast<u16>(gDP.loadTile->lrt);
|
|
|
|
info.width = static_cast<u16>(gDP.loadTile->lrs);
|
2014-11-11 11:28:08 +00:00
|
|
|
info.dxt = dxt;
|
2020-11-14 09:54:28 +00:00
|
|
|
info.size = static_cast<u8>(gDP.textureImage.size);
|
2014-11-11 11:28:08 +00:00
|
|
|
info.loadType = LOADTYPE_BLOCK;
|
|
|
|
|
2022-03-29 21:42:02 +00:00
|
|
|
const u32 width = (lrs - uls + 1);// & (0x1000 - 1);
|
2018-11-04 11:45:33 +00:00
|
|
|
u32 bytes = width << gDP.loadTile->size >> 1;
|
2022-03-29 21:42:02 +00:00
|
|
|
//if ((bytes & 7) != 0)
|
|
|
|
// bytes = (bytes & (~7U)) + 8;
|
2016-07-02 18:09:26 +00:00
|
|
|
|
|
|
|
info.bytes = bytes;
|
2022-01-16 17:27:17 +00:00
|
|
|
word address = gDP.textureImage.address + ult * gDP.textureImage.bpl + (uls << gDP.textureImage.size >> 1);
|
|
|
|
|
|
|
|
#ifdef NATIVE
|
|
|
|
if(address == 0 || address == 0xCDCDCDCD)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2015-04-04 08:27:53 +00:00
|
|
|
if (bytes == 0 || (address + bytes) > RDRAMSize) {
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg(DEBUG_NORMAL | DEBUG_ERROR, "// Attempting to load texture block out of range\n");
|
|
|
|
DebugMsg(DEBUG_NORMAL, "gDPLoadBlock( %i, %i, %i, %i, %i );\n", tile, uls, ult, lrs, dxt );
|
2013-04-05 06:13:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-09-29 15:24:30 +00:00
|
|
|
gDP.loadTile->frameBufferAddress = 0;
|
2018-09-16 15:15:28 +00:00
|
|
|
CheckForFrameBufferTexture(address, info.width, bytes); // Load data to TMEM even if FB texture is found. See comment to texturedRectDepthBufferCopy
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2019-05-08 14:04:24 +00:00
|
|
|
const u32 texLowerBound = gDP.loadTile->tmem;
|
|
|
|
const u32 texUpperBound = gDP.loadTile->tmem + (bytes >> 3);
|
|
|
|
for (u32 i = 0; i < tile; ++i) {
|
|
|
|
if (gDP.tiles[i].tmem >= texLowerBound && gDP.tiles[i].tmem < texUpperBound) {
|
|
|
|
gDPLoadTileInfo &info = gDP.loadInfo[gDP.tiles[i].tmem];
|
|
|
|
info.loadType = LOADTYPE_BLOCK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-28 05:26:45 +00:00
|
|
|
if (gDP.loadTile->size == G_IM_SIZ_32b)
|
2014-11-10 15:22:58 +00:00
|
|
|
gDPLoadBlock32(gDP.loadTile->uls, gDP.loadTile->lrs, dxt);
|
2014-10-28 06:12:30 +00:00
|
|
|
else if (gDP.loadTile->format == G_IM_FMT_YUV)
|
|
|
|
memcpy(TMEM, &RDRAM[address], bytes); // HACK!
|
2014-10-28 05:26:45 +00:00
|
|
|
else {
|
2015-06-17 07:22:21 +00:00
|
|
|
u32 tmemAddr = gDP.loadTile->tmem;
|
2020-11-14 09:54:28 +00:00
|
|
|
UnswapCopyWrap(RDRAM, address, reinterpret_cast<u8*>(TMEM), tmemAddr << 3, 0xFFF, bytes);
|
2016-03-26 15:14:42 +00:00
|
|
|
if (dxt != 0) {
|
|
|
|
u32 dxtCounter = 0;
|
|
|
|
u32 qwords = (bytes >> 3);
|
|
|
|
u32 line = 0;
|
|
|
|
while (true) {
|
|
|
|
do {
|
|
|
|
++tmemAddr;
|
|
|
|
--qwords;
|
|
|
|
if (qwords == 0)
|
|
|
|
goto end_dxt_test;
|
|
|
|
dxtCounter += dxt;
|
|
|
|
} while ((dxtCounter & 0x800) == 0);
|
|
|
|
do {
|
|
|
|
++line;
|
|
|
|
--qwords;
|
|
|
|
if (qwords == 0)
|
|
|
|
goto end_dxt_test;
|
|
|
|
dxtCounter += dxt;
|
|
|
|
} while ((dxtCounter & 0x800) != 0);
|
2022-03-29 21:42:02 +00:00
|
|
|
DWordInterleaveWrap(reinterpret_cast<u32*>(TMEM), tmemAddr << 1, LOAD_BLOCK32_MASK, line);
|
2015-06-17 07:22:21 +00:00
|
|
|
tmemAddr += line;
|
2016-03-26 15:14:42 +00:00
|
|
|
line = 0;
|
2014-10-28 05:26:45 +00:00
|
|
|
}
|
2016-03-26 15:14:42 +00:00
|
|
|
end_dxt_test:
|
2022-03-29 21:42:02 +00:00
|
|
|
DWordInterleaveWrap(reinterpret_cast<u32*>(TMEM), tmemAddr << 1, LOAD_BLOCK32_MASK, line);
|
2016-03-26 15:14:42 +00:00
|
|
|
}
|
2014-10-28 05:26:45 +00:00
|
|
|
}
|
2017-05-25 08:54:30 +00:00
|
|
|
|
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPLoadBlock( %i, %i, %i, %i, %i );\n", tile, uls, ult, lrs, dxt );
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDPLoadTLUT( u32 tile, u32 uls, u32 ult, u32 lrs, u32 lrt )
|
|
|
|
{
|
|
|
|
gDPSetTileSize( tile, uls, ult, lrs, lrt );
|
2017-05-21 09:00:01 +00:00
|
|
|
if (gDP.tiles[tile].tmem < 256) {
|
|
|
|
DebugMsg(DEBUG_NORMAL | DEBUG_ERROR, "gDPLoadTLUT wrong tile tmem addr: tile[%d].tmem=%04x;\n", tile, gDP.tiles[tile].tmem);
|
2014-11-22 17:54:06 +00:00
|
|
|
return;
|
2017-05-21 09:00:01 +00:00
|
|
|
}
|
2020-11-14 09:54:28 +00:00
|
|
|
u16 count = static_cast<u16>((gDP.tiles[tile].lrs - gDP.tiles[tile].uls + 1) * (gDP.tiles[tile].lrt - gDP.tiles[tile].ult + 1));
|
2022-01-16 17:27:17 +00:00
|
|
|
word address = gDP.textureImage.address + gDP.tiles[tile].ult * gDP.textureImage.bpl + (gDP.tiles[tile].uls << gDP.textureImage.size >> 1);
|
2020-11-14 09:54:28 +00:00
|
|
|
u16 pal = static_cast<u16>((gDP.tiles[tile].tmem - 256) >> 4);
|
2018-09-05 16:18:50 +00:00
|
|
|
u16 * dest = reinterpret_cast<u16*>(TMEM);
|
|
|
|
u32 destIdx = gDP.tiles[tile].tmem << 2;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
|
|
|
int i = 0;
|
2014-09-22 14:52:59 +00:00
|
|
|
while (i < count) {
|
|
|
|
for (u16 j = 0; (j < 16) && (i < count); ++j, ++i) {
|
2022-01-16 17:27:17 +00:00
|
|
|
#ifdef NATIVE
|
2022-03-29 21:42:02 +00:00
|
|
|
//dest[(destIdx | LOAD_BLOCK32_MAX) & 0x07FF] = *reinterpret_cast<u16*>(RDRAM + (address ^ 2));
|
2022-01-16 17:27:17 +00:00
|
|
|
dest[(destIdx) & 0x07FF] = *reinterpret_cast<u16*>(RDRAM + (address));
|
|
|
|
#else
|
2022-03-29 21:42:02 +00:00
|
|
|
dest[(destIdx | LOAD_BLOCK32_MAX) & 0x07FF] = swapword(*reinterpret_cast<u16*>(RDRAM + (address ^ 2)));
|
2022-01-16 17:27:17 +00:00
|
|
|
#endif
|
2014-10-25 08:37:44 +00:00
|
|
|
address += 2;
|
2017-11-01 10:45:24 +00:00
|
|
|
destIdx += 4;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
2014-09-01 16:21:40 +00:00
|
|
|
|
2020-03-30 02:21:06 +00:00
|
|
|
gDP.paletteCRC16[pal] = CRC_CalculatePalette(UINT64_MAX, &TMEM[256 + (pal << 4)], 16);
|
2017-11-01 10:45:24 +00:00
|
|
|
pal = (pal + 1) & 0x0F;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2020-04-04 14:13:00 +00:00
|
|
|
gDP.paletteCRC256 = CRC_Calculate(UINT64_MAX, gDP.paletteCRC16, sizeof(u64) * 16);
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-11-17 14:02:46 +00:00
|
|
|
if (TFH.isInited()) {
|
2020-11-14 09:54:28 +00:00
|
|
|
const u16 start = static_cast<u16>(gDP.tiles[tile].tmem) - 256; // starting location in the palettes
|
|
|
|
u16 *spal = reinterpret_cast<u16*>(RDRAM + gDP.textureImage.address);
|
|
|
|
memcpy(reinterpret_cast<u8*>(gDP.TexFilterPalette + start), spal, u32(count)<<1);
|
2014-11-17 14:02:46 +00:00
|
|
|
}
|
|
|
|
|
2013-04-05 06:13:26 +00:00
|
|
|
gDP.changed |= CHANGED_TMEM;
|
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPLoadTLUT( %i, %i, %i, %i, %i );\n",
|
2013-04-05 06:13:26 +00:00
|
|
|
tile, gDP.tiles[tile].uls, gDP.tiles[tile].ult, gDP.tiles[tile].lrs, gDP.tiles[tile].lrt );
|
|
|
|
}
|
|
|
|
|
2018-08-22 14:48:30 +00:00
|
|
|
void gDPSetScissor(u32 mode, s16 xh, s16 yh, s16 xl, s16 yl)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
|
|
|
gDP.scissor.mode = mode;
|
2018-08-22 14:48:30 +00:00
|
|
|
gDP.scissor.xh = xh;
|
|
|
|
gDP.scissor.yh = yh;
|
|
|
|
gDP.scissor.xl = xl;
|
|
|
|
gDP.scissor.yl = yl;
|
|
|
|
gDP.scissor.ulx = _FIXED2FLOAT(xh, 2);
|
|
|
|
gDP.scissor.uly = _FIXED2FLOAT(yh, 2);
|
|
|
|
gDP.scissor.lrx = _FIXED2FLOAT(xl, 2);
|
|
|
|
gDP.scissor.lry = _FIXED2FLOAT(yl, 2);
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2018-12-09 09:48:53 +00:00
|
|
|
gDP.changed |= CHANGED_SCISSOR | CHANGED_REJECT_BOX;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
#ifdef DEBUG_DUMP
|
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetScissor( %s, %.2f, %.2f, %.2f, %.2f );\n",
|
2013-04-05 06:13:26 +00:00
|
|
|
ScissorModeText[gDP.scissor.mode],
|
|
|
|
gDP.scissor.ulx,
|
|
|
|
gDP.scissor.uly,
|
|
|
|
gDP.scissor.lrx,
|
|
|
|
gDP.scissor.lry );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-08-10 11:10:44 +00:00
|
|
|
void gDPFillRectangle( s32 ulx, s32 uly, s32 lrx, s32 lry )
|
|
|
|
{
|
2017-01-15 07:57:25 +00:00
|
|
|
GraphicsDrawer & drawer = dwnd().getDrawer();
|
2016-03-12 14:02:12 +00:00
|
|
|
if (gDP.otherMode.cycleType == G_CYC_FILL) {
|
|
|
|
++lrx;
|
|
|
|
++lry;
|
|
|
|
} else if (lry == uly)
|
2015-02-19 13:31:12 +00:00
|
|
|
++lry;
|
2015-04-09 14:32:43 +00:00
|
|
|
|
2017-02-17 08:50:55 +00:00
|
|
|
enum {
|
|
|
|
dbNone,
|
|
|
|
dbFound,
|
|
|
|
dbCleared
|
|
|
|
} depthBuffer = dbNone;
|
2013-06-04 14:05:56 +00:00
|
|
|
if (gDP.depthImageAddress == gDP.colorImage.address) {
|
2013-06-30 15:03:16 +00:00
|
|
|
// 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
|
2015-03-05 13:43:32 +00:00
|
|
|
if (gDP.fillColor.color == DepthClearColor) {
|
2017-02-17 08:50:55 +00:00
|
|
|
depthBuffer = dbFound;
|
2018-09-24 14:39:42 +00:00
|
|
|
if (config.generalEmulation.enableFragmentDepthWrite == 0) {
|
2018-09-27 11:31:41 +00:00
|
|
|
drawer.clearDepthBuffer();
|
2017-02-17 08:50:55 +00:00
|
|
|
depthBuffer = dbCleared;
|
2016-09-11 11:08:03 +00:00
|
|
|
} else
|
2018-09-27 11:31:41 +00:00
|
|
|
depthBufferList().setCleared(true);
|
2013-06-30 15:03:16 +00:00
|
|
|
}
|
2015-03-05 13:43:32 +00:00
|
|
|
} else if (gDP.fillColor.color == DepthClearColor && gDP.otherMode.cycleType == G_CYC_FILL) {
|
2017-02-17 08:50:55 +00:00
|
|
|
depthBuffer = dbFound;
|
2014-09-08 11:00:13 +00:00
|
|
|
depthBufferList().saveBuffer(gDP.colorImage.address);
|
2018-10-06 16:50:23 +00:00
|
|
|
if (config.generalEmulation.enableFragmentDepthWrite == 0 ||
|
|
|
|
(config.generalEmulation.hacks & hack_Snap) != 0) {
|
2018-09-27 11:31:41 +00:00
|
|
|
drawer.clearDepthBuffer();
|
2017-02-17 08:50:55 +00:00
|
|
|
depthBuffer = dbCleared;
|
2016-09-11 11:08:03 +00:00
|
|
|
} else
|
2018-09-27 11:31:41 +00:00
|
|
|
depthBufferList().setCleared(true);
|
2016-04-02 07:56:43 +00:00
|
|
|
}
|
|
|
|
|
2017-02-17 08:50:55 +00:00
|
|
|
if (depthBuffer != dbCleared) {
|
2016-03-20 07:24:26 +00:00
|
|
|
if (gDP.otherMode.cycleType == G_CYC_FILL) {
|
2017-03-01 04:49:58 +00:00
|
|
|
f32 fillColor[4];
|
|
|
|
gDPGetFillColor(fillColor);
|
2018-09-24 09:54:29 +00:00
|
|
|
gDP.rectColor.r = fillColor[0];
|
|
|
|
gDP.rectColor.g = fillColor[1];
|
|
|
|
gDP.rectColor.b = fillColor[2];
|
|
|
|
gDP.rectColor.a = fillColor[3];
|
2017-03-01 04:49:58 +00:00
|
|
|
} else {
|
|
|
|
gDP.rectColor = gDPInfo::Color();
|
|
|
|
}
|
2018-09-24 09:54:29 +00:00
|
|
|
drawer.drawRect(ulx, uly, lrx, lry);
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2018-10-17 08:49:21 +00:00
|
|
|
if (gDP.otherMode.cycleType == G_CYC_FILL)
|
|
|
|
frameBufferList().fillRDRAM(ulx, uly, lrx, lry);
|
|
|
|
|
2017-11-15 07:42:04 +00:00
|
|
|
frameBufferList().setBufferChanged(f32(lry));
|
2017-02-27 10:33:04 +00:00
|
|
|
|
2017-09-12 07:48:17 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPFillRectangle #%i- #%i ( %i, %i, %i, %i );\n", gSP.tri_num, gSP.tri_num +1, ulx, uly, lrx, lry );
|
|
|
|
gSP.tri_num += 2;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDPSetConvert( s32 k0, s32 k1, s32 k2, s32 k3, s32 k4, s32 k5 )
|
|
|
|
{
|
2020-11-14 09:54:28 +00:00
|
|
|
gDP.convert.k0 = static_cast<s32>(static_cast<u32>(SIGN(k0, 9) << 1)) + 1;
|
|
|
|
gDP.convert.k1 = static_cast<s32>(static_cast<u32>(SIGN(k1, 9) << 1)) + 1;
|
|
|
|
gDP.convert.k2 = static_cast<s32>(static_cast<u32>(SIGN(k2, 9) << 1)) + 1;
|
|
|
|
gDP.convert.k3 = static_cast<s32>(static_cast<u32>(SIGN(k3, 9) << 1)) + 1;
|
2017-10-22 13:50:57 +00:00
|
|
|
gDP.convert.k4 = k4;
|
|
|
|
gDP.convert.k5 = k5;
|
2017-05-25 08:54:30 +00:00
|
|
|
|
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetConvert( %i, %i, %i, %i, %i, %i );\n", k0, k1, k2, k3, k4, k5);
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDPSetKeyR( u32 cR, u32 sR, u32 wR )
|
|
|
|
{
|
2018-05-31 09:59:44 +00:00
|
|
|
gDP.key.center.r = _FIXED2FLOATCOLOR( cR, 8 );
|
|
|
|
gDP.key.scale.r = _FIXED2FLOATCOLOR( sR, 8 );
|
|
|
|
gDP.key.width.r = _FIXED2FLOATCOLOR( wR, 8 );
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetKeyR( %u, %u, %u );\n", cR, sR, wR );
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDPSetKeyGB(u32 cG, u32 sG, u32 wG, u32 cB, u32 sB, u32 wB )
|
|
|
|
{
|
2018-05-31 09:59:44 +00:00
|
|
|
gDP.key.center.g = _FIXED2FLOATCOLOR( cG, 8 );
|
|
|
|
gDP.key.scale.g = _FIXED2FLOATCOLOR( sG, 8 );
|
|
|
|
gDP.key.width.g = _FIXED2FLOATCOLOR( wG, 8 );
|
|
|
|
gDP.key.center.b = _FIXED2FLOATCOLOR( cB, 8 );
|
|
|
|
gDP.key.scale.b = _FIXED2FLOATCOLOR( sB, 8 );
|
|
|
|
gDP.key.width.b = _FIXED2FLOATCOLOR( wB, 8 );
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPSetKeyGB( %u, %u, %u, %u, %u, %u );\n",
|
|
|
|
cG, sG, wG, cB, sB, wB );
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 16:43:01 +00:00
|
|
|
void gDPTextureRectangle(f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, s16 s, s16 t, f32 dsdx, f32 dtdy , bool flip)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-22 14:52:59 +00:00
|
|
|
if (gDP.otherMode.cycleType == G_CYC_COPY) {
|
2018-07-02 12:24:18 +00:00
|
|
|
dsdx /= 4.0f;
|
2016-03-12 14:02:12 +00:00
|
|
|
lrx += 1.0f;
|
2013-04-05 06:13:26 +00:00
|
|
|
lry += 1.0f;
|
2021-01-31 14:25:27 +00:00
|
|
|
} else if (lry - uly < 1.0f) {
|
|
|
|
lry = ceil(lry);
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2013-12-02 06:10:33 +00:00
|
|
|
gDPTile *textureTileOrg[2];
|
|
|
|
textureTileOrg[0] = gSP.textureTile[0];
|
|
|
|
textureTileOrg[1] = gSP.textureTile[1];
|
2013-04-05 06:13:26 +00:00
|
|
|
gSP.textureTile[0] = &gDP.tiles[tile];
|
2021-10-11 23:22:23 +00:00
|
|
|
gSP.textureTile[1] = needReplaceTex1ByTex0() ? &gDP.tiles[tile] : &gDP.tiles[(tile + 1) & 7];
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2013-06-13 18:55:51 +00:00
|
|
|
// HACK ALERT!
|
2017-11-11 16:43:01 +00:00
|
|
|
if (s == 0x4000 && (gDP.colorImage.width + gSP.textureTile[0]->uls < 512))
|
2017-12-16 06:15:57 +00:00
|
|
|
s = 0;
|
2013-06-13 18:55:51 +00:00
|
|
|
|
2020-10-31 08:40:03 +00:00
|
|
|
gDP.rectColor = gDPInfo::Color();
|
2020-10-30 08:43:56 +00:00
|
|
|
|
2021-03-05 17:42:30 +00:00
|
|
|
gDP.lastTexRectInfo.ulx = ulx;
|
|
|
|
gDP.lastTexRectInfo.lrx = lrx;
|
|
|
|
gDP.lastTexRectInfo.uly = uly;
|
|
|
|
gDP.lastTexRectInfo.lry = lry;
|
|
|
|
gDP.lastTexRectInfo.s = !flip ? s : t;
|
|
|
|
gDP.lastTexRectInfo.t = !flip ? t : s;
|
|
|
|
gDP.lastTexRectInfo.dsdx = !flip ? dsdx : dtdy;
|
|
|
|
gDP.lastTexRectInfo.dtdy = !flip ? dtdy : dsdx;
|
|
|
|
|
2021-08-07 11:54:51 +00:00
|
|
|
f32 S = _FIXED2FLOAT(!flip ? s : t, 5);
|
|
|
|
f32 T = _FIXED2FLOAT(!flip ? t : s, 5);
|
|
|
|
f32 DSDX = !flip ? dsdx : dtdy;
|
|
|
|
f32 DTDY = !flip ? dtdy : dsdx;
|
|
|
|
f32 uls = S + (ceilf(ulx) - ulx) * DSDX;
|
|
|
|
f32 lrs = S + (ceilf(lrx) - ulx - 1.0f) * DSDX;
|
|
|
|
f32 ult = T + (ceilf(uly) - uly) * DTDY;
|
|
|
|
f32 lrt = T + (ceilf(lry) - uly - 1.0f) * DTDY;
|
|
|
|
|
2021-11-20 12:34:21 +00:00
|
|
|
if (config.graphics2D.enableTexCoordBounds != 0) {
|
|
|
|
gDP.m_texCoordBounds.valid = true;
|
|
|
|
gDP.m_texCoordBounds.uls = fmin(uls, lrs);
|
|
|
|
gDP.m_texCoordBounds.ult = fmin(ult, lrt);
|
|
|
|
gDP.m_texCoordBounds.lrs = fmax(uls, lrs);
|
|
|
|
gDP.m_texCoordBounds.lrt = fmax(ult, lrt);
|
|
|
|
}
|
2021-08-07 11:54:51 +00:00
|
|
|
|
2017-01-15 07:57:25 +00:00
|
|
|
GraphicsDrawer & drawer = dwnd().getDrawer();
|
2017-11-11 16:43:01 +00:00
|
|
|
GraphicsDrawer::TexturedRectParams params(ulx, uly, lrx, lry, dsdx, dtdy, s, t,
|
2017-01-15 07:57:25 +00:00
|
|
|
flip, false, true, frameBufferList().getCurrent());
|
2019-01-26 08:08:55 +00:00
|
|
|
if (config.graphics2D.enableNativeResTexrects == 0 && config.graphics2D.correctTexrectCoords != Config::tcDisable)
|
2017-01-15 07:57:25 +00:00
|
|
|
drawer.correctTexturedRectParams(params);
|
|
|
|
drawer.drawTexturedRect(params);
|
2013-12-02 06:10:33 +00:00
|
|
|
|
|
|
|
gSP.textureTile[0] = textureTileOrg[0];
|
|
|
|
gSP.textureTile[1] = textureTileOrg[1];
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2017-02-26 15:07:47 +00:00
|
|
|
frameBufferList().setBufferChanged(lry);
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2016-04-14 07:21:06 +00:00
|
|
|
if (flip)
|
2017-11-11 16:43:01 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPTextureRectangleFlip( %f, %f, %f, %f, %i, %f, %f, %f, %f);\n",
|
|
|
|
ulx, uly, lrx, lry, tile, s/32.0f, t/32.0f, dsdx, dtdy );
|
2016-04-14 07:21:06 +00:00
|
|
|
else
|
2018-02-18 05:43:04 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPTextureRectangle( %f, %f, %f, %f, %i, %f, %f, %f, %f );\n",
|
2017-11-11 16:43:01 +00:00
|
|
|
ulx, uly, lrx, lry, tile, s/32.0f, t/32.0f, dsdx, dtdy);
|
2017-09-12 07:48:17 +00:00
|
|
|
gSP.tri_num += 2;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDPFullSync()
|
|
|
|
{
|
2015-10-31 02:36:16 +00:00
|
|
|
if (config.frameBufferEmulation.copyAuxToRDRAM != 0) {
|
|
|
|
frameBufferList().copyAux();
|
|
|
|
frameBufferList().removeAux();
|
|
|
|
}
|
|
|
|
|
2017-01-15 07:57:25 +00:00
|
|
|
dwnd().getDrawer().flush();
|
2021-06-05 15:32:01 +00:00
|
|
|
dwnd().getDrawer().dropRenderState();
|
2015-12-10 14:55:08 +00:00
|
|
|
|
2018-10-25 10:29:50 +00:00
|
|
|
frameBufferList().updateCurrentBufferEndAddress();
|
2018-08-27 15:35:30 +00:00
|
|
|
|
2018-10-25 10:29:50 +00:00
|
|
|
FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent();
|
2020-10-19 15:10:01 +00:00
|
|
|
if (pCurrentBuffer != nullptr)
|
|
|
|
pCurrentBuffer->copyDepthTexture();
|
2016-10-19 04:05:30 +00:00
|
|
|
if ((config.frameBufferEmulation.copyToRDRAM != Config::ctDisable || (config.generalEmulation.hacks & hack_subscreen) != 0) &&
|
2016-04-17 09:31:59 +00:00
|
|
|
!FBInfo::fbInfo.isSupported() &&
|
2018-08-27 15:35:30 +00:00
|
|
|
pCurrentBuffer != nullptr &&
|
|
|
|
!pCurrentBuffer->isAuxiliary()
|
2016-04-17 09:31:59 +00:00
|
|
|
)
|
2018-10-25 10:29:50 +00:00
|
|
|
FrameBuffer_CopyToRDRAM(gDP.colorImage.address, config.frameBufferEmulation.copyToRDRAM == Config::ctSync);
|
2015-10-31 03:11:33 +00:00
|
|
|
|
2017-10-24 06:34:22 +00:00
|
|
|
if (RSP.LLE) {
|
2016-09-23 05:05:48 +00:00
|
|
|
if (config.frameBufferEmulation.copyDepthToRDRAM != Config::cdDisable && !FBInfo::fbInfo.isSupported())
|
2015-08-27 13:39:29 +00:00
|
|
|
FrameBuffer_CopyDepthBuffer(gDP.colorImage.address);
|
|
|
|
}
|
2015-07-13 18:27:40 +00:00
|
|
|
|
2013-04-05 06:13:26 +00:00
|
|
|
*REG.MI_INTR |= MI_INTR_DP;
|
|
|
|
|
|
|
|
CheckInterrupts();
|
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "gDPFullSync();\n" );
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDPTileSync()
|
|
|
|
{
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL | DEBUG_IGNORED, "gDPTileSync();\n" );
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPPipeSync(const Gwords words)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2022-01-16 17:27:17 +00:00
|
|
|
const word line = _SHIFTR(words.w0, 0, 16);
|
|
|
|
const char* file = (const char*)words.w1;
|
|
|
|
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL | DEBUG_IGNORED, "gDPPipeSync();\n" );
|
2022-01-16 17:27:17 +00:00
|
|
|
|
|
|
|
if (line && file) {
|
|
|
|
DebugMsg(DEBUG_NORMAL, "\nLINE %s : %d;\n\n", file, line);
|
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gDPLoadSync()
|
|
|
|
{
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL | DEBUG_IGNORED, "gDPLoadSync();\n" );
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPNoOp(const Gwords words)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2022-01-16 17:27:17 +00:00
|
|
|
const word line = _SHIFTR(words.w0, 0, 16);
|
|
|
|
const char* file = (const char*)words.w1;
|
|
|
|
|
|
|
|
DebugMsg(DEBUG_NORMAL | DEBUG_IGNORED, "gDPNoOp();\n");
|
|
|
|
|
|
|
|
if (line && file) {
|
|
|
|
DebugMsg(DEBUG_NORMAL, "\nLINE %s : %d;\n\n", file, line);
|
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
2014-10-07 10:59:54 +00:00
|
|
|
|
2020-02-02 12:50:00 +00:00
|
|
|
LLETriangle::LLETriangle()
|
|
|
|
{
|
2020-03-11 06:55:30 +00:00
|
|
|
m_textureTileOrg[0] = gSP.textureTile[0];
|
|
|
|
m_textureTileOrg[1] = gSP.textureTile[1];
|
2020-02-02 12:50:00 +00:00
|
|
|
m_textureScaleOrg[0] = m_textureScaleOrg[1] = 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
LLETriangle& LLETriangle::get()
|
|
|
|
{
|
|
|
|
static LLETriangle lleTriangle;
|
|
|
|
return lleTriangle;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LLETriangle::start(u32 _tile)
|
|
|
|
{
|
|
|
|
if (!m_flushed)
|
|
|
|
return;
|
|
|
|
m_textureTileOrg[0] = gSP.textureTile[0];
|
|
|
|
m_textureTileOrg[1] = gSP.textureTile[1];
|
|
|
|
m_textureScaleOrg[0] = gSP.texture.scales;
|
|
|
|
m_textureScaleOrg[1] = gSP.texture.scalet;
|
2020-03-09 09:04:20 +00:00
|
|
|
gSP.texture.tile = _tile;
|
2020-02-02 12:50:00 +00:00
|
|
|
gSP.textureTile[0] = &gDP.tiles[_tile];
|
2021-10-11 23:22:23 +00:00
|
|
|
gSP.textureTile[1] = needReplaceTex1ByTex0() ? &gDP.tiles[_tile] : &gDP.tiles[(_tile + 1) & 7];
|
2020-02-02 12:50:00 +00:00
|
|
|
gSP.texture.scales = 1.0f;
|
|
|
|
gSP.texture.scalet = 1.0f;
|
2020-03-09 09:05:02 +00:00
|
|
|
m_flushed = false;
|
2020-02-02 12:50:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void LLETriangle::flush(u32 _cmd)
|
|
|
|
{
|
|
|
|
if (_cmd >= 0x08 && _cmd <= 0x0f)
|
|
|
|
return;
|
2020-10-31 08:40:03 +00:00
|
|
|
|
2020-02-02 12:50:00 +00:00
|
|
|
GraphicsDrawer & drawer = dwnd().getDrawer();
|
|
|
|
if (drawer.getDMAVerticesCount() > 0) {
|
|
|
|
drawer.drawScreenSpaceTriangle(drawer.getDMAVerticesCount(), graphics::drawmode::TRIANGLES);
|
|
|
|
}
|
|
|
|
gSP.textureTile[0] = m_textureTileOrg[0];
|
|
|
|
gSP.textureTile[1] = m_textureTileOrg[1];
|
|
|
|
gSP.texture.scales = m_textureScaleOrg[0];
|
|
|
|
gSP.texture.scalet = m_textureScaleOrg[1];
|
2020-03-09 09:05:02 +00:00
|
|
|
m_flushed = true;
|
2014-10-07 10:59:54 +00:00
|
|
|
}
|
|
|
|
|
2020-11-11 05:17:20 +00:00
|
|
|
void LLETriangle::draw(bool _shade, bool _texture, bool _zbuffer, u32 * _pData)
|
2020-02-02 12:50:00 +00:00
|
|
|
{
|
|
|
|
DebugMsg(DEBUG_NORMAL, "gDPLLETriangle shade: %d, texture: %d, zbuffer: %d\n",
|
|
|
|
int(_shade), int(_texture), int(_zbuffer));
|
|
|
|
|
|
|
|
gSP.texture.level = _SHIFTR(_pData[0], 19, 3);
|
|
|
|
const u32 tile = _SHIFTR(_pData[0], 16, 3);
|
2020-03-04 15:37:10 +00:00
|
|
|
if (tile != m_tile)
|
|
|
|
flush(0);
|
|
|
|
m_tile = tile;
|
2020-11-11 05:17:20 +00:00
|
|
|
// const int flip = (_pData[0] & 0x800000) >> 23; // unused
|
2020-02-02 12:50:00 +00:00
|
|
|
start(tile);
|
|
|
|
|
2020-11-11 05:17:20 +00:00
|
|
|
s32* pDataSigned = reinterpret_cast<s32*>(_pData);
|
|
|
|
int yl = SIGN(pDataSigned[0], 14);
|
|
|
|
int ym = pDataSigned[1] >> 16;
|
2020-02-02 12:50:00 +00:00
|
|
|
ym = SIGN(ym, 14);
|
2020-11-11 05:17:20 +00:00
|
|
|
int yh = SIGN(pDataSigned[1], 14);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
2020-11-11 05:17:20 +00:00
|
|
|
int xl = SIGN(pDataSigned[2], 28);
|
|
|
|
int xh = SIGN(pDataSigned[4], 28);
|
|
|
|
int xm = SIGN(pDataSigned[6], 28);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
2020-11-11 05:17:20 +00:00
|
|
|
const int dxldy = SIGN(pDataSigned[3], 30);
|
|
|
|
const int dxhdy = SIGN(pDataSigned[5], 30);
|
|
|
|
const int dxmdy = SIGN(pDataSigned[7], 30);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
|
|
|
yh &= ~3;
|
|
|
|
|
|
|
|
int r = 0xff, g = 0xff, b = 0xff, a = 0xff;
|
|
|
|
int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0;
|
|
|
|
int drde = 0, dgde = 0, dbde = 0, dade = 0;
|
|
|
|
|
|
|
|
if (_shade) {
|
2020-11-11 05:17:20 +00:00
|
|
|
r = static_cast<int>((_pData[8] & 0xffff0000) | ((_pData[12] >> 16) & 0x0000ffff));
|
|
|
|
g = static_cast<int>(((_pData[8] << 16) & 0xffff0000) | (_pData[12] & 0x0000ffff));
|
|
|
|
b = static_cast<int>((_pData[9] & 0xffff0000) | ((_pData[13] >> 16) & 0x0000ffff));
|
|
|
|
a = static_cast<int>(((_pData[9] << 16) & 0xffff0000) | (_pData[13] & 0x0000ffff));
|
|
|
|
drdx = static_cast<int>((_pData[10] & 0xffff0000) | ((_pData[14] >> 16) & 0x0000ffff));
|
|
|
|
dgdx = static_cast<int>(((_pData[10] << 16) & 0xffff0000) | (_pData[14] & 0x0000ffff));
|
|
|
|
dbdx = static_cast<int>((_pData[11] & 0xffff0000) | ((_pData[15] >> 16) & 0x0000ffff));
|
|
|
|
dadx = static_cast<int>(((_pData[11] << 16) & 0xffff0000) | (_pData[15] & 0x0000ffff));
|
|
|
|
drde = static_cast<int>((_pData[16] & 0xffff0000) | ((_pData[20] >> 16) & 0x0000ffff));
|
|
|
|
dgde = static_cast<int>(((_pData[16] << 16) & 0xffff0000) | (_pData[20] & 0x0000ffff));
|
|
|
|
dbde = static_cast<int>((_pData[17] & 0xffff0000) | ((_pData[21] >> 16) & 0x0000ffff));
|
|
|
|
dade = static_cast<int>(((_pData[17] << 16) & 0xffff0000) | (_pData[21] & 0x0000ffff));
|
2020-02-02 12:50:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int s = 0, t = 0, w = 0x30000;
|
|
|
|
int dsdx = 0, dtdx = 0, dwdx = 0;
|
|
|
|
int dsde = 0, dtde = 0, dwde = 0;
|
|
|
|
if (_texture) {
|
2020-11-11 05:17:20 +00:00
|
|
|
s = static_cast<int>((_pData[24] & 0xffff0000) | ((_pData[28] >> 16) & 0x0000ffff));
|
|
|
|
t = static_cast<int>(((_pData[24] << 16) & 0xffff0000) | (_pData[28] & 0x0000ffff));
|
|
|
|
w = static_cast<int>((_pData[25] & 0xffff0000) | ((_pData[29] >> 16) & 0x0000ffff));
|
|
|
|
dsdx = static_cast<int>((_pData[26] & 0xffff0000) | ((_pData[30] >> 16) & 0x0000ffff));
|
|
|
|
dtdx = static_cast<int>(((_pData[26] << 16) & 0xffff0000) | (_pData[30] & 0x0000ffff));
|
|
|
|
dwdx = static_cast<int>((_pData[27] & 0xffff0000) | ((_pData[31] >> 16) & 0x0000ffff));
|
|
|
|
dsde = static_cast<int>((_pData[32] & 0xffff0000) | ((_pData[36] >> 16) & 0x0000ffff));
|
|
|
|
dtde = static_cast<int>(((_pData[32] << 16) & 0xffff0000) | (_pData[36] & 0x0000ffff));
|
|
|
|
dwde = static_cast<int>((_pData[33] & 0xffff0000) | ((_pData[37] >> 16) & 0x0000ffff));
|
2020-02-02 12:50:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int z = 0xffff0000;
|
|
|
|
int dzdx = 0, dzde = 0;
|
|
|
|
if (_zbuffer) {
|
2020-11-11 05:17:20 +00:00
|
|
|
z = pDataSigned[40];
|
|
|
|
dzdx = pDataSigned[41];
|
|
|
|
dzde = pDataSigned[42];
|
2020-02-02 12:50:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::array<SPVertex, 8> vertices;
|
|
|
|
|
|
|
|
auto cscale = [](int c) {
|
|
|
|
return _FIXED2FLOATCOLOR((((c) > 0x3ff0000 ? 0x3ff0000 : ((c) < 0 ? 0 : (c))) >> 18), 8);
|
|
|
|
};
|
|
|
|
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 rf = cscale(r << 2);
|
|
|
|
f32 gf = cscale(g << 2);
|
|
|
|
f32 bf = cscale(b << 2);
|
|
|
|
f32 af = cscale(a << 2);
|
|
|
|
f32 wf = f32(w) / f32(0xffff0000);
|
|
|
|
f32 zf = f32(z) / f32(0xffff0000);
|
|
|
|
f32 sf = f32(s) / f32(1 << 18);
|
|
|
|
f32 tf = f32(t) / f32(1 << 18);
|
|
|
|
|
|
|
|
f32 drdef = _FIXED2FLOAT(((drde >> 2) & ~1), 16) / 255.0f;
|
|
|
|
f32 dgdef = _FIXED2FLOAT(((dgde >> 2) & ~1), 16) / 255.0f;
|
|
|
|
f32 dbdef = _FIXED2FLOAT(((dbde >> 2) & ~1), 16) / 255.0f;
|
|
|
|
f32 dadef = _FIXED2FLOAT(((dade >> 2) & ~1), 16) / 255.0f;
|
|
|
|
f32 dwdef = f32(dwde >> 2) / f32(0xffff0000);
|
|
|
|
f32 dzdef = f32(dzde >> 2) / f32(0xffff0000);
|
|
|
|
|
|
|
|
f32 dsdef = f32(dsde >> 2) / f32(1 << 18);
|
|
|
|
f32 dtdef = f32(dtde >> 2) / f32(1 << 18);
|
|
|
|
|
|
|
|
f32 drdxf = _FIXED2FLOAT(drdx, 16) / 255.0f;
|
|
|
|
f32 dgdxf = _FIXED2FLOAT(dgdx, 16) / 255.0f;
|
|
|
|
f32 dbdxf = _FIXED2FLOAT(dbdx, 16) / 255.0f;
|
|
|
|
f32 dadxf = _FIXED2FLOAT(dadx, 16) / 255.0f;
|
|
|
|
|
|
|
|
f32 dwdxf = f32(dwdx >> 2) / f32(0xffff0000);
|
|
|
|
f32 dzdxf = f32(dzdx >> 2) / f32(0xffff0000);
|
|
|
|
|
|
|
|
f32 dsdxf = _FIXED2FLOAT(((dsdx >> 2) & ~1), 16);
|
|
|
|
f32 dtdxf = _FIXED2FLOAT(((dtdx >> 2) & ~1), 16);
|
|
|
|
|
|
|
|
f32 xhf = _FIXED2FLOAT((xh & ~0x1), 16);
|
|
|
|
f32 xmf = _FIXED2FLOAT((xm & ~0x1), 16);
|
|
|
|
|
|
|
|
f32 yhf = f32(yh);
|
|
|
|
f32 ymf = f32(ym);
|
|
|
|
f32 ylf = f32(yl);
|
|
|
|
f32 hk = _FIXED2FLOAT(((dxhdy >> 2) & ~0x1), 16);
|
|
|
|
f32 mk = _FIXED2FLOAT(((dxmdy >> 2) & ~0x1), 16);
|
|
|
|
f32 hc = xhf - hk * yhf;
|
|
|
|
f32 mc = xmf - mk * yhf;
|
|
|
|
|
|
|
|
auto updateVtx = [&](SPVertex * vtx, f32 diffY, f32 diffx)
|
2020-02-02 12:50:00 +00:00
|
|
|
{
|
|
|
|
if (_shade) {
|
2020-03-02 06:08:48 +00:00
|
|
|
auto colorClamp = [](f32 c) -> f32
|
2020-02-02 12:50:00 +00:00
|
|
|
{
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 res;
|
|
|
|
if (c < 0.0f)
|
2020-02-02 12:50:00 +00:00
|
|
|
res = 0.0f;
|
2020-03-02 06:08:48 +00:00
|
|
|
else if (c > 1.0f)
|
2020-02-02 12:50:00 +00:00
|
|
|
res = 1.0f;
|
|
|
|
else
|
2020-03-02 06:08:48 +00:00
|
|
|
res = static_cast<f32>(c);
|
2020-02-02 12:50:00 +00:00
|
|
|
return res;
|
|
|
|
};
|
|
|
|
|
|
|
|
vtx->r = colorClamp(rf + drdef * diffY + drdxf * diffx);
|
|
|
|
vtx->g = colorClamp(gf + dgdef * diffY + dgdxf * diffx);
|
|
|
|
vtx->b = colorClamp(bf + dbdef * diffY + dbdxf * diffx);
|
|
|
|
vtx->a = colorClamp(af + dadef * diffY + dadxf * diffx);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_zbuffer) {
|
2020-03-02 06:08:48 +00:00
|
|
|
//((gDP.otherMode.depthSource == G_ZS_PRIM) ? gDP.primDepth.z : f32(u32(z)) / 0xffff0000)
|
2020-02-02 12:50:00 +00:00
|
|
|
vtx->z = (gDP.otherMode.depthSource == G_ZS_PRIM) ?
|
2020-03-04 15:35:37 +00:00
|
|
|
gDP.primDepth.z :
|
2020-03-02 06:08:48 +00:00
|
|
|
static_cast<f32>((zf + dzdef * diffY + dzdxf * diffx * 4.0f)*2.0f);
|
2020-02-02 12:50:00 +00:00
|
|
|
//if (vtx->z < 0.0f)
|
|
|
|
// vtx->z = 1.0f + vtx->z - ceil(vtx->z);
|
|
|
|
} else
|
2020-02-13 11:08:03 +00:00
|
|
|
vtx->z = 0.0f;
|
2020-02-02 12:50:00 +00:00
|
|
|
|
|
|
|
if (_texture) {
|
|
|
|
if (gDP.otherMode.texturePersp != 0) {
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 vw = wf + dwdef * diffY + dwdxf * diffx * 4.0f;
|
|
|
|
vtx->w = static_cast<f32>(1.0f / (vw > 0.0f ? vw : (1.0f + vw - ceil(vw))));
|
|
|
|
//vtx->w = static_cast<f32>(1.0f / vw);
|
|
|
|
if (vw <= 0.0f) {
|
2020-02-02 12:50:00 +00:00
|
|
|
// TODO fix with proper coords
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->s = static_cast<f32>(1 << gSP.textureTile[0]->masks);
|
|
|
|
vtx->t = static_cast<f32>(1 << gSP.textureTile[0]->maskt);
|
2020-02-02 12:50:00 +00:00
|
|
|
} else {
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->s = static_cast<f32>((sf + dsdef * diffY + dsdxf*diffx) / vw * 0.0625f);
|
|
|
|
vtx->t = static_cast<f32>((tf + dtdef * diffY + dtdxf*diffx) / vw * 0.0625f);
|
2020-02-02 12:50:00 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
vtx->w = 1.0f;
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->s = static_cast<f32>((sf + dsdef * diffY + dsdxf*diffx) * 0.125f);
|
|
|
|
vtx->t = static_cast<f32>((tf + dtdef * diffY + dtdxf*diffx) * 0.125f);
|
2020-02-02 12:50:00 +00:00
|
|
|
}
|
|
|
|
} else
|
|
|
|
vtx->w = 1.0f;
|
|
|
|
//assert(!isnan(vtx->x));
|
|
|
|
};
|
|
|
|
|
|
|
|
u32 vtxCount = 0;
|
2020-03-02 06:08:48 +00:00
|
|
|
if (fabs(hk - mk) < 0.00000001f) {
|
2020-02-02 12:50:00 +00:00
|
|
|
SPVertex * vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(hk * yhf + hc);
|
|
|
|
vtx->y = static_cast<f32>(yhf * 0.25f);
|
|
|
|
updateVtx(vtx, 0.0f, 0.0f);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
|
|
|
if (mc != hc) {
|
|
|
|
vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(mk * yhf + mc);
|
|
|
|
vtx->y = static_cast<f32>(yhf * 0.25f);
|
|
|
|
updateVtx(vtx, 0.0f, (mc - hc));
|
2020-02-02 12:50:00 +00:00
|
|
|
}
|
|
|
|
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 diffym = (ymf - yhf);
|
|
|
|
f32 xhym = (hk * ymf + hc);
|
|
|
|
f32 xmym = (mk * ymf + mc);
|
|
|
|
f32 diffxm = (xmym - xhym);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
|
|
|
#if 1
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 vw = wf + dwdef * diffym + dwdxf * diffxm * 4.0f;
|
|
|
|
if (vw <= 0.0f) {
|
|
|
|
f32 xhyf, xmyf, diffyf, diffxf;
|
|
|
|
f32 yf = ymf;
|
2020-02-02 12:50:00 +00:00
|
|
|
do {
|
2020-03-02 06:08:48 +00:00
|
|
|
yf -= 1.0f;
|
2020-02-02 12:50:00 +00:00
|
|
|
diffyf = (yf - yhf);
|
|
|
|
xhyf = hk * yf + hc;
|
|
|
|
xmyf = mk * yf + mc;
|
|
|
|
diffxf = xmyf - xhyf;
|
2020-03-02 06:08:48 +00:00
|
|
|
vw = wf + dwdef * diffyf + dwdxf * diffxf * 4.0f;
|
|
|
|
} while (vw <= 0.0f && yf > yhf);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
|
|
|
SPVertex * vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(xhyf);
|
2020-11-14 09:54:28 +00:00
|
|
|
vtx->y = static_cast<f32>(yf * 0.25f);
|
2020-03-02 06:08:48 +00:00
|
|
|
updateVtx(vtx, diffyf, 0.0f);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
|
|
|
vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(xmyf);
|
2020-11-14 09:54:28 +00:00
|
|
|
vtx->y = static_cast<f32>(yf * 0.25f);
|
2020-02-02 12:50:00 +00:00
|
|
|
updateVtx(vtx, diffyf, diffxf);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(xhym);
|
2020-11-14 09:54:28 +00:00
|
|
|
vtx->y = static_cast<f32>(ymf * 0.25f);
|
2020-03-02 06:08:48 +00:00
|
|
|
updateVtx(vtx, diffym, 0.0f);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
|
|
|
vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(xmym);
|
2020-11-14 09:54:28 +00:00
|
|
|
vtx->y = static_cast<f32>(ymf * 0.25f);
|
2020-02-02 12:50:00 +00:00
|
|
|
updateVtx(vtx, diffym, diffxm);
|
|
|
|
|
|
|
|
if (dxldy != dxmdy && ym < yl) {
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 xlf = _FIXED2FLOAT((xl & ~1), 16);
|
|
|
|
f32 lk = _FIXED2FLOAT(((dxldy >> 2) & ~1), 16);
|
|
|
|
f32 lc = xlf - lk * ym;
|
|
|
|
f32 y4f = (lc - hc) / (hk - lk);
|
2020-02-02 12:50:00 +00:00
|
|
|
vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(hk * y4f + hc);
|
2020-11-14 09:54:28 +00:00
|
|
|
vtx->y = static_cast<f32>(y4f * 0.25f);
|
2020-03-02 06:08:48 +00:00
|
|
|
updateVtx(vtx, (y4f - yhf), 0.0f);
|
2020-02-02 12:50:00 +00:00
|
|
|
}
|
|
|
|
} else {
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 y0f = (mc - hc) / (hk - mk);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
|
|
|
SPVertex * vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(hk * y0f + hc);
|
|
|
|
vtx->y = static_cast<f32>(y0f * 0.25f);
|
|
|
|
updateVtx(vtx, (y0f - yhf), 0.0f);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 y1f = ymf;
|
|
|
|
f32 xlf = _FIXED2FLOAT((xl & ~1), 16);
|
|
|
|
f32 lk = _FIXED2FLOAT(((dxldy >> 2) & ~1), 16);
|
|
|
|
f32 lc = xlf - lk * y1f;
|
2020-02-02 12:50:00 +00:00
|
|
|
|
2020-03-02 06:08:48 +00:00
|
|
|
//f32 lc = xt - lk * yf;
|
2020-02-02 12:50:00 +00:00
|
|
|
//if ((dxldy >> 2) == (dxmdy >> 2))
|
|
|
|
// y1f = (lc - hc) / (hk - lk);
|
|
|
|
//else
|
|
|
|
// y1f = (lc - mc) / (mk - lk);
|
|
|
|
|
|
|
|
//if (y1f < ymf)
|
|
|
|
// y1f = ymf;
|
|
|
|
|
|
|
|
vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(xlf);
|
2020-11-14 09:54:28 +00:00
|
|
|
vtx->y = static_cast<f32>(y1f * 0.25f);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 x1f = hk * y1f + hc;
|
|
|
|
f32 diffx1 = xlf - x1f;
|
2020-02-02 12:50:00 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
if ((dxldy >> 2) == (dxmdy >> 2))
|
|
|
|
y1f = (lc - hc) / (hk - lk);
|
|
|
|
else
|
|
|
|
y1f = (lc - mc) / (mk - lk);
|
|
|
|
#endif
|
|
|
|
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 diffy1 = (y1f - yhf);
|
2020-02-02 12:50:00 +00:00
|
|
|
updateVtx(vtx, diffy1, diffx1);
|
|
|
|
|
|
|
|
#if 1
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 vw1 = wf + dwdef * diffy1 + dwdxf * diffx1 * 4.0f;
|
|
|
|
if (vw1 <= 0.0f) {
|
|
|
|
f32 y1_1f = y1f;
|
|
|
|
f32 vw1_1 = vw1;
|
|
|
|
f32 x1_1f = x1f;
|
|
|
|
f32 x1_2f = xlf;
|
|
|
|
f32 diffy1_1 = diffy1;
|
|
|
|
f32 diffx1_1 = diffx1;
|
2020-02-02 12:50:00 +00:00
|
|
|
do {
|
2020-03-02 06:08:48 +00:00
|
|
|
y1_1f += 1.0f;
|
2020-02-02 12:50:00 +00:00
|
|
|
diffy1_1 = (y1_1f - yhf);
|
|
|
|
x1_1f = hk * y1_1f + hc;
|
|
|
|
x1_2f = lk * y1_1f + lc;
|
|
|
|
diffx1_1 = x1_2f - x1_1f;
|
2020-03-02 06:08:48 +00:00
|
|
|
vw1_1 = wf + dwdef * diffy1_1 + dwdxf * diffx1_1 * 4.0f;
|
|
|
|
} while (vw1_1 <= 0.0f && y1_1f < ylf);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
|
|
|
vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(x1_1f);
|
|
|
|
vtx->y = static_cast<f32>(y1_1f * 0.25f);
|
|
|
|
updateVtx(vtx, diffy1_1, 0.0f);
|
2020-02-02 12:50:00 +00:00
|
|
|
|
|
|
|
vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(x1_2f);
|
|
|
|
vtx->y = static_cast<f32>(y1_1f * 0.25f);
|
2020-02-02 12:50:00 +00:00
|
|
|
updateVtx(vtx, diffy1_1, diffx1_1);
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (hk == lk) {
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 lrx = lk * ylf + lc;
|
2020-02-02 12:50:00 +00:00
|
|
|
vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(lrx);
|
|
|
|
vtx->y = static_cast<f32>(ylf * 0.25f - (vertices[1].y - vertices[0].y));
|
|
|
|
f32 ydiff = (vtx->y*4.0f - yhf);
|
2020-02-02 12:50:00 +00:00
|
|
|
updateVtx(vtx, ydiff, diffx1);
|
|
|
|
|
|
|
|
vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(lrx);
|
|
|
|
vtx->y = static_cast<f32>(ylf*0.25f);
|
2020-02-02 12:50:00 +00:00
|
|
|
ydiff = (ylf - yhf);
|
|
|
|
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 x2f = hk * ylf + hc;
|
|
|
|
f32 diffx2 = vtx->x - x2f;
|
2020-02-02 12:50:00 +00:00
|
|
|
updateVtx(vtx, ydiff, diffx2);
|
2020-11-14 09:54:28 +00:00
|
|
|
} else if (mk == lk) {
|
2020-02-02 12:50:00 +00:00
|
|
|
vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(hk * ylf + hc);
|
|
|
|
vtx->y = static_cast<f32>(ylf * 0.25f);
|
|
|
|
updateVtx(vtx, (ylf - yhf), 0.0f);
|
2020-11-14 09:54:28 +00:00
|
|
|
} else {
|
2020-03-02 06:08:48 +00:00
|
|
|
f32 y2f = ylf;
|
2020-02-02 12:50:00 +00:00
|
|
|
|
|
|
|
if (yl == ym) {
|
|
|
|
y2f = (lc - mc) / (mk - lk);
|
2020-11-14 09:54:28 +00:00
|
|
|
} else {
|
2020-02-02 12:50:00 +00:00
|
|
|
y2f = (lc - hc) / (hk - lk);
|
|
|
|
}
|
|
|
|
|
|
|
|
vtx = &vertices[vtxCount++];
|
2020-03-02 06:08:48 +00:00
|
|
|
vtx->x = static_cast<f32>(hk * y2f + hc);
|
|
|
|
vtx->y = static_cast<f32>(y2f * 0.25f);
|
|
|
|
updateVtx(vtx, (y2f - yhf), 0.0f);
|
2020-02-02 12:50:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_texture)
|
|
|
|
gDP.changed |= CHANGED_TILE;
|
|
|
|
if (_zbuffer)
|
|
|
|
gSP.geometryMode |= G_ZBUFFER;
|
|
|
|
|
|
|
|
GraphicsDrawer & drawer = dwnd().getDrawer();
|
|
|
|
|
|
|
|
for (u32 i = 0; i < vtxCount - 2; ++i) {
|
|
|
|
for (u32 j = 0; j < 3; ++j) {
|
|
|
|
SPVertex & v = drawer.getCurrentDMAVertex();
|
|
|
|
v = vertices[i + j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPTriFill(word w0, word w1)
|
2014-10-07 10:59:54 +00:00
|
|
|
{
|
2020-11-11 05:17:20 +00:00
|
|
|
u32 ewdata[44];
|
2020-02-02 12:50:00 +00:00
|
|
|
memcpy(&ewdata[0], RDP.cmd_data + RDP.cmd_cur, 8 * sizeof(s32));
|
|
|
|
memset(&ewdata[8], 0, 36 * sizeof(s32));
|
|
|
|
LLETriangle::get().draw(0, 0, 0, ewdata);
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "trifill\n");
|
2014-10-07 10:59:54 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPTriShade(word w0, word w1)
|
2014-10-07 10:59:54 +00:00
|
|
|
{
|
2020-11-11 05:17:20 +00:00
|
|
|
u32 ewdata[44];
|
2020-02-02 12:50:00 +00:00
|
|
|
memcpy(&ewdata[0], RDP.cmd_data + RDP.cmd_cur, 24 * sizeof(s32));
|
|
|
|
memset(&ewdata[24], 0, 20 * sizeof(s32));
|
|
|
|
LLETriangle::get().draw(1, 0, 0, ewdata);
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "trishade\n");
|
2014-10-07 10:59:54 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPTriTxtr(word w0, word w1)
|
2014-10-07 10:59:54 +00:00
|
|
|
{
|
2020-11-11 05:17:20 +00:00
|
|
|
u32 ewdata[44];
|
2020-02-02 12:50:00 +00:00
|
|
|
memcpy(&ewdata[0], RDP.cmd_data + RDP.cmd_cur, 8 * sizeof(s32));
|
|
|
|
memset(&ewdata[8], 0, 16 * sizeof(s32));
|
|
|
|
memcpy(&ewdata[24], RDP.cmd_data + RDP.cmd_cur + 8, 16 * sizeof(s32));
|
|
|
|
memset(&ewdata[40], 0, 4 * sizeof(s32));
|
|
|
|
LLETriangle::get().draw(0, 1, 0, ewdata);
|
|
|
|
DebugMsg(DEBUG_NORMAL, "tritxtr\n");
|
2014-10-07 10:59:54 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPTriShadeTxtr(word w0, word w1)
|
2014-10-07 10:59:54 +00:00
|
|
|
{
|
2020-11-11 05:17:20 +00:00
|
|
|
u32 ewdata[44];
|
2020-02-02 12:50:00 +00:00
|
|
|
memcpy(&ewdata[0], RDP.cmd_data + RDP.cmd_cur, 40 * sizeof(s32));
|
|
|
|
memset(&ewdata[40], 0, 4 * sizeof(s32));
|
|
|
|
LLETriangle::get().draw(1, 1, 0, ewdata);
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "trishadetxtr\n");
|
2014-10-07 10:59:54 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPTriFillZ(word w0, word w1)
|
2014-10-07 10:59:54 +00:00
|
|
|
{
|
2020-11-11 05:17:20 +00:00
|
|
|
u32 ewdata[44];
|
2020-02-02 12:50:00 +00:00
|
|
|
memcpy(&ewdata[0], RDP.cmd_data + RDP.cmd_cur, 8 * sizeof(s32));
|
|
|
|
memset(&ewdata[8], 0, 32 * sizeof(s32));
|
|
|
|
memcpy(&ewdata[40], RDP.cmd_data + RDP.cmd_cur + 8, 4 * sizeof(s32));
|
|
|
|
LLETriangle::get().draw(0, 0, 1, ewdata);
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "trifillz\n");
|
2014-10-07 10:59:54 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPTriShadeZ(word w0, word w1)
|
2014-10-07 10:59:54 +00:00
|
|
|
{
|
2020-11-11 05:17:20 +00:00
|
|
|
u32 ewdata[44];
|
2020-02-02 12:50:00 +00:00
|
|
|
memcpy(&ewdata[0], RDP.cmd_data + RDP.cmd_cur, 24 * sizeof(s32));
|
|
|
|
memset(&ewdata[24], 0, 16 * sizeof(s32));
|
|
|
|
memcpy(&ewdata[40], RDP.cmd_data + RDP.cmd_cur + 24, 4 * sizeof(s32));
|
|
|
|
LLETriangle::get().draw(1, 0, 1, ewdata);
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "trishadez\n");
|
2014-10-07 10:59:54 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPTriTxtrZ(word w0, word w1)
|
2014-10-07 10:59:54 +00:00
|
|
|
{
|
2020-11-11 05:17:20 +00:00
|
|
|
u32 ewdata[44];
|
2020-02-02 12:50:00 +00:00
|
|
|
memcpy(&ewdata[0], RDP.cmd_data + RDP.cmd_cur, 8 * sizeof(s32));
|
|
|
|
memset(&ewdata[8], 0, 16 * sizeof(s32));
|
|
|
|
memcpy(&ewdata[24], RDP.cmd_data + RDP.cmd_cur + 8, 16 * sizeof(s32));
|
|
|
|
memcpy(&ewdata[40], RDP.cmd_data + RDP.cmd_cur + 24, 4 * sizeof(s32));
|
|
|
|
LLETriangle::get().draw(0, 1, 1, ewdata);
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "tritxtrz\n");
|
2014-10-07 10:59:54 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 17:27:17 +00:00
|
|
|
void gDPTriShadeTxtrZ(word w0, word w1)
|
2014-10-07 10:59:54 +00:00
|
|
|
{
|
2020-11-11 05:17:20 +00:00
|
|
|
u32 ewdata[44];
|
2020-02-02 12:50:00 +00:00
|
|
|
memcpy(&ewdata[0], RDP.cmd_data + RDP.cmd_cur, 44 * sizeof(s32));
|
|
|
|
LLETriangle::get().draw(1, 1, 1, ewdata);
|
2017-05-25 08:54:30 +00:00
|
|
|
DebugMsg( DEBUG_NORMAL, "trishadetxtrz\n");
|
2014-10-07 10:59:54 +00:00
|
|
|
}
|