Sonic B&W Collect as many Rings as you can! Sonic B&W is a ROM hack of Sonic the Hedgehog, that adds a visual modification/gimmick to the base game; collecting rings gradually changes the colors and music of South Island! Getting hit, however, undoes this effect. Have 50 rings by the end of the stage to activate and enter special stages! (Epilepsy Warning: There are occasional instances of flashing background colors) This started out as a small tech demo a few years ago, but in the last couple of months I decided to expand upon it, add new features, and experiment with the special stages. Features: -Two ways to play: Select sound '80' in the Sound Test to toggle 'Grayscale Mode', which uses a different palette than the default. -Brand-New style of Special Stage, with 6 new stages available. To skip to the Special Stage you want, play sound '93' in the sound test once for every emerald (once for Stage 2, twice for Stage 3, etc.). I plan to actually make a menu for this later. (Tap C at Title Screen). -I'll add new features to this gradually in the future, to expand the project a bit. Current Version: Coming Soon Previous Version: Not Available Spoiler: Screenshots Screenshots: GrayScale Mode: Special Stage: Spoiler: Known Bugs Known Bugs: -There are a couple of small graphical errors in the special stages -Spikes do not entirely reverse the color effect, when hit. -Ring count in the special stages don't update consistently. -Palette Cycling in certain zones is disabled, as they cause crashes, for some reason. Special Thanks: Coding Help: MarkeyJester StephenUK FireRat Novidicus GenesisFan64/Gardeguey - For the PalLoad_Loop quick loading subroutine. Tools: MainMemory - SonLVL, S1SSE, etc. snkenjoi - Flex 2 Xenowhirl - SonMapEd
I've yet to play the actual hack, but: It's easy enough and I'm sure you can pull it off on your own since you're better than me, but I can give you the soniNeko source code if you want to save time. I might put it in a guide or something, but it's a rather niche feature and it's extremely easy anyway so I'm not sure how useful such a guide would be.
An interesting hack idea, I'll say. I like the special stages too, but I dunno if this would work for a full game. Maybe if it was exclusive to a single zone that would be a cool gimmick idea, cause I dunno if the full game is manageable with all of this (maybe an original zone with a new layout would work better for this kind of thing). Also small nitpick, but that remix of Rockman and Forte's Intro Stage theme is garbage, no other way to put it. It sounds so empty, and it doesn't do the original any justice at all. So, all in all, a neat spin on the "limbo-esque" hack, but one that feels like a one trick pony.
On what TruffledToad said, if you want I could give you a version of the Rockman & Forte intro stage I made recently. On the hack itself, it's a unique concept, I'll give you that. I'm just not quite sure how it makes the game different other than the visuals and music. A cool idea would be changing Sonic's physics slightly the more rings you get, and restoring them when you get hit. I'd have no idea how to do that though. I liked the Special Stages, they were a nice change from the original even if they felt slow at times. B&W is a bit of a strange name, why not call it something like, Sonic Colour Contrast? (Bad joke was bad.) Good idea, nice execution, but feels like a proof of concept to me.
Although I want to improve it myself, I could definitely use your code as a reference. The way I've done menus in previous hacks was a bit sloppy/hackish, so I should spend some time getting better at making good user interfaces. Thanks, I really do appreciate the offer! Well, at this stage it really is just a small proof of concept/gimmick-hack; this is why the level select is enabled by default. I do want to expand on the project though, and provide a fuller experience. Don't worry, I don't consider this a nitpick at all! I'm aware that the port is indeed blatantly awful at the moment (this is indicative of my current SMPS ability/knowledge). But I certainly plan to improve upon it! SMPS is a bit of a struggle for me, but I do have an understanding/vision of how I would like the track to sound; I'm just not there yet skill-wise. Thanks for the response! I'm honestly not quite directly aiming for the 'limbo' idea/concept (which is why I started to introduce other palettes as options), although silhouetting is something I've come to enjoy in Sonic 1's art, aesthetically. Thanks for the offer! However, I do want to personally make my own version, and improve myself. Neat ideas, and thanks for the feedback (and the bad joke). Right now the hack is pretty much is a proof of concept; a base point from which to create something more substantial in the future. I released this demo out of curiosity to see what people thought of the ideas presented, so I appreciate the comments!
Very well then. I'll just paste it here instead of sending it privately, so if there are any blatant errors, someone better than me can improve it. As I said, it's quite simple, I literally copied the Sound Test selector; this requires a free byte in RAM to hold the Special Stage number. How to use the Special Stage number in the Special Stage routine is even simpler (just copy that byte to $FFFFFE16), so that's left to the reader. I'll paste from the line before the first modified one, to the line after the last modified one. Original code: Code: bsr.w LevSel_ChgLine move.w #$E680,d3 cmpi.w #$14,($FFFFFF82).w bne.s loc_3550 move.w #$C680,d3 loc_3550: move.l #$6C300003,($C00004).l ; screen position (sound test) move.w ($FFFFFF84).w,d0 addi.w #$80,d0 move.b d0,d2 lsr.b #4,d0 bsr.w LevSel_ChgSnd move.b d2,d0 bsr.w LevSel_ChgSnd rts ; End of function LevSelTextLoad Modified code: Code: bsr.w LevSel_ChgLine loc_3550: ; sound test number move.w #$E680,d3 ; set gray color cmpi.w #$15,($FFFFFF82).w ; am I sound testing? bne.s loc_3550_gray ; if not, use gray color move.w #$C680,d3 ; if yes, use yellow color loc_3550_gray: move.l #$6C300003,($C00004).l ; screen position (sound test) move.w ($FFFFFF84).w,d0 ; song number in sound test addi.w #$80,d0 move.b d0,d2 lsr.b #4,d0 bsr.w LevSel_ChgSnd move.b d2,d0 bsr.w LevSel_ChgSnd loc_3550b: ; special stage number move.w #$E680,d3 ; set gray color cmpi.w #$14,($FFFFFF82).w ; am I special staging? bne.s loc_3550b_gray ; if not, use gray color move.w #$C680,d3 ; if yes, use yellow color loc_3550b_gray: move.l #$6BB00003,($C00004).l ; screen position (special stage) move.b ($FFFFFFFF).w,d0 ; special stage number addi.w #$1,d0 move.b d0,d2 lsr.b #4,d0 bsr.w LevSel_ChgSnd move.b d2,d0 bsr.w LevSel_ChgSnd loc_3550_common: rts More original code: Code: LevSel_SndTest: ; XREF: LevSelControls cmpi.w #$14,($FFFFFF82).w ; is item $14 selected? bne.s LevSel_NoMove ; if not, branch move.b ($FFFFF605).w,d1 andi.b #$C,d1 ; is left/right pressed? beq.s LevSel_NoMove ; if not, branch move.w ($FFFFFF84).w,d0 btst #2,d1 ; is left pressed? beq.s LevSel_Right ; if not, branch subq.w #1,d0 ; subtract 1 from sound test bcc.s LevSel_Right moveq #$4F,d0 ; if sound test moves below 0, set to $4F LevSel_Right: btst #3,d1 ; is right pressed? beq.s LevSel_Refresh2 ; if not, branch addq.w #1,d0 ; add 1 to sound test cmpi.w #$50,d0 bcs.s LevSel_Refresh2 moveq #0,d0 ; if sound test moves above $4F, set to 0 LevSel_Refresh2: move.w d0,($FFFFFF84).w ; set sound test number bsr.w LevSelTextLoad ; refresh text LevSel_NoMove: rts More modified code: Code: LevSel_SndTest: ; XREF: LevSelControls move.w ($FFFFFF84).w,d0 ; check the sound ID cmpi.w #$0,d0 ; is it zero? (aka 80) bne.s LevSelAllRight ; if not, branch moveq #1,d0 ; if sound test is 80 (100) then it turns to 1 (81) bra.s LevSel_Refresh3 ; no need to check it more if I set it to 1 (81) kthx LevSelAllRight: cmpi.w #$15,($FFFFFF82).w ; is item $15 selected? (sound test) bne.s LevSel_AllRightB ; if not, branch move.b ($FFFFF605).w,d1 andi.b #$C,d1 ; is left/right pressed? beq.w LevSel_NoMove ; if not, branch move.w ($FFFFFF84).w,d0 btst #2,d1 ; is left pressed? beq.s LevSel_Right ; if not, branch subq.w #1,d0 ; subtract 1 from sound test cmpi.w #$0,d0 ; is it zero? bne.s LevSel_Refresh2 ; if not, branch moveq #$7F,d0 ; if sound test is 0 (80) then it turns to 7F (FF) bra.s LevSel_Refresh3 ; no need to check it more if I set it to 7F (FF) kthx LevSel_Right: btst #3,d1 ; is right pressed? beq.s LevSel_Refresh3 ; if not, branch addq.w #1,d0 ; add 1 to sound test cmpi.w #$80,d0 ; is it 80? (100) bne.s LevSel_Refresh2 ; if not, branch moveq #1,d0 ; if sound test is 80 (100) then it turns to 1 (81) bra.s LevSel_Refresh3 ; no need to check it more if I set it to 1 (81) kthx ; here I am writing a NINEKODE to add a gap in the middle of the sound test list LevSel_Refresh2: cmpi.w #$20,d0 ; is it 20? (A0) bne.s LevSel_Refresh22 ; if not, branch moveq #song1,d0 ; if sound test is 20 (A0) then it turns to song1 (smallest of the highest allowed values) bra.s LevSel_Refresh3 ; no need to check it more if I set it to song1 kthx LevSel_Refresh22: cmpi.w #song2,d0 ; is it song2 (one unit smaller than the smallest of the highest allowed values) bne.s LevSel_Refresh3 ; if not, branch moveq #$1F,d0 ; if sound test is song2 then it turns to 1F (9F) LevSel_Refresh3: move.w d0,($FFFFFF84).w ; set sound test number bsr.w LevSelTextLoad ; refresh text bra.w LevSel_NoMove ; at this point, we're done LevSel_AllRightB: cmpi.w #$14,($FFFFFF82).w ; is item $14 selected? (special stage) bne.s LevSel_NoMove ; if not, branch move.b ($FFFFF605).w,d1 andi.b #$C,d1 ; is left/right pressed? beq.s LevSel_NoMove ; if not, branch move.b ($FFFFFFFF).w,d0 btst #2,d1 ; is left pressed? beq.s LevSel_RightB ; if not, branch subq.b #1,d0 ; subtract 1 from sound test cmpi.b #-1,d0 ; is it -1? bne.s LevSel_Refresh3B ; if not, branch moveq #$5,d0 ; if special stage is -1 (0) then it turns to 5 (6) bra.s LevSel_Refresh3B ; no need to check it more if I set it to 5 (6) kthx LevSel_RightB: btst #3,d1 ; is right pressed? beq.s LevSel_Refresh3B ; if not, branch addq.b #1,d0 ; add 1 to sound test cmpi.b #$6,d0 ; is it 6? (7) bne.s LevSel_Refresh3B ; if not, branch moveq #0,d0 ; if special stage is 6 (7) then it turns to 0 (1) ; bra.s LevSel_Refresh3B ; no need to check it more if I set it to 0 (1) kthx LevSel_Refresh3B: move.b d0,($FFFFFFFF).w ; set special stage number bsr.w LevSelTextLoad ; refresh text LevSel_NoMove: rts Please note that I added one line because of Good Morning Zone, so the $14 and the $15 should probably be $13 and $14 respectively (since the Sound Test is $14 in the original code), but I'm not in a position to double check that right now. Also, you might have added/removed levels in your hack as well, so it's a good thing to make sure that the line numbers are correct. Also please note that I used address $FFFFFFFF for the Special Stage number, but any free byte will do. I also advise to clear that byte AND the collected emeralds when starting a regular game, or you might get bizarre behaviour instead of playing the first Special Stage when you enter the first big ring in the game (one might even play all 6 Special Stages from the Level Select and start the game with all the Emeralds). I'm not sure why I didn't use $FFFFFE16 directly, I did that 10 years ago and I don't remember a thing. It is very well possible that I was just being stupid and that $FFFFFE16 is safe to use, so you don't even need to copy from $FFFFFFFF to $FFFFFE16 when you load the Special Stage. Again, not sure about this, there might have been a valid reason. Also also please note that I added a "hole" in the Sound Test to exclude the Sound Effects and the invalid IDs, so only actual songs are shown (song1 and song2 are two constants declared at the top of the code). You probably don't want that, but as I said, I'm so rusty with asm after 10 years that I felt more comfortable to just give you my code as it is instead of tampering with it myself. I hope that this helps. And I also hope that I didn't forget any relevant modification, maybe it would have been better if I just sent you the source code as a whole and call it a day as I originally planned, it wouldn't have been a problem if the code was all mine, but other people helped (mainly Puto) and I'm not sure if they would be ok with me sharing their code without permission, so I only pasted code which I'm sure I wrote myself. Sorry if this is even worse than you expected. The fact that not even then I was very good at asm, and that 10 years passed on top of that, is starting to make me think that posting all this stuff might not have been my brightest idea, the "Tech Member" status on Sonic Retro should be stripped from me after this. Also sorry that I derailed your topic. If you feel I went overboard, this can be split somewhere else. Man I hate myself.
Thanks again man, I appreciate the reference. Woah, don't get so down on yourself! You're a household name in the community, and you have a lot to be proud of. You've inspired and helped a lot of people over the years, including myself.