joypad management in PVSnesLib - state sometimes reset

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
joypad management in PVSnesLib - state sometimes reset
by on (#236548)
Hello,

Still with PVSneslib, i would like to run with main sprite when right key is pressed twice.

I saw that when you keep button pressed, its state is sometimes reset.

This minimal code reproduce issue :

Code:
//#include <snes.h>
#include "snes/console.h"
#include "snes/interrupt.h"
#include "snes/pad.h"

int main(void)
{
   consoleInit();   
   unsigned short pad0;
   
   //setMode(BG_MODE1,0);
   //bgSetDisable(1);
   //bgSetDisable(2);
   //setScreenOn();
   
   while(true)
   {
      pad0 = padsCurrent(0);
      if (pad0 & KEY_DOWN)
      {
         consoleNocashMessage("PRESSED\r\n");
      }
      else
         consoleNocashMessage("RELEASED\r\n");
      
      WaitForVBlank();
   }
   return 0;
}


If you check console in no$sns, you will find "released" lines between "pressed"
I checked in pvsneslib how is managed pads and scanPads function which give state for pad0 = padsCurrent(0); is called during VBlank,

Function is wrote in asm and i am not familiar with it :

Code:
;---------------------------------------------------------------------------------
; void scanPads(void)
scanPads:
   php
   phb
   phy
   
   sep   #$20                                   ; change bank address to 0
   lda.b   #$0
   pha
   plb
   
   rep   #$20                                   ; copy joy states
   ldy   pad_keys
   sty   pad_keysold
   ldy   pad_keys+2
   sty   pad_keysold+2
   
;-:   lda   REG_SLHV                                   ; wait until past lines 224,225
;   lda   REG_OPHCT
;   cmp   #224
;   beq   -
;   cmp   #225
;   beq   -

-:   lda   REG_HVBJOY                             ; wait until joypads are ready
   lsr
   bcs -

   lda   REG_JOY1L                              ; read joypad register #1
   bit   #$0F                                   ; catch non-joypad input
   beq   +                                      ; (bits 0-3 should be zero)
   lda.b   #$0
+   sta   pad_keys                               ; store 'current' state
   eor   pad_keysold                            ; compute 'down' state from bits that
   and   pad_keys                               ; have changed from 0 to 1
   sta   pad_keysrepeat                         ;

   lda   REG_JOY2L                              ; read joypad register #2
   bit   #$0F                                   ; catch non-joypad input
   beq   +                                      ; (bits 0-3 should be zero)
   lda.b   #$0
+   sta   pad_keys+2                             ; store 'current' state
   eor   pad_keysold+2                          ; compute 'down' state from bits that
   and   pad_keys+2                             ; have changed from 0 to 1
   sta   pad_keysrepeat+2                       ;

   ply
   plb
   plp
   rtl


i tried to compare it with other implementation sample but my level doesn't permit to say if it is correct or not.

Can you say me if you think something is wrong or if it doesn't come from this function ?

If you have any other idea that could explain this issue, i will be happy to hear clues :)

Thanks for your help
Re: joypad management in PVSnesLib - state sometimes reset
by on (#236593)
I add few informations. This is the main.c file generated to asm file, juste before using wla:

Code:
.include "hdr.asm"
.accu 16
.index 16
.16bit
.define __main_locals 2
.section ".text_0x0" superfree
main:
.ifgr __main_locals 0
tsa
sec
sbc #__main_locals
tas
.endif
jsr.l consoleInit
__local_2:
lda.l pad_keys + 0
sta -2 + __main_locals + 1,s
and.w #1024
sta.b tcc__r0
lda.b tcc__r0 ; DON'T OPTIMIZE
bne +
brl __local_0
+
pea.w :__tccs_L.5
pea.w __tccs_L.5 + 0
jsr.l consoleNocashMessage
tsa
clc
adc #4
tas
bra __local_1
__local_0:
pea.w :__tccs_L.6
pea.w __tccs_L.6 + 0
jsr.l consoleNocashMessage
tsa
clc
adc #4
tas
__local_1:
jsr.l WaitForVBlank
bra __local_2
lda.w #0
sta.b tcc__r0
__local_3:
.ifgr __main_locals 0
tsa
clc
adc #__main_locals
tas
.endif
rtl
.ends
.ramsection "ram.data" bank $7f slot 3
__local_dummy.data dsb 1
.ends
.section ".data" superfree
__local_dummy.data: .db 0
.ends
.section ".rodata" superfree
__tccs_L.5: .db $50,$52,$45,$53,$53,$45,$44,$d,$a,$0
__tccs_L.6: .db $52,$45,$4c,$45,$41,$53,$45,$44,$d,$a,$0
.ends



.ramsection ".bss" bank $7e slot 2
__local_dummybss dsb 1
.ends


Is it possible that it is a bug while generating this one ?
I try to locate where the bug comes from, if it is in PVSnesLib or in tool used after to build the rom.
Re: joypad management in PVSnesLib - state sometimes reset
by on (#236595)
hoit wrote:
-: lda REG_HVBJOY ; wait until joypads are ready
lsr
bcs -
Checking that [$004212] & $01 is clear at the start of your function does not mean that it will remain clear when you actually read the registers, especially if you execute this code immediately after waiting for vblank.

That's what gave me problems here.
Re: joypad management in PVSnesLib - state sometimes reset
by on (#236598)
In other words, have two loops instead of one: wait until it's set, then wait until it's clear.
Re: joypad management in PVSnesLib - state sometimes reset
by on (#236676)
I hoped it was only a line to change!
I need to learn 65816 asm to do this because i don't know how to implement it.

Thanks for you help
Re: joypad management in PVSnesLib - state sometimes reset
by on (#236686)
Here's the change you need to make. This:
Code:
-:   lda   REG_HVBJOY                             ; wait until joypads are ready
   lsr
   bcs -

needs to be:
Code:
-:   lda   REG_HVBJOY                             ; wait until joypads are being read
   lsr
   bcc -

-:   lda   REG_HVBJOY                             ; wait until joypads are ready
   lsr
   bcs -
Re: joypad management in PVSnesLib - state sometimes reset
by on (#236692)
I think I'd actually recommend ignoring the VBlank bit altogether and just synchronizing to the AutoRead bit instead...
Re: joypad management in PVSnesLib - state sometimes reset
by on (#236722)
Thanks for these informations.
I juste tried this code but my issue is still existing : i get few release states when button is pressed.

So i investigated on the second solution to understand (with autoread bit in NMI) and it seems to be already implemented in the lib :

I saw this in ConsoleInit() function (the first function to call in program) :

// enable NMI, enable autojoy
REG_NMITIMEN = INT_VBLENABLE | INT_JOYPAD_ENABLE;


and INT_JOYPAD_ENABLE is declared like that :
#define INT_JOYPAD_ENABLE (1)
Joypad Enable (0=Disable, 1=Enable Automatic Reading of Joypad)


Do you have any other idea ? :)