don't click here

Basic Questions & Answers thread

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

  1. OrionNavattan

    OrionNavattan

    Tech Member
    166
    164
    43
    Oregon
    I made use of the unused demo recorder by doing something like this. Note that I used SRAM to record the inputs, since I couldn't find a free area of RAM large enough to record all the inputs without overflowing.

    Code (ASM):
    1.  
    2. MoveSonicInDemo:
    3. tst.w (v_demo_mode).w ; is demo mode on?
    4. bne.s MDemo_On ; if yes, branch
    5. ;rts ;  delete this rts, causing this subroutine to carry straight into the demo recorder
    6.  
    7. DemoRecorder:
    8. lea ($200001).l,a1 ; record to SRAM, be sure to enable SRAM support in the header if you do this
    9. move.w (v_demo_input_counter).w,d0 ; get number of inputs so far
    10.  
     
    Last edited: Jan 27, 2023
  2. That might be a tad too intense for me right now, still waiting for my programmer brother to begin teaching me code, so do we have a list of what all the values are for each button input and the formula to tell how long it will be held?
     
  3. nineko

    nineko

    I am the Holy Cat Tech Member
    6,308
    486
    63
    italy
  4. Devon

    Devon

    I'm a loser, baby, so why don't you kill me? Tech Member
    1,248
    1,419
    93
    your mom
    Because, it's over 12 years old and not exactly the easiest to find. It's not even on the hacking utilities wiki page, or in any other easy to access central area for finding tools that I know of. You have to specifically search for it on the forums, and if you don't even know that it exists, then that's kinda a problem.
     
    Last edited: Jan 28, 2023
  5. Alright, grabbed it and I'll try to figure it out later. Working on a different thing atm.
     
  6. DeltaWooloo

    DeltaWooloo

    Be a boss-man and come to my big and tall man shop Member
    Is there any guide/tutorial that teaches me how palette cycling work under Sonic 1's engine? I have slightly learned how palette cycling works however I'm having a hard time playing around with the code and understanding how it worked. In this case, I'm trying to set one palette cycle for the background and the other for the foreground. I can show you an example of what I'm trying to do.
     
    Last edited: Jan 30, 2023
  7. OrionNavattan

    OrionNavattan

    Tech Member
    166
    164
    43
    Oregon
    I'm a little hesitant to answer given that I've barely looked at this myself, but it sounds like you want to have two palette cycles running independently of each other (that is, on separate timers)?
     
  8. DeltaWooloo

    DeltaWooloo

    Be a boss-man and come to my big and tall man shop Member
    Basically, yeah, what you said; I mainly want to have the background and foreground run different palette cycles. I know you have to separate the palettes lines and use different colours separately so they don't conflict but I'd rather investigate and see if there's a suitable alternative or a viable solution/workaround to this that'll definitely benefit me and engage my knowledge into a new skill that should be helpful in the foreseeable future.
     
  9. OrionNavattan

    OrionNavattan

    Tech Member
    166
    164
    43
    Oregon
    The palette cycle code for Sonic 2's MTZ is probably worth a look (three separate cycles running on independent timers).
    Code (ASM):
    1.  
    2. ; Code from Orion's Sonic 2 disassembly.
    3. ; PalCycle_MTZ in Sonic 2 AS
    4. PCycle_MTZ:  
    5.        subq.w   #1,(v_palcycle_time).w           ; deincrement timer 1
    6.        bpl.s   .cycle2                   ; if time remains, branch    
    7.        move.w   #$11,(v_palcycle_time).w       ; reset timer to 17 frames
    8.        lea   (Pal_MTZCyc1).l,a0
    9.        move.w   (v_palcycle_num).w,d0           ; get cycle number
    10.        addq.w   #2,(v_palcycle_num).w           ; increment cycle number
    11.        cmpi.w   #$C,(v_palcycle_num).w           ; is it greater than 10?
    12.        bcs.s   .no_reset1               ; if not, branch
    13.        move.w   #0,(v_palcycle_num).w           ; reset cycle number
    14.  
    15.    .no_reset1:            
    16.        lea   (v_pal_dry_line3+(5*2)).w,a1       ; 3rd line, 5 colors in
    17.        move.w   (a0,d0.w),(a1)               ; copy one color
    18.  
    19.    .cycle2:            
    20.        subq.w   #1,(v_palcycle_time2).w           ; deincrement timer 2
    21.        bpl.s   .cycle3                   ; if time remains, branch
    22.        move.w   #2,(v_palcycle_time2).w           ; reset timer to 2 frames
    23.        lea   (Pal_MTZCyc2).l,a0
    24.        move.w   (v_palcycle_num2).w,d0           ; get cycle number    
    25.        addq.w   #2,(v_palcycle_num2).w           ; increment cycle number
    26.        cmpi.w   #6,(v_palcycle_num2).w           ; is it greater than 6?
    27.        bcs.s   .no_reset2               ; if not, branch
    28.        move.w   #0,(v_palcycle_num2).w           ; reset cycle number
    29.  
    30.    .no_reset2:            
    31.        lea   (v_pal_dry_line3+(1*2)).w,a1       ; 3rd line, 1 color in
    32.        move.l   (a0,d0.w),(a1)+               ; copy two colors
    33.        move.w   4(a0,d0.w),(a1)               ; copy one more color
    34.  
    35.    .cycle3:            
    36.        subq.w   #1,(v_palcycle_time3).w           ; deincrement timer 3
    37.        bpl.s   .exit                   ; if time remains, exit
    38.        move.w   #9,(v_palcycle_time3).w           ; reset timer to 9 frames
    39.        lea   (Pal_MTZCyc3).l,a0
    40.        move.w   (v_palcycle_num3).w,d0           ; get cycle number
    41.        addq.w   #2,(v_palcycle_num3).w           ; increment cycle number
    42.        cmpi.w   #$14,(v_palcycle_num3).w       ; is it greater than 20?
    43.        bcs.s   .no_reset3               ; if not, branch
    44.        move.w   #0,(v_palcycle_num3).w           ; reset cycle number
    45.  
    46.    .no_reset3:            
    47.        lea   (v_pal_dry_line3+(15*2)).w,a1       ; 3rd line, 15 colors in
    48.        move.w   (a0,d0.w),(a1)               ; copy one color
    49.  
    50.  
     
    Last edited: Jan 31, 2023
  10. Felik

    Felik

    Member
    1,857
    82
    28
    I'm sorry in advance if this is the wrong place to ask my question but is there a finished Sonic Mania mod that restores OG palettes in Enore mode?
    I really love Encore mode's freedom to swap characters at will but I absolutely hate like 70% of the "reimagined" palettes.
    Google gives me a bunch of unfinished/abandoned mods to choose from.
     
  11. Can someone pleas explain how the hell the conveyer platforms in Labyrinth Zone work lol? Also SonLVL help for this is appreciated, but I understand if that should be moved to that topic
     
  12. Devon

    Devon

    I'm a loser, baby, so why don't you kill me? Tech Member
    1,248
    1,419
    93
    your mom
    The conveyor belt platform object utilizes its subtype value to determine which set of platforms to spawn in. To do that, you would place the object around the area where the platforms should spawn, and set its subtype to $80 + ID. ID 0 would pick "lz1pf1", 1 would pick "lz1pf2", etc. The index for these are located in the stage object layout index.

    The actual platform spawn data starts off with a word value that represents the number of platforms to spawn minus 1 (because of the dbf instruction). After that is the information for each platform to spawn. Each entry holds 3 word values: its X position, its Y position, and another subtype value. We'll touch upon that soon.

    [​IMG]
    [​IMG]
    [​IMG]

    Now, this particular subtype value actually indicates which path ID and which path node the platform starts moving towards. This subtype is calculated with (Path ID * $10) + Path node ID.

    The actual path data is located at "LCon_Data", after the object code. It uses the path ID to pick which entry in the index table to use. As for the data, it starts off with a word that represents the size of the path data in bytes (excluding this and the next word). The next word represents the "center X position" of the path. Usually, this is the same value as the the X position of the platform object spawner placed in the stage layout. This value helps with determining when to despawn the platforms.

    After that are the positions of the nodes. Each node takes 2 words, an X and Y position, and this is what the path node ID refers to. A platform will move towards whatever specific node it is assigned to, and then advance to the next one.

    [​IMG]
    [​IMG]
    [​IMG]
    [​IMG]

    So, let's use the data I've shown here to build everything up. Let's start with the nodes. The path has $18 bytes of path data, which means there are 6 nodes (6 * 4 bytes = $18), and the path's center X position is $1070:
    • ($1078, $21A)
    • ($10BE, $260)
    • ($10BE, $393)
    • ($108C, $3C5)
    • ($1022, $390)
    • ($1022, $244)
    [​IMG]

    Now, let's take a look at the platform spawn data as shown above. There are 8 platforms:
    • ($1078, $21A), Path 0 Node 0 ($00)
    • ($10BE, $291), Path 0 Node 2 ($02)
    • ($10BE, $307), Path 0 Node 2 ($02)
    • ($10BE, $37E), Path 0 Node 2 ($02)
    • ($105C, $390), Path 0 Node 4 ($04)
    • ($1022, $352), Path 0 Node 5 ($05)
    • ($1022, $2DB), Path 0 Node 5 ($05)
    • ($1022, $265), Path 0 Node 5 ($05)
    [​IMG]

    And yeah, fun fact, this particular set of platform spawn coordinates has a misplaced platform.

    [​IMG]

    It's hard to notice because you enter this area from above, and the platform will quickly move towards its designated node and continue on the path. I digress, though.

    In SonLVL, you can place the spawner, and set its subtype to pick which set of platforms to spawn in. Notice how the spawner's X position is the same as the path's center X position.

    [​IMG]

    Also, the wheels use the same object ID as the platform spawner, but its subtype is set to $7F. There is a special check for that subtype in the code. Unfortunately, it doesn't seem like you can directly edit the path data or platform spawn positions. You had to do that manually.

    One more thing: if you have a wider path, you might need to place multiple spawners with the same subtype across it to prevent premature despawning, due to the way object despawning offscreen works. Act 3 does this, for instance:

    [​IMG]
    [​IMG]

    The code also specifically checks if it is in act 3 to account for this in the despawn check code.

    And you might ask "wouldn't that spawn double the platforms?" The answer is that it checks if a platform group of a specific subtype ID is already spawned in via a flag in RAM, and if it is, it will delete itself, preventing duplicates.

    The Scrap Bran Zone spinning conveyor belt platforms work the same way, with the path data located at "off_164A6".
     
  13. So the paths themselves have to be edited in code. Fun. That's beyond the parameters of the challenge I set for myself, so new conveyor belts are out of the question I guess. Also, do the X coordinates of the scripted path and the spawner have to match? Would that explain why they won't spawn in the level no matter where I try to add a new one?
     
  14. Devon

    Devon

    I'm a loser, baby, so why don't you kill me? Tech Member
    1,248
    1,419
    93
    your mom
    Every coordinate is absolute, not relative, so no matter where you place the spawner, it will always place the platforms in the designated coordinates in the data. The path's center X position doesn't necessarily have to match the spawner's X position, really, but that's just how they handled it.
     
  15. MainMemory

    MainMemory

    Kate the Wolf Tech Member
    4,742
    338
    63
    SonLVL
    I'd love to enable path editing in SonLVL, but I can't come up with a way to handle it.
     
  16. I’ve been trying to run FW-KENSC on my computer to Compress a chunk file with Kosinski Compression (the version outputted by SonLVL ended up being too large by 90 bytes; it should be exactly 11,888 bytes), yet I simply can’t seem to be able to run it.
    I’ve tried compatibility options and tried dragging the binary file onto the executable to run it, and no luck. Is there anything I’m missing? For reference, I’m running Windows 10 on my PC.
     
    Last edited: Feb 11, 2023
  17. MainMemory

    MainMemory

    Kate the Wolf Tech Member
    4,742
    338
    63
    SonLVL
    It's a command line program, you'd have to run it through the Command Prompt and give it appropriate options so it knows what to do.
    Or, you can install the shell extension for something a bit easier to use.
     
  18. Cokie

    Cokie

    C. Okie Member
    76
    22
    8
    Sonic The Hedgehog 1's FindNearestTile starts with below code. Want to make sure Im correctly understading this.

    First: The lsr.w #2 and andi.w #$380 get the row offset of the line the object is in level layout data. This is becuase each line is 0x80 bytes in the level layout (0x40 bytes for FG and 0x40 bytes for BG), half of the height of an actual line / row that is drawn which is 256 pixels. So the object's Y rounded down to the nearest 0x80 bytes ( down to the start address of that line's foreground data in level layout ) gets it's row offset?

    I am explaining this really really bad, and apologize for that. Would someone please put it in clearer words as I feel i am missing terminology proper, and perhaps concepts.

    What would be calculated if you did not and 0x380 ... would it yield nothing relavent. Do all steps in a calculation have individual purpose that isolated have a meaning or are some algorithm / processes of the nature where one step mean nothing without entirety of all steps? Also I assume and with 0x380 is because 0x380 is the start offset for the foreground data of the 8th and final line?

    Second: Assume the x step of lsr 8 , and 0x7F get the column / chunk that the object is in , and this is added to offset? Again how would I properly says this? How would I properly say that this column position is added to the level's layouts line / row base address to get the address of the chunk in the level layout that the object is in? I think a few concepts are missing, Also why AND with 0x7F?

    Level
    0xA400 - A43F

    0xA480 - 0XA4BF

    , half of the actuall height of each line which is 256 pixels.
    So the object's
    position divided by two rounded down to the 0x80 , which is the rounded down to the row base
    height is double that 256 piels. So Thus the chunk that the object
    is in, divided by two gives the
    FindNearestTile:
    move.w d2,d0 ; get y-pos. of bottom edge of object
    lsr.w #1,d0
    andi.w #$380,d0
    move.w d3,d1 ; get x-pos. of object
    lsr.w #8,d1
    andi.w #$7F,d1
    add.w d1,d0 ; combine

    Many Thanks!!!!
     
  19. Halved

    Halved

    What Member
    28
    3
    3
    Is there a way to bring back the HPZ tiles? Even if I try to put the files from the Wai disassembly (i converted the Nemesis zone art to Kosinski), it still displays a garbled mess. Also, is it because of the pattern load order that the emerald, bridge, etc appear garbled? (I also put the correct art file and added the BINCLUDE's) In certain places the art works fine but at some places it doesn't. Here's the current PlrList:
    Code (Text):
    1. PlrList_Hpz1: plrlistheader
    2.     plreq ArtTile_ArtNem_HPZ_Bridge, ArtNem_HPZ_Bridge
    3.     plreq ArtTile_ArtNem_HPZ_Waterfall, ArtNem_HPZ_Waterfall
    4.     plreq ArtTile_ArtNem_HPZPlatform, ArtNem_HPZPlatform
    5.     plreq ArtTile_ArtNem_HPZOrb, ArtNem_HPZOrb
    6.     plreq ArtTile_ArtNem_HPZ_Emerald, ArtNem_HPZ_Emerald
    7.     plreq ArtTile_ArtNem_WaterSurface, ArtNem_WaterSurface
    8. PlrList_Hpz1_End
    The only thing working fine currently is the WaterSurface. This is the order from the Wai disassembly by the way.
    Here's also some screenshots: https://imgur.com/a/1BrLkx2
     
    Last edited: Feb 12, 2023
  20. Nik Pi

    Nik Pi

    Member
    482
    303
    63
    Kazakhstan
    Sonic 2: Archives
    Hum..
    Have you inserted maps for chunks or blocks?
    As I know- bloks' mappings are uncompressed in SW disasm so it can be the reason