Since the thread is still alive and well, and I decided to dip my toe back into things... I wanna touch on something that always bugged me in Sonic 1, and I almost guarantee no one noticed. But I did 4 years ago when I last worked on a hack, and I do again now. Sonic 1 has a 64 color palette file of all white, just for the background on the sega screen... Which the game branches away to go set up, and then come back to load it into RAM... Nah, methinks that could be optimized. Now, if you want to replace the Sega BG palette to something more colorful, you might not opt to do this... hell you might not opt to anyway, but I think it's good to share anyway. Someone could learn something. Go to @loadpal: under GM_Sega: and replace this: Code (Text): @loadpal: ;moveq #palid_SegaBG,d0 ;bsr.w PalLoad2 ; load Sega logo palette NOTE: I tweaked it to fade into white, because I think it looks nicer... so keep that in mind if you decide to do this. Code (Text): @loadpal: ;moveq #palid_SegaBG,d0 ;bsr.w PalLoad1 ; load Sega logo palette - Tweaked to allow fade in ; Nah, let's make that more efficient, shall we? lea (v_pal_dry_dup).l,a3 moveq #$3F,d7 @loop: move.w #cWhite,(a3)+ ; move data to RAM dbf d7,@loop bsr.w PaletteFadeIn ; added to allow fade in If you instead want to change it to a proper, more colorful palette to suit you, then disregard my changes but still change to PalLoad1 and add PaletteFadeIn to make it look a lot nicer.
Question... has anyone ever accidentally made the Final Zone boss unhittable? My guess is that I either did something inadvertently to the SolidObject Routine or a shift to OSTs made something not work. I'll PM a ROM to someone willing to test but I just wonder if anyone's had this happen to them. In hindsight I could've put this in Basic Q/A but IDK how to Delete posts now. Forum's changed a bit.
I don't have an answer to the Final Zone question, but to 'delete' posts, just edit the post to request that it be deleted (this is how it always worked, right?)
I thought so... but I hit Edit and didn't see a Delete button. Either I'm just blind or I'm not used to any changes that have been made since I was last here
I know I'm quoting a glitch Clownacy posted nearly 5 years ago, but it's to do with a question I currently have. I seem to recall an obscure glitch in Marble Zone Act 2 where if you perfectly ran through the start, hitting both Buzz Bombers and triggering the switch fast enough, you can somehow crash the game. I could've sworn I saw video of this once but oddly I can't find evidence of this anywhere so now I'm starting to think I'm experiencing the Mandela Effect or something. Has anyone ever experienced a bug like this... and could it be related to this issue that Clownacy fixed?
If I remember right, that bug was listed on various wikis (Sonic Retro and TCRF included). Eventually a thread was created where people tried to recreate it, and it was determined that the bug did not actually exist, so it was removed. The bug that I fixed shouldn't cause any crashes anyway - it's simply a null-pointer dereference that's harmless in Sonic 1's case, because it only reads a byte. The bug only matters because it causes a crash when you port objects to Sonic 2. The reason it does is because Sonic 2 would read a word instead of a byte, and the address it would try to read from would be odd, causing a crash.
Small fix to a peculiar bug: If you get a game over by drowning, the title screen will stop scrolling. This is because $F744 is set when the player drowns, which is the scroll lock flag. However it doesn't get cleared at the title screen. Here's a hardware demonstration (Featuring anxiety filled Kilo's heavy breathing and tripping) The fix to this is a really simple one. At Title_LoadText, just before the branch to LevelSizeLoad, clear $F744.
I'm interested in the score reset back to last checkpoint, imo that's the way it should be. Though i do think monitor behaviour is fine the way it is. Just thought it would be handy to list some bugs I've found for people to look at if interested, i'm not yet skilled enough to figure them out at present Here are bug's I've found Starlight Zone Glitch: when the zone fades in on the bottom just right of centre there's a couple of vertical blue bars that appear for a few frames (not tested on revision 0, you can see it at the start of the demo) The next glitch happens when you roll into a rock from the right side (found it when testing spindash) there's a bridge in green hill act 2 i think it is where there's rocks either side if you roll into the right from the right you tend to go into the rock a few pixels then get pushed out (sometimes doesn't trigger) There is a small period of time where if you hit an invincibility monitor you can still die before the sparkles appear (I'm actually planning on looking into this one as i think it's an easy fix and if so will post it) When testing the Air Roll I found this (I don't think it's related to air roll though): if you press jump just as you hit a spring you don't get the spring sound but still get the spring bonus height and animation, I believe you have to hit jump the same frame as you hit the spring for this to occur And from my count there's still about 9 bugs on https://info.sonicretro.org/Sonic_the_Hedgehog_(16-bit)/Bugs#General_bugs yet to be fixed, that I've yet to come across bug fixes for. Edit: I have just tried to confirm 2 and 4 2: defiantly happens, i just tested it with the rock left of the bridge on GHZ2 just before the end goal run towards the rock and go into a roll and you will roll into the rock 4: I cannot get to trigger again so it must be if you have air roll on and you jump at the same time as the spring, i have implemented a variation of air roll where you can't curl into a ball if you are in the spring jump animation but will roll if in the air and not in the spring jump animation, will toggle my implementation to the original one from the guide confirm this is the cause. Edit 2: 4: I have tested this a second time with the air roll feature and still cannot get it to activate when i originally found that bug i managed to get it to activate a few times so i'm wondering if this was related to having the OptimiseSound enabled at the time or something similar. Also I may have fixed 3 since, the toggle on invincibility was the first thing in the Pow_ChkInvinc: after the monitor type check (I thought that might happen later before i looked at that subroutine) what i ended up doing is making it so that Pow_ChkInvinc gets checked before all the other monitors and that "seems" to make the monitor activate faster, but it's a hard one to test because i don't know a good location to hit a monitor then immediately hit an enemy or trap, though I am aware i have done this which is how i discovered it in the first place. Edit 3: 4: Tested this again after disabling the air roll from previous attempt, the only difference is this time i was facing left on the spring, I bounced continuously and hit jump at just the right time and the spring sound did not play (it's the first spring at the start of GHZ1 I tested with) Pretty sure I was facing left when I originally found this bug. (what is it with bugs when facing left in this game)
I do apologise regarding the thread being bumped but I believe what I'm about to show is a no-brainer. In Sonic (3) and Knuckles, when you hit a monitor from below, you hit it rather than it bouncing to the floor like in Sonic 1, 2 and 3. I'll demostrate it for you: Sonic 3 and Knuckles allows you to hit the monitor from below. This is not the case for Sonic 1 (applies to its sequel) If you want to make the monitor behave like S3K in Sonic 1 and 2, it's pretty simple to do. In Sonic 1 (Hivebrain), locate Touch_Monitor and this is what you will get: Code (Text): Touch_Monitor: tst.w $12(a0) ; is Sonic moving upwards? bpl.s loc_1AF1E ; if not, branch move.w $C(a0),d0 subi.w #$10,d0 cmp.w $C(a1),d0 bcs.s locret_1AF2E neg.w $12(a0) ; reverse Sonic's y-motion move.w #-$180,$12(a1) tst.b $25(a1) bne.s locret_1AF2E addq.b #4,$25(a1) ; advance the monitor's routine counter rts If you look in the last 6 lines of code, it makes sure it reverses Sonic's y-motion in order for the monitor to fall. In S3K, the code is removed in order for this behaviour to occur, so remove the last 6 lines of code. In Sonic 2 (GitHub), locate Touch_Monitor and you will see this: Code (Text): Touch_Monitor: btst #1,status(a0) beq.s loc_3F768 tst.w y_vel(a0) ; is Sonic moving upwards? bpl.s loc_3F768 ; if not, branch move.w y_pos(a0),d0 subi.w #$10,d0 cmp.w y_pos(a1),d0 blo.s return_3F78A neg.w y_vel(a0) ; reverse Sonic's y-motion move.w #-$180,y_vel(a1) tst.b routine_secondary(a1) bne.s return_3F78A move.b #4,routine_secondary(a1) ; set the monitor's routine counter rts As I previously said, the last 6 lines reverses Sonic's y-motion in order for the monitor to fall. We don't want that so remove it. Now save, build and let's test it! And there we go, it behaves as intended! Enjoy!
Code (Text): ; =========================================================================== ; --------------------------------------------------------------------------- ; Object 19 - unused rolling ball (placeable in Debug Mode) ; --------------------------------------------------------------------------- Obj19: ; XREF: Obj_Index moveq #0,d0 move.b $24(a0),d0 move.w Obj19_Index(pc,d0.w),d1 jmp Obj19_Index(pc,d1.w) ; --------------------------------------------------------------------------- Obj19_Index: dc.w Obj19_Main-Obj19_Index ; 0 dc.w Obj19_Move-Obj19_Index ; 2 dc.w Obj19_Move2-Obj19_Index ; 4 dc.w Obj19_Delete-Obj19_Index ; 6 dc.w Obj19_Solid-Obj19_Index ; 8 ; --------------------------------------------------------------------------- ; loc_5C98: Obj19_Main: move.b #$18,$16(a0) move.b #$C,$17(a0) bsr.w ObjectFall jsr (ObjHitFloor).l tst.w d1 bpl.s locret_5CEC add.w d1,$C(a0) move.w #0,$12(a0) move.b #8,$24(a0) move.l #Map_obj48,4(a0) move.w #$43AA,2(a0) move.b #4,1(a0) move.b #3,$18(a0) move.b #$18,$19(a0) move.b #1,$1F(a0) bsr.w sub_5DC8 locret_5CEC: rts ; --------------------------------------------------------------------------- ; loc_5CEE: Obj19_Solid: move.w #$23,d1 move.w #$18,d2 move.w #$18,d3 move.w 8(a0),d4 bsr.w SolidObject btst #5,$22(a0) bne.s loc_5D14 move.w ($FFFFD008).w,d0 sub.w 8(a0),d0 bcs.s loc_5D20 loc_5D14: move.b #2,$24(a0) move.w #$80,$14(a0) loc_5D20: bsr.w sub_5DC8 bsr.w DisplaySprite bra.w loc_5E2A ; --------------------------------------------------------------------------- ; loc_5D2C: Obj19_Move: btst #1,$22(a0) bne.w Obj19_Move2 bsr.w sub_5DC8 bsr.w Obj19_Calc bsr.w SpeedToPos move.w #$23,d1 move.w #$18,d2 move.w #$18,d3 move.w 8(a0),d4 bsr.w SolidObject jsr (Sonic_AnglePos).l cmpi.w #$20,8(a0) bcc.s loc_5D70 move.w #$20,8(a0) move.w #$400,$14(a0) loc_5D70: btst #1,$22(a0) beq.s loc_5D7E move.w #$FC00,$12(a0) loc_5D7E: bsr.w DisplaySprite bra.w loc_5E2A ; --------------------------------------------------------------------------- ; loc_5D86: Obj19_Move2: bsr.w sub_5DC8 bsr.w SpeedToPos move.w #$23,d1 move.w #$18,d2 move.w #$18,d3 move.w 8(a0),d4 bsr.w SolidObject jsr (Sonic_Floor).l btst #1,$22(a0) beq.s loc_5DC0 move.w $12(a0),d0 addi.w #$28,d0 move.w d0,$12(a0) loc_5DC0: bsr.w DisplaySprite bra.s loc_5E2A ; --------------------------------------------------------------------------- sub_5DC8: tst.b $1A(a0) beq.s Obj19_Animate move.b #0,$1A(a0) rts ; --------------------------------------------------------------------------- ; loc_5DD6: Obj19_Animate: move.b $14(a0),d0 beq.s loc_5E02 bmi.s loc_5E0A subq.b #1,$1E(a0) bpl.s loc_5E02 neg.b d0 addq.b #8,d0 bcs.s loc_5DEC moveq #0,d0 loc_5DEC: move.b d0,$1E(a0) move.b $1F(a0),d0 addq.b #1,d0 cmpi.b #4,d0 bne.s loc_5DFE moveq #1,d0 loc_5DFE: move.b d0,$1F(a0) loc_5E02: move.b $1F(a0),$1A(a0) rts ; --------------------------------------------------------------------------- loc_5E0A: subq.b #1,$1E(a0) bpl.s loc_5E02 addq.b #8,d0 bcs.s loc_5E16 moveq #0,d0 loc_5E16: move.b d0,$1E(a0) move.b $1F(a0),d0 subq.b #1,d0 bne.s loc_5E24 moveq #3,d0 loc_5E24: move.b d0,$1F(a0) bra.s loc_5E02 ; --------------------------------------------------------------------------- loc_5E2A: move.w 8(a0),d0 andi.w #$FF80,d0 move.w ($FFFFF700).w,d1 subi.w #$80,d1 andi.w #$FF80,d1 sub.w d1,d0 cmpi.w #$280,d0 bhi.w DeleteObject rts ; --------------------------------------------------------------------------- ; loc_5E4A: Obj19_Delete: bra.w DeleteObject ; --------------------------------------------------------------------------- ; sub_5E50: Obj19_Calc: move.b $26(a0),d0 bsr.w CalcSine move.w d0,d2 muls.w #$38,d2 asr.l #8,d2 add.w d2,$14(a0) muls.w $14(a0),d1 asr.l #8,d1 move.w d1,$10(a0) muls.w $14(a0),d0 asr.l #8,d0 move.w d0,$12(a0) rts The rolling ball code ported to Sonic 1 Final! Still not sure what causes it to float when stood on, unless someone decides to provide a explanation.
I actually believe I can explain the floating. The status flag for Sonic standing on the object is the same as the one used by Sonic for if he isn't on the ground but shouldn't fall. Since this reuses routines from Sonic's collision, it sees that status bit 3 of the object is set, and then triggers that very behavior, causing the ball to float. The primary ways to avoid this is to either make the ball jump to labels in that code which avoids the checks for bit 3, OR make new variants of those routines which remove the checks which are only relevant to the player character.
The ClearScreen routine is broken. One of the functions is intended to clear the H-scroll buffer, from $CC00 to $CFFF. It does this by loading the H-scroll buffer into a1, and then moving longword 0 into it, and increment. However, the amount of times it was meant to loop was set too high and actually goes into the SST space. It ends up clearing up to $D004. This is unnoticeable mid game since ClearScreen is never ran mid-game (Logically) To fix this, go to loc_133A and change Code (Text): move.w #$100,d1 to Code (Text): move.w #$FF,d1 This probably happened because Naka forgot that dbf loops one more time than you actually set it.
I think you're wrong. it was in the DeformBgLayer label. You have to change the tst.b to clr.w to solve the drown bug problem.
Uh.... that's not how this works! If you change that, you'll change the code flow at some point to be beyond what was intended! tst.b checks if the byte is 0, and uses that for a conditional branch! clr.w sets a WHOLE WORD to 0! Also, Iso's not incorrect here. The issue is with that RAM address not being cleared when entering the title screen. Their solution is the more logical one.
Ok, I'll actually supply the code change to make. Change this: Code (Text): jsr (Sonic_AnglePos).l Into this: Code (Text): jsr (loc_14602).l Skips the check.
I'm curious: with respect to this post (content abridged and linked for clarity): What are these bugs? I've been meaning to fix the display-before-delete series of bugs, but have hesitated for many of them (mainly those involving modifying the stack pointer), not knowing which ones are safe and which ones are not.
Hmm... it seems one archive I found differs in how objects 2E and 4C/4D are fixed. Such edits are of course obscured thanks to the new forum software, but at least it seems like the current guide should be bug-free. Thanks for the heads up.
I rewrote the 'extend music range' guide to have a far less hackish implementation. Despite Github Sonic 1 being my enemy, I am not above using it for guides, although Hivebrain users shouldn't have too hard a time implementing it in their disassembly.