Merge pull request #38 from libretro/master

Libretro Updates
This commit is contained in:
ekeeke 2014-12-06 17:15:19 +01:00
commit 20a2337abe
2 changed files with 657 additions and 168 deletions

View File

@ -4,110 +4,125 @@ FRONTEND_SUPPORTS_RGB565 = 1
ifneq ($(EMSCRIPTEN),) ifneq ($(EMSCRIPTEN),)
platform = emscripten platform = emscripten
endif endif
ifeq ($(platform),) ifeq ($(platform),)
platform = unix platform = unix
ifeq ($(shell uname -a),) ifeq ($(shell uname -a),)
platform = win platform = win
else ifneq ($(findstring MINGW,$(shell uname -a)),) else ifneq ($(findstring MINGW,$(shell uname -a)),)
platform = win platform = win
else ifneq ($(findstring Darwin,$(shell uname -a)),) else ifneq ($(findstring Darwin,$(shell uname -a)),)
platform = osx platform = osx
arch = intel arch = intel
ifeq ($(shell uname -p),powerpc) ifeq ($(shell uname -p),powerpc)
arch = ppc arch = ppc
endif endif
else ifneq ($(findstring win,$(shell uname -a)),) else ifneq ($(findstring win,$(shell uname -a)),)
platform = win platform = win
endif endif
endif endif
# system platform # system platform
system_platform = unix system_platform = unix
ifeq ($(shell uname -a),) ifeq ($(shell uname -a),)
EXE_EXT = .exe EXE_EXT = .exe
system_platform = win system_platform = win
else ifneq ($(findstring Darwin,$(shell uname -a)),) else ifneq ($(findstring Darwin,$(shell uname -a)),)
system_platform = osx system_platform = osx
arch = intel arch = intel
ifeq ($(shell uname -p),powerpc) ifeq ($(shell uname -p),powerpc)
arch = ppc arch = ppc
endif endif
else ifneq ($(findstring MINGW,$(shell uname -a)),) else ifneq ($(findstring MINGW,$(shell uname -a)),)
system_platform = win system_platform = win
endif endif
TARGET_NAME := genesis_plus_gx TARGET_NAME := genesis_plus_gx
# Unix
ifeq ($(platform), unix) ifeq ($(platform), unix)
TARGET := $(TARGET_NAME)_libretro.so TARGET := $(TARGET_NAME)_libretro.so
fpic := -fPIC fpic := -fPIC
SHARED := -shared -Wl,--version-script=libretro/link.T -Wl,--no-undefined -lz SHARED := -shared -Wl,--version-script=libretro/link.T -Wl,--no-undefined -lz
ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN
PLATFORM_DEFINES := -DHAVE_ZLIB PLATFORM_DEFINES := -DHAVE_ZLIB
# OS X
else ifeq ($(platform), osx) else ifeq ($(platform), osx)
TARGET := $(TARGET_NAME)_libretro.dylib TARGET := $(TARGET_NAME)_libretro.dylib
fpic := -fPIC fpic := -fPIC
SHARED := -dynamiclib -lz SHARED := -dynamiclib -lz
ifeq ($(arch),ppc) ifeq ($(arch),ppc)
ENDIANNESS_DEFINES := -DBYTE_ORDER=BIG_ENDIAN ENDIANNESS_DEFINES := -DBYTE_ORDER=BIG_ENDIAN
else else
ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN
endif endif
PLATFORM_DEFINES := -DHAVE_ZLIB PLATFORM_DEFINES := -DHAVE_ZLIB
OSXVER = `sw_vers -productVersion | cut -d. -f 2` OSXVER = `sw_vers -productVersion | cut -d. -f 2`
OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"` OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"`
ifeq ($(OSX_LT_MAVERICKS),"YES") ifeq ($(OSX_LT_MAVERICKS),"YES")
fpic += -mmacosx-version-min=10.5 fpic += -mmacosx-version-min=10.5
endif endif
# iOS
else ifeq ($(platform), ios) else ifeq ($(platform), ios)
TARGET := $(TARGET_NAME)_libretro_ios.dylib TARGET := $(TARGET_NAME)_libretro_ios.dylib
fpic := -fPIC fpic := -fPIC
SHARED := -dynamiclib -lz SHARED := -dynamiclib -lz
ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN
PLATFORM_DEFINES := -DHAVE_ZLIB PLATFORM_DEFINES := -DHAVE_ZLIB
ifeq ($(IOSSDK),) ifeq ($(IOSSDK),)
IOSSDK := $(shell xcrun -sdk iphoneos -show-sdk-path) IOSSDK := $(shell xcrun -sdk iphoneos -show-sdk-path)
endif endif
CC = clang -arch armv7 -isysroot $(IOSSDK) CC = clang -arch armv7 -isysroot $(IOSSDK)
OSXVER = `sw_vers -productVersion | cut -d. -f 2` OSXVER = `sw_vers -productVersion | cut -d. -f 2`
OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"` OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"`
ifeq ($(OSX_LT_MAVERICKS),"YES") ifeq ($(OSX_LT_MAVERICKS),"YES")
CC += -miphoneos-version-min=5.0 CC += -miphoneos-version-min=5.0
PLATFORM_DEFINES += -miphoneos-version-min=5.0 PLATFORM_DEFINES += -miphoneos-version-min=5.0
endif endif
# QNX
else ifeq ($(platform), qnx) else ifeq ($(platform), qnx)
TARGET := $(TARGET_NAME)_libretro_qnx.so TARGET := $(TARGET_NAME)_libretro_qnx.so
fpic := -fPIC fpic := -fPIC
SHARED := -lm -shared -Wl,--version-script=libretro/link.T -Wl,--no-undefined -lz SHARED := -lm -shared -Wl,--version-script=libretro/link.T -Wl,--no-undefined -lz
ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN
PLATFORM_DEFINES := -DHAVE_ZLIB PLATFORM_DEFINES := -DHAVE_ZLIB
CC = qcc -Vgcc_ntoarmv7le CC = qcc -Vgcc_ntoarmv7le
AR = qcc -Vgcc_ntoarmv7le AR = qcc -Vgcc_ntoarmv7le
PLATFORM_DEFINES := -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp PLATFORM_DEFINES := -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp
# PS3
else ifeq ($(platform), ps3) else ifeq ($(platform), ps3)
TARGET := $(TARGET_NAME)_libretro_ps3.a TARGET := $(TARGET_NAME)_libretro_ps3.a
CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe
AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe
PLATFORM_DEFINES := -D__CELLOS_LV2 -DALT_RENDER -DBYTE_ORDER=BIG_ENDIAN PLATFORM_DEFINES := -D__CELLOS_LV2 -DALT_RENDER -DBYTE_ORDER=BIG_ENDIAN
STATIC_LINKING = 1 STATIC_LINKING = 1
# sncps3
else ifeq ($(platform), sncps3) else ifeq ($(platform), sncps3)
TARGET := $(TARGET_NAME)_libretro_ps3.a TARGET := $(TARGET_NAME)_libretro_ps3.a
CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe
AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe
PLATFORM_DEFINES := -D__CELLOS_LV2 -DALT_RENDER -DBYTE_ORDER=BIG_ENDIAN PLATFORM_DEFINES := -D__CELLOS_LV2 -DALT_RENDER -DBYTE_ORDER=BIG_ENDIAN
STATIC_LINKING = 1 STATIC_LINKING = 1
# Lightweight PS3 Homebrew SDK
else ifeq ($(platform), psl1ght) else ifeq ($(platform), psl1ght)
TARGET := $(TARGET_NAME)_libretro_psl1ght.a$(EXE_EXT) TARGET := $(TARGET_NAME)_libretro_psl1ght.a$(EXE_EXT)
CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT)
AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT)
PLATFORM_DEFINES := -D__CELLOS_LV2 -DALT_RENDER PLATFORM_DEFINES := -D__CELLOS_LV2 -DALT_RENDER
STATIC_LINKING = 1 STATIC_LINKING = 1
# PSP
else ifeq ($(platform), psp1) else ifeq ($(platform), psp1)
TARGET := $(TARGET_NAME)_libretro_psp1.a$(EXE_EXT) TARGET := $(TARGET_NAME)_libretro_psp1.a$(EXE_EXT)
CC = psp-gcc$(EXE_EXT) CC = psp-gcc$(EXE_EXT)
@ -116,64 +131,77 @@ else ifeq ($(platform), psp1)
PLATFORM_DEFINES := -DPSP PLATFORM_DEFINES := -DPSP
CFLAGS += -G0 CFLAGS += -G0
STATIC_LINKING = 1 STATIC_LINKING = 1
else ifeq ($(platform), xenon)
TARGET := $(TARGET_NAME)_libretro_xenon360.a
CC = xenon-gcc$(EXE_EXT)
AR = xenon-ar$(EXE_EXT)
PLATFORM_DEFINES := -D__LIBXENON__ -DALT_RENDER
ENDIANNESS_DEFINES := -DBYTE_ORDER=BIG_ENDIAN
STATIC_LINKING = 1
else ifeq ($(platform), ngc)
TARGET := $(TARGET_NAME)_libretro_ngc.a
CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT)
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
STATIC_LINKING = 1
else ifeq ($(platform), wii)
TARGET := $(TARGET_NAME)_libretro_wii.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
else ifneq (,$(findstring armv,$(platform)))
TARGET := $(TARGET_NAME)_libretro.so
fpic := -fPIC
SHARED := -shared -Wl,--version-script=libretro/link.T -Wl,--no-undefined -lz
ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN
PLATFORM_DEFINES := -DHAVE_ZLIB
CC = gcc
ifneq (,$(findstring cortexa8,$(platform)))
PLATFORM_DEFINES += -marm -mcpu=cortex-a8
else ifneq (,$(findstring cortexa9,$(platform)))
PLATFORM_DEFINES += -marm -mcpu=cortex-a9
endif
PLATFORM_DEFINES += -marm
ifneq (,$(findstring neon,$(platform)))
PLATFORM_DEFINES += -mfpu=neon
HAVE_NEON = 1
endif
ifneq (,$(findstring softfloat,$(platform)))
PLATFORM_DEFINES += -mfloat-abi=softfp
else ifneq (,$(findstring hardfloat,$(platform)))
PLATFORM_DEFINES += -mfloat-abi=hard
endif
PLATFORM_DEFINES += -DARM
else ifeq ($(platform), emscripten)
TARGET := $(TARGET_NAME)_libretro_emscripten.bc
ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN
else
TARGET := $(TARGET_NAME)_libretro.dll
CC = gcc
SHARED := -shared -static-libgcc -static-libstdc++ -Wl,--version-script=libretro/link.T -Wl,--no-undefined -lz
ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN # Xbox 360
PLATFORM_DEFINES := -DHAVE_ZLIB else ifeq ($(platform), xenon)
TARGET := $(TARGET_NAME)_libretro_xenon360.a
CC = xenon-gcc$(EXE_EXT)
AR = xenon-ar$(EXE_EXT)
PLATFORM_DEFINES := -D__LIBXENON__ -DALT_RENDER
ENDIANNESS_DEFINES := -DBYTE_ORDER=BIG_ENDIAN
STATIC_LINKING = 1
# Nintendo Game Cube
else ifeq ($(platform), ngc)
TARGET := $(TARGET_NAME)_libretro_ngc.a
CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT)
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
STATIC_LINKING = 1
# Nintendo Wii
else ifeq ($(platform), wii)
TARGET := $(TARGET_NAME)_libretro_wii.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
# ARM
else ifneq (,$(findstring armv,$(platform)))
TARGET := $(TARGET_NAME)_libretro.so
fpic := -fPIC
SHARED := -shared -Wl,--version-script=libretro/link.T -Wl,--no-undefined -lz
ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN
PLATFORM_DEFINES := -DHAVE_ZLIB
CC = gcc
ifneq (,$(findstring cortexa8,$(platform)))
PLATFORM_DEFINES += -marm -mcpu=cortex-a8
else ifneq (,$(findstring cortexa9,$(platform)))
PLATFORM_DEFINES += -marm -mcpu=cortex-a9
endif
PLATFORM_DEFINES += -marm
ifneq (,$(findstring neon,$(platform)))
PLATFORM_DEFINES += -mfpu=neon
HAVE_NEON = 1
endif
ifneq (,$(findstring softfloat,$(platform)))
PLATFORM_DEFINES += -mfloat-abi=softfp
else ifneq (,$(findstring hardfloat,$(platform)))
PLATFORM_DEFINES += -mfloat-abi=hard
endif
PLATFORM_DEFINES += -DARM
# emscripten
else ifeq ($(platform), emscripten)
TARGET := $(TARGET_NAME)_libretro_emscripten.bc
ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN
# Windows
else
TARGET := $(TARGET_NAME)_libretro.dll
CC = gcc
SHARED := -shared -static-libgcc -static-libstdc++ -Wl,--version-script=libretro/link.T -Wl,--no-undefined -lz
ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN
PLATFORM_DEFINES := -DHAVE_ZLIB
endif endif
ifeq ($(DEBUG), 1) ifeq ($(DEBUG), 1)
CFLAGS += -O0 -g CFLAGS += -O0 -g
else ifeq ($(platform),qnx) else ifeq ($(platform),qnx)
CFLAGS += -Os -DNDEBUG CFLAGS += -Os -DNDEBUG
else ifeq ($(platform), emscripten) else ifeq ($(platform), emscripten)
@ -192,25 +220,25 @@ include $(LIBRETRO_DIR)/Makefile.common
OBJECTS := $(SOURCES_C:.c=.o) OBJECTS := $(SOURCES_C:.c=.o)
ifeq ($(LOGSOUND), 1) ifeq ($(LOGSOUND), 1)
LIBRETRO_CFLAGS := -DLOGSOUND LIBRETRO_CFLAGS := -DLOGSOUND
endif endif
DEFINES := -DUSE_LIBTREMOR DEFINES := -DUSE_LIBTREMOR
CFLAGS += $(fpic) $(DEFINES) $(CODE_DEFINES) CFLAGS += $(fpic) $(DEFINES) $(CODE_DEFINES)
ifeq ($(FRONTEND_SUPPORTS_RGB565), 1) ifeq ($(FRONTEND_SUPPORTS_RGB565), 1)
# if you have a new frontend that supports RGB565 # if you have a new frontend that supports RGB565
BPP_DEFINES = -DUSE_16BPP_RENDERING -DFRONTEND_SUPPORTS_RGB565 BPP_DEFINES = -DUSE_16BPP_RENDERING -DFRONTEND_SUPPORTS_RGB565
else else
BPP_DEFINES = -DUSE_15BPP_RENDERING BPP_DEFINES = -DUSE_15BPP_RENDERING
endif endif
LIBRETRO_CFLAGS += $(INCFLAGS) LIBRETRO_CFLAGS += $(INCFLAGS)
LIBRETRO_CFLAGS += $(BPP_DEFINES) \ LIBRETRO_CFLAGS += $(BPP_DEFINES) \
$(ENDIANNESS_DEFINES) \ $(ENDIANNESS_DEFINES) \
$(PLATFORM_DEFINES) \ $(PLATFORM_DEFINES) \
-D__LIBRETRO__ -D__LIBRETRO__
ifeq ($(platform), qnx) ifeq ($(platform), qnx)
LIBRETRO_CFLAGS += -D__inline__=inline LIBRETRO_CFLAGS += -D__inline__=inline
@ -241,4 +269,3 @@ clean:
rm -f $(TARGET) rm -f $(TARGET)
.PHONY: clean clean-objs .PHONY: clean clean-objs

