1 /******************************************************************************
2 * Arachnoid Graphics Plugin for Mupen64Plus
3 * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
5 * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
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.
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.
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 *****************************************************************************/
22 #include "TextureLoader.h"
24 #include "TextureCache.h"
26 #include "assembler.h"
29 #include "CRCCalculator2.h"
31 //-----------------------------------------------------------------------------
33 //-----------------------------------------------------------------------------
34 TextureLoader::TextureLoader()
39 //-----------------------------------------------------------------------------
41 //-----------------------------------------------------------------------------
42 TextureLoader::~TextureLoader()
47 //-----------------------------------------------------------------------------
49 //! Saves pointers to objects
50 //-----------------------------------------------------------------------------
51 bool TextureLoader::initialize(RDP* rdp, Memory* memory)
56 m_currentTile = &m_tiles[7];
60 //-----------------------------------------------------------------------------
62 //! Stores information about texture image.
63 //-----------------------------------------------------------------------------
64 void TextureLoader::setTextureImage(unsigned int format, unsigned int size, unsigned int width, unsigned int segmentAddress)
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;
73 //-----------------------------------------------------------------------------
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 )
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;
95 if ( !m_tiles[tile].masks )
96 m_tiles[tile].clamps = 1;
97 if ( !m_tiles[tile].maskt )
98 m_tiles[tile].clampt = 1;
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;
106 //-----------------------------------------------------------------------------
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)
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 );
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)
128 void (*Interleave)( void *mem, unsigned int numDWords );
131 //unsigned int tile = _SHIFTR( ucode->w1, 24, 3 );
133 unsigned int address, height, bpl, line, y;
134 unsigned long long *dest;
138 this->setTileSize(tile, s0, t0, s1, t1);
139 m_currentTile = &m_tiles[tile];
141 if (m_currentTile->line == 0)
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);
150 if (((address + height * bpl) > m_memory->getRDRAMSize()) || (((m_currentTile->tmem << 3) + bpl * height) > 4096)) // Stay within TMEM
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)
159 line = m_currentTile->line << 1;
160 Interleave = QWordInterleave;
164 line = m_currentTile->line;
165 Interleave = DWordInterleave;
168 for (y = 0; y < height; y++)
170 UnswapCopy( src, dest, bpl );
171 if (y & 1) Interleave( dest, line );
173 src += m_textureImage.bpl;
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)
184 unsigned int dxt = t1;
187 this->setTileSize(tile, s0, t0, s1, t1);
188 m_currentTile = &m_tiles[tile];
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);
194 if ((bytes == 0) || ((address + bytes) > m_memory->getRDRAMSize()) || (((m_currentTile->tmem << 3) + bytes) > 4096))
199 unsigned long long* src = (unsigned long long*)m_memory->getRDRAM(address);
200 unsigned long long* dest = m_memory->getTextureMemory(m_currentTile->tmem);
202 unsigned int line = 0;
206 void (*Interleave)( void *mem, unsigned int numDWords );
208 line = (2047 + dxt) / dxt;
209 unsigned int bpl = line << 3;
210 unsigned int height = bytes / bpl;
212 if (m_currentTile->size == G_IM_SIZ_32b)
213 Interleave = QWordInterleave;
215 Interleave = DWordInterleave;
217 for (unsigned int y = 0; y < height; y++)
219 UnswapCopy( src, dest, bpl );
220 if (y & 1) Interleave( dest, line );
227 UnswapCopy( src, dest, bytes );
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)
236 CRCCalculator2 crcCalculator;
239 this->setTileSize(tile, s0, t0, s1, t1);
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);
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);
249 unsigned short pal = (m_tiles[tile].tmem - 256) >> 4;
254 for (unsigned short j = 0; (j < 16) && (i < count); j++, i++)
256 unsigned short color = swapword( src[i^1] );
262 m_rdp->m_paletteCRC16[pal] = crcCalculator.calcPaletteCRC(0xFFFFFFFF, m_memory->getTextureMemory(256 + (pal << 4)), 16);
266 m_rdp->m_paletteCRC256 = crcCalculator.calcCRC(0xFFFFFFFF, m_rdp->m_paletteCRC16, 64);