News:

11 March 2016 - Forum Rules

Main Menu

Display graphic on the Snes

Started by yugisokubodai, June 05, 2016, 08:17:15 PM

Previous topic - Next topic

yugisokubodai

Hello,

I'm starting a simple program that display graphic tiles on the screen without using DMA.
I have some doubts because the documents out there are not clear at some points. Here's my code.


1. Header
2. Initalization
3. Main code like this

sep #$20
rep #$10

lda #$11 //bg1 16x16, mode 1
sta $2105

lda #$04 //Tile map location $400 Vram
[b]sta $2107[/b]

lda #$01 //Tileset address at $1000
[b]sta $210b[/b]

lda #$01
sta $212c //enable bg1

lda #$80
sta $2115

ldx #$1000
[b]stx $2116[/b]


wait_vblank:
lda $4210
and #$80
bit #$80
beq wait_vblank


ldx #$0000
REP #$20

write_tile:
lda sprite,x
[b]sta $2118[/b]
inx
inx
[b]cpx #$0800[/b] //2048 bytes
bne write_tile


stz $210D //BG1 scroll
stz $210E

LDA #$02
STA $2121

sep #$20
rep #$10

lda #$1f
sta $2122
lda #$3c
sta $2122

infinity:
jmp infinity

sprite:
incbin "sprite.smc"



What I'm not clear are:


  • Storing 04 to $2107 means that the tile map starts at $400 x 2 = $800 in Vram. So which register I should write to in order to make the tiles appear from $800? For example, I want the tile #02 to appear at (0,0) and tile #03 to appear at (0,1) at the upper left corner.
  • Storing 01 to $210B  means that the tile set (graphic data) starts at $1000 x 2 = $2000 in Vram. I'm clear at this point, but not with $2116 as described below.
  • According to some documents, $2116 is described as "This register is used to set the initial address for a VRAM upload or download". So what exactly it does?
    After trying and get error many times, I realized that $2116 tells $2118 the address in Vram to write tile (graphic) data to.
    For example,

    Lda #$01
    Sta $210B   ; Tile data starts from $2000 in Vram

    Ldx #$400
    Stx $2116    ; ----------> Tile data starts from $800?

    write_tile:
       lda sprite,x
       sta $2118
       inx
       inx
       cpx #$0800   //2048 bytes
       bne write_tile

    Althought the tile data appears from $2000 Vram, but actually $2118 will write the data from $800.
    So my understanding is, whatever the value of $210B is, the actual graphic data will be at whatever address that $2116 tells. Is my understanding right?

  • write_tile:
       lda sprite,x
       sta $2118
       inx
       inx
       cpx #$0800   //2048 bytes
       bne write_tile

    This write tile (graphic data) to Vram, since I use 32x32 screen, so there're 2048 bytes to write. But I checked the Vram and there's only #$400. I wonder why. My graphic data is also 2048 bytes.

兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

Disch

SNES has 2 VRAM chips, each are 32K in size.  It interleaves VRAM between these two chips, so that each 2-byte word is split with the low byte being on one chip and the high byte being on another chip.  Therefore, everything is accessed by WORD addresses rather than BYTE addresses.  And it might be easier to visualize it that way.

So in this response, I'm going to use WORD addresses for all VRAM accesses unless I specifically say I'm doing otherwise.


Quote from: yugisokubodai on June 05, 2016, 08:17:15 PM
Storing 04 to $2107 means that the tile map starts at $400 x 2 = $800 in Vram. So which register I should write to in order to make the tiles appear from $800? For example, I want the tile #02 to appear at (0,0) and tile #03 to appear at (0,1) at the upper left corner.

VRAM is a blank slate.  Some of it will contain patterns and some of it will contain tilemaps.  The SNES doesn't care what data you put where as long as you tell it where to find everything.

04->2107 is telling the SNES you want it to look at address $0400 for the tilemap.

This means, to draw to the tilemap, you would write #$0400 to register $2116/7 to set the address, followed by the words you want to draw to $2118/9.


QuoteStoring 01 to $210B  means that the tile set (graphic data) starts at $1000 x 2 = $2000 in Vram. I'm clear at this point, but not with $2116 as described below.

Correct:  01->210B  means BG1's patterns will be read from word address $2000


QuoteAccording to some documents, $2116 is described as "This register is used to set the initial address for a VRAM upload or download". So what exactly it does?

Main system memory can be accessed directly via banks $7E/7F.  However, VRAM is tied to the PPU and not the CPU, and therefore cannot be accessed directly.  Therefore, you have to set the 'address' with 2116, and then write the data with 2118.

Example:

lda #$0400
sta $2116    ; set PPU Addr to word address 0400

lda #$FFEE
sta $2118    ; write the word 'FFEE' to VRAM[0400]



QuoteAlthought the tile data appears from $2000 Vram, but actually $2118 will write the data from $800.
So my understanding is, whatever the value of $210B is, the actual graphic data will be at whatever address that $2116 tells. Is my understanding right?

