News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: Zelda NES Hacking Questions  (Read 1597 times)

RetroNova10

  • Jr. Member
  • **
  • Posts: 25
    • View Profile
Zelda NES Hacking Questions
« on: April 03, 2018, 07:40:16 pm »
To start off, I'll say that I have little to no experience with asm, but I do generally understand the basics of it (how it implements different commands and such). I also am quite lacking when it comes to knowledge of NES hardware and software as well. I do know Java, however, and have worked in a few other languages as well, so I have a sense of how software works and everything of that nature.

I'm generally more focused on game design. I really want to make a more artistically-interesting Zelda hack with different areas (dungeons and overworld), because I love working within limitations (I've made custom content for Banjo-Kazooie and DOOM II).


So, I drew several tiles and began drawing over those in the ROM. However, I had forgotten that many 16x16 sprites reuse 8x8 tiles as to save memory.


So I'm curious: how can I disable this tile reusing, so that I can have the freedom of allowing sprites to be more uniquely drawn?

I'm thinking one part of the solution might require ROM expansion, and, if not, I'm assuming the following question's solution will...

How can I increase the number of possible tiles (and possibly increase variation of palettes used for tiles within one room)?


On another note, here's the planned look of the title screen, and mockup concept of the box art (just for fun. I haven't gotten around to writing "Return" in the proper handwritten font yet)  ;).




Thanks for reading!

Disch

  • Hero Member
  • *****
  • Posts: 2618
  • NES Junkie
    • View Profile
Re: Zelda NES Hacking Questions
« Reply #1 on: April 04, 2018, 12:51:06 am »
Quote
So I'm curious: how can I disable this tile reusing, so that I can have the freedom of allowing sprites to be more uniquely drawn?

This is handled differently in each game.  Somewhere in the ROM is some kind of data structure that indicates which 8x8 tiles are used to construct the full sprite (as well as the coordinates to draw them relative to the sprite position).  You'll have to find this data to modify it, though again, the exact format of it can vary so I don't really know what to tell you to look for.

Some possible ways of finding it:
- Check a wiki or something (like DataCrystal).  LoZ is a pretty popular game so this information may have been found already.
- Use a file corrupter:  You can use the PPU viewer in FCEUX to see which tile number represents the 8x8 portion of a sprite.  Corrupt the ROM to change occurances of that byte to something else and narrow down which byte is the byte you're looking for.
- Do a back-trace and examine the assembly to see where it's getting the data from.  LoZ uses the $02xx page in memory to store its OAM, so watch [interesting] writes to that range to see where it's getting the values from.



Though remember, even if you do this, you still are limited to 256 sprites tiles at any one time.

Quote
How can I increase the number of possible tiles

Do you mean 8x8 pixel tiles? Or "map tiles"  (floor, sand, statue, block, etc)

The latter would involve completely redesigning the map format and writing all new code to load your new maps.  Needless to say this is quite a big job and would require lots of asm work.  Plus it would render any map editors completely useless as they wouldn't recognize your new format.

As for the former... it doesn't look like all the CHR is used for dungeons (there are a LOT of blank tiles)... so you might be able to the CHR to put more graphics in, and modify the TSA for the map tiles to make use of them.

Quote
(and possibly increase variation of palettes used for tiles within one room)?

You can't have more than 4 BG palettes on-screen at once.  <-   This is a hard limit of the NES.  No way around it*.
In dungeons, LoZ seems to use them like so:

2 palettes for the HUD at the top of the screen (red/pink/orange for the life meter and coin/key images ... and white/blue for everything else)
2 palettes for the actual map

So you can't add more palettes for the map without removing them from the HUD.  OR you could have the HUD and map share a palette, but this would have the side-effect of some tiles not "fading out" in dark rooms (or, if you change it so they DO fade out... part of the HUD will also fade out)



Quote
I'm thinking one part of the solution might require ROM expansion

ROM expansion is not a magic cure-all.  It's not exactly trivial on the NES, and making use of the extra space requires a good amount of asm work anyway, as you need to swap PRG banks around -- which can lead to game-crashing bugs if you don't know what you're doing.

My word of advice here is:  if you don't know enough asm to know how to expand the ROM and make use of the expanded space -- you probably don't know enough asm to know whether or not you need to expand the ROM in the first place.




(*you can technically get around it by swapping palettes mid-frame but this is extraordinarily difficult to do properly and is generally not something to be considered)
« Last Edit: April 04, 2018, 07:49:36 am by Disch »

RetroNova10

  • Jr. Member
  • **
  • Posts: 25
    • View Profile
Re: Zelda NES Hacking Questions
« Reply #2 on: April 04, 2018, 10:36:50 am »
Thank you so much for the extensive response!

