It is currently Fri Sep 21, 2018 9:56 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Tue Feb 20, 2018 4:37 pm 
Offline

Joined: Tue Feb 20, 2018 3:10 pm
Posts: 3
Hello everybody, I'm totally new here and don't know much about NES programming, so I apologize in advance if my questions are really dumb.

So, a little background, back in 2007 I took up the challenge of hacking NG3 back to it's japanese difficulty, and although I managed to restore the damage done by the enemies to the original famicom values, restore the original power ups and eliminate the limited continues, I never found a way to edit the spots where the enemies appeared in each level, and change those enemies back to the ones used in the japanese original. So out in frustration I abandoned my project...

So anyway, what I want to do now is mod the game and change the levels around. And I want to start by redesigning some backgrounds.

Basically what I want to do right now is to find where the game stores the background for each level map so I can rearrange the position of the tiles that are used in it and redisign it, without changing the actual objects of the level, just the background. It's my understanding that I can edit the tiles with a tile editor, but that's not what I need to do. What I need to change is the position where a tile appears in the background.

FCEUX lets me see the tile file and nametable, (addresses 2000 to 22FF) but that's not where the actual map is stored in the ROM, just what is displayed right at that moment in the screen, right? So I'm trying to find where those values (that identify each tile) are loaded from, with the debugger, because I'm guessing that's where the actual map is stored, but so far haven't had much success, just encounter little chunks of the map here and there.

Since it's my understaning that there are no universal map/level editors, my plan is to find where the game stores the map and edit it manually, rearranging the placement of each tile. But that would still have the problem of the palette being different when the tile is used in another place...

Is there a better, more intelligent, way to do this? Perhaps it could be done with an already existing utility? Perhaps with Shiryu's NES screen editor? But how I load the NG map into it if I can't even find it in the ROM?

Anyway, thanks in advance for any advice and orientation.


Last edited by Daniel X on Tue Feb 20, 2018 11:18 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Tue Feb 20, 2018 4:54 pm 
Offline
Formerly WheelInventor

Joined: Thu Apr 14, 2016 2:55 am
Posts: 1778
Location: Gothenburg, Sweden
Quote:
but that's not where the actual map is stored in the ROM, just what is displayed right at that moment in the screen, right?

Yes. Or rather, that is what can potentially be shown on-screen with the help of the scroll register. You generally have more nametable space than screen space - often worth 2 screens, sometimes more.

Nametables are 2d arrays in RAM which the PPU is using to fetch the right tile. Map data tends to look different from game to game. It could theoretically be stored as raw nametable-compliant data, but this is generally speaking wasteful on what little ROM space there is. It might instead be compressed, metatiled, drawn with the help of algorithms, stampcloned from structures varying in size (at least these are the most common methods), or a combination of said methods. I don't know what ninja gaiden 3 is using.

_________________
http://www.frankengraphics.com - personal NES blog


Top
 Profile  
 
PostPosted: Tue Feb 20, 2018 6:57 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10814
Location: Rio de Janeiro - Brazil
Name tables are the final format in which backgrounds are presented to the player, but since raw name table data is quite large (1kb per screen), any game with more than a couple of screens (i.e. pretty much any NES game) is guaranteed to use a much more compact format to represent maps in the ROM.

Each game stores maps differently, so there's no general purpose tool for this kind of editing. Each game has to be individually reverse-engineered so that their map formats can be cracked. Many popular games have already been analyzed to death, and already have documents and tools to make a hacker's job easier, but if this isn't the case of the game you're hacking, you'll have to do the reverse-engineering yourself.

Typically you start by putting breakpoints on name table writes, so you can see where the game is copying the data from. This will probably be a buffer in RAM. The next step is to use breakpoints to find out where the data in that buffer is coming from. Just keep following the data like that, and you'll eventually find where in the ROM it's coming from. The complicated part is that the data isn't simply copied from place to place, it actually goes through several transformations, and making sense of these algorithms isn't always easy.


