d07c171f |
1 | /* |
2 | Copyright (C) 2002 Rice1964 |
3 | Copyright (C) 2009-2011 Richard Goedeken |
4 | |
5 | This program is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU General Public License |
7 | as published by the Free Software Foundation; either version 2 |
8 | of the License, or (at your option) any later version. |
9 | |
10 | This program is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | GNU General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU General Public License |
16 | along with this program; if not, write to the Free Software |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
18 | |
19 | */ |
20 | |
21 | #include <vector> |
22 | |
23 | #include <stdarg.h> |
24 | |
25 | #include "osal_opengl.h" |
26 | |
27 | #define M64P_PLUGIN_PROTOTYPES 1 |
28 | #include "m64p_types.h" |
29 | #include "m64p_common.h" |
30 | #include "m64p_plugin.h" |
31 | #include "osal_dynamiclib.h" |
32 | |
33 | #include "Config.h" |
34 | #include "Debugger.h" |
35 | #include "DeviceBuilder.h" |
36 | #include "FrameBuffer.h" |
37 | #include "GraphicsContext.h" |
38 | #include "Render.h" |
39 | #include "RSP_Parser.h" |
40 | #include "TextureFilters.h" |
41 | #include "TextureManager.h" |
42 | #include "Video.h" |
43 | #include "version.h" |
44 | |
45 | //======================================================= |
46 | // local variables |
47 | |
48 | static void (*l_DebugCallback)(void *, int, const char *) = NULL; |
49 | static void *l_DebugCallContext = NULL; |
50 | static int l_PluginInit = 0; |
51 | |
52 | //======================================================= |
53 | // global variables |
54 | |
55 | PluginStatus status; |
56 | GFX_INFO g_GraphicsInfo; |
57 | CCritSect g_CritialSection; |
58 | |
59 | unsigned int g_dwRamSize = 0x400000; |
60 | unsigned int *g_pRDRAMu32 = NULL; |
61 | signed char *g_pRDRAMs8 = NULL; |
62 | unsigned char *g_pRDRAMu8 = NULL; |
63 | |
64 | RECT frameWriteByCPURect; |
65 | std::vector<RECT> frameWriteByCPURects; |
66 | RECT frameWriteByCPURectArray[20][20]; |
67 | bool frameWriteByCPURectFlag[20][20]; |
68 | std::vector<uint32> frameWriteRecord; |
69 | |
70 | void (*renderCallback)(int) = NULL; |
71 | |
72 | /* definitions of pointers to Core config functions */ |
73 | ptr_ConfigOpenSection ConfigOpenSection = NULL; |
74 | ptr_ConfigSetParameter ConfigSetParameter = NULL; |
75 | ptr_ConfigGetParameter ConfigGetParameter = NULL; |
76 | ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL; |
77 | ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL; |
78 | ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL; |
79 | ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL; |
80 | ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL; |
81 | ptr_ConfigGetParamInt ConfigGetParamInt = NULL; |
82 | ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL; |
83 | ptr_ConfigGetParamBool ConfigGetParamBool = NULL; |
84 | ptr_ConfigGetParamString ConfigGetParamString = NULL; |
85 | |
86 | ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL; |
87 | ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL; |
88 | ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL; |
89 | ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL; |
90 | |
91 | /* definitions of pointers to Core video extension functions */ |
92 | ptr_VidExt_Init CoreVideo_Init = NULL; |
93 | ptr_VidExt_Quit CoreVideo_Quit = NULL; |
94 | ptr_VidExt_ListFullscreenModes CoreVideo_ListFullscreenModes = NULL; |
95 | ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode = NULL; |
96 | ptr_VidExt_SetCaption CoreVideo_SetCaption = NULL; |
97 | ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen = NULL; |
98 | ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow = NULL; |
99 | ptr_VidExt_GL_GetProcAddress CoreVideo_GL_GetProcAddress = NULL; |
100 | ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute = NULL; |
101 | ptr_VidExt_GL_GetAttribute CoreVideo_GL_GetAttribute = NULL; |
102 | ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers = NULL; |
103 | |
104 | // For Fameskip |
105 | float mspervi = 1000.0f/60.0f; //default is shortest frame |
106 | float numvi = 0.0f; |
107 | |
108 | |
109 | //--------------------------------------------------------------------------------------- |
110 | // Forward function declarations |
111 | |
112 | extern "C" EXPORT void CALL RomClosed(void); |
113 | |
114 | //--------------------------------------------------------------------------------------- |
115 | // Static (local) functions |
116 | static void ChangeWindowStep2() |
117 | { |
118 | status.bDisableFPS = true; |
119 | windowSetting.bDisplayFullscreen = !windowSetting.bDisplayFullscreen; |
120 | g_CritialSection.Lock(); |
121 | windowSetting.bDisplayFullscreen = CGraphicsContext::Get()->ToggleFullscreen(); |
122 | |
123 | CGraphicsContext::Get()->Clear(CLEAR_COLOR_AND_DEPTH_BUFFER); |
124 | CGraphicsContext::Get()->UpdateFrame(); |
125 | CGraphicsContext::Get()->Clear(CLEAR_COLOR_AND_DEPTH_BUFFER); |
126 | CGraphicsContext::Get()->UpdateFrame(); |
127 | CGraphicsContext::Get()->Clear(CLEAR_COLOR_AND_DEPTH_BUFFER); |
128 | CGraphicsContext::Get()->UpdateFrame(); |
129 | g_CritialSection.Unlock(); |
130 | status.bDisableFPS = false; |
131 | status.ToToggleFullScreen = FALSE; |
132 | } |
133 | |
134 | static void ResizeStep2(void) |
135 | { |
136 | g_CritialSection.Lock(); |
137 | |
138 | // Delete all OpenGL textures |
139 | gTextureManager.CleanUp(); |
140 | RDP_Cleanup(); |
141 | // delete our opengl renderer |
142 | CDeviceBuilder::GetBuilder()->DeleteRender(); |
143 | |
144 | // call video extension function with updated width, height (this creates a new OpenGL context) |
145 | windowSetting.uDisplayWidth = status.gNewResizeWidth; |
146 | windowSetting.uDisplayHeight = status.gNewResizeHeight; |
147 | CoreVideo_ResizeWindow(windowSetting.uDisplayWidth, windowSetting.uDisplayHeight); |
148 | |
149 | // re-initialize our OpenGL graphics context state |
150 | bool res = CGraphicsContext::Get()->ResizeInitialize(windowSetting.uDisplayWidth, windowSetting.uDisplayHeight, !windowSetting.bDisplayFullscreen); |
151 | if (res) |
152 | { |
153 | // re-create the OpenGL renderer |
154 | CDeviceBuilder::GetBuilder()->CreateRender(); |
155 | CRender::GetRender()->Initialize(); |
156 | DLParser_Init(); |
157 | } |
158 | |
159 | g_CritialSection.Unlock(); |
160 | status.ToResize = false; |
161 | } |
162 | |
163 | static void UpdateScreenStep2 (void) |
164 | { |
165 | status.bVIOriginIsUpdated = false; |
166 | |
167 | if( status.ToToggleFullScreen && status.gDlistCount > 0 ) |
168 | { |
169 | ChangeWindowStep2(); |
170 | return; |
171 | } |
172 | if (status.ToResize && status.gDlistCount > 0) |
173 | { |
174 | ResizeStep2(); |
175 | return; |
176 | } |
177 | |
178 | g_CritialSection.Lock(); |
179 | |
180 | //framskip, count vi |
181 | numvi++; |
182 | |
183 | if( status.bHandleN64RenderTexture ) |
184 | g_pFrameBufferManager->CloseRenderTexture(true); |
185 | |
186 | g_pFrameBufferManager->SetAddrBeDisplayed(*g_GraphicsInfo.VI_ORIGIN_REG); |
187 | |
188 | if( status.gDlistCount == 0 ) |
189 | { |
190 | // CPU frame buffer update |
191 | uint32 width = *g_GraphicsInfo.VI_WIDTH_REG; |
192 | if( (*g_GraphicsInfo.VI_ORIGIN_REG & (g_dwRamSize-1) ) > width*2 && *g_GraphicsInfo.VI_H_START_REG != 0 && width != 0 ) |
193 | { |
194 | SetVIScales(); |
195 | CRender::GetRender()->DrawFrameBuffer(true); |
196 | CGraphicsContext::Get()->UpdateFrame(); |
197 | } |
198 | g_CritialSection.Unlock(); |
199 | return; |
200 | } |
201 | |
202 | TXTRBUF_DETAIL_DUMP(TRACE1("VI ORIG is updated to %08X", *g_GraphicsInfo.VI_ORIGIN_REG)); |
203 | |
204 | if( currentRomOptions.screenUpdateSetting == SCREEN_UPDATE_AT_VI_UPDATE ) |
205 | { |
206 | CGraphicsContext::Get()->UpdateFrame(); |
207 | |
208 | DEBUGGER_IF_DUMP( pauseAtNext, TRACE1("Update Screen: VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG)); |
209 | DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_FRAME); |
210 | DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_SET_CIMG); |
211 | g_CritialSection.Unlock(); |
212 | return; |
213 | } |
214 | |
215 | TXTRBUF_DETAIL_DUMP(TRACE1("VI ORIG is updated to %08X", *g_GraphicsInfo.VI_ORIGIN_REG)); |
216 | |
217 | if( currentRomOptions.screenUpdateSetting == SCREEN_UPDATE_AT_VI_UPDATE_AND_DRAWN ) |
218 | { |
219 | if( status.bScreenIsDrawn ) |
220 | { |
221 | CGraphicsContext::Get()->UpdateFrame(); |
222 | DEBUGGER_IF_DUMP( pauseAtNext, TRACE1("Update Screen: VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG)); |
223 | } |
224 | else |
225 | { |
226 | DEBUGGER_IF_DUMP( pauseAtNext, TRACE1("Skip Screen Update: VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG)); |
227 | } |
228 | |
229 | DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_FRAME); |
230 | DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_SET_CIMG); |
231 | g_CritialSection.Unlock(); |
232 | return; |
233 | } |
234 | |
235 | if( currentRomOptions.screenUpdateSetting==SCREEN_UPDATE_AT_VI_CHANGE ) |
236 | { |
237 | |
238 | if( *g_GraphicsInfo.VI_ORIGIN_REG != status.curVIOriginReg ) |
239 | { |
240 | if( *g_GraphicsInfo.VI_ORIGIN_REG < status.curDisplayBuffer || *g_GraphicsInfo.VI_ORIGIN_REG > status.curDisplayBuffer+0x2000 ) |
241 | { |
242 | status.curDisplayBuffer = *g_GraphicsInfo.VI_ORIGIN_REG; |
243 | status.curVIOriginReg = status.curDisplayBuffer; |
244 | //status.curRenderBuffer = NULL; |
245 | |
246 | CGraphicsContext::Get()->UpdateFrame(); |
247 | DEBUGGER_IF_DUMP( pauseAtNext, TRACE1("Update Screen: VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG)); |
248 | DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_FRAME); |
249 | DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_SET_CIMG); |
250 | } |
251 | else |
252 | { |
253 | status.curDisplayBuffer = *g_GraphicsInfo.VI_ORIGIN_REG; |
254 | status.curVIOriginReg = status.curDisplayBuffer; |
255 | DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_FRAME, {DebuggerAppendMsg("Skip Screen Update, closed to the display buffer, VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG);}); |
256 | } |
257 | } |
258 | else |
259 | { |
260 | DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_FRAME, {DebuggerAppendMsg("Skip Screen Update, the same VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG);}); |
261 | } |
262 | |
263 | g_CritialSection.Unlock(); |
264 | return; |
265 | } |
266 | |
267 | if( currentRomOptions.screenUpdateSetting >= SCREEN_UPDATE_AT_1ST_CI_CHANGE ) |
268 | { |
269 | status.bVIOriginIsUpdated=true; |
270 | DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_FRAME, {DebuggerAppendMsg("VI ORIG is updated to %08X", *g_GraphicsInfo.VI_ORIGIN_REG);}); |
271 | g_CritialSection.Unlock(); |
272 | return; |
273 | } |
274 | |
275 | DEBUGGER_IF_DUMP( pauseAtNext, TRACE1("VI is updated, No screen update: VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG)); |
276 | DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_FRAME); |
277 | DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_SET_CIMG); |
278 | |
279 | g_CritialSection.Unlock(); |
280 | } |
281 | |
282 | static void ProcessDListStep2(void) |
283 | { |
284 | g_CritialSection.Lock(); |
285 | if( status.toShowCFB ) |
286 | { |
287 | CRender::GetRender()->DrawFrameBuffer(true); |
288 | status.toShowCFB = false; |
289 | } |
290 | |
291 | try |
292 | { |
293 | DLParser_Process((OSTask *)(g_GraphicsInfo.DMEM + 0x0FC0)); |
294 | } |
295 | catch (...) |
296 | { |
297 | TRACE0("Unknown Error in ProcessDList"); |
298 | TriggerDPInterrupt(); |
299 | TriggerSPInterrupt(); |
300 | } |
301 | |
302 | g_CritialSection.Unlock(); |
303 | } |
304 | |
305 | static bool StartVideo(void) |
306 | { |
307 | windowSetting.dps = windowSetting.fps = -1; |
308 | windowSetting.lastSecDlistCount = windowSetting.lastSecFrameCount = 0xFFFFFFFF; |
309 | |
310 | g_CritialSection.Lock(); |
311 | |
312 | memcpy(&g_curRomInfo.romheader, g_GraphicsInfo.HEADER, sizeof(ROMHeader)); |
313 | unsigned char *puc = (unsigned char *) &g_curRomInfo.romheader; |
314 | unsigned int i; |
315 | unsigned char temp; |
316 | for (i = 0; i < sizeof(ROMHeader); i += 4) /* byte-swap the ROM header */ |
317 | { |
318 | temp = puc[i]; |
319 | puc[i] = puc[i+3]; |
320 | puc[i+3] = temp; |
321 | temp = puc[i+1]; |
322 | puc[i+1] = puc[i+2]; |
323 | puc[i+2] = temp; |
324 | } |
325 | |
326 | ROM_GetRomNameFromHeader(g_curRomInfo.szGameName, &g_curRomInfo.romheader); |
327 | Ini_GetRomOptions(&g_curRomInfo); |
328 | char *p = (char *) g_curRomInfo.szGameName + (strlen((char *) g_curRomInfo.szGameName) -1); // -1 to skip null |
329 | while (p >= (char *) g_curRomInfo.szGameName) |
330 | { |
331 | if( *p == ':' || *p == '\\' || *p == '/' ) |
332 | *p = '-'; |
333 | p--; |
334 | } |
335 | GenerateCurrentRomOptions(); |
336 | status.dwTvSystem = CountryCodeToTVSystem(g_curRomInfo.romheader.nCountryID); |
337 | if( status.dwTvSystem == TV_SYSTEM_NTSC ) { |
338 | status.fRatio = 0.75f; |
339 | mspervi=1000.0f/60.0f; //for framskipping |
340 | } else { |
341 | status.fRatio = 9/11.0f; |
342 | mspervi=1000.0f/50.0f; |
343 | } |
344 | printf("TV system=%s, ms per VI=%f\n", (status.dwTvSystem==TV_SYSTEM_NTSC)?"NTSC":"PAL", mspervi); |
345 | InitExternalTextures(); |
346 | |
347 | try { |
348 | CDeviceBuilder::GetBuilder()->CreateGraphicsContext(); |
349 | CGraphicsContext::InitWindowInfo(); |
350 | printf("bool res = CGraphicsContext::Get()->Initialize(640, 480, !windowSetting.bDisplayFullscreen);\n"); |
351 | bool res = CGraphicsContext::Get()->Initialize(640, 480, !windowSetting.bDisplayFullscreen); |
352 | if (!res) |
353 | { |
354 | printf("!res\n"); |
355 | g_CritialSection.Unlock(); |
356 | return false; |
357 | } |
358 | CDeviceBuilder::GetBuilder()->CreateRender(); |
359 | CRender::GetRender()->Initialize(); |
360 | DLParser_Init(); |
361 | status.bGameIsRunning = true; |
362 | } |
363 | catch(...) |
364 | { |
365 | DebugMessage(M64MSG_ERROR, "Exception caught while starting video renderer"); |
366 | throw 0; |
367 | } |
368 | printf("VideoInit finished\n"); |
369 | g_CritialSection.Unlock(); |
370 | return true; |
371 | } |
372 | |
373 | static void StopVideo() |
374 | { |
375 | g_CritialSection.Lock(); |
376 | status.bGameIsRunning = false; |
377 | |
378 | try { |
379 | CloseExternalTextures(); |
380 | |
381 | // Kill all textures? |
382 | gTextureManager.RecycleAllTextures(); |
383 | gTextureManager.CleanUp(); |
384 | RDP_Cleanup(); |
385 | |
386 | CDeviceBuilder::GetBuilder()->DeleteRender(); |
387 | CGraphicsContext::Get()->CleanUp(); |
388 | CDeviceBuilder::GetBuilder()->DeleteGraphicsContext(); |
389 | } |
390 | catch(...) |
391 | { |
392 | TRACE0("Some exceptions during RomClosed"); |
393 | } |
394 | |
395 | g_CritialSection.Unlock(); |
396 | windowSetting.dps = windowSetting.fps = -1; |
397 | windowSetting.lastSecDlistCount = windowSetting.lastSecFrameCount = 0xFFFFFFFF; |
398 | status.gDlistCount = status.gFrameCount = 0; |
399 | |
400 | } |
401 | |
402 | //--------------------------------------------------------------------------------------- |
403 | // Global functions, for use by other source files in this plugin |
404 | |
405 | void SetVIScales() |
406 | { |
407 | if( g_curRomInfo.VIHeight>0 && g_curRomInfo.VIWidth>0 ) |
408 | { |
409 | windowSetting.fViWidth = windowSetting.uViWidth = g_curRomInfo.VIWidth; |
410 | windowSetting.fViHeight = windowSetting.uViHeight = g_curRomInfo.VIHeight; |
411 | } |
412 | else if( g_curRomInfo.UseCIWidthAndRatio && g_CI.dwWidth ) |
413 | { |
414 | windowSetting.fViWidth = windowSetting.uViWidth = g_CI.dwWidth; |
415 | windowSetting.fViHeight = windowSetting.uViHeight = |
416 | g_curRomInfo.UseCIWidthAndRatio == USE_CI_WIDTH_AND_RATIO_FOR_NTSC ? g_CI.dwWidth/4*3 : g_CI.dwWidth/11*9; |
417 | } |
418 | else |
419 | { |
420 | float xscale, yscale; |
421 | uint32 val = *g_GraphicsInfo.VI_X_SCALE_REG & 0xFFF; |
422 | xscale = (float)val / (1<<10); |
423 | uint32 start = *g_GraphicsInfo.VI_H_START_REG >> 16; |
424 | uint32 end = *g_GraphicsInfo.VI_H_START_REG&0xFFFF; |
425 | uint32 width = *g_GraphicsInfo.VI_WIDTH_REG; |
426 | windowSetting.fViWidth = (end-start)*xscale; |
427 | if( abs((int)(windowSetting.fViWidth - width) ) < 8 ) |
428 | { |
429 | windowSetting.fViWidth = (float)width; |
430 | } |
431 | else |
432 | { |
433 | DebuggerAppendMsg("fViWidth = %f, Width Reg=%d", windowSetting.fViWidth, width); |
434 | } |
435 | |
436 | val = (*g_GraphicsInfo.VI_Y_SCALE_REG & 0xFFF);// - ((*g_GraphicsInfo.VI_Y_SCALE_REG>>16) & 0xFFF); |
437 | if( val == 0x3FF ) val = 0x400; |
438 | yscale = (float)val / (1<<10); |
439 | start = *g_GraphicsInfo.VI_V_START_REG >> 16; |
440 | end = *g_GraphicsInfo.VI_V_START_REG&0xFFFF; |
441 | windowSetting.fViHeight = (end-start)/2*yscale; |
442 | |
443 | if( yscale == 0 ) |
444 | { |
445 | windowSetting.fViHeight = windowSetting.fViWidth*status.fRatio; |
446 | } |
447 | else |
448 | { |
449 | if( *g_GraphicsInfo.VI_WIDTH_REG > 0x300 ) |
450 | windowSetting.fViHeight *= 2; |
451 | |
452 | if( windowSetting.fViWidth*status.fRatio > windowSetting.fViHeight && (*g_GraphicsInfo.VI_X_SCALE_REG & 0xFF) != 0 ) |
453 | { |
454 | if( abs(int(windowSetting.fViWidth*status.fRatio - windowSetting.fViHeight)) < 8 ) |
455 | { |
456 | windowSetting.fViHeight = windowSetting.fViWidth*status.fRatio; |
457 | } |
458 | /* |
459 | else |
460 | { |
461 | if( abs(windowSetting.fViWidth*status.fRatio-windowSetting.fViHeight) > windowSetting.fViWidth*0.1f ) |
462 | { |
463 | if( status.fRatio > 0.8 ) |
464 | windowSetting.fViHeight = windowSetting.fViWidth*3/4; |
465 | //windowSetting.fViHeight = (*g_GraphicsInfo.VI_V_SYNC_REG - 0x2C)/2; |
466 | } |
467 | } |
468 | */ |
469 | } |
470 | |
471 | if( windowSetting.fViHeight<100 || windowSetting.fViWidth<100 ) |
472 | { |
473 | //At sometime, value in VI_H_START_REG or VI_V_START_REG are 0 |
474 | windowSetting.fViWidth = (float)*g_GraphicsInfo.VI_WIDTH_REG; |
475 | windowSetting.fViHeight = windowSetting.fViWidth*status.fRatio; |
476 | } |
477 | } |
478 | |
479 | windowSetting.uViWidth = (unsigned short)(windowSetting.fViWidth/4); |
480 | windowSetting.fViWidth = windowSetting.uViWidth *= 4; |
481 | |
482 | windowSetting.uViHeight = (unsigned short)(windowSetting.fViHeight/4); |
483 | windowSetting.fViHeight = windowSetting.uViHeight *= 4; |
484 | uint16 optimizeHeight = (uint16)(windowSetting.uViWidth*status.fRatio); |
485 | optimizeHeight &= ~3; |
486 | |
487 | uint16 optimizeHeight2 = (uint16)(windowSetting.uViWidth*3/4); |
488 | optimizeHeight2 &= ~3; |
489 | |
490 | if( windowSetting.uViHeight != optimizeHeight && windowSetting.uViHeight != optimizeHeight2 ) |
491 | { |
492 | if( abs(windowSetting.uViHeight-optimizeHeight) <= 8 ) |
493 | windowSetting.fViHeight = windowSetting.uViHeight = optimizeHeight; |
494 | else if( abs(windowSetting.uViHeight-optimizeHeight2) <= 8 ) |
495 | windowSetting.fViHeight = windowSetting.uViHeight = optimizeHeight2; |
496 | } |
497 | |
498 | |
499 | if( gRDP.scissor.left == 0 && gRDP.scissor.top == 0 && gRDP.scissor.right != 0 ) |
500 | { |
501 | if( (*g_GraphicsInfo.VI_X_SCALE_REG & 0xFF) != 0x0 && gRDP.scissor.right == windowSetting.uViWidth ) |
502 | { |
503 | // Mario Tennis |
504 | if( abs(int( windowSetting.fViHeight - gRDP.scissor.bottom )) < 8 ) |
505 | { |
506 | windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom; |
507 | } |
508 | else if( windowSetting.fViHeight < gRDP.scissor.bottom ) |
509 | { |
510 | windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom; |
511 | } |
512 | windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom; |
513 | } |
514 | else if( gRDP.scissor.right == windowSetting.uViWidth - 1 && gRDP.scissor.bottom != 0 ) |
515 | { |
516 | if( windowSetting.uViHeight != optimizeHeight && windowSetting.uViHeight != optimizeHeight2 ) |
517 | { |
518 | if( status.fRatio != 0.75 && windowSetting.fViHeight > optimizeHeight/2 ) |
519 | { |
520 | windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom + gRDP.scissor.top + 1; |
521 | } |
522 | } |
523 | } |
524 | else if( gRDP.scissor.right == windowSetting.uViWidth && gRDP.scissor.bottom != 0 && status.fRatio != 0.75 ) |
525 | { |
526 | if( windowSetting.uViHeight != optimizeHeight && windowSetting.uViHeight != optimizeHeight2 ) |
527 | { |
528 | if( status.fRatio != 0.75 && windowSetting.fViHeight > optimizeHeight/2 ) |
529 | { |
530 | windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom + gRDP.scissor.top + 1; |
531 | } |
532 | } |
533 | } |
534 | } |
535 | } |
536 | SetScreenMult(windowSetting.uDisplayWidth/windowSetting.fViWidth, windowSetting.uDisplayHeight/windowSetting.fViHeight); |
537 | } |
538 | |
539 | void TriggerDPInterrupt(void) |
540 | { |
541 | *(g_GraphicsInfo.MI_INTR_REG) |= MI_INTR_DP; |
542 | g_GraphicsInfo.CheckInterrupts(); |
543 | } |
544 | |
545 | void TriggerSPInterrupt(void) |
546 | { |
547 | *(g_GraphicsInfo.MI_INTR_REG) |= MI_INTR_SP; |
548 | g_GraphicsInfo.CheckInterrupts(); |
549 | } |
550 | |
551 | void _VIDEO_DisplayTemporaryMessage(const char *Message) |
552 | { |
553 | } |
554 | |
555 | void DebugMessage(int level, const char *message, ...) |
556 | { |
557 | char msgbuf[1024]; |
558 | va_list args; |
559 | |
560 | if (l_DebugCallback == NULL) |
561 | return; |
562 | |
563 | va_start(args, message); |
564 | vsprintf(msgbuf, message, args); |
565 | |
566 | (*l_DebugCallback)(l_DebugCallContext, level, msgbuf); |
567 | |
568 | va_end(args); |
569 | } |
570 | |
571 | //--------------------------------------------------------------------------------------- |
572 | // Global functions, exported for use by the core library |
573 | |
574 | // since these functions are exported, they need to have C-style names |
575 | #ifdef __cplusplus |
576 | extern "C" { |
577 | #endif |
578 | |
579 | /* Mupen64Plus plugin functions */ |
580 | EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context, |
581 | void (*DebugCallback)(void *, int, const char *)) |
582 | { |
583 | if (l_PluginInit) |
584 | return M64ERR_ALREADY_INIT; |
585 | |
586 | /* first thing is to set the callback function for debug info */ |
587 | l_DebugCallback = DebugCallback; |
588 | l_DebugCallContext = Context; |
589 | |
590 | /* attach and call the CoreGetAPIVersions function, check Config and Video Extension API versions for compatibility */ |
591 | ptr_CoreGetAPIVersions CoreAPIVersionFunc; |
592 | CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreLibHandle, "CoreGetAPIVersions"); |
593 | if (CoreAPIVersionFunc == NULL) |
594 | { |
595 | DebugMessage(M64MSG_ERROR, "Core emulator broken; no CoreAPIVersionFunc() function found."); |
596 | return M64ERR_INCOMPATIBLE; |
597 | } |
598 | int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion; |
599 | (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL); |
600 | if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000)) |
601 | { |
602 | DebugMessage(M64MSG_ERROR, "Emulator core Config API (v%i.%i.%i) incompatible with plugin (v%i.%i.%i)", |
603 | VERSION_PRINTF_SPLIT(ConfigAPIVersion), VERSION_PRINTF_SPLIT(CONFIG_API_VERSION)); |
604 | return M64ERR_INCOMPATIBLE; |
605 | } |
606 | if ((VidextAPIVersion & 0xffff0000) != (VIDEXT_API_VERSION & 0xffff0000)) |
607 | { |
608 | DebugMessage(M64MSG_ERROR, "Emulator core Video Extension API (v%i.%i.%i) incompatible with plugin (v%i.%i.%i)", |
609 | VERSION_PRINTF_SPLIT(VidextAPIVersion), VERSION_PRINTF_SPLIT(VIDEXT_API_VERSION)); |
610 | return M64ERR_INCOMPATIBLE; |
611 | } |
612 | |
613 | /* Get the core config function pointers from the library handle */ |
614 | ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreLibHandle, "ConfigOpenSection"); |
615 | ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigSetParameter"); |
616 | ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParameter"); |
617 | ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultInt"); |
618 | ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultFloat"); |
619 | ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultBool"); |
620 | ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultString"); |
621 | ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamInt"); |
622 | ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamFloat"); |
623 | ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamBool"); |
624 | ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamString"); |
625 | |
626 | ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetSharedDataFilepath"); |
627 | ConfigGetUserConfigPath = (ptr_ConfigGetUserConfigPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserConfigPath"); |
628 | ConfigGetUserDataPath = (ptr_ConfigGetUserDataPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserDataPath"); |
629 | ConfigGetUserCachePath = (ptr_ConfigGetUserCachePath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserCachePath"); |
630 | |
631 | if (!ConfigOpenSection || !ConfigSetParameter || !ConfigGetParameter || |
632 | !ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString || |
633 | !ConfigGetParamInt || !ConfigGetParamFloat || !ConfigGetParamBool || !ConfigGetParamString || |
634 | !ConfigGetSharedDataFilepath || !ConfigGetUserConfigPath || !ConfigGetUserDataPath || !ConfigGetUserCachePath) |
635 | { |
636 | DebugMessage(M64MSG_ERROR, "Couldn't connect to Core configuration functions"); |
637 | return M64ERR_INCOMPATIBLE; |
638 | } |
639 | |
640 | /* Get the core Video Extension function pointers from the library handle */ |
641 | CoreVideo_Init = (ptr_VidExt_Init) osal_dynlib_getproc(CoreLibHandle, "VidExt_Init"); |
642 | CoreVideo_Quit = (ptr_VidExt_Quit) osal_dynlib_getproc(CoreLibHandle, "VidExt_Quit"); |
643 | CoreVideo_ListFullscreenModes = (ptr_VidExt_ListFullscreenModes) osal_dynlib_getproc(CoreLibHandle, "VidExt_ListFullscreenModes"); |
644 | CoreVideo_SetVideoMode = (ptr_VidExt_SetVideoMode) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetVideoMode"); |
645 | CoreVideo_SetCaption = (ptr_VidExt_SetCaption) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetCaption"); |
646 | CoreVideo_ToggleFullScreen = (ptr_VidExt_ToggleFullScreen) osal_dynlib_getproc(CoreLibHandle, "VidExt_ToggleFullScreen"); |
647 | CoreVideo_ResizeWindow = (ptr_VidExt_ResizeWindow) osal_dynlib_getproc(CoreLibHandle, "VidExt_ResizeWindow"); |
648 | CoreVideo_GL_GetProcAddress = (ptr_VidExt_GL_GetProcAddress) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_GetProcAddress"); |
649 | CoreVideo_GL_SetAttribute = (ptr_VidExt_GL_SetAttribute) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SetAttribute"); |
650 | CoreVideo_GL_GetAttribute = (ptr_VidExt_GL_GetAttribute) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_GetAttribute"); |
651 | CoreVideo_GL_SwapBuffers = (ptr_VidExt_GL_SwapBuffers) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SwapBuffers"); |
652 | |
653 | if (!CoreVideo_Init || !CoreVideo_Quit || !CoreVideo_ListFullscreenModes || !CoreVideo_SetVideoMode || |
654 | !CoreVideo_ResizeWindow || !CoreVideo_SetCaption || !CoreVideo_ToggleFullScreen || !CoreVideo_GL_GetProcAddress || |
655 | !CoreVideo_GL_SetAttribute || !CoreVideo_GL_GetAttribute || !CoreVideo_GL_SwapBuffers) |
656 | { |
657 | DebugMessage(M64MSG_ERROR, "Couldn't connect to Core video extension functions"); |
658 | return M64ERR_INCOMPATIBLE; |
659 | } |
660 | |
661 | /* open config section handles and set parameter default values */ |
662 | if (!InitConfiguration()) |
663 | return M64ERR_INTERNAL; |
664 | |
665 | l_PluginInit = 1; |
666 | return M64ERR_SUCCESS; |
667 | } |
668 | |
669 | EXPORT m64p_error CALL PluginShutdown(void) |
670 | { |
671 | if (!l_PluginInit) |
672 | return M64ERR_NOT_INIT; |
673 | |
674 | if( status.bGameIsRunning ) |
675 | { |
676 | RomClosed(); |
677 | } |
678 | if (bIniIsChanged) |
679 | { |
680 | WriteIniFile(); |
681 | TRACE0("Write back INI file"); |
682 | } |
683 | |
684 | /* reset some local variables */ |
685 | l_DebugCallback = NULL; |
686 | l_DebugCallContext = NULL; |
687 | |
688 | l_PluginInit = 0; |
689 | return M64ERR_SUCCESS; |
690 | } |
691 | |
692 | EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities) |
693 | { |
694 | /* set version info */ |
695 | if (PluginType != NULL) |
696 | *PluginType = M64PLUGIN_GFX; |
697 | |
698 | if (PluginVersion != NULL) |
699 | *PluginVersion = PLUGIN_VERSION; |
700 | |
701 | if (APIVersion != NULL) |
702 | *APIVersion = VIDEO_PLUGIN_API_VERSION; |
703 | |
704 | if (PluginNamePtr != NULL) |
705 | *PluginNamePtr = PLUGIN_NAME; |
706 | |
707 | if (Capabilities != NULL) |
708 | { |
709 | *Capabilities = 0; |
710 | } |
711 | |
712 | return M64ERR_SUCCESS; |
713 | } |
714 | |
715 | //------------------------------------------------------------------------------------- |
716 | |
717 | |
718 | EXPORT void CALL ChangeWindow (void) |
719 | { |
720 | if( status.ToToggleFullScreen ) |
721 | status.ToToggleFullScreen = FALSE; |
722 | else |
723 | status.ToToggleFullScreen = TRUE; |
724 | } |
725 | |
726 | //--------------------------------------------------------------------------------------- |
727 | |
728 | EXPORT void CALL MoveScreen (int xpos, int ypos) |
729 | { |
730 | } |
731 | |
732 | //--------------------------------------------------------------------------------------- |
733 | EXPORT void CALL RomClosed(void) |
734 | { |
735 | TRACE0("To stop video"); |
736 | Ini_StoreRomOptions(&g_curRomInfo); |
737 | StopVideo(); |
738 | TRACE0("Video is stopped"); |
739 | } |
740 | |
741 | EXPORT int CALL RomOpen(void) |
742 | { |
743 | /* Read RiceVideoLinux.ini file, set up internal variables by reading values from core configuration API */ |
744 | LoadConfiguration(); |
745 | |
746 | if( g_CritialSection.IsLocked() ) |
747 | { |
748 | g_CritialSection.Unlock(); |
749 | TRACE0("g_CritialSection is locked when game is starting, unlock it now."); |
750 | } |
751 | status.bDisableFPS=false; |
752 | |
753 | g_dwRamSize = 0x800000; |
754 | |
755 | #ifdef DEBUGGER |
756 | if( debuggerPause ) |
757 | { |
758 | debuggerPause = FALSE; |
759 | usleep(100 * 1000); |
760 | } |
761 | #endif |
762 | |
763 | if (!StartVideo()) |
764 | return 0; |
765 | |
766 | return 1; |
767 | } |
768 | |
769 | |
770 | //--------------------------------------------------------------------------------------- |
771 | EXPORT void CALL UpdateScreen(void) |
772 | { |
773 | if(options.bShowFPS) |
774 | { |
775 | static unsigned int lastTick=0; |
776 | static int frames=0; |
777 | unsigned int nowTick = SDL_GetTicks(); |
778 | frames++; |
779 | if(lastTick + 5000 <= nowTick) |
780 | { |
781 | char caption[200]; |
782 | sprintf(caption, "%s v%i.%i.%i - %.3f VI/S", PLUGIN_NAME, VERSION_PRINTF_SPLIT(PLUGIN_VERSION), frames/5.0); |
783 | CoreVideo_SetCaption(caption); |
784 | frames = 0; |
785 | lastTick = nowTick; |
786 | } |
787 | } |
788 | UpdateScreenStep2(); |
789 | } |
790 | |
791 | //--------------------------------------------------------------------------------------- |
792 | |
793 | EXPORT void CALL ViStatusChanged(void) |
794 | { |
795 | g_CritialSection.Lock(); |
796 | SetVIScales(); |
797 | CRender::g_pRender->UpdateClipRectangle(); |
798 | g_CritialSection.Unlock(); |
799 | } |
800 | |
801 | //--------------------------------------------------------------------------------------- |
802 | EXPORT void CALL ViWidthChanged(void) |
803 | { |
804 | g_CritialSection.Lock(); |
805 | SetVIScales(); |
806 | CRender::g_pRender->UpdateClipRectangle(); |
807 | g_CritialSection.Unlock(); |
808 | } |
809 | |
810 | EXPORT int CALL InitiateGFX(GFX_INFO Gfx_Info) |
811 | { |
812 | memset(&status, 0, sizeof(status)); |
813 | memcpy(&g_GraphicsInfo, &Gfx_Info, sizeof(GFX_INFO)); |
814 | |
815 | g_pRDRAMu8 = Gfx_Info.RDRAM; |
816 | g_pRDRAMu32 = (uint32*)Gfx_Info.RDRAM; |
817 | g_pRDRAMs8 = (signed char *)Gfx_Info.RDRAM; |
818 | |
819 | windowSetting.fViWidth = 320; |
820 | windowSetting.fViHeight = 240; |
821 | status.ToToggleFullScreen = FALSE; |
822 | status.ToResize = false; |
823 | status.bDisableFPS=false; |
824 | |
825 | if (!InitConfiguration()) |
826 | { |
827 | DebugMessage(M64MSG_ERROR, "Failed to read configuration data"); |
828 | return FALSE; |
829 | } |
830 | |
831 | CGraphicsContext::InitWindowInfo(); |
832 | CGraphicsContext::InitDeviceParameters(); |
833 | |
834 | return(TRUE); |
835 | } |
836 | |
837 | EXPORT void CALL ResizeVideoOutput(int width, int height) |
838 | { |
839 | // save the new window resolution. actual resizing operation is asynchronous (it happens later) |
840 | status.gNewResizeWidth = width; |
841 | status.gNewResizeHeight = height; |
842 | status.ToResize = true; |
843 | } |
844 | |
845 | //--------------------------------------------------------------------------------------- |
846 | |
847 | EXPORT void CALL ProcessRDPList(void) |
848 | { |
849 | try |
850 | { |
851 | RDP_DLParser_Process(); |
852 | } |
853 | catch (...) |
854 | { |
855 | TRACE0("Unknown Error in ProcessRDPList"); |
856 | TriggerDPInterrupt(); |
857 | TriggerSPInterrupt(); |
858 | } |
859 | } |
860 | |
861 | EXPORT void CALL ProcessDList(void) |
862 | { |
863 | ProcessDListStep2(); |
864 | } |
865 | |
866 | //--------------------------------------------------------------------------------------- |
867 | |
868 | /****************************************************************** |
869 | Function: FrameBufferRead |
870 | Purpose: This function is called to notify the dll that the |
871 | frame buffer memory is beening read at the given address. |
872 | DLL should copy content from its render buffer to the frame buffer |
873 | in N64 RDRAM |
874 | DLL is responsible to maintain its own frame buffer memory addr list |
875 | DLL should copy 4KB block content back to RDRAM frame buffer. |
876 | Emulator should not call this function again if other memory |
877 | is read within the same 4KB range |
878 | |
879 | Since depth buffer is also being watched, the reported addr |
880 | may belong to depth buffer |
881 | input: addr rdram address |
882 | val val |
883 | size 1 = uint8, 2 = uint16, 4 = uint32 |
884 | output: none |
885 | *******************************************************************/ |
886 | |
887 | EXPORT void CALL FBRead(uint32 addr) |
888 | { |
889 | g_pFrameBufferManager->FrameBufferReadByCPU(addr); |
890 | } |
891 | |
892 | |
893 | /****************************************************************** |
894 | Function: FrameBufferWrite |
895 | Purpose: This function is called to notify the dll that the |
896 | frame buffer has been modified by CPU at the given address. |
897 | |
898 | Since depth buffer is also being watched, the reported addr |
899 | may belong to depth buffer |
900 | |
901 | input: addr rdram address |
902 | val val |
903 | size 1 = uint8, 2 = uint16, 4 = uint32 |
904 | output: none |
905 | *******************************************************************/ |
906 | |
907 | EXPORT void CALL FBWrite(uint32 addr, uint32 size) |
908 | { |
909 | g_pFrameBufferManager->FrameBufferWriteByCPU(addr, size); |
910 | } |
911 | |
912 | /************************************************************************ |
913 | Function: FBGetFrameBufferInfo |
914 | Purpose: This function is called by the emulator core to retrieve frame |
915 | buffer information from the video plugin in order to be able |
916 | to notify the video plugin about CPU frame buffer read/write |
917 | operations |
918 | |
919 | size: |
920 | = 1 byte |
921 | = 2 word (16 bit) <-- this is N64 default depth buffer format |
922 | = 4 dword (32 bit) |
923 | |
924 | when frame buffer information is not available yet, set all values |
925 | in the FrameBufferInfo structure to 0 |
926 | |
927 | input: FrameBufferInfo pinfo[6] |
928 | pinfo is pointed to a FrameBufferInfo structure which to be |
929 | filled in by this function |
930 | output: Values are return in the FrameBufferInfo structure |
931 | Plugin can return up to 6 frame buffer info |
932 | ************************************************************************/ |
933 | |
934 | EXPORT void CALL FBGetFrameBufferInfo(void *p) |
935 | { |
936 | FrameBufferInfo * pinfo = (FrameBufferInfo *)p; |
937 | memset(pinfo,0,sizeof(FrameBufferInfo)*6); |
938 | |
939 | //if( g_ZI.dwAddr == 0 ) |
940 | //{ |
941 | // memset(pinfo,0,sizeof(FrameBufferInfo)*6); |
942 | //} |
943 | //else |
944 | { |
945 | for (int i=0; i<5; i++ ) |
946 | { |
947 | if( status.gDlistCount-g_RecentCIInfo[i].lastUsedFrame > 30 || g_RecentCIInfo[i].lastUsedFrame == 0 ) |
948 | { |
949 | //memset(&pinfo[i],0,sizeof(FrameBufferInfo)); |
950 | } |
951 | else |
952 | { |
953 | pinfo[i].addr = g_RecentCIInfo[i].dwAddr; |
954 | pinfo[i].size = 2; |
955 | pinfo[i].width = g_RecentCIInfo[i].dwWidth; |
956 | pinfo[i].height = g_RecentCIInfo[i].dwHeight; |
957 | TXTRBUF_DETAIL_DUMP(TRACE3("Protect 0x%08X (%d,%d)", g_RecentCIInfo[i].dwAddr, g_RecentCIInfo[i].dwWidth, g_RecentCIInfo[i].dwHeight)); |
958 | pinfo[5].width = g_RecentCIInfo[i].dwWidth; |
959 | pinfo[5].height = g_RecentCIInfo[i].dwHeight; |
960 | } |
961 | } |
962 | |
963 | pinfo[5].addr = g_ZI.dwAddr; |
964 | //pinfo->size = g_RecentCIInfo[5].dwSize; |
965 | pinfo[5].size = 2; |
966 | TXTRBUF_DETAIL_DUMP(TRACE3("Protect 0x%08X (%d,%d)", pinfo[5].addr, pinfo[5].width, pinfo[5].height)); |
967 | } |
968 | } |
969 | |
970 | // Plugin spec 1.3 functions |
971 | EXPORT void CALL ShowCFB(void) |
972 | { |
973 | status.toShowCFB = true; |
974 | } |
975 | |
976 | //void ReadScreen2( void *dest, int *width, int *height, int bFront ) |
977 | EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int bFront) |
978 | { |
979 | if (width == NULL || height == NULL) |
980 | return; |
981 | |
982 | *width = windowSetting.uDisplayWidth; |
983 | *height = windowSetting.uDisplayHeight; |
984 | |
985 | if (dest == NULL) |
986 | return; |
987 | |
988 | #if SDL_VIDEO_OPENGL |
989 | #ifndef HAVE_GLES |
990 | //*TODO*, what's the use of this function ? *SEB* |
991 | GLint oldMode; |
992 | glGetIntegerv( GL_READ_BUFFER, &oldMode ); |
993 | if (bFront) |
994 | glReadBuffer( GL_FRONT ); |
995 | else |
996 | glReadBuffer( GL_BACK ); |
997 | glReadPixels( 0, 0, windowSetting.uDisplayWidth, windowSetting.uDisplayHeight, |
998 | GL_RGB, GL_UNSIGNED_BYTE, dest ); |
999 | glReadBuffer( oldMode ); |
1000 | #endif |
1001 | #endif |
1002 | } |
1003 | |
1004 | |
1005 | EXPORT void CALL SetRenderingCallback(void (*callback)(int)) |
1006 | { |
1007 | renderCallback = callback; |
1008 | } |
1009 | |
1010 | #ifdef __cplusplus |
1011 | } |
1012 | #endif |
1013 | |