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 | //----------------------------------------------------------------------------- |
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 | } |