Hornpipe2 Posted February 26, 2008 Share Posted February 26, 2008 My joystick checking routines span pages and pages. Has anyone got an efficient technique for polling joysticks? The best I can do is a series of: CheckP1Up LDA #%00000001 BIT SWCHA BNE CheckP1Down (do something) CheckP1Down LDA #%00000010 BIT SWCHA BNE CheckP1Right (do something) ... It may be that what I'm really looking for is a good solution to: (decrement a counter, but only if it's above 0) or (decrement a counter, but if it goes below 0, reset it to N) Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted February 26, 2008 Share Posted February 26, 2008 LDA SWCHA ROR BCS CheckP1Down (do P1 up) CheckP1Down: ROR BCS CheckP1Left (do P1 down) CheckP1Left: ROR BCS CheckP1Right (do P1 left) CheckP1Right: ROR BCS CheckP0Up (do P1 right) CheckP0Up: etc Only issue is you need to preserve A in the (do xxxx) sections. Can do something like: PHA (do something) PLA if you have the stack free, TAX (do something) TXA if you're routine isn't using X or TAY (do something) TYA if your routine isn't using Y Quote Link to comment Share on other sites More sharing options...
Devin Posted February 27, 2008 Share Posted February 27, 2008 You could also use a table approach: LDA SWCHA BIT JOY_UP BEQ JoystickUp BIT JOY_DOWN BEQ JoystickDown BIT JOY_LEFT BEQ JoystickLeft BIT JOY_RIGHT BEQ JoystickRight ;=== No input JMP JoystickEnd JoystickUp ... JMP JoystickEnd JoystickDown ... JMP JoystickEnd JoystickLeft ... JMP JoystickEnd JoystickRight ... JMP JoystickEnd ;---------------------------------------- ;Table. Has to be memory for BIT command ;---------------------------------------- JOY_UP .byte #%00010000 ;Up bit JOY_DOWN .byte #%00100000 ;Down bit JOY_LEFT .byte #%01000000 ;Left bit JOY_RIGHT .byte #%10000000 ;Right bit JoystickEnd Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted February 27, 2008 Share Posted February 27, 2008 My joystick checking routines span pages and pages. Has anyone got an efficient technique for polling joysticks? The best I can do is a series of: CheckP1Up LDA #%00000001 BIT SWCHA BNE CheckP1Down (do something) CheckP1Down LDA #%00000010 BIT SWCHA BNE CheckP1Right (do something) ... It will depend on what you want to happen when the stick is moved one way or another, but the most efficient method I can think of is to read the joystick and store it all at once in a variable, then use that variable as an index into two tables-- an x motion table, and a y motion table. The following code is in batari Basic, but can be easily converted into assembly: dim joy0 = temp6 joy0 = SWCHA / 16 : rem * for joy1, use joy1 = SWCHA player0x = player0x + xmotion[joy0] : rem * 0, 1, or 255 (i.e., -1) player0y = player0y + ymotion[joy0] : rem * 0, 1, or 255 (i.e., -1) rem * etc. data xmotion 0,0,0,0,1,1,1,1,255,255,255,255,0,0,0,0 end data ymotion 0,1,255,0,0,1,255,0,0,1,255,0,0,1,255,0 end It may be that what I'm really looking for is a good solution to: (decrement a counter, but only if it's above 0) or (decrement a counter, but if it goes below 0, reset it to N) I'm not sure what you're getting at here, or what it has to do with polling a joystick-- unless you're wanting to implement some kind of "debounce" logic? I think that for a joystick, you might want to use two debounce flags/counters-- one for x (left/right), and one for y (up/down). Michael Quote Link to comment Share on other sites More sharing options...
TROGDOR Posted February 27, 2008 Share Posted February 27, 2008 (edited) My joystick checking routines span pages and pages. Has anyone got an efficient technique for polling joysticks? The best I can do is a series of: CheckP1Up LDA #%00000001 BIT SWCHA BNE CheckP1Down (do something) CheckP1Down LDA #%00000010 BIT SWCHA BNE CheckP1Right (do something) ... It may be that what I'm really looking for is a good solution to: (decrement a counter, but only if it's above 0) or (decrement a counter, but if it goes below 0, reset it to N) Be careful when reading SWCHA. It's generally better to load SWCHA into a register or a temp variable at the start of your joystick routine. Don't do multiple checks directly against SWCHA in one frame. The danger is that the user will happen to press the joystick in the middle of the joystick checking routine, which would cause SWCHA to change state in the middle of the logic. This caused a nasty transitional logic bug in Master of Arcturus. I generally use a technique similar to Supercat, except I store the register in a temp var so I don't have to worry about preservation. However, I really like Michael's lookup technique. It's very elegant, definitely faster, and may even be less ROM. I may try this out in Stellar Fortress. Edited February 27, 2008 by TROGDOR Quote Link to comment Share on other sites More sharing options...
Cybergoth Posted February 27, 2008 Share Posted February 27, 2008 You could also use a table approach: Nice idea for BIT usage, but there's no advantage over the standard bit-shifting approach Darrel posted, which is not only a lot more efficient, but will also handle diagonal movement automatically. You can even just loop it back to the first shift and do the second joystick with the same code, if you hold a player index (0 or 1) in the X or Y register, executing stuff like INC xPos,X in the branches. Quote Link to comment Share on other sites More sharing options...
TROGDOR Posted February 27, 2008 Share Posted February 27, 2008 (edited) Here's what Michael's routine would look like in assembly: LDA SWCHA LSR LSR LSR LSR TAY ; Store for later use. LSR LSR ; A now holds D7 and D6 from SWCHA in bits 1 and 0. TAX LDA JoyDeltaTable,X CLC ADC Xloc STA Xloc TYA AND #%00000011 TAX LDA JoyDeltaTable,X EOR #$FF SEC ; 2s Compliment from the above EOR. ADC Yloc STA Yloc JoyDeltaTable .byte #0 .byte #1 .byte #255 .byte #0 Note that by adding two more LSRs in the X delta check, and using a 2s compliment on the Y delta, you can reduce the 32 byte ROM table down to just 4 bytes. I haven't tested this code, but it looks like it should work. Edited February 27, 2008 by TROGDOR Quote Link to comment Share on other sites More sharing options...
Cybergoth Posted February 27, 2008 Share Posted February 27, 2008 Here's what Michael's routine would look like in assembly: It does neither look faster, nor smaller than the bit-shifting code. Add in the need for boundry checks and you'll realize that with this approach you actually don't even know where you're going Quote Link to comment Share on other sites More sharing options...
TROGDOR Posted February 28, 2008 Share Posted February 28, 2008 Here's what Michael's routine would look like in assembly: It does neither look faster, nor smaller than the bit-shifting code. Add in the need for boundry checks and you'll realize that with this approach you actually don't even know where you're going Details. Details. I was having so much fun optimizing the look-up code, I didn't go back and byte/cycle count the bit-shifting code. You burst my bubble. Bit shifting is definitely the way to go. But without the 2s complement, it's not nearly as sexy. Quote Link to comment Share on other sites More sharing options...
Cybergoth Posted February 28, 2008 Share Posted February 28, 2008 Details. Details. I was having so much fun optimizing the look-up code, I didn't go back and byte/cycle count the bit-shifting code. You burst my bubble. Bit shifting is definitely the way to go. But without the 2s complement, it's not nearly as sexy. Well, the bit-shifting code is just 4 times this: ROR; or any other shifter BCS NotMe INC/DEC pos That is 20 bytes and 31/32 cycles depending on wether the stick is pushed straight or diagonal. Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted February 28, 2008 Share Posted February 28, 2008 Here's what Michael's routine would look like in assembly: It does neither look faster, nor smaller than the bit-shifting code. Add in the need for boundry checks and you'll realize that with this approach you actually don't even know where you're going Details. Details. I was having so much fun optimizing the look-up code, I didn't go back and byte/cycle count the bit-shifting code. You burst my bubble. Bit shifting is definitely the way to go. But without the 2s complement, it's not nearly as sexy. I admit that my example wasn't as compact (smaller/faster) as the bit-shifting approach, but using the joystick bits as an index into a 16-byte table can still be useful. As I said, it really depends on what you want to have happen when the stick is pushed in a given direction. For example, you could identify all nine directions separately (the ninth direction being the center), so that "up-left" could be detected all at once without having to check for "up" and then check for "left" as well. Also, in my "xmotion" and "ymotion" tables, I took contradictory readings into account, such as "up-left-down," which would amount to just "left," since "up" and "down" would cancel each other out. True, you can't (or aren't supposed to be able to) push the stick in opposite directions at the same time-- but I've read that some games had Easter eggs that required the player to push the stick in all four directions at once, and you could detect that sort of situation very easily if you treat all 4 bits as a single value ranging from 0 to 15. On the other hand, if you had one of those funky "up-left-down" situations with the bit-shift approach, you would end up moving up, then moving left, then moving down, so you would waste time moving up and then down when you could have just ignored those two motions (since they cancel each other out). Additionally, the table could be expanded to 32 bytes-- 2 bytes per index value-- to get 16 JMP vectors, if for some reason you wanted to have a different routine for each possible direction, including the "contradictory" directions. For instance, you could have one Easter egg triggered by "up-down," a different Easter egg triggered by "up-left-down," etc. Michael Quote Link to comment Share on other sites More sharing options...
Cybergoth Posted February 28, 2008 Share Posted February 28, 2008 but using the joystick bits as an index into a 16-byte table can still be useful. I usually use that direction table coming from the other side, i.e. I pick a random value, look up the direction bits from the table and voilà: AI joystick input! As you are already mentioning, usually 13 bytes are good enough, since 1100 is the highest combo a joystick can do. You can use the 7 unused bit patterns to put an emphasis on (a) certain direction(s) for the AI though. Quote Link to comment Share on other sites More sharing options...
Hornpipe2 Posted April 14, 2008 Author Share Posted April 14, 2008 (edited) One simple optimization if you're going with the bit-shifting code: CheckP0Right LDA SWCHA BMI CheckLeft ... CheckP0Left ROL BMI CheckDown ... CheckP0Down ROL BMI CheckUp ... CheckP0Up ROL BMI CheckP1Right ... CheckP1Right ... Using BMI and ROL shaves off that initial rotate to set Carry Bit, saving a byte and 2 cycles : ) Edited April 14, 2008 by Hornpipe2 Quote Link to comment Share on other sites More sharing options...
Cybergoth Posted April 14, 2008 Share Posted April 14, 2008 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.