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.