mirror of
https://github.com/libretro/RetroArch
synced 2025-02-07 21:39:54 +00:00
Merge pull request #1634 from aliaspider/master
(CTR/3DS) video/audio drivers update.
This commit is contained in:
commit
46cadbe846
@ -21,20 +21,24 @@
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
bool nonblocking;
|
bool nonblocking;
|
||||||
|
bool playing;
|
||||||
int16_t* l;
|
int16_t* l;
|
||||||
int16_t* r;
|
int16_t* r;
|
||||||
int16_t* silence;
|
|
||||||
|
|
||||||
uint32_t l_paddr;
|
uint32_t l_paddr;
|
||||||
uint32_t r_paddr;
|
uint32_t r_paddr;
|
||||||
uint32_t silence_paddr;
|
|
||||||
|
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
|
|
||||||
|
uint32_t playpos;
|
||||||
|
uint32_t cpu_ticks_per_sample;
|
||||||
|
uint64_t cpu_ticks_last;
|
||||||
|
|
||||||
int rate;
|
int rate;
|
||||||
|
|
||||||
} ctr_audio_t;
|
} ctr_audio_t;
|
||||||
|
|
||||||
#define CTR_AUDIO_COUNT (1u << 12u)
|
#define CTR_AUDIO_COUNT (1u << 11u)
|
||||||
#define CTR_AUDIO_COUNT_MASK (CTR_AUDIO_COUNT - 1u)
|
#define CTR_AUDIO_COUNT_MASK (CTR_AUDIO_COUNT - 1u)
|
||||||
#define CTR_AUDIO_SIZE (CTR_AUDIO_COUNT * sizeof(int16_t))
|
#define CTR_AUDIO_SIZE (CTR_AUDIO_COUNT * sizeof(int16_t))
|
||||||
#define CTR_AUDIO_SIZE_MASK (CTR_AUDIO_SIZE - 1u)
|
#define CTR_AUDIO_SIZE_MASK (CTR_AUDIO_SIZE - 1u)
|
||||||
@ -52,31 +56,30 @@ static void *ctr_audio_init(const char *device, unsigned rate, unsigned latency)
|
|||||||
|
|
||||||
ctr_audio_t *ctr = (ctr_audio_t*)calloc(1, sizeof(ctr_audio_t));
|
ctr_audio_t *ctr = (ctr_audio_t*)calloc(1, sizeof(ctr_audio_t));
|
||||||
|
|
||||||
ctr->l = linearAlloc(CTR_AUDIO_SIZE);
|
ctr->l = linearAlloc(CTR_AUDIO_SIZE);
|
||||||
ctr->r = linearAlloc(CTR_AUDIO_SIZE);
|
ctr->r = linearAlloc(CTR_AUDIO_SIZE);
|
||||||
ctr->silence = linearAlloc(CTR_AUDIO_SIZE);
|
|
||||||
|
|
||||||
memset(ctr->l, 0, CTR_AUDIO_SIZE);
|
memset(ctr->l, 0, CTR_AUDIO_SIZE);
|
||||||
memset(ctr->r, 0, CTR_AUDIO_SIZE);
|
memset(ctr->r, 0, CTR_AUDIO_SIZE);
|
||||||
memset(ctr->silence, 0, CTR_AUDIO_SIZE);
|
|
||||||
|
|
||||||
ctr->l_paddr = osConvertVirtToPhys((u32)ctr->l);
|
ctr->l_paddr = osConvertVirtToPhys((u32)ctr->l);
|
||||||
ctr->r_paddr = osConvertVirtToPhys((u32)ctr->r);
|
ctr->r_paddr = osConvertVirtToPhys((u32)ctr->r);
|
||||||
ctr->silence_paddr = osConvertVirtToPhys((u32)ctr->silence);
|
|
||||||
|
|
||||||
ctr->pos = 0;
|
ctr->pos = 0;
|
||||||
ctr->rate = rate;
|
ctr->rate = rate;
|
||||||
|
ctr->cpu_ticks_per_sample = CSND_TIMER(rate) * 4;
|
||||||
|
|
||||||
GSPGPU_FlushDataCache(NULL, (u8*)ctr->silence, CTR_AUDIO_SIZE);
|
GSPGPU_FlushDataCache(NULL, (u8*)ctr->l_paddr, CTR_AUDIO_SIZE);
|
||||||
|
GSPGPU_FlushDataCache(NULL, (u8*)ctr->r_paddr, CTR_AUDIO_SIZE);
|
||||||
csndPlaySound(0x8, SOUND_LOOPMODE(CSND_LOOPMODE_NORMAL)| SOUND_FORMAT(CSND_ENCODING_PCM16),
|
csndPlaySound(0x8, SOUND_LOOPMODE(CSND_LOOPMODE_NORMAL)| SOUND_FORMAT(CSND_ENCODING_PCM16),
|
||||||
rate, ctr->silence, ctr->silence, CTR_AUDIO_SIZE);
|
rate, 1.0, -1.0, ctr->l, ctr->l, CTR_AUDIO_SIZE);
|
||||||
|
|
||||||
csndPlaySound(0x9, SOUND_LOOPMODE(CSND_LOOPMODE_NORMAL)| SOUND_FORMAT(CSND_ENCODING_PCM16),
|
csndPlaySound(0x9, SOUND_LOOPMODE(CSND_LOOPMODE_NORMAL)| SOUND_FORMAT(CSND_ENCODING_PCM16),
|
||||||
rate, ctr->silence, ctr->silence, CTR_AUDIO_SIZE);
|
rate, 1.0, 1.0, ctr->r, ctr->r, CTR_AUDIO_SIZE);
|
||||||
|
|
||||||
CSND_SetVol(0x8, 0xFFFF, 0);
|
ctr->playpos = 0;
|
||||||
CSND_SetVol(0x9, 0, 0xFFFF);
|
ctr->cpu_ticks_last = svcGetSystemTick();
|
||||||
csndExecCmds(false);
|
ctr->playing = true;
|
||||||
|
|
||||||
return ctr;
|
return ctr;
|
||||||
}
|
}
|
||||||
@ -92,7 +95,6 @@ static void ctr_audio_free(void *data)
|
|||||||
|
|
||||||
linearFree(ctr->l);
|
linearFree(ctr->l);
|
||||||
linearFree(ctr->r);
|
linearFree(ctr->r);
|
||||||
linearFree(ctr->silence);
|
|
||||||
|
|
||||||
free(ctr);
|
free(ctr);
|
||||||
}
|
}
|
||||||
@ -107,45 +109,35 @@ static ssize_t ctr_audio_write(void *data, const void *buf, size_t size)
|
|||||||
int i;
|
int i;
|
||||||
const uint16_t* src = buf;
|
const uint16_t* src = buf;
|
||||||
|
|
||||||
RARCH_PERFORMANCE_INIT(ctraudio_f);
|
RARCH_PERFORMANCE_INIT(ctraudio_f);
|
||||||
RARCH_PERFORMANCE_START(ctraudio_f);
|
RARCH_PERFORMANCE_START(ctraudio_f);
|
||||||
|
|
||||||
CSND_ChnInfo channel_info;
|
uint64_t current_tick = svcGetSystemTick();
|
||||||
csndGetState(0x8, &channel_info);
|
uint32_t samples_played = (current_tick - ctr->cpu_ticks_last) / ctr->cpu_ticks_per_sample;
|
||||||
|
ctr->playpos = (ctr->playpos + samples_played) & CTR_AUDIO_COUNT_MASK;
|
||||||
|
ctr->cpu_ticks_last += samples_played * ctr->cpu_ticks_per_sample;
|
||||||
|
|
||||||
uint32_t playpos;
|
|
||||||
if((channel_info.samplePAddr >= (ctr->l_paddr)) &&
|
|
||||||
(channel_info.samplePAddr < (ctr->l_paddr + CTR_AUDIO_SIZE)))
|
|
||||||
{
|
|
||||||
playpos = (channel_info.samplePAddr - ctr->l_paddr) / sizeof(uint16_t);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CSND_SetBlock(0x8, 1, ctr->l_paddr, CTR_AUDIO_SIZE);
|
|
||||||
CSND_SetBlock(0x9, 1, ctr->r_paddr, CTR_AUDIO_SIZE);
|
|
||||||
csndExecCmds(false);
|
|
||||||
playpos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((((playpos - ctr->pos) & CTR_AUDIO_COUNT_MASK) < (CTR_AUDIO_COUNT >> 2)) ||
|
if((((ctr->playpos - ctr->pos) & CTR_AUDIO_COUNT_MASK) < (CTR_AUDIO_COUNT >> 2)) ||
|
||||||
(((ctr->pos - playpos ) & CTR_AUDIO_COUNT_MASK) < (CTR_AUDIO_COUNT >> 4)) ||
|
(((ctr->pos - ctr->playpos ) & CTR_AUDIO_COUNT_MASK) < (CTR_AUDIO_COUNT >> 4)) ||
|
||||||
(((playpos - ctr->pos) & CTR_AUDIO_COUNT_MASK) < (size >> 2)))
|
(((ctr->playpos - ctr->pos) & CTR_AUDIO_COUNT_MASK) < (size >> 2)))
|
||||||
{
|
{
|
||||||
if (ctr->nonblocking)
|
if (ctr->nonblocking)
|
||||||
ctr->pos = (playpos + (CTR_AUDIO_COUNT >> 1)) & CTR_AUDIO_COUNT_MASK;
|
ctr->pos = (ctr->playpos + (CTR_AUDIO_COUNT >> 1)) & CTR_AUDIO_COUNT_MASK;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
do{
|
do{
|
||||||
|
/* todo: compute the correct sleep period */
|
||||||
svcSleepThread(100000);
|
svcSleepThread(100000);
|
||||||
// svcSleepThread(((s64)(CTR_AUDIO_COUNT >> 8) * 1000000000) / ctr->rate);
|
current_tick = svcGetSystemTick();
|
||||||
csndGetState(0x8, &channel_info);
|
samples_played = (current_tick - ctr->cpu_ticks_last) / ctr->cpu_ticks_per_sample;
|
||||||
playpos = (channel_info.samplePAddr - ctr->l_paddr) / sizeof(uint16_t);
|
ctr->playpos = (ctr->playpos + samples_played) & CTR_AUDIO_COUNT_MASK;
|
||||||
}while (((playpos - ctr->pos) & CTR_AUDIO_COUNT_MASK) < (CTR_AUDIO_COUNT >> 1)
|
ctr->cpu_ticks_last += samples_played * ctr->cpu_ticks_per_sample;
|
||||||
|| (((ctr->pos - playpos) & CTR_AUDIO_COUNT_MASK) < (CTR_AUDIO_COUNT >> 4)));
|
}while (((ctr->playpos - ctr->pos) & CTR_AUDIO_COUNT_MASK) < (CTR_AUDIO_COUNT >> 1)
|
||||||
|
|| (((ctr->pos - ctr->playpos) & CTR_AUDIO_COUNT_MASK) < (CTR_AUDIO_COUNT >> 4)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < (size >> 1); i += 2)
|
for (i = 0; i < (size >> 1); i += 2)
|
||||||
{
|
{
|
||||||
ctr->l[ctr->pos] = src[i];
|
ctr->l[ctr->pos] = src[i];
|
||||||
@ -153,6 +145,9 @@ static ssize_t ctr_audio_write(void *data, const void *buf, size_t size)
|
|||||||
ctr->pos++;
|
ctr->pos++;
|
||||||
ctr->pos &= CTR_AUDIO_COUNT_MASK;
|
ctr->pos &= CTR_AUDIO_COUNT_MASK;
|
||||||
}
|
}
|
||||||
|
GSPGPU_FlushDataCache(NULL, (u8*)ctr->l, CTR_AUDIO_SIZE);
|
||||||
|
GSPGPU_FlushDataCache(NULL, (u8*)ctr->r, CTR_AUDIO_SIZE);
|
||||||
|
|
||||||
|
|
||||||
RARCH_PERFORMANCE_STOP(ctraudio_f);
|
RARCH_PERFORMANCE_STOP(ctraudio_f);
|
||||||
|
|
||||||
@ -163,31 +158,51 @@ static bool ctr_audio_stop(void *data)
|
|||||||
{
|
{
|
||||||
ctr_audio_t* ctr = (ctr_audio_t*)data;
|
ctr_audio_t* ctr = (ctr_audio_t*)data;
|
||||||
|
|
||||||
CSND_SetBlock(0x8, 1, ctr->silence_paddr, CTR_AUDIO_SIZE);
|
/* using SetPlayState would make tracking the playback
|
||||||
CSND_SetBlock(0x9, 1, ctr->silence_paddr, CTR_AUDIO_SIZE);
|
* position more difficult */
|
||||||
|
|
||||||
|
// CSND_SetPlayState(0x8, 0);
|
||||||
|
// CSND_SetPlayState(0x9, 0);
|
||||||
|
|
||||||
|
/* setting the channel volume to 0 seems to make it
|
||||||
|
* impossible to set it back to full volume later */
|
||||||
|
|
||||||
|
CSND_SetVol(0x8, 0x00000001, 0);
|
||||||
|
CSND_SetVol(0x9, 0x00010000, 0);
|
||||||
csndExecCmds(false);
|
csndExecCmds(false);
|
||||||
|
|
||||||
|
ctr->playing = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ctr_audio_alive(void *data)
|
static bool ctr_audio_alive(void *data)
|
||||||
{
|
{
|
||||||
(void)data;
|
ctr_audio_t* ctr = (ctr_audio_t*)data;
|
||||||
return true;
|
return ctr->playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ctr_audio_start(void *data)
|
static bool ctr_audio_start(void *data)
|
||||||
{
|
{
|
||||||
ctr_audio_t* ctr = (ctr_audio_t*)data;
|
ctr_audio_t* ctr = (ctr_audio_t*)data;
|
||||||
|
global_t *global = global_get_ptr();
|
||||||
|
|
||||||
// csndPlaySound(0x8, SOUND_LOOPMODE(CSND_LOOPMODE_NORMAL)| SOUND_FORMAT(CSND_ENCODING_PCM16),
|
/* prevents restarting audio when the menu
|
||||||
// ctr->rate, ctr->l_paddr + ((ctr->pos + (CTR_AUDIO_SIZE / 2)) & CTR_AUDIO_SIZE_MASK),
|
* is toggled off on shutdown */
|
||||||
// (u32*)ctr->silence_paddr, CTR_AUDIO_SIZE);
|
|
||||||
|
if (global->system.shutdown)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// CSND_SetPlayState(0x8, 1);
|
||||||
|
// CSND_SetPlayState(0x9, 1);
|
||||||
|
|
||||||
|
CSND_SetVol(0x8, 0x00008000, 0);
|
||||||
|
CSND_SetVol(0x9, 0x80000000, 0);
|
||||||
|
|
||||||
CSND_SetBlock(0x8, 1, ctr->l_paddr, CTR_AUDIO_SIZE);
|
|
||||||
CSND_SetBlock(0x9, 1, ctr->r_paddr, CTR_AUDIO_SIZE);
|
|
||||||
csndExecCmds(false);
|
csndExecCmds(false);
|
||||||
|
|
||||||
|
ctr->playing = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,28 +228,37 @@ static bool ctr_frame(void* data, const void* frame,
|
|||||||
|
|
||||||
extern bool select_pressed;
|
extern bool select_pressed;
|
||||||
|
|
||||||
RARCH_PERFORMANCE_INIT(ctrframe_f);
|
|
||||||
RARCH_PERFORMANCE_START(ctrframe_f);
|
|
||||||
|
|
||||||
if (!width || !height)
|
if (!width || !height)
|
||||||
{
|
{
|
||||||
gspWaitForEvent(GSPEVENT_VBlank0, true);
|
gspWaitForEvent(GSPEVENT_VBlank0, true);
|
||||||
goto end;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!aptMainLoop())
|
if(!aptMainLoop())
|
||||||
{
|
{
|
||||||
event_command(EVENT_CMD_QUIT);
|
event_command(EVENT_CMD_QUIT);
|
||||||
goto end;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (select_pressed)
|
if (select_pressed)
|
||||||
{
|
{
|
||||||
event_command(EVENT_CMD_QUIT);
|
event_command(EVENT_CMD_QUIT);
|
||||||
goto end;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
svcWaitSynchronization(gspEvents[GSPEVENT_P3D], 20000000);
|
||||||
|
svcClearEvent(gspEvents[GSPEVENT_P3D]);
|
||||||
|
svcWaitSynchronization(gspEvents[GSPEVENT_PPF], 20000000);
|
||||||
|
svcClearEvent(gspEvents[GSPEVENT_PPF]);
|
||||||
|
|
||||||
|
gfxSwapBuffersGpu();
|
||||||
frames++;
|
frames++;
|
||||||
|
|
||||||
|
if (ctr->vsync)
|
||||||
|
svcWaitSynchronization(gspEvents[GSPEVENT_VBlank0], U64_MAX);
|
||||||
|
|
||||||
|
svcClearEvent(gspEvents[GSPEVENT_VBlank0]);
|
||||||
|
|
||||||
currentTick = svcGetSystemTick();
|
currentTick = svcGetSystemTick();
|
||||||
uint32_t diff = currentTick - lastTick;
|
uint32_t diff = currentTick - lastTick;
|
||||||
if(diff > CTR_CPU_TICKS_PER_SECOND)
|
if(diff > CTR_CPU_TICKS_PER_SECOND)
|
||||||
@ -260,23 +269,10 @@ static bool ctr_frame(void* data, const void* frame,
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("fps: %8.4f frames: %i\r", fps, total_frames++);
|
printf("fps: %8.4f frames: %i\r", fps, total_frames++);
|
||||||
// fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
/* enable this to profile the core without video output */
|
RARCH_PERFORMANCE_INIT(ctrframe_f);
|
||||||
#if 0
|
RARCH_PERFORMANCE_START(ctrframe_f);
|
||||||
if (!ctr->menu_texture_enable)
|
|
||||||
goto end;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
svcWaitSynchronization(gspEvents[GSPEVENT_P3D], 20000000);
|
|
||||||
svcClearEvent(gspEvents[GSPEVENT_P3D]);
|
|
||||||
svcWaitSynchronization(gspEvents[GSPEVENT_PPF], 20000000);
|
|
||||||
svcClearEvent(gspEvents[GSPEVENT_PPF]);
|
|
||||||
|
|
||||||
gfxSwapBuffersGpu();
|
|
||||||
|
|
||||||
if (ctr->vsync)
|
|
||||||
gspWaitForEvent(GSPEVENT_VBlank0, true);
|
|
||||||
|
|
||||||
ctrGuSetMemoryFill(true, (u32*)CTR_GPU_FRAMEBUFFER, 0x00000000,
|
ctrGuSetMemoryFill(true, (u32*)CTR_GPU_FRAMEBUFFER, 0x00000000,
|
||||||
(u32*)(CTR_GPU_FRAMEBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)),
|
(u32*)(CTR_GPU_FRAMEBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)),
|
||||||
@ -363,9 +359,6 @@ static bool ctr_frame(void* data, const void* frame,
|
|||||||
ctrGuDisplayTransfer(true, CTR_GPU_FRAMEBUFFER, 240,400, CTRGU_RGBA8,
|
ctrGuDisplayTransfer(true, CTR_GPU_FRAMEBUFFER, 240,400, CTRGU_RGBA8,
|
||||||
gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), 240,400,CTRGU_RGB8, CTRGU_MULTISAMPLE_NONE);
|
gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), 240,400,CTRGU_RGB8, CTRGU_MULTISAMPLE_NONE);
|
||||||
|
|
||||||
|
|
||||||
end:
|
|
||||||
// gspWaitForEvent(GSPEVENT_VBlank0, true);
|
|
||||||
RARCH_PERFORMANCE_STOP(ctrframe_f);
|
RARCH_PERFORMANCE_STOP(ctrframe_f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user