I just wanted to make a topic for my project I've been steadily working on for the past couple weeks or so.
What this project is aiming to do is modify SMB2 and 'enhance' it if you will to an extent. My friend and I are still in talks on what exactly is going on, but one of the big things we want to do is add another playable character into the roster with the other four. (This isn't as hard as it sounds). We're also hoping to update the graphics a bit overall too! This includes maps, enemies, PCs and items.
This is quite an undertaking and it may or may not ever be finished, but I definitely want to get the basis ready and go from there and release it for other people when the time comes.
So what exactly has been going on so far? Kind of a toughy to explain.
The first bit was forcing Super Mario All-Stars to load SMB2 on the fly. As soon as I figured out how to do that, I removed as much of the other Mario game's code as possible. Obviously I'm sure I missed quite a bit of the actual 'ASM' but the other games graphics, music, level data, etc.. has been removed to allow for over 1MB of extra space. So now, when All-Stars is booted, it'll do the whole coin blip with the Nintendo logo then shoot right into the SMB2 title screen!
The second aspect I realized after studying the code a bit was how incredibly ludicrous the graphic storage for PC's were along with their animation data. Everything was hardcoded to the frikin 'T'. Even animations were flat out coded instead of having a routine to set things up properly. Of course, since all characters share the same data this wasn't a big deal for this game, but for what we hope to do it was incredibly hindering.
What has been done?
1. The entire PC graphic routine has been rewritten from ground up. The main routine that stored PC graphics was actually shared with the POW/Crystal Orb/Flask.. for whatever reason. I have no clue why they did that. Now, the POW/Orb/Flask routine has been split and set into it's own bit and their graphics in VRAM have been shuffled to accommodate for much larger PC graphics.
2. The PC graphic routine, as I said, has been rewritten ground up. The routine NOW loads the PC graphics based on what 'frame' is currently in RAM (Stored at 7E:02F3 now since that value goes unused from removing the old code). The code checks what PC you are then loads the frame that you're on. It then loads the proper data for that specific PC and that specific frame and THEN stores the graphics into VRAM.
This is done to allow for extreme flexibility on how to handle graphics the way the user wants. Of course, the data has to be properly setup in ROM. Right now, it reads 3 bytes to get the pointer to the PC graphics. It then reads the following 2 bytes to dictate HOW much of the data to send to VRAM. This way we can clearly specify how much we want from the current section.
3. Animation Data is now a 'thing'. Basically, 7E:00C7 (Current PC Action) is now dictated for animation use. Whenever this is set to another value, it loads a new animation. There's some kinks to work out with this still in the long run but overall it works quite well. This allows for much longer animations and timing purely based on a couple bits instead of hard-coded data.
4. Sprite Assembly is in! It does exactly how it sounds, it assembles sprites. What happens it the graphics needed get sent to VRAM through the 'Sprite Setup' that is now in-game. The Assembly picks the right tile to use and the X/Y coordinates of the tile as well based on the PCs location. Thus, allowing larger PC sprites. This same thing will apply for enemies and objects later down the road too!
There's some kinks of course, always is until its all perfectly setup, but they're pretty minor. Though, they're really hard to work with so it might be a bit before they're actually fully done.
What needs to be done?
1. Big and small sprites. This one I don't think will be TOO hard. I think what I need to do is either find a byte that dictates if you're big or small, if not, make one that does. It'll check that and then load the proper graphics based off of that byte. Basically giving flexibility for big and small sprites.
2. Add a check in the animation data if you're holding something or not. All this will do is add a specific number of bytes to load 'new' animations with your hands up for all frames. I'm actually thinking of splitting this off into it's own section for PC's as well but we'll see.
I really would like to give a screenshot but there's literally no visual change at the moment. It's all underneath the game that's going on. I'm trying to get it to load and play the game like it normally would, but with the new code so we KNOW it's working.
I honestly have no idea if the way I'm doing it is the proper way to handle animation data, but it's working great so far so I won't obsess over it too much.
The only other way I can think of to properly do animation stuff even more clear is if I completely rewrite the game's system for PC's to be based more off of button presses and 'commands' being written. Right now, the code is constantly running and only a few pieces of code run when you're moving, otherwise it tends to just run everything constantly. We'll see.
But right now walking for Peach is in and working (Minus the delay), idle is working and jumping is working. Need to start working on the 'duck' frame and the 'climb' frame. That'll cover the basics then it'll be onto when you have an item in hand and what not.
Edit: I've decided that now might be the best time for me to rewrite how the game handles certain commands and change it over to something new. Right now, I'm noticing I have to manually write out every single check to make sure animations don't eliminate one each other, when they update, etc.. which is really, really not a good way to handle it.
I'm going to figure out what few areas use 7E:00C7 for checking and writing then alter that significantly. 7E:00C7 will still be the 'PC Action' but MUCH more expanded and also be more specific for PC animations and commands instead of just being a check for a specific command. This time, it'll actually LOAD the appropriate code with the command. Of course, the only problem with that now is actually putting in the code to properly update the command byte as you move.
Edit #2: After finally having some down time to work on this again, I BELIEVE I finally got the animation transitions working! The PC can now walk left or right with the delay they had in the original game, it'll then switch over to the proper walking animation. If the speed of the PC is at max velocity, it'll display their running animation instead!
With that in, we can now have separate animations for:
Animation Data, VRAM Data and Sprite Assembly now ALL work! I'm most likely going to come back and tweak them up a bit for more flexibility in the future, but right now, they do their job perfectly fine!
So what does this mean? Well, new animations are very much possible now. The VRAM graphic storage method now means you can call graphics from anywhere in the ROM and designate how much you need to send into VRAM making it extremely nice if sprites are scattered about. The Sprite Assembly is basically what pieces the sprites together using what's in VRAM. Technically, if all sprites are the same height/width no matter the animation, they could all use the same Sprite Assembly pointer, which is what would work perfect in the original game. For obvious reasons I have every frame with their own sprite assembly.
I can't remember if I posted it above or not, but I also had to shuffle the OAM table they use in RAM a bit. There's a HUUUGEE amount of space that can be used for it, but PCs only took up 8 bytes of it. From what I tested, I don't think the entire OAM table ever goes fully used on any scene except possibly the ending. Other than that, I altered the enemies to start loading about.. I think it was 40-60 bytes later down the road. This gives PCs more sprite room in the OAM table thus allowing for larger sprites!
Of course, I have a few kinks to work out so far with all of this new data. First and foremost there's issue with animation priority. It works out really nicely overall, but the problem is that I have it consistently storing 00 to 7E:00C7 (PC Action) if you're not moving. Otherwise, if you use the movement keys it does walking, if any button is held down to increase movement you turn into a running animation, etc.. Down is ducking, jumping is there as well. The big problem comes in if you try climbing something. It works just fine for the most part, but the moment you move left or right on the rope you change back into the walking animation. I can obviously write a check to fix that though I feel like there's an easier way to handle all of this, I just can't figure it out.
But yeah, tl;dr.
1. Larger PC sprites are possible
2. More OAM room for PCs
3. VRAM has been shuffled significantly to allow more PC room
4. New animations are possible
5. New PC sprites possible
Some plans that are coming up is the entire setup of how enemies are loaded into VRAM. Right now, it loads all the enemies data needed as the world loads from what I saw. I'm sure there's exceptions for some boss fights like Wart and such, but otherwise they are setup wordly. What I plan to do is alter the entire routine to store PER SCREEN. Anytime you enter a door, new level, new screen, vase, etc.. It'll read the bytes needed and store the graphics into VRAM. This would remove unnecessary sprite data allowing for larger enemy sprites and possibly more dynamic animations for them.
The other big plan is to also figure out a possible new hit detection system. Right now from what I saw, it actually compares the PC's X/Y coordinates to the object or missile you touch. That's fine and dandy.. until for example, Birdo. You can be small AND ducking yet you'd still get hit by the egg. Why? Because your X/Y coordinates are the same, just the sprite looks smaller.
I'm trying to figure out a system to work with that.. Maybe some sort of height/width system for every sprite/missile in the game that way things can be extremely dynamic on certain aspects. Taller characters would obviously get hit more often and ducking may not even be an option to dodge something while smaller characters, AKA Toad, would be able to dodge no problem.
All in all, there's a long way to go for this but it's making headway one bit at a time!
Triple post? Hopefully this is allowed since it's hefty updates.
Alright, so, things are going progressively smooth! I hit a bump.. a rather nasty one but I think it's okay now. I had a feeling about my Animation Data system being kind of.. wrong so I ended up rewriting it and now it's performing exactly how I had hoped it would.
7E:00C7 IS officially used fully now as the current PC Action. It loads the value there to see what you're doing then jumps to the proper location to get the right animation data and whatever else is needed.
The Sprite Assembly routine has been fixed as well! Sprites would not mirror left or right properly if they were over two pieces of sprite assembly. This has been fixed and now things can be used left or right without issues no matter the size. Also, the issue I was having with the Y coordinates not looping properly on the screen has been fixed as well! This allows for full use of the screen for placing sprites together now!
So what do we have so far on commands with animations? Here's the current list:
00 - Idle
01 - Beginning to Walk
02 - Walking/Running
03 - Beginning to duck
04 - Ducking
05 - Jumping
06 - Duck to jump-transition to jump
07 - Death
08 - Climbing
09 - Transition to falling/Falling
0A - Pick something up
0B - Super Jump
0C - Damaged
I'm trying to figure out a way to combine the 'beginning to walk' with the walking/running, same with ducking and duck-jump transition and such to save up commands. But these all act as their own things and thus allow for their own animations, which all are working as intended!
I still have to get the small sprites properly and for when you're holding an item, but otherwise everything seems to be going as I hoped!
As for damaged/death and such, I plan to add a LOT of specific checks so we can have multitudes of animations depending on what happens.
I also want to update the hit detection system.. I'm.. just honestly not sure how to go about it. I want it to be based the PC/Enemy/Object height a bit so if you're ducking, you can actually DUCK underneath projectiles and such.
I can't wait to see more info! Good luck! My Deviantart friends and I created some hypothetical sprites for a SMB2Mix hack, so feel free to use them.
I've been thinking of getting back into this again as a temporary side project while I'm working on Sailor Moon: Another Story re-translation with a small group of people.
I'm tampering with the idea of dropping the animation extension bit I did and keep it simple, but allow for the larger sprites with their own sprite assembly and such. This way it'll allow people to do larger characters as a test. Although, I need to learn some C# or something so I can create a utility for easy editing of said data.
Not 'officially' back on the project but I've done a couple tweaks.
Main one is that SMB2 had a hard constant check that'd see if 7E:02A9 was == 00 or > 00. If it was > 00, it'd allow palettes to be updated, otherwise, what you saw on screen was it. I've removed that check entirely so now palettes can be swapped at anytime without that extra stupid tidbit.
I'm still checking the side-effects of another change I did. It was some code that set HDMA channels 0-3.. not sure what they did yet as I've only been testing the first level, but it fixed NUMEROUS amounts of HDMA flickering I was encountering when you had a Star activated and moved across the level. It was probably just an emulator only bug but it was annoying as hell nonetheless. Until I can find an actual side effect that causes problems from this, it remains removed and actually allows the expanded graphic storage that I wanted, which is nice.
On another note, I'm thinking of removing the POW/Flask/Orb's from being animated. That, or I'll have to wait until I completely revamp how enemy graphics are stored and how screen handling works.
My idea still is to have enemies, tile sets and such be loaded on a 'per screen' basis instead of a 'per world' basis. By per screen, I mean when you enter a new area (i.e. Vine, Cave, etc..) where it'll reload all the data so it has what it needs to instead of having EVERYTHING at once. This causes a lot of graphic squishing and makes it hard to allow extra animations for anything.
Doing it this way would allow the POW/Flask/Orb to act independent and be called ONLY if they're on that screen with proper separate sprite data with the new Sprite Assembly code I have implemented for PC's (Which I plan to port over to every other sprite object too).
Still a massive amount of work load ahead of me as I'm thinking of heavily reworking my animation code once more.
Slowly but surely! This project isn't dead, but very much on the slow end of things. If I'm able to learn enough actual programming in due time, I could possibly whip up a mini editor for all the extra data I have to allow SOME sort of modification, but that won't be for a long while until I learn it myself or someone else is interested enough to volunteer in the far future.
I've converted the ROM to 'FastROM' so now there is FAR less sprite lag. The main noticeable one I found right on the first level is when you run over to the waterfall with the logs coming up. That would lag quite a bit on the normal game.
With it being 'FastROM' now, you can have the maximum number of hearts AND carry an enemy with you and there's still absolutely no lag!
This is significant for much later down the road in a few areas and aspects that I have plans for but that's all for now! Still have yet to figure out what I want to do with the animation code but so far, everything is going quite splendidly!
Edit: Woops! Looks like I hit some issues. There's a lot of data I forgot to change to properly load the 'new' banks. It worked fine in SNES9X which is weird, but it broke horrendously in every other emulator. I'm tracking down all the unchanged data and trying to fix it. It seems like the only real problems I had were the sprite pointers and such I added but even then something else is breaking with them.. not sure what.
Edit 2: Fixed many crashing issues and locational issues. There's bound to be more that pop up in time but I'm pretty sure I've nailed every single one thus far.
Biggish update incoming! ...Still have yet to finish rewriting the animation data.
Sprite HUD is being implemented with some graphical updates to accompany it a bit. The hearts are from Super Princess Peach but colored down to SMB2 standards. The rest is essentially graphics taken from the GBA version of SMB2. The only real thing missing is the 'SCORE' counter. That'll display directly under the PC's lives once I figure out how to have it work properly. Both PC lives and the coin counter update as they should!
If you've noticed, the panel door graphics are slightly different. I had to go the 'cheap' route and just mirror the top and bottom sprites to make room for the HUD in OAM. The doors originally used SIXTEEN sprites in total before! They now only use FOUR! This allows for the entire HUD to be rendered properly and then some room as well. I may make use of the extra room and shove the PC sprite data up another row or two for more OAM room on their part. If not, I'll use a small chunk of it for the 'glitter' effect on collecting coins.
Forgot to update this screenshot. This was before the lives counter was implemented.
Other part of the date. Cherries have aesthetically being replaced with 'coins'. Right now, they use SMB2's original coin design without the 'I' thing in the center. Obviously a place holder until an actual coin graphic is made up. It DOES animate too. I have yet to implement the 'sparkle FX' that SMW does when coin collecting but I'll get on that soon! They also play a coin SFX when collected!
However, temporarily still, once you hit 5 cherries it'll reset and summon a star. I plan to alter level layouts so there's coins about and possibly change some of the vegetables to be coins too. This shouldn't be TOO bad considering the NES and SNES version share the exact same data when it comes to Layer 1 level layout, which is what the cherries are on. The biggest issue will be just moving ALLLLLLL the level data into a blank area and tweaking it up a bit. But otherwise, it's shaping up very well so far!
Minorish update. Still working on the HUD a bit. Ran into some problems when I was trying to add in the 'score' that rises up when you defeat enemies. Turns out, I only had enough room for 'four' of them on screen at once.. but they'd get overwritten by doors and BOMB explosions.
With that, I've rewritten doors so they ALWAYS are the lowest priority on sprites and include a new bit of data. When the PC fades to black completely, it erases them off screen allowing the door to close without any layering issues. This also works on the Golden Doors as well.
Even with that, there's still only room for four scores floating up. The best I can do is move the PC data down one more row in the OAM table along with the enemy data. This would allow 6 scores in total to appear on screen at once and allow the normal amount of other stuff as well.
Bombs are now also low on the priority list as well. So they appear behind all sprites.
All in all, it's getting there slowly but surely.
Fun fact: This hack, thus far, does NOT work on ZSNES but it does work on every other emulator including BSNES accurate. Not sure why, but I thought that was pretty funny considering it's usually the absolute opposite.
Edit: All enemy/projectile OAM has been moved up another row along with the PC data. This now allows for 6 scores on screen at once. Also, I was able to redo partially my PC routine to be more automatic and not so hard-coded. This way, it even fixed some sizing issues as well! It's been a great productive day today!
Edit 2: Well, this is an interesting find. It turns out that there is a bit of a hit box system in this game. The thing is, it's NOT with the PC, it's all with the enemies and projectiles. I'm not sure if there's a 'size' yet, but there's definitely X/Y coordinates of it based on the object. So technically, I could add in a mini routine here that checks if the PC is ducking, if so, it'd increase the hit box Y coordinates by a few so it DOESN'T hit you. (IE: Birdo's egg being the largest offender)
NOTE: These graphics are NOT final and are just a show casing of what's possible!
Another update with the engine finally. This video showcases a much larger Peach sprite along with the new animation/sprite assembly system.
First things first: Right now, there's enough room for eight 16x16 blocks for the PCs. Six of those are for the general graphics, the last two are for other things that I'll elaborate later on down the road.
Sprite Assembly is as it is. Each 16x16 chunk or even 8x8 chunk can be set anywhere on screen to allow for a larger sprite. However, the PC's can only have 16 sprites at max unfortunately due to how the OAM works in this game.
Animation system is the biggest addition. There can be various animations depending on the circumstances and the code. Right now from the ground up, this is the list:
Beginning to walk
Beginning to walk uses the new bit of code where the animation changes only AFTER the current animation has completed, same for stop walking. Walking is just a normal animation that plays until you stop moving. However, each animation can have specific checks like whether you're in the air, ground, moving, not moving, ducking, climbing etc.. Or even depending if you switch directions fast enough and such which would allow for a 'turning' animation too! The possibilities are pretty high with this.