X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=platform%2Flibretro%2Flibretro.c;h=581702c9d9d6c14ed1cce996160e665d2859ab5e;hb=8046160f29c9fb41e9b7471bec8d8cb53fec0e5c;hp=62b168e39cec8d423437154e74c436a7e1d51174;hpb=eac0e638190211e579f169357dfaff28c0aa801a;p=picodrive.git diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index 62b168e..581702c 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -26,13 +26,16 @@ #ifdef _3DS #include "3ds/3ds_utils.h" -#define MEMOP_PROT 6 +#define MEMOP_MAP 4 +#define MEMOP_UNMAP 5 +#define MEMOP_PROT 6 + int svcDuplicateHandle(unsigned int* out, unsigned int original); int svcCloseHandle(unsigned int handle); int svcControlProcessMemory(unsigned int process, void* addr0, void* addr1, unsigned int size, unsigned int type, unsigned int perm); -#define MEMOP_MAP 4 -#define MEMOP_UNMAP 5 +void* linearMemAlign(size_t size, size_t alignment); +void linearFree(void* mem); static int ctr_svchack_successful = 0; #endif @@ -52,8 +55,14 @@ static retro_audio_sample_batch_t audio_batch_cb; #define VOUT_MAX_WIDTH 320 #define VOUT_MAX_HEIGHT 240 + +static const float VOUT_PAR = 0.0; +static const float VOUT_4_3 = (224.0f * (4.0f / 3.0f)); +static const float VOUT_CRT = (224.0f * 1.29911f); + static void *vout_buf; static int vout_width, vout_height, vout_offset; +static float user_vout_width = 0.0; #ifdef _MSC_VER static short sndBuffer[2*44100/50]; @@ -452,6 +461,11 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols) vout_height = line_count; vout_offset = vout_width * start_line; + + // Update the geometry + struct retro_system_av_info av_info; + retro_get_system_av_info(&av_info); + environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &av_info); } void emu_32x_startup(void) @@ -466,7 +480,7 @@ void lprintf(const char *fmt, ...) vsprintf(buffer, fmt, ap); /* TODO - add 'level' param for warning/error messages? */ if (log_cb) - log_cb(RETRO_LOG_INFO, "%s\n", fmt, ap); + log_cb(RETRO_LOG_INFO, "%s", buffer); va_end(ap); } @@ -474,12 +488,13 @@ void lprintf(const char *fmt, ...) void retro_set_environment(retro_environment_t cb) { static const struct retro_variable vars[] = { - //{ "region", "Region; Auto|NTSC|PAL" }, - { "picodrive_input1", "Input device 1; 3 button pad|6 button pad|None" }, - { "picodrive_input2", "Input device 2; 3 button pad|6 button pad|None" }, - { "picodrive_sprlim", "No sprite limit; disabled|enabled" }, - { "picodrive_ramcart", "MegaCD RAM cart; disabled|enabled" }, - { "picodrive_region", "Region; Auto|Japan NTSC|Japan PAL|US|Europe" }, + { "picodrive_input1", "Input device 1; 3 button pad|6 button pad|None" }, + { "picodrive_input2", "Input device 2; 3 button pad|6 button pad|None" }, + { "picodrive_sprlim", "No sprite limit; disabled|enabled" }, + { "picodrive_ramcart", "MegaCD RAM cart; disabled|enabled" }, + { "picodrive_region", "Region; Auto|Japan NTSC|Japan PAL|US|Europe" }, + { "picodrive_region_fps", "Region FPS; Auto|NTSC|PAL" }, + { "picodrive_aspect", "Core-provided aspect ratio; PAR|4/3|CRT" }, #ifdef DRC_SH2 { "picodrive_drc", "Dynamic recompilers; enabled|disabled" }, #endif @@ -520,11 +535,16 @@ void retro_get_system_av_info(struct retro_system_av_info *info) memset(info, 0, sizeof(*info)); info->timing.fps = Pico.m.pal ? 50 : 60; info->timing.sample_rate = 44100; - info->geometry.base_width = 320; + info->geometry.base_width = vout_width; info->geometry.base_height = vout_height; - info->geometry.max_width = VOUT_MAX_WIDTH; - info->geometry.max_height = VOUT_MAX_HEIGHT; - info->geometry.aspect_ratio = 4.0f / 3.0f; + info->geometry.max_width = vout_width; + info->geometry.max_height = vout_height; + + float common_width = vout_width; + if (user_vout_width != 0) + common_width = user_vout_width; + + info->geometry.aspect_ratio = common_width / vout_height; } /* savestates */ @@ -862,8 +882,8 @@ bool retro_load_game(const struct retro_game_info *info) { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT,"Mode" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, @@ -875,91 +895,31 @@ bool retro_load_game(const struct retro_game_info *info) { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, - - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" }, - { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, - - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" }, - { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, - - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" }, - { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, - - { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, - { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, - { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, - { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, - { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, - { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" }, - { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" }, - { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" }, - { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" }, - { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" }, - { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" }, - { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, - - { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, - { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, - { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, - { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, - { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, - { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" }, - { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" }, - { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" }, - { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" }, - { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" }, - { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" }, - { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, - - { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, - { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, - { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, - { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, - { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, - { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" }, - { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" }, - { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" }, - { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" }, - { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" }, - { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" }, - { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT,"Mode" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 0 }, }; - environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); + struct retro_input_descriptor desc_sms[] = { + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Button 1 Start" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Button 2" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Button Pause" }, + + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Button 1 Start" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Button 2" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Button Pause" }, + + { 0 }, + }; enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565; if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) { @@ -1011,6 +971,11 @@ bool retro_load_game(const struct retro_game_info *info) break; } + if (media_type == PM_MARK3) + environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc_sms); + else + environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); + PicoLoopPrepare(); PicoWriteSound = snd_write; @@ -1035,38 +1000,64 @@ unsigned retro_get_region(void) return Pico.m.pal ? RETRO_REGION_PAL : RETRO_REGION_NTSC; } -void *retro_get_memory_data(unsigned id) +void *retro_get_memory_data(unsigned type) { - if (id != RETRO_MEMORY_SAVE_RAM) - return NULL; + uint8_t* data; - if (PicoAHW & PAHW_MCD) - return Pico_mcd->bram; - else - return SRam.data; + switch(type) + { + case RETRO_MEMORY_SAVE_RAM: + if (PicoAHW & PAHW_MCD) + data = Pico_mcd->bram; + else + data = SRam.data; + break; + case RETRO_MEMORY_SYSTEM_RAM: + if (PicoAHW & PAHW_SMS) + data = Pico.vramb; + else + data = Pico.ram; + break; + default: + data = NULL; + break; + } + + return data; } -size_t retro_get_memory_size(unsigned id) +size_t retro_get_memory_size(unsigned type) { unsigned int i; int sum; - - if (id != RETRO_MEMORY_SAVE_RAM) - return 0; - - if (PicoAHW & PAHW_MCD) - // bram - return 0x2000; - - if (Pico.m.frame_count == 0) - return SRam.size; - - // if game doesn't write to sram, don't report it to - // libretro so that RA doesn't write out zeroed .srm - for (i = 0, sum = 0; i < SRam.size; i++) - sum |= SRam.data[i]; - - return (sum != 0) ? SRam.size : 0; + + switch(type) + { + case RETRO_MEMORY_SAVE_RAM: + if (PicoAHW & PAHW_MCD) + // bram + return 0x2000; + + if (Pico.m.frame_count == 0) + return SRam.size; + + // if game doesn't write to sram, don't report it to + // libretro so that RA doesn't write out zeroed .srm + for (i = 0, sum = 0; i < SRam.size; i++) + sum |= SRam.data[i]; + + return (sum != 0) ? SRam.size : 0; + + case RETRO_MEMORY_SYSTEM_RAM: + if (PicoAHW & PAHW_SMS) + return sizeof(Pico.vramb); + else + return sizeof(Pico.ram); + + default: + return 0; + } + } void retro_reset(void) @@ -1141,6 +1132,7 @@ static void update_variables(void) PicoOpt &= ~POPT_EN_MCD_RAMCART; } + int OldPicoRegionOverride = PicoRegionOverride; var.value = NULL; var.key = "picodrive_region"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { @@ -1156,6 +1148,47 @@ static void update_variables(void) PicoRegionOverride = 8; } + int OldPicoRegionFPSOverride = PicoRegionFPSOverride; + var.value = NULL; + var.key = "picodrive_region_fps"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if (strcmp(var.value, "Auto") == 0) + PicoRegionFPSOverride = 0; + else if (strcmp(var.value, "NTSC") == 0) + PicoRegionFPSOverride = 1; + else if (strcmp(var.value, "PAL") == 0) + PicoRegionFPSOverride = 2; + } + + // Update region, fps and sound flags if needed + if (PicoRegionOverride != OldPicoRegionOverride || + PicoRegionFPSOverride != OldPicoRegionFPSOverride) + { + PicoDetectRegion(); + PicoLoopPrepare(); + PsndRerate(1); + } + + float old_user_vout_width = user_vout_width; + var.value = NULL; + var.key = "picodrive_aspect"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if (strcmp(var.value, "4/3") == 0) + user_vout_width = VOUT_4_3; + else if (strcmp(var.value, "CRT") == 0) + user_vout_width = VOUT_CRT; + else + user_vout_width = VOUT_PAR; + } + + if (user_vout_width != old_user_vout_width) + { + // Update the geometry + struct retro_system_av_info av_info; + retro_get_system_av_info(&av_info); + environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &av_info); + } + #ifdef DRC_SH2 var.value = NULL; var.key = "picodrive_drc"; @@ -1235,7 +1268,11 @@ void retro_init(void) vout_width = 320; vout_height = 240; +#ifdef _3DS + vout_buf = linearMemAlign(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2, 0x80); +#else vout_buf = malloc(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2); +#endif PicoInit(); PicoDrawSetOutFormat(PDF_RGB555, 0); @@ -1250,5 +1287,11 @@ void retro_init(void) void retro_deinit(void) { +#ifdef _3DS + linearFree(vout_buf); +#else + free(vout_buf); +#endif + vout_buf = NULL; PicoExit(); }