2 Copyright (C) 2002 Rice1964
3 Copyright (C) 2009-2011 Richard Goedeken
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.
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.
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.
25 #include "osal_opengl.h"
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"
35 #include "DeviceBuilder.h"
36 #include "FrameBuffer.h"
37 #include "GraphicsContext.h"
39 #include "RSP_Parser.h"
40 #include "TextureFilters.h"
41 #include "TextureManager.h"
45 //=======================================================
48 static void (*l_DebugCallback)(void *, int, const char *) = NULL;
49 static void *l_DebugCallContext = NULL;
50 static int l_PluginInit = 0;
52 //=======================================================
56 GFX_INFO g_GraphicsInfo;
57 CCritSect g_CritialSection;
59 unsigned int g_dwRamSize = 0x400000;
60 unsigned int *g_pRDRAMu32 = NULL;
61 signed char *g_pRDRAMs8 = NULL;
62 unsigned char *g_pRDRAMu8 = NULL;
64 RECT frameWriteByCPURect;
65 std::vector<RECT> frameWriteByCPURects;
66 RECT frameWriteByCPURectArray[20][20];
67 bool frameWriteByCPURectFlag[20][20];
68 std::vector<uint32> frameWriteRecord;
70 void (*renderCallback)(int) = NULL;
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;
86 ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL;
87 ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL;
88 ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL;
89 ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL;
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;
104 //---------------------------------------------------------------------------------------
105 // Forward function declarations
107 extern "C" EXPORT void CALL RomClosed(void);
109 //---------------------------------------------------------------------------------------
110 // Static (local) functions
111 static void ChangeWindowStep2()
113 status.bDisableFPS = true;
114 windowSetting.bDisplayFullscreen = !windowSetting.bDisplayFullscreen;
115 g_CritialSection.Lock();
116 windowSetting.bDisplayFullscreen = CGraphicsContext::Get()->ToggleFullscreen();
118 CGraphicsContext::Get()->Clear(CLEAR_COLOR_AND_DEPTH_BUFFER);
119 CGraphicsContext::Get()->UpdateFrame();
120 CGraphicsContext::Get()->Clear(CLEAR_COLOR_AND_DEPTH_BUFFER);
121 CGraphicsContext::Get()->UpdateFrame();
122 CGraphicsContext::Get()->Clear(CLEAR_COLOR_AND_DEPTH_BUFFER);
123 CGraphicsContext::Get()->UpdateFrame();
124 g_CritialSection.Unlock();
125 status.bDisableFPS = false;
126 status.ToToggleFullScreen = FALSE;
129 static void ResizeStep2(void)
131 g_CritialSection.Lock();
133 // Delete all OpenGL textures
134 gTextureManager.CleanUp();
136 // delete our opengl renderer
137 CDeviceBuilder::GetBuilder()->DeleteRender();
139 // call video extension function with updated width, height (this creates a new OpenGL context)
140 windowSetting.uDisplayWidth = status.gNewResizeWidth;
141 windowSetting.uDisplayHeight = status.gNewResizeHeight;
142 CoreVideo_ResizeWindow(windowSetting.uDisplayWidth, windowSetting.uDisplayHeight);
144 // re-initialize our OpenGL graphics context state
145 bool res = CGraphicsContext::Get()->ResizeInitialize(windowSetting.uDisplayWidth, windowSetting.uDisplayHeight, !windowSetting.bDisplayFullscreen);
148 // re-create the OpenGL renderer
149 CDeviceBuilder::GetBuilder()->CreateRender();
150 CRender::GetRender()->Initialize();
154 g_CritialSection.Unlock();
155 status.ToResize = false;
158 static void UpdateScreenStep2 (void)
160 status.bVIOriginIsUpdated = false;
162 if( status.ToToggleFullScreen && status.gDlistCount > 0 )
167 if (status.ToResize && status.gDlistCount > 0)
173 g_CritialSection.Lock();
174 if( status.bHandleN64RenderTexture )
175 g_pFrameBufferManager->CloseRenderTexture(true);
177 g_pFrameBufferManager->SetAddrBeDisplayed(*g_GraphicsInfo.VI_ORIGIN_REG);
179 if( status.gDlistCount == 0 )
181 // CPU frame buffer update
182 uint32 width = *g_GraphicsInfo.VI_WIDTH_REG;
183 if( (*g_GraphicsInfo.VI_ORIGIN_REG & (g_dwRamSize-1) ) > width*2 && *g_GraphicsInfo.VI_H_START_REG != 0 && width != 0 )
186 CRender::GetRender()->DrawFrameBuffer(true);
187 CGraphicsContext::Get()->UpdateFrame();
189 g_CritialSection.Unlock();
193 TXTRBUF_DETAIL_DUMP(TRACE1("VI ORIG is updated to %08X", *g_GraphicsInfo.VI_ORIGIN_REG));
195 if( currentRomOptions.screenUpdateSetting == SCREEN_UPDATE_AT_VI_UPDATE )
197 CGraphicsContext::Get()->UpdateFrame();
199 DEBUGGER_IF_DUMP( pauseAtNext, TRACE1("Update Screen: VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG));
200 DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_FRAME);
201 DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_SET_CIMG);
202 g_CritialSection.Unlock();
206 TXTRBUF_DETAIL_DUMP(TRACE1("VI ORIG is updated to %08X", *g_GraphicsInfo.VI_ORIGIN_REG));
208 if( currentRomOptions.screenUpdateSetting == SCREEN_UPDATE_AT_VI_UPDATE_AND_DRAWN )
210 if( status.bScreenIsDrawn )
212 CGraphicsContext::Get()->UpdateFrame();
213 DEBUGGER_IF_DUMP( pauseAtNext, TRACE1("Update Screen: VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG));
217 DEBUGGER_IF_DUMP( pauseAtNext, TRACE1("Skip Screen Update: VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG));
220 DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_FRAME);
221 DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_SET_CIMG);
222 g_CritialSection.Unlock();
226 if( currentRomOptions.screenUpdateSetting==SCREEN_UPDATE_AT_VI_CHANGE )
229 if( *g_GraphicsInfo.VI_ORIGIN_REG != status.curVIOriginReg )
231 if( *g_GraphicsInfo.VI_ORIGIN_REG < status.curDisplayBuffer || *g_GraphicsInfo.VI_ORIGIN_REG > status.curDisplayBuffer+0x2000 )
233 status.curDisplayBuffer = *g_GraphicsInfo.VI_ORIGIN_REG;
234 status.curVIOriginReg = status.curDisplayBuffer;
235 //status.curRenderBuffer = NULL;
237 CGraphicsContext::Get()->UpdateFrame();
238 DEBUGGER_IF_DUMP( pauseAtNext, TRACE1("Update Screen: VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG));
239 DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_FRAME);
240 DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_SET_CIMG);
244 status.curDisplayBuffer = *g_GraphicsInfo.VI_ORIGIN_REG;
245 status.curVIOriginReg = status.curDisplayBuffer;
246 DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_FRAME, {DebuggerAppendMsg("Skip Screen Update, closed to the display buffer, VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG);});
251 DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_FRAME, {DebuggerAppendMsg("Skip Screen Update, the same VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG);});
254 g_CritialSection.Unlock();
258 if( currentRomOptions.screenUpdateSetting >= SCREEN_UPDATE_AT_1ST_CI_CHANGE )
260 status.bVIOriginIsUpdated=true;
261 DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_FRAME, {DebuggerAppendMsg("VI ORIG is updated to %08X", *g_GraphicsInfo.VI_ORIGIN_REG);});
262 g_CritialSection.Unlock();
266 DEBUGGER_IF_DUMP( pauseAtNext, TRACE1("VI is updated, No screen update: VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG));
267 DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_FRAME);
268 DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_SET_CIMG);
270 g_CritialSection.Unlock();
273 static void ProcessDListStep2(void)
275 g_CritialSection.Lock();
276 if( status.toShowCFB )
278 CRender::GetRender()->DrawFrameBuffer(true);
279 status.toShowCFB = false;
284 DLParser_Process((OSTask *)(g_GraphicsInfo.DMEM + 0x0FC0));
288 TRACE0("Unknown Error in ProcessDList");
289 TriggerDPInterrupt();
290 TriggerSPInterrupt();
293 g_CritialSection.Unlock();
296 static bool StartVideo(void)
298 windowSetting.dps = windowSetting.fps = -1;
299 windowSetting.lastSecDlistCount = windowSetting.lastSecFrameCount = 0xFFFFFFFF;
301 g_CritialSection.Lock();
303 memcpy(&g_curRomInfo.romheader, g_GraphicsInfo.HEADER, sizeof(ROMHeader));
304 unsigned char *puc = (unsigned char *) &g_curRomInfo.romheader;
307 for (i = 0; i < sizeof(ROMHeader); i += 4) /* byte-swap the ROM header */
317 ROM_GetRomNameFromHeader(g_curRomInfo.szGameName, &g_curRomInfo.romheader);
318 Ini_GetRomOptions(&g_curRomInfo);
319 char *p = (char *) g_curRomInfo.szGameName + (strlen((char *) g_curRomInfo.szGameName) -1); // -1 to skip null
320 while (p >= (char *) g_curRomInfo.szGameName)
322 if( *p == ':' || *p == '\\' || *p == '/' )
327 GenerateCurrentRomOptions();
328 status.dwTvSystem = CountryCodeToTVSystem(g_curRomInfo.romheader.nCountryID);
329 if( status.dwTvSystem == TV_SYSTEM_NTSC )
330 status.fRatio = 0.75f;
332 status.fRatio = 9/11.0f;;
334 InitExternalTextures();
337 CDeviceBuilder::GetBuilder()->CreateGraphicsContext();
338 CGraphicsContext::InitWindowInfo();
340 bool res = CGraphicsContext::Get()->Initialize(640, 480, !windowSetting.bDisplayFullscreen);
343 g_CritialSection.Unlock();
346 CDeviceBuilder::GetBuilder()->CreateRender();
347 CRender::GetRender()->Initialize();
349 status.bGameIsRunning = true;
353 DebugMessage(M64MSG_ERROR, "Exception caught while starting video renderer");
357 g_CritialSection.Unlock();
361 static void StopVideo()
363 g_CritialSection.Lock();
364 status.bGameIsRunning = false;
367 CloseExternalTextures();
369 // Kill all textures?
370 gTextureManager.RecycleAllTextures();
371 gTextureManager.CleanUp();
374 CDeviceBuilder::GetBuilder()->DeleteRender();
375 CGraphicsContext::Get()->CleanUp();
376 CDeviceBuilder::GetBuilder()->DeleteGraphicsContext();
380 TRACE0("Some exceptions during RomClosed");
383 g_CritialSection.Unlock();
384 windowSetting.dps = windowSetting.fps = -1;
385 windowSetting.lastSecDlistCount = windowSetting.lastSecFrameCount = 0xFFFFFFFF;
386 status.gDlistCount = status.gFrameCount = 0;
390 //---------------------------------------------------------------------------------------
391 // Global functions, for use by other source files in this plugin
395 if( g_curRomInfo.VIHeight>0 && g_curRomInfo.VIWidth>0 )
397 windowSetting.fViWidth = windowSetting.uViWidth = g_curRomInfo.VIWidth;
398 windowSetting.fViHeight = windowSetting.uViHeight = g_curRomInfo.VIHeight;
400 else if( g_curRomInfo.UseCIWidthAndRatio && g_CI.dwWidth )
402 windowSetting.fViWidth = windowSetting.uViWidth = g_CI.dwWidth;
403 windowSetting.fViHeight = windowSetting.uViHeight =
404 g_curRomInfo.UseCIWidthAndRatio == USE_CI_WIDTH_AND_RATIO_FOR_NTSC ? g_CI.dwWidth/4*3 : g_CI.dwWidth/11*9;
408 float xscale, yscale;
409 uint32 val = *g_GraphicsInfo.VI_X_SCALE_REG & 0xFFF;
410 xscale = (float)val / (1<<10);
411 uint32 start = *g_GraphicsInfo.VI_H_START_REG >> 16;
412 uint32 end = *g_GraphicsInfo.VI_H_START_REG&0xFFFF;
413 uint32 width = *g_GraphicsInfo.VI_WIDTH_REG;
414 windowSetting.fViWidth = (end-start)*xscale;
415 if( abs((int)(windowSetting.fViWidth - width) ) < 8 )
417 windowSetting.fViWidth = (float)width;
421 DebuggerAppendMsg("fViWidth = %f, Width Reg=%d", windowSetting.fViWidth, width);
424 val = (*g_GraphicsInfo.VI_Y_SCALE_REG & 0xFFF);// - ((*g_GraphicsInfo.VI_Y_SCALE_REG>>16) & 0xFFF);
425 if( val == 0x3FF ) val = 0x400;
426 yscale = (float)val / (1<<10);
427 start = *g_GraphicsInfo.VI_V_START_REG >> 16;
428 end = *g_GraphicsInfo.VI_V_START_REG&0xFFFF;
429 windowSetting.fViHeight = (end-start)/2*yscale;
433 windowSetting.fViHeight = windowSetting.fViWidth*status.fRatio;
437 if( *g_GraphicsInfo.VI_WIDTH_REG > 0x300 )
438 windowSetting.fViHeight *= 2;
440 if( windowSetting.fViWidth*status.fRatio > windowSetting.fViHeight && (*g_GraphicsInfo.VI_X_SCALE_REG & 0xFF) != 0 )
442 if( abs(int(windowSetting.fViWidth*status.fRatio - windowSetting.fViHeight)) < 8 )
444 windowSetting.fViHeight = windowSetting.fViWidth*status.fRatio;
449 if( abs(windowSetting.fViWidth*status.fRatio-windowSetting.fViHeight) > windowSetting.fViWidth*0.1f )
451 if( status.fRatio > 0.8 )
452 windowSetting.fViHeight = windowSetting.fViWidth*3/4;
453 //windowSetting.fViHeight = (*g_GraphicsInfo.VI_V_SYNC_REG - 0x2C)/2;
459 if( windowSetting.fViHeight<100 || windowSetting.fViWidth<100 )
461 //At sometime, value in VI_H_START_REG or VI_V_START_REG are 0
462 windowSetting.fViWidth = (float)*g_GraphicsInfo.VI_WIDTH_REG;
463 windowSetting.fViHeight = windowSetting.fViWidth*status.fRatio;
467 windowSetting.uViWidth = (unsigned short)(windowSetting.fViWidth/4);
468 windowSetting.fViWidth = windowSetting.uViWidth *= 4;
470 windowSetting.uViHeight = (unsigned short)(windowSetting.fViHeight/4);
471 windowSetting.fViHeight = windowSetting.uViHeight *= 4;
472 uint16 optimizeHeight = (uint16)(windowSetting.uViWidth*status.fRatio);
473 optimizeHeight &= ~3;
475 uint16 optimizeHeight2 = (uint16)(windowSetting.uViWidth*3/4);
476 optimizeHeight2 &= ~3;
478 if( windowSetting.uViHeight != optimizeHeight && windowSetting.uViHeight != optimizeHeight2 )
480 if( abs(windowSetting.uViHeight-optimizeHeight) <= 8 )
481 windowSetting.fViHeight = windowSetting.uViHeight = optimizeHeight;
482 else if( abs(windowSetting.uViHeight-optimizeHeight2) <= 8 )
483 windowSetting.fViHeight = windowSetting.uViHeight = optimizeHeight2;
487 if( gRDP.scissor.left == 0 && gRDP.scissor.top == 0 && gRDP.scissor.right != 0 )
489 if( (*g_GraphicsInfo.VI_X_SCALE_REG & 0xFF) != 0x0 && gRDP.scissor.right == windowSetting.uViWidth )
492 if( abs(int( windowSetting.fViHeight - gRDP.scissor.bottom )) < 8 )
494 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom;
496 else if( windowSetting.fViHeight < gRDP.scissor.bottom )
498 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom;
500 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom;
502 else if( gRDP.scissor.right == windowSetting.uViWidth - 1 && gRDP.scissor.bottom != 0 )
504 if( windowSetting.uViHeight != optimizeHeight && windowSetting.uViHeight != optimizeHeight2 )
506 if( status.fRatio != 0.75 && windowSetting.fViHeight > optimizeHeight/2 )
508 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom + gRDP.scissor.top + 1;
512 else if( gRDP.scissor.right == windowSetting.uViWidth && gRDP.scissor.bottom != 0 && status.fRatio != 0.75 )
514 if( windowSetting.uViHeight != optimizeHeight && windowSetting.uViHeight != optimizeHeight2 )
516 if( status.fRatio != 0.75 && windowSetting.fViHeight > optimizeHeight/2 )
518 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom + gRDP.scissor.top + 1;
524 SetScreenMult(windowSetting.uDisplayWidth/windowSetting.fViWidth, windowSetting.uDisplayHeight/windowSetting.fViHeight);
527 void TriggerDPInterrupt(void)
529 *(g_GraphicsInfo.MI_INTR_REG) |= MI_INTR_DP;
530 g_GraphicsInfo.CheckInterrupts();
533 void TriggerSPInterrupt(void)
535 *(g_GraphicsInfo.MI_INTR_REG) |= MI_INTR_SP;
536 g_GraphicsInfo.CheckInterrupts();
539 void _VIDEO_DisplayTemporaryMessage(const char *Message)
543 void DebugMessage(int level, const char *message, ...)
548 if (l_DebugCallback == NULL)
551 va_start(args, message);
552 vsprintf(msgbuf, message, args);
554 (*l_DebugCallback)(l_DebugCallContext, level, msgbuf);
559 //---------------------------------------------------------------------------------------
560 // Global functions, exported for use by the core library
562 // since these functions are exported, they need to have C-style names
567 /* Mupen64Plus plugin functions */
568 EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
569 void (*DebugCallback)(void *, int, const char *))
572 return M64ERR_ALREADY_INIT;
574 /* first thing is to set the callback function for debug info */
575 l_DebugCallback = DebugCallback;
576 l_DebugCallContext = Context;
578 /* attach and call the CoreGetAPIVersions function, check Config and Video Extension API versions for compatibility */
579 ptr_CoreGetAPIVersions CoreAPIVersionFunc;
580 CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreLibHandle, "CoreGetAPIVersions");
581 if (CoreAPIVersionFunc == NULL)
583 DebugMessage(M64MSG_ERROR, "Core emulator broken; no CoreAPIVersionFunc() function found.");
584 return M64ERR_INCOMPATIBLE;
586 int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
587 (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL);
588 if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000))
590 DebugMessage(M64MSG_ERROR, "Emulator core Config API (v%i.%i.%i) incompatible with plugin (v%i.%i.%i)",
591 VERSION_PRINTF_SPLIT(ConfigAPIVersion), VERSION_PRINTF_SPLIT(CONFIG_API_VERSION));
592 return M64ERR_INCOMPATIBLE;
594 if ((VidextAPIVersion & 0xffff0000) != (VIDEXT_API_VERSION & 0xffff0000))
596 DebugMessage(M64MSG_ERROR, "Emulator core Video Extension API (v%i.%i.%i) incompatible with plugin (v%i.%i.%i)",
597 VERSION_PRINTF_SPLIT(VidextAPIVersion), VERSION_PRINTF_SPLIT(VIDEXT_API_VERSION));
598 return M64ERR_INCOMPATIBLE;
601 /* Get the core config function pointers from the library handle */
602 ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreLibHandle, "ConfigOpenSection");
603 ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigSetParameter");
604 ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParameter");
605 ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultInt");
606 ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultFloat");
607 ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultBool");
608 ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultString");
609 ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamInt");
610 ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamFloat");
611 ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamBool");
612 ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamString");
614 ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetSharedDataFilepath");
615 ConfigGetUserConfigPath = (ptr_ConfigGetUserConfigPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserConfigPath");
616 ConfigGetUserDataPath = (ptr_ConfigGetUserDataPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserDataPath");
617 ConfigGetUserCachePath = (ptr_ConfigGetUserCachePath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserCachePath");
619 if (!ConfigOpenSection || !ConfigSetParameter || !ConfigGetParameter ||
620 !ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString ||
621 !ConfigGetParamInt || !ConfigGetParamFloat || !ConfigGetParamBool || !ConfigGetParamString ||
622 !ConfigGetSharedDataFilepath || !ConfigGetUserConfigPath || !ConfigGetUserDataPath || !ConfigGetUserCachePath)
624 DebugMessage(M64MSG_ERROR, "Couldn't connect to Core configuration functions");
625 return M64ERR_INCOMPATIBLE;
628 /* Get the core Video Extension function pointers from the library handle */
629 CoreVideo_Init = (ptr_VidExt_Init) osal_dynlib_getproc(CoreLibHandle, "VidExt_Init");
630 CoreVideo_Quit = (ptr_VidExt_Quit) osal_dynlib_getproc(CoreLibHandle, "VidExt_Quit");
631 CoreVideo_ListFullscreenModes = (ptr_VidExt_ListFullscreenModes) osal_dynlib_getproc(CoreLibHandle, "VidExt_ListFullscreenModes");
632 CoreVideo_SetVideoMode = (ptr_VidExt_SetVideoMode) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetVideoMode");
633 CoreVideo_SetCaption = (ptr_VidExt_SetCaption) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetCaption");
634 CoreVideo_ToggleFullScreen = (ptr_VidExt_ToggleFullScreen) osal_dynlib_getproc(CoreLibHandle, "VidExt_ToggleFullScreen");
635 CoreVideo_ResizeWindow = (ptr_VidExt_ResizeWindow) osal_dynlib_getproc(CoreLibHandle, "VidExt_ResizeWindow");
636 CoreVideo_GL_GetProcAddress = (ptr_VidExt_GL_GetProcAddress) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_GetProcAddress");
637 CoreVideo_GL_SetAttribute = (ptr_VidExt_GL_SetAttribute) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SetAttribute");
638 CoreVideo_GL_GetAttribute = (ptr_VidExt_GL_GetAttribute) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_GetAttribute");
639 CoreVideo_GL_SwapBuffers = (ptr_VidExt_GL_SwapBuffers) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SwapBuffers");
641 if (!CoreVideo_Init || !CoreVideo_Quit || !CoreVideo_ListFullscreenModes || !CoreVideo_SetVideoMode ||
642 !CoreVideo_ResizeWindow || !CoreVideo_SetCaption || !CoreVideo_ToggleFullScreen || !CoreVideo_GL_GetProcAddress ||
643 !CoreVideo_GL_SetAttribute || !CoreVideo_GL_GetAttribute || !CoreVideo_GL_SwapBuffers)
645 DebugMessage(M64MSG_ERROR, "Couldn't connect to Core video extension functions");
646 return M64ERR_INCOMPATIBLE;
649 /* open config section handles and set parameter default values */
650 if (!InitConfiguration())
651 return M64ERR_INTERNAL;
654 return M64ERR_SUCCESS;
657 EXPORT m64p_error CALL PluginShutdown(void)
660 return M64ERR_NOT_INIT;
662 if( status.bGameIsRunning )
669 TRACE0("Write back INI file");
672 /* reset some local variables */
673 l_DebugCallback = NULL;
674 l_DebugCallContext = NULL;
677 return M64ERR_SUCCESS;
680 EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
682 /* set version info */
683 if (PluginType != NULL)
684 *PluginType = M64PLUGIN_GFX;
686 if (PluginVersion != NULL)
687 *PluginVersion = PLUGIN_VERSION;
689 if (APIVersion != NULL)
690 *APIVersion = VIDEO_PLUGIN_API_VERSION;
692 if (PluginNamePtr != NULL)
693 *PluginNamePtr = PLUGIN_NAME;
695 if (Capabilities != NULL)
700 return M64ERR_SUCCESS;
703 //-------------------------------------------------------------------------------------
706 EXPORT void CALL ChangeWindow (void)
708 if( status.ToToggleFullScreen )
709 status.ToToggleFullScreen = FALSE;
711 status.ToToggleFullScreen = TRUE;
714 //---------------------------------------------------------------------------------------
716 EXPORT void CALL MoveScreen (int xpos, int ypos)
720 //---------------------------------------------------------------------------------------
721 EXPORT void CALL RomClosed(void)
723 TRACE0("To stop video");
724 Ini_StoreRomOptions(&g_curRomInfo);
726 TRACE0("Video is stopped");
729 EXPORT int CALL RomOpen(void)
731 /* Read RiceVideoLinux.ini file, set up internal variables by reading values from core configuration API */
734 if( g_CritialSection.IsLocked() )
736 g_CritialSection.Unlock();
737 TRACE0("g_CritialSection is locked when game is starting, unlock it now.");
739 status.bDisableFPS=false;
741 g_dwRamSize = 0x800000;
746 debuggerPause = FALSE;
758 //---------------------------------------------------------------------------------------
759 EXPORT void CALL UpdateScreen(void)
763 static unsigned int lastTick=0;
765 unsigned int nowTick = SDL_GetTicks();
767 if(lastTick + 5000 <= nowTick)
770 sprintf(caption, "%s v%i.%i.%i - %.3f VI/S", PLUGIN_NAME, VERSION_PRINTF_SPLIT(PLUGIN_VERSION), frames/5.0);
771 CoreVideo_SetCaption(caption);
779 //---------------------------------------------------------------------------------------
781 EXPORT void CALL ViStatusChanged(void)
783 g_CritialSection.Lock();
785 CRender::g_pRender->UpdateClipRectangle();
786 g_CritialSection.Unlock();
789 //---------------------------------------------------------------------------------------
790 EXPORT void CALL ViWidthChanged(void)
792 g_CritialSection.Lock();
794 CRender::g_pRender->UpdateClipRectangle();
795 g_CritialSection.Unlock();
798 EXPORT int CALL InitiateGFX(GFX_INFO Gfx_Info)
800 memset(&status, 0, sizeof(status));
801 memcpy(&g_GraphicsInfo, &Gfx_Info, sizeof(GFX_INFO));
803 g_pRDRAMu8 = Gfx_Info.RDRAM;
804 g_pRDRAMu32 = (uint32*)Gfx_Info.RDRAM;
805 g_pRDRAMs8 = (signed char *)Gfx_Info.RDRAM;
807 windowSetting.fViWidth = 320;
808 windowSetting.fViHeight = 240;
809 status.ToToggleFullScreen = FALSE;
810 status.ToResize = false;
811 status.bDisableFPS=false;
813 if (!InitConfiguration())
815 DebugMessage(M64MSG_ERROR, "Failed to read configuration data");
819 CGraphicsContext::InitWindowInfo();
820 CGraphicsContext::InitDeviceParameters();
825 EXPORT void CALL ResizeVideoOutput(int width, int height)
827 // save the new window resolution. actual resizing operation is asynchronous (it happens later)
828 status.gNewResizeWidth = width;
829 status.gNewResizeHeight = height;
830 status.ToResize = true;
833 //---------------------------------------------------------------------------------------
835 EXPORT void CALL ProcessRDPList(void)
839 RDP_DLParser_Process();
843 TRACE0("Unknown Error in ProcessRDPList");
844 TriggerDPInterrupt();
845 TriggerSPInterrupt();
849 EXPORT void CALL ProcessDList(void)
854 //---------------------------------------------------------------------------------------
856 /******************************************************************
857 Function: FrameBufferRead
858 Purpose: This function is called to notify the dll that the
859 frame buffer memory is beening read at the given address.
860 DLL should copy content from its render buffer to the frame buffer
862 DLL is responsible to maintain its own frame buffer memory addr list
863 DLL should copy 4KB block content back to RDRAM frame buffer.
864 Emulator should not call this function again if other memory
865 is read within the same 4KB range
867 Since depth buffer is also being watched, the reported addr
868 may belong to depth buffer
869 input: addr rdram address
871 size 1 = uint8, 2 = uint16, 4 = uint32
873 *******************************************************************/
875 EXPORT void CALL FBRead(uint32 addr)
877 g_pFrameBufferManager->FrameBufferReadByCPU(addr);
881 /******************************************************************
882 Function: FrameBufferWrite
883 Purpose: This function is called to notify the dll that the
884 frame buffer has been modified by CPU at the given address.
886 Since depth buffer is also being watched, the reported addr
887 may belong to depth buffer
889 input: addr rdram address
891 size 1 = uint8, 2 = uint16, 4 = uint32
893 *******************************************************************/
895 EXPORT void CALL FBWrite(uint32 addr, uint32 size)
897 g_pFrameBufferManager->FrameBufferWriteByCPU(addr, size);
900 /************************************************************************
901 Function: FBGetFrameBufferInfo
902 Purpose: This function is called by the emulator core to retrieve frame
903 buffer information from the video plugin in order to be able
904 to notify the video plugin about CPU frame buffer read/write
909 = 2 word (16 bit) <-- this is N64 default depth buffer format
912 when frame buffer information is not available yet, set all values
913 in the FrameBufferInfo structure to 0
915 input: FrameBufferInfo pinfo[6]
916 pinfo is pointed to a FrameBufferInfo structure which to be
917 filled in by this function
918 output: Values are return in the FrameBufferInfo structure
919 Plugin can return up to 6 frame buffer info
920 ************************************************************************/
922 EXPORT void CALL FBGetFrameBufferInfo(void *p)
924 FrameBufferInfo * pinfo = (FrameBufferInfo *)p;
925 memset(pinfo,0,sizeof(FrameBufferInfo)*6);
927 //if( g_ZI.dwAddr == 0 )
929 // memset(pinfo,0,sizeof(FrameBufferInfo)*6);
933 for (int i=0; i<5; i++ )
935 if( status.gDlistCount-g_RecentCIInfo[i].lastUsedFrame > 30 || g_RecentCIInfo[i].lastUsedFrame == 0 )
937 //memset(&pinfo[i],0,sizeof(FrameBufferInfo));
941 pinfo[i].addr = g_RecentCIInfo[i].dwAddr;
943 pinfo[i].width = g_RecentCIInfo[i].dwWidth;
944 pinfo[i].height = g_RecentCIInfo[i].dwHeight;
945 TXTRBUF_DETAIL_DUMP(TRACE3("Protect 0x%08X (%d,%d)", g_RecentCIInfo[i].dwAddr, g_RecentCIInfo[i].dwWidth, g_RecentCIInfo[i].dwHeight));
946 pinfo[5].width = g_RecentCIInfo[i].dwWidth;
947 pinfo[5].height = g_RecentCIInfo[i].dwHeight;
951 pinfo[5].addr = g_ZI.dwAddr;
952 //pinfo->size = g_RecentCIInfo[5].dwSize;
954 TXTRBUF_DETAIL_DUMP(TRACE3("Protect 0x%08X (%d,%d)", pinfo[5].addr, pinfo[5].width, pinfo[5].height));
958 // Plugin spec 1.3 functions
959 EXPORT void CALL ShowCFB(void)
961 status.toShowCFB = true;
964 //void ReadScreen2( void *dest, int *width, int *height, int bFront )
965 EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int bFront)
967 if (width == NULL || height == NULL)
970 *width = windowSetting.uDisplayWidth;
971 *height = windowSetting.uDisplayHeight;
978 glGetIntegerv( GL_READ_BUFFER, &oldMode );
980 glReadBuffer( GL_FRONT );
982 glReadBuffer( GL_BACK );
983 glReadPixels( 0, 0, windowSetting.uDisplayWidth, windowSetting.uDisplayHeight,
984 GL_RGB, GL_UNSIGNED_BYTE, dest );
985 glReadBuffer( oldMode );
990 EXPORT void CALL SetRenderingCallback(void (*callback)(int))
992 renderCallback = callback;