Arachnoid GLESv1.1 plugin. Compile and run (a bit glitchy and no frameskip) on the...
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / main.cpp
CommitLineData
22726e4d 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
55char g_cfgFilename[] = "ConfigGraphicsPlugin.cfg"; //!< Name configuration file
56GFX_INFO g_graphicsInfo; //!< Information about window, memory...
57GraphicsPlugin g_graphicsPlugin; //!< Main class for application
58Config g_config(&g_graphicsPlugin); //!< Handles configuration
59
60void (*renderCallback)(int) = NULL;
61
62
63/* definitions of pointers to Core config functions */
64ptr_ConfigOpenSection ConfigOpenSection = NULL;
65ptr_ConfigSetParameter ConfigSetParameter = NULL;
66ptr_ConfigGetParameter ConfigGetParameter = NULL;
67ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL;
68ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL;
69ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL;
70ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL;
71ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL;
72ptr_ConfigGetParamInt ConfigGetParamInt = NULL;
73ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL;
74ptr_ConfigGetParamBool ConfigGetParamBool = NULL;
75ptr_ConfigGetParamString ConfigGetParamString = NULL;
76
77ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL;
78ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL;
79ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL;
80ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL;
81
82/* definitions of pointers to Core video extension functions */
83ptr_VidExt_Init CoreVideo_Init = NULL;
84ptr_VidExt_Quit CoreVideo_Quit = NULL;
85ptr_VidExt_ListFullscreenModes CoreVideo_ListFullscreenModes = NULL;
86ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode = NULL;
87ptr_VidExt_SetCaption CoreVideo_SetCaption = NULL;
88ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen = NULL;
89ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow = NULL;
90ptr_VidExt_GL_GetProcAddress CoreVideo_GL_GetProcAddress = NULL;
91ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute = NULL;
92ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers = NULL;
93
94//-----------------------------------------------------------------------------
95// Mupen64plus 2.0 Common Plugin API Functions
96//-----------------------------------------------------------------------------
97#ifdef __cplusplus
98extern "C" {
99#endif
100EXPORT 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
190EXPORT 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
200EXPORT 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//-----------------------------------------------------------------------------
243EXPORT 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//-----------------------------------------------------------------------------
256EXPORT 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//-----------------------------------------------------------------------------
268EXPORT 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//-----------------------------------------------------------------------------
276EXPORT 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//-----------------------------------------------------------------------------
288EXPORT 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//-----------------------------------------------------------------------------
306EXPORT 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//-----------------------------------------------------------------------------
337EXPORT 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//-----------------------------------------------------------------------------
349EXPORT 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//-----------------------------------------------------------------------------
359EXPORT 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//-----------------------------------------------------------------------------
371EXPORT 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//-----------------------------------------------------------------------------
388EXPORT 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//-----------------------------------------------------------------------------
398EXPORT 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//-----------------------------------------------------------------------------
409EXPORT 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//-----------------------------------------------------------------------------
419EXPORT 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//-----------------------------------------------------------------------------
428EXPORT 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//-----------------------------------------------------------------------------
437EXPORT 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//-----------------------------------------------------------------------------
446EXPORT void FBGetFrameBufferInfo(void *p)
447{
448 //TODO
449}
450
451#ifdef __cplusplus
452}
453#endif