From 7dbeddece123a1c46181e931074276b9f2b2f769 Mon Sep 17 00:00:00 2001 From: EkeEke Date: Sun, 2 Mar 2014 17:51:00 +0100 Subject: [PATCH] [libretro] - fixed framebuffer size for PAL interlaced mode - added support for in-game resolution changes through RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO --- libretro/libretro.c | 27 +++--- libretro/libretro.h | 203 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 204 insertions(+), 26 deletions(-) diff --git a/libretro/libretro.c b/libretro/libretro.c index 97cd50c..28440d1 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -53,7 +53,7 @@ static uint8_t brm_format[0x40] = static uint8_t temp[0x10000]; static int16 soundbuffer[3068]; -static uint16_t bitmap_data_[1024 * 512]; +static uint16_t bitmap_data_[720 * 576]; static const double pal_fps = 53203424.0 / (3420.0 * 313.0); static const double ntsc_fps = 53693175.0 / (3420.0 * 262.0); @@ -210,14 +210,10 @@ void osd_input_update(void) static void init_bitmap(void) { memset(&bitmap, 0, sizeof(bitmap)); - bitmap.width = 1024; - bitmap.height = 512; - bitmap.pitch = 1024 * 2; + bitmap.width = 720; + bitmap.height = 576; + bitmap.pitch = 720 * 2; bitmap.data = (uint8_t *)bitmap_data_; - bitmap.viewport.w = 0; - bitmap.viewport.h = 0; - bitmap.viewport.x = 0; - bitmap.viewport.y = 0; } static void config_default(void) @@ -474,6 +470,8 @@ static void check_variables(void) orig_value = config.system; if (!strcmp(var.value, "sg-1000")) config.system = SYSTEM_SG; + else if (!strcmp(var.value, "sg-1000 II")) + config.system = SYSTEM_SGII; else if (!strcmp(var.value, "mark-III")) config.system = SYSTEM_MARKIII; else if (!strcmp(var.value, "master system")) @@ -760,7 +758,7 @@ unsigned retro_api_version(void) { return RETRO_API_VERSION; } void retro_set_environment(retro_environment_t cb) { static const struct retro_variable vars[] = { - { "system_hw", "System hardware; auto|sg-1000|mark-III|master system|master system II|game gear|mega drive / genesis" }, + { "system_hw", "System hardware; auto|sg-1000|sg-1000 II|mark-III|master system|master system II|game gear|mega drive / genesis" }, { "region_detect", "System region; auto|ntsc-u|pal|ntsc-j" }, { "force_dtack", "System lockups; enabled|disabled" }, { "addr_error", "68k address error; enabled|disabled" }, @@ -773,7 +771,7 @@ void retro_set_environment(retro_environment_t cb) { "blargg_ntsc_filter", "Blargg NTSC filter; disabled|monochrome|composite|svideo|rgb" }, { "overscan", "Borders; disabled|top/bottom|left/right|full" }, { "gg_extra", "Game Gear extended screen; disabled|enabled" }, - { "render", "Interlaced mode resolution; normal|double" }, + { "render", "Interlaced mode 2 output; single field|double field" }, { NULL, NULL }, }; @@ -800,8 +798,8 @@ void retro_get_system_av_info(struct retro_system_av_info *info) { info->geometry.base_width = vwidth; info->geometry.base_height = vheight; - info->geometry.max_width = 1024; - info->geometry.max_height = 512; + info->geometry.max_width = 720; + info->geometry.max_height = 576; info->geometry.aspect_ratio = 4.0 / 3.0; info->timing.fps = snd.frame_rate; info->timing.sample_rate = 44100; @@ -1000,11 +998,14 @@ void retro_run(void) if (bitmap.viewport.changed & 1) { + struct retro_system_av_info info; bitmap.viewport.changed &= ~1; update_viewport(); + retro_get_system_av_info(&info); + environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &info); } - video_cb(bitmap.data, vwidth, vheight, 1024 * 2); + video_cb(bitmap.data, vwidth, vheight, 720 * 2); audio_cb(soundbuffer, audio_update(soundbuffer)); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated); diff --git a/libretro/libretro.h b/libretro/libretro.h index aaff348..4a50847 100755 --- a/libretro/libretro.h +++ b/libretro/libretro.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2013 The RetroArch team +/* Copyright (C) 2010-2014 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro API header (libretro.h). @@ -27,11 +27,13 @@ #include #include -// Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. #ifdef __cplusplus extern "C" { -#else -#if defined(_MSC_VER) && !defined(SN_TARGET_PS3) && !defined(__cplusplus) +#endif + +#ifndef __cplusplus +#if defined(_MSC_VER) && !defined(SN_TARGET_PS3) +/* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */ #define bool unsigned char #define true 1 #define false 0 @@ -94,9 +96,6 @@ extern "C" { // Eventually _PRESSED will return false for an index. No further presses are registered at this point. #define RETRO_DEVICE_POINTER 6 -// FIXME: Document this. -#define RETRO_DEVICE_SENSOR_ACCELEROMETER 7 - // These device types are specializations of the base types above. // They should only be used in retro_set_controller_type() to inform libretro implementations // about use of a very specific device type. @@ -153,11 +152,6 @@ extern "C" { #define RETRO_DEVICE_ID_POINTER_Y 1 #define RETRO_DEVICE_ID_POINTER_PRESSED 2 -// Id values for SENSOR types. -#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_X 0 -#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Y 1 -#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Z 2 - // Returned from retro_get_region(). #define RETRO_REGION_NTSC 0 #define RETRO_REGION_PAL 1 @@ -385,7 +379,7 @@ enum retro_mod // Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), and reserved to avoid possible ABI clash. #define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * -- // Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'. - // Should not be used for trivial messages, which should simply be logged to stderr. + // Should not be used for trivial messages, which should simply be logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a fallback, stderr). #define RETRO_ENVIRONMENT_SHUTDOWN 7 // N/A (NULL) -- // Requests the frontend to shutdown. // Should only be used if game has a specific @@ -421,6 +415,9 @@ enum retro_mod // If so, no such directory is defined, // and it's up to the implementation to find a suitable directory. // + // NOTE: Some cores used this folder also for "save" data such as memory cards, etc, for lack of a better place to put it. + // This is now discouraged, and if possible, cores should try to use the new GET_SAVE_DIRECTORY. + // #define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 // const enum retro_pixel_format * -- // Sets the internal pixel format used by the implementation. @@ -564,6 +561,52 @@ enum retro_mod // as certain platforms cannot use use stderr for logging. It also allows the frontend to // show logging information in a more suitable way. // If this interface is not used, libretro cores should log to stderr as desired. +#define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28 + // struct retro_perf_callback * -- + // Gets an interface for performance counters. This is useful for performance logging in a + // cross-platform way and for detecting architecture-specific features, such as SIMD support. +#define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29 + // struct retro_location_callback * -- + // Gets access to the location interface. + // The purpose of this interface is to be able to retrieve location-based information from the host device, + // such as current latitude / longitude. + // +#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 + // const char ** -- + // Returns the "content" directory of the frontend. + // This directory can be used to store specific assets that the core relies upon, such as art assets, + // input data, etc etc. + // The returned value can be NULL. + // If so, no such directory is defined, + // and it's up to the implementation to find a suitable directory. + // +#define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31 + // const char ** -- + // Returns the "save" directory of the frontend. + // This directory can be used to store SRAM, memory cards, high scores, etc, if the libretro core + // cannot use the regular memory interface (retro_get_memory_data()). + // + // NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for similar things before. + // They should still check GET_SYSTEM_DIRECTORY if they want to be backwards compatible. + // The path here can be NULL. It should only be non-NULL if the frontend user has set a specific save path. + // +#define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 + // const struct retro_system_av_info * -- + // Sets a new av_info structure. This can only be called from within retro_run(). + // This should *only* be used if the core is completely altering the internal resolutions, aspect ratios, timings, sampling rate, etc. + // Calling this can require a full reinitialization of video/audio drivers in the frontend, + // so it is important to call it very sparingly, and usually only with the users explicit consent. + // An eventual driver reinit will happen so that video and audio callbacks + // happening after this call within the same retro_run() call will target the newly initialized driver. + // + // This callback makes it possible to support configurable resolutions in games, which can be useful to + // avoid setting the "worst case" in max_width/max_height. + // + // ***HIGHLY RECOMMENDED*** Do not call this callback every time resolution changes in an emulator core if it's + // expected to be a temporary change, for the reasons of possible driver reinit. + // This call is not a free pass for not trying to provide correct values in retro_get_system_av_info(). + // + // If this returns false, the frontend does not acknowledge a changed av_info struct. enum retro_log_level { @@ -583,6 +626,98 @@ struct retro_log_callback retro_log_printf_t log; }; +// Performance related functions +// +// ID values for SIMD CPU features +#define RETRO_SIMD_SSE (1 << 0) +#define RETRO_SIMD_SSE2 (1 << 1) +#define RETRO_SIMD_VMX (1 << 2) +#define RETRO_SIMD_VMX128 (1 << 3) +#define RETRO_SIMD_AVX (1 << 4) +#define RETRO_SIMD_NEON (1 << 5) +#define RETRO_SIMD_SSE3 (1 << 6) +#define RETRO_SIMD_SSSE3 (1 << 7) +#define RETRO_SIMD_MMX (1 << 8) +#define RETRO_SIMD_MMXEXT (1 << 9) +#define RETRO_SIMD_SSE4 (1 << 10) +#define RETRO_SIMD_SSE42 (1 << 11) +#define RETRO_SIMD_AVX2 (1 << 12) +#define RETRO_SIMD_VFPU (1 << 13) + +typedef uint64_t retro_perf_tick_t; +typedef int64_t retro_time_t; + +struct retro_perf_counter +{ + const char *ident; + retro_perf_tick_t start; + retro_perf_tick_t total; + retro_perf_tick_t call_cnt; + + bool registered; +}; + +// Returns current time in microseconds. Tries to use the most accurate timer available. +typedef retro_time_t (*retro_perf_get_time_usec_t)(void); +// A simple counter. Usually nanoseconds, but can also be CPU cycles. +// Can be used directly if desired (when creating a more sophisticated performance counter system). +typedef retro_perf_tick_t (*retro_perf_get_counter_t)(void); +// Returns a bit-mask of detected CPU features (RETRO_SIMD_*). +typedef uint64_t (*retro_get_cpu_features_t)(void); +// Asks frontend to log and/or display the state of performance counters. +// Performance counters can always be poked into manually as well. +typedef void (*retro_perf_log_t)(void); +// Register a performance counter. +// ident field must be set with a discrete value and other values in retro_perf_counter must be 0. +// Registering can be called multiple times. To avoid calling to frontend redundantly, you can check registered field first. +typedef void (*retro_perf_register_t)(struct retro_perf_counter *counter); +// Starts and stops a registered counter. +typedef void (*retro_perf_start_t)(struct retro_perf_counter *counter); +typedef void (*retro_perf_stop_t)(struct retro_perf_counter *counter); + +// For convenience it can be useful to wrap register, start and stop in macros. +// E.g.: +// #ifdef LOG_PERFORMANCE +// #define RETRO_PERFORMANCE_INIT(perf_cb, name) static struct retro_perf_counter name = {#name}; if (!name.registered) perf_cb.perf_register(&(name)) +// #define RETRO_PERFORMANCE_START(perf_cb, name) perf_cb.perf_start(&(name)) +// #define RETRO_PERFORMANCE_STOP(perf_cb, name) perf_cb.perf_stop(&(name)) +// #else +// ... Blank macros ... +// #endif +// These can then be used mid-functions around code snippets. +// +// extern struct retro_perf_callback perf_cb; // Somewhere in the core. +// +// void do_some_heavy_work(void) +// { +// RETRO_PERFORMANCE_INIT(cb, work_1); +// RETRO_PERFORMANCE_START(cb, work_1); +// heavy_work_1(); +// RETRO_PERFORMANCE_STOP(cb, work_1); +// +// RETRO_PERFORMANCE_INIT(cb, work_2); +// RETRO_PERFORMANCE_START(cb, work_2); +// heavy_work_2(); +// RETRO_PERFORMANCE_STOP(cb, work_2); +// } +// +// void retro_deinit(void) +// { +// perf_cb.perf_log(); // Log all perf counters here for example. +// } + +struct retro_perf_callback +{ + retro_perf_get_time_usec_t get_time_usec; + retro_get_cpu_features_t get_cpu_features; + + retro_perf_get_counter_t get_perf_counter; + retro_perf_register_t perf_register; + retro_perf_start_t perf_start; + retro_perf_stop_t perf_stop; + retro_perf_log_t perf_log; +}; + // FIXME: Document the sensor API and work out behavior. // It will be marked as experimental until then. enum retro_sensor_action @@ -593,10 +728,17 @@ enum retro_sensor_action RETRO_SENSOR_DUMMY = INT_MAX }; +// Id values for SENSOR types. +#define RETRO_SENSOR_ACCELEROMETER_X 0 +#define RETRO_SENSOR_ACCELEROMETER_Y 1 +#define RETRO_SENSOR_ACCELEROMETER_Z 2 + typedef bool (*retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned rate); +typedef float (*retro_sensor_get_input_t)(unsigned port, unsigned id); struct retro_sensor_interface { retro_set_sensor_state_t set_sensor_state; + retro_sensor_get_input_t get_sensor_input; }; //// @@ -653,6 +795,41 @@ struct retro_camera_callback retro_camera_lifetime_status_t deinitialized; }; +// Sets the interval of time and/or distance at which to update/poll location-based data. +// To ensure compatibility with all location-based implementations, values for both +// interval_ms and interval_distance should be provided. +// interval_ms is the interval expressed in milliseconds. +// interval_distance is the distance interval expressed in meters. +typedef void (*retro_location_set_interval_t)(unsigned interval_ms, unsigned interval_distance); + +// Start location services. The device will start listening for changes to the +// current location at regular intervals (which are defined with retro_location_set_interval_t). +typedef bool (*retro_location_start_t)(void); + +// Stop location services. The device will stop listening for changes to the current +// location. +typedef void (*retro_location_stop_t)(void); + +// Get the position of the current location. Will set parameters to 0 if no new +// location update has happened since the last time. +typedef bool (*retro_location_get_position_t)(double *lat, double *lon, double *horiz_accuracy, + double *vert_accuracy); + +// Callback which signals when the location driver is initialized and/or deinitialized. +// retro_location_start_t can be called in initialized callback. +typedef void (*retro_location_lifetime_status_t)(void); + +struct retro_location_callback +{ + retro_location_start_t start; + retro_location_stop_t stop; + retro_location_get_position_t get_position; + retro_location_set_interval_t set_interval; + + retro_location_lifetime_status_t initialized; + retro_location_lifetime_status_t deinitialized; +}; + enum retro_rumble_effect { RETRO_RUMBLE_STRONG = 0,