phijor / ctroller

Use your 3DS as a gamepad on linux
GNU General Public License v3.0
39 stars 12 forks source link

[Feature Request] Touchpad as Button zones? #12

Open lmachucab opened 4 years ago

lmachucab commented 4 years ago

This software is pretty good, in the first place. I've been using it for a while.

I was wondering if there was the possibility to extend the configurability of this program to allow the user to set sections of the 3DS's Touchpad as virtual Buttons, thus extending the capacity in number of buttons, or even number of axes, that the physical console can provide.

This would be particularly useful in contexts where you want to use your 3DS as a controller for a system that does not have a concept of, or a use for, the touchpad input. Using it as a N64 controller for example would allow to set button zones for the C-directional buttons, or in the PS2/PS3 would allow to set up zones as the L2 / R2 buttons.

In general, this would benefit users of physical "original" 3DS more than "New" 3DS but I would presume the latter could still find some use to it. Users of consoles with more button entries than the 3DS, such as the N64 or the Play Station consoles, would also benefit.

Furthermore, depending on the number of virtual buttons that can be added this would allow ready access to an emulator's functions if the emulator is capable of associating gamepad commands to their own menu options (such as save/load game states, system pause, etc).

For an example of already existing implementation of the concept see the touchpad panels in the Monster Hunter series 3 and 4 for the 3DS, which provide both "action buttons" on the panel and a mirror of the physical D-pad, that can be used on the right side of the screen so players of the 3DS model can access the functions with their right hand. This Siliconera article showcases a touchpad panel with a D-pad control and an action button (the "kick" icon on the screen). Here's the star screenshot reproduced:

Monster Hunter example usage of touchpad panels

I'm unsure how would this be implemented, but I would presume that native touchscreen and "button zones" would be mutually exclusive. The latter could use a (series of) template describing which areas of the screen are converted to what J0x input (IINM, from J0A onward?).

I've taken the liberty of elaborating crappy ASCII mockups for example:

+-----------+----+-----------+
|           |    |           |
|   (J10)   |    |  (J11)    |
+-----------+----+-----------+
|                            |
|                            |
|           (J12)            |
|                            |
+----------------------------+

Users could map eg.:

Input on the feasibility of this would be appreciated. Also I have my physical system available for testing.

EDIT: Another mockup~

+--------------------+-------+
|                    |       |
|                    |   A   |
|                    +---+---+
|                    | B | C |
|                    +---+---+
|           E        |   D   |
|                    |       |
+--------------------+-------+

In this example users could map entries A, B, C, D, to the four C↑ C↓ C← C→ buttons of the N64 and could then map E to... who knows, Z?

hugojmaia commented 4 years ago

I managed to do this.

I haven't poked around the 3ds side of things, so the touchscreen there still shows the info text. 320 pixels wide and 240 pixels tall, you can chop it up any way you want with the px and py value checks.

Just for fun here's the block of if's for your first mockup:

if (touch && hid->touchscreen.px < 140 && hid->touchscreen.py < 60)
    events[8].value = 1;
if (touch && hid->touchscreen.px > 179 && hid->touchscreen.py < 60)
    events[9].value = 1; 

Idk yet how to add more buttons to this, but say you wanna do one of the cstick positions for (J12) Between events[i].value = hid->cstick.dx; and i++ add:

if (touch && hid->touchscreen.py > 59)
    events[i].value = 30000

30000 is way above the 40% mark many emulators use to detect analog input. In case of the x value, positive is right, negative is left. For y value, negative is up, positive is down.

I had fun cracking this thing, next step is figure out how to build a cia for the 3ds and have something drawn on the screen.

lmachucab commented 4 years ago

Wow, I had been looking at the code, very specifically at the same devices/gamepad.c file, I just couldn't figure out which things went where.

I'll give this a try in my local copy for the first mockup. If anything, it should already cover a lot.

I presume the 3DS side of things would also require changing the observable behaviour of the application in that it wouldn't no longer not redraw the lower screen. From what I recall from similar applications that perform gamepad functionality for the PSP, avoiding drawing the screen when in gamepad mode was also a battery-saving measure, is this also true for the 3DS CIA?

hugojmaia commented 4 years ago

I can't say anything about how it uses up the battery on my 3DS. Never ran any tests on it and had either the 3DS already plugged in or it was at full charge when booting up ctroller on the system for a gaming session of 5 hours max.

I have some plans for this thing, namely give things on the 3ds side an interface of some sort and hopefully an IP input box with a confirm button, so it doesn't crash the console when the IP is wrong. And on the desktop side it'll need a better framework on button remapping and maybe treat the d-pad like a digital set of axis like any other usb controller (It's how modern hardware prevents left+right or up+down inputs).

But first I have to figure out how to properly release my current set of changes to my fork on github, it's still unchanged from the original and I also need to figure out how to properly link the libraries to be able to build it for the 3DS.