Arachnoid GLESv1.1 plugin. Compile and run (a bit glitchy and no frameskip) on the...
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / RDP / RDP.cpp
CommitLineData
22726e4d 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>
42using std::max;
43
44//-----------------------------------------------------------------------------
45//! Defines
46//-----------------------------------------------------------------------------
47#define MI_INTR_DP 0x00000020 //!< RDP Interrupt signal
48
49//-----------------------------------------------------------------------------
50//! Static Variables
51//-----------------------------------------------------------------------------
52Memory* RDP::m_memory = 0;
53
54//-----------------------------------------------------------------------------
55//! Constructor
56//-----------------------------------------------------------------------------
57RDP::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//-----------------------------------------------------------------------------
78RDP::~RDP()
79{
80}
81
82//-----------------------------------------------------------------------------
83//* Initialize
84//! Sets pointers to managers and initializes objects
85//-----------------------------------------------------------------------------
86bool 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//-----------------------------------------------------------------------------
116void 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//-----------------------------------------------------------------------------
127void 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//-----------------------------------------------------------------------------
282void 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//-----------------------------------------------------------------------------
292void 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//-----------------------------------------------------------------------------
301void 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//-----------------------------------------------------------------------------
310void 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//-----------------------------------------------------------------------------
332void 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//-----------------------------------------------------------------------------
353void 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//-----------------------------------------------------------------------------
369void 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//-----------------------------------------------------------------------------
386void 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//-----------------------------------------------------------------------------
400void 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//-----------------------------------------------------------------------------
414void 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//-----------------------------------------------------------------------------
426void 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//-----------------------------------------------------------------------------
438void 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//-----------------------------------------------------------------------------
449void 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//-----------------------------------------------------------------------------
471void RDP::RDP_FullSync()
472{
473 this->triggerInterrupt();
474}
475
476//*****************************************************************************
477// Rendering
478//*****************************************************************************
479
480//-----------------------------------------------------------------------------
481//* Fill Rect
482//! Renders a rectangle
483//-----------------------------------------------------------------------------
484void 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//-----------------------------------------------------------------------------
566void 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//-----------------------------------------------------------------------------
630void 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//-----------------------------------------------------------------------------
668void 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//-----------------------------------------------------------------------------
687void 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//-----------------------------------------------------------------------------
700void 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//-----------------------------------------------------------------------------
708void 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//-----------------------------------------------------------------------------
723void 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//-----------------------------------------------------------------------------
736void 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//-----------------------------------------------------------------------------
754void 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//-----------------------------------------------------------------------------
764void 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//-----------------------------------------------------------------------------
778void 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//-----------------------------------------------------------------------------
848void 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}