1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-06-27 23:14:05 +00:00
GLideN64/src/RDP.cpp
2022-03-29 17:42:18 -04:00

663 lines
18 KiB
C++

#include <assert.h>
#include <memory.h>
#include <cstring>
#include "N64.h"
#include "RSP.h"
#include "RDP.h"
#include "GBI.h"
#include "gDP.h"
#include "gSP.h"
#include "Config.h"
#include "DebugDump.h"
#include "DisplayWindow.h"
#ifdef NATIVE
#define RDRAM ((u8*)0)
#endif
#define SIGN_MASK(n) (1 << (12 - 1))
#define SIGN12(a) \
(a & SIGN_MASK(12) ? \
(((1 << 12) / 2 - (a & (SIGN_MASK(12) - 1))) * -1) \
: (a))
void RDP_Unknown( const Gwords words )
{
DebugMsg(DEBUG_NORMAL, "RDP_Unknown\r\n");
DebugMsg(DEBUG_NORMAL, "\tUnknown RDP opcode %02X\r\n", _SHIFTR(words.w0, 24, 8));
}
void RDP_NoOp( const Gwords words )
{
gDPNoOp(words);
}
void RDP_MarkSegment(const Gwords words) {
RSP.translateSegment = true;
}
void RDP_SetCImg( const Gwords words )
{
gDPSetColorImage( _SHIFTR( words.w0, 21, 3 ), // fmt
_SHIFTR( words.w0, 19, 2 ), // siz
_SHIFTR( words.w0, 0, 12 ) + 1, // width
words.w1 ); // img
}
void RDP_SetZImg( const Gwords words )
{
gDPSetDepthImage( words.w1 ); // img
}
void RDP_SetTImg( const Gwords words )
{
gDPSetTextureImage( _SHIFTR( words.w0, 21, 3), // fmt
_SHIFTR( words.w0, 19, 2 ), // siz
_SHIFTR( words.w0, 0, 12 ) + 1, // width
words.w1 ); // img
}
void RDP_SetCombine( const Gwords words )
{
gDPSetCombine( _SHIFTR( words.w0, 0, 24 ), // muxs0
words.w1 ); // muxs1
}
void RDP_SetEnvColor( const Gwords words )
{
gDPSetEnvColor( _SHIFTR( words.w1, 24, 8 ), // r
_SHIFTR( words.w1, 16, 8 ), // g
_SHIFTR( words.w1, 8, 8 ), // b
_SHIFTR( words.w1, 0, 8 ) ); // a
}
void RDP_SetPrimColor( const Gwords words )
{
gDPSetPrimColor( _SHIFTR( words.w0, 8, 5 ), // m
_SHIFTR( words.w0, 0, 8 ), // l
_SHIFTR( words.w1, 24, 8 ), // r
_SHIFTR( words.w1, 16, 8 ), // g
_SHIFTR( words.w1, 8, 8 ), // b
_SHIFTR( words.w1, 0, 8 ) ); // a
}
void RDP_SetBlendColor( const Gwords words )
{
gDPSetBlendColor( _SHIFTR( words.w1, 24, 8 ), // r
_SHIFTR( words.w1, 16, 8 ), // g
_SHIFTR( words.w1, 8, 8 ), // b
_SHIFTR( words.w1, 0, 8 ) ); // a
}
void RDP_SetFogColor( const Gwords words )
{
gDPSetFogColor( _SHIFTR( words.w1, 24, 8 ), // r
_SHIFTR( words.w1, 16, 8 ), // g
_SHIFTR( words.w1, 8, 8 ), // b
_SHIFTR( words.w1, 0, 8 ) ); // a
}
void RDP_SetFillColor( const Gwords words )
{
gDPSetFillColor( words.w1 );
}
void RDP_FillRect( const Gwords words )
{
const u32 ulx = _SHIFTR(words.w1, 14, 10);
const u32 uly = _SHIFTR(words.w1, 2, 10);
const u32 lrx = _SHIFTR(words.w0, 14, 10);
const u32 lry = _SHIFTR(words.w0, 2, 10);
if (lrx < ulx || lry < uly)
return;
gDPFillRectangle(ulx, uly, lrx, lry);
}
void RDP_SetTile( const Gwords words )
{
gDPSetTile( _SHIFTR( words.w0, 21, 3 ), // fmt
_SHIFTR( words.w0, 19, 2 ), // siz
_SHIFTR( words.w0, 9, 9 ), // line
_SHIFTR( words.w0, 0, 9 ), // tmem
_SHIFTR( words.w1, 24, 3 ), // tile
_SHIFTR( words.w1, 20, 4 ), // palette
_SHIFTR( words.w1, 18, 2 ), // cmt
_SHIFTR( words.w1, 8, 2 ), // cms
_SHIFTR( words.w1, 14, 4 ), // maskt
_SHIFTR( words.w1, 4, 4 ), // masks
_SHIFTR( words.w1, 10, 4 ), // shiftt
_SHIFTR( words.w1, 0, 4 ) ); // shifts
}
#define LRS_UPPER_VALUE (_SHIFTR(words.w1, 27, 5) << 12)
#define TILE_VALUE _SHIFTR(words.w1, 24, 3)
#define LRS_VALUE _SHIFTR(words.w1, 12, 12)
#define LRT_VALUE _SHIFTR(words.w1, 0, 12)
void RDP_LoadTile( const Gwords words )
{
gDPLoadTile( TILE_VALUE, // tile
_SHIFTR( words.w0, 12, 12 ), // uls
_SHIFTR( words.w0, 0, 12 ), // ult
LRS_VALUE | LRS_UPPER_VALUE, // lrs
LRT_VALUE ); // lrt
}
static u32 lbw0, lbw1;
void RDP_LoadBlock( const Gwords words )
{
lbw0 = words.w0;
lbw1 = words.w1;
gDPLoadBlock( TILE_VALUE, // tile
_SHIFTR( words.w0, 12, 12 ), // uls
_SHIFTR( words.w0, 0, 12 ), // ult
LRS_VALUE | LRS_UPPER_VALUE, // lrs
LRT_VALUE ); // dxt
}
void RDP_RepeatLastLoadBlock()
{
RDP_LoadBlock(Gwords(lbw0, lbw1));
}
void RDP_SetTileSize( const Gwords words )
{
gDPSetTileSize( TILE_VALUE, // tile
_SHIFTR( words.w0, 12, 12 ), // uls
_SHIFTR( words.w0, 0, 12 ), // ult
LRS_VALUE | LRS_UPPER_VALUE, // lrs
LRT_VALUE ); // lrt
}
void RDP_LoadTLUT( const Gwords words )
{
gDPLoadTLUT( TILE_VALUE, // tile
_SHIFTR( words.w0, 12, 12 ), // uls
_SHIFTR( words.w0, 0, 12 ), // ult
LRS_VALUE | LRS_UPPER_VALUE, // lrs
LRT_VALUE ); // lrt
}
void RDP_SetOtherMode( const Gwords words )
{
gDPSetOtherMode( _SHIFTR( words.w0, 0, 24 ), // mode0
words.w1 ); // mode1
}
void RDP_SetPrimDepth( const Gwords words )
{
gDPSetPrimDepth( _SHIFTR( words.w1, 16, 16 ), // z
_SHIFTR( words.w1, 0, 16 ) ); // dz
}
void RDP_SetScissor( const Gwords words )
{
gDPSetScissor( _SHIFTR( words.w1, 24, 2 ), // mode
_SHIFTR( words.w0, 12, 12 ), // ulx
_SHIFTR( words.w0, 0, 12 ), // uly
_SHIFTR( words.w1, 12, 12 ), // lrx
_SHIFTR( words.w1, 0, 12 ) ); // lry
}
void RDP_SetConvert( const Gwords words )
{
gDPSetConvert( _SHIFTR( words.w0, 13, 9 ), // k0
_SHIFTR( words.w0, 4, 9 ), // k1
_SHIFTL( words.w0, 5, 4 ) | _SHIFTR( words.w1, 27, 5 ), // k2
_SHIFTR( words.w1, 18, 9 ), // k3
_SHIFTR( words.w1, 9, 9 ), // k4
_SHIFTR( words.w1, 0, 9 ) ); // k5
}
void RDP_SetKeyR( const Gwords words )
{
gDPSetKeyR( _SHIFTR( words.w1, 8, 8 ), // cR
_SHIFTR( words.w1, 0, 8 ), // sR
_SHIFTR( words.w1, 16, 12 ) ); // wR
}
void RDP_SetKeyGB( const Gwords words )
{
gDPSetKeyGB( _SHIFTR( words.w1, 24, 8 ), // cG
_SHIFTR( words.w1, 16, 8 ), // sG
_SHIFTR( words.w0, 12, 12 ), // wG
_SHIFTR( words.w1, 8, 8 ), // cB
_SHIFTR( words.w1, 0, 8 ), // SB
_SHIFTR( words.w0, 0, 12 ) ); // wB
}
void RDP_FullSync( const Gwords words )
{
gDPFullSync();
}
void RDP_TileSync( const Gwords words )
{
gDPTileSync();
}
void RDP_PipeSync( const Gwords words )
{
gDPPipeSync(words);
}
void RDP_LoadSync( const Gwords words )
{
gDPLoadSync();
}
static
bool _getTexRectParams(word & w2, word & w3)
{
if (RSP.LLE) {
w2 = RDP.w2;
w3 = RDP.w3;
return true;
}
enum {
gspTexRect,
gdpTexRect,
halfTexRect
} texRectMode = gdpTexRect;
const word cmd1 = (*(word*)&RDRAM[RSP.PC[RSP.PCi] + 0]) >> 24;
const word cmd2 = (*(word*)&RDRAM[RSP.PC[RSP.PCi] + sizeof(Gwords)]) >> 24;
if (cmd1 == G_RDPHALF_1) {
if (cmd2 == G_RDPHALF_2)
texRectMode = gspTexRect;
} else if (cmd1 == 0xB3) {
texRectMode = halfTexRect;
} else if (cmd1 == 0xF1)
texRectMode = halfTexRect;
switch (texRectMode) {
case gspTexRect:
w2 = *(word*)&RDRAM[RSP.PC[RSP.PCi] + 4];
RSP.PC[RSP.PCi] += sizeof(Gwords);
w3 = *(word*)&RDRAM[RSP.PC[RSP.PCi] + 4];
RSP.PC[RSP.PCi] += sizeof(Gwords);
break;
case gdpTexRect:
if ((config.generalEmulation.hacks & hack_WinBack) != 0) {
RSP.PC[RSP.PCi] += sizeof(Gwords);
return false;
}
{
const word ucode = GBI.getMicrocodeType();
if (ucode == F5Rogue || ucode == F5Indi_Naboo) {
w2 = *(word*)&RDRAM[RSP.PC[RSP.PCi] + 8];
w3 = *(word*)&RDRAM[RSP.PC[RSP.PCi] + 12];
RSP.PC[RSP.PCi] += sizeof(Gwords);
return true;
}
}
w2 = *(word*)&RDRAM[RSP.PC[RSP.PCi] + 0];
w3 = *(word*)&RDRAM[RSP.PC[RSP.PCi] + 4];
RSP.PC[RSP.PCi] += sizeof(Gwords);
break;
case halfTexRect:
w2 = 0;
w3 = *(word*)&RDRAM[RSP.PC[RSP.PCi] + 4];
RSP.PC[RSP.PCi] += sizeof(Gwords);
break;
default:
assert(false && "Unknown texrect mode");
}
return true;
}
static
void _TexRect( const Gwords words, bool flip )
{
word w2, w3;
if (!_getTexRectParams(w2, w3))
return;
RDP.w0 = words.w0;
RDP.w1 = words.w1;
const u32 rawScalerValue = _SHIFTR(words.w1, 27, 5);
const s32 ulx = SIGN12(_SHIFTR(words.w1, 12, 12)) << rawScalerValue;
const s32 uly = _SHIFTR(words.w1, 0, 12);
const s32 lrx = SIGN12(_SHIFTR(words.w0, 12, 12)) << rawScalerValue;
const s32 lry = _SHIFTR(words.w0, 0, 12);
if (lrx < ulx || lry < uly)
return;
if (gDP.otherMode.cycleType == G_CYC_COPY)
gDPTextureRectangle(
f32(ulx >> 2),
f32(uly >> 2),
f32(lrx >> 2),
f32(lry >> 2),
_SHIFTR(words.w1, 24, 3), // tile
(s16)_SHIFTR(w2, 16, 16), // s
(s16)_SHIFTR(w2, 0, 16), // t
_FIXED2FLOAT((s16)_SHIFTR(w3, 16, 16), 10), // dsdx
_FIXED2FLOAT((s16)_SHIFTR(w3, 0, 16), 10), // dsdy
flip);
else
gDPTextureRectangle(
_FIXED2FLOAT(ulx, 2),
_FIXED2FLOAT(uly, 2),
_FIXED2FLOAT(lrx, 2),
_FIXED2FLOAT(lry, 2),
_SHIFTR(words.w1, 24, 3), // tile
(s16)_SHIFTR(w2, 16, 16), // s
(s16)_SHIFTR(w2, 0, 16), // t
_FIXED2FLOAT((s16)_SHIFTR(w3, 16, 16), 10), // dsdx
_FIXED2FLOAT((s16)_SHIFTR(w3, 0, 16), 10), // dsdy
flip);
}
void RDP_TexRectFlip( const Gwords words )
{
_TexRect(words, true);
}
void RDP_TexRect( const Gwords words )
{
_TexRect(words, false);
}
void RDP_TriFill(const Gwords words)
{
gDPTriFill(words.w0, words.w1);
}
void RDP_TriShade(const Gwords words)
{
gDPTriShade(words.w0, words.w1);
}
void RDP_TriTxtr(const Gwords words)
{
gDPTriTxtr(words.w0, words.w1);
}
void RDP_TriShadeTxtr(const Gwords words)
{
gDPTriShadeTxtr(words.w0, words.w1);
}
void RDP_TriFillZ(const Gwords words)
{
gDPTriFillZ(words.w0, words.w1);
}
void RDP_TriShadeZ(const Gwords words)
{
gDPTriShadeZ(words.w0, words.w1);
}
void RDP_TriTxtrZ(const Gwords words)
{
gDPTriTxtrZ(words.w0, words.w1);
}
void RDP_TriShadeTxtrZ(const Gwords words)
{
gDPTriShadeTxtrZ(words.w0, words.w1);
}
RDPInfo RDP;
void RDP_Init()
{
// Initialize RDP commands to RDP_UNKNOWN
for (int i = 0xC8; i <= 0xCF; i++)
GBI.cmd[i] = RDP_Unknown;
// Initialize RDP commands to RDP_UNKNOWN
for (int i = 0xE4; i <= 0xFF; i++)
GBI.cmd[i] = RDP_Unknown;
// Set known GBI commands
GBI.cmd[G_NOOP] = RDP_NoOp;
GBI.cmd[G_SETCIMG] = RDP_SetCImg;
GBI.cmd[G_SETZIMG] = RDP_SetZImg;
GBI.cmd[G_SETTIMG] = RDP_SetTImg;
GBI.cmd[G_SETCOMBINE] = RDP_SetCombine;
GBI.cmd[G_SETENVCOLOR] = RDP_SetEnvColor;
GBI.cmd[G_SETPRIMCOLOR] = RDP_SetPrimColor;
GBI.cmd[G_SETBLENDCOLOR] = RDP_SetBlendColor;
GBI.cmd[G_SETFOGCOLOR] = RDP_SetFogColor;
GBI.cmd[G_SETFILLCOLOR] = RDP_SetFillColor;
GBI.cmd[G_FILLRECT] = RDP_FillRect;
GBI.cmd[G_SETTILE] = RDP_SetTile;
GBI.cmd[G_LOADTILE] = RDP_LoadTile;
GBI.cmd[G_LOADBLOCK] = RDP_LoadBlock;
GBI.cmd[G_SETTILESIZE] = RDP_SetTileSize;
GBI.cmd[G_LOADTLUT] = RDP_LoadTLUT;
GBI.cmd[G_RDPSETOTHERMODE] = RDP_SetOtherMode;
GBI.cmd[G_SETPRIMDEPTH] = RDP_SetPrimDepth;
GBI.cmd[G_SETSCISSOR] = RDP_SetScissor;
GBI.cmd[G_SETCONVERT] = RDP_SetConvert;
GBI.cmd[G_SETKEYR] = RDP_SetKeyR;
GBI.cmd[G_SETKEYGB] = RDP_SetKeyGB;
GBI.cmd[G_RDPFULLSYNC] = RDP_FullSync;
GBI.cmd[G_RDPTILESYNC] = RDP_TileSync;
GBI.cmd[G_RDPPIPESYNC] = RDP_PipeSync;
GBI.cmd[G_RDPLOADSYNC] = RDP_LoadSync;
GBI.cmd[G_TEXRECTFLIP] = RDP_TexRectFlip;
GBI.cmd[G_TEXRECT] = RDP_TexRect;
GBI.cmd[G_RDPNOOP] = RDP_NoOp;
#ifdef NATIVE
GBI.cmd[G_MARK_SEGMENT] = RDP_MarkSegment;
#endif
RDP.w0 = RDP.w1 = RDP.w2 = RDP.w3 = 0;
RDP.cmd_ptr = RDP.cmd_cur = 0;
}
static
GBIFunc LLEcmd[64] = {
/* 0x00 */
RDP_NoOp, RDP_Unknown, RDP_Unknown, RDP_Unknown,
RDP_Unknown, RDP_Unknown, RDP_Unknown, RDP_Unknown,
RDP_TriFill, RDP_TriFillZ, RDP_TriTxtr, RDP_TriTxtrZ,
RDP_TriShade, RDP_TriShadeZ, RDP_TriShadeTxtr, RDP_TriShadeTxtrZ,
/* 0x10 */
RDP_Unknown, RDP_Unknown, RDP_Unknown, RDP_Unknown,
RDP_Unknown, RDP_Unknown, RDP_Unknown, RDP_Unknown,
RDP_Unknown, RDP_Unknown, RDP_Unknown, RDP_Unknown,
RDP_Unknown, RDP_Unknown, RDP_Unknown, RDP_Unknown,
/* 0x20 */
RDP_Unknown, RDP_Unknown, RDP_Unknown, RDP_Unknown,
RDP_TexRect, RDP_TexRectFlip, RDP_LoadSync, RDP_PipeSync,
RDP_TileSync, RDP_FullSync, RDP_SetKeyGB, RDP_SetKeyR,
RDP_SetConvert, RDP_SetScissor, RDP_SetPrimDepth, RDP_SetOtherMode,
/* 0x30 */
RDP_LoadTLUT, RDP_Unknown, RDP_SetTileSize, RDP_LoadBlock,
RDP_LoadTile, RDP_SetTile, RDP_FillRect, RDP_SetFillColor,
RDP_SetFogColor, RDP_SetBlendColor, RDP_SetPrimColor, RDP_SetEnvColor,
RDP_SetCombine, RDP_SetTImg, RDP_SetZImg, RDP_SetCImg
};
static
const u32 CmdLength[64] =
{
8, // 0x00, No Op
8, // 0x01, ???
8, // 0x02, ???
8, // 0x03, ???
8, // 0x04, ???
8, // 0x05, ???
8, // 0x06, ???
8, // 0x07, ???
32, // 0x08, Non-Shaded Triangle
32+16, // 0x09, Non-Shaded, Z-Buffered Triangle
32+64, // 0x0a, Textured Triangle
32+64+16, // 0x0b, Textured, Z-Buffered Triangle
32+64, // 0x0c, Shaded Triangle
32+64+16, // 0x0d, Shaded, Z-Buffered Triangle
32+64+64, // 0x0e, Shaded+Textured Triangle
32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle
8, // 0x10, ???
8, // 0x11, ???
8, // 0x12, ???
8, // 0x13, ???
8, // 0x14, ???
8, // 0x15, ???
8, // 0x16, ???
8, // 0x17, ???
8, // 0x18, ???
8, // 0x19, ???
8, // 0x1a, ???
8, // 0x1b, ???
8, // 0x1c, ???
8, // 0x1d, ???
8, // 0x1e, ???
8, // 0x1f, ???
8, // 0x20, ???
8, // 0x21, ???
8, // 0x22, ???
8, // 0x23, ???
16, // 0x24, Texture_Rectangle
16, // 0x25, Texture_Rectangle_Flip
8, // 0x26, Sync_Load
8, // 0x27, Sync_Pipe
8, // 0x28, Sync_Tile
8, // 0x29, Sync_Full
8, // 0x2a, Set_Key_GB
8, // 0x2b, Set_Key_R
8, // 0x2c, Set_Convert
8, // 0x2d, Set_Scissor
8, // 0x2e, Set_Prim_Depth
8, // 0x2f, Set_Other_Modes
8, // 0x30, Load_TLUT
8, // 0x31, ???
8, // 0x32, Set_Tile_Size
8, // 0x33, Load_Block
8, // 0x34, Load_Tile
8, // 0x35, Set_Tile
8, // 0x36, Fill_Rectangle
8, // 0x37, Set_Fill_Color
8, // 0x38, Set_Fog_Color
8, // 0x39, Set_Blend_Color
8, // 0x3a, Set_Prim_Color
8, // 0x3b, Set_Env_Color
8, // 0x3c, Set_Combine
8, // 0x3d, Set_Texture_Image
8, // 0x3e, Set_Mask_Image
8 // 0x3f, Set_Color_Image
};
void RDP_Half_1( u32 _c )
{
word w0 = 0, w1 = _c;
word cmd = _SHIFTR( _c, 24, 8 );
if (cmd >= 0xc8 && cmd <=0xcf) {//triangle command
DebugMsg(DEBUG_NORMAL, "gDPHalf_1 LLE Triangle\n");
RDP.cmd_ptr = 0;
RDP.cmd_cur = 0;
do {
RDP.cmd_data[RDP.cmd_ptr++] = w1;
RSP_CheckDLCounter();
w0 = *(word*)&RDRAM[RSP.PC[RSP.PCi]];
w1 = *(word*)&RDRAM[RSP.PC[RSP.PCi] + 4];
RSP.cmd = _SHIFTR( w0, 24, 8 );
DebugMsg(DEBUG_NORMAL, "0x%08lX: CMD=0x%02lX w0=0x%08lX w1=0x%08lX\n", RSP.PC[RSP.PCi], _SHIFTR(w0, 24, 8), w0, w1);
RSP.PC[RSP.PCi] += sizeof(Gwords);
// RSP.nextCmd = _SHIFTR( *(u32*)&RDRAM[RSP.PC[RSP.PCi]], 24, 8 );
} while (RSP.cmd != 0xb3);
RDP.cmd_data[RDP.cmd_ptr++] = w1;
RSP.cmd = (RDP.cmd_data[RDP.cmd_cur] >> 24) & 0x3f;
w0 = RDP.cmd_data[RDP.cmd_cur+0];
w1 = RDP.cmd_data[RDP.cmd_cur+1];
LLEcmd[RSP.cmd](Gwords(w0, w1));
LLETriangle::get().flush(cmd);
} else {
DebugMsg(DEBUG_NORMAL | DEBUG_IGNORED, "gDPHalf_1()\n");
}
}
#ifdef NATIVE
#define rdram ((u32*)0)
#define rsp_dmem ((u32*)0)
#else
#define rdram ((u32*)RDRAM)
#define rsp_dmem ((u32*)DMEM)
#endif
#define dp_start (*(word*)REG.DPC_START)
#define dp_end (*(word*)REG.DPC_END)
#define dp_current (*(word*)REG.DPC_CURRENT)
#define dp_status (*(word*)REG.DPC_STATUS)
#ifdef NATIVE
inline u32 READ_RDP_DATA(word address) {
return rsp_dmem[(address & 0xfff) >> 2];
}
#else
inline u32 READ_RDP_DATA(word address)
{
if (dp_status & 0x1) // XBUS_DMEM_DMA enabled
return rsp_dmem[(address & 0xfff)>>2];
else
return rdram[(address & 0xffffff)>>2];
}
#endif
void RDP_ProcessRDPList()
{
if (ConfigOpen || dwnd().isResizeWindow()) {
dp_start = dp_current = dp_end;
gDPFullSync();
return;
}
const u32 length = dp_end - dp_current;
if (dp_end <= dp_current) return;
RSP.LLE = true;
// load command data
for (u32 i = 0; i < length; i += 4) {
RDP.cmd_data[RDP.cmd_ptr] = READ_RDP_DATA(dp_current + i);
RDP.cmd_ptr = (RDP.cmd_ptr + 1) & maxCMDMask;
}
bool setZero = true;
while (RDP.cmd_cur != RDP.cmd_ptr) {
word cmd = (RDP.cmd_data[RDP.cmd_cur] >> 24) & 0x3f;
if ((((RDP.cmd_ptr - RDP.cmd_cur)&maxCMDMask) * 4) < CmdLength[cmd]) {
setZero = false;
break;
}
if (RDP.cmd_cur + CmdLength[cmd] / 4 > MAXCMD)
::memcpy(RDP.cmd_data + MAXCMD, RDP.cmd_data, CmdLength[cmd] - (MAXCMD - RDP.cmd_cur) * 4);
// execute the command
RDP.w0 = RDP.cmd_data[RDP.cmd_cur + 0];
RDP.w1 = RDP.cmd_data[RDP.cmd_cur + 1];
RDP.w2 = RDP.cmd_data[RDP.cmd_cur + 2];
RDP.w3 = RDP.cmd_data[RDP.cmd_cur + 3];
RSP.cmd = cmd;
#ifdef DEBUG_DUMP
DebugMsg(DEBUG_LOW, "CMD=0x%02lX words.w0=0x%08lX words.w1=0x%08lX\n", cmd, RDP.w0, RDP.w1);
#endif
LLETriangle::get().flush(cmd);
LLEcmd[cmd](Gwords(RDP.w0, RDP.w1));
RDP.cmd_cur = (RDP.cmd_cur + CmdLength[cmd] / 4) & maxCMDMask;
}
if (setZero) {
RDP.cmd_ptr = 0;
RDP.cmd_cur = 0;
}
gDP.changed |= CHANGED_COLORBUFFER;
gDP.changed &= ~CHANGED_CPU_FB_WRITE;
dp_start = dp_current = dp_end;
}