Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / plugin / plugin.c
CommitLineData
451ab91e 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus - plugin.c *
3 * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4 * Copyright (C) 2002 Hacktarux *
5 * Copyright (C) 2009 Richard Goedeken *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
21 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
22
23#include <stdlib.h>
24
25#include "plugin.h"
26
27#include "api/callbacks.h"
28#include "api/m64p_common.h"
29#include "api/m64p_plugin.h"
30#include "api/m64p_types.h"
31
32#include "main/rom.h"
33#include "main/version.h"
34#include "memory/memory.h"
35
36#include "osal/dynamiclib.h"
37
38#include "dummy_audio.h"
39#include "dummy_video.h"
40#include "dummy_input.h"
41#include "dummy_rsp.h"
42
43CONTROL Controls[4];
44
45/* global function pointers - initialized on core startup */
46gfx_plugin_functions gfx;
47audio_plugin_functions audio;
48input_plugin_functions input;
49rsp_plugin_functions rsp;
50
51/* local data structures and functions */
52static const gfx_plugin_functions dummy_gfx = {
53 dummyvideo_PluginGetVersion,
54 dummyvideo_ChangeWindow,
55 dummyvideo_InitiateGFX,
56 dummyvideo_MoveScreen,
57 dummyvideo_ProcessDList,
58 dummyvideo_ProcessRDPList,
59 dummyvideo_RomClosed,
60 dummyvideo_RomOpen,
61 dummyvideo_ShowCFB,
62 dummyvideo_UpdateScreen,
63 dummyvideo_ViStatusChanged,
64 dummyvideo_ViWidthChanged,
65 dummyvideo_ReadScreen2,
66 dummyvideo_SetRenderingCallback,
67 dummyvideo_ResizeVideoOutput,
68 dummyvideo_FBRead,
69 dummyvideo_FBWrite,
70 dummyvideo_FBGetFrameBufferInfo
71};
72
73static const audio_plugin_functions dummy_audio = {
74 dummyaudio_PluginGetVersion,
75 dummyaudio_AiDacrateChanged,
76 dummyaudio_AiLenChanged,
77 dummyaudio_InitiateAudio,
78 dummyaudio_ProcessAList,
79 dummyaudio_RomClosed,
80 dummyaudio_RomOpen,
81 dummyaudio_SetSpeedFactor,
82 dummyaudio_VolumeUp,
83 dummyaudio_VolumeDown,
84 dummyaudio_VolumeGetLevel,
85 dummyaudio_VolumeSetLevel,
86 dummyaudio_VolumeMute,
87 dummyaudio_VolumeGetString
88};
89
90static const input_plugin_functions dummy_input = {
91 dummyinput_PluginGetVersion,
92 dummyinput_ControllerCommand,
93 dummyinput_GetKeys,
94 dummyinput_InitiateControllers,
95 dummyinput_ReadController,
96 dummyinput_RomClosed,
97 dummyinput_RomOpen,
98 dummyinput_SDL_KeyDown,
99 dummyinput_SDL_KeyUp
100};
101
102static const rsp_plugin_functions dummy_rsp = {
103 dummyrsp_PluginGetVersion,
104 dummyrsp_DoRspCycles,
105 dummyrsp_InitiateRSP,
106 dummyrsp_RomClosed
107};
108
109static GFX_INFO gfx_info;
110static AUDIO_INFO audio_info;
111static CONTROL_INFO control_info;
112static RSP_INFO rsp_info;
113
114static int l_RspAttached = 0;
115static int l_InputAttached = 0;
116static int l_AudioAttached = 0;
117static int l_GfxAttached = 0;
118
119static unsigned int dummy;
120
121/* local functions */
122static void EmptyFunc(void)
123{
124}
125
126// Handy macro to avoid code bloat when loading symbols
127#define GET_FUNC(type, field, name) \
128 ((field = (type)osal_dynlib_getproc(plugin_handle, name)) != NULL)
129
130// code to handle backwards-compatibility to video plugins with API_VERSION < 02.1.0. This API version introduced a boolean
131// flag in the rendering callback, which told the core whether or not the current screen has been freshly redrawn since the
132// last time the callback was called.
133static void (*l_mainRenderCallback)(int) = NULL;
134static ptr_SetRenderingCallback l_old1SetRenderingCallback = NULL;
135
136static void backcompat_videoRenderCallback(int unused) // this function will be called by the video plugin as the render callback
137{
138 if (l_mainRenderCallback != NULL)
139 l_mainRenderCallback(1); // assume screen is always freshly redrawn (otherwise screenshots won't work w/ OSD enabled)
140}
141
142static void backcompat_setRenderCallbackIntercept(void (*callback)(int))
143{
144 l_mainRenderCallback = callback;
145}
146
147static void plugin_disconnect_gfx(void)
148{
149 gfx = dummy_gfx;
150 l_GfxAttached = 0;
151 l_mainRenderCallback = NULL;
152}
153
154static m64p_error plugin_connect_gfx(m64p_dynlib_handle plugin_handle)
155{
156 /* attach the Video plugin function pointers */
157 if (plugin_handle != NULL)
158 {
159 m64p_plugin_type PluginType;
160 int PluginVersion, APIVersion;
161
162 if (l_GfxAttached)
163 return M64ERR_INVALID_STATE;
164
165 /* set function pointers for required functions */
166 if (!GET_FUNC(ptr_PluginGetVersion, gfx.getVersion, "PluginGetVersion") ||
167 !GET_FUNC(ptr_ChangeWindow, gfx.changeWindow, "ChangeWindow") ||
168 !GET_FUNC(ptr_InitiateGFX, gfx.initiateGFX, "InitiateGFX") ||
169 !GET_FUNC(ptr_MoveScreen, gfx.moveScreen, "MoveScreen") ||
170 !GET_FUNC(ptr_ProcessDList, gfx.processDList, "ProcessDList") ||
171 !GET_FUNC(ptr_ProcessRDPList, gfx.processRDPList, "ProcessRDPList") ||
172 !GET_FUNC(ptr_RomClosed, gfx.romClosed, "RomClosed") ||
173 !GET_FUNC(ptr_RomOpen, gfx.romOpen, "RomOpen") ||
174 !GET_FUNC(ptr_ShowCFB, gfx.showCFB, "ShowCFB") ||
175 !GET_FUNC(ptr_UpdateScreen, gfx.updateScreen, "UpdateScreen") ||
176 !GET_FUNC(ptr_ViStatusChanged, gfx.viStatusChanged, "ViStatusChanged") ||
177 !GET_FUNC(ptr_ViWidthChanged, gfx.viWidthChanged, "ViWidthChanged") ||
178 !GET_FUNC(ptr_ReadScreen2, gfx.readScreen, "ReadScreen2") ||
179 !GET_FUNC(ptr_SetRenderingCallback, gfx.setRenderingCallback, "SetRenderingCallback") ||
180 !GET_FUNC(ptr_FBRead, gfx.fBRead, "FBRead") ||
181 !GET_FUNC(ptr_FBWrite, gfx.fBWrite, "FBWrite") ||
182 !GET_FUNC(ptr_FBGetFrameBufferInfo, gfx.fBGetFrameBufferInfo, "FBGetFrameBufferInfo"))
183 {
184 DebugMessage(M64MSG_ERROR, "broken Video plugin; function(s) not found.");
185 plugin_disconnect_gfx();
186 return M64ERR_INPUT_INVALID;
187 }
188
189 /* set function pointers for optional functions */
190 gfx.resizeVideoOutput = (ptr_ResizeVideoOutput) osal_dynlib_getproc(plugin_handle, "ResizeVideoOutput");
191
192 /* check the version info */
193 (*gfx.getVersion)(&PluginType, &PluginVersion, &APIVersion, NULL, NULL);
194 if (PluginType != M64PLUGIN_GFX || (APIVersion & 0xffff0000) != (GFX_API_VERSION & 0xffff0000))
195 {
196 DebugMessage(M64MSG_ERROR, "incompatible Video plugin");
197 plugin_disconnect_gfx();
198 return M64ERR_INCOMPATIBLE;
199 }
200
201 /* handle backwards-compatibility */
202 if (APIVersion < 0x020100)
203 {
204 DebugMessage(M64MSG_WARNING, "Fallback for Video plugin API (%02i.%02i.%02i) < 2.1.0. Screenshots may contain On Screen Display text", VERSION_PRINTF_SPLIT(APIVersion));
205 // tell the video plugin to make its rendering callback to me (it's old, and doesn't have the bScreenRedrawn flag)
206 gfx.setRenderingCallback(backcompat_videoRenderCallback);
207 l_old1SetRenderingCallback = gfx.setRenderingCallback; // save this just for future use
208 gfx.setRenderingCallback = (ptr_SetRenderingCallback) backcompat_setRenderCallbackIntercept;
209 }
210 if (APIVersion < 0x20200 || gfx.resizeVideoOutput == NULL)
211 {
212 DebugMessage(M64MSG_WARNING, "Fallback for Video plugin API (%02i.%02i.%02i) < 2.2.0. Resizable video will not work", VERSION_PRINTF_SPLIT(APIVersion));
213 gfx.resizeVideoOutput = dummyvideo_ResizeVideoOutput;
214 }
215
216 l_GfxAttached = 1;
217 }
218 else
219 plugin_disconnect_gfx();
220
221 return M64ERR_SUCCESS;
222}
223
224static m64p_error plugin_start_gfx(void)
225{
226 /* fill in the GFX_INFO data structure */
227 gfx_info.HEADER = (unsigned char *) rom;
228 gfx_info.RDRAM = (unsigned char *) rdram;
229 gfx_info.DMEM = (unsigned char *) SP_DMEM;
230 gfx_info.IMEM = (unsigned char *) SP_IMEM;
231 gfx_info.MI_INTR_REG = &(MI_register.mi_intr_reg);
232 gfx_info.DPC_START_REG = &(dpc_register.dpc_start);
233 gfx_info.DPC_END_REG = &(dpc_register.dpc_end);
234 gfx_info.DPC_CURRENT_REG = &(dpc_register.dpc_current);
235 gfx_info.DPC_STATUS_REG = &(dpc_register.dpc_status);
236 gfx_info.DPC_CLOCK_REG = &(dpc_register.dpc_clock);
237 gfx_info.DPC_BUFBUSY_REG = &(dpc_register.dpc_bufbusy);
238 gfx_info.DPC_PIPEBUSY_REG = &(dpc_register.dpc_pipebusy);
239 gfx_info.DPC_TMEM_REG = &(dpc_register.dpc_tmem);
240 gfx_info.VI_STATUS_REG = &(vi_register.vi_status);
241 gfx_info.VI_ORIGIN_REG = &(vi_register.vi_origin);
242 gfx_info.VI_WIDTH_REG = &(vi_register.vi_width);
243 gfx_info.VI_INTR_REG = &(vi_register.vi_v_intr);
244 gfx_info.VI_V_CURRENT_LINE_REG = &(vi_register.vi_current);
245 gfx_info.VI_TIMING_REG = &(vi_register.vi_burst);
246 gfx_info.VI_V_SYNC_REG = &(vi_register.vi_v_sync);
247 gfx_info.VI_H_SYNC_REG = &(vi_register.vi_h_sync);
248 gfx_info.VI_LEAP_REG = &(vi_register.vi_leap);
249 gfx_info.VI_H_START_REG = &(vi_register.vi_h_start);
250 gfx_info.VI_V_START_REG = &(vi_register.vi_v_start);
251 gfx_info.VI_V_BURST_REG = &(vi_register.vi_v_burst);
252 gfx_info.VI_X_SCALE_REG = &(vi_register.vi_x_scale);
253 gfx_info.VI_Y_SCALE_REG = &(vi_register.vi_y_scale);
254 gfx_info.CheckInterrupts = EmptyFunc;
255
256 /* call the audio plugin */
257 if (!gfx.initiateGFX(gfx_info))
258 return M64ERR_PLUGIN_FAIL;
259
260 return M64ERR_SUCCESS;
261}
262
263static void plugin_disconnect_audio(void)
264{
265 audio = dummy_audio;
266 l_AudioAttached = 0;
267}
268
269static m64p_error plugin_connect_audio(m64p_dynlib_handle plugin_handle)
270{
271 /* attach the Audio plugin function pointers */
272 if (plugin_handle != NULL)
273 {
274 m64p_plugin_type PluginType;
275 int PluginVersion, APIVersion;
276
277 if (l_AudioAttached)
278 return M64ERR_INVALID_STATE;
279
280 if (!GET_FUNC(ptr_PluginGetVersion, audio.getVersion, "PluginGetVersion") ||
281 !GET_FUNC(ptr_AiDacrateChanged, audio.aiDacrateChanged, "AiDacrateChanged") ||
282 !GET_FUNC(ptr_AiLenChanged, audio.aiLenChanged, "AiLenChanged") ||
283 !GET_FUNC(ptr_InitiateAudio, audio.initiateAudio, "InitiateAudio") ||
284 !GET_FUNC(ptr_ProcessAList, audio.processAList, "ProcessAList") ||
285 !GET_FUNC(ptr_RomOpen, audio.romOpen, "RomOpen") ||
286 !GET_FUNC(ptr_RomClosed, audio.romClosed, "RomClosed") ||
287 !GET_FUNC(ptr_SetSpeedFactor, audio.setSpeedFactor, "SetSpeedFactor") ||
288 !GET_FUNC(ptr_VolumeUp, audio.volumeUp, "VolumeUp") ||
289 !GET_FUNC(ptr_VolumeDown, audio.volumeDown, "VolumeDown") ||
290 !GET_FUNC(ptr_VolumeGetLevel, audio.volumeGetLevel, "VolumeGetLevel") ||
291 !GET_FUNC(ptr_VolumeSetLevel, audio.volumeSetLevel, "VolumeSetLevel") ||
292 !GET_FUNC(ptr_VolumeMute, audio.volumeMute, "VolumeMute") ||
293 !GET_FUNC(ptr_VolumeGetString, audio.volumeGetString, "VolumeGetString"))
294 {
295 DebugMessage(M64MSG_ERROR, "broken Audio plugin; function(s) not found.");
296 plugin_disconnect_audio();
297 return M64ERR_INPUT_INVALID;
298 }
299
300 /* check the version info */
301 (*audio.getVersion)(&PluginType, &PluginVersion, &APIVersion, NULL, NULL);
302 if (PluginType != M64PLUGIN_AUDIO || (APIVersion & 0xffff0000) != (AUDIO_API_VERSION & 0xffff0000))
303 {
304 DebugMessage(M64MSG_ERROR, "incompatible Audio plugin");
305 plugin_disconnect_audio();
306 return M64ERR_INCOMPATIBLE;
307 }
308
309 l_AudioAttached = 1;
310 }
311 else
312 plugin_disconnect_audio();
313
314 return M64ERR_SUCCESS;
315}
316
317static m64p_error plugin_start_audio(void)
318{
319 /* fill in the AUDIO_INFO data structure */
320 audio_info.RDRAM = (unsigned char *) rdram;
321 audio_info.DMEM = (unsigned char *) SP_DMEM;
322 audio_info.IMEM = (unsigned char *) SP_IMEM;
323 audio_info.MI_INTR_REG = &(MI_register.mi_intr_reg);
324 audio_info.AI_DRAM_ADDR_REG = &(ai_register.ai_dram_addr);
325 audio_info.AI_LEN_REG = &(ai_register.ai_len);
326 audio_info.AI_CONTROL_REG = &(ai_register.ai_control);
327 audio_info.AI_STATUS_REG = &dummy;
328 audio_info.AI_DACRATE_REG = &(ai_register.ai_dacrate);
329 audio_info.AI_BITRATE_REG = &(ai_register.ai_bitrate);
330 audio_info.CheckInterrupts = EmptyFunc;
331
332 /* call the audio plugin */
333 if (!audio.initiateAudio(audio_info))
334 return M64ERR_PLUGIN_FAIL;
335
336 return M64ERR_SUCCESS;
337}
338
339static void plugin_disconnect_input(void)
340{
341 input = dummy_input;
342 l_InputAttached = 0;
343}
344
345static m64p_error plugin_connect_input(m64p_dynlib_handle plugin_handle)
346{
347 /* attach the Input plugin function pointers */
348 if (plugin_handle != NULL)
349 {
350 m64p_plugin_type PluginType;
351 int PluginVersion, APIVersion;
352
353 if (l_InputAttached)
354 return M64ERR_INVALID_STATE;
355
356 if (!GET_FUNC(ptr_PluginGetVersion, input.getVersion, "PluginGetVersion") ||
357 !GET_FUNC(ptr_ControllerCommand, input.controllerCommand, "ControllerCommand") ||
358 !GET_FUNC(ptr_GetKeys, input.getKeys, "GetKeys") ||
359 !GET_FUNC(ptr_InitiateControllers, input.initiateControllers, "InitiateControllers") ||
360 !GET_FUNC(ptr_ReadController, input.readController, "ReadController") ||
361 !GET_FUNC(ptr_RomOpen, input.romOpen, "RomOpen") ||
362 !GET_FUNC(ptr_RomClosed, input.romClosed, "RomClosed") ||
363 !GET_FUNC(ptr_SDL_KeyDown, input.keyDown, "SDL_KeyDown") ||
364 !GET_FUNC(ptr_SDL_KeyUp, input.keyUp, "SDL_KeyUp"))
365 {
366 DebugMessage(M64MSG_ERROR, "broken Input plugin; function(s) not found.");
367 plugin_disconnect_input();
368 return M64ERR_INPUT_INVALID;
369 }
370
371 /* check the version info */
372 (*input.getVersion)(&PluginType, &PluginVersion, &APIVersion, NULL, NULL);
373 if (PluginType != M64PLUGIN_INPUT || (APIVersion & 0xffff0000) != (INPUT_API_VERSION & 0xffff0000))
374 {
375 DebugMessage(M64MSG_ERROR, "incompatible Input plugin");
376 plugin_disconnect_input();
377 return M64ERR_INCOMPATIBLE;
378 }
379
380 l_InputAttached = 1;
381 }
382 else
383 plugin_disconnect_input();
384
385 return M64ERR_SUCCESS;
386}
387
388static m64p_error plugin_start_input(void)
389{
390 int i;
391
392 /* fill in the CONTROL_INFO data structure */
393 control_info.Controls = Controls;
394 for (i=0; i<4; i++)
395 {
396 Controls[i].Present = 0;
397 Controls[i].RawData = 0;
398 Controls[i].Plugin = PLUGIN_NONE;
399 }
400
401 /* call the input plugin */
402 input.initiateControllers(control_info);
403
404 return M64ERR_SUCCESS;
405}
406
407static void plugin_disconnect_rsp(void)
408{
409 rsp = dummy_rsp;
410 l_RspAttached = 0;
411}
412
413static m64p_error plugin_connect_rsp(m64p_dynlib_handle plugin_handle)
414{
415 /* attach the RSP plugin function pointers */
416 if (plugin_handle != NULL)
417 {
418 m64p_plugin_type PluginType;
419 int PluginVersion, APIVersion;
420
421 if (l_RspAttached)
422 return M64ERR_INVALID_STATE;
423
424 if (!GET_FUNC(ptr_PluginGetVersion, rsp.getVersion, "PluginGetVersion") ||
425 !GET_FUNC(ptr_DoRspCycles, rsp.doRspCycles, "DoRspCycles") ||
426 !GET_FUNC(ptr_InitiateRSP, rsp.initiateRSP, "InitiateRSP") ||
427 !GET_FUNC(ptr_RomClosed, rsp.romClosed, "RomClosed"))
428 {
429 DebugMessage(M64MSG_ERROR, "broken RSP plugin; function(s) not found.");
430 plugin_disconnect_rsp();
431 return M64ERR_INPUT_INVALID;
432 }
433
434 /* check the version info */
435 (*rsp.getVersion)(&PluginType, &PluginVersion, &APIVersion, NULL, NULL);
436 if (PluginType != M64PLUGIN_RSP || (APIVersion & 0xffff0000) != (RSP_API_VERSION & 0xffff0000))
437 {
438 DebugMessage(M64MSG_ERROR, "incompatible RSP plugin");
439 plugin_disconnect_rsp();
440 return M64ERR_INCOMPATIBLE;
441 }
442
443 l_RspAttached = 1;
444 }
445 else
446 plugin_disconnect_rsp();
447
448 return M64ERR_SUCCESS;
449}
450
451static m64p_error plugin_start_rsp(void)
452{
453 /* fill in the RSP_INFO data structure */
454 rsp_info.RDRAM = (unsigned char *) rdram;
455 rsp_info.DMEM = (unsigned char *) SP_DMEM;
456 rsp_info.IMEM = (unsigned char *) SP_IMEM;
457 rsp_info.MI_INTR_REG = &MI_register.mi_intr_reg;
458 rsp_info.SP_MEM_ADDR_REG = &sp_register.sp_mem_addr_reg;
459 rsp_info.SP_DRAM_ADDR_REG = &sp_register.sp_dram_addr_reg;
460 rsp_info.SP_RD_LEN_REG = &sp_register.sp_rd_len_reg;
461 rsp_info.SP_WR_LEN_REG = &sp_register.sp_wr_len_reg;
462 rsp_info.SP_STATUS_REG = &sp_register.sp_status_reg;
463 rsp_info.SP_DMA_FULL_REG = &sp_register.sp_dma_full_reg;
464 rsp_info.SP_DMA_BUSY_REG = &sp_register.sp_dma_busy_reg;
465 rsp_info.SP_PC_REG = &rsp_register.rsp_pc;
466 rsp_info.SP_SEMAPHORE_REG = &sp_register.sp_semaphore_reg;
467 rsp_info.DPC_START_REG = &dpc_register.dpc_start;
468 rsp_info.DPC_END_REG = &dpc_register.dpc_end;
469 rsp_info.DPC_CURRENT_REG = &dpc_register.dpc_current;
470 rsp_info.DPC_STATUS_REG = &dpc_register.dpc_status;
471 rsp_info.DPC_CLOCK_REG = &dpc_register.dpc_clock;
472 rsp_info.DPC_BUFBUSY_REG = &dpc_register.dpc_bufbusy;
473 rsp_info.DPC_PIPEBUSY_REG = &dpc_register.dpc_pipebusy;
474 rsp_info.DPC_TMEM_REG = &dpc_register.dpc_tmem;
475 rsp_info.CheckInterrupts = EmptyFunc;
476 rsp_info.ProcessDlistList = gfx.processDList;
477 rsp_info.ProcessAlistList = audio.processAList;
478 rsp_info.ProcessRdpList = gfx.processRDPList;
479 rsp_info.ShowCFB = gfx.showCFB;
480
481 /* call the RSP plugin */
482 rsp.initiateRSP(rsp_info, NULL);
483
484 return M64ERR_SUCCESS;
485}
486
487/* global functions */
488m64p_error plugin_connect(m64p_plugin_type type, m64p_dynlib_handle plugin_handle)
489{
490 switch(type)
491 {
492 case M64PLUGIN_GFX:
493 if (plugin_handle != NULL && (l_AudioAttached || l_InputAttached || l_RspAttached))
494 DebugMessage(M64MSG_WARNING, "Front-end bug: plugins are attached in wrong order.");
495 return plugin_connect_gfx(plugin_handle);
496 case M64PLUGIN_AUDIO:
497 if (plugin_handle != NULL && (l_InputAttached || l_RspAttached))
498 DebugMessage(M64MSG_WARNING, "Front-end bug: plugins are attached in wrong order.");
499 return plugin_connect_audio(plugin_handle);
500 case M64PLUGIN_INPUT:
501 if (plugin_handle != NULL && (l_RspAttached))
502 DebugMessage(M64MSG_WARNING, "Front-end bug: plugins are attached in wrong order.");
503 return plugin_connect_input(plugin_handle);
504 case M64PLUGIN_RSP:
505 return plugin_connect_rsp(plugin_handle);
506 default:
507 return M64ERR_INPUT_INVALID;
508 }
509
510 return M64ERR_INTERNAL;
511}
512
513m64p_error plugin_start(m64p_plugin_type type)
514{
515 switch(type)
516 {
517 case M64PLUGIN_RSP:
518 return plugin_start_rsp();
519 case M64PLUGIN_GFX:
520 return plugin_start_gfx();
521 case M64PLUGIN_AUDIO:
522 return plugin_start_audio();
523 case M64PLUGIN_INPUT:
524 return plugin_start_input();
525 default:
526 return M64ERR_INPUT_INVALID;
527 }
528
529 return M64ERR_INTERNAL;
530}
531
532m64p_error plugin_check(void)
533{
534 if (!l_GfxAttached)
535 DebugMessage(M64MSG_WARNING, "No video plugin attached. There will be no video output.");
536 if (!l_RspAttached)
537 DebugMessage(M64MSG_WARNING, "No RSP plugin attached. The video output will be corrupted.");
538 if (!l_AudioAttached)
539 DebugMessage(M64MSG_WARNING, "No audio plugin attached. There will be no sound output.");
540 if (!l_InputAttached)
541 DebugMessage(M64MSG_WARNING, "No input plugin attached. You won't be able to control the game.");
542
543 return M64ERR_SUCCESS;
544}
545