Added missing launcher
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / main.cpp
1 /******************************************************************************
2  * Arachnoid Graphics Plugin for Mupen64Plus
3  * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
4  *
5  * Copyright (C) 2009 Jon Ring
6  * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  *****************************************************************************/
22
23 //Includes
24 #define M64P_PLUGIN_PROTOTYPES 1
25 #include "m64p.h"
26 #include "GraphicsPlugin.h"        //Main class
27 #include "config/Config.h"         //Configuration   
28 #include "Logger.h"                //Debug logger
29 #include "MemoryLeakDetector.h"    //For detecting memory leaks
30
31 #include "m64p_types.h"
32 #include "m64p_common.h"
33 #include "m64p_plugin.h"
34 #include "m64p_config.h"
35 #include "m64p_vidext.h"
36
37 #include "osal_dynamiclib.h"
38
39 //Definitions
40 #define PLUGIN_NAME "Arachnoid Video Plugin"
41 #define PLUGIN_VERSION           0x020000
42 #define VIDEO_PLUGIN_API_VERSION 0x020200
43 #define CONFIG_API_VERSION       0x020000
44 #define VIDEXT_API_VERSION       0x030000
45
46 #define VERSION_PRINTF_SPLIT(x) (((x) >> 16) & 0xffff), (((x) >> 8) & 0xff), ((x) & 0xff)
47
48 #define MI_INTR_DP 0x00000020      //!< RDP Interrupt signal
49 #define MI_INTR_SP 0x00000001      //!< RSP Interrupt signal
50
51 //-----------------------------------------------------------------------------
52 // Global variables
53 //-----------------------------------------------------------------------------
54
55 char              g_cfgFilename[] = "ConfigGraphicsPlugin.cfg";  //!< Name configuration file
56 GFX_INFO          g_graphicsInfo;                                //!< Information about window, memory...
57 GraphicsPlugin    g_graphicsPlugin;                              //!< Main class for application
58 Config            g_config(&g_graphicsPlugin);                   //!< Handles configuration
59
60 void (*renderCallback)(int) = NULL;
61
62
63 /* definitions of pointers to Core config functions */
64 ptr_ConfigOpenSection      ConfigOpenSection = NULL;
65 ptr_ConfigSetParameter     ConfigSetParameter = NULL;
66 ptr_ConfigGetParameter     ConfigGetParameter = NULL;
67 ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL;
68 ptr_ConfigSetDefaultInt    ConfigSetDefaultInt = NULL;
69 ptr_ConfigSetDefaultFloat  ConfigSetDefaultFloat = NULL;
70 ptr_ConfigSetDefaultBool   ConfigSetDefaultBool = NULL;
71 ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL;
72 ptr_ConfigGetParamInt      ConfigGetParamInt = NULL;
73 ptr_ConfigGetParamFloat    ConfigGetParamFloat = NULL;
74 ptr_ConfigGetParamBool     ConfigGetParamBool = NULL;
75 ptr_ConfigGetParamString   ConfigGetParamString = NULL;
76
77 ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL;
78 ptr_ConfigGetUserConfigPath     ConfigGetUserConfigPath = NULL;
79 ptr_ConfigGetUserDataPath       ConfigGetUserDataPath = NULL;
80 ptr_ConfigGetUserCachePath      ConfigGetUserCachePath = NULL;
81
82 /* definitions of pointers to Core video extension functions */
83 ptr_VidExt_Init                  CoreVideo_Init = NULL;
84 ptr_VidExt_Quit                  CoreVideo_Quit = NULL;
85 ptr_VidExt_ListFullscreenModes   CoreVideo_ListFullscreenModes = NULL;
86 ptr_VidExt_SetVideoMode          CoreVideo_SetVideoMode = NULL;
87 ptr_VidExt_SetCaption            CoreVideo_SetCaption = NULL;
88 ptr_VidExt_ToggleFullScreen      CoreVideo_ToggleFullScreen = NULL;
89 ptr_VidExt_ResizeWindow          CoreVideo_ResizeWindow = NULL;
90 ptr_VidExt_GL_GetProcAddress     CoreVideo_GL_GetProcAddress = NULL;
91 ptr_VidExt_GL_SetAttribute       CoreVideo_GL_SetAttribute = NULL;
92 ptr_VidExt_GL_SwapBuffers        CoreVideo_GL_SwapBuffers = NULL;
93
94 //-----------------------------------------------------------------------------
95 // Mupen64plus 2.0 Common Plugin API Functions
96 //-----------------------------------------------------------------------------
97 #ifdef __cplusplus
98 extern "C" {
99 #endif
100 EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
101                                    void (*DebugCallback)(void *, int, const char *))
102 {
103     char logMsg[530];
104     Logger::getSingleton().initialize(DebugCallback, Context);
105     Logger::getSingleton().printMsg("PluginStartup");
106
107     /* attach and call the CoreGetAPIVersions function, check Config and Video Extension API versions for compatibility */
108     ptr_CoreGetAPIVersions CoreAPIVersionFunc;
109     CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreLibHandle, "CoreGetAPIVersions");
110     if (CoreAPIVersionFunc == NULL)
111     {
112         sprintf(logMsg, "Core emulator broken; no CoreAPIVersionFunc() function found.");
113         Logger::getSingleton().printMsg(logMsg, M64MSG_ERROR);
114         return M64ERR_INCOMPATIBLE;
115     }
116     int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
117     (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL);
118     if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000))
119     {
120         sprintf(logMsg, "Emulator core Config API (v%i.%i.%i) incompatible with plugin (v%i.%i.%i)",
121                 VERSION_PRINTF_SPLIT(ConfigAPIVersion), VERSION_PRINTF_SPLIT(CONFIG_API_VERSION));
122         Logger::getSingleton().printMsg(logMsg, M64MSG_ERROR);
123         return M64ERR_INCOMPATIBLE;
124     }
125     if ((VidextAPIVersion & 0xffff0000) != (VIDEXT_API_VERSION & 0xffff0000))
126     {
127         sprintf(logMsg, "Emulator core Video Extension API (v%i.%i.%i) incompatible with plugin (v%i.%i.%i)",
128                 VERSION_PRINTF_SPLIT(VidextAPIVersion), VERSION_PRINTF_SPLIT(VIDEXT_API_VERSION));
129         Logger::getSingleton().printMsg(logMsg, M64MSG_ERROR);
130         return M64ERR_INCOMPATIBLE;
131     }
132
133     /* Get the core config function pointers from the library handle */
134     ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreLibHandle, "ConfigOpenSection");
135     ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigSetParameter");
136     ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParameter");
137     ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultInt");
138     ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultFloat");
139     ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultBool");
140     ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultString");
141     ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamInt");
142     ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamFloat");
143     ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamBool");
144     ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamString");
145
146     ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetSharedDataFilepath");
147     ConfigGetUserConfigPath = (ptr_ConfigGetUserConfigPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserConfigPath");
148     ConfigGetUserDataPath = (ptr_ConfigGetUserDataPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserDataPath");
149     ConfigGetUserCachePath = (ptr_ConfigGetUserCachePath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserCachePath");
150
151     if (!ConfigOpenSection   || !ConfigSetParameter    || !ConfigGetParameter ||
152         !ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString ||
153         !ConfigGetParamInt   || !ConfigGetParamFloat   || !ConfigGetParamBool   || !ConfigGetParamString ||
154         !ConfigGetSharedDataFilepath || !ConfigGetUserConfigPath || !ConfigGetUserDataPath || !ConfigGetUserCachePath)
155     {
156         Logger::getSingleton().printMsg("Couldn't connect to Core configuration functions", M64MSG_ERROR);
157         return M64ERR_INCOMPATIBLE;
158     }
159
160     /* Get the core Video Extension function pointers from the library handle */
161     CoreVideo_Init = (ptr_VidExt_Init) osal_dynlib_getproc(CoreLibHandle, "VidExt_Init");
162     CoreVideo_Quit = (ptr_VidExt_Quit) osal_dynlib_getproc(CoreLibHandle, "VidExt_Quit");
163     CoreVideo_ListFullscreenModes = (ptr_VidExt_ListFullscreenModes) osal_dynlib_getproc(CoreLibHandle, "VidExt_ListFullscreenModes");
164     CoreVideo_SetVideoMode = (ptr_VidExt_SetVideoMode) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetVideoMode");
165     CoreVideo_SetCaption = (ptr_VidExt_SetCaption) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetCaption");
166     CoreVideo_ToggleFullScreen = (ptr_VidExt_ToggleFullScreen) osal_dynlib_getproc(CoreLibHandle, "VidExt_ToggleFullScreen");
167     CoreVideo_ResizeWindow = (ptr_VidExt_ResizeWindow) osal_dynlib_getproc(CoreLibHandle, "VidExt_ResizeWindow");
168     CoreVideo_GL_GetProcAddress = (ptr_VidExt_GL_GetProcAddress) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_GetProcAddress");
169     CoreVideo_GL_SetAttribute = (ptr_VidExt_GL_SetAttribute) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SetAttribute");
170     CoreVideo_GL_SwapBuffers = (ptr_VidExt_GL_SwapBuffers) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SwapBuffers");
171
172     if (!CoreVideo_Init || !CoreVideo_Quit || !CoreVideo_ListFullscreenModes || !CoreVideo_SetVideoMode ||
173         !CoreVideo_SetCaption || !CoreVideo_ToggleFullScreen || !CoreVideo_GL_GetProcAddress ||
174         !CoreVideo_GL_SetAttribute || !CoreVideo_GL_SwapBuffers || !CoreVideo_ResizeWindow)
175     {
176         Logger::getSingleton().printMsg("Couldn't connect to Core video functions", M64MSG_ERROR);
177         return M64ERR_INCOMPATIBLE;
178     }
179
180     //Read configuration
181     if (g_config.initialize())
182     {
183         g_config.load();
184         g_graphicsPlugin.setConfig(g_config.getConfig());
185     }
186
187     return M64ERR_SUCCESS;
188 }
189
190 EXPORT m64p_error CALL PluginShutdown(void)
191 {
192     //Close Logger
193     Logger::getSingleton().printMsg("CloseDLL\n");
194     Logger::getSingleton().dispose();   
195
196     //g_graphicsPlugin.dispose();  
197     return M64ERR_SUCCESS;
198 }
199
200 EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
201 {
202     /* set version info */
203     if (PluginType != NULL)
204         *PluginType = M64PLUGIN_GFX;
205
206     if (PluginVersion != NULL)
207         *PluginVersion = PLUGIN_VERSION;
208
209     if (APIVersion != NULL)
210         *APIVersion = VIDEO_PLUGIN_API_VERSION;
211     
212     if (PluginNamePtr != NULL)
213         *PluginNamePtr = PLUGIN_NAME;
214
215     if (Capabilities != NULL)
216     {
217         *Capabilities = 0;
218     }
219                     
220     return M64ERR_SUCCESS;
221 }
222
223
224
225 //-----------------------------------------------------------------------------
226 // Mupen64plus 2.0 Video Plugin API Functions
227 //-----------------------------------------------------------------------------
228
229
230 //-----------------------------------------------------------------------------
231 //* InitiateGFX
232 //! This function is called when the DLL is started to give
233 //! information from the emulator that the n64 graphics
234 //!    uses. This is not called from the emulation thread.
235 //! @param[in] Gfx_Info Information about rom and emulator
236 //! @return true on success, FALSE on failure to initialise
237 //!           
238 //! @note on interrupts :
239 //!    To generate an interrupt set the appropriate bit in MI_INTR_REG
240 //!    and then  the function CheckInterrupts to tell the emulator
241 //!    that there is a waiting interrupt.
242 //-----------------------------------------------------------------------------
243 EXPORT BOOL CALL InitiateGFX(GFX_INFO Gfx_Info)
244 {
245     Logger::getSingleton().printMsg("InitiateGFX");
246
247     //Save Graphics Info
248     memcpy(&g_graphicsInfo, &Gfx_Info, sizeof(GFX_INFO));
249     return true;
250 }
251
252 //-----------------------------------------------------------------------------
253 //* Rom Open
254 //! This function is called when a rom is open. (from the emulation thread)
255 //-----------------------------------------------------------------------------
256 EXPORT int CALL RomOpen()
257 {
258     Logger::getSingleton().printMsg("RomOpen\n");
259     return g_graphicsPlugin.initialize(&g_graphicsInfo);
260 }
261
262 //-----------------------------------------------------------------------------
263 //* Resize Video Output
264 //! This function is called to force us to resize our output OpenGL window.
265 //! This is currently unsupported, and should never be called because we do
266 //! not pass the RESIZABLE flag to VidExt_SetVideoMode when initializing.
267 //-----------------------------------------------------------------------------
268 EXPORT void CALL ResizeVideoOutput(int Width, int Height)
269 {
270 }
271
272 //-----------------------------------------------------------------------------
273 //* Rom Closed
274 //! This function is called when a rom is closed.
275 //-----------------------------------------------------------------------------
276 EXPORT void CALL RomClosed()
277 {
278     //Logger::getSingleton().printMsg("RomClosed\n");
279     //Destroy 
280     g_graphicsPlugin.dispose();
281 }
282
283 //-----------------------------------------------------------------------------
284 //* Update Screen
285 //! This function is called in response to a vsync of the
286 //! screen where the VI bit in MI_INTR_REG has already been set
287 //-----------------------------------------------------------------------------
288 EXPORT void CALL UpdateScreen()
289 {
290     if (g_config.getConfig()->screenUpdateSetting == SCREEN_UPDATE_VI)
291         g_graphicsPlugin.drawScreen();
292     else if (g_config.getConfig()->screenUpdateSetting == SCREEN_UPDATE_CI)
293         g_graphicsPlugin.setDrawScreenSignal();
294     else
295     {
296         Logger::getSingleton().printMsg("Invalid screen update setting!", M64MSG_WARNING);
297         g_graphicsPlugin.drawScreen();
298     }
299 }
300
301
302 //-----------------------------------------------------------------------------
303 //* ProcessDList
304 //! This function is called when there is a Dlist to be processed. (High level GFX list)
305 //-----------------------------------------------------------------------------
306 EXPORT void CALL ProcessDList()
307 {
308     Logger::getSingleton().printMsg("ProcessDList\n");
309
310     try
311     {
312         g_graphicsPlugin.viStatusChanged();
313         g_graphicsPlugin.processDisplayList();
314     }
315     catch (...)
316     {
317         Logger::getSingleton().printMsg("Unknown Error processing DisplayList", M64MSG_WARNING); 
318         //MessageBox(0, "Unknown Error processing DisplayList", "Arachnoid Graphics Plugin", MB_OK|MB_SETFOREGROUND); 
319
320         g_graphicsPlugin.dispose();
321         g_graphicsPlugin.initialize(&g_graphicsInfo);
322
323         //Trigger Interupts
324         *(g_graphicsInfo.MI_INTR_REG) |= MI_INTR_DP;
325         g_graphicsInfo.CheckInterrupts();
326         *(g_graphicsInfo.MI_INTR_REG) |= MI_INTR_SP;
327         g_graphicsInfo.CheckInterrupts();    
328     }
329 }
330
331
332 //-----------------------------------------------------------------------------
333 //* ProcessRDPList
334 //! This function is called when there is a Dlist to be processed. (Low level GFX list)
335 //! @todo ProcessRDPList
336 //-----------------------------------------------------------------------------
337 EXPORT void CALL ProcessRDPList()
338 {
339     Logger::getSingleton().printMsg("ProcessRDPList\n");
340     //TODO
341 }
342
343 //-----------------------------------------------------------------------------
344 //* Show CFB
345 //! Usally once Dlists are started being displayed, cfb is
346 //! ignored. This function tells the dll to start displaying
347 //! them again.
348 //-----------------------------------------------------------------------------
349 EXPORT void CALL ShowCFB()
350 {
351     Logger::getSingleton().printMsg("ShowCFB\n");
352 }
353
354 //-----------------------------------------------------------------------------
355 //* ViStatusChanged
356 //! This function is called to notify the dll that the
357 //! ViStatus registers value has been changed.
358 //-----------------------------------------------------------------------------
359 EXPORT void CALL ViStatusChanged()
360 {
361     Logger::getSingleton().printMsg("ViStatusChanged");
362
363     //g_graphicsPlugin.viStatusChanged();
364 }
365
366 //-----------------------------------------------------------------------------
367 //* ViWidthChanged
368 //! This function is called to notify the dll that the
369 //! ViWidth registers value has been changed.
370 //-----------------------------------------------------------------------------
371 EXPORT void CALL ViWidthChanged()
372 {    
373     Logger::getSingleton().printMsg("ViWidthChanged");
374     //g_graphicsPlugin.viStatusChanged();
375 }
376
377 //-----------------------------------------------------------------------------
378 //* MoveScreen
379 //! This function is called in response to the emulator
380 //! receiving a WM_MOVE passing the xpos and ypos passed
381 //! from that message.
382 //! @param xpos The x-coordinate of the upper-left corner of the 
383 //!             client area of the window.
384 //! @param ypos The y-coordinate of the upper-left corner of the
385 //!             client area of the window. 
386 //! @todo MoveScreen
387 //----------------------------------------------------------------------------- 
388 EXPORT void CALL MoveScreen(int xpos, int ypos)
389 {
390     Logger::getSingleton().printMsg("MoveScreen\n");
391     //TODO
392 }
393
394 //-----------------------------------------------------------------------------
395 //* ChangeWindow
396 //! Toggle between fullscreen and window mode
397 //-----------------------------------------------------------------------------
398 EXPORT void CALL ChangeWindow()
399 {
400     Logger::getSingleton().printMsg("ChangeWindow\n");
401     //Toggle Fullscreen
402     g_graphicsPlugin.toggleFullscreen();
403 }
404
405 //-----------------------------------------------------------------------------
406 //* ReadScreen2
407 //! This function reads the pixels of the currently displayed screen
408 //-----------------------------------------------------------------------------
409 EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front)
410 {
411     g_graphicsPlugin.takeScreenshot(dest, width, height, front);
412 }
413
414 //-----------------------------------------------------------------------------
415 //* SetRenderingCallback
416 //! Allows the core to register a callback function that will be called by the 
417 //! graphics plugin just before the the frame buffers are swapped.
418 //-----------------------------------------------------------------------------
419 EXPORT void CALL SetRenderingCallback(void (*callback)(int))
420 {
421     OpenGLManager::getSingleton().setRenderingCallback(callback);
422 }
423
424 //-----------------------------------------------------------------------------
425 //* FBRead
426 //! Read data from frame buffer into emulated RAM space 
427 //-----------------------------------------------------------------------------
428 EXPORT void CALL FBRead(unsigned int addr)
429 {
430     //TODO
431 }
432
433 //-----------------------------------------------------------------------------
434 //* FBWrite
435 //! Write data from emulated RAM space into frame buffer
436 //-----------------------------------------------------------------------------
437 EXPORT void CALL FBWrite(unsigned int addr, unsigned int size)
438 {
439     //TODO
440 }
441
442 //-----------------------------------------------------------------------------
443 //* FBWrite
444 //! Get some information about the frame buffer 
445 //-----------------------------------------------------------------------------
446 EXPORT void FBGetFrameBufferInfo(void *p)
447 {
448     //TODO
449 }
450
451 #ifdef __cplusplus
452 }
453 #endif