Arachnoid GLESv1.1 plugin. Compile and run (a bit glitchy and no frameskip) on the...
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / texture / TextureLoader.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 "TextureLoader.h"
23#include "Memory.h"
24#include "TextureCache.h"
25#include "GBIDefs.h"
26#include "assembler.h"
27#include "Logger.h"
28#include "RDP.h"
29#include "CRCCalculator2.h"
30
31//-----------------------------------------------------------------------------
32//! Constructor
33//-----------------------------------------------------------------------------
34TextureLoader::TextureLoader()
35{
36
37}
38
39//-----------------------------------------------------------------------------
40//! Destructor
41//-----------------------------------------------------------------------------
42TextureLoader::~TextureLoader()
43{
44
45}
46
47//-----------------------------------------------------------------------------
48//* Initialize
49//! Saves pointers to objects
50//-----------------------------------------------------------------------------
51bool TextureLoader::initialize(RDP* rdp, Memory* memory)
52{
53 m_rdp = rdp;
54 m_memory = memory;
55
56 m_currentTile = &m_tiles[7];
57 return true;
58}
59
60//-----------------------------------------------------------------------------
61//* Set Texture Image
62//! Stores information about texture image.
63//-----------------------------------------------------------------------------
64void TextureLoader::setTextureImage(unsigned int format, unsigned int size, unsigned int width, unsigned int segmentAddress)
65{
66 m_textureImage.address = m_memory->getRDRAMAddress( segmentAddress );
67 m_textureImage.format = format;
68 m_textureImage.size = size;
69 m_textureImage.width = width + 1; //Note: add plus one, glN64 does it outside of function
70 m_textureImage.bpl = m_textureImage.width << m_textureImage.size >> 1;
71}
72
73//-----------------------------------------------------------------------------
74//* Set Tile
75//! Stores information about an rdp tile.
76//-----------------------------------------------------------------------------
77void TextureLoader::setTile( int format, int size, int line, int tmem, int tile, int palette,
78 int clampS, int clampT, int mirrorS, int mirrorT, int maskS,
79 int maskT, int shiftS, int shiftT )
80{
81 m_tiles[tile].format = format;
82 m_tiles[tile].size = size;
83 m_tiles[tile].line = line;
84 m_tiles[tile].tmem = tmem;
85 m_tiles[tile].palette = palette;
86 m_tiles[tile].clamps = clampS;
87 m_tiles[tile].clampt = clampT;
88 m_tiles[tile].mirrors = mirrorS;
89 m_tiles[tile].mirrort = mirrorT;
90 m_tiles[tile].masks = maskS;
91 m_tiles[tile].maskt = maskT;
92 m_tiles[tile].shiftt = shiftT;
93 m_tiles[tile].shifts = shiftS;
94
95 if ( !m_tiles[tile].masks )
96 m_tiles[tile].clamps = 1;
97 if ( !m_tiles[tile].maskt )
98 m_tiles[tile].clampt = 1;
99
100 //
101 if (((size == G_IM_SIZ_4b) || (size == G_IM_SIZ_8b)) && (format == G_IM_FMT_RGBA)) {
102 m_tiles[tile].format = G_IM_FMT_CI;
103 }
104}
105
106//-----------------------------------------------------------------------------
107//* Set Tile Size
108//! Stores size information for a rdp tile.
109//-----------------------------------------------------------------------------
110void TextureLoader::setTileSize(int tile, unsigned int s0, unsigned int t0, unsigned int s1, unsigned int t1)
111{
112 m_tiles[tile].uls = _SHIFTR( s0, 2, 10 );
113 m_tiles[tile].ult = _SHIFTR( t0, 2, 10 );
114 m_tiles[tile].lrs = _SHIFTR( s1, 2, 10 );
115 m_tiles[tile].lrt = _SHIFTR( t1, 2, 10 );
116 m_tiles[tile].fuls = _FIXED2FLOAT( s0, 2 );
117 m_tiles[tile].fult = _FIXED2FLOAT( t0, 2 );
118 m_tiles[tile].flrs = _FIXED2FLOAT( s1, 2 );
119 m_tiles[tile].flrt = _FIXED2FLOAT( t1, 2 );
120}
121
122//-----------------------------------------------------------------------------
123//* Load Tile (to texture memory)
124//! Kopies texture data from RDRAM to Texture Memory
125//-----------------------------------------------------------------------------
126void TextureLoader::loadTile(int tile, int s0, int t0, int s1, int t1)
127{
128 void (*Interleave)( void *mem, unsigned int numDWords );
129
130
131 //unsigned int tile = _SHIFTR( ucode->w1, 24, 3 );
132
133 unsigned int address, height, bpl, line, y;
134 unsigned long long *dest;
135 unsigned char *src;
136
137 //Set new Tile Size
138 this->setTileSize(tile, s0, t0, s1, t1);
139 m_currentTile = &m_tiles[tile];
140
141 if (m_currentTile->line == 0)
142 return;
143
144 address = m_textureImage.address + m_currentTile->ult * m_textureImage.bpl + (m_currentTile->uls << m_textureImage.size >> 1);
145 dest = m_memory->getTextureMemory( m_currentTile->tmem );
146 bpl = (m_currentTile->lrs - m_currentTile->uls + 1) << m_currentTile->size >> 1;
147 height = m_currentTile->lrt - m_currentTile->ult + 1;
148 src = m_memory->getRDRAM(address);
149
150 if (((address + height * bpl) > m_memory->getRDRAMSize()) || (((m_currentTile->tmem << 3) + bpl * height) > 4096)) // Stay within TMEM
151 {
152 return;
153 }
154
155 // Line given for 32-bit is half what it seems it should since they split the
156 // high and low words. I'm cheating by putting them together.
157 if (m_currentTile->size == G_IM_SIZ_32b)
158 {
159 line = m_currentTile->line << 1;
160 Interleave = QWordInterleave;
161 }
162 else
163 {
164 line = m_currentTile->line;
165 Interleave = DWordInterleave;
166 }
167
168 for (y = 0; y < height; y++)
169 {
170 UnswapCopy( src, dest, bpl );
171 if (y & 1) Interleave( dest, line );
172
173 src += m_textureImage.bpl;
174 dest += line;
175 }
176}
177
178//-----------------------------------------------------------------------------
179//* Load Block (to texture memory)
180//! Kopies texture data from RDRAM to Texture Memory
181//-----------------------------------------------------------------------------
182void TextureLoader::loadBlock(int tile, int s0, int t0, int s1, int t1)
183{
184 unsigned int dxt = t1;
185
186 //Set new Tile Size
187 this->setTileSize(tile, s0, t0, s1, t1);
188 m_currentTile = &m_tiles[tile];
189
190
191 unsigned int bytes = (s1 + 1) << m_currentTile->size >> 1;
192 unsigned int address = m_textureImage.address + t0 * m_textureImage.bpl + (s0 << m_textureImage.size >> 1);
193
194 if ((bytes == 0) || ((address + bytes) > m_memory->getRDRAMSize()) || (((m_currentTile->tmem << 3) + bytes) > 4096))
195 {
196 return;
197 }
198
199 unsigned long long* src = (unsigned long long*)m_memory->getRDRAM(address);
200 unsigned long long* dest = m_memory->getTextureMemory(m_currentTile->tmem);
201
202 unsigned int line = 0;
203
204 if (dxt > 0)
205 {
206 void (*Interleave)( void *mem, unsigned int numDWords );
207
208 line = (2047 + dxt) / dxt;
209 unsigned int bpl = line << 3;
210 unsigned int height = bytes / bpl;
211
212 if (m_currentTile->size == G_IM_SIZ_32b)
213 Interleave = QWordInterleave;
214 else
215 Interleave = DWordInterleave;
216
217 for (unsigned int y = 0; y < height; y++)
218 {
219 UnswapCopy( src, dest, bpl );
220 if (y & 1) Interleave( dest, line );
221
222 src += line;
223 dest += line;
224 }
225 }
226 else
227 UnswapCopy( src, dest, bytes );
228}
229
230//-----------------------------------------------------------------------------
231//* Load Texture Look up table (to texture memory)
232//! Kopies texture data from RDRAM to Texture Memory
233//-----------------------------------------------------------------------------
234void TextureLoader::loadTLUT(int tile, int s0, int t0, int s1, int t1)
235{
236 CRCCalculator2 crcCalculator;
237
238 //Set new Tile Size
239 this->setTileSize(tile, s0, t0, s1, t1);
240
241
242 unsigned short count = (m_tiles[tile].lrs - m_tiles[tile].uls + 1) * (m_tiles[tile].lrt - m_tiles[tile].ult + 1);
243 unsigned int address = m_textureImage.address + m_tiles[tile].ult * m_textureImage.bpl + (m_tiles[tile].uls << m_textureImage.size >> 1);
244
245 //Copy from rdram to texture memory
246 unsigned short *src = (unsigned short*)m_memory->getRDRAM(address);
247 unsigned short *dest = (unsigned short*)m_memory->getTextureMemory(m_tiles[tile].tmem);
248
249 unsigned short pal = (m_tiles[tile].tmem - 256) >> 4;
250
251 int i = 0;
252 while (i < count)
253 {
254 for (unsigned short j = 0; (j < 16) && (i < count); j++, i++)
255 {
256 unsigned short color = swapword( src[i^1] );
257 *dest = color;
258 dest += 4;
259 }
260
261
262 m_rdp->m_paletteCRC16[pal] = crcCalculator.calcPaletteCRC(0xFFFFFFFF, m_memory->getTextureMemory(256 + (pal << 4)), 16);
263 pal++;
264 }
265
266 m_rdp->m_paletteCRC256 = crcCalculator.calcCRC(0xFFFFFFFF, m_rdp->m_paletteCRC16, 64);
267}