nesdev.com
http://forums.nesdev.com/

Branch instructions result in infinite loop?
http://forums.nesdev.com/viewtopic.php?f=3&t=15934
Page 1 of 2

Author:  PolarBITS [ Fri May 12, 2017 9:32 am ]
Post subject:  Branch instructions result in infinite loop?

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?)

Author:  tokumaru [ Fri May 12, 2017 9:37 am ]
Post subject:  Re: Branch instructions result in infinite loop?

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.

Quote:
(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.

Author:  PolarBITS [ Fri May 12, 2017 6:44 pm ]
Post subject:  Re: Branch instructions result in infinite loop?

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?

Author:  tokumaru [ Fri May 12, 2017 6:50 pm ]
Post subject:  Re: Branch instructions result in infinite loop?

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.

Author:  PolarBITS [ Fri May 12, 2017 6:54 pm ]
Post subject:  Re: Branch instructions result in infinite loop?

Right. Nothing seems to be writing anything to bit 7 of $2002 though.

Author:  PolarBITS [ Fri May 12, 2017 6:56 pm ]
Post subject:  Re: Branch instructions result in infinite loop?

Hold on nevermind it's usually set at powerup. I'm dumb lol

Author:  tokumaru [ Fri May 12, 2017 7:14 pm ]
Post subject:  Re: Branch instructions result in infinite loop?

$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.

Author:  tokumaru [ Fri May 12, 2017 8:16 pm ]
Post subject:  Re: Branch instructions result in infinite loop?

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.

Author:  PolarBITS [ Sat May 13, 2017 9:15 am ]
Post subject:  Re: Branch instructions result in infinite loop?

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?

Author:  rainwarrior [ Sat May 13, 2017 10:39 am ]
Post subject:  Re: Branch instructions result in infinite loop?

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.

Author:  nostromo [ Sat May 13, 2017 10:51 am ]
Post subject:  Re: Branch instructions result in infinite loop?

Quote:
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.

Author:  rainwarrior [ Sat May 13, 2017 11:02 am ]
Post subject:  Re: Branch instructions result in infinite loop?

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".

Author:  tokumaru [ Sat May 13, 2017 12:37 pm ]
Post subject:  Re: Branch instructions result in infinite loop?

This non standard notation threw me off too, I also assumed that was "indexed Y".

Author:  PolarBITS [ Sat May 13, 2017 12:38 pm ]
Post subject:  Re: Branch instructions result in infinite loop?

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.

Author:  tepples [ Sat May 13, 2017 12:44 pm ]
Post subject:  Re: Branch instructions result in infinite loop?

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

Page 1 of 2 All times are UTC - 7 hours
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/