Genesis-Plus-GX/psp2/emumain.c

443 lines
10 KiB
C

#include "emumain.h"
#include <psp2/types.h>
#include <psp2/kernel/threadmgr.h>
#include "time.h"
#include <psp2/rtc.h>
#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 <debugnet.h>
#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){
sceKernelWaitSema(console_mtx, 1, 0); //lock
//debugNetPrintf(DEBUG,"start %d %d \n",soundPosRead,soundPosWrite);
}
memcpy(ptr_s,&soundbuffer[soundPosWrite],sizeof(short)*samples*2);
soundPosWrite +=samples*2;
if(soundPosWrite+(samples*2)>=(SOUND_SAMPLES*2*10)){
soundPosWrite = 0;
}
}
else /* Render silence */
for (i = 0; i < samples; i++)
buf[i].stereo.l = buf[i].stereo.r = 0;
}