News:

11 March 2016 - Forum Rules

Main Menu

Tracking Where to Write Tiles In VRAM

Started by justin3009, July 10, 2016, 09:53:25 AM

Previous topic - Next topic

justin3009

This is probably overly complicated for what I'm trying to do in-game, as was seen in the HDMA topic, of trying to get the dialogue boxes to write on BG 1 instead of BG 3 which would allow much more sleek looking designs and allow possible themes as well.

The problem I'm seriously having right now is how to properly track where in VRAM to write the tiles depending on the PC's location on screen.  If it was just plain 256x256 size it'd be no problem but the game uses 512x256 on all maps including the menu originally.  (The menu is now forced to be 256x256 as it's much easier to work with in that area).  The method's I've seen are from Chrono Trigger and Final Fantasy 6.  FF6's wouldn't work due to the game always being in 256x256 from what I can see while Chrono Trigger is 512x256, like BOF II.  The problem therein lies with how Chrono Trigger is using HDMA to properly switch the BG1/3 Tile Map but also retaining the original tile map location as well for the tiles.  Honestly not sure how the heck this works and it's probably the best way to go, but it's also overly complicated and hard to figure out.

The method that may be easiest is just to track the PC's location as you're on screen but that becomes complicated since most of BOF II's maps have more than one location on it but it gets cut off from view as you're moving.  Setting it to 256x256 actually kind of broke this so I'm not sure that's plausible but just setting it to 256x256 in general cuts the layer data in half which would need a tile map rewrite.. which is a bit of a pain considering one half of Layer 1 is at 9800 and the other half is at A000.. so they both fill their portions to the brim and I don't think there's an easy way to 'merge' them for a bit during dialogue without some funky issues.

Minus that, tracking the player is a bit obnoxious because of the multiple location on screen issue.  There could be a building that's say 100 tiles up from you but it's cut off from view, but you're currently in an area that's 100 tiles below and there's no plausible way to reach the above location unless you're 'forced' there from an exit.  So the X/Y camera coordinates could easily be 00 00 or they could be 40 FF which is kind of an ass to work with.

Honestly, I'm not sure how to track this properly nor do I know if this is the best way to go.  If I understood more on how Chrono Trigger uses HDMA for that I could probably replicate it to an extent but it's incredibly tricky.

If I could get any tips on this it'd be wonderful or maybe even a better method.  If worst comes to worst I'll just drop it back to Layer 3 and that'll be that.  I was hoping for Layer 1 mainly because the menu looks all spiffy but then the dialogue box is just.. bland.
'We have to find some way to incorporate the general civilians in the plot.'

'We'll kill off children in the Juuban district with an infection where they cough up blood and are found hanging themselves from cherry blossom trees.'

Disch

I'm not sure this approach is the best one.  IIRC in that other thread you had some free space in VRAM, right?  So draw you dialogue box there, then split the screen with HDMA to draw it.

justin3009

How does one split the screen with HDMA?  I honestly never knew this was even possible until it was noted that Chrono Trigger does it.  I don't understand how that works entirely.
'We have to find some way to incorporate the general civilians in the plot.'

'We'll kill off children in the Juuban district with an infection where they cough up blood and are found hanging themselves from cherry blossom trees.'

henke37

Just remember the fact that it's possible to change any rendering parameter during hblank unless explicitly forbidden.

Disch

Here's my best attempt to explain it visually:



justin3009

Yep, I can understand what it does in that regards of changing tile maps, I just don't understand how exactly it does it.  Are there specific registers it writes to that makes it read from a certain tile map and such like normal VRAM but using the HDMA bits?  The thing I noticed in Chrono Trigger is that it had a small section of RAM that told the tile map sizes for the regular map and then another for the 'HDMA' bit.  I think there was more as well that dictated where the tile map was too via VRAM address.
'We have to find some way to incorporate the general civilians in the plot.'

'We'll kill off children in the Juuban district with an infection where they cough up blood and are found hanging themselves from cherry blossom trees.'

Disch

Quote from: justin3009 on July 10, 2016, 04:37:15 PM
Are there specific registers it writes to that makes it read from a certain tile map and such like normal VRAM but using the HDMA bits?

It's the same as the normal registers.  $2107-210A control the tilemap address and size.

Maybe the problem here is a lack of understanding about what HDMA is and/or how it works?

Anomie's "regs.txt" document (link) describes it pretty well in the "DMA AND HDMA" section.  Basically HDMA will count down the scanlines, then will perform a specific write (or series of writes) to a register at address $21xx  (which is where most of the PPU regs sit).  But if you have a specific question I might be able to help answer it.

