#include "emumain.h" #include #include #include "time.h" #include #define SCE_KERNEL_OK 0 #include "psplib/pl_rewind.h" #include "psplib/pl_file.h" #include "psplib/pl_snd.h" #include "psplib/pl_perf.h" #include "psplib/pl_util.h" #include "psplib/pl_psp.h" #include "psplib/video.h" #include "psplib/ctrl.h" #include "shared.h" #include "sound.h" #include "system.h" #include "md_ntsc.h" #include "sms_ntsc.h" //#include #define ip_server "192.168.1.130" #define port_server 18194 PspImage *Screen; pl_rewind Rewinder; static pl_perf_counter FpsCounter; static int ClearScreen; static int ScreenX, ScreenY, ScreenW, ScreenH; static int TicksPerUpdate; static u32 TicksPerSecond; static u64 LastTick; static u64 CurrentTick; static int Frame; static int Rewinding; extern pl_file_path CurrentGame; extern EmulatorOptions Options; extern const u64 ButtonMask[]; extern const int ButtonMapId[]; extern struct ButtonConfig ActiveConfig; extern char *ScreenshotPath; static short soundbuffer[SOUND_SAMPLES*2*10]; static int soundPosWrite = 0; static int soundPosRead = 0; static SceUID console_mtx; static inline void RenderVideo(); static void AudioCallback(pl_snd_sample* buf, unsigned int samples, void *userdata); void MixerCallback(int16 **stream, int16 **output, int length); md_ntsc_t *md_ntsc; sms_ntsc_t *sms_ntsc; int bEmulate; void osd_input_update() { /* Reset input */ input.pad[0] = 0; input.analog[0][0] = 0x7F; static SceCtrlData pad; static int autofire_status = 0; /* Check the input */ if (pspCtrlPollControls(&pad)) { if (--autofire_status < 0) autofire_status = Options.AutoFire; /* Parse input */ int i, on, code; for (i = 0; ButtonMapId[i] >= 0; i++) { code = ActiveConfig.ButtonMap[ButtonMapId[i]]; on = (pad.buttons & ButtonMask[i]) == ButtonMask[i]; /* Check to see if a button set is pressed. If so, unset it, so it */ /* doesn't trigger any other combination presses. */ if (on) pad.buttons &= ~ButtonMask[i]; if (code & AFI) { if (on && (autofire_status == 0)) input.pad[0] |= CODE_MASK(code); continue; } else if (code & JOY) { if (on) { input.pad[0] |= CODE_MASK(code); } continue; } else if (code & SYS) { if (on) { if (CODE_MASK(code) == (INPUT_START)) input.system[0] |= INPUT_START; } continue; } if (code & SPC) { switch (CODE_MASK(code)) { case SPC_MENU: if (on) bEmulate=0; break; case SPC_REWIND: Rewinding = on; break; } } } } return; } void InitEmulator() { //debugNetInit(ip_server,port_server,DEBUG); set_config_defaults(); ClearScreen = 0; /* Initialize screen buffer */ Screen = pspImageCreateVram(720, 576, PSP_IMAGE_16BPP); // pspImageClear(Screen, 0x8000); console_mtx = sceKernelCreateSema("sound_sema", 0, 0, 1, 0); /*if (console_mtx > 0) { debugNetPrintf(DEBUG,"Sound Mutex UID: 0x%08X\n", console_mtx); }*/ /* Set up bitmap structure */ memset(&bitmap, 0, sizeof(t_bitmap)); bitmap.width = Screen->Width; bitmap.height = Screen->Height; bitmap.pitch = (bitmap.width * 2); bitmap.data = (unsigned char *)Screen->Pixels; bitmap.viewport.changed = 3; pl_snd_set_callback(0, AudioCallback, NULL); } void RunEmulator() { float ratio; //debugNetPrintf(DEBUG,"RunEmulator\n"); pspImageClear(Screen, 0); //debugNetPrintf(DEBUG,"ImageClear\n"); if(bitmap.viewport.changed & 1) { bitmap.viewport.changed &= ~1; /* source bitmap */ Screen->Viewport.Width = bitmap.viewport.w+2*bitmap.viewport.x; Screen->Viewport.Height = bitmap.viewport.h+2*bitmap.viewport.y; } /* Recompute screen size/position */ switch (Options.DisplayMode) { default: case DISPLAY_MODE_UNSCALED: ScreenW = Screen->Viewport.Width; ScreenH = Screen->Viewport.Height; break; case DISPLAY_MODE_FIT_HEIGHT: ratio = (float)SCR_HEIGHT / (float)Screen->Viewport.Height; ScreenW = (float)bitmap.viewport.w * ratio - 2; ScreenH = SCR_HEIGHT; break; case DISPLAY_MODE_FILL_SCREEN: ScreenW = SCR_WIDTH; ScreenH = SCR_HEIGHT; break; case DISPLAY_MODE_2X: ScreenW = Screen->Viewport.Width*2; ScreenH = Screen->Viewport.Height*2; break; case DISPLAY_MODE_3X: ScreenW = Screen->Viewport.Width*3; ScreenH = Screen->Viewport.Height*3; break; } //debugNetPrintf(DEBUG,"screensize %d %d\n" ,Screen->Viewport.Width ,Screen->Viewport.Height); ScreenX = (SCR_WIDTH / 2) - (ScreenW / 2); ScreenY = (SCR_HEIGHT / 2) - (ScreenH / 2); /* Init performance counter */ pl_perf_init_counter(&FpsCounter); /* Recompute update frequency */ TicksPerSecond = sceRtcGetTickResolution(); if (Options.UpdateFreq) { TicksPerUpdate = TicksPerSecond / (Options.UpdateFreq / (Options.Frameskip + 1)); sceRtcGetCurrentTick(&LastTick); } Frame = 0; ClearScreen = 2; Rewinding = 0; //pl_rewind_realloc(&Rewinder); int frames_until_save = 0; /* Resume sound */ pl_snd_resume(0); /* Wait for V. refresh */ pspVideoWaitVSync(); bEmulate = 1; /* Main emulation loop */ while (!ExitPSP&&bEmulate) { /* Rewind/save state */ /*if (!Rewinding) { if (--frames_until_save <= 0) { frames_until_save = Options.RewindSaveRate; pl_rewind_save(&Rewinder); } } else { frames_until_save = Options.RewindSaveRate; if (!pl_rewind_restore(&Rewinder)) continue; }*/ /* Run the system emulation for a frame */ if (++Frame <= Options.Frameskip) { /* Skip frame */ if (system_hw == SYSTEM_MCD) { system_frame_scd(1); } else if ((system_hw & SYSTEM_PBC) == SYSTEM_MD) { system_frame_gen(1); } else { system_frame_sms(1); } } else { if (system_hw == SYSTEM_MCD) { system_frame_scd(0); } else if ((system_hw & SYSTEM_PBC) == SYSTEM_MD) { system_frame_gen(0); } else { system_frame_sms(0); } Frame = 0; /* Display */ if(bitmap.viewport.changed & 1) { bitmap.viewport.changed &= ~1; /* source bitmap */ Screen->Viewport.Width = bitmap.viewport.w+2*bitmap.viewport.x; Screen->Viewport.Height = bitmap.viewport.h+2*bitmap.viewport.y; /* Recompute screen size/position */ switch (Options.DisplayMode) { default: case DISPLAY_MODE_UNSCALED: ScreenW = Screen->Viewport.Width; ScreenH = Screen->Viewport.Height; break; case DISPLAY_MODE_FIT_HEIGHT: ratio = (float)SCR_HEIGHT / (float)Screen->Viewport.Height; ScreenW = (float)bitmap.viewport.w * ratio - 2; ScreenH = SCR_HEIGHT; break; case DISPLAY_MODE_FILL_SCREEN: ScreenW = SCR_WIDTH; ScreenH = SCR_HEIGHT; break; case DISPLAY_MODE_2X: ScreenW = Screen->Viewport.Width*2; ScreenH = Screen->Viewport.Height*2; break; case DISPLAY_MODE_3X: ScreenW = Screen->Viewport.Width*3; ScreenH = Screen->Viewport.Height*3; break; } ScreenX = (SCR_WIDTH / 2) - (ScreenW / 2); ScreenY = (SCR_HEIGHT / 2) - (ScreenH / 2); } //debugNetPrintf(DEBUG,"main %d %d \n",soundPosRead,soundPosWrite); int size = audio_update(&soundbuffer[soundPosRead])*2; //debugNetPrintf(DEBUG,"filling %d \n",size); soundPosRead +=size; if(soundPosRead+size>=(SOUND_SAMPLES*2*10)){ soundPosRead = 0; } if((soundPosRead-soundPosWrite)>=(SOUND_SAMPLES*2)||(soundPosRead-soundPosWrite)<0){ sceKernelSignalSema(console_mtx, 1); //lock } RenderVideo(); } } /* Stop sound */ pl_snd_pause(0); } void TrashEmulator() { pl_rewind_destroy(&Rewinder); /* Trash screen */ if (Screen) pspImageDestroy(Screen); if (CurrentGame[0] != '\0') { /* Release emulation resources */ audio_shutdown(); error_shutdown(); } //debugNetFinish(); } void RenderVideo() { /* Update the display */ pspVideoBegin(); /* Clear the buffer first, if necessary */ if (ClearScreen >= 0) { ClearScreen--; pspVideoClearScreen(); } pspVideoPutImage(Screen, ScreenX, ScreenY, ScreenW, ScreenH); /* Show FPS counter */ if (Options.ShowFps) { static char fps_display[32]; sprintf(fps_display, " %3.02f", pl_perf_update_counter(&FpsCounter)); int width = pspFontGetTextWidth(&PspStockFont, fps_display); int height = pspFontGetLineHeight(&PspStockFont); pspVideoFillRect(SCR_WIDTH - width, 0, SCR_WIDTH, height, PSP_COLOR_BLACK); pspVideoPrint(&PspStockFont, SCR_WIDTH - width, 0, fps_display, PSP_COLOR_WHITE); } pspVideoEnd(); /* Wait if needed */ if (Options.UpdateFreq) { do { sceRtcGetCurrentTick(&CurrentTick); } while (CurrentTick - LastTick < TicksPerUpdate); LastTick = CurrentTick; } /* Wait for VSync signal */ if (Options.VSync) pspVideoWaitVSync(); /* Swap buffers */ pspVideoSwapBuffers(); } static void AudioCallback(pl_snd_sample *buf, unsigned int samples, void *userdata) { int i; //debugNetPrintf(DEBUG,"wait %d %d \n",totalSamples,samples); if (!Rewinding) { short* ptr_s = (short*)buf; //debugNetPrintf(DEBUG,"wait %d %d \n",soundPosRead,soundPosWrite); if((soundPosRead-soundPosWrite)=(SOUND_SAMPLES*2*10)){ soundPosWrite = 0; } } else /* Render silence */ for (i = 0; i < samples; i++) buf[i].stereo.l = buf[i].stereo.r = 0; }