Page 1 of 1
How does this piece of 65C816 assembly code work?
Posted: Wed Apr 10, 2019 8:09 pm
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:
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:
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!

Re: How does this piece of 65C816 assembly code work?
Posted: Wed Apr 10, 2019 9:40 pm
by BigEd
Welcome!
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.
Re: How does this piece of 65C816 assembly code work?
Posted: Wed Apr 10, 2019 10:49 pm
by Dr Jefyll
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.
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
Re: How does this piece of 65C816 assembly code work?
Posted: Thu Apr 11, 2019 7:19 am
by BitWise
The value of the address register is automatically incremented after every write.
https://wiki.superfamicom.org/registers#toc-42
Re: How does this piece of 65C816 assembly code work?
Posted: Thu Apr 11, 2019 7:53 am
by GARTHWILSON
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.
Re: How does this piece of 65C816 assembly code work?
Posted: Thu Apr 11, 2019 2:27 pm
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)
Re: How does this piece of 65C816 assembly code work?
Posted: Fri Apr 12, 2019 4:33 am
by kc5tja
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).
Re: How does this piece of 65C816 assembly code work?
Posted: Fri Apr 12, 2019 11:53 am
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.
Re: How does this piece of 65C816 assembly code work?
Posted: Fri Apr 12, 2019 12:31 pm
by BigEd
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