don't click here

Basic Questions & Answers thread

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

  1. Kyuu

    Kyuu

    Memory Access Violation Member
    Okay, I feel like I'm missing something really obvious here, but no matter how hard I look, I can't tell what.

    I've pored over the fall-curl routine and compared it to code in the original game that checks Sonic's status, and I can't tell what's wrong. I tried coding a double-jump subroutine (comparing it to S3&K's lightning shield double-jump routine) in a similar manner, but still no dice.

    [68k]Sonic_DoubleJump:
    tst.b DoubleJump(a0) ; is Sonic already double-jumping?
    beq.s @return ; if yes, branch
    btst #2,obStatus(a0) ; is Sonic spinning?
    beq.s @return ; if not, branch
    btst #1,obStatus(a0) ; is Sonic airborne?
    beq.s @return ; if not, branch
    [...]

    Sonic_FallCurl:
    btst #1,(v_player+obStatus).w ; is Sonic airborne?
    beq.s @return ; if not, branch
    cmpi.b #id_Roll,obAnim(a0) ; is Sonic already rolling?
    beq.s @return ; if yes, branch
    btst #bitDn,(v_jpadpress2).w ; is down pressed?
    bne.s @return ; if yes, branch[/68k]

    Is this the wrong way to check Sonic's status in S1? Is there something in the code, whether it's mine or somewhere else, that would cause these routines to constantly branch even if the status in question is set? I really can't tell what the problem is here. :(
     
  2. Clownacy

    Clownacy

    Tech Member
    1,149
    823
    93
    Isn't the DoubleJump(a0) check backwards? It should be a non-zero when Sonic's double jumping.
     
  3. Kyuu

    Kyuu

    Memory Access Violation Member
    Whoops, I didn't even realize that. :specialed:

    Even then, though, the code doesn't work. I'm sorry for posting basically the same thing over and over again, but this is seriously doing my head in.

    [68k];---------------------------------------------------------------------------
    ; Subroutine to allow the player to curl into a ball in midair
    ;---------------------------------------------------------------------------
    ;||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||

    Sonic_FallCurl:
    btst #1,(v_player+obStatus).w ; is Sonic airborne?
    beq.s @return ; if not, branch
    cmpi.b #id_Roll,obAnim(a0) ; is Sonic already rolling?
    beq.s @return ; if yes, branch
    btst #bitDn,(v_jpadpress2).w ; is down pressed?
    bne.s @return ; if yes, branch
    @curl:
    bset #2,obStatus(a0) ; set sonic's status to rolling
    move.b #$E,obHeight(a0) ; set sonic's height
    move.b #7,obWidth(a0) ; set sonic's width
    move.b #id_Roll,obAnim(a0) ; use "rolling" animation
    addq.w #5,obY(a0) ; add #5 to sonic's y position
    sfx sfx_Roll,0,0,0 ; play rolling sound
    @return:
    rts ; return to routine
    ; End of subroutine Sonic_FallCurl[/68k]

    [68k]; ---------------------------------------------------------------------------
    ; Subroutine to allow Sonic to double-jump
    ;---------------------------------------------------------------------------
    ;||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||

    Sonic_DoubleJump:
    tst.b DoubleJump(a0) ; is Sonic already double-jumping?
    bne.s @return ; if yes, branch
    btst #2,obStatus(a0) ; is Sonic spinning?
    beq.s @return ; if not, branch
    btst #1,obStatus(a0) ; is Sonic airborne?
    beq.s @return ; if not, branch
    move.b (v_jpadpress2).w,d0 ; load joypad data into d0
    andi.b #$70,d0 ; have A/B/C been pressed?
    beq.s @return ; if not, branch
    @dbljmp:
    move.b #1,DoubleJump(a0) ; set double-jump flag
    move.w #-$580,obVelY(a0) ; subtract $580 from sonic's velocity to bounce upwards
    sfx sfx_Jump,0,0,0 ; play jumping sound
    @return:
    rts ; return[/68k]

    Is there something wrong with how I'm checking Sonic's status in either of these routines? From cocking about with the first one, I'm more or less certain that's where the problem is. They're both branched to in the code, and I've included both of the .asm files in the ROM. I just... can't get either of them to work properly.
     
  4. Kyuu

    Kyuu

    Memory Access Violation Member
    herp derp double post
    I've actually stumbled upon an even faster solution, courtesy of SSRG (I think, my memory's awful). Split the frame ID's out of Sonic's mappings file (I've got another file called "Sonic Frame Constants.asm" which is include'd in the main .asm file), then find where both Sonic's mappings and DPLC files are included. Move the appropriate label above the include, like so:

    [68k]Map_Sonic:
    include "_maps\Sonic.asm"
    SonicDynPLC:
    include "_maps\Sonic - Dynamic Gfx script.asm"[/68k]

    This way, you can just save the SME output over the files themselves and the ROM will still build fine (though I'd recommend backing it up before trying that either way, of course). :)

    On that note, I've finally solved what was wrong with my fall-curl/double-jump routines. Sort of. I'm still not sure why this change made them work, but it did, so I'm not complaining :v:

    Replacing the branch to "locret_134C2" in Sonic_JumpHeight with a branch to the double-jump subroutine made it work (after I made sure to clear the double-jump flag when Sonic lands on the ground :specialed: ), and a bsr to the fall-curl routine in Sonic_MdJump made that work. Both of these came from comparing what I was doing to the S3&K disassembly. Fun times :v:
     
  5. AURORA☆FIELDS

    AURORA☆FIELDS

    The cute one here Tech Member
    216
    24
    18
    Finland
    AMPS
    Sonic_MdJump and Sonic_MdJump2 in fact control Sonic's movement when he is jumping and rolljumping respectively, so bsring any code to be executed during a jump or rolljump is rather helpful in fact.
     
  6. Kyuu

    Kyuu

    Memory Access Violation Member
    That's definitely something I'm going to keep in mind for the future, if just to avoid shenanigans like this :v:

    On that note, one last unrelated question then I'll disappear for a while again - I'm trying to free up VRAM space by making the shield and invincibility stars use DPLCs like Sonic and the spin-dash dust do. The SCHG page for Sonic 1 says this:


    Problem? Comparing this to Sonic's DPLC script, I can't understand what the hell's going on. I can tell that the first byte is the number of "pieces" in the sprite and that the third byte is where the first tiles used in the sprite appear, which makes sense, but I'm extremely confused as to what the second value means. Here are the standing frame and first waiting frame's DPLCs as-is, for reference.

    [68k]SME_owWdr_FF: dc.b 4, $20, 0, $30, 3, $50, 7, $20, $D
    SME_owWdr_108: dc.b 2, $B0, $10, $20, $1C[/68k]

    Unless I'm misunderstanding something majorly here, the higher nybble of $20 would be 0010, wouldn't it? The thing is, that's equal to $2, while Sonic's standing frame uses 16 tiles. Having said that, though, the first waiting frame uses 11 tiles, which - again, if I'm not mistaken - is equal to the higher nybble of $B0, and coincides with what the SCHG says.

    That also doesn't help me understand what's up with some of the other DPLCs:

    [68k]SME_owWdr_10D: dc.b 5, 0, $1F, $10, $20, $50, $22, $10, $28, $30, $2A
    SME_owWdr_118: dc.b 5, 0, $1F, $10, $20, $50, $22, $10, $28, $30, $2E
    SME_owWdr_123: dc.b 5, 0, $1F, $50, $22, $10, $28, $30, $2E, $10, $32
    SME_owWdr_12E: dc.b 5, 0, $1F, $10, $20, $10, $28, $10, $22, $70, $34[/68k]

    If it's not too much trouble, could someone explain the format here so even an idiot like me can understand? Thanks.

    EDIT: where did all these size tags come from
     
  7. MainMemory

    MainMemory

    Kate the Wolf Tech Member
    4,802
    388
    63
    SonLVL
    SonMapEd sets the DPLCs up so that each sprite piece has a separate DPLC entry. There are four DPLC entries in the standing frame, so we can assume that the sprite is made of four pieces. The first entry loads 3 tiles from offset 0, the second loads 4 tiles from offset 3, the third loads 6 tiles from offset 7, and the last loads 3 tiles from offset $D. 3+4+6+3=16.
    It is possible to optimize DPLCs of 16 tiles or less into one entry, but SonMapEd can't load that properly because it's really dumb. Flex (and any of my tools) can read such things just fine though.
     
  8. AURORA☆FIELDS

    AURORA☆FIELDS

    The cute one here Tech Member
    216
    24
    18
    Finland
    AMPS
    Code (Text):
    1. SME_owWdr_10D:
    2.     dc.b 5
    3.     dc.w $001F, $1020, $5022, $1028, $302A
    SonMapEd outputs DPLC in a single line with incorrect format visually, rather than making an actual representation of what it should look like. There I took one of your example lines and made it look like it truly should, and as you may figure the result is already way more readable. However using this you can probably figure out a pattern as to how you can read the DPLC from SonMapEd's ugly output
     
  9. MainMemory

    MainMemory

    Kate the Wolf Tech Member
    4,802
    388
    63
    SonLVL
    If you want something readable, my sprite mappings macros might help, as they split DPLCs into length/source pairs like this. The only problem with that is that neither SonMapEd nor Flex can read mappings/dplcs like this, so you'd have to convert them back and forth. Presumably you have some plans for editing by hand though, if you're so interested in the format, and any tools using SonLVL's API can use the macros just fine.
     
  10. Kyuu

    Kyuu

    Memory Access Violation Member
    Ahhh, I see how things work now. Thanks, both of you! :)
     
  11. Clownacy

    Clownacy

    Tech Member
    1,149
    823
    93
    Maybe I'm going mad, but isn't SST $23 unused for Sonic and Tails? I've noticed Sonic_RecordPos backing it up as part of a move.w operation on status (SST $22), which S3K replaces with a move.b and a backup of art_tile, but I can't find anything indicating $23 is used in any other way.

    EDIT: Wow, I really should've mentioned I was talking about Sonic 2.
     
  12. AURORA☆FIELDS

    AURORA☆FIELDS

    The cute one here Tech Member
    216
    24
    18
    Finland
    AMPS
    Sonic 1 does definitely not use it and from quickly glancing over XenoWhirl 2007 disassembly neither seems Sonic 2 using it. From looking at the code, they just likely needed to spend 4 bytes to something, so moving a word was easy solution *cough cough*
     
  13. Kyuu

    Kyuu

    Memory Access Violation Member
    Okay, god dammit, I wanted to solve this on my own, but I'm lost. Still having trouble with DPLCs and whatnot.

    Here's what my DPLC loading routine looks like:

    [68k]; ---------------------------------------------------------------------------
    ; Red Star Ring DPLC loading subroutine
    ; ---------------------------------------------------------------------------

    RSR_LoadDPLC: ; XREF: Obj01_Control; et al
    moveq #0,d0
    move.b obFrame(a0),d0 ; load frame number
    cmp.b $32(a0),d0
    beq.s locret_RSR
    move.b d0,$32(a0)
    ; this is where Sonic_LoadGFX loads Sonic's PLCs, I do that outside this routine
    add.w d0,d0
    adda.w (a2,d0.w),a2
    move.w (a2)+,d5
    subq.w #1,d5
    bmi.s locret_RSR
    move.w $3C(a0),d4
    ; this is where Sonic_LoadGFX loads Sonic's art, I do that outside this routine

    RSRDPLC_ReadEntry:
    moveq #0,d1
    move.b (a2)+,d1
    lsl.w #8,d1
    move.b (a2)+,d1
    move.w d1,d3
    lsr.w #8,d3
    andi.w #$F0,d3
    addi.w #$10,d3
    andi.w #$FFF,d1
    lsl.l #5,d1
    add.l d6,d1
    move.w d4,d2
    add.w d3,d4
    add.w d3,d4
    jsr (QueueDMATransfer).l
    dbf d5,RSRDPLC_ReadEntry ; repeat for number of entries

    locret_RSR:
    rts

    ; End of function Sonic_LoadGfx[/68k]

    Here's how art/DPLCs are loaded for the routine:

    [68k]Dust_LoadArt: ; CODE XREF: h+6EF4?j h+6F00?j ...
    move.l #Art_Dust,d6
    lea (Dust_DPLC).l,a2
    bsr.s Dust_LoadDPLC ; this is for the spindash dust specifically, which has a separate routine because I don't want to break that by mistake
    rts [/68k]

    And here's how the shield/invincibility object is set up for it:

    [68k]Shi_Main: ; Routine 0
    addq.b #2,obRoutine(a0)
    move.l #Map_Shield,obMap(a0)
    ; move.l #DPLC_Shield,obDPLC(a0) ; $3C and obDPLC are the same, I goofed when comparing code between S2 and S3K
    move.b #4,obRender(a0)
    move.b #1,obPriority(a0)
    move.b #$10,obActWid(a0)
    move.w #$540,obGfx(a0) ; vvv
    move.w #$A800,$3C(a0) ; Yes, these overwrite a tile of the spring graphics, this was me trying something out to see if it fixed anything (it didn't)
    tst.b obAnim(a0) ; is object a shield?
    bne.s @stars ; if not, branch
    rts
    [...]

    lea (Ani_Shield).l,a1
    jsr AnimateSprite
    move.l #Art_ShieldStars,d6
    lea (DPLC_Shield).l,a2
    jsr RSR_LoadDPLC
    jmp DisplaySprite[/68k]

    The problem - the shield and the red star ring don't work properly. In Regen, the game effectively crashes with an address error, and in Gens+, the game lags considerably and the shield/invincibility have garbled graphics. Despite that, some of the art does correctly get loaded into VRAM, though it loads far more than is actually used (to the point where it might as well not be using DPLCs). I think it's due to reading/writing to odd addresses, but I don't know what's causing that behaviour.

    I kinda suspected at first that it was because I'd screwed up when creating the DPLCs for the object (TIL Flex has a DPLC editor :specialed:), but fixing the shield mappings/DPLCs and testing it again didn't yield any different results. Could someone point me in the right direction here? Thanks.
     
  14. Pokepunch

    Pokepunch

    Member
    85
    0
    6
    UK
    A Sonic 2 Hack
    I advise you to take a good look at how S3&K does it, the way the shields use DPLCs in particular. The Shield routines give you everything you need, PLCLoad_Shields is the DPLC loading routine.
     
  15. Kyuu

    Kyuu

    Memory Access Violation Member
    I've done that. Modifying my code to be more similar to S3K's just causes the game to lock up on both Regen and Gens - it seems to be reading unrelated data as code, but I don't even know where it's getting the data from this time. Other than sprite priority (which isn't something I'm planning on touching just yet), the only difference between what I've got and S3K/S2's is the #tiles_to_bytes instruction, and I can't even tell what that does (or rather, how to do it manually - no, porting the macro over didn't work).

    I'm now getting a bunch of illegal instruction and line 1010/1111 errors, but I can't pin down the locations of the addresses.
     
  16. MainMemory

    MainMemory

    Kate the Wolf Tech Member
    4,802
    388
    63
    SonLVL
    The tiles_to_bytes function multiplies the argument by $20 (32), the size of a 4bpp 8x8 tile in bytes.
     
  17. E-122-Psi

    E-122-Psi

    Member
    2,536
    729
    93
    Okay I'm new to placing sound files from other games into Sonic 1 (specifically S3+K). Is it as simple as the one in the spin dash tutorial, or do they need to be reprogrammed and such?
     
  18. AURORA☆FIELDS

    AURORA☆FIELDS

    The cute one here Tech Member
    216
    24
    18
    Finland
    AMPS
    They need to be converted, first from Z80 to 68k format (afaik its just a byteswap), and then from SMPS Z80/SMPS Z80 S3K to SMPS 68k, which I am not sure how to do. However as sound effects are different than music, normal SMPS converting tools wont work.
     
  19. Kyuu

    Kyuu

    Memory Access Violation Member
    Okay, I finally got my DPLCs and whatnot working. There are still some bugs to work out - the shield and stars are still slightly garbled, and the first frame of the shield is loading more tiles than it uses - and the star ring object is still very broken, but I've finally got the ROM running properly in both Gens+ and Regen.

    Turns out, the problem was something to do with the DPLCs and mappings. Flex loaded them perfectly fine and everything looked to be in order, but SonMapED wouldn't accept them. I went and edited a backup of the files by hand until everything looked right in SME, and then things started working in-game. No wonder I couldn't find anything wrong with the DPLC loading routines, there wasn't anything wrong there in the first place! :v: (nothing fatally wrong, at least)
     
  20. Campbellsonic

    Campbellsonic

    Member
    19
    0
    1
    I'm trying to port Sonic's sprites from S3K to Sonic 1. I'm familiar with SonMapEd and have been using it to edit mappings, and I figured porting Sonic's sprites would be as simple as loading Sonic's art, mappings, and DPLCs from S3K and exporting them in Sonic 1 format, but that's where I was horribly wrong. The majority of Sonic's sprites are completely garbled in-game, however some of them are still assembled properly. Looking into the mappings files, there doesn't seem to be anything structured differently between the original ones and the S3k-ported ones, leading me to believe the trouble lies within the DPLCs. The problem there is that I have no idea what I'm looking at when I open those up. So... Can anybody point me in the right direction?