11 March 2016 - Forum Rules

Main Menu

Super Mario Bros 3 level from scratch.

Started by ahakomi, April 20, 2015, 08:15:39 PM

Previous topic - Next topic


I have a quick question. If I'm creating my own level using super mario bros 3 workshop is there anyway i can give the level it's own enemy and level/stage data (for pointer purposes) using another program or even SMB3WS? I tried creating my own level after deleting my object set data in the rom bank (in this example i was creating a plains level so i deleted all the plains data before hand on the rom) when i went to save the level, it tried to save it in 1-1 (which to be fair i opened 1-1 to edit).

Can I give these levels from scratch different level data so it'll recognize the level as it's own unique level with it's own level and enemy data pointers? :)

Quick Curly

Just type in your custom offsets for Object Data and Enemy Data when you're loading your level in the Level/Offset Selector in SMB3 Workshop to edit it.

Same idea when you edit your pointers in the Pointers mode in the SMB3 Map Editor.

Just to note as well, you want to make sure you're not overwriting any data and code definitions at the beginning of each Object Set ROM bank (graphic tiles used to display objects, object sizes, object functions, etc.), and only clear out the level data.

These are the ranges that I currently clear for my level editing:

                 Enemies  (0C04D-0E00F)
                1-Plains  (1E509-2000F)
               2-Dungeon  (2A867-2C00F)
                 3-Hilly  (20587-2200F)
             4-Sky/C-Ice  (227E0-2400F)
5-Plant/B-Giant/D-Clouds  (26A6F-2800F)
          6-Water/8-Pipe  (24DD4-2600F)
                9-Desert  (28F36-2A00F)
                  A-Ship  (2EC07-3000F)
           E-Underground  (1A587-1C00F)

Like I mentioned previously in the other topic, there are some collections of data that you might want to leave alone, but if you clear them out, you can always fit them in where you want them to be, if you even need them.

It's really helpful to keep track of your custom offsets, too. Not only for keeping all of the offsets handy if you need to go back to old level designs again, but for making sure where your next data sets can begin. Remember - all of your enemies are in one ROM bank, and then you'll be using different ROM banks depending on the kind of level you want to make next (i.e. Object Set). So, some form of organization is very important to keep track of everything.

Basically, to know the earliest free space that you have still available to fit in as many of your own levels as you can, and make them as long as you possibly can with the freedom of not having to work within the original level sizes, you'll have to spend quite a bit of time in a hex editor to track down where the next data sets begin for both objects and enemies whenever you're ready to start a new level, and after you finish creating a new level to know where the data ends and where the next level can begin to be created from.

