Moving the direct page from $0000

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Moving the direct page from $0000
by on (#233065)
In this post, koitsu wrote:
The short of it is that ca65/ld65 has no comprehension of direct page, only zero page, which can cause complications if using tcd (a fairly commonly used opcode on 65816). Maybe this doesn't matter with cc65, since it itself is handling declaration and organisation of variables.

He cited his previous posts about the issue (#140305 and #140698) as well.

A few issues related to support for nonzero direct page base have been filed against cc65 and ca65: #194, #317, and #498. See also mailing list discussion. It's important not only for 65816 but also for the HuC6280 in the TurboGrafx-16, which fixes D at $2000. Until these are fixed, what workarounds have been used if needed? How often do games use D != $0000?
Re: Moving the direct page from $0000
by on (#233077)
On ca65:

The .setdp compiler extension seemed like a good approach, syntactically at least. The problem wasn't syntax, though, it was figuring out all the places in the code that assume 0 and adapting every one of them.

Greg King did that direct-page branch of ca65, and maybe it's been 2.5 years, but given the obscurity of this compiler I'm not surprised there hasn't been action on it. Resolving a complex question like that requires people using and testing these things and putting them through their paces, and I'm not sure if anyone at all has been testing this branch.

As for what I started doing instead, I thought about macros for a while, but that approach irritated me. Instead, I just fall back to using < and probably an .assert on the high byte of a relevant address somewhere nearby. Clearly mark the code that moves the direct page, and just watch what you're doing while you're inside it. Try to keep it in self-contained areas, and don't spaghetti the use of DP.
Re: Moving the direct page from $0000
by on (#233084)
I haven't looked at the recommended implementations or models, but I will point out there's an uncommon-but-useful technique used on the SNES anyway that could potentially confuse the assembler or linker, depending on the user's code or configuration: it involves moving DP to the base of the MMIO register region of choice, followed by using direct page read/writes. An example during SNES init (solely for a case of space savings, since the cycle savings don't really gain you much in a routine run at RESET time):

Code:
rep #$20
lda #$2100
tcd
sep #$20
lda #$8f
sta $00
stz $01
stz $02
stz $03
stz $05
...
rep #$20
lda #$0000
tcd

Some games (ex. Square titles) are known to use a similar technique when doing large sums of MMIO register reads/writes in timing-critical sections, since the cycle gains are worth it. I believe Chrono Trigger does exactly this.

I only mention it because $2100-2133 and $4200-421F and $43x0-43xA are MMIO register regions, so if there was a particular MEMORY section for these for some reason, I'm not sure if the assembler or linker would do the right thing. It's also very (read: strongly) possible I'm worrying about nothing.
Re: Moving the direct page from $0000
by on (#233222)
I see TDC more than TCD, as its a faster/smaller way to clear 16Bit A to 0