Branch instructions result in infinite loop?

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

PolarBITS
Posts: 21
Joined: Mon May 01, 2017 4:11 pm

Branch instructions result in infinite loop?

Post by PolarBITS »

The first instructions in the rom for Donkey Kong are the following:

SEI
CLD
LDA 10
STA $2000
LDX ff
TXS
LDA $2002
AND 80, imm
BEQ f9, imm

Since BEQ branches if the zero flag is set, and $2002 is 0 initially, LDA sets the zero flag when it executes. BEQ then branches 7 bytes back to the LDA command, and it loops forever like this. Am I doing something wrong, or is the CPU waiting for some signal from the PPU here? (I know that $2000-$2007 are PPU registers, and since $2002 is being read, the CPU could be waiting for something?)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Branch instructions result in infinite loop?

Post by tokumaru »

PolarBITS wrote:is the CPU waiting for some signal from the PPU here?
Yes, it's waiting for the PPU to signal that vblank has started.

Since you're apparently coding an NES emulator, it might be a good idea to familiarize yourself with the basic architecture of the system, otherwise you'll run into all sorts of little surprises like this.
(I know that $2000-$2007 are PPU registers, and since $2002 is being read, the CPU could be waiting for something?)
When in doubt, look at the PPU's documentation to see what bits of which register are being used/watched, and you should get a better idea of what the code is trying to do.
PolarBITS
Posts: 21
Joined: Mon May 01, 2017 4:11 pm

Re: Branch instructions result in infinite loop?

Post by PolarBITS »

I'm looking at the PPU documentation and I'm a bit confused. STA writes 0x10 (16 in decimal and 00010000 in binary) to address $2000. The byte that controls vblank is the first one, byte 7, yet it seems to be set to 0. What am I missing?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Branch instructions result in infinite loop?

Post by tokumaru »

PolarBITS wrote:The byte
You mean bit. Anyway, that bit controls whether the PPU generates an NMI every time vblank starts, not whether vblanks happen. Even if NMIs are turned off, vblanks will still happen, and their occurrence will be signaled in bit 7 of register $2002.
PolarBITS
Posts: 21
Joined: Mon May 01, 2017 4:11 pm

Re: Branch instructions result in infinite loop?

Post by PolarBITS »

Right. Nothing seems to be writing anything to bit 7 of $2002 though.
PolarBITS
Posts: 21
Joined: Mon May 01, 2017 4:11 pm

Re: Branch instructions result in infinite loop?

Post by PolarBITS »

Hold on nevermind it's usually set at powerup. I'm dumb lol
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Branch instructions result in infinite loop?

Post by tokumaru »

$2002 is a read-only register. Games read it to get information about what the PPU is doing, they aren't supposed to write to $2002.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Branch instructions result in infinite loop?

Post by tokumaru »

One thing that's important to note it's that memory-mapped registers are NOT memory. They are "ports" that allow the CPU to communicate with other parts of the hardware, such as the PPU and the APU. The CPU writes to these ports to send messages, but the written values are not stored in actual memory locations that can be read back. The CPU can also read from certain registers to receive messages from other parts of the system, and this is different from a memory read, because what you get is a dynamic value supplied by the hardware being pooled, not a static byte that was previously stored in a memory location.
PolarBITS
Posts: 21
Joined: Mon May 01, 2017 4:11 pm

Re: Branch instructions result in infinite loop?

Post by PolarBITS »

After the BEQ I have the following instructions:

LDY 07, imm
STY 01, zp
LDY 00, imm
STY 00, zp
LDA 00, imm
STA 00, indY
DEY
BNE fb, imm
DEC 01, zp
BPL f7, imm

This still results in an infinite loop for me. If I'm getting it right, the following happens:

7 is stored in Y
Y is stored in $0001 (value of $0001 is now 7)
0 is stored in Y
Y is stored in $0000 (value of $0000 is now 0)
0 is stored in A
A is stored in the value at $0000 plus Y (therefore A is stored in $0000, same effect as above)
Y is decremented (Y is now -1 and the Negative flag is set)
The program branches back to (STA 00), because the negative flag is set.

This causes another infinite loop. What's the problem here?
User avatar
rainwarrior
Posts: 8733
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Branch instructions result in infinite loop?

Post by rainwarrior »

PolarBITS wrote:Y is decremented (Y is now -1 and the Negative flag is set)
The program branches back to (STA 00), because the negative flag is set.

This causes another infinite loop. What's the problem here?
BNE does not branch on negative, BNE branches on not-zero. It is the opposite of BEQ. (BNE = branch not equal, BEQ = branch equal. Would have been nicer if they were named BZC and BZS maybe?)

BMI branches on negative (branch minus), and BPL branches on positive (branch plus). (Again, BNS and BNC would have been clearer, IMO.)

DEY will eventally set the zero flag when Y reaches zero. (On the first test it will be $FF = -1, on the 256th test it will be back down to 0.)

DEC $01 will eventually set the negative flag when ($01) rolls over to $FF.
nostromo
Posts: 9
Joined: Tue Aug 12, 2014 11:25 pm
Location: Sonora, Mexico

Re: Branch instructions result in infinite loop?

Post by nostromo »

A is stored in the value at $0000 plus Y (therefore A is stored in $0000, same effect as above)
wrong. Instruction "sta ($00), y" is post indexed indirect, That mean register A is stored in
address "at where" is pointing address $0000 plus y, not address $00 plus y.

address $0000 = 00
address $0001 = 07
register y = 0
sta ($00),y = $0700 + y = $0700

for what I can see this code fill with 0's entirely the main RAM.
User avatar
rainwarrior
Posts: 8733
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Branch instructions result in infinite loop?

Post by rainwarrior »

Ah, yeah I figured it was a "clear RAM" loop (PolarBITS seems to be working through a startup sequence), but I had neglected to notice that this loop overwrites its own counters, i.e. $01 is expected to be overwritten with 0 at some point. Interesting that this loop will leave with ($01)=$FF after that last DEC, and it has to write the $00XX page last.

If "indY" meant "indexed Y" it would overwrite $01 right away and the BPL would trigger on the first test, but yeah obviously it is "indirect Y".
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Branch instructions result in infinite loop?

Post by tokumaru »

This non standard notation threw me off too, I also assumed that was "indexed Y".
PolarBITS
Posts: 21
Joined: Mon May 01, 2017 4:11 pm

Re: Branch instructions result in infinite loop?

Post by PolarBITS »

rainwarrior wrote:(On the first test it will be $FF = -1, on the 256th test it will be back down to 0.)
[/quote]

So you're saying that all numbers in RAM are unsigned bytes? I completely forgot about that lol.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Branch instructions result in infinite loop?

Post by tepples »

Everything on a 6502 is unsigned, with the exception of the V flag in ADC, CMP, and SBC. N just means bit 7.
Post Reply