Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - Clarification on SAT Buffer Map address in "Create a Racing Game" tutorial

Reply to topic
Author Message
  • Joined: 03 Dec 2021
  • Posts: 54
Reply with quote
Clarification on SAT Buffer Map address in "Create a Racing Game" tutorial
Post Posted: Fri Aug 26, 2022 7:10 pm
Hello everyone,

This question comes from what is surely my misunderstanding of how things work.

In hang-on's tutorial "Create a Racing Game", a SAT buffer is used to update the sprites and to copy them to VRAM only during VBLANK.

The SAT Buffer Map is set to span 256 addresses, from $c000 to $c0ff.

Here comes my question: isn't address $c000 supposed to be the start of the Colour RAM (CRAM)? Wouldn't using this address for the SAT buffer corrupt somehow the palette? And finally, why sometimes I see that SAT address begins at address $3f00 while others I see $7f00?

As you can tell, I am still very confused :)
  View user's profile Send private message
  • Joined: 08 Sep 2018
  • Posts: 270
Reply with quote
Post Posted: Fri Aug 26, 2022 7:43 pm
$c000 is the start of work ram. technically the SAT buffer can be wherever you'd like in ram except for typically the back kilobyte (for stack safety).

$3f00 is the starting location of SAT in VRAM, and not work ram. $7f00 or maybe just $7f which is a write PSG port. I couldnt find anything that referenced the address $7f00 in word form in this tutorial.
  View user's profile Send private message
  • Joined: 06 Mar 2022
  • Posts: 593
  • Location: London, UK
Reply with quote
Post Posted: Fri Aug 26, 2022 7:44 pm
Last edited by willbritton on Fri Aug 26, 2022 7:57 pm; edited 2 times in total
There are three separate memory spaces in the system to consider.

- the Z80 memory map of 64KB which is directly connected to the CPU. This is (under most circumstances) split into 48KB of notional ROM space from $0000 to $bfff and 16KB of notional RAM space from $c000 to $ffff.

- the VRAM space of 16KB which is directly connected to the VDP.

- the "color RAM" space of just 192 bits organised as 32x6 bits. This is actually embedded inside the VDP.

The really important thing to note is that these memory spaces are not connected to each other, which means that address 0 in the main memory space is a different location from address 0 in the VRAM and is a different location from colour 0 in the color RAM.

So holding the SAT at address $c000 in system RAM can't possibly interfere with the operation of the VDP.

The other point to mention is that it's not possible to write directly to either VRAM or to color RAM. The VDP can only be interfaced by sending special sequences of commands to its I/O ports. Sending the command $c0 to the command port of the VDP (port $bf) is used to send data into the color RAM. This is not the same as writing data to address $c000 of system RAM, its just a coincidence.
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 593
  • Location: London, UK
Reply with quote
Post Posted: Fri Aug 26, 2022 7:54 pm
Last edited by willbritton on Fri Aug 26, 2022 8:25 pm; edited 2 times in total
Ah, sorry @IllusionOfMana, we just crossed posts there!

@umbe as for the other part of your question:

umbe1987 wrote
And finally, why sometimes I see that SAT address begins at address $3f00 while others I see $7f00?

The address in question is $3f00. The procedure for writing data to VRAM involves setting the two most significant bits of the first byte to 01. Setting the two MSBs of $3f00 to 01 results in $7f00, so sending $7f00 to port $bf means "start writing to VRAM from address $3f00".

There are a few really good guides on this site about how the VDP and the system in general work, but I'd highly recommend starting with this one which is very easy to understand, if slightly inaccurate in places.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3757
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Fri Aug 26, 2022 7:55 pm
willbritton wrote
Sending the command $c0 to the command port of the VDP (port $bc) is used to send data into the color RAM. This is not the same as writing data to address $c000 of system RAM, its just a coincidence.


I find it easier to think of the color RAM as a write-only part of Video RAM that start at address $C000 and that's 32 bytes long. It doesn't overlap the other parts of Video RAM because that is mapped at address $0000-$3FFF if you want to read and at address $4000-$7FFF if you want to write. But maybe this is more confusing instead? Let me explain with a short table

  • $0000 - $3FFF : read from VRAM address $0000 - $3FFF
  • $4000 - $7FFF : write to VRAM address $0000 - $3FFF
  • $8000 - $8AFF : write to VDP register number underlined the value in red
  • $C000 - $C01F : write to CRAM address $00-$1F
  View user's profile Send private message Visit poster's website
  • Joined: 03 Dec 2021
  • Posts: 54
Reply with quote
Post Posted: Fri Aug 26, 2022 9:00 pm
Thank you all for the many useful replies!

I will take some time to understand them.

I think what confuses me is seeing the same HEX value ($c000), both used to say "CRAM starts here", and "hold SAT at this address in system RAM".

If I understood correctly now, in the former it refers to the ABSOLUTE address of a memory slot, while in the latter it is the RELATIVE position of an address with respect to something (in this case the system RAM, which starts at $c000 and thus it should be ABSOLUTE address $c000 +$c000 = $18000).

Is it correct (does this make sense)?
  View user's profile Send private message
  • Joined: 06 Mar 2022
  • Posts: 593
  • Location: London, UK
Reply with quote
Post Posted: Fri Aug 26, 2022 9:07 pm
That's an interesting idea @sverx, I kind of like the thinking there!

Just important I guess for beginners to remember that those three regions aren't actually contiguous - e.g. if you send $ff and $3f to the cmd port to read vram $3fff, then read a byte, you don't end up in "write space", you just circle round to $0000. Similarly if you send $ff and $7f to the cmd port to write vram $3fff, then read a byte, you don't find yourself in color space.

