OBJS += plugins/cdrcimg/cdrcimg.o
# dfinput
-OBJS += plugins/dfinput/pad.o
+OBJS += plugins/dfinput/main.o plugins/dfinput/pad.o plugins/dfinput/guncon.o
# gui
OBJS += frontend/main.o frontend/plugin.o
ifdef PCNT
CFLAGS += -DPCNT
endif
+ifndef NO_TSLIB
+frontend/%.o: CFLAGS += -DHAVE_TSLIB
+OBJS += frontend/pl_gun_ts.o
+endif
frontend/%.o: CFLAGS += -DIN_EVDEV
frontend/menu.o: frontend/revision.h
emu_action_old = emu_action;
switch (emu_action) {
- case SACTION_NONE:
- return;
case SACTION_ENTER_MENU:
menu_loop();
return;
snprintf(hud_msg, sizeof(hud_msg), "SCREENSHOT TAKEN");
break;
}
+ default:
+ return;
}
hud_new_msg = 3;
return;
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);
}
int main(int argc, char *argv[])
//in_probe();
plat_init();
menu_init(); // loads config
+ pl_init();
if (psxout)
Config.PsxOut = 1;
SACTION_PREV_SSLOT,
SACTION_TOGGLE_FSKIP,
SACTION_SCREENSHOT,
+ SACTION_GUN_TRIGGER = 16,
+ SACTION_GUN_A,
+ SACTION_GUN_B,
+ SACTION_GUN_TRIGGER2,
};
+#define SACTION_GUN_MASK (0x0f << SACTION_GUN_TRIGGER)
+
static inline void emu_set_action(enum sched_action action_)
{
extern enum sched_action emu_action, emu_action_old;
#include "../libpcsxcore/cdrom.h"
#include "../libpcsxcore/psemu_plugin_defs.h"
#include "../libpcsxcore/new_dynarec/new_dynarec.h"
-#include "../plugins/dfinput/pad.h"
+#include "../plugins/dfinput/main.h"
#include "revision.h"
#define MENU_X2 1
static int scaling, filter, cpu_clock, cpu_clock_st, volume_boost;
static char rom_fname_reload[MAXPATHLEN];
static char last_selected_fname[MAXPATHLEN];
-static int warned_about_bios, region, in_type_sel;
+static int warned_about_bios, region, in_type_sel1, in_type_sel2;
static int memcard1_sel, memcard2_sel;
int g_opts;
Config.PsxAuto = 0;
Config.PsxType = region - 1;
}
- in_type = in_type_sel ? PSE_PAD_TYPE_ANALOGPAD : PSE_PAD_TYPE_STANDARD;
+ switch (in_type_sel1) {
+ case 1: in_type1 = PSE_PAD_TYPE_ANALOGPAD; break;
+ case 2: in_type1 = PSE_PAD_TYPE_GUNCON; break;
+ default: in_type1 = PSE_PAD_TYPE_STANDARD;
+ }
+ switch (in_type_sel2) {
+ case 1: in_type2 = PSE_PAD_TYPE_ANALOGPAD; break;
+ case 2: in_type2 = PSE_PAD_TYPE_GUNCON; break;
+ default: in_type2 = PSE_PAD_TYPE_STANDARD;
+ }
if (in_evdev_allow_abs_only != allow_abs_only_old) {
pandora_rescan_inputs();
allow_abs_only_old = in_evdev_allow_abs_only;
volume_boost = 0;
region = 0;
- in_type_sel = 0;
+ in_type_sel1 = in_type_sel2 = 0;
in_evdev_allow_abs_only = 0;
Config.Xa = Config.Cdda = Config.Sio =
Config.SpuIrq = Config.RCntFix = Config.VSyncWA = 0;
CE_INTVAL(state_slot),
CE_INTVAL(cpu_clock),
CE_INTVAL(g_opts),
- CE_INTVAL(in_type_sel),
+ CE_INTVAL(in_type_sel1),
+ CE_INTVAL(in_type_sel2),
CE_INTVAL_P(frameskip),
CE_INTVAL_P(gpu_peops.iUseDither),
CE_INTVAL_P(gpu_peops.dwActFixes),
{ "Toggle Frameskip ", 1 << SACTION_TOGGLE_FSKIP },
{ "Take Screenshot ", 1 << SACTION_SCREENSHOT },
{ "Enter Menu ", 1 << SACTION_ENTER_MENU },
+ { "Gun Trigger ", 1 << SACTION_GUN_TRIGGER },
+ { "Gun A button ", 1 << SACTION_GUN_A },
+ { "Gun B button ", 1 << SACTION_GUN_B },
+ { "Gun Offscreen Trigger", 1 << SACTION_GUN_TRIGGER2 },
{ NULL, 0 }
};
return 0;
}
-static const char *men_in_type_sel[] = { "Standard (SCPH-1080)", "Analog (SCPH-1150)", NULL };
+static const char *men_in_type_sel[] = {
+ "Standard (SCPH-1080)",
+ "Analog (SCPH-1150)",
+ "GunCon",
+ NULL
+};
static const char h_nub_btns[] = "Experimental, keep this OFF if unsure. Select rescan after change.";
+static const char h_notsgun[] = "Don't trigger (shoot) when touching screen in gun games.";
static menu_entry e_menu_keyconfig[] =
{
- mee_handler_id("Player 1", MA_CTRL_PLAYER1, key_config_loop_wrap),
- mee_handler_id("Player 2", MA_CTRL_PLAYER2, key_config_loop_wrap),
- mee_handler_id("Emulator controls", MA_CTRL_EMU, key_config_loop_wrap),
+ mee_handler_id("Player 1", MA_CTRL_PLAYER1, key_config_loop_wrap),
+ mee_handler_id("Player 2", MA_CTRL_PLAYER2, key_config_loop_wrap),
+ mee_handler_id("Emulator/Gun controls", MA_CTRL_EMU, key_config_loop_wrap),
mee_label (""),
- mee_enum ("Controller", 0, in_type_sel, men_in_type_sel),
+ mee_enum ("Port 1 device", 0, in_type_sel1, men_in_type_sel),
+ mee_enum ("Port 2 device", 0, in_type_sel2, men_in_type_sel),
mee_onoff_h ("Nubs as buttons", 0, in_evdev_allow_abs_only, 1, h_nub_btns),
+ mee_onoff_h ("No TS Gun trigger", 0, g_opts, OPT_TSGUN_NOTRIGGER, h_notsgun),
mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_savecfg, mgn_saveloadcfg),
mee_cust_nosave("Save cfg for loaded game", MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg),
mee_handler ("Rescan devices", mh_input_rescan),
fprintf(stderr, "Warning: GPU_open returned %d\n", ret);
}
- dfinput_activate(in_type == PSE_PAD_TYPE_ANALOGPAD);
+ dfinput_activate();
}
void me_update_msg(const char *msg)
OPT_SHOWCPU = 1 << 1,
OPT_NO_FRAMELIM = 1 << 2,
OPT_SHOWSPU = 1 << 3,
+ OPT_TSGUN_NOTRIGGER = 1 << 4,
};
extern int g_opts;
--- /dev/null
+/*
+ * (C) Gražvydas "notaz" Ignotas, 2011
+ *
+ * This work is licensed under the terms of any of these licenses
+ * (at your option):
+ * - GNU GPL, version 2 or later.
+ * - GNU LGPL, version 2.1 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <tslib.h>
+#include "plugin_lib.h"
+#include "pl_gun_ts.h"
+#include "menu.h"
+#include "../plugins/dfinput/main.h"
+
+static int gun_x, gun_y, gun_in;
+static int ts_multiplier_x, ts_multiplier_y, ts_offs_x, ts_offs_y;
+static int (*pts_read)(struct tsdev *dev, struct ts_sample *sample, int nr);
+
+#define limit(v, min, max) \
+ if (v < min) v = min; \
+ else if (v > max) v = max
+
+void pl_gun_ts_update(struct tsdev *ts, int *x, int *y, int *in)
+{
+ struct ts_sample sample;
+ int sx = 0, sy = 0, sp = 0, updated = 0;
+
+ if (ts != NULL) {
+ while (pts_read(ts, &sample, 1) > 0) {
+ sx = sample.x;
+ sy = sample.y;
+ sp = sample.pressure;
+ updated = 1;
+ }
+
+ if (updated) {
+ gun_x = (sx - ts_offs_x) * ts_multiplier_x >> 10;
+ gun_y = (sy - ts_offs_y) * ts_multiplier_y >> 10;
+ limit(gun_x, 0, 1023);
+ limit(gun_y, 0, 1023);
+ if (sp && !(g_opts & OPT_TSGUN_NOTRIGGER))
+ gun_in |= GUNIN_TRIGGER;
+ else
+ gun_in &= ~GUNIN_TRIGGER;
+ }
+ }
+
+ *x = gun_x;
+ *y = gun_y;
+ *in = gun_in | in_state_gun;
+}
+
+void pl_set_gun_rect(int x, int y, int w, int h)
+{
+ ts_offs_x = x;
+ ts_offs_y = y;
+ ts_multiplier_x = (1<<20) / w;
+ ts_multiplier_y = (1<<20) / h;
+}
+
+struct tsdev *pl_gun_ts_init(void)
+{
+ struct tsdev *(*pts_open)(const char *dev_name, int nonblock) = NULL;
+ int (*pts_config)(struct tsdev *) = NULL;
+ int (*pts_close)(struct tsdev *) = NULL;
+ const char *tsdevname;
+ struct tsdev *ts;
+ void *ltsh;
+
+ tsdevname = getenv("TSLIB_TSDEVICE");
+ if (tsdevname == NULL)
+ tsdevname = "/dev/input/touchscreen0";
+
+ // avoid hard dep on tslib
+ ltsh = dlopen("/usr/lib/libts-1.0.so.0", RTLD_LAZY);
+ if (ltsh == NULL)
+ ltsh = dlopen("/usr/lib/libts-0.0.so.0", RTLD_LAZY);
+ if (ltsh == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ goto fail;
+ }
+
+ pts_open = dlsym(ltsh, "ts_open");
+ pts_config = dlsym(ltsh, "ts_config");
+ pts_read = dlsym(ltsh, "ts_read");
+ pts_close = dlsym(ltsh, "ts_close");
+ if (pts_open == NULL || pts_config == NULL || pts_read == NULL || pts_close == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ goto fail_dlsym;
+ }
+
+ ts = pts_open(tsdevname, 1);
+ if (ts == NULL)
+ goto fail_open;
+ if (pts_config(ts) != 0)
+ goto fail_config;
+
+ // FIXME: we should be able to get this somewhere
+ // the problem is this doesn't always match resolution due to different display modes
+ pl_set_gun_rect(0, 0, 800, 480);
+ return ts;
+
+fail_config:
+ pts_close(ltsh);
+fail_open:
+fail_dlsym:
+ dlclose(ltsh);
+ ltsh = NULL;
+fail:
+ fprintf(stderr, "Could not open touchscreen\n");
+ return NULL;
+}
+
--- /dev/null
+#ifdef HAVE_TSLIB
+
+struct tsdev;
+
+struct tsdev *pl_gun_ts_init(void);
+void pl_gun_ts_update(struct tsdev *ts, int *x, int *y, int *in);
+void pl_set_gun_rect(int x, int y, int w, int h);
+
+#else
+
+#define pl_gun_ts_init() NULL
+#define pl_gun_ts_update(...) do {} while (0)
+
+#endif
#include "linux/fbdev.h"
#include "linux/oshide.h"
#include "plugin_lib.h"
+#include "pl_gun_ts.h"
#include "omap.h"
#include "pandora.h"
int omap_enable_layer(int enabled)
{
+ if (enabled)
+ pl_set_gun_rect(g_layer_x, g_layer_y, g_layer_w, g_layer_h);
+
return omap_setup_layer_(vout_fbdev_get_fd(layer_fb), enabled,
g_layer_x, g_layer_y, g_layer_w, g_layer_h, 0);
}
/* PAD */
static long PADreadPort1(PadDataS *pad)
{
- pad->controllerType = in_type;
+ pad->controllerType = in_type1;
pad->buttonStatus = ~in_keystate;
- if (in_type == PSE_PAD_TYPE_ANALOGPAD) {
+ if (in_type1 == PSE_PAD_TYPE_ANALOGPAD) {
pad->leftJoyX = in_a1[0];
pad->leftJoyY = in_a1[1];
pad->rightJoyX = in_a2[0];
static long PADreadPort2(PadDataS *pad)
{
- pad->controllerType = PSE_PAD_TYPE_STANDARD;
+ pad->controllerType = in_type2;
pad->buttonStatus = ~in_keystate >> 16;
return 0;
}
#include "menu.h"
#include "main.h"
#include "pcnt.h"
+#include "pl_gun_ts.h"
#include "../libpcsxcore/new_dynarec/new_dynarec.h"
#include "../libpcsxcore/psemu_plugin_defs.h"
void *pl_fbdev_buf;
int pl_frame_interval;
-int in_type, in_keystate, in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 };
+int in_type1, in_type2;
+int in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 };
+int in_keystate, in_state_gun;
+static void *ts;
static int pl_fbdev_w, pl_fbdev_h, pl_fbdev_bpp;
static int flip_cnt, vsync_cnt, flips_per_sec, tick_per_sec;
static float vsps_cur;
static int vsync_usec_time;
-static int get_cpu_ticks(void)
+
+static __attribute__((noinline)) int get_cpu_ticks(void)
{
static unsigned long last_utime;
static int fd;
unsigned int emu_act;
in_update(actions);
- if (in_type == PSE_PAD_TYPE_ANALOGPAD)
+ if (in_type1 == PSE_PAD_TYPE_ANALOGPAD)
in_update_analogs();
emu_act = actions[IN_BINDTYPE_EMU];
+ in_state_gun = (emu_act & SACTION_GUN_MASK) >> SACTION_GUN_TRIGGER;
+
+ emu_act &= ~SACTION_GUN_MASK;
if (emu_act) {
int which = 0;
for (; !(emu_act & 1); emu_act >>= 1, which++)
#endif
}
+void pl_update_gun(int *xn, int *xres, int *y, int *in)
+{
+ if (ts)
+ pl_gun_ts_update(ts, xn, y, in);
+
+ *xres = pl_fbdev_w;
+ *y = *y * pl_fbdev_h >> 10;
+}
+
#define MAX_LAG_FRAMES 3
#define tvdiff(tv, tv_old) \
fprintf(stderr, "could not start watchdog: %d\n", ret);
}
+void pl_init(void)
+{
+ ts = pl_gun_ts_init();
+}
DKEY_CROSS,
DKEY_SQUARE,
};
-extern int in_type, in_keystate, in_a1[2], in_a2[2];
+extern int in_type1, in_type2;
+extern int in_keystate, in_state_gun, in_a1[2], in_a2[2];
void in_update_analogs(void);
extern void *pl_fbdev_buf;
void pl_text_out16(int x, int y, const char *texto, ...);
void pl_start_watchdog(void);
void *pl_prepare_screenshot(int *w, int *h, int *bpp);
+void pl_init(void);
+
+void pl_update_gun(int *xn, int *xres, int *y, int *in);
struct rearmed_cbs {
void (*pl_get_layer_pos)(int *x, int *y, int *w, int *h);
typedef struct
{
- uint32_t flags;
- uint32_t status;
+ unsigned int flags;
+ unsigned int status;
void* window;
unsigned char reserved[100];
} gpuQueryS;
static GtkWidget *window, *drawing;
void *pl_fbdev_buf;
-int in_type = PSE_PAD_TYPE_STANDARD;
+int in_type1 = PSE_PAD_TYPE_STANDARD, in_type2 = PSE_PAD_TYPE_STANDARD;
int in_keystate, in_a1[2], in_a2[2];
static int keymap[65536];
--- /dev/null
+/*
+ * (C) Gražvydas "notaz" Ignotas, 2011
+ *
+ * This work is licensed under the terms of any of these licenses
+ * (at your option):
+ * - GNU GPL, version 2 or later.
+ * - GNU LGPL, version 2.1 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <string.h>
+#include "main.h"
+
+static unsigned char buf[8];
+
+unsigned char PADpoll_guncon(unsigned char value)
+{
+ if (CurByte == 0) {
+ CurCmd = value;
+ CurByte++;
+ return 0x63; // regardless of cmd
+ }
+
+ if (CurCmd != 0x42 || CurByte >= 8)
+ return 0xff; // verified
+
+ return buf[CurByte++];
+}
+
+unsigned char PADstartPoll_guncon(int pad)
+{
+ int x, xn = 0, y = 0, in = 0, xres = 256;
+ CurByte = 0;
+
+ buf[2] = buf[3] = 0xff;
+ pl_update_gun(&xn, &xres, &y, &in);
+
+ // while y = const + line counter, what is x?
+ // for 256 mode, hw dumped offsets x, y: 0x5a, 0x20
+ //x = 0x5a + (356 * xn >> 10);
+ x = 0x5a - (xres - 256) / 3 + (((xres - 256) / 3 + 356) * xn >> 10);
+ y = 0x20 + y;
+
+ if (in & GUNIN_TRIGGER)
+ buf[3] &= ~0x20;
+ if (in & GUNIN_BTNA)
+ buf[2] &= ~0x08;
+ if (in & GUNIN_BTNB)
+ buf[3] &= ~0x40;
+ if (in & GUNIN_TRIGGER2) {
+ buf[3] &= ~0x20;
+ x = 1;
+ y = 10;
+ }
+ buf[4] = x;
+ buf[5] = x >> 8;
+ buf[6] = y;
+ buf[7] = y >> 8;
+
+ return 0xff;
+}
+
+void guncon_init(void)
+{
+ memset(buf, 0xff, sizeof(buf));
+ buf[1] = 0x5a;
+}
+
--- /dev/null
+/*
+ * (C) Gražvydas "notaz" Ignotas, 2011
+ *
+ * This work is licensed under the terms of any of these licenses
+ * (at your option):
+ * - GNU GPL, version 2 or later.
+ * - GNU LGPL, version 2.1 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "main.h"
+
+unsigned char CurPad, CurByte, CurCmd, CmdLen;
+
+/* since this is not a proper plugin, so we'll hook emu internals in a hackish way like this */
+extern void *PAD1_startPoll, *PAD1_poll;
+extern void *PAD2_startPoll, *PAD2_poll;
+extern unsigned char PAD1__startPoll(int pad);
+extern unsigned char PAD2__startPoll(int pad);
+extern unsigned char PAD1__poll(unsigned char value);
+extern unsigned char PAD2__poll(unsigned char value);
+
+static int old_controller_type1 = -1, old_controller_type2 = -1;
+
+#define select_pad(n) \
+ if (pad.controllerType != old_controller_type##n) \
+ { \
+ switch (pad.controllerType) \
+ { \
+ case PSE_PAD_TYPE_ANALOGPAD: \
+ PAD##n##_startPoll = PADstartPoll_pad; \
+ PAD##n##_poll = PADpoll_pad; \
+ pad_init(); \
+ break; \
+ case PSE_PAD_TYPE_GUNCON: \
+ PAD##n##_startPoll = PADstartPoll_guncon; \
+ PAD##n##_poll = PADpoll_guncon; \
+ guncon_init(); \
+ break; \
+ case PSE_PAD_TYPE_GUN: \
+ default: \
+ PAD##n##_startPoll = PAD##n##__startPoll; \
+ PAD##n##_poll = PAD##n##__poll; \
+ break; \
+ } \
+ }
+
+void dfinput_activate(void)
+{
+ PadDataS pad;
+
+ PAD1_readPort1(&pad);
+ select_pad(1);
+
+ PAD2_readPort2(&pad);
+ select_pad(2);
+}
--- /dev/null
+#include "../../libpcsxcore/psemu_plugin_defs.h"
+
+extern unsigned char CurPad, CurByte, CurCmd, CmdLen;
+
+/* analog pad */
+unsigned char PADpoll_pad(unsigned char value);
+unsigned char PADstartPoll_pad(int pad);
+void pad_init(void);
+
+/* GunCon */
+unsigned char PADpoll_guncon(unsigned char value);
+unsigned char PADstartPoll_guncon(int pad);
+void guncon_init(void);
+
+void dfinput_activate(void);
+
+/* get button state and pad type from main emu */
+extern long (*PAD1_readPort1)(PadDataS *pad);
+extern long (*PAD2_readPort2)(PadDataS *pad);
+
+/* get gunstate from emu frontend, x range 0-1023 */
+#define GUNIN_TRIGGER (1<<0)
+#define GUNIN_BTNA (1<<1)
+#define GUNIN_BTNB (1<<2)
+#define GUNIN_TRIGGER2 (1<<3) /* offscreen trigger */
+extern void pl_update_gun(int *xn, int *xres, int *y, int *in);
#include <stdint.h>
#include "../../libpcsxcore/psemu_plugin_defs.h"
+#include "main.h"
enum {
ANALOG_LEFT = 0,
0x00}
};
-static uint8_t CurPad = 0, CurByte = 0, CurCmd = 0, CmdLen = 0;
static uint8_t *buf;
static uint8_t do_cmd(void)
}
}
-static unsigned char PADpoll_(unsigned char value) {
+#if 0
+#include <stdio.h>
+unsigned char PADpoll_(unsigned char value);
+unsigned char PADpoll(unsigned char value) {
+ unsigned char b = CurByte, r = PADpoll_(value);
+ printf("poll[%d] %02x %02x\n", b, value, r);
+ return r;
+}
+#define PADpoll PADpoll_
+#endif
+
+unsigned char PADpoll_pad(unsigned char value) {
if (CurByte == 0) {
CurCmd = value;
return buf[CurByte++];
}
-#if 0
-#include <stdio.h>
-static unsigned char PADpoll(unsigned char value) {
- unsigned char b = CurByte, r = PADpoll_(value);
- printf("poll[%d] %02x %02x\n", b, value, r);
- return r;
-}
-#else
-#define PADpoll PADpoll_
-#endif
-
-/* hack.. */
-extern long (*PAD1_readPort1)(PadDataS *pad);
-
-static unsigned char PADstartPoll1(int pad) {
- CurPad = 0;
+unsigned char PADstartPoll_pad(int pad) {
+ CurPad = pad - 1;
CurByte = 0;
- PAD1_readPort1(&padstate[0].pad);
+ if (pad == 1)
+ PAD1_readPort1(&padstate[0].pad);
+ else
+ PAD2_readPort2(&padstate[1].pad);
return 0xFF;
}
-/* some more hacks here but oh well */
-extern void *PAD1_startPoll, *PAD1_poll;
-
-void dfinput_activate(int yes)
+void pad_init(void)
{
- static void *old_start, *old_poll;
-
- if (!yes) {
- if (PAD1_startPoll == PADstartPoll1)
- PAD1_startPoll = old_start;
- if (PAD1_poll == PADpoll)
- PAD1_poll = old_poll;
- return;
- }
-
- if (PAD1_startPoll == PADstartPoll1 && PAD1_poll == PADpoll)
- return;
-
- old_start = PAD1_startPoll;
- old_poll = PAD1_poll;
- PAD1_startPoll = PADstartPoll1;
- PAD1_poll = PADpoll;
+ int i;
PAD1_readPort1(&padstate[0].pad);
- padstate[0].PadID = padstate[0].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD ? 0x73 : 0x41;
- padstate[0].PadMode = padstate[0].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD;
+ PAD2_readPort2(&padstate[1].pad);
- padstate[1].PadID = 0x41;
- padstate[1].PadMode = 0;
+ for (i = 0; i < 2; i++) {
+ padstate[i].PadID = padstate[i].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD ? 0x73 : 0x41;
+ padstate[i].PadMode = padstate[i].pad.controllerType == PSE_PAD_TYPE_ANALOGPAD;
+ }
}
-
+++ /dev/null
-void dfinput_activate(int yes);
-