Commit 62a06c10 authored by jdgleaver's avatar jdgleaver
Browse files

Miscellaneous fixes/improvements

parent d9456ae1
DEBUG = 0
FRONTEND_SUPPORTS_RGB565 = 1
FRONTEND_SUPPORTS_XRGB8888 = 0
TARGET_NAME := handy
GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)"
......@@ -53,6 +54,7 @@ ifeq ($(platform), unix)
fpic := -fPIC
TARGET := $(TARGET_NAME)_libretro.so
SHARED := -shared -Wl,-version-script=$(LIBRETRO_DIR)/link.T -Wl,-no-undefined
FRONTEND_SUPPORTS_XRGB8888 = 1
# OS X
else ifeq ($(platform),osx)
......@@ -522,6 +524,7 @@ else
CC ?= gcc
CXX ?= g++
SHARED := -shared -static-libgcc -static-libstdc++ -Wl,-no-undefined -Wl,-version-script=$(LIBRETRO_DIR)/link.T
FRONTEND_SUPPORTS_XRGB8888 = 1
endif
......@@ -532,7 +535,7 @@ include Makefile.common
OBJECTS := $(SOURCES_CXX:.cpp=.o)
ifeq ($(DEBUG),1)
FLAGS += -O0
FLAGS += -O0 -g
else
FLAGS += -O2 -DNDEBUG
endif
......
LIBRETRO_COMM_DIR := $(CORE_DIR)/libretro-common
INCFLAGS = -I$(CORE_DIR)/lynx \
-I$(CORE_DIR)/libretro \
-I$(CORE_DIR)
-I$(CORE_DIR) \
-I$(LIBRETRO_COMM_DIR)/include \
ifneq (,$(findstring msvc2003,$(platform)))
INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc
......@@ -10,6 +13,10 @@ ifeq ($(FRONTEND_SUPPORTS_RGB565), 1)
FLAGS += -DFRONTEND_SUPPORTS_RGB565
endif
ifeq ($(FRONTEND_SUPPORTS_XRGB8888), 1)
FLAGS += -DFRONTEND_SUPPORTS_XRGB8888
endif
SOURCES_CXX := $(CORE_DIR)/lynx/lynxdec.cpp \
$(CORE_DIR)/lynx/cart.cpp \
$(CORE_DIR)/lynx/memmap.cpp \
......
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_inline.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_INLINE_H
#define __LIBRETRO_SDK_INLINE_H
#ifndef INLINE
#if defined(_WIN32) || defined(__INTEL_COMPILER)
#define INLINE __inline
#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
#define INLINE inline
#elif defined(__GNUC__)
#define INLINE __inline__
#else
#define INLINE
#endif
#endif
#endif
#include "libretro.h"
#include "libretro_core_options.h"
#include <string.h>
#include <fstream>
#include "handy.h"
static retro_log_printf_t log_cb;
......@@ -16,17 +19,6 @@ static int16_t *soundBuffer = NULL;
#define RETRO_LYNX_WIDTH 160
#define RETRO_LYNX_HEIGHT 102
#if defined(DINGUX)
/* If a display mode of width 102 (or an integer
* multiple thereof) is requested on OpenDingux
* devices, the OS crashes. This is not a user
* space error, and there is no way to capture/
* handle it - the OS simply dies (instantly).
* Thus when the Lynx display is rotated, we
* have to pad the screen 'height' to the nearest
* 'safe' value (112) */
#define RETRO_LYNX_HEIGHT_ROTATE 112
#endif
// core options
static uint8_t lynx_rot = MIKIE_NO_ROTATE;
......@@ -34,22 +26,13 @@ static uint8_t lynx_width = RETRO_LYNX_WIDTH;
static uint8_t lynx_height = RETRO_LYNX_HEIGHT;
static int RETRO_PIX_BYTES = 2;
#if defined(FRONTEND_SUPPORTS_RGB565)
static int RETRO_PIX_DEPTH = 16;
#else
static int RETRO_PIX_DEPTH = 15;
#endif
#if defined(DINGUX)
/* When the Lynx display is rotated on OpenDingux
* devices, we offset the framebuffer pointer. To
* ensure the buffer cannot overflow, increase its
* overall size by a corresponding amount (we end
* up allocating more memory than we need, but this
* is harmless...) */
static uint8_t framebuffer[
RETRO_LYNX_WIDTH *
(RETRO_LYNX_WIDTH + (RETRO_LYNX_HEIGHT_ROTATE - RETRO_LYNX_HEIGHT)) *
4];
#else
static uint8_t framebuffer[RETRO_LYNX_WIDTH*RETRO_LYNX_WIDTH*4];
#endif
static bool newFrame = false;
static bool initialized = false;
......@@ -94,7 +77,6 @@ static map btn_map_rot_90[] = {
static map* btn_map;
static bool update_video = false;
static bool libretro_supports_input_bitmasks;
static bool select_button;
......@@ -102,6 +84,9 @@ static void check_color_depth(void)
{
if (RETRO_PIX_DEPTH == 24)
{
/* If XRGB8888 support is compiled in, attempt to
* set 24 bit colour depth */
#if defined(FRONTEND_SUPPORTS_XRGB8888)
enum retro_pixel_format rgb888 = RETRO_PIXEL_FORMAT_XRGB8888;
if(!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb888))
......@@ -109,8 +94,24 @@ static void check_color_depth(void)
if(log_cb) log_cb(RETRO_LOG_ERROR, "Pixel format XRGB8888 not supported by platform.\n");
RETRO_PIX_BYTES = 2;
#if defined(FRONTEND_SUPPORTS_RGB565)
RETRO_PIX_DEPTH = 16;
#else
RETRO_PIX_DEPTH = 15;
#endif
}
#else
/* XRGB8888 support is *not* compiled in.
* If we reach this point, then unforeseen
* errors have occurred - just 'reset' colour
* depth to 16 bit */
RETRO_PIX_BYTES = 2;
#if defined(FRONTEND_SUPPORTS_RGB565)
RETRO_PIX_DEPTH = 16;
#else
RETRO_PIX_DEPTH = 15;
#endif
#endif
}
if (RETRO_PIX_BYTES == 2)
......@@ -157,7 +158,6 @@ static UBYTE* lynx_display_callback(ULONG objref)
video_cb(framebuffer, lynx_width, lynx_height, RETRO_LYNX_WIDTH*RETRO_PIX_BYTES);
for(int total = 0; total < gAudioBufferPointer/4; )
total += audio_batch_cb(soundBuffer + total*2, (gAudioBufferPointer/4) - total);
gAudioBufferPointer = 0;
......@@ -165,16 +165,7 @@ static UBYTE* lynx_display_callback(ULONG objref)
newFrame = true;
#if defined(DINGUX)
/* If Lynx display is rotated, offset the framebuffer
* by half the OpenDingux padding width */
if ((lynx_rot == MIKIE_ROTATE_R) ||
(lynx_rot == MIKIE_ROTATE_L))
return (UBYTE*)(framebuffer +
(((RETRO_LYNX_HEIGHT_ROTATE - RETRO_LYNX_HEIGHT) >> 1) * RETRO_PIX_BYTES));
else
#endif
return (UBYTE*)framebuffer;
return (UBYTE*)framebuffer;
}
static void lynx_rotate()
......@@ -194,38 +185,18 @@ static void lynx_rotate()
break;
case MIKIE_ROTATE_R:
#if defined(DINGUX)
/* OpenDingux - 'width' must be padded to a
* safe value */
lynx_width = RETRO_LYNX_HEIGHT_ROTATE;
#else
lynx_width = RETRO_LYNX_HEIGHT;
#endif
lynx_height = RETRO_LYNX_WIDTH;
btn_map = btn_map_rot_90;
break;
case MIKIE_ROTATE_L:
#if defined(DINGUX)
/* OpenDingux - 'width' must be padded to a
* safe value */
lynx_width = RETRO_LYNX_HEIGHT_ROTATE;
#else
lynx_width = RETRO_LYNX_HEIGHT;
#endif
lynx_height = RETRO_LYNX_WIDTH;
btn_map = btn_map_rot_270;
break;
}
#if defined(DINGUX)
/* Since the OpenDingux framebuffer may
* contain padding, ensure that it gets
* zeroed out whenever the rotation changes
* (avoids garbage pixels) */
memset(framebuffer, 0, sizeof(framebuffer));
#endif
switch (RETRO_PIX_DEPTH)
{
case 15: lynx->DisplaySetAttributes(lynx_rot, MIKIE_PIXEL_FORMAT_16BPP_555, RETRO_LYNX_WIDTH*2, lynx_display_callback, (ULONG)0); break;
......@@ -258,36 +229,23 @@ static void check_variables(void)
lynx_rotate();
}
#if defined(DINGUX)
#if defined(FRONTEND_SUPPORTS_XRGB8888)
/* Only read colour depth setting on first run */
if (!initialized)
{
int old_value = RETRO_PIX_BYTES;
var.key = "handy_gfx_colors";
var.value = NULL;
/* Set 16bpp by default */
RETRO_PIX_BYTES = 2;
RETRO_PIX_DEPTH = 16;
if (old_value != RETRO_PIX_BYTES)
update_video = true;
}
#else
var.key = "handy_gfx_colors";
var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
int old_value = RETRO_PIX_BYTES;
if (strcmp(var.value, "16bit") == 0)
{
RETRO_PIX_BYTES = 2;
RETRO_PIX_DEPTH = 16;
}
else if (strcmp(var.value, "24bit") == 0)
{
RETRO_PIX_BYTES = 4;
RETRO_PIX_DEPTH = 24;
}
if (old_value != RETRO_PIX_BYTES)
update_video = true;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
if (strcmp(var.value, "24bit") == 0)
{
RETRO_PIX_BYTES = 4;
RETRO_PIX_DEPTH = 24;
}
}
#endif
}
......@@ -329,20 +287,9 @@ void retro_deinit(void)
void retro_set_environment(retro_environment_t cb)
{
static const struct retro_variable vars[] = {
{ "handy_rot", "Display rotation; None|90|270" },
#if !defined(DINGUX)
/* 24bit colour depth is too slow for
* OpenDingux devices, and toggling colour
* depths may cause a crash... */
{ "handy_gfx_colors", "Color depth; 16bit|24bit" },
#endif
{ NULL, NULL },
};
cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars);
environ_cb = cb;
libretro_set_core_options(environ_cb);
}
void retro_set_audio_sample(retro_audio_sample_t cb)
......@@ -492,26 +439,6 @@ void retro_run(void)
lynx_input();
if (update_video /*|| update_audio*/)
{
struct retro_system_av_info system_av_info;
if (update_video)
{
memset(&system_av_info, 0, sizeof(system_av_info));
environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &system_av_info);
check_color_depth();
lynx_rotate();
}
retro_get_system_av_info(&system_av_info);
environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &system_av_info);
update_video = false;
//update_audio = false;
}
gAudioLastUpdateCycle = gSystemCycleCount;
while (!newFrame)
......@@ -588,9 +515,6 @@ bool retro_load_game(const struct retro_game_info *info)
btn_map = btn_map_no_rot;
lynx_rotate();
update_video = false;
//update_audio = false;
initialized = true;
return true;
......
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this libretro API header (libretro.h).
......@@ -278,6 +278,10 @@ enum retro_language
RETRO_LANGUAGE_ARABIC = 16,
RETRO_LANGUAGE_GREEK = 17,
RETRO_LANGUAGE_TURKISH = 18,
RETRO_LANGUAGE_SLOVAK = 19,
RETRO_LANGUAGE_PERSIAN = 20,
RETRO_LANGUAGE_HEBREW = 21,
RETRO_LANGUAGE_ASTURIAN = 22,
RETRO_LANGUAGE_LAST,
/* Ensure sizeof(enum) == sizeof(int) */
......@@ -1087,10 +1091,10 @@ enum retro_mod
#define RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE (50 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* float * --
* Float value that lets us know what target refresh rate
* Float value that lets us know what target refresh rate
* is curently in use by the frontend.
*
* The core can use the returned value to set an ideal
* The core can use the returned value to set an ideal
* refresh rate/framerate.
*/
......@@ -1098,7 +1102,7 @@ enum retro_mod
/* bool * --
* Boolean value that indicates whether or not the frontend supports
* input bitmasks being returned by retro_input_state_t. The advantage
* of this is that retro_input_state_t has to be only called once to
* of this is that retro_input_state_t has to be only called once to
* grab all button states instead of multiple times.
*
* If it returns true, you can pass RETRO_DEVICE_ID_JOYPAD_MASK as 'id'
......@@ -1117,7 +1121,7 @@ enum retro_mod
* This may be still be done regardless of the core options
* interface version.
*
* If version is 1 however, core options may instead be set by
* If version is >= 1 however, core options may instead be set by
* passing an array of retro_core_option_definition structs to
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of
* retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL.
......@@ -1132,8 +1136,8 @@ enum retro_mod
* GET_VARIABLE.
* This allows the frontend to present these variables to
* a user dynamically.
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
* returns an API version of 1.
* This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
* returns an API version of >= 1.
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
* This should be called the first time as early as
* possible (ideally in retro_set_environment).
......@@ -1169,8 +1173,6 @@ enum retro_mod
* i.e. it should be feasible to cycle through options
* without a keyboard.
*
* First entry should be treated as a default.
*
* Example entry:
* {
* "foo_option",
......@@ -1196,8 +1198,8 @@ enum retro_mod
* GET_VARIABLE.
* This allows the frontend to present these variables to
* a user dynamically.
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
* returns an API version of 1.
* This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
* returns an API version of >= 1.
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
* This should be called the first time as early as
* possible (ideally in retro_set_environment).
......@@ -1257,7 +1259,82 @@ enum retro_mod
*
* 'data' points to an unsigned variable
*/
#define RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION 57
/* unsigned * --
* Unsigned value is the API version number of the disk control
* interface supported by the frontend. If callback return false,
* API version is assumed to be 0.
*
* In legacy code, the disk control interface is defined by passing
* a struct of type retro_disk_control_callback to
* RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
* This may be still be done regardless of the disk control
* interface version.
*
* If version is >= 1 however, the disk control interface may
* instead be defined by passing a struct of type
* retro_disk_control_ext_callback to
* RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE.
* This allows the core to provide additional information about
* disk images to the frontend and/or enables extra
* disk control functionality by the frontend.
*/
#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE 58
/* const struct retro_disk_control_ext_callback * --
* Sets an interface which frontend can use to eject and insert
* disk images, and also obtain information about individual
* disk image files registered by the core.
* This is used for games which consist of multiple images and
* must be manually swapped out by the user (e.g. PSX, floppy disk
* based systems).
*/
#define RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION 59
/* unsigned * --
* Unsigned value is the API version number of the message
* interface supported by the frontend. If callback returns
* false, API version is assumed to be 0.
*
* In legacy code, messages may be displayed in an
* implementation-specific manner by passing a struct
* of type retro_message to RETRO_ENVIRONMENT_SET_MESSAGE.
* This may be still be done regardless of the message
* interface version.
*
* If version is >= 1 however, messages may instead be
* displayed by passing a struct of type retro_message_ext
* to RETRO_ENVIRONMENT_SET_MESSAGE_EXT. This allows the
* core to specify message logging level, priority and
* destination (OSD, logging interface or both).
*/
#define RETRO_ENVIRONMENT_SET_MESSAGE_EXT 60
/* const struct retro_message_ext * --
* Sets a message to be displayed in an implementation-specific
* manner for a certain amount of 'frames'. Additionally allows
* the core to specify message logging level, priority and
* destination (OSD, logging interface or both).
* Should not be used for trivial messages, which should simply be
* logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a
* fallback, stderr).
*/
#define RETRO_ENVIRONMENT_GET_INPUT_MAX_USERS 61
/* unsigned * --
* Unsigned value is the number of active input devices
* provided by the frontend. This may change between
* frames, but will remain constant for the duration
* of each frame.
* If callback returns true, a core need not poll any
* input device with an index greater than or equal to
* the number of active devices.
* If callback returns false, the number of active input
* devices is unknown. In this case, all input devices
* should be considered active.
*/
/* VFS functionality */
/* File paths:
......@@ -2307,7 +2384,8 @@ struct retro_keyboard_callback
retro_keyboard_event_t callback;
};
/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE &
* RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE.
* Should be set for implementations which can swap out multiple disk
* images in runtime.
*
......@@ -2365,6 +2443,53 @@ typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index,
* with replace_image_index. */
typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void);
/* Sets initial image to insert in drive when calling
* core_load_game().
* Since we cannot pass the initial index when loading
* content (this would require a major API change), this
* is set by the frontend *before* calling the core's
* retro_load_game()/retro_load_game_special() implementation.
* A core should therefore cache the index/path values and handle
* them inside retro_load_game()/retro_load_game_special().
* - If 'index' is invalid (index >= get_num_images()), the
* core should ignore the set value and instead use 0
* - 'path' is used purely for error checking - i.e. when
* content is loaded, the core should verify that the
* disk specified by 'index' has the specified file path.
* This is to guard against auto selecting the wrong image
* if (for example) the user should modify an existing M3U
* playlist. We have to let the core handle this because
* set_initial_image() must be called before loading content,
* i.e. the frontend cannot access image paths in advance
* and thus cannot perform the error check itself.
* If set path and content path do not match, the core should
* ignore the set 'index' value and instead use 0
* Returns 'false' if index or 'path' are invalid, or core
* does not support this functionality
*/
typedef bool (RETRO_CALLCONV *retro_set_initial_image_t)(unsigned index, const char *path);
/* Fetches the path of the specified disk image file.
* Returns 'false' if index is invalid (index >= get_num_images())
* or path is otherwise unavailable.
*/
typedef bool (RETRO_CALLCONV *retro_get_image_path_t)(unsigned index, char *path, size_t len);
/* Fetches a core-provided 'label' for the specified disk
* image file. In the simplest case this may be a file name
* (without extension), but for cores with more complex
* content requirements information may be provided to
* facilitate user disk swapping - for example, a core
* running floppy-disk-based content may uniquely label
* save disks, data disks, level disks, etc. with names
* corresponding to in-game disk change prompts (so the
* frontend can provide better user guidance than a 'dumb'
* disk index value).
* Returns 'false' if index is invalid (index >= get_num_images())
* or label is otherwise unavailable.
*/
typedef bool (RETRO_CALLCONV *retro_get_image_label_t)(unsigned index, char *label, size_t len);
struct retro_disk_control_callback
{
retro_set_eject_state_t set_eject_state;
......@@ -2378,6 +2503,27 @@ struct retro_disk_control_callback
retro_add_image_index_t add_image_index;
};
struct retro_disk_control_ext_callback
{
retro_set_eject_state_t set_eject_state;
retro_get_eject_state_t get_eject_state;
retro_get_image_index_t get_image_index;
retro_set_image_index_t set_image_index;
retro_get_num_images_t get_num_images;
retro_replace_image_index_t replace_image_index;
retro_add_image_index_t add_image_index;
/* NOTE: Frontend will only attempt to record/restore
* last used disk index if both set_initial_image()
* and get_image_path() are implemented */
retro_set_initial_image_t set_initial_image; /* Optional - may be NULL */
retro_get_image_path_t get_image_path; /* Optional - may be NULL */
retro_get_image_label_t get_image_label; /* Optional - may be NULL */
};
enum retro_pixel_format
{
/* 0RGB1555, native endian.
......@@ -2408,6 +2554,104 @@ struct retro_message
unsigned frames; /* Duration in frames of message. */
};
enum retro_message_target
{
RETRO_MESSAGE_TARGET_ALL = 0,
RETRO_MESSAGE_TARGET_OSD,
RETRO_MESSAGE_TARGET_LOG
};
enum retro_message_type
{
RETRO_MESSAGE_TYPE_NOTIFICATION = 0,
RETRO_MESSAGE_TYPE_NOTIFICATION_ALT,
RETRO_MESSAGE_TYPE_STATUS,
RETRO_MESSAGE_TYPE_PROGRESS
};
struct retro_message_ext
{
/* Message string to be displayed/logged */
const char *msg;
/* Duration (in ms) of message when targeting the OSD */
unsigned duration;
/* Message priority when targeting the OSD
* > When multiple concurrent messages are sent to
* the frontend and the frontend does not have the
* capacity to display them all, messages with the
* *highest* priority value should be shown
* > There is no upper limit to a message priority
* value (within the bounds of the unsigned data type)
* > In the reference frontend (RetroArch), the same
* priority values are used for frontend-generated
* notifications, which are typically assigned values
* between 0 and 3 depending upon importance */
unsigned priority;