From 31edafde039cf3a88e3b9d76322c061831670a9d Mon Sep 17 00:00:00 2001 From: aliaspider Date: Sun, 6 Nov 2016 11:55:56 +0100 Subject: [PATCH 1/5] (WIIU) add timers, fix retro_sleep. --- frontend/drivers/platform_wiiu.c | 6 +++--- libretro-common/features/features_cpu.c | 9 +++++++-- libretro-common/include/retro_miscellaneous.h | 3 ++- wiiu/system/wiiu.h | 18 ++++++++++++++++++ wiiu/wiiu_dbg.h | 1 + 5 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 wiiu/system/wiiu.h diff --git a/frontend/drivers/platform_wiiu.c b/frontend/drivers/platform_wiiu.c index fb944d32bd..0946a98da9 100644 --- a/frontend/drivers/platform_wiiu.c +++ b/frontend/drivers/platform_wiiu.c @@ -262,7 +262,7 @@ int __entry_menu(int argc, char **argv) #if 0 int argc_ = 2; // char* argv_[] = {"sd:/retroarch/retroarch.elf", "sd:/rom.nes", NULL}; - char* argv_[] = {"sd:/retroarch/retroarch.elf", "sd:/content/rom.sfc", NULL}; + char* argv_[] = {"sd:/retroarch/retroarch.elf", "sd:/rom.sfc", NULL}; rarch_main(argc_, argv_, NULL); #else @@ -274,8 +274,8 @@ int __entry_menu(int argc, char **argv) unsigned sleep_ms = 0; int ret = runloop_iterate(&sleep_ms); -// if (ret == 1 && sleep_ms > 0) -// retro_sleep(sleep_ms); + if (ret == 1 && sleep_ms > 0) + retro_sleep(sleep_ms); task_queue_ctl(TASK_QUEUE_CTL_CHECK, NULL); if (ret == -1) break; diff --git a/libretro-common/features/features_cpu.c b/libretro-common/features/features_cpu.c index b6c2f73f5c..0dafa77eba 100644 --- a/libretro-common/features/features_cpu.c +++ b/libretro-common/features/features_cpu.c @@ -73,6 +73,11 @@ #include #endif +#ifdef WIIU +#include +#include "wiiu/system/wiiu.h" +#endif + #if defined(_3DS) #include <3ds/svc.h> #include <3ds/os.h> @@ -169,7 +174,7 @@ retro_perf_tick_t cpu_features_get_perf_counter(void) #elif defined(_3DS) time_ticks = svcGetSystemTick(); #elif defined(WIIU) - time_ticks = 0; + time_ticks = OSGetSystemTime(); #elif defined(__mips__) struct timeval tv; gettimeofday(&tv,NULL); @@ -219,7 +224,7 @@ retro_time_t cpu_features_get_time_usec(void) #elif defined(VITA) return sceKernelGetProcessTimeWide(); #elif defined(WIIU) - return 0; + return ticks_to_us(OSGetSystemTime()); #else #error "Your platform does not have a timer function implemented in cpu_features_get_time_usec(). Cannot continue." #endif diff --git a/libretro-common/include/retro_miscellaneous.h b/libretro-common/include/retro_miscellaneous.h index d0ad4aeeca..83d004b8a0 100644 --- a/libretro-common/include/retro_miscellaneous.h +++ b/libretro-common/include/retro_miscellaneous.h @@ -34,6 +34,7 @@ #include #elif defined(WIIU) #include +#include "system/wiiu.h" #elif defined(PSP) #include #elif defined(VITA) @@ -103,7 +104,7 @@ static INLINE void retro_sleep(unsigned msec) #elif defined(GEKKO) || defined(__PSL1GHT__) || defined(__QNX__) usleep(1000 * msec); #elif defined(WIIU) - OSSleepTicks(((uint64_t)msec * 248625000)/4000000); + OSSleepTicks(ms_to_ticks(msec)); #else struct timespec tv = {0}; tv.tv_sec = msec / 1000; diff --git a/wiiu/system/wiiu.h b/wiiu/system/wiiu.h new file mode 100644 index 0000000000..84aadd8ee3 --- /dev/null +++ b/wiiu/system/wiiu.h @@ -0,0 +1,18 @@ +#ifndef WIIU_H +#define WIIU_H + +#define wiiu_bus_clock (17 * 13 * 5*5*5 * 5*5*5 * 3*3 * 2*2*2) // 248.625000 Mhz +#define wiiu_cpu_clock (17 * 13 * 5*5*5 * 5*5*5 * 5 * 3*3 * 2*2*2) // 1243.125000 Mhz +#define wiiu_timer_clock (17 * 13 * 5*5*5 * 5*5*5 * 3*3 * 2) // 62.156250 Mhz + +#define sec_to_ticks(s) (((17 * 13 * 5*5*5 * 5*5*5 * 3*3 * 2) * (uint64_t)(s))) +#define ms_to_ticks(ms) (((17 * 13 * 5*5*5 * 3*3) * (uint64_t)(ms)) / (2*2)) +#define us_to_ticks(us) (((17 * 13 * 3*3) * (uint64_t)(us)) / (2*2* 2*2*2)) +#define ns_to_ticks(ns) (((17 * 13 * 3*3) * (uint64_t)(ns)) / (2*2* 2*2*2* 2*2*2 *5*5*5)) + +#define ticks_to_sec(ticks) (((uint64_t)(ticks)) / (17 * 13 * 5*5*5 * 5*5*5 * 3*3 * 2)) +#define ticks_to_ms(ticks) (((uint64_t)(ticks) * (2*2)) / (17 * 13 * 5*5*5 * 3*3)) +#define ticks_to_us(ticks) (((uint64_t)(ticks) * (2*2 * 2*2*2)) / (17 * 13 * 3*3)) +#define ticks_to_ns(ticks) (((uint64_t)(ticks) * (2*2 * 2*2*2 * 2*2*2 * 5*5*5)) / (17 * 13 * 3*3)) + +#endif // WIIU_H diff --git a/wiiu/wiiu_dbg.h b/wiiu/wiiu_dbg.h index 63851d18ef..d596e21284 100644 --- a/wiiu/wiiu_dbg.h +++ b/wiiu/wiiu_dbg.h @@ -16,6 +16,7 @@ extern "C" { #define DEBUG_LINE() do{printf("%s:%d.\n",__FUNCTION__, __LINE__);fflush(stdout);}while(0) #define DEBUG_STR(X) printf( "%s: %s\n", #X, (char*)(X)) #define DEBUG_VAR(X) printf( "%-20s: 0x%08X\n", #X, (u32)(X)) +#define DEBUG_VAR2(X) printf( "%-20s: 0x%08X (%i)\n", #X, (u32)(X), (int)(X)) #define DEBUG_INT(X) printf( "%-20s: %10i\n", #X, (s32)(X)) #define DEBUG_FLOAT(X) printf( "%-20s: %10.3f\n", #X, (float)(X)) #define DEBUG_VAR64(X) printf( #X"\r\t\t\t\t : 0x%016llX\n", (u64)(X)) From a0383e6b6a39e7e3305f39abb385e6405ccb5cdc Mon Sep 17 00:00:00 2001 From: aliaspider Date: Sun, 6 Nov 2016 18:59:39 +0100 Subject: [PATCH 2/5] (WIIU) keep the dynlib handles. --- wiiu/system/dynamic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wiiu/system/dynamic.c b/wiiu/system/dynamic.c index da1766a5c2..e10c13933b 100644 --- a/wiiu/system/dynamic.c +++ b/wiiu/system/dynamic.c @@ -8,11 +8,11 @@ #undef EXPORT #undef EXPORT_BEGIN -#undef EXPORT_END +//#undef EXPORT_END #define EXPORT(name) do{if(OSDynLoad_FindExport(handle, 0, #name, &addr_##name) < 0)OSFatal("Function " # name " is NULL");} while(0) #define EXPORT_BEGIN(lib) OSDynLoad_Acquire(#lib, &handle) -#define EXPORT_END() OSDynLoad_Release(handle) +//#define EXPORT_END() OSDynLoad_Release(handle) void InitFunctionPointers(void) { From e5a07a406aa9ccc31775d1fec36c6f8b6e2160ac Mon Sep 17 00:00:00 2001 From: aliaspider Date: Sun, 6 Nov 2016 18:59:50 +0100 Subject: [PATCH 3/5] (WIIU) cleanup debug code from the video driver. --- gfx/drivers/wiiu_gfx.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/gfx/drivers/wiiu_gfx.c b/gfx/drivers/wiiu_gfx.c index 30c118d862..238e840216 100644 --- a/gfx/drivers/wiiu_gfx.c +++ b/gfx/drivers/wiiu_gfx.c @@ -112,15 +112,6 @@ static wiiu_set_position(position_t* position, GX2ColorBuffer* draw_buffer, floa position[3].x = -1.0f; position[3].y = 1.0f; - DEBUG_FLOAT(position[0].x); - DEBUG_FLOAT(position[0].y); - DEBUG_FLOAT(position[1].x); - DEBUG_FLOAT(position[1].y); - DEBUG_FLOAT(position[2].x); - DEBUG_FLOAT(position[2].y); - DEBUG_FLOAT(position[3].x); - DEBUG_FLOAT(position[3].y); - GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, position, 4 * sizeof(*position)); } @@ -306,10 +297,6 @@ static void* wiiu_gfx_init(const video_info_t* video, ((uint32_t*)wiiu->menu.texture.surface.image)[i] = 0xFFFFFFFF; ((uint32_t*)wiiu->menu.texture.surface.image)[0] = 0xFF0000FF; - DEBUG_VAR(wiiu->menu.texture.surface.width); - DEBUG_VAR(wiiu->menu.texture.surface.height); - DEBUG_VAR(wiiu->menu.texture.surface.alignment); - DEBUG_VAR(wiiu->menu.texture.surface.imageSize); GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, wiiu->menu.texture.surface.image, wiiu->menu.texture.surface.imageSize); @@ -333,8 +320,6 @@ static void* wiiu_gfx_init(const video_info_t* video, *input_data = wiiuinput; } - DEBUG_LINE(); - return wiiu; } static void wiiu_gfx_free(void* data) @@ -378,7 +363,6 @@ static void wiiu_gfx_free(void* data) free(wiiu); - DEBUG_LINE(); } static bool wiiu_gfx_frame(void* data, const void* frame, @@ -581,9 +565,6 @@ static void wiiu_set_texture_frame(void* data, const void* frame, bool rgb32, const uint16_t* src = frame; uint16_t* dst = (uint16_t*)wiiu->menu.texture.surface.image; - DEBUG_VAR(width); - DEBUG_VAR(height); - for (i = 0; i < height; i++) { memcpy(dst, src, width * sizeof(uint16_t)); From 5a17f0ba3c90ab9b452969659adbf11493bf02ea Mon Sep 17 00:00:00 2001 From: aliaspider Date: Sun, 6 Nov 2016 19:03:08 +0100 Subject: [PATCH 4/5] add missing copyright notice. --- wiiu/gx2_shader_inl.h | 15 +++++++++++++++ wiiu/tex_shader.c | 14 ++++++++++++++ wiiu/tex_shader.h | 15 +++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/wiiu/gx2_shader_inl.h b/wiiu/gx2_shader_inl.h index 2ffaa959de..bf35cfcaf2 100644 --- a/wiiu/gx2_shader_inl.h +++ b/wiiu/gx2_shader_inl.h @@ -1,3 +1,18 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2014-2016 - Ali Bouhlel + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + #ifndef GX2_SHADER_INL_H #define GX2_SHADER_INL_H diff --git a/wiiu/tex_shader.c b/wiiu/tex_shader.c index fd1ad28f2b..d97475d477 100644 --- a/wiiu/tex_shader.c +++ b/wiiu/tex_shader.c @@ -1,3 +1,17 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2014-2016 - Ali Bouhlel + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ #include #include diff --git a/wiiu/tex_shader.h b/wiiu/tex_shader.h index 7b162f0037..fa2571aa17 100644 --- a/wiiu/tex_shader.h +++ b/wiiu/tex_shader.h @@ -1,3 +1,18 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2014-2016 - Ali Bouhlel + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + #ifndef TEX_SHADER_H #define TEX_SHADER_H #include From 86763e1e268c60eecf7a05f1d8174e01f5b1357c Mon Sep 17 00:00:00 2001 From: aliaspider Date: Sun, 6 Nov 2016 19:03:41 +0100 Subject: [PATCH 5/5] (WiiU) implement a sound driver. --- Makefile.wiiu | 2 +- audio/audio_driver.c | 3 + audio/audio_driver.h | 1 + audio/drivers/wiiu_audio.c | 300 +++++++++++++++++++++++++++++++++++++ 4 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 audio/drivers/wiiu_audio.c diff --git a/Makefile.wiiu b/Makefile.wiiu index bac0f270a4..26bffb9128 100644 --- a/Makefile.wiiu +++ b/Makefile.wiiu @@ -45,7 +45,7 @@ else # OBJ += menu/drivers_display/menu_display_wiiu.o OBJ += input/drivers/wiiu_input.o OBJ += input/drivers_joypad/wiiu_joypad.o -# OBJ += audio/drivers/wiiu_audio.o + OBJ += audio/drivers/wiiu_audio.o OBJ += frontend/drivers/platform_wiiu.o OBJ += gfx/video_filters/2xsai.o OBJ += gfx/video_filters/super2xsai.o diff --git a/audio/audio_driver.c b/audio/audio_driver.c index 5b04251860..dd5b79b4b5 100644 --- a/audio/audio_driver.c +++ b/audio/audio_driver.c @@ -96,6 +96,9 @@ static const audio_driver_t *audio_drivers[] = { #ifdef GEKKO &audio_gx, #endif +#ifdef WIIU + &audio_ax, +#endif #ifdef EMSCRIPTEN &audio_rwebaudio, #endif diff --git a/audio/audio_driver.h b/audio/audio_driver.h index 1845d31c58..16b3c6210f 100644 --- a/audio/audio_driver.h +++ b/audio/audio_driver.h @@ -204,6 +204,7 @@ extern audio_driver_t audio_coreaudio; extern audio_driver_t audio_xenon360; extern audio_driver_t audio_ps3; extern audio_driver_t audio_gx; +extern audio_driver_t audio_ax; extern audio_driver_t audio_psp; extern audio_driver_t audio_ctr_csnd; extern audio_driver_t audio_ctr_dsp; diff --git a/audio/drivers/wiiu_audio.c b/audio/drivers/wiiu_audio.c new file mode 100644 index 0000000000..0754567ab7 --- /dev/null +++ b/audio/drivers/wiiu_audio.c @@ -0,0 +1,300 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2014-2016 - Ali Bouhlel + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "wiiu/wiiu_dbg.h" + +#include "audio/audio_driver.h" +#include "configuration.h" +#include "performance_counters.h" +#include "runloop.h" + +typedef struct +{ + AXVoice* voice_l; + AXVoice* voice_r; + uint16_t* buffer_l; + uint16_t* buffer_r; + AXVoiceOffsets offsets_l; + AXVoiceOffsets offsets_r; + bool nonblocking; + bool playing; + + uint32_t pos; + uint32_t playpos; + uint32_t cpu_ticks_last; +} ax_audio_t; + +#define AX_AUDIO_COUNT (1u << 14u) +#define AX_AUDIO_COUNT_MASK (AX_AUDIO_COUNT - 1u) +#define AX_AUDIO_SIZE (AX_AUDIO_COUNT * sizeof(int16_t)) +#define AX_AUDIO_SIZE_MASK (AX_AUDIO_SIZE - 1u) + + +#define AX_AUDIO_RATE 48000 +#define ax_audio_ticks_to_samples(ticks) (((ticks) * 64) / 82875) +#define ax_audio_samples_to_ticks(samples) (((samples) * 82875) / 64) + +static void ax_voice_callback(ax_audio_t* ax_audio) +{ + DEBUG_LINE(); +} + +static void ax_audio_update_playpos(ax_audio_t* ax_audio) +{ + uint32_t samples_played = ax_audio_ticks_to_samples(OSGetSystemTick() - ax_audio->cpu_ticks_last); + + ax_audio->playpos = (ax_audio->playpos + samples_played) & AX_AUDIO_COUNT_MASK; + ax_audio->cpu_ticks_last += ax_audio_samples_to_ticks(samples_played); +} + +void ax_frame_callback(void) +{ + DEBUG_LINE(); +} + +static void* ax_audio_init(const char* device, unsigned rate, unsigned latency) +{ + ax_audio_t* ax = (ax_audio_t*)calloc(1, sizeof(ax_audio_t)); + + if (!ax) + return NULL; + + AXInitParams init = {AX_INIT_RENDERER_48KHZ, 0, 0}; + + AXInitWithParams(&init); + + ax->voice_l = AXAcquireVoice(10, (AXVoiceCallbackFn)ax_voice_callback, ax); + ax->voice_r = AXAcquireVoice(10, (AXVoiceCallbackFn)ax_voice_callback, ax); + if(!ax->voice_l || !ax->voice_r) + { + free(ax); + return NULL; + } + ax->buffer_l = malloc(AX_AUDIO_SIZE); + ax->buffer_r = malloc(AX_AUDIO_SIZE); + ax->offsets_l.data = ax->buffer_l; + ax->offsets_l.currentOffset = 0; + ax->offsets_l.loopOffset = 0; + ax->offsets_l.endOffset = AX_AUDIO_COUNT; + ax->offsets_l.loopingEnabled = AX_VOICE_LOOP_ENABLED; + ax->offsets_l.dataType = AX_VOICE_FORMAT_LPCM16; + ax->offsets_r.data = ax->buffer_r; + ax->offsets_r.currentOffset = 0; + ax->offsets_r.loopOffset = 0; + ax->offsets_r.endOffset = AX_AUDIO_COUNT; + ax->offsets_r.loopingEnabled = AX_VOICE_LOOP_ENABLED; + ax->offsets_r.dataType = AX_VOICE_FORMAT_LPCM16; + AXSetVoiceOffsets(ax->voice_l, &ax->offsets_l); + AXSetVoiceOffsets(ax->voice_r, &ax->offsets_r); + + AXSetVoiceSrcType(ax->voice_l, AX_VOICE_SRC_TYPE_NONE); + AXSetVoiceSrcType(ax->voice_r, AX_VOICE_SRC_TYPE_NONE); + AXSetVoiceSrcRatio(ax->voice_l, 1.0f); + AXSetVoiceSrcRatio(ax->voice_r, 1.0f); + AXVoiceVeData ve = {0x4000, 0}; + AXSetVoiceVe(ax->voice_l, &ve); + AXSetVoiceVe(ax->voice_r, &ve); + AXVoiceDeviceMixData mix = {0}; + mix.bus[0].volume = 0x4000; + mix.bus[1].volume = 0x0000; + AXSetVoiceDeviceMix(ax->voice_l, AX_DEVICE_TYPE_DRC, 0, &mix); + AXSetVoiceDeviceMix(ax->voice_l, AX_DEVICE_TYPE_TV, 0, &mix); + mix.bus[0].volume = 0x0000; + mix.bus[1].volume = 0x4000; + AXSetVoiceDeviceMix(ax->voice_r, AX_DEVICE_TYPE_DRC, 0, &mix); + AXSetVoiceDeviceMix(ax->voice_r, AX_DEVICE_TYPE_TV, 0, &mix); + AXSetVoiceState(ax->voice_l, AX_VOICE_STATE_PLAYING); + AXSetVoiceState(ax->voice_r, AX_VOICE_STATE_PLAYING); + + ax->pos = 0; + ax->playpos = 0; + ax->playing = true; + ax->cpu_ticks_last = OSGetSystemTick(); + + config_get_ptr()->audio.out_rate = AX_AUDIO_RATE; + + return ax; +} + +static void ax_audio_free(void* data) +{ + ax_audio_t* ax = (ax_audio_t*)data; + + free(ax->buffer_l); + free(ax->buffer_r); + free(ax); + AXQuit(); +} + +static ssize_t ax_audio_write(void* data, const void* buf, size_t size) +{ + int i; + static struct retro_perf_counter ax_audio_write_perf = {0}; + ax_audio_t* ax = (ax_audio_t*)data; + const uint16_t* src = buf; + uint32_t samples_played = 0; + uint64_t current_tick = 0; + + performance_counter_init(&ax_audio_write_perf, "ax_audio_write"); + performance_counter_start(&ax_audio_write_perf); + + ax_audio_update_playpos(ax); + + if ((((ax->playpos - ax->pos) & AX_AUDIO_COUNT_MASK) < (AX_AUDIO_COUNT >> 2)) || + (((ax->pos - ax->playpos) & AX_AUDIO_COUNT_MASK) < (AX_AUDIO_COUNT >> 4)) || + (((ax->playpos - ax->pos) & AX_AUDIO_COUNT_MASK) < (size >> 2))) + { + if (ax->nonblocking) + ax->pos = (ax->playpos + (AX_AUDIO_COUNT >> 1)) & AX_AUDIO_COUNT_MASK; + else + { + do + { + /* todo: compute the correct sleep period */ + retro_sleep(1); + ax_audio_update_playpos(ax); + } + while (((ax->playpos - ax->pos) & AX_AUDIO_COUNT_MASK) < (AX_AUDIO_COUNT >> 1) + || (((ax->pos - ax->playpos) & AX_AUDIO_COUNT_MASK) < (AX_AUDIO_COUNT >> 4))); + } + } + + uint16_t* dst_l = (uint16_t*)ax->buffer_l; + for (i = 0; i < (size >> 1); i += 2) + { +// ax->l[ax->pos] = src[i]; +// ax->r[ax->pos] = src[i + 1]; + ax->buffer_l[ax->pos] = (src[i]); + ax->buffer_r[ax->pos] = (src[i + 1]); + ax->pos++; + ax->pos &= AX_AUDIO_COUNT_MASK; + } + DCFlushRange(ax->buffer_l, AX_AUDIO_SIZE); + DCFlushRange(ax->buffer_r, AX_AUDIO_SIZE); + + + performance_counter_stop(&ax_audio_write_perf); + + return size; +} + +static bool ax_audio_stop(void* data) +{ + ax_audio_t* ax = (ax_audio_t*)data; + + /* TODO */ + if(ax->playing) + { +// AXSetVoiceVeDelta(ax->voice, -128); + AXVoiceVeData ve = {0}; + AXSetVoiceVe(ax->voice_l, &ve); + AXSetVoiceVe(ax->voice_r, &ve); + ax->playing = false; + } + + return true; +} + +static bool ax_audio_alive(void* data) +{ + ax_audio_t* ax = (ax_audio_t*)data; + return ax->playing; +} + +static bool ax_audio_start(void* data) +{ + ax_audio_t* ax = (ax_audio_t*)data; + + /* Prevents restarting audio when the menu + * is toggled off on shutdown */ + + if (runloop_ctl(RUNLOOP_CTL_IS_SHUTDOWN, NULL)) + return true; + + /* TODO */ + + if(!ax->playing) + { + AXVoiceVeData ve = {0x4000, 0}; + AXSetVoiceVe(ax->voice_l, &ve); + AXSetVoiceVe(ax->voice_r, &ve); + +// AXSetVoiceVeDelta(ax->voice, 128); + ax->playing = true; + } + + return true; +} + +static void ax_audio_set_nonblock_state(void* data, bool state) +{ + ax_audio_t* ax = (ax_audio_t*)data; + +// if (ax) +// ax->nonblocking = state; + ax->nonblocking = true; +} + +static bool ax_audio_use_float(void* data) +{ + (void)data; + return false; +} + +static size_t ax_audio_write_avail(void* data) +{ + ax_audio_t* ax = (ax_audio_t*)data; + + ax_audio_update_playpos(ax); + return (ax->playpos - ax->pos) & AX_AUDIO_COUNT_MASK; +} + +static size_t ax_audio_buffer_size(void* data) +{ + (void)data; + return AX_AUDIO_COUNT; +} + + +audio_driver_t audio_ax = +{ + ax_audio_init, + ax_audio_write, + ax_audio_stop, + ax_audio_start, + ax_audio_alive, + ax_audio_set_nonblock_state, + ax_audio_free, + ax_audio_use_float, + "AX", + NULL, + NULL, + ax_audio_write_avail, + ax_audio_buffer_size +};