Quote
Some possible ways of finding it:
- Check a wiki or something (like DataCrystal).  LoZ is a pretty popular game so this information may have been found already.
- Use a file corrupter:  You can use the PPU viewer in FCEUX to see which tile number represents the 8x8 portion of a sprite.  Corrupt the ROM to change occurances of that byte to something else and narrow down which byte is the byte you're looking for.
- Do a back-trace and examine the assembly to see where it's getting the data from.  LoZ uses the $02xx page in memory to store its OAM, so watch [interesting] writes to that range to see where it's getting the values from.
Yeah, I've been using the FCEUX PPU viewer and hex editor to change palettes.

I have actually been to the Zelda NES's site on DataCrystal, but I had never checked any of the useful sub-pages relating to it, such as https://datacrystal.romhacking.net/wiki/The_Legend_of_Zelda:ROM_map and https://datacrystal.romhacking.net/wiki/The_Legend_of_Zelda:Character_Palette_Assignments.

Quote
Somewhere in the ROM is some kind of data structure that indicates which 8x8 tiles are used to construct the full sprite (as well as the coordinates to draw them relative to the sprite position).
Isn't this called T(ile)S(quaroid)A(ssembler)? I guess I'll have to do some research on this. I've been looking around the DataCrystal Zelda page, and it seems like the following addresses could contain it?

I've been trying to find the location of the TSA stuff, but to no avail. It's a pity that the handy (yet very specific) information needed to accomplish these isn't out there, or at least isn't very easily obtainable. I'm sure there are a few people out there, who have experience with Zelda memory, that would be able to help more thoroughly.

