frontend: initial libretro support
authornotaz <notasas@gmail.com>
Sun, 29 Jul 2012 00:23:29 +0000 (03:23 +0300)
committernotaz <notasas@gmail.com>
Sun, 29 Jul 2012 15:09:56 +0000 (18:09 +0300)
..and some refactoring

Makefile
configure
frontend/libretro.c [new file with mode: 0644]
frontend/libretro.h [new file with mode: 0644]
frontend/main.c
frontend/main.h
maemo/hildon.c
maemo/main.c
plugins/gpu-gles/gpulib_if.c

index 527ddd9..5739ef8 100644 (file)
--- 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
 
index 00511bd..6552ef5 100755 (executable)
--- 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 (file)
index 0000000..29276bd
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 (file)
index 0000000..8aa579e
--- /dev/null
@@ -0,0 +1,333 @@
+#ifndef LIBRETRO_H__
+#define LIBRETRO_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#else
+#if defined(_MSC_VER) && !defined(__cplusplus)
+#define bool unsigned char
+#define true 1
+#define false 0
+#else
+#include <stdbool.h>
+#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
index 15eae71..bb6aaa9 100644 (file)
@@ -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;
index 9483798..bdb4870 100644 (file)
 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);
 
index 8e7635a..afe7bb2 100644 (file)
@@ -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_;
index 7412791..2da693d 100644 (file)
@@ -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;
index c669b63..ce7f00d 100644 (file)
@@ -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),