Arachnoid GLESv1.1 plugin. Compile and run (a bit glitchy and no frameskip) on the...
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / RSP / RSP.cpp
1 /******************************************************************************
2  * Arachnoid Graphics Plugin for Mupen64Plus
3  * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
4  *
5  * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
6  *
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.
11  *
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.
16  *
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  *****************************************************************************/
21
22 #include "RSP.h"
23 #include "../UCodeDefs.h"
24 #include "../RDP/RDP.h"
25 #include <cmath>
26 #include "GBIDefs.h"
27 #include "VI.h"
28 #include "Memory.h"
29 #include "Logger.h"
30 #include "OpenGLRenderer.h"
31 #include "OpenGLManager.h"
32 #include "RSPLightManager.h"
33 #include "FogManager.h"
34 #include "DisplayListParser.h"
35 #include "MathLib.h"
36 #include "MathLib.h"
37
38 #define MI_INTR_SP                 0x00000001  //!< RSP Interrupt signal
39
40 //Geometry Mode Definitions
41 #define G_ZBUFFER                0x00000001
42 #define G_SHADE                    0x00000004
43 #define G_FOG                    0x00010000
44 #define G_LIGHTING                0x00020000
45 #define G_TEXTURE_GEN            0x00040000
46 #define G_TEXTURE_GEN_LINEAR    0x00080000
47 #define G_LOD                    0x00100000
48
49 //-----------------------------------------------------------------------------
50 //! Constructor
51 //-----------------------------------------------------------------------------
52 RSP::RSP()
53 {
54     m_texturesChanged = false;
55     m_matrixMgr = 0;
56     m_vertexMgr = 0;
57     m_lightMgr  = 0;
58 }
59
60 //-----------------------------------------------------------------------------
61 //! Destructor
62 //-----------------------------------------------------------------------------
63 RSP::~RSP()
64 {
65     dispose();
66 }
67
68 //-----------------------------------------------------------------------------
69 //* Initialize
70 //-----------------------------------------------------------------------------
71 bool RSP::initialize(GFX_INFO* graphicsInfo, RDP* rdp, Memory* memory, VI* vi, DisplayListParser* dlp, FogManager* fogMgr)
72 {
73     //Save pointers
74     m_graphicsInfo = graphicsInfo;
75     m_rdp = rdp;
76     m_vi = vi;
77     m_memory = memory;
78     m_displayListParser = dlp;
79     m_fogMgr = fogMgr;       
80
81     //Initialize Matrix Manager
82     m_matrixMgr = new RSPMatrixManager();
83     if ( !m_matrixMgr->initialize(m_memory) ) {
84         return false;
85     }
86
87     //Initialzie Light Manager
88     m_lightMgr = new RSPLightManager();
89     if ( !m_lightMgr->initialize(m_memory) ) {
90         return false;
91     }
92
93     //Initialzie Vertex Manager
94     m_vertexMgr = new RSPVertexManager();
95     if ( !m_vertexMgr->initialize(&OpenGLManager::getSingleton(), m_memory, m_matrixMgr, m_lightMgr) ) {
96         return false;
97     }
98
99     m_textureTiles[0] = m_rdp->getTile(0);
100     m_textureTiles[1] = m_rdp->getTile(1);
101
102     return true;
103 }
104
105 //-----------------------------------------------------------------------------
106 //* Dispose
107 //-----------------------------------------------------------------------------
108 void RSP::dispose()
109 {
110     if ( m_matrixMgr ) { delete m_matrixMgr; m_matrixMgr = 0; }
111     if ( m_vertexMgr ) { delete m_vertexMgr; m_vertexMgr = 0; }
112     if ( m_lightMgr  ) { delete m_lightMgr ; m_lightMgr  = 0; }    
113 }
114
115 //-----------------------------------------------------------------------------
116 //* Update Geometry States
117 //-----------------------------------------------------------------------------
118 void RSP::updateGeometryStates()
119 {
120     bool cullFront           = (m_geometryMode & GBI::G_CULL_FRONT    ) != 0;
121     bool cullBack            = (m_geometryMode & GBI::G_CULL_BACK     ) != 0;
122     bool fog                 = (m_geometryMode & G_FOG                ) != 0;
123     bool textureGen          = (m_geometryMode & G_TEXTURE_GEN        ) != 0;
124     bool lighting            = (m_geometryMode & G_LIGHTING           ) != 0;
125     bool zBuffer             = (m_geometryMode & G_ZBUFFER            ) != 0;
126
127     //Update states
128     m_lightMgr->setLightEnabled(lighting);
129     m_vertexMgr->setTexCoordGenType( textureGen ? TCGT_LINEAR : TCGT_NONE);
130     OpenGLManager::getSingleton().setZBufferEnabled(zBuffer);
131     OpenGLManager::getSingleton().setCullMode(cullFront, cullBack);
132     OpenGLManager::getSingleton().setFogEnabled(fog);
133 }
134
135 //-----------------------------------------------------------------------------
136 // Reset
137 //-----------------------------------------------------------------------------
138 void RSP::reset()
139 {
140     m_matrixMgr->resetMatrices();
141 }
142
143 //-----------------------------------------------------------------------------
144 //* Trigger Interupt
145 //-----------------------------------------------------------------------------
146 void RSP::triggerInterrupt()
147 {
148     *(m_graphicsInfo->MI_INTR_REG) |= MI_INTR_SP;
149     m_graphicsInfo->CheckInterrupts();    
150 }
151
152 //-----------------------------------------------------------------------------
153 //* Move Segment
154 //-----------------------------------------------------------------------------
155 void RSP::moveSegment(int segmentID, int value)
156 {
157     m_memory->setSegment(segmentID, value);
158 }
159
160 //-----------------------------------------------------------------------------
161 // Set Viewport
162 // FIXME
163 //-----------------------------------------------------------------------------
164 void RSP::moveMemViewport(unsigned int segmentAddress)
165 {
166     //Get Adress
167     unsigned int rdramAddress = m_memory->getRDRAMAddress(segmentAddress);
168
169     //Error controll
170     if ( rdramAddress + 16 > m_memory->getRDRAMSize() )
171     {
172         Logger::getSingleton().printMsg("MoveMem Viewport, accessed invalid memory", M64MSG_ERROR);
173         return;
174     }
175
176     m_viewport.vscale[0] = _FIXED2FLOAT( *(short*)m_memory->getRDRAM(rdramAddress +  2), 2 );
177     m_viewport.vscale[1] = _FIXED2FLOAT( *(short*)m_memory->getRDRAM(rdramAddress     ), 2 );
178     m_viewport.vscale[2] = _FIXED2FLOAT( *(short*)m_memory->getRDRAM(rdramAddress +  6), 10 );// * 0.00097847357f;
179     m_viewport.vscale[3] = *(short*)m_memory->getRDRAM(rdramAddress +  4);
180     m_viewport.vtrans[0] = _FIXED2FLOAT( *(short*)m_memory->getRDRAM(rdramAddress + 10), 2 );
181     m_viewport.vtrans[1] = _FIXED2FLOAT( *(short*)m_memory->getRDRAM(rdramAddress +  8), 2 );
182     m_viewport.vtrans[2] = _FIXED2FLOAT( *(short*)m_memory->getRDRAM(rdramAddress + 14), 10 );// * 0.00097847357f;
183     m_viewport.vtrans[3] = *(short*)m_memory->getRDRAM(rdramAddress + 12);
184
185     m_viewport.x      = m_viewport.vtrans[0] - m_viewport.vscale[0];
186     m_viewport.y      = m_viewport.vtrans[1] - m_viewport.vscale[1];
187     m_viewport.width  = m_viewport.vscale[0] * 2;
188     m_viewport.height = m_viewport.vscale[1] * 2;
189     m_viewport.nearz  = m_viewport.vtrans[2] - m_viewport.vscale[2];
190     m_viewport.farz   = (m_viewport.vtrans[2] + m_viewport.vscale[2]) ;
191
192     /*
193     //Set Viewport
194     OpenGLManager::getSingleton().setViewport( 
195             m_viewport.x, // * OGL.scaleX, 
196             m_viewport.y, //(VI.height - (gSP.viewport.y + gSP.viewport.height)) * OGL.scaleY + OGL.heightOffset, 
197             //(m_vi->getHeight() - (m_viewport.y + m_viewport.height)),
198             m_viewport.width, // * OGL.scaleX, 
199             m_viewport.height, // * OGL.scaleY,
200             0.0f,   //m_viewport.nearz, 
201             1.0f ); //m_viewport.farz );            
202             */
203 }
204
205 //-----------------------------------------------------------------------------
206 //* Load UCode Ex
207 //! @todo Change ucode while running
208 //-----------------------------------------------------------------------------
209 void RSP::RSP_LoadUcodeEx( unsigned int uc_start, unsigned int uc_dstart, unsigned short uc_dsize )
210 {
211     Logger::getSingleton().printMsg("RSP_LoadUcodeEx - Unimplemented", M64MSG_WARNING);
212     //TODO or skip
213
214     /*
215
216     RSP.PCi = 0;
217     gSP.matrix.modelViewi = 0;
218     gSP.changed |= CHANGED_MATRIX;
219     gSP.status[0] = gSP.status[1] = gSP.status[2] = gSP.status[3] = 0;
220
221     if ((((uc_start & 0x1FFFFFFF) + 4096) > RDRAMSize) || (((uc_dstart & 0x1FFFFFFF) + uc_dsize) > RDRAMSize))
222     {
223             return;
224     }
225
226     MicrocodeInfo *ucode = GBI_DetectMicrocode( uc_start, uc_dstart, uc_dsize );
227
228     if (ucode->type != NONE)
229         GBI_MakeCurrent( ucode );
230     else
231         SetEvent( RSP.threadMsg[RSPMSG_CLOSE] );
232     */
233 }
234
235 //*****************************************************************************
236 // Matrix Functions
237 //*****************************************************************************
238
239 //-----------------------------------------------------------------------------
240 // RSP Matrix
241 //-----------------------------------------------------------------------------
242 void RSP::RSP_Matrix( unsigned int segmentAddress, bool projectionMatrix, bool push, bool replace )
243
244     Logger::getSingleton().printMsg("RSP_Matrix");
245     m_matrixMgr->addMatrix( segmentAddress,             //Segment adress 
246                             projectionMatrix,           //Projection or view matrix?
247                             push,                       //Save Current Matrix?
248                             replace );                  //Replace aka Load or Mult 
249 }
250
251 //-----------------------------------------------------------------------------
252 // RSP DMA Matrix
253 //-----------------------------------------------------------------------------
254 void RSP::RSP_DMAMatrix( unsigned int matrix, unsigned char index, unsigned char multiply )
255 {
256     m_matrixMgr->DMAMatrix(m_memory->getRDRAMAddress(matrix), index, multiply);
257 }
258
259 //-----------------------------------------------------------------------------
260 // RSP Force Matrix
261 //-----------------------------------------------------------------------------
262 void RSP::RSP_ForceMatrix( unsigned int segmentAddress )
263
264     // Logger::getSingleton().printMsg("RSP_ForceMatrix", M64MSG_WARNING);
265     m_matrixMgr->ForceMatrix( m_memory->getRDRAMAddress(segmentAddress));
266 }
267
268 //-----------------------------------------------------------------------------
269 // Pop Matrix
270 //-----------------------------------------------------------------------------
271 void RSP::RSP_PopMatrix( )
272 {
273     m_matrixMgr->popMatrix();
274 }
275
276 //-----------------------------------------------------------------------------
277 //* Pop Matrix N
278 //! Pop Matrix from stack N number of times
279 //! @param num The number of matrices to pop from matrix-stack
280 //-----------------------------------------------------------------------------
281 void RSP::RSP_PopMatrixN( unsigned int num )
282
283     m_matrixMgr->popMatrixN(num);
284 }
285
286 //-----------------------------------------------------------------------------
287 // Insert Matrix
288 //-----------------------------------------------------------------------------
289 void RSP::RSP_InsertMatrix(unsigned int where, unsigned int num)
290 {
291     m_matrixMgr->insertMatrix(where, num);
292 }
293
294 //*****************************************************************************
295 // Misc
296 //*****************************************************************************
297
298 //-----------------------------------------------------------------------------
299 // Fog Factor
300 //-----------------------------------------------------------------------------
301 void RSP::RSP_FogFactor(short fogMultiplier, short fogOffset)
302 {
303     m_fogMgr->setFogSettings((float)fogMultiplier, (float)fogOffset);
304 }
305
306 //-----------------------------------------------------------------------------
307 // Texture
308 //-----------------------------------------------------------------------------
309 void RSP::RSP_Texture( float scaleS, float scaleT, int level, int tile, int on )
310
311     //Set Texture
312     m_texture.scaleS = (scaleS != 0.0f) ? scaleS : 1.0f;
313     m_texture.scaleT = (scaleT != 0.0f) ? scaleT : 1.0f;
314     m_texture.level  = level;
315     m_texture.on     = on;
316     m_texture.tile   = tile;
317
318     //Set Tiles (note: There are max 8 tiles)    
319     if ( tile < 7 )
320     {
321         m_textureTiles[0] = m_rdp->getTile(tile);
322         m_textureTiles[1] = m_rdp->getTile(tile+1);
323     }
324     else
325     {
326         m_textureTiles[0] = m_rdp->getTile(tile);
327         m_textureTiles[1] = m_rdp->getTile(tile);
328     }
329
330     m_texturesChanged = true;
331 }
332
333 //-----------------------------------------------------------------------------
334 // Set DMA Offsets
335 //-----------------------------------------------------------------------------
336 void RSP::RSP_SetDMAOffsets( unsigned int mtxoffset, unsigned int vtxoffset )
337 {
338     m_matrixMgr->setRDRAMOffset(mtxoffset);
339     m_vertexMgr->setRDRAMOffset(vtxoffset);
340 }
341
342 //*****************************************************************************
343 // Light
344 //*****************************************************************************
345
346 //-----------------------------------------------------------------------------
347 // RSP Light
348 //-----------------------------------------------------------------------------
349 void RSP::RSP_Light( unsigned int lightIndex, unsigned int segmentAddress )
350
351     m_lightMgr->setLight(lightIndex, m_memory->getRDRAMAddress(segmentAddress) );
352 }
353
354 //-----------------------------------------------------------------------------
355 // Num Lights
356 //-----------------------------------------------------------------------------
357 void RSP::RSP_NumLights( int numLights )
358
359     m_lightMgr->setNumLights(numLights);
360 }
361
362 //-----------------------------------------------------------------------------
363 // Light Color
364 //-----------------------------------------------------------------------------
365 void RSP::RSP_LightColor( unsigned int lightIndex, unsigned int packedColor )
366 {
367     m_lightMgr->setLightColor(lightIndex, packedColor);
368 }
369
370 //*****************************************************************************
371 // Vertex
372 //*****************************************************************************
373
374 //-----------------------------------------------------------------------------
375 // Vertex
376 //-----------------------------------------------------------------------------
377 void RSP::RSP_Vertex( unsigned int segmentAddress, unsigned int numVertices, unsigned int firstVertexIndex  )
378
379     m_vertexMgr->setVertices(m_memory->getRDRAMAddress(segmentAddress), numVertices, firstVertexIndex);
380 }
381
382 //-----------------------------------------------------------------------------
383 // Modify Vertex
384 //-----------------------------------------------------------------------------
385 void RSP::RSP_ModifyVertex( unsigned int vtx, unsigned int where, unsigned int val )
386 {
387     m_vertexMgr->modifyVertex(vtx, where, val);
388 }
389
390 void RSP::RSP_SetVertexColor( unsigned int vtx, float r, float g, float b, float a)
391 {
392     m_vertexMgr->setVertexColor(vtx, r,g,b,a);
393 }
394
395 void RSP::RSP_SetVertexTexCoord( unsigned int vtx, float s, float t)
396 {
397     m_vertexMgr->setVertexTextureCoord(vtx, s,t);
398 }
399
400 //-----------------------------------------------------------------------------
401 //! Color Index Vertex
402 //! param segmentAddress Address to register where there is an RDRAM address 
403 //!                      used to retrieve vertices from RDRAM.
404 //! param numVertices Number of vertices to retrive from RDRAM.
405 //! param firstVertexIndex Index of first vertex
406 //-----------------------------------------------------------------------------
407 void RSP::RSP_CIVertex(unsigned int segmentAddress, unsigned int numVertices, unsigned int firstVertexIndex )
408 {    
409     m_vertexMgr->ciVertex(segmentAddress, numVertices, firstVertexIndex);
410 }
411
412 //-----------------------------------------------------------------------------
413 // DMA Vertex
414 //-----------------------------------------------------------------------------
415 void RSP::RSP_DMAVertex( unsigned int v, unsigned int n, unsigned int v0 )
416 {
417     m_vertexMgr->DMAVertex(v, n, v0);
418 }
419
420 //-----------------------------------------------------------------------------
421 // Set Vertex Color Base
422 //-----------------------------------------------------------------------------
423 void RSP::RSP_SetVertexColorBase(unsigned int segmentAddress)
424 {
425     m_vertexMgr->setVertexColorBase( m_memory->getRDRAMAddress(segmentAddress) );
426 }
427
428 //*****************************************************************************
429 // Display List
430 //*****************************************************************************
431
432 //-----------------------------------------------------------------------------
433 // Display List
434 //-----------------------------------------------------------------------------
435 void RSP::RSP_DisplayList(unsigned int segmentAddress)
436 {
437     m_displayListParser->displayList(segmentAddress);
438 }
439
440 //-----------------------------------------------------------------------------
441 // DMA Display List
442 //-----------------------------------------------------------------------------
443 void RSP::RSP_DMADisplayList( unsigned int w0, unsigned int w1 )
444
445     m_displayListParser->DMADisplayList(w0, w1);
446 }
447
448 //-----------------------------------------------------------------------------
449 // Branch Display List
450 //-----------------------------------------------------------------------------
451 void RSP::RSP_BranchList( unsigned int dl )
452
453     m_displayListParser->branchDisplayList(dl);
454 }
455
456 //-----------------------------------------------------------------------------
457 // Branch Display List Z
458 //-----------------------------------------------------------------------------
459 void RSP::RSP_BranchLessZ( unsigned int branchdl, unsigned int vtx, float zval )
460
461     if ( m_vertexMgr->getVertex(vtx)->z <= zval ) {
462         m_displayListParser->branchDisplayList(branchdl);
463     }
464 }
465
466 //-----------------------------------------------------------------------------
467 // End Display List
468 //-----------------------------------------------------------------------------
469 void RSP::RSP_EndDisplayList() 
470
471     m_displayListParser->endDisplayList();
472 }
473
474 //-----------------------------------------------------------------------------
475 //* Cull Display List
476 //! @todo Cull Display List
477 //-----------------------------------------------------------------------------
478 void RSP::RSP_CullDisplayList( unsigned int v0, unsigned int vn )
479 {
480     //Logger::getSingleton().printMsg("RSP_CullDisplayList - Unimplemented", M64MSG_WARNING);
481     //TODO
482 }
483
484 //*****************************************************************************
485 // Indices
486 //*****************************************************************************
487
488 //-----------------------------------------------------------------------------
489 // 1 Triangle
490 //-----------------------------------------------------------------------------
491 void RSP::RSP_1Triangle( int v0, int v1, int v2)
492
493     m_vertexMgr->add1Triangle(v0, v1, v2);
494 }
495
496 //-----------------------------------------------------------------------------
497 // 2 Trangles
498 //-----------------------------------------------------------------------------
499 void RSP::RSP_2Triangles( int v00, int v01, int v02, int flag0, 
500                     int v10, int v11, int v12, int flag1 )
501 {            
502     m_vertexMgr->add1Triangle(v00, v01, v02);        
503     m_vertexMgr->add1Triangle(v10, v11, v12);
504 }
505
506 //-----------------------------------------------------------------------------
507 // 4 Triangles
508 //-----------------------------------------------------------------------------
509 void RSP::RSP_4Triangles( int v00, int v01, int v02,
510                     int v10, int v11, int v12,
511                     int v20, int v21, int v22,
512                     int v30, int v31, int v32 )
513 {
514     m_vertexMgr->add1Triangle(v00, v01, v02);
515     m_vertexMgr->add1Triangle(v10, v11, v12);
516     m_vertexMgr->add1Triangle(v20, v21, v22);
517     m_vertexMgr->add1Triangle(v30, v31, v32);
518 }
519
520 //-----------------------------------------------------------------------------
521 // DMA Triangel
522 //-----------------------------------------------------------------------------
523 void RSP::RSP_DMATriangles( unsigned int tris, unsigned int n )
524
525     m_vertexMgr->addDMATriangles(tris, n);
526 }
527
528 //-----------------------------------------------------------------------------
529 // Quadrangle
530 //-----------------------------------------------------------------------------
531 void RSP::RSP_1Quadrangle( int v0, int v1, int v2, int v3 )
532 {
533     m_vertexMgr->add1Triangle(v0, v1, v2);
534     m_vertexMgr->add1Triangle(v0, v2, v3);
535 }
536
537 //*****************************************************************************
538 // Geometry Mode
539 //*****************************************************************************
540
541 //-----------------------------------------------------------------------------
542 // Geometry Mode
543 //-----------------------------------------------------------------------------
544 void RSP::RSP_GeometryMode(unsigned int clear, unsigned int set)
545
546     RSP_ClearGeometryMode(clear);
547     RSP_SetGeometryMode(set);    
548 }
549
550 //-----------------------------------------------------------------------------
551 // Set Geometry Mode
552 //-----------------------------------------------------------------------------
553 void RSP::RSP_SetGeometryMode( unsigned int mode )
554
555     m_geometryMode |= mode;
556     updateGeometryStates();
557 }
558
559 //-----------------------------------------------------------------------------
560 // Clear Geometry Mode
561 //-----------------------------------------------------------------------------
562 void RSP::RSP_ClearGeometryMode( unsigned int mode )
563 {
564     m_geometryMode &= ~mode;
565     updateGeometryStates();
566 }
567
568 //*****************************************************************************
569 // Other
570 //*****************************************************************************
571
572 void RSP::RSP_Line3D( int v0, int v1, int flag )
573 {
574     Logger::getSingleton().printMsg("RSP_Line3D - Unimplemented", M64MSG_WARNING);
575 }
576 void RSP::RSP_LineW3D( int v0, int v1, int wd, int flag )
577 {
578     Logger::getSingleton().printMsg("RSP_LineW3D - Unimplemented", M64MSG_WARNING);
579 }
580 void RSP::RSP_ObjRectangle( unsigned int sp )
581 {
582     Logger::getSingleton().printMsg("RSP_ObjRectangle - Unimplemented", M64MSG_WARNING);
583 }
584 void RSP::RSP_ObjSprite( unsigned int sp )
585 {
586     Logger::getSingleton().printMsg("RSP_ObjSprite - Unimplemented", M64MSG_WARNING);
587 }
588 void RSP::RSP_ObjLoadTxtr( unsigned int tx )
589 {
590     Logger::getSingleton().printMsg("RSP_ObjLoadTxtr - Unimplemented", M64MSG_WARNING);
591 }
592 void RSP::RSP_ObjLoadTxSprite( unsigned int txsp )
593 {
594     Logger::getSingleton().printMsg("RSP_ObjLoadTxSprite - Unimplemented", M64MSG_WARNING);
595 }
596 void RSP::RSP_ObjLoadTxRectR( unsigned int txsp )
597 {
598     Logger::getSingleton().printMsg("RSP_ObjLoadTxRectR - Unimplemented", M64MSG_WARNING);
599 }
600 void RSP::RSP_BgRect1Cyc( unsigned int bg )
601 {
602     Logger::getSingleton().printMsg("RSP_BgRect1Cyc - Unimplemented", M64MSG_WARNING);
603 }
604 void RSP::RSP_BgRectCopy( unsigned int bg )
605 {
606     Logger::getSingleton().printMsg("RSP_BgRectCopy - Unimplemented", M64MSG_WARNING);
607 }
608 void RSP::RSP_ObjMatrix( unsigned int mtx )
609
610     Logger::getSingleton().printMsg("RSP_ObjMatrix - Unimplemented", M64MSG_WARNING);
611 }
612 void RSP::RSP_ObjSubMatrix( unsigned int mtx )
613 {
614     Logger::getSingleton().printMsg("RSP_ObjSubMatrix - Unimplemented", M64MSG_WARNING);
615 }
616
617 //*****************************************************************************
618 // Non important functions
619 //*****************************************************************************
620
621 void RSP::RSP_Sprite2DBase( unsigned int base ) {
622     Logger::getSingleton().printMsg("RSP_Sprite2DBase - Unimplemented", M64MSG_WARNING);
623 }
624
625 void RSP::RSP_LookAt( unsigned int l ) {
626     Logger::getSingleton().printMsg("RSP_LookAt - Unimplemented", M64MSG_WARNING);
627 }
628
629 void RSP::RSP_ClipRatio( unsigned int r ) {
630     Logger::getSingleton().printMsg("RSP_ClipRatio - Unimplemented", M64MSG_WARNING);
631 }
632
633 void RSP::RSP_PerspNormalize( unsigned short scale ) {
634     Logger::getSingleton().printMsg("RSP_PerspNormalize - Unimplemented", M64MSG_WARNING);
635 }