Anyone Interested in Doing "SMB Special" for NES?

Started by SMB2J-2Q, February 06, 2008, 11:26:50 AM

Previous topic - Next topic


i noticed with the expanded rom theres no flags on the flag poles in the later worlds noticed on 7-1
pluss the 8-2 in the pc88 version looks diffrent from the one in the roms


nice job Karatorian :)

QuoteI'm interested in compiling a list of outstanding differences between the games so that we have a checklist of things that need to be done.

Ok well off the top of my head

Hidden blocks with power up
? blocks with starman

Power ups:

Falling spikes
Flaming barrels
Long firebar spinning left

Quotethe 8-2 in the pc88 version looks diffrent from the one in the roms

it's not techincally possible to create that crazy castle :(  the code should be hacked to not include the blocks at the bottom of the castles in that level though

also in 7-1 the flag disappears when you get the power up or 1up which is close to the pole.  the flag sprite is treated like a power up and only one power up is allowed on the screen

edit:  hmm i noticed i was a little over zealous with the optimization and removed the 1up from 1-2.  will have to fix that


i wasn't really talking about the castle
in 8-2 it starts with the castle on the island (musroom looking thing) a pitfilled with water than an L Pipe which leads to the underwater scene, and falling in the pit gets you to the wter room. every thing else is the same that i could see in that level.


the water isn't included cause in SMBS it is lower than it is possible to put it in SMB.  the L pipe is replaced with a regular pipe cause if you go in the sideways pipe entrance it will cause you to exit a pipe not fall from the top of the screen.  as for the falling in the pit and being in the water section, how do know that happens?  you've played it?  or seen it on a video?

edit:  i put the 1up back in 1-2


i acutally played it. i loose one life and start in the water section


I was thinking that might have been the case.  that level has a "secondary level entrance" which is used after you die.  I bet if you let time run out in 1-2 before you go down the pipe, you would end up in the underground part after losing a life.


As promised, I've cleaned up the source code and am providing it here for interested hackers. Also, I've produced a new patch which incorporates the small changes I made while cleaning it up.

On the surface, nothing (should) have changed. Under the hood, things are a little bit different. I restored the level looping code. We don't need it, but I figured that others might be interested in the ROM expansion for thier own projects, so that makes it easier on them. I also made a few minor code changes, mostly to organize things nicely and to optimize a few inefficient hacks.

Now that I've gotten that out of the way, I guess I'll have to go back to my orginal "next step" and fix the inverted pipe graphics.
Current ProjectsFinal Fantasy EngineSMB Special for NESStudio Karatorian
@loop: lda (src),y — sta (dst),y — iny — bne @loop — inc src+1 — inc dst+1 — dex — bne @loop



Cool, I'm gonna play these patches before hitting the bed.  :thumbsup:

EDIT: I found this bug...

Stuck in a brick *Laughs like Peter Griffin*

I played through both patches, everything else went smooth...  :beer:


Yes, I used the latest 1-4 patch.

Goonie, which patch did you find that bug in? The 5-8 patch from frantik, my 1-8 patch, or both?

I've looked into implimenting the additional eight blocks required to impliment all of those used in SMBS. While I've only done some preliminary investigation, it doesn't look like it'll be that hard to add them. I'll investigate some more and let you know what I find out.
Current ProjectsFinal Fantasy EngineSMB Special for NESStudio Karatorian
@loop: lda (src),y — sta (dst),y — iny — bne @loop — inc src+1 — inc dst+1 — dex — bne @loop


Are there any complete maps of both the original PC88 version and this version? If not, can they be made availiable? I want to be able to look at both versions side by side w/o playing them or watching videos.


Karatorian: my bad, I forgot to say which patch I used when I found that bug. I used your latest patch world8-ex-v2.ips. ^_^;


There is one thing about the .PY file in the TOOLS directory: Python support in Windows 98 isn't supported anymore. So you might have to rewrite it to another language!

