Basic Questions & Answers thread

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

  1. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    9
    18
    United Kingdom
    YouTuber
    You've said you've ported the layer deformation over from S2Beta, but have you made sure that the index is actually pointing to it? I'm guessing you have, but thought I'd ask. You've made sure the RAM addresses all equal their equivalents but does the data/address registers also equal their equivalents? No doubt they changed it arounda bit from Sonic 1 to Sonic 2. I'm not sure on this so take this with a pinch of salt, but worth checking.

    Camera_X_pos_coarse, just means it's checking how far away the object is from the camera sides. Most objects branch to a subroutine (MarkObjgone in Sonic 2), that checks every frame if the object is pretty much too far away and if so, delete itself, otherwise, display it.

    Code (ASM):
    1.     move.w  x_pos(a0),d0
    2.     andi.w  #$FF80,d0
    3.     sub.w   (Camera_X_pos_coarse).w,d0
    4.     cmpi.w  #$280,d0            ; Is it too far away from (or off) the screen?
    5.     bhi.w   +               ; If so, delete the object, no longer needed
    6.     bra.w   DisplaySprite           ; It's still close by; display it
    7. +
    I don't think that wil lexplain why your objects are displaying right though...
     
  2. Kyuu

    Kyuu

    Memory Access Violation Member
    Yeah, the index is loading HPZ's deform data. Other than the blocks overwriting each other/whatever happens to the lower part of the background while it's offscreen, it does actually scroll the same way as it does in S2B. Looking at the routine again, I think the address registers might be responsible - Sonic 2 sets a whole bunch of addresses and such that Sonic 1 doesn't even have in some cases (as in 2-player stuff). I'm going to experiment with this a bit more and see if I can figure it out...

    As for the waterfall, I've figured out what was wrong - The object subtype in debug was spawning what was effectively a "0-height" waterfall, so it was just creating the splash object. OOPS :specialed:

    On that note though, question related to sprite priority - in Sonic 2, it's possible to have sprites appear over the level's high plane (as the HPZ waterfall does, for instance). Is there a way to do this in Sonic 1?
     
  3. FireRat

    FireRat

    Nah. Fuck it. Misfit
    48
    9
    8
    Chile
    Mobius Evolution 2
    Bit $F from object art's VRAM location needs to be set.
    If you have something like move.w #$3A0,2(a0), change it to move.w #$83A0,2(a0).
     
  4. Kyuu

    Kyuu

    Memory Access Violation Member
    I was just about to post saying I'd figured it out, oops :v: Thanks though! :)

    EDIT: Okay, I've been dicking about with the HPZ Deform routine to see if I can figure out what's going wrong in it, and I'm still not sure how to fix it. Having said that, I think I've figured out where the problem is - it's something to do with how Sonic 1 scrolls background tiles that are offscreen.

    I'm not certain if that's all there is to it, because even when it's on-screen the upper part of the background has issues relating to overwriting tiles. Making progress, at any rate.
     
  5. RetroKoH

    RetroKoH

    Member
    1,661
    17
    18
    Project Sonic 8x16
    Got a quick question regarding monitors. I've been working on a mod for Sonic 1 REV C, that would allow me to have other characters without interfering with palettes and such... so far, it's been more or less a success. But I'm having an issue with the Monitor, more or less the Eggman monitor in particular. When the monitor is broken, we know that the powerup icon is given the first piece of the mapping as its sprite, which is its icon. HOWEVER, This doesn't work for me, as you can likely guess with my mappings for the Eggman monitor below:

    Code (Text):
    1.  
    2.  
    3. @eggman:    spriteHeader
    4.     spritePiece -8, -$B, 1, 2, $3C, 0, 0, 0, 0 ; Overlay to preserve skin color
    5.     spritePiece 0, -$B, 1, 2, $3C, 1, 0, 0, 0 ; Overlay to preserve skin color
    6.     spritePiece -8, -$B, 2, 2, $18, 0, 0, 1, 0
    7.     spritePiece -$10, -$11, 4, 4, 0, 0, 0, 1, 0
    8. @eggman_End
    9.  

    The overlays are needed to help the monitor retain its proper color, as I have MOST of the monitor pieces using line 1, where the skin color is not present... instead of line 0. Now, using the normal code, when the Eggman monitor is broken, the sprite that appears is NOT the whole of the icon, rather it is half of the overlay (the first piece). I've tried to remedy this with the following modification:

    Code (Text):
    1.  
    2.  
    3.         move.b  anim(a0),d0 ; get subtype
    4.         cmpi.b  #1,d0      ; is it the Eggman monitor?
    5.         bne.s   @noteggman ; if not, branch
    6.         move.l  #Map_EggIcon,mappings(a0) [size=2]; Add new mappings, to accomodate for overlay with Eggman monitor[/size]
    7.         move.b  #0,mapping_frame(a0)
    8.         rts
    9.     @noteggman:
    10.                 addq.b  #2,d0
    11.         move.b  d0,mapping_frame(a0)    ; use correct frame
    12.                 movea.l #Map_Monitor,a1
    13.         add.b   d0,d0
    14.         adda.w  (a1,d0.w),a1
    15.         addq.w  #1,a1
    16.         move.l  a1,mappings(a0)
    17.  

    The above snippet is at the start of the powerup icon code, and checks if it is the Eggman monitor, and if so, goes to new mappings specifically for the icon, which look like so:

    Code (Text):
    1.  
    2.  
    3. Map_EggIcon:    mappingsTable
    4.     mappingsTableEntry.w    @eggmanicon
    5.  
    6. @eggmanicon:    spriteHeader
    7.     spritePiece -8, -$B, 1, 2, $3C, 0, 0, 0, 0 ; Overlay
    8.     spritePiece 0, -$B, 1, 2, $3C, 1, 0, 0, 0 ; Overlay
    9.     spritePiece -8, -$B, 2, 2, $18, 0, 0, 1, 0
    10. @eggmanicon_End
    11.  
    Now, instead of getting my monitor icon, I get a garbled mess (ONLY for Eggman... other monitors are fine). I believe there is something wrong with how I implemented the code, itself... but I could be wrong. Other than the garbled icon mess, everything else behaves the exact same, with no issues. If screenshots are necessary, I'll post when I return.
     
  6. MainMemory

    MainMemory

    Kate the Wolf Tech Member
    4,548
    142
    43
    SonLVL
    You need to clear bit 5 in the render flags, which tells BuildSprites to read a single sprite piece.
     
  7. RetroKoH

    RetroKoH

    Member
    1,661
    17
    18
    Project Sonic 8x16
    Much thanks, MainMemory! Works like a charm. I'll take some time to look more into what exactly the render flags do, to be better prepared for next time.
     
  8. Clownacy

    Clownacy

    Tech Member
    837
    79
    28
    I have a question regarding Sonic 1's sound driver again. Recently, I've been going over the handful of 'S1 driver to S2' guides, and found a strange theme: PlaySoundStereo is changed to be PlayMusic.

    My studies of the GitHub S1 disassembly show that an equivalent to SFX_to_play2 does exist, but using it in S2 has a heck of a bizarre effect: It literally queues to play WITH the NEXT sound effect. Say you pick up a ring, you hear nothing. Then you jump, and only then do both the jump sound and the ring sound play. This has been giving me hell for whole hours on a project I've been working on, and after fixing it using a method that only seems to break things further, all I can say is "Why? Oh god, why?!"

    It works just fine in Sonic 1, just look at PlaySound_Special:

    Code (ASM):
    1. PlaySound_Special:
    2.         move.b  d0,(v_snddriver_ram+v_playsnd2).w
    3.         rts

    Look, it uses playsnd2/SFX_to_play2! I honestly can't imagine this being a problem with the driver itself, as I've ported the Clone Driver and an unchanged S1 driver and still had this problem, so my only guess is that it has to do with the s2.asm side of things such as the branch to Init_Sonic1_Sound_Driver, which is actually UpdateMusic.

    I'd investigate this specific area further, as I've just made the connection while writing this, and am pretty damn sure this is where the problem lies, seriously, there has to be a missing branch to a differently-named "UpdateSFX" in there somewhere, that'd explain the queuing bug, but I'm at my end here; the last thing I want to do is sift through that S1 disassembly looking for a routine or reference that I might not even recognise. I'm more so hoping some of you have immediate knowledge on this. Sorry for the ranting, but this has had me pulling my hair out!


    EDIT: I didn't think me looking would make things worse, but it did:

    SO, according to the macros, in Sonic 1, music uses PlaySound (v_playsnd1), sfx use PlaySound_Special (v_playsnd2). Bosses use PlaySound to restore Zone music. The signpost uses PlaySound_Special to play the Level Cleared theme. The water countdown uses PlaySound to play the drowning theme. This is a mess.

    Looking at this, music (and special sounds) is queued to v_playsnd1 through PlayMusic, normal sounds are queued to v_playsnd2 through PlaySound.

    So either I'm losing my mind, or this is finally starting to make sense.

    This is why bad labelling is bad! Every single guide based on it keeps that now-inaccurate label and I've just pissed away so much time trying to figure it out! PlayMusic is PlaySound, PlaySound is PlaySound_Special, PlaySound Special is PlayMusic- AAH! (It also doesn't help that the S1 disasm is in so many pieces I just though its PlayMusic was elsewhere. It never crossed my mind that it was PlaySound)

    Okay, I suppose now's as good a time as any to spill the beans: I'm working on something to make this problem a thing of the past. I'm also going to bring that darn guide up to date, any objections?
     
  9. ValleyBell

    ValleyBell

    Tech Member
    243
    14
    18
    researching SMPS sound drivers
    Let's have a look at the sound queue slots from Sonic 1: (SVN/GitHub disassembly, locations are relative to 68k RAM F000)
    Code (Text):
    1. v_playsnd0: = $009  ; sound or music copied from below
    2. v_playsnd1: = $00A  ; sound or music to play
    3. v_playsnd2: = $00B  ; special sound to play
    4. v_playnull: = $00C  ; unused sound to play
    5.  
    And now let us compare that with the slots from Sonic 2 (2007 disassembly, the SVN one doesn't list memory locations)
    Code (Text):
    1. Music_to_play =         ramaddr( $FFFFFFE0 )
    2. SFX_to_play =           ramaddr( $FFFFFFE1 ) ; normal
    3. SFX_to_play_2 =         ramaddr( $FFFFFFE2 ) ; alternating stereo
    4. Music_to_play_2 =       ramaddr( $FFFFFFE4 ) ; alternate (higher priority?) slot
    5.  
    Although you might think that the number of slots is the same, there is a small difference.

    In Sonic 1, you're not supposed to use v_playsnd0, because it's actually not part of the queue and is overwritten with the contents of the queue. Also, v_playnull is actually a semi-broken v_playsnd3.
    So without modifications, you have 2 slots. (Both can be used for music and SFX, btw.)

    In Sonic 2, you actually have two sound queues - one in the 68k RAM and one in the Z80 RAM.
    The one in Z80 RAM works similar to Sonic 1's queue, but has the bug with the third slot fixed and makes sure to not overwrite its v_playsnd0 (called zQueueToPlay there), but that's not important for us.
    The queue located in 68k RAM uses the memory locations listed above and copies them to Z80 RAM once per frame.
    SFX_to_play 1 and 2 are copied to v_playsnd1 (zSFXToPlay) and v_playsnd2 (zSFXStereoToPlay) respectively as you would expect it, but both Music_to_play values are written to v_playsnd0. (The first non-null value is used.)

    So when porting the Sonic 1 driver to Sonic 2, you need to reduce the sound queue from 2x music + 2x sound effect to 2x (music or sound effect)
    The guide makes music and special SFX to go one slot and normal SFX to another to reduce the risk of overwriting a queued sound ID.

    If you wonder why these calls are so random, you need to know something and keep that in mind:
    There is no difference between music and sound ID except for the actual value. For the sound driver, everything is the same, no matter if you use PlaySound, PlayMusic or PlaySound_Special.
    (That means you can play music by calling PlaySound and play SFX by calling PlaySound and that will work as well as using the "correct" calls.)


    Btw, that queue bug is a bug in the sound driver.
    Code (Text):
    1. @skipfadein:    ;loc_71BB2
    2.         tst.w   v_playsnd1(a6)      ; is a music or sound queued for played?
    3.         beq.s   @nosndinput ; if not, branch
    4.         jsr Sound_Play(pc)
    5.  
    6. @nosndinput:    ;loc_71BBC
    7.         cmpi.b  #$80,v_playsnd0(a6) ; is song queue set for silence?
    8.         beq.s   @nonewsound ; If yes, branch
    9.         jsr Sound_ChkValue(pc)
    10.  
    That tst.w checks, if the sound queue is empty or not. This checks v_playsnd1 and v_playsnd2, but not v_playnull. Change it to tst.l (which is what Shinobi 3 does, btw) and you will be able to use the third slot normally.
    (also, Sound_Play should actually be "DoSoundQueue" and Sound_ChkValue should be "PlaySoundID")
     
  10. Clownacy

    Clownacy

    Tech Member
    837
    79
    28
    Yikes, looks like I dug myself into a hole, here. I understand what made you think this, but I never consciously used v_playnull or v_playsnd0, though, during my rant, I was accidentally writing to v_playnull. I blame the S2 disasm's funky way of allocating RAM for that. Thanks for piecing the process together, by the time I got it working, my logic behind how it worked was a mess.

    Also, thanks a lot for the method of fixing v_playnull, I'd imagine formatting PlaySound to resemble S2's PlayMusic would allow more SFXes to be queued at once? Then again, SoundPriorities would just choose one over the other anyway. That said, would the only benefit be a bigger SFX 'pool' for SoundPriorities to pick from, in the event of many SFXes being played at a time?

    Anyhow, thanks, now my project is almost complete!

    [/rant]
     
  11. ValleyBell

    ValleyBell

    Tech Member
    243
    14
    18
    researching SMPS sound drivers
    There is a benefit in improved PlayMusic/PlaySound routines, because sound priorities work a bit differently than you might think.
    Let me explain how sound priorities work:
    You play a sound effect with priority $40, so the current priority gets set to $40.
    While this effect is still playing (doesn't have to be in the same frame), you play another one with priority $20. The queue system will ignore this one, because $20 < $40. (even if they would play on different FM or PSG channels)
    While the effect is still playing, you play another one, but with priority $45. It will play and set the current priority to $45. (because $45 >= $40)
    Now the first sound effect finishes - the sound priority will be RESET, allowing all following SFX to play. Even one with priority $20 while the one with priority $45 is still playing.
    Then everything repeats.

    Sound priorities work independently from the number of sounds in the queue. It makes no difference if you put multiple sounds in the queue within one frame or one every 5 frames.
    The only limitation is, that the driver can only load one song or sound effect per frame. So the first one that isn't ignored is processed and the rest is done during the next frame(s).
     
  12. RetroKoH

    RetroKoH

    Member
    1,661
    17
    18
    Project Sonic 8x16
    Quick question... in Sonic 3K, why THIS:


    Code (Text):
    1.  
    2.  
    3. ; =============== S U B R O U T I N E =======================================
    4.  
    5.  
    6. SetUp_ObjAttributes:
    7.         move.l  (a1)+,mappings(a0)      ; Mappings location
    8.  
    9. SetUp_ObjAttributes2:
    10.         move.w  (a1)+,art_tile(a0)      ; VRAM offset
    11.  
    12. SetUp_ObjAttributes3:
    13.         move.w  (a1)+,priority(a0)      ; Priority
    14.         move.b  (a1)+,width_pixels(a0)      ; Width
    15.         move.b  (a1)+,height_pixels(a0)     ; Height
    16.         move.b  (a1)+,mapping_frame(a0)     ; Mappings frame
    17.         move.b  (a1)+,collision_flags(a0)   ; Collision Number
    18.         bset    #2,render_flags(a0)     ; Object uses world coordinates
    19.         addq.b  #2,routine(a0)          ; Increase routine counter
    20.  
    21. locret_8405E:
    22.         rts
    23. ; End of function SetUp_ObjAttributes
    24.  
    Almost every object in S3K uses it when it is spawned... instead of the standard instructions to assign the same values, done in S1 and S2... and it has to JUMP to this subroutine, no less... WHY?
    Is there any advantage to this?
     
  13. MarkeyJester

    MarkeyJester

    A D V A N C E Resident Jester
    2,080
    211
    43
    Japan
    Saving on memory, as in, having one routine to set the values, and multiple single jumps, with a single array of the object values. You'll also save memory on objects that might use the same values.

    Functionality from a programmer's point of view might be another reason. That is to say you may find it easier to write out an array of values and load the address to a1 and call the routine, rather than writing out the list of instructions and places the values are being moved to, each and every time. But I feel this one is up for debate.
     
  14. Steelrush

    Steelrush

    Every good deed has its reward. Member
    18
    0
    1
    A humid place
    Blaze the Cat in Sonic 2
    I have a question for the other users here; does anyone know how to convert collision volumes, sprites, level layouts, level sizes, and objects from the Sonic 2 beta to Sonic 2 final? I have searched just about every site (including this one) for guides and things of the like to figure this out, but have not found anything of the sort. Nor have I found tools that can convert things these kinds of things from Sonic 2's beta to the final version of the game. I would greatly appreciate the assistance.
     
  15. MainMemory

    MainMemory

    Kate the Wolf Tech Member
    4,548
    142
    43
    SonLVL
  16. Clownacy

    Clownacy

    Tech Member
    837
    79
    28
    Level sizes are a file in S1 (misc/Level Size Array.bin), and a table in S2, S2B, and S3K as 'LevelSize', 'Level_Size_Array' and 'LevelSizes', respectively. Each act's entry is four words/two longwords long. The S2 disasm uses words for defining these, while the others (excluding S1 as it uses a bin file) uses longwords, so the '$0,'s aren't visible there. Just copy the values across, though they don't need to be changed if you keep the 'dc.l's.

    Objects are a fun challenge. The S3K shields taught me that. But they take quite a bit of explaining, and since you're stuck on the sprites, I won't dwell on this, you'll need to get that out of the way first. To sum it up, if you have the sprites added and the mappings ported, all you'd need to do is copy the code across, add a pointer to it in the Obj_Index, and add a pointer to its art (and a VRAM location) under its zone's Plr_list. Of concern are the labels that differ between disasms, just correct them and things should be good to go. To be safe, I'd equate the RAM addresses, VRAM address and priority moved to art_tile, and the SSTs and the sort, all pointed to in the object's code.
     
  17. Steelrush

    Steelrush

    Every good deed has its reward. Member
    18
    0
    1
    A humid place
    Blaze the Cat in Sonic 2
    Not just the sprites, though. My current focus right now is restoring the scrapped levels to Sonic 2 final, and the part I'm having the most trouble with is finding and getting the pointers to read the data to the lost levels. For example, I can't find what pointers Hidden Palace Zone is using for its layout and collision volumes.
     
  18. MainMemory

    MainMemory

    Kate the Wolf Tech Member
    4,548
    142
    43
    SonLVL
    I highly recommend you start with this:
    If you need help putting the data into a Sonic 2 disassembly, I can assist you.
     
  19. Clownacy

    Clownacy

    Tech Member
    837
    79
    28
    Oh, that? Take a look at LevelArtPointers. You'll find what you're looking for in terms of art, that and many other things: PLCs, palette, 16x16 mappings, 128x128 mappings.

    The collision is under Off_ColP and Off_ColS. Note that those aren't as well labelled. The line commented as "8" is HPZ. A good way for tracking this stuff down is just searching "EHZ", and seeing where it takes you. You'll find all kinds of zone-specific tables and pointers. You should be able to work from there.
     
  20. FireRat

    FireRat

    Nah. Fuck it. Misfit
    48
    9
    8
    Chile
    Mobius Evolution 2
    I have a pretty simple question... what's the ASM68k's equivalent for "narg" in AS? I'm trying to convert this macro to AS:

    Code (ASM):
    1.  
    2. locVRAM:    macro loc,controlport
    3.         if (narg=1)
    4.         move.l  #($40000000+((loc&$3FFF)<<16)+((loc&$C000)>>14)),(vdp_control_port).l
    5.         else
    6.         move.l  #($40000000+((loc&$3FFF)<<16)+((loc&$C000)>>14)),controlport
    7.         endif
    8.         endm