34cf4058 |
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 | |
90768f93 |
142 | #if 1 |
143 | if (config.autoFrameSkip) |
144 | { |
145 | OGL_UpdateFrameTime(); |
146 | |
147 | if (OGL.consecutiveSkips < 1) |
148 | { |
149 | unsigned t = 0; |
150 | for(int i = 0; i < OGL_FRAMETIME_NUM; i++) t += OGL.frameTime[i]; |
151 | t *= config.targetFPS; |
152 | if (config.romPAL) t = (t * 5) / 6; |
153 | if (t > (OGL_FRAMETIME_NUM * 1000)) |
154 | { |
155 | OGL.consecutiveSkips++; |
156 | OGL.frameSkipped++; |
157 | RSP.busy = FALSE; |
158 | RSP.DList++; |
159 | *REG.MI_INTR |= MI_INTR_SP | MI_INTR_DP; |
160 | CheckInterrupts(); |
161 | return; |
162 | } |
163 | } |
164 | } |
165 | else if ((OGL.frame_vsync % config.frameRenderRate) != 0) |
166 | { |
167 | OGL.frameSkipped++; |
168 | RSP.busy = FALSE; |
169 | RSP.DList++; |
170 | *REG.MI_INTR |= MI_INTR_SP | MI_INTR_DP; |
171 | CheckInterrupts(); |
172 | return; |
173 | } |
174 | #else |
34cf4058 |
175 | if (frameSkipper.willSkipNext()) |
176 | { |
177 | OGL.frameSkipped++; |
178 | RSP.busy = FALSE; |
179 | RSP.DList++; |
180 | |
181 | /* avoid hang on frameskip */ |
90768f93 |
182 | // *REG.MI_INTR |= MI_INTR_DP; |
183 | // CheckInterrupts(); |
184 | *REG.MI_INTR |= MI_INTR_SP | MI_INTR_DP; |
34cf4058 |
185 | CheckInterrupts(); |
186 | return; |
187 | } |
90768f93 |
188 | #endif |
34cf4058 |
189 | OGL.consecutiveSkips = 0; |
190 | RSP_ProcessDList(); |
191 | OGL.mustRenderDlist = true; |
192 | } |
193 | |
194 | EXPORT void CALL ProcessRDPList(void) |
195 | { |
196 | } |
197 | |
198 | EXPORT void CALL ResizeVideoOutput(int Width, int Height) |
199 | { |
200 | } |
201 | |
202 | EXPORT void CALL RomClosed (void) |
203 | { |
204 | OGL_Stop(); // paulscode, OGL_Stop missing from Yongzh's code |
205 | } |
206 | |
207 | EXPORT int CALL RomOpen (void) |
208 | { |
209 | RSP_Init(); |
210 | OGL.frame_vsync = 0; |
211 | OGL.frame_dl = 0; |
212 | OGL.frame_prevdl = -1; |
213 | OGL.mustRenderDlist = false; |
214 | |
215 | frameSkipper.setTargetFPS(config.romPAL ? 50 : 60); |
216 | return 1; |
217 | } |
218 | |
219 | EXPORT void CALL RomResumed(void) |
220 | { |
221 | frameSkipper.start(); |
222 | } |
223 | |
224 | EXPORT void CALL ShowCFB (void) |
225 | { |
226 | } |
227 | |
228 | EXPORT void CALL UpdateScreen (void) |
229 | { |
230 | frameSkipper.update(); |
231 | |
232 | //has there been any display lists since last update |
233 | if (OGL.frame_prevdl == OGL.frame_dl) return; |
234 | |
235 | OGL.frame_prevdl = OGL.frame_dl; |
236 | |
237 | if (OGL.frame_dl > 0) OGL.frame_vsync++; |
238 | |
239 | if (OGL.mustRenderDlist) |
240 | { |
241 | OGL.screenUpdate=true; |
242 | VI_UpdateScreen(); |
243 | OGL.mustRenderDlist = false; |
244 | } |
245 | } |
246 | |
247 | EXPORT void CALL ViStatusChanged (void) |
248 | { |
249 | } |
250 | |
251 | EXPORT void CALL ViWidthChanged (void) |
252 | { |
253 | } |
254 | |
255 | /****************************************************************** |
256 | Function: FrameBufferRead |
257 | Purpose: This function is called to notify the dll that the |
258 | frame buffer memory is beening read at the given address. |
259 | DLL should copy content from its render buffer to the frame buffer |
260 | in N64 RDRAM |
261 | DLL is responsible to maintain its own frame buffer memory addr list |
262 | DLL should copy 4KB block content back to RDRAM frame buffer. |
263 | Emulator should not call this function again if other memory |
264 | is read within the same 4KB range |
265 | |
266 | Since depth buffer is also being watched, the reported addr |
267 | may belong to depth buffer |
268 | input: addr rdram address |
269 | val val |
270 | size 1 = uint8, 2 = uint16, 4 = uint32 |
271 | output: none |
272 | *******************************************************************/ |
273 | |
274 | EXPORT void CALL FBRead(u32 addr) |
275 | { |
276 | } |
277 | |
278 | /****************************************************************** |
279 | Function: FrameBufferWrite |
280 | Purpose: This function is called to notify the dll that the |
281 | frame buffer has been modified by CPU at the given address. |
282 | |
283 | Since depth buffer is also being watched, the reported addr |
284 | may belong to depth buffer |
285 | |
286 | input: addr rdram address |
287 | val val |
288 | size 1 = uint8, 2 = uint16, 4 = uint32 |
289 | output: none |
290 | *******************************************************************/ |
291 | |
292 | EXPORT void CALL FBWrite(u32 addr, u32 size) |
293 | { |
294 | } |
295 | |
296 | /************************************************************************ |
297 | Function: FBGetFrameBufferInfo |
298 | Purpose: This function is called by the emulator core to retrieve frame |
299 | buffer information from the video plugin in order to be able |
300 | to notify the video plugin about CPU frame buffer read/write |
301 | operations |
302 | |
303 | size: |
304 | = 1 byte |
305 | = 2 word (16 bit) <-- this is N64 default depth buffer format |
306 | = 4 dword (32 bit) |
307 | |
308 | when frame buffer information is not available yet, set all values |
309 | in the FrameBufferInfo structure to 0 |
310 | |
311 | input: FrameBufferInfo pinfo[6] |
312 | pinfo is pointed to a FrameBufferInfo structure which to be |
313 | filled in by this function |
314 | output: Values are return in the FrameBufferInfo structure |
315 | Plugin can return up to 6 frame buffer info |
316 | ************************************************************************/ |
317 | |
318 | EXPORT void CALL FBGetFrameBufferInfo(void *p) |
319 | { |
320 | } |
321 | |
322 | // paulscode, API changed this to "ReadScreen2" in Mupen64Plus 1.99.4 |
323 | EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front) |
324 | { |
325 | /* TODO: 'int front' was added in 1.99.4. What to do with this here? */ |
326 | OGL_ReadScreen(dest, width, height); |
327 | } |
328 | |
329 | EXPORT void CALL SetRenderingCallback(void (*callback)()) |
330 | { |
331 | renderCallback = callback; |
332 | } |
333 | |
334 | EXPORT void CALL SetFrameSkipping(bool autoSkip, int maxSkips) |
335 | { |
336 | frameSkipper.setSkips( |
337 | autoSkip ? FrameSkipper::AUTO : FrameSkipper::MANUAL, |
338 | maxSkips); |
339 | } |
340 | |
341 | EXPORT void CALL SetStretchVideo(bool stretch) |
342 | { |
343 | config.stretchVideo = stretch; |
344 | } |
345 | |
346 | EXPORT void CALL StartGL() |
347 | { |
348 | OGL_Start(); |
349 | } |
350 | |
351 | EXPORT void CALL StopGL() |
352 | { |
353 | OGL_Stop(); |
354 | } |
355 | |
356 | EXPORT void CALL ResizeGL(int width, int height) |
357 | { |
358 | const float ratio = (config.romPAL ? 9.0f/11.0f : 0.75f); |
359 | int videoWidth = width; |
360 | int videoHeight = height; |
361 | |
362 | if (!config.stretchVideo) { |
363 | videoWidth = (int) (height / ratio); |
364 | if (videoWidth > width) { |
365 | videoWidth = width; |
366 | videoHeight = (int) (width * ratio); |
367 | } |
368 | } |
369 | int x = (width - videoWidth) / 2; |
370 | int y = (height - videoHeight) / 2; |
371 | |
372 | OGL_ResizeWindow(x, y, videoWidth, videoHeight); |
373 | } |
374 | |
375 | } // extern "C" |
376 | |