A loop that writes to $2006 more than twice?

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
User avatar
SusiKette
Posts: 147
Joined: Fri Mar 16, 2018 1:52 pm
Location: Finland

A loop that writes to $2006 more than twice?

Post by SusiKette »

I saw this loop in Rockman 3's reset code (not sure if Mega Man 3 has it, but it probably will). As far as I know only the first two writes to $2006 after reading $2002 have any significant results. The EOR in the loop is also a bit odd. It would write #$00 every other loop and #$10 on the others, but it still doesn't have any significant meaning what the loop is supposed to achieve.

Code: Select all

 LDA $2002
 LDA #$10
 TAY
 
Loop:
 STA $2006
 STA $2006
 EOR #$10
 DEY
 BNE Loop
I'm not sure if the second write to $2006 resets the latch similar to reading $2002, but according to FCEUX it does since the PPU address changes between $0000 and $1010.

EDIT: I should also add that there are no writes to $2007 anywhere near this loop
Last edited by SusiKette on Fri Jul 05, 2019 1:45 am, edited 1 time in total.
Avatar is pixel art of Noah Prime from Astral Chain
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: A loop that writes to $2006 more than twice?

Post by lidnariq »

SusiKette wrote:As far as I know only the first two writes to $2006
If rendering is disabled, only the last two writes will have any significant results. (nesdevwiki:PPU scrolling)
after reading $2005
$2005 is a write-only register. They might have meant to type $2002...
it still doesn't have any significant meaning what the loop is supposed to achieve.
It doesn't obviously do anything useful.

Even if rendering were enabled, the main loop there is only 15 cycles long, or 45 pixels: far too fast to be anything interesting graphically.
User avatar
SusiKette
Posts: 147
Joined: Fri Mar 16, 2018 1:52 pm
Location: Finland

Re: A loop that writes to $2006 more than twice?

Post by SusiKette »

It was supposed to be $2002. That was my mistake. Still there is no reason I know of to write useless code.
Avatar is pixel art of Noah Prime from Astral Chain
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: A loop that writes to $2006 more than twice?

Post by tokumaru »

We have a far better understanding of the intricacies of the PPU today than developers back in the day had. It's not unusual to find useless PPU accesses in commercial games.
User avatar
Quietust
Posts: 1920
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: A loop that writes to $2006 more than twice?

Post by Quietust »

This logic is actually quite common in games which used the MMC3. Its actual function is to manually clock the IRQ counter 8 times (by toggling the VRAM address between $0000 and $1010), though we don't actually know why this was done - perhaps it was for compatibility with older chip revisions, to make sure the counter was initialized properly.

Interestingly, there are also quite a few games (including Super Mario Bros. 3) which used a broken version of that code, performing EOR #$00 instead of EOR #$10 - given that these games seemed to work just fine, this would be consistent with the idea of the code being used for compatibility with older (perhaps pre-production) chips.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
Fiskbit
Posts: 891
Joined: Sat Nov 18, 2017 9:15 pm

Re: A loop that writes to $2006 more than twice?

Post by Fiskbit »

I believe these writes are done to work around the poorly-understood bug described here with consecutive-scanline reloads and mentioned on the wiki as "pathological behavior". I don't know why games clock the counter so many times, but at least some clocking is required to make things safe in case a reset comes right after a reload.
Ti_
Posts: 61
Joined: Sat Aug 03, 2013 3:08 pm
Location: Russia
Contact:

Re: A loop that writes to $2006 more than twice?

Post by Ti_ »

Super Contra does same every frame:

Code: Select all

BANKF:EC7E                 LDA     #$10
BANKF:EC80                 LDX     #$FF
BANKF:EC82                 LDY     #0
BANKF:EC84                 STY     PPU_ADDRESS
BANKF:EC87                 STY     PPU_ADDRESS
BANKF:EC8A                 STA     PPU_ADDRESS
BANKF:EC8D                 STA     PPU_ADDRESS
BANKF:EC90                 STY     PPU_ADDRESS
BANKF:EC93                 STY     PPU_ADDRESS
BANKF:EC96                 STA     PPU_ADDRESS
BANKF:EC99                 STA     PPU_ADDRESS
BANKF:EC9C                 STY     PPU_ADDRESS
BANKF:EC9F                 STY     PPU_ADDRESS
BANKF:ECA2                 STX     $C000
BANKF:ECA5                 STX     $C001
It also has delays after each write to APU reg:

Code: Select all

BANKE:8F8C WAIT_NOP:
BANKE:8F8C                 NOP
BANKE:8F8D                 NOP
BANKE:8F8E                 NOP
BANKE:8F8F                 NOP
BANKE:8F90                 NOP
BANKE:8F91                 NOP
BANKE:8F92                 NOP
BANKE:8F93                 NOP
BANKE:8F94                 NOP
BANKE:8F95                 NOP
BANKE:8F96                 RTS
BANKE:8F96 ; End of function WAIT_NOP
And also here:
Tiny Toon Adventures (U)
Power Blade (U) [!]
Parodius (E) [!]
Super Contra 7 (Unl)
Lu Ye Xian Zong (Ch)

Only wait nops in apu:
TwinBee 3 - Poko Poko Dai Maou (J) [!]
Post Reply