I would go with the programming language called Euphoria. It supports a whole lot of OSes, Including Windows.

(or make an EXE using PY2EXE, Although it is not even a good idea in windows 98)
I Hath Returned...

BTW My username is not Hamtaro129. THAT IS WRONG, Please correct immediately or I will try to correct it myself!


QuoteI've looked into implimenting the additional eight blocks required to impliment all of those used in SMBS. While I've only done some preliminary investigation, it doesn't look like it'll be that hard to add them. I'll investigate some more and let you know what I find out.

you'll have to mess with "ClimbMTileUpperExt" among other things if you do that.  not sure where the data telling the game how many blocks total of each type is though.  edit:  acutally i see you just change the pointers in MetatileGraphics .  Course then there's the additional problem of changing the level data decoder to recognize the new objects too lol

googie:  yeah i knew about that bug i thought i fixed it before the patch went out

marioxb:  i wish i knew an easy way to render the SMB levels to graphics cause we have the SMBS ones already


In regards to Python not being supported on Windows 98, well '98 is no longer supported by Microsoft either. My position is that Windows is unsupported by my code. Sure, seeing as it's written in Python and I avoid OS specific modules, it should work wherever Python is supported, but if it doesn't I don't loose much sleep over it. While it may seem elitist, I got fed up with Windows back when I was running Windows 95, and I've never looked back.

One thing I did consider doing, but decided against was to provide the contents of the "data" directory to provide easier build support for non un*x users. In retrospect, perhaps I should have done so.

As for rewritting the level extrator in another language, I have no interest in doing so, especially if the only reason to do so it for '98 support. Python is my language of choice and I only code in other languages if there is a compelling reason to do so. I don't feel that in this case there is.

In regards to the new blocks, I actually started my investiagion by looking at DecodeAreaData, so I know how to handle that part. Additionally, I've looked at the metatile stuff and the BumpBlock routine, so I've got a pretty good idea as to what's required to add new blocks.

However, on further investigation, I've discovered a few things that may complicate matters. SMB object IDs are seven bits long. However, for normal objects, they're divided into two classes. If any of the upper three bits of the object ID are set, the object is considered a Large Object. If none of the upper three bits are set, the object is a Small Object.

This effectively limits the number of Small Objects (which blocks are) to sixteen. SMB uses twelve small objects, all which we need. In addition we need seven more blocks. This presents a bit of a problem. However, five of the additional blocks are all hidden blocks containing the (rare) new power-ups. I've considered several methods whereby all five of these blocks could be represented by a single object. How exactly that would work out depends on whether any given level or world requires more than one of them.

I've considered two methods. The first would be to simply hardcode the power-up based on the current world (or level, if required). This would proably be the simplest, but it'd be inflexible and wouldn't work if any level requires more than one new power-up. The other method I considered is to use an unused special row object to set the power-up type. This would be more flexible, but it would require a free byte of memory to store the power-up (memory is pretty tight in SMB, but I could use the SRAM) and would expand the size of the level data by two bytes for each special power-up.

The other snag is that the bump block code expects the block objects to be a sequencial range of IDs. Unless I can come up with a work around for this, adding any blocks would require renumbering three objects, specifically, the WaterPipe, EmptyBlock, and Jumpspring objects. I'd rather not do this as it'd require even more special effort on the part of anyone editing levels for the modified engine (frantik in the case of our port).

However, I think I can work around the issue by allowing the block handling code to treat these objects as blocks, but simply ignore them. I've yet to investigate whether this will cause any issues, but I think it should work. It's not as clean as I'd like, but renumbering existing objects seems be a bit excessive. (I'd do it if it was a solo project, but I have others to consider and would prefer not to break too many existing tools.)

So anyway, that's the state of the investigation in adding custom blocks. I'm going to go hack the code and see if what I've figured out in theory works in practice.

