That is how I was doing it too. I always felt there had to be a better way.snarfblam wrote: ... it checks the flag set by the NMI and if set, then runs the NMI routine.
Metroid ported to use the MMC3.
Moderator: Moderators
Re: Metroid ported to use the MMC3.
Re: Metroid ported to use the MMC3.
An update:
The Metroid disassembly is incredibly disorganized. It's pretty clear that multiple people were working on this project, and that the left hand didn't know what the right was doing. Over the past few days of tidying the source code up, I've seen many dead ends - code that looks like it would do something but (a) is never called, or (b) because of the input data it receives, it always exits immediately. Redundant loading of variables, as in the snippet below, is common:
The AI routines are labyrinth, inefficient, and have inconsistent ways of calling subroutines. Because the code is disorganized and bizarre, I'm uncertain that fully documenting the remaining code would be helpful to anyone. While Metroid was certainly an amazing accomplishment for its time, it wouldn't be a good template for future projects.
That said, I think I've done something pretty neat.
The original disassembly referenced a ton of hardcoded addresses. I've managed to replace all of these in the $C000-$FFFF range (the hardwired last bank that contains the main game engine) with labels - although not very descriptive ones as of yet. If I decide to continue working on this project, I'm going to start cleaning up the GameEngine.asm source code file - perhaps separating it out, placing all related code together. Thus this project would become less of a straight disassembly of Metroid - instead, a better organized and lightly optimized version of that game.
We'll see.
The Metroid disassembly is incredibly disorganized. It's pretty clear that multiple people were working on this project, and that the left hand didn't know what the right was doing. Over the past few days of tidying the source code up, I've seen many dead ends - code that looks like it would do something but (a) is never called, or (b) because of the input data it receives, it always exits immediately. Redundant loading of variables, as in the snippet below, is common:
Code: Select all
LC457:
lda MirrorCntrl ;Load MirrorCntrl into A.
jmp PrepPPUMirror
...
PrepPPUMirror:
lda MirrorCntrl ;Load MirrorCntrl into A.
jmp SetPPUMirror ;Set mirroring through MMC3 chip.The AI routines are labyrinth, inefficient, and have inconsistent ways of calling subroutines. Because the code is disorganized and bizarre, I'm uncertain that fully documenting the remaining code would be helpful to anyone. While Metroid was certainly an amazing accomplishment for its time, it wouldn't be a good template for future projects.
That said, I think I've done something pretty neat.
The original disassembly referenced a ton of hardcoded addresses. I've managed to replace all of these in the $C000-$FFFF range (the hardwired last bank that contains the main game engine) with labels - although not very descriptive ones as of yet. If I decide to continue working on this project, I'm going to start cleaning up the GameEngine.asm source code file - perhaps separating it out, placing all related code together. Thus this project would become less of a straight disassembly of Metroid - instead, a better organized and lightly optimized version of that game.
We'll see.
Re: Metroid ported to use the MMC3.
A quick note: UxROM is not MMC3, TxROM is.pops wrote:That said, I think I've done something pretty neat.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
Re: Metroid ported to use the MMC3.
Ha. I started using that designation for a different project, months ago, and never double checked it. Thanks. 
Re: Metroid ported to use the MMC3.
About the disorganized code. Exactly 10 years ago, I tried out SnowBro's metedit, and I remembered there was a patch that reduced the size of level data by about 1/4 or something due to metroid storing attribute bits for every object placed when the whole screen was set to a single attribute anyway.
Also the PHP as the first thing in NMI.
Also the PHP as the first thing in NMI.
Re: Metroid ported to use the MMC3.
I'm certain this isn't the case - the very first room in Brinstar contains objects using all four BG palettes.43110 wrote:I remembered there was a patch that reduced the size of level data by about 1/4 or something due to metroid storing attribute bits for every object placed when the whole screen was set to a single attribute anyway.
However, on the subject of making level data much smaller:
Each area in Metroid (Brinstar, Tourian, etc.) occupies a single 16kb bank. Almost 50% of these Area banks is occupied by the sound engine and AI routines common to every Area bank. These shared routines are further duplicated in other banks. I estimate that eliminating this shared data would save almost 36kb of rom space! I'm certain it would be possible to move these shared routines into a single shared bank of ~8kb (leaving ~8kb of space left over for new AI/graphics routines), while simultaneously doubling the space available for an Area's rooms/structures/graphics/music data. There's also ~3kb of free space in the Graphics bank.
I've started reorganizing the code in the fixed code bank: instead of a single 9600 line file, there's now separate files for graphics routines, sound effects, PPU writing, room display, and so on. There's still a ton of work left to go, of course. I've also eliminated ~240 bytes of data - and the game still runs fine, as far as I can tell (I haven't done a complete run through yet).
- rainwarrior
- Posts: 8062
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Metroid ported to use the MMC3.
I read this and I was quite surprised they would waste so much space duplicating routines like this that could easily be reached by a banked-jump, but then I realized that this would have been unavoidable on the FDS, so it kinda makes sense as a port from that version.pops wrote:Each area in Metroid (Brinstar, Tourian, etc.) occupies a single 16kb bank. Almost 50% of these Area banks is occupied by the sound engine and AI routines common to every Area bank. These shared routines are further duplicated in other banks.
Re: Metroid ported to use the MMC3.
Same as if you first looked at Kid Icarus, you probably wouldn't guess that it needs 8 KB of WRAM.rainwarrior wrote:I read this and I was quite surprised they would waste so much space duplicating routines like this that could easily be reached by a banked-jump, but then I realized that this would have been unavoidable on the FDS, so it kinda makes sense as a port from that version.pops wrote:Each area in Metroid (Brinstar, Tourian, etc.) occupies a single 16kb bank. Almost 50% of these Area banks is occupied by the sound engine and AI routines common to every Area bank. These shared routines are further duplicated in other banks.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
Re: Metroid ported to use the MMC3.
If your game is 80K, there's no hurt in duplication anyway.
Re: Metroid ported to use the MMC3.
You know, I've already written a hack to expand Metroid that places each level's object and screen definitions into its own 16k bank.
Re: Metroid ported to use the MMC3.
I didn't know that.snarfblam wrote:You know, I've already written a hack to expand Metroid that places each level's object and screen definitions into its own 16k bank.
What modifications did you make? Did you have to make any trade-offs?
Re: Metroid ported to use the MMC3.
It was basically removing the third byte of each of the object data in room definitions, and letting the attribute byte of the whole room take charge. Not that much of a saver for sure.pops wrote:I'm certain this isn't the case - the very first room in Brinstar contains objects using all four BG palettes.43110 wrote:I remembered there was a patch that reduced the size of level data by about 1/4 or something due to metroid storing attribute bits for every object placed when the whole screen was set to a single attribute anyway.
Re: Metroid ported to use the MMC3.
I expanded the ROM from 8 to 16 banks (256 KB), and converted it from CHR RAM to CHR ROM. Each level's object and screen definitions were moved to their own bank, giving you $4000 for them. Removing the CHR and object/screen definitions from level data banks also frees up more room than you'll ever need for palettes, item data, etc. Originally, the only time bank swapping occurred was when switching levels. Since the sound engine (called from NMI) is stored in the original level data bank, when I added bank-swapping code to access the moved object/screen data, I had to add a safeguard to the NMI routine to make sure the proper bank is loaded.pops wrote:What modifications did you make? Did you have to make any trade-offs?
Aside from that, I did some data shuffling to keep the organization of banks more consistent.
The game doesn't do anything tricky with CHR RAM. There are 18 or so predefined (4 KB) CHR arrangements so that made it easy to convert to CHR ROM. Since there were extra CHR ROM banks, I added the ability to cycle banks for animated background tiles (as seen in 'Roids). Alternatively, you could use the extra banks to do CHR swaps and provide different tilesets for different areas of a level for more variety, which is what I'm doing with a hack I'm working on.
The expansion can be applied via my level editor.
Re: Metroid ported to use the MMC3.
This is brilliant. I know you can use the MMC3 to split up CHR ROM into 2x2kb and 4x1kb chunks. Do you use the 2kb chunks for BG or sprites?snarfblam wrote:... converted it from CHR RAM to CHR ROM.
Did you consider putting the songs in their own 16kb banks? The sound engine takes up 3414 bytes at present and it might be possible to slim it slightly further. The average song data is about 300 bytes; the largest is the title song at about 1000 bytes. With that in mind, you could put all the music and sound data into its own bank and have tons of room left over for new music.Since the sound engine (called from NMI) is stored in the original level data bank, when I added bank-swapping code to access the moved object/screen data, I had to add a safeguard to the NMI routine to make sure the proper bank is loaded.
Do you have any updates on the hack you're working on?
Re: Metroid ported to use the MMC3.
Here's a thought: how do you think a music engine like Famitone 2 would compare, feature-wise, with the default Metroid music engine? I think that with a little awesome engineering, it would be possible to replace one with the other...