diff --git a/Makefile.wii b/Makefile.wii index 89364c3a9c..c6a6c38ae5 100644 --- a/Makefile.wii +++ b/Makefile.wii @@ -14,6 +14,8 @@ CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++ LD = $(DEVKITPPC)/bin/powerpc-eabi-ld +FREETYPECONFIG = $(DEVKITPRO)/portlibs/ppc/bin/freetype-config + DOL_TARGET := retroarch.dol ELF_TARGET := retroarch.elf @@ -21,10 +23,10 @@ INCLUDE := -I. -I$(DEVKITPRO)/libogc/include LIBDIRS := -L$(DEVKITPRO)/libogc/lib/wii -L. MACHDEP := -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -CFLAGS += -Wall -std=gnu99 $(MACHDEP) $(INCLUDE) -CXXFLAGS += -Wall -std=gnu99 $(MACHDEP) $(INCLUDE) -LDFLAGS := $(MACHDEP) -LIBS := -lfat -lretro -lwiiuse -logc -lbte -lfreetype +CFLAGS += -Wall -std=gnu99 $(MACHDEP) $(INCLUDE) $(shell $(FREETYPECONFIG) --cflags) +CXXFLAGS += -Wall -std=gnu99 $(MACHDEP) $(INCLUDE) $(shell $(FREETYPECONFIG) --cflags) +LDFLAGS := $(MACHDEP) $(shell $(FREETYPECONFIG) --libs) +LIBS := -lfat -lretro -lwiiuse -logc -lbte OBJ = console/griffin/griffin.o console/font.bmpobj console/rzlib/rzlib.o diff --git a/wii/audio.c b/wii/audio.c index 06ba4b3b27..541946a386 100644 --- a/wii/audio.c +++ b/wii/audio.c @@ -23,9 +23,9 @@ #include #include -#define CHUNK_FRAMES 256 +#define CHUNK_FRAMES 8 #define CHUNK_SIZE (CHUNK_FRAMES * sizeof(uint32_t)) -#define BLOCKS 4 +#define BLOCKS 128 typedef struct { @@ -40,7 +40,7 @@ typedef struct bool nonblock; } wii_audio_t; -static wii_audio_t *g_audio; +static wii_audio_t *g_audio = NULL; static void dma_callback(void) { @@ -55,19 +55,33 @@ static void dma_callback(void) static void *wii_audio_init(const char *device, unsigned rate, unsigned latency) { - static bool inited = false; - if (!inited) + AUDIO_Init(NULL); + AUDIO_RegisterDMACallback(dma_callback); + + if (abs((int) rate - 32000) < 1000) + { + AUDIO_SetDSPSampleRate(AI_SAMPLERATE_32KHZ); + g_settings.audio.out_rate = 32000; + } + else { - AUDIO_Init(NULL); AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ); g_settings.audio.out_rate = 48000; - AUDIO_RegisterDMACallback(dma_callback); - inited = true; } - g_audio = memalign(32, sizeof(*g_audio)); - memset(g_audio, 0, sizeof(*g_audio)); - LWP_InitQueue(&g_audio->cond); + if (!g_audio) + { + g_audio = memalign(32, sizeof(*g_audio)); + memset(g_audio, 0, sizeof(*g_audio)); + LWP_InitQueue(&g_audio->cond); + } + else + { + memset(g_audio->data, 0, sizeof(g_audio->data)); + g_audio->dma_busy = g_audio->dma_next = 0; + g_audio->write_ptr = 0; + g_audio->nonblock = false; + } g_audio->dma_write = BLOCKS - 1; DCFlushRange(g_audio->data, sizeof(g_audio->data)); @@ -130,6 +144,12 @@ static bool wii_audio_start(void *data) static void wii_audio_free(void *data) { AUDIO_StopDMA(); + AUDIO_RegisterDMACallback(NULL); + if (g_audio && g_audio->cond) + { + LWP_CloseQueue(g_audio->cond); + g_audio->cond = 0; + } if (data) free(data); g_audio = NULL; diff --git a/wii/main.c b/wii/main.c index e12dca3ba9..9cf0ef2239 100644 --- a/wii/main.c +++ b/wii/main.c @@ -158,6 +158,8 @@ int main(void) do{ repeat = rarch_main_iterate(); }while(repeat && !g_console.frame_advance_enable); + + audio_stop_func(); } if(g_console.emulator_initialized) diff --git a/wii/video.c b/wii/video.c index 338f8b00ff..55f466521b 100644 --- a/wii/video.c +++ b/wii/video.c @@ -25,12 +25,13 @@ // All very hardcoded for now. -static void *g_framebuf[3]; -static unsigned g_vi_framebuf; -static unsigned g_render_framebuf; +static void *g_framebuf[2]; +static unsigned g_current_framebuf; static unsigned g_filter; static bool g_vsync; +static lwpq_t g_video_cond; +static volatile bool g_draw_done; struct { @@ -45,25 +46,24 @@ static size_t display_list_size; static void retrace_callback(u32 retrace_count) { (void)retrace_count; - VIDEO_SetNextFramebuffer(g_framebuf[g_vi_framebuf % 3]); - VIDEO_Flush(); - if (g_vi_framebuf < g_render_framebuf) - g_vi_framebuf++; + g_draw_done = true; + LWP_ThreadSignal(g_video_cond); } static void setup_video_mode(GXRModeObj *mode) { VIDEO_Configure(mode); - for (unsigned i = 0; i < 3; i++) + for (unsigned i = 0; i < 2; i++) { g_framebuf[i] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(mode)); VIDEO_ClearFrameBuffer(mode, g_framebuf[i], COLOR_BLACK); } - g_vi_framebuf = 0; - g_render_framebuf = 1; + g_current_framebuf = 0; + g_draw_done = true; + LWP_InitQueue(&g_video_cond); VIDEO_SetNextFramebuffer(g_framebuf[0]); - VIDEO_SetPreRetraceCallback(retrace_callback); + VIDEO_SetPostRetraceCallback(retrace_callback); VIDEO_SetBlack(false); VIDEO_Flush(); VIDEO_WaitVSync(); @@ -171,7 +171,7 @@ void wii_video_deinit(void) VIDEO_SetBlack(true); VIDEO_Flush(); - for (unsigned i = 0; i < 3; i++) + for (unsigned i = 0; i < 2; i++) free(MEM_K1_TO_K0(g_framebuf[i])); } @@ -186,6 +186,84 @@ static void *wii_init(const video_info_t *video, return (void*)-1; } +static void update_texture_asm(const uint32_t *src, + unsigned width, unsigned height, unsigned pitch) +{ + register uint32_t tmp0, tmp1, tmp2, tmp3, line2, line2b, line3, line3b, line4, line4b, line5; + register uint32_t ormask = 0x80008000u; + register uint32_t *dst = g_tex.data; + + __asm__ __volatile__ ( + " srwi %[width], %[width], 2 \n" + " srwi %[height], %[height], 2 \n" + " subi %[tmp3], %[dst], 4 \n" + " mr %[dst], %[tmp3] \n" + " subi %[dst], %[dst], 4 \n" + " mr %[line2], %[pitch] \n" + " addi %[line2b], %[line2], 4 \n" + " mulli %[line3], %[pitch], 2 \n" + " addi %[line3b], %[line3], 4 \n" + " mulli %[line4], %[pitch], 3 \n" + " addi %[line4b], %[line4], 4 \n" + " mulli %[line5], %[pitch], 4 \n" + + "2: mtctr %[width] \n" + " mr %[tmp0], %[src] \n" + + "1: lwz %[tmp1], 0(%[src]) \n" + " or %[tmp1], %[tmp1], %[ormask] \n" + " stwu %[tmp1], 8(%[dst]) \n" + " lwz %[tmp2], 4(%[src]) \n" + " or %[tmp2], %[tmp2], %[ormask] \n" + " stwu %[tmp2], 8(%[tmp3]) \n" + + " lwzx %[tmp1], %[line2], %[src] \n" + " or %[tmp1], %[tmp1], %[ormask] \n" + " stwu %[tmp1], 8(%[dst]) \n" + " lwzx %[tmp2], %[line2b], %[src] \n" + " or %[tmp2], %[tmp2], %[ormask] \n" + " stwu %[tmp2], 8(%[tmp3]) \n" + + " lwzx %[tmp1], %[line3], %[src] \n" + " or %[tmp1], %[tmp1], %[ormask] \n" + " stwu %[tmp1], 8(%[dst]) \n" + " lwzx %[tmp2], %[line3b], %[src] \n" + " or %[tmp2], %[tmp2], %[ormask] \n" + " stwu %[tmp2], 8(%[tmp3]) \n" + + " lwzx %[tmp1], %[line4], %[src] \n" + " or %[tmp1], %[tmp1], %[ormask] \n" + " stwu %[tmp1], 8(%[dst]) \n" + " lwzx %[tmp2], %[line4b], %[src] \n" + " or %[tmp2], %[tmp2], %[ormask] \n" + " stwu %[tmp2], 8(%[tmp3]) \n" + + " addi %[src], %[src], 8 \n" + " bdnz 1b \n" + + " add %[src], %[tmp0], %[line5] \n" + " subic. %[height], %[height], 1 \n" + " bne 2b \n" + : [tmp0] "=&b" (tmp0), + [tmp1] "=&b" (tmp1), + [tmp2] "=&b" (tmp2), + [tmp3] "=&b" (tmp3), + [line2] "=&b" (line2), + [line2b] "=&b" (line2b), + [line3] "=&b" (line3), + [line3b] "=&b" (line3b), + [line4] "=&b" (line4), + [line4b] "=&b" (line4b), + [line5] "=&b" (line5), + [dst] "+b" (dst) + : [src] "b" (src), + [width] "b" (width), + [height] "b" (height), + [pitch] "b" (pitch), + [ormask] "b" (ormask) + ); +} + // Set MSB to get full RGB555. #define RGB15toRGB5A3(col) ((col) | 0x80008000u) @@ -193,7 +271,7 @@ static void *wii_init(const video_info_t *video, { \ const uint32_t *tmp_src = src; \ uint32_t *tmp_dst = dst; \ - for (unsigned x = 0; x < width; x += 8, tmp_src += 8, tmp_dst += 32) \ + for (unsigned x = 0; x < width2; x += 8, tmp_src += 8, tmp_dst += 32) \ { \ tmp_dst[ 0 + off] = RGB15toRGB5A3(tmp_src[0]); \ tmp_dst[ 1 + off] = RGB15toRGB5A3(tmp_src[1]); \ @@ -210,23 +288,30 @@ static void *wii_init(const video_info_t *video, static void update_texture(const uint32_t *src, unsigned width, unsigned height, unsigned pitch) { - pitch >>= 2; - width &= ~15; - height &= ~3; - width >>= 1; - - // Texture data is 4x4 tiled @ 15bpp. - // Use 32-bit to transfer more data per cycle. - uint32_t *dst = g_tex.data; - for (unsigned i = 0; i < height; i += 4, dst += 4 * width) + if (!(width & 3) && !(height & 3)) { - BLIT_LINE(0) - BLIT_LINE(2) - BLIT_LINE(4) - BLIT_LINE(6) + update_texture_asm(src, width, height, pitch); } - - init_texture(width << 1, height); + else + { + pitch >>= 2; + width &= ~15; + height &= ~3; + unsigned width2 = width >> 1; + + // Texture data is 4x4 tiled @ 15bpp. + // Use 32-bit to transfer more data per cycle. + uint32_t *dst = g_tex.data; + for (unsigned i = 0; i < height; i += 4, dst += 4 * width2) + { + BLIT_LINE(0) + BLIT_LINE(2) + BLIT_LINE(4) + BLIT_LINE(6) + } + } + + init_texture(width, height); DCFlushRange(g_tex.data, sizeof(g_tex.data)); GX_InvalidateTexAll(); } @@ -238,16 +323,19 @@ static bool wii_frame(void *data, const void *frame, (void)data; (void)msg; + while (g_vsync && !g_draw_done) + LWP_ThreadSleep(g_video_cond); + + g_draw_done = false; + g_current_framebuf ^= 1; update_texture(frame, width, height, pitch); GX_CallDispList(display_list, display_list_size); GX_DrawDone(); - GX_CopyDisp(g_framebuf[g_render_framebuf % 3], GX_TRUE); + GX_CopyDisp(g_framebuf[g_current_framebuf], GX_TRUE); GX_Flush(); - - g_render_framebuf++; - if (g_vsync && g_render_framebuf >= g_vi_framebuf + 2) - VIDEO_WaitVSync(); + VIDEO_SetNextFramebuffer(g_framebuf[g_current_framebuf]); + VIDEO_Flush(); return true; } @@ -255,7 +343,7 @@ static bool wii_frame(void *data, const void *frame, static void wii_set_nonblock_state(void *data, bool state) { (void)data; - (void)state; + g_vsync = !state; } static bool wii_alive(void *data)