1 /******************************************************************************
2 * Arachnoid Graphics Plugin for Mupen64Plus
3 * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
5 * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *****************************************************************************/
28 #include "UCodeDefs.h"
31 #include "DisplayListParser.h"
34 #define F3DEX2_MTX_STACKSIZE 18
36 #define F3DEX2_MTX_MODELVIEW 0x00
37 #define F3DEX2_MTX_PROJECTION 0x04
38 #define F3DEX2_MTX_MUL 0x00
39 #define F3DEX2_MTX_LOAD 0x02
40 #define F3DEX2_MTX_NOPUSH 0x00
41 #define F3DEX2_MTX_PUSH 0x01
43 #define F3DEX2_TEXTURE_ENABLE 0x00000000
44 #define F3DEX2_SHADING_SMOOTH 0x00200000
45 #define F3DEX2_CULL_FRONT 0x00000200
46 #define F3DEX2_CULL_BACK 0x00000400
47 #define F3DEX2_CULL_BOTH 0x00000600
48 #define F3DEX2_CLIPPING 0x00800000
50 #define F3DEX2_MV_VIEWPORT 8
52 #define F3DEX2_MWO_aLIGHT_1 0x00
53 #define F3DEX2_MWO_bLIGHT_1 0x04
54 #define F3DEX2_MWO_aLIGHT_2 0x18
55 #define F3DEX2_MWO_bLIGHT_2 0x1c
56 #define F3DEX2_MWO_aLIGHT_3 0x30
57 #define F3DEX2_MWO_bLIGHT_3 0x34
58 #define F3DEX2_MWO_aLIGHT_4 0x48
59 #define F3DEX2_MWO_bLIGHT_4 0x4c
60 #define F3DEX2_MWO_aLIGHT_5 0x60
61 #define F3DEX2_MWO_bLIGHT_5 0x64
62 #define F3DEX2_MWO_aLIGHT_6 0x78
63 #define F3DEX2_MWO_bLIGHT_6 0x7c
64 #define F3DEX2_MWO_aLIGHT_7 0x90
65 #define F3DEX2_MWO_bLIGHT_7 0x94
66 #define F3DEX2_MWO_aLIGHT_8 0xa8
67 #define F3DEX2_MWO_bLIGHT_8 0xac
70 #define F3DEX2_RDPHALF_2 0xF1
71 #define F3DEX2_SETOTHERMODE_H 0xE3
72 #define F3DEX2_SETOTHERMODE_L 0xE2
73 #define F3DEX2_RDPHALF_1 0xE1
74 #define F3DEX2_SPNOOP 0xE0
75 #define F3DEX2_ENDDL 0xDF
76 #define F3DEX2_DL 0xDE
77 #define F3DEX2_LOAD_UCODE 0xDD
78 #define F3DEX2_MTX 0xDA
79 #define F3DEX2_GEOMETRYMODE 0xD9
80 #define F3DEX2_POPMTX 0xD8
81 #define F3DEX2_TEXTURE 0xD7
82 #define F3DEX2_DMA_IO 0xD6
83 #define F3DEX2_SPECIAL_1 0xD5
84 #define F3DEX2_SPECIAL_2 0xD4
85 #define F3DEX2_SPECIAL_3 0xD3
87 #define F3DEX2_VTX 0x01
88 #define F3DEX2_MODIFYVTX 0x02
89 #define F3DEX2_CULLDL 0x03
90 #define F3DEX2_BRANCH_Z 0x04
91 #define F3DEX2_TRI1 0x05
92 #define F3DEX2_TRI2 0x06
93 #define F3DEX2_QUAD 0x07
94 #define F3DEX2_LINE3D 0x08
97 //-----------------------------------------------------------------------------
99 //-----------------------------------------------------------------------------
100 RSP* UCode5::m_rsp = 0; //!< Pointer to Reality Signal Processor
101 RDP* UCode5::m_rdp = 0; //!< Pointer to Reality Drawing Processor
102 Memory* UCode5::m_memory = 0;
103 GBI* UCode5::m_gbi = 0;
104 DisplayListParser* UCode5::m_displayListParser = 0;
106 //-----------------------------------------------------------------------------
108 //-----------------------------------------------------------------------------
113 //-----------------------------------------------------------------------------
115 //-----------------------------------------------------------------------------
120 //-----------------------------------------------------------------------------
122 //-----------------------------------------------------------------------------
123 void UCode5::initialize(GBI* gbi, RSP* rsp, RDP* rdp, Memory* memory, DisplayListParser* dlp)
129 m_displayListParser = dlp;
132 //-----------------------------------------------------------------------------
134 //-----------------------------------------------------------------------------
135 void UCode5::initializeGBI()
138 GBI_InitFlags( F3DEX2 );
141 // GBI Command Command Value Command Function
142 GBI_SetGBI( GBI::G_RDPHALF_2, F3DEX2_RDPHALF_2, m_gbi->m_cmds, UCode0::F3D_RDPHalf_2 );
143 GBI_SetGBI( GBI::G_SETOTHERMODE_H, F3DEX2_SETOTHERMODE_H, m_gbi->m_cmds, F3DEX2_SetOtherMode_H );
144 GBI_SetGBI( GBI::G_SETOTHERMODE_L, F3DEX2_SETOTHERMODE_L, m_gbi->m_cmds, F3DEX2_SetOtherMode_L );
145 GBI_SetGBI( GBI::G_RDPHALF_1, F3DEX2_RDPHALF_1, m_gbi->m_cmds, UCode0::F3D_RDPHalf_1 );
146 GBI_SetGBI( GBI::G_SPNOOP, F3DEX2_SPNOOP, m_gbi->m_cmds, UCode0::F3D_SPNoOp );
147 GBI_SetGBI( GBI::G_ENDDL, F3DEX2_ENDDL, m_gbi->m_cmds, UCode0::F3D_EndDL );
148 GBI_SetGBI( GBI::G_DL, F3DEX2_DL, m_gbi->m_cmds, UCode0::F3D_DList );
149 GBI_SetGBI( GBI::G_LOAD_UCODE, F3DEX2_LOAD_UCODE, m_gbi->m_cmds, UCode1::F3DEX_Load_uCode );
150 GBI_SetGBI( GBI::G_MOVEMEM, F3DEX2_MOVEMEM, m_gbi->m_cmds, F3DEX2_MoveMem );
151 GBI_SetGBI( GBI::G_MOVEWORD, F3DEX2_MOVEWORD, m_gbi->m_cmds, F3DEX2_MoveWord );
152 GBI_SetGBI( GBI::G_MTX, F3DEX2_MTX, m_gbi->m_cmds, F3DEX2_Mtx );
153 GBI_SetGBI( GBI::G_GEOMETRYMODE, F3DEX2_GEOMETRYMODE, m_gbi->m_cmds, F3DEX2_GeometryMode );
154 GBI_SetGBI( GBI::G_POPMTX, F3DEX2_POPMTX, m_gbi->m_cmds, F3DEX2_PopMtx );
155 GBI_SetGBI( GBI::G_TEXTURE, F3DEX2_TEXTURE, m_gbi->m_cmds, F3DEX2_Texture );
156 GBI_SetGBI( GBI::G_DMA_IO, F3DEX2_DMA_IO, m_gbi->m_cmds, F3DEX2_DMAIO );
157 GBI_SetGBI( GBI::G_SPECIAL_1, F3DEX2_SPECIAL_1, m_gbi->m_cmds, F3DEX2_Special_1 );
158 GBI_SetGBI( GBI::G_SPECIAL_2, F3DEX2_SPECIAL_2, m_gbi->m_cmds, F3DEX2_Special_2 );
159 GBI_SetGBI( GBI::G_SPECIAL_3, F3DEX2_SPECIAL_3, m_gbi->m_cmds, F3DEX2_Special_3 );
160 GBI_SetGBI( GBI::G_VTX, F3DEX2_VTX, m_gbi->m_cmds, F3DEX2_Vtx );
161 GBI_SetGBI( GBI::G_MODIFYVTX, F3DEX2_MODIFYVTX, m_gbi->m_cmds, UCode1::F3DEX_ModifyVtx );
162 GBI_SetGBI( GBI::G_CULLDL, F3DEX2_CULLDL, m_gbi->m_cmds, UCode1::F3DEX_CullDL );
163 GBI_SetGBI( GBI::G_BRANCH_Z, F3DEX2_BRANCH_Z, m_gbi->m_cmds, UCode1::F3DEX_Branch_Z );
164 GBI_SetGBI( GBI::G_TRI1, F3DEX2_TRI1, m_gbi->m_cmds, F3DEX2_Tri1 );
165 GBI_SetGBI( GBI::G_TRI2, F3DEX2_TRI2, m_gbi->m_cmds, UCode1::F3DEX_Tri2 );
166 GBI_SetGBI( GBI::G_QUAD, F3DEX2_QUAD, m_gbi->m_cmds, F3DEX2_Quad );
167 GBI_SetGBI( GBI::G_LINE3D, F3DEX2_LINE3D, m_gbi->m_cmds, F3DEX2_Line3D );
170 //*****************************************************************************
172 //*****************************************************************************
174 //-----------------------------------------------------------------------------
176 //! @todo Bomberman2 hack
177 //! @todo South park rally hack
178 //-----------------------------------------------------------------------------
179 void UCode5::F3DEX2_Mtx( MicrocodeArgument* ucode )
181 Logger::getSingleton().printMsg("F3DEX2_Mtx", M64MSG_VERBOSE);
182 RSPUCodeAddMatrixF3DEX2* temp = (RSPUCodeAddMatrixF3DEX2*)ucode;
184 //TODO Bomberman2 hack
185 if( temp->param == 0 && temp->lenght == 0 )
187 //Bomberman2TextRect(ucode);
188 Logger::getSingleton().printMsg("F3DEX2_Mtx - Bomberman2TextRect - Unimplemented", M64MSG_WARNING);
193 m_rsp->RSP_Matrix( temp->segmentAddress, temp->projection, !temp->nopush, temp->load );
195 //For Conker Bad Fur Day
196 m_rsp->getVertexMgr()->setConkerAddress(0);
198 //TODO South park rally hack
201 //-----------------------------------------------------------------------------
203 //-----------------------------------------------------------------------------
204 void UCode5::F3DEX2_PopMtx( MicrocodeArgument* ucode )
206 Logger::getSingleton().printMsg("F3DEX2_PopMtx", M64MSG_VERBOSE);
208 m_rsp->RSP_PopMatrixN( ucode->w1 >> 6 );
211 //*****************************************************************************
213 //*****************************************************************************
215 //-----------------------------------------------------------------------------
217 //-----------------------------------------------------------------------------
218 void UCode5::F3DEX2_Texture( MicrocodeArgument* ucode )
220 Logger::getSingleton().printMsg("F3DEX2_Texture", M64MSG_VERBOSE);
222 float scaleS = _FIXED2FLOAT( _SHIFTR( ucode->w1, 16, 16 ), 16 );
223 float scaleT = _FIXED2FLOAT( _SHIFTR( ucode->w1, 0, 16 ), 16 );
224 int level = _SHIFTR( ucode->w0, 11, 3 );
225 int tile = _SHIFTR( ucode->w0, 8, 3 );
226 int on = _SHIFTR( ucode->w0, 1, 7 );
228 m_rsp->RSP_Texture(scaleS, scaleT, level, tile, on);
231 //*****************************************************************************
232 // Vertices and indices
233 //*****************************************************************************
235 //-----------------------------------------------------------------------------
237 //-----------------------------------------------------------------------------
238 void UCode5::F3DEX2_Vtx( MicrocodeArgument* ucode )
240 Logger::getSingleton().printMsg("F3DEX2_Vtx", M64MSG_VERBOSE);
241 RSPUCodeAddVerticesF3DEX2* temp = (RSPUCodeAddVerticesF3DEX2*)ucode;
244 m_rsp->RSP_Vertex(temp->segmentAddress, temp->numVertices, temp->vertexEnd - temp->numVertices);
247 //-----------------------------------------------------------------------------
249 //! @todo Add triangle flag
250 //-----------------------------------------------------------------------------
251 void UCode5::F3DEX2_Tri1( MicrocodeArgument* ucode )
253 Logger::getSingleton().printMsg("F3DEX2_Tri1", M64MSG_VERBOSE);
254 RSPUCodeAddOneTriangleF3DEX2* temp = (RSPUCodeAddOneTriangleF3DEX2*)ucode;
257 m_rsp->RSP_1Triangle( temp->index0 / 2, temp->index1 / 2, temp->index2 / 2); //TODO flag
260 //-----------------------------------------------------------------------------
262 //-----------------------------------------------------------------------------
263 void UCode5::F3DEX2_Quad( MicrocodeArgument* ucode )
265 Logger::getSingleton().printMsg("F3DEX2_Quad", M64MSG_VERBOSE);
266 RSPUCodeAddOneQuadF3DEX2* temp = (RSPUCodeAddOneQuadF3DEX2*)ucode;
269 m_rsp->RSP_2Triangles( temp->v0 / 2, temp->v1 / 2, temp->v2 / 2, 0,
270 temp->v3 / 2, temp->v4 / 2, temp->v5 / 2, 0 );
273 //-----------------------------------------------------------------------------
275 //-----------------------------------------------------------------------------
276 void UCode5::F3DEX2_Line3D( MicrocodeArgument* ucode )
278 Logger::getSingleton().printMsg("F3DEX2_Line3D - Unimplemented", M64MSG_WARNING);
282 //*****************************************************************************
284 //*****************************************************************************
286 //-----------------------------------------------------------------------------
288 //-----------------------------------------------------------------------------
289 void UCode5::F3DEX2_MoveMem( MicrocodeArgument* ucode )
291 Logger::getSingleton().printMsg("F3DEX2_MoveMem", M64MSG_VERBOSE);
293 switch (_SHIFTR( ucode->w0, 0, 8 ))
295 case F3DEX2_MV_VIEWPORT:
296 m_rsp->moveMemViewport( ucode->w1 );
299 m_rsp->RSP_ForceMatrix( ucode->w1 );
300 m_displayListParser->increasePC(8); // force matrix takes two commands
304 unsigned int dwOffset2 = ((ucode->w0) >> 5) & 0x3FFF;
310 s8 * pcBase = g_pRDRAMs8 + addr;
311 LOG_UCODE(" RSP_GBI1_MV_MEM_LOOKATX %f %f %f",
312 (float)pcBase[8 ^ 0x3],
313 (float)pcBase[9 ^ 0x3],
314 (float)pcBase[10 ^ 0x3]);
320 s8 * pcBase = g_pRDRAMs8 + addr;
321 LOG_UCODE(" RSP_GBI1_MV_MEM_LOOKATY %f %f %f",
322 (float)pcBase[8 ^ 0x3],
323 (float)pcBase[9 ^ 0x3],
324 (float)pcBase[10 ^ 0x3]);
327 default: //0x30/48/60
329 uint32 dwLight = (dwOffset2 - 0x30)/0x18;
330 LOG_UCODE(" Light %d:", dwLight);
331 RSP_MoveMemLight(dwLight, addr);
337 unsigned int offset = _SHIFTR( ucode->w0, 8, 8 ) << 3;
341 m_rsp->RSP_Light( ((offset - 24) / 24) - 1, ucode->w1);
345 static bool warned = false;
347 Logger::getSingleton().printMsg("F3DEX2_MoveMem - Light - Unimplemented", M64MSG_WARNING);
356 //-----------------------------------------------------------------------------
358 //-----------------------------------------------------------------------------
359 void UCode5::F3DEX2_MoveWord(MicrocodeArgument* ucode)
361 Logger::getSingleton().printMsg("F3DEX2_MoveWord", M64MSG_VERBOSE);
362 RSPUCodeMoveWordF3DEX2* temp = (RSPUCodeMoveWordF3DEX2*)ucode;
364 switch ( temp->type )
367 Logger::getSingleton().printMsg("ForceMatrix - Unimplemented", M64MSG_WARNING); // Handled in movemem???
371 m_rsp->RSP_InsertMatrix( _SHIFTR( ucode->w0, 0, 16 ), ucode->w1 );
375 m_rsp->RSP_NumLights(temp->value / 24);
379 m_rsp->moveSegment(temp->offset>>2, temp->value & 0x00FFFFFF);
383 //gSPClipRatio( ucode->w1 );
387 m_rsp->RSP_FogFactor( (short)temp->fm, (short)temp->fo);
391 //gSPPerspNormalize( w1 );
395 if ( (temp->offset & 0x7) == 0 )
397 m_rsp->RSP_LightColor(temp->offset / 0x18, temp->value);
403 //-----------------------------------------------------------------------------
405 //-----------------------------------------------------------------------------
406 void UCode5::F3DEX2_GeometryMode( MicrocodeArgument* ucode )
408 Logger::getSingleton().printMsg("F3DEX2_GeometryMode", M64MSG_VERBOSE);
410 m_rsp->RSP_GeometryMode( ~_SHIFTR( ucode->w0, 0, 24 ), ucode->w1 );
413 //-----------------------------------------------------------------------------
415 //! @todo more case in switch
416 //-----------------------------------------------------------------------------
417 void UCode5::F3DEX2_SetOtherMode_H( MicrocodeArgument* ucode )
419 Logger::getSingleton().printMsg("F3DEX2_SetOtherMode_H", M64MSG_VERBOSE);
421 switch (32 - _SHIFTR( ucode->w0, 8, 8 ) - (_SHIFTR( ucode->w0, 0, 8 ) + 1))
423 case G_MDSFT_CYCLETYPE: m_rdp->setCycleType( ucode->w1 >> G_MDSFT_CYCLETYPE ); break;
424 case G_MDSFT_TEXTLUT: m_rdp->setTextureLUT( ucode->w1 >> G_MDSFT_TEXTLUT ); break;
427 case G_MDSFT_PIPELINE: //m_rdp->setPiplineMode( w1 >> G_MDSFT_PIPELINE );
429 case G_MDSFT_TEXTPERSP: //m_rdp->setTexturePerspective( w1 >> G_MDSFT_TEXTPERSP );
431 case G_MDSFT_TEXTDETAIL: //m_rdp->setTextureDetail( w1 >> G_MDSFT_TEXTDETAIL );
433 case G_MDSFT_TEXTLOD: //gDPSetTextureLOD( w1 >> G_MDSFT_TEXTLOD );
435 case G_MDSFT_TEXTFILT: //gDPSetTextureFilter( w1 >> G_MDSFT_TEXTFILT );
437 case G_MDSFT_TEXTCONV: //gDPSetTextureConvert( w1 >> G_MDSFT_TEXTCONV );
439 case G_MDSFT_COMBKEY: //gDPSetCombineKey( w1 >> G_MDSFT_COMBKEY );
441 case G_MDSFT_RGBDITHER: //gDPSetColorDither( w1 >> G_MDSFT_RGBDITHER );
443 case G_MDSFT_ALPHADITHER: //gDPSetAlphaDither( w1 >> G_MDSFT_ALPHADITHER );
446 Logger::getSingleton().printMsg("F3DEX2_SetOtherMode_L - Unknown type", M64MSG_WARNING);
448 unsigned int length = _SHIFTR( ucode->w0, 0, 8 ) + 1;
449 unsigned int shift = 32 - _SHIFTR( ucode->w0, 8, 8 ) - length;
450 unsigned int mask = ((1 << length) - 1) << shift;
452 m_rdp->m_otherMode.h &= ~mask;
453 m_rdp->m_otherMode.h |= ucode->w1 & mask;
455 m_rdp->setUpdateCombiner(true);
460 //-----------------------------------------------------------------------------
462 //-----------------------------------------------------------------------------
463 void UCode5::F3DEX2_SetOtherMode_L( MicrocodeArgument* ucode )
465 Logger::getSingleton().printMsg("F3DEX2_SetOtherMode_L", M64MSG_VERBOSE);
467 switch (32 - _SHIFTR( ucode->w0, 8, 8 ) - (_SHIFTR( ucode->w0, 0, 8 ) + 1))
469 case G_MDSFT_ALPHACOMPARE:
470 m_rdp->setAlphaCompareMode(ucode->w1 >> G_MDSFT_ALPHACOMPARE);
472 case G_MDSFT_ZSRCSEL:
473 m_rdp->setDepthSource( ucode->w1 >> G_MDSFT_ZSRCSEL );
475 case G_MDSFT_RENDERMODE:
476 m_rdp->setRenderMode( ucode->w1 );
479 unsigned int length = _SHIFTR( ucode->w0, 0, 8 ) + 1;
480 unsigned int shift = 32 - _SHIFTR( ucode->w0, 8, 8 ) - length;
481 unsigned int mask = ((1 << length) - 1) << shift;
482 m_rdp->m_otherMode.l &= ~mask;
483 m_rdp->m_otherMode.l |= ucode->w1 & mask;
488 //*****************************************************************************
490 //*****************************************************************************
492 void UCode5::F3DEX2_DMAIO( MicrocodeArgument* ucode ) {
493 Logger::getSingleton().printMsg("F3DEX2_DMAIO", M64MSG_VERBOSE);
496 void UCode5::F3DEX2_Special_1( MicrocodeArgument* ucode ) {
497 Logger::getSingleton().printMsg("F3DEX2_Special_1", M64MSG_VERBOSE);
500 void UCode5::F3DEX2_Special_2( MicrocodeArgument* ucode ) {
501 Logger::getSingleton().printMsg("F3DEX2_Special_2", M64MSG_VERBOSE);
504 void UCode5::F3DEX2_Special_3( MicrocodeArgument* ucode ) {
505 Logger::getSingleton().printMsg("F3DEX2_Special_3", M64MSG_VERBOSE);
509 //*****************************************************************************
510 // Unimportant Functions
511 //*****************************************************************************
512 void UCode5::F3DEX2_Reserved1(MicrocodeArgument* ucode) {
513 Logger::getSingleton().printMsg("F3DEX2_Reserved1", M64MSG_VERBOSE);