News:

11 March 2016 - Forum Rules

Main Menu

HDMA Question (SNES)

Started by justin3009, July 01, 2016, 05:15:17 PM

Previous topic - Next topic

justin3009

I'm rather curious on this and I'm extremely confused on how the heck Chrono Trigger is handling it.

I'm trying to rework the dialogue box a bit in Breath of Fire 2 so it can also keep the pretty looking tiles thus allowing multiple themes whenever it gets implemented... but of course that's not really possible due to how honestly most SNES games work.

As far as I can see, it looks like Chrono Trigger has HDMA that may actually read the tilemap data specifically for the dialogue box, although I could be wrong?  Honestly I'm not sure what it's doing but it's using Layer 1 to draw the dialogue box as well as everything else it needs while retaining the full quality like the menu and such.

Any idea how this works?  There may be other games that do this but I have honestly not seen any other game (Or that I can remember) that uses Layer 1 or 2 as dialogue box needs while keeping the background tiles and such where they are.
'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 looked at the gameplay but didn't look at any of the actual code.  Take this with a grain of salt:

CT's dialog box takes up the entirety of the screen width  (there's nothing seen left or right of it).  Therefore, it's entirely possible it's doing a NES-style raster effect where it just cuts to a different screen to draw the box.

You might normally think of each layer having a fixed tilemap that the game has to draw to... but a thing to remember is that the tilemap can be changed with a single register write.  And if you HDMA that write so it falls between two scanlines, you'll effectively "split the screen" by having the PPU stop drawing from the "world" tilemap and start drawing from the "dialogue" tilemap.

Do another write a few scanlines later to switch back and you're all set.

Bregalad

Chrono Trigger uses HDMA in textboxes to do a couple of different things :

  • Change the adress of tilemap of layer 0 and 2
  • Disable the timemap 1 and sprites
  • Change the scrolling to a fixed position for layer 0 and 2 (and then back to normal below the dialog box)
  • Use transparency to a lighting effect on layer 0 (and then back to normal below the dialog box)

I'm not exactly sure how this is done but probably most HDMA channels are taken up for this effect. Breath of Fire II's dialog boxes are however extremely simple - they are just rendered with layer 2. I do not see any advantage of hacking CT to have uglier dialog boxes.

justin3009

I'm aiming more of implement Chrono Trigger's styled dialogue boxes into Breath of Fire II.  Not the graphics but how the effect is done.

That split screen thing sounds plausible in a way.  vSNES noted.. I can't remember if it was X or Y address but it was wayyyyyyy into the 8000 for coordinates which was kind of striking.  That'd be super weird though wouldn't it since you're able to move around while the dialogue box is shown and even when it's drawing.

Edit: That might be right though.  Using vSNES without the dialogue box shows the coordinates properly and the Tilemap address DOES indeed change.  I'm surprised how this is pulled off though especially since you can move around with it and it doesn't seem to destroy any graphics.
'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

The problem with implementing the split screen approach is you'll need a chunk of unused VRAM to draw the text box to.  I would guess most games probably don't have much VRAM available at any given time.

justin3009

I'm curious how much it does need.  I think I have about 1536 free bytes that are available to use anytime during the on-screen dialogue.  (It's nice as well since you CAN'T move while the dialogue box is open, in fact, all events stop it looks like).

Edit: Wait, could I theoretically copy part of the tilemap that's on screen with the dialogue box into the blank space and then draw the dialogue box OVER the original tilemap?  Then once it's done, just have it write only a couple lines at a time as it's closing to give it the effect of 'closing' itself?
'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 01, 2016, 05:42:00 PM
I'm curious how much it does need.  I think I have about 1536 free bytes that are available to use anytime during the on-screen dialogue.

Assuming that's all in 1 clump that should be enough.  You don't need space for a full tilemap, just enough to hold the tiles you want to draw onscreen.

QuoteEdit: Wait, could I theoretically copy part of the tilemap that's on screen with the dialogue box into the blank space and then draw the dialogue box OVER the original tilemap?  Then once it's done, just have it write only a couple lines at a time as it's closing to give it the effect of 'closing' itself?

yeah.  I think that's what Der Langrisser does.

Downside here is this will all have to be done in VBlank.  And you'll have to do it a few lines at a time because you probably won't be able to finish all the drawing in a single frame.

This approach is probably more complicated, though, since you have to do scrolling computations to determine what part of the tilemap you want to replace.

justin3009

That shouldn't be a problem I don't think.  BOFII clears the dialogue box in an instant but it draws it one line at a time.  I could probably just use the original method it does but instead have it use Layer 1 instead!

Kind of an obvious solution but I didn't even think about it.  Thank you SO much for the help and the ideas on this!
'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.'

KingMike

