don't click here

Basic Questions & Answers thread

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

  1. Felik

    Felik

    Member
    1,845
    78
    28
    Thank you!
     
  2. GT Koopa

    GT Koopa

    Member
    2,021
    18
    18
    Elgin, IL
    Flicky Turncoat DX, T.L.W.S. Vs M.G.W.
    I have always wanted to do serious custom zones in sonic 2, but something that stopped me was custom music. I could never get the S2 Clone Driver to work. So I try out the new tutorial and it turns out it isn't compatible with the 2007 disassembly version, the one I am used to. So I once again download the latest S2 disassembly, and got reminded why I disliked it so much:

    [​IMG]

    Pluses instead of the generic location labels. Can somebody please tell me how ALL this works? I assume the more pluses in a redirect command the more downwards you go. If you want to go up, do you use a minus (-)? Why was it changed to this?
     
  3. FraGag

    FraGag

    Tech Member
    A + or a - in label position defines a "nameless temporary label", as the AS User Manual calls them. You can reference them by using up to 3 + or - signs. One + means the next + label, two means the second next + label; one - means the previous - label, etc. Also, you can use / to define a label that can be accessed in both directions.

    I remember changing many labels to these many years ago, as I thought I couldn't give meaningful names to those labels (or I was just lazy), and I admit I went a bit crazy with it. Also, I now realize it's dangerous when you want to add code between a nameless temporary label and its references and you use nameless temporary labels, because suddenly some references point elsewhere without warning (unless you happen to encounter an out-of-range error).
     
  4. Caverns 4

    Caverns 4

    Member
    346
    0
    16
    Sonic: Retold
    The "+"'s are as FraGag said, essentially a local label. using a branch to '+' just means "branch to the next plus", branching to '++' means "branch to the plus after next", and finally, '+++' means jump ahead three pluses. One or two pluses can be more useful than a couple of extra named labels since it can be hard to create unique names for so many needed labels, but I'll admit that +++'s are bit excessive.

    As you asked, a '+' means going down, and a '-' means going up, and the same logic with a '-' applies as with a plus.

    Also, as demonstrated with SingleObjLoad, if you want a location to be a '+' and a '-' simultaneously, you can use '/' as a bi label.

    Hope that clears things up.
     
  5. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    To elaborate more on labels in AS and their usage patterns in disasemblies: you have 4 kinds of labels:
    • normal labels: global labels that can be referenced from anywhere in the program; they must be globally unique. An awful lot of times, they end up with generic and useless names such as label_91FA.
    • nameless temporaries: the plusses, minuses and slashes. They are mostly used in the S2 disassembly; at times, they are more readable than generic labels, but their overuse can made pieces of code less readable. They can also break if you add or remove code and are not careful; and the only warning you could potentlally get in this case is an out-of-range branch. They only work well with normal labels and other nameless temporaries, in and across macros.
    • named temporaries: labels starting with a $ exist only until they cross another type of label. They are most used in the S&K disassembly, and is the closest in idea (but not in workings) to ASM68K's labels starting with an @. In practice, they don't work well for referencing backwards (despite AS's manual using these as examples), and they don't work well in or across macros. They work only with normal labels and other named temporaries... sometimes. A good temporary label name can enhance readability in more cases than the nameless temporaries, but since named temporaries are so buggy, they aren't as useful as they could.
    • composed "temporaries": labels starting with a period. The nearest non-dotted label above is prepended to all those labels, meaning they work like ASM68K's @ labels; but unlike those, they can be accessed from anywhere in the program (by using the "full" name). When used consistently, they can be used in or across macros without problems; they work best when mixed with normal labels or other composed temporaries. They are most used in... my generic error debugger screen, and nowhere else publicly available. A well selected composed "temporary" label can enhance readability in more cases than nameless temporaries, and composed "temporaries" work a lot better (currently) than named temporaries.
    I, for one, would like to see composed "temporaries" used more often and the others less often; this would be a huge undertaking, to be sure, but I can see only benefits here. Especially if their few bugs are fixed, and FraGag's assembler (whenever it is released) has a bug-free implementation of them (or an equivalent).
     
  6. MainMemory

    MainMemory

    Kate the Wolf Tech Member
    4,735
    334
    63
    SonLVL
    My port of the Sonic 1 disassembly to AS uses composed labels in place of all previously local labels, because of the buggy nature of AS' temporary labels.
     
  7. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    That is good to know, yes; I haven't had time yet to look over that branch, but it has gained some points (in my estimation) sight-unseen because of that [​IMG]
     
  8. Jimmy Hedgehog

    Jimmy Hedgehog

    Member
    1,728
    8
    18
    England - Slough
    Getting the motivation to continue old projects
    Random question that doesn't warrant its own topic, has there been any hacking/disassemblies done for some of the lesser-liked Game Gear games, like Labyrinth? Doubt I'll do anything with the information, I'm just curious.
     
  9. Clownacy

    Clownacy

    Tech Member
    1,053
    581
    93
    While looking through 68K SMPS, I keep seeing this:

    Code (ASM):
    1.     addq.w  #4,sp   ; Tamper with return value to not return to caller
    2.     rts
    I'm still unsure of certain areas of the Program Counter and this here is one of them. What does forcing this do? If the rts pops a longword from the Stack to the PC, but the Stack's been offset to read the longword before the usual one, how does this never result in the garbage data being written to the PC? My only guess is that this expects for there to be two consecutive 'return addresses' in the Stack, so...

    Code (ASM):
    1.     jsr (Branch1).l
    2.     nop
    3.     nop
    4. Branch1:
    5.     jsr (Branch2).l
    6.     nop
    7.     nop
    8. Branch2:
    9.     addq.w  #4,sp
    10.     rts
    ...would result in the rts setting the PC, not to the address after jsr (Branch2).l, but the one after jsr (Branch1).l, due to the skipping of the second return address. Looking at an instance under S1's @locdblret (loc_721B6), the Stack-skipping would cause the jsr to Sound_ChkValue to not be returned to, but the jsr to UpdateMusic (sub_71B4C). Making it so that if @locdblret is ever reached, the driver will stop processing until the next V-Int.

    Is that the function, and if so, is there any practical use to this besides being a way to temporarily change a jsr (second of two) into a jmp?
     
  10. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    405
    63
    Japan
    The practical use comes from what's outside the call instructions, in other words, you need to look at it from a further distance, I.e. "why" did they skip a return address? "why" did they want to return to the second from previous call? It's that answer that can explain the purpose.

    The best example I can show you, is by using the spindash, I say this because you'll likely be familiar with it.

    Code (Text):
    1. Obj01_MdNormal:
    2.     bsr.w   Sonic_CheckSpindash
    3.     bsr.w   Sonic_Jump
    4.     bsr.w   Sonic_SlopeResist
    5.     bsr.w   Sonic_Move
    6.     bsr.w   Sonic_Roll
    7.     bsr.w   Sonic_LevelBound
    8.     jsr ObjectMove
    9.     bsr.w   AnglePos
    10.     bsr.w   Sonic_SlopeRepel
    For the record, ObjectMove takes the speed values, and adds them to the positions correctly. The spindash subroutine actively puts news speeds into Sonic/Tails as it is being charged, the problem with doing that though is the subroutine "ObjectMove" will take the speed and start moving Sonic, before the player has had the chance to fully charge, or even release the spindash. The jump subroutine will read that buttons A, B or C are being pressed and will activate the jumping mechanism. The rolling subroutine will detect down is being held and that there is speed, resulting in a moving standard roll, the other routines may also cause problems when the spindash is attempting to be charged. So you don't want these routines ran, unless the spindash is not charging.

    Within the spindash routine, you'll find:

    Code (Text):
    1.     addq.l  #4,sp
    ...in the two places where the charge is functional, this will ensure that once the spindash subroutine has done what it needs to do to charge, when it returns, all of the subroutines afterwards never get the chance to run, and never get the chance to interrupt the spindash in any way. Instead, the subroutine will return to the previous call, which was here:

    Code (Text):
    1.     move.b  status(a0),d0
    2.     andi.w  #6,d0   ; %0000 %0110
    3.     move.w  Obj01_Modes(pc,d0.w),d1
    4.     jsr Obj01_Modes(pc,d1.w)    ; run Sonic's movement control code
    5. +
    6.     cmpi.w  #-$100,(Camera_Min_Y_pos).w ; is vertical wrapping enabled?
    7.     bne.s   +               ; if not, branch
    For the sound driver of course, one purpose you'll find may sit here:

    Code (Text):
    1. loc_71CE0:
    2.         jsr sub_71D9E(pc)
    3.         jsr sub_71DC6(pc)
    4.         bra.w   loc_71E24
    The last routine there "loc_71E24" sends the FM frequency to the YM2612, however, should a situation occur where the frequency doesn't need updating, any one of those two subroutine above it, can advance the stack to remove the return address, to prevent the update of the FM frequency (For example, if the frequency hasn't changed since the last time it was sent).

    Other reasons may include data you push into the stack to store away, but have no use to reload again (for example, the subroutine comes to a situation, where you don't need that data you put into the stack after all), regardless of whether or not you need that data again, you still need the stack position to be where it was at before you pushed data into it:

    Code (Text):
    1.         move.w  #$0123,-(sp)
    2.         pea ($0020).w,-(sp)
    3.  
    4.         ...some code here...
    5.  
    6.         ...turns out in this situation, the data in the stack was not needed.
    7.  
    8.         addi.w  #$000C,sp
    9.         rts
     
  11. Clownacy

    Clownacy

    Tech Member
    1,053
    581
    93
    Thanks, that makes sense.

    I've been trying to expand my version of Vladikcomper's Optimising Z80 Stops guide in my Clone Driver's topic. He says that the stops are redundant and that's why they're removed. Inside V_ (and H_)Int in Sonic 2, the Z80 is stopped for DMA transfers, the relay of information to S2's Z80 Sound Driver, and Joypad Input-related code. Now, ignoring DMA transfers, the Z80 has to be stopped so that the 68K can interact with addresses that are inside the Z80's memory space ($A00000-$A0FFFF).

    I can understand this with things such as the YM2612's registers, which are around $A04000, and S2's driver input, which is around $A01B80, but JoypadInit and ReadJoypads have the Z80 stopped before being branched to, even though the addresses they seemingly have the Z80 stopped for, HW_Port_1_Data, HW_Port_2_Data, HW_Port_1_Control, HW_Port_2_Control, and HW_Expansion_Control, they're all $A10003+, beyond they address space that the Z80 restricts access to! I understand that there are some stops that are correct and required, I've left them be. But Vlad's guide only went through S1's V_Blank, which contains branches to, and Z80 stops for, ReadJoypads, so he indirectly removed the stops for them also, though he never mentioned them, only talking about DMA transfers, so they may have been unintentional. In S1, all branches to ReadJoypads are inside the same blocks of code between Z80stops and starts as DMA transfers, while in S2, there's one instance where the Z80 is stopped and started only for a branch to ReadJoypads, this is under VintSub14.

    This is my current understanding of the situation, so... are all of these stops really that redundant and erroneous? Or did I get the Z80's memory space wrong? I can't test on hardware, and though Regen claims that there's no problem in removing those stops, I doubt its accuracy, so I can't test this myself.
     
  12. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    405
    63
    Japan
    That would be correct, when accessing the I/O section of the hardware, you do not need to halt the Z80. These Z80 halts when accessing the I/O space, or attempting DMA transfers where requested by SEGA, and documented in their manual. Naturally, the programmers had to abide by those rules, they were paid to after all, even though it is completely unnecessary. The only time you really need to halt the Z80 is when accessing the Z80's memory space A00000 to A0FFFF (Z80 0000 - FFFF).
     
  13. AkumaYin

    AkumaYin

    Member
    286
    6
    18
    Hi, I need help with something. For testing purposes, I'm trying to make a cheat code that gives Sonic all Chaos Emeralds by pressing C at the title screen in Sonic 1. The whole pressing the button and playing the Chaos Emerald sound works, but every time I go to the ending sequence, it shows the normal ending, probably because I'm not telling it to set the flag correctly. Help would be appreciated. [​IMG]
     
  14. Clownacy

    Clownacy

    Tech Member
    1,053
    581
    93
    v_emeralds needs to equal 6 for the good ending to trigger. There's a check for this just above the End_LoadData label, this one affects what layout is loaded (more/no flowers), and there's another under ESon_Main, which determines Sonic's and others' behaviour during the ending (releasing the Chaos Emeralds).

    Going by this, your cheat should just be move.b #6,(v_emeralds).w. Do note that PlayLevel actually clears v_emeralds when it's processed. That code is called when you press start on the title screen, and by the Level Select when you choose a level. A solution would be to have your cheat not only set v_emeralds to 6, but to also set a separate flag. This flag is checked just before PlayLevel tries to clear v_emeralds, and if that flag is set (the cheat's enabled), that line of code is skipped over, so it doesn't clear v_emeralds.
     
  15. Felik

    Felik

    Member
    1,845
    78
    28
    Guys can you tell me please at which speed Sonic and other characters can run/roll on water in hydrocity act 2? Maybe I'm just blind but physics guide doesn't seem to cover that.
     
  16. Aerosol

    Aerosol

    Not here. Moderator
    11,163
    573
    93
    Not where I want to be.
    Sonic (?): Coming summer of 2055...?
    You could probably figure it out yourself with a little math and proper usage of the frame advance feature.
     
  17. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    405
    63
    Japan
    I'd say 7 pixels minimum movement, I say this because upon running a spindash across the water and letting Sonic slow down, it isn't until the speed drops to below 0x07.00 that the splash sprites disappear and he starts falling into the water. Please note, I used readings from RAM to find this info rather than the disassembly, so it may be inaccurate.
     
  18. Hitaxas

    Hitaxas

    Retro 80's themed Twitch streamer ( on hiatus) Member
    Speaking of running on water, where is that located in the asm file? I want to remove it as I'm looking to mess around with S3K a little.
     
  19. Shockwave

    Shockwave

    Member
    26
    0
    1
    LA, CA
    Sonic: South Island Warped
    Check under Obj_HCZWaterSplash. Specifically, loc_384B2. Everything, or at least most of everything pertaining to water running should be there.
     
  20. Hitaxas

    Hitaxas

    Retro 80's themed Twitch streamer ( on hiatus) Member
    What I did find was this line: move.b #1,($FFFFB19E).w, commenting that out actually removes running on water.

    It appears it's also handled by Obj_HCZWaterSplash, but the above ram address isn't called for anywhere in the code at all, so how does it also handle running on water?

    Any insight into this would be interesting.

    Edit: sub_3857E seems to be the part that checks for a player's x_vel, putting an rts at the beginning of this code prevents running on water. Very close to figuring this out. :)