diff options
| -rw-r--r-- | .gitignore | 6 | ||||
| -rw-r--r-- | Makefile | 53 | ||||
| -rw-r--r-- | core.c | 4 | ||||
| -rw-r--r-- | menu.c | 21 | ||||
| -rw-r--r-- | options.c | 75 | ||||
| -rw-r--r-- | options.h | 3 | ||||
| -rw-r--r-- | patches/fbalpha2012/0001-trimui-build.patch | 48 | ||||
| -rw-r--r-- | patches/fbalpha2012/1000-update-libretro-h.patch | 854 | ||||
| -rw-r--r-- | patches/fbalpha2012/1001-add-auto-frameskip.patch | 297 | ||||
| -rw-r--r-- | patches/gambatte/0001-trimui-build.patch | 50 | ||||
| -rw-r--r-- | patches/mame2000/0001-trimui-build.patch | 51 | ||||
| -rw-r--r-- | patches/mame2000/1000-update-libretro-h.patch | 863 | ||||
| -rw-r--r-- | patches/mame2000/1001-add-frameskip.patch | 276 | ||||
| -rw-r--r-- | patches/mame2000/1002-add-sound-options.patch | 72 | ||||
| -rw-r--r-- | patches/mame2000/1003-shorten-options.patch | 23 | ||||
| -rw-r--r-- | patches/mame2003_plus/0001-trimui-build.patch | 48 | ||||
| -rw-r--r-- | patches/snes9x2002/0001-trimui-support.patch | 2 | ||||
| -rw-r--r-- | scale.c | 18 | 
18 files changed, 2720 insertions, 44 deletions
@@ -4,6 +4,10 @@  /profile  picoarch +/fbalpha2012 +/gambatte  /gpsp +/mame2000 +/mame2003_plus  /snes9x2002 -/snes9x2005
\ No newline at end of file +/snes9x2005 @@ -4,6 +4,8 @@ platform   ?= unix  CC        = $(CROSS_COMPILE)gcc  SYSROOT   = $(shell $(CC) --print-sysroot) +PROCS     = -j4 +  OBJS      = libpicofe/input.o libpicofe/in_sdl.o libpicofe/linux/in_evdev.o libpicofe/linux/plat.o libpicofe/fonts.o libpicofe/readpng.o libpicofe/config_file.o config.o core.o menu.o main.o options.o scale.o unzip.o  BIN       = picoarch @@ -14,7 +16,19 @@ CFLAGS     += -I./ $(shell $(SYSROOT)/usr/bin/sdl-config --cflags)  LDFLAGS    = -lc -ldl -lgcc -lm -lSDL -lasound -lpng -lz -Wl,--gc-sections -flto -CORES      = gpsp snes9x2002 snes9x2005 +# Unpolished or slow cores that build +# EXTRA_CORES += fbalpha2012 +# EXTRA_CORES += gambatte +# EXTRA_CORES += mame2003_plus + +CORES     = gpsp mame2000 snes9x2002 snes9x2005 $(EXTRA_CORES) + +gambatte_REPO = https://github.com/libretro/gambatte-libretro +mame2000_REPO = https://github.com/libretro/mame2000-libretro +mame2003_plus_REPO = https://github.com/libretro/mame2003-plus-libretro + +fbalpha2012_BUILD_PATH = fbalpha2012/svn-current/trunk +fbalpha2012_MAKEFILE = makefile.libretro  ifeq ($(platform), trimui)  	OBJS += plat_trimui.o @@ -59,6 +73,9 @@ endif  SOFILES = $(foreach core,$(CORES),$(core)_libretro.so) +print-%: +	@echo '$*=$($*)' +  all: $(BIN) cores  plat_trimui.o: plat_sdl.c @@ -71,6 +88,8 @@ define CORE_template =  $1_REPO ?= https://github.com/libretro/$(1)/ +$1_BUILD_PATH ?= $(1) +  $1_MAKE = make $(and $($1_MAKEFILE),-f $($1_MAKEFILE)) platform=$(platform) $(and $(DEBUG),DEBUG=$(DEBUG)) $(and $(PROFILE),PROFILE=$(PROFILE)) $($(1)_FLAGS)  $(1): @@ -79,11 +98,11 @@ $(1):  	(test ! -d patches/$(1)) || (cd $(1) && $(foreach patch, $(sort $(wildcard patches/$(1)/*.patch)), patch -p1 < ../$(patch) &&) true)  $(1)_libretro.so: $(1) -	cd $(1) && $$($1_MAKE) -	cp $(1)/$(1)_libretro.so . +	cd $$($1_BUILD_PATH) && $$($1_MAKE) $(PROCS) +	cp $$($1_BUILD_PATH)/$(1)_libretro.so .  clean-$(1): -	test ! -d $(1) || cd $(1) && $$($1_MAKE) clean +	test ! -d $(1) || cd $$($1_BUILD_PATH) && $$($1_MAKE) clean  	rm -f $(1)_libretro.so  endef @@ -102,6 +121,15 @@ force-clean: clean  ifeq ($(platform), trimui) +fbalpha2012_NAME = fba2012 +fbalpha2012_ROM_DIR = ARCADE +fbalpha2012_TYPES = zip +fbalpha2012_PAK_NAME = Arcade (FBA) + +gambatte_ROM_DIR = GB +gambatte_TYPES = gb,gbc,dmg,zip +gambatte_PAK_NAME = Game Boy +  gpsp_ROM_DIR = GBA  gpsp_TYPES = gba,bin,zip  gpsp_PAK_NAME = Game Boy Advance @@ -111,12 +139,21 @@ needs-swap  endef +mame2000_ROM_DIR = ARCADE +mame2000_TYPES = zip +mame2000_PAK_NAME = Arcade + +mame2003_plus_NAME = mame2003+ +mame2003_plus_ROM_DIR = ARCADE +mame2003_plus_TYPES = zip +mame2003_plus_PAK_NAME = Arcade (MAME 2003-plus) +  snes9x2002_ROM_DIR = SFC -snes9x2002_TYPES = smc,fig,sfc,gd3,gd7,dx2,bsx,swc +snes9x2002_TYPES = smc,fig,sfc,gd3,gd7,dx2,bsx,swc,zip  snes9x2002_PAK_NAME = Super Nintendo  snes9x2005_ROM_DIR = SFC -snes9x2005_TYPES = smc,fig,sfc,gd3,gd7,dx2,bsx,swc +snes9x2005_TYPES = smc,fig,sfc,gd3,gd7,dx2,bsx,swc,zip  snes9x2005_PAK_NAME = Super Nintendo (2005)  # -- gmenunx @@ -128,8 +165,10 @@ dist-gmenu-section:  define CORE_gmenushortcut = +$1_NAME ?= $1 +  define $1_SHORTCUT -title=$1 +title=$$($1_NAME)  exec=/mnt/SDCARD/Apps/picoarch/picoarch  params=/mnt/SDCARD/Apps/picoarch/$1_libretro.so  selectordir=/mnt/SDCARD/Roms/$($1_ROM_DIR) @@ -547,14 +547,12 @@ int core_load_content(const char *path) {  	PA_INFO("Screen: %dx%d\n", av_info.geometry.base_width, av_info.geometry.base_height);  	PA_INFO("Audio sample rate: %f\n", av_info.timing.sample_rate);  	PA_INFO("Frame rate: %f\n", av_info.timing.fps); +	PA_INFO("Reported aspect ratio: %f\n", av_info.geometry.aspect_ratio);  	sample_rate = av_info.timing.sample_rate;  	frame_rate = av_info.timing.fps;  	aspect_ratio = av_info.geometry.aspect_ratio; -	if (!aspect_ratio) -		aspect_ratio = (float)av_info.geometry.base_width / (float)av_info.geometry.base_height; -  #ifdef MMENU  	gamepak_related_name(save_template_path, MAX_PATH, ".st%i");  #endif @@ -81,6 +81,24 @@ me_bind_action snes_ctrl_actions[] =  	{ NULL,       0 }  }; +me_bind_action mame_ctrl_actions[] = +{ +	{ "UP       ",  1 << RETRO_DEVICE_ID_JOYPAD_UP}, +	{ "DOWN     ",  1 << RETRO_DEVICE_ID_JOYPAD_DOWN }, +	{ "LEFT     ",  1 << RETRO_DEVICE_ID_JOYPAD_LEFT }, +	{ "RIGHT    ",  1 << RETRO_DEVICE_ID_JOYPAD_RIGHT }, +	{ "BUTTON 1 ",  1 << RETRO_DEVICE_ID_JOYPAD_B }, +	{ "BUTTON 2 ",  1 << RETRO_DEVICE_ID_JOYPAD_A }, +	{ "BUTTON 3 ",  1 << RETRO_DEVICE_ID_JOYPAD_Y }, +	{ "BUTTON 4 ",  1 << RETRO_DEVICE_ID_JOYPAD_X }, +	{ "BUTTON 5 ",  1 << RETRO_DEVICE_ID_JOYPAD_L }, +	{ "BUTTON 6 ",  1 << RETRO_DEVICE_ID_JOYPAD_R }, +	{ "START    ",  1 << RETRO_DEVICE_ID_JOYPAD_START }, +	{ "COIN     ",  1 << RETRO_DEVICE_ID_JOYPAD_SELECT }, +	{ "OSD MENU ",  1 << RETRO_DEVICE_ID_JOYPAD_R2 }, +	{ NULL,       0 } +}; +  /* Must be a superset of all possible actions. This is used when   * saving config, and if an entry isn't here, the saver won't see   * it. */ @@ -273,6 +291,9 @@ static int key_config_loop_wrap(int id, int keys)  	} else if (strstr(core_name, "snes")) {  		actions = snes_ctrl_actions;  		action_size = array_size(snes_ctrl_actions); +	} else if (strstr(core_name, "mame")) { +		actions = mame_ctrl_actions; +		action_size = array_size(mame_ctrl_actions);  	}  	switch (id) { @@ -62,6 +62,14 @@ static int options_default_override(const char *key) {  		return 1;  	} else if (!strcmp(key, "snes9x2002_frameskip_interval")) {  		return 3; +	} else if (!strcmp(key, "mame2000-frameskip")) { +		return 1; +	} else if (!strcmp(key, "mame2000-frameskip_interval")) { +		return 1; +	} else if (!strcmp(key, "mame2000-skip_disclaimer")) { +		return 1; +	} else if (!strcmp(key, "mame2000-sample_rate")) { +		return 1;  	}  	return -1; @@ -85,16 +93,26 @@ void options_init(const struct retro_core_option_definition *defs) {  	for (i = 0; i < core_options.len; i++) {  		int j, len; +		const struct retro_core_option_definition *def = &core_options.defs[i];  		struct core_option_entry *entry = &core_options.entries[i]; -		entry->def = &core_options.defs[i]; -		entry->value = options_default_index(entry->def->key); +		len = strlen(def->key) + 1; +		entry->key = (char *)calloc(len, sizeof(char)); +		if (!entry->key) { +			PA_ERROR("Error allocating option entries\n"); +			options_free(); +			return; +		} +		strncpy(entry->key, def->key, len); + +		entry->def = def; +		entry->value = options_default_index(def->key);  		entry->prev_value = entry->value; -		entry->blocked = option_blocked(entry->def->key); +		entry->blocked = option_blocked(def->key);  		if (entry->blocked)  			core_options.visible_len--; -		len = strlen(entry->def->desc) + 1; +		len = strlen(def->desc) + 1;  		entry->desc = (char *)calloc(len, sizeof(char));  		if (!entry->desc) {  			PA_ERROR("Error allocating option entries\n"); @@ -102,22 +120,22 @@ void options_init(const struct retro_core_option_definition *defs) {  			return;  		} -		strncpy(entry->desc, entry->def->desc, len); +		strncpy(entry->desc, def->desc, len);  		truncate(entry->desc, MAX_DESC_LEN); -		if (entry->def->info) { -			len = strlen(entry->def->info) + 1; +		if (def->info) { +			len = strlen(def->info) + 1;  			entry->info = (char *)calloc(len, sizeof(char));  			if (!entry->info) {  				PA_ERROR("Error allocating description string\n");  				options_free();  				return;  			} -			strncpy(entry->info, entry->def->info, len); +			strncpy(entry->info, def->info, len);  			wrap(entry->info, MAX_LINE_LEN, MAX_LINES);  		} -		for (j = 0; entry->def->values[j].value; j++) +		for (j = 0; def->values[j].value; j++)  			;  		j++; /* Make room for NULL entry */ @@ -129,10 +147,10 @@ void options_init(const struct retro_core_option_definition *defs) {  		} -		for (j = 0; entry->def->values[j].value; j++) { -			const char *label = entry->def->values[j].label; +		for (j = 0; def->values[j].value; j++) { +			const char *label = def->values[j].label;  			if (!label) { -				label = entry->def->values[j].value; +				label = def->values[j].value;  			}  			entry->options[j] = label;  		} @@ -146,7 +164,6 @@ void options_init_variables(const struct retro_variable *vars) {  		;  	core_options.visible_len = core_options.len = i; -	core_options.vars = vars;  	core_options.entries = (struct core_option_entry *)calloc(core_options.len, sizeof(struct core_option_entry));  	if (!core_options.entries) { @@ -159,18 +176,27 @@ void options_init_variables(const struct retro_variable *vars) {  		int j = 0;  		int len;  		struct core_option_entry *entry = &core_options.entries[i]; +		const struct retro_variable *var = &vars[i];  		char *p;  		char *opt_ptr;  		char *value; -		entry->var = &core_options.vars[i]; -		entry->value = options_default_index(entry->var->key); +		len = strlen(var->key) + 1; +		entry->key = (char *)calloc(len, sizeof(char)); +		if (!entry->key) { +			PA_ERROR("Error allocating option entries\n"); +			options_free(); +			return; +		} +		strncpy(entry->key, var->key, len); + +		entry->value = options_default_index(var->key);  		entry->prev_value = entry->value; -		entry->blocked = option_blocked(entry->var->key); +		entry->blocked = option_blocked(var->key);  		if (entry->blocked)  			core_options.visible_len--; -		len = strlen(entry->var->value) + 1; +		len = strlen(var->value) + 1;  		value = (char *)calloc(len, sizeof(char));  		if (!value) {  			PA_ERROR("Error allocating option entries\n"); @@ -180,7 +206,7 @@ void options_init_variables(const struct retro_variable *vars) {  		entry->retro_var_value = value; -		strncpy(value, entry->var->value, len); +		strncpy(value, var->value, len);  		p = strchr(value, ';');  		if (p && *(p + 1) == ' ') { @@ -236,18 +262,12 @@ void options_update_changed(void) {  }  const char* options_get_key(int index) { -	if (core_options.defs) { -		return core_options.defs[index].key; -	} else { -		return core_options.vars[index].key; -	} +	return core_options.entries[index].key;  }  struct core_option_entry* options_get_entry(const char* key) {  	for(size_t i = 0; i < core_options.len; i++) { -		const char *opt_key = core_options.defs ? -			core_options.defs[i].key : -			core_options.vars[i].key; +		const char *opt_key = options_get_key(i);  		if (!strcmp(opt_key, key)) {  			return &core_options.entries[i]; @@ -366,6 +386,9 @@ void options_free(void) {  			} else if (entry->desc) {  				free(entry->desc);  			} +			if (entry->key) { +				free(entry->key); +			}  		}  		free(core_options.entries);  	} @@ -11,6 +11,7 @@ extern enum scale_size scale_size;  extern enum scale_filter scale_filter;  struct core_option_entry { +	char *key;  	int value;  	int prev_value;  	char *desc; @@ -19,7 +20,6 @@ struct core_option_entry {  	char *info;  	const char **options;  	const struct retro_core_option_definition *def; -	const struct retro_variable *var;  };  struct core_options { @@ -28,7 +28,6 @@ struct core_options {  	bool changed;  	struct core_option_entry *entries;  	const struct retro_core_option_definition *defs; -	const struct retro_variable *vars;  };  extern struct core_options core_options; diff --git a/patches/fbalpha2012/0001-trimui-build.patch b/patches/fbalpha2012/0001-trimui-build.patch new file mode 100644 index 0000000..d1710ab --- /dev/null +++ b/patches/fbalpha2012/0001-trimui-build.patch @@ -0,0 +1,48 @@ +diff --git a/svn-current/trunk/makefile.libretro b/svn-current/trunk/makefile.libretro +index 3cff287..f619a20 100644 +--- a/svn-current/trunk/makefile.libretro ++++ b/svn-current/trunk/makefile.libretro +@@ -334,6 +334,21 @@ else ifeq ($(platform), gcw0) +    CFLAGS += -ffast-math -march=mips32 -mtune=mips32r2 -mhard-float +    CXXFLAGS += -std=gnu++11 -ffast-math -march=mips32 -mtune=mips32r2 -mhard-float +  ++# Trimui ++else ifeq ($(platform), trimui) ++	TARGET := $(TARGET_NAME)_libretro.so ++	CC = $(CROSS_COMPILE)gcc ++	CXX = $(CROSS_COMPILE)g++ ++	AR = $(CROSS_COMPILE)ar ++	SHARED := -shared -Wl,-no-undefined -Wl,--version-script=$(LIBRETRO_DIR)/link.T ++	LDFLAGS += -fno-PIC -flto ++	CFLAGS += -fomit-frame-pointer -ffast-math -mcpu=arm926ej-s -mtune=arm926ej-s -fno-PIC -flto ++	CXXFLAGS += -fomit-frame-pointer -ffast-math -mcpu=arm926ej-s -mtune=arm926ej-s -fno-PIC -flto -DUSE_CYCLONE ++	OPTIMIZE := -Ofast -DNDEBUG ++	ifeq (,$(DEBUG)) ++		LDFLAGS += -s ++	endif ++ + # Windows MSVC 2003 Xbox 1 + else ifeq ($(platform), xbox1_msvc2003) + TARGET := $(TARGET_NAME)_libretro_xdk1.lib +@@ -700,11 +715,21 @@ endif + ifeq ($(DEBUG), 1) +    CFLAGS += -O0 -g +    CXXFLAGS += -O0 -g ++else ifneq (,$(OPTIMIZE)) ++	CFLAGS += $(OPTIMIZE) ++	CXXFLAGS += $(OPTIMIZE) + else +    CFLAGS += -O2 -DNDEBUG +    CXXFLAGS += -O2 -DNDEBUG + endif +  ++ifeq ($(PROFILE), GENERATE) ++	CFLAGS	+= -fprofile-generate=./profile/fbalpha2012 ++	LDFLAGS	+= -lgcov ++else ifeq ($(PROFILE), APPLY) ++	CFLAGS	+= -fprofile-use -fprofile-dir=../profile/fbalpha2012 -fbranch-probabilities ++endif ++ + ifeq ($(platform), sncps3) +    WARNINGS_DEFINES = + else ifneq (,$(findstring msvc,$(platform))) diff --git a/patches/fbalpha2012/1000-update-libretro-h.patch b/patches/fbalpha2012/1000-update-libretro-h.patch new file mode 100644 index 0000000..03c35d2 --- /dev/null +++ b/patches/fbalpha2012/1000-update-libretro-h.patch @@ -0,0 +1,854 @@ +diff --git a/svn-current/trunk/src/burner/libretro/libretro.h b/svn-current/trunk/src/burner/libretro/libretro.h +index 0c71f8d..32aa15f 100755 +--- a/svn-current/trunk/src/burner/libretro/libretro.h ++++ b/svn-current/trunk/src/burner/libretro/libretro.h +@@ -1,4 +1,4 @@ +-/* 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,11 @@ 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_FINNISH             = 23, +    RETRO_LANGUAGE_LAST, +  +    /* Ensure sizeof(enum) == sizeof(int) */ +@@ -708,6 +713,9 @@ enum retro_mod +                                             * state of rumble motors in controllers. +                                             * A strong and weak motor is supported, and they can be +                                             * controlled indepedently. ++                                            * Should be called from either retro_init() or retro_load_game(). ++                                            * Should not be called from retro_set_environment(). ++                                            * Returns false if rumble functionality is unavailable. +                                             */ + #define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 +                                            /* uint64_t * -- +@@ -1087,10 +1095,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 +1106,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 +1125,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 +1140,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 +1177,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 +1202,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 +1263,236 @@ 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. ++                                            */ ++ ++#define RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK 62 ++                                           /* const struct retro_audio_buffer_status_callback * -- ++                                            * Lets the core know the occupancy level of the frontend ++                                            * audio buffer. Can be used by a core to attempt frame ++                                            * skipping in order to avoid buffer under-runs. ++                                            * A core may pass NULL to disable buffer status reporting ++                                            * in the frontend. ++                                            */ ++ ++#define RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY 63 ++                                           /* const unsigned * -- ++                                            * Sets minimum frontend audio latency in milliseconds. ++                                            * Resultant audio latency may be larger than set value, ++                                            * or smaller if a hardware limit is encountered. A frontend ++                                            * is expected to honour requests up to 512 ms. ++                                            * ++                                            * - If value is less than current frontend ++                                            *   audio latency, callback has no effect ++                                            * - If value is zero, default frontend audio ++                                            *   latency is set ++                                            * ++                                            * May be used by a core to increase audio latency and ++                                            * therefore decrease the probability of buffer under-runs ++                                            * (crackling) when performing 'intensive' operations. ++                                            * A core utilising RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK ++                                            * to implement audio-buffer-based frame skipping may achieve ++                                            * optimal results by setting the audio latency to a 'high' ++                                            * (typically 6x or 8x) integer multiple of the expected ++                                            * frame time. ++                                            * ++                                            * WARNING: This can only be called from within retro_run(). ++                                            * Calling this can require a full reinitialization of audio ++                                            * drivers in the frontend, so it is important to call it very ++                                            * sparingly, and usually only with the users explicit consent. ++                                            * An eventual driver reinitialize will happen so that audio ++                                            * callbacks happening after this call within the same retro_run() ++                                            * call will target the newly initialized driver. ++                                            */ ++ ++#define RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE 64 ++                                           /* const struct retro_fastforwarding_override * -- ++                                            * Used by a libretro core to override the current ++                                            * fastforwarding mode of the frontend. ++                                            * If NULL is passed to this function, the frontend ++                                            * will return true if fastforwarding override ++                                            * functionality is supported (no change in ++                                            * fastforwarding state will occur in this case). ++                                            */ ++ ++#define RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE 65 ++                                           /* const struct retro_system_content_info_override * -- ++                                            * Allows an implementation to override 'global' content ++                                            * info parameters reported by retro_get_system_info(). ++                                            * Overrides also affect subsystem content info parameters ++                                            * set via RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO. ++                                            * This function must be called inside retro_set_environment(). ++                                            * If callback returns false, content info overrides ++                                            * are unsupported by the frontend, and will be ignored. ++                                            * If callback returns true, extended game info may be ++                                            * retrieved by calling RETRO_ENVIRONMENT_GET_GAME_INFO_EXT ++                                            * in retro_load_game() or retro_load_game_special(). ++                                            * ++                                            * 'data' points to an array of retro_system_content_info_override ++                                            * structs terminated by a { NULL, false, false } element. ++                                            * If 'data' is NULL, no changes will be made to the frontend; ++                                            * a core may therefore pass NULL in order to test whether ++                                            * the RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE and ++                                            * RETRO_ENVIRONMENT_GET_GAME_INFO_EXT callbacks are supported ++                                            * by the frontend. ++                                            * ++                                            * For struct member descriptions, see the definition of ++                                            * struct retro_system_content_info_override. ++                                            * ++                                            * Example: ++                                            * ++                                            * - struct retro_system_info: ++                                            * { ++                                            *    "My Core",                      // library_name ++                                            *    "v1.0",                         // library_version ++                                            *    "m3u|md|cue|iso|chd|sms|gg|sg", // valid_extensions ++                                            *    true,                           // need_fullpath ++                                            *    false                           // block_extract ++                                            * } ++                                            * ++                                            * - Array of struct retro_system_content_info_override: ++                                            * { ++                                            *    { ++                                            *       "md|sms|gg", // extensions ++                                            *       false,       // need_fullpath ++                                            *       true         // persistent_data ++                                            *    }, ++                                            *    { ++                                            *       "sg",        // extensions ++                                            *       false,       // need_fullpath ++                                            *       false        // persistent_data ++                                            *    }, ++                                            *    { NULL, false, false } ++                                            * } ++                                            * ++                                            * Result: ++                                            * - Files of type m3u, cue, iso, chd will not be ++                                            *   loaded by the frontend. Frontend will pass a ++                                            *   valid path to the core, and core will handle ++                                            *   loading internally ++                                            * - Files of type md, sms, gg will be loaded by ++                                            *   the frontend. A valid memory buffer will be ++                                            *   passed to the core. This memory buffer will ++                                            *   remain valid until retro_deinit() returns ++                                            * - Files of type sg will be loaded by the frontend. ++                                            *   A valid memory buffer will be passed to the core. ++                                            *   This memory buffer will remain valid until ++                                            *   retro_load_game() (or retro_load_game_special()) ++                                            *   returns ++                                            * ++                                            * NOTE: If an extension is listed multiple times in ++                                            * an array of retro_system_content_info_override ++                                            * structs, only the first instance will be registered ++                                            */ ++ ++#define RETRO_ENVIRONMENT_GET_GAME_INFO_EXT 66 ++                                           /* const struct retro_game_info_ext ** -- ++                                            * Allows an implementation to fetch extended game ++                                            * information, providing additional content path ++                                            * and memory buffer status details. ++                                            * This function may only be called inside ++                                            * retro_load_game() or retro_load_game_special(). ++                                            * If callback returns false, extended game information ++                                            * is unsupported by the frontend. In this case, only ++                                            * regular retro_game_info will be available. ++                                            * RETRO_ENVIRONMENT_GET_GAME_INFO_EXT is guaranteed ++                                            * to return true if RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE ++                                            * returns true. ++                                            * ++                                            * 'data' points to an array of retro_game_info_ext structs. ++                                            * ++                                            * For struct member descriptions, see the definition of ++                                            * struct retro_game_info_ext. ++                                            * ++                                            * - If function is called inside retro_load_game(), ++                                            *   the retro_game_info_ext array is guaranteed to ++                                            *   have a size of 1 - i.e. the returned pointer may ++                                            *   be used to access directly the members of the ++                                            *   first retro_game_info_ext struct, for example: ++                                            * ++                                            *      struct retro_game_info_ext *game_info_ext; ++                                            *      if (environ_cb(RETRO_ENVIRONMENT_GET_GAME_INFO_EXT, &game_info_ext)) ++                                            *         printf("Content Directory: %s\n", game_info_ext->dir); ++                                            * ++                                            * - If the function is called inside retro_load_game_special(), ++                                            *   the retro_game_info_ext array is guaranteed to have a ++                                            *   size equal to the num_info argument passed to ++                                            *   retro_load_game_special() ++                                            */ ++ + /* VFS functionality */ +  + /* File paths: +@@ -2147,6 +2382,30 @@ struct retro_frame_time_callback +    retro_usec_t reference; + }; +  ++/* Notifies a libretro core of the current occupancy ++ * level of the frontend audio buffer. ++ * ++ * - active: 'true' if audio buffer is currently ++ *           in use. Will be 'false' if audio is ++ *           disabled in the frontend ++ * ++ * - occupancy: Given as a value in the range [0,100], ++ *              corresponding to the occupancy percentage ++ *              of the audio buffer ++ * ++ * - underrun_likely: 'true' if the frontend expects an ++ *                    audio buffer underrun during the ++ *                    next frame (indicates that a core ++ *                    should attempt frame skipping) ++ * ++ * It will be called right before retro_run() every frame. */ ++typedef void (RETRO_CALLCONV *retro_audio_buffer_status_callback_t)( ++      bool active, unsigned occupancy, bool underrun_likely); ++struct retro_audio_buffer_status_callback ++{ ++   retro_audio_buffer_status_callback_t callback; ++}; ++ + /* Pass this to retro_video_refresh_t if rendering to hardware. +  * Passing NULL to retro_video_refresh_t is still a frame dupe as normal. +  * */ +@@ -2307,7 +2566,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 +2625,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 +2685,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 +2736,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; ++   /* Message logging level (info, warn, error, etc.) */ ++   enum retro_log_level level; ++   /* Message destination: OSD, logging interface or both */ ++   enum retro_message_target target; ++   /* Message 'type' when targeting the OSD ++    * > RETRO_MESSAGE_TYPE_NOTIFICATION: Specifies that a ++    *   message should be handled in identical fashion to ++    *   a standard frontend-generated notification ++    * > RETRO_MESSAGE_TYPE_NOTIFICATION_ALT: Specifies that ++    *   message is a notification that requires user attention ++    *   or action, but that it should be displayed in a manner ++    *   that differs from standard frontend-generated notifications. ++    *   This would typically correspond to messages that should be ++    *   displayed immediately (independently from any internal ++    *   frontend message queue), and/or which should be visually ++    *   distinguishable from frontend-generated notifications. ++    *   For example, a core may wish to inform the user of ++    *   information related to a disk-change event. It is ++    *   expected that the frontend itself may provide a ++    *   notification in this case; if the core sends a ++    *   message of type RETRO_MESSAGE_TYPE_NOTIFICATION, an ++    *   uncomfortable 'double-notification' may occur. A message ++    *   of RETRO_MESSAGE_TYPE_NOTIFICATION_ALT should therefore ++    *   be presented such that visual conflict with regular ++    *   notifications does not occur ++    * > RETRO_MESSAGE_TYPE_STATUS: Indicates that message ++    *   is not a standard notification. This typically ++    *   corresponds to 'status' indicators, such as a core's ++    *   internal FPS, which are intended to be displayed ++    *   either permanently while a core is running, or in ++    *   a manner that does not suggest user attention or action ++    *   is required. 'Status' type messages should therefore be ++    *   displayed in a different on-screen location and in a manner ++    *   easily distinguishable from both standard frontend-generated ++    *   notifications and messages of type RETRO_MESSAGE_TYPE_NOTIFICATION_ALT ++    * > RETRO_MESSAGE_TYPE_PROGRESS: Indicates that message reports ++    *   the progress of an internal core task. For example, in cases ++    *   where a core itself handles the loading of content from a file, ++    *   this may correspond to the percentage of the file that has been ++    *   read. Alternatively, an audio/video playback core may use a ++    *   message of type RETRO_MESSAGE_TYPE_PROGRESS to display the current ++    *   playback position as a percentage of the runtime. 'Progress' type ++    *   messages should therefore be displayed as a literal progress bar, ++    *   where: ++    *   - 'retro_message_ext.msg' is the progress bar title/label ++    *   - 'retro_message_ext.progress' determines the length of ++    *     the progress bar ++    * NOTE: Message type is a *hint*, and may be ignored ++    * by the frontend. If a frontend lacks support for ++    * displaying messages via alternate means than standard ++    * frontend-generated notifications, it will treat *all* ++    * messages as having the type RETRO_MESSAGE_TYPE_NOTIFICATION */ ++   enum retro_message_type type; ++   /* Task progress when targeting the OSD and message is ++    * of type RETRO_MESSAGE_TYPE_PROGRESS ++    * > -1:    Unmetered/indeterminate ++    * > 0-100: Current progress percentage ++    * NOTE: Since message type is a hint, a frontend may ignore ++    * progress values. Where relevant, a core should therefore ++    * include progress percentage within the message string, ++    * such that the message intent remains clear when displayed ++    * as a standard frontend-generated notification */ ++   int8_t progress; ++}; ++ + /* Describes how the libretro implementation maps a libretro input bind +  * to its internal input system through a human readable string. +  * This string can be used to better let a user configure input. */ +@@ -2428,7 +2854,7 @@ struct retro_input_descriptor + struct retro_system_info + { +    /* All pointers are owned by libretro implementation, and pointers must +-    * remain valid until retro_deinit() is called. */ ++    * remain valid until it is unloaded. */ +  +    const char *library_name;      /* Descriptive name of library. Should not +                                    * contain any version numbers, etc. */ +@@ -2470,6 +2896,213 @@ struct retro_system_info +    bool        block_extract; + }; +  ++/* Defines overrides which modify frontend handling of ++ * specific content file types. ++ * An array of retro_system_content_info_override is ++ * passed to RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE ++ * NOTE: In the following descriptions, references to ++ *       retro_load_game() may be replaced with ++ *       retro_load_game_special() */ ++struct retro_system_content_info_override ++{ ++   /* A list of file extensions for which the override ++    * should apply, delimited by a 'pipe' character ++    * (e.g. "md|sms|gg") ++    * Permitted file extensions are limited to those ++    * included in retro_system_info::valid_extensions ++    * and/or retro_subsystem_rom_info::valid_extensions */ ++   const char *extensions; ++ ++   /* Overrides the need_fullpath value set in ++    * retro_system_info and/or retro_subsystem_rom_info. ++    * To reiterate: ++    * ++    * If need_fullpath is true and retro_load_game() is called: ++    *    - retro_game_info::path is guaranteed to contain a valid ++    *      path to an existent file ++    *    - retro_game_info::data and retro_game_info::size are invalid ++    * ++    * If need_fullpath is false and retro_load_game() is called: ++    *    - retro_game_info::path may be NULL ++    *    - retro_game_info::data and retro_game_info::size are guaranteed ++    *      to be valid ++    * ++    * In addition: ++    * ++    * If need_fullpath is true and retro_load_game() is called: ++    *    - retro_game_info_ext::full_path is guaranteed to contain a valid ++    *      path to an existent file ++    *    - retro_game_info_ext::archive_path may be NULL ++    *    - retro_game_info_ext::archive_file may be NULL ++    *    - retro_game_info_ext::dir is guaranteed to contain a valid path ++    *      to the directory in which the content file exists ++    *    - retro_game_info_ext::name is guaranteed to contain the ++    *      basename of the content file, without extension ++    *    - retro_game_info_ext::ext is guaranteed to contain the ++    *      extension of the content file in lower case format ++    *    - retro_game_info_ext::data and retro_game_info_ext::size ++    *      are invalid ++    * ++    * If need_fullpath is false and retro_load_game() is called: ++    *    - If retro_game_info_ext::file_in_archive is false: ++    *       - retro_game_info_ext::full_path is guaranteed to contain ++    *         a valid path to an existent file ++    *       - retro_game_info_ext::archive_path may be NULL ++    *       - retro_game_info_ext::archive_file may be NULL ++    *       - retro_game_info_ext::dir is guaranteed to contain a ++    *         valid path to the directory in which the content file exists ++    *       - retro_game_info_ext::name is guaranteed to contain the ++    *         basename of the content file, without extension ++    *       - retro_game_info_ext::ext is guaranteed to contain the ++    *         extension of the content file in lower case format ++    *    - If retro_game_info_ext::file_in_archive is true: ++    *       - retro_game_info_ext::full_path may be NULL ++    *       - retro_game_info_ext::archive_path is guaranteed to ++    *         contain a valid path to an existent compressed file ++    *         inside which the content file is located ++    *       - retro_game_info_ext::archive_file is guaranteed to ++    *         contain a valid path to an existent content file ++    *         inside the compressed file referred to by ++    *         retro_game_info_ext::archive_path ++    *            e.g. for a compressed file '/path/to/foo.zip' ++    *            containing 'bar.sfc' ++    *             > retro_game_info_ext::archive_path will be '/path/to/foo.zip' ++    *             > retro_game_info_ext::archive_file will be 'bar.sfc' ++    *       - retro_game_info_ext::dir is guaranteed to contain a ++    *         valid path to the directory in which the compressed file ++    *         (containing the content file) exists ++    *       - retro_game_info_ext::name is guaranteed to contain ++    *         EITHER ++    *         1) the basename of the compressed file (containing ++    *            the content file), without extension ++    *         OR ++    *         2) the basename of the content file inside the ++    *            compressed file, without extension ++    *         In either case, a core should consider 'name' to ++    *         be the canonical name/ID of the the content file ++    *       - retro_game_info_ext::ext is guaranteed to contain the ++    *         extension of the content file inside the compressed file, ++    *         in lower case format ++    *    - retro_game_info_ext::data and retro_game_info_ext::size are ++    *      guaranteed to be valid */ ++   bool need_fullpath; ++ ++   /* If need_fullpath is false, specifies whether the content ++    * data buffer available in retro_load_game() is 'persistent' ++    * ++    * If persistent_data is false and retro_load_game() is called: ++    *    - retro_game_info::data and retro_game_info::size ++    *      are valid only until retro_load_game() returns ++    *    - retro_game_info_ext::data and retro_game_info_ext::size ++    *      are valid only until retro_load_game() returns ++    * ++    * If persistent_data is true and retro_load_game() is called: ++    *    - retro_game_info::data and retro_game_info::size ++    *      are valid until retro_deinit() returns ++    *    - retro_game_info_ext::data and retro_game_info_ext::size ++    *      are valid until retro_deinit() returns */ ++   bool persistent_data; ++}; ++ ++/* Similar to retro_game_info, but provides extended ++ * information about the source content file and ++ * game memory buffer status. ++ * And array of retro_game_info_ext is returned by ++ * RETRO_ENVIRONMENT_GET_GAME_INFO_EXT ++ * NOTE: In the following descriptions, references to ++ *       retro_load_game() may be replaced with ++ *       retro_load_game_special() */ ++struct retro_game_info_ext ++{ ++   /* - If file_in_archive is false, contains a valid ++    *   path to an existent content file (UTF-8 encoded) ++    * - If file_in_archive is true, may be NULL */ ++   const char *full_path; ++ ++   /* - If file_in_archive is false, may be NULL ++    * - If file_in_archive is true, contains a valid path ++    *   to an existent compressed file inside which the ++    *   content file is located (UTF-8 encoded) */ ++   const char *archive_path; ++ ++   /* - If file_in_archive is false, may be NULL ++    * - If file_in_archive is true, contain a valid path ++    *   to an existent content file inside the compressed ++    *   file referred to by archive_path (UTF-8 encoded) ++    *      e.g. for a compressed file '/path/to/foo.zip' ++    *      containing 'bar.sfc' ++    *      > archive_path will be '/path/to/foo.zip' ++    *      > archive_file will be 'bar.sfc' */ ++   const char *archive_file; ++ ++   /* - If file_in_archive is false, contains a valid path ++    *   to the directory in which the content file exists ++    *   (UTF-8 encoded) ++    * - If file_in_archive is true, contains a valid path ++    *   to the directory in which the compressed file ++    *   (containing the content file) exists (UTF-8 encoded) */ ++   const char *dir; ++ ++   /* Contains the canonical name/ID of the content file ++    * (UTF-8 encoded). Intended for use when identifying ++    * 'complementary' content named after the loaded file - ++    * i.e. companion data of a different format (a CD image ++    * required by a ROM), texture packs, internally handled ++    * save files, etc. ++    * - If file_in_archive is false, contains the basename ++    *   of the content file, without extension ++    * - If file_in_archive is true, then string is ++    *   implementation specific. A frontend may choose to ++    *   set a name value of: ++    *   EITHER ++    *   1) the basename of the compressed file (containing ++    *      the content file), without extension ++    *   OR ++    *   2) the basename of the content file inside the ++    *      compressed file, without extension ++    *   RetroArch sets the 'name' value according to (1). ++    *   A frontend that supports routine loading of ++    *   content from archives containing multiple unrelated ++    *   content files may set the 'name' value according ++    *   to (2). */ ++   const char *name; ++ ++   /* - If file_in_archive is false, contains the extension ++    *   of the content file in lower case format ++    * - If file_in_archive is true, contains the extension ++    *   of the content file inside the compressed file, ++    *   in lower case format */ ++   const char *ext; ++ ++   /* String of implementation specific meta-data. */ ++   const char *meta; ++ ++   /* Memory buffer of loaded game content. Will be NULL: ++    * IF ++    * - retro_system_info::need_fullpath is true and ++    *   retro_system_content_info_override::need_fullpath ++    *   is unset ++    * OR ++    * - retro_system_content_info_override::need_fullpath ++    *   is true */ ++   const void *data; ++ ++   /* Size of game content memory buffer, in bytes */ ++   size_t size; ++ ++   /* True if loaded content file is inside a compressed ++    * archive */ ++   bool file_in_archive; ++ ++   /* - If data is NULL, value is unset/ignored ++    * - If data is non-NULL: ++    *   - If persistent_data is false, data and size are ++    *     valid only until retro_load_game() returns ++    *   - If persistent_data is true, data and size are ++    *     are valid until retro_deinit() returns */ ++   bool persistent_data; ++}; ++ + struct retro_game_geometry + { +    unsigned base_width;    /* Nominal video width of game. */ +@@ -2522,8 +3155,20 @@ struct retro_core_option_display + }; +  + /* Maximum number of values permitted for a core option +- * NOTE: This may be increased on a core-by-core basis +- * if required (doing so has no effect on the frontend) */ ++ * > Note: We have to set a maximum value due the limitations ++ *   of the C language - i.e. it is not possible to create an ++ *   array of structs each containing a variable sized array, ++ *   so the retro_core_option_definition values array must ++ *   have a fixed size. The size limit of 128 is a balancing ++ *   act - it needs to be large enough to support all 'sane' ++ *   core options, but setting it too large may impact low memory ++ *   platforms. In practise, if a core option has more than ++ *   128 values then the implementation is likely flawed. ++ *   To quote the above API reference: ++ *      "The number of possible options should be very limited ++ *       i.e. it should be feasible to cycle through options ++ *       without a keyboard." ++ */ + #define RETRO_NUM_CORE_OPTION_VALUES_MAX 128 +  + struct retro_core_option_value +@@ -2615,6 +3260,47 @@ struct retro_framebuffer +                                        Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ + }; +  ++/* Used by a libretro core to override the current ++ * fastforwarding mode of the frontend */ ++struct retro_fastforwarding_override ++{ ++   /* Specifies the runtime speed multiplier that ++    * will be applied when 'fastforward' is true. ++    * For example, a value of 5.0 when running 60 FPS ++    * content will cap the fast-forward rate at 300 FPS. ++    * Note that the target multiplier may not be achieved ++    * if the host hardware has insufficient processing ++    * power. ++    * Setting a value of 0.0 (or greater than 0.0 but ++    * less than 1.0) will result in an uncapped ++    * fast-forward rate (limited only by hardware ++    * capacity). ++    * If the value is negative, it will be ignored ++    * (i.e. the frontend will use a runtime speed ++    * multiplier of its own choosing) */ ++   float ratio; ++ ++   /* If true, fastforwarding mode will be enabled. ++    * If false, fastforwarding mode will be disabled. */ ++   bool fastforward; ++ ++   /* If true, and if supported by the frontend, an ++    * on-screen notification will be displayed while ++    * 'fastforward' is true. ++    * If false, and if supported by the frontend, any ++    * on-screen fast-forward notifications will be ++    * suppressed */ ++   bool notification; ++ ++   /* If true, the core will have sole control over ++    * when fastforwarding mode is enabled/disabled; ++    * the frontend will not be able to change the ++    * state set by 'fastforward' until either ++    * 'inhibit_toggle' is set to false, or the core ++    * is unloaded */ ++   bool inhibit_toggle; ++}; ++ + /* Callbacks */ +  + /* Environment callback. Gives implementations a way of performing diff --git a/patches/fbalpha2012/1001-add-auto-frameskip.patch b/patches/fbalpha2012/1001-add-auto-frameskip.patch new file mode 100644 index 0000000..e497b81 --- /dev/null +++ b/patches/fbalpha2012/1001-add-auto-frameskip.patch @@ -0,0 +1,297 @@ +diff --git a/svn-current/trunk/src/burner/libretro/libretro.cpp b/svn-current/trunk/src/burner/libretro/libretro.cpp +index 639aab9..1b23498 100644 +--- a/svn-current/trunk/src/burner/libretro/libretro.cpp ++++ b/svn-current/trunk/src/burner/libretro/libretro.cpp +@@ -153,6 +153,72 @@ void retro_set_environment(retro_environment_t cb) +    environ_cb = cb; + } +  ++/* Frameskipping Support */ ++ ++unsigned frameskip_type             = 0; ++unsigned frameskip_threshold        = 0; ++uint16_t frameskip_counter          = 0; ++unsigned frameskip_interval         = 0; ++ ++static bool retro_audio_buff_active        = false; ++static unsigned retro_audio_buff_occupancy = 0; ++static bool retro_audio_buff_underrun      = false; ++ ++static unsigned audio_latency              = 0; ++static bool update_audio_latency           = false; ++ ++static void retro_audio_buff_status_cb( ++      bool active, unsigned occupancy, bool underrun_likely) ++{ ++   retro_audio_buff_active    = active; ++   retro_audio_buff_occupancy = occupancy; ++   retro_audio_buff_underrun  = underrun_likely; ++} ++ ++void init_frameskip(void) ++{ ++   if (frameskip_type > 0) ++   { ++      struct retro_audio_buffer_status_callback buf_status_cb; ++ ++      buf_status_cb.callback = retro_audio_buff_status_cb; ++      if (!environ_cb(RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK, ++            &buf_status_cb)) ++      { ++         if (log_cb) ++            log_cb(RETRO_LOG_WARN, "Frameskip disabled - frontend does not support audio buffer status monitoring.\n"); ++ ++         retro_audio_buff_active    = false; ++         retro_audio_buff_occupancy = 0; ++         retro_audio_buff_underrun  = false; ++         audio_latency              = 0; ++      } ++      else ++      { ++         /* Frameskip is enabled - increase frontend ++          * audio latency to minimise potential ++          * buffer underruns */ ++#ifdef FBACORES_CPS ++         float frame_time_msec = 1000.0f / 59.629403f; ++#else ++         float frame_time_msec = 1000.0f / ((float)nBurnFPS / 100.0f); ++#endif ++         /* Set latency to 6x current frame time... */ ++         audio_latency = (unsigned)((6.0f * frame_time_msec) + 0.5f); ++ ++         /* ...then round up to nearest multiple of 32 */ ++         audio_latency = (audio_latency + 0x1F) & ~0x1F; ++      } ++   } ++   else ++   { ++      environ_cb(RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK, NULL); ++      audio_latency = 0; ++   } ++ ++   update_audio_latency = true; ++} ++ + char g_rom_dir[MAX_PATH]; + char g_save_dir[1024]; + char g_system_dir[1024]; +@@ -789,6 +855,14 @@ void retro_init() +       log_cb = log_dummy; +  +    BurnLibInit(); ++   frameskip_type             = 0; ++   frameskip_threshold        = 0; ++   frameskip_counter          = 0; ++   retro_audio_buff_active    = false; ++   retro_audio_buff_occupancy = 0; ++   retro_audio_buff_underrun  = false; ++   audio_latency              = 0; ++   update_audio_latency       = false; + } +  + void retro_deinit() +@@ -828,10 +902,50 @@ void retro_run() + { +    int width, height; +    BurnDrvGetVisibleSize(&width, &height); ++   int nSkipFrame = 0; ++ +    pBurnDraw = (uint8_t*)g_fba_frame; +  +    InputMake(); +  ++   /* Check whether current frame should ++    * be skipped */ ++   if ((frameskip_type > 0) && retro_audio_buff_active) ++   { ++      switch (frameskip_type) ++      { ++         case 1: /* auto */ ++            nSkipFrame = retro_audio_buff_underrun ? 1 : 0; ++            break; ++         case 2: /* manual */ ++            nSkipFrame = (retro_audio_buff_occupancy < frameskip_threshold) ? 1 : 0; ++            break; ++         default: ++            nSkipFrame = 0; ++            break; ++      } ++ ++      if (!nSkipFrame || (frameskip_counter >= frameskip_interval)) ++      { ++         nSkipFrame        = 0; ++         frameskip_counter = 0; ++      } ++      else ++         frameskip_counter++; ++   } ++ ++   if (nSkipFrame) ++      pBurnDraw = NULL; ++ ++   /* If frameskip settings have changed, update ++    * frontend audio latency */ ++   if (update_audio_latency) ++   { ++      environ_cb(RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY, ++            &audio_latency); ++      update_audio_latency = false; ++   } ++ +    ForceFrameStep(); +  +    unsigned drv_flags = BurnDrvGetFlags(); +@@ -851,7 +965,11 @@ void retro_run() +          nBurnPitch = width * pitch_size; +    } +  +-   video_cb(g_fba_frame, width, height, nBurnPitch); ++   if (!nSkipFrame) ++      video_cb(g_fba_frame, width, height, nBurnPitch); ++   else ++      video_cb(NULL, width, height, nBurnPitch); ++ +    audio_batch_cb(g_audio_buf, nBurnSoundLen); +  +    bool updated = false; +@@ -860,7 +978,7 @@ void retro_run() +       neo_geo_modes old_g_opt_neo_geo_mode = g_opt_neo_geo_mode; +       bool old_bVerticalMode = bVerticalMode; +  +-      check_variables(); ++      check_variables(false); +  +       apply_dipswitch_from_variables(); +  +@@ -1166,7 +1284,7 @@ bool retro_load_game(const struct retro_game_info *info) +       SetControllerInfo(); +  +       set_environment(); +-      check_variables(); ++      check_variables(true); +  +       pBurnSoundOut = g_audio_buf; +       nBurnSoundRate = AUDIO_SAMPLERATE; +diff --git a/svn-current/trunk/src/burner/libretro/retro_common.cpp b/svn-current/trunk/src/burner/libretro/retro_common.cpp +index 6b8bf31..95c994a 100644 +--- a/svn-current/trunk/src/burner/libretro/retro_common.cpp ++++ b/svn-current/trunk/src/burner/libretro/retro_common.cpp +@@ -62,6 +62,11 @@ INT32 g_audio_samplerate = 48000; + UINT8 *diag_input; + neo_geo_modes g_opt_neo_geo_mode = NEO_GEO_MODE_MVS; +  ++extern unsigned frameskip_type; ++extern unsigned frameskip_threshold; ++extern uint16_t frameskip_counter; ++extern unsigned frameskip_interval; ++ + #ifdef USE_CYCLONE + // 0 - c68k, 1 - m68k + // we don't use cyclone by default because it breaks savestates cross-platform compatibility (including netplay) +@@ -78,9 +83,11 @@ static UINT8 diag_input_select_l_r[] =  {RETRO_DEVICE_ID_JOYPAD_SELECT, RETRO_DE +  + // Global core options + static const struct retro_variable var_empty = { NULL, NULL }; ++static const struct retro_variable var_fbneo_frameskip = { "fbneo-frameskip-type", "Frameskip ; disabled|auto|threshold" }; ++static const struct retro_variable var_fbneo_frameskip_threshold = { "fbneo-threshold", "FS Threshold (%) ; 30|40|50|60" }; ++static const struct retro_variable var_fbneo_frameskip_interval = { "fbneo-interval", "FS Interval ; 0|1|2|3|4|5|6|7|8|9" }; + static const struct retro_variable var_fbneo_allow_depth_32 = { "fbneo-allow-depth-32", "Use 32-bits color depth when available; disabled|enabled" }; + static const struct retro_variable var_fbneo_vertical_mode = { "fbneo-vertical-mode", "Vertical mode; disabled|enabled" }; +-static const struct retro_variable var_fbneo_frameskip = { "fbneo-frameskip", "Frameskip; 0|1|2|3|4|5" }; + static const struct retro_variable var_fbneo_cpu_speed_adjust = { "fbneo-cpu-speed-adjust", "CPU overclock; 100|110|120|130|140|150|160|170|180|190|200" }; + static const struct retro_variable var_fbneo_diagnostic_input = { "fbneo-diagnostic-input", "Diagnostic Input; None|Hold Start|Start + A + B|Hold Start + A + B|Start + L + R|Hold Start + L + R|Hold Select|Select + A + B|Hold Select + A + B|Select + L + R|Hold Select + L + R" }; + static const struct retro_variable var_fbneo_hiscores = { "fbneo-hiscores", "Hiscores; enabled|disabled" }; +@@ -227,9 +234,11 @@ void set_environment() + #endif +  + 	// Add the Global core options ++	vars_systems.push_back(&var_fbneo_frameskip); ++	vars_systems.push_back(&var_fbneo_frameskip_threshold); ++	vars_systems.push_back(&var_fbneo_frameskip_interval); + 	vars_systems.push_back(&var_fbneo_allow_depth_32); + 	vars_systems.push_back(&var_fbneo_vertical_mode); +-	vars_systems.push_back(&var_fbneo_frameskip); + 	vars_systems.push_back(&var_fbneo_cpu_speed_adjust); + 	vars_systems.push_back(&var_fbneo_hiscores); + 	if (nGameType != RETRO_GAME_TYPE_NEOCD) +@@ -304,9 +313,40 @@ void set_environment() + #endif + } +  +-void check_variables(void) ++void check_variables(bool first_run) + { + 	struct retro_variable var = {0}; ++	bool prev_frameskip_type; ++ ++	var.key = var_fbneo_frameskip.key; ++	var.value = NULL; ++ ++	prev_frameskip_type = frameskip_type; ++	frameskip_type      = 0; ++ ++	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) ++	{ ++		if (strcmp(var.value, "auto") == 0) ++			frameskip_type = 1; ++		if (strcmp(var.value, "threshold") == 0) ++			frameskip_type = 2; ++	} ++ ++	var.key = var_fbneo_frameskip_threshold.key; ++	var.value = NULL; ++ ++	frameskip_threshold = 30; ++ ++	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) ++		frameskip_threshold = strtol(var.value, NULL, 10); ++ ++	var.key = var_fbneo_frameskip_interval.key; ++	var.value = NULL; ++ ++	frameskip_interval = 1; ++ ++	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) ++		frameskip_interval = strtol(var.value, NULL, 10); +  + 	var.key = var_fbneo_cpu_speed_adjust.key; + 	if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var)) +@@ -542,6 +582,11 @@ void check_variables(void) + 			bCycloneEnabled = false; + 	} + #endif ++ ++	/* Reinitialise frameskipping, if required */ ++	if (!first_run && ++	    ((frameskip_type     != prev_frameskip_type))) ++		init_frameskip(); + } +  + #ifdef USE_CYCLONE +diff --git a/svn-current/trunk/src/burner/libretro/retro_common.h b/svn-current/trunk/src/burner/libretro/retro_common.h +index 3efc786..f4feae6 100644 +--- a/svn-current/trunk/src/burner/libretro/retro_common.h ++++ b/svn-current/trunk/src/burner/libretro/retro_common.h +@@ -78,7 +78,8 @@ char* str_char_replace(char* destination, char c_find, char c_replace); + void set_neo_system_bios(); + void evaluate_neogeo_bios_mode(const char* drvname); + void set_environment(); +-void check_variables(void); ++void check_variables(bool first_run); ++void init_frameskip(); + #ifdef USE_CYCLONE + void SetSekCpuCore(); + #endif +diff --git a/svn-current/trunk/src/burner/libretro/retro_input.cpp b/svn-current/trunk/src/burner/libretro/retro_input.cpp +index d6b1980..2bf2e8d 100644 +--- a/svn-current/trunk/src/burner/libretro/retro_input.cpp ++++ b/svn-current/trunk/src/burner/libretro/retro_input.cpp +@@ -2293,7 +2293,7 @@ void InputInit() + 	// Update core option for diagnostic inputs + 	set_environment(); + 	// Read the user core option values +-	check_variables(); ++	check_variables(false); +  + 	// The list of input descriptors is filled, we can assign them to retroarch + 	//SetInputDescriptors(); diff --git a/patches/gambatte/0001-trimui-build.patch b/patches/gambatte/0001-trimui-build.patch new file mode 100644 index 0000000..9beb11b --- /dev/null +++ b/patches/gambatte/0001-trimui-build.patch @@ -0,0 +1,50 @@ +diff --git a/Makefile.libretro b/Makefile.libretro +index f41fcc2..50a1134 100644 +--- a/Makefile.libretro ++++ b/Makefile.libretro +@@ -368,6 +368,21 @@ else ifeq ($(platform), gcw0) +    CFLAGS += -fomit-frame-pointer -ffast-math -march=mips32 -mtune=mips32r2 -mhard-float +    CXXFLAGS += $(CFLAGS) +  ++# Trimui ++else ifeq ($(platform), trimui) ++	TARGET := $(TARGET_NAME)_libretro.so ++	CC = $(CROSS_COMPILE)gcc ++	CXX = $(CROSS_COMPILE)g++ ++	AR = $(CROSS_COMPILE)ar ++	SHARED := -shared -Wl,--version-script=$(version_script) ++	LDFLAGS += -fno-PIC -flto ++	PLATFORM_DEFINES := -DCC_RESAMPLER -DCC_RESAMPLER_NO_HIGHPASS ++	CFLAGS += -fomit-frame-pointer -ffast-math -mcpu=arm926ej-s -mtune=arm926ej-s -fno-PIC -flto ++	OPTIMIZE := -Ofast -DNDEBUG ++	ifeq (,$(DEBUG)) ++		LDFLAGS += -s ++	endif ++ + # RETROFW + else ifeq ($(platform), retrofw) +    TARGET := $(TARGET_NAME)_libretro.so +@@ -622,10 +637,23 @@ ifneq (,$(findstring msvc,$(platform))) +    CFLAGS   += -MT +    CXXFLAGS += -MT + endif ++ifneq (,$(OPTIMIZE)) ++	CFLAGS += $(OPTIMIZE) ++	CXXFLAGS += $(OPTIMIZE) ++else +    CFLAGS   += -O2 -DNDEBUG +    CXXFLAGS += -O2 -DNDEBUG + endif +  ++endif ++ ++ifeq ($(PROFILE), GENERATE) ++	CFLAGS	+= -fprofile-generate=./profile/gambatte ++	LDFLAGS	+= -lgcov ++else ifeq ($(PROFILE), APPLY) ++	CFLAGS	+= -fprofile-use -fprofile-dir=../profile/gambatte -fbranch-probabilities ++endif ++ + ifeq (,$(findstring msvc,$(platform))) + CXXFLAGS += -fno-exceptions -fno-rtti + CXXFLAGS += -std=c++98 diff --git a/patches/mame2000/0001-trimui-build.patch b/patches/mame2000/0001-trimui-build.patch new file mode 100644 index 0000000..52492b8 --- /dev/null +++ b/patches/mame2000/0001-trimui-build.patch @@ -0,0 +1,51 @@ +diff --git a/Makefile b/Makefile +index 4b0667a..8ebaebe 100644 +--- a/Makefile ++++ b/Makefile +@@ -335,6 +335,26 @@ else ifeq ($(platform), gcw0) +    DISABLE_ERROR_LOGGING := 1 +    CFLAGS += -march=mips32 -mtune=mips32r2 -mhard-float +  ++# Trimui ++else ifeq ($(platform), trimui) ++	TARGET = $(TARGET_NAME)_libretro.so ++	CC = $(CROSS_COMPILE)gcc ++	CXX = $(CROSS_COMPILE)g++ ++	AR = $(CROSS_COMPILE)ar ++	LDFLAGS += -shared -Wl,--version-script=link.T -Wl,-no-undefined -fno-PIC -flto ++	CFLAGS += -fomit-frame-pointer -ffast-math -mcpu=arm926ej-s -mtune=arm926ej-s -fno-PIC -flto ++	CFLAGS += -fsingle-precision-constant ++	CFLAGS += -fno-exceptions -fcommon -fno-unwind-tables -fno-asynchronous-unwind-tables ++	CFLAGS += -funroll-loops -fno-optimize-sibling-calls ++	DISABLE_ERROR_LOGGING := 1 ++  ARM = 1 ++	USE_CYCLONE = 1 ++	USE_DRZ80 = 1 ++  OPTIMIZE := -Ofast -DNDEBUG ++	ifeq (,$(DEBUG)) ++		LDFLAGS += -s ++	endif ++ + # Windows MSVC 2010 x64 + else ifeq ($(platform), windows_msvc2010_x64) + 	CC  = cl.exe +@@ -522,10 +542,19 @@ endif +  + ifeq ($(DEBUG), 1) + CFLAGS += -O0 -g ++else ifneq (,$(OPTIMIZE)) ++CFLAGS += $(OPTIMIZE) + else + CFLAGS += -O2 -DNDEBUG + endif +  ++ifeq ($(PROFILE), GENERATE) ++	CFLAGS	+= -fprofile-generate=./profile/mame2000 ++	LDFLAGS	+= -lgcov ++else ifeq ($(PROFILE), APPLY) ++	CFLAGS	+= -fprofile-use -fprofile-dir=../profile/mame2000 -fbranch-probabilities ++endif ++ + # compiler, linker and utilities + RM = rm -f + LIBS = -lm diff --git a/patches/mame2000/1000-update-libretro-h.patch b/patches/mame2000/1000-update-libretro-h.patch new file mode 100644 index 0000000..c1568ac --- /dev/null +++ b/patches/mame2000/1000-update-libretro-h.patch @@ -0,0 +1,863 @@ +diff --git a/src/libretro/libretro-common/include/libretro.h b/src/libretro/libretro-common/include/libretro.h +index 2b7fc95..32aa15f 100644 +--- a/src/libretro/libretro-common/include/libretro.h ++++ b/src/libretro/libretro-common/include/libretro.h +@@ -1,4 +1,4 @@ +-/* 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). +@@ -69,7 +69,7 @@ extern "C" { + #      endif + #    endif + #  else +-#      if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__CELLOS_LV2__) ++#      if defined(__GNUC__) && __GNUC__ >= 4 + #        define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default"))) + #      else + #        define RETRO_API RETRO_CALLCONV +@@ -278,6 +278,11 @@ 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_FINNISH             = 23, +    RETRO_LANGUAGE_LAST, +  +    /* Ensure sizeof(enum) == sizeof(int) */ +@@ -708,6 +713,9 @@ enum retro_mod +                                             * state of rumble motors in controllers. +                                             * A strong and weak motor is supported, and they can be +                                             * controlled indepedently. ++                                            * Should be called from either retro_init() or retro_load_game(). ++                                            * Should not be called from retro_set_environment(). ++                                            * Returns false if rumble functionality is unavailable. +                                             */ + #define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 +                                            /* uint64_t * -- +@@ -1087,10 +1095,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 +1106,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 +1125,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 +1140,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 +1177,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 +1202,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 +1263,236 @@ 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. ++                                            */ ++ ++#define RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK 62 ++                                           /* const struct retro_audio_buffer_status_callback * -- ++                                            * Lets the core know the occupancy level of the frontend ++                                            * audio buffer. Can be used by a core to attempt frame ++                                            * skipping in order to avoid buffer under-runs. ++                                            * A core may pass NULL to disable buffer status reporting ++                                            * in the frontend. ++                                            */ ++ ++#define RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY 63 ++                                           /* const unsigned * -- ++                                            * Sets minimum frontend audio latency in milliseconds. ++                                            * Resultant audio latency may be larger than set value, ++                                            * or smaller if a hardware limit is encountered. A frontend ++                                            * is expected to honour requests up to 512 ms. ++                                            * ++                                            * - If value is less than current frontend ++                                            *   audio latency, callback has no effect ++                                            * - If value is zero, default frontend audio ++                                            *   latency is set ++                                            * ++                                            * May be used by a core to increase audio latency and ++                                            * therefore decrease the probability of buffer under-runs ++                                            * (crackling) when performing 'intensive' operations. ++                                            * A core utilising RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK ++                                            * to implement audio-buffer-based frame skipping may achieve ++                                            * optimal results by setting the audio latency to a 'high' ++                                            * (typically 6x or 8x) integer multiple of the expected ++                                            * frame time. ++                                            * ++                                            * WARNING: This can only be called from within retro_run(). ++                                            * Calling this can require a full reinitialization of audio ++                                            * drivers in the frontend, so it is important to call it very ++                                            * sparingly, and usually only with the users explicit consent. ++                                            * An eventual driver reinitialize will happen so that audio ++                                            * callbacks happening after this call within the same retro_run() ++                                            * call will target the newly initialized driver. ++                                            */ ++ ++#define RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE 64 ++                                           /* const struct retro_fastforwarding_override * -- ++                                            * Used by a libretro core to override the current ++                                            * fastforwarding mode of the frontend. ++                                            * If NULL is passed to this function, the frontend ++                                            * will return true if fastforwarding override ++                                            * functionality is supported (no change in ++                                            * fastforwarding state will occur in this case). ++                                            */ ++ ++#define RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE 65 ++                                           /* const struct retro_system_content_info_override * -- ++                                            * Allows an implementation to override 'global' content ++                                            * info parameters reported by retro_get_system_info(). ++                                            * Overrides also affect subsystem content info parameters ++                                            * set via RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO. ++                                            * This function must be called inside retro_set_environment(). ++                                            * If callback returns false, content info overrides ++                                            * are unsupported by the frontend, and will be ignored. ++                                            * If callback returns true, extended game info may be ++                                            * retrieved by calling RETRO_ENVIRONMENT_GET_GAME_INFO_EXT ++                                            * in retro_load_game() or retro_load_game_special(). ++                                            * ++                                            * 'data' points to an array of retro_system_content_info_override ++                                            * structs terminated by a { NULL, false, false } element. ++                                            * If 'data' is NULL, no changes will be made to the frontend; ++                                            * a core may therefore pass NULL in order to test whether ++                                            * the RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE and ++                                            * RETRO_ENVIRONMENT_GET_GAME_INFO_EXT callbacks are supported ++                                            * by the frontend. ++                                            * ++                                            * For struct member descriptions, see the definition of ++                                            * struct retro_system_content_info_override. ++                                            * ++                                            * Example: ++                                            * ++                                            * - struct retro_system_info: ++                                            * { ++                                            *    "My Core",                      // library_name ++                                            *    "v1.0",                         // library_version ++                                            *    "m3u|md|cue|iso|chd|sms|gg|sg", // valid_extensions ++                                            *    true,                           // need_fullpath ++                                            *    false                           // block_extract ++                                            * } ++                                            * ++                                            * - Array of struct retro_system_content_info_override: ++                                            * { ++                                            *    { ++                                            *       "md|sms|gg", // extensions ++                                            *       false,       // need_fullpath ++                                            *       true         // persistent_data ++                                            *    }, ++                                            *    { ++                                            *       "sg",        // extensions ++                                            *       false,       // need_fullpath ++                                            *       false        // persistent_data ++                                            *    }, ++                                            *    { NULL, false, false } ++                                            * } ++                                            * ++                                            * Result: ++                                            * - Files of type m3u, cue, iso, chd will not be ++                                            *   loaded by the frontend. Frontend will pass a ++                                            *   valid path to the core, and core will handle ++                                            *   loading internally ++                                            * - Files of type md, sms, gg will be loaded by ++                                            *   the frontend. A valid memory buffer will be ++                                            *   passed to the core. This memory buffer will ++                                            *   remain valid until retro_deinit() returns ++                                            * - Files of type sg will be loaded by the frontend. ++                                            *   A valid memory buffer will be passed to the core. ++                                            *   This memory buffer will remain valid until ++                                            *   retro_load_game() (or retro_load_game_special()) ++                                            *   returns ++                                            * ++                                            * NOTE: If an extension is listed multiple times in ++                                            * an array of retro_system_content_info_override ++                                            * structs, only the first instance will be registered ++                                            */ ++ ++#define RETRO_ENVIRONMENT_GET_GAME_INFO_EXT 66 ++                                           /* const struct retro_game_info_ext ** -- ++                                            * Allows an implementation to fetch extended game ++                                            * information, providing additional content path ++                                            * and memory buffer status details. ++                                            * This function may only be called inside ++                                            * retro_load_game() or retro_load_game_special(). ++                                            * If callback returns false, extended game information ++                                            * is unsupported by the frontend. In this case, only ++                                            * regular retro_game_info will be available. ++                                            * RETRO_ENVIRONMENT_GET_GAME_INFO_EXT is guaranteed ++                                            * to return true if RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE ++                                            * returns true. ++                                            * ++                                            * 'data' points to an array of retro_game_info_ext structs. ++                                            * ++                                            * For struct member descriptions, see the definition of ++                                            * struct retro_game_info_ext. ++                                            * ++                                            * - If function is called inside retro_load_game(), ++                                            *   the retro_game_info_ext array is guaranteed to ++                                            *   have a size of 1 - i.e. the returned pointer may ++                                            *   be used to access directly the members of the ++                                            *   first retro_game_info_ext struct, for example: ++                                            * ++                                            *      struct retro_game_info_ext *game_info_ext; ++                                            *      if (environ_cb(RETRO_ENVIRONMENT_GET_GAME_INFO_EXT, &game_info_ext)) ++                                            *         printf("Content Directory: %s\n", game_info_ext->dir); ++                                            * ++                                            * - If the function is called inside retro_load_game_special(), ++                                            *   the retro_game_info_ext array is guaranteed to have a ++                                            *   size equal to the num_info argument passed to ++                                            *   retro_load_game_special() ++                                            */ ++ + /* VFS functionality */ +  + /* File paths: +@@ -2147,6 +2382,30 @@ struct retro_frame_time_callback +    retro_usec_t reference; + }; +  ++/* Notifies a libretro core of the current occupancy ++ * level of the frontend audio buffer. ++ * ++ * - active: 'true' if audio buffer is currently ++ *           in use. Will be 'false' if audio is ++ *           disabled in the frontend ++ * ++ * - occupancy: Given as a value in the range [0,100], ++ *              corresponding to the occupancy percentage ++ *              of the audio buffer ++ * ++ * - underrun_likely: 'true' if the frontend expects an ++ *                    audio buffer underrun during the ++ *                    next frame (indicates that a core ++ *                    should attempt frame skipping) ++ * ++ * It will be called right before retro_run() every frame. */ ++typedef void (RETRO_CALLCONV *retro_audio_buffer_status_callback_t)( ++      bool active, unsigned occupancy, bool underrun_likely); ++struct retro_audio_buffer_status_callback ++{ ++   retro_audio_buffer_status_callback_t callback; ++}; ++ + /* Pass this to retro_video_refresh_t if rendering to hardware. +  * Passing NULL to retro_video_refresh_t is still a frame dupe as normal. +  * */ +@@ -2307,7 +2566,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 +2625,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 +2685,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 +2736,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; ++   /* Message logging level (info, warn, error, etc.) */ ++   enum retro_log_level level; ++   /* Message destination: OSD, logging interface or both */ ++   enum retro_message_target target; ++   /* Message 'type' when targeting the OSD ++    * > RETRO_MESSAGE_TYPE_NOTIFICATION: Specifies that a ++    *   message should be handled in identical fashion to ++    *   a standard frontend-generated notification ++    * > RETRO_MESSAGE_TYPE_NOTIFICATION_ALT: Specifies that ++    *   message is a notification that requires user attention ++    *   or action, but that it should be displayed in a manner ++    *   that differs from standard frontend-generated notifications. ++    *   This would typically correspond to messages that should be ++    *   displayed immediately (independently from any internal ++    *   frontend message queue), and/or which should be visually ++    *   distinguishable from frontend-generated notifications. ++    *   For example, a core may wish to inform the user of ++    *   information related to a disk-change event. It is ++    *   expected that the frontend itself may provide a ++    *   notification in this case; if the core sends a ++    *   message of type RETRO_MESSAGE_TYPE_NOTIFICATION, an ++    *   uncomfortable 'double-notification' may occur. A message ++    *   of RETRO_MESSAGE_TYPE_NOTIFICATION_ALT should therefore ++    *   be presented such that visual conflict with regular ++    *   notifications does not occur ++    * > RETRO_MESSAGE_TYPE_STATUS: Indicates that message ++    *   is not a standard notification. This typically ++    *   corresponds to 'status' indicators, such as a core's ++    *   internal FPS, which are intended to be displayed ++    *   either permanently while a core is running, or in ++    *   a manner that does not suggest user attention or action ++    *   is required. 'Status' type messages should therefore be ++    *   displayed in a different on-screen location and in a manner ++    *   easily distinguishable from both standard frontend-generated ++    *   notifications and messages of type RETRO_MESSAGE_TYPE_NOTIFICATION_ALT ++    * > RETRO_MESSAGE_TYPE_PROGRESS: Indicates that message reports ++    *   the progress of an internal core task. For example, in cases ++    *   where a core itself handles the loading of content from a file, ++    *   this may correspond to the percentage of the file that has been ++    *   read. Alternatively, an audio/video playback core may use a ++    *   message of type RETRO_MESSAGE_TYPE_PROGRESS to display the current ++    *   playback position as a percentage of the runtime. 'Progress' type ++    *   messages should therefore be displayed as a literal progress bar, ++    *   where: ++    *   - 'retro_message_ext.msg' is the progress bar title/label ++    *   - 'retro_message_ext.progress' determines the length of ++    *     the progress bar ++    * NOTE: Message type is a *hint*, and may be ignored ++    * by the frontend. If a frontend lacks support for ++    * displaying messages via alternate means than standard ++    * frontend-generated notifications, it will treat *all* ++    * messages as having the type RETRO_MESSAGE_TYPE_NOTIFICATION */ ++   enum retro_message_type type; ++   /* Task progress when targeting the OSD and message is ++    * of type RETRO_MESSAGE_TYPE_PROGRESS ++    * > -1:    Unmetered/indeterminate ++    * > 0-100: Current progress percentage ++    * NOTE: Since message type is a hint, a frontend may ignore ++    * progress values. Where relevant, a core should therefore ++    * include progress percentage within the message string, ++    * such that the message intent remains clear when displayed ++    * as a standard frontend-generated notification */ ++   int8_t progress; ++}; ++ + /* Describes how the libretro implementation maps a libretro input bind +  * to its internal input system through a human readable string. +  * This string can be used to better let a user configure input. */ +@@ -2428,7 +2854,7 @@ struct retro_input_descriptor + struct retro_system_info + { +    /* All pointers are owned by libretro implementation, and pointers must +-    * remain valid until retro_deinit() is called. */ ++    * remain valid until it is unloaded. */ +  +    const char *library_name;      /* Descriptive name of library. Should not +                                    * contain any version numbers, etc. */ +@@ -2470,6 +2896,213 @@ struct retro_system_info +    bool        block_extract; + }; +  ++/* Defines overrides which modify frontend handling of ++ * specific content file types. ++ * An array of retro_system_content_info_override is ++ * passed to RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE ++ * NOTE: In the following descriptions, references to ++ *       retro_load_game() may be replaced with ++ *       retro_load_game_special() */ ++struct retro_system_content_info_override ++{ ++   /* A list of file extensions for which the override ++    * should apply, delimited by a 'pipe' character ++    * (e.g. "md|sms|gg") ++    * Permitted file extensions are limited to those ++    * included in retro_system_info::valid_extensions ++    * and/or retro_subsystem_rom_info::valid_extensions */ ++   const char *extensions; ++ ++   /* Overrides the need_fullpath value set in ++    * retro_system_info and/or retro_subsystem_rom_info. ++    * To reiterate: ++    * ++    * If need_fullpath is true and retro_load_game() is called: ++    *    - retro_game_info::path is guaranteed to contain a valid ++    *      path to an existent file ++    *    - retro_game_info::data and retro_game_info::size are invalid ++    * ++    * If need_fullpath is false and retro_load_game() is called: ++    *    - retro_game_info::path may be NULL ++    *    - retro_game_info::data and retro_game_info::size are guaranteed ++    *      to be valid ++    * ++    * In addition: ++    * ++    * If need_fullpath is true and retro_load_game() is called: ++    *    - retro_game_info_ext::full_path is guaranteed to contain a valid ++    *      path to an existent file ++    *    - retro_game_info_ext::archive_path may be NULL ++    *    - retro_game_info_ext::archive_file may be NULL ++    *    - retro_game_info_ext::dir is guaranteed to contain a valid path ++    *      to the directory in which the content file exists ++    *    - retro_game_info_ext::name is guaranteed to contain the ++    *      basename of the content file, without extension ++    *    - retro_game_info_ext::ext is guaranteed to contain the ++    *      extension of the content file in lower case format ++    *    - retro_game_info_ext::data and retro_game_info_ext::size ++    *      are invalid ++    * ++    * If need_fullpath is false and retro_load_game() is called: ++    *    - If retro_game_info_ext::file_in_archive is false: ++    *       - retro_game_info_ext::full_path is guaranteed to contain ++    *         a valid path to an existent file ++    *       - retro_game_info_ext::archive_path may be NULL ++    *       - retro_game_info_ext::archive_file may be NULL ++    *       - retro_game_info_ext::dir is guaranteed to contain a ++    *         valid path to the directory in which the content file exists ++    *       - retro_game_info_ext::name is guaranteed to contain the ++    *         basename of the content file, without extension ++    *       - retro_game_info_ext::ext is guaranteed to contain the ++    *         extension of the content file in lower case format ++    *    - If retro_game_info_ext::file_in_archive is true: ++    *       - retro_game_info_ext::full_path may be NULL ++    *       - retro_game_info_ext::archive_path is guaranteed to ++    *         contain a valid path to an existent compressed file ++    *         inside which the content file is located ++    *       - retro_game_info_ext::archive_file is guaranteed to ++    *         contain a valid path to an existent content file ++    *         inside the compressed file referred to by ++    *         retro_game_info_ext::archive_path ++    *            e.g. for a compressed file '/path/to/foo.zip' ++    *            containing 'bar.sfc' ++    *             > retro_game_info_ext::archive_path will be '/path/to/foo.zip' ++    *             > retro_game_info_ext::archive_file will be 'bar.sfc' ++    *       - retro_game_info_ext::dir is guaranteed to contain a ++    *         valid path to the directory in which the compressed file ++    *         (containing the content file) exists ++    *       - retro_game_info_ext::name is guaranteed to contain ++    *         EITHER ++    *         1) the basename of the compressed file (containing ++    *            the content file), without extension ++    *         OR ++    *         2) the basename of the content file inside the ++    *            compressed file, without extension ++    *         In either case, a core should consider 'name' to ++    *         be the canonical name/ID of the the content file ++    *       - retro_game_info_ext::ext is guaranteed to contain the ++    *         extension of the content file inside the compressed file, ++    *         in lower case format ++    *    - retro_game_info_ext::data and retro_game_info_ext::size are ++    *      guaranteed to be valid */ ++   bool need_fullpath; ++ ++   /* If need_fullpath is false, specifies whether the content ++    * data buffer available in retro_load_game() is 'persistent' ++    * ++    * If persistent_data is false and retro_load_game() is called: ++    *    - retro_game_info::data and retro_game_info::size ++    *      are valid only until retro_load_game() returns ++    *    - retro_game_info_ext::data and retro_game_info_ext::size ++    *      are valid only until retro_load_game() returns ++    * ++    * If persistent_data is true and retro_load_game() is called: ++    *    - retro_game_info::data and retro_game_info::size ++    *      are valid until retro_deinit() returns ++    *    - retro_game_info_ext::data and retro_game_info_ext::size ++    *      are valid until retro_deinit() returns */ ++   bool persistent_data; ++}; ++ ++/* Similar to retro_game_info, but provides extended ++ * information about the source content file and ++ * game memory buffer status. ++ * And array of retro_game_info_ext is returned by ++ * RETRO_ENVIRONMENT_GET_GAME_INFO_EXT ++ * NOTE: In the following descriptions, references to ++ *       retro_load_game() may be replaced with ++ *       retro_load_game_special() */ ++struct retro_game_info_ext ++{ ++   /* - If file_in_archive is false, contains a valid ++    *   path to an existent content file (UTF-8 encoded) ++    * - If file_in_archive is true, may be NULL */ ++   const char *full_path; ++ ++   /* - If file_in_archive is false, may be NULL ++    * - If file_in_archive is true, contains a valid path ++    *   to an existent compressed file inside which the ++    *   content file is located (UTF-8 encoded) */ ++   const char *archive_path; ++ ++   /* - If file_in_archive is false, may be NULL ++    * - If file_in_archive is true, contain a valid path ++    *   to an existent content file inside the compressed ++    *   file referred to by archive_path (UTF-8 encoded) ++    *      e.g. for a compressed file '/path/to/foo.zip' ++    *      containing 'bar.sfc' ++    *      > archive_path will be '/path/to/foo.zip' ++    *      > archive_file will be 'bar.sfc' */ ++   const char *archive_file; ++ ++   /* - If file_in_archive is false, contains a valid path ++    *   to the directory in which the content file exists ++    *   (UTF-8 encoded) ++    * - If file_in_archive is true, contains a valid path ++    *   to the directory in which the compressed file ++    *   (containing the content file) exists (UTF-8 encoded) */ ++   const char *dir; ++ ++   /* Contains the canonical name/ID of the content file ++    * (UTF-8 encoded). Intended for use when identifying ++    * 'complementary' content named after the loaded file - ++    * i.e. companion data of a different format (a CD image ++    * required by a ROM), texture packs, internally handled ++    * save files, etc. ++    * - If file_in_archive is false, contains the basename ++    *   of the content file, without extension ++    * - If file_in_archive is true, then string is ++    *   implementation specific. A frontend may choose to ++    *   set a name value of: ++    *   EITHER ++    *   1) the basename of the compressed file (containing ++    *      the content file), without extension ++    *   OR ++    *   2) the basename of the content file inside the ++    *      compressed file, without extension ++    *   RetroArch sets the 'name' value according to (1). ++    *   A frontend that supports routine loading of ++    *   content from archives containing multiple unrelated ++    *   content files may set the 'name' value according ++    *   to (2). */ ++   const char *name; ++ ++   /* - If file_in_archive is false, contains the extension ++    *   of the content file in lower case format ++    * - If file_in_archive is true, contains the extension ++    *   of the content file inside the compressed file, ++    *   in lower case format */ ++   const char *ext; ++ ++   /* String of implementation specific meta-data. */ ++   const char *meta; ++ ++   /* Memory buffer of loaded game content. Will be NULL: ++    * IF ++    * - retro_system_info::need_fullpath is true and ++    *   retro_system_content_info_override::need_fullpath ++    *   is unset ++    * OR ++    * - retro_system_content_info_override::need_fullpath ++    *   is true */ ++   const void *data; ++ ++   /* Size of game content memory buffer, in bytes */ ++   size_t size; ++ ++   /* True if loaded content file is inside a compressed ++    * archive */ ++   bool file_in_archive; ++ ++   /* - If data is NULL, value is unset/ignored ++    * - If data is non-NULL: ++    *   - If persistent_data is false, data and size are ++    *     valid only until retro_load_game() returns ++    *   - If persistent_data is true, data and size are ++    *     are valid until retro_deinit() returns */ ++   bool persistent_data; ++}; ++ + struct retro_game_geometry + { +    unsigned base_width;    /* Nominal video width of game. */ +@@ -2522,8 +3155,20 @@ struct retro_core_option_display + }; +  + /* Maximum number of values permitted for a core option +- * NOTE: This may be increased on a core-by-core basis +- * if required (doing so has no effect on the frontend) */ ++ * > Note: We have to set a maximum value due the limitations ++ *   of the C language - i.e. it is not possible to create an ++ *   array of structs each containing a variable sized array, ++ *   so the retro_core_option_definition values array must ++ *   have a fixed size. The size limit of 128 is a balancing ++ *   act - it needs to be large enough to support all 'sane' ++ *   core options, but setting it too large may impact low memory ++ *   platforms. In practise, if a core option has more than ++ *   128 values then the implementation is likely flawed. ++ *   To quote the above API reference: ++ *      "The number of possible options should be very limited ++ *       i.e. it should be feasible to cycle through options ++ *       without a keyboard." ++ */ + #define RETRO_NUM_CORE_OPTION_VALUES_MAX 128 +  + struct retro_core_option_value +@@ -2615,6 +3260,47 @@ struct retro_framebuffer +                                        Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ + }; +  ++/* Used by a libretro core to override the current ++ * fastforwarding mode of the frontend */ ++struct retro_fastforwarding_override ++{ ++   /* Specifies the runtime speed multiplier that ++    * will be applied when 'fastforward' is true. ++    * For example, a value of 5.0 when running 60 FPS ++    * content will cap the fast-forward rate at 300 FPS. ++    * Note that the target multiplier may not be achieved ++    * if the host hardware has insufficient processing ++    * power. ++    * Setting a value of 0.0 (or greater than 0.0 but ++    * less than 1.0) will result in an uncapped ++    * fast-forward rate (limited only by hardware ++    * capacity). ++    * If the value is negative, it will be ignored ++    * (i.e. the frontend will use a runtime speed ++    * multiplier of its own choosing) */ ++   float ratio; ++ ++   /* If true, fastforwarding mode will be enabled. ++    * If false, fastforwarding mode will be disabled. */ ++   bool fastforward; ++ ++   /* If true, and if supported by the frontend, an ++    * on-screen notification will be displayed while ++    * 'fastforward' is true. ++    * If false, and if supported by the frontend, any ++    * on-screen fast-forward notifications will be ++    * suppressed */ ++   bool notification; ++ ++   /* If true, the core will have sole control over ++    * when fastforwarding mode is enabled/disabled; ++    * the frontend will not be able to change the ++    * state set by 'fastforward' until either ++    * 'inhibit_toggle' is set to false, or the core ++    * is unloaded */ ++   bool inhibit_toggle; ++}; ++ + /* Callbacks */ +  + /* Environment callback. Gives implementations a way of performing diff --git a/patches/mame2000/1001-add-frameskip.patch b/patches/mame2000/1001-add-frameskip.patch new file mode 100644 index 0000000..a07582e --- /dev/null +++ b/patches/mame2000/1001-add-frameskip.patch @@ -0,0 +1,276 @@ +diff --git a/src/libretro/libretro.c b/src/libretro/libretro.c +index 521a561..514e335 100644 +--- a/src/libretro/libretro.c ++++ b/src/libretro/libretro.c +@@ -51,6 +51,20 @@ static scond_t   *libretro_cond = NULL; + static slock_t   *libretro_mutex = NULL; + #endif +  ++unsigned frameskip_type                  = 0; ++unsigned frameskip_threshold             = 0; ++unsigned frameskip_counter               = 0; ++unsigned frameskip_interval              = 0; ++ ++int retro_audio_buff_active              = false; ++unsigned retro_audio_buff_occupancy      = 0; ++int retro_audio_buff_underrun            = false; ++ ++unsigned retro_audio_latency             = 0; ++int update_audio_latency                 = false; ++ ++int should_skip_frame                    = 0; ++ + int game_index = -1; + unsigned short *gp2x_screen15; + int thread_done = 0; +@@ -151,10 +165,87 @@ static bool libretro_supports_bitmasks = false; +  + unsigned skip_disclaimer = 0; +  +-static void update_variables(void) ++static void retro_audio_buff_status_cb( ++      bool active, unsigned occupancy, bool underrun_likely) ++{ ++   retro_audio_buff_active    = active; ++   retro_audio_buff_occupancy = occupancy; ++   retro_audio_buff_underrun  = underrun_likely; ++} ++ ++static void retro_set_audio_buff_status_cb(void) ++{ ++   if (frameskip_type > 0) ++   { ++      struct retro_audio_buffer_status_callback buf_status_cb; ++ ++      buf_status_cb.callback = retro_audio_buff_status_cb; ++      if (!environ_cb(RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK, ++            &buf_status_cb)) ++      { ++         retro_audio_buff_active    = false; ++         retro_audio_buff_occupancy = 0; ++         retro_audio_buff_underrun  = false; ++         retro_audio_latency        = 0; ++      } ++      else ++      { ++         /* Frameskip is enabled - increase frontend ++          * audio latency to minimise potential ++          * buffer underruns */ ++         uint32_t frame_time_usec = 1000000.0 / Machine->drv->frames_per_second; ++ ++         /* Set latency to 6x current frame time... */ ++         retro_audio_latency = (unsigned)(6 * frame_time_usec / 1000); ++ ++         /* ...then round up to nearest multiple of 32 */ ++         retro_audio_latency = (retro_audio_latency + 0x1F) & ~0x1F; ++      } ++   } ++   else ++   { ++      environ_cb(RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK, NULL); ++      retro_audio_latency = 0; ++   } ++ ++   update_audio_latency = true; ++} ++ ++static void update_variables(bool first_run) + { +     struct retro_variable var; +-     ++    bool prev_frameskip_type; ++ ++    var.key = "mame2000-frameskip"; ++    var.value = NULL; ++ ++    prev_frameskip_type = frameskip_type; ++    frameskip_type      = 0; ++ ++    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) ++    { ++       if (strcmp(var.value, "auto") == 0) ++          frameskip_type = 1; ++       if (strcmp(var.value, "threshold") == 0) ++          frameskip_type = 2; ++    } ++ ++    var.key = "mame2000-frameskip_threshold"; ++    var.value = NULL; ++ ++    frameskip_threshold = 30; ++ ++    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) ++       frameskip_threshold = strtol(var.value, NULL, 10); ++ ++    var.key = "mame2000-frameskip_interval"; ++    var.value = NULL; ++ ++    frameskip_interval = 1; ++ ++    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) ++       frameskip_interval = strtol(var.value, NULL, 10); ++ +     var.value = NULL; +     var.key = "mame2000-skip_disclaimer"; +      +@@ -180,11 +271,19 @@ static void update_variables(void) +     } +     else +         global_showinfo = 0; ++ ++   /* Reinitialise frameskipping, if required */ ++   if (!first_run && ++       ((frameskip_type     != prev_frameskip_type))) ++      retro_set_audio_buff_status_cb(); + } +  + void retro_set_environment(retro_environment_t cb) + { +    static const struct retro_variable vars[] = { ++      { "mame2000-frameskip", "Frameskip ; disabled|auto|threshold" }, ++      { "mame2000-frameskip_threshold", "Frameskip Threshold (%); 30|40|50|60" }, ++      { "mame2000-frameskip_interval", "Frameskip Interval; 1|2|3|4|5|6|7|8|9" }, +       { "mame2000-skip_disclaimer", "Skip Disclaimer; enabled|disabled" }, +       { "mame2000-show_gameinfo", "Show Game Information; disabled|enabled" }, +       { NULL, NULL }, +@@ -475,7 +574,7 @@ void retro_init(void) +    libretro_mutex = slock_new(); + #endif +    init_joy_list(); +-   update_variables(); ++   update_variables(true); +  +    if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL)) +       libretro_supports_bitmasks = true; +@@ -496,6 +595,14 @@ void retro_deinit(void) + #endif +  +    libretro_supports_bitmasks = false; ++   frameskip_type             = 0; ++   frameskip_threshold        = 0; ++   frameskip_counter          = 0; ++   retro_audio_buff_active    = false; ++   retro_audio_buff_occupancy = 0; ++   retro_audio_buff_underrun  = false; ++   retro_audio_latency        = 0; ++   update_audio_latency       = false; + } +  + unsigned retro_api_version(void) +@@ -560,9 +667,13 @@ void retro_run(void) +    update_input(); +  +    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) +-      update_variables(); ++      update_variables(false); ++ ++   if (should_skip_frame) ++      video_cb(NULL, gfx_width, gfx_height, gfx_width * 2); ++   else ++      video_cb(gp2x_screen15, gfx_width, gfx_height, gfx_width * 2); +  +-   video_cb(gp2x_screen15, gfx_width, gfx_height, gfx_width * 2); +    if (samples_per_frame) +    { +       if (usestereo) +@@ -584,6 +695,19 @@ void retro_run(void) + #ifndef WANT_LIBCO +    unlock_mame(); + #endif ++ ++   /* If frameskip/timing settings have changed, ++    * update frontend audio latency ++    * > Can do this before or after the frameskip ++    *   check, but doing it after means we at least ++    *   retain the current frame's audio output */ ++   if (update_audio_latency) ++   { ++      environ_cb(RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY, ++                 &retro_audio_latency); ++      update_audio_latency = false; ++   } ++ + } +  + bool retro_load_game(const struct retro_game_info *info) +@@ -895,6 +1019,7 @@ bool retro_load_game(const struct retro_game_info *info) +    run_thread = sthread_create(run_thread_proc, NULL); + #endif +  ++   retro_set_audio_buff_status_cb(); +    return true; + } +  +diff --git a/src/libretro/video.c b/src/libretro/video.c +index ce13ea0..f97ac05 100644 +--- a/src/libretro/video.c ++++ b/src/libretro/video.c +@@ -8,6 +8,17 @@ extern int isIpad; + extern int emulated_width; + extern int emulated_height; + extern int safe_render_path; ++ ++extern unsigned frameskip_type; ++extern unsigned frameskip_threshold; ++extern unsigned frameskip_counter; ++extern unsigned frameskip_interval; ++ ++extern int retro_audio_buff_active; ++extern unsigned retro_audio_buff_occupancy; ++extern int retro_audio_buff_underrun; ++extern int should_skip_frame; ++ + int iOS_exitPause = 0; + int iOS_cropVideo = 0; + int iOS_aspectRatio = 0; +@@ -793,7 +804,7 @@ static INLINE void pan_display(void) +  + int osd_skip_this_frame(void) + { +-   return 0; ++   return should_skip_frame; + } +  + /* Update the display. */ +@@ -902,6 +913,41 @@ void osd_update_video_and_audio(struct osd_bitmap *bitmap) + 	/* Check for PGUP, PGDN and pan screen */ + 	pan_display(); +  ++	should_skip_frame = 0; ++	/* Check whether current frame should ++	 * be skipped */ ++	if ((frameskip_type > 0) && ++	    retro_audio_buff_active) ++	{ ++		int skip_frame; ++ ++		switch (frameskip_type) ++		{ ++		case 1: /* auto */ ++			skip_frame = retro_audio_buff_underrun; ++			break; ++		case 2: /* threshold */ ++			skip_frame = (retro_audio_buff_occupancy < frameskip_threshold); ++			break; ++		default: ++			skip_frame = 0; ++			break; ++		} ++ ++		if (skip_frame) ++		{ ++			if(frameskip_counter < frameskip_interval) ++			{ ++				should_skip_frame = 1; ++				frameskip_counter++; ++			} ++			else ++				frameskip_counter = 0; ++		} ++		else ++			frameskip_counter = 0; ++	} ++ +    hook_video_done(); + } +  diff --git a/patches/mame2000/1002-add-sound-options.patch b/patches/mame2000/1002-add-sound-options.patch new file mode 100644 index 0000000..266ce95 --- /dev/null +++ b/patches/mame2000/1002-add-sound-options.patch @@ -0,0 +1,72 @@ +diff --git a/src/libretro/libretro.c b/src/libretro/libretro.c +index bf0ed70..d51b9f0 100644 +--- a/src/libretro/libretro.c ++++ b/src/libretro/libretro.c +@@ -65,6 +65,9 @@ int update_audio_latency                 = false; +  + int should_skip_frame                    = 0; +  ++static int sample_rate                   = 32000; ++static int stereo_enabled                = true; ++ + int game_index = -1; + unsigned short *gp2x_screen15; + int thread_done = 0; +@@ -272,6 +275,27 @@ static void update_variables(bool first_run) +     else +         global_showinfo = 0; +  ++    var.value = NULL; ++    var.key = "mame2000-sample_rate"; ++ ++    sample_rate = 32000; ++ ++    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) ++       sample_rate = strtol(var.value, NULL, 10); ++ ++    var.value = NULL; ++    var.key = "mame2000-stereo"; ++ ++    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) ++    { ++        if(strcmp(var.value, "enabled") == 0) ++            stereo_enabled = true; ++        else ++            stereo_enabled = false; ++    } ++    else ++        stereo_enabled = true; ++ +    /* Reinitialise frameskipping, if required */ +    if (!first_run && +        ((frameskip_type     != prev_frameskip_type))) +@@ -286,6 +310,8 @@ void retro_set_environment(retro_environment_t cb) +       { "mame2000-frameskip_interval", "Frameskip Interval; 1|2|3|4|5|6|7|8|9" }, +       { "mame2000-skip_disclaimer", "Skip Disclaimer; enabled|disabled" }, +       { "mame2000-show_gameinfo", "Show Game Information; disabled|enabled" }, ++      { "mame2000-sample_rate", "Audio Rate (Restart); 32000|11025|22050|32000|44100" }, ++      { "mame2000-stereo", "Stereo (Restart); enabled|disabled" }, +       { NULL, NULL }, +    }; +    environ_cb = cb; +@@ -643,7 +669,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info) +    }; +    struct retro_system_timing t = { +       Machine->drv->frames_per_second, +-      32000.0 ++      (double)Machine->sample_rate +    }; +    info->timing = t; +    info->geometry = g; +@@ -881,8 +907,9 @@ bool retro_load_game(const struct retro_game_info *info) +    i=create_path_recursive(cheatdir); +    if(i!=0)printf("error %d creating cheat \"%s\"\n", i,cheatdir); +  +-   Machine->sample_rate = 32000; +-   options.samplerate = 32000; ++   Machine->sample_rate = sample_rate; ++   options.samplerate = sample_rate; ++   usestereo = stereo_enabled; +  +    /* This is needed so emulated YM3526/YM3812 chips are used instead on physical ones. */ +    options.use_emulated_ym3812 = 1; diff --git a/patches/mame2000/1003-shorten-options.patch b/patches/mame2000/1003-shorten-options.patch new file mode 100644 index 0000000..49e0d5c --- /dev/null +++ b/patches/mame2000/1003-shorten-options.patch @@ -0,0 +1,23 @@ +diff --git a/src/libretro/libretro.c b/src/libretro/libretro.c +index f9b3cfe..aad93bc 100644 +--- a/src/libretro/libretro.c ++++ b/src/libretro/libretro.c +@@ -306,12 +306,12 @@ void retro_set_environment(retro_environment_t cb) + { +    static const struct retro_variable vars[] = { +       { "mame2000-frameskip", "Frameskip ; disabled|auto|threshold" }, +-      { "mame2000-frameskip_threshold", "Frameskip Threshold (%); 30|40|50|60" }, +-      { "mame2000-frameskip_interval", "Frameskip Interval; 1|2|3|4|5|6|7|8|9" }, +-      { "mame2000-skip_disclaimer", "Skip Disclaimer; enabled|disabled" }, +-      { "mame2000-show_gameinfo", "Show Game Information; disabled|enabled" }, +-      { "mame2000-sample_rate", "Audio Rate (Restart); 32000|11025|22050|32000|44100" }, +-      { "mame2000-stereo", "Stereo (Restart); enabled|disabled" }, ++      { "mame2000-frameskip_threshold", "FS Threshold (%); 30|40|50|60" }, ++      { "mame2000-frameskip_interval", "FS Interval; 1|2|3|4|5|6|7|8|9" }, ++      { "mame2000-skip_disclaimer", "Skip Disclaimer; disabled|enabled" }, ++      { "mame2000-show_gameinfo", "Show Game Info; disabled|enabled" }, ++      { "mame2000-sample_rate", "Snd. Rate (Restart); 11025|22050|32000|44100" }, ++      { "mame2000-stereo", "Stereo (Restart); disabled|enabled" }, +       { NULL, NULL }, +    }; +    environ_cb = cb; diff --git a/patches/mame2003_plus/0001-trimui-build.patch b/patches/mame2003_plus/0001-trimui-build.patch new file mode 100644 index 0000000..8b2bbac --- /dev/null +++ b/patches/mame2003_plus/0001-trimui-build.patch @@ -0,0 +1,48 @@ +diff --git a/Makefile b/Makefile +index 14082f8..364a327 100644 +--- a/Makefile ++++ b/Makefile +@@ -489,6 +489,23 @@ else ifeq ($(platform), gcw0) + 	fpic := -fPIC -nostdlib + 	CFLAGS += -lm -march=mips32 -mtune=mips32r2 -mhard-float +  ++# Trimui ++else ifeq ($(platform), trimui) ++	TARGET = $(TARGET_NAME)_libretro.so ++	CC = $(CROSS_COMPILE)gcc ++	CXX = $(CROSS_COMPILE)g++ ++	AR = $(CROSS_COMPILE)ar ++	LDFLAGS += -shared -Wl,--version-script=link.T -Wl,-no-undefined -fno-PIC -flto ++	CFLAGS += -std=c99 -fomit-frame-pointer -ffast-math -mcpu=arm926ej-s -mtune=arm926ej-s -fno-PIC -flto ++	CXXFLAGS = $(CFLAGS) -fno-rtti -fno-exceptions ++	LIBS := -lc -lgcc -lm ++	CPU_ARCH := arm ++	ARM = 1 ++	OPTIMIZE := -Ofast -DNDEBUG ++	ifeq (,$(DEBUG)) ++		LDFLAGS += -s ++	endif ++ + # RetroFW + else ifeq ($(platform), retrofw) + 	TARGET := $(TARGET_NAME)_libretro.so +@@ -795,10 +812,19 @@ CFLAGS += -DRETRO_PROFILE=$(RETRO_PROFILE) + # Disable optimization when debugging ##################### + ifeq ($(DEBUG), 1) + 	CFLAGS += -O0 -g3 ++else ifneq (,$(OPTIMIZE)) ++	CFLAGS += $(OPTIMIZE) + else + 	CFLAGS += -O2 -DNDEBUG + endif +  ++ifeq ($(PROFILE), GENERATE) ++	CFLAGS	+= -fprofile-generate=./profile/mame2003_plus ++	LDFLAGS	+= -lgcov ++else ifeq ($(PROFILE), APPLY) ++	CFLAGS	+= -fprofile-use -fprofile-dir=../profile/mame2003_plus -fbranch-probabilities ++endif ++ + ifneq (,$(findstring msvc,$(platform))) + ifeq ($(DEBUG),1) + 	CFLAGS += -MTd diff --git a/patches/snes9x2002/0001-trimui-support.patch b/patches/snes9x2002/0001-trimui-support.patch index eadb54c..1f7659d 100644 --- a/patches/snes9x2002/0001-trimui-support.patch +++ b/patches/snes9x2002/0001-trimui-support.patch @@ -12,7 +12,7 @@ index e42d169..a1f8794 100644  +	AR = $(CROSS_COMPILE)ar  +	SHARED := -shared -Wl,--version-script=libretro/link.T -Wl,--no-undefined  +	CFLAGS += -fsingle-precision-constant -fno-PIC -flto -+	CFLAGS += -DLSB_FIRST -DFAST_ALIGNED_LSB_WORD_ACCESS -DRIGHTSHIFT_IS_SAR ++	CFLAGS += -DLSB_FIRST -DRIGHTSHIFT_IS_SAR  +	CFLAGS += -std=c99 -fomit-frame-pointer -ffast-math -mcpu=arm926ej-s -mtune=arm926ej-s  +	LDFLAGS += -flto  +	OFLAGS += -Ofast -DNDEBUG=1 @@ -2,6 +2,7 @@  #include <stdlib.h>  #include <string.h>  #include "core.h" +#include "main.h"  #include "options.h"  #include "scale.h" @@ -326,6 +327,14 @@ static void scale_sharp_256xXXX_320xXXX(unsigned w, unsigned h, size_t pitch, co  }  static void scale_select_scaler(unsigned w, unsigned h, size_t pitch) { +	double current_aspect_ratio = aspect_ratio > 0 ? aspect_ratio : ((double)w / (double)h); + +	/* mame2000 sets resolutions / aspect ration without notifying +	 * of changes, new should always override old */ +	if (!strcmp(core_name, "mame2000")) { +		current_aspect_ratio = ((double)w / (double)h); +	} +  	scaler = NULL;  	if (blend_args.blend_line != NULL) { @@ -340,13 +349,13 @@ static void scale_select_scaler(unsigned w, unsigned h, size_t pitch) {  	} else if (scale_size == SCALE_SIZE_ASPECT ||  	           (scale_size == SCALE_SIZE_NONE && (w > SCREEN_WIDTH || h > SCREEN_HEIGHT))) {  		dst_w = SCREEN_WIDTH; -		dst_h = SCREEN_WIDTH / aspect_ratio + 0.5; +		dst_h = SCREEN_WIDTH / current_aspect_ratio + 0.5;  		dst_offs = ((SCREEN_HEIGHT-dst_h)/2) * SCREEN_PITCH;  		if (dst_h > SCREEN_HEIGHT) { -			dst_w = SCREEN_HEIGHT * aspect_ratio + 0.5; +			dst_w = SCREEN_HEIGHT * current_aspect_ratio + 0.5;  			dst_h = SCREEN_HEIGHT; -			dst_offs = ((SCREEN_WIDTH-dst_w)/2); +			dst_offs = ((SCREEN_WIDTH-dst_w)/2) * SCREEN_BPP;  		}  	} else if (scale_size == SCALE_SIZE_NONE) {  		unsigned dst_x = ((SCREEN_WIDTH - w) * SCREEN_BPP / 2); @@ -369,7 +378,7 @@ static void scale_select_scaler(unsigned w, unsigned h, size_t pitch) {  		}  	} -	if (!scaler && aspect_ratio == 4.0f / 3.0f && w == 256) { +	if (!scaler && current_aspect_ratio == 4.0f / 3.0f && w == 256) {  		if (scale_filter == SCALE_FILTER_SHARP) {  			scaler = scale_sharp_256xXXX_320xXXX;  			return; @@ -416,6 +425,7 @@ void scale_update_scaler(void) {  void scale(unsigned w, unsigned h, size_t pitch, const void *src, void *dst) {  	if (w != prev.w || h != prev.h || pitch != prev.pitch) { +		PA_INFO("Dimensions changed to %dx%d\n", w, h);  		scale_select_scaler(w, h, pitch);  		prev.w = w; prev.h = h; prev.pitch = pitch;  	}  | 
