mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-25 18:51:49 +01:00
added GX_Flush(), documented sound rendering core
This commit is contained in:
parent
840a370418
commit
f6a242a031
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user