GLES2N64 (from mupen64plus-ae) plugin. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / gles2n64 / src / gles2N64.cpp
1
2 #include <dlfcn.h>
3 #include <string.h>
4 //#include <cpu-features.h>
5
6 #include "m64p_types.h"
7 #include "m64p_plugin.h"
8
9 #include "gles2N64.h"
10 #include "Debug.h"
11 #include "OpenGL.h"
12 #include "N64.h"
13 #include "RSP.h"
14 #include "RDP.h"
15 #include "VI.h"
16 #include "Config.h"
17 #include "Textures.h"
18 #include "ShaderCombiner.h"
19 #include "3DMath.h"
20 #include "FrameSkipper.h"
21 #include "ticks.h"
22
23 //#include "ae_bridge.h"
24
25 ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL;
26
27 static FrameSkipper frameSkipper;
28
29 u32         last_good_ucode = (u32) -1;
30 void        (*CheckInterrupts)( void );
31 void        (*renderCallback)() = NULL;
32
33 extern "C" {
34
35 EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle,
36         void *Context, void (*DebugCallback)(void *, int, const char *))
37 {
38 printf("GLES2N64 Plugin StartUp\n");
39     ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath)
40             dlsym(CoreLibHandle, "ConfigGetSharedDataFilepath");
41
42 #ifdef __NEON_OPT
43 /*    if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM &&
44             (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0)*/
45     {
46         MathInitNeon();
47         gSPInitNeon();
48     }
49 #endif
50     return M64ERR_SUCCESS;
51 }
52
53 EXPORT m64p_error CALL PluginShutdown(void)
54 {
55 }
56
57 EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType,
58         int *PluginVersion, int *APIVersion, const char **PluginNamePtr,
59         int *Capabilities)
60 {
61     /* set version info */
62     if (PluginType != NULL)
63         *PluginType = M64PLUGIN_GFX;
64
65     if (PluginVersion != NULL)
66         *PluginVersion = PLUGIN_VERSION;
67
68     if (APIVersion != NULL)
69         *APIVersion = PLUGIN_API_VERSION;
70     
71     if (PluginNamePtr != NULL)
72         *PluginNamePtr = PLUGIN_NAME;
73
74     if (Capabilities != NULL)
75     {
76         *Capabilities = 0;
77     }
78                     
79     return M64ERR_SUCCESS;
80 }
81
82 EXPORT void CALL ChangeWindow (void)
83 {
84 }
85
86 EXPORT void CALL MoveScreen (int xpos, int ypos)
87 {
88 }
89
90 EXPORT int CALL InitiateGFX (GFX_INFO Gfx_Info)
91 {
92 printf("InitateGFX\n");
93     DMEM = Gfx_Info.DMEM;
94     IMEM = Gfx_Info.IMEM;
95     RDRAM = Gfx_Info.RDRAM;
96
97     REG.MI_INTR = (u32*) Gfx_Info.MI_INTR_REG;
98     REG.DPC_START = (u32*) Gfx_Info.DPC_START_REG;
99     REG.DPC_END = (u32*) Gfx_Info.DPC_END_REG;
100     REG.DPC_CURRENT = (u32*) Gfx_Info.DPC_CURRENT_REG;
101     REG.DPC_STATUS = (u32*) Gfx_Info.DPC_STATUS_REG;
102     REG.DPC_CLOCK = (u32*) Gfx_Info.DPC_CLOCK_REG;
103     REG.DPC_BUFBUSY = (u32*) Gfx_Info.DPC_BUFBUSY_REG;
104     REG.DPC_PIPEBUSY = (u32*) Gfx_Info.DPC_PIPEBUSY_REG;
105     REG.DPC_TMEM = (u32*) Gfx_Info.DPC_TMEM_REG;
106
107     REG.VI_STATUS = (u32*) Gfx_Info.VI_STATUS_REG;
108     REG.VI_ORIGIN = (u32*) Gfx_Info.VI_ORIGIN_REG;
109     REG.VI_WIDTH = (u32*) Gfx_Info.VI_WIDTH_REG;
110     REG.VI_INTR = (u32*) Gfx_Info.VI_INTR_REG;
111     REG.VI_V_CURRENT_LINE = (u32*) Gfx_Info.VI_V_CURRENT_LINE_REG;
112     REG.VI_TIMING = (u32*) Gfx_Info.VI_TIMING_REG;
113     REG.VI_V_SYNC = (u32*) Gfx_Info.VI_V_SYNC_REG;
114     REG.VI_H_SYNC = (u32*) Gfx_Info.VI_H_SYNC_REG;
115     REG.VI_LEAP = (u32*) Gfx_Info.VI_LEAP_REG;
116     REG.VI_H_START = (u32*) Gfx_Info.VI_H_START_REG;
117     REG.VI_V_START = (u32*) Gfx_Info.VI_V_START_REG;
118     REG.VI_V_BURST = (u32*) Gfx_Info.VI_V_BURST_REG;
119     REG.VI_X_SCALE = (u32*) Gfx_Info.VI_X_SCALE_REG;
120     REG.VI_Y_SCALE = (u32*) Gfx_Info.VI_Y_SCALE_REG;
121
122     CheckInterrupts = Gfx_Info.CheckInterrupts;
123
124     Config_LoadConfig();
125     Config_LoadRomConfig(Gfx_Info.HEADER);
126
127     ticksInitialize();
128     if( config.autoFrameSkip )
129         frameSkipper.setSkips( FrameSkipper::AUTO, config.maxFrameSkip );
130     else
131         frameSkipper.setSkips( FrameSkipper::MANUAL, config.maxFrameSkip );
132
133         OGL_Start();
134
135     return 1;
136 }
137
138 EXPORT void CALL ProcessDList(void)
139 {
140     OGL.frame_dl++;
141
142     if (frameSkipper.willSkipNext())
143     {
144         OGL.frameSkipped++;
145         RSP.busy = FALSE;
146         RSP.DList++;
147
148         /* avoid hang on frameskip */
149         *REG.MI_INTR |= MI_INTR_DP;
150         CheckInterrupts();
151         *REG.MI_INTR |= MI_INTR_SP;
152         CheckInterrupts();
153         return;
154     }
155
156     OGL.consecutiveSkips = 0;
157     RSP_ProcessDList();
158     OGL.mustRenderDlist = true;
159 }
160
161 EXPORT void CALL ProcessRDPList(void)
162 {
163 }
164
165 EXPORT void CALL ResizeVideoOutput(int Width, int Height)
166 {
167 }
168
169 EXPORT void CALL RomClosed (void)
170 {
171     OGL_Stop();  // paulscode, OGL_Stop missing from Yongzh's code
172 }
173
174 EXPORT int CALL RomOpen (void)
175 {
176     RSP_Init();
177     OGL.frame_vsync = 0;
178     OGL.frame_dl = 0;
179     OGL.frame_prevdl = -1;
180     OGL.mustRenderDlist = false;
181
182     frameSkipper.setTargetFPS(config.romPAL ? 50 : 60);
183     return 1;
184 }
185
186 EXPORT void CALL RomResumed(void)
187 {
188     frameSkipper.start();
189 }
190
191 EXPORT void CALL ShowCFB (void)
192 {
193 }
194
195 EXPORT void CALL UpdateScreen (void)
196 {
197     frameSkipper.update();
198
199     //has there been any display lists since last update
200     if (OGL.frame_prevdl == OGL.frame_dl) return;
201
202     OGL.frame_prevdl = OGL.frame_dl;
203
204     if (OGL.frame_dl > 0) OGL.frame_vsync++;
205
206     if (OGL.mustRenderDlist)
207     {
208         OGL.screenUpdate=true;
209         VI_UpdateScreen();
210         OGL.mustRenderDlist = false;
211     }
212 }
213
214 EXPORT void CALL ViStatusChanged (void)
215 {
216 }
217
218 EXPORT void CALL ViWidthChanged (void)
219 {
220 }
221
222 /******************************************************************
223   Function: FrameBufferRead
224   Purpose:  This function is called to notify the dll that the
225             frame buffer memory is beening read at the given address.
226             DLL should copy content from its render buffer to the frame buffer
227             in N64 RDRAM
228             DLL is responsible to maintain its own frame buffer memory addr list
229             DLL should copy 4KB block content back to RDRAM frame buffer.
230             Emulator should not call this function again if other memory
231             is read within the same 4KB range
232
233             Since depth buffer is also being watched, the reported addr
234             may belong to depth buffer
235   input:    addr        rdram address
236             val         val
237             size        1 = uint8, 2 = uint16, 4 = uint32
238   output:   none
239 *******************************************************************/ 
240
241 EXPORT void CALL FBRead(u32 addr)
242 {
243 }
244
245 /******************************************************************
246   Function: FrameBufferWrite
247   Purpose:  This function is called to notify the dll that the
248             frame buffer has been modified by CPU at the given address.
249
250             Since depth buffer is also being watched, the reported addr
251             may belong to depth buffer
252
253   input:    addr        rdram address
254             val         val
255             size        1 = uint8, 2 = uint16, 4 = uint32
256   output:   none
257 *******************************************************************/ 
258
259 EXPORT void CALL FBWrite(u32 addr, u32 size)
260 {
261 }
262
263 /************************************************************************
264 Function: FBGetFrameBufferInfo
265 Purpose:  This function is called by the emulator core to retrieve frame
266           buffer information from the video plugin in order to be able
267           to notify the video plugin about CPU frame buffer read/write
268           operations
269
270           size:
271             = 1     byte
272             = 2     word (16 bit) <-- this is N64 default depth buffer format
273             = 4     dword (32 bit)
274
275           when frame buffer information is not available yet, set all values
276           in the FrameBufferInfo structure to 0
277
278 input:    FrameBufferInfo pinfo[6]
279           pinfo is pointed to a FrameBufferInfo structure which to be
280           filled in by this function
281 output:   Values are return in the FrameBufferInfo structure
282           Plugin can return up to 6 frame buffer info
283  ************************************************************************/
284
285 EXPORT void CALL FBGetFrameBufferInfo(void *p)
286 {
287 }
288
289 // paulscode, API changed this to "ReadScreen2" in Mupen64Plus 1.99.4
290 EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front)
291 {
292 /* TODO: 'int front' was added in 1.99.4.  What to do with this here? */
293     OGL_ReadScreen(dest, width, height);
294 }
295
296 EXPORT void CALL SetRenderingCallback(void (*callback)())
297 {
298     renderCallback = callback;
299 }
300
301 EXPORT void CALL SetFrameSkipping(bool autoSkip, int maxSkips)
302 {
303     frameSkipper.setSkips(
304             autoSkip ? FrameSkipper::AUTO : FrameSkipper::MANUAL,
305             maxSkips);
306 }
307
308 EXPORT void CALL SetStretchVideo(bool stretch)
309 {
310     config.stretchVideo = stretch;
311 }
312
313 EXPORT void CALL StartGL()
314 {
315     OGL_Start();
316 }
317
318 EXPORT void CALL StopGL()
319 {
320     OGL_Stop();
321 }
322
323 EXPORT void CALL ResizeGL(int width, int height)
324 {
325     const float ratio = (config.romPAL ? 9.0f/11.0f : 0.75f);
326     int videoWidth = width;
327     int videoHeight = height;
328
329     if (!config.stretchVideo) {
330         videoWidth = (int) (height / ratio);
331         if (videoWidth > width) {
332             videoWidth = width;
333             videoHeight = (int) (width * ratio);
334         }
335     }
336     int x = (width - videoWidth) / 2;
337     int y = (height - videoHeight) / 2;
338
339     OGL_ResizeWindow(x, y, videoWidth, videoHeight);
340 }
341
342 } // extern "C"
343