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
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 //-----------------------------------------------------------------------------
34 TextureLoader::TextureLoader()
35 {
36
37 }
38
39 //-----------------------------------------------------------------------------
40 //! Destructor
41 //-----------------------------------------------------------------------------
42 TextureLoader::~TextureLoader()
43 {
44
45 }
46
47 //-----------------------------------------------------------------------------
48 //* Initialize
49 //! Saves pointers to objects
50 //-----------------------------------------------------------------------------
51 bool 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 //-----------------------------------------------------------------------------
64 void 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 //-----------------------------------------------------------------------------
77 void 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 //-----------------------------------------------------------------------------
110 void 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 //-----------------------------------------------------------------------------
126 void 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 //-----------------------------------------------------------------------------
182 void 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 //-----------------------------------------------------------------------------
234 void 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 }