Page 1 of 1
6Button reading routine, C code and a glitch!.
Posted: Fri Aug 21, 2009 7:38 am
by Fonzie
Hi Guys,
I've been trying to edit the classic 3button reading function so it can handle 6buttons as well.
The idea is to always read twice the joypad (even if its 3button), and look if the second read is different than the first (if so, its 6button joypad, ORRRRR bad contacts!).
That sounds like a horrible idea, heh?
My idea was to get the stuff done as fast as possible (without the trick to query the joypad).
It works, but it has some glitches time to time (like once every 10 minutes of play).
Is there anyway to improve it without loosing too much speed?
C, still.
Since I'm not relying on Vint, it would be awesome to have workaround for the famous "bad result if read more than once per frame" syndrome.
Bellow is my current code.
I'm storing result in WORDS, instead of the good old BYTE of Kaneda's routines
I'm never really fresh when it comes to such stuff ^^ And programming in general, seems
Code: Select all
pb = (uchar *) 0xa10003;
*pb = 0x40;
asm("nop");
asm("nop");
asm("nop");
i = *pb & 0x3f; //6 lower bits
*pb = 0;
asm("nop");
asm("nop");
asm("nop");
j = (*pb & 0x30) << 2; //2 top bits
fvr_joypad_result[1]=(i|j); /*p1*/
//Other read
*pb = 0x40;
asm("nop");
asm("nop");
*pb = 0;
asm("nop");
asm("nop");
//Other read to enable 6 button
*pb = 0x40;
asm("nop");
asm("nop");
j=(*pb);
*pb = 0;
if((fvr_joypad_result[1]&0xF)!=(j&0xF))//6 button pad :)
{
j<<=8;//Shift J result
fvr_joypad_result[1]|=j;
fvr_joypad_result[1]=~fvr_joypad_result[1];
fvr_joypad_result[1]=fvr_joypad_result[1]&0xFFF;
}
else
{
fvr_joypad_result[1]=~fvr_joypad_result[1];
fvr_joypad_result[1]=fvr_joypad_result[1]&0xFF;
}
Thanks for your help.
Fonzie
Posted: Fri Aug 21, 2009 8:48 am
by HardWareMan
My 6-button routine:
Code: Select all
*Buttons map
JoyUp equ $0001
JoyDown equ $0002
JoyUpDown equ $0003
JoyLeft equ $0004
JoyRight equ $0008
JoyLeftRight equ $000C
JoyCursor equ $000F
JoyB equ $0010
JoyC equ $0020
JoyA equ $0040
JoyABC equ $0070
JoyStart equ $0080
JoyABCS equ $00F0
JoyZ equ $0100
JoyY equ $0200
JoyX equ $0400
JoyMode equ $0800
JoyMS equ $0880
JoyXYZM equ $0F00
JoyAnyButton equ $0FF0
JoyAnyKey equ $0FFF
*Joypad polling
clr.l d0 *Clear d0
clr.l d1 *Clear d1
move.b #$40,$A10003 *SYN = 1
nop *Delay
nop *Delay
move.b $A10003,d1 *Reading first 6 buttons
andi.b #$3F,d1 *Mask it
move.b #$00,$A10003 *SYN = 0
nop *Delay
nop *Delay
move.b $A10003,d0 *Read second 2 buttons
and.b #$30,d0 *Mask it
rol.b #2,d0 *Shift by 2 bits
or.b d0,d1 *Combine basic 8 buttons and store it to d1
move.b #$40,$A10003 *SYN = 1
nop *Delay
nop *Delay
move.b #$00,$A10003 *SYN = 0
nop *Delay
nop *Delay
move.b #$40,$A10003 *SYN = 1
nop *Delay
nop *Delay
move.b #$00,$A10003 *SYN = 0
nop *Delay
nop *Delay
move.b #$40,$A10003 *SYN = 1
nop *Delay
nop *All this for unlock extra buttons (XYZM)
move.b $A10003,d0 *Read extra buttons
andi.b #$0F,d0 *Mask it
eor.b #$0F,d0 *Invert it
rol.l #8,d0 *Shift it by 8 bits
or.w d1,d0 *Combine it with basic buttons
not.b d0 *Invert basic buttons
move.b #$40,$A10003 *SYN = 1
move.w d0,KeyState *Save joystick state
And I think, that second byte (when first time you set SYN=0) contains in LRUD field an ID, wich will different for each hardware, and 0xF for unattached open port. At least Comix Zone, using this field, recognize 3 or 6 button pads.
I wish to get full ID table of Genesis/MD peripheral hardware.
And one more thing: 6 button joypad, when you set it to extra button mode for reading them, needs some time to reset own state. So, you can't read twice 6 button joypad so fast.
Posted: Fri Aug 21, 2009 9:50 am
by GManiac
You can borrow 6-button routine from any original game, for example, from Comix Zone. I did so
It even detects 3/6 button joypad after reading.
up: oh, I'm inattentive. Never mind.
Posted: Fri Aug 21, 2009 9:56 am
by Eke
I wish to get full ID table of Genesis/MD peripheral hardware.
is that what you want ?
Posted: Fri Aug 21, 2009 11:47 am
by HardWareMan
Eke wrote:I wish to get full ID table of Genesis/MD peripheral hardware.
is that what you want ?
Yes. But this is incomplete information, isn't it?
PS {img} tags not working. But URLs is works fine.
Posted: Fri Aug 21, 2009 1:03 pm
by Eke
Yes. But this is incomplete information, isn't it?
what other peripheral hardware are they ?
Justifier,Menacer, EA 4-Way-Play ?
From game disassembling, I know Justifier lightguns should return 0x01 and it seems Menacer returns 0x00
Posted: Fri Aug 21, 2009 4:05 pm
by Chilly Willy
Here's the code I use to read 3/6 button controllers. Anyone who wishes to use it is free to do so.
Code: Select all
| get current pad value
| entry: a0 = pad control port
| exit: d2 = pad value (0 0 0 1 M X Y Z S A C B R L D U) or (0 0 0 0 0 0 0 0 S A C B R L D U)
get_pad:
bsr.b get_input /* - 0 s a 0 0 d u - 1 c b r l d u */
move.w d0,d1
andi.w #0x0C00,d0
bne.b no_pad
bsr.b get_input /* - 0 s a 0 0 d u - 1 c b r l d u */
bsr.b get_input /* - 0 s a 0 0 0 0 - 1 c b m x y z */
move.w d0,d2
bsr.b get_input /* - 0 s a 1 1 1 1 - 1 c b r l d u */
andi.w #0x0F00,d0 /* 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 */
cmpi.w #0x0F00,d0
beq.b common /* six button pad */
move.w #0x010F,d2 /* three button pad */
common:
lsl.b #4,d2 /* - 0 s a 0 0 0 0 m x y z 0 0 0 0 */
lsl.w #4,d2 /* 0 0 0 0 m x y z 0 0 0 0 0 0 0 0 */
andi.w #0x303F,d1 /* 0 0 s a 0 0 0 0 0 0 c b r l d u */
move.b d1,d2 /* 0 0 0 0 m x y z 0 0 c b r l d u */
lsr.w #6,d1 /* 0 0 0 0 0 0 0 0 s a 0 0 0 0 0 0 */
or.w d1,d2 /* 0 0 0 0 m x y z s a c b r l d u */
eori.w #0x1FFF,d2 /* 0 0 0 1 M X Y Z S A C B R L D U */
rts
no_pad:
move.w #0xF000,d2
rts
| read single phase from controller
get_input:
move.b #0x00,(a0)
nop
nop
move.b (a0),d0
move.b #0x40,(a0)
lsl.w #8,d0
move.b (a0),d0
rts
Posted: Fri Aug 21, 2009 9:13 pm
by TmEE co.(TM)
You can read 6button pad few times a frame, but its best if you read things only once, and since frame is the smallest time unit in a typical frame based game engine(not taking Hints into account), you don't really need to read things more.
I'd just have a controller type detection routine and do a single IF when reading controllers... its highly unlikely someone changes controllers while playing, and when it happens, the one must suffer the possible consequences
Posted: Sat Aug 22, 2009 5:51 am
by HardWareMan
Eke wrote:...EA 4-Way-Play ?
This schematic was developed at 1994-1995.
It was tested on all AE Sports (i'm problably a spammer, NHL, NBA) and works fine with "Street Racer" too. Don't surely remeber, but it works with "General Chaos" too, I guess. As you can see, EA 4Way Play use first port for ID. And it must be 0x3 (I guess it just test D3 and D2 =0, D1 and D0 don't care. And this status must be all time, except joypad reading. And this was start point for development this device for me (I accidentally connect D0-D3 to GND, and "Street Racer" unblocked menus for 4 players mode). In middle 90s I don't had PC and internet, so I don't use dissassembler.
PS Zero Tolerance link cable was developed by me too, just analyzing port pin activity.
Posted: Sat Aug 22, 2009 6:20 am
by Chilly Willy
TmEE co.(TM) wrote:You can read 6button pad few times a frame, but its best if you read things only once, and since frame is the smallest time unit in a typical frame based game engine(not taking Hints into account), you don't really need to read things more.
I'd just have a controller type detection routine and do a single IF when reading controllers... its highly unlikely someone changes controllers while playing, and when it happens, the one must suffer the possible consequences
I call my pad routines during the vertical blank, and only if the last call didn't return 0xF000 (which meant there was no pad there). If you call it during the vertical blank regardless of the previous return, it allows you to sense controllers being changed on the fly.
Posted: Mon Aug 24, 2009 3:25 am
by 8bitwizard
Did you declare pb as volatile?
Posted: Tue Aug 25, 2009 3:01 am
by Fonzie
pb as volatile?
Yep I did sir!
Thank you all for posting.
>HardWareMan
Seeing your code. I was wondering... Lets say there is a 3button joypad plugged, how would you be sure that X/Y/Z/Mode wouldn't reflect UP/DOWN/LEFT/RIGHT ?
I dont see any test in your code (I'm newbie at asm!).
At least Comix Zone, using this field, recognize 3 or 6 button pads.
Umm ok, but then it means that 6button joypad have a specific ID compared to 3buttons one
And given the doc posted by Eke, they share same id (0xd?)
>Chilly Willy
Ok, so from what I understood, you suppose its 6 buttons IF next reads return 1111 bits on the X's read.
"
bsr.b get_input /* - 0 s a 1 1 1 1 - 1 c b r l d u */
andi.w #0x0F00,d0 /* 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 */
cmpi.w #0x0F00,d0
"
Ok, so after many toggling, it finaly returns 1111...
I think I got the logic, i'll try to improve my C code!
Thanks guys!