I want to offer an extension for ROM hacks and homebrew to be able to add rumble support to SNES gamepads.
Obviously, this'll be optional, but designed in a way it could work on real hardware if an adapter for a PC gamepad were made.
As for why? Well, why not?
My thought is to add it to the IObit of the gamepads:
Whenever the latch is cleared (1->0 transition), the IObit value, eg $4201.(d7 player 1, d6 player 2) goes into an 8-bit shift register (shift left: x=x<<1|iobit). So basically: set the latch, set IObit, clear the latch to clock it. Repeat eight times. Whenever the shift register == 'F' (for Force Feedback), 0x46, 0b0010'0110, the controller will begin to rumble. Stopping the rumble will be just writing another bit into the register. Whenever the shift register != 'F', rumble stops. I don't know if we should have an automatic timeout (and if so after how long?) or if that just adds to the complexity.
The choice of 'F' is so that no matter what is written in the next six writes, it won't start another rumble:
And when you write 'F' again, it won't activate until the eighth and final write:
Another option we could potentially do while we're at it would be to support analog read-out.
While reading the joypad 16 times to get the controller state from data1, analog axis data would be output to data2. The first 8-bits would be the X-axis, the next 8-bits the Y-axis, in little-endian ordering, so in this way, the results from auto-joypad polling would place X into $4219 (player 1) or $421b (player 2), and Y into $421d (player 1) or $421f (player 2.)
Since this bit reads as 0 with stock controllers, a value of 0x00 will be considered "no analog support present." 0x80 will represent a centered axis, 0x01 will represent up/left, 0xff will represent down/right.
If we're worried about this interfering with existing games, we could require a one-time write of 'A' (for Analog) to the shift-register to unlock the support. But I feel that'd be annoying to have to hook the reset vector of games to enable it in hacks.
Obviously, this isn't compatible with multitaps, so no five-player Super Rumbleman hack.
Is this agreeable? Any feedback (no pun intended)? I just posted v109, so we should have at least a month to work on this with bsnes WIPs and make changes if needed.
...
In the past, Zsnexbox did this via a form of cheat codes. It'd have a list of memory address watchpoints, and whenever those RAM addresses were written, the gamepad would rumble. The upside of it was that the author was able to add support for dozens of games very rapidly.
But the downsides were that it couldn't ever work on real hardware, and there were tons of false positives (games clearing RAM at reset, rumble during other parts of the game like end-of-level scoring when it deducts your health to add to your score, etc etc.)
Like MSU1 and the proposed widescreen, I think if we're going to do it, it needs to be done right to leave a good impression.
Obviously, this'll be optional, but designed in a way it could work on real hardware if an adapter for a PC gamepad were made.
As for why? Well, why not?
My thought is to add it to the IObit of the gamepads:
Whenever the latch is cleared (1->0 transition), the IObit value, eg $4201.(d7 player 1, d6 player 2) goes into an 8-bit shift register (shift left: x=x<<1|iobit). So basically: set the latch, set IObit, clear the latch to clock it. Repeat eight times. Whenever the shift register == 'F' (for Force Feedback), 0x46, 0b0010'0110, the controller will begin to rumble. Stopping the rumble will be just writing another bit into the register. Whenever the shift register != 'F', rumble stops. I don't know if we should have an automatic timeout (and if so after how long?) or if that just adds to the complexity.
The choice of 'F' is so that no matter what is written in the next six writes, it won't start another rumble:
Code:
01000110
1000110x
000110xx
00110xxx
0110xxxx
110xxxxx
10xxxxxx
0xxxxxxx
1000110x
000110xx
00110xxx
0110xxxx
110xxxxx
10xxxxxx
0xxxxxxx
And when you write 'F' again, it won't activate until the eighth and final write:
Code:
01000110
10001100
00011001
00110010
01100100
11001000
10010001
00100011
10001100
00011001
00110010
01100100
11001000
10010001
00100011
Another option we could potentially do while we're at it would be to support analog read-out.
While reading the joypad 16 times to get the controller state from data1, analog axis data would be output to data2. The first 8-bits would be the X-axis, the next 8-bits the Y-axis, in little-endian ordering, so in this way, the results from auto-joypad polling would place X into $4219 (player 1) or $421b (player 2), and Y into $421d (player 1) or $421f (player 2.)
Since this bit reads as 0 with stock controllers, a value of 0x00 will be considered "no analog support present." 0x80 will represent a centered axis, 0x01 will represent up/left, 0xff will represent down/right.
If we're worried about this interfering with existing games, we could require a one-time write of 'A' (for Analog) to the shift-register to unlock the support. But I feel that'd be annoying to have to hook the reset vector of games to enable it in hacks.
Obviously, this isn't compatible with multitaps, so no five-player Super Rumbleman hack.
Is this agreeable? Any feedback (no pun intended)? I just posted v109, so we should have at least a month to work on this with bsnes WIPs and make changes if needed.
...
In the past, Zsnexbox did this via a form of cheat codes. It'd have a list of memory address watchpoints, and whenever those RAM addresses were written, the gamepad would rumble. The upside of it was that the author was able to add support for dozens of games very rapidly.
But the downsides were that it couldn't ever work on real hardware, and there were tons of false positives (games clearing RAM at reset, rumble during other parts of the game like end-of-level scoring when it deducts your health to add to your score, etc etc.)
Like MSU1 and the proposed widescreen, I think if we're going to do it, it needs to be done right to leave a good impression.