henke37

In other words, HDMA is just a convenience feature so that you don't have to listen for the IRQ and do the poke manually.

justin3009

I can understand the basis of HDMA and such, I don't quite understand how it can write to the same $2xxx register that dictates the tilemap size and location but not have it interfere with the original byte that's there.  In fact, I don't really understand how it does ANY of that aspect without causing a horrible jumbled mess of everything on screen.
'We have to find some way to incorporate the general civilians in the plot.'

'We'll kill off children in the Juuban district with an infection where they cough up blood and are found hanging themselves from cherry blossom trees.'

Disch

#9
Quote from: justin3009 on July 12, 2016, 05:23:17 PM
I can understand the basis of HDMA and such, I don't quite understand how it can write to the same $2xxx register that dictates the tilemap size and location but not have it interfere with the original byte that's there.

It does interfere with the byte that's there.  It replaces it.  That's kind of the whole point.

QuoteIn fact, I don't really understand how it does ANY of that aspect without causing a horrible jumbled mess of everything on screen.

The SNES renders things one scanline at a time*.  Once it renders them, they're rendered and visible and impossible to change.

So if you tell HDMA to change the tilemap on scanline 100 ... scanlines 0-99 have already rendered ... they're done.  Your change (the new tilemap) will take effect for scanlines 100+ only.



Which is effectively how "splitting the screen" works.
- You render the top section with the "normal" settings.
- Then change the settings for the middle section to draw the dialogue box
- Then change/revert the settings back to their original value to draw the bottom portion




*(Technically it renders "1 pixel at a time" or even finer than that.  But given how all emulators -- even the super-strict Higan/BSNES -- emulate on a scanline-by-scanline basis and nobody really knows the details of what the SNES is doing during each individual scanline..... "1 scanline at a time" is close enough)

justin3009

I'm assuming then that it repeatedly is switching the bytes while the dialogue box and such is initiated then since the HDMA is constantly going when it's drawn.  Would that be a safe assumption?
'We have to find some way to incorporate the general civilians in the plot.'

'We'll kill off children in the Juuban district with an infection where they cough up blood and are found hanging themselves from cherry blossom trees.'

Disch

Quote from: justin3009 on July 12, 2016, 06:11:49 PM
I'm assuming then that it repeatedly is switching the bytes while the dialogue box and such is initiated then since the HDMA is constantly going when it's drawn.  Would that be a safe assumption?

It will switch the bytes exactly twice:  once to start the dialogue box, and again to stop it.

HDMA is "constantly going" in that it counts scanlines as they go by.  Once the desired number of scanlines pass, it will pause the CPU for a few cycles while it jumps in and does the desired writes, then will let the CPU resume.  HDMA effectively just let's you skip the process of counting scanlines yourself (which you had to do on older systems like the NES).

tryphon


justin3009

Ah okay, I think I got a much better understanding of that now.  Certainly makes a lot more sense than what it did before so thank you much on the clarification!
'We have to find some way to incorporate the general civilians in the plot.'

'We'll kill off children in the Juuban district with an infection where they cough up blood and are found hanging themselves from cherry blossom trees.'

Revenant

Quote from: Disch on July 12, 2016, 05:54:17 PM
*(Technically it renders "1 pixel at a time" or even finer than that.  But given how all emulators -- even the super-strict Higan/BSNES -- emulate on a scanline-by-scanline basis and nobody really knows the details of what the SNES is doing during each individual scanline..... "1 scanline at a time" is close enough)

