mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-28 12:11:50 +01:00
fixed audio/video synchronization in interlaced & progressive modes
This commit is contained in:
parent
cd14774e03
commit
54f1b14aa9
@ -988,7 +988,7 @@ static void systemmenu ()
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case 0: /*** Region Force ***/
|
||||
case 0: /*** Force Region ***/
|
||||
config.region_detect = (config.region_detect + 1) % 4;
|
||||
if (config.region_detect == 0)
|
||||
sprintf (items[0].text, "Console Region: AUTO");
|
||||
@ -1004,18 +1004,13 @@ static void systemmenu ()
|
||||
/* reset console region */
|
||||
region_autodetect();
|
||||
|
||||
/* update framerate */
|
||||
if (vdp_pal)
|
||||
framerate = 50.0;
|
||||
else
|
||||
framerate = ((config.tv_mode == 0) || (config.tv_mode == 2)) ? (1000000.0/16715.0) : 60.0;
|
||||
|
||||
/* save YM2612 context */
|
||||
temp = memalign(32,YM2612GetContextSize());
|
||||
if (temp)
|
||||
memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||
|
||||
/* reinitialize all timings */
|
||||
framerate = vdp_pal ? 50.0 : ((config.tv_mode == 1) ? 60.0 : ((config.render || interlaced) ? 59.94 : (1000000.0/16715.0)));
|
||||
audio_init(snd.sample_rate, framerate);
|
||||
system_init();
|
||||
|
||||
@ -1212,6 +1207,27 @@ static void videomenu ()
|
||||
config.render = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vdp_pal && cart.romsize)
|
||||
{
|
||||
/* save YM2612 context */
|
||||
temp = memalign(32,YM2612GetContextSize());
|
||||
if (temp)
|
||||
memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||
|
||||
/* reinitialize audio timings */
|
||||
framerate = (config.tv_mode == 1) ? 60.0 : ((config.render || interlaced) ? 59.94 : (1000000.0/16715.0));
|
||||
audio_init(snd.sample_rate, framerate);
|
||||
sound_init();
|
||||
|
||||
/* restore YM2612 context */
|
||||
if (temp)
|
||||
{
|
||||
YM2612Restore(temp);
|
||||
free(temp);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.render == 1)
|
||||
sprintf (items[0].text,"Display: INTERLACED");
|
||||
else if (config.render == 2)
|
||||
@ -1225,26 +1241,24 @@ static void videomenu ()
|
||||
{
|
||||
config.tv_mode = (config.tv_mode + 1) % 3;
|
||||
|
||||
/* update framerate */
|
||||
if (vdp_pal)
|
||||
framerate = 50.0;
|
||||
else
|
||||
framerate = ((config.tv_mode == 0) || (config.tv_mode == 2)) ? (1000000.0/16715.0) : 60.0;
|
||||
|
||||
/* save YM2612 context */
|
||||
temp = memalign(32,YM2612GetContextSize());
|
||||
if (temp)
|
||||
memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||
|
||||
/* reinitialize audio timings */
|
||||
audio_init(snd.sample_rate, framerate);
|
||||
sound_init();
|
||||
|
||||
/* restore YM2612 context */
|
||||
if (temp)
|
||||
if (!vdp_pal && cart.romsize)
|
||||
{
|
||||
YM2612Restore(temp);
|
||||
free(temp);
|
||||
/* save YM2612 context */
|
||||
temp = memalign(32,YM2612GetContextSize());
|
||||
if (temp)
|
||||
memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||
|
||||
/* reinitialize audio timings */
|
||||
framerate = (config.tv_mode == 1) ? 60.0 : ((config.render || interlaced) ? 59.94 : (1000000.0/16715.0));
|
||||
audio_init(snd.sample_rate, framerate);
|
||||
sound_init();
|
||||
|
||||
/* restore YM2612 context */
|
||||
if (temp)
|
||||
{
|
||||
YM2612Restore(temp);
|
||||
free(temp);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.tv_mode == 0)
|
||||
|
@ -71,7 +71,10 @@ void gx_audio_Init(void)
|
||||
stat(fname, &filestat);
|
||||
Bg_music_ogg_size = filestat.st_size;
|
||||
Bg_music_ogg = memalign(32,Bg_music_ogg_size);
|
||||
if (Bg_music_ogg) fread(Bg_music_ogg,1,Bg_music_ogg_size,f);
|
||||
if (Bg_music_ogg)
|
||||
{
|
||||
fread(Bg_music_ogg,1,Bg_music_ogg_size,f);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
@ -84,7 +87,9 @@ void gx_audio_Shutdown(void)
|
||||
ASND_Pause(1);
|
||||
ASND_End();
|
||||
if (Bg_music_ogg)
|
||||
{
|
||||
free(Bg_music_ogg);
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
@ -111,24 +116,19 @@ void gx_audio_Update(void)
|
||||
/* Therefore we need to make sure frame emulation is completed before current DMA is */
|
||||
/* completed, either by synchronizing frame emulation with DMA start or by syncing it */
|
||||
/* with Vertical Interrupt and outputing a suitable number of samples per frame. */
|
||||
/* In 60hz mode, VSYNC period is actually 16715 ms which is 802.32 samples at 48kHz. */
|
||||
/* */
|
||||
/* In both cases, audio DMA need to be synchronized with VSYNC and therefore need to */
|
||||
/* be resynchronized (restarted) every time video settings are changed (hopefully, */
|
||||
/* this generally happens while no music is played. */
|
||||
if (!audioStarted)
|
||||
{
|
||||
audioStarted = 1;
|
||||
|
||||
/* when not using 60hz mode, frame emulation is synchronized with Audio Interface DMA */
|
||||
if (gc_pal | vdp_pal)
|
||||
AUDIO_RegisterDMACallback(ai_callback);
|
||||
|
||||
/* restart audio DMA */
|
||||
AUDIO_StopDMA();
|
||||
AUDIO_StartDMA();
|
||||
if (frameticker > 1)
|
||||
frameticker = 1;
|
||||
audioStarted = 1;
|
||||
|
||||
/* resynchronize emulation */
|
||||
frameticker = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,6 +150,12 @@ void gx_audio_Start(void)
|
||||
AUDIO_RegisterDMACallback(NULL);
|
||||
DSP_Halt();
|
||||
|
||||
/* when not using 60hz mode, frame emulation is synchronized with Audio Interface DMA */
|
||||
if (gc_pal | vdp_pal)
|
||||
{
|
||||
AUDIO_RegisterDMACallback(ai_callback);
|
||||
}
|
||||
|
||||
/* reset emulation audio processing */
|
||||
memset(soundbuffer, 0, 2 * 3840);
|
||||
audioStarted = 0;
|
||||
|
@ -1306,9 +1306,13 @@ void gx_video_Start(void)
|
||||
{
|
||||
/* 50Hz/60Hz mode */
|
||||
if ((config.tv_mode == 1) || ((config.tv_mode == 2) && vdp_pal))
|
||||
{
|
||||
gc_pal = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gc_pal = 0;
|
||||
}
|
||||
|
||||
#ifdef HW_RVL
|
||||
VIDEO_SetTrapFilter(config.trap);
|
||||
@ -1318,7 +1322,9 @@ void gx_video_Start(void)
|
||||
/* VSYNC callbacks */
|
||||
/* in 60hz mode, frame emulation is synchronized with Video Interrupt */
|
||||
if (!gc_pal && !vdp_pal)
|
||||
{
|
||||
VIDEO_SetPreRetraceCallback(vi_callback);
|
||||
}
|
||||
VIDEO_SetPostRetraceCallback(NULL);
|
||||
VIDEO_Flush();
|
||||
|
||||
@ -1342,9 +1348,13 @@ void gx_video_Start(void)
|
||||
{
|
||||
/* allocate filters */
|
||||
if (!sms_ntsc)
|
||||
{
|
||||
sms_ntsc = (sms_ntsc_t *)memalign(32,sizeof(sms_ntsc_t));
|
||||
}
|
||||
if (!md_ntsc)
|
||||
{
|
||||
md_ntsc = (md_ntsc_t *)memalign(32,sizeof(md_ntsc_t));
|
||||
}
|
||||
|
||||
/* setup filters default configuration */
|
||||
switch (config.ntsc)
|
||||
@ -1366,9 +1376,13 @@ void gx_video_Start(void)
|
||||
|
||||
/* lightgun textures */
|
||||
if (config.gun_cursor[0] && (input.dev[4] == DEVICE_LIGHTGUN))
|
||||
{
|
||||
crosshair[0] = gxTextureOpenPNG(Crosshair_p1_png,0);
|
||||
}
|
||||
if (config.gun_cursor[1] && (input.dev[5] == DEVICE_LIGHTGUN))
|
||||
{
|
||||
crosshair[1] = gxTextureOpenPNG(Crosshair_p2_png,0);
|
||||
}
|
||||
|
||||
/* GX emulation rendering */
|
||||
gxResetRendering(0);
|
||||
@ -1382,7 +1396,7 @@ void gx_video_Update(void)
|
||||
{
|
||||
int update = bitmap.viewport.changed & 1;
|
||||
|
||||
/* check if display has changed */
|
||||
/* check if display has changed during frame */
|
||||
if (update)
|
||||
{
|
||||
/* update texture size */
|
||||
@ -1391,11 +1405,15 @@ void gx_video_Update(void)
|
||||
|
||||
/* interlaced mode */
|
||||
if (config.render && interlaced)
|
||||
{
|
||||
vheight = vheight << 1;
|
||||
}
|
||||
|
||||
/* ntsc filter */
|
||||
if (config.ntsc)
|
||||
{
|
||||
vwidth = (reg[12] & 1) ? MD_NTSC_OUT_WIDTH(vwidth) : SMS_NTSC_OUT_WIDTH(vwidth);
|
||||
}
|
||||
|
||||
/* texels size must be multiple of 4 */
|
||||
vwidth = (vwidth >> 2) << 2;
|
||||
@ -1407,16 +1425,22 @@ void gx_video_Update(void)
|
||||
|
||||
/* configure texture filtering */
|
||||
if (!config.bilinear)
|
||||
{
|
||||
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,0.0,10.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1);
|
||||
}
|
||||
|
||||
/* load texture object */
|
||||
GX_LoadTexObj(&texobj, GX_TEXMAP0);
|
||||
|
||||
/* update TV mode */
|
||||
/* update rendering mode */
|
||||
if (config.render)
|
||||
{
|
||||
rmode = tvmodes[gc_pal*3 + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
rmode = tvmodes[gc_pal*3 + interlaced];
|
||||
}
|
||||
|
||||
/* update aspect ratio */
|
||||
gxResetScaler(vwidth);
|
||||
@ -1426,7 +1450,6 @@ void gx_video_Update(void)
|
||||
|
||||
/* update VI mode */
|
||||
VIDEO_Configure(rmode);
|
||||
VIDEO_Flush();
|
||||
}
|
||||
|
||||
/* texture is now directly mapped by the line renderer */
|
||||
@ -1438,37 +1461,46 @@ void gx_video_Update(void)
|
||||
/* render textured quad */
|
||||
draw_square();
|
||||
|
||||
/* LightGun marks */
|
||||
/* Lightgun marks */
|
||||
if (crosshair[0])
|
||||
{
|
||||
gxDrawCrosshair(crosshair[0], input.analog[0][0],input.analog[0][1]);
|
||||
}
|
||||
if (crosshair[1])
|
||||
{
|
||||
gxDrawCrosshair(crosshair[1], input.analog[1][0],input.analog[1][1]);
|
||||
}
|
||||
|
||||
/* swap XFB */
|
||||
/* swap XFB */
|
||||
whichfb ^= 1;
|
||||
|
||||
/* copy EFB to XFB */
|
||||
GX_DrawDone();
|
||||
GX_CopyDisp(xfb[whichfb], GX_TRUE);
|
||||
GX_Flush();
|
||||
|
||||
/* XFB is ready to be displayed */
|
||||
VIDEO_SetNextFramebuffer(xfb[whichfb]);
|
||||
VIDEO_Flush();
|
||||
|
||||
if (update)
|
||||
{
|
||||
/* Clear update flags */
|
||||
bitmap.viewport.changed &= ~1;
|
||||
|
||||
/* field synchronization */
|
||||
VIDEO_WaitVSync();
|
||||
if (rmode->viTVMode & VI_NON_INTERLACE)
|
||||
{
|
||||
VIDEO_WaitVSync();
|
||||
}
|
||||
else while (VIDEO_GetNextField() != odd_frame)
|
||||
{
|
||||
VIDEO_WaitVSync();
|
||||
if (frameticker > 1)
|
||||
frameticker = 1;
|
||||
}
|
||||
|
||||
/* force audio DMA resynchronization */
|
||||
/* audio & video resynchronization */
|
||||
audioStarted = 0;
|
||||
|
||||
bitmap.viewport.changed &= ~1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ static bool FindIOS(u32 ios)
|
||||
***************************************************************************/
|
||||
static void load_bios(void)
|
||||
{
|
||||
/* reset BIOS flag */
|
||||
/* clear BIOS detection flag */
|
||||
config.tmss &= ~2;
|
||||
|
||||
/* open BIOS file */
|
||||
@ -116,8 +116,12 @@ static void load_bios(void)
|
||||
fread(bios_rom, 1, 0x800, fp);
|
||||
fclose(fp);
|
||||
|
||||
/* update BIOS flags */
|
||||
config.tmss |= 2;
|
||||
/* check ROM file */
|
||||
if (!strncmp((char *)(bios_rom + 0x120),"GENESIS OS", 10))
|
||||
{
|
||||
/* valid BIOS detected */
|
||||
config.tmss |= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void init_machine(void)
|
||||
@ -173,8 +177,8 @@ static void run_emulation(void)
|
||||
ConfigRequested = 0;
|
||||
|
||||
/* start video & audio */
|
||||
gx_audio_Start();
|
||||
gx_video_Start();
|
||||
gx_audio_Start();
|
||||
frameticker = 1;
|
||||
}
|
||||
|
||||
@ -182,8 +186,8 @@ static void run_emulation(void)
|
||||
if (frameticker > 1)
|
||||
{
|
||||
/* skip frame */
|
||||
frameticker = 0;
|
||||
system_frame(1);
|
||||
frameticker = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -198,6 +202,32 @@ static void run_emulation(void)
|
||||
/* update audio */
|
||||
gx_audio_Update();
|
||||
|
||||
/* check interlaced mode change */
|
||||
if (bitmap.viewport.changed & 4)
|
||||
{
|
||||
/* in original 60hz modes, audio is synced with framerate */
|
||||
if (!config.render && !vdp_pal && (config.tv_mode != 1))
|
||||
{
|
||||
u8 *temp = memalign(32,YM2612GetContextSize());
|
||||
if (temp)
|
||||
{
|
||||
/* save YM2612 context */
|
||||
memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||
|
||||
/* framerate has changed, reinitialize audio timings */
|
||||
audio_init(48000, interlaced ? 59.94 : (1000000.0/16715.0));
|
||||
sound_init();
|
||||
|
||||
/* restore YM2612 context */
|
||||
YM2612Restore(temp);
|
||||
free(temp);
|
||||
}
|
||||
}
|
||||
|
||||
/* clear flag */
|
||||
bitmap.viewport.changed &= ~4;
|
||||
}
|
||||
|
||||
/* wait for next frame */
|
||||
while (frameticker < 1)
|
||||
usleep(1);
|
||||
@ -227,12 +257,8 @@ void reloadrom (int size, char *name)
|
||||
{
|
||||
/* initialize audio back-end */
|
||||
/* 60hz video mode requires synchronization with Video Interrupt. */
|
||||
/* VSYNC period is 16715 us on Wii/Gamecube (approx. 802.32 samples per frame) */
|
||||
float framerate;
|
||||
if (vdp_pal)
|
||||
framerate = 50.0;
|
||||
else
|
||||
framerate = ((config.tv_mode == 0) || (config.tv_mode == 2)) ? (1000000.0/16715.0) : 60.0;
|
||||
/* Framerate is 59.94 fps in interlaced/progressive modes, ~59.825 fps in non-interlaced mode */
|
||||
float framerate = vdp_pal ? 50.0 : ((config.tv_mode == 1) ? 60.0 : (config.render ? 59.94 : (1000000.0/16715.0)));
|
||||
audio_init(48000, framerate);
|
||||
|
||||
/* System Power ON */
|
||||
|
@ -114,7 +114,6 @@ void SN76489_Init(float PSGClockValue, int SamplingRate)
|
||||
SN76489_Context *p = &SN76489;
|
||||
p->dClock=PSGClockValue/16.0/SamplingRate;
|
||||
SN76489_Config(MUTE_ALLON, VOL_FULL, FB_SEGAVDP, SRW_SEGAVDP, config.psgBoostNoise);
|
||||
SN76489_Reset();
|
||||
}
|
||||
|
||||
void SN76489_Reset(void)
|
||||
|
@ -178,18 +178,21 @@ int sound_update(unsigned int cycles)
|
||||
int avail = Fir_Resampler_avail();
|
||||
|
||||
/* resynchronize FM & PSG chips */
|
||||
if (avail < size)
|
||||
{
|
||||
/* FM chip is late for one sample */
|
||||
YM2612Update(Fir_Resampler_buffer(), 1);
|
||||
Fir_Resampler_write(2);
|
||||
fm_cycles_count += fm_cycles_ratio;
|
||||
}
|
||||
else
|
||||
if (avail > size)
|
||||
{
|
||||
/* FM chip is ahead */
|
||||
fm_cycles_count += (avail - size) * psg_cycles_ratio;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (avail < size)
|
||||
{
|
||||
/* FM chip is late for one sample */
|
||||
YM2612Update(Fir_Resampler_buffer(), 1);
|
||||
Fir_Resampler_write(2);
|
||||
avail = Fir_Resampler_avail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LOGSOUND
|
||||
|
@ -334,7 +334,7 @@ void system_frame (int do_skip)
|
||||
{
|
||||
im2_flag = ((reg[12] & 6) == 6);
|
||||
odd_frame = 1;
|
||||
bitmap.viewport.changed = 1;
|
||||
bitmap.viewport.changed = 5;
|
||||
}
|
||||
|
||||
/* active screen height */
|
||||
|
Loading…
Reference in New Issue
Block a user