How does this piece of 65C816 assembly code work?

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Post Reply
rchoudhary
Posts: 3
Joined: 10 Apr 2019

How does this piece of 65C816 assembly code work?

Post by rchoudhary »

I am working with assembly for the 65C816, specifically to make a SNES ROM. In a guide I found online there was some code to set the background color. The SNES supports 16-bit color so the format is as such:

Code: Select all

0bbbbbgggggrrrrr
It said that the $2122 refers to the Color Data Register. I know that the 65C816 is a 16-bit CPU, and I'm assuming it's word-addressable so that every address refers to a 16-bit location.

Here is a snippet the code the guide provided that changes the background color to blue:

Code: Select all

    SEP         #$20        ; Set the A register to 8-bit.
    LDA         #%00000000  ; Load the low byte of the blue color.
    STA         $2122
    LDA         #%01111100  ; Load the high byte of the blue color.
    STA         $2122
What I don't understand is why we set the A register to 8-bit mode if color is a 16-bit value? And then how do 2 STA's with 8-bit operands to $2122 result in a 16-bit write to $2122?

Also according to this wiki article, $2122 is the "Data for CG-RAM Write" and $2121 is the "Address for CG-RAM Write". How does the write to $2122 happen successfully without first writing to $2121?

My main file also has a line:

Code: Select all

.include "Snes_Init.asm"
and within Snes_Init.asm there is a line

Code: Select all

stz 	$2121   ; Color number register ($0-ff)
which gets called. Is this is how the CG-RAM Write Address is set?

Any help clarifying would be appreciated! :)
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: How does this piece of 65C816 assembly code work?

Post by BigEd »

Welcome!
rchoudhary wrote:
I know that the 65C816 is a 16-bit CPU, and I'm assuming it's word-addressable so that every address refers to a 16-bit location.
It's a 16-bit capable CPU, but like most such, all locations are byte addresses, and whether an access will refer to a single byte or to a pair of bytes depends on the mode: the mode of the CPU and/or the addressing mode of the instruction.

In this case, with A in 8 bit mode, each of the stores will be a single byte, to the given address.

Looks like you've already spotted how the "Address for CG-RAM Write" is initialised.

So the only remaining question is how do two consecutive writes cause a 16 bit value to be written - and the answer I think is that the peripheral in question is built that way. It accepts consecutive accesses and forms them into a 16 bit update. That's a slightly unusual design choice, but not unheard-of.
User avatar
Dr Jefyll
Posts: 3525
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: How does this piece of 65C816 assembly code work?

Post by Dr Jefyll »

rchoudhary wrote:

Code: Select all

stz 	$2121   ; Color number register ($0-ff)
Is this is how the CG-RAM Write Address is set?
I'm not a NES guy, but it looks to me as if it is. :)
Quote:
how do 2 STA's with 8-bit operands to $2122 result in a 16-bit write to $2122?
Yes, that would be ridiculous if you were writing to memory. But the writes go the registers of some sort of specialized I/O device, with its own peculiar behavior.

There's lots of 6502/65816 expertise on this forum, but for specifics of NES programming you may wish to also visit http://forums.nesdev.com

cheers
Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
BitWise
In Memoriam
Posts: 996
Joined: 02 Mar 2004
Location: Berkshire, UK
Contact:

Re: How does this piece of 65C816 assembly code work?

Post by BitWise »

The value of the address register is automatically incremented after every write.
https://wiki.superfamicom.org/registers#toc-42
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: How does this piece of 65C816 assembly code work?

Post by GARTHWILSON »

BitWise wrote:
The value of the address register is automatically incremented after every write.
https://wiki.superfamicom.org/registers#toc-42
In that case, could you omit A0 from the register-select inputs on that IC, and leave the accumulator in 16-bit mode and do a single LDA#%0111110000000000, STA $2122 (so that the second byte gets stored to the same address as the first)? What I'm thinking of is that all the IC's register-select inputs would still be connected, but offset by one bit to the address bus, so you can still write to all addresses.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
Dr Jefyll
Posts: 3525
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: How does this piece of 65C816 assembly code work?

Post by Dr Jefyll »

Garth, I feel the same way you do. I hate to see two consecutive 8-bit operations (as in that snippet above) when I know the '816 is potentially capable of doing the job in a single, 16-bit operation.

I'm only guessing, but I can think of a few possible reasons why the NES designers didn't do as you suggest and connect the peripheral IC's Least-Significant register-select input to CPU A1; connect LS+1 to A2 etc. Maybe they didn't think of the idea, or didn't want to double the size of the address range devoted to the peripheral IC. But my strongest hunch is that the peripheral IC requires completion time for the internal auto-increment Andrew mentioned, and thus isn't capable of accepting back-to-back writes.

(Edit typos)
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
kc5tja
Posts: 1706
Joined: 04 Jan 2003

Re: How does this piece of 65C816 assembly code work?

Post by kc5tja »

Dr Jefyll wrote:
But my strongest hunch is that the peripheral IC requires completion time for the internal auto-increment Andrew mentioned, and thus isn't capable of accepting back-to-back writes.
To be fair, that's what the RDY signal was intended to address. If they'd used it, the 16-bit write still would have been faster and more convenient to use.

I'm also speculating, but more likely than not, they had a bunch of chip logic already drawn out in rubylith that they just wanted to re-use as-is. Perhaps the PPU has 16-bit registers elsewhere in its map. If you used A1..An+1 to address the chip, then those registers would have to be read with 8-bit reads instead, since now their once back-to-back bytes are no longer adjacent. After all, unless you're color-cycling, tweaking the palette registers occurs only fairly rarely; manipulating a raster compare register would happen much more frequently (experience on the Commodore 64 suggests multiple times a frame).
White Flame
Posts: 704
Joined: 24 Jul 2012

Re: How does this piece of 65C816 assembly code work?

Post by White Flame »

The settling on which CPU to use might also have happened late, after some of the S-PPU design was locked in, with a requirement of having an 8-bit data bus. Or just a matter of the left hand not knowing that the right hand can do 16-bit writes.

But yeah, rchoudhary, to set a color you first write which color you want to write to in $2121, then write 2 separate bytes into $2122 to set the 16-bit color value. The mechanism at $2122 handles consecutive writes and places them in consecutive destinations; it's not a memory byte.

Note that there are other actual 16-bit registers; this particular pair is more a general byte-writing interface to CGRAM, writing as many bytes as you want. It also allows the DMA to stream bytes into it. But it would have been nice if they allowed the 16-bit CPU writes as well. It does seem that VRAM allows for 16-bit access, just not CGRAM.
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: How does this piece of 65C816 assembly code work?

Post by BigEd »

White Flame wrote:
The settling on which CPU to use might also have happened late, after some of the S-PPU design was locked in, with a requirement of having an 8-bit data bus. Or just a matter of the left hand not knowing that the right hand can do 16-bit writes.
Indeed it seems widely understood that the original idea and perhaps the prototype was a 68000 based console. A combination of cost reduction and an idea of backwards compatibility led to a change. But I don't know how late or early that was.
Ref: Super Power, Spoony Bards, and Silverware: The Super Nintendo Entertainment System
Also ref: https://retrocomputing.stackexchange.co ... 68000-snes
Post Reply