e0005825d1c6554c39a208f53122c11586c4088a
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / RDP / RDP.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 "RDP.h"
23 #include "GBIDefs.h"
24 #include "GBI.h"
25 #include "RSP.h"
26 #include "DisplayListParser.h"
27 #include "assembler.h"
28 #include "OpenGLRenderer.h"
29 #include "TextureCache.h"
30 #include "VI.h"
31 #include "Memory.h"
32 #include "OpenGLManager.h"
33 #include "OpenGL2DRenderer.h"
34 #include "AdvancedCombinerManager.h"
35 #include "FogManager.h"
36 #include "Logger.h"
37 #include "MathLib.h"
38 #include "RomDetector.h"
39 #include "m64p.h"
40 #include "OpenGL.h"
41 #include <algorithm>
42 using std::max;
43
44 //-----------------------------------------------------------------------------
45 //! Defines
46 //-----------------------------------------------------------------------------
47 #define MI_INTR_DP          0x00000020  //!< RDP Interrupt signal
48
49 //-----------------------------------------------------------------------------
50 //! Static Variables
51 //-----------------------------------------------------------------------------
52 Memory* RDP::m_memory  = 0;
53
54 //-----------------------------------------------------------------------------
55 //! Constructor
56 //-----------------------------------------------------------------------------
57 RDP::RDP()
58 {
59     m_graphicsInfo       = 0;    
60     m_changedTiles       = false;
61     m_textureMode        = TM_NORMAL;
62     m_loadType           = LOADTYPE_BLOCK;
63     m_tmemChanged        = false;  
64     m_textureLUT         = 0;   
65     m_texRectWidth       = 1; 
66     m_texRectHeight      = 1;
67     m_displayListParser  = 0;
68     m_primitiveZ         = 0;
69     m_combinerMgr        = 0;
70     m_textureLoader      = 0;
71     m_openGL2DRenderer   = 0;
72     m_screenUpdatePending= false;
73 }
74
75 //-----------------------------------------------------------------------------
76 //! Destructor
77 //-----------------------------------------------------------------------------
78 RDP::~RDP()
79 {
80 }
81
82 //-----------------------------------------------------------------------------
83 //* Initialize
84 //! Sets pointers to managers and initializes objects
85 //-----------------------------------------------------------------------------
86 bool RDP::initialize(GFX_INFO* graphicsInfo, RSP* rsp, Memory* memory, GBI* gbi, TextureCache* textureCache, VI* vi, DisplayListParser* displayListParser, FogManager* fogMgr)
87 {
88     //Set pointers
89     m_graphicsInfo      = graphicsInfo;
90     m_rsp               = rsp;
91     m_vi                = vi;
92     m_memory            = memory;
93     m_displayListParser = displayListParser;
94     m_textureCache      = textureCache;
95     m_fogMgr            = fogMgr;
96
97     //Create combiner manager
98     m_combinerMgr = new AdvancedCombinerManager();
99     m_combinerMgr->initialize();
100
101     //Create texture loader
102     m_textureLoader = new TextureLoader();
103     m_textureLoader->initialize(this, m_memory);
104
105     //Create OpenGL 2D Renderer
106     m_openGL2DRenderer = new OpenGL2DRenderer();
107     m_openGL2DRenderer->initialize(vi);
108
109     return true;
110 }
111
112 //-----------------------------------------------------------------------------
113 //* Dispose
114 //! Delets all allocated memory
115 //-----------------------------------------------------------------------------
116 void RDP::dispose()
117 {
118     if ( m_combinerMgr      ) { delete m_combinerMgr;      m_combinerMgr      = 0; }
119     if ( m_textureLoader    ) { delete m_textureLoader;    m_textureLoader    = 0; }
120     if ( m_openGL2DRenderer ) { delete m_openGL2DRenderer; m_openGL2DRenderer = 0; }
121 }
122
123 //-----------------------------------------------------------------------------
124 //* Update States
125 //! Sets OpenGL states, updates combiner, activates textures, sets blender
126 //-----------------------------------------------------------------------------
127 void RDP::updateStates()
128 {
129     //Depth Compare
130     if (m_otherMode.depthCompare)
131         glDepthFunc( GL_LEQUAL );
132     else
133         glDepthFunc( GL_ALWAYS );
134
135     //Depth Update
136     if (m_otherMode.depthUpdate)
137         glDepthMask( true );
138     else
139         glDepthMask( false );
140
141     // Depth Mode
142     if (m_otherMode.depthMode == ZMODE_DEC)
143     {
144         glEnable( GL_POLYGON_OFFSET_FILL );
145         glPolygonOffset( -3.0f, -3.0f );
146     }
147     else
148     {
149         glDisable( GL_POLYGON_OFFSET_FILL );
150     }
151
152     // Alpha Compare
153     if ((m_otherMode.alphaCompare == G_AC_THRESHOLD) && !(m_otherMode.alphaCvgSel))
154     {
155         glEnable( GL_ALPHA_TEST );
156         glAlphaFunc( (m_combinerMgr->getBlendColor()[3] > 0.0f) ? GL_GEQUAL : GL_GREATER, m_combinerMgr->getBlendColor()[3] );
157     }
158     // Used in TEX_EDGE and similar render modes
159     else if (m_otherMode.cvgXAlpha)
160     {
161         glEnable( GL_ALPHA_TEST );
162         glAlphaFunc( GL_GEQUAL, 0.5f );  // Arbitrary number -- gives nice results though
163     }
164     else
165         glDisable( GL_ALPHA_TEST );
166
167     //Combiner
168     if ( m_updateCombiner )
169     {
170         if ( m_otherMode.cycleType == G_CYC_COPY)
171         {
172             m_combinerMgr->setMux(72057594037727865LL, m_otherMode.cycleType); //Only normal texturing                                                                    
173             m_combinerMgr->selectCombine(m_otherMode.cycleType);
174         }
175         else if  ( m_otherMode.cycleType == G_CYC_FILL )
176         {
177             m_combinerMgr->setMux( 72057594037828926LL, m_otherMode.cycleType );
178             m_combinerMgr->selectCombine(m_otherMode.cycleType);
179         }
180         else
181         {
182             m_combinerMgr->selectCombine(m_otherMode.cycleType);
183         }
184         m_updateCombiner = false;
185         m_updateCombineColors = true;
186     }
187
188     if ( m_updateCombineColors )
189     {
190         m_combinerMgr->updateCombineColors();
191         m_updateCombineColors = false;
192     }
193
194     //Texturing
195     if ( m_changedTiles || m_tmemChanged || m_rsp->getTexturesChanged() ) 
196     {
197         m_combinerMgr->beginTextureUpdate();
198
199         //Update Texture channel 0
200         if ( m_combinerMgr->getUsesTexture0() )
201         {
202             //Enable texture 0
203             m_textureCache->update(0);
204             m_rsp->setTexturesChanged(false);
205             m_changedTiles = false;
206             m_tmemChanged = false;
207         }
208         else
209         {
210             //Disable texture 0
211             glActiveTextureARB( GL_TEXTURE0_ARB + 0 );
212             glDisable(GL_TEXTURE_2D);  
213         }
214
215         //Update Texture channel 1
216         if (  m_combinerMgr->getUsesTexture1() )
217         {
218             //Enable texture 1
219             m_textureCache->update(1);
220             m_rsp->setTexturesChanged(false);
221             m_changedTiles = false;
222             m_tmemChanged = false;
223         }
224         else
225         {
226             //Disable textureing 1
227             glActiveTextureARB( GL_TEXTURE0_ARB + 1 );
228             glDisable(GL_TEXTURE_2D); 
229         }
230
231         m_combinerMgr->endTextureUpdate();
232     }
233
234     // Blending
235     if (    (m_otherMode.forceBlender) &&    
236             (m_otherMode.cycleType != G_CYC_COPY) &&
237             (m_otherMode.cycleType != G_CYC_FILL) &&
238             !(m_otherMode.alphaCvgSel))
239     {
240         glEnable( GL_BLEND );
241         switch (m_otherMode.l >> 16)
242         {
243             case 0x0448: // Add
244             case 0x055A:
245                 glBlendFunc( GL_ONE, GL_ONE );
246                 break;
247             case 0x0C08: // 1080 Sky
248             case 0x0F0A: // Used LOTS of places
249                 glBlendFunc( GL_ONE, GL_ZERO );
250                 break;
251             case 0xC810: // Blends fog
252             case 0xC811: // Blends fog
253             case 0x0C18: // Standard interpolated blend
254             case 0x0C19: // Used for antialiasing
255             case 0x0050: // Standard interpolated blend
256             case 0x0055: // Used for antialiasing
257                 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
258                 break;
259             case 0x0FA5: // Seems to be doing just blend color - maybe combiner can be used for this?
260             case 0x5055: // Used in Paper Mario intro, I'm not sure if this is right...
261                 glBlendFunc( GL_ZERO, GL_ONE );
262                 break;
263             default:
264                 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
265                 break;
266         }
267     }
268     else
269         glDisable( GL_BLEND );
270
271     if (m_otherMode.cycleType == G_CYC_FILL)
272     {
273         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
274         glEnable( GL_BLEND );
275     }
276 }
277
278 //-----------------------------------------------------------------------------
279 //* Reset
280 //! Resets all states on RDP
281 //-----------------------------------------------------------------------------
282 void RDP::reset()
283 {
284     setTextureFiltering( G_TF_POINT );
285     setRenderMode(0);
286 }
287
288 //-----------------------------------------------------------------------------
289 //* Trigger Interrupt
290 //! Tell emulator that the RDP is idle
291 //-----------------------------------------------------------------------------
292 void RDP::triggerInterrupt()
293 {
294     *(m_graphicsInfo->MI_INTR_REG) |= MI_INTR_DP;
295     m_graphicsInfo->CheckInterrupts();
296 }
297
298 //-----------------------------------------------------------------------------
299 //* Set Alpha Compare Mode
300 //-----------------------------------------------------------------------------
301 void RDP::setAlphaCompareMode(unsigned int mode)
302 {
303     m_otherMode.alphaCompare = mode;
304     OpenGLManager::getSingleton().setAlphaTest( m_otherMode.alphaCompare != 0 );
305 }
306
307 //-----------------------------------------------------------------------------
308 //* Set Render Mode
309 //-----------------------------------------------------------------------------
310 void RDP::setRenderMode(unsigned int w1)
311 {
312     unsigned int mode1 = (w1 & 0xCCCCFFFF);
313     unsigned int mode2 = (w1 & 0x3333FFFF);
314
315     m_otherMode.l &= 0x00000007;
316     m_otherMode.l |= mode1 | mode2;
317 }
318
319 //#############################################################################
320 //  UCODE FUNCTIONS:
321 //#############################################################################
322
323 //*****************************************************************************
324 // Combiner Mode
325 //*****************************************************************************
326
327 //-----------------------------------------------------------------------------
328 //* Set Combine
329 //! Sets all combiner variables on combiner that tells it how to combine
330 //! the diffrent colors and textures.
331 //-----------------------------------------------------------------------------
332 void RDP::RDP_SetCombine(MicrocodeArgument* ucode)
333
334     int mux0 = _SHIFTR( ucode->w0, 0, 24 );
335     int mux1 = ucode->w1;
336     m_combinerMgr->setMux(mux0, mux1, (G_CYCLE_TYPE)m_otherMode.cycleType);
337
338     m_updateCombiner = true;    
339 }
340
341 //*****************************************************************************
342 // Colors
343 //*****************************************************************************
344
345 //-----------------------------------------------------------------------------
346 //* Set Environment Color
347 //! Sets Environment Color on combiner
348 //! @param r Red component of color (0.0 - 1.0)
349 //! @param g Green component of color (0.0 - 1.0)
350 //! @param b Blue component of color (0.0 - 1.0)
351 //! @param a Alpha component of color (0.0 - 1.0)
352 //-----------------------------------------------------------------------------
353 void RDP::RDP_SetEnvColor(float r, float g, float b, float a)
354
355     m_combinerMgr->setEnvColor(r, g, b, a);
356     m_updateCombineColors = true;
357 }
358
359 //-----------------------------------------------------------------------------
360 //* Set Prim Color
361 //! Sets Prim Color on combiner
362 //! @param r Red component of color (0.0 - 1.0)
363 //! @param g Green component of color (0.0 - 1.0)
364 //! @param b Blue component of color (0.0 - 1.0)
365 //! @param a Alpha component of color (0.0 - 1.0)
366 //! @param primLodMin
367 //! @param primLevel
368 //-----------------------------------------------------------------------------
369 void RDP::RDP_SetPrimColor(float r, float g, float b, float a, unsigned int primLodMin, unsigned int primLevel)
370
371     int primLodFrac = max(primLevel, primLodMin);
372     m_combinerMgr->setPrimLodMin(primLodMin);
373     m_combinerMgr->setPrimLodFrac(primLodFrac / 255.0f);
374     m_combinerMgr->setPrimColor(r, g, b, a);
375     m_updateCombineColors = true;
376 }
377
378 //-----------------------------------------------------------------------------
379 //* Set Blend Color
380 //! Sets Blend Color on combiner
381 //! @param r Red component of color (0.0 - 1.0)
382 //! @param g Green component of color (0.0 - 1.0)
383 //! @param b Blue component of color (0.0 - 1.0)
384 //! @param a Alpha component of color (0.0 - 1.0)
385 //-----------------------------------------------------------------------------
386 void RDP::RDP_SetBlendColor(float r, float g, float b, float a)
387 {
388     m_combinerMgr->setBlendColor(r, g, b, a);
389     m_updateCombineColors = true;
390 }
391
392 //-----------------------------------------------------------------------------
393 //* Set Fill Color
394 //! Sets Fill Color on combiner
395 //! @param r Red component of color (0.0 - 1.0)
396 //! @param g Green component of color (0.0 - 1.0)
397 //! @param b Blue component of color (0.0 - 1.0)
398 //! @param a Alpha component of color (0.0 - 1.0)
399 //-----------------------------------------------------------------------------
400 void RDP::RDP_SetFillColor(float r, float g, float b, float a)
401
402     m_combinerMgr->setFillColor(r, g, b, a);
403     m_updateCombineColors = true;
404 }
405
406 //-----------------------------------------------------------------------------
407 //* Set Fog Color
408 //! Sets fog color used when rendering fog
409 //! @param r Red component of color (0.0 - 1.0)
410 //! @param g Green component of color (0.0 - 1.0)
411 //! @param b Blue component of color (0.0 - 1.0)
412 //! @param a Alpha component of color (0.0 - 1.0)
413 //-----------------------------------------------------------------------------
414 void RDP::RDP_SetFogColor(float r, float g, float b, float a)
415
416     m_fogMgr->setFogColor(r, g, b, a);
417 }
418
419 //*****************************************************************************
420 // Misc
421 //*****************************************************************************
422
423 //-----------------------------------------------------------------------------
424 //! Set Other Mode
425 //-----------------------------------------------------------------------------
426 void RDP::RDP_SetOtherMode(MicrocodeArgument* ucode)
427 {          
428     unsigned int mode0 = _SHIFTR( ucode->w0, 0, 24 );    
429     unsigned int mode1 = ucode->w1;                    
430
431     m_otherMode.h = mode0;
432     m_otherMode.l = mode1;
433 }
434
435 //-----------------------------------------------------------------------------
436 //! Set Prim Depth
437 //-----------------------------------------------------------------------------
438 void RDP::RDP_SetPrimDepth(unsigned int dwZ, unsigned int dwDZ)
439 {  
440     unsigned int primitiveDepth = dwZ & 0x7FFF;
441
442     //Convert to float
443     m_primitiveZ = (float)(primitiveDepth)/(float)0x8000;
444  }
445
446 //-----------------------------------------------------------------------------
447 //! Set Scissor
448 //-----------------------------------------------------------------------------
449 void RDP::RDP_SetScissor(int x0, int y0, int x1, int y1, int mode)
450 {  
451     //Get Scale
452     float vsx = OpenGLManager::getSingleton().getViewScaleX();
453     float vsy = OpenGLManager::getSingleton().getViewScaleY();
454     
455     //Get Offset
456     int offset = 0; //TODO: height offset?
457
458     //Set Scissor
459     OpenGLManager::getSingleton().setScissor( 
460                x0 * vsx, 
461                (m_vi->getHeight() - y1) * vsy + offset,
462                (x1 - x0) * vsx, 
463                (y1 - y0) * vsy 
464     );
465 }
466
467 //-----------------------------------------------------------------------------
468 //* Set Full Sync
469 //! Called when RDP is finished 
470 //-----------------------------------------------------------------------------
471 void RDP::RDP_FullSync()
472
473     this->triggerInterrupt();
474 }
475
476 //*****************************************************************************
477 // Rendering
478 //*****************************************************************************
479
480 //-----------------------------------------------------------------------------
481 //* Fill Rect
482 //! Renders a rectangle
483 //-----------------------------------------------------------------------------
484 void RDP::RDP_FillRect(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1)
485
486     //Logger::getSingleton() << "RDP_FillRect: " << (int)x0 << " " << (int)y0 << " " << (int)x1 << " " << (int)y1 << "\n";
487
488     //Increase rectangle size?
489     if( m_otherMode.cycleType >= G_CYC_COPY )
490     {
491         x1++;
492         y1++;
493     }
494
495     //Clear Depth Buffer?
496     if ( m_depthImageInfo.rdramAddress == m_colorImageInfo.rdramAddress )
497     {
498         //Clear the Z Buffer
499         updateStates();
500         glDepthMask( true );
501         glClear(GL_DEPTH_BUFFER_BIT);
502
503         // Depth update
504         if (m_otherMode.depthUpdate)
505         {
506             glDepthMask(GL_TRUE);
507         }
508         else
509         {
510             glDepthMask(GL_FALSE);
511         }
512
513         return;
514     }
515
516     //Clear Color Buffer?
517     if ( m_otherMode.cycleType == G_CYC_FILL)
518     {
519         if ( x0 == 0 && y0 == 0 && x1 == m_vi->getWidth() && y1 == m_vi->getHeight() )
520         {
521             const float* fillColor = m_combinerMgr->getFillColor();
522             glClearColor(fillColor[0], fillColor[1], fillColor[2], fillColor[3]);
523             bool scissor = OpenGLManager::getSingleton().getScissorEnabled();
524             OpenGLManager::getSingleton().setScissorEnabled(false);
525             glClear(GL_COLOR_BUFFER_BIT);
526             OpenGLManager::getSingleton().setScissorEnabled(scissor);
527             return;
528         }
529     }
530
531     //Update States
532     this->updateStates();   
533
534     //Ignore fill rects?
535     if ( ROMDetector::getSingleton().getIgnoreFillRects() ) 
536     {
537         return;
538     }
539
540     //Disable Scissor
541     glDisable( GL_SCISSOR_TEST );
542
543     //Set Viewport
544     //int oldViewport[4];
545     //glGetIntegerv(GL_VIEWPORT, oldViewport);
546     //glViewport(0, 0, OpenGLManager::getSingleton().getWidth(), OpenGLManager::getSingleton().getHeight() ); 
547     glDepthRange(0.0f, 1.0f);
548
549     //Get depth and color
550     float depth = m_otherMode.depthSource == 1 ? m_primitiveZ : 0;  //TODO: Use RSP viewport nearz?
551     float* color = m_otherMode.cycleType == G_CYC_FILL ? m_combinerMgr->getFillColor() : m_combinerMgr->getPrimColor();
552
553     //Render rectangle
554     m_openGL2DRenderer->renderQuad(color, x0, y0, x1, y1, depth);
555
556     //Reset viewport
557     //glViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);     
558
559     //Reset Scissor
560     glEnable( GL_SCISSOR_TEST );
561 }
562
563 //-----------------------------------------------------------------------------
564 // Texture Rectangle Flip
565 //-----------------------------------------------------------------------------
566 void RDP::RDP_TexRectFlip(unsigned int dwXH, unsigned int dwYH, unsigned int dwXL, unsigned int dwYL, 
567                           unsigned int tileno, unsigned int dwS, unsigned int dwT, int nDSDX, int nDTDY)
568 {   
569     Logger::getSingleton().printMsg("RDP_TexRect");
570
571     float fS0 = (float)dwS / 32.0f;
572     float fT0 = (float)dwT / 32.0f;
573
574     float fDSDX = (float)nDSDX / 1024.0f;
575     float fDTDY = (float)nDTDY / 1024.0f;
576
577     if (m_otherMode.cycleType == G_CYC_COPY)
578     {
579         fDSDX /= 4.0f;    // In copy mode 4 pixels are copied at once.
580         dwXH++;
581         dwYH++;
582     }
583     else if (m_otherMode.cycleType == G_CYC_FILL )
584     {
585         dwXH++;
586         dwYH++;
587     }
588
589     float fS1 = fS0 + (fDSDX * (dwYH - dwYL));
590     float fT1 = fT0 + (fDTDY * (dwXH - dwXL));
591
592     //Set Current Texture tiles
593     m_rsp->setTile( m_textureLoader->getTile(tileno), 0);
594     if ( tileno < 7 ) 
595     {
596         m_rsp->setTile( m_textureLoader->getTile(tileno + 1), 1);
597     }
598     else {
599         m_rsp->setTile( m_textureLoader->getTile(tileno), 1);
600     }
601
602     m_texRectWidth = (unsigned int)fS1;
603     m_texRectHeight = (unsigned int)fT1;
604
605     //Update States
606     this->updateStates();
607
608     float t0u0 = 0, t0v0 = 0, t0u1 =0, t0v1 = 0;
609     if ( m_textureCache->getCurrentTexture(0) )
610     {
611         t0u0 = (fS0) * m_textureCache->getCurrentTexture(0)->shiftScaleS - m_textureLoader->getTile(tileno)->uls;
612         t0v0 = (fT0) * m_textureCache->getCurrentTexture(0)->shiftScaleT - m_textureLoader->getTile(tileno)->ult;
613         t0u1 = t0u0 + (fDSDX * (dwYH - dwYL))*m_textureCache->getCurrentTexture(0)->shiftScaleS;
614         t0v1 = t0v0 + (fDTDY * (dwXH - dwXL))*m_textureCache->getCurrentTexture(0)->shiftScaleT;
615     }
616
617     _textureRectangleFlip(dwXL, dwYL, dwXH, dwYH, t0u0, t0v0, t0u1, t0v1, tileno);
618         
619     //Restore RSP Tile
620     int rspTile = m_rsp->getTexture().tile;
621     m_rsp->setTile( m_textureLoader->getTile(tileno), 0);
622     m_rsp->setTile( m_textureLoader->getTile(rspTile < 7 ? rspTile + 1 : rspTile), 1);
623 }
624
625 //-----------------------------------------------------------------------------
626 //* Texture Rect
627 //! Not this command use 128bits and not 64 bits wich could cause some
628 //! problems with the program counter.
629 //-----------------------------------------------------------------------------
630 void RDP::RDP_TexRect(unsigned int dwXH, unsigned int dwYH, unsigned int dwXL, unsigned int dwYL, 
631                       unsigned int tileno, unsigned short dwS, unsigned short dwT, unsigned short nDSDX, unsigned short nDTDY)
632
633     Logger::getSingleton().printMsg("RDP_TexRect");    
634
635     glEnable(GL_TEXTURE_2D);
636
637     //Convert to signed
638     short s16S = *(short*)(&dwS);
639     short s16T = *(short*)(&dwT);
640     short s16DSDX  = *(short*)(&nDSDX);
641     short s16DTDY    = *(short*)(&nDTDY);
642
643     //Convert to float
644     float s = s16S / 32.0f;
645     float t = s16T / 32.0f;
646     float dsdx = s16DSDX / 1024.0f;
647     float dtdy = s16DTDY / 1024.0f;
648
649
650     float ulx = (float)dwXH;
651     float uly = (float)dwYH;
652     float lrx = (float)dwXL;
653     float lry = (float)dwYL;
654
655     int tile = tileno;
656
657     _textureRectangle(ulx, uly, lrx, lry, tile, s, t, dsdx, dtdy, false);
658 }
659
660 //*****************************************************************************
661 // Texturing
662 //*****************************************************************************
663
664 //-----------------------------------------------------------------------------
665 //* Set Color Image
666 //! Sets information about color image
667 //-----------------------------------------------------------------------------
668 void RDP::RDP_SetCImg(unsigned int format, unsigned int size, unsigned int width, unsigned int segmentAddress)
669
670     m_colorImageInfo.rdramAddress = m_memory->getRDRAMAddress( segmentAddress );
671     m_colorImageInfo.format       = format;
672     m_colorImageInfo.size         = size;
673     m_colorImageInfo.width        = width + 1; //Note: add plus one
674     m_colorImageInfo.bpl          = m_colorImageInfo.width << m_colorImageInfo.size >> 1;
675     
676     if (m_screenUpdatePending)
677     {
678         OpenGLManager::getSingleton().endRendering();
679         m_screenUpdatePending = false;
680     }
681 }
682
683 //-----------------------------------------------------------------------------
684 //* Set Z Image
685 //! Sets information about depth image
686 //-----------------------------------------------------------------------------
687 void RDP::RDP_SetZImg(unsigned int format, unsigned int size, unsigned int width, unsigned int segmentAddress)
688
689     m_depthImageInfo.rdramAddress = m_memory->getRDRAMAddress( segmentAddress );
690     m_depthImageInfo.format       = format;
691     m_depthImageInfo.size         = size;
692     m_depthImageInfo.width        = width + 1; //Note: add plus one
693     m_depthImageInfo.bpl          = m_colorImageInfo.width << m_colorImageInfo.size >> 1;
694 }
695
696 //-----------------------------------------------------------------------------
697 //* Set Texture Image
698 //! Sets information about texture image
699 //-----------------------------------------------------------------------------
700 void RDP::RDP_SetTImg(unsigned int format, unsigned int size, unsigned int width, unsigned int segmentAddress)
701
702     m_textureLoader->setTextureImage(format, size, width, segmentAddress);
703 }
704
705 //-----------------------------------------------------------------------------
706 // Set Tile
707 //-----------------------------------------------------------------------------
708 void RDP::RDP_SetTile(int format, int size, int line, int tmem, int tile, 
709                       int palette, int clampS, int clampT, int mirrorS, 
710                       int mirrorT, int maskS, int maskT, int shiftS, int shiftT )
711
712     //Set Tile
713     m_textureLoader->setTile( format, size, line, tmem, tile, palette, 
714                               clampS, clampT, mirrorS, mirrorT, maskS, maskT,
715                               shiftS, shiftT );
716
717     //m_changedTiles = true;    ??? Not needed?
718 }
719
720 //-----------------------------------------------------------------------------
721 //* Load Tile
722 //-----------------------------------------------------------------------------
723 void RDP::RDP_LoadTile(int tile, int s0, int t0, int s1, int t1)
724
725     //Load Tile
726     m_textureLoader->loadTile(tile, s0, t0, s1, t1);
727
728     m_textureMode = TM_NORMAL;
729     m_loadType    = LOADTYPE_TILE;
730     m_tmemChanged = true;    
731 }    
732
733 //-----------------------------------------------------------------------------
734 // Load Block
735 //-----------------------------------------------------------------------------
736 void RDP::RDP_LoadBlock(int tile, int s0, int t0, int s1, int t1)
737 {  
738     //Load Block
739     m_textureLoader->loadBlock(tile, s0, t0, s1, t1);
740
741     m_textureMode = TM_NORMAL;
742     m_loadType    = LOADTYPE_BLOCK;
743     m_tmemChanged = true;
744 }
745
746 //-----------------------------------------------------------------------------
747 //! Sets the size of tile
748 //! @Param tile Index of the tile to set size on
749 //! @param s0 Texture Coordinats for first vertex coordinate
750 //! @param t0 Texture Coordinats for first vertex coordinate
751 //! @param s1 Texture Coordinats for second vertex coordinate
752 //! @param t1 Texture Coordinats for second vertex coordinate
753 //-----------------------------------------------------------------------------
754 void RDP::RDP_SetTileSize(int tile, unsigned int s0, unsigned int t0, unsigned int s1, unsigned int t1)
755 {  
756     m_textureLoader->setTileSize( tile, s0, t0, s1, t1);
757
758     m_changedTiles = true;    
759 }
760
761 //-----------------------------------------------------------------------------
762 // Load Texture Look Up Table
763 //-----------------------------------------------------------------------------
764 void RDP::RDP_LoadTLUT(int tile, int s0, int t0, int s1, int t1)
765 {   
766     m_textureLoader->loadTLUT(tile, s0, t0, s1, t1);
767
768     m_tmemChanged = true;
769 }
770
771 //*****************************************************************************
772 // Private Functions
773 //*****************************************************************************
774
775 //-----------------------------------------------------------------------------
776 // Texture Rectangle
777 //-----------------------------------------------------------------------------
778 void RDP::_textureRectangle(float ulx, float uly, float lrx, float lry, int tile, float s, float t, float dsdx, float dtdy,bool flip)
779 {
780     bool zEnabled = OpenGLManager::getSingleton().getZBufferEnabled();
781     OpenGLManager::getSingleton().setZBufferEnabled(false);
782
783     //Copy Mode
784     if (  m_otherMode.cycleType == G_CYC_COPY )
785     {
786         dsdx = 1.0;
787         lrx += 1.0f;
788         lry += 1.0f;
789     }
790     else if (m_otherMode.cycleType == G_CYC_FILL )
791     {
792         lrx++;
793         lry++;
794     }
795
796     //Set Current Texture tiles
797     m_rsp->setTile( m_textureLoader->getTile(tile), 0);
798     m_rsp->setTile( m_textureLoader->getTile(tile < 7 ? tile + 1 : tile), 1);
799
800
801     float lrs = s + (lrx - ulx - 1) * dsdx;
802     float lrt = t + (lry - uly - 1) * dtdy;
803
804     //Change mode to texture rectangle
805     if ( m_textureMode == TM_NORMAL )
806         m_textureMode = TM_TEXRECT;
807
808     m_texRectWidth  = (unsigned int)(max( lrs, s ) + dsdx);
809     m_texRectHeight = (unsigned int)(max( lrt, t ) + dtdy);
810
811     //Update States
812     this->updateStates();
813
814     //glViewport( 0, 0, OpenGLManager::getSingleton().getWidth(), OpenGLManager::getSingleton().getHeight() );
815
816     glDisable(GL_SCISSOR_TEST);
817
818     if (lrs > s)
819     {
820         if (lrt > t)
821             OpenGLRenderer::getSingleton().renderTexRect( ulx, uly, lrx, lry, s, t, lrs, lrt, flip );
822         else
823             OpenGLRenderer::getSingleton().renderTexRect( ulx, lry, lrx, uly, s, lrt, lrs, t, flip );
824     }
825     else
826     {
827         if (lrt > t)
828             OpenGLRenderer::getSingleton().renderTexRect( lrx, uly, ulx, lry, lrs, t, s, lrt, flip );
829         else
830             OpenGLRenderer::getSingleton().renderTexRect( lrx, lry, ulx, uly, lrs, lrt, s, t, flip );
831     }
832
833     //Restore RSP Tile
834     int rspTile = m_rsp->getTexture().tile;
835     m_rsp->setTile( m_textureLoader->getTile( rspTile ), 0);
836     m_rsp->setTile( m_textureLoader->getTile(rspTile < 7 ? rspTile + 1 : rspTile), 1);
837
838     //glViewport( 0, m_windowMgr->getHeightOffset(), OpenGLManager::getSingleton().getWidth(), OpenGLManager::getSingleton().getHeight() );
839
840     glEnable(GL_SCISSOR_TEST);
841     OpenGLManager::getSingleton().setZBufferEnabled(zEnabled);
842 }
843
844 //-----------------------------------------------------------------------------
845 //* Texture Rectangle Flip
846 //! @todo: Clamp Tile
847 //-----------------------------------------------------------------------------
848 void RDP::_textureRectangleFlip(int nX0, int nY0, int nX1, int nY1, float fS0, float fT0, float fS1, float fT1, int tile)
849 {
850     //Disable z buffer
851     bool zEnabled = OpenGLManager::getSingleton().getZBufferEnabled();
852     OpenGLManager::getSingleton().setZBufferEnabled(false);
853
854     float widthDiv = (float)m_textureLoader->getTile( m_rsp->getTexture().tile )->getWidth();
855     float heightDiv = (float)m_textureLoader->getTile( m_rsp->getTexture().tile )->getHeight();
856
857     float t0u0 = fS0 / widthDiv;
858     float t0v0 = fT0 / heightDiv;
859     float t0u1 = (fS1 - fS0)/ widthDiv + t0u0;
860     float t0v1 = (fT1 - fT0)/ heightDiv + t0v0;
861
862     float depth = m_otherMode.depthSource == 1 ? m_primitiveZ : 0;  //TODO: Use RSP viewport nearz?
863
864     static bool warned = false;
865     if( t0u0 >= 0 && t0u1 <= 1 && t0u1 >= t0u0 ) 
866     {
867         //TODO: Clamp Tile
868         if (!warned)
869         {
870             warned = true;
871             Logger::getSingleton().printMsg("_textureRectangleFlip - unimplemented", M64MSG_WARNING);
872         }
873     }
874     if( t0v0 >= 0 && t0v1 <= 1 && t0v1 >= t0v0 ) 
875     {
876         //TODO: Clamp tile
877         if (!warned)
878         {
879             warned = true;
880             Logger::getSingleton().printMsg("_textureRectangleFlip - unimplemented", M64MSG_WARNING);
881         }
882     }
883
884     //HACK 
885     if ( ROMDetector::getSingleton().getRomID() == SUPER_MARIO_64 )
886     {
887         t0u0 *= 0.5f;
888         t0v0 *= 0.5f;    
889         t0u1 *= 0.5f;    
890         t0v1 *= 0.5f;
891     }
892
893     //glViewport( 0, m_windowMgr->getHeightOffset(), OpenGLManager::getSingleton().getWidth(), OpenGLManager::getSingleton().getHeight() );
894
895     //Get Color
896     float color[4] = { 1,1,1,0 }; 
897     this->getCombinerMgr()->getCombinerColor(    &color[0] );
898     float secondaryColor[4] = { 1,1,1,1 };
899
900     if (  m_otherMode.cycleType == G_CYC_COPY )
901     {
902         glActiveTextureARB( GL_TEXTURE0_ARB );
903         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
904         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
905     }
906
907     //Disable Scissor
908     glDisable( GL_SCISSOR_TEST );
909
910     //Render Quad
911     m_openGL2DRenderer->renderFlippedTexturedQuad( color, secondaryColor,
912                                                    (float)nX0, (float)nY0,
913                                                    (float)nX1, (float)nY1,
914                                                    depth,
915                                                    t0u0, t0v0,
916                                                    t0u1, t0v1, 
917                                                    t0u0, t0v0,
918                                                    t0u1, t0v1 );
919
920     //Restore states
921     glEnable(GL_SCISSOR_TEST);
922     OpenGLManager::getSingleton().setZBufferEnabled(zEnabled);
923 }