bsnes/higan actually does have a pixel-by-pixel renderer - that's one of the main draws of the "accuracy" profile. That's how it is able to emulate things like changing the background mode mid-scanline (that's mode 7 on the left and mode 1 on the right), and some of the visual effects in Air Strike Patrol, which is commonly cited as one of the games that made a per-pixel renderer necessary.

KingMike

Quote from: Revenant on July 12, 2016, 09:58:24 PM
and some of the visual effects in Air Strike Patrol, which is commonly cited as one of the games that made a per-pixel renderer necessary.
Why use a sprite for the plane's shadow when we can do something much more complicated? ;D
"My watch says 30 chickens" Google, 2018

Disch

Quote from: Revenant on July 12, 2016, 09:58:24 PM
bsnes/higan actually does have a pixel-by-pixel renderer - that's one of the main draws of the "accuracy" profile. That's how it is able to emulate things like changing the background mode mid-scanline (that's mode 7 on the left and mode 1 on the right), and some of the visual effects in Air Strike Patrol, which is commonly cited as one of the games that made a per-pixel renderer necessary.

I stand corrected!  I guess SNES emulation has made strides since I last checked.  Good to hear.

justin3009

One last thing to be sure I understand this! So basically what's going on is that when it switches the tilemap with HDMA going, it's doing it one scanline at a time. The tile map is already predetermined in drawn in VRAM, but HDMA does it one line at a time as it displays so it doesn't cause any graphic corruption. After its done with however many lines, it switches back to the original tilemap setting.

Does it then keep repeatedly switch the tilemap byte repeatedly as the dialogue box is there? I'm assuming it does because altering any byte of data that dictates with HDMA going causes graphic corruption.
'We have to find some way to incorporate the general civilians in the plot.'

'We'll kill off children in the Juuban district with an infection where they cough up blood and are found hanging themselves from cherry blossom trees.'

Disch

Quote from: justin3009 on July 13, 2016, 09:47:35 AM
One last thing to be sure I understand this! So basically what's going on is that when it switches the tilemap with HDMA going, it's doing it one scanline at a time. The tile map is already predetermined in drawn in VRAM, but HDMA does it one line at a time as it displays so it doesn't cause any graphic corruption. After its done with however many lines, it switches back to the original tilemap setting.

Does it then keep repeatedly switch the tilemap byte repeatedly as the dialogue box is there? I'm assuming it does because altering any byte of data that dictates with HDMA going causes graphic corruption.

Err... well... HDMA doesn't display anything.  Let's backtrack a bit.


BIG PICTURE

The PPU is what draws stuff.  It has a chunk of memory in VRAM as well as a bunch of registers.  Games tell it what to draw by filling VRAM with graphic tiles, tilemaps... then sets PPU settings by writing appropriate junk to the PPU registers.

When it's time for the frame to be rendered, the PPU will constantly be checking all those regs and doing VRAM fetches to draw the appropriate pixel to the screen.  Which means if you change a PPU register in the middle of the frames, that will [more or less] immediately change how the PPU draws.

The thing to note here is that program code on the CPU is run in parallel with the rendering done on the PPU.  So really this is all about timing.

I don't remember the cycle counts exactly, but each scanline takes the PPU roughly ~150 CPU cycles to complete.  For a point of reference, LDA immediate takes the CPU 2 cycles to complete.  So the game can run maybe 40 instructions or so in the span of one "scanline" worth of time.

On older systems like the NES... games that wanted to split the screen would have to count the number of cycles they executed to keep track of the "time", so that they can know when the PPU is about to start drawing a specific scanline.  But with HDMA you don't have to do that.

All HDMA does... is it watches the PPU execute scanlines... counts them as they pass.... then when the desired number of scanlines pass, it cuts in and does a quick write to change how the PPU will draw from that point on.

So if you want the screen to switch to a dialogue box on scanline 100, you'd tell HDMA to count 100 scanlines then do a write to switch tilemaps.


QuoteDoes it then keep repeatedly switch the tilemap byte repeatedly as the dialogue box is there?

You could do it that way, but no that's not what you'd want.

To switch the tilemaps you only need the HDMA to do exactly two writes.  One at the start of the dialogue box, and one at the end.  That's it.

- HDMA waits for X scanlines while the PPU draws the normal world
- HDMA cuts in, does a single write to switch tilemap
- HDMA waits for Y scanlines while the PPU draws the dialogue box
- HDMA cuts in again, does a single write to switch tilemap back to its original state
- HDMA is done -- PPU draws the normal world for the rest of the frame.



QuoteI'm assuming it does because altering any byte of data that dictates with HDMA going causes graphic corruption.

I might not understand what you mean here -- but HDMA does not cause graphic corruption when you use it properly.  This is exactly what it was designed to do -- it makes carefully timed writes to PPU registers mid-frame for easy split-screen effects.  That's its entire function.

justin3009

That's what I get when typing frantically on break at work with my phone.

What I meant was I assumed it kept repeatedly switching the bytes as if I mess with anything in RAM where the HDMA reads or even where the game regularly reads, it causes graphic corruption to occur, not that HDMA IS causing it, but the data being read appears to be read constantly.
'We have to find some way to incorporate the general civilians in the plot.'

'We'll kill off children in the Juuban district with an infection where they cough up blood and are found hanging themselves from cherry blossom trees.'