mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-11-11 05:15:11 +01:00
443 lines
10 KiB
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;
|
|
}
|