mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-28 12:11:50 +01:00
[GCN/Wii]
*fixed audio/video desync that could occur after loading a new game *improved general synchronization of frame execution *modified ASNDLIB shutdown to prevent potential memory leak with DSP tasks *changed some global variables to use int type by default for optimization *some code cleanup
This commit is contained in:
parent
f44d38b537
commit
bad0696190
@ -34,10 +34,10 @@
|
||||
u8 soundbuffer[2][3840] ATTRIBUTE_ALIGN(32);
|
||||
|
||||
/* Current work soundbuffer */
|
||||
u8 mixbuffer;
|
||||
u32 mixbuffer;
|
||||
|
||||
/* audio DMA status */
|
||||
static u8 audioStarted = 0;
|
||||
static u32 audioStarted = 0;
|
||||
|
||||
/* Background music */
|
||||
static u8 *Bg_music_ogg = NULL;
|
||||
@ -56,9 +56,9 @@ static void ai_callback(void)
|
||||
/* AUDIO engine initialization */
|
||||
void gx_audio_Init(void)
|
||||
{
|
||||
/* Initialize AUDIO hardware */
|
||||
/* Default samplerate is 48kHZ */
|
||||
/* Default DMA callback is programmed */
|
||||
/* Initialize AUDIO processing library (ASNDLIB) */
|
||||
/* AUDIO & DSP hardware are initialized */
|
||||
/* Default samplerate is set to 48kHz */
|
||||
ASND_Init();
|
||||
|
||||
/* Load background music from FAT device */
|
||||
@ -83,7 +83,8 @@ void gx_audio_Shutdown(void)
|
||||
StopOgg();
|
||||
ASND_Pause(1);
|
||||
ASND_End();
|
||||
if (Bg_music_ogg) free(Bg_music_ogg);
|
||||
if (Bg_music_ogg)
|
||||
free(Bg_music_ogg);
|
||||
}
|
||||
|
||||
/***
|
||||
@ -92,8 +93,11 @@ void gx_audio_Shutdown(void)
|
||||
This function retrieves samples for the frame then set the next DMA parameters
|
||||
Parameters will be taken in account only when current DMA operation is over
|
||||
***/
|
||||
void gx_audio_Update(int size)
|
||||
void gx_audio_Update(void)
|
||||
{
|
||||
/* retrieve audio samples */
|
||||
int size = audio_update() * 4;
|
||||
|
||||
/* set next DMA soundbuffer */
|
||||
s16 *sb = (s16 *)(soundbuffer[mixbuffer]);
|
||||
mixbuffer ^= 1;
|
||||
@ -101,11 +105,21 @@ void gx_audio_Update(int size)
|
||||
AUDIO_InitDMA((u32) sb, size);
|
||||
|
||||
/* Start Audio DMA */
|
||||
/* this is only called once, DMA being automatically restarted when previous one is over */
|
||||
/* If DMA settings are not updated at that time, the same soundbuffer will be played again */
|
||||
/* this is only called once to kick-off DMA from external memory to audio interface */
|
||||
/* DMA operation is automatically restarted when all samples have been sent. */
|
||||
/* If DMA settings are not updated at that time, previous sound buffer will be used. */
|
||||
/* 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. */
|
||||
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);
|
||||
|
||||
AUDIO_StartDMA();
|
||||
if (frameticker > 1)
|
||||
frameticker = 1;
|
||||
@ -120,20 +134,20 @@ void gx_audio_Update(int size)
|
||||
***/
|
||||
void gx_audio_Start(void)
|
||||
{
|
||||
/* shutdown menu audio */
|
||||
/* shutdown background music */
|
||||
PauseOgg(1);
|
||||
StopOgg();
|
||||
|
||||
/* shutdown menu audio processing */
|
||||
ASND_Pause(1);
|
||||
ASND_End();
|
||||
AUDIO_StopDMA();
|
||||
AUDIO_RegisterDMACallback(NULL);
|
||||
DSP_Halt();
|
||||
|
||||
/* reset emulation audio processing */
|
||||
memset(soundbuffer, 0, 2 * 3840);
|
||||
audioStarted = 0;
|
||||
mixbuffer = 0;
|
||||
|
||||
/* reset sound buffers */
|
||||
memset(soundbuffer, 0, 2 * 3840);
|
||||
|
||||
/* By default, use audio DMA to synchronize frame emulation */
|
||||
if (gc_pal | vdp_pal)
|
||||
AUDIO_RegisterDMACallback(ai_callback);
|
||||
}
|
||||
|
||||
/***
|
||||
@ -145,9 +159,12 @@ void gx_audio_Start(void)
|
||||
***/
|
||||
void gx_audio_Stop(void)
|
||||
{
|
||||
/* restart menu audio (this will automatically stops current audio DMA) */
|
||||
/* restart menu audio processing */
|
||||
DSP_Unhalt();
|
||||
ASND_Init();
|
||||
ASND_Pause(0);
|
||||
|
||||
/* play background music */
|
||||
if (Bg_music_ogg && !Shutdown)
|
||||
{
|
||||
PauseOgg(0);
|
||||
|
@ -26,12 +26,12 @@
|
||||
#define _GC_AUDIO_H_
|
||||
|
||||
extern u8 soundbuffer[2][3840];
|
||||
extern u8 mixbuffer;
|
||||
extern u32 mixbuffer;
|
||||
|
||||
extern void gx_audio_Init(void);
|
||||
extern void gx_audio_Shutdown(void);
|
||||
extern void gx_audio_Start(void);
|
||||
extern void gx_audio_Stop(void);
|
||||
extern void gx_audio_Update(int size);
|
||||
extern void gx_audio_Update(void);
|
||||
|
||||
#endif
|
||||
|
@ -37,7 +37,7 @@
|
||||
#define HELD_SPEED 4
|
||||
|
||||
/* Menu request flag */
|
||||
u8 ConfigRequested = 0;
|
||||
u32 ConfigRequested = 0;
|
||||
|
||||
/* Configurable Genesis keys */
|
||||
#define KEY_BUTTONA 0
|
||||
|
@ -49,6 +49,6 @@ extern void gx_input_Config(u8 num, u8 type, u8 max_keys);
|
||||
extern void gx_input_UpdateEmu(void);
|
||||
extern void gx_input_UpdateMenu(u32 cnt);
|
||||
|
||||
extern u8 ConfigRequested;
|
||||
extern u32 ConfigRequested;
|
||||
|
||||
#endif
|
||||
|
@ -48,14 +48,14 @@ extern const u8 Crosshair_p1_png[];
|
||||
extern const u8 Crosshair_p2_png[];
|
||||
|
||||
/*** VI ***/
|
||||
unsigned int *xfb[2]; /* External Framebuffers */
|
||||
int whichfb = 0; /* Current Framebuffer */
|
||||
u32 *xfb[2]; /* External Framebuffers */
|
||||
u32 whichfb = 0; /* Current Framebuffer */
|
||||
GXRModeObj *vmode; /* Default Video Mode */
|
||||
u8 *texturemem; /* Texture Data */
|
||||
u8 *screenshot; /* Texture Data */
|
||||
|
||||
/* 50/60hz flag */
|
||||
u8 gc_pal = 0;
|
||||
/*** 50/60hz flag ***/
|
||||
u32 gc_pal = 0;
|
||||
|
||||
/*** NTSC Filters ***/
|
||||
sms_ntsc_t sms_ntsc;
|
||||
@ -1282,14 +1282,13 @@ void gx_video_Start(void)
|
||||
gc_pal = 0;
|
||||
|
||||
/* VSYNC callbacks */
|
||||
/* in 60hz mode we use VSYNC to synchronize frame emulation */
|
||||
/* in 60hz mode, frame emulation is synchronized with Video Interrupt */
|
||||
if (!gc_pal && !vdp_pal)
|
||||
VIDEO_SetPreRetraceCallback(vi_callback);
|
||||
VIDEO_SetPostRetraceCallback(NULL);
|
||||
VIDEO_Flush();
|
||||
VIDEO_WaitVSync();
|
||||
|
||||
/* interlaced/progressive mode */
|
||||
/* interlaced/progressive Video mode */
|
||||
if (config.render == 2)
|
||||
{
|
||||
tvmodes[2]->viTVMode = VI_TVMODE_NTSC_PROG;
|
||||
@ -1306,7 +1305,8 @@ void gx_video_Start(void)
|
||||
{
|
||||
bitmap.viewport.x = (reg[12] & 1) ? 16 : 12;
|
||||
bitmap.viewport.y = (reg[1] & 8) ? 0 : 8;
|
||||
if (vdp_pal) bitmap.viewport.y += 24;
|
||||
if (vdp_pal)
|
||||
bitmap.viewport.y += 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1314,6 +1314,10 @@ void gx_video_Start(void)
|
||||
bitmap.viewport.y = 0;
|
||||
}
|
||||
|
||||
/* reinitialize video size */
|
||||
vwidth = bitmap.viewport.w + (2 * bitmap.viewport.x);
|
||||
vheight = bitmap.viewport.h + (2 * bitmap.viewport.y);
|
||||
|
||||
/* software NTSC filters */
|
||||
if (config.ntsc == 1)
|
||||
{
|
||||
@ -1348,6 +1352,9 @@ void gx_video_Start(void)
|
||||
|
||||
/* reset GX rendering */
|
||||
gxResetRendering(0);
|
||||
|
||||
/* resynchronize emulation with VSYNC*/
|
||||
VIDEO_WaitVSync();
|
||||
}
|
||||
|
||||
/* GX render update */
|
||||
@ -1365,11 +1372,14 @@ void gx_video_Update(void)
|
||||
|
||||
/* if width has been changed, do no render this frame */
|
||||
/* this fixes texture glitches when changing width middle-frame */
|
||||
if (vwidth != old_vwidth) return;
|
||||
if (vwidth != old_vwidth)
|
||||
return;
|
||||
|
||||
/* special cases */
|
||||
if (config.render && interlaced) vheight = vheight << 1;
|
||||
if (config.ntsc) vwidth = (reg[12]&1) ? MD_NTSC_OUT_WIDTH(vwidth) : SMS_NTSC_OUT_WIDTH(vwidth);
|
||||
if (config.render && interlaced)
|
||||
vheight = vheight << 1;
|
||||
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;
|
||||
@ -1380,14 +1390,17 @@ void gx_video_Update(void)
|
||||
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
|
||||
/* reset TV mode */
|
||||
if (config.render) rmode = tvmodes[gc_pal*3 + 2];
|
||||
else rmode = tvmodes[gc_pal*3 + interlaced];
|
||||
if (config.render)
|
||||
rmode = tvmodes[gc_pal*3 + 2];
|
||||
else
|
||||
rmode = tvmodes[gc_pal*3 + interlaced];
|
||||
|
||||
/* reset aspect ratio */
|
||||
gxResetScaler(vwidth,vheight);
|
||||
@ -1410,8 +1423,10 @@ void gx_video_Update(void)
|
||||
draw_square();
|
||||
|
||||
/* 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]);
|
||||
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 */
|
||||
whichfb ^= 1;
|
||||
@ -1427,9 +1442,12 @@ void gx_video_Update(void)
|
||||
{
|
||||
/* field synchronizations */
|
||||
VIDEO_WaitVSync();
|
||||
if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||
else while (VIDEO_GetNextField() != odd_frame) VIDEO_WaitVSync();
|
||||
if (frameticker > 1) frameticker = 1;
|
||||
if (rmode->viTVMode & VI_NON_INTERLACE)
|
||||
VIDEO_WaitVSync();
|
||||
else while (VIDEO_GetNextField() != odd_frame)
|
||||
VIDEO_WaitVSync();
|
||||
if (frameticker > 1)
|
||||
frameticker = 1;
|
||||
bitmap.viewport.changed = 0;
|
||||
}
|
||||
}
|
||||
|
@ -40,11 +40,11 @@ typedef struct
|
||||
} gx_texture;
|
||||
|
||||
/* Global variables */
|
||||
extern unsigned int *xfb[2];
|
||||
extern int whichfb;
|
||||
extern u32 *xfb[2];
|
||||
extern u32 whichfb;
|
||||
extern GXRModeObj *vmode;
|
||||
extern u8 *texturemem;
|
||||
extern u8 gc_pal;
|
||||
extern u32 gc_pal;
|
||||
|
||||
|
||||
/* GX rendering */
|
||||
|
@ -30,12 +30,13 @@
|
||||
#include "dvd.h"
|
||||
|
||||
#include <fat.h>
|
||||
#include <ogc/cast.h>
|
||||
|
||||
#ifdef HW_RVL
|
||||
#include <wiiuse/wpad.h>
|
||||
#endif
|
||||
|
||||
u8 Shutdown = 0;
|
||||
u32 Shutdown = 0;
|
||||
|
||||
#ifdef HW_RVL
|
||||
|
||||
@ -163,19 +164,18 @@ void shutdown(void)
|
||||
* M A I N
|
||||
*
|
||||
***************************************************************************/
|
||||
u8 fat_enabled = 0;
|
||||
u32 fat_enabled = 0;
|
||||
u32 frameticker = 0;
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
CAST_Init();
|
||||
|
||||
#ifdef HW_RVL
|
||||
/* initialize DVDX */
|
||||
DI_Close();
|
||||
DI_Init();
|
||||
#endif
|
||||
|
||||
int size;
|
||||
|
||||
/* initialize hardware */
|
||||
gx_video_Init();
|
||||
gx_input_Init();
|
||||
@ -255,44 +255,40 @@ int main (int argc, char *argv[])
|
||||
if (ConfigRequested)
|
||||
{
|
||||
/* stop video & audio */
|
||||
gx_video_Stop();
|
||||
gx_audio_Stop();
|
||||
gx_video_Stop();
|
||||
|
||||
/* show menu */
|
||||
MainMenu ();
|
||||
ConfigRequested = 0;
|
||||
|
||||
/* start video & audio */
|
||||
/* always restart video first because it setup gc_pal */
|
||||
gx_video_Start();
|
||||
gx_audio_Start();
|
||||
|
||||
/* reset framesync */
|
||||
gx_video_Start();
|
||||
frameticker = 1;
|
||||
}
|
||||
|
||||
if (frameticker > 1)
|
||||
{
|
||||
/* skip frame */
|
||||
frameticker-=2;
|
||||
system_frame (1);
|
||||
system_frame(1);
|
||||
--frameticker;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* framesync */
|
||||
while (frameticker < 1) usleep(1);
|
||||
frameticker--;
|
||||
while (frameticker < 1)
|
||||
usleep(10);
|
||||
|
||||
/* render frame */
|
||||
system_frame (0);
|
||||
system_frame(0);
|
||||
--frameticker;
|
||||
|
||||
/* update video */
|
||||
gx_video_Update();
|
||||
}
|
||||
|
||||
/* retrieve audio samples */
|
||||
size = audio_update();
|
||||
|
||||
/* update video & audio */
|
||||
gx_video_Update();
|
||||
gx_audio_Update(size * 4);
|
||||
/* update audio */
|
||||
gx_audio_Update();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -49,6 +49,6 @@ extern void legal();
|
||||
extern void reloadrom (int size, char *name);
|
||||
extern void shutdown();
|
||||
extern u32 frameticker;
|
||||
extern u8 Shutdown;
|
||||
extern u32 Shutdown;
|
||||
|
||||
#endif /* _OSD_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user