1 #include "emumain.h"
2
3 #include <psp2/types.h>
4 #include <psp2/kernel/threadmgr.h>
5 #include "time.h"
6 #include <psp2/rtc.h>
7
8 #define SCE_KERNEL_OK 0
9
10 #include "psplib/pl_rewind.h"
11 #include "psplib/pl_file.h"
12 #include "psplib/pl_snd.h"
13 #include "psplib/pl_perf.h"
14 #include "psplib/pl_util.h"
15 #include "psplib/pl_psp.h"
16 #include "psplib/video.h"
17 #include "psplib/ctrl.h"
18
19 #include "shared.h"
20 #include "sound.h"
21 #include "system.h"
22 #include "md_ntsc.h"
23 #include "sms_ntsc.h"
24
25 //#include <debugnet.h>
26
27 #define ip_server "192.168.1.130"
28 #define port_server 18194
29
30 PspImage *Screen;
31 pl_rewind Rewinder;
32
33 static pl_perf_counter FpsCounter;
34 static int ClearScreen;
35 static int ScreenX, ScreenY, ScreenW, ScreenH;
36 static int TicksPerUpdate;
37 static u32 TicksPerSecond;
38 static u64 LastTick;
39 static u64 CurrentTick;
40 static int Frame;
41
42 static int Rewinding;
43
44 extern pl_file_path CurrentGame;
45 extern EmulatorOptions Options;
46 extern const u64 ButtonMask[];
47 extern const int ButtonMapId[];
48 extern struct ButtonConfig ActiveConfig;
49 extern char *ScreenshotPath;
50
51 static short soundbuffer[SOUND_SAMPLES*2*10];
52 static int soundPosWrite = 0;
53 static int soundPosRead = 0;
54 static SceUID console_mtx;
55
56
57
58 static inline void RenderVideo();
59 static void AudioCallback(pl_snd_sample* buf,
60 unsigned int samples,
61 void *userdata);
62 void MixerCallback(int16 **stream, int16 **output, int length);
63 md_ntsc_t *md_ntsc;
64 sms_ntsc_t *sms_ntsc;
65
66 int bEmulate;
67
osd_input_update()68 void osd_input_update()
69 {
70
71 /* Reset input */
72 input.pad[0] = 0;
73 input.analog[0][0] = 0x7F;
74
75 static SceCtrlData pad;
76 static int autofire_status = 0;
77
78 /* Check the input */
79 if (pspCtrlPollControls(&pad))
80 {
81 if (--autofire_status < 0)
82 autofire_status = Options.AutoFire;
83
84 /* Parse input */
85 int i, on, code;
86 for (i = 0; ButtonMapId[i] >= 0; i++)
87 {
88 code = ActiveConfig.ButtonMap[ButtonMapId[i]];
89 on = (pad.buttons & ButtonMask[i]) == ButtonMask[i];
90
91 /* Check to see if a button set is pressed. If so, unset it, so it */
92 /* doesn't trigger any other combination presses. */
93 if (on) pad.buttons &= ~ButtonMask[i];
94
95 if (code & AFI)
96 {
97 if (on && (autofire_status == 0))
98 input.pad[0] |= CODE_MASK(code);
99 continue;
100 }
101 else if (code & JOY)
102 {
103 if (on) {
104 input.pad[0] |= CODE_MASK(code);
105 }
106 continue;
107 }
108 else if (code & SYS)
109 {
110 if (on)
111 {
112 if (CODE_MASK(code) == (INPUT_START))
113 input.system[0] |= INPUT_START;
114 }
115 continue;
116 }
117
118
119 if (code & SPC)
120 {
121 switch (CODE_MASK(code))
122 {
123 case SPC_MENU:
124 if (on) bEmulate=0;
125 break;
126 case SPC_REWIND:
127 Rewinding = on;
128 break;
129 }
130 }
131 }
132 }
133
134 return;
135 }
136
InitEmulator()137 void InitEmulator()
138 {
139
140 //debugNetInit(ip_server,port_server,DEBUG);
141
142 set_config_defaults();
143
144 ClearScreen = 0;
145
146 /* Initialize screen buffer */
147 Screen = pspImageCreateVram(720, 576, PSP_IMAGE_16BPP);
148
149 // pspImageClear(Screen, 0x8000);
150
151 console_mtx = sceKernelCreateSema("sound_sema", 0, 0, 1, 0);
152 /*if (console_mtx > 0) {
153 debugNetPrintf(DEBUG,"Sound Mutex UID: 0x%08X\n", console_mtx);
154 }*/
155
156 /* Set up bitmap structure */
157 memset(&bitmap, 0, sizeof(t_bitmap));
158 bitmap.width = Screen->Width;
159 bitmap.height = Screen->Height;
160 bitmap.pitch = (bitmap.width * 2);
161 bitmap.data = (unsigned char *)Screen->Pixels;
162 bitmap.viewport.changed = 3;
163
164 pl_snd_set_callback(0, AudioCallback, NULL);
165 }
166
RunEmulator()167 void RunEmulator()
168 {
169 float ratio;
170 //debugNetPrintf(DEBUG,"RunEmulator\n");
171
172 pspImageClear(Screen, 0);
173 //debugNetPrintf(DEBUG,"ImageClear\n");
174
175
176 if(bitmap.viewport.changed & 1)
177 {
178 bitmap.viewport.changed &= ~1;
179
180 /* source bitmap */
181 Screen->Viewport.Width = bitmap.viewport.w+2*bitmap.viewport.x;
182 Screen->Viewport.Height = bitmap.viewport.h+2*bitmap.viewport.y;
183
184 }
185
186 /* Recompute screen size/position */
187 switch (Options.DisplayMode)
188 {
189 default:
190 case DISPLAY_MODE_UNSCALED:
191 ScreenW = Screen->Viewport.Width;
192 ScreenH = Screen->Viewport.Height;
193 break;
194 case DISPLAY_MODE_FIT_HEIGHT:
195 ratio = (float)SCR_HEIGHT / (float)Screen->Viewport.Height;
196 ScreenW = (float)bitmap.viewport.w * ratio - 2;
197 ScreenH = SCR_HEIGHT;
198 break;
199 case DISPLAY_MODE_FILL_SCREEN:
200 ScreenW = SCR_WIDTH;
201 ScreenH = SCR_HEIGHT;
202 break;
203 case DISPLAY_MODE_2X:
204 ScreenW = Screen->Viewport.Width*2;
205 ScreenH = Screen->Viewport.Height*2;
206 break;
207 case DISPLAY_MODE_3X:
208 ScreenW = Screen->Viewport.Width*3;
209 ScreenH = Screen->Viewport.Height*3;
210 break;
211 }
212 //debugNetPrintf(DEBUG,"screensize %d %d\n" ,Screen->Viewport.Width ,Screen->Viewport.Height);
213
214 ScreenX = (SCR_WIDTH / 2) - (ScreenW / 2);
215 ScreenY = (SCR_HEIGHT / 2) - (ScreenH / 2);
216
217 /* Init performance counter */
218 pl_perf_init_counter(&FpsCounter);
219
220 /* Recompute update frequency */
221 TicksPerSecond = sceRtcGetTickResolution();
222 if (Options.UpdateFreq)
223 {
224 TicksPerUpdate = TicksPerSecond
225 / (Options.UpdateFreq / (Options.Frameskip + 1));
226 sceRtcGetCurrentTick(&LastTick);
227 }
228 Frame = 0;
229 ClearScreen = 2;
230 Rewinding = 0;
231
232 //pl_rewind_realloc(&Rewinder);
233
234 int frames_until_save = 0;
235
236 /* Resume sound */
237 pl_snd_resume(0);
238
239 /* Wait for V. refresh */
240 pspVideoWaitVSync();
241
242 bEmulate = 1;
243 /* Main emulation loop */
244 while (!ExitPSP&&bEmulate)
245 {
246 /* Rewind/save state */
247 /*if (!Rewinding)
248 {
249 if (--frames_until_save <= 0)
250 {
251 frames_until_save = Options.RewindSaveRate;
252 pl_rewind_save(&Rewinder);
253 }
254 }
255 else
256 {
257 frames_until_save = Options.RewindSaveRate;
258 if (!pl_rewind_restore(&Rewinder))
259 continue;
260 }*/
261
262 /* Run the system emulation for a frame */
263 if (++Frame <= Options.Frameskip)
264 {
265 /* Skip frame */
266 if (system_hw == SYSTEM_MCD)
267 {
268 system_frame_scd(1);
269 }
270 else if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
271 {
272 system_frame_gen(1);
273 }
274 else
275 {
276 system_frame_sms(1);
277 }
278 }
279 else
280 {
281 if (system_hw == SYSTEM_MCD)
282 {
283 system_frame_scd(0);
284 }
285 else if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
286 {
287 system_frame_gen(0);
288 }
289 else
290 {
291 system_frame_sms(0);
292 }
293
294 Frame = 0;
295 /* Display */
296 if(bitmap.viewport.changed & 1)
297 {
298 bitmap.viewport.changed &= ~1;
299
300 /* source bitmap */
301 Screen->Viewport.Width = bitmap.viewport.w+2*bitmap.viewport.x;
302 Screen->Viewport.Height = bitmap.viewport.h+2*bitmap.viewport.y;
303
304 /* Recompute screen size/position */
305 switch (Options.DisplayMode)
306 {
307 default:
308 case DISPLAY_MODE_UNSCALED:
309 ScreenW = Screen->Viewport.Width;
310 ScreenH = Screen->Viewport.Height;
311 break;
312 case DISPLAY_MODE_FIT_HEIGHT:
313 ratio = (float)SCR_HEIGHT / (float)Screen->Viewport.Height;
314 ScreenW = (float)bitmap.viewport.w * ratio - 2;
315 ScreenH = SCR_HEIGHT;
316 break;
317 case DISPLAY_MODE_FILL_SCREEN:
318 ScreenW = SCR_WIDTH;
319 ScreenH = SCR_HEIGHT;
320 break;
321 case DISPLAY_MODE_2X:
322 ScreenW = Screen->Viewport.Width*2;
323 ScreenH = Screen->Viewport.Height*2;
324 break;
325 case DISPLAY_MODE_3X:
326 ScreenW = Screen->Viewport.Width*3;
327 ScreenH = Screen->Viewport.Height*3;
328 break;
329 }
330
331 ScreenX = (SCR_WIDTH / 2) - (ScreenW / 2);
332 ScreenY = (SCR_HEIGHT / 2) - (ScreenH / 2);
333
334 }
335 //debugNetPrintf(DEBUG,"main %d %d \n",soundPosRead,soundPosWrite);
336 int size = audio_update(&soundbuffer[soundPosRead])*2;
337 //debugNetPrintf(DEBUG,"filling %d \n",size);
338
339 soundPosRead +=size;
340 if(soundPosRead+size>=(SOUND_SAMPLES*2*10)){
341 soundPosRead = 0;
342 }
343 if((soundPosRead-soundPosWrite)>=(SOUND_SAMPLES*2)||(soundPosRead-soundPosWrite)<0){
344 sceKernelSignalSema(console_mtx, 1); //lock
345 }
346 RenderVideo();
347
348 }
349 }
350
351 /* Stop sound */
352 pl_snd_pause(0);
353 }
354
TrashEmulator()355 void TrashEmulator()
356 {
357 pl_rewind_destroy(&Rewinder);
358
359 /* Trash screen */
360 if (Screen) pspImageDestroy(Screen);
361
362 if (CurrentGame[0] != '\0')
363 {
364 /* Release emulation resources */
365 audio_shutdown();
366 error_shutdown();
367 }
368 //debugNetFinish();
369
370 }
371
372
373
RenderVideo()374 void RenderVideo()
375 {
376 /* Update the display */
377 pspVideoBegin();
378
379 /* Clear the buffer first, if necessary */
380 if (ClearScreen >= 0)
381 {
382 ClearScreen--;
383 pspVideoClearScreen();
384 }
385
386 pspVideoPutImage(Screen, ScreenX, ScreenY, ScreenW, ScreenH);
387
388 /* Show FPS counter */
389 if (Options.ShowFps)
390 {
391 static char fps_display[32];
392 sprintf(fps_display, " %3.02f", pl_perf_update_counter(&FpsCounter));
393
394 int width = pspFontGetTextWidth(&PspStockFont, fps_display);
395 int height = pspFontGetLineHeight(&PspStockFont);
396
397 pspVideoFillRect(SCR_WIDTH - width, 0, SCR_WIDTH, height, PSP_COLOR_BLACK);
398 pspVideoPrint(&PspStockFont, SCR_WIDTH - width, 0, fps_display, PSP_COLOR_WHITE);
399 }
400
401 pspVideoEnd();
402
403 /* Wait if needed */
404 if (Options.UpdateFreq)
405 {
406 do { sceRtcGetCurrentTick(&CurrentTick); }
407 while (CurrentTick - LastTick < TicksPerUpdate);
408 LastTick = CurrentTick;
409 }
410
411 /* Wait for VSync signal */
412 if (Options.VSync)
413 pspVideoWaitVSync();
414
415 /* Swap buffers */
416 pspVideoSwapBuffers();
417 }
418
AudioCallback(pl_snd_sample * buf,unsigned int samples,void * userdata)419 static void AudioCallback(pl_snd_sample *buf,
420 unsigned int samples,
421 void *userdata)
422 {
423 int i;
424 //debugNetPrintf(DEBUG,"wait %d %d \n",totalSamples,samples);
425 if (!Rewinding)
426 {
427 short* ptr_s = (short*)buf;
428 //debugNetPrintf(DEBUG,"wait %d %d \n",soundPosRead,soundPosWrite);
429 if((soundPosRead-soundPosWrite)<SOUND_SAMPLES*2){
430 sceKernelWaitSema(console_mtx, 1, 0); //lock
431 //debugNetPrintf(DEBUG,"start %d %d \n",soundPosRead,soundPosWrite);
432 }
433 memcpy(ptr_s,&soundbuffer[soundPosWrite],sizeof(short)*samples*2);
434 soundPosWrite +=samples*2;
435 if(soundPosWrite+(samples*2)>=(SOUND_SAMPLES*2*10)){
436 soundPosWrite = 0;
437 }
438 }
439 else /* Render silence */
440 for (i = 0; i < samples; i++)
441 buf[i].stereo.l = buf[i].stereo.r = 0;
442 }
443