Joypad reading timings

Yesterday, Tomy reported a bug on real hardware about the joypad reading in the rom I provided. It happens that I moved the pad reading into an event managed by my event engine processed during NMI. My first tough like Tomy is that there might be a problem reading the pad during NMI interrupt. It was time to read the docs…

The SNES documentation is quite clear about that. Pad should be read 215 (214.55) ┬Ás after the VBlank started (NMI Interrupt is trigered at start of VBlank). They state that it’s a good practice to read the pad after DMA of at least 576 byte.

One other precaution is to not set the joy enable register during VBlank, if it’s not the case readed data might not be valid.

I tried to put it after the proccessEvents(); function but it still seem to not work properly. So I finally set it after the waitForVBlank in the big while loop in main.c. I will analyse some games next week to clarify how they really doing it cleanly.

I still need to finalize the tests with tomy from Tototek. Thanks Tomy for all your testing.

++ Lint

5 Responses to “Joypad reading timings”

  1. Tomy Says:

    I find a semi-fix solution. You can add readPad event in NMI. Add this line to pad.c ,

    while (*(byte*)0×4212 & 0×01);


    padNumber = padNumber << 1;

    Register 0×4212 bit0 is auto read pad status. If it is set, mean data is valid.
    Then you can use joypad to control now. You can enter debug screen and back. Also background can scrolling. But new problem again. You can not use fade-in and fade-out. It will hang.

    Any idea ?

  2. Tomy Says:

    Forgot to say, it will hang on both bsnes and real hardware. So, you can test it on emulator.

  3. Tomy Says:

    Oh, sorry. 0×4212 bit0 set mean reading in progress. Clear mean completed. So, add this line.

    while (!(*(byte*)0×4212 & 0×01)){}

    But it still hang fade-in and fade-out.

  4. lint Says:

    Tanks again a lot Tomy. I missed the usage of the 4212 register. The event function to read the pad is now nicely working, the problem are my events managing functions. When there is 3 events, removeEvent isn’t doing the work really good. So I will check that this week if I find time (I might be quite busy all week). Then i should refine event functions so I can add an event where i need to, or make sure it’s always at end of queue, I will certainly do something based on a priority value.

    ++ Lint

  5. Tomy Says:

    I tested it. If I removed these two lines, it work good.

    addEvent(&mosaicIn, 1);
    addEvent(&mosaicOut, 1);

    But if scrolling is running, you do fade-in/out, then it will hang.
    So, you only can do fade-in/out when display is still.

    In debug function, if I change this line, it don’t work.

    while(! {}

    readPad is no function. Maybe pad1 variable not pass to debug function ?