VRAM is strictly 16KB and so the next address from $3fff is always $0000; and color RAM is only 32 bytes, so writing to $1f in color RAM takes you to $00, not $20.

Also worth noting that there's actually very little difference between sending a read command and a write command to the cmd port. Both leave the VDP in the same mode, the only difference is that the read command pre-loads the read buffer so that the next read of port $be returns a value, and also the read command auto-increments the address by 1 immediately whereas the write command doesn't. For example, if you send $00 and $00 to the cmd port, and then *write* to the data port you'll actually write to address $0001 whereas if you send $00 and $70 to the cmd port and then write to the data port you'll write to $0000 as expected.
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 593
  • Location: London, UK
Reply with quote
Post Posted: Fri Aug 26, 2022 9:23 pm
umbe1987 wrote
I think what confuses me is seeing the same HEX value ($c000), both used to say "CRAM starts here", and "hold SAT at this address in system RAM".

If I understood correctly now, in the former it refers to the ABSOLUTE address of a memory slot, while in the latter it is the RELATIVE position of an address with respect to something (in this case the system RAM, which starts at $c000 and thus it should be ABSOLUTE address $c000 +$c000 = $18000).


Not really anything to do with absolute or relative addressing. Again, the $c0 thing being used for both color RAM and the start of system RAM is just a complete coincidence.

This is how you write a value (let's say 15 or $0f) to address $c000 in system RAM:

ld a, $0f     ; put 15 into register a in the CPU
ld ($c000), a ; write the contents of register a to $c000 in RAM


Conversely, here's how you set colour 0 in the VDP to yellow:

ld c, $bf    ; $bf is the VDP command port
out (c), $00 ; we are setting colour 0
nop          ; we must wait to allow the VDP to recover from the first byte!
out (c), $c0 ; $c0 is a special code to tell the VDP to go into "write color RAM" mode

; at this point the VDP is ready to accept colour data, starting at colour index 0.  Now we just need to write the actual colour data...

ld c, $be    ; $be is the VDP data port
out (c), $0f ; $0f will give us yellow

; now we have written yellow to colour 0


Again, the $c0 in both of these snippets means something totally different. In the first example, if we had been writing to RAM address $d000 we would have changed the $c0 to $d0, but in the second example we must use $c0 because that is the "write colour RAM" command.

In fact, when I said "$c0 is a special code" that's not the whole truth, it's actually only the two most significant bits of the first byte in the sequence that are the code for the VDP to tell it which mode to be in:

00 = Read VRAM mode
01 = Write VRAM mode
10 = Write VDP register (works instantly)
11 = Write color RAM mode

The rest of the two byte sequence determine the argument to the command. So writing to colour zero is (with underscores for emphasis):
11_000000000_00000

Only the last 5 zeros actually matter to set colour zero. The other 9 don't make a difference.

Converting this binary to hex you get $c0 for the first byte and $00 for the second byte. The bytes need to be sent in reverse order to the VDP, so first you send $00 and then $c0, which is exactly what I've done in the example above.
  View user's profile Send private message Visit poster's website
  • Joined: 03 Dec 2021
  • Posts: 54
Reply with quote
Post Posted: Fri Aug 26, 2022 9:43 pm
willbritton wrote
umbe1987 wrote
I think what confuses me is seeing the same HEX value ($c000), both used to say "CRAM starts here", and "hold SAT at this address in system RAM".

If I understood correctly now, in the former it refers to the ABSOLUTE address of a memory slot, while in the latter it is the RELATIVE position of an address with respect to something (in this case the system RAM, which starts at $c000 and thus it should be ABSOLUTE address $c000 +$c000 = $18000).


Not really anything to do with absolute or relative addressing. Again, the $c0 thing being used for both color RAM and the start of system RAM is just a complete coincidence.

This is how you write a value (let's say 15 or $0f) to address $c000 in system RAM:

ld a, $0f     ; put 15 into register a in the CPU
ld ($c000), a ; write the contents of register a to $c000 in RAM


Conversely, here's how you set colour 0 in the VDP to yellow:

ld c, $bf    ; $bf is the VDP command port
out (c), $00 ; we are setting colour 0
nop          ; we must wait to allow the VDP to recover from the first byte!
out (c), $c0 ; $c0 is a special code to tell the VDP to go into "write color RAM" mode

; at this point the VDP is ready to accept colour data, starting at colour index 0.  Now we just need to write the actual colour data...

ld c, $be    ; $be is the VDP data port
out (c), $0f ; $0f will give us yellow

; now we have written yellow to colour 0


Again, the $c0 in both of these snippets means something totally different. In the first example, if we had been writing to RAM address $d000 we would have changed the $c0 to $d0, but in the second example we must use $c0 because that is the "write colour RAM" command.

In fact, when I said "$c0 is a special code" that's not the whole truth, it's actually only the two most significant bits of the first byte in the sequence that are the code for the VDP to tell it which mode to be in:

00 = Read VRAM mode
01 = Write VRAM mode
10 = Write VDP register (works instantly)
11 = Write color RAM mode

The rest of the two byte sequence determine the argument to the command. So writing to colour zero is (with underscores for emphasis):
11_000000000_00000

Only the last 5 zeros actually matter to set colour zero. The other 9 don't make a difference.

Converting this binary to hex you get $c0 for the first byte and $00 for the second byte. The bytes need to be sent in reverse order to the VDP, so first you send $00 and then $c0, which is exactly what I've done in the example above.


Thanks, your example and explanation definitely clarified the mess I had in my mind. Really appreciate it.
  View user's profile Send private message
Reply to topic



Back to the top of this page

Back to SMS Power!