From 2707890fe9b91e4b3326b4bf30b13ccf50d6dbb3 Mon Sep 17 00:00:00 2001 From: Toad King <toadking@toadking.com> Date: Sat, 10 Sep 2016 14:04:14 -0500 Subject: [PATCH 01/23] this should fix the corrupted graphics on emscripten --- Makefile.libretro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.libretro b/Makefile.libretro index ec8d06a..7bc2a40 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -267,7 +267,7 @@ else ifneq (,$(findstring armv,$(platform))) # emscripten else ifeq ($(platform), emscripten) TARGET := $(TARGET_NAME)_libretro_$(platform).bc - ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN -DHAVE_ZLIB + ENDIANNESS_DEFINES := -DLSB_FIRST -DALIGN_LONG -DBYTE_ORDER=LITTLE_ENDIAN -DHAVE_ZLIB STATIC_LINKING = 1 # GCW0 From 64ee605076b4f63e3a3a65316323cc61f210f030 Mon Sep 17 00:00:00 2001 From: Toad King <toadking@toadking.com> Date: Sun, 11 Sep 2016 15:55:39 -0500 Subject: [PATCH 02/23] emscripten does not guarantee byte arrays to be aligned on word boundaries, specify alignment for them --- core/vdp_ctrl.c | 18 +++++++++--------- core/vdp_render.c | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/vdp_ctrl.c b/core/vdp_ctrl.c index f630765..ce8b1a1 100644 --- a/core/vdp_ctrl.c +++ b/core/vdp_ctrl.c @@ -54,15 +54,15 @@ } /* VDP context */ -uint8 sat[0x400]; /* Internal copy of sprite attribute table */ -uint8 vram[0x10000]; /* Video RAM (64K x 8-bit) */ -uint8 cram[0x80]; /* On-chip color RAM (64 x 9-bit) */ -uint8 vsram[0x80]; /* On-chip vertical scroll RAM (40 x 11-bit) */ -uint8 reg[0x20]; /* Internal VDP registers (23 x 8-bit) */ -uint8 hint_pending; /* 0= Line interrupt is pending */ -uint8 vint_pending; /* 1= Frame interrupt is pending */ -uint16 status; /* VDP status flags */ -uint32 dma_length; /* DMA remaining length */ +uint8 sat[0x400] __attribute__((aligned(4))); /* Internal copy of sprite attribute table */ +uint8 vram[0x10000] __attribute__((aligned(4))); /* Video RAM (64K x 8-bit) */ +uint8 cram[0x80] __attribute__((aligned(4))); /* On-chip color RAM (64 x 9-bit) */ +uint8 vsram[0x80] __attribute__((aligned(4))); /* On-chip vertical scroll RAM (40 x 11-bit) */ +uint8 reg[0x20]; /* Internal VDP registers (23 x 8-bit) */ +uint8 hint_pending; /* 0= Line interrupt is pending */ +uint8 vint_pending; /* 1= Frame interrupt is pending */ +uint16 status; /* VDP status flags */ +uint32 dma_length; /* DMA remaining length */ /* Global variables */ uint16 ntab; /* Name table A base address */ diff --git a/core/vdp_render.c b/core/vdp_render.c index 485949a..c9493b3 100644 --- a/core/vdp_render.c +++ b/core/vdp_render.c @@ -553,7 +553,7 @@ static const uint32 tms_palette[16] = #endif /* Cached and flipped patterns */ -static uint8 bg_pattern_cache[0x80000]; +static uint8 bg_pattern_cache[0x80000] __attribute__((aligned(4))); /* Sprite pattern name offset look-up table (Mode 5) */ static uint8 name_lut[0x400]; From 7013886b8ed66fd9c3a559b37dc1cea3ac8fe2a8 Mon Sep 17 00:00:00 2001 From: Benjamin Hodgetts <ben@xnode.org> Date: Mon, 26 Sep 2016 17:45:19 +0100 Subject: [PATCH 03/23] Create a default makefile and link it to the libretro file to use that by default. --- Makefile | 1 + 1 file changed, 1 insertion(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..087932e --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +include Makefile.libretro From 02ec6fdf0ebabe2b01824b7f906c2b27e68fa7dd Mon Sep 17 00:00:00 2001 From: Gregor Richards <hg-yff@gregor.im> Date: Sun, 9 Oct 2016 10:01:46 -0400 Subject: [PATCH 04/23] Report platform-dependent savestates. --- libretro/libretro.c | 3 + libretro/libretro.h | 414 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 327 insertions(+), 90 deletions(-) diff --git a/libretro/libretro.c b/libretro/libretro.c index 46be902..c43afbb 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -1988,6 +1988,7 @@ void retro_init(void) { struct retro_log_callback log; unsigned level, rgb565; + uint64_t serialization_quirks = RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT; sms_ntsc = calloc(1, sizeof(sms_ntsc_t)); md_ntsc = calloc(1, sizeof(md_ntsc_t)); @@ -2009,6 +2010,8 @@ void retro_init(void) log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); #endif check_system_specs(); + + environ_cb(RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS, &serialization_quirks); } void retro_deinit(void) diff --git a/libretro/libretro.h b/libretro/libretro.h index 16c274a..2579e8b 100755 --- a/libretro/libretro.h +++ b/libretro/libretro.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2014 The RetroArch team +/* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro API header (libretro.h). @@ -43,6 +43,40 @@ extern "C" { #endif #endif +#ifndef RETRO_CALLCONV +# if defined(__GNUC__) && defined(__i386__) && !defined(__x86_64__) +# define RETRO_CALLCONV __attribute__((cdecl)) +# elif defined(_MSC_VER) && defined(_M_X86) && !defined(_M_X64) +# define RETRO_CALLCONV __cdecl +# else +# define RETRO_CALLCONV /* all other platforms only have one calling convention each */ +# endif +#endif + +#ifndef RETRO_API +# if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) +# ifdef RETRO_IMPORT_SYMBOLS +# ifdef __GNUC__ +# define RETRO_API RETRO_CALLCONV __attribute__((__dllimport__)) +# else +# define RETRO_API RETRO_CALLCONV __declspec(dllimport) +# endif +# else +# ifdef __GNUC__ +# define RETRO_API RETRO_CALLCONV __attribute__((__dllexport__)) +# else +# define RETRO_API RETRO_CALLCONV __declspec(dllexport) +# endif +# endif +# else +# if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__CELLOS_LV2__) +# define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default"))) +# else +# define RETRO_API RETRO_CALLCONV +# endif +# endif +#endif + /* Used for checking API/ABI mismatches that can break libretro * implementations. * It is not incremented for compatible changes to the API. @@ -165,13 +199,15 @@ extern "C" { #define RETRO_DEVICE_ID_ANALOG_Y 1 /* Id values for MOUSE. */ -#define RETRO_DEVICE_ID_MOUSE_X 0 -#define RETRO_DEVICE_ID_MOUSE_Y 1 -#define RETRO_DEVICE_ID_MOUSE_LEFT 2 -#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 -#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4 -#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5 -#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6 +#define RETRO_DEVICE_ID_MOUSE_X 0 +#define RETRO_DEVICE_ID_MOUSE_Y 1 +#define RETRO_DEVICE_ID_MOUSE_LEFT 2 +#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 +#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4 +#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5 +#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6 +#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP 7 +#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN 8 /* Id values for LIGHTGUN types. */ #define RETRO_DEVICE_ID_LIGHTGUN_X 0 @@ -206,6 +242,8 @@ enum retro_language RETRO_LANGUAGE_KOREAN = 9, RETRO_LANGUAGE_CHINESE_TRADITIONAL = 10, RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 11, + RETRO_LANGUAGE_ESPERANTO = 12, + RETRO_LANGUAGE_POLISH = 13, RETRO_LANGUAGE_LAST, /* Ensure sizeof(enum) == sizeof(int) */ @@ -693,9 +731,10 @@ enum retro_mod * location-based information from the host device, * such as current latitude / longitude. */ -#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 +#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 /* Old name, kept for compatibility. */ +#define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30 /* const char ** -- - * Returns the "content" directory of the frontend. + * Returns the "core assets" 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. @@ -851,6 +890,122 @@ enum retro_mod * Returns the specified language of the frontend, if specified by the user. * It can be used by the core for localization purposes. */ +#define RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER (40 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_framebuffer * -- + * Returns a preallocated framebuffer which the core can use for rendering + * the frame into when not using SET_HW_RENDER. + * The framebuffer returned from this call must not be used + * after the current call to retro_run() returns. + * + * The goal of this call is to allow zero-copy behavior where a core + * can render directly into video memory, avoiding extra bandwidth cost by copying + * memory from core to video memory. + * + * If this call succeeds and the core renders into it, + * the framebuffer pointer and pitch can be passed to retro_video_refresh_t. + * If the buffer from GET_CURRENT_SOFTWARE_FRAMEBUFFER is to be used, + * the core must pass the exact + * same pointer as returned by GET_CURRENT_SOFTWARE_FRAMEBUFFER; + * i.e. passing a pointer which is offset from the + * buffer is undefined. The width, height and pitch parameters + * must also match exactly to the values obtained from GET_CURRENT_SOFTWARE_FRAMEBUFFER. + * + * It is possible for a frontend to return a different pixel format + * than the one used in SET_PIXEL_FORMAT. This can happen if the frontend + * needs to perform conversion. + * + * It is still valid for a core to render to a different buffer + * even if GET_CURRENT_SOFTWARE_FRAMEBUFFER succeeds. + * + * A frontend must make sure that the pointer obtained from this function is + * writeable (and readable). + */ + +enum retro_hw_render_interface_type +{ + RETRO_HW_RENDER_INTERFACE_VULKAN = 0, + RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX +}; + +/* Base struct. All retro_hw_render_interface_* types + * contain at least these fields. */ +struct retro_hw_render_interface +{ + enum retro_hw_render_interface_type interface_type; + unsigned interface_version; +}; +#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const struct retro_hw_render_interface ** -- + * Returns an API specific rendering interface for accessing API specific data. + * Not all HW rendering APIs support or need this. + * The contents of the returned pointer is specific to the rendering API + * being used. See the various headers like libretro_vulkan.h, etc. + * + * GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called. + * Similarly, after context_destroyed callback returns, + * the contents of the HW_RENDER_INTERFACE are invalidated. + */ + +#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const bool * -- + * If true, the libretro implementation supports achievements + * either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS + * or via retro_get_memory_data/retro_get_memory_size. + * + * This must be called before the first call to retro_run. + */ + +enum retro_hw_render_context_negotiation_interface_type +{ + RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN = 0, + RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_DUMMY = INT_MAX +}; + +/* Base struct. All retro_hw_render_context_negotiation_interface_* types + * contain at least these fields. */ +struct retro_hw_render_context_negotiation_interface +{ + enum retro_hw_render_context_negotiation_interface_type interface_type; + unsigned interface_version; +}; +#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const struct retro_hw_render_context_negotiation_interface * -- + * Sets an interface which lets the libretro core negotiate with frontend how a context is created. + * The semantics of this interface depends on which API is used in SET_HW_RENDER earlier. + * This interface will be used when the frontend is trying to create a HW rendering context, + * so it will be used after SET_HW_RENDER, but before the context_reset callback. + */ + +/* Serialized state is incomplete in some way. Set if serialization is + * usable in typical end-user cases but should not be relied upon to + * implement frame-sensitive frontend features such as netplay or + * rerecording. */ +#define RETRO_SERIALIZATION_QUIRK_INCOMPLETE (1 << 0) +/* The core must spend some time initializing before serialization is + * supported. retro_serialize() will initially fail; retro_unserialize() + * and retro_serialize_size() may or may not work correctly either. */ +#define RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE (1 << 1) +/* Serialization size may change within a session. */ +#define RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE (1 << 2) +/* Set by the frontend to acknowledge that it supports variable-sized + * states. */ +#define RETRO_SERIALIZATION_QUIRK_FRONT_VARIABLE_SIZE (1 << 3) +/* Serialized state can only be loaded during the same session. */ +#define RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION (1 << 4) +/* Serialized state cannot be loaded on an architecture with a different + * endianness from the one it was saved on. */ +#define RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT (1 << 5) +/* Serialized state cannot be loaded on a different platform from the one it + * was saved on for reasons other than endianness, such as word size + * dependence */ +#define RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT (1 << 6) + +#define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44 + /* uint64_t * -- + * Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't + * recognize or support. Should be set in either retro_init or retro_load_game, but not both. + */ + #define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */ #define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ @@ -907,9 +1062,9 @@ struct retro_memory_descriptor /* To go from emulated address to physical address, the following * order applies: - * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. - * - * The address space name must consist of only a-zA-Z0-9_-, + * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. */ + + /* The address space name must consist of only a-zA-Z0-9_-, * should be as short as feasible (maximum length is 8 plus the NUL), * and may not be any other address space plus one or more 0-9A-F * at the end. @@ -929,12 +1084,43 @@ struct retro_memory_descriptor * 'a'+'A' - valid (neither is a prefix of each other) * 'AR'+blank - valid ('R' is not in 0-9A-F) * 'ARB'+blank - valid (the B can't be part of the address either, because - * there is no namespace 'AR') + * there is no namespace 'AR') * blank+'B' - not valid, because it's ambigous which address space B1234 - * would refer to. + * would refer to. * The length can't be used for that purpose; the frontend may want * to append arbitrary data to an address, without a separator. */ const char *addrspace; + + /* TODO: When finalizing this one, add a description field, which should be + * "WRAM" or something roughly equally long. */ + + /* TODO: When finalizing this one, replace 'select' with 'limit', which tells + * which bits can vary and still refer to the same address (limit = ~select). + * TODO: limit? range? vary? something else? */ + + /* TODO: When finalizing this one, if 'len' is above what 'select' (or + * 'limit') allows, it's bankswitched. Bankswitched data must have both 'len' + * and 'select' != 0, and the mappings don't tell how the system switches the + * banks. */ + + /* TODO: When finalizing this one, fix the 'len' bit removal order. + * For len=0x1800, pointer 0x1C00 should go to 0x1400, not 0x0C00. + * Algorithm: Take bits highest to lowest, but if it goes above len, clear + * the most recent addition and continue on the next bit. + * TODO: Can the above be optimized? Is "remove the lowest bit set in both + * pointer and 'len'" equivalent? */ + + /* TODO: Some emulators (MAME?) emulate big endian systems by only accessing + * the emulated memory in 32-bit chunks, native endian. But that's nothing + * compared to Darek Mihocka <http://www.emulators.com/docs/nx07_vm101.htm> + * (section Emulation 103 - Nearly Free Byte Reversal) - he flips the ENTIRE + * RAM backwards! I'll want to represent both of those, via some flags. + * + * I suspect MAME either didn't think of that idea, or don't want the #ifdef. + * Not sure which, nor do I really care. */ + + /* TODO: Some of those flags are unused and/or don't really make sense. Clean + * them up. */ }; /* The frontend may use the largest value of 'start'+'select' in a @@ -1064,7 +1250,7 @@ struct retro_subsystem_info unsigned id; }; -typedef void (*retro_proc_address_t)(void); +typedef void (RETRO_CALLCONV *retro_proc_address_t)(void); /* libretro API extension functions: * (None here so far). @@ -1080,7 +1266,7 @@ typedef void (*retro_proc_address_t)(void); * e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo". * The returned function pointer must be cast to the corresponding type. */ -typedef retro_proc_address_t (*retro_get_proc_address_t)(const char *sym); +typedef retro_proc_address_t (RETRO_CALLCONV *retro_get_proc_address_t)(const char *sym); struct retro_get_proc_address_interface { @@ -1098,7 +1284,7 @@ enum retro_log_level }; /* Logging function. Takes log level argument as well. */ -typedef void (*retro_log_printf_t)(enum retro_log_level level, +typedef void (RETRO_CALLCONV *retro_log_printf_t)(enum retro_log_level level, const char *fmt, ...); struct retro_log_callback @@ -1125,6 +1311,11 @@ struct retro_log_callback #define RETRO_SIMD_VFPU (1 << 13) #define RETRO_SIMD_PS (1 << 14) #define RETRO_SIMD_AES (1 << 15) +#define RETRO_SIMD_VFPV3 (1 << 16) +#define RETRO_SIMD_VFPV4 (1 << 17) +#define RETRO_SIMD_POPCNT (1 << 18) +#define RETRO_SIMD_MOVBE (1 << 19) +#define RETRO_SIMD_CMOV (1 << 20) typedef uint64_t retro_perf_tick_t; typedef int64_t retro_time_t; @@ -1142,34 +1333,34 @@ struct retro_perf_counter /* Returns current time in microseconds. * Tries to use the most accurate timer available. */ -typedef retro_time_t (*retro_perf_get_time_usec_t)(void); +typedef retro_time_t (RETRO_CALLCONV *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); +typedef retro_perf_tick_t (RETRO_CALLCONV *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); +typedef uint64_t (RETRO_CALLCONV *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); +typedef void (RETRO_CALLCONV *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); +typedef void (RETRO_CALLCONV *retro_perf_register_t)(struct retro_perf_counter *counter); /* Starts a registered counter. */ -typedef void (*retro_perf_start_t)(struct retro_perf_counter *counter); +typedef void (RETRO_CALLCONV *retro_perf_start_t)(struct retro_perf_counter *counter); /* Stops a registered counter. */ -typedef void (*retro_perf_stop_t)(struct retro_perf_counter *counter); +typedef void (RETRO_CALLCONV *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.: @@ -1232,10 +1423,10 @@ enum retro_sensor_action #define RETRO_SENSOR_ACCELEROMETER_Y 1 #define RETRO_SENSOR_ACCELEROMETER_Z 2 -typedef bool (*retro_set_sensor_state_t)(unsigned port, +typedef bool (RETRO_CALLCONV *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); +typedef float (RETRO_CALLCONV *retro_sensor_get_input_t)(unsigned port, unsigned id); struct retro_sensor_interface { @@ -1252,22 +1443,22 @@ enum retro_camera_buffer }; /* Starts the camera driver. Can only be called in retro_run(). */ -typedef bool (*retro_camera_start_t)(void); +typedef bool (RETRO_CALLCONV *retro_camera_start_t)(void); /* Stops the camera driver. Can only be called in retro_run(). */ -typedef void (*retro_camera_stop_t)(void); +typedef void (RETRO_CALLCONV *retro_camera_stop_t)(void); /* Callback which signals when the camera driver is initialized * and/or deinitialized. * retro_camera_start_t can be called in initialized callback. */ -typedef void (*retro_camera_lifetime_status_t)(void); +typedef void (RETRO_CALLCONV *retro_camera_lifetime_status_t)(void); /* A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. * Width, height and pitch are similar to retro_video_refresh_t. * First pixel is top-left origin. */ -typedef void (*retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, +typedef void (RETRO_CALLCONV *retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, unsigned width, unsigned height, size_t pitch); /* A callback for when OpenGL textures are used. @@ -1288,7 +1479,7 @@ typedef void (*retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, * GL-specific typedefs are avoided here to avoid relying on gl.h in * the API definition. */ -typedef void (*retro_camera_frame_opengl_texture_t)(unsigned texture_id, +typedef void (RETRO_CALLCONV *retro_camera_frame_opengl_texture_t)(unsigned texture_id, unsigned texture_target, const float *affine); struct retro_camera_callback @@ -1298,13 +1489,17 @@ struct retro_camera_callback */ uint64_t caps; - unsigned width; /* Desired resolution for camera. Is only used as a hint. */ + /* Desired resolution for camera. Is only used as a hint. */ + unsigned width; unsigned height; - retro_camera_start_t start; /* Set by frontend. */ - retro_camera_stop_t stop; /* Set by frontend. */ + + /* Set by frontend. */ + retro_camera_start_t start; + retro_camera_stop_t stop; /* Set by libretro core if raw framebuffer callbacks will be used. */ retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; + /* Set by libretro core if OpenGL texture callbacks will be used. */ retro_camera_frame_opengl_texture_t frame_opengl_texture; @@ -1330,28 +1525,28 @@ struct retro_camera_callback * 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, +typedef void (RETRO_CALLCONV *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); +typedef bool (RETRO_CALLCONV *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); +typedef void (RETRO_CALLCONV *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, +typedef bool (RETRO_CALLCONV *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); +typedef void (RETRO_CALLCONV *retro_location_lifetime_status_t)(void); struct retro_location_callback { @@ -1379,7 +1574,7 @@ enum retro_rumble_effect * * Returns true if rumble state request was honored. * Calling this before first retro_run() is likely to return false. */ -typedef bool (*retro_set_rumble_state_t)(unsigned port, +typedef bool (RETRO_CALLCONV *retro_set_rumble_state_t)(unsigned port, enum retro_rumble_effect effect, uint16_t strength); struct retro_rumble_interface @@ -1388,7 +1583,7 @@ struct retro_rumble_interface }; /* Notifies libretro that audio data should be written. */ -typedef void (*retro_audio_callback_t)(void); +typedef void (RETRO_CALLCONV *retro_audio_callback_t)(void); /* True: Audio driver in frontend is active, and callback is * expected to be called regularily. @@ -1397,7 +1592,7 @@ typedef void (*retro_audio_callback_t)(void); * called with true. * Initial state is false (inactive). */ -typedef void (*retro_audio_set_state_callback_t)(bool enabled); +typedef void (RETRO_CALLCONV *retro_audio_set_state_callback_t)(bool enabled); struct retro_audio_callback { @@ -1414,7 +1609,7 @@ struct retro_audio_callback * * In those scenarios the reference frame time value will be used. */ typedef int64_t retro_usec_t; -typedef void (*retro_frame_time_callback_t)(retro_usec_t usec); +typedef void (RETRO_CALLCONV *retro_frame_time_callback_t)(retro_usec_t usec); struct retro_frame_time_callback { retro_frame_time_callback_t callback; @@ -1438,15 +1633,15 @@ struct retro_frame_time_callback * Also called first time video driver is initialized, * allowing libretro core to initialize resources. */ -typedef void (*retro_hw_context_reset_t)(void); +typedef void (RETRO_CALLCONV *retro_hw_context_reset_t)(void); /* Gets current framebuffer which is to be rendered to. * Could change every frame potentially. */ -typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void); +typedef uintptr_t (RETRO_CALLCONV *retro_hw_get_current_framebuffer_t)(void); /* Get a symbol from HW context. */ -typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym); +typedef retro_proc_address_t (RETRO_CALLCONV *retro_hw_get_proc_address_t)(const char *sym); enum retro_hw_context_type { @@ -1464,6 +1659,9 @@ enum retro_hw_context_type * use the corresponding enums directly. */ RETRO_HW_CONTEXT_OPENGLES_VERSION = 5, + /* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */ + RETRO_HW_CONTEXT_VULKAN = 6, + RETRO_HW_CONTEXT_DUMMY = INT_MAX }; @@ -1486,23 +1684,28 @@ struct retro_hw_render_callback */ retro_hw_context_reset_t context_reset; - /* Set by frontend. */ + /* Set by frontend. + * TODO: This is rather obsolete. The frontend should not + * be providing preallocated framebuffers. */ retro_hw_get_current_framebuffer_t get_current_framebuffer; /* Set by frontend. */ retro_hw_get_proc_address_t get_proc_address; - /* Set if render buffers should have depth component attached. */ + /* Set if render buffers should have depth component attached. + * TODO: Obsolete. */ bool depth; - /* Set if stencil buffers should be attached. */ + /* Set if stencil buffers should be attached. + * TODO: Obsolete. */ bool stencil; /* If depth and stencil are true, a packed 24/8 buffer will be added. * Only attaching stencil is invalid and will be ignored. */ /* Use conventional bottom-left origin convention. If false, - * standard libretro top-left origin semantics are used. */ + * standard libretro top-left origin semantics are used. + * TODO: Move to GL specific interface. */ bool bottom_left_origin; /* Major version number for core GL context or GLES 3.1+. */ @@ -1513,6 +1716,7 @@ struct retro_hw_render_callback /* If this is true, the frontend will go very far to avoid * resetting context in scenarios like toggling fullscreen, etc. + * TODO: Obsolete? Maybe frontend should just always assume this ... */ bool cache_context; @@ -1562,7 +1766,7 @@ struct retro_hw_render_callback * Similarily if only a keycode event is generated with no corresponding * character, character should be 0. */ -typedef void (*retro_keyboard_event_t)(bool down, unsigned keycode, +typedef void (RETRO_CALLCONV *retro_keyboard_event_t)(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers); struct retro_keyboard_callback @@ -1586,24 +1790,24 @@ struct retro_keyboard_callback /* If ejected is true, "ejects" the virtual disk tray. * When ejected, the disk image index can be set. */ -typedef bool (*retro_set_eject_state_t)(bool ejected); +typedef bool (RETRO_CALLCONV *retro_set_eject_state_t)(bool ejected); /* Gets current eject state. The initial state is 'not ejected'. */ -typedef bool (*retro_get_eject_state_t)(void); +typedef bool (RETRO_CALLCONV *retro_get_eject_state_t)(void); /* Gets current disk index. First disk is index 0. * If return value is >= get_num_images(), no disk is currently inserted. */ -typedef unsigned (*retro_get_image_index_t)(void); +typedef unsigned (RETRO_CALLCONV *retro_get_image_index_t)(void); /* Sets image index. Can only be called when disk is ejected. * The implementation supports setting "no disk" by using an * index >= get_num_images(). */ -typedef bool (*retro_set_image_index_t)(unsigned index); +typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index); /* Gets total number of images which are available to use. */ -typedef unsigned (*retro_get_num_images_t)(void); +typedef unsigned (RETRO_CALLCONV *retro_get_num_images_t)(void); struct retro_game_info; @@ -1619,14 +1823,14 @@ struct retro_game_info; * returned 4 before. * Index 1 will be removed, and the new index is 3. */ -typedef bool (*retro_replace_image_index_t)(unsigned index, +typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index, const struct retro_game_info *info); /* Adds a new valid index (get_num_images()) to the internal disk list. * This will increment subsequent return values from get_num_images() by 1. * This image index cannot be used until a disk image has been set * with replace_image_index. */ -typedef bool (*retro_add_image_index_t)(void); +typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void); struct retro_disk_control_callback { @@ -1779,11 +1983,41 @@ struct retro_game_info const char *meta; /* String of implementation specific meta-data. */ }; +#define RETRO_MEMORY_ACCESS_WRITE (1 << 0) + /* The core will write to the buffer provided by retro_framebuffer::data. */ +#define RETRO_MEMORY_ACCESS_READ (1 << 1) + /* The core will read from retro_framebuffer::data. */ +#define RETRO_MEMORY_TYPE_CACHED (1 << 0) + /* The memory in data is cached. + * If not cached, random writes and/or reading from the buffer is expected to be very slow. */ +struct retro_framebuffer +{ + void *data; /* The framebuffer which the core can render into. + Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. + The initial contents of data are unspecified. */ + unsigned width; /* The framebuffer width used by the core. Set by core. */ + unsigned height; /* The framebuffer height used by the core. Set by core. */ + size_t pitch; /* The number of bytes between the beginning of a scanline, + and beginning of the next scanline. + Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ + enum retro_pixel_format format; /* The pixel format the core must use to render into data. + This format could differ from the format used in + SET_PIXEL_FORMAT. + Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ + + unsigned access_flags; /* How the core will access the memory in the framebuffer. + RETRO_MEMORY_ACCESS_* flags. + Set by core. */ + unsigned memory_flags; /* Flags telling core how the memory has been mapped. + RETRO_MEMORY_TYPE_* flags. + Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ +}; + /* Callbacks */ /* Environment callback. Gives implementations a way of performing * uncommon tasks. Extensible. */ -typedef bool (*retro_environment_t)(unsigned cmd, void *data); +typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data); /* Render a frame. Pixel format is 15-bit 0RGB1555 native endian * unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). @@ -1796,14 +2030,14 @@ typedef bool (*retro_environment_t)(unsigned cmd, void *data); * Certain graphic APIs, such as OpenGL ES, do not like textures * that are not packed in memory. */ -typedef void (*retro_video_refresh_t)(const void *data, unsigned width, +typedef void (RETRO_CALLCONV *retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch); /* Renders a single audio frame. Should only be used if implementation * generates a single sample at a time. * Format is signed 16-bit native endian. */ -typedef void (*retro_audio_sample_t)(int16_t left, int16_t right); +typedef void (RETRO_CALLCONV *retro_audio_sample_t)(int16_t left, int16_t right); /* Renders multiple audio frames in one go. * @@ -1811,11 +2045,11 @@ typedef void (*retro_audio_sample_t)(int16_t left, int16_t right); * I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. * Only one of the audio callbacks must ever be used. */ -typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, +typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data, size_t frames); /* Polls input. */ -typedef void (*retro_input_poll_t)(void); +typedef void (RETRO_CALLCONV *retro_input_poll_t)(void); /* Queries for input for player 'port'. device will be masked with * RETRO_DEVICE_MASK. @@ -1824,7 +2058,7 @@ typedef void (*retro_input_poll_t)(void); * have been set with retro_set_controller_port_device() * will still use the higher level RETRO_DEVICE_JOYPAD to request input. */ -typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, +typedef int16_t (RETRO_CALLCONV *retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); /* Sets callbacks. retro_set_environment() is guaranteed to be called @@ -1832,25 +2066,25 @@ typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, * * The rest of the set_* functions are guaranteed to have been called * before the first call to retro_run() is made. */ -void retro_set_environment(retro_environment_t); -void retro_set_video_refresh(retro_video_refresh_t); -void retro_set_audio_sample(retro_audio_sample_t); -void retro_set_audio_sample_batch(retro_audio_sample_batch_t); -void retro_set_input_poll(retro_input_poll_t); -void retro_set_input_state(retro_input_state_t); +RETRO_API void retro_set_environment(retro_environment_t); +RETRO_API void retro_set_video_refresh(retro_video_refresh_t); +RETRO_API void retro_set_audio_sample(retro_audio_sample_t); +RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t); +RETRO_API void retro_set_input_poll(retro_input_poll_t); +RETRO_API void retro_set_input_state(retro_input_state_t); /* Library global initialization/deinitialization. */ -void retro_init(void); -void retro_deinit(void); +RETRO_API void retro_init(void); +RETRO_API void retro_deinit(void); /* Must return RETRO_API_VERSION. Used to validate ABI compatibility * when the API is revised. */ -unsigned retro_api_version(void); +RETRO_API unsigned retro_api_version(void); /* Gets statically known system info. Pointers provided in *info * must be statically allocated. * Can be called at any time, even before retro_init(). */ -void retro_get_system_info(struct retro_system_info *info); +RETRO_API void retro_get_system_info(struct retro_system_info *info); /* Gets information about system audio/video timings and geometry. * Can be called only after retro_load_game() has successfully completed. @@ -1858,7 +2092,7 @@ void retro_get_system_info(struct retro_system_info *info); * variable if needed. * E.g. geom.aspect_ratio might not be initialized if core doesn't * desire a particular aspect ratio. */ -void retro_get_system_av_info(struct retro_system_av_info *info); +RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info); /* Sets device to be used for player 'port'. * By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all @@ -1868,10 +2102,10 @@ void retro_get_system_av_info(struct retro_system_av_info *info); * hint to the libretro core when a core cannot automatically detect the * appropriate input device type on its own. It is also relevant when a * core can change its behavior depending on device type. */ -void retro_set_controller_port_device(unsigned port, unsigned device); +RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device); /* Resets the current game. */ -void retro_reset(void); +RETRO_API void retro_reset(void); /* Runs the game for one video frame. * During retro_run(), input_poll callback must be called at least once. @@ -1881,7 +2115,7 @@ void retro_reset(void); * a frame if GET_CAN_DUPE returns true. * In this case, the video callback can take a NULL argument for data. */ -void retro_run(void); +RETRO_API void retro_run(void); /* Returns the amount of data the implementation requires to serialize * internal state (save states). @@ -1889,35 +2123,35 @@ void retro_run(void); * returned size is never allowed to be larger than a previous returned * value, to ensure that the frontend can allocate a save state buffer once. */ -size_t retro_serialize_size(void); +RETRO_API size_t retro_serialize_size(void); /* Serializes internal state. If failed, or size is lower than * retro_serialize_size(), it should return false, true otherwise. */ -bool retro_serialize(void *data, size_t size); -bool retro_unserialize(const void *data, size_t size); +RETRO_API bool retro_serialize(void *data, size_t size); +RETRO_API bool retro_unserialize(const void *data, size_t size); -void retro_cheat_reset(void); -void retro_cheat_set(unsigned index, bool enabled, const char *code); +RETRO_API void retro_cheat_reset(void); +RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code); /* Loads a game. */ -bool retro_load_game(const struct retro_game_info *game); +RETRO_API bool retro_load_game(const struct retro_game_info *game); /* Loads a "special" kind of game. Should not be used, * except in extreme cases. */ -bool retro_load_game_special( +RETRO_API bool retro_load_game_special( unsigned game_type, const struct retro_game_info *info, size_t num_info ); /* Unloads a currently loaded game. */ -void retro_unload_game(void); +RETRO_API void retro_unload_game(void); /* Gets region of game. */ -unsigned retro_get_region(void); +RETRO_API unsigned retro_get_region(void); /* Gets region of memory. */ -void *retro_get_memory_data(unsigned id); -size_t retro_get_memory_size(unsigned id); +RETRO_API void *retro_get_memory_data(unsigned id); +RETRO_API size_t retro_get_memory_size(unsigned id); #ifdef __cplusplus } From acb0f3ded7efcd91d5f5f175654fc75b52d5a88b Mon Sep 17 00:00:00 2001 From: twinaphex <libretro@gmail.com> Date: Sat, 15 Oct 2016 13:26:37 +0200 Subject: [PATCH 05/23] Time to add copyright notices to everything --- libretro/libretro.c | 41 +++++++++++++++++++++++++++++++++++++++++ libretro/osd.h | 40 ++++++++++++++++++++++++++++++++++++++++ libretro/scrc32.c | 41 +++++++++++++++++++++++++++++++++++++++++ libretro/scrc32.h | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+) diff --git a/libretro/libretro.c b/libretro/libretro.c index c43afbb..9f76ea3 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -1,3 +1,44 @@ +/**************************************************************************** + * config.c + * + * Genesis Plus GX configuration file support + * + * Copyright Eke-Eke (2007-2015) + * + * Copyright Daniel De Matteis (2012-2016) + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************/ + #ifndef _MSC_VER #include <stdbool.h> #endif diff --git a/libretro/osd.h b/libretro/osd.h index 867599a..63198bf 100644 --- a/libretro/osd.h +++ b/libretro/osd.h @@ -1,3 +1,43 @@ +/**************************************************************************** + * osd.h + * + * Genesis Plus GX configuration file support + * + * Copyright Eke-Eke (2007-2016) + * + * Copyright Daniel De Matteis (2012-2016) + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************/ #ifndef _OSD_H #define _OSD_H diff --git a/libretro/scrc32.c b/libretro/scrc32.c index 8ae2f1d..f4799b1 100644 --- a/libretro/scrc32.c +++ b/libretro/scrc32.c @@ -1,3 +1,44 @@ +/**************************************************************************** + * scrc32.c + * + * Genesis Plus GX configuration file support + * + * Copyright Eke-Eke (2007-2015) + * + * Copyright Daniel De Matteis (2012-2016) + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************/ + #ifndef _S_CRC32_H #define _S_CRC32_H diff --git a/libretro/scrc32.h b/libretro/scrc32.h index 2432c78..81e3fe1 100644 --- a/libretro/scrc32.h +++ b/libretro/scrc32.h @@ -1,3 +1,43 @@ +/**************************************************************************** + * scrc32.h + * + * Genesis Plus GX configuration file support + * + * Copyright Eke-Eke (2007-2015) + * + * Copyright Daniel De Matteis (2012-2016) + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************/ #ifndef _S_CRC32_H #define _S_CRC32_H From b0ee59c26f182005c5ff6b4b7627ba2401beabad Mon Sep 17 00:00:00 2001 From: twinaphex <libretro@gmail.com> Date: Sat, 15 Oct 2016 13:33:10 +0200 Subject: [PATCH 06/23] Adding ToadKing copyrights on changed files --- core/vdp_ctrl.c | 1 + core/vdp_render.c | 1 + 2 files changed, 2 insertions(+) diff --git a/core/vdp_ctrl.c b/core/vdp_ctrl.c index ce8b1a1..a6d8832 100644 --- a/core/vdp_ctrl.c +++ b/core/vdp_ctrl.c @@ -6,6 +6,7 @@ * * Copyright (C) 1998-2003 Charles Mac Donald (original code) * Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX) + * Copyright (C) 2016 Michael Lelli (Emscripten changes) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: diff --git a/core/vdp_render.c b/core/vdp_render.c index c9493b3..6781823 100644 --- a/core/vdp_render.c +++ b/core/vdp_render.c @@ -6,6 +6,7 @@ * * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code) * Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX) + * Copyright (C) 2016 Michael Lelli (Emscripten changes) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: From 257bb97ce9ff3f2b7f66a9408dd39c3c1f84e7b9 Mon Sep 17 00:00:00 2001 From: twinaphex <libretro@gmail.com> Date: Sat, 15 Oct 2016 17:03:40 +0200 Subject: [PATCH 07/23] Update license header --- libretro/libretro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libretro/libretro.c b/libretro/libretro.c index 9f76ea3..94e73e5 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -1,5 +1,5 @@ /**************************************************************************** - * config.c + * libretro.c * * Genesis Plus GX configuration file support * From 3c6d839da44bd13c218fb6200e7d6c080aa6a67d Mon Sep 17 00:00:00 2001 From: twinaphex <libretro@gmail.com> Date: Mon, 7 Nov 2016 02:18:17 +0100 Subject: [PATCH 08/23] Add wiiu target --- Makefile.libretro | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 7bc2a40..357358c 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -138,7 +138,7 @@ else ifeq ($(platform), sncps3) # Lightweight PS3 Homebrew SDK else ifeq ($(platform), psl1ght) - TARGET := $(TARGET_NAME)_libretro_psl1ght.a$(EXE_EXT) + TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) PLATFORM_DEFINES := -D__CELLOS_LV2 -DALT_RENDER @@ -146,7 +146,7 @@ else ifeq ($(platform), psl1ght) # PSP else ifeq ($(platform), psp1) - TARGET := $(TARGET_NAME)_libretro_psp1.a$(EXE_EXT) + TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = psp-gcc$(EXE_EXT) AR = psp-ar$(EXE_EXT) ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN @@ -156,7 +156,7 @@ else ifeq ($(platform), psp1) # Vita else ifeq ($(platform), vita) - TARGET := $(TARGET_NAME)_libretro_vita.a$(EXE_EXT) + TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = arm-vita-eabi-gcc$(EXE_EXT) AR = arm-vita-eabi-ar$(EXE_EXT) CFLAGS += -O3 -mfloat-abi=hard -ffast-math -fsingle-precision-constant @@ -166,7 +166,7 @@ else ifeq ($(platform), vita) # CTR (3DS) else ifeq ($(platform), ctr) - TARGET := $(TARGET_NAME)_libretro_ctr.a + TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = $(DEVKITARM)/bin/arm-none-eabi-gcc$(EXE_EXT) AR = $(DEVKITARM)/bin/arm-none-eabi-ar$(EXE_EXT) ENDIANNESS_DEFINES := -DLSB_FIRST -DALIGN_LONG -DBYTE_ORDER=LITTLE_ENDIAN -DUSE_DYNAMIC_ALLOC @@ -223,7 +223,7 @@ else ifeq ($(platform), xenon) # Nintendo Game Cube else ifeq ($(platform), ngc) - TARGET := $(TARGET_NAME)_libretro_ngc.a + TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) ENDIANNESS_DEFINES := -DBYTE_ORDER=BIG_ENDIAN @@ -232,13 +232,22 @@ else ifeq ($(platform), ngc) # Nintendo Wii else ifeq ($(platform), wii) - TARGET := $(TARGET_NAME)_libretro_wii.a + TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) PLATFORM_DEFINES := -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DALT_RENDER ENDIANNESS_DEFINES := -DBYTE_ORDER=BIG_ENDIAN STATIC_LINKING = 1 +# Nintendo Wii +else ifeq ($(platform), wiiu) + TARGET := $(TARGET_NAME)_libretro_$(platform).a + CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) + AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) + PLATFORM_DEFINES := -DGEKKO -DWIIU -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DALT_RENDER + ENDIANNESS_DEFINES := -DBYTE_ORDER=BIG_ENDIAN + STATIC_LINKING = 1 + # ARM else ifneq (,$(findstring armv,$(platform))) TARGET := $(TARGET_NAME)_libretro.so From 40c978223b86ec642214691dc8493fbcd9d9fd3c Mon Sep 17 00:00:00 2001 From: aliaspider <aliaspider@gmail.com> Date: Tue, 8 Nov 2016 06:50:39 +0100 Subject: [PATCH 09/23] (WIIU) use dynamic allocation of rom buffer. --- Makefile.libretro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.libretro b/Makefile.libretro index 357358c..a944873 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -244,7 +244,7 @@ else ifeq ($(platform), wiiu) TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - PLATFORM_DEFINES := -DGEKKO -DWIIU -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DALT_RENDER + PLATFORM_DEFINES := -DGEKKO -DWIIU -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DALT_RENDER -DUSE_DYNAMIC_ALLOC ENDIANNESS_DEFINES := -DBYTE_ORDER=BIG_ENDIAN STATIC_LINKING = 1 From fd06e074bb6d9836db8f7f6dbca5c3a2f6a050c8 Mon Sep 17 00:00:00 2001 From: Gregor Richards <hg-yff@gregor.im> Date: Fri, 9 Dec 2016 18:07:12 -0500 Subject: [PATCH 10/23] Report git version with library_version --- Makefile.libretro | 4 ++++ libretro/jni/Android.mk | 5 +++++ libretro/libretro.c | 5 ++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Makefile.libretro b/Makefile.libretro index a944873..027411f 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -36,6 +36,10 @@ endif TARGET_NAME := genesis_plus_gx LIBM := -lm +GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" +ifneq ($(GIT_VERSION)," unknown") + CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" +endif # Unix ifeq ($(platform), unix) diff --git a/libretro/jni/Android.mk b/libretro/jni/Android.mk index d081632..2058772 100644 --- a/libretro/jni/Android.mk +++ b/libretro/jni/Android.mk @@ -2,6 +2,11 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) +GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" +ifneq ($(GIT_VERSION)," unknown") + LOCAL_CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" +endif + WANT_CRC32 := 1 CORE_DIR := ../.. diff --git a/libretro/libretro.c b/libretro/libretro.c index 94e73e5..ba5b7f9 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -1664,7 +1664,10 @@ void retro_set_input_state(retro_input_state_t cb) { input_state_cb = cb; } void retro_get_system_info(struct retro_system_info *info) { info->library_name = "Genesis Plus GX"; - info->library_version = "v1.7.4"; +#ifndef GIT_VERSION +#define GIT_VERSION "" +#endif + info->library_version = "v1.7.4" GIT_VERSION; info->valid_extensions = "mdx|md|smd|gen|bin|cue|iso|sms|gg|sg"; info->block_extract = false; info->need_fullpath = true; From 9e314b76299c809c7d34447613010c058138df4a Mon Sep 17 00:00:00 2001 From: sergiobenrocha2 <sergiobenrocha2@gmail.com> Date: Mon, 2 Jan 2017 01:14:46 -0200 Subject: [PATCH 11/23] Can't cherry-pick 13029e2; conflicting with other commits, doing it manually. --- libretro/libretro.c | 4 ++-- libretro/osd.h | 3 ++- libretro/scrc32.c | 3 +-- libretro/scrc32.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libretro/libretro.c b/libretro/libretro.c index ba5b7f9..66cb692 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -1,9 +1,9 @@ /**************************************************************************** * libretro.c * - * Genesis Plus GX configuration file support + * Genesis Plus GX libretro port * - * Copyright Eke-Eke (2007-2015) + * Copyright Eke-Eke (2007-2016) * * Copyright Daniel De Matteis (2012-2016) * diff --git a/libretro/osd.h b/libretro/osd.h index 63198bf..03c57d4 100644 --- a/libretro/osd.h +++ b/libretro/osd.h @@ -1,7 +1,7 @@ /**************************************************************************** * osd.h * - * Genesis Plus GX configuration file support + * Genesis Plus GX libretro port * * Copyright Eke-Eke (2007-2016) * @@ -38,6 +38,7 @@ * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************************/ + #ifndef _OSD_H #define _OSD_H diff --git a/libretro/scrc32.c b/libretro/scrc32.c index f4799b1..4cef4c9 100644 --- a/libretro/scrc32.c +++ b/libretro/scrc32.c @@ -1,7 +1,7 @@ /**************************************************************************** * scrc32.c * - * Genesis Plus GX configuration file support + * Genesis Plus GX libretro port * * Copyright Eke-Eke (2007-2015) * @@ -38,7 +38,6 @@ * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************************/ - #ifndef _S_CRC32_H #define _S_CRC32_H diff --git a/libretro/scrc32.h b/libretro/scrc32.h index 81e3fe1..76156b8 100644 --- a/libretro/scrc32.h +++ b/libretro/scrc32.h @@ -1,7 +1,7 @@ /**************************************************************************** * scrc32.h * - * Genesis Plus GX configuration file support + * Genesis Plus GX libretro port * * Copyright Eke-Eke (2007-2015) * From f66676d86877e52e20d011fdc36148e8745ac5a8 Mon Sep 17 00:00:00 2001 From: Nadavbh <nadavbh@gmail.com> Date: Sat, 7 Jan 2017 23:02:39 +0200 Subject: [PATCH 12/23] implemented get RETRO_MEMORY_SYSTEM_RAM --- libretro/libretro.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libretro/libretro.c b/libretro/libretro.c index 7621242..b38100a 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -2048,6 +2048,8 @@ void *retro_get_memory_data(unsigned id) { case RETRO_MEMORY_SAVE_RAM: return sram.sram; + case RETRO_MEMORY_SYSTEM_RAM: + return work_ram; default: return NULL; @@ -2084,7 +2086,8 @@ size_t retro_get_memory_size(unsigned id) } } } - + case RETRO_MEMORY_SYSTEM_RAM: + return 0x10000; default: return 0; } From 82bdba60aa111b1522d99d6ee4c6d73bdeeb2b07 Mon Sep 17 00:00:00 2001 From: Jools Wills <buzz@exotica.org.uk> Date: Wed, 11 Jan 2017 01:25:18 +0000 Subject: [PATCH 13/23] fix indent (tabs -> spaces) --- libretro/libretro.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libretro/libretro.c b/libretro/libretro.c index b38100a..1a5c121 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -2048,8 +2048,8 @@ void *retro_get_memory_data(unsigned id) { case RETRO_MEMORY_SAVE_RAM: return sram.sram; - case RETRO_MEMORY_SYSTEM_RAM: - return work_ram; + case RETRO_MEMORY_SYSTEM_RAM: + return work_ram; default: return NULL; From 25626ea2519507fb56fbdbba6bb0287ae9ec441a Mon Sep 17 00:00:00 2001 From: EkeEke <ekeeke31@gmail.com> Date: Sun, 18 Dec 2016 22:38:50 +0100 Subject: [PATCH 14/23] [Core/Sound] improved PSG accuracy (fixes high-frequency aliasing noises in Captain Silver, Kenseiden, Phantasy Star & many other SMS games, thanks to Enik for the help) --- core/sound/sn76489.c | 440 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 440 insertions(+) create mode 100644 core/sound/sn76489.c diff --git a/core/sound/sn76489.c b/core/sound/sn76489.c new file mode 100644 index 0000000..27ea516 --- /dev/null +++ b/core/sound/sn76489.c @@ -0,0 +1,440 @@ +/* + SN76489 emulation + by Maxim in 2001 and 2002 + converted from my original Delphi implementation + + I'm a C newbie so I'm sure there are loads of stupid things + in here which I'll come back to some day and redo + + Includes: + - Super-high quality tone channel "oversampling" by calculating fractional positions on transitions + - Noise output pattern reverse engineered from actual SMS output + - Volume levels taken from actual SMS output + + 07/08/04 Charles MacDonald + Modified for use with SMS Plus: + - Added support for multiple PSG chips. + - Added reset/config/update routines. + - Added context management routines. + - Removed SN76489_GetValues(). + - Removed some unused variables. + + 25/04/07 Eke-Eke (Genesis Plus GX) + - Removed stereo GG support (unused) + - Made SN76489_Update outputs 16bits mono samples + - Replaced volume table with VGM plugin's one + + 05/01/09 Eke-Eke (Genesis Plus GX) + - Modified Cut-Off frequency (according to Steve Snake: http://www.smspower.org/forums/viewtopic.php?t=1746) + + 24/08/10 Eke-Eke (Genesis Plus GX) + - Removed multichip support (unused) + - Removed alternate volume table, panning & mute support (unused) + - Removed configurable Feedback and Shift Register Width (always use Sega ones) + - Added linear resampling using Blip Buffer (based on Blargg's implementation: http://www.smspower.org/forums/viewtopic.php?t=11376) + + 01/09/12 Eke-Eke (Genesis Plus GX) + - Added generic Blip-Buffer support internally, using common Master Clock as timebase + - Re-added stereo GG support + - Re-added configurable Feedback and Shift Register Width + - Rewrote core with various optimizations + + 04/11/16 Eke-Eke (Genesis Plus GX) + - improved resampling quality (removes aliasing noise when using high frequency tones) + - removed cut-off value (improves emulation accuracy of highest frequency tones) + - modified channels output to 0/1 like real chip instead of -1/+1 (fixes PCM voices when cut-off value is removed) + +*/ + +#include "shared.h" + +#define PSG_MCYCLES_RATIO (16 * 15) + +/* Initial state of shift register */ +#define NoiseInitialState 0x8000 + +/* original Texas Instruments TMS SN76489AN (rev. A) used in SG-1000, SC-3000H & SF-7000 computers */ +#define FB_DISCRETE 0x0006 +#define SRW_DISCRETE 15 + +/* SN76489AN clone integrated in Sega's VDP chips (315-5124, 315-5246, 315-5313, Game Gear) */ +#define FB_SEGAVDP 0x0009 +#define SRW_SEGAVDP 16 + +typedef struct +{ + /* Configuration */ + int PreAmp[4][2]; /* stereo channels pre-amplification ratio (%) */ + int NoiseFeedback; + int SRWidth; + + /* PSG registers: */ + int Registers[8]; /* Tone, vol x4 */ + int LatchedRegister; + int NoiseShiftRegister; + int NoiseFreq; /* Noise channel signal generator frequency */ + + /* Output calculation variables */ + int ToneFreqVals[4]; /* Frequency register values (counters) */ + int ToneFreqPos[4]; /* Frequency channel flip-flops */ + int Channel[4][2]; /* current amplitude of each (stereo) channel */ + int ChanOut[4][2]; /* current output value of each (stereo) channel */ + + /* Internal M-clock counter */ + unsigned long clocks; + +} SN76489_Context; + +static const uint16 PSGVolumeValues[16] = +{ + /* These values are taken from a real SMS2's output */ + /*{892,892,892,760,623,497,404,323,257,198,159,123,96,75,60,0}, */ + /* I can't remember why 892... :P some scaling I did at some point */ + /* these values are true volumes for 2dB drops at each step (multiply previous by 10^-0.1) */ + 1516,1205,957,760,603,479,381,303,240,191,152,120,96,76,60,0 +}; + +static SN76489_Context SN76489; + +void SN76489_Init(int type) +{ + int i; + + for (i=0; i<4; i++) + { + SN76489.PreAmp[i][0] = 100; + SN76489.PreAmp[i][1] = 100; + } + + if (type == SN_DISCRETE) + { + SN76489.NoiseFeedback = FB_DISCRETE; + SN76489.SRWidth = SRW_DISCRETE; + } + else + { + SN76489.NoiseFeedback = FB_SEGAVDP; + SN76489.SRWidth = SRW_SEGAVDP; + } +} + +void SN76489_Reset() +{ + int i; + + for(i = 0; i <= 3; i++) + { + /* Initialise PSG state */ + SN76489.Registers[2*i] = 1; /* tone freq=1 */ + SN76489.Registers[2*i+1] = 0xf; /* vol=off */ + + /* Set counters to 0 */ + SN76489.ToneFreqVals[i] = 0; + + /* Set flip-flops to 1 */ + SN76489.ToneFreqPos[i] = 1; + + /* Clear stereo channels amplitude */ + SN76489.Channel[i][0] = 0; + SN76489.Channel[i][1] = 0; + + /* Clear stereo channel outputs in delta buffer */ + SN76489.ChanOut[i][0] = 0; + SN76489.ChanOut[i][1] = 0; + } + + /* Initialise latched register index */ + SN76489.LatchedRegister = 0; + + /* Initialise noise generator */ + SN76489.NoiseShiftRegister=NoiseInitialState; + SN76489.NoiseFreq = 0x10; + + /* Reset internal M-cycle counter */ + SN76489.clocks = 0; +} + +void *SN76489_GetContextPtr(void) +{ + return (uint8 *)&SN76489; +} + +int SN76489_GetContextSize(void) +{ + return sizeof(SN76489_Context); +} + +/* Updates tone amplitude in delta buffer. Call whenever amplitude might have changed. */ +INLINE void UpdateToneAmplitude(int i, int time) +{ + int delta; + + /* left output */ + delta = (SN76489.Channel[i][0] * SN76489.ToneFreqPos[i]) - SN76489.ChanOut[i][0]; + if (delta != 0) + { + SN76489.ChanOut[i][0] += delta; + blip_add_delta(snd.blips[0][0], time, delta); + } + + /* right output */ + delta = (SN76489.Channel[i][1] * SN76489.ToneFreqPos[i]) - SN76489.ChanOut[i][1]; + if (delta != 0) + { + SN76489.ChanOut[i][1] += delta; + blip_add_delta(snd.blips[0][1], time, delta); + } +} + +/* Updates noise amplitude in delta buffer. Call whenever amplitude might have changed. */ +INLINE void UpdateNoiseAmplitude(int time) +{ + int delta; + + /* left output */ + delta = (SN76489.Channel[3][0] * ( SN76489.NoiseShiftRegister & 0x1 )) - SN76489.ChanOut[3][0]; + if (delta != 0) + { + SN76489.ChanOut[3][0] += delta; + blip_add_delta(snd.blips[0][0], time, delta); + } + + /* right output */ + delta = (SN76489.Channel[3][1] * ( SN76489.NoiseShiftRegister & 0x1 )) - SN76489.ChanOut[3][1]; + if (delta != 0) + { + SN76489.ChanOut[3][1] += delta; + blip_add_delta(snd.blips[0][1], time, delta); + } +} + +/* Runs tone channel for clock_length clocks */ +static void RunTone(int i, int clocks) +{ + int time; + + /* Update in case a register changed etc. */ + UpdateToneAmplitude(i, SN76489.clocks); + + /* Time of next transition */ + time = SN76489.ToneFreqVals[i]; + + /* Process any transitions that occur within clocks we're running */ + while (time < clocks) + { + /* Flip the flip-flop */ + SN76489.ToneFreqPos[i] ^= 1; + UpdateToneAmplitude(i, time); + + /* Advance to time of next transition */ + time += SN76489.Registers[i*2] * PSG_MCYCLES_RATIO; + } + + /* Update channel tone counter */ + SN76489.ToneFreqVals[i] = time; +} + +/* Runs noise channel for clock_length clocks */ +static void RunNoise(int clocks) +{ + int time; + + /* Noise channel: match to tone2 if in slave mode */ + int NoiseFreq = SN76489.NoiseFreq; + if (NoiseFreq == 0x80) + { + NoiseFreq = SN76489.Registers[2*2]; + SN76489.ToneFreqVals[3] = SN76489.ToneFreqVals[2]; + } + + /* Update in case a register changed etc. */ + UpdateNoiseAmplitude(SN76489.clocks); + + /* Time of next transition */ + time = SN76489.ToneFreqVals[3]; + + /* Process any transitions that occur within clocks we're running */ + while (time < clocks) + { + /* Flip the flip-flop */ + SN76489.ToneFreqPos[3] ^= 1; + if (SN76489.ToneFreqPos[3]) + { + /* On the positive edge of the square wave (only once per cycle) */ + int Feedback = SN76489.NoiseShiftRegister; + if ( SN76489.Registers[6] & 0x4 ) + { + /* White noise */ + /* Calculate parity of fed-back bits for feedback */ + /* Do some optimised calculations for common (known) feedback values */ + /* If two bits fed back, I can do Feedback=(nsr & fb) && (nsr & fb ^ fb) */ + /* since that's (one or more bits set) && (not all bits set) */ + Feedback = ((Feedback & SN76489.NoiseFeedback) && ((Feedback & SN76489.NoiseFeedback) ^ SN76489.NoiseFeedback)); + } + else /* Periodic noise */ + Feedback = Feedback & 1; + + SN76489.NoiseShiftRegister = (SN76489.NoiseShiftRegister >> 1) | (Feedback << (SN76489.SRWidth - 1)); + UpdateNoiseAmplitude(time); + } + + /* Advance to time of next transition */ + time += NoiseFreq * PSG_MCYCLES_RATIO; + } + + /* Update channel tone counter */ + SN76489.ToneFreqVals[3] = time; +} + +static void SN76489_RunUntil(unsigned int clocks) +{ + int i; + + /* Run noise first, since it might use current value of third tone frequency counter */ + RunNoise(clocks); + + /* Run tone channels */ + for (i=0; i<3; ++i) + { + RunTone(i, clocks); + } +} + +void SN76489_Config(unsigned int clocks, int preAmp, int boostNoise, int stereo) +{ + int i; + + /* cycle-accurate Game Gear stereo */ + if (clocks > SN76489.clocks) + { + /* Run chip until current timestamp */ + SN76489_RunUntil(clocks); + + /* Update internal M-cycle counter */ + SN76489.clocks += ((clocks - SN76489.clocks + PSG_MCYCLES_RATIO - 1) / PSG_MCYCLES_RATIO) * PSG_MCYCLES_RATIO; + } + + for (i=0; i<4; i++) + { + /* stereo channel pre-amplification */ + SN76489.PreAmp[i][0] = preAmp * ((stereo >> (i + 4)) & 1); + SN76489.PreAmp[i][1] = preAmp * ((stereo >> (i + 0)) & 1); + + /* noise channel boost (applied to all channels) */ + SN76489.PreAmp[i][0] = SN76489.PreAmp[i][0] << boostNoise; + SN76489.PreAmp[i][1] = SN76489.PreAmp[i][1] << boostNoise; + + /* update stereo channel amplitude */ + SN76489.Channel[i][0]= (PSGVolumeValues[SN76489.Registers[i*2 + 1]] * SN76489.PreAmp[i][0]) / 100; + SN76489.Channel[i][1]= (PSGVolumeValues[SN76489.Registers[i*2 + 1]] * SN76489.PreAmp[i][1]) / 100; + } +} + +void SN76489_Update(unsigned int clocks) +{ + int i; + + if (clocks > SN76489.clocks) + { + /* Run chip until current timestamp */ + SN76489_RunUntil(clocks); + + /* Update internal M-cycle counter */ + SN76489.clocks += ((clocks - SN76489.clocks + PSG_MCYCLES_RATIO - 1) / PSG_MCYCLES_RATIO) * PSG_MCYCLES_RATIO; + } + + /* Adjust internal M-cycle counter for next frame */ + SN76489.clocks -= clocks; + + /* Adjust channel time counters for new frame */ + for (i=0; i<4; ++i) + { + SN76489.ToneFreqVals[i] -= clocks; + } +} + +void SN76489_Write(unsigned int clocks, unsigned int data) +{ + unsigned int index; + + if (clocks > SN76489.clocks) + { + /* run chip until current timestamp */ + SN76489_RunUntil(clocks); + + /* update internal M-cycle counter */ + SN76489.clocks += ((clocks - SN76489.clocks + PSG_MCYCLES_RATIO - 1) / PSG_MCYCLES_RATIO) * PSG_MCYCLES_RATIO; + } + + if (data & 0x80) + { + /* latch byte %1 cc t dddd */ + SN76489.LatchedRegister = index = (data >> 4) & 0x07; + } + else + { + /* restore latched register index */ + index = SN76489.LatchedRegister; + } + + switch (index) + { + case 0: + case 2: + case 4: /* Tone Channels frequency */ + { + if (data & 0x80) + { + /* Data byte %1 cc t dddd */ + SN76489.Registers[index] = (SN76489.Registers[index] & 0x3f0) | (data & 0xf); + } + else + { + /* Data byte %0 - dddddd */ + SN76489.Registers[index] = (SN76489.Registers[index] & 0x00f) | ((data & 0x3f) << 4); + } + + /* zero frequency behaves the same as a value of 1 */ + if (SN76489.Registers[index] == 0) + { + SN76489.Registers[index] = 1; + } + break; + } + + case 1: + case 3: + case 5: /* Tone Channels attenuation */ + { + data &= 0x0f; + SN76489.Registers[index] = data; + data = PSGVolumeValues[data]; + index >>= 1; + SN76489.Channel[index][0] = (data * SN76489.PreAmp[index][0]) / 100; + SN76489.Channel[index][1] = (data * SN76489.PreAmp[index][1]) / 100; + break; + } + + case 6: /* Noise control */ + { + SN76489.Registers[6] = data & 0x0f; + + /* reset shift register */ + SN76489.NoiseShiftRegister = NoiseInitialState; + + /* set noise signal generator frequency */ + SN76489.NoiseFreq = 0x10 << (data&0x3); + break; + } + + case 7: /* Noise attenuation */ + { + data &= 0x0f; + SN76489.Registers[7] = data; + data = PSGVolumeValues[data]; + SN76489.Channel[3][0] = (data * SN76489.PreAmp[3][0]) / 100; + SN76489.Channel[3][1] = (data * SN76489.PreAmp[3][1]) / 100; + break; + } + } +} From cb2193583b424b66c29b3fb6cb0af16f93d236c5 Mon Sep 17 00:00:00 2001 From: EkeEke <ekeeke31@gmail.com> Date: Sun, 18 Dec 2016 23:09:16 +0100 Subject: [PATCH 15/23] [Core/Sound] optimized Blip Buffer implementation for stereo streams (thanks to David Knight for original idea) --- core/sound/sn76489.c | 46 ++++++++++++-------------------------------- 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/core/sound/sn76489.c b/core/sound/sn76489.c index 27ea516..da0a1b6 100644 --- a/core/sound/sn76489.c +++ b/core/sound/sn76489.c @@ -167,45 +167,23 @@ int SN76489_GetContextSize(void) /* Updates tone amplitude in delta buffer. Call whenever amplitude might have changed. */ INLINE void UpdateToneAmplitude(int i, int time) { - int delta; - - /* left output */ - delta = (SN76489.Channel[i][0] * SN76489.ToneFreqPos[i]) - SN76489.ChanOut[i][0]; - if (delta != 0) - { - SN76489.ChanOut[i][0] += delta; - blip_add_delta(snd.blips[0][0], time, delta); - } - - /* right output */ - delta = (SN76489.Channel[i][1] * SN76489.ToneFreqPos[i]) - SN76489.ChanOut[i][1]; - if (delta != 0) - { - SN76489.ChanOut[i][1] += delta; - blip_add_delta(snd.blips[0][1], time, delta); - } + /* left & right output */ + int delta_l = (SN76489.Channel[i][0] * SN76489.ToneFreqPos[i]) - SN76489.ChanOut[i][0]; + int delta_r = (SN76489.Channel[i][1] * SN76489.ToneFreqPos[i]) - SN76489.ChanOut[i][1]; + blip_add_delta(snd.blips[0], time, delta_l, delta_r); + SN76489.ChanOut[i][0] += delta_l; + SN76489.ChanOut[i][1] += delta_r; } /* Updates noise amplitude in delta buffer. Call whenever amplitude might have changed. */ INLINE void UpdateNoiseAmplitude(int time) { - int delta; - - /* left output */ - delta = (SN76489.Channel[3][0] * ( SN76489.NoiseShiftRegister & 0x1 )) - SN76489.ChanOut[3][0]; - if (delta != 0) - { - SN76489.ChanOut[3][0] += delta; - blip_add_delta(snd.blips[0][0], time, delta); - } - - /* right output */ - delta = (SN76489.Channel[3][1] * ( SN76489.NoiseShiftRegister & 0x1 )) - SN76489.ChanOut[3][1]; - if (delta != 0) - { - SN76489.ChanOut[3][1] += delta; - blip_add_delta(snd.blips[0][1], time, delta); - } + /* left & right output */ + int delta_l = (SN76489.Channel[3][0] * ( SN76489.NoiseShiftRegister & 0x1 )) - SN76489.ChanOut[3][0]; + int delta_r = (SN76489.Channel[3][1] * ( SN76489.NoiseShiftRegister & 0x1 )) - SN76489.ChanOut[3][1]; + blip_add_delta(snd.blips[0], time, delta_l, delta_r); + SN76489.ChanOut[3][0] += delta_l; + SN76489.ChanOut[3][1] += delta_r; } /* Runs tone channel for clock_length clocks */ From 61b10c57e244c64ce0b946bd16a6d5e3383a7fc3 Mon Sep 17 00:00:00 2001 From: EkeEke <ekeeke31@gmail.com> Date: Sun, 18 Dec 2016 23:36:59 +0100 Subject: [PATCH 16/23] [Core/Sound] rewrote PSG core from scratch & replaced deprecated "PSG boot noise" option with optional Hiqh Quality PSG resampling --- core/sound/sn76489.c | 418 ------------------------------------------- 1 file changed, 418 deletions(-) delete mode 100644 core/sound/sn76489.c diff --git a/core/sound/sn76489.c b/core/sound/sn76489.c deleted file mode 100644 index da0a1b6..0000000 --- a/core/sound/sn76489.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - SN76489 emulation - by Maxim in 2001 and 2002 - converted from my original Delphi implementation - - I'm a C newbie so I'm sure there are loads of stupid things - in here which I'll come back to some day and redo - - Includes: - - Super-high quality tone channel "oversampling" by calculating fractional positions on transitions - - Noise output pattern reverse engineered from actual SMS output - - Volume levels taken from actual SMS output - - 07/08/04 Charles MacDonald - Modified for use with SMS Plus: - - Added support for multiple PSG chips. - - Added reset/config/update routines. - - Added context management routines. - - Removed SN76489_GetValues(). - - Removed some unused variables. - - 25/04/07 Eke-Eke (Genesis Plus GX) - - Removed stereo GG support (unused) - - Made SN76489_Update outputs 16bits mono samples - - Replaced volume table with VGM plugin's one - - 05/01/09 Eke-Eke (Genesis Plus GX) - - Modified Cut-Off frequency (according to Steve Snake: http://www.smspower.org/forums/viewtopic.php?t=1746) - - 24/08/10 Eke-Eke (Genesis Plus GX) - - Removed multichip support (unused) - - Removed alternate volume table, panning & mute support (unused) - - Removed configurable Feedback and Shift Register Width (always use Sega ones) - - Added linear resampling using Blip Buffer (based on Blargg's implementation: http://www.smspower.org/forums/viewtopic.php?t=11376) - - 01/09/12 Eke-Eke (Genesis Plus GX) - - Added generic Blip-Buffer support internally, using common Master Clock as timebase - - Re-added stereo GG support - - Re-added configurable Feedback and Shift Register Width - - Rewrote core with various optimizations - - 04/11/16 Eke-Eke (Genesis Plus GX) - - improved resampling quality (removes aliasing noise when using high frequency tones) - - removed cut-off value (improves emulation accuracy of highest frequency tones) - - modified channels output to 0/1 like real chip instead of -1/+1 (fixes PCM voices when cut-off value is removed) - -*/ - -#include "shared.h" - -#define PSG_MCYCLES_RATIO (16 * 15) - -/* Initial state of shift register */ -#define NoiseInitialState 0x8000 - -/* original Texas Instruments TMS SN76489AN (rev. A) used in SG-1000, SC-3000H & SF-7000 computers */ -#define FB_DISCRETE 0x0006 -#define SRW_DISCRETE 15 - -/* SN76489AN clone integrated in Sega's VDP chips (315-5124, 315-5246, 315-5313, Game Gear) */ -#define FB_SEGAVDP 0x0009 -#define SRW_SEGAVDP 16 - -typedef struct -{ - /* Configuration */ - int PreAmp[4][2]; /* stereo channels pre-amplification ratio (%) */ - int NoiseFeedback; - int SRWidth; - - /* PSG registers: */ - int Registers[8]; /* Tone, vol x4 */ - int LatchedRegister; - int NoiseShiftRegister; - int NoiseFreq; /* Noise channel signal generator frequency */ - - /* Output calculation variables */ - int ToneFreqVals[4]; /* Frequency register values (counters) */ - int ToneFreqPos[4]; /* Frequency channel flip-flops */ - int Channel[4][2]; /* current amplitude of each (stereo) channel */ - int ChanOut[4][2]; /* current output value of each (stereo) channel */ - - /* Internal M-clock counter */ - unsigned long clocks; - -} SN76489_Context; - -static const uint16 PSGVolumeValues[16] = -{ - /* These values are taken from a real SMS2's output */ - /*{892,892,892,760,623,497,404,323,257,198,159,123,96,75,60,0}, */ - /* I can't remember why 892... :P some scaling I did at some point */ - /* these values are true volumes for 2dB drops at each step (multiply previous by 10^-0.1) */ - 1516,1205,957,760,603,479,381,303,240,191,152,120,96,76,60,0 -}; - -static SN76489_Context SN76489; - -void SN76489_Init(int type) -{ - int i; - - for (i=0; i<4; i++) - { - SN76489.PreAmp[i][0] = 100; - SN76489.PreAmp[i][1] = 100; - } - - if (type == SN_DISCRETE) - { - SN76489.NoiseFeedback = FB_DISCRETE; - SN76489.SRWidth = SRW_DISCRETE; - } - else - { - SN76489.NoiseFeedback = FB_SEGAVDP; - SN76489.SRWidth = SRW_SEGAVDP; - } -} - -void SN76489_Reset() -{ - int i; - - for(i = 0; i <= 3; i++) - { - /* Initialise PSG state */ - SN76489.Registers[2*i] = 1; /* tone freq=1 */ - SN76489.Registers[2*i+1] = 0xf; /* vol=off */ - - /* Set counters to 0 */ - SN76489.ToneFreqVals[i] = 0; - - /* Set flip-flops to 1 */ - SN76489.ToneFreqPos[i] = 1; - - /* Clear stereo channels amplitude */ - SN76489.Channel[i][0] = 0; - SN76489.Channel[i][1] = 0; - - /* Clear stereo channel outputs in delta buffer */ - SN76489.ChanOut[i][0] = 0; - SN76489.ChanOut[i][1] = 0; - } - - /* Initialise latched register index */ - SN76489.LatchedRegister = 0; - - /* Initialise noise generator */ - SN76489.NoiseShiftRegister=NoiseInitialState; - SN76489.NoiseFreq = 0x10; - - /* Reset internal M-cycle counter */ - SN76489.clocks = 0; -} - -void *SN76489_GetContextPtr(void) -{ - return (uint8 *)&SN76489; -} - -int SN76489_GetContextSize(void) -{ - return sizeof(SN76489_Context); -} - -/* Updates tone amplitude in delta buffer. Call whenever amplitude might have changed. */ -INLINE void UpdateToneAmplitude(int i, int time) -{ - /* left & right output */ - int delta_l = (SN76489.Channel[i][0] * SN76489.ToneFreqPos[i]) - SN76489.ChanOut[i][0]; - int delta_r = (SN76489.Channel[i][1] * SN76489.ToneFreqPos[i]) - SN76489.ChanOut[i][1]; - blip_add_delta(snd.blips[0], time, delta_l, delta_r); - SN76489.ChanOut[i][0] += delta_l; - SN76489.ChanOut[i][1] += delta_r; -} - -/* Updates noise amplitude in delta buffer. Call whenever amplitude might have changed. */ -INLINE void UpdateNoiseAmplitude(int time) -{ - /* left & right output */ - int delta_l = (SN76489.Channel[3][0] * ( SN76489.NoiseShiftRegister & 0x1 )) - SN76489.ChanOut[3][0]; - int delta_r = (SN76489.Channel[3][1] * ( SN76489.NoiseShiftRegister & 0x1 )) - SN76489.ChanOut[3][1]; - blip_add_delta(snd.blips[0], time, delta_l, delta_r); - SN76489.ChanOut[3][0] += delta_l; - SN76489.ChanOut[3][1] += delta_r; -} - -/* Runs tone channel for clock_length clocks */ -static void RunTone(int i, int clocks) -{ - int time; - - /* Update in case a register changed etc. */ - UpdateToneAmplitude(i, SN76489.clocks); - - /* Time of next transition */ - time = SN76489.ToneFreqVals[i]; - - /* Process any transitions that occur within clocks we're running */ - while (time < clocks) - { - /* Flip the flip-flop */ - SN76489.ToneFreqPos[i] ^= 1; - UpdateToneAmplitude(i, time); - - /* Advance to time of next transition */ - time += SN76489.Registers[i*2] * PSG_MCYCLES_RATIO; - } - - /* Update channel tone counter */ - SN76489.ToneFreqVals[i] = time; -} - -/* Runs noise channel for clock_length clocks */ -static void RunNoise(int clocks) -{ - int time; - - /* Noise channel: match to tone2 if in slave mode */ - int NoiseFreq = SN76489.NoiseFreq; - if (NoiseFreq == 0x80) - { - NoiseFreq = SN76489.Registers[2*2]; - SN76489.ToneFreqVals[3] = SN76489.ToneFreqVals[2]; - } - - /* Update in case a register changed etc. */ - UpdateNoiseAmplitude(SN76489.clocks); - - /* Time of next transition */ - time = SN76489.ToneFreqVals[3]; - - /* Process any transitions that occur within clocks we're running */ - while (time < clocks) - { - /* Flip the flip-flop */ - SN76489.ToneFreqPos[3] ^= 1; - if (SN76489.ToneFreqPos[3]) - { - /* On the positive edge of the square wave (only once per cycle) */ - int Feedback = SN76489.NoiseShiftRegister; - if ( SN76489.Registers[6] & 0x4 ) - { - /* White noise */ - /* Calculate parity of fed-back bits for feedback */ - /* Do some optimised calculations for common (known) feedback values */ - /* If two bits fed back, I can do Feedback=(nsr & fb) && (nsr & fb ^ fb) */ - /* since that's (one or more bits set) && (not all bits set) */ - Feedback = ((Feedback & SN76489.NoiseFeedback) && ((Feedback & SN76489.NoiseFeedback) ^ SN76489.NoiseFeedback)); - } - else /* Periodic noise */ - Feedback = Feedback & 1; - - SN76489.NoiseShiftRegister = (SN76489.NoiseShiftRegister >> 1) | (Feedback << (SN76489.SRWidth - 1)); - UpdateNoiseAmplitude(time); - } - - /* Advance to time of next transition */ - time += NoiseFreq * PSG_MCYCLES_RATIO; - } - - /* Update channel tone counter */ - SN76489.ToneFreqVals[3] = time; -} - -static void SN76489_RunUntil(unsigned int clocks) -{ - int i; - - /* Run noise first, since it might use current value of third tone frequency counter */ - RunNoise(clocks); - - /* Run tone channels */ - for (i=0; i<3; ++i) - { - RunTone(i, clocks); - } -} - -void SN76489_Config(unsigned int clocks, int preAmp, int boostNoise, int stereo) -{ - int i; - - /* cycle-accurate Game Gear stereo */ - if (clocks > SN76489.clocks) - { - /* Run chip until current timestamp */ - SN76489_RunUntil(clocks); - - /* Update internal M-cycle counter */ - SN76489.clocks += ((clocks - SN76489.clocks + PSG_MCYCLES_RATIO - 1) / PSG_MCYCLES_RATIO) * PSG_MCYCLES_RATIO; - } - - for (i=0; i<4; i++) - { - /* stereo channel pre-amplification */ - SN76489.PreAmp[i][0] = preAmp * ((stereo >> (i + 4)) & 1); - SN76489.PreAmp[i][1] = preAmp * ((stereo >> (i + 0)) & 1); - - /* noise channel boost (applied to all channels) */ - SN76489.PreAmp[i][0] = SN76489.PreAmp[i][0] << boostNoise; - SN76489.PreAmp[i][1] = SN76489.PreAmp[i][1] << boostNoise; - - /* update stereo channel amplitude */ - SN76489.Channel[i][0]= (PSGVolumeValues[SN76489.Registers[i*2 + 1]] * SN76489.PreAmp[i][0]) / 100; - SN76489.Channel[i][1]= (PSGVolumeValues[SN76489.Registers[i*2 + 1]] * SN76489.PreAmp[i][1]) / 100; - } -} - -void SN76489_Update(unsigned int clocks) -{ - int i; - - if (clocks > SN76489.clocks) - { - /* Run chip until current timestamp */ - SN76489_RunUntil(clocks); - - /* Update internal M-cycle counter */ - SN76489.clocks += ((clocks - SN76489.clocks + PSG_MCYCLES_RATIO - 1) / PSG_MCYCLES_RATIO) * PSG_MCYCLES_RATIO; - } - - /* Adjust internal M-cycle counter for next frame */ - SN76489.clocks -= clocks; - - /* Adjust channel time counters for new frame */ - for (i=0; i<4; ++i) - { - SN76489.ToneFreqVals[i] -= clocks; - } -} - -void SN76489_Write(unsigned int clocks, unsigned int data) -{ - unsigned int index; - - if (clocks > SN76489.clocks) - { - /* run chip until current timestamp */ - SN76489_RunUntil(clocks); - - /* update internal M-cycle counter */ - SN76489.clocks += ((clocks - SN76489.clocks + PSG_MCYCLES_RATIO - 1) / PSG_MCYCLES_RATIO) * PSG_MCYCLES_RATIO; - } - - if (data & 0x80) - { - /* latch byte %1 cc t dddd */ - SN76489.LatchedRegister = index = (data >> 4) & 0x07; - } - else - { - /* restore latched register index */ - index = SN76489.LatchedRegister; - } - - switch (index) - { - case 0: - case 2: - case 4: /* Tone Channels frequency */ - { - if (data & 0x80) - { - /* Data byte %1 cc t dddd */ - SN76489.Registers[index] = (SN76489.Registers[index] & 0x3f0) | (data & 0xf); - } - else - { - /* Data byte %0 - dddddd */ - SN76489.Registers[index] = (SN76489.Registers[index] & 0x00f) | ((data & 0x3f) << 4); - } - - /* zero frequency behaves the same as a value of 1 */ - if (SN76489.Registers[index] == 0) - { - SN76489.Registers[index] = 1; - } - break; - } - - case 1: - case 3: - case 5: /* Tone Channels attenuation */ - { - data &= 0x0f; - SN76489.Registers[index] = data; - data = PSGVolumeValues[data]; - index >>= 1; - SN76489.Channel[index][0] = (data * SN76489.PreAmp[index][0]) / 100; - SN76489.Channel[index][1] = (data * SN76489.PreAmp[index][1]) / 100; - break; - } - - case 6: /* Noise control */ - { - SN76489.Registers[6] = data & 0x0f; - - /* reset shift register */ - SN76489.NoiseShiftRegister = NoiseInitialState; - - /* set noise signal generator frequency */ - SN76489.NoiseFreq = 0x10 << (data&0x3); - break; - } - - case 7: /* Noise attenuation */ - { - data &= 0x0f; - SN76489.Registers[7] = data; - data = PSGVolumeValues[data]; - SN76489.Channel[3][0] = (data * SN76489.PreAmp[3][0]) / 100; - SN76489.Channel[3][1] = (data * SN76489.PreAmp[3][1]) / 100; - break; - } - } -} From 2bafab042e17eca2add6509a8c302d04b493c672 Mon Sep 17 00:00:00 2001 From: orbea <ovariegata@yahoo.com> Date: Thu, 19 Jan 2017 16:35:21 -0800 Subject: [PATCH 17/23] Allow setting GIT_VERSION --- Makefile.libretro | 2 +- libretro/jni/Android.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 027411f..e84f9ee 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -36,7 +36,7 @@ endif TARGET_NAME := genesis_plus_gx LIBM := -lm -GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" +GIT_VERSION ?= " $(shell git rev-parse --short HEAD || echo unknown)" ifneq ($(GIT_VERSION)," unknown") CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" endif diff --git a/libretro/jni/Android.mk b/libretro/jni/Android.mk index 2058772..00a6ebd 100644 --- a/libretro/jni/Android.mk +++ b/libretro/jni/Android.mk @@ -2,7 +2,7 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" +GIT_VERSION ?= " $(shell git rev-parse --short HEAD || echo unknown)" ifneq ($(GIT_VERSION)," unknown") LOCAL_CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" endif From 0f1d9501cf2c5011ec4ddc393d9ed3313018b808 Mon Sep 17 00:00:00 2001 From: aliaspider <aliaspider@gmail.com> Date: Mon, 23 Jan 2017 18:50:33 +0100 Subject: [PATCH 18/23] (ngc/Wii/WiiU) buildfix for devkitpro r29. --- Makefile.libretro | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index e84f9ee..833a3e6 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -232,6 +232,7 @@ else ifeq ($(platform), ngc) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) ENDIANNESS_DEFINES := -DBYTE_ORDER=BIG_ENDIAN PLATFORM_DEFINES := -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -DALT_RENDER + PLATFORM_DEFINES += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int STATIC_LINKING = 1 # Nintendo Wii @@ -240,15 +241,17 @@ else ifeq ($(platform), wii) CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) PLATFORM_DEFINES := -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DALT_RENDER + PLATFORM_DEFINES += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int ENDIANNESS_DEFINES := -DBYTE_ORDER=BIG_ENDIAN STATIC_LINKING = 1 -# Nintendo Wii +# Nintendo WiiU else ifeq ($(platform), wiiu) TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - PLATFORM_DEFINES := -DGEKKO -DWIIU -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DALT_RENDER -DUSE_DYNAMIC_ALLOC + PLATFORM_DEFINES := -DGEKKO -DWIIU -DHW_RVL -mwup -mcpu=750 -meabi -mhard-float -DALT_RENDER -DUSE_DYNAMIC_ALLOC + PLATFORM_DEFINES += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int ENDIANNESS_DEFINES := -DBYTE_ORDER=BIG_ENDIAN STATIC_LINKING = 1 From 9f9a4288a36cd1e16b3c202a5891d3e327fc5059 Mon Sep 17 00:00:00 2001 From: twinaphex <libretro@gmail.com> Date: Tue, 24 Jan 2017 02:21:05 +0100 Subject: [PATCH 19/23] return 'false' if info is NULL (retro_load_game) --- libretro/libretro.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libretro/libretro.c b/libretro/libretro.c index 1a5c121..779f039 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -1926,13 +1926,16 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code) bool retro_load_game(const struct retro_game_info *info) { int i; - const char *dir; + const char *dir = NULL; #if defined(_WIN32) - char slash = '\\'; + char slash = '\\'; #else - char slash = '/'; + char slash = '/'; #endif + if (!info) + return false; + extract_directory(g_rom_dir, info->path, sizeof(g_rom_dir)); extract_name(g_rom_name, info->path, sizeof(g_rom_name)); From afa38e3e37f542b597e000cee973acabe3b2fd9e Mon Sep 17 00:00:00 2001 From: twinaphex <libretro@gmail.com> Date: Tue, 24 Jan 2017 14:40:49 +0100 Subject: [PATCH 20/23] Better error handling --- libretro/libretro.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/libretro/libretro.c b/libretro/libretro.c index 779f039..86cca13 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -1936,6 +1936,19 @@ bool retro_load_game(const struct retro_game_info *info) if (!info) return false; +#ifdef FRONTEND_SUPPORTS_RGB565 + unsigned rgb565 = RETRO_PIXEL_FORMAT_RGB565; + if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565)) + if (log_cb) + log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); +#endif + + sms_ntsc = calloc(1, sizeof(sms_ntsc_t)); + md_ntsc = calloc(1, sizeof(md_ntsc_t)); + + init_bitmap(); + config_default(); + extract_directory(g_rom_dir, info->path, sizeof(g_rom_dir)); extract_name(g_rom_name, info->path, sizeof(g_rom_name)); @@ -2038,6 +2051,12 @@ void retro_unload_game(void) { if (system_hw == SYSTEM_MCD) bram_save(); + + audio_shutdown(); + if (md_ntsc) + free(md_ntsc); + if (sms_ntsc) + free(sms_ntsc); } unsigned retro_get_region(void) { return vdp_pal ? RETRO_REGION_PAL : RETRO_REGION_NTSC; } @@ -2105,15 +2124,9 @@ static void check_system_specs(void) void retro_init(void) { struct retro_log_callback log; - unsigned level, rgb565; + unsigned level = 1; uint64_t serialization_quirks = RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT; - sms_ntsc = calloc(1, sizeof(sms_ntsc_t)); - md_ntsc = calloc(1, sizeof(md_ntsc_t)); - init_bitmap(); - config_default(); - - level = 1; environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) @@ -2121,12 +2134,6 @@ void retro_init(void) else log_cb = NULL; -#ifdef FRONTEND_SUPPORTS_RGB565 - rgb565 = RETRO_PIXEL_FORMAT_RGB565; - if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565)) - if (log_cb) - log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); -#endif check_system_specs(); environ_cb(RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS, &serialization_quirks); @@ -2134,15 +2141,12 @@ void retro_init(void) void retro_deinit(void) { - audio_shutdown(); - if (md_ntsc) - free(md_ntsc); - if (sms_ntsc) - free(sms_ntsc); - } -void retro_reset(void) { gen_reset(0); } +void retro_reset(void) +{ + gen_reset(0); +} void retro_run(void) { From 1d678b8cae105b0e31446794ca9a4af001d615f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Benjamim?= <sergio_br2@yahoo.com.br> Date: Sat, 11 Feb 2017 16:54:41 -0200 Subject: [PATCH 21/23] Use disabled/enabled like other settings. --- libretro/libretro.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libretro/libretro.c b/libretro/libretro.c index 86cca13..73819fd 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -1146,7 +1146,7 @@ static void check_variables(void) var.key = "genesis_plus_gx_gun_cursor"; environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); { - if (strcmp(var.value, "no") == 0) + if (strcmp(var.value, "disabled") == 0) config.gun_cursor = 0; else config.gun_cursor = 1; @@ -1155,7 +1155,7 @@ static void check_variables(void) var.key = "genesis_plus_gx_invert_mouse"; environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); { - if (strcmp(var.value, "no") == 0) + if (strcmp(var.value, "disabled") == 0) config.invert_mouse = 0; else config.invert_mouse = 1; @@ -1535,8 +1535,8 @@ void retro_set_environment(retro_environment_t cb) { "genesis_plus_gx_gg_extra", "Game Gear extended screen; disabled|enabled" }, { "genesis_plus_gx_aspect_ratio", "Core-provided aspect ratio; auto|NTSC PAR|PAL PAR" }, { "genesis_plus_gx_render", "Interlaced mode 2 output; single field|double field" }, - { "genesis_plus_gx_gun_cursor", "Show Lightgun crosshair; no|yes" }, - { "genesis_plus_gx_invert_mouse", "Invert Mouse Y-axis; no|yes" }, + { "genesis_plus_gx_gun_cursor", "Show Lightgun crosshair; disabled|enabled" }, + { "genesis_plus_gx_invert_mouse", "Invert Mouse Y-axis; disabled|enabled" }, { NULL, NULL }, }; From 641fb280bc03a26f642ed3bafbffded13b0fcf81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Benjamim?= <sergio_br2@yahoo.com.br> Date: Sun, 12 Feb 2017 16:41:12 -0200 Subject: [PATCH 22/23] Revert "Adding ToadKing copyrights on changed files" This reverts commit b0ee59c26f182005c5ff6b4b7627ba2401beabad, this was not in Twinaphex fork. --- core/vdp_ctrl.c | 1 - core/vdp_render.c | 1 - 2 files changed, 2 deletions(-) diff --git a/core/vdp_ctrl.c b/core/vdp_ctrl.c index a6d8832..ce8b1a1 100644 --- a/core/vdp_ctrl.c +++ b/core/vdp_ctrl.c @@ -6,7 +6,6 @@ * * Copyright (C) 1998-2003 Charles Mac Donald (original code) * Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX) - * Copyright (C) 2016 Michael Lelli (Emscripten changes) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: diff --git a/core/vdp_render.c b/core/vdp_render.c index 6781823..c9493b3 100644 --- a/core/vdp_render.c +++ b/core/vdp_render.c @@ -6,7 +6,6 @@ * * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code) * Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX) - * Copyright (C) 2016 Michael Lelli (Emscripten changes) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: From 25035ea8db95c0d4c3d72adc8265419312df5e8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Benjamim?= <sergio_br2@yahoo.com.br> Date: Sun, 12 Feb 2017 16:43:04 -0200 Subject: [PATCH 23/23] Revert "Create a default makefile" This reverts commit 7013886b8ed66fd9c3a559b37dc1cea3ac8fe2a8, see https://github.com/ekeeke/Genesis-Plus-GX/pull/120#issuecomment-279205212 --- Makefile | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Makefile diff --git a/Makefile b/Makefile deleted file mode 100644 index 087932e..0000000 --- a/Makefile +++ /dev/null @@ -1 +0,0 @@ -include Makefile.libretro