1 #include <stdint.h>
2 #include <stdlib.h>
3
4 #include "OpenGL.h"
5 #include "FrameBuffer.h"
6 #include "RSP.h"
7 #include "RDP.h"
8 #include "Textures.h"
9 #include "ShaderCombiner.h"
10 #include "VI.h"
11
12 struct FrameBufferInfo frameBuffer;
13 CachedTexture *g_RDRAMtoFB;
14
FrameBuffer_Init(void)15 void FrameBuffer_Init(void)
16 {
17 frameBuffer.current = NULL;
18 frameBuffer.top = NULL;
19 frameBuffer.bottom = NULL;
20 frameBuffer.numBuffers = 0;
21 }
22
FrameBuffer_RemoveBottom(void)23 void FrameBuffer_RemoveBottom(void)
24 {
25 struct FrameBuffer *newBottom = (struct FrameBuffer*)
26 frameBuffer.bottom->higher;
27
28 TextureCache_Remove( frameBuffer.bottom->texture );
29
30 if (frameBuffer.bottom == frameBuffer.top)
31 frameBuffer.top = NULL;
32
33 free( frameBuffer.bottom );
34
35 frameBuffer.bottom = newBottom;
36
37 if (frameBuffer.bottom != NULL)
38 frameBuffer.bottom->lower = NULL;
39
40 frameBuffer.numBuffers--;
41 }
42
FrameBuffer_Remove(struct FrameBuffer * buffer)43 void FrameBuffer_Remove( struct FrameBuffer *buffer )
44 {
45 if ((buffer == frameBuffer.bottom) &&
46 (buffer == frameBuffer.top))
47 {
48 frameBuffer.top = NULL;
49 frameBuffer.bottom = NULL;
50 }
51 else if (buffer == frameBuffer.bottom)
52 {
53 frameBuffer.bottom = buffer->higher;
54
55 if (frameBuffer.bottom)
56 frameBuffer.bottom->lower = NULL;
57 }
58 else if (buffer == frameBuffer.top)
59 {
60 frameBuffer.top = buffer->lower;
61
62 if (frameBuffer.top)
63 frameBuffer.top->higher = NULL;
64 }
65 else
66 {
67 buffer->higher->lower = buffer->lower;
68 buffer->lower->higher = buffer->higher;
69 }
70
71 if (buffer->texture)
72 TextureCache_Remove( buffer->texture );
73
74 free( buffer );
75
76 frameBuffer.numBuffers--;
77 }
78
FrameBuffer_RemoveBuffer(uint32_t address)79 void FrameBuffer_RemoveBuffer( uint32_t address )
80 {
81 struct FrameBuffer *current = (struct FrameBuffer*)frameBuffer.bottom;
82
83 while (current != NULL)
84 {
85 if (current->m_startAddress == address)
86 {
87 current->texture = NULL;
88 FrameBuffer_Remove( current );
89 return;
90 }
91 current = current->higher;
92 }
93 }
94
FrameBuffer_AddTop(void)95 struct FrameBuffer *FrameBuffer_AddTop(void)
96 {
97 struct FrameBuffer *newtop = (struct FrameBuffer*)malloc( sizeof(struct FrameBuffer ) );
98
99 newtop->texture = TextureCache_AddTop();
100
101 newtop->lower = frameBuffer.top;
102 newtop->higher = NULL;
103
104 if (frameBuffer.top)
105 frameBuffer.top->higher = newtop;
106
107 if (!frameBuffer.bottom)
108 frameBuffer.bottom = newtop;
109
110 frameBuffer.top = newtop;
111
112 frameBuffer.numBuffers++;
113
114 return newtop;
115 }
116
FrameBuffer_MoveToTop(struct FrameBuffer * newtop)117 void FrameBuffer_MoveToTop( struct FrameBuffer *newtop )
118 {
119 if (newtop == frameBuffer.top)
120 return;
121
122 if (newtop == frameBuffer.bottom)
123 {
124 frameBuffer.bottom = newtop->higher;
125 frameBuffer.bottom->lower = NULL;
126 }
127 else
128 {
129 newtop->higher->lower = newtop->lower;
130 newtop->lower->higher = newtop->higher;
131 }
132
133 newtop->higher = NULL;
134 newtop->lower = frameBuffer.top;
135 frameBuffer.top->higher = newtop;
136 frameBuffer.top = newtop;
137
138 TextureCache_MoveToTop( newtop->texture );
139 }
140
FrameBuffer_Destroy(void)141 void FrameBuffer_Destroy(void)
142 {
143 while (frameBuffer.bottom)
144 FrameBuffer_RemoveBottom();
145 }
146
FrameBuffer_SaveBuffer(uint32_t address,uint16_t format,uint16_t size,uint16_t width,uint16_t height,bool unknown)147 void FrameBuffer_SaveBuffer( uint32_t address, uint16_t format, uint16_t size, uint16_t width, uint16_t height, bool unknown)
148 {
149 struct FrameBuffer *current = frameBuffer.top;
150
151 if (width != VI.width && height == 0)
152 return;
153
154 (void)format;
155 (void)unknown;
156
157 /* Search through saved frame buffers */
158 while (current != NULL)
159 {
160 if ((current->m_startAddress == address) &&
161 (current->m_width == width) &&
162 (current->m_height == height) &&
163 (current->m_size == size))
164 {
165 if ((current->m_scaleX != OGL.scaleX) ||
166 (current->m_scaleY != OGL.scaleY))
167 {
168 FrameBuffer_Remove( current );
169 break;
170 }
171
172 /* code goes here */
173 *(uint32_t*)&gfx_info.RDRAM[current->m_startAddress] = current->m_startAddress;
174
175 current->m_changed = true;
176
177 FrameBuffer_MoveToTop( current );
178
179 gSP.changed |= CHANGED_TEXTURE;
180 return;
181 }
182 current = current->lower;
183 }
184
185 /* Wasn't found, create a new one */
186 current = FrameBuffer_AddTop();
187
188 current->m_startAddress = address;
189 current->m_endAddress = address + ((width * height << size >> 1) - 1);
190 current->m_width = width;
191 current->m_height = height;
192 current->m_size = size;
193 current->m_scaleX = OGL.scaleX;
194 current->m_scaleY = OGL.scaleY;
195
196 current->texture->width = current->m_width * OGL.scaleX;
197 current->texture->height = current->m_height * OGL.scaleY;
198 current->texture->clampS = 1;
199 current->texture->clampT = 1;
200 current->texture->address = current->m_startAddress;
201 current->texture->clampWidth = current->m_width;
202 current->texture->clampHeight = current->m_height;
203 current->texture->frameBufferTexture = true;
204 current->texture->maskS = 0;
205 current->texture->maskT = 0;
206 current->texture->mirrorS = 0;
207 current->texture->mirrorT = 0;
208 current->texture->realWidth = pow2( current->m_width * OGL.scaleX );
209 current->texture->realHeight = pow2( current->m_height * OGL.scaleY );
210 current->texture->textureBytes = current->texture->realWidth * current->texture->realHeight * 4;
211 cache.cachedBytes += current->texture->textureBytes;
212
213 /* code goes here - just bind texture and copy it over */
214 *(uint32_t*)&gfx_info.RDRAM[current->m_startAddress] = current->m_startAddress;
215
216 current->m_changed = true;
217
218 gSP.changed |= CHANGED_TEXTURE;
219 }
220
FrameBuffer_GetCurrent(void)221 struct FrameBuffer *FrameBuffer_GetCurrent(void)
222 {
223 return (struct FrameBuffer*)frameBuffer.top;
224 }
225
FrameBuffer_RenderBuffer(uint32_t address)226 void FrameBuffer_RenderBuffer( uint32_t address )
227 {
228 struct FrameBuffer *current = (struct FrameBuffer*)frameBuffer.top;
229
230 while (current != NULL)
231 {
232 if ((current->m_startAddress <= address) &&
233 (current->m_endAddress >= address))
234 {
235 /* code goes here */
236
237 current->m_changed = false;
238
239 FrameBuffer_MoveToTop( current );
240
241 gSP.changed |= CHANGED_TEXTURE | CHANGED_VIEWPORT;
242 gDP.changed |= CHANGED_COMBINE;
243 return;
244 }
245 current = current->lower;
246 }
247 }
248
FrameBuffer_RestoreBuffer(uint32_t address,uint16_t size,uint16_t width)249 void FrameBuffer_RestoreBuffer( uint32_t address, uint16_t size, uint16_t width )
250 {
251 struct FrameBuffer *current = (struct FrameBuffer*)frameBuffer.top;
252
253 while (current != NULL)
254 {
255 if ((current->m_startAddress == address) &&
256 (current->m_width == width) &&
257 (current->m_size == size))
258 {
259
260 /* code goes here */
261
262 FrameBuffer_MoveToTop( current );
263
264 gSP.changed |= CHANGED_TEXTURE | CHANGED_VIEWPORT;
265 gDP.changed |= CHANGED_COMBINE;
266 return;
267 }
268 current = current->lower;
269 }
270 }
271
FrameBuffer_FindBuffer(uint32_t address)272 struct FrameBuffer *FrameBuffer_FindBuffer( uint32_t address )
273 {
274 struct FrameBuffer *current = (struct FrameBuffer*)frameBuffer.top;
275
276 while (current)
277 {
278 if ((current->m_startAddress <= address) &&
279 (current->m_endAddress >= address))
280 return current;
281 current = current->lower;
282 }
283
284 return NULL;
285 }
286
FrameBuffer_ActivateBufferTexture(int16_t t,struct FrameBuffer * buffer)287 void FrameBuffer_ActivateBufferTexture( int16_t t, struct FrameBuffer *buffer )
288 {
289 buffer->texture->scaleS = OGL.scaleX / (float)buffer->texture->realWidth;
290 buffer->texture->scaleT = OGL.scaleY / (float)buffer->texture->realHeight;
291
292 if (gSP.textureTile[t]->shifts > 10)
293 buffer->texture->shiftScaleS = (float)(1 << (16 - gSP.textureTile[t]->shifts));
294 else if (gSP.textureTile[t]->shifts > 0)
295 buffer->texture->shiftScaleS = 1.0f / (float)(1 << gSP.textureTile[t]->shifts);
296 else
297 buffer->texture->shiftScaleS = 1.0f;
298
299 if (gSP.textureTile[t]->shiftt > 10)
300 buffer->texture->shiftScaleT = (float)(1 << (16 - gSP.textureTile[t]->shiftt));
301 else if (gSP.textureTile[t]->shiftt > 0)
302 buffer->texture->shiftScaleT = 1.0f / (float)(1 << gSP.textureTile[t]->shiftt);
303 else
304 buffer->texture->shiftScaleT = 1.0f;
305
306 if (gDP.loadTile->loadType == LOADTYPE_TILE)
307 {
308 buffer->texture->offsetS = gDP.loadTile->uls;
309 buffer->texture->offsetT = (float)buffer->m_height -
310 (gDP.loadTile->ult + (gDP.textureImage.address - buffer->m_startAddress) / (buffer->m_width << buffer->m_size >> 1));
311 }
312 else
313 {
314 buffer->texture->offsetS = 0.0f;
315 buffer->texture->offsetT = (float)buffer->m_height - (gDP.textureImage.address - buffer->m_startAddress) / (buffer->m_width << buffer->m_size >> 1);
316 }
317
318 FrameBuffer_MoveToTop( buffer );
319 TextureCache_ActivateTexture( t, buffer->texture );
320 gDP.changed |= CHANGED_FB_TEXTURE;
321 }
322
FrameBuffer_ActivateBufferTextureBG(int16_t t,struct FrameBuffer * buffer)323 void FrameBuffer_ActivateBufferTextureBG(int16_t t, struct FrameBuffer *buffer )
324 {
325 if (buffer == NULL || buffer->texture == NULL)
326 return;
327
328 buffer->texture->scaleS = OGL.scaleX / (float)buffer->texture->realWidth;
329 buffer->texture->scaleT = OGL.scaleY / (float)buffer->texture->realHeight;
330
331 buffer->texture->shiftScaleS = 1.0f;
332 buffer->texture->shiftScaleT = 1.0f;
333
334 buffer->texture->offsetS = gSP.bgImage.imageX;
335 buffer->texture->offsetT = (float)buffer->m_height - gSP.bgImage.imageY;
336
337 FrameBuffer_MoveToTop( buffer );
338 TextureCache_ActivateTexture( t, buffer->texture );
339 gDP.changed |= CHANGED_FB_TEXTURE;
340 }
341
FrameBuffer_CopyFromRDRAM(uint32_t _address,bool _bUseAlpha)342 void FrameBuffer_CopyFromRDRAM( uint32_t _address, bool _bUseAlpha )
343 {
344 /* stub */
345 }
346
FrameBuffer_CopyToRDRAM(uint32_t _address)347 void FrameBuffer_CopyToRDRAM( uint32_t _address )
348 {
349 /* stub */
350 }
351
FrameBuffer_CopyDepthBuffer(uint32_t _address)352 void FrameBuffer_CopyDepthBuffer( uint32_t _address )
353 {
354 /* stub */
355 }
356