From 38c2028e228dcf17f3b4b0ac7e6984d1e1c6df79 Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 29 Jul 2012 03:23:29 +0300 Subject: [PATCH 1/1] frontend: initial libretro support ..and some refactoring --- Makefile | 43 +++-- configure | 25 ++- frontend/libretro.c | 345 +++++++++++++++++++++++++++++++++++ frontend/libretro.h | 333 +++++++++++++++++++++++++++++++++ frontend/main.c | 98 +++++----- frontend/main.h | 6 + maemo/hildon.c | 4 - maemo/main.c | 15 +- plugins/gpu-gles/gpulib_if.c | 3 +- 9 files changed, 791 insertions(+), 81 deletions(-) create mode 100644 frontend/libretro.c create mode 100644 frontend/libretro.h diff --git a/Makefile b/Makefile index 527ddd92..5739ef8d 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ endif #DRC_DBG = 1 #PCNT = 1 -all: config.mak $(TARGET) plugins_ +all: config.mak target_ plugins_ ifneq ($(wildcard config.mak),) config.mak: ./configure @@ -111,28 +111,43 @@ OBJS += plugins/dfinput/main.o plugins/dfinput/pad.o plugins/dfinput/guncon.o # gui OBJS += frontend/main.o frontend/plugin.o -OBJS += frontend/plugin_lib.o frontend/common/readpng.o -OBJS += frontend/common/fonts.o frontend/linux/plat.o -ifeq "$(PLATFORM)" "maemo" -OBJS += maemo/hildon.o maemo/main.o -maemo/%.o: maemo/%.c -else -OBJS += frontend/menu.o frontend/linux/in_evdev.o -OBJS += frontend/common/input.o +OBJS += frontend/common/readpng.o frontend/common/fonts.o +OBJS += frontend/linux/plat.o ifeq "$(PLATFORM)" "generic" OBJS += frontend/plat_sdl.o frontend/common/in_sdl.o +USE_FRONTEND = 1 endif ifeq "$(PLATFORM)" "pandora" OBJS += frontend/linux/fbdev.o OBJS += frontend/plat_omap.o frontend/linux/xenv.o OBJS += frontend/plat_pandora.o +USE_FRONTEND = 1 endif ifeq "$(PLATFORM)" "caanoo" OBJS += frontend/plat_pollux.o frontend/in_tsbutton.o frontend/blit320.o OBJS += frontend/gp2x/in_gp2x.o frontend/warm/warm.o +USE_FRONTEND = 1 +endif +ifeq "$(PLATFORM)" "maemo" +OBJS += maemo/hildon.o maemo/main.o +maemo/%.o: maemo/%.c +OBJS += frontend/plugin_lib.o +endif +ifeq "$(PLATFORM)" "libretro" +OBJS += frontend/libretro.o +endif +ifeq "$(USE_FRONTEND)" "1" +OBJS += frontend/menu.o frontend/linux/in_evdev.o +OBJS += frontend/common/input.o +OBJS += frontend/plugin_lib.o +ifeq "$(HAVE_TSLIB)" "1" +frontend/%.o: CFLAGS += -DHAVE_TSLIB +OBJS += frontend/pl_gun_ts.o +endif +else +CFLAGS += -DNO_FRONTEND endif -endif # !maemo ifdef X11 frontend/%.o: CFLAGS += -DX11 @@ -141,12 +156,8 @@ endif ifdef PCNT CFLAGS += -DPCNT endif -ifeq "$(HAVE_TSLIB)" "1" -frontend/%.o: CFLAGS += -DHAVE_TSLIB -OBJS += frontend/pl_gun_ts.o -endif frontend/%.o: CFLAGS += -DIN_EVDEV -frontend/menu.o frontend/plat_sdl.o: frontend/revision.h +frontend/menu.o frontend/main.o frontend/plat_sdl.o: frontend/revision.h libpcsxcore/gte_nf.o: libpcsxcore/gte.c $(CC) -c -o $@ $^ $(CFLAGS) -DFLAGLESS @@ -160,6 +171,8 @@ frontend/revision.h: FORCE %.o: %.S $(CC) $(CFLAGS) -c $^ -o $@ +target_: $(TARGET) + $(TARGET): $(OBJS) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) -Wl,-Map=$@.map diff --git a/configure b/configure index 00511bd1..6552ef52 100755 --- a/configure +++ b/configure @@ -24,9 +24,9 @@ check_define() # setting options to "yes" or "no" will make that choice default, # "" means "autodetect". -platform_list="generic pandora maemo caanoo" +platform_list="generic pandora maemo caanoo libretro" platform="generic" -sound_driver_list="oss alsa none" +sound_driver_list="oss alsa libretro none" sound_driver="alsa" plugins="plugins/spunull/spunull.so \ plugins/dfxvideo/gpu_peops.so plugins/gpu_unai/gpu_unai.so" @@ -74,6 +74,9 @@ set_platform() drc_cache_base="yes" optimize_arm926ej="yes" ;; + libretro) + sound_driver="libretro" + ;; *) echo "unsupported platform: $platform" exit 1 @@ -118,7 +121,7 @@ if [ "$show_help" = "yes" ]; then fi case "$sound_driver" in -oss|alsa|none) +oss|alsa|libretro|none) ;; *) echo "unsupported sound driver: $sound_driver" @@ -201,17 +204,24 @@ if [ "$ram_fixed" = "yes" ]; then CFLAGS="$CFLAGS -DRAM_FIXED" fi -if [ "$platform" = "generic" ]; then +case "$platform" in +generic) generic_cflags=`sdl-config --cflags` generic_ldlibs=`sdl-config --libs` CFLAGS="$CFLAGS $generic_cflags" LDFLAGS="$LDFLAGS $generic_ldlibs" -elif [ "$platform" = "maemo" ]; then + ;; +maemo) maemo_cflags=`pkg-config --cflags hildon-1` maemo_ldlibs=`pkg-config --libs hildon-1` CFLAGS="$CFLAGS -DMAEMO -DMAEMO_CHANGES $maemo_cflags" LDFLAGS="$LDFLAGS $maemo_ldlibs" -fi + ;; +libretro) + CFLAGS="$CFLAGS -fPIC" + LDFLAGS="$LDFLAGS -shared" + ;; +esac # check for tslib (only headers needed) if [ "x$have_tslib" = "x" ]; then @@ -277,6 +287,9 @@ echo "LDLIBS += $LDLIBS" >> $config_mak echo "PLUGIN_CFLAGS += $PLUGIN_CFLAGS" >> $config_mak echo >> $config_mak +if [ "$platform" = "libretro" ]; then + echo "TARGET = libretro.so" >> $config_mak +fi echo "ARCH = $ARCH" >> $config_mak echo "PLATFORM = $platform" >> $config_mak case "$sound_driver" in diff --git a/frontend/libretro.c b/frontend/libretro.c new file mode 100644 index 00000000..29276bda --- /dev/null +++ b/frontend/libretro.c @@ -0,0 +1,345 @@ +/* + * (C) notaz, 2012 + * + * This work is licensed under the terms of the GNU GPLv2 or later. + * See the COPYING file in the top-level directory. + */ + +#include +#include +#include + +#include "../libpcsxcore/misc.h" +#include "../libpcsxcore/psxcounters.h" +#include "../libpcsxcore/new_dynarec/new_dynarec.h" +#include "main.h" +#include "plugin.h" +#include "plugin_lib.h" +#include "revision.h" +#include "libretro.h" + +static retro_video_refresh_t video_cb; +static retro_input_poll_t input_poll_cb; +static retro_input_state_t input_state_cb; +static retro_environment_t environ_cb; +static retro_audio_sample_batch_t audio_batch_cb; + +static void *vout_buf; +static int vout_width, vout_height; +static int samples_sent, samples_to_send; +static int plugins_opened; + +/* PCSX ReARMed core calls and stuff */ +int in_type1, in_type2; +int in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 }; +int in_keystate; +int in_enable_vibration; + +static int vout_open(void) +{ + return 0; +} + +static void *vout_set_mode(int w, int h, int bpp) +{ + vout_width = w; + vout_height = h; + return vout_buf; +} + +/* FIXME: either teach PCSX to blit to RGB1555 or RetroArch to support RGB565 */ +static void convert(void *buf, size_t size) +{ + unsigned int i, v, *p = buf; + + for (i = 0; i < size / 2; i++) { + v = p[i]; + p[i] = (v & 0x001f001f) | ((v >> 1) & 0x7fe07fe0); + } +} + +static void *vout_flip(void) +{ + pl_rearmed_cbs.flip_cnt++; + convert(vout_buf, vout_width * vout_height * 2); + video_cb(vout_buf, vout_width, vout_height, vout_width * 2); + + return vout_buf; +} + +static void vout_close(void) +{ +} + +struct rearmed_cbs pl_rearmed_cbs = { + .pl_vout_open = vout_open, + .pl_vout_set_mode = vout_set_mode, + .pl_vout_flip = vout_flip, + .pl_vout_close = vout_close, + /* from psxcounters */ + .gpu_hcnt = &hSyncCount, + .gpu_frame_count = &frame_counter, +}; + +void pl_frame_limit(void) +{ + /* called once per frame, make psxCpu->Execute() above return */ + stop = 1; +} + +void pl_timing_prepare(int is_pal) +{ +} + +void plat_trigger_vibrate(int is_strong) +{ +} + +void pl_update_gun(int *xn, int *xres, int *y, int *in) +{ +} + +/* sound calls */ +void SetupSound(void) +{ +} + +void RemoveSound(void) +{ +} + +unsigned long SoundGetBytesBuffered(void) +{ + if (samples_to_send > samples_sent) + return 0; /* give more samples */ + else + return 1; +} + +void SoundFeedStreamData(void *buf, long bytes) +{ + audio_batch_cb(buf, bytes / 4); + samples_sent += bytes / 4; +} + +/* libretro */ +void retro_set_environment(retro_environment_t cb) { environ_cb = cb; } +void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; } +void retro_set_audio_sample(retro_audio_sample_t cb) { (void)cb; } +void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { audio_batch_cb = cb; } +void retro_set_input_poll(retro_input_poll_t cb) { input_poll_cb = cb; } +void retro_set_input_state(retro_input_state_t cb) { input_state_cb = cb; } + +unsigned retro_api_version(void) +{ + return RETRO_API_VERSION; +} + +void retro_set_controller_port_device(unsigned port, unsigned device) +{ +} + +void retro_get_system_info(struct retro_system_info *info) +{ + memset(info, 0, sizeof(*info)); + info->library_name = "PCSX-ReARMed"; + info->library_version = REV; + info->valid_extensions = "bin|cue|img|mdf|pbp|cbn"; + info->need_fullpath = true; +} + +void retro_get_system_av_info(struct retro_system_av_info *info) +{ + memset(info, 0, sizeof(*info)); + info->timing.fps = 60; + info->timing.sample_rate = 44100; + info->geometry.base_width = 320; + info->geometry.base_height = 240; + info->geometry.max_width = 640; + info->geometry.max_height = 512; + info->geometry.aspect_ratio = 4.0 / 3.0; +} + +/* TODO */ +size_t retro_serialize_size(void) +{ + return 0; +} + +bool retro_serialize(void *data, size_t size) +{ + return false; +} + +bool retro_unserialize(const void *data, size_t size) +{ + return false; +} + +void retro_cheat_reset(void) +{ +} + +void retro_cheat_set(unsigned index, bool enabled, const char *code) +{ +} + +bool retro_load_game(const struct retro_game_info *info) +{ + if (plugins_opened) { + ClosePlugins(); + plugins_opened = 0; + } + + set_cd_image(info->path); + + /* have to reload after set_cd_image for correct cdr plugin */ + if (LoadPlugins() == -1) { + printf("faled to load plugins\n"); + return false; + } + + plugins_opened = 1; + NetOpened = 0; + + if (OpenPlugins() == -1) { + printf("faled to open plugins\n"); + return false; + } + + plugin_call_rearmed_cbs(); + + Config.PsxAuto = 1; + if (CheckCdrom() == -1) { + printf("unsupported/invalid CD image: %s\n", info->path); + return false; + } + + SysReset(); + + if (LoadCdrom() == -1) { + printf("could not load CD-ROM!\n"); + return false; + } + emu_on_new_cd(); + + return true; +} + +bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info) +{ + return false; +} + +void retro_unload_game(void) +{ +} + +unsigned retro_get_region(void) +{ + return RETRO_REGION_NTSC; +} + +void *retro_get_memory_data(unsigned id) +{ + return NULL; +} + +size_t retro_get_memory_size(unsigned id) +{ + return 0; +} + +void retro_reset(void) +{ + SysReset(); +} + +static const unsigned short retro_psx_map[] = { + [RETRO_DEVICE_ID_JOYPAD_B] = 1 << DKEY_CROSS, + [RETRO_DEVICE_ID_JOYPAD_Y] = 1 << DKEY_SQUARE, + [RETRO_DEVICE_ID_JOYPAD_SELECT] = 1 << DKEY_SELECT, + [RETRO_DEVICE_ID_JOYPAD_START] = 1 << DKEY_START, + [RETRO_DEVICE_ID_JOYPAD_UP] = 1 << DKEY_UP, + [RETRO_DEVICE_ID_JOYPAD_DOWN] = 1 << DKEY_DOWN, + [RETRO_DEVICE_ID_JOYPAD_LEFT] = 1 << DKEY_LEFT, + [RETRO_DEVICE_ID_JOYPAD_RIGHT] = 1 << DKEY_RIGHT, + [RETRO_DEVICE_ID_JOYPAD_A] = 1 << DKEY_CIRCLE, + [RETRO_DEVICE_ID_JOYPAD_X] = 1 << DKEY_TRIANGLE, + [RETRO_DEVICE_ID_JOYPAD_L] = 1 << DKEY_L1, + [RETRO_DEVICE_ID_JOYPAD_R] = 1 << DKEY_R1, + [RETRO_DEVICE_ID_JOYPAD_L2] = 1 << DKEY_L2, + [RETRO_DEVICE_ID_JOYPAD_R2] = 1 << DKEY_R2, + [RETRO_DEVICE_ID_JOYPAD_L3] = 1 << DKEY_L3, + [RETRO_DEVICE_ID_JOYPAD_R3] = 1 << DKEY_R3, +}; +#define RETRO_PSX_MAP_LEN (sizeof(retro_psx_map) / sizeof(retro_psx_map[0])) + +void retro_run(void) +{ + int i; + + input_poll_cb(); + in_keystate = 0; + for (i = 0; i < RETRO_PSX_MAP_LEN; i++) + if (input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, i)) + in_keystate |= retro_psx_map[i]; + in_keystate <<= 16; + for (i = 0; i < RETRO_PSX_MAP_LEN; i++) + if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i)) + in_keystate |= retro_psx_map[i]; + + stop = 0; + psxCpu->Execute(); + + samples_to_send += 44100 / 60; +} + +void retro_init(void) +{ + const char *bios[] = { "scph1001", "scph5501", "scph7001" }; + const char *dir; + char path[256]; + FILE *f = NULL; + int i, ret, level; + + ret = emu_core_preinit(); + ret |= emu_core_init(); + if (ret != 0) { + printf("PCSX init failed, sorry\n"); + exit(1); + } + + vout_buf = malloc(640 * 512 * 2); + + if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir) + { + snprintf(Config.BiosDir, sizeof(Config.BiosDir), "%s/", dir); + + for (i = 0; i < sizeof(bios) / sizeof(bios[0]); i++) { + snprintf(path, sizeof(path), "%s/%s.bin", dir, bios[i]); + f = fopen(path, "r"); + if (f != NULL) { + snprintf(Config.Bios, sizeof(Config.Bios), "%s.bin", bios[i]); + break; + } + } + } + if (f != NULL) { + printf("found BIOS file: %s\n", Config.Bios); + fclose(f); + } + else + printf("no BIOS files found.\n"); + + level = 1; + environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); +} + +void retro_deinit(void) +{ + SysClose(); + free(vout_buf); + vout_buf = NULL; +} + diff --git a/frontend/libretro.h b/frontend/libretro.h new file mode 100644 index 00000000..8aa579e8 --- /dev/null +++ b/frontend/libretro.h @@ -0,0 +1,333 @@ +#ifndef LIBRETRO_H__ +#define LIBRETRO_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#else +#if defined(_MSC_VER) && !defined(__cplusplus) +#define bool unsigned char +#define true 1 +#define false 0 +#else +#include +#endif +#endif + +#define RETRO_API_VERSION 1 + +#define RETRO_DEVICE_MASK 0xff +#define RETRO_DEVICE_NONE 0 +#define RETRO_DEVICE_JOYPAD 1 +#define RETRO_DEVICE_MOUSE 2 +#define RETRO_DEVICE_KEYBOARD 3 +#define RETRO_DEVICE_LIGHTGUN 4 +#define RETRO_DEVICE_ANALOG 5 + +#define RETRO_DEVICE_JOYPAD_MULTITAP ((1 << 8) | RETRO_DEVICE_JOYPAD) +#define RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE ((1 << 8) | RETRO_DEVICE_LIGHTGUN) +#define RETRO_DEVICE_LIGHTGUN_JUSTIFIER ((2 << 8) | RETRO_DEVICE_LIGHTGUN) +#define RETRO_DEVICE_LIGHTGUN_JUSTIFIERS ((3 << 8) | RETRO_DEVICE_LIGHTGUN) + +#define RETRO_DEVICE_ID_JOYPAD_B 0 +#define RETRO_DEVICE_ID_JOYPAD_Y 1 +#define RETRO_DEVICE_ID_JOYPAD_SELECT 2 +#define RETRO_DEVICE_ID_JOYPAD_START 3 +#define RETRO_DEVICE_ID_JOYPAD_UP 4 +#define RETRO_DEVICE_ID_JOYPAD_DOWN 5 +#define RETRO_DEVICE_ID_JOYPAD_LEFT 6 +#define RETRO_DEVICE_ID_JOYPAD_RIGHT 7 +#define RETRO_DEVICE_ID_JOYPAD_A 8 +#define RETRO_DEVICE_ID_JOYPAD_X 9 +#define RETRO_DEVICE_ID_JOYPAD_L 10 +#define RETRO_DEVICE_ID_JOYPAD_R 11 +#define RETRO_DEVICE_ID_JOYPAD_L2 12 +#define RETRO_DEVICE_ID_JOYPAD_R2 13 +#define RETRO_DEVICE_ID_JOYPAD_L3 14 +#define RETRO_DEVICE_ID_JOYPAD_R3 15 + +#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 +#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 +#define RETRO_DEVICE_ID_ANALOG_X 0 +#define RETRO_DEVICE_ID_ANALOG_Y 1 + +#define RETRO_DEVICE_ID_MOUSE_X 0 +#define RETRO_DEVICE_ID_MOUSE_Y 1 +#define RETRO_DEVICE_ID_MOUSE_LEFT 2 +#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 + +#define RETRO_DEVICE_ID_LIGHTGUN_X 0 +#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 +#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 +#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 +#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 +#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 +#define RETRO_DEVICE_ID_LIGHTGUN_START 6 + +#define RETRO_REGION_NTSC 0 +#define RETRO_REGION_PAL 1 + +#define RETRO_MEMORY_MASK 0xff +#define RETRO_MEMORY_SAVE_RAM 0 +#define RETRO_MEMORY_RTC 1 +#define RETRO_MEMORY_SYSTEM_RAM 2 +#define RETRO_MEMORY_VIDEO_RAM 3 + +#define RETRO_MEMORY_SNES_BSX_RAM ((1 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_BSX_PRAM ((2 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM ((3 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM ((4 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_GAME_BOY_RAM ((5 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_GAME_BOY_RTC ((6 << 8) | RETRO_MEMORY_RTC) + +#define RETRO_GAME_TYPE_BSX 0x101 +#define RETRO_GAME_TYPE_BSX_SLOTTED 0x102 +#define RETRO_GAME_TYPE_SUFAMI_TURBO 0x103 +#define RETRO_GAME_TYPE_SUPER_GAME_BOY 0x104 + + +// Environment commands. +#define RETRO_ENVIRONMENT_SET_ROTATION 1 // const unsigned * -- + // Sets screen rotation of graphics. + // Is only implemented if rotation can be accelerated by hardware. + // Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, 270 degrees + // counter-clockwise respectively. + // +#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 // bool * -- + // Boolean value whether or not the implementation should use overscan, or crop away overscan. + // +#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 // bool * -- + // Boolean value whether or not RetroArch supports frame duping, + // passing NULL to video frame callback. + // +#define RETRO_ENVIRONMENT_GET_VARIABLE 4 // struct retro_variable * -- + // Interface to aquire user-defined information from environment + // that cannot feasibly be supported in a multi-system way. + // Mostly used for obscure, + // specific features that the user can tap into when neseccary. + // +#define RETRO_ENVIRONMENT_SET_VARIABLES 5 // const struct retro_variable * -- + // Allows an implementation to signal the environment + // which variables it might want to check for later using GET_VARIABLE. + // 'data' points to an array of retro_variable structs terminated by a { NULL, NULL } element. + // retro_variable::value should contain a human readable description of the key. + // +#define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * -- + // Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'. + // Should not be used for trivial messages, which should simply be logged to stderr. +#define RETRO_ENVIRONMENT_SHUTDOWN 7 // N/A (NULL) -- + // Requests the frontend to shutdown. + // Should only be used if game has a specific + // way to shutdown the game from a menu item or similar. + // +#define RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL 8 + // const unsigned * -- + // Gives a hint to the frontend how demanding this implementation + // is on a system. E.g. reporting a level of 2 means + // this implementation should run decently on all frontends + // of level 2 and up. + // + // It can be used by the frontend to potentially warn + // about too demanding implementations. + // + // The levels are "floating", but roughly defined as: + // 1: Low-powered devices such as Raspberry Pi, smart phones, tablets, etc. + // 2: Medium-spec consoles, such as PS3/360, with sub-par CPUs. + // 3: Modern desktop/laptops with reasonably powerful CPUs. + // 4: High-end desktops with very powerful CPUs. + // + // This function can be called on a per-game basis, + // as certain games an implementation can play might be + // particularily demanding. + // If called, it should be called in retro_load_game(). + // +#define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 + // const char ** -- + // Returns the "system" directory of the frontend. + // This directory can be used to store system specific ROMs such as BIOSes, configuration data, etc. + // The returned value can be NULL. + // If so, no such directory is defined, + // and it's up to the implementation to find a suitable directory. + // +#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 + // const enum retro_pixel_format * -- + // Sets the internal pixel format used by the implementation. + // The default pixel format is RETRO_PIXEL_FORMAT_XRGB1555. + // If the call returns false, the frontend does not support this pixel format. + // This function should be called inside retro_load_game() or retro_get_system_av_info(). + +enum retro_pixel_format +{ + RETRO_PIXEL_FORMAT_0RGB1555 = 0, // 0RGB1555, native endian. 0 bit must be set to 0. + RETRO_PIXEL_FORMAT_XRGB8888 // XRGB8888, native endian. X bits are ignored. +}; + +struct retro_message +{ + const char *msg; // Message to be displayed. + unsigned frames; // Duration in frames of message. +}; + +struct retro_system_info +{ + const char *library_name; // Descriptive name of library. Should not contain any version numbers, etc. + const char *library_version; // Descriptive version of core. + + const char *valid_extensions; // A string listing probably rom extensions the core will be able to load, separated with pipe. + // I.e. "bin|rom|iso". + // Typically used for a GUI to filter out extensions. + + bool need_fullpath; // If true, retro_load_game() is guaranteed to provide a valid pathname in retro_game_info::path. + // ::data and ::size are both invalid. + // If false, ::data and ::size are guaranteed to be valid, but ::path might not be valid. + // This is typically set to true for libretro implementations that must load from file. + // Implementations should strive for setting this to false, as it allows the frontend to perform patching, etc. + + bool block_extract; // If true, the frontend is not allowed to extract any archives before loading the real ROM. + // Necessary for certain libretro implementations that load games from zipped archives. +}; + +struct retro_game_geometry +{ + unsigned base_width; // Nominal video width of game. + unsigned base_height; // Nominal video height of game. + unsigned max_width; // Maximum possible width of game. + unsigned max_height; // Maximum possible height of game. + + float aspect_ratio; // Nominal aspect ratio of game. If aspect_ratio is <= 0.0, + // an aspect ratio of base_width / base_height is assumed. + // A frontend could override this setting if desired. +}; + +struct retro_system_timing +{ + double fps; // FPS of video content. + double sample_rate; // Sampling rate of audio. +}; + +struct retro_system_av_info +{ + struct retro_game_geometry geometry; + struct retro_system_timing timing; +}; + +struct retro_variable +{ + const char *key; // Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. + // If NULL, obtains the complete environment string if more complex parsing is necessary. + // The environment string is formatted as key-value pairs delimited by semicolons as so: + // "key1=value1;key2=value2;..." + const char *value; // Value to be obtained. If key does not exist, it is set to NULL. +}; + +struct retro_game_info +{ + const char *path; // Path to game, UTF-8 encoded. Usually used as a reference. + // May be NULL if rom was loaded from stdin or similar. + // retro_system_info::need_fullpath guaranteed that this path is valid. + const void *data; // Memory buffer of loaded game. Will be NULL if need_fullpath was set. + size_t size; // Size of memory buffer. + const char *meta; // String of implementation specific meta-data. +}; + +// Callbacks +// +// Environment callback. Gives implementations a way of performing uncommon tasks. Extensible. +typedef bool (*retro_environment_t)(unsigned cmd, void *data); + +// Render a frame. Pixel format is 15-bit 0RGB1555 native endian unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). +// Width and height specify dimensions of buffer. +// Pitch specifices length in bytes between two lines in buffer. +typedef void (*retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch); + +// Renders a single audio frame. Should only be used if implementation generates a single sample at a time. +// Format is signed 16-bit native endian. +typedef void (*retro_audio_sample_t)(int16_t left, int16_t right); +// Renders multiple audio frames in one go. One frame is defined as a sample of left and right channels, interleaved. +// I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. +// Only one of the audio callbacks must ever be used. +typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, size_t frames); + +// Polls input. +typedef void (*retro_input_poll_t)(void); +// Queries for input for player 'port'. device will be masked with RETRO_DEVICE_MASK. +// Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that have been set with retro_set_controller_port_device() +// will still use the higher level RETRO_DEVICE_JOYPAD to request input. +typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); + +// Sets callbacks. retro_set_environment() is guaranteed to be called before retro_init(). +// The rest of the set_* functions are guaranteed to have been called before the first call to retro_run() is made. +void retro_set_environment(retro_environment_t); +void retro_set_video_refresh(retro_video_refresh_t); +void retro_set_audio_sample(retro_audio_sample_t); +void retro_set_audio_sample_batch(retro_audio_sample_batch_t); +void retro_set_input_poll(retro_input_poll_t); +void retro_set_input_state(retro_input_state_t); + +// Library global initialization/deinitialization. +void retro_init(void); +void retro_deinit(void); + +// Must return RETRO_API_VERSION. Used to validate ABI compatibility when the API is revised. +unsigned retro_api_version(void); + +// Gets statically known system info. Pointers provided in *info must be statically allocated. +// Can be called at any time, even before retro_init(). +void retro_get_system_info(struct retro_system_info *info); + +// Gets information about system audio/video timings and geometry. +// Can be called only after retro_load_game() has successfully completed. +void retro_get_system_av_info(struct retro_system_av_info *info); + +// Sets device to be used for player 'port'. +void retro_set_controller_port_device(unsigned port, unsigned device); + +// Resets the current game. +void retro_reset(void); + +// Runs the game for one video frame. +// During retro_run(), input_poll callback must be called at least once. +// +// If a frame is not rendered for reasons where a game "dropped" a frame, +// this still counts as a frame, and retro_run() should explicitly dupe a frame if GET_CAN_DUPE returns true. +// In this case, the video callback can take a NULL argument for data. +void retro_run(void); + +// Returns the amount of data the implementation requires to serialize internal state (save states). +// Beetween calls to retro_load_game() and retro_unload_game(), the returned size is never allowed to be larger than a previous returned value, to +// ensure that the frontend can allocate a save state buffer once. +size_t retro_serialize_size(void); + +// Serializes internal state. If failed, or size is lower than retro_serialize_size(), it should return false, true otherwise. +bool retro_serialize(void *data, size_t size); +bool retro_unserialize(const void *data, size_t size); + +void retro_cheat_reset(void); +void retro_cheat_set(unsigned index, bool enabled, const char *code); + +// Loads a game. +bool retro_load_game(const struct retro_game_info *game); + +// Loads a "special" kind of game. Should not be used except in extreme cases. +bool retro_load_game_special( + unsigned game_type, + const struct retro_game_info *info, size_t num_info +); + +// Unloads a currently loaded game. +void retro_unload_game(void); + +// Gets region of game. +unsigned retro_get_region(void); + +// Gets region of memory. +void *retro_get_memory_data(unsigned id); +size_t retro_get_memory_size(unsigned id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/frontend/main.c b/frontend/main.c index 15eae716..bb6aaa95 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -29,6 +29,7 @@ #include "common/readpng.h" #include "common/input.h" #include "linux/in_evdev.h" +#include "revision.h" // don't include debug.h - it breaks ARM build (R1 redefined) void StartDebugger(); @@ -190,15 +191,11 @@ static void check_memcards(void) void do_emu_action(void) { - char buf[MAXPATHLEN]; int ret; emu_action_old = emu_action; switch (emu_action) { - case SACTION_ENTER_MENU: - menu_loop(); - return; case SACTION_LOAD_STATE: ret = emu_load_state(state_slot); snprintf(hud_msg, sizeof(hud_msg), ret == 0 ? "LOADED" : "FAIL!"); @@ -207,6 +204,10 @@ void do_emu_action(void) ret = emu_save_state(state_slot); snprintf(hud_msg, sizeof(hud_msg), ret == 0 ? "SAVED" : "FAIL!"); break; +#ifndef NO_FRONTEND + case SACTION_ENTER_MENU: + menu_loop(); + return; case SACTION_NEXT_SSLOT: state_slot++; if (state_slot > 9) @@ -216,7 +217,12 @@ void do_emu_action(void) state_slot--; if (state_slot < 0) state_slot = 9; - goto do_state_slot; +do_state_slot: + snprintf(hud_msg, sizeof(hud_msg), "STATE SLOT %d [%s]", state_slot, + emu_check_state(state_slot) == 0 ? "USED" : "FREE"); + hud_new_msg = 3; + printf("* %s\n", hud_msg); + break; case SACTION_TOGGLE_FSKIP: pl_rearmed_cbs.fskip_advice = 0; pl_rearmed_cbs.frameskip++; @@ -229,6 +235,7 @@ void do_emu_action(void) break; case SACTION_SCREENSHOT: { + char buf[MAXPATHLEN]; void *scrbuf; int w, h, bpp; time_t t = time(NULL); @@ -253,17 +260,12 @@ void do_emu_action(void) case SACTION_MINIMIZE: plat_minimize(); return; +#endif default: return; } - hud_new_msg = 3; - return; -do_state_slot: - snprintf(hud_msg, sizeof(hud_msg), "STATE SLOT %d [%s]", state_slot, - emu_check_state(state_slot) == 0 ? "USED" : "FREE"); hud_new_msg = 3; - printf("* %s\n", hud_msg); } static int cdidcmp(const char *id1, const char *id2) @@ -380,7 +382,7 @@ void emu_on_new_cd(void) hud_new_msg = 2; } -int main(int argc, char *argv[]) +int emu_core_preinit(void) { // what is the name of the config file? // it may be redefined by -cfg on the command line @@ -391,16 +393,35 @@ int main(int argc, char *argv[]) memset(&Config, 0, sizeof(Config)); - CheckSubDir(); set_default_paths(); emu_set_default_config(); - check_memcards(); strcpy(Config.Bios, "HLE"); -#ifdef MAEMO - extern int maemo_main(int argc, char **argv); - return maemo_main(argc, argv); -#else + return 0; +} + +int emu_core_init(void) +{ + CheckSubDir(); + check_memcards(); + + if (EmuInit() == -1) { + printf("PSX emulator couldn't be initialized.\n"); + return -1; + } + + LoadMcds(Config.Mcd1, Config.Mcd2); + + if (Config.Debug) { + StartDebugger(); + } + + return 0; +} + +#ifndef NO_FRONTEND +int main(int argc, char *argv[]) +{ char file[MAXPATHLEN] = ""; char path[MAXPATHLEN]; const char *cdfile = NULL; @@ -409,6 +430,8 @@ int main(int argc, char *argv[]) int loadst = 0; int i; + emu_core_preinit(); + // read command line options for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-psxout")) psxout = 1; @@ -442,17 +465,16 @@ int main(int argc, char *argv[]) else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) { - printf(PACKAGE_NAME " " PACKAGE_VERSION "\n"); + printf("PCSX-ReARMed " REV "\n"); printf("%s\n", _( " pcsx [options] [file]\n" "\toptions:\n" "\t-cdfile FILE\tRuns a CD image file\n" - "\t-nogui\t\tDon't open the GTK GUI\n" "\t-cfg FILE\tLoads desired configuration file (default: ~/.pcsx/pcsx.cfg)\n" "\t-psxout\t\tEnable PSX output\n" "\t-load STATENUM\tLoads savestate STATENUM (1-5)\n" "\t-h -help\tDisplay this message\n" - "\tfile\t\tLoads file\n")); + "\tfile\t\tLoads a PSX EXE file\n")); return 0; } else { strncpy(file, argv[i], MAXPATHLEN); @@ -471,9 +493,6 @@ int main(int argc, char *argv[]) if (cdfile) set_cd_image(cdfile); - if (SysInit() == -1) - return 1; - // frontend stuff // init input but leave probing to platform code, // they add input drivers and may need to modify them after probe @@ -482,6 +501,8 @@ int main(int argc, char *argv[]) plat_init(); menu_init(); // loads config + emu_core_init(); + if (psxout) Config.PsxOut = 1; @@ -547,33 +568,14 @@ int main(int argc, char *argv[]) do_emu_action(); } - return 0; -#endif -} - -int SysInit() { - if (EmuInit() == -1) { - printf("PSX emulator couldn't be initialized.\n"); - return -1; - } - - LoadMcds(Config.Mcd1, Config.Mcd2); - - if (Config.Debug) { - StartDebugger(); - } - return 0; } +#endif void SysRunGui() { printf("SysRunGui\n"); } -void StartGui() { - printf("StartGui\n"); -} - static void dummy_lace() { } @@ -610,12 +612,12 @@ void SysUpdate() { void OnFile_Exit() { printf("OnFile_Exit\n"); -#ifndef MAEMO - menu_finish(); -#endif SysClose(); +#ifndef NO_FRONTEND + menu_finish(); plat_finish(); exit(0); +#endif } int get_state_filename(char *buf, int size, int i) { @@ -729,7 +731,7 @@ static int _OpenPlugins(void) { MAKE_PATH(dotdir, "/.pcsx/plugins/", NULL); - strcpy(info.EmuName, "PCSX " PACKAGE_VERSION); + strcpy(info.EmuName, "PCSX"); strncpy(info.CdromID, CdromId, 9); strncpy(info.CdromLabel, CdromLabel, 9); info.psxMem = psxM; diff --git a/frontend/main.h b/frontend/main.h index 94837989..bdb48702 100644 --- a/frontend/main.h +++ b/frontend/main.h @@ -35,6 +35,12 @@ extern char cfgfile_basename[MAXPATHLEN]; extern int state_slot; + +/* emu_core_preinit - must be the very first call + * emu_core_init - to be called after platform-specific setup */ +int emu_core_preinit(void); +int emu_core_init(void); + void emu_set_default_config(void); void emu_on_new_cd(void); diff --git a/maemo/hildon.c b/maemo/hildon.c index 8e7635a6..afe7bb2a 100644 --- a/maemo/hildon.c +++ b/maemo/hildon.c @@ -186,10 +186,6 @@ void maemo_init(int *argc, char ***argv) pl_rearmed_cbs.only_16bpp = 1; } -void menu_loop(void) -{ -} - void *plat_gvideo_set_mode(int *w_, int *h_, int *bpp_) { int w = *w_, h = *h_; diff --git a/maemo/main.c b/maemo/main.c index 74127919..2da693d0 100644 --- a/maemo/main.c +++ b/maemo/main.c @@ -38,20 +38,26 @@ static void ChangeWorkingDirectory(char *exe) } } -int maemo_main(int argc, char **argv) +int main(int argc, char **argv) { - ChangeWorkingDirectory("c"); char file[MAXPATHLEN] = ""; char path[MAXPATHLEN]; const char *cdfile = NULL; int loadst = 0; int i; + emu_core_preinit(); + ChangeWorkingDirectory("c"); + strcpy(Config.BiosDir, "/home/user/MyDocs"); strcpy(Config.PluginsDir, "/opt/maemo/usr/games/plugins"); snprintf(Config.PatchesDir, sizeof(Config.PatchesDir), "/opt/maemo/usr/games" PATCHES_DIR); Config.PsxAuto = 1; + pl_init(); + + emu_core_init(); + // read command line options for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-psxout")) Config.PsxOut = 1; @@ -97,11 +103,6 @@ int maemo_main(int argc, char **argv) strcpy(file_name, strrchr(cdfile,'/')); } - if (SysInit() == -1) - return 1; - - pl_init(); - if (LoadPlugins() == -1) { SysMessage("Failed loading plugins!"); return 1; diff --git a/plugins/gpu-gles/gpulib_if.c b/plugins/gpu-gles/gpulib_if.c index c669b634..ce7f00dc 100644 --- a/plugins/gpu-gles/gpulib_if.c +++ b/plugins/gpu-gles/gpulib_if.c @@ -702,7 +702,8 @@ void vout_set_config(const struct rearmed_cbs *cbs) void SetAspectRatio(void) { - cbs->pl_get_layer_pos(&rRatioRect.left, &rRatioRect.top, &rRatioRect.right, &rRatioRect.bottom); + if (cbs->pl_get_layer_pos) + cbs->pl_get_layer_pos(&rRatioRect.left, &rRatioRect.top, &rRatioRect.right, &rRatioRect.bottom); glScissor(rRatioRect.left, iResY-(rRatioRect.top+rRatioRect.bottom), -- 2.39.2