From f6a242a031b72e613f0a13eaa5ef09c75c961b97 Mon Sep 17 00:00:00 2001 From: ekeeke31 Date: Fri, 19 Dec 2008 15:38:26 +0000 Subject: [PATCH] added GX_Flush(), documented sound rendering core --- source/ngc/ngc.c | 14 +++--- source/ngc/ogc_audio.c | 99 +++++++++++++++++++++++++++--------------- source/ngc/ogc_video.c | 6 ++- 3 files changed, 76 insertions(+), 43 deletions(-) diff --git a/source/ngc/ngc.c b/source/ngc/ngc.c index ae95ae8..e7931e5 100644 --- a/source/ngc/ngc.c +++ b/source/ngc/ngc.c @@ -79,7 +79,7 @@ static void load_bios() static void init_machine (void) { - /* Allocate cart_rom here */ + /* Allocate cart_rom here ( 10 MBytes ) */ cart_rom = memalign(32, 10 * 1024 * 1024); /* BIOS support */ @@ -194,16 +194,16 @@ int main (int argc, char *argv[]) if (frameticker > 1) { - /* Frame skipping */ + /* frameskipping */ frameticker--; system_frame (1); } else { - /* Delay */ + /* frame sync */ while (!frameticker) usleep(10); - /* Render Frame */ + /* frame rendering */ system_frame (0); RenderedFrameCount++; } @@ -214,7 +214,7 @@ int main (int argc, char *argv[]) ogc_audio__update(); ogc_video__update(); - /* Check rendered frames (FPS) */ + /* check rendered frames (FPS) */ FrameCount++; if (FrameCount == vdp_rate) { @@ -226,14 +226,14 @@ int main (int argc, char *argv[]) /* Check for Menu request */ if (ConfigRequested) { - /* stop AUDIO */ + /* stop Audio */ ogc_audio__stop(); /* go to menu */ MainMenu (); ConfigRequested = 0; - /* reset frame timings */ + /* reset frame sync */ frameticker = 0; FrameCount = 0; RenderedFrameCount = 0; diff --git a/source/ngc/ogc_audio.c b/source/ngc/ogc_audio.c index 7dc0843..8491454 100644 --- a/source/ngc/ogc_audio.c +++ b/source/ngc/ogc_audio.c @@ -23,71 +23,102 @@ #include "shared.h" -/* global datas */ -unsigned char soundbuffer[2][3840] ATTRIBUTE_ALIGN(32); -u8 mixbuffer = 0; +/* DMA soundbuffers (required to be 32-bytes aligned) + Length is dimensionned for one frame of emulation (see below) + To prevent audio clashes, we use double buffering technique: + one buffer is the active DMA buffer + the other one is the current work buffer (updated during frame emulation) + We do not need more since frame emulation is synchronized with DMA execution +*/ +u8 soundbuffer[2][3840] ATTRIBUTE_ALIGN(32); -static int IsPlaying = 0; -static int dma_len = 3200; +/* Current work soundbuffer */ +u8 mixbuffer = 1; + +/* Current DMA status (1: DMA in progress, 0: DMA stopped) */ +static int IsPlaying = 0; + +/* Current DMA length (required to be a factor of 32-bytes) + length is calculated regarding current emulation timings: + PAL timings : 50 frames/sec, 48000 samples/sec = 960 samples per frame = 3840 bytes (16 bits stereo samples) + NTSC timings: 60 frames/sec, 48000 samples/sec = 800 samples per frame = 3200 bytes (16 bits stereo samples) +*/ +static int dma_len = 3200; + +/*** + AudioDmaCallback -/*** AudioDmaCallback Genesis Plus only provides sound data on completion of each frame. - To try to make the audio less choppy, we synchronize emulation with audio DMA - This ensure we only update audio framebuffer when DMA is finished + To try to make the audio less choppy, we synchronize frame emulation with audio DMA + This ensure we don't access current active audiobuffer until a new DMA has been started + This also makes frame emulation sync completely independent from video sync ***/ static void AudioDmaCallback() { frameticker++; } +/*** + ogc_audio__init + + This function initializes the Audio Interface and DMA callback + Default samplerate is set to 48khZ + ***/ void ogc_audio__init(void) { AUDIO_Init (NULL); AUDIO_SetDSPSampleRate (AI_SAMPLERATE_48KHZ); AUDIO_RegisterDMACallback (AudioDmaCallback); - mixbuffer = 0; memset(soundbuffer, 0, 2 * 3840); } +/*** + ogc_audio__update + + This function is called at the end of each frame, once the current soundbuffer has been updated + DMA sync and switching ensure we never access the active DMA buffer + This function set the next DMA buffer + Parameters will be taken in account ONLY when current DMA has finished + ***/ void ogc_audio__update(void) { - /* buffer size */ - uint32 dma_len = vdp_pal ? 3840 : 3200; - - /* update DMA settings (this will only be taken in account when current DMA finishes) */ AUDIO_InitDMA((u32) soundbuffer[mixbuffer], dma_len); - - /* flush data from CPU cache */ DCFlushRange(soundbuffer[mixbuffer], dma_len); - - /* switch buffer */ mixbuffer ^= 1; } -void ogc_audio__stop(void) -{ - /* stop audio DMA */ - AUDIO_StopDMA (); - IsPlaying = 0; - - /* reset audio buffers */ - mixbuffer = 0; - memset(soundbuffer, 0, 2 * 3840); -} +/*** + ogc_audio__start + This function restarts Audio DMA processing + This is called only ONCE, when emulation loop starts or when coming back from Main Menu + DMA length is used for frame emulation synchronization (PAL & NTSC timings) + DMA is *automatically* restarted once the configured audio length has been output + When DMA parameters are not updated, same soundbuffer is played again + DMA parameters can be updated using successive calls to AUDIO_InitDMA (see above) + ***/ void ogc_audio__start(void) { if (!IsPlaying) { - /* buffer size */ dma_len = vdp_pal ? 3840 : 3200; - - /* set first DMA parameters */ - AUDIO_InitDMA((u32) soundbuffer[1], dma_len); - - /* start audio DMA */ + AUDIO_InitDMA((u32) soundbuffer[0], dma_len); AUDIO_StartDMA(); - IsPlaying = 1; } } + +/*** + ogc_audio__stop + + This function reset current Audio DMA process and clear soundbuffers + This is called when going back to Main Menu + DMA need to be restarted when going back to the game (see above) + ***/ +void ogc_audio__stop(void) +{ + AUDIO_StopDMA (); + IsPlaying = 0; + mixbuffer = 1; + memset(soundbuffer, 0, 2 * 3840); +} diff --git a/source/ngc/ogc_video.c b/source/ngc/ogc_video.c index 7bc31be..43d725d 100644 --- a/source/ngc/ogc_video.c +++ b/source/ngc/ogc_video.c @@ -377,10 +377,11 @@ static void gxStart(void) /*** Reset XFB ***/ GX_CopyDisp (xfb[whichfb ^ 1], GX_TRUE); + GX_Flush (); /*** Initialize texture data ***/ - texturemem = memalign(32, TEX_WIDTH * TEX_HEIGHT * 2); - memset (texturemem, 0, TEX_WIDTH * TEX_HEIGHT * 2); + texturemem = memalign(32, TEX_SIZE); + memset (texturemem, 0, TEX_SIZE); /*** Initialize renderer */ draw_init(); @@ -545,6 +546,7 @@ void ogc_video__reset() GX_SetPixelFmt (rmode->aa ? GX_PF_RGB565_Z16 : GX_PF_RGB8_Z24, GX_ZC_LINEAR); guOrtho(p, rmode->efbHeight/2, -(rmode->efbHeight/2), -(rmode->fbWidth/2), rmode->fbWidth/2, 100, 1000); GX_LoadProjectionMtx (p, GX_ORTHOGRAPHIC); + GX_Flush (); /* Software NTSC filter */ if (config.ntsc == 1)