Top
 Profile  
 
PostPosted: Tue Feb 27, 2018 9:23 am 
Offline

Joined: Tue Feb 20, 2018 3:10 pm
Posts: 3
FrankenGraphics wrote:
Quote:

Map data tends to look different from game to game. It could theoretically be stored as raw nametable-compliant data, but this is generally speaking wasteful on what little ROM space there is. It might instead be compressed, metatiled, drawn with the help of algorithms, stampcloned from structures varying in size (at least these are the most common methods), or a combination of said methods.

Thanks a lot for all that info! Guess I will need to do more homework and investigate what method is the game using :D

tokumaru wrote:
Quote:
Typically you start by putting breakpoints on name table writes, so you can see where the game is copying the data from. This will probably be a buffer in RAM. The next step is to use breakpoints to find out where the data in that buffer is coming from. Just keep following the data like that, and you'll eventually find where in the ROM it's coming from.

Yes, that's exactly what I have doing! However, something I can't quite understand is happening: after following the data from breakpoint to breakpoint I reached this address:

07:C149:B1 57 LDA ($57),Y @ $87E8 = #$91
07:C14B:9D F0 05 STA $05F0,X @ $05F1 = #$15

91 is the value that is finally displayed in the nametable and it seems to be loaded from the $87E8 address, so the next logical step would be to create a writing breaking point for $87E8, to find out where that address it getting that data from, right? But the thing is, after creating the breaking point, nothing happened! It seems like nothing is ever written in $87E8, which is weird since when I create a reading breaking point for $87E8, at the moment when is read the value is indeed 91, but right before is 00, so obviously something is writting data into it, right? So then, why the writing breaking point doesn't detect this change?


Top
 Profile  
 
PostPosted: Tue Feb 27, 2018 10:14 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 359
$8000 to $FFFF is ROM (writes will have no effect). Values can change due to bankswitching.


Top
 Profile  
 
PostPosted: Tue Feb 27, 2018 11:02 am 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3605
Location: Mountain View, CA
Daniel X wrote:
Yes, that's exactly what I have doing! However, something I can't quite understand is happening: after following the data from breakpoint to breakpoint I reached this address:

07:C149:B1 57 LDA ($57),Y @ $87E8 = #$91
07:C14B:9D F0 05 STA $05F0,X @ $05F1 = #$15

91 is the value that is finally displayed in the nametable and it seems to be loaded from the $87E8 address, so the next logical step would be to create a writing breaking point for $87E8, to find out where that address it getting that data from, right? But the thing is, after creating the breaking point, nothing happened! It seems like nothing is ever written in $87E8, which is weird since when I create a reading breaking point for $87E8, at the moment when is read the value is indeed 91, but right before is 00, so obviously something is writting data into it, right? So then, why the writing breaking point doesn't detect this change?

lda ($57),y is a read operation (load accumulator), not a write operation. The load is being done (through indirect addressing) from address $87E8. That should explain why your write breakpoint never got triggered.

The subsequent sta $05f0,x is a write operation (store accumulator), which is writing to address $05f0 + X index register (so address $05f1), which is in RAM.

There is certainly code run later on (almost certainly in the NMI handler) that reads content from RAM (presumably $05f0 as a base address) and writes it to the PPU (probably via sta $2007) after setting up the relevant nametable address location via writes to $2006. See the nesdev wiki for what those "magic addresses" (re: $2006, $2007) do. (They're actually called MMIO registers, or memory-mapped registers -- not to be confused with CPU registers (A, X, and Y)).


Top
 Profile  
 
PostPosted: Tue Feb 27, 2018 5:46 pm 
Offline

Joined: Tue Feb 20, 2018 3:10 pm
Posts: 3
Ok guys, thanks a lot for clearing that up! Guess I'm gonna educate myself more on bank switching and MMIO registers before asking the next batch of questions! :beer:


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group