diff --git a/dynamic.h b/dynamic.h
index 79ed70ab16d..0f1d238ee75 100644
--- a/dynamic.h
+++ b/dynamic.h
@@ -68,6 +68,13 @@ struct retro_core_t
unsigned poll_type;
uint8_t flags;
+
+ /**
+ * Arbitrary core data.
+ *
+ * @see RETRO_ENVIRONMENT_GET_CORE_DATA
+ */
+ void *core_data;
};
diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h
index 1d7e765a55d..6c5d4ce374c 100644
--- a/libretro-common/include/libretro.h
+++ b/libretro-common/include/libretro.h
@@ -2574,6 +2574,32 @@ enum retro_mod
*/
#define RETRO_ENVIRONMENT_GET_FILE_BROWSER_START_DIRECTORY 80
+/**
+ * Sets a pointer to arbitrary data for the actively running core.
+ *
+ * Intended for use as a substitute for global state, which is a common
+ * source of bugs. Can be set in either \c retro_init() or \c retro_load_game().
+ *
+ * @param[in] data void *. Pointer to the data to set.
+ * @return \c true if the environment call is available.
+ *
+ * @see RETRO_ENVIRONMENT_GET_CORE_DATA
+ */
+#define RETRO_ENVIRONMENT_SET_CORE_DATA (81 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+
+/**
+ * Gets a pointer to arbitrary data for the actively running core.
+ *
+ * This is persistent for the lifetime of the core until \c retro_deinit() is called.
+ *
+ * @param[out] data void **. Pointer to the data that was set.
+ * May be \c NULL if the data was not set yet.
+ * @return \c true if the environment call is available.
+ *
+ * @see RETRO_ENVIRONMENT_SET_CORE_DATA
+ */
+#define RETRO_ENVIRONMENT_GET_CORE_DATA (82 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+
/**@}*/
/**
diff --git a/runloop.c b/runloop.c
index 80c8891cce7..507c02f5dac 100644
--- a/runloop.c
+++ b/runloop.c
@@ -3556,6 +3556,18 @@ bool runloop_environment_cb(unsigned cmd, void *data)
}
}
break;
+
+ case RETRO_ENVIRONMENT_SET_CORE_DATA:
+ runloop_st->current_core.core_data = data;
+ break;
+
+ case RETRO_ENVIRONMENT_GET_CORE_DATA:
+ if (data != NULL) {
+ void **core_data = (void **)data;
+ *core_data = runloop_st->current_core.core_data;
+ }
+ break;
+
default:
RARCH_LOG("[Environ]: UNSUPPORTED (#%u).\n", cmd);
return false;