Basic Questions & Answers thread

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

  1. Alriightyman

    Alriightyman

    I am back... from the dead! Tech Member
    354
    3
    18
    Largo, FL
    0101001101101111011011100110100101100011 00000010: 0101001100000011 01000101011001000110100101110100011010010110111101101110
    1. I have not tested this, but I would assume going to
    Code (Text):
    1.  
    2. ; sub_4BD2:
    3. SetLevelEndType:
    4.  
    would solve your issue. It checks which acts should have a signpost and which should not.

    2. I am not sure about this though.
     
  2. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    9
    18
    United Kingdom
    YouTuber


    This is a weird one. "MarkObjGone" (or "gone2") screams at this object. I had a look and it seems that when Sonic is on the lift, if Tails is far away, it will delete itself. And vice-versa.


    Although, MarkObjGone is useless in 2player. If it's 2 player, it will just branch to displaysprite instead. There's only one branch to markobjgone in this object, and there's nothing else in the code to suggest that it's deleting itself.

    Although, it seems to me, once the lift has started moving, once it's reached a certain distance from its original starting location, it will delete itself. Seems to me the x_pos isn't updating itself? Yet, it moves?

    x_pos is moved to objoff_30(a0) when the object is created, but unsure why, because it seems like it's never read again. I also took it out and nothing about the object changed. A real mystery on this one (with my knowledge anyway) =P
     
  3. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,153
    38
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    Ever since Markey posted his guide, I have been toying with doing just that. I can do the perfect fade you want, but at a cost in terms of RAM -- so far, the best I got needs two full bytes per channel (R, G, B) per palette entry to do the fade. This much RAM is easily available in S2, but not in S1 or S3&K.
     
  4. RetroKoH

    RetroKoH

    Member
    1,661
    17
    18
    Project Sonic 8x16
    If you can get some kind of solution... could you also assist with the fade-to-white bit as well?
    And to elaborate on dsrb's post, yes... I am a hacking noob, but instead of people pointing that out, I'm hoping I could actually learn something.
     
  5. dsrb

    dsrb

    Member
    3,149
    0
    0
    Whoa, hang on – I was referring to my question and me, not you!

    flamewing, that's cool to hear; I look forward to hearing how you get on.
     
  6. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,153
    38
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    The theory behind it is simple -- one has to do a linear regression in each channel. The original did this, but did each channel in sequence; Markey's code does the same, but in parallel -- but he does not account for the different rates that each channel should use, and this is the problem. The root of the issue is the fact that we are dealing with integers, and fractions are needed in most cases.

    One way to deal with this is as follows. Please note that this is not the complete code or tutorial -- it is a general description of how it goes.

    Pre-initialization code, part 1: this is run for each palette entry, and depends on the type of fade:
    To fade from black or to fade to white:
    Code (Text):
    1. moveq   #0,d0
    2. moveq   #0,d1
    3. moveq   #0,d2
    4. move.w  #$200,d0    ; Increase blue channel
    5. move.w  #$020,d1    ; Increase green channel
    6. move.w  #$002,d2    ; Increase red channel
    7. swap    d0
    8. swap    d1
    9. swap    d2
    To fade to black or to fade from white:
    Code (Text):
    1. moveq   #0,d0
    2. moveq   #0,d1
    3. moveq   #0,d2
    4. move.w  #-$200,d0   ; Decrease blue channel
    5. move.w  #-$020,d1   ; Decrease green channel
    6. move.w  #-$002,d2   ; Decrease red channel
    7. swap    d0
    8. swap    d1
    9. swap    d2
    What this does is this: the high word of the registers is how much to add to the color each time a channel needs to be updated. The low word will be filled in the next step:

    Pre-initialization code, part 2: this is run for each palette entry, and depends on the type of fade:
    To fade from black or to fade to black:
    Code (Text):
    1. move.b  (a0),d0
    2. move.w  (a0)+,d2
    3. move.b  d2,d1
    4. lsr.w   #4,d1
    5. andi.w  #$E,d2
    To fade to white or to fade from white:
    Code (Text):
    1. move.w  #$00E,d0
    2. move.w  #$0EE,d2
    3. sub.b   (a0),d0
    4. sub.w   (a0)+,d2
    5. move.b  d2,d1
    6. lsr.w   #4,d1
    7. andi.w  #$E,d2
    This splits the starting and final colors into channels and puts the absolute value of (final value - starting value) as the low word of the corresponding channel. The pre-initialization being done, time now to initialize the color channels for the raycasting:
    Code (Text):
    1. ; Start by sorting the colors so that d0 is the brightest component and d2
    2. ; is the darkest component. We do this with a bubble sort:
    3. cmp.b   d2,d1
    4. bcc.s   +
    5. exg.l   d1,d2   ; Keep the channel's color delta attached to the value change
    6. +
    7. cmp.b   d2,d0
    8. bcc.s   +
    9. exg.l   d0,d2   ; Keep the channel's color delta attached to the value change
    10. +
    11. cmp.b   d1,d0
    12. bcc.s   +
    13. exg.l   d0,d1   ; Keep the channel's color delta attached to the value change
    14. +
    15. ; Now d0 is the maximum delta, d1 is the middle delta and d2 is the minimum
    16. ; delta, and the high word of these registers are the value to add when it
    17. ; is necessary to change that color.
    18.  
    19. ; Make d3 high word = 2 * color, d3 low word = 2 * color - 2 * max color,
    20. ; and low word of d1 = 2 * color - max color (integer linear regression):
    21. add.w   d1,d1
    22. move.w  d1,d3
    23. swap    d3
    24. sub.w   d0,d1
    25. move.w  d1,d3
    26. sub.w   d0,d3
    27. ; Make d4 high word = 2 * color, d4 low word = 2 * color - 2 * max color,
    28. ; and low word of d2 = 2 * color - max color (integer linear regression):
    29. add.w   d2,d2
    30. move.w  d2,d4
    31. swap    d4
    32. sub.w   d0,d2
    33. move.w  d2,d4
    34. sub.w   d0,d4
    35. ; Convert low word of d0 into a counter -- the number of steps that we have
    36. ; to increment the highest delta to reach target (for use with dbcc).
    37. lsr.w   #1,d0
    38. subq.w  #1,d0
    At this point, we have all the information needed to do a perfect fade of the 3 channels of a single color. These values need to be stored somewhere, for all colors; specifically, d0, d1, d2, d3 and d4 need to go to RAM; all of this for each color to be faded.

    The fade itself is simple: assuming that d0, d1, d2, d3 and d4 are loaded with the same values above, and that the address of the current color being processed is at a0, then:
    Code (Text):
    1.     move.w  (a0),d5 ; Fetch color
    2.     swap    d0
    3.     add.w   d0,d5   ; The main channel is always updated
    4.     swap    d0
    5.     tst.w   d1      ; Do we need to update the middle channel?
    6.     bpl.s   +       ; Branch if yes
    7.     swap    d3
    8.     add.w   d3,d1   ; Increment counter
    9.     swap    d3
    10.     bra.s   ++
    11. +
    12.     swap    d1
    13.     add.w   d1,d5   ; Update middle channel
    14.     swap    d1
    15.     add.w   d3,d1
    16. +
    17.     tst.w   d2      ; Do we need to update the low channel?
    18.     bpl.s   +
    19.     swap    d4
    20.     add.w   d4,d2   ; Increment counter
    21.     swap    d4
    22.     bra.s   ++
    23. +
    24.     swap    d2
    25.     add.w   d2,d5   ; Update low channel
    26.     swap    d2
    27.     add.w   d4,d2
    28. +
    29.     move.w  d3,(a0)+    ; Store color and move on to the next color to fade
    What this does is use integer raytracing to perform the linear regression -- the major dimension is always updated, the minor dimensions are updated less often. The above is the RAM-intensive version of the fader: it takes 4 bytes for the faster channel, 8 bytes for each of the slower ones. This is the basis of the technique that can be used to make a CPU-intensive version instead -- which uses less RAM, but not the 2 bytes per channel I incorrectly claimed above (memory fail), but 4 bytes per channel.

    Of course, I now have just thought of a ROM-intensive version which could theoretically use the mythical 2 bytes per channel by making use of lookup tables. I will look a bit into it, and post again if I have anything.
     
  7. E-122-Psi

    E-122-Psi

    Member
    2,132
    329
    63
    Another toughie, I have a character move in S3 uses has a control lock. I noticed that when using this move in Competition Mode before a race starts, the countdown keeps restarting (if I alter the move to never end, it stops altogether, implying the control lock is involved). Is there any reason why the countdown reacts this way and to get round it?
     
  8. Tets

    Tets

    one rude dude Oldbie
    837
    9
    18
    So with all the recent Sonic 2 ASM bug fixes and guides put out recently, I decided to get back into the hacking thing. I followed redhotsonic's "free two universal SSTs" and "port the S3K priority manager" guides, both of which seemed to go smoothly, but I later found several things had gone wrong during the process. I'm not posting this in either of the respective threads as I'm not convinced it's a fault in the guides, rather I think it's human error. Part of it I imagine is that I had to adapt a lot of the SST guide as it was created with the 2007 disassembly in mind, and I must have got some things wrong (I'm working with the latest repository version).

    What's going wrong is some of the bosses freeze the game (EHZ and ARZ, but probably more) and the special stage controls are all fucked up (can't really describe how, it's unpredictable at best). I do have a backup of s2.asm, so in the event that I simply can't figure out what's going wrong I can easily revert, but both guides involved a lot of busywork that I'd rather not repeat if I can avoid it.

    The upside is that after all the code optimizations, I was able to implement the water ripple effect in ARZ and CPZ with little to no noticeable lag, and there are still a few more optimizations I have yet to do.
     
  9. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    9
    18
    United Kingdom
    YouTuber
    Both guides are from me, oh shit =P

    Special stages controls going wrong, I cannot explain. That shouldn't happen at all. Boss freezes? That's more than likely a priority error.


    Can you post in the priority manager porting topic and tell us what bosses freezes and when it happens (I'm guessing ARZ boss freezes instantly)? That way, if it is a bug with the guide, we can fix it in that topic, making everyone aware of it who has applied the manager to their hack.


    As for the SST guide, did you follow part 1, or part 2, or both? If you want the Priority manager in your hack, then part 2 from the SST guide is the only relevant one.

    redhotsonic
     
  10. MoDule

    MoDule

    Tech Member
    323
    5
    18
    Procrastinating from writing bug-fix guides
    I'm pretty sure this happens, because in 2p mode object deletion is handled by the objects manager instead of the objects themselves, from what I understand. Apparently it's doing it wrong for the HTZ lifts, most likely because they move very far horizontally. Mind, this is just speculation.
    As for how to fix it, other than replacing the objects manager with a new one, I wouldn't know. With the changes I made to the s3k objects manager (so far unreleased, I think) it definitely works.
     
  11. Azu

    Azu

    I must be stupid. Member
    I'm not sure if this belongs here, but are there any level maps for Sonic 3D Blast?
     
  12. Thorn

    Thorn

    Tech Member
    334
    14
    18
    Home
    Sonic 2 Retro Remix
    ^ Yes.

    Also, try playing a non-Genesis version for very simplistic maps on the pause screen.
     
  13. E-122-Psi

    E-122-Psi

    Member
    2,132
    329
    63
    Cool might edit it in if you release it. Anything else work differently in 2P mode with the new objects manager?
     
  14. E-122-Psi

    E-122-Psi

    Member
    2,132
    329
    63
    Does anyone know how to edit Sonic and Knuckles' speed/acceleration stats separately in the S3K disassembly? There seems to be a character speeds section near the bottom, but when I edit it, nothing seems to change. Other coding seems to be labelled for both characters.
     
  15. Overlord

    Overlord

    Now playable in Smash Bros Ultimate Moderator
    18,344
    423
    63
    Berkshire, England
    Learning Cymraeg
    Regen glitch discussion has been moved here on request: http://forums.sonicretro.org/index.php?showtopic=29219
     
  16. theocas

    theocas

    Tech Member
    346
    0
    16
    So I've been wondering for quite a while on how to get objects to go in a circle, so I dedicated last night to figuring it out and just wanted to share that with you guys. (Didn't feel like it was worth being a new topic, but if a mod feels that is the case then split it please.)

    The way it works is by applying a simple Trigonometry concept called the "Unit Circle." By calculating the sine and cosine of a specific angle, you can get the X and Y values for a point on a circle at that angle. (That's how it was explained to me — there's probably better explanations out there.) The Sonic engine happens to coincidentally have a routine that'll calculate a sine and cosine, albeit only with 256 angle values, however this isn't real problematic. It actually lifts the data from a LUT for optimisation purposes.

    We can obviously use this method to make an object (or anything else you may choose to) go in a circle. To do that, we'll first need to look at how the Sonic engine does it's sine and cosine calculation. Here's the routine from Sonic 1, commented by me:

    Code (ASM):
    1.  
    2. CalcSine:               ; XREF: SS_BGAnimate; et al
    3.         andi.w  #$FF, d0                                    ; Get lower byte
    4.         add.w   d0, d0                                      ; Multiply by 2
    5.         addi.w  #$80, d0                                    ; Add 128
    6.         move.w  Sine_Data(pc, d0.w), d1                             ; Get value out of table (Cosine value)
    7.         subi.w  #$80, d0                                    ; Subtract 128
    8.         move.w  Sine_Data(pc, d0.w), d0                             ; Get another value out of the table (Sine Value)
    9.         rts
    10. ; End of function CalcSine
    11.  
    12. ; ===========================================================================
    13.  
    14. Sine_Data:  incbin  misc\sinewave.bin                               ; values for a 360° sine wave
    Like I said above, this routine uses a byte as the angle offset, but due to the Mega Drive's limited screen size, if you're displaying anything with this sine data it shouldn't be too noticeable. Now, as with the concept of the Unit Circle I explained above, we can simply add the sine and cosine value to the X and Y values of the object, respectively to make it go clockwise (reverse it to make it go counterclockwise!) But if you were to simply add those to SST $8 and $C, the object wouldn't stay in one place. To fix that, you have to back up the object's X and Y positions up to another space in it's SST entry when it's loaded, like so:

    Code (ASM):
    1.  
    2.         move.w  $8(a0), $30(a0)                                 ; Back up X
    3.         move.w  $C(a0), $32(a0)                                 ; Back up Y
    Now, instead of adding the output of the CalcSine function to the SST's X and Y positions, you restore the backed up positions to registers and add them, then write the values of those registers to the X and Y position. That's all dandy, but you may notice the object not on screen or making a huge circle. Reason for that is that CalcSine outputs signed word values. To make these values work a bit better with object rotation, we can shift them to the right to divide them, like so:

    Code (ASM):
    1.  
    2.         move.b  $29(a0), d0                                 ; Get the angle to d0
    3.         move.w  $30(a0), d6                                 ; Write backed up X to d6
    4.         move.w  $32(a0), d5                                 ; Write backed up Y to d5
    5.        
    6.         moveq   #2, d2                                      ; Shift offset (written to register to reduce memory fetches for instruction)
    7.        
    8.         jsr CalcSine                                    ; Get sine and cosine (d0, d1)
    9.        
    10.         asr.w   d2, d0                                      ; Shift the sine value
    11.         asr.w   d2, d1                                      ; Shift the cosine value
    12.        
    13.         add.w   d0, d6                                      ; Add sine to X
    14.         add.w   d1, d5                                      ; Cosine to Y
    15.  
    16.         move.w  d6, $8(a0)                                  ; Set X
    17.         move.w  d5, $C(a0)                                  ; Set Y
    18.  
    As a rule of thumb, each shift is a division of two. So, shifting by two bits will divide the sine by four, shifting three by eight, four by 16, and so on. Note the use of asr, as this keeps the signage of the number intact. If you were to use lsr, you would only get about a fourth of a circle. Also note if you don't want the number to be shifted, you can remove the ars's and the moveq above the jump to CalcSine. Here's a few pictures illustrating the different shift values:

    Shift right 1 bit:
    [​IMG]

    Shift right 2 bits:
    [​IMG]

    Shift right 3 bits:
    [​IMG]

    Shift right 4 bits:
    [​IMG]

    Those are five different sprites, each with a different value added to the angle each frame to give the impression of them moving in a nice circle. Hopefully this information helps someone out there =P
     
  17. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    9
    18
    United Kingdom
    YouTuber
    Your answer accidently got moved to the Regen topic here. Incase, here is the posts:







     
  18. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,153
    38
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    Took me a while to find out what was going on (being forced to get off my lazy arse helps...); check this post.
     
  19. RetroKoH

    RetroKoH

    Member
    1,661
    17
    18
    Project Sonic 8x16
    I am trying to edit S3K tiles with Triad, and am running into quite the issue. Many sprites, in particular ALMOST everything in the General/Sprites/ folder have this issue.

    When I try to edit a compressed file from this folder, (Let's use the Monkey Dude.bin for an example) Obviously it has to be decompressed first. - Unless I'm mistaken, it is Nemesis compressed...

    I decompress it, and everything in the tile is set to 0. I tried this with Triad, SonMapEd, The KENS Data Compression Tool importing the sprite into SonLVL's object definition... the problem is with the file, after I decompress it, is completely 0.

    I don't know why... Nothing in Sonic 1 or 2 does this, and some of the files in S3K don't do this.

    I'm sorry if this doesn't warrant its own topic, but I have a feeling that this is an error with files in the disassembly or something... and thought it would warrant a topic if that is the case. PLEASE correct me if I am wrong.

    NOTE: all files in the game appear as they should, as other than decompressing, I didn't edit anything.

    Any thoughts?
     
  20. MainMemory

    MainMemory

    Kate the Wolf Tech Member
    4,552
    146
    43
    SonLVL
    It and presumably those other files are Moduled Kosinski compressed.