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;
105 float mspervi = 1000.0f/60.0f; //default is shortest frame
109 //---------------------------------------------------------------------------------------
110 // Forward function declarations
112 extern "C" EXPORT void CALL RomClosed(void);
114 //---------------------------------------------------------------------------------------
115 // Static (local) functions
116 static void ChangeWindowStep2()
118 status.bDisableFPS = true;
119 windowSetting.bDisplayFullscreen = !windowSetting.bDisplayFullscreen;
120 g_CritialSection.Lock();
121 windowSetting.bDisplayFullscreen = CGraphicsContext::Get()->ToggleFullscreen();
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;
134 static void ResizeStep2(void)
136 g_CritialSection.Lock();
138 // Delete all OpenGL textures
139 gTextureManager.CleanUp();
141 // delete our opengl renderer
142 CDeviceBuilder::GetBuilder()->DeleteRender();
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);
149 // re-initialize our OpenGL graphics context state
150 bool res = CGraphicsContext::Get()->ResizeInitialize(windowSetting.uDisplayWidth, windowSetting.uDisplayHeight, !windowSetting.bDisplayFullscreen);
153 // re-create the OpenGL renderer
154 CDeviceBuilder::GetBuilder()->CreateRender();
155 CRender::GetRender()->Initialize();
159 g_CritialSection.Unlock();
160 status.ToResize = false;
163 static void UpdateScreenStep2 (void)
165 status.bVIOriginIsUpdated = false;
167 if( status.ToToggleFullScreen && status.gDlistCount > 0 )
172 if (status.ToResize && status.gDlistCount > 0)
178 g_CritialSection.Lock();
183 if( status.bHandleN64RenderTexture )
184 g_pFrameBufferManager->CloseRenderTexture(true);
186 g_pFrameBufferManager->SetAddrBeDisplayed(*g_GraphicsInfo.VI_ORIGIN_REG);
188 if( status.gDlistCount == 0 )
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 )
195 CRender::GetRender()->DrawFrameBuffer(true);
196 CGraphicsContext::Get()->UpdateFrame();
198 g_CritialSection.Unlock();
202 TXTRBUF_DETAIL_DUMP(TRACE1("VI ORIG is updated to %08X", *g_GraphicsInfo.VI_ORIGIN_REG));
204 if( currentRomOptions.screenUpdateSetting == SCREEN_UPDATE_AT_VI_UPDATE )
206 CGraphicsContext::Get()->UpdateFrame();
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();
215 TXTRBUF_DETAIL_DUMP(TRACE1("VI ORIG is updated to %08X", *g_GraphicsInfo.VI_ORIGIN_REG));
217 if( currentRomOptions.screenUpdateSetting == SCREEN_UPDATE_AT_VI_UPDATE_AND_DRAWN )
219 if( status.bScreenIsDrawn )
221 CGraphicsContext::Get()->UpdateFrame();
222 DEBUGGER_IF_DUMP( pauseAtNext, TRACE1("Update Screen: VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG));
226 DEBUGGER_IF_DUMP( pauseAtNext, TRACE1("Skip Screen Update: VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG));
229 DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_FRAME);
230 DEBUGGER_PAUSE_COUNT_N_WITHOUT_UPDATE(NEXT_SET_CIMG);
231 g_CritialSection.Unlock();
235 if( currentRomOptions.screenUpdateSetting==SCREEN_UPDATE_AT_VI_CHANGE )
238 if( *g_GraphicsInfo.VI_ORIGIN_REG != status.curVIOriginReg )
240 if( *g_GraphicsInfo.VI_ORIGIN_REG < status.curDisplayBuffer || *g_GraphicsInfo.VI_ORIGIN_REG > status.curDisplayBuffer+0x2000 )
242 status.curDisplayBuffer = *g_GraphicsInfo.VI_ORIGIN_REG;
243 status.curVIOriginReg = status.curDisplayBuffer;
244 //status.curRenderBuffer = NULL;
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);
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);});
260 DEBUGGER_PAUSE_AND_DUMP_NO_UPDATE(NEXT_FRAME, {DebuggerAppendMsg("Skip Screen Update, the same VIORIG=%08X", *g_GraphicsInfo.VI_ORIGIN_REG);});
263 g_CritialSection.Unlock();
267 if( currentRomOptions.screenUpdateSetting >= SCREEN_UPDATE_AT_1ST_CI_CHANGE )
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();
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);
279 g_CritialSection.Unlock();
282 static void ProcessDListStep2(void)
284 g_CritialSection.Lock();
285 if( status.toShowCFB )
287 CRender::GetRender()->DrawFrameBuffer(true);
288 status.toShowCFB = false;
293 DLParser_Process((OSTask *)(g_GraphicsInfo.DMEM + 0x0FC0));
297 TRACE0("Unknown Error in ProcessDList");
298 TriggerDPInterrupt();
299 TriggerSPInterrupt();
302 g_CritialSection.Unlock();
305 static bool StartVideo(void)
307 windowSetting.dps = windowSetting.fps = -1;
308 windowSetting.lastSecDlistCount = windowSetting.lastSecFrameCount = 0xFFFFFFFF;
310 g_CritialSection.Lock();
312 memcpy(&g_curRomInfo.romheader, g_GraphicsInfo.HEADER, sizeof(ROMHeader));
313 unsigned char *puc = (unsigned char *) &g_curRomInfo.romheader;
316 for (i = 0; i < sizeof(ROMHeader); i += 4) /* byte-swap the ROM header */
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)
331 if( *p == ':' || *p == '\\' || *p == '/' )
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
341 status.fRatio = 9/11.0f;
342 mspervi=1000.0f/50.0f;
344 printf("TV system=%s, ms per VI=%f\n", (status.dwTvSystem==TV_SYSTEM_NTSC)?"NTSC":"PAL", mspervi);
345 InitExternalTextures();
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);
355 g_CritialSection.Unlock();
358 CDeviceBuilder::GetBuilder()->CreateRender();
359 CRender::GetRender()->Initialize();
361 status.bGameIsRunning = true;
365 DebugMessage(M64MSG_ERROR, "Exception caught while starting video renderer");
368 printf("VideoInit finished\n");
369 g_CritialSection.Unlock();
373 static void StopVideo()
375 g_CritialSection.Lock();
376 status.bGameIsRunning = false;
379 CloseExternalTextures();
381 // Kill all textures?
382 gTextureManager.RecycleAllTextures();
383 gTextureManager.CleanUp();
386 CDeviceBuilder::GetBuilder()->DeleteRender();
387 CGraphicsContext::Get()->CleanUp();
388 CDeviceBuilder::GetBuilder()->DeleteGraphicsContext();
392 TRACE0("Some exceptions during RomClosed");
395 g_CritialSection.Unlock();
396 windowSetting.dps = windowSetting.fps = -1;
397 windowSetting.lastSecDlistCount = windowSetting.lastSecFrameCount = 0xFFFFFFFF;
398 status.gDlistCount = status.gFrameCount = 0;
402 //---------------------------------------------------------------------------------------
403 // Global functions, for use by other source files in this plugin
407 if( g_curRomInfo.VIHeight>0 && g_curRomInfo.VIWidth>0 )
409 windowSetting.fViWidth = windowSetting.uViWidth = g_curRomInfo.VIWidth;
410 windowSetting.fViHeight = windowSetting.uViHeight = g_curRomInfo.VIHeight;
412 else if( g_curRomInfo.UseCIWidthAndRatio && g_CI.dwWidth )
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;
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 )
429 windowSetting.fViWidth = (float)width;
433 DebuggerAppendMsg("fViWidth = %f, Width Reg=%d", windowSetting.fViWidth, width);
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;
445 windowSetting.fViHeight = windowSetting.fViWidth*status.fRatio;
449 if( *g_GraphicsInfo.VI_WIDTH_REG > 0x300 )
450 windowSetting.fViHeight *= 2;
452 if( windowSetting.fViWidth*status.fRatio > windowSetting.fViHeight && (*g_GraphicsInfo.VI_X_SCALE_REG & 0xFF) != 0 )
454 if( abs(int(windowSetting.fViWidth*status.fRatio - windowSetting.fViHeight)) < 8 )
456 windowSetting.fViHeight = windowSetting.fViWidth*status.fRatio;
461 if( abs(windowSetting.fViWidth*status.fRatio-windowSetting.fViHeight) > windowSetting.fViWidth*0.1f )
463 if( status.fRatio > 0.8 )
464 windowSetting.fViHeight = windowSetting.fViWidth*3/4;
465 //windowSetting.fViHeight = (*g_GraphicsInfo.VI_V_SYNC_REG - 0x2C)/2;
471 if( windowSetting.fViHeight<100 || windowSetting.fViWidth<100 )
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;
479 windowSetting.uViWidth = (unsigned short)(windowSetting.fViWidth/4);
480 windowSetting.fViWidth = windowSetting.uViWidth *= 4;
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;
487 uint16 optimizeHeight2 = (uint16)(windowSetting.uViWidth*3/4);
488 optimizeHeight2 &= ~3;
490 if( windowSetting.uViHeight != optimizeHeight && windowSetting.uViHeight != optimizeHeight2 )
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;
499 if( gRDP.scissor.left == 0 && gRDP.scissor.top == 0 && gRDP.scissor.right != 0 )
501 if( (*g_GraphicsInfo.VI_X_SCALE_REG & 0xFF) != 0x0 && gRDP.scissor.right == windowSetting.uViWidth )
504 if( abs(int( windowSetting.fViHeight - gRDP.scissor.bottom )) < 8 )
506 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom;
508 else if( windowSetting.fViHeight < gRDP.scissor.bottom )
510 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom;
512 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom;
514 else if( gRDP.scissor.right == windowSetting.uViWidth - 1 && gRDP.scissor.bottom != 0 )
516 if( windowSetting.uViHeight != optimizeHeight && windowSetting.uViHeight != optimizeHeight2 )
518 if( status.fRatio != 0.75 && windowSetting.fViHeight > optimizeHeight/2 )
520 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom + gRDP.scissor.top + 1;
524 else if( gRDP.scissor.right == windowSetting.uViWidth && gRDP.scissor.bottom != 0 && status.fRatio != 0.75 )
526 if( windowSetting.uViHeight != optimizeHeight && windowSetting.uViHeight != optimizeHeight2 )
528 if( status.fRatio != 0.75 && windowSetting.fViHeight > optimizeHeight/2 )
530 windowSetting.fViHeight = windowSetting.uViHeight = gRDP.scissor.bottom + gRDP.scissor.top + 1;
536 SetScreenMult(windowSetting.uDisplayWidth/windowSetting.fViWidth, windowSetting.uDisplayHeight/windowSetting.fViHeight);
539 void TriggerDPInterrupt(void)
541 *(g_GraphicsInfo.MI_INTR_REG) |= MI_INTR_DP;
542 g_GraphicsInfo.CheckInterrupts();
545 void TriggerSPInterrupt(void)
547 *(g_GraphicsInfo.MI_INTR_REG) |= MI_INTR_SP;
548 g_GraphicsInfo.CheckInterrupts();
551 void _VIDEO_DisplayTemporaryMessage(const char *Message)
555 void DebugMessage(int level, const char *message, ...)
560 if (l_DebugCallback == NULL)
563 va_start(args, message);
564 vsprintf(msgbuf, message, args);
566 (*l_DebugCallback)(l_DebugCallContext, level, msgbuf);
571 //---------------------------------------------------------------------------------------
572 // Global functions, exported for use by the core library
574 // since these functions are exported, they need to have C-style names
579 /* Mupen64Plus plugin functions */
580 EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
581 void (*DebugCallback)(void *, int, const char *))
584 return M64ERR_ALREADY_INIT;
586 /* first thing is to set the callback function for debug info */
587 l_DebugCallback = DebugCallback;
588 l_DebugCallContext = Context;
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)
595 DebugMessage(M64MSG_ERROR, "Core emulator broken; no CoreAPIVersionFunc() function found.");
596 return M64ERR_INCOMPATIBLE;
598 int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
599 (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL);
600 if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000))
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;
606 if ((VidextAPIVersion & 0xffff0000) != (VIDEXT_API_VERSION & 0xffff0000))
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;
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");
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");
631 if (!ConfigOpenSection || !ConfigSetParameter || !ConfigGetParameter ||
632 !ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString ||
633 !ConfigGetParamInt || !ConfigGetParamFloat || !ConfigGetParamBool || !ConfigGetParamString ||
634 !ConfigGetSharedDataFilepath || !ConfigGetUserConfigPath || !ConfigGetUserDataPath || !ConfigGetUserCachePath)
636 DebugMessage(M64MSG_ERROR, "Couldn't connect to Core configuration functions");
637 return M64ERR_INCOMPATIBLE;
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");
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)
657 DebugMessage(M64MSG_ERROR, "Couldn't connect to Core video extension functions");
658 return M64ERR_INCOMPATIBLE;
661 /* open config section handles and set parameter default values */
662 if (!InitConfiguration())
663 return M64ERR_INTERNAL;
666 return M64ERR_SUCCESS;
669 EXPORT m64p_error CALL PluginShutdown(void)
672 return M64ERR_NOT_INIT;
674 if( status.bGameIsRunning )
681 TRACE0("Write back INI file");
684 /* reset some local variables */
685 l_DebugCallback = NULL;
686 l_DebugCallContext = NULL;
689 return M64ERR_SUCCESS;
692 EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
694 /* set version info */
695 if (PluginType != NULL)
696 *PluginType = M64PLUGIN_GFX;
698 if (PluginVersion != NULL)
699 *PluginVersion = PLUGIN_VERSION;
701 if (APIVersion != NULL)
702 *APIVersion = VIDEO_PLUGIN_API_VERSION;
704 if (PluginNamePtr != NULL)
705 *PluginNamePtr = PLUGIN_NAME;
707 if (Capabilities != NULL)
712 return M64ERR_SUCCESS;
715 //-------------------------------------------------------------------------------------
718 EXPORT void CALL ChangeWindow (void)
720 if( status.ToToggleFullScreen )
721 status.ToToggleFullScreen = FALSE;
723 status.ToToggleFullScreen = TRUE;
726 //---------------------------------------------------------------------------------------
728 EXPORT void CALL MoveScreen (int xpos, int ypos)
732 //---------------------------------------------------------------------------------------
733 EXPORT void CALL RomClosed(void)
735 TRACE0("To stop video");
736 Ini_StoreRomOptions(&g_curRomInfo);
738 TRACE0("Video is stopped");
741 EXPORT int CALL RomOpen(void)
743 /* Read RiceVideoLinux.ini file, set up internal variables by reading values from core configuration API */
746 if( g_CritialSection.IsLocked() )
748 g_CritialSection.Unlock();
749 TRACE0("g_CritialSection is locked when game is starting, unlock it now.");
751 status.bDisableFPS=false;
753 g_dwRamSize = 0x800000;
758 debuggerPause = FALSE;
770 //---------------------------------------------------------------------------------------
771 EXPORT void CALL UpdateScreen(void)
775 static unsigned int lastTick=0;
777 unsigned int nowTick = SDL_GetTicks();
779 if(lastTick + 5000 <= nowTick)
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);
791 //---------------------------------------------------------------------------------------
793 EXPORT void CALL ViStatusChanged(void)
795 g_CritialSection.Lock();
797 CRender::g_pRender->UpdateClipRectangle();
798 g_CritialSection.Unlock();
801 //---------------------------------------------------------------------------------------
802 EXPORT void CALL ViWidthChanged(void)
804 g_CritialSection.Lock();
806 CRender::g_pRender->UpdateClipRectangle();
807 g_CritialSection.Unlock();
810 EXPORT int CALL InitiateGFX(GFX_INFO Gfx_Info)
812 memset(&status, 0, sizeof(status));
813 memcpy(&g_GraphicsInfo, &Gfx_Info, sizeof(GFX_INFO));
815 g_pRDRAMu8 = Gfx_Info.RDRAM;
816 g_pRDRAMu32 = (uint32*)Gfx_Info.RDRAM;
817 g_pRDRAMs8 = (signed char *)Gfx_Info.RDRAM;
819 windowSetting.fViWidth = 320;
820 windowSetting.fViHeight = 240;
821 status.ToToggleFullScreen = FALSE;
822 status.ToResize = false;
823 status.bDisableFPS=false;
825 if (!InitConfiguration())
827 DebugMessage(M64MSG_ERROR, "Failed to read configuration data");
831 CGraphicsContext::InitWindowInfo();
832 CGraphicsContext::InitDeviceParameters();
837 EXPORT void CALL ResizeVideoOutput(int width, int height)
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;
845 //---------------------------------------------------------------------------------------
847 EXPORT void CALL ProcessRDPList(void)
851 RDP_DLParser_Process();
855 TRACE0("Unknown Error in ProcessRDPList");
856 TriggerDPInterrupt();
857 TriggerSPInterrupt();
861 EXPORT void CALL ProcessDList(void)
866 //---------------------------------------------------------------------------------------
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
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
879 Since depth buffer is also being watched, the reported addr
880 may belong to depth buffer
881 input: addr rdram address
883 size 1 = uint8, 2 = uint16, 4 = uint32
885 *******************************************************************/
887 EXPORT void CALL FBRead(uint32 addr)
889 g_pFrameBufferManager->FrameBufferReadByCPU(addr);
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.
898 Since depth buffer is also being watched, the reported addr
899 may belong to depth buffer
901 input: addr rdram address
903 size 1 = uint8, 2 = uint16, 4 = uint32
905 *******************************************************************/
907 EXPORT void CALL FBWrite(uint32 addr, uint32 size)
909 g_pFrameBufferManager->FrameBufferWriteByCPU(addr, size);
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
921 = 2 word (16 bit) <-- this is N64 default depth buffer format
924 when frame buffer information is not available yet, set all values
925 in the FrameBufferInfo structure to 0
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 ************************************************************************/
934 EXPORT void CALL FBGetFrameBufferInfo(void *p)
936 FrameBufferInfo * pinfo = (FrameBufferInfo *)p;
937 memset(pinfo,0,sizeof(FrameBufferInfo)*6);
939 //if( g_ZI.dwAddr == 0 )
941 // memset(pinfo,0,sizeof(FrameBufferInfo)*6);
945 for (int i=0; i<5; i++ )
947 if( status.gDlistCount-g_RecentCIInfo[i].lastUsedFrame > 30 || g_RecentCIInfo[i].lastUsedFrame == 0 )
949 //memset(&pinfo[i],0,sizeof(FrameBufferInfo));
953 pinfo[i].addr = g_RecentCIInfo[i].dwAddr;
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;
963 pinfo[5].addr = g_ZI.dwAddr;
964 //pinfo->size = g_RecentCIInfo[5].dwSize;
966 TXTRBUF_DETAIL_DUMP(TRACE3("Protect 0x%08X (%d,%d)", pinfo[5].addr, pinfo[5].width, pinfo[5].height));
970 // Plugin spec 1.3 functions
971 EXPORT void CALL ShowCFB(void)
973 status.toShowCFB = true;
976 //void ReadScreen2( void *dest, int *width, int *height, int bFront )
977 EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int bFront)
979 if (width == NULL || height == NULL)
982 *width = windowSetting.uDisplayWidth;
983 *height = windowSetting.uDisplayHeight;
990 //*TODO*, what's the use of this function ? *SEB*
992 glGetIntegerv( GL_READ_BUFFER, &oldMode );
994 glReadBuffer( GL_FRONT );
996 glReadBuffer( GL_BACK );
997 glReadPixels( 0, 0, windowSetting.uDisplayWidth, windowSetting.uDisplayHeight,
998 GL_RGB, GL_UNSIGNED_BYTE, dest );
999 glReadBuffer( oldMode );
1005 EXPORT void CALL SetRenderingCallback(void (*callback)(int))
1007 renderCallback = callback;