Maybe?  You're phrasing this kind of weird.

2116 tells 2118 where to write to.
210B tells the PPU where to look for patterns.



Quote
This write tile (graphic data) to Vram, since I use 32x32 screen, so there're 2048 bytes to write. But I checked the Vram and there's only #$400. I wonder why. My graphic data is also 2048 bytes.

That should be writing $800 bytes ($400 words).  Though maybe you aren't force-blanking so maybe you are running out of VBlank time?  For big chunks of drawing, you really should force blank by writing:
0F->2100

yugisokubodai

Thank you for your reply.
According to your reply, I correct my understanding as:

1. Set tilemap address by $2107, for example tilemap starts at $400
2. Set tileset (pattern) by $210B, for example tileset starts at $1000
3. Use $2118 to write the tile to tilemap address which was set by $2107, for example write word "0A00" to tilemap
4. Before writing with $2118, must tell the coordinate of the tile in tilemap using $2116

For example

lda #$0412
sta $2116   

lda #$0A00
sta $2118 

The tile #0A will appear at (1,1) of the screen (row 1, column 1). In other way, the PPU will looks for patern #0A from $1000, then put it in (1,1) of the screen. Is this correct?

Then, how to write the actual tileset (pattern) to $1000? If $2118 is used to write tile #, then which register is used to write the graphic data to $1000?
兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

Disch

#3
QuoteThe tile #0A will appear at (1,1) of the screen (row 1, column 1)

Ehhh... #$0A00 is not tile A, it's tile $200 using palette #2   (EDIT:  had incorrect info here before).   #$000A would be tile A.

Have you written $80->2115 ?  If you didn't, that's probably screwing with your VRAM writes.

Also if you write it to address $0412, that would be row=0 column=18

Row=1, col=1 would be address $0421


Quote from: yugisokubodai on June 05, 2016, 10:28:01 PM
Then, how to write the actual tileset (pattern) to $1000? If $2118 is used to write tile #, then which register is used to write the graphic data to $1000?

2118 is not used to write tile number -- it's used to write data to VRAM.  Both the tileset and the tilemap are in VRAM, so you write to each of them the same way.

If your tileset is at address $1000, then do:

#$1000 -> $2116
data -> $2118

yugisokubodai

#4
Thank you very much.
Now I fully understand the mechanism of uploading data to Vram.
Here's some result.



June 11, 2016, 09:29:48 PM - (Auto Merged - Double Posts are not allowed before 7 days.)

There's a new problem arise. It's about the palette.
Say, I have the portrait in BG1, which is 16 colors and the text in BG3, 4 colors.

The problem is when I wrote to $2121 and $2122, it effects BG1 (the portrait) and BG3 (tex).
What should I do to seperate one palette for BG1 and one for BG3?

兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

Rappa

Write 1 palet to ram where it points to tilemap.

AWJ

Quote from: yugisokubodai on June 07, 2016, 07:11:37 PMThe problem is when I wrote to $2121 and $2122, it effects BG1 (the portrait) and BG3 (tex).
What should I do to seperate one palette for BG1 and one for BG3?



In mode 1, BG3 uses the first 32 colors in the palette. You need to make your BG1/BG2 tiles use a color attribute that doesn't overlap with the colors used by BG3 (i.e. 2 or greater).

yugisokubodai

Thank you.
I wrote the color ($2121, $2122 combo) twice. One for BG1 and one for BG3. They're not the same but still the palette for BG3 seems doesn't work.
兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

Disch

Did you change the palette bits for the background tile (in the tilemap)?

See 'p' bits:

Each entry in the tilemap is 2 bytes, formatted as (high low):
  vhopppcc cccccccc

  v/h  = Vertical/Horizontal flip this tile.
  o    = Tile priority.
  ppp  = Tile palette. The number of entries in the palette depends on the Mode
      and the BG.
  cccccccccc = Tile number.

yugisokubodai

Oh thank you, by changing the ppp bits, I can control the color now.
兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

UltimateUrinater

Wait..did you create those graphics yourself? Cuz I have been looking for a simple way to create snes graphics of my own...Maybe i just havent been searching hard enough. :thumbsup:

henke37

That's obviously from Fire emblem.

Bahamut ZERO

Quote from: UltimateUrinater on July 23, 2016, 01:53:21 AM
Wait..did you create those graphics yourself? Cuz I have been looking for a simple way to create snes graphics of my own...Maybe i just havent been searching hard enough. :thumbsup:

YYCHR is what I use to make/edit SNES graphics. Usually I just take a random rom, blank everything out with the first color (transparent) in a palette, and then go to town like it's MS paint.  :thumbsup:

Tile Layer Pro's another option I see most people use, but I find it to be clunky as balls compared to YYCHR. TLP does, however, have a tile arranger, but I just open up a second instance of YYCHR to accomplish the same with it's copy n paste functions (can't remember if TLP has copy/paste, it's been awhile since I've used it last).

Hope that helps!
Like Super Mario Land? Then you'll love my first completed Rom Hack: Maniac on the Run!