Quote
Do you mean 8x8 pixel tiles? Or "map tiles"  (floor, sand, statue, block, etc)
I meant 8x8 pixel tiles (I can't recall the exact term for them, assuming there is one).

About the "increase palettes", (sorry, I wasn't very clear about what I meant) I was talking about having overworld rooms that had more palette sprite variety than simply the outer border and inner palette regions. For example, in The Legend of Link hack, there are often single tiles within the room that uses a palette unlike the inner and border palette regions.

And, seeing as there is unused memory, I'm guessing I can simply modify the data nearby to the 8x8 tiles using TileMolester or TileLayerPro and add more, then using the "id" of those tiles in the room layout definitions. Although, I guess that would require me to assign palettes to them, which shouldn't be too tricky. (this should be useful: https://datacrystal.romhacking.net/wiki/The_Legend_of_Zelda:Character_Palette_Assignments)

There was something else I had intended to add to this reply, although I've forgotten now. Hopefully it'll turn up. Again, thanks for reading!

Fiskbit

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Zelda NES Hacking Questions
« Reply #3 on: April 04, 2018, 03:03:44 pm »
The Legend of Link is able to do that because the entire screen data system was rewritten for it. You'd need a fair amount of skill with assembly to be able to do something similar for your hack.

The TSA/metatile data for the overworld is located at $1698C-169C3 and $169C4-169F3, and there are two formats. The second region is 4 bytes per block determining the 4 tiles that make up each of the first 16 blocks (IDs #$00-0F), while the first region is 1 byte per block determining the first tile to use for a given block (IDs #$00-37) and also indicates whether a block is an interactive block. If the start tile data is #$E6-EA, the block will be an interactive block (using an object ID from the list at $16980-16985) and its start tile will be replaced (according to the replacement start tile list at $16986-1698B). Then, if the block ID is #$10 or above, the block is built from 4 consecutive tiles beginning with the start tile; otherwise, it uses the 4 bytes for this block from the other table. Note that the two dungeon passageway screens are treated as overworld screens, so blocks that don't make sense in an overworld context may be used there. The only 4-byte block that I believe is unused is ID #$04. Also, interactive blocks indicated by start tiles #$E9 (pushable armos) and #$EA (bombable armos) are unused.

Were you to repurpose any existing unused blocks, you'd need to update the columns that the screen is built out of. This is not an easy task. That is discussed in detail in this post.

The dungeon block data at $16728-1672F is a lot more restrictive. These are start tiles for each of the 8 dungeon blocks, but if the value is < #$70 or >= #$F3, the tile is repeated 4 times to form the block rather than using 4 consecutive tiles.

Changing the game to make blocks less restrictive is possible, of course, but it's not trivial. For the overworld, in addition to relocating the 4-byte table to a location that would allow it to house all 64 possible blocks and updating the overworld screen building function ($16A04), you'd need to update the mechanism used for replacing onscreen blocks (such as when pushing a block), which is based around the start tile system. For dungeons, you'd need to add a 4-byte table system, too.

(Note that it's been a while since I've worked with the above information, so it's possible I got one or more things a little wrong.)

Regarding ROM expansion, unless you're doing something really crazy (and probably not even then), this is not a game that really needs to be expanded. There is ample free space available in every bank except the last one, and it's fairly easy to relocate a lot of the code from the last bank to other ones.

IAmCaptPlanet

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Zelda NES Hacking Questions
« Reply #4 on: April 05, 2018, 03:42:48 pm »
cool, i like the idea of finishing out a NES Zelda "trilogy

Legend of Zelda
Adventures of Link
Return of Ganon

would be cool if it could have both styles from 1 & 2 (overworld and dungeons like 1 AND sidescrolling caves/areas and towns like 2)

RetroNova10

  • Jr. Member
  • **
  • Posts: 25
    • View Profile
Re: Zelda NES Hacking Questions
« Reply #5 on: April 05, 2018, 10:22:31 pm »
Quote
cool, i like the idea of finishing out a NES Zelda "trilogy

Legend of Zelda
Adventures of Link
Return of Ganon

Certainly! That was my intent. I've always wanted it to be a complete, trilogy, and the very satisfying consistent naming style really works.

Quote
would be cool if it could have both styles from 1 & 2 (overworld and dungeons like 1 AND sidescrolling caves/areas and towns like 2)

Oh man. I wish I had enough experience, knowledge, and skill with NES hacking to accomplish that! I guess I always could do what the Bow and other items' rooms did, where it made it look like a side scroller... Now that I think about it, I'm definitely going to consider it!

April 07, 2018, 11:41:57 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Thank you so much for this useful information!

Quote
(IDs #$00-0F)
What are the different kinds of intractability? (and what value defines each one?)

April 08, 2018, 01:14:00 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Additionally, why do sprites seem to be offset, not being contained into one 8x8 tile?

« Last Edit: April 08, 2018, 01:14:01 pm by RetroNova10 »

The3Dude

  • Jr. Member
  • **
  • Posts: 44
    • View Profile
Re: Zelda NES Hacking Questions
« Reply #6 on: April 12, 2018, 05:57:02 pm »
Yes they can!!! Use this utility https://www.romhacking.net/utilities/958/

Then click on pattern, change it to 16x and press the minus symbol until they are lined up.
~The3Dude~

Trax

  • Sr. Member
  • ****
  • Posts: 462
    • View Profile
    • Trax ROM Hacking
Re: Zelda NES Hacking Questions
« Reply #7 on: April 12, 2018, 07:30:53 pm »
For information that is not on DataCrystal, use my disassemblies, and RAM Map :

http://www.bwass.org/romhack/zelda1/zelda1bank0.txt
http://www.bwass.org/romhack/zelda1/zelda1bank1.txt
http://www.bwass.org/romhack/zelda1/zelda1bank2.txt
http://www.bwass.org/romhack/zelda1/zelda1bank3.txt
http://www.bwass.org/romhack/zelda1/zelda1bank4.txt
http://www.bwass.org/romhack/zelda1/zelda1bank5.txt
http://www.bwass.org/romhack/zelda1/zelda1bank6.txt
http://www.bwass.org/romhack/zelda1/zelda1bank7.txt
http://www.bwass.org/romhack/zelda1/zelda1rammap.txt

I have more than 95% of the ROM disassembled. If I found out what a data table does, I comment briefly. If you see a question mark, it means it's my best guess and I'm not sure. You don't have to understand all the code, but the comments can give you an idea of what's happening. Some tables may be partially formatted or analyzed. Keep in mind that I use real addresses, so you have to add 0x10 to compensate for the ROM header.

There are explanations for tile mappings in Bank 5, at 1697C for Overworld, and 16718 for Dungeons.

Here are a few other things of interest:

Code: [Select]
4000: Pointer Table for Text (26 * 2 = 4C bytes)
404C: Text Data (plus info on text data structure)
45A2: Table for Text Pointers Offsets and Attributes (15 bytes)
6E04: Tile Mapping Codes for Enemies (6B bytes)
6E6F: Sprite Codes for Cave Characters (14 bytes)
6E83: Tile Mapping Codes for Enemy Frames (CC bytes)
6F4F: Table for Enemy Attributes (CC bytes) (Palette Code and Flipping)
7127: Items Tile Mappings Offsets (25 bytes) (Offset into table at 714C)

RetroNova10

  • Jr. Member
  • **
  • Posts: 25
    • View Profile
Re: Zelda NES Hacking Questions
« Reply #8 on: April 12, 2018, 10:27:56 pm »
Thanks a lot for the info, Trax! I still don't understand how column definitions work, could you give a more descriptive explanation?

Trax

  • Sr. Member
  • ****
  • Posts: 462
    • View Profile
    • Trax ROM Hacking
Re: Zelda NES Hacking Questions
« Reply #9 on: April 15, 2018, 12:55:54 am »
For starters, what I call "Column Data" is the codes associated with the different columns. There are 16 columns per screen for the Overworld. Column definitions define what tiles make the columns themselves. Column data starts at 15418 (Bank 5), and you always have 0x10 bytes per screen. The Overworld has 0x80 screens, but some are recycled, so in reality, it's 0x7C unique screens. Therefore, 0x7C0 bytes in total.

Column definitions start at 0x15BD8 (Bank 5), and are stored using a weird byte structure. Here it is:

Code: [Select]
..xx xxxx Tile Code
.x.. .... Tile is Repeated Once
x... .... Start of a Column Definition

Bits 0-5 are self-explanatory. If bit 6 is set, then repeat the tile once. This is for saving space, some sort of simple compression scheme. Bit 7 determines if this byte represents the beginning of a column. This one is a bit more confusing, so let's take an example. We have the starting screen, Code 77, and its column data:

Code: [Select]
01 A7 84 90 10 02 A5 08 08 A0 06 06 06 06 01 01
Let's take the second column, code A7. To find the beginning of the data for this column's definition bytes, we start by taking bits 4-7. This will give us a "column group". This one is group A. Bits 0-3 give us how far in the column definition data we will go before processing bytes. Our example is 7. So we basically need to find the 8th (because it's zero-based) byte that has bit 7 set. Take pointer A from table at 0x19D0F (Bank 6). The pointer gives us 0x15E27. Let's go back to bank 5 at this offset. We have:

Code: [Select]
DB 5B 34 4E 4E 1A 1B
DB 5B 35 4E 4E 1A 1B
9B 35 4E 4E 4E 0E 33 1B
9B 34 4E 4E 4E 0E 32 1B
9B 34 4E 4E 4E 0E 1A 1B
9B 35 4E 4E 4E 0E 1A 1B
DB 5B 34 0E 32
DB 5B 35 0E 33 5B
DB 34 4E 4E 0E 32
DB 35 4E 4E 0E 33
DB 5B 07 4E 4E 4E

You see a pattern here? I added a line break every time I bumped into a byte that has bit 7 set. Each of these lines are the actual data used to compose columns. The first on the list above is for 0xA0. Our example is 0xA7, so the decoding goes like this:

Code: [Select]
DB xx.x x.xx Tile Code 1B, repeat once, start of column definition
5B .x.x x.xx Tile Code 1B, repeat once
35 ..xx .x.x Tile Code 35
0E .... xxx. Tile Code 0E
33 ..xx ..xx Tile Code 33
5B .x.x x.xx Tile Code 1B, repeat once
DB xx.x x.xx Tile Code 1B, repeat once

Uncompressed we get this sequence of Tile Codes:

1B 1B 1B 1B 35 0E 33 1B 1B 1B 1B

Notice that I spilled over a byte that has bit 7 set. It doesn't matter. You only care about bit 7 when you want to find the starting point in the data. When you decode bytes, you simply go on until you have 0xB (11) tiles decoded. The matrix that makes a screen is 16x11 tiles. You do that 16 times and you have all the tiles codes you need for one screen.

Any questions?  8)

RetroNova10

  • Jr. Member
  • **
  • Posts: 25
    • View Profile
Re: Zelda NES Hacking Questions
« Reply #10 on: April 15, 2018, 01:38:47 am »
Wow. This was so incredibly helpful! I'm still a little fuzzy on the concept. I hadn't realized that the values in the HEX that are normally viewed as hexadecimal actually have to be thought of as binary in order to format them correctly (unless I'm totally wrong). Is there some kind of list of tile ID's that I could use when creating columns? Additionally, what exactly are the pointers, and how are they used?

Thank you SO much!

Trax

  • Sr. Member
  • ****
  • Posts: 462
    • View Profile
    • Trax ROM Hacking
Re: Zelda NES Hacking Questions
« Reply #11 on: April 18, 2018, 01:50:23 am »
You're welcome  :thumbsup:

So yes, of course, if you're going to do ROM Hacking, you have to understand bit fields. As for pointers, you should totally learn that concept too, and how to convert from pointers to actual ROM offsets, and vice-versa. I'm sure there are plenty of documents on that subject in the Documents section of RHDN. There's even a category called "Pointer Hacking".

Tile Codes and Tile Mappings for the Overworld are at 0x1697C (bank 5). A Tile Code < 0x10 means that you have to refer to the table at 0x169B4, and use the Tile Code as an index. Four bytes per entry, there are your tile IDs. This means that the first 0x10 tiles of the table at 0x1697C are not useful. The next bytes, though, are used for Tile Codes >= 0x10. A Tile Code "C" means the tile is made of C, C+1, C+2, C+3. As an example, Tile Code 0x1B (full rocky wall), value is 0xD8. It means the tile is made of D8-D9-DA-DB. All tiles are layed out in inverted N pattern, which is, in order: top-left, bottom-left, top-right, bottom-right.

Also, you have to consider tiles that contain secrets, which are codes E5 to EA. Their corresponding tile codes are at 0x16976.