From 9d287666f9636783dc8aac06bfb0e960a02f1d0e Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sat, 20 Apr 2019 19:24:17 -0230 Subject: [PATCH] Fixed libretro errors preventing a successful build. Still TODO is actually test this functionality. --- src/libretro/StellaLIBRETRO.cxx | 36 +- src/libretro/StellaLIBRETRO.hxx | 6 +- src/libretro/libretro.cxx | 1079 +++++++++++++++---------------- src/windows/Stella.vcxproj | 6 +- 4 files changed, 558 insertions(+), 569 deletions(-) diff --git a/src/libretro/StellaLIBRETRO.cxx b/src/libretro/StellaLIBRETRO.cxx index f119a6c5c..2751a7bf7 100644 --- a/src/libretro/StellaLIBRETRO.cxx +++ b/src/libretro/StellaLIBRETRO.cxx @@ -41,7 +41,7 @@ StellaLIBRETRO::StellaLIBRETRO() video_aspect_pal = 0; video_palette = "standard"; - video_filter = NTSCFilter::PRESET_OFF; + video_filter = NTSCFilter::Preset::OFF; video_ready = false; audio_samples = 0; @@ -49,7 +49,7 @@ StellaLIBRETRO::StellaLIBRETRO() video_phosphor = "byrom"; video_phosphor_blend = 60; - + rom_image = make_unique(getROMMax()); system_ready = false; @@ -108,7 +108,7 @@ bool StellaLIBRETRO::create(bool logging) //fastscbios // Fast loading of Supercharger BIOS - settings.setValue("tv.filter", video_filter); + settings.setValue("tv.filter", static_cast(video_filter)); settings.setValue("tv.phosphor", video_phosphor); settings.setValue("tv.phosblend", video_phosphor_blend); @@ -214,11 +214,11 @@ void StellaLIBRETRO::updateAudio() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool StellaLIBRETRO::loadState(const void* data, uInt32 size) +bool StellaLIBRETRO::loadState(const void* data, size_t size) { Serializer state; - state.putByteArray(reinterpret_cast(data), size); + state.putByteArray(reinterpret_cast(data), static_cast(size)); if (!myOSystem->state().loadState(state)) return false; @@ -227,7 +227,7 @@ bool StellaLIBRETRO::loadState(const void* data, uInt32 size) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool StellaLIBRETRO::saveState(void* data, uInt32 size) +bool StellaLIBRETRO::saveState(void* data, size_t size) { Serializer state; @@ -262,7 +262,7 @@ float StellaLIBRETRO::getVideoAspect() { if (!video_aspect_ntsc) // non-interlace square pixel clock -- 1.0 pixel @ color burst -- double-width pixels - par = (6.1363635 / 3.579545454) / 2; + par = (6.1363635f / 3.579545454f) / 2; else par = video_aspect_ntsc / 100.0; } @@ -270,7 +270,7 @@ float StellaLIBRETRO::getVideoAspect() { if (!video_aspect_pal) // non-interlace square pixel clock -- 0.8 pixel @ color burst -- double-width pixels - par = (7.3750000 / (4.43361875 * 4/5)) / 2; + par = (7.3750000f / (4.43361875f * 4/5)) / 2; else par = video_aspect_pal / 100.0; } @@ -313,11 +313,11 @@ bool StellaLIBRETRO::getVideoResize() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void StellaLIBRETRO::setROM(const void* data, uInt32 size) +void StellaLIBRETRO::setROM(const void* data, size_t size) { memcpy(rom_image.get(), data, size); - rom_size = size; + rom_size = static_cast(size); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -341,20 +341,10 @@ void StellaLIBRETRO::setConsoleFormat(uInt32 mode) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void StellaLIBRETRO::setVideoFilter(uInt32 mode) { - switch (mode) + if (system_ready && mode <= 5) { - case 0: video_filter = NTSCFilter::PRESET_OFF; break; - case 1: video_filter = NTSCFilter::PRESET_COMPOSITE; break; - case 2: video_filter = NTSCFilter::PRESET_SVIDEO; break; - case 3: video_filter = NTSCFilter::PRESET_RGB; break; - case 4: video_filter = NTSCFilter::PRESET_BAD; break; - case 5: video_filter = NTSCFilter::PRESET_CUSTOM; break; - } - - if (system_ready) - { - myOSystem->settings().setValue("tv.filter", static_cast(video_filter)); - myOSystem->frameBuffer().tiaSurface().setNTSC(video_filter); + myOSystem->settings().setValue("tv.filter", mode); + myOSystem->frameBuffer().tiaSurface().setNTSC(static_cast(mode)); } } diff --git a/src/libretro/StellaLIBRETRO.hxx b/src/libretro/StellaLIBRETRO.hxx index d41f55b14..472d6d0f9 100644 --- a/src/libretro/StellaLIBRETRO.hxx +++ b/src/libretro/StellaLIBRETRO.hxx @@ -49,8 +49,8 @@ class StellaLIBRETRO void runFrame(); - bool loadState(const void* data, uInt32 size); - bool saveState(void* data, uInt32 size); + bool loadState(const void* data, size_t size); + bool saveState(void* data, size_t size); public: const char* getCoreName() { return "Stella"; } @@ -93,7 +93,7 @@ class StellaLIBRETRO Int16* getAudioBuffer() { return audio_buffer.get(); } public: - void setROM(const void* data, uInt32 size); + void setROM(const void* data, size_t size); void setConsoleFormat(uInt32 mode); diff --git a/src/libretro/libretro.cxx b/src/libretro/libretro.cxx index e5df651d7..adf38583c 100644 --- a/src/libretro/libretro.cxx +++ b/src/libretro/libretro.cxx @@ -1,540 +1,539 @@ -#ifndef _MSC_VER -#include -#include -#endif -#include -#include -#include - -#ifdef _MSC_VER -#define snprintf _snprintf -#endif - -#include "libretro.h" - -#include "StellaLIBRETRO.hxx" -#include "Event.hxx" -#include "Version.hxx" - - -static StellaLIBRETRO stella; - -static retro_log_printf_t log_cb; -static retro_video_refresh_t video_cb; -static retro_input_poll_t input_poll_cb; -static retro_input_state_t input_state_cb; -static retro_environment_t environ_cb; -static retro_audio_sample_t audio_cb; -static retro_audio_sample_batch_t audio_batch_cb; -static struct retro_system_av_info g_av_info; - -// libretro UI settings -static int setting_ntsc, setting_pal; -static int setting_stereo, setting_filter, setting_palette; -static int setting_phosphor, setting_console, setting_phosphor_blend; - -static bool system_reset; - -static unsigned input_devices[2]; - -// TODO input: -// https://github.com/libretro/blueMSX-libretro/blob/master/libretro.c -// https://github.com/libretro/libretro-o2em/blob/master/libretro.c - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uint32_t libretro_read_rom(void* data) -{ - memcpy(data, stella.getROM(), stella.getROMSize()); - - return stella.getROMSize(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void update_input() -{ - if(!input_poll_cb) return; - input_poll_cb(); - - -#define EVENT stella.setInputEvent - - EVENT(Event::JoystickZeroUp, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP)); - EVENT(Event::JoystickZeroDown, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN)); - EVENT(Event::JoystickZeroLeft, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)); - EVENT(Event::JoystickZeroRight, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)); - EVENT(Event::JoystickZeroFire, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)); - - EVENT(Event::JoystickOneUp, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP)); - EVENT(Event::JoystickOneDown, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN)); - EVENT(Event::JoystickOneLeft, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)); - EVENT(Event::JoystickOneRight, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)); - EVENT(Event::JoystickOneFire, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)); - - EVENT(Event::ConsoleLeftDiffA, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L)); - EVENT(Event::ConsoleLeftDiffB, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2)); - EVENT(Event::ConsoleColor, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3)); - EVENT(Event::ConsoleRightDiffA, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R)); - EVENT(Event::ConsoleRightDiffB, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2)); - EVENT(Event::ConsoleBlackWhite, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3)); - EVENT(Event::ConsoleSelect, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT)); - EVENT(Event::ConsoleReset, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START)); - -#undef EVENT -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void update_geometry() -{ - struct retro_system_av_info av_info; - - retro_get_system_av_info(&av_info); - - environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &av_info); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void update_system_av() -{ - struct retro_system_av_info av_info; - - retro_get_system_av_info(&av_info); - - environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &av_info); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void update_variables(bool init = false) -{ - bool geometry_update = false; - - char key[256]; - struct retro_variable var; - -#define RETRO_GET(x) \ - var.key = x; \ - var.value = NULL; \ - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var)) - - RETRO_GET("stella_filter") - { - int value = 0; - - if(!strcmp(var.value, "disabled")) value = 0; - else if(!strcmp(var.value, "composite")) value = 1; - else if(!strcmp(var.value, "s-video")) value = 2; - else if(!strcmp(var.value, "rgb")) value = 3; - else if(!strcmp(var.value, "badly adjusted")) value = 4; - - if(setting_filter != value) - { - stella.setVideoFilter(value); - - geometry_update = true; - setting_filter = value; - } - } - - RETRO_GET("stella_ntsc_aspect") - { - int value = 0; - - if(!strcmp(var.value, "par")) value = 0; - else value = atoi(var.value); - - if(setting_ntsc != value) - { - stella.setVideoAspectNTSC(value); - - geometry_update = true; - setting_ntsc = value; - } - } - - RETRO_GET("stella_pal_aspect") - { - int value = 0; - - if(!strcmp(var.value, "par")) value = 0; - else value = atoi(var.value); - - if(setting_pal != value) - { - stella.setVideoAspectPAL(value); - - setting_pal = value; - geometry_update = true; - } - } - - RETRO_GET("stella_palette") - { - int value = 0; - - if(!strcmp(var.value, "standard")) value = 0; - else if(!strcmp(var.value, "z26")) value = 1; - - if(setting_palette != value) - { - stella.setVideoPalette(value); - - setting_palette = value; - } - } - - RETRO_GET("stella_console") - { - int value = 0; - - if(!strcmp(var.value, "auto")) value = 0; - else if(!strcmp(var.value, "ntsc")) value = 1; - else if(!strcmp(var.value, "pal")) value = 2; - else if(!strcmp(var.value, "secam")) value = 3; - else if(!strcmp(var.value, "ntsc50")) value = 4; - else if(!strcmp(var.value, "pal60")) value = 5; - else if(!strcmp(var.value, "secam60")) value = 6; - - if(setting_console != value) - { - stella.setConsoleFormat(value); - - setting_console = value; - system_reset = true; - } - } - - RETRO_GET("stella_stereo") - { - int value = 0; - - if(!strcmp(var.value, "auto")) value = 0; - else if(!strcmp(var.value, "off")) value = 1; - else if(!strcmp(var.value, "on")) value = 2; - - if(setting_stereo != value) - { - stella.setAudioStereo(value); - - setting_stereo = value; - } - } - - RETRO_GET("stella_phosphor") - { - int value = 0; - - if(!strcmp(var.value, "auto")) value = 0; - else if(!strcmp(var.value, "off")) value = 1; - else if(!strcmp(var.value, "on")) value = 2; - - if(setting_phosphor != value) - { - stella.setVideoPhosphor(value, setting_phosphor_blend); - - setting_phosphor = value; - } - } - - RETRO_GET("stella_phosphor_blend") - { - int value = 0; - - value = atoi(var.value); - - if(setting_phosphor_blend != value) - { - stella.setVideoPhosphor(setting_phosphor, value); - - setting_phosphor_blend = value; - } - } - - if(!init && !system_reset) - { - if(geometry_update) update_geometry(); - } - -#undef RETRO_GET -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static bool reset_system() -{ - // clean restart - stella.destroy(); - - // apply libretro settings first - update_variables(true); - - // start system - if(!stella.create(log_cb ? true : false)) return false; - - // reset libretro window - update_geometry(); - - system_reset = false; - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -unsigned retro_api_version() -{ - return RETRO_API_VERSION; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -unsigned retro_get_region() -{ - return stella.getVideoNTSC() ? RETRO_REGION_NTSC : RETRO_REGION_PAL; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; } -void retro_set_audio_sample(retro_audio_sample_t cb) { audio_cb = cb; } -void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { audio_batch_cb = cb; } -void retro_set_input_poll(retro_input_poll_t cb) { input_poll_cb = cb; } -void retro_set_input_state(retro_input_state_t cb) { input_state_cb = cb; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void retro_get_system_info(struct retro_system_info *info) -{ - memset(info,0,sizeof(retro_system_info)); - - info->library_name = stella.getCoreName(); -#ifndef GIT_VERSION -#define GIT_VERSION "" -#endif - info->library_version = STELLA_VERSION GIT_VERSION; - info->valid_extensions = stella.getROMExtensions(); - info->need_fullpath = false; - info->block_extract = false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void retro_get_system_av_info(struct retro_system_av_info *info) -{ - memset(info,0,sizeof(retro_system_av_info)); - - info->timing.fps = stella.getVideoRate(); - info->timing.sample_rate = stella.getAudioRate(); - - info->geometry.base_width = stella.getRenderWidth(); - info->geometry.base_height = stella.getRenderHeight(); - - info->geometry.max_width = stella.getVideoWidthMax(); - info->geometry.max_height = stella.getVideoHeightMax(); - - info->geometry.aspect_ratio = stella.getVideoAspect(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void retro_set_controller_port_device(unsigned port, unsigned device) -{ - if(port < 2) - { - switch (device) - { - case RETRO_DEVICE_NONE: - input_devices[port] = RETRO_DEVICE_NONE; - break; - - case RETRO_DEVICE_JOYPAD: - input_devices[port] = RETRO_DEVICE_JOYPAD; - break; - - case RETRO_DEVICE_MOUSE: - input_devices[port] = RETRO_DEVICE_MOUSE; - break; - - case RETRO_DEVICE_KEYBOARD: - input_devices[port] = RETRO_DEVICE_KEYBOARD; - break; - - default: - if (log_cb) log_cb(RETRO_LOG_ERROR, "%s\n", "[libretro]: Invalid device, setting type to RETRO_DEVICE_JOYPAD ..."); - input_devices[port] = RETRO_DEVICE_JOYPAD; - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void retro_set_environment(retro_environment_t cb) -{ - environ_cb = cb; - - struct retro_variable variables[] = { - // Adding more variables and rearranging them is safe. - { "stella_console", "Console display; auto|ntsc|pal|secam|ntsc50|pal60|secam60"}, - { "stella_filter", "TV effects; disabled|composite|s-video|rgb|badly adjusted"}, - { "stella_ntsc_aspect", "NTSC aspect %; par|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85"}, - { "stella_pal_aspect", "PAL aspect %; par|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103"}, - { "stella_stereo", "Stereo sound; auto|off|on"}, - { "stella_palette", "Palette colors; standard|z26"}, - { "stella_phosphor", "Phosphor mode; auto|off|on"}, - { "stella_phosphor_blend", "Phosphor blend %; 60|65|70|75|80|85|90|95|100|0|5|10|15|20|25|30|35|40|45|50|55"}, - { NULL, NULL }, - }; - - environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void retro_init() -{ - struct retro_log_callback log; - unsigned level = 4; - - log_cb = NULL; - if(environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) log_cb = log.log; - - environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool retro_load_game(const struct retro_game_info *info) -{ - enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888; - - struct retro_input_descriptor desc[] = { - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Fire" }, - - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "Left Difficulty A" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "Left Difficulty B" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "Color" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Right Difficulty A" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "Right Difficulty B" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "Black/White" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, - { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Reset" }, - - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, - { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Fire" }, - - { 0 }, - }; - - if(!info || info->size >= stella.getROMMax()) return false; - - environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); - - if(!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) - { - if(log_cb) log_cb(RETRO_LOG_INFO, "[Stella]: XRGB8888 is not supported.\n"); - return false; - } - - - stella.setROM(info->data, info->size); - - return reset_system(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info) -{ - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void retro_reset() -{ - stella.reset(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void retro_run() -{ - bool updated = false; - - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) - update_variables(); - - if(system_reset) - { - reset_system(); - update_system_av(); - return; - } - - - update_input(); - - - stella.runFrame(); - - if(stella.getVideoResize()) - update_geometry(); - - - //printf("retro_run - %d %d %d - %d\n", stella.getVideoWidth(), stella.getVideoHeight(), stella.getVideoPitch(), stella.getAudioSize() ); - - if(stella.getVideoReady()) - video_cb(stella.getVideoBuffer(), stella.getVideoWidth(), stella.getVideoHeight(), stella.getVideoPitch()); - - if(stella.getAudioReady()) - audio_batch_cb(stella.getAudioBuffer(), stella.getAudioSize()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void retro_unload_game() -{ - stella.destroy(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void retro_deinit() -{ - stella.destroy(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -size_t retro_serialize_size() -{ - return stella.getStateSize(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool retro_serialize(void *data, size_t size) -{ - return stella.saveState(data, size); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool retro_unserialize(const void *data, size_t size) -{ - return stella.loadState(data, size); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void *retro_get_memory_data(unsigned id) -{ - switch (id) - { - //case RETRO_MEMORY_SYSTEM_RAM: return stella.getRAM(); - default: return NULL; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -size_t retro_get_memory_size(unsigned id) -{ - switch (id) - { - //case RETRO_MEMORY_SYSTEM_RAM: return stella.getRAMSize(); - default: return 0; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void retro_cheat_reset() -{} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void retro_cheat_set(unsigned index, bool enabled, const char *code) -{} +#ifndef _MSC_VER +#include +#include +#endif +#include +#include +#include + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +#include "libretro.h" + +#include "StellaLIBRETRO.hxx" +#include "Event.hxx" +#include "Version.hxx" + + +static StellaLIBRETRO stella; + +static retro_log_printf_t log_cb; +static retro_video_refresh_t video_cb; +static retro_input_poll_t input_poll_cb; +static retro_input_state_t input_state_cb; +static retro_environment_t environ_cb; +static retro_audio_sample_t audio_cb; +static retro_audio_sample_batch_t audio_batch_cb; +static struct retro_system_av_info g_av_info; + +// libretro UI settings +static int setting_ntsc, setting_pal; +static int setting_stereo, setting_filter, setting_palette; +static int setting_phosphor, setting_console, setting_phosphor_blend; + +static bool system_reset; + +static unsigned input_devices[2]; + +// TODO input: +// https://github.com/libretro/blueMSX-libretro/blob/master/libretro.c +// https://github.com/libretro/libretro-o2em/blob/master/libretro.c + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uint32_t libretro_read_rom(void* data) +{ + memcpy(data, stella.getROM(), stella.getROMSize()); + + return stella.getROMSize(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +static void update_input() +{ + if(!input_poll_cb) return; + input_poll_cb(); + + +#define EVENT stella.setInputEvent + + EVENT(Event::JoystickZeroUp, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP)); + EVENT(Event::JoystickZeroDown, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN)); + EVENT(Event::JoystickZeroLeft, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)); + EVENT(Event::JoystickZeroRight, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)); + EVENT(Event::JoystickZeroFire, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)); + + EVENT(Event::JoystickOneUp, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP)); + EVENT(Event::JoystickOneDown, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN)); + EVENT(Event::JoystickOneLeft, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)); + EVENT(Event::JoystickOneRight, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)); + EVENT(Event::JoystickOneFire, input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B)); + + EVENT(Event::ConsoleLeftDiffA, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L)); + EVENT(Event::ConsoleLeftDiffB, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2)); + EVENT(Event::ConsoleColor, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3)); + EVENT(Event::ConsoleRightDiffA, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R)); + EVENT(Event::ConsoleRightDiffB, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2)); + EVENT(Event::ConsoleBlackWhite, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3)); + EVENT(Event::ConsoleSelect, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT)); + EVENT(Event::ConsoleReset, input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START)); + +#undef EVENT +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +static void update_geometry() +{ + struct retro_system_av_info av_info; + + retro_get_system_av_info(&av_info); + + environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &av_info); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +static void update_system_av() +{ + struct retro_system_av_info av_info; + + retro_get_system_av_info(&av_info); + + environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &av_info); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +static void update_variables(bool init = false) +{ + bool geometry_update = false; + + struct retro_variable var; + +#define RETRO_GET(x) \ + var.key = x; \ + var.value = NULL; \ + if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var)) + + RETRO_GET("stella_filter") + { + int value = 0; + + if(!strcmp(var.value, "disabled")) value = 0; + else if(!strcmp(var.value, "composite")) value = 1; + else if(!strcmp(var.value, "s-video")) value = 2; + else if(!strcmp(var.value, "rgb")) value = 3; + else if(!strcmp(var.value, "badly adjusted")) value = 4; + + if(setting_filter != value) + { + stella.setVideoFilter(value); + + geometry_update = true; + setting_filter = value; + } + } + + RETRO_GET("stella_ntsc_aspect") + { + int value = 0; + + if(!strcmp(var.value, "par")) value = 0; + else value = atoi(var.value); + + if(setting_ntsc != value) + { + stella.setVideoAspectNTSC(value); + + geometry_update = true; + setting_ntsc = value; + } + } + + RETRO_GET("stella_pal_aspect") + { + int value = 0; + + if(!strcmp(var.value, "par")) value = 0; + else value = atoi(var.value); + + if(setting_pal != value) + { + stella.setVideoAspectPAL(value); + + setting_pal = value; + geometry_update = true; + } + } + + RETRO_GET("stella_palette") + { + int value = 0; + + if(!strcmp(var.value, "standard")) value = 0; + else if(!strcmp(var.value, "z26")) value = 1; + + if(setting_palette != value) + { + stella.setVideoPalette(value); + + setting_palette = value; + } + } + + RETRO_GET("stella_console") + { + int value = 0; + + if(!strcmp(var.value, "auto")) value = 0; + else if(!strcmp(var.value, "ntsc")) value = 1; + else if(!strcmp(var.value, "pal")) value = 2; + else if(!strcmp(var.value, "secam")) value = 3; + else if(!strcmp(var.value, "ntsc50")) value = 4; + else if(!strcmp(var.value, "pal60")) value = 5; + else if(!strcmp(var.value, "secam60")) value = 6; + + if(setting_console != value) + { + stella.setConsoleFormat(value); + + setting_console = value; + system_reset = true; + } + } + + RETRO_GET("stella_stereo") + { + int value = 0; + + if(!strcmp(var.value, "auto")) value = 0; + else if(!strcmp(var.value, "off")) value = 1; + else if(!strcmp(var.value, "on")) value = 2; + + if(setting_stereo != value) + { + stella.setAudioStereo(value); + + setting_stereo = value; + } + } + + RETRO_GET("stella_phosphor") + { + int value = 0; + + if(!strcmp(var.value, "auto")) value = 0; + else if(!strcmp(var.value, "off")) value = 1; + else if(!strcmp(var.value, "on")) value = 2; + + if(setting_phosphor != value) + { + stella.setVideoPhosphor(value, setting_phosphor_blend); + + setting_phosphor = value; + } + } + + RETRO_GET("stella_phosphor_blend") + { + int value = 0; + + value = atoi(var.value); + + if(setting_phosphor_blend != value) + { + stella.setVideoPhosphor(setting_phosphor, value); + + setting_phosphor_blend = value; + } + } + + if(!init && !system_reset) + { + if(geometry_update) update_geometry(); + } + +#undef RETRO_GET +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +static bool reset_system() +{ + // clean restart + stella.destroy(); + + // apply libretro settings first + update_variables(true); + + // start system + if(!stella.create(log_cb ? true : false)) return false; + + // reset libretro window + update_geometry(); + + system_reset = false; + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +unsigned retro_api_version() +{ + return RETRO_API_VERSION; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +unsigned retro_get_region() +{ + return stella.getVideoNTSC() ? RETRO_REGION_NTSC : RETRO_REGION_PAL; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; } +void retro_set_audio_sample(retro_audio_sample_t cb) { audio_cb = cb; } +void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { audio_batch_cb = cb; } +void retro_set_input_poll(retro_input_poll_t cb) { input_poll_cb = cb; } +void retro_set_input_state(retro_input_state_t cb) { input_state_cb = cb; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void retro_get_system_info(struct retro_system_info *info) +{ + memset(info,0,sizeof(retro_system_info)); + + info->library_name = stella.getCoreName(); +#ifndef GIT_VERSION +#define GIT_VERSION "" +#endif + info->library_version = STELLA_VERSION GIT_VERSION; + info->valid_extensions = stella.getROMExtensions(); + info->need_fullpath = false; + info->block_extract = false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void retro_get_system_av_info(struct retro_system_av_info *info) +{ + memset(info,0,sizeof(retro_system_av_info)); + + info->timing.fps = stella.getVideoRate(); + info->timing.sample_rate = stella.getAudioRate(); + + info->geometry.base_width = stella.getRenderWidth(); + info->geometry.base_height = stella.getRenderHeight(); + + info->geometry.max_width = stella.getVideoWidthMax(); + info->geometry.max_height = stella.getVideoHeightMax(); + + info->geometry.aspect_ratio = stella.getVideoAspect(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void retro_set_controller_port_device(unsigned port, unsigned device) +{ + if(port < 2) + { + switch (device) + { + case RETRO_DEVICE_NONE: + input_devices[port] = RETRO_DEVICE_NONE; + break; + + case RETRO_DEVICE_JOYPAD: + input_devices[port] = RETRO_DEVICE_JOYPAD; + break; + + case RETRO_DEVICE_MOUSE: + input_devices[port] = RETRO_DEVICE_MOUSE; + break; + + case RETRO_DEVICE_KEYBOARD: + input_devices[port] = RETRO_DEVICE_KEYBOARD; + break; + + default: + if (log_cb) log_cb(RETRO_LOG_ERROR, "%s\n", "[libretro]: Invalid device, setting type to RETRO_DEVICE_JOYPAD ..."); + input_devices[port] = RETRO_DEVICE_JOYPAD; + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void retro_set_environment(retro_environment_t cb) +{ + environ_cb = cb; + + struct retro_variable variables[] = { + // Adding more variables and rearranging them is safe. + { "stella_console", "Console display; auto|ntsc|pal|secam|ntsc50|pal60|secam60"}, + { "stella_filter", "TV effects; disabled|composite|s-video|rgb|badly adjusted"}, + { "stella_ntsc_aspect", "NTSC aspect %; par|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85"}, + { "stella_pal_aspect", "PAL aspect %; par|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103"}, + { "stella_stereo", "Stereo sound; auto|off|on"}, + { "stella_palette", "Palette colors; standard|z26"}, + { "stella_phosphor", "Phosphor mode; auto|off|on"}, + { "stella_phosphor_blend", "Phosphor blend %; 60|65|70|75|80|85|90|95|100|0|5|10|15|20|25|30|35|40|45|50|55"}, + { NULL, NULL }, + }; + + environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void retro_init() +{ + struct retro_log_callback log; + unsigned level = 4; + + log_cb = NULL; + if(environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) log_cb = log.log; + + environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool retro_load_game(const struct retro_game_info *info) +{ + enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888; + + struct retro_input_descriptor desc[] = { + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Fire" }, + + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "Left Difficulty A" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "Left Difficulty B" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "Color" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Right Difficulty A" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "Right Difficulty B" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "Black/White" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Reset" }, + + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Fire" }, + + { 0 }, + }; + + if(!info || info->size >= stella.getROMMax()) return false; + + environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); + + if(!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) + { + if(log_cb) log_cb(RETRO_LOG_INFO, "[Stella]: XRGB8888 is not supported.\n"); + return false; + } + + + stella.setROM(info->data, info->size); + + return reset_system(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info) +{ + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void retro_reset() +{ + stella.reset(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void retro_run() +{ + bool updated = false; + + if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) + update_variables(); + + if(system_reset) + { + reset_system(); + update_system_av(); + return; + } + + + update_input(); + + + stella.runFrame(); + + if(stella.getVideoResize()) + update_geometry(); + + + //printf("retro_run - %d %d %d - %d\n", stella.getVideoWidth(), stella.getVideoHeight(), stella.getVideoPitch(), stella.getAudioSize() ); + + if(stella.getVideoReady()) + video_cb(stella.getVideoBuffer(), stella.getVideoWidth(), stella.getVideoHeight(), stella.getVideoPitch()); + + if(stella.getAudioReady()) + audio_batch_cb(stella.getAudioBuffer(), stella.getAudioSize()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void retro_unload_game() +{ + stella.destroy(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void retro_deinit() +{ + stella.destroy(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +size_t retro_serialize_size() +{ + return stella.getStateSize(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool retro_serialize(void *data, size_t size) +{ + return stella.saveState(data, size); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool retro_unserialize(const void *data, size_t size) +{ + return stella.loadState(data, size); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void *retro_get_memory_data(unsigned id) +{ + switch (id) + { + //case RETRO_MEMORY_SYSTEM_RAM: return stella.getRAM(); + default: return NULL; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +size_t retro_get_memory_size(unsigned id) +{ + switch (id) + { + //case RETRO_MEMORY_SYSTEM_RAM: return stella.getRAMSize(); + default: return 0; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void retro_cheat_reset() +{} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void retro_cheat_set(unsigned index, bool enabled, const char *code) +{} diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj index 4c0a774fa..1dc4dbcd3 100644 --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -294,8 +294,8 @@ X64 - Full - Default + MaxSpeed + AnySuitable true ..\yacc;..\emucore;..\emucore\tia;..\emucore\tia\frame-manager;..\common;..\common\tv_filters;..\gui;..\debugger\gui;..\debugger;..\windows;..\cheat;..\zlib;..\libpng;%(AdditionalIncludeDirectories) BSPF_WINDOWS;WIN32;NDEBUG;JOYSTICK_SUPPORT;DEBUGGER_SUPPORT;WINDOWED_SUPPORT;SOUND_SUPPORT;CHEATCODE_SUPPORT;%(PreprocessorDefinitions) @@ -1399,4 +1399,4 @@ - + \ No newline at end of file