About memory page, Branching and cycle

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
About memory page, Branching and cycle
by on (#61566)
I have read documentations regarding the memory map of nes. I know how they are devided (Zero page, stack, ram etc.). What i don't understand is memory paging, how are memory being paged??


When i was implementing 6502 opcode BPL, documents tells me that "branch on result plus". From what i understand, branch if negative flag is not set. Here comes my question in mind "What the hell is branching??? :lol: ". What does branching do???

my disassembler code:
Code:
[C077] LDX #$02
[C079] LDA $2000
[C07C] BPL $FB <- this is where i got confused :lol:



my last problem is about opcode cycle. the BPL cycle is 2 but the document tells me that "Add 1 if branch on same page. 2 if different."
Which brings me back to the first problem....

Taken here:
Quote:
http://6502.wikicomplete.info/bpl


Hope you guys can help me with this thnx :D [/quote]

by on (#61571)
A page in 6502 is 256 bytes. It's pretty easy to understand:

$0000-00FF = page 0
$0100-01FF = page 1
$0200-02FF = page 1
...
$0F00-0FFF = page 15
$1000-11FF = page 16
...

You get the idea.

Regarding branch-related opcodes: the operand is a signed number. This is why branch opcodes have a limitation in range of -128 to +127 bytes from the PC. In this case, the branch is signed (MSB / bit 7 of the operand is set), indicating when the condition is met, the PC is to go backwards (e.g. branch backwards).

$FF - $FB = 4. Assuming the branch condition is met, the PC will have 4 subtracted from it, and will continue operation there. It's important to remember that the PC increments at the operand (the "$FB" portion), so when this instruction executes, the PC is actually at $C07D.

So, the disassembly in question therefore becomes this:

Code:
$C077: A2 02      LDX #$02
$C079: AD 00 20   LDA $2000
$C07C: 10 FB      BPL $C079  ; BPL $FB, or BPL -4


$C07D - 4 = $C079.

If you truly want to understand how it works: it's two's complement. I'd rather not explain why; here's a better description (see section "Relative Addressing").

Now take this example code:

Code:
$C077: A2 02      LDX #$02
$C079: AD 00 20   LDA $2000
$C07C: 10 0A      BPL $C088  ; BPL $0A, or BPL +10


In this case, the operand is positive (MSB / bit 7 of $0A is not set), which means the branch goes forward. $C07D + 10 = $C087. But wait, the branch there says $C088, so how did this happen? Because the PC is incremented by one after executing the instruction, so $C087 + 1 = $C088.

Branching itself is just a form of JMP, but is limited to the above range of bytes. Branching is conditional (you already know this), but it also saves a byte compared to JMP (JMP = 3 bytes, branch = 2 bytes).

Hope this helps.

by on (#61573)
Here's the way I think of it: branch is a two-byte instruction. It executes normally like any other, incrementing the PC twice and taking two cycles. Then, if the branch will be taken, it adds the signed operand to the PC and takes one extra cycle (totaling three cycles now). If this requires alteration of the upper 8 bits of the PC, then it takes a second extra cycle (totaling four cycles). $FF signed is -1, $FE signed is -2, etc. down to $80 signed being -128.
Re: About memory page, Branching and cycle
by on (#61581)
meatloaf69 wrote:
how are memory being paged??


- If you're speaking about memory mappers, well, each PRG data bank is 2000h bytes long. "Paged" is the same of PRG bank "mapped" to:

CPU 8000-9FFF, A000-BFFF, ...

by on (#61591)
thnx for the info guys... this really helped me alot. 8). Now i got a clearer view of things... I can now continue coding :twisted:

by on (#61595)
How do you guys implement the "add extra cycles if page boundary is crossed" in your emulator in a fast way? Any good ideas?

by on (#61596)
Compare the old high byte of PC with the new one.

by on (#61598)
In my emulator I don't know the NES PC until it's required (due to speed reasons) so I guess I have to be creative to think of something else.

by on (#61599)
Align the roms and ram/sram to a 256 byte boundary, examine the pointer.

And you'll have a hell of a time getting The Magic of Scheherezade to work correctly when the enemies cast spells on you.

by on (#61600)
That's obviously clever. Thanks for the idea. :)

How about that ROM you mentioned, does it heavily rely on branch-timing?