Oh, and one last thing. The current source release and expanded patch are missing one change from frantik's patches. The size of the platforms isn't fixed at six tiles. It's a pretty easy thing to fix, but I forgot all about it.
Current ProjectsFinal Fantasy EngineSMB Special for NESStudio Karatorian
@loop: lda (src),y — sta (dst),y — iny — bne @loop — inc src+1 — inc dst+1 — dex — bne @loop


I was thinking of doing a PHP port of the level extrator but i don't fully understand the action of struct.unpack which is used heavily


If you wish to port the level extractor to another language, feel free to do so. The struct module is used to access raw binary data, which, as a very high level language, Python doesn't have direct support for. Basically, struct.unpack turns a string containing binary data into Pythonic high level types and struct.pack does the opposite. What sort of data it deals with is specified by the format string. For the full details, see the struct module documentation. While it looks complicated, it's actually pretty easy to use.

Please keep in mind that the level extractor isn't the cleansest code around. In fact, if it weren't basically required as part of the SMBS for NES build proccess, I wouldn't have released it in it's current state. At some point in the future, I intend to clean it up, make it's features more generic, add a user interface (command line, of course), and package it as a general purpose SMB level manipulation utility. At such time I will proably release stand alone binaries (created with Freeze and PyExe) in addition to the source release.

Finally, I've yet to decide on a license for the level extractor or other original source code produced for this project. While the SMB dissassembly and most of the modified code are derivative works of Nintendo owned code and are legally grey or outright illegal, other code, such as my mapper drivers, the level extractor, and the build scripts are all copyrighted by me. The current copyright notice on this code, "All Rites Reveresed", is a placeholder that will be filled in with a proper licence statement once I decide on a licence. That said, I will be using some sort of open license, so anyone producing derivative code in the interim will not suddenly be denied the right to do so.

On a different matter, my work on the block code was interrupted by other conserns, so I haven't produced any results as of yet. I hope to get at least some work done on it later tonight.
Current ProjectsFinal Fantasy EngineSMB Special for NESStudio Karatorian
@loop: lda (src),y — sta (dst),y — iny — bne @loop — inc src+1 — inc dst+1 — dex — bne @loop


yeah instead of a more or less direct port of your code it think i would be better off just starting from scratch.  could you provide the extracted level data so i can see what the output should look like?


To assist frantik with building his own level extration tool and to allow building of the ROM by persons without Python, you can download a pack containg the level data here.

The level data is spit into two files. One is a ".bin" file containing the level headers (pointers, etc.) and data, and the other is a ".s" file containing machine generated ASM code that defines lables required by the main source code and other administivia. The generated ASM is included in two places in the source proper. Due to some conditional compilation options, the file does different things at these to locations.

The first place in in the main banks where there the level data originally was. Here it defines a number of lables and includes the portion of the binary that contains the level headers. The other location is in the dedicated level bank. Here it included the level enemy and object data. (Which is copied into SRAM on boot up.)

The reason that the level data was split from the level headers is that the total size is greater than 8k, so it wouldn't all fit in SRAM. By leaving the headers in the main bank, the level data proper fits into the SRAM.

The SMB level headers are fairly complex and not documented anywhere I could find. If you need any help understanding their format, please let me know. (I've been thinking about writing a comprehesive doc on the SMB level data format, but it's only one item on a long list, so it may be some time before (if ever) I get around to it.)
Current ProjectsFinal Fantasy EngineSMB Special for NESStudio Karatorian
@loop: lda (src),y — sta (dst),y — iny — bne @loop — inc src+1 — inc dst+1 — dex — bne @loop


so the pointers tot he level data ends up being hardcoded into binary file huh?  what is the starting memory location of the level data (basically the location the the first pointer points to?) 

Also how does the compiled code know where to look for the pointer table?  the info in the binary file has no labels or whatnot.  for example "WorldAddrOffsets" is called in the source but i cannot find the label anywhere. 

edit:  oh DahrkDaiz did a document with info on level headers and whatnot: