don't click here

Basic Questions & Answers thread

Discussion in 'Engineering & Reverse Engineering' started by Tweaker, May 29, 2008.

  1. This one's more of a software question, but are there any good level editor programs for the Mega Drive Sonic titles available for Linux?
     
  2. Devon

    Devon

    help me, i am in hell Tech Member
    1,408
    1,710
    93
    your mom
    You should be able to run SonLVL with Mono.
     
  3. Chainspike

    Chainspike

    Stealing rings since 1994 Member
    173
    90
    28
    Death Egg Zone
    S3C Delta
    Animation frames past $F0 will not work because some of them are reserved for animation script functions. For example, $FF is hardcoded to mark the end of an animation. For your second question, this should not be too difficult. The first thing you would want to do is make a duplicate of Sonic's current art, mappings, and DPLCs and include them in the disassembly. Then, you will need to modify the super transformation code to load the new art/mappings when Sonic turns super. Sonic 3 already does this for the mappings and DPLCs, and it could probably be used a reference for implementing it in Sonic 2.
     
  4. RetroKoH

    RetroKoH

    Member
    1,722
    101
    43
    S1Fixed: A successor to ReadySonic
    Right, so I've got a minor bone to pick with the GitHub Sonic 1. I just noticed what I believe to be are two bugs I don't remember ever being in the game. And I'm seeing them in both the built file, AND the included s1rev00 and rev01 files. Were these bugs seriously ALWAYS in the game? I can't be imagining this...

    1st. The title screen music sounds slightly off the first time you play it. After the percussion, the melody kicks in, and the second note sounds way off. I'd love for any audiophiles to confirm this. NOTE: This didn't occur when playing the track in Sound Test, and I think it only occurred in ReGen emulator. Not in Gens.

    2nd. Spring Yard Zone Act 1. For some reason there is a blue flicker that looks like the Spotlight object's sprite that appears below the title card when you start the zone. This occurs in every test I've done thus far.

    Like I said, I don't remember these bugs ever occurring before, and they don't occur in any of my archived ROM builds.
     
  5. Wafer

    Wafer

    Find me on Twitter instead Member
    255
    75
    28
    @RetroKoH There's an easy way to test this. I downloaded a known good dump of REV0 from a ROM set and compared it against the binary packaged in the repo using HxD: the files are identical. For good measure, I also built the game from source and ran chkbitperfect.rev00.bat, which confirmed that the source is building a binary identical to the packaged binary.

    I'm not gonna do any further testing or diagnosis, because I'm satisfied that the repo is accurate. My suspicions are that either your memory or regen is at fault.
     
  6. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,242
    498
    63
    Japan

    The SMPS driver for the title screen actually performs the voice/instrument/patch update before the key off is even registered (just by the nature of the software), this is not the main problem though at least not for this instance. But, the emulation for Regen is not perfect, FM5's non-slot (modulator) operators are not firing as they should do, leaving only the slot (carrier) playing on its own, so it sounds like a ringing instead. I suspect it's a problem with Regen not setting it's channels up correctly on start up, and it likely gets confused and probably thinks the keys are already on and it should be on the decay phase.

    When data is written to the YM2612 ports, Regen unpacks the operator ports to a second set of segregated operator register slots (for example, the algorithm and the feedback are separated into their own RAM spots) and the values are automatically shifted/multiplied/whatever so the emulator doesn't have to keep doing it over and over again (it's sort of like a cache if you will). I suspect this is out of sync on start up, while the main operator RAM slots are fine, the pre-calculated cache copies might be corrupt in one or two rare spots. There might be some timing issues too, for if you play the game at 50Hz, it does not happen.

    tl;dr, it's the emulator and not the ROM.

    It's always happened, but it's so brief you never noticed until now. You probably already know the spotlight appearing is simply due to it using the same palette line as Sonic's/Title cards, so it cannot fade in, it has to just "appear".

    But the reason it appears down below is because the scroll positions are not transferred to VSRAM/H-Scroll in VRAM until after the level is rendered. In the init routine for the level, the level data is loaded including the X and Y position for Sonic and it'll setup the camera's X and Y position correctly relative to Sonic (with boundaries, etc). The scrolling (deform) routine is ran so the correct V/H-scroll values are written to their RAM buffers. But then, the level is set to render its mappings fully to the plane, this is done within the main routine and not during V-blank, furthermore, there is a lengthy delay between the level render and the next allowed V-blank interrupt as the routine is still setting things up. The next V-blank interrupt will be allowed during the fade in subroutine. I think the idea was that the level is usually not using Sonic's palette line, so it doesn't matter if the H/V scroll positions are unaligned and have not updated yet, you won't see those until the fade in occurs (in which case V-blank is ran and the scroll tables are transferred), but I don't think they anticipated the level artist actually using the first line.

    The solution is very simple, after the scroll call, allow V-blank to run before the level rendering subroutine is called. For the Hivebrain, goto "loc_3946:" and find:

    Code (Text):
    1.         bsr.w   DeformBgLayer
    ...place this below it:
    Code (Text):
    1.         move.b  #$C,($FFFFF62A).w
    2.         bsr.w   DelayProgram
    This will allow V-blank to run and to transfer the V/H-scroll tables across before the level itself is rendered.
     
  7. Hitaxas

    Hitaxas

    Retro 80's themed Twitch streamer ( on hiatus) Member
    Ok, so in S2 I know that Sonic_RecordPos is in part responsible for the AI version of Tails' controls and tracking so that it keeps up with Sonic. However I fail to see where the Tails object calls for it in anyway... How could I make it so he isn't always up Sonic's butt all the time? Sonic wants some social distancing. I want him to not overlap with Sonic when idle, rather, stand directly behind him.
     
  8. RetroKoH

    RetroKoH

    Member
    1,722
    101
    43
    S1Fixed: A successor to ReadySonic
    Once I was able to reproduce all of this in Hivebrain (after my initial post) I came to the same conclusion as you. One thing I also hadnt considered was the machine running the emulator. This IS the first time I started hacking on my newer laptop, after all. IDK if that would impact anything...

    Also, cheers Markey for the in-depth explanation. Especially for the second one. I can't believe I NEVER noticed that... or maybe I did and somehow didn't remember. Honestly I wasn't looking for it and noticed immediately. Things like that just trigger in my mind immediately, it's why I hate cinemas when so many people also attend.

    But I digress, cheers for this guys!
     
  9. Wafer

    Wafer

    Find me on Twitter instead Member
    255
    75
    28
    Fun aside: I'm currently hacking Smash TV for the Master System to support full twin stick play with two controllers, but I was getting weird control locks when I was firing on a diagonal.

    It only occurred to me about an hour ago that the problem was the keyboard matrix in my MacBook preventing simultaneous keypresses. Moral of the story: don't trust your emulator host (and, y'know, test control stuff using something other than a keyboard).

    @Hitaxas That's because Tails doesn't call that subroutine, because Tails shouldn't be recording Sonic's position, only Sonic does that.

    You need to look for Sonic_Pos_Record_Buf and its friend Sonic_Pos_Record_Index. The relevant parts appear to be TailsCPU_Flying_Part2 and TailsCPU_Normal_SonicOK.
     
    Last edited: May 4, 2020
  10. Hitaxas

    Hitaxas

    Retro 80's themed Twitch streamer ( on hiatus) Member
    Ehh, those are RAM addresses. You are correct though, the CPU code does some stuff with those addresses, specifically at TailsCPU_Normal_SonicOK

    I've tried to fiddle with it, but I cannot tweak Tails to stay behind Sonic.
     
  11. Wafer

    Wafer

    Find me on Twitter instead Member
    255
    75
    28
    Yup, they're RAM addresses for storing Sonic's position. Which is how the Tails AI knows where to head to. So when they get loaded into a register by the Tails AI, you want to figure out which way Sonic is facing and use that to add a positive or negative amount to the x_pos that comes out of it before it gets loaded into Tails_CPU_target_x (in fact Tails_CPU_target_x is another thing you should be looking for in the code).

    BTW, be aware that this could possibly lead to Tails freaking out and running off edges into spikes, or jumping up against a wall. If you want to avoid that, you'll need to figure out how to make Tails more aware of his surroundings, which I daresay is out-of-scope for this thread, but one solution would be to see whether Tails starts falling when he reaches the target, and if so set him to fly instead, or set him to stop if he's trying to get to a point inside a wall. It's not great, but it's the most straightforward way that comes to mind.

    One thing you might want to do is do a distance check between Tails and Sonic if Sonic is stopped, and have the CPU switch to a routine to have Tails stop if he's within a short distance and Tails is on solid ground.

    Another issue you might have is Tails desyncing from Sonic's actions. Part of the reason Tails likes to run right up to Sonic's position is because, unless he falls behind Sonic or gets separated from him somehow, he just "replays" player 1's controls with a slight delay. This might actually be a bigger deal, because in Sonic 2 Versus Edition when I moved Tails' start position up level to Sonic's, it desynced the EHZ 2P demo before the demo could end. If Tails jumps too soon he might miss a platform/ledge, if he jumps too late he might not be on any solid ground to launch off.

    tldr AI code is HARD. The Sonic games cheat by making Tails mimic Sonic wherever possible, and putting him into a panic state or flying if he can't get to Sonic, depending on whether Tails is offscreen or not.
     
    Last edited: May 4, 2020
  12. Hitaxas

    Hitaxas

    Retro 80's themed Twitch streamer ( on hiatus) Member
    AI is tricky indeed. I was successful in getting Tails to always be just behind or in front of Sonic, and never overlapping. But as you said, now comes the issue of movement, I haven't been able to reverse the change if main player is moving.

    The method I used was simple

    under
    Code (Text):
    1. TailsCPU_Normal_SonicOK:
    2.     bsr.w    TailsCPU_CheckDespawn
    3.     tst.w    (Tails_control_counter).w    ; if CPU has control
    4.     bne.w    TailsCPU_Normal_HumanControl        ; (if not, branch)
    5.     tst.b    obj_control(a0)            ; and Tails isn't fully object controlled (&$80)
    6.     bmi.w    TailsCPU_Normal_HumanControl        ; (if not, branch)
    7.     tst.w    move_lock(a0)            ; and Tails' movement is locked (usually because he just fell down a slope)
    8.     beq.s    +                    ; (if not, branch)
    9.     tst.w    inertia(a0)            ; and Tails is stopped, then...
    10.     bne.s    +                    ; (if not, branch)
    11.     move.w    #8,(Tails_CPU_routine).w    ; => TailsCPU_Panic
    12. +
    13.  
    14.     lea    (Sonic_Pos_Record_Buf).w,a1
    15.     move.w    #$10,d1
    16.     lsl.b    #2,d1
    17.     addq.b    #4,d1
    18.     move.w    (Sonic_Pos_Record_Index).w,d0
    19.     sub.b    d1,d0
    20.     move.w    (a1,d0.w),d2    ; d2 = earlier x position of Sonic
    I placed
    Code (Text):
    1.         subi.w   #$16,d2   ; socially distance Tails from Sonic
    If I could just reverse this subtraction from d2 only while moving, I would imagine it could solve the issue, but all attempts have been fruitless.


    Edit: IIRC, Flamewing was partially successful in this endeavor in their Sonic 2 Heroes hack. Maybe I might need a chat with them.
     
    Last edited: May 4, 2020
  13. RetroKoH

    RetroKoH

    Member
    1,722
    101
    43
    S1Fixed: A successor to ReadySonic
    Got myself a problem porting the SpinDash sound to Sonic 1. I've done it a few times before with no issue but for some reason, it doesn't like me today. I included a Pastebin of the code. I know I've done something wrong but I can't seem to figure out what. Would anyone be so kind as to take a glance? I'm sure it's a tiny thing I'm missing: https://pastebin.com/13kyhCMS

    Basically the problem is, while the sound starts playing fine, and REVS up also, it seems to cut out if I let the Spindash idle for a bit. Not sure why that is. Kinda reminds me of my motorbike, come to think of it...:V
     
    Last edited: May 6, 2020
  14. Hitaxas

    Hitaxas

    Retro 80's themed Twitch streamer ( on hiatus) Member
  15. Wafer

    Wafer

    Find me on Twitter instead Member
    255
    75
    28
    @Hitaxas Could his normal AI routine still be running and pointing him towards the target_x that you set to be behind Sonic?
     
  16. Dulappy

    Dulappy

    koronesuki Member
    49
    7
    8
    Greece
    sonic
    So, I keep getting a "branch out of range" on this lea instruction in Sonic 1 and I can't figure out why.
    Code (Text):
    1.  
    2.         move.l     a4,-(sp)
    3.         lea        (v_screenposx).w,a4
    I tried looking it up online and messing around with the code but to no luck.

    EDIT: Nevermind, it looks like it was an unrelated error popping up a few lines of code lower, even though errors.txt was saying it was on the lea instruction.
     
    Last edited: May 7, 2020
  17. Hitaxas

    Hitaxas

    Retro 80's themed Twitch streamer ( on hiatus) Member
    That was exactly it! Thanks for pointing that out. :)
    To fix this, I ran a check for the carrying sonic flag, and skipped the TailsCPU_Normal_FilterAction routine if the flag was positive. Worked like a charm.


    Edit: OK, so new issue. In porting this code, I noticed Tails hands are behind Sonic's when carrying him. So I went back and checked in S3K, same deal. What would be the best way to remedy this?

    Edit2: I was able to fix this by setting Tails' priority to 0 when carrying Sonic, I set the priority back to normal in the Tails resetonfloor routine. Seems to work well. Wonder why this wasn't done in the first place. :eyebrow:
     
    Last edited: May 7, 2020
  18. Wafer

    Wafer

    Find me on Twitter instead Member
    255
    75
    28
    Do you mean "behind Sonic's"? If so, you could add a new animation frame for Sonic with Tails' hands pasted on to it.

    Alternatively, you can force Tails to render in front of Sonic by conditionally rendering their sprites from the sprite table in reverse order. I've done something like this before in my own hack. You need to look in BuildSprites_NextObj, and maybe BuildSprites_LevelLoop, it looks as though the relevant register is d6, and maybe d7 (I only did this in the routine for drawing the lower screen in versus mode and I didn't comment what I was doing, so I'm a bit fuzzy on the specifics).

    Edit: ninja'd by your own edit. You might find that Tails renders over some things that he shouldn't do with your solution.
     
    Last edited: May 7, 2020
  19. RetroKoH

    RetroKoH

    Member
    1,722
    101
    43
    S1Fixed: A successor to ReadySonic
    Going with what Wafer said, I wouldn't change Tails priority in that way. IIRC by default, player characters are at a priority of 2 (converted to word value of $100). The ideal solution is adding a mapping piece that places Tails hands over Sonic. I did the same thing in my hack in a few different instances to get around the palette limitations, as well as making things just appear better. But be mindful if doing it this way as well, because too many sprite pieces isn't good either. Correct me if I'm wrong, but I think the console can only render so many pieces on one scanline.
     
  20. Hitaxas

    Hitaxas

    Retro 80's themed Twitch streamer ( on hiatus) Member
    Interesting, if I ever decide to go further than I currently plan (I.E new level art or such), I will keep it in mind. The method seems to work for me, and in all my testing so far, Tails doesn't appear over anything he shouldn't. I've tested in multiple zones that have level art or other sprites in the foreground of players too.

    Unrelated, I have another issue I'd like to get resolved. I coded a move for Sonic, it works fine. Except it sometimes doesn't break monitors. I thought this issue could be resolved simply by editing the Touch_Monitor routine (specifically the loc_3F768 just under it) to check for the animation the attack plays, much like it checks for if the player is in a ball, yet he lands on the top of them instead.

    Code (Text):
    1. ; SONIC AND TAILS SPECIFIC CODE
    2. ; Edited to check for a few conditions
    3. loc_3F768:
    4.     cmpa.w    #MainCharacter,a0
    5.     beq.s    +
    6.     tst.w    (Two_player_mode).w
    7.     beq.s    return_3F78A
    8. +
    9.     cmpi.b #$27,anim(a0)            ; is Sonic drilling?
    10.     bne.w   +                                   ; if not, branch
    11.     move.b    #4,routine(a1)
    12.     move.w    a0,parent(a1)
    13.     rts
    14. +
    15.     cmpi.b    #2,anim(a0)
    16.     bne.s    return_3F78A
    17.     btst    #7,status(a0)                ; was Jump Dash flag set?
    18.     bne.s   HomingMonitorBounce     ; if yes, branch
    19.     neg.w    y_vel(a0)                   ; reverse Sonic's y-motion
    20. +
    21.     move.b    #4,routine(a1)
    22.     move.w    a0,parent(a1)
    23.  
    24. return_3F78A:
    25.     rts
    26.  
    27. HomingMonitorBounce:
    28.     jsr     EnemyHomingBounce
    29.     move.b    #4,routine(a1)
    30.     move.w    a0,parent(a1)
    31.     rts

    Edit: I figured it out, not only did I need to edit the above subroutine, I also needed to make a change to SolidObject_Monitor_Sonic

    Code (Text):
    1. SolidObject_Monitor_Sonic:
    2.     btst    d6,status(a0)
    3.     bne.s    loc_12782
    4.     cmpi.b #$27,anim(a1)     ; is Sonic drilling?
    5.     bne.w   +                            ; if not, branch
    6.     rts
    7. +
    8.     cmpi.b    #2,anim(a1)     ; is Sonic spinning?
    9.     bne.w    loc_199F0         ; if not, branch
    10.     rts
    Yet another question, how can I make new objects collidable with enemies?
     
    Last edited: May 9, 2020