The HUD code in Sonic 1 has it where it's part of the normal object system whereas in Sonic 2, 3 and Knuckles, it's manually written into the priority table and gets called from the sprite rendering routine. To port this over to Sonic 1 (Hivebrain), the old HUD code needs to be removed and to do that, go to Obj21 and you should see something like this: Code: Obj21: ; XREF: Obj_Index moveq #0,d0 move.b $24(a0),d0 move.w Obj21_Index(pc,d0.w),d1 jmp Obj21_Index(pc,d1.w) ; =========================================================================== Obj21_Index: dc.w Obj21_Main-Obj21_Index dc.w Obj21_Flash-Obj21_Index ; =========================================================================== Obj21_Main: ; XREF: Obj21_Main addq.b #2,$24(a0) move.w #$90,8(a0) move.w #$108,$A(a0) move.l #Map_obj21,4(a0) move.w #$6CA,2(a0) move.b #0,1(a0) move.b #0,$18(a0) Obj21_Flash: ; XREF: Obj21_Main tst.w ($FFFFFE20).w ; do you have any rings? beq.s Obj21_Flash2 ; if not, branch clr.b $1A(a0) ; make all counters yellow jmp DisplaySprite ; =========================================================================== Obj21_Flash2: moveq #0,d0 btst #3,($FFFFFE05).w bne.s Obj21_Display addq.w #1,d0 ; make ring counter flash red cmpi.b #9,($FFFFFE23).w ; have 9 minutes elapsed? bne.s Obj21_Display ; if not, branch addq.w #2,d0 ; make time counter flash red Obj21_Display: move.b d0,$1A(a0) jmp DisplaySprite ; =========================================================================== change it to look like this: Code: Obj21: ; XREF: Obj_Index rts ; =========================================================================== You won't need the old HUD code anymore because it's handled by this new routine which I will post below. Now for the new HUD code, add this below the rts in the block of code posted above: Code: ; --------------------------------------------------------------------------- ; HUD Object code - SCORE, TIME, RINGS ; --------------------------------------------------------------------------- loc_40804: tst.w ($FFFFFE20).w beq.s loc_40820 moveq #0,d1 btst #3,($FFFFFE05).w bne.s BranchTo_loc_40836 cmpi.b #9,($FFFFFE23).w bne.s BranchTo_loc_40836 addq.w #2,d1 BranchTo_loc_40836 bra.s loc_40836 ; =========================================================================== loc_40820: moveq #0,d1 btst #3,($FFFFFE05).w bne.s loc_40836 addq.w #1,d1 cmpi.b #9,($FFFFFE23).w bne.s loc_40836 addq.w #2,d1 loc_40836: move.w #$90,d3 move.w #$108,d2 lea (Map_Obj21).l,a1 movea.w #$6CA,a3 add.w d1,d1 adda.w (a1,d1.w),a1 moveq #0,d1 move.b (a1)+,d1 subq.b #1,d1 bmi.s return_40858 jsr sub_D762 return_40858: rts ; End of function h This is the HUD code from S2 slightly modified to work with Sonic 1's mapping system. For the rest of the code, go to BuildSprites and change this part: Code: BuildSprites: ; XREF: TitleScreen; et al lea ($FFFFF800).w,a2 ; set address for sprite table moveq #0,d5 lea ($FFFFAC00).w,a4 moveq #7,d7 to this: Code: BuildSprites: ; XREF: TitleScreen; et al lea ($FFFFF800).w,a2 ; set address for sprite table moveq #0,d5 moveq #0,d4 tst.b ($FFFFFFD0).w ; this was level_started_flag beq.s BuildSprites_2 jsr loc_40804 BuildSprites_2: lea ($FFFFAC00).w,a4 moveq #7,d7 For the level_started_flag you can use any unused RAM address for it. I used $FFFFFFD0 for this guide. Go to SegaScreen and then scroll down until you see this line: Code: move.w #0,($FFFFF660).w add this below it: Code: move.b #0,($FFFFFFD0).w Go to Title_ClrPallet and you should see this line somewhere below it: Code: move.b #$8A,($FFFFD080).w ; load "SONIC TEAM PRESENTS" object add this below it: Code: move.b #0,($FFFFFFD0).w Go to Level and you should see this somewhere below it: Code: bset #7,($FFFFF600).w ; add $80 to screen mode (for pre level sequence) add this below it: Code: move.b #0,($FFFFFFD0).w Further down at loc_3946 you should see this somewhere below the label: Code: move.b #$21,($FFFFD040).w ; load HUD object replace that with this: Code: move.b #1,($FFFFFFD0).w Go to SS_ClrNemRam and find this line below it: Code: move.b #9,($FFFFD000).w ; load special stage Sonic object add this below it: Code: move.b #0,($FFFFFFD0).w Go to End_LoadSonic and find this line below it: Code: move.b #$21,($FFFFD040).w ; load HUD object replace it with this: Code: move.b #1,($FFFFFFD0).w Then go to Cred_ClrPallet and find this line below it: Code: move.b #$8A,($FFFFD080).w ; load credits object and add this below it: Code: move.b #0,($FFFFFFD0).w And for the last step (thanks Iso) go to Cont_ClrObjRam and find this line: Code: move.b #4,($FFFFD0E4).w then add this below it: Code: move.b #0,($FFFFFFD0).w You're now done and should have a near perfect port of S2's HUD code to Sonic 1. It also fixes the bug where "Time" does not flash if you have 9 minutes on the timer and have rings. The source code with all steps applied is provided below.
Seems you forgot a step! The fix is easy enough, simply go to Cont_ClrObjRam:, and under Code: move.b #4,($FFFFD0E4).w Clear the HUD draw flag Code: move.b #0,($FFFFFFD0).w
Would it be possible to make a version of this guide for the Github disassemblies? Or at least, add some commenting to the code, some actually descriptive labels, and/or replace magic numbers with constants? It's incredibly difficult for people to follow the replacement code in comparison to the original if they're not using the Hivebrain disassembly! EDIT: Okay, so I've gotten this working in the GitHub disassembly! I'll be editing this post again with an updated version of your guide in a bit. EDIT 2: Here's the guide in OP, modified to work with the GitHub disassembly. First, go to /_incObj/21 HUD.asm and replace the entire contents with the following: Code: ; --------------------------------------------------------------------------- ; Object 21 - SCORE, TIME, RINGS (DEPRECATED) ; --------------------------------------------------------------------------- HUD: rts ; --------------------------------------------------------------------------- ; HUD Object code - SCORE, TIME, RINGS ; --------------------------------------------------------------------------- loc_40804: tst.w ($FFFFFE20).w beq.s loc_40820 moveq #0,d1 btst #3,($FFFFFE05).w bne.s BranchTo_loc_40836 cmpi.b #9,($FFFFFE23).w bne.s BranchTo_loc_40836 addq.w #2,d1 BranchTo_loc_40836 bra.s loc_40836 ; =========================================================================== loc_40820: moveq #0,d1 btst #3,($FFFFFE05).w bne.s loc_40836 addq.w #1,d1 cmpi.b #9,($FFFFFE23).w bne.s loc_40836 addq.w #2,d1 loc_40836: move.w #$90,d3 move.w #$108,d2 lea (Map_HUD).l,a1 movea.w #$6CA,a3 add.w d1,d1 adda.w (a1,d1.w),a1 moveq #0,d1 move.b (a1)+,d1 subq.b #1,d1 bmi.s return_40858 jsr (BuildSpr_Normal).l return_40858: rts ; End of function h This is generally the same as the original guide's, as I haven't replaced all the magic addresses with their proper constants versions. However, I did make two important changes: loading the HUD mappings from the proper location, and using the modern label for what was originally "sub_D762". Now, in Variables.asm, we need to define a new variable for when to enable/disable drawing the HUD. This is called "level_started_flag" in the original guide, but here we'll call it "v_level_started_flag". The address used in the original guide was $FFFFFFD0, but if you are using Project Sonic 1: Two Eight, this is used for collision plane management. Instead, we'll use a byte after the player 2 input registers, as there are a bunch of free bytes after it. So, look for: Code: v_jpadpress1: equ $FFFFF605 ; joypad 1 input - pressed ...and add this after it: Code: v_jpad2hold1: equ $FFFFF606 ; joypad 2 input - held v_jpad2press1: equ $FFFFF607 ; joypad 2 input - pressed v_level_started_flag: equ $FFFFF608 ; Level started flag (As an added bonus, now you can track player 2's inputs! Perhaps make your cheat codes trickier by using the second controller?) Now, in sonic.asm, go to the label "BuildSprites" and replace this: Code: BuildSprites: ; XREF: TitleScreen; et al lea ($FFFFF800).w,a2 ; set address for sprite table moveq #0,d5 lea ($FFFFAC00).w,a4 moveq #7,d7 ...with this: Code: BuildSprites: ; XREF: TitleScreen; et al lea ($FFFFF800).w,a2 ; set address for sprite table moveq #0,d5 moveq #0,d4 tst.b (v_level_started_flag).w ; this was level_started_flag beq.s BuildSprites_2 jsr loc_40804 BuildSprites_2: lea ($FFFFAC00).w,a4 moveq #7,d7 Next, go to the label "GM_Sega" and after this line: Code: move.w #0,(v_pal_buffer+$10).w ...add this line: Code: move.b #0,(v_level_started_flag).w Next, go to the label "Tit_ClrPal" and after this line: Code: move.b #id_CreditsText,(v_objspace+$80).w ; load "SONIC TEAM PRESENTS" object ...add this line: Code: move.b #0,(v_level_started_flag).w Next, go to the label "GM_Level" and after this line: Code: bset #7,(v_gamemode).w ; add $80 to screen mode (for pre level sequence) ...add this line: Code: move.b #0,(v_level_started_flag).w Next, go to the label "Level_SkipTtlCard" and replace this line: Code: move.b #id_HUD,(v_objspace+$40).w ; load HUD object ...with this line: Code: move.b #1,(v_level_started_flag).w Next, go to the label "SS_ClrNemRam" and after this line: Code: move.b #id_SonicSpecial,(v_player).w ; load special stage Sonic object ...add this line: Code: move.b #0,(v_level_started_flag).w Next, go to the label "Cont_ClrObjRam" and after this line: Code: move.b #4,(v_objspace+$80+obFrame).w ...add this line: Code: move.b #0,(v_level_started_flag).w Next, go to the label "End_LoadSonic" and replace this line: Code: move.b #id_HUD,(v_objspace+$40).w ; load HUD object ...with this line: Code: move.b #1,(v_level_started_flag).w Finally, go to the label "Cred_ClrPal" and after this line: Code: move.b #id_CreditsText,(v_objspace+$80).w ; load credits object ...add this line: Code: move.b #0,(v_level_started_flag).w That's it! Compile and you should be good to go!