Code Monkey home page Code Monkey logo

joydev's Introduction

Aim

In certain NES games, execution of special attack moves requires pressing multiple buttons in a particular order.

For example, Teenage Mutant Ninja Turtles 3 for NES requires pressing A + B combination to execute the special attack.

Is it possible to use a single spare button (like X or Y) press to simulate pressing of the A + B combination?

gamepad

Details

When executing the special attack (by actually executing the A + B combination), we can obtain the following trace from jstest program,

$ jstest /dev/input/js0
Axes:  0:     0  1:     0 Buttons:  0:off  1:on   2:off  3:off
Axes:  0:     0  1:     0 Buttons:  0:off  1:on   2:on   3:off
Axes:  0:     0  1:     0 Buttons:  0:off  1:on   2:off  3:off
Axes:  0:     0  1:     0 Buttons:  0:off  1:off  2:off  3:off

I have modified the joydev kernel driver to implement these "state transitions" when the Y button is pressed.

From a12297c000216e81ab2394c246a5888369ab246a Mon Sep 17 00:00:00 2001
From: Dhiru Kholia <[email protected]>
Date: Sat, 22 Apr 2017 20:37:33 +0530
Subject: [PATCH] USB gamepad hack to trigger "special attack" by a single
 keypress

$ jstest /dev/input/js0

For special attack in "Teenage Mutant Ninja Turtles III: The Manhattan
Project" we require,

Axes:  0:     0  1:     0 Buttons:  0:off  1:on   2:off  3:off
Axes:  0:     0  1:     0 Buttons:  0:off  1:on   2:on   3:off
Axes:  0:     0  1:     0 Buttons:  0:off  1:on   2:off  3:off
Axes:  0:     0  1:     0 Buttons:  0:off  1:off  2:off  3:off
---
 drivers/input/joydev.c | 41 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 39 insertions(+), 2 deletions(-)

diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 29d677c..7b8f816 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -148,8 +148,45 @@ static void joydev_event(struct input_handle *handle,
 	event.time = jiffies_to_msecs(jiffies);

 	rcu_read_lock();
-	list_for_each_entry_rcu(client, &joydev->client_list, node)
-		joydev_pass_event(client, &event);
+	// B = 2, A = 1, Y = 3 (on a USB SNES gamepad)
+	list_for_each_entry_rcu(client, &joydev->client_list, node) {
+		// When Y is pressed, simulate special attack (A + B), which
+		// requires the following transitions.
+		//
+		// Axes:  0:     0  1:     0 Buttons:  0:off  1:on   2:off  3:off
+		// Axes:  0:     0  1:     0 Buttons:  0:off  1:on   2:on   3:off
+		// Axes:  0:     0  1:     0 Buttons:  0:off  1:on   2:off  3:off
+		// Axes:  0:     0  1:     0 Buttons:  0:off  1:off  2:off  3:off
+		if (event.number == 3) { // something to do with Y button
+			if (event.value == 1) { // Y press
+				// A on
+				event.type = JS_EVENT_BUTTON;
+				event.number = 1;
+				event.value = 1;
+				joydev_pass_event(client, &event);
+				// B on
+				event.type = JS_EVENT_BUTTON;
+				event.time = event.time + 80;
+				event.number = 2;
+				event.value = 1;
+				joydev_pass_event(client, &event);
+				// B off
+				event.type = JS_EVENT_BUTTON;
+				event.time = event.time + 160;
+				event.number = 2;
+				event.value = 0;
+				joydev_pass_event(client, &event);
+				// A off
+				event.time = event.time + 30;
+				event.number = 1;
+				event.value = 0;
+				joydev_pass_event(client, &event);
+			} else { // do nothing on Y unpress
+			}
+		} else {
+			joydev_pass_event(client, &event);
+		}
+	}
 	rcu_read_unlock();

 	wake_up_interruptible(&joydev->wait);
--
2.7.4

Problem

With the patched joydev driver, jstest seems to work OK (use jstest --event /dev/input/js0 to verify this). When I actually press the Y button, it seems to emulate A + B pressing combination.

The kernel modifications seem to be OK. See the puNES-joystick-debug.patch puNES patch for verify that the modified joystick events are successfully reaching puNES.

However, special moves in the games do not get triggered in emulation softwares like FCEUX or puNES.

I am wondering what/where the problem is. Do I need to introduce some artifical delay between the four joydev_pass_event calls in my patch?

Update: I added the required delays using the mdelay function but still no joy. The actual delay doesn't seem to happen between the joydev_pass_event calls for some unknown reason.

References

joydev's People

Contributors

kholia avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.