Merge pull request #143 from negativeExponent/libretro_updates

libretro-common and general input-related updates
This commit is contained in:
hizzlekizzle 2019-12-28 08:07:43 -06:00 committed by GitHub
commit 9142408648
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 539 additions and 243 deletions

View File

@ -931,23 +931,23 @@ int cdrom_read_subq(libretro_vfs_implementation_file *stream, unsigned char *buf
if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point >= 1 && point <= 99)
{
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
printf("[CDROM] Track start time: (MSF %02u:%02u:%02u) ", (unsigned)pmin, (unsigned)psec, (unsigned)pframe);
printf("Track start time: (aMSF %02u:%02u:%02u) ", (unsigned)pmin, (unsigned)psec, (unsigned)pframe);
}
else if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point == 0xA0)
{
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
printf("[CDROM] First Track Number: %d ", pmin);
printf("[CDROM] Disc Type: %d ", psec);
printf("First Track Number: %d ", pmin);
printf("Disc Type: %d ", psec);
}
else if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point == 0xA1)
{
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
printf("[CDROM] Last Track Number: %d ", pmin);
printf("Last Track Number: %d ", pmin);
}
else if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point == 0xA2)
{
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
printf("[CDROM] Lead-out runtime: (MSF %02u:%02u:%02u) ", (unsigned)pmin, (unsigned)psec, (unsigned)pframe);
printf("Lead-out start time: (aMSF %02u:%02u:%02u) ", (unsigned)pmin, (unsigned)psec, (unsigned)pframe);
}
printf("\n");
@ -1494,9 +1494,7 @@ bool cdrom_is_media_inserted(libretro_vfs_implementation_file *stream)
bool cdrom_drive_has_media(const char drive)
{
RFILE *file;
char cdrom_path_bin[256];
cdrom_path_bin[0] = '\0';
char cdrom_path_bin[256] = {0};
cdrom_device_fillpath(cdrom_path_bin, sizeof(cdrom_path_bin), drive, 1, false);
@ -1690,8 +1688,11 @@ void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char tra
#ifdef __linux__
pos = strlcpy(path, "cdrom://drive", len);
if (len > pos)
if (len > pos + 1)
{
path[pos++] = drive;
path[pos] = '\0';
}
pos = strlcat(path, ".cue", len);
#endif
@ -1702,8 +1703,11 @@ void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char tra
#ifdef _WIN32
pos = strlcpy(path, "cdrom://", len);
if (len > pos)
if (len > pos + 1)
{
path[pos++] = drive;
path[pos] = '\0';
}
pos += snprintf(path + pos, len - pos, ":/drive-track%02d.bin", track);
#else

View File

@ -114,16 +114,16 @@
#endif
static retro_vfs_stat_t path_stat_cb = NULL;
static retro_vfs_mkdir_t path_mkdir_cb = NULL;
static retro_vfs_stat_t path_stat_cb = retro_vfs_stat_impl;
static retro_vfs_mkdir_t path_mkdir_cb = retro_vfs_mkdir_impl;
void path_vfs_init(const struct retro_vfs_interface_info* vfs_info)
{
const struct retro_vfs_interface*
vfs_iface = vfs_info->iface;
path_stat_cb = NULL;
path_mkdir_cb = NULL;
path_stat_cb = retro_vfs_stat_impl;
path_mkdir_cb = retro_vfs_mkdir_impl;
if (vfs_info->required_interface_version < PATH_REQUIRED_VFS_VERSION || !vfs_iface)
return;
@ -132,13 +132,9 @@ void path_vfs_init(const struct retro_vfs_interface_info* vfs_info)
path_mkdir_cb = vfs_iface->mkdir;
}
#define path_stat_internal(path, size) ((path_stat_cb != NULL) ? path_stat_cb((path), (size)) : retro_vfs_stat_impl((path), (size)))
#define path_mkdir_norecurse(dir) ((path_mkdir_cb != NULL) ? path_mkdir_cb((dir)) : retro_vfs_mkdir_impl((dir)))
int path_stat(const char *path)
{
return path_stat_internal(path, NULL);
return path_stat_cb(path, NULL);
}
/**
@ -151,23 +147,23 @@ int path_stat(const char *path)
*/
bool path_is_directory(const char *path)
{
return (path_stat_internal(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
return (path_stat_cb(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
}
bool path_is_character_special(const char *path)
{
return (path_stat_internal(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0;
return (path_stat_cb(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0;
}
bool path_is_valid(const char *path)
{
return (path_stat_internal(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0;
return (path_stat_cb(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0;
}
int32_t path_get_size(const char *path)
{
int32_t filesize = 0;
if (path_stat_internal(path, &filesize) != 0)
if (path_stat_cb(path, &filesize) != 0)
return filesize;
return -1;
@ -233,7 +229,7 @@ bool path_mkdir(const char *dir)
if (norecurse)
{
int ret = path_mkdir_norecurse(dir);
int ret = path_mkdir_cb(dir);
/* Don't treat this as an error. */
if (ret == -2 && path_is_directory(dir))
@ -393,11 +389,11 @@ void fill_pathname(char *out_path, const char *in_path,
* present in 'in_path', it will be ignored.
*
*/
void fill_pathname_noext(char *out_path, const char *in_path,
size_t fill_pathname_noext(char *out_path, const char *in_path,
const char *replace, size_t size)
{
strlcpy(out_path, in_path, size);
strlcat(out_path, replace, size);
return strlcat(out_path, replace, size);
}
char *find_last_slash(const char *str)
@ -435,12 +431,8 @@ void fill_pathname_slash(char *path, size_t size)
/* Try to preserve slash type. */
if (last_slash != (path + path_len - 1))
{
char join_str[2];
join_str[0] = '\0';
strlcpy(join_str, last_slash, sizeof(join_str));
strlcat(path, join_str, size);
path[path_len] = last_slash[0];
path[path_len+1] = '\0';
}
}
@ -461,7 +453,7 @@ void fill_pathname_slash(char *path, size_t size)
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
**/
void fill_pathname_dir(char *in_dir, const char *in_basename,
size_t fill_pathname_dir(char *in_dir, const char *in_basename,
const char *replace, size_t size)
{
const char *base = NULL;
@ -469,7 +461,7 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
fill_pathname_slash(in_dir, size);
base = path_basename(in_basename);
strlcat(in_dir, base, size);
strlcat(in_dir, replace, size);
return strlcat(in_dir, replace, size);
}
/**
@ -480,14 +472,14 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
*
* Copies basename of @in_path into @out_path.
**/
void fill_pathname_base(char *out, const char *in_path, size_t size)
size_t fill_pathname_base(char *out, const char *in_path, size_t size)
{
const char *ptr = path_basename(in_path);
if (!ptr)
ptr = in_path;
strlcpy(out, ptr, size);
return strlcpy(out, ptr, size);
}
void fill_pathname_base_noext(char *out,
@ -497,12 +489,12 @@ void fill_pathname_base_noext(char *out,
path_remove_extension(out);
}
void fill_pathname_base_ext(char *out,
size_t fill_pathname_base_ext(char *out,
const char *in_path, const char *ext,
size_t size)
{
fill_pathname_base_noext(out, in_path, size);
strlcat(out, ext, size);
return strlcat(out, ext, size);
}
/**
@ -597,7 +589,7 @@ void fill_pathname_parent_dir(char *out_dir,
* E.g.:
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
**/
void fill_dated_filename(char *out_filename,
size_t fill_dated_filename(char *out_filename,
const char *ext, size_t size)
{
time_t cur_time = time(NULL);
@ -605,7 +597,7 @@ void fill_dated_filename(char *out_filename,
strftime(out_filename, size,
"RetroArch-%m%d-%H%M%S", tm_);
strlcat(out_filename, ext, size);
return strlcat(out_filename, ext, size);
}
/**
@ -655,6 +647,7 @@ void fill_str_dated_filename(char *out_filename,
void path_basedir(char *path)
{
char *last = NULL;
if (strlen(path) < 2)
return;
@ -858,13 +851,9 @@ char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks)
t++;
}
else if (next - p == 1 && p[0] == '.')
{
p += 2;
}
else if (next - p == 0)
{
p += 1;
}
else
{
/* fail when truncating */
@ -901,7 +890,7 @@ end:
*
* E.g. path /a/b/e/f.cg with base /a/b/c/d/ turns into ../../e/f.cg
**/
void path_relative_to(char *out,
size_t path_relative_to(char *out,
const char *path, const char *base, size_t size)
{
size_t i;
@ -912,10 +901,7 @@ void path_relative_to(char *out,
if (strlen(path) >= 2 && strlen(base) >= 2
&& path[1] == ':' && base[1] == ':'
&& path[0] != base[0])
{
strlcpy(out, path, size);
return;
}
return strlcpy(out, path, size);
#endif
/* Trim common beginning */
@ -929,7 +915,8 @@ void path_relative_to(char *out,
for (i = 0; trimmed_base[i]; i++)
if (trimmed_base[i] == path_default_slash_c())
strlcat(out, ".." path_default_slash(), size);
strlcat(out, trimmed_path, size);
return strlcat(out, trimmed_path, size);
}
/**
@ -969,7 +956,7 @@ void fill_pathname_resolve_relative(char *out_path,
* Makes sure not to get two consecutive slashes
* between directory and path.
**/
void fill_pathname_join(char *out_path,
size_t fill_pathname_join(char *out_path,
const char *dir, const char *path, size_t size)
{
if (out_path != dir)
@ -978,10 +965,10 @@ void fill_pathname_join(char *out_path,
if (*out_path)
fill_pathname_slash(out_path, size);
strlcat(out_path, path, size);
return strlcat(out_path, path, size);
}
void fill_pathname_join_special_ext(char *out_path,
size_t fill_pathname_join_special_ext(char *out_path,
const char *dir, const char *path,
const char *last, const char *ext,
size_t size)
@ -991,25 +978,25 @@ void fill_pathname_join_special_ext(char *out_path,
fill_pathname_slash(out_path, size);
strlcat(out_path, last, size);
strlcat(out_path, ext, size);
return strlcat(out_path, ext, size);
}
void fill_pathname_join_concat_noext(char *out_path,
size_t fill_pathname_join_concat_noext(char *out_path,
const char *dir, const char *path,
const char *concat,
size_t size)
{
fill_pathname_noext(out_path, dir, path, size);
strlcat(out_path, concat, size);
return strlcat(out_path, concat, size);
}
void fill_pathname_join_concat(char *out_path,
size_t fill_pathname_join_concat(char *out_path,
const char *dir, const char *path,
const char *concat,
size_t size)
{
fill_pathname_join(out_path, dir, path, size);
strlcat(out_path, concat, size);
return strlcat(out_path, concat, size);
}
void fill_pathname_join_noext(char *out_path,
@ -1030,7 +1017,7 @@ void fill_pathname_join_noext(char *out_path,
* Joins a directory (@dir) and path (@path) together
* using the given delimiter (@delim).
**/
void fill_pathname_join_delim(char *out_path, const char *dir,
size_t fill_pathname_join_delim(char *out_path, const char *dir,
const char *path, const char delim, size_t size)
{
size_t copied;
@ -1044,15 +1031,16 @@ void fill_pathname_join_delim(char *out_path, const char *dir,
out_path[copied+1] = '\0';
if (path)
strlcat(out_path, path, size);
copied = strlcat(out_path, path, size);
return copied;
}
void fill_pathname_join_delim_concat(char *out_path, const char *dir,
size_t fill_pathname_join_delim_concat(char *out_path, const char *dir,
const char *path, const char delim, const char *concat,
size_t size)
{
fill_pathname_join_delim(out_path, dir, path, delim, size);
strlcat(out_path, concat, size);
return strlcat(out_path, concat, size);
}
/**
@ -1070,7 +1058,7 @@ void fill_pathname_join_delim_concat(char *out_path, const char *dir,
* E.g.: "/path/to/game.img" -> game.img
* "/path/to/myarchive.7z#folder/to/game.img" -> game.img
*/
void fill_short_pathname_representation(char* out_rep,
size_t fill_short_pathname_representation(char* out_rep,
const char *in_path, size_t size)
{
char path_short[PATH_MAX_LENGTH];
@ -1080,7 +1068,7 @@ void fill_short_pathname_representation(char* out_rep,
fill_pathname(path_short, path_basename(in_path), "",
sizeof(path_short));
strlcpy(out_rep, path_short, size);
return strlcpy(out_rep, path_short, size);
}
void fill_short_pathname_representation_noext(char* out_rep,
@ -1298,20 +1286,24 @@ void fill_pathname_application_path(char *s, size_t len)
CFStringRef bundle_path = CFURLCopyPath(bundle_url);
CFStringGetCString(bundle_path, s, len, kCFStringEncodingUTF8);
#ifdef HAVE_COCOATOUCH
// This needs to be done so that the path becomes /private/var/... and this
// is used consistently throughout for the iOS bundle path
char resolved_bundle_dir_buf[PATH_MAX_LENGTH] = {0};
if (realpath(s, resolved_bundle_dir_buf))
{
strlcpy(s,resolved_bundle_dir_buf, len);
strlcat(s,"/",len);
}
{
/* This needs to be done so that the path becomes
* /private/var/... and this
* is used consistently throughout for the iOS bundle path */
char resolved_bundle_dir_buf[PATH_MAX_LENGTH] = {0};
if (realpath(s, resolved_bundle_dir_buf))
{
strlcpy(s, resolved_bundle_dir_buf, len - 1);
strlcat(s, "/", len);
}
}
#endif
CFRelease(bundle_path);
CFRelease(bundle_url);
#ifndef HAVE_COCOATOUCH
// Not sure what this does but it breaks stuff for iOS so skipping
/* Not sure what this does but it breaks
* stuff for iOS, so skipping */
retro_assert(strlcat(s, "nobin", len) < len);
#endif
return;

View File

@ -26,7 +26,6 @@
#ifdef _MSC_VER
#ifdef __cplusplus
#include <complex>
extern "C" {
#endif

View File

@ -178,7 +178,7 @@ char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks);
*
* E.g. path /a/b/e/f.cgp with base /a/b/c/d/ turns into ../../e/f.cgp
**/
void path_relative_to(char *out, const char *path, const char *base, size_t size);
size_t path_relative_to(char *out, const char *path, const char *base, size_t size);
/**
* path_is_absolute:
@ -226,7 +226,7 @@ void fill_pathname(char *out_path, const char *in_path,
* E.g.:
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
**/
void fill_dated_filename(char *out_filename,
size_t fill_dated_filename(char *out_filename,
const char *ext, size_t size);
/**
@ -259,7 +259,7 @@ void fill_str_dated_filename(char *out_filename,
* present in 'in_path', it will be ignored.
*
*/
void fill_pathname_noext(char *out_path, const char *in_path,
size_t fill_pathname_noext(char *out_path, const char *in_path,
const char *replace, size_t size);
/**
@ -289,7 +289,7 @@ char *find_last_slash(const char *str);
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
**/
void fill_pathname_dir(char *in_dir, const char *in_basename,
size_t fill_pathname_dir(char *in_dir, const char *in_basename,
const char *replace, size_t size);
/**
@ -300,12 +300,12 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
*
* Copies basename of @in_path into @out_path.
**/
void fill_pathname_base(char *out_path, const char *in_path, size_t size);
size_t fill_pathname_base(char *out_path, const char *in_path, size_t size);
void fill_pathname_base_noext(char *out_dir,
const char *in_path, size_t size);
void fill_pathname_base_ext(char *out,
size_t fill_pathname_base_ext(char *out,
const char *in_path, const char *ext,
size_t size);
@ -376,20 +376,20 @@ void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
* Makes sure not to get two consecutive slashes
* between directory and path.
**/
void fill_pathname_join(char *out_path, const char *dir,
size_t fill_pathname_join(char *out_path, const char *dir,
const char *path, size_t size);
void fill_pathname_join_special_ext(char *out_path,
size_t fill_pathname_join_special_ext(char *out_path,
const char *dir, const char *path,
const char *last, const char *ext,
size_t size);
void fill_pathname_join_concat_noext(char *out_path,
size_t fill_pathname_join_concat_noext(char *out_path,
const char *dir, const char *path,
const char *concat,
size_t size);
void fill_pathname_join_concat(char *out_path,
size_t fill_pathname_join_concat(char *out_path,
const char *dir, const char *path,
const char *concat,
size_t size);
@ -408,10 +408,10 @@ void fill_pathname_join_noext(char *out_path,
* Joins a directory (@dir) and path (@path) together
* using the given delimiter (@delim).
**/
void fill_pathname_join_delim(char *out_path, const char *dir,
size_t fill_pathname_join_delim(char *out_path, const char *dir,
const char *path, const char delim, size_t size);
void fill_pathname_join_delim_concat(char *out_path, const char *dir,
size_t fill_pathname_join_delim_concat(char *out_path, const char *dir,
const char *path, const char delim, const char *concat,
size_t size);
@ -430,7 +430,7 @@ void fill_pathname_join_delim_concat(char *out_path, const char *dir,
* E.g.: "/path/to/game.img" -> game.img
* "/path/to/myarchive.7z#folder/to/game.img" -> game.img
*/
void fill_short_pathname_representation(char* out_rep,
size_t fill_short_pathname_representation(char* out_rep,
const char *in_path, size_t size);
void fill_short_pathname_representation_noext(char* out_rep,

View File

@ -1248,6 +1248,16 @@ enum retro_mod
* default when calling SET_VARIABLES/SET_CORE_OPTIONS.
*/
#define RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER 56
/* unsigned * --
*
* Allows an implementation to ask frontend preferred hardware
* context to use. Core should use this information to deal
* with what specific context to request with SET_HW_RENDER.
*
* 'data' points to an unsigned variable
*/
/* VFS functionality */
/* File paths:
@ -1924,6 +1934,10 @@ enum retro_sensor_action
{
RETRO_SENSOR_ACCELEROMETER_ENABLE = 0,
RETRO_SENSOR_ACCELEROMETER_DISABLE,
RETRO_SENSOR_GYROSCOPE_ENABLE,
RETRO_SENSOR_GYROSCOPE_DISABLE,
RETRO_SENSOR_ILLUMINANCE_ENABLE,
RETRO_SENSOR_ILLUMINANCE_DISABLE,
RETRO_SENSOR_DUMMY = INT_MAX
};
@ -1932,6 +1946,10 @@ enum retro_sensor_action
#define RETRO_SENSOR_ACCELEROMETER_X 0
#define RETRO_SENSOR_ACCELEROMETER_Y 1
#define RETRO_SENSOR_ACCELEROMETER_Z 2
#define RETRO_SENSOR_GYROSCOPE_X 3
#define RETRO_SENSOR_GYROSCOPE_Y 4
#define RETRO_SENSOR_GYROSCOPE_Z 5
#define RETRO_SENSOR_ILLUMINANCE 6
typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port,
enum retro_sensor_action action, unsigned rate);

View File

@ -41,6 +41,7 @@ union string_list_elem_attr
struct string_list_elem
{
char *data;
void *userdata;
union string_list_elem_attr attr;
};
@ -87,6 +88,19 @@ bool string_list_find_elem_prefix(const struct string_list *list,
*/
struct string_list *string_split(const char *str, const char *delim);
/**
* string_separate:
* @str : string to turn into a string list
* @delim : delimiter character to use for separating the string.
*
* Creates a new string list based on string @str, delimited by @delim.
* Includes empty strings - i.e. two adjacent delimiters will resolve
* to a string list element of "".
*
* Returns: new string list if successful, otherwise NULL.
*/
struct string_list *string_separate(char *str, const char *delim);
/**
* string_list_new:
*

View File

@ -26,7 +26,7 @@
#include <stdio.h>
#include <stdint.h>
#if defined(__CELLOS_LV2__) || defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH)
#if defined(__CELLOS_LV2__) || defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH) || defined(HAVE_LIBNX)
/* No mman available */
#elif defined(_WIN32) && !defined(_XBOX)
#include <windows.h>

View File

@ -89,7 +89,9 @@ typedef int ssize_t;
/* C++11 says this one isn't needed, but apparently (some versions of) mingw require it anyways */
/* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */
/* https://github.com/libretro/RetroArch/issues/6009 */
#define __STDC_FORMAT_MACROS
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS 1
#endif
#include <inttypes.h>
#endif
#ifndef PRId64

View File

@ -61,7 +61,7 @@ int64_t filestream_truncate(RFILE *stream, int64_t length);
* Opens a file for reading or writing, depending on the requested mode.
* Returns a pointer to an RFILE if opened successfully, otherwise NULL.
**/
RFILE *filestream_open(const char *path, unsigned mode, unsigned hints);
RFILE* filestream_open(const char *path, unsigned mode, unsigned hints);
int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position);
@ -77,7 +77,7 @@ int filestream_close(RFILE *stream);
int64_t filestream_read_file(const char *path, void **buf, int64_t *len);
char *filestream_gets(RFILE *stream, char *s, size_t len);
char* filestream_gets(RFILE *stream, char *s, size_t len);
int filestream_getc(RFILE *stream);
@ -101,11 +101,12 @@ int filestream_delete(const char *path);
int filestream_rename(const char *old_path, const char *new_path);
const char *filestream_get_path(RFILE *stream);
const char* filestream_get_path(RFILE *stream);
bool filestream_exists(const char *path);
char *filestream_getline(RFILE *stream);
/* Returned pointer must be freed by the caller. */
char* filestream_getline(RFILE *stream);
libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream);

View File

@ -49,27 +49,9 @@ static INLINE bool string_is_equal(const char *a, const char *b)
#define string_is_not_equal(a, b) !string_is_equal((a), (b))
#define string_add_pair_open(s, size) strlcat((s), " (", (size))
#define string_add_pair_close(s, size) strlcat((s), ")", (size))
#define string_add_bracket_open(s, size) strlcat((s), "{", (size))
#define string_add_bracket_close(s, size) strlcat((s), "}", (size))
#define string_add_single_quote(s, size) strlcat((s), "'", (size))
#define string_add_quote(s, size) strlcat((s), "\"", (size))
#define string_add_colon(s, size) strlcat((s), ":", (size))
#define string_add_glob_open(s, size) strlcat((s), "glob('*", (size))
#define string_add_glob_close(s, size) strlcat((s), "*')", (size))
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
static INLINE void string_add_between_pairs(char *s, const char *str,
size_t size)
{
string_add_pair_open(s, size);
strlcat(s, str, size);
string_add_pair_close(s, size);
}
static INLINE bool string_is_equal_case_insensitive(const char *a,
const char *b)
{
@ -129,6 +111,41 @@ char *string_trim_whitespace(char *const s);
char *word_wrap(char *buffer, const char *string,
int line_width, bool unicode, unsigned max_lines);
/* Splits string into tokens seperated by 'delim'
* > Returned token string must be free()'d
* > Returns NULL if token is not found
* > After each call, 'str' is set to the position after the
* last found token
* > Tokens *include* empty strings
* Usage example:
* char *str = "1,2,3,4,5,6,7,,,10,";
* char **str_ptr = &str;
* char *token = NULL;
* while((token = string_tokenize(str_ptr, ",")))
* {
* printf("%s\n", token);
* free(token);
* token = NULL;
* }
*/
char* string_tokenize(char **str, const char *delim);
/* Removes every instance of character 'c' from 'str' */
void string_remove_all_chars(char *str, char c);
/* Replaces every instance of character 'find' in 'str'
* with character 'replace' */
void string_replace_all_chars(char *str, char find, char replace);
/* Converts string to unsigned integer.
* Returns 0 if string is invalid */
unsigned string_to_unsigned(const char *str);
/* Converts hexadecimal string to unsigned integer.
* Handles optional leading '0x'.
* Returns 0 if string is invalid */
unsigned string_hex_to_unsigned(const char *str);
RETRO_END_DECLS
#endif

View File

@ -47,7 +47,10 @@ void string_list_free(struct string_list *list)
{
if (list->elems[i].data)
free(list->elems[i].data);
list->elems[i].data = NULL;
if (list->elems[i].userdata)
free(list->elems[i].userdata);
list->elems[i].data = NULL;
list->elems[i].userdata = NULL;
}
free(list->elems);
@ -256,6 +259,59 @@ error:
return NULL;
}
/**
* string_separate:
* @str : string to turn into a string list
* @delim : delimiter character to use for separating the string.
*
* Creates a new string list based on string @str, delimited by @delim.
* Includes empty strings - i.e. two adjacent delimiters will resolve
* to a string list element of "".
*
* Returns: new string list if successful, otherwise NULL.
*/
struct string_list *string_separate(char *str, const char *delim)
{
char *token = NULL;
char **str_ptr = NULL;
struct string_list *list = NULL;
/* Sanity check */
if (!str || string_is_empty(delim))
goto error;
str_ptr = &str;
list = string_list_new();
if (!list)
goto error;
token = string_tokenize(str_ptr, delim);
while (token)
{
union string_list_elem_attr attr;
attr.i = 0;
if (!string_list_append(list, token, attr))
goto error;
free(token);
token = NULL;
token = string_tokenize(str_ptr, delim);
}
return list;
error:
if (token)
free(token);
if (list)
string_list_free(list);
return NULL;
}
/**
* string_list_find_elem:
* @list : pointer to string list

View File

@ -154,7 +154,7 @@ int64_t filestream_truncate(RFILE *stream, int64_t length)
* Opens a file for reading or writing, depending on the requested mode.
* Returns a pointer to an RFILE if opened successfully, otherwise NULL.
**/
RFILE *filestream_open(const char *path, unsigned mode, unsigned hints)
RFILE* filestream_open(const char *path, unsigned mode, unsigned hints)
{
struct retro_vfs_file_handle *fp = NULL;
RFILE* output = NULL;
@ -176,7 +176,7 @@ RFILE *filestream_open(const char *path, unsigned mode, unsigned hints)
return output;
}
char *filestream_gets(RFILE *stream, char *s, size_t len)
char* filestream_gets(RFILE *stream, char *s, size_t len)
{
int c = 0;
char *p = s;
@ -399,7 +399,7 @@ int filestream_rename(const char *old_path, const char *new_path)
return retro_vfs_file_rename_impl(old_path, new_path);
}
const char *filestream_get_path(RFILE *stream)
const char* filestream_get_path(RFILE *stream)
{
if (filestream_get_path_cb != NULL)
return filestream_get_path_cb(stream->hfile);
@ -572,13 +572,14 @@ bool filestream_write_file(const char *path, const void *data, int64_t size)
return true;
}
char *filestream_getline(RFILE *stream)
/* Returned pointer must be freed by the caller. */
char* filestream_getline(RFILE *stream)
{
char* newline_tmp = NULL;
char *newline_tmp = NULL;
size_t cur_size = 8;
size_t idx = 0;
int in = 0;
char* newline = (char*)malloc(9);
char *newline = (char*)malloc(9);
if (!stream || !newline)
{

View File

@ -237,3 +237,148 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode,
return buffer;
}
/* Splits string into tokens seperated by 'delim'
* > Returned token string must be free()'d
* > Returns NULL if token is not found
* > After each call, 'str' is set to the position after the
* last found token
* > Tokens *include* empty strings
* Usage example:
* char *str = "1,2,3,4,5,6,7,,,10,";
* char **str_ptr = &str;
* char *token = NULL;
* while((token = string_tokenize(str_ptr, ",")))
* {
* printf("%s\n", token);
* free(token);
* token = NULL;
* }
*/
char* string_tokenize(char **str, const char *delim)
{
/* Taken from https://codereview.stackexchange.com/questions/216956/strtok-function-thread-safe-supports-empty-tokens-doesnt-change-string# */
char *str_ptr = NULL;
char *delim_ptr = NULL;
char *token = NULL;
size_t token_len = 0;
/* Sanity checks */
if (!str || string_is_empty(delim))
return NULL;
str_ptr = *str;
/* Note: we don't check string_is_empty() here,
* empty strings are valid */
if (!str_ptr)
return NULL;
/* Search for delimiter */
delim_ptr = strstr(str_ptr, delim);
if (delim_ptr)
token_len = delim_ptr - str_ptr;
else
token_len = strlen(str_ptr);
/* Allocate token string */
token = (char *)malloc((token_len + 1) * sizeof(char));
if (!token)
return NULL;
/* Copy token */
strlcpy(token, str_ptr, (token_len + 1) * sizeof(char));
token[token_len] = '\0';
/* Update input string pointer */
*str = delim_ptr ? delim_ptr + strlen(delim) : NULL;
return token;
}
/* Removes every instance of character 'c' from 'str' */
void string_remove_all_chars(char *str, char c)
{
char *read_ptr = NULL;
char *write_ptr = NULL;
if (string_is_empty(str))
return;
read_ptr = str;
write_ptr = str;
while (*read_ptr != '\0')
{
*write_ptr = *read_ptr++;
write_ptr += (*write_ptr != c) ? 1 : 0;
}
*write_ptr = '\0';
}
/* Replaces every instance of character 'find' in 'str'
* with character 'replace' */
void string_replace_all_chars(char *str, char find, char replace)
{
char *str_ptr = str;
if (string_is_empty(str))
return;
while((str_ptr = strchr(str_ptr, find)) != NULL)
*str_ptr++ = replace;
}
/* Converts string to unsigned integer.
* Returns 0 if string is invalid */
unsigned string_to_unsigned(const char *str)
{
const char *ptr = NULL;
if (string_is_empty(str))
return 0;
for (ptr = str; *ptr != '\0'; ptr++)
{
if (!isdigit(*ptr))
return 0;
}
return (unsigned)strtoul(str, NULL, 10);
}
/* Converts hexadecimal string to unsigned integer.
* Handles optional leading '0x'.
* Returns 0 if string is invalid */
unsigned string_hex_to_unsigned(const char *str)
{
const char *hex_str = str;
const char *ptr = NULL;
size_t len;
if (string_is_empty(str))
return 0;
/* Remove leading '0x', if required */
len = strlen(str);
if (len >= 2)
if ((str[0] == '0') &&
((str[1] == 'x') || (str[1] == 'X')))
hex_str = str + 2;
if (string_is_empty(hex_str))
return 0;
/* Check for valid characters */
for (ptr = hex_str; *ptr != '\0'; ptr++)
{
if (!isxdigit(*ptr))
return 0;
}
return (unsigned)strtoul(hex_str, NULL, 16);
}

View File

@ -172,7 +172,7 @@
#endif
#if defined(_WIN32) && !defined(_XBOX)
#if defined(_WIN32)
#if !defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER >= 1400)
#define ATLEAST_VC2005
#endif
@ -938,7 +938,9 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
/* if fileXioGetStat fails */
int dir_ret = fileXioDopen(path);
is_dir = dir_ret > 0;
fileXioDclose(dir_ret);
if (is_dir) {
fileXioDclose(dir_ret);
}
}
else
is_dir = FIO_S_ISDIR(buf.mode);
@ -1117,11 +1119,13 @@ static bool dirent_check_error(libretro_vfs_implementation_dir *rdir)
#endif
}
libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool include_hidden)
libretro_vfs_implementation_dir *retro_vfs_opendir_impl(
const char *name, bool include_hidden)
{
#if defined(_WIN32)
unsigned path_len;
char path_buf[1024];
size_t copied = 0;
#if defined(LEGACY_WIN32)
char *path_local = NULL;
#else
@ -1145,21 +1149,24 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool i
path_buf[0] = '\0';
path_len = strlen(name);
copied = strlcpy(path_buf, name, sizeof(path_buf));
/* Non-NT platforms don't like extra slashes in the path */
if (name[path_len - 1] == '\\')
snprintf(path_buf, sizeof(path_buf), "%s*", name);
else
snprintf(path_buf, sizeof(path_buf), "%s\\*", name);
if (name[path_len - 1] != '\\')
path_buf[copied++] = '\\';
path_buf[copied] = '*';
path_buf[copied+1] = '\0';
#if defined(LEGACY_WIN32)
path_local = utf8_to_local_string_alloc(path_buf);
rdir->directory = FindFirstFile(path_local, &rdir->entry);
path_local = utf8_to_local_string_alloc(path_buf);
rdir->directory = FindFirstFile(path_local, &rdir->entry);
if (path_local)
free(path_local);
#else
path_wide = utf8_to_utf16_string_alloc(path_buf);
rdir->directory = FindFirstFileW(path_wide, &rdir->entry);
path_wide = utf8_to_utf16_string_alloc(path_buf);
rdir->directory = FindFirstFileW(path_wide, &rdir->entry);
if (path_wide)
free(path_wide);
@ -1229,19 +1236,23 @@ const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *rdir
{
#if defined(_WIN32)
#if defined(LEGACY_WIN32)
char *name_local = local_to_utf8_string_alloc(rdir->entry.cFileName);
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
strlcpy(rdir->entry.cFileName, name_local, sizeof(rdir->entry.cFileName));
{
char *name_local = local_to_utf8_string_alloc(rdir->entry.cFileName);
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
strlcpy(rdir->entry.cFileName, name_local, sizeof(rdir->entry.cFileName));
if (name_local)
free(name_local);
if (name_local)
free(name_local);
}
#else
char *name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
{
char *name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
if (name)
free(name);
if (name)
free(name);
}
#endif
return (char*)rdir->entry.cFileName;
#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) || defined(ORBIS)
@ -1249,7 +1260,8 @@ const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *rdir
#elif defined(PS2)
return rdir->entry.name;
#else
if (!rdir || !rdir->entry)
return NULL;
return rdir->entry->d_name;
#endif
}

View File

@ -55,62 +55,10 @@ using namespace Windows::Storage::FileProperties;
#include <string/stdstring.h>
#include <retro_environment.h>
#include <uwp/uwp_func.h>
#include <uwp/uwp_async.h>
namespace
{
/* Dear Microsoft
* I really appreciate all the effort you took to not provide any
* synchronous file APIs and block all attempts to synchronously
* wait for the results of async tasks for "smooth user experience",
* but I'm not going to run and rewrite all RetroArch cores for
* async I/O. I hope you like this hack I made instead.
*/
template<typename T>
T RunAsync(std::function<concurrency::task<T>()> func)
{
volatile bool finished = false;
Platform::Exception^ exception = nullptr;
T result;
func().then([&finished, &exception, &result](concurrency::task<T> t) {
try
{
result = t.get();
}
catch (Platform::Exception^ exception_)
{
exception = exception_;
}
finished = true;
});
/* Don't stall the UI thread - prevents a deadlock */
Windows::UI::Core::CoreWindow^ corewindow = Windows::UI::Core::CoreWindow::GetForCurrentThread();
while (!finished)
{
if (corewindow) {
corewindow->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent);
}
}
if (exception != nullptr)
throw exception;
return result;
}
template<typename T>
T RunAsyncAndCatchErrors(std::function<concurrency::task<T>()> func, T valueOnError)
{
try
{
return RunAsync<T>(func);
}
catch (Platform::Exception^ e)
{
return valueOnError;
}
}
void windowsize_path(wchar_t* path)
{
/* UWP deals with paths containing / instead of \ way worse than normal Windows */

View File

@ -1179,7 +1179,9 @@ static void set_volume (uint32_t *ptr, unsigned number)
#define MAX_PLAYERS 5
#define MAX_BUTTONS 15
static uint8_t input_buf[MAX_PLAYERS][2] = {};
static uint8_t input_type[MAX_PLAYERS] = {};
static uint8_t input_buf[MAX_PLAYERS][5] = {};
static float mouse_sensitivity = 1.0f;
// Array to keep track of whether a given player's button is turbo
static int turbo_enable[MAX_PLAYERS][MAX_BUTTONS] = {};
@ -1340,6 +1342,13 @@ static void check_variables(void)
else
turbo_toggle_alt = false;
}
var.key = "pce_mouse_sensitivity";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
mouse_sensitivity = atof(var.value);
}
}
bool retro_load_game(const struct retro_game_info *info)
@ -1396,8 +1405,10 @@ bool retro_load_game(const struct retro_game_info *info)
}
// Possible endian bug ...
for (unsigned i = 0; i < MAX_PLAYERS; i++)
PCEINPUT_SetInput(i, "gamepad", &input_buf[i][0]);
for (unsigned i = 0; i < MAX_PLAYERS; i++) {
input_type[i] = RETRO_DEVICE_JOYPAD;
PCEINPUT_SetInput(i, "gamepad", (uint8_t*)&input_buf[i][0]);
}
VDC_SetPixelFormat();
@ -1495,53 +1506,93 @@ static void update_input(void)
for (unsigned j = 0; j < MAX_PLAYERS; j++)
{
uint16_t input_state = 0;
// read normal inputs
for (unsigned i = 0; i < MAX_BUTTONS; i++)
switch (input_type[j])
{
input_state |= input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, map[i]) ? (1 << i) : 0;
case RETRO_DEVICE_JOYPAD:
{
uint16_t input_state = 0;
// handle turbo buttons
if (turbo_enable[j][i] == 1) // Check whether a given button is turbo-capable
// read normal inputs
for (unsigned i = 0; i < MAX_BUTTONS; i++)
{
if (input_state & (1 << i))
input_state |= input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, map[i]) ? (1 << i) : 0;
// handle turbo buttons
if (turbo_enable[j][i] == 1) // Check whether a given button is turbo-capable
{
if (turbo_counter[j][i] < 2) // Some PCE games needs 2 frames to react to button presses, so
input_state |= 1 << i; // trigger turbo button at counter 0 and 1
if (input_state & (1 << i))
{
if (turbo_counter[j][i] < 2) // Some PCE games needs 2 frames to react to button presses, so
input_state |= 1 << i; // trigger turbo button at counter 0 and 1
else
input_state &= ~(1 << i);
turbo_counter[j][i]++; // Counter is incremented by 1
if (turbo_counter[j][i] > Turbo_Delay) // When the counter exceeds turbo delay, reset counter to zero
turbo_counter[j][i] = 0;
}
else
input_state &= ~(1 << i);
turbo_counter[j][i]++; // Counter is incremented by 1
if (turbo_counter[j][i] > Turbo_Delay) // When the counter exceeds turbo delay, reset counter to zero
turbo_counter[j][i] = 0;
turbo_counter[j][i] = 0; // Reset counter if button is not pressed.
}
else
turbo_counter[j][i] = 0; // Reset counter if button is not pressed.
}
else
turbo_counter[j][i] = 0; // Reset counter if button is not pressed.
turbo_counter[j][i] = 0; // Reset counter if button is not pressed.
// handle 2/6 button mode switching
if (turbo_map_selected[i] != -1 && Turbo_Toggling && !AVPad6Enabled[j])
{
if (input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, map[i]))
// handle 2/6 button mode switching
if (turbo_map_selected[i] != -1 && Turbo_Toggling && !AVPad6Enabled[j])
{
if (turbo_toggle_down[j][i] == 0)
if (input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, map[i]))
{
turbo_toggle_down[j][i] = 1;
turbo_enable[j][turbo_map_selected[i]] = turbo_enable[j][turbo_map_selected[i]] ^ 1;
MDFN_DispMessage("Pad %i Button %s Turbo %s", j + 1,
i == (!turbo_toggle_alt ? 9 : 14) ? "I" : "II",
turbo_enable[j][turbo_map_selected[i]] ? "ON" : "OFF" );
if (turbo_toggle_down[j][i] == 0)
{
turbo_toggle_down[j][i] = 1;
turbo_enable[j][turbo_map_selected[i]] = turbo_enable[j][turbo_map_selected[i]] ^ 1;
MDFN_DispMessage("Pad %i Button %s Turbo %s", j + 1,
i == (!turbo_toggle_alt ? 9 : 14) ? "I" : "II",
turbo_enable[j][turbo_map_selected[i]] ? "ON" : "OFF" );
}
}
else turbo_toggle_down[j][i] = 0;
}
else turbo_toggle_down[j][i] = 0;
}
}
// Input data must be little endian.
input_buf[j][0] = (input_state >> 0) & 0xff;
input_buf[j][1] = (input_state >> 8) & 0xff;
// Input data must be little endian.
input_buf[j][0] = (input_state >> 0) & 0xff;
input_buf[j][1] = (input_state >> 8) & 0xff;
} break;
case RETRO_DEVICE_MOUSE:
{
int16_t raw_x = input_state_cb(j, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X);
int16_t raw_y = input_state_cb(j, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y);
int16_t x = (int16_t)roundf((float)raw_x * mouse_sensitivity);
int16_t y = (int16_t)roundf((float)raw_y * mouse_sensitivity);
input_buf[j][0] = (x >> 0) & 0xff;
input_buf[j][1] = (x >> 8) & 0xff;
input_buf[j][2] = (y >> 0) & 0xff;
input_buf[j][3] = (y >> 8) & 0xff;
input_buf[j][4] = 0;
// left mouse button
if (input_state_cb(j, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT))
input_buf[j][4] |= (1 << 0);
// right mouse button
if (input_state_cb(j, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT))
input_buf[j][4] |= (1 << 1);
// select
if (input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT))
input_buf[j][4] |= (1 << 2);
// start
if (input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START) ||
input_state_cb(j, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_MIDDLE))
input_buf[j][4] |= (1 << 3);
} break;
} // case
}
}
@ -1675,13 +1726,21 @@ unsigned retro_api_version(void)
void retro_set_controller_port_device(unsigned in_port, unsigned device)
{
if (in_port > 4)
return;
switch(device)
{
case RETRO_DEVICE_JOYPAD:
PCEINPUT_SetInput(in_port, "gamepad", &input_buf[in_port][0]);
input_type[in_port] = RETRO_DEVICE_JOYPAD;
PCEINPUT_SetInput(in_port, "gamepad", (uint8_t*)&input_buf[in_port][0]);
break;
case RETRO_DEVICE_MOUSE:
PCEINPUT_SetInput(in_port, "mouse", &input_buf[in_port][0]);
input_type[in_port] = RETRO_DEVICE_MOUSE;
PCEINPUT_SetInput(in_port, "mouse", (uint8_t*)&input_buf[in_port][0]);
break;
default:
input_type[in_port] = RETRO_DEVICE_NONE;
break;
}
}
@ -1697,6 +1756,9 @@ void retro_set_environment(retro_environment_t cb)
};
static const struct retro_controller_info ports[] = {
{ pads, 2 },
{ pads, 2 },
{ pads, 2 },
{ pads, 2 },
{ pads, 2 },
{ 0 },

View File

@ -320,6 +320,35 @@ struct retro_core_option_definition option_defs_us[] = {
},
"1"
},
{
"pce_mouse_sensitivity",
"Mouse Sensitivity",
"Configure the PCE Mouse device type's sensitivity.",
{
{ "0.25", NULL },
{ "0.50", NULL },
{ "0.75", NULL },
{ "1.00", NULL },
{ "1.25", NULL },
{ "1.50", NULL },
{ "1.75", NULL },
{ "2.00", NULL },
{ "2.25", NULL },
{ "2.50", NULL },
{ "2.75", NULL },
{ "3.00", NULL },
{ "3.25", NULL },
{ "3.50", NULL },
{ "3.75", NULL },
{ "4.00", NULL },
{ "4.25", NULL },
{ "4.50", NULL },
{ "4.75", NULL },
{ "5.00", NULL },
{ NULL, NULL },
},
"1.25"
},
{
"pce_turbo_delay",
"Turbo Delay",

View File

@ -51,11 +51,11 @@ void PCEINPUT_Init(void)
SyncSettings();
}
void PCEINPUT_SetInput(int port, const char *type, void *ptr)
void PCEINPUT_SetInput(unsigned port, const char *type, uint8 *ptr)
{
if(!strcasecmp(type, "gamepad"))
if(!strcmp(type, "gamepad"))
InputTypes[port] = 1;
else if(!strcasecmp(type, "mouse"))
else if(!strcmp(type, "mouse"))
InputTypes[port] = 2;
else
InputTypes[port] = 0;
@ -82,9 +82,9 @@ void INPUT_Frame(void)
}
else if(InputTypes[x] == 2)
{
mouse_x[x] += (int32)MDFN_de32lsb(data_ptr[x] + 0);
mouse_y[x] += (int32)MDFN_de32lsb(data_ptr[x] + 4);
pce_mouse_button[x] = *(uint8 *)(data_ptr[x] + 8);
mouse_x[x] += (int16)MDFN_de16lsb(data_ptr[x] + 0);
mouse_y[x] += (int16)MDFN_de16lsb(data_ptr[x] + 2);
pce_mouse_button[x] = *(uint8 *)(data_ptr[x] + 4);
}
}
}
@ -148,11 +148,7 @@ uint8 INPUT_Read(unsigned int A)
}
else
{
if(pce_mouse_button[tmp_ri] & 1)
ret ^= 0x3; //pce_mouse_button[tmp_ri];
if(pce_mouse_button[tmp_ri] & 0x2)
ret ^= 0x8;
ret ^= pce_mouse_button[tmp_ri] & 0xF;
}
}
else

View File

@ -3,7 +3,7 @@
void PCEINPUT_Init(void);
void PCEINPUT_SettingChanged(const char *name);
void PCEINPUT_SetInput(int port, const char *type, void *ptr);
void PCEINPUT_SetInput(unsigned port, const char *type, uint8 *ptr);
uint8 INPUT_Read(unsigned int A);
void INPUT_Write(unsigned int A, uint8 V);
void INPUT_Frame(void);