For example, if I'm starting a completely new SMB3 hack from scratch right now, say that I've already cleared out all of those object and enemy data ranges for creating levels, and I'm going to make a Plains level first. In the FCEUXD hex editor that I use, I'll scroll down to the 0xC010 area for enemies. Each data set needs a start (00 or 01 for enemies, and a 9-byte level header for objects, which I'll just set as 00 00 00 00 00 00 00 00 00) and an end (FF). The first FF is at 0xC04C, which is needed to terminate the enemy data starting at 0xC048. So, the earliest spot we can start adding new enemies in (without just completing clearing everything else out, which includes the enemy data used for Mushroom Houses) is 0xC04D. I change that to a 01 and save.

Next, I scroll down to the Plains bank and find 0x1E509. I change 0x1E509 - 0x1E511 (0x9) to 9 "00"s, so that a level header is set up, which I can edit properly once I load the level in SMB3 Workshop.

When I open SMB3 Workshop and load my new SMB3 hack in it, the Level/Offset Selector opens automatically, with World 1, Level 1 selected by default. Since 1-1 is a Plains level and I'm planning to create a new Plains level, I can use the 1-1 slot to load my proper Object Data and Enemy Data. Although, you really don't have to, as you can change the Object Set to what you need it to be, though you have to set it according to what kind of level you're going to be making, and input the proper Object Data and Enemy Data. The offsets and Object Set that you put in here doesn't mean that you're changing different levels in the ROM to Object Sets that they can't be or anything like that. The slot that you have selected when you load a level doesn't mean that you're loading a specific old level. SMB3 Workshop was designed with editing the original levels in mind, with the default programmed offsets and Object Sets for each level for easy access. However, for SMB3 hacks with the original levels cleared out, they no longer exist anyway.

Long story short, you're typing in your custom offsets for your own levels whenever you load SMB3 Workshop for easy visual editing. In my case, I would change Enemy Data to C04D, Object Data to 1E509, and Object Set to "1 Plains" if it wasn't already those settings, and then choose OK. Now, I'm editing Enemy Data starting at 0xC04D, and Object Data starting at 0x1E509, in the Plains bank.

After I've created my level, I would go back in the hex editor, find the actual ends of both the new level's Object Data and Enemy Data, make sure that each is terminated by "FF", and then create new beginnings for the next Enemy Data for the next level that I make (01), and the next Object Data for the next Plains level that I make (9 "00"s). I might not necessarily decide to make another new Plains level for my next design, but at least the header is set up for it, and I've recorded the starting offset for it in my text file to remember what it is for the next Plains level I will make. I'll always need to know where the next Enemy Data set can begin, however, because I'll always be using that ROM bank for my level designs, except for the case where a level I make doesn't have any enemies, in which case, I can use 0xC010 as the Enemy Data for any level whenever I set the pointer for it in the SMB3 Map Editor. However, without connecting areas, you'll likely always need a new Enemy Data set, because the level can only end if there's a chest, an automatic ending, or a goal card, which are all enemies.

Please let me know if you need any other specific information.


Okay, i think im understanding what you're saying. I'm at home, i'll have to fiddle with this some more when i get home as im at work currently.

For scenario purposes, let's say i wanna keep all my levels from the plant/giant/cloudy set, BUT i'd like to add at least two levels. @0x27FEC i could start my next 9-byte level header, correct? Then once im completely finished, and i go to save my level, can input my new level address @ 0x27FEC and then new enemy data... but for my enemy data, would i use an already existing number or would i use the freespace offset from the rom (aka use the spare hexidecimal from the enemy data)

Quick Curly

Well, in your scenario, unfortunately, you only have a few free bytes to work with in the Plant/Giant/Cloudy ROM bank if you keep all of your other levels, and there most likely aren't enough bytes to add even one new level, let alone two, unless they're only a few bytes long each, which means they won't be full levels.

But for the sake of the process, yes, World 5 - Hammer Bros. 3 starts at 0x27FC3 and ends at 0x27FEB (0x29) with the first FF, so from 0x27FEC - 0x27FF4 (0x9) you could put in 9 "00"s for your next level's 9-byte header.

For the pointer that you use for your level on a World Map, you would type in 27FEC for the Object Data.

As for Enemy Data, you could potentially do either. You can use the same Enemy Data sets for multiple levels, because they're the same. If you load one that you've already made for another level and change it, it'll be changed for all of them because you're modifying the same set, so be careful. Basically, using Enemy Data that already exists for other levels means that you need to design your levels around that specific Enemy Data. I've done that before, so it isn't unheard of. The original SMB3 does this with some levels, such as Hammer Bros. levels in the same world, End Castles (0xD2BF), and Anchors Away (0xD6AC).

If you have free space in the Enemy Data ROM bank, you can set up a new set to use for a new level. It really depends on what exactly you plan to do with your level designs.


Okay, so I sorta noticed when I took out all the plains levels created my first level, the enemy level and pointers were both at 1e512 and c050 respectively (I only have one enemy). When I went to create my second level I think my object data was 1e534 and my enemy data was c055, sometimes the enemies don't show up when i try to save them. it's rather annoying. should i just move my enemy data pointer down some. I'm trying to conserve space. I'm editing my levels with Super Mario Bros. 3 workshop.

ALSO! I'm trying to do the music ASM hack using the debugger on an SMB3 PRG.1 rom. Is there anyway i can use the debugger in FCEUX to track where the music starts in each level or the world map perhaps :) I'm using version 2.1.5 and I was wondering if this were possible. I'm gonna be honest, I really don't know how to use this damn thing, it's sorta frustrating but I figure I'll figure it out sooner or later, I mean i DID just create my own level from scratch and gave it it's own pointers  :crazy: :crazy:

Quick Curly

Hmm. That's strange. As long as you load the proper enemy data offset for your level, and you use valid enemies, they should show up. There's a way that you can make 3-byte objects, 4-byte objects, and enemies disappear and appear under the View menu, through More. However, everything should be visible by default, so you probably would have figured out those functions if you had somehow clicked in there by accident.

I did a quick test of something. In a copy of the original Super Mario Bros. 3 ROM, I changed 0xC537 (the start of the enemy data for 1-1) to FF. Playing the level in FCEUXD, the enemies still showed up. However, in SMB3 Workshop, the enemies didn't. Did you not change the first byte of your enemy data string to 01? SMB3 Workshop will stop loading enemy bytes once it hits FF, apparently even if the very first byte is FF, even though the first byte of an enemy data string isn't even for an enemy.
It seems that this is most likely the solution to your issue, but please let me know if it somehow isn't. If it isn't, I might require more information, like the actual bytes in your enemy data.

Also, there's no need to separate your enemy data sets with more than just one FF to terminate the previous one before the next. Plus, you most likely should have more than enough space in the entire enemy data ROM bank. I've never even used the whole thing, and I tend to insert quite a few enemies in each area of every level. Although, my levels do tend to be larger, so I don't have as many individual levels, either. :P

As for music, what specifically are you looking for? The music data itself, or where the values are loaded from to determine which song is used for the levels and maps?

For music editing, it's definitely more involved with being able to get something that actually works, though the data can be found and documented. I remember writing it down years ago, but I no longer have those notes in my current possession. To document them again would take some time, but I'm not going to focus on that right now.

As for music values, this post contains the ROM offsets for map music.

0x143CA-0x143D2 (0x9) - World Map Music when arriving from Warp Zone.
0x3C424-0x3C42C (0x9) - World Map Music.

You have to change both values to make sure that the music for each map will be the same, regardless of wherever Mario or Luigi comes from.

0x143CA - World 1: 01
0x143CB - World 2: 02
0x143CC - World 3: 03
0x143CD - World 4: 04
0x143CE - World 5: 05
0x143CF - World 6: 06
0x143D0 - World 7: 07
0x143D1 - World 8: 08
0x143D2 - World 9: 0B

0x3C424 - World 1: 01
0x3C425 - World 2: 02
0x3C426 - World 3: 03
0x3C427 - World 4: 04
0x3C428 - World 5: 05
0x3C429 - World 6: 06
0x3C42A - World 7: 07
0x3C42B - World 8: 08
0x3C42C - World 9: 0B

Here is the music that you can get for each value:

00 - No Music
01 - World 1 Map
02 - World 2 Map
03 - World 3 Map
04 - World 4 Map
05 - World 5 Map
06 - World 6 Map
07 - World 7 Map
08 - World 8 Map
09 - World 9 Map/Coin Heaven
0A - Star Power
0B - Warp Whistle - World 9 Map/Coin Heaven
0C - Music Box
0D - Returning to Earth with the Wand
0E - Game Theme
0F - Princess Saved
10 - Plains
20 - Underground
30 - Water
40 - Dungeon
50 - Boss
60 - Ship
70 - Battle
80 - Mushroom House
90 - Hilly
A0 - Mushroom House (#2)
B0 - Bowser Fight
C0 - Boss (Lighter)
D0 - Music Mix (#1)
E0 - Music Mix (#2)
F0 - Music Mix (#3)

The code that determines the music to play in a level/area depending on the value in the level header is located at 0x3D8D8 in the ROM ($98C8 when loaded in RAM).

$98C8:B1 61     LDA ($61),Y @ $B467 = #$00
$98CA:29 0F     AND #$0F
$98CC:AA        TAX
$98CD:BD AC 97  LDA $97AC,X @ $97AC = #$10

AND #$0F strips the first 4 bits and uses the last 4 bits of the 9th of 9 bytes loaded from the level header to determine which value is loaded from another set/collection of values, at $97AC, which is at 0x3D7BC in the ROM.

0x3D7BC - 0x3D7CB (0x10)
10 20 30 40 50 60 70 80 90 0D 09 A9 00 8D 00 07

However, see the "A9 00 8D 00 07"? That's actually code, and the original game never intends for those bytes to be used as values to determine songs in the levels. In SMB3 Workshop, you have the option to choose between 16 music selections, but the last 5 were never meant to be used.
Therefore, you could potentially have 5 more possible selections to provide more variety. However, if you change the values at the original location in the ROM from where the songs come from, you would be destroying code.
So, the best option is to change where the game loads the song values from.

At 0x3D8DE in the ROM, change AC 97 to 10 9F. This will change the loading RAM address from $97AC to $9F10. This new location is at 0x3DF20 in the ROM.

At 0x3DF20, your new level songs value table, if you want to call it that, will be from the range of 0x3DF20 - 0x3DF2F (0x10).

You can insert the values for the songs that you want. I would recommend keeping the first 11 values the same as they originally were to make it easier to remember what they are when you're changing the music in SMB3 Workshop. That is, if you plan to use all of that music to begin with. It really is up to you!

The collection that I used for Luigi's Chronicles 2 was the following (although, for my implementation, I used $9F1B, or 0x3DF2B, as the starting point instead, for whatever reason - I really can't remember :P):

0x3DF20 - 0x3DF2F (0x10)
10 20 30 40 50 60 70 80 90 0D 09 0A 00 0E 0F B0

My first 11 music options are the same as the original game, but now I can also use the Star Power theme, no music, Game Theme, the Princess Saved theme, and the Bowser Fight music.
Remember, however, that using some of the songs in levels might not work as intended due to the speed-up effect when the time approaches the 100-seconds mark, like music intended for maps. Also, if you set no music for in a level, and you enter with or collect a star at some point, once the star power expires, the Star Power theme will still continue playing. Similarly, if you hit a P-Switch.
If a level starts with 100 seconds time, however, the speed-up effect won't activate.

As for time, the original game's code only allows for 4 possible values: 300 (0x), 400 (4x), 200 (8x), or infinite (Cx) seconds.

The code that determines the time in a level starts at 0x3D8C4 in the ROM ($98B4 in RAM).

$98B4:B1 61     LDA ($61),Y @ $B467 = #$00
$98B6:29 C0     AND #$C0
$98B8:18        CLC
$98B9:2A        ROL
$98BA:2A        ROL
$98BB:2A        ROL
$98BC:AA        TAX
$98BD:BD A8 97  LDA $97A8,X @ $97A8 = #$03
$98C0:8D EE 05  STA $05EE = #$04

At 0x3D7B8 in the ROM, or $97A8 in RAM, there are the values that the game uses for setting the time.

0x3D7B8 - 0x3D7BB (0x4)
03 04 02 00

This is my modified code:

$98B4:B1 61     LDA ($61),Y @ $B467 = #$41     A: 41  X: 07  Y: 08
$98B6:29 F0     AND #$F0                       A: 40  X: 07  Y: 08
$98B8:18        CLC                            A: 40  X: 07  Y: 08
$98B9:4A        LSR                            A: 20  X: 07  Y: 08
$98BA:4A        LSR                            A: 10  X: 07  Y: 08
$98BB:4A        LSR                            A: 08  X: 07  Y: 08
$98BC:4A        LSR                            A: 04  X: 07  Y: 08
$98BD:AA        TAX                            A: 04  X: 04  Y: 08
$98BE:8D EE 05  STA $05EE = #$04               A: 04  X: 04  Y: 08
$98C1:EA        NOP
$98C2:EA        NOP

0x3D8C4 - 0x3D8D2 (0xF)

B1 61 29 C0 18 2A 2A 2A AA BD A8 97 8D EE 05

B1 61 29 F0 18 4A 4A 4A 4A AA 8D EE 05 EA EA

Instead of loading the values that determine the times from $97A8 in RAM or 0x3D7B8 in the ROM, which limits you to only four possible values, the unnecessary bits of the level header value are stripped so that you are left with a valid time value, making 0/infinite, 100, 200, 300, 400, 500, 600, 700, 800, and 900 possible (don't go past 9). You can set 0, 4, and 8 in SMB3 Workshop (for infinite, 400, and 800), but for any other specific value, you'll have to modify the 9th level header byte directly in a hex editor yourself.

Values to be loaded: 0x 1x 2x 3x 4x 5x 6x 7x 8x 9x

OPERATION   HEX   DEC     128 064 032 016 008 004 002 001
             0x    0- 15    0   0   0   0   x   x   x   x
             1x   16- 31    0   0   0   1   x   x   x   x
             2x   32- 47    0   0   1   0   x   x   x   x
             3x   48- 63    0   0   1   1   x   x   x   x
             4x   64- 79    0   1   0   0   x   x   x   x
             5x   80- 95    0   1   0   1   x   x   x   x
             6x   96-111    0   1   1   0   x   x   x   x
             7x  112-127    0   1   1   1   x   x   x   x
             8x  128-143    1   0   0   0   x   x   x   x
             9x  144-159    1   0   0   1   x   x   x   x

So AND #$F0:

             F0   240       1   1   1   1   0   0   0   0

Original - AND #$C0:
             C0   192       1   1   0   0   0   0   0   0

The first 4 bits are used for the time, and the last four bits are used for the music. With the original code, AND #$C0 limited you to only four possible values, as only the first two bits were used. With AND #$F0, you have more options for time settings depending on how your different levels and worlds overall vary in size and difficulty.

If you have anymore questions, please feel free to ask. I'm excited about your hack coming together! :)

By the way, were you still planning to submit your previous SMB3 hack like you mentioned before, or do you feel that starting fresh is what you would prefer to do?


Now, I have one final question. Before I ask, I'll answer yours, i probably shouldn't post it here however i've avoided submitting the hack because my memory's so screwed i dont know all the required information for the rom hack itself and plus there's a lot of grammatical errors (like how I was just being stupid typing random words into a text editor thinking it wouldn't save because it like NEVER save and it saved the word "f*ck" so now when you finish the third world end castle, the level says ~I f*ck enclosed a jewel...~ and my mother laughs hard everytime we play it on our IMBNES emulator, it is pretty funny but still) I actually have decided I wasn't going to modify it anymore, i like it as is, besides I have three worlds finished of a game i've been working on now and all the information I've been learning from you lovely individuals, i've been trying to compile so i can make a hack using the last version of the game. The game im currently working on now I'm probably going to stay within those bytes and parameters like i have been and make a game for someone like my niece to play when she's bored. My next game, I really want to change the music. I admired someone who added pokemon music from pokemon red and blue, I'd enjoy doing that for my mother because she and I are both HUGE pokemon fans. Plus we named our dog after a pokemon so the concept would be cute and it'd make her smile. So that's why I have so many questions about the music and the debugger because im highly interested in doing that and creating my own levels from scratch which I seem to have a handle on! :) I think it'd be cool to create another powerup but to be honest, I have no idea where I'd even start to even BEGIN to do that. I will make sure i learn how to add or modify the music i want to. I want to add/change three songs. the first song is from fist of the north star, and the second being from pokemon, the third being that i absolutely WANT to include the birabuto theme from Super Mario Land as another overworld theme! If I could do that at least, I'd be very pleased and happy. I figure I could change the music from world 1 to the Jakko's Army level theme from Fist of the North star, (the world 1 level theme is the only theme i can track using the debugger or at least remember how to)

My question is this:

When I find the music bytes for world 1, and when I find the music bytes for jakko's army, would i copy the bytes over from Jakko'sArmy and paste over the one's from World 1, and if not, would I have to do something more extensive? Sorry I have so many questions.. lol 

Quick Curly

No worries at all! Please, ask everything! It's great to see new posts and forum activity. It reminds me of years ago when everyone was posting about SMB3 hacking. It's not really the case anymore, unfortunately.
I've always felt that more communication between fellow hackers alike encourages us all, and I definitely feel that sharing stories and helping each other continues to motivate me after all these years. :)

Short answer, no details - each game generally has its own music system. Unfortunately, you can't simply copy bytes from one game and paste them into another to get the same exact song. You pretty much have to figure out how the music works for both games, and manually input it one note at a time, while accounting for each channel, the tempo, and everything else music-related.

Years ago, JaSp made a new SMB3 Music Inserter utility, but it was made with Reuben in mind.
Even before that, he had made an SMB3 Music Editor for the original SMB3. I happened to find another old topic on Board 2 where he posted some notes and the program.
Going after the SMB3 Music Format...
Even if you don't use the program to edit anything, you could use it to find out how the different songs work for SMB3. From what I remember, some songs share the same data, so you have to be careful about what you edit.
Read JaSp's posts for his very helpful explanations to hopefully find the information that you're looking for. Years later, thank you again, JaSp! :)

Again, years ago, back when I was still working on Luigi's Chronicles 2, I was in the process of replacing the World 1 Map music with Midna's Lament from The Legend of Zelda: Twilight Princess. What I did was refer to piano sheet music for the song to find out which notes to use. It was working out just fine until I decided that I just wanted to finish the hack off and didn't bother editing any music. :P I mention this to present one possible approach for trying to replace as many different songs as you hope to.

As for your hack, your download is in ROM format, which means that your file includes the original game's data and code that you haven't changed, and there are rules about that so that we can hopefully continue being able to enjoy the hobby of ROM hacking without worrying too much about legal issues, not that I'll really go on about that.
In short, I would recommend using Lunar IPS to create an IPS patch of your hack so that you can distribute it with less of a legal issue. You need to provide the original, unmodified Super Mario Bros. 3 ROM as a source, and then your hacked/modified Super Mario Bros. 3 ROM for the utility to create an IPS patch file, which contains all of the changes that you made from the original SMB3, so that when someone else uses Lunar IPS to apply the patch to their copy of SMB3, your hack will be produced as a result, but you didn't distribute the full SMB3 ROM for them to come to possess it.
I've seen quite a few posts lately mentioning how IPS isn't really a great format to use for patches anymore, but I guess I'm just old school, and I've never had any issues with it. A suggestion I have is to also download the free hex editor, HxD, and through Analysis, find and record the check-sums (such as CRC-16, CRC-32, SHA-1, and MD-5) for your original SMB3 ROM to provide so that other people know which version to apply your hack's IPS patch to. As another option, you could try ROM Hasher.
Ultimately, it's up to you. You could try beat and its BPS patch format, or the older UPS patch format. I'm unfamiliar with them, so I can only provide personal experience concerning the IPS patch format.

From what I could see of your first hacking attempt though, it appears to be pretty sweet! I don't know if it was intentional, but in the first Pipe level, the player starts with a Goomba's Shoe; I couldn't progress up the waterfall with it, and there was no way to lose it without direct modification, from what I could tell, unless I was missing something. Not that you necessarily intended to release it until I mentioned it again and I didn't mean to pressure you into it if that's how it came across, but I was just wondering. Regardless, again, I did like what I saw! I took a peek at some of the level designs in SMB3 Workshop and they look very well done to me! :thumbsup:


You shouldn't start with Goompa (Kuribo's) shoe! So weird!  However i will be very cautious about the IPS patch. I actually have Lunar IPS so you cant be that ancient lol! I appreciate your help so much! I'm gonna read these posts :)

Quick Curly

Yeah, it is. Ha ha. It seems that when I played the hack in FCE Ultra eXtended-Debug 1.0a, I didn't start with the Goomba's Shoe. I initially tried playing it in Nestopia v1.40, as Nestopia has always been my personal preference for just playing NES games and hacks. So I guess that I won't use Nestopia to play this hack. :P
Just to confirm, I decided to test your hack in VirtuaNES v0.97 as well, and I didn't start with the Goomba's Shoe in that emulator either. So I guess, my old school preference for Nestopia is the reason I was stuck in this case. :P
It's all good, though! I look forward to enjoying your first hack, and your continuous progress with your new one! :beer:


If you dont mind me asking did the music editor come with a readme?

Quick Curly

Unfortunately, I don't believe that it did.


Well that's okay, I'll figure it out somehow! Thank you though. :D