Quote from: justin3009 on July 01, 2016, 05:42:00 PM
I'm curious how much it does need.  I think I have about 1536 free bytes that are available to use anytime during the on-screen dialogue.  (It's nice as well since you CAN'T move while the dialogue box is open, in fact, all events stop it looks like).
There is one secret.
Spoiler
The colosseum event. After the fight with Katt, you can move during that cutscene to push her back and cause a minor plot variation.
At least I think there's a dialogue box open during the time you can move but I'm not 100% on that.
[close]
"My watch says 30 chickens" Google, 2018

Bregalad

The problem is that you'll have to draw the box at a different address to compensate tilemap's scrolling. You'll also have to draw the tilemap back when the box closes. No big deal, but hacking this into an existing game...

With the NES, this was the only way to do textboxes at all. There's a reason they (mostly) stopped to do this on SNES when multiple layers became available... because coding this is a major annoyance. For the NES game I'm developing, the piece of code that does this is by far the most shitty and messy piece of code. However I cannot really fix that. Of course, NES attributes doesn't help, so with SNES and attributes being used in the higher bits of tile number entry will already help a lot.

Nevertheless you could get nice looking textboxes with this. Using graphic clip windows, you could even have the same lighting effect.

justin3009

#10
I totally forgot about that scene where it does scroll.  If worst comes to worst I could probably just have it forcefully close the dialogue box so there's no worry on that.  I don't think I could properly implement it scrolling with the screen as I still don't have a good handle on HDMA and everything else quite yet.  Just allowing better tiles is a huge step forward for this.

Edit: Okay now that I'm actually thinking about it with some time I have spare today, how would one go about figuring out a way to determine 'where' you the character is currently according to VRAM with BG 1/2 and such?  I'm sure it's different for each game and my best guess to go off of would be Final Fantasy 6 since both of these games use tile movement and share a very similar system.

Edit 2: Was studying Chrono Trigger's system a bit still.  I'm actually really confused by it still.  The Tilemap address does, indeed, change for BG1 and 3.. but the BG1 address is changed to where BG3's is, so they share the same area oddly enough.  But even then, it STILL uses the original Tilemap location to draw the BG1 tiles!  As far as I can see it looks like it's using HDMA basically as a way to draw the rest of the tiles but that seems.. odd.  If I could replicate what they did I could probably make it work but they do some crazy stuff with that game, most notably setting the Y coordinates to way in the 8000 which sets Vector D in Mode 7 to be 256 and it's coordinates to be 8000+ as well... blegh.

I'm trying to figure out an approach to BOFII that I can use but I'm coming up empty handed.  With how the game draws tiles originally, even adding in a separate routine to draw the remainder of Layer 1 will still overwrite everything so I can't simply just change the tilemap to be 256x256 instead of 512x256 without some extreme rewriting of every tile map in the game.  Minus that, I cannot figure out a proper method to get the location in VRAM to write to depending on the players coordinates or even the cameras.  There's so many variables that it's making it nigh impossible to do.  It's doable just.. I'm not sure what will work.
'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 02, 2016, 09:23:13 AM
Edit 2: Was studying Chrono Trigger's system a bit still.  I'm actually really confused by it still.  The Tilemap address does, indeed, change for BG1 and 3.. but the BG1 address is changed to where BG3's is, so they share the same area oddly enough.  But even then, it STILL uses the original Tilemap location to draw the BG1 tiles!  As far as I can see it looks like it's using HDMA basically as a way to draw the rest of the tiles but that seems.. odd.  If I could replicate what they did I could probably make it work but they do some crazy stuff with that game, most notably setting the Y coordinates to way in the 8000 which sets Vector D in Mode 7 to be 256 and it's coordinates to be 8000+ as well... blegh.

It shouldn't be as complicated as you're making it sound.  Did you find the HDMA byte-string?  Can you paste it here so I can see it?  I'm not all that familiar with SNES debuggers so finding it myself would take a bit and I'm lazy.


QuoteI'm trying to figure out an approach to BOFII that I can use but I'm coming up empty handed.  With how the game draws tiles originally, even adding in a separate routine to draw the remainder of Layer 1 will still overwrite everything so I can't simply just change the tilemap to be 256x256 instead of 512x256 without some extreme rewriting of every tile map in the game.  Minus that, I cannot figure out a proper method to get the location in VRAM to write to depending on the players coordinates or even the cameras.  There's so many variables that it's making it nigh impossible to do.  It's doable just.. I'm not sure what will work.

Tilemap address, tilemap size, scroll.... all of that can be changed with HDMA.  You dont' have to change any of your existing tilemaps -- all you have to do is set up HDMA so it splits the screen at two points in the frame.  The first time, changing tilemap address (& maybe size) to point to your new tilemap... and change the scroll.  And the second time, you "undo" all that and restore the original tielmap drawing stuff.

Conceptually it isn't really that complicated.