View File

@ -81,6 +81,32 @@ static retro_input_state_t input_state_cb;
static retro_environment_t environ_cb; static retro_environment_t environ_cb;
static retro_audio_sample_batch_t audio_cb; static retro_audio_sample_batch_t audio_cb;
/* Cheat Support */
#define MAX_CHEATS (150)
#define MAX_DESC_LENGTH (63)
typedef struct
{
char code[12];
char text[MAX_DESC_LENGTH];
uint8_t enable;
uint16_t data;
uint16_t old;
uint32_t address;
uint8_t *prev;
} CHEATENTRY;
static int maxcheats = 0;
static int maxROMcheats = 0;
static int maxRAMcheats = 0;
static CHEATENTRY cheatlist[MAX_CHEATS];
static uint8_t cheatIndexes[MAX_CHEATS];
static char ggvalidchars[] = "ABCDEFGHJKLMNPRSTVWXYZ0123456789";
static char arvalidchars[] = "0123456789ABCDEF";
/************************************ /************************************
* Genesis Plus GX implementation * Genesis Plus GX implementation
************************************/ ************************************/
@ -169,6 +195,8 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize, char *exten
return size; return size;
} }
void RAMCheatUpdate(void);
void osd_input_update(void) void osd_input_update(void)
{ {
int i, player = 0; int i, player = 0;
@ -176,6 +204,9 @@ void osd_input_update(void)
input_poll_cb(); input_poll_cb();
/* Update RAM patches */
RAMCheatUpdate();
for (i = 0; i < MAX_INPUTS; i++) for (i = 0; i < MAX_INPUTS; i++)
{ {
temp = 0; temp = 0;
@ -442,6 +473,7 @@ static void config_default(void)
config.addr_error = 1; config.addr_error = 1;
config.bios = 0; config.bios = 0;
config.lock_on = 0; config.lock_on = 0;
config.lcd = 0; /* 0.8 fixed point */
/* video options */ /* video options */
config.overscan = 0; config.overscan = 0;
@ -675,7 +707,7 @@ static void check_variables(void)
bool reinit = false; bool reinit = false;
struct retro_variable var = {0}; struct retro_variable var = {0};
var.key = "system_hw"; var.key = "genesis_plus_gx_system_hw";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
orig_value = config.system; orig_value = config.system;
@ -724,7 +756,7 @@ static void check_variables(void)
} }
} }
var.key = "region_detect"; var.key = "genesis_plus_gx_region_detect";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
orig_value = config.region_detect; orig_value = config.region_detect;
@ -747,7 +779,7 @@ static void check_variables(void)
} }
} }
var.key = "force_dtack"; var.key = "genesis_plus_gx_force_dtack";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
if (!strcmp(var.value, "enabled")) if (!strcmp(var.value, "enabled"))
@ -756,7 +788,7 @@ static void check_variables(void)
config.force_dtack = 0; config.force_dtack = 0;
} }
var.key = "addr_error"; var.key = "genesis_plus_gx_addr_error";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
if (!strcmp(var.value, "enabled")) if (!strcmp(var.value, "enabled"))
@ -765,7 +797,7 @@ static void check_variables(void)
m68k.aerr_enabled = config.addr_error = 0; m68k.aerr_enabled = config.addr_error = 0;
} }
var.key = "lock_on"; var.key = "genesis_plus_gx_lock_on";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
orig_value = config.lock_on; orig_value = config.lock_on;
@ -785,7 +817,7 @@ static void check_variables(void)
} }
} }
var.key = "ym2413"; var.key = "genesis_plus_gx_ym2413";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
orig_value = config.ym2413; orig_value = config.ym2413;
@ -807,7 +839,7 @@ static void check_variables(void)
} }
} }
var.key = "dac_bits"; var.key = "genesis_plus_gx_dac_bits";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
if (!strcmp(var.value, "enabled")) if (!strcmp(var.value, "enabled"))
@ -818,7 +850,7 @@ static void check_variables(void)
YM2612Config(config.dac_bits); YM2612Config(config.dac_bits);
} }
var.key = "blargg_ntsc_filter"; var.key = "genesis_plus_gx_blargg_ntsc_filter";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
orig_value = config.ntsc; orig_value = config.ntsc;
@ -854,7 +886,7 @@ static void check_variables(void)
update_viewports = true; update_viewports = true;
} }
var.key = "lcd_filter"; var.key = "genesis_plus_gx_lcd_filter";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
if (strcmp(var.value, "disabled") == 0) if (strcmp(var.value, "disabled") == 0)
@ -863,7 +895,7 @@ static void check_variables(void)
config.lcd = (uint8)(0.80 * 256); config.lcd = (uint8)(0.80 * 256);
} }
var.key = "overscan"; var.key = "genesis_plus_gx_overscan";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
orig_value = config.overscan; orig_value = config.overscan;
@ -879,7 +911,7 @@ static void check_variables(void)
update_viewports = true; update_viewports = true;
} }
var.key = "gg_extra"; var.key = "genesis_plus_gx_gg_extra";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
orig_value = config.gg_extra; orig_value = config.gg_extra;
@ -891,7 +923,7 @@ static void check_variables(void)
update_viewports = true; update_viewports = true;
} }
var.key = "render"; var.key = "genesis_plus_gx_render";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
orig_value = config.render; orig_value = config.render;
@ -903,7 +935,7 @@ static void check_variables(void)
update_viewports = true; update_viewports = true;
} }
var.key = "gun_cursor"; var.key = "genesis_plus_gx_gun_cursor";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
if (strcmp(var.value, "off") == 0) if (strcmp(var.value, "off") == 0)
@ -912,7 +944,7 @@ static void check_variables(void)
config.gun_cursor = 1; config.gun_cursor = 1;
} }
var.key = "invert_mouse"; var.key = "genesis_plus_gx_invert_mouse";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
{ {
if (strcmp(var.value, "off") == 0) if (strcmp(var.value, "off") == 0)
@ -940,6 +972,314 @@ static void check_variables(void)
} }
} }
/* Cheat Support */
static uint32_t decode_cheat(char *string, int index)
{
char *p;
int i,n;
uint32_t len = 0;
uint32_t address = 0;
uint16_t data = 0;
uint8_t ref = 0;
/* 16-bit Game Genie code (ABCD-EFGH) */
if ((strlen(string) >= 9) && (string[4] == '-'))
{
/* 16-bit system only */
if ((system_hw & SYSTEM_PBC) != SYSTEM_MD)
{
return 0;
}
for (i = 0; i < 8; i++)
{
if (i == 4) string++;
p = strchr (ggvalidchars, *string++);
if (p == NULL) return 0;
n = p - ggvalidchars;
switch (i)
{
case 0:
data |= n << 3;
break;
case 1:
data |= n >> 2;
address |= (n & 3) << 14;
break;
case 2:
address |= n << 9;
break;
case 3:
address |= (n & 0xF) << 20 | (n >> 4) << 8;
break;
case 4:
data |= (n & 1) << 12;
address |= (n >> 1) << 16;
break;
case 5:
data |= (n & 1) << 15 | (n >> 1) << 8;
break;
case 6:
data |= (n >> 3) << 13;
address |= (n & 7) << 5;
break;
case 7:
address |= n;
break;
}
}
/* code length */
len = 9;
}
/* 8-bit Game Genie code (DDA-AAA-XXX) */
else if ((strlen(string) >= 11) && (string[3] == '-') && (string[7] == '-'))
{
/* 8-bit system only */
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
{
return 0;
}
/* decode 8-bit data */
for (i=0; i<2; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
data |= (n << ((1 - i) * 4));
}
/* decode 16-bit address (low 12-bits) */
for (i=0; i<3; i++)
{
if (i==1) string++; /* skip separator */
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
address |= (n << ((2 - i) * 4));
}
/* decode 16-bit address (high 4-bits) */
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
n ^= 0xF; /* bits inversion */
address |= (n << 12);
/* RAM address are also supported */
if (address >= 0xC000)
{
/* convert to 24-bit Work RAM address */
address = 0xFF0000 | (address & 0x1FFF);
}
/* decode reference 8-bit data */
for (i=0; i<2; i++)
{
string++; /* skip separator and 2nd digit */
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
ref |= (n << ((1 - i) * 4));
}
ref = (ref >> 2) | ((ref & 0x03) << 6); /* 2-bit right rotation */
ref ^= 0xBA; /* XOR */
/* update old data value */
cheatlist[index].old = ref;
/* code length */
len = 11;
}
/* Action Replay code */
else if (string[6] == ':')
{
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
{
/* 16-bit code (AAAAAA:DDDD) */
if (strlen(string) < 11) return 0;
/* decode 24-bit address */
for (i=0; i<6; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
address |= (n << ((5 - i) * 4));
}
/* decode 16-bit data */
string++;
for (i=0; i<4; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
data |= (n << ((3 - i) * 4));
}
/* code length */
len = 11;
}
else
{
/* 8-bit code (xxAAAA:DD) */
if (strlen(string) < 9) return 0;
/* decode 16-bit address */
string+=2;
for (i=0; i<4; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
address |= (n << ((3 - i) * 4));
}
/* ROM addresses are not supported */
if (address < 0xC000) return 0;
/* convert to 24-bit Work RAM address */
address = 0xFF0000 | (address & 0x1FFF);
/* decode 8-bit data */
string++;
for (i=0; i<2; i++)
{
p = strchr (arvalidchars, *string++);
if (p == NULL) return 0;
n = (p - arvalidchars) & 0xF;
data |= (n << ((1 - i) * 4));
}
/* code length */
len = 9;
}
}
/* Valid code found ? */
if (len)
{
/* update cheat address & data values */
cheatlist[index].address = address;
cheatlist[index].data = data;
cheatlist[index].enable = 1; // Enable the cheat by default
}
/* return code length (0 = invalid) */
return len;
}
static void apply_cheats(void)
{
uint8_t *ptr;
/* clear ROM&RAM patches counter */
maxROMcheats = maxRAMcheats = 0;
int i;
for (i = 0; i < maxcheats; i++)
{
if (cheatlist[i].enable)
{
if (cheatlist[i].address < cart.romsize)
{
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
{
/* patch ROM data */
cheatlist[i].old = *(uint16_t *)(cart.rom + (cheatlist[i].address & 0xFFFFFE));
*(uint16_t *)(cart.rom + (cheatlist[i].address & 0xFFFFFE)) = cheatlist[i].data;
}
else
{
/* add ROM patch */
maxROMcheats++;
cheatIndexes[MAX_CHEATS - maxROMcheats] = i;
/* get current banked ROM address */
ptr = &z80_readmap[(cheatlist[i].address) >> 10][cheatlist[i].address & 0x03FF];
/* check if reference matches original ROM data */
if (((uint8_t)cheatlist[i].old) == *ptr)
{
/* patch data */
*ptr = cheatlist[i].data;
/* save patched ROM address */
cheatlist[i].prev = ptr;
}
else
{
/* no patched ROM address yet */
cheatlist[i].prev = NULL;
}
}
}
else if (cheatlist[i].address >= 0xFF0000)
{
/* add RAM patch */
cheatIndexes[maxRAMcheats++] = i;
}
}
}
}
static void clear_cheats(void)
{
int i = maxcheats;
/* disable cheats in reversed order in case the same address is used by multiple patches */
while (i > 0)
{
if (cheatlist[i-1].enable)
{
if (cheatlist[i-1].address < cart.romsize)
{
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
{
/* restore original ROM data */
*(uint16_t *)(cart.rom + (cheatlist[i-1].address & 0xFFFFFE)) = cheatlist[i-1].old;
}
else
{
/* check if previous banked ROM address has been patched */
if (cheatlist[i-1].prev != NULL)
{
/* restore original data */
*cheatlist[i-1].prev = cheatlist[i-1].old;
/* no more patched ROM address */
cheatlist[i-1].prev = NULL;
}
}
}
}
i--;
}
}
static void remove_cheats(void)
{
int i = maxcheats;
while (i > 0)
{
if (cheatlist[i-1].enable)
{
cheatlist[i-1].text[0] = 0;
cheatlist[i-1].code[0] = 0;
cheatlist[i-1].address = 0;
cheatlist[i-1].data = 0;
cheatlist[i-1].enable = 0;
maxcheats--;
}
i--;
}
}
/****************************************************************************
* RAMCheatUpdate
*
* Apply RAM patches (this should be called once per frame)
*
****************************************************************************/
void RAMCheatUpdate(void)
{
int index, cnt = maxRAMcheats;
while (cnt)
{
/* get cheat index */
index = cheatIndexes[--cnt];
/* apply RAM patch */
//if (cheatlist[index].data & 0xFF00)
if (cheatlist[index].data & 0x00FF) // For LSB?
{
/* word patch */
*(uint16_t *)(work_ram + (cheatlist[index].address & 0xFFFE)) = cheatlist[index].data;
}
else
{
/* byte patch */
work_ram[cheatlist[index].address & 0xFFFF] = cheatlist[index].data;
}
}
}
/************************************ /************************************
* libretro implementation * libretro implementation
************************************/ ************************************/
@ -948,20 +1288,20 @@ unsigned retro_api_version(void) { return RETRO_API_VERSION; }
void retro_set_environment(retro_environment_t cb) void retro_set_environment(retro_environment_t cb)
{ {
static const struct retro_variable vars[] = { static const struct retro_variable vars[] = {
{ "system_hw", "System hardware; auto|sg-1000|sg-1000 II|mark-III|master system|master system II|game gear|mega drive / genesis" }, { "genesis_plus_gx_system_hw", "System hardware; auto|sg-1000|sg-1000 II|mark-III|master system|master system II|game gear|mega drive / genesis" },
{ "region_detect", "System region; auto|ntsc-u|pal|ntsc-j" }, { "genesis_plus_gx_region_detect", "System region; auto|ntsc-u|pal|ntsc-j" },
{ "force_dtack", "System lockups; enabled|disabled" }, { "genesis_plus_gx_force_dtack", "System lockups; enabled|disabled" },
{ "addr_error", "68k address error; enabled|disabled" }, { "genesis_plus_gx_addr_error", "68k address error; enabled|disabled" },
{ "lock_on", "Cartridge lock-on; disabled|game genie|action replay (pro)|sonic & knuckles" }, { "genesis_plus_gx_lock_on", "Cartridge lock-on; disabled|game genie|action replay (pro)|sonic & knuckles" },
{ "ym2413", "Master System FM; auto|disabled|enabled" }, { "genesis_plus_gx_ym2413", "Master System FM; auto|disabled|enabled" },
{ "dac_bits", "YM2612 DAC quantization; disabled|enabled" }, { "genesis_plus_gx_dac_bits", "YM2612 DAC quantization; disabled|enabled" },
{ "blargg_ntsc_filter", "Blargg NTSC filter; disabled|monochrome|composite|svideo|rgb" }, { "genesis_plus_gx_blargg_ntsc_filter", "Blargg NTSC filter; disabled|monochrome|composite|svideo|rgb" },
{ "lcd_filter", "LCD Ghosting filter; disabled|enabled" }, { "genesis_plus_gx_lcd_filter", "LCD Ghosting filter; disabled|enabled" },
{ "overscan", "Borders; disabled|top/bottom|left/right|full" }, { "genesis_plus_gx_overscan", "Borders; disabled|top/bottom|left/right|full" },
{ "gg_extra", "Game Gear extended screen; disabled|enabled" }, { "genesis_plus_gx_gg_extra", "Game Gear extended screen; disabled|enabled" },
{ "render", "Interlaced mode 2 output; single field|double field" }, { "genesis_plus_gx_render", "Interlaced mode 2 output; single field|double field" },
{ "gun_cursor", "Show Lightgun crosshair; no|yes" }, { "genesis_plus_gx_gun_cursor", "Show Lightgun crosshair; no|yes" },
{ "invert_mouse", "Invert Mouse Y-axis; no|yes" }, { "genesis_plus_gx_invert_mouse", "Invert Mouse Y-axis; no|yes" },
{ NULL, NULL }, { NULL, NULL },
}; };
@ -1172,12 +1512,24 @@ bool retro_unserialize(const void *data, size_t size)
return TRUE; return TRUE;
} }
void retro_cheat_reset(void) {} void retro_cheat_reset(void)
{
/* clear existing ROM patches */
clear_cheats();
/* remove cheats from the list */
remove_cheats();
}
void retro_cheat_set(unsigned index, bool enabled, const char *code) void retro_cheat_set(unsigned index, bool enabled, const char *code)
{ {
(void)index; /* clear existing ROM patches */
(void)enabled; clear_cheats();
(void)code; /* interpret code and give it an index */
decode_cheat((char *)code, maxcheats);
/* increment cheat count */
maxcheats++;
/* apply ROM patches */
apply_cheats();
} }
bool retro_load_game(const struct retro_game_info *info) bool retro_load_game(const struct retro_game_info *info)
@ -1190,6 +1542,116 @@ bool retro_load_game(const struct retro_game_info *info)
char slash = '/'; char slash = '/';
#endif #endif
struct retro_input_descriptor desc[] = {
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" },
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" },
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" },
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" },
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" },
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" },
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" },
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
{ 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
{ 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
{ 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
{ 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
{ 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" },
{ 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" },
{ 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" },
{ 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" },
{ 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" },
{ 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" },
{ 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" },
{ 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
{ 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
{ 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
{ 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
{ 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
{ 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" },
{ 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" },
{ 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" },
{ 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" },
{ 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" },
{ 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" },
{ 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" },
{ 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
{ 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
{ 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
{ 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
{ 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
{ 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" },
{ 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" },
{ 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" },
{ 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" },
{ 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" },
{ 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" },
{ 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" },
{ 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
{ 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
{ 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
{ 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
{ 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
{ 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" },
{ 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" },
{ 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" },
{ 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" },
{ 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" },
{ 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" },
{ 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" },
{ 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
{ 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
{ 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
{ 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
{ 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
{ 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" },
{ 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" },
{ 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" },
{ 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" },
{ 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" },
{ 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" },
{ 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" },
{ 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
{ 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
{ 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
{ 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
{ 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
{ 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" },
{ 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" },
{ 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" },
{ 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" },
{ 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" },
{ 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" },
{ 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Mode" },
{ 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" },
{ 0 },
};
environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);
extract_directory(g_rom_dir, info->path, sizeof(g_rom_dir)); extract_directory(g_rom_dir, info->path, sizeof(g_rom_dir));
if (!environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) || !dir) if (!environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) || !dir)