Branch instructions result in infinite loop?
Moderator: Moderators
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?)
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?)
Re: Branch instructions result in infinite loop?
Yes, it's waiting for the PPU to signal that vblank has started.PolarBITS wrote:is the CPU waiting for some signal from the PPU here?
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.
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.(I know that $2000-$2007 are PPU registers, and since $2002 is being read, the CPU could be waiting for something?)
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?
Re: Branch instructions result in infinite loop?
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 wrote:The byte
Re: Branch instructions result in infinite loop?
Right. Nothing seems to be writing anything to bit 7 of $2002 though.
Re: Branch instructions result in infinite loop?
Hold on nevermind it's usually set at powerup. I'm dumb lol
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.
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.
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?
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?
- rainwarrior
- Posts: 8735
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Branch instructions result in infinite loop?
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?)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?
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.
Re: Branch instructions result in infinite loop?
wrong. Instruction "sta ($00), y" is post indexed indirect, That mean register A is stored inA is stored in the value at $0000 plus Y (therefore A is stored in $0000, same effect as above)
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.
- rainwarrior
- Posts: 8735
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
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".
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".
Re: Branch instructions result in infinite loop?
This non standard notation threw me off too, I also assumed that was "indexed Y".
Re: Branch instructions result in infinite loop?
[/quote]rainwarrior wrote:(On the first test it will be $FF = -1, on the 256th test it will be back down to 0.)
So you're saying that all numbers in RAM are unsigned bytes? I completely forgot about that lol.
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.