Arachnoid GLESv1.1 plugin. Compile and run (a bit glitchy and no frameskip) on the...
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / RSP / RSPMatrixManager.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 "RSPMatrixManager.h"
23#include "Memory.h"
24#include <cmath> //modff
25#include "GBI.h" //SHIFT
26#include "GBIDefs.h" //_FIXED2FLOAT
27//-----------------------------------------------------------------------------
28//! Constructor
29//-----------------------------------------------------------------------------
30RSPMatrixManager::RSPMatrixManager()
31{
32
33}
34
35//-----------------------------------------------------------------------------
36//! Destructor
37//-----------------------------------------------------------------------------
38RSPMatrixManager::~RSPMatrixManager()
39{
40
41}
42
43//-----------------------------------------------------------------------------
44//* Initialize
45//-----------------------------------------------------------------------------
46bool RSPMatrixManager::initialize(Memory* memory)
47{
48 m_memory = memory;
49 m_rdramOffset = 0;
50 return true;
51}
52
53//-----------------------------------------------------------------------------
54//! Add Matrix
55//! @param segmentAddress Later converted to RDRam address pointing to Matrix to load
56//! @param projectionMatrix True if matrix is a projection matrix,
57//! False if matrix is a modelview matrix
58//! @param push True if adding a new matrix to stack(and saving the old one)
59//! @param replace True if loading matrix (glLoadMatrix), false if multiplying with the previus matrix (glMultMatrix)
60//-----------------------------------------------------------------------------
61void RSPMatrixManager::addMatrix(unsigned int segmentAddress, bool projectionMatrix, bool push, bool replace)
62{
63 unsigned int rdramAddress = m_memory->getRDRAMAddress(segmentAddress);
64
65 if (rdramAddress + 64 > m_memory->getRDRAMSize() ) {
66 return;
67 }
68
69 Matrix4 temp;
70 _loadMatrix(rdramAddress, temp);
71
72 if ( projectionMatrix )
73 {
74 _setProjection(temp, push, replace);
75 }
76 else
77 {
78 _setWorldView(temp, push, replace);
79 }
80
81 _updateCombinedMatrix();
82}
83
84//-----------------------------------------------------------------------------
85//! Insert Matrix
86//-----------------------------------------------------------------------------
87void RSPMatrixManager::insertMatrix(unsigned int where, unsigned int num)
88{
89 float fraction, integer;
90
91 _updateCombinedMatrix();
92
93 if ((where & 0x3) || (where > 0x3C))
94 {
95 return;
96 }
97
98 if (where < 0x20)
99 {
100 fraction = modff( m_worldProject[0][where >> 1], &integer );
101 m_worldProject[0][where >> 1] = (short)_SHIFTR( num, 16, 16 ) + fabs( fraction );
102
103 fraction = modff( m_worldProject[0][(where >> 1) + 1], &integer );
104 m_worldProject[0][(where >> 1) + 1] = (short)_SHIFTR( num, 0, 16 ) + fabs( fraction );
105 }
106 else
107 {
108 float newValue;
109
110 fraction = modff( m_worldProject[0][(where - 0x20) >> 1], &integer );
111 newValue = integer + _FIXED2FLOAT( _SHIFTR( num, 16, 16 ), 16);
112
113 // Make sure the sign isn't lost
114 if ((integer == 0.0f) && (fraction != 0.0f))
115 newValue = newValue * (fraction / fabs( fraction ));
116
117 m_worldProject[0][(where - 0x20) >> 1] = newValue;
118
119 fraction = modff( m_worldProject[0][((where - 0x20) >> 1) + 1], &integer );
120 newValue = integer + _FIXED2FLOAT( _SHIFTR( num, 0, 16 ), 16 );
121
122 // Make sure the sign isn't lost
123 if ((integer == 0.0f) && (fraction != 0.0f))
124 newValue = newValue * (fraction / fabs( fraction ));
125
126 m_worldProject[0][((where - 0x20) >> 1) + 1] = newValue;
127 }
128}
129void RSPMatrixManager::ForceMatrix(unsigned int rdramAddress)
130{
131 _loadMatrix(rdramAddress, m_worldProject);
132}
133
134
135
136//-----------------------------------------------------------------------------
137// Pop Matrix
138//-----------------------------------------------------------------------------
139void RSPMatrixManager::popMatrix()
140{
141 if ( m_modelViewMatrixTop > 0 )
142 {
143 m_modelViewMatrixTop--; //Pop Matrix from stack
144 }
145
146 _updateCombinedMatrix();
147}
148
149//-----------------------------------------------------------------------------
150// Pop Matrix N
151//-----------------------------------------------------------------------------
152void RSPMatrixManager::popMatrixN(unsigned int num)
153{
154 if ( m_modelViewMatrixTop > num - 1)
155 {
156 m_modelViewMatrixTop -= num;
157 }
158
159 _updateCombinedMatrix();
160}
161
162//-----------------------------------------------------------------------------
163//! DMA Matrix
164//-----------------------------------------------------------------------------
165void RSPMatrixManager::DMAMatrix( unsigned int rdramAddress, unsigned char index, unsigned char multiply )
166{
167 //Get final address
168 unsigned int address = m_rdramOffset + rdramAddress;
169
170 if (address + 64 > m_memory->getRDRAMSize())
171 {
172 return;
173 }
174
175 //Load Matrix from Memory
176 Matrix4 temp;
177 _loadMatrix(rdramAddress, temp);
178
179 //Set Modelview index
180 m_modelViewMatrixTop = index;
181
182 //FIXME: Other way around?
183 if (multiply)
184 {
185 m_modelViewMatrices[m_modelViewMatrixTop] = m_modelViewMatrices[0];
186 m_modelViewMatrices[m_modelViewMatrixTop] = m_modelViewMatrices[m_modelViewMatrixTop] * temp;
187 }
188 else
189 {
190 m_modelViewMatrices[m_modelViewMatrixTop] = temp;
191 }
192
193 //Set Projection Matrix to Identity
194 m_projectionMatrices[m_projectionMatrixTop] = Matrix4::IDENTITY;
195
196 //Update Matrices
197 _updateCombinedMatrix();
198}
199
200//-----------------------------------------------------------------------------
201//! Reset Matrices
202//-----------------------------------------------------------------------------
203void RSPMatrixManager::resetMatrices()
204{
205 m_modelViewMatrices[0] = Matrix4::IDENTITY;
206 m_projectionMatrices[0] = Matrix4::IDENTITY;
207
208 m_modelViewMatrixTop = 0;
209 m_projectionMatrixTop = 0;
210
211 _updateCombinedMatrix();
212}
213
214//-----------------------------------------------------------------------------
215//! Load Matrix
216//-----------------------------------------------------------------------------
217void RSPMatrixManager::_loadMatrix(unsigned int addr, Matrix4& out)
218{
219 if ( addr + 64 > m_memory->getRDRAMSize() ) {
220 return;
221 }
222
223 unsigned char* RDRAM = m_memory->getRDRAM();
224
225
226 for (int i = 0; i < 4; i++)
227 {
228 for (int j = 0; j < 4; j++)
229 {
230 int hi = *(short *)(RDRAM + ((addr+(i<<3)+(j<<1) )^0x2));
231 unsigned short lo = *(unsigned short *)(RDRAM + ((addr+(i<<3)+(j<<1) + 32)^0x2));
232 out[i][j] = (float)((hi<<16) | (lo))/ 65536.0f;
233 }
234 }
235}
236
237//-----------------------------------------------------------------------------
238//! Set Projection Matrix
239//-----------------------------------------------------------------------------
240void RSPMatrixManager::_setProjection(const Matrix4& mat, bool push, bool replace)
241{
242 Matrix4& oldMatrix = m_projectionMatrices[m_projectionMatrixTop];
243
244 if (push)
245 {
246 m_projectionMatrixTop++;
247 }
248
249 if ( replace )
250 {
251 m_projectionMatrices[m_projectionMatrixTop] = mat;
252 }
253 else
254 {
255 m_projectionMatrices[m_projectionMatrixTop] = mat * oldMatrix;
256 }
257
258 _updateCombinedMatrix();
259}
260
261//-----------------------------------------------------------------------------
262//! Set World View Matrix
263//-----------------------------------------------------------------------------
264void RSPMatrixManager::_setWorldView(const Matrix4 & mat, bool push, bool replace)
265{
266 Matrix4& oldMatrix = m_modelViewMatrices[m_modelViewMatrixTop];
267
268 if (push)
269 {
270 m_modelViewMatrixTop++;
271 }
272
273 if ( replace )
274 {
275 m_modelViewMatrices[m_modelViewMatrixTop] = mat;
276 }
277 else
278 {
279 m_modelViewMatrices[m_modelViewMatrixTop] = mat * oldMatrix;
280 }
281
282 _updateCombinedMatrix();
283}
284
285//-----------------------------------------------------------------------------
286//! Update Combined Matrix
287//-----------------------------------------------------------------------------
288void RSPMatrixManager::_updateCombinedMatrix()
289{
290 m_worldProject = m_modelViewMatrices[m_modelViewMatrixTop] * m_projectionMatrices[m_projectionMatrixTop];
291}