RSP LLE plugin. Compile and run (slowly, eat 50% CPU) on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-rsp-z64 / src / main_rsp.cpp
1 /*
2  * z64
3  *
4  * Copyright (C) 2007  ziggy
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20 **/
21
22 #include "rsp.h"
23 #include <assert.h>
24 #include <stdarg.h>
25
26 #define RSP_Z64_VERSION        0x020000
27 #define RSP_PLUGIN_API_VERSION 0x020000
28
29 static void (*l_DebugCallback)(void *, int, const char *) = NULL;
30 static void *l_DebugCallContext = NULL;
31 static bool l_PluginInit = false;
32
33 #if 0
34 static void dump()
35 {
36     FILE * fp = fopen("rsp.dump", "w");
37     assert(fp);
38     fwrite(rdram, 8*1024, 1024, fp);
39     fwrite(rsp_dmem, 0x2000, 1, fp);
40     fwrite(rsp.ext.MI_INTR_REG, 4, 1, fp);
41
42     fwrite(rsp.ext.SP_MEM_ADDR_REG, 4, 1, fp);
43     fwrite(rsp.ext.SP_DRAM_ADDR_REG, 4, 1, fp);
44     fwrite(rsp.ext.SP_RD_LEN_REG, 4, 1, fp);
45     fwrite(rsp.ext.SP_WR_LEN_REG, 4, 1, fp);
46     fwrite(rsp.ext.SP_STATUS_REG, 4, 1, fp);
47     fwrite(rsp.ext.SP_DMA_FULL_REG, 4, 1, fp);
48     fwrite(rsp.ext.SP_DMA_BUSY_REG, 4, 1, fp);
49     fwrite(rsp.ext.SP_PC_REG, 4, 1, fp);
50     fwrite(rsp.ext.SP_SEMAPHORE_REG, 4, 1, fp);
51
52     fwrite(rsp.ext.DPC_START_REG, 4, 1, fp);
53     fwrite(rsp.ext.DPC_END_REG, 4, 1, fp);
54     fwrite(rsp.ext.DPC_CURRENT_REG, 4, 1, fp);
55     fwrite(rsp.ext.DPC_STATUS_REG, 4, 1, fp);
56     fwrite(rsp.ext.DPC_CLOCK_REG, 4, 1, fp);
57     fwrite(rsp.ext.DPC_BUFBUSY_REG, 4, 1, fp);
58     fwrite(rsp.ext.DPC_PIPEBUSY_REG, 4, 1, fp);
59     fwrite(rsp.ext.DPC_TMEM_REG, 4, 1, fp);
60     fclose(fp);
61 }
62 #endif
63
64 void log(m64p_msg_level level, const char *msg, ...)
65 {
66     char buf[1024];
67     va_list args;
68     va_start(args, msg);
69     vsnprintf(buf, 1023, msg, args);
70     buf[1023]='\0';
71     va_end(args);
72     if (l_DebugCallback)
73     {
74         l_DebugCallback(l_DebugCallContext, level, buf);
75     }
76 }
77
78 #ifdef __cplusplus
79 extern "C" {
80 #endif
81
82     /* DLL-exported functions */
83     EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
84         void (*DebugCallback)(void *, int, const char *))
85     {
86
87         if (l_PluginInit)
88             return M64ERR_ALREADY_INIT;
89
90         ///* first thing is to set the callback function for debug info */
91         l_DebugCallback = DebugCallback;
92         l_DebugCallContext = Context;
93
94         ///* this plugin doesn't use any Core library functions (ex for Configuration), so no need to keep the CoreLibHandle */
95
96         l_PluginInit = true;
97         return M64ERR_SUCCESS;
98     }
99
100     EXPORT m64p_error CALL PluginShutdown(void)
101     {
102         if (!l_PluginInit)
103             return M64ERR_NOT_INIT;
104
105         ///* reset some local variable */
106         l_DebugCallback = NULL;
107         l_DebugCallContext = NULL;
108
109         l_PluginInit = 0;
110         return M64ERR_SUCCESS;
111     }
112
113     EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
114     {
115         /* set version info */
116         if (PluginType != NULL)
117             *PluginType = M64PLUGIN_RSP;
118
119         if (PluginVersion != NULL)
120             *PluginVersion = RSP_Z64_VERSION;
121
122         if (APIVersion != NULL)
123             *APIVersion = RSP_PLUGIN_API_VERSION;
124
125         if (PluginNamePtr != NULL)
126             *PluginNamePtr = "Z64 RSP Plugin";
127
128         if (Capabilities != NULL)
129         {
130             *Capabilities = 0;
131         }
132
133         return M64ERR_SUCCESS;
134     }
135
136     EXPORT unsigned int CALL DoRspCycles(unsigned int Cycles)
137     {
138         //#define VIDEO_HLE_ALLOWED
139         //#define AUDIO_HLE_ALLOWED
140
141 #if defined (AUDIO_HLE_ALLOWED) || defined (VIDEO_HLE_ALLOWED)
142         unsigned int TaskType = *(unsigned int *)(z64_rspinfo.DMEM + 0xFC0);
143 #endif
144
145 #ifdef VIDEO_HLE_ALLOWED
146 #if 0
147         if (TaskType == 1) {
148             SDL_Event event;
149             while (SDL_PollEvent(&event)) {
150                 switch (event.type) {
151                     case SDL_KEYDOWN:
152                         switch (event.key.keysym.sym) {
153                             case 'd':
154                                 printf("Dumping !\n");
155                                 dump();
156                                 break;
157                         }
158                         break;
159                 }
160             }
161         }
162 #endif
163
164         if (TaskType == 1) {
165             if (z64_rspinfo.ProcessDlistList != NULL) {
166                 z64_rspinfo.ProcessDlistList();
167             }
168             *z64_rspinfo.SP_STATUS_REG |= (0x0203);
169             if ((*z64_rspinfo.SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) {
170                 *z64_rspinfo.MI_INTR_REG |= R4300i_SP_Intr;
171                 z64_rspinfo.CheckInterrupts();
172             }
173
174             *z64_rspinfo.DPC_STATUS_REG &= ~0x0002;
175             return Cycles;
176         }
177 #endif
178
179 #ifdef AUDIO_HLE_ALLOWED
180         if (TaskType == 2) {
181             if (z64_rspinfo.ProcessAlistList != NULL) {
182                 z64_rspinfo.ProcessAlistList();
183             }
184             *z64_rspinfo.SP_STATUS_REG |= (0x0203);
185             if ((*z64_rspinfo.SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) {
186                 *z64_rspinfo.MI_INTR_REG |= R4300i_SP_Intr;
187                 z64_rspinfo.CheckInterrupts();
188             }
189             return Cycles;
190         }  
191 #endif
192
193         if (z64_rspinfo.CheckInterrupts==NULL)
194             log(M64MSG_WARNING, "Emulator doesn't provide CheckInterrupts routine");
195         return rsp_execute(0x100000);
196         //return Cycles;
197     }
198
199     EXPORT void CALL InitiateRSP(RSP_INFO Rsp_Info, unsigned int *CycleCount)
200     {
201         log(M64MSG_STATUS, "INITIATE RSP");
202         rsp_init(Rsp_Info);
203         memset(((UINT32*)z64_rspinfo.DMEM), 0, 0x2000);
204         //*CycleCount = 0; //Causes segfault, doesn't seem to be used anyway
205     }
206
207     EXPORT void CALL RomClosed(void)
208     {
209         extern int rsp_gen_cache_hit;
210         extern int rsp_gen_cache_miss;
211         log(M64MSG_STATUS, "cache hit %d miss %d %g%%", rsp_gen_cache_hit, rsp_gen_cache_miss,
212             rsp_gen_cache_miss*100.0f/rsp_gen_cache_hit);
213         rsp_gen_cache_hit = rsp_gen_cache_miss = 0;
214
215 #ifdef RSPTIMING
216         int i,j;
217         UINT32 op, op2;
218
219         for(i=0; i<0x140;i++) {
220             if (i>=0x100)
221                 op = (0x12<<26) | (0x10 << 21) | (i&0x3f);
222             else if (i>=0xc0)
223                 op = (0x3a<<26) | ((i&0x1f)<<11);
224             else if (i>=0xa0)
225                 op = (0x32<<26) | ((i&0x1f)<<11);
226             else if (i>=0x80)
227                 op = (0x12<<26) | ((i&0x1f)<<21);
228             else if (i>=0x40)
229                 op = (0<<26) | (i&0x3f);
230             else
231                 op = (i&0x3f)<<26;
232
233             char s[128], s2[128];
234             rsp_dasm_one(s, 0x800, op);
235             //rsp_dasm_one(s2, 0x800, op2);
236             if (rsptimings[i])
237                 printf("%10g %10g %7d\t%30s\n"
238                 /*"%10g %10g %7d\t%30s\n"*/,
239                 rsptimings[i]/(rspcounts[i]*1.0f), rsptimings[i]*(1.0f), rspcounts[i], s//,
240                 //timings[k]/1.0f/counts[k], counts[k], s2
241                 );
242         }
243 #endif
244
245         //rsp_init(z64_rspinfo);
246     }
247 #ifdef __cplusplus
248 }
249 #endif