It is currently Mon Apr 22, 2019 9:48 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 5 posts ] 
Author Message
PostPosted: Sat Apr 06, 2019 8:36 pm 
Offline

Joined: Sat Apr 06, 2019 8:17 pm
Posts: 2
I feel like I must be missing something here, but I'm seeing some strange behavior with my controls when using the NMI with vblank (bit 7 of PPUSTATUS set).

My code works fine most of the time, however it seems to occasionally read all buttons as being pressed when NMI vblank is enabled, and I can reproduce this both in Mesen and FCEUX.

Here is the minimum amount of code I could still reproduce this with;

Code:
JOYPAD1 = $4016
JOYPAD2 = $4017
PPU_CTRL = $2000
PPU_SCROLL = $2005

.segment "HEADER"
   .byte "NES"
   .byte $1A
   .byte $01
   .byte $01

.segment "ZEROPAGE"
   JOYPAD1_STATE: .res $01
   JOYPAD1_SEEN: .res $01

.segment "STARTUP"
.proc nmi
   LDA #$00
   STA PPU_SCROLL
   STA PPU_SCROLL
   RTI
.endproc

.proc readinput
   LDA #$01
   STA JOYPAD1
   LDA #$00
   STA JOYPAD1
   LDA #$01
   STA JOYPAD1_STATE

loop:
   LDA JOYPAD1
   LSR A
   ROL JOYPAD1_STATE
   BCC loop
   RTS
.endproc

.proc handleinput
   LDA JOYPAD1_STATE
   CMP #$00
   BEQ nothingpressed
   STA JOYPAD1_SEEN

nothingpressed:
   RTS
.endproc

.proc reset
   LDA #%10000000     
   STA PPU_CTRL

loop:
   JSR readinput
   JSR handleinput
   JMP loop
.endproc

.proc irq
   RTI
.endproc

.segment "VECTORS"
   .addr nmi
   .addr reset
   .addr irq


My controller management code (readinput) is very heavily based on the Controller Reading article from the wiki, and as such I'm sure that I must be doing something wrong elsewhere.

I know that the NMI in my example isn't actually doing anything by setting PPUSCROLL to zero, but an empty NMI does not cause the issue. The program that this was taken from set PPU_SCROLL to the value of a memory address, and as such the altered code above is not much different and still reproduces the issue.

After leaving the program running for a couple of seconds, FF is written to JOYPAD_SEEN, indicating that all bits were somehow set when reading the controller.

Has anyone experienced anything like this before?


Top
 Profile  
 
PostPosted: Sat Apr 06, 2019 8:51 pm 
Offline

Joined: Sat Apr 06, 2019 8:17 pm
Posts: 2
Someone pointed out that I'm not restoring the A register in my NMI, which I'm using within readinput. Oops! :roll:


Top
 Profile  
 
PostPosted: Sat Apr 06, 2019 9:01 pm 
Online

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8265
Location: Seattle
jackwilsdon wrote:
.proc readinput
Uh. This stops after the first button that wasn't pressed...


Last edited by lidnariq on Sat Apr 06, 2019 10:57 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Sat Apr 06, 2019 9:48 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21319
Location: NE Indiana, USA (NTSC)
lidnariq wrote:
Uh. This stops after the first button that wasn't pressed...

It looks to me like the same one-hot ring counter that my own controller reading routine uses. The bit read from the controller goes into the least significant bit of JOYPAD1_STATE. The bit that controls the loop comes out the other (most significant) end, and it always takes eight shifts before the lone 1 bit in the $01 value written to JOYPAD1_STATE at the start of the loop reaches the carry.

Other examples of ring counters on the NES: The MMC1 is believed to use the same structure for its 5-bit serial load register. The master clock bus divider on the NES CPU uses a different form of ring counter.

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
PostPosted: Sat Apr 06, 2019 10:12 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11295
Location: Rio de Janeiro - Brazil
jackwilsdon wrote:
Someone pointed out that I'm not restoring the A register in my NMI, which I'm using within readinput. Oops! :roll:

Yup, when the NMI interrupts the main thread, which is running over and over (without waiting for the next frame), it trashes the accumulator and returns, screwing up the logic in the main thread.

It's good practice to backup and restore any registers you use inside interrupt handlers.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: lidnariq and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group