Basic Questions and Answers Thread

Discussion in 'Discussion & Q&A' started by Malevolence, Jul 7, 2009.

  1. Sinkdude

    Sinkdude He looked much leaner on TV Member

    Joined:
    May 6, 2008
    Messages:
    41
    Location:
    Michigan
    I'm currently reworking on the Sonic 2 ROM hack project (with a new fresh disassembly to work with) and I'm working on adding FireRat's reworked generic Sega Screen to it. I need to make sure I'm porting this right, as the code was originally prepared for Sonic 1's GIt disassembly when he wrote it and I'm translating the variables and constants to those of Sonic 2's.

    Anything you need to point out on this, let me know and I'll see what I can do.

    The code itself is under the spoiler.
    Code:
    ; ---------------------------------------------------------------------------
    ; Sega screen
    ; ---------------------------------------------------------------------------
    
    GM_Sega:
                    move.b    #MusID_Stop,d0
                bsr.w    PlayMusic ; stop music
            bsr.w    ClearPLC
            bsr.w    Pal_FadeToBlack
            lea    ($C00004).l,a6
            move.w    #$8004,(a6)
            move.w    #$8200+(VRAM_SegaScr_Plane_A_Name_Table>>10),(a6)    ; set foreground nametable address
            move.w    #$8400+(VRAM_SegaScr_Plane_B_Name_Table>>13),(a6)    ; set background nametable address
            move.w    #$8700,(a6)            ; set background colour (palette entry 0)
            move.w    #$8B00,(a6)            ; full-screen vertical scrolling
            move.w    #$8134,(a6)            ; disable display
            clr.b    (Water_fullscreen_flag).w
            move    #$2700,sr
            bsr.w    ClearScreen
            dmaFillVRAM    $20
            lea    (Nem_NewSegaLogo).l,a0        ; load Sega logo patterns on tile #1
            bsr.w    NemDec
            lea    ($FF0000).l,a1
            lea    (Eni_NewSegaLogo).l,a0        ; load Sega logo mappings
            moveq    #1,d0                ; start from tile #1
            bsr.w    EniDec
            copyTilemap    $FF0000,(vram_bg+$61E),((96/8)-1),((32/8)-1)
    
            tst.b   (Graphics_Flags).w            ; is console Japanese?
            bpl.s   NewSega_jmp0                ; if yes, branch
            dmaFillVRAM    (VRAM_SegaScr_Plane_A_Name_Table+$634),4(a6)        ; set position to write to..
            move.l    #$00310032,(a6)            ; and write "TM"
    NewSega_jmp0:        move.w    #$EEE,v_pal_dry+$02+$80
            move.w    #-2,PalCycle_Frame        ; minus size of an entry
            move.w    #1,(PalCycle_Timer).w
    
            lea    Normal_palette+$04+$80,a1
            bsr    Palcycle_Sega
            move.w    #$8174,$C00004            ; enable display
            bsr.w    PaletteFadeIn
                move.b    #SndID_SegaSound,d0
                    bsr.w    PlaySound    ; play "SEGA" sound
            move.w    #3*60,(Demo_Time_left).w        ; stay for 3 seconds
    
    NewSega_WaitEnd:
            move.b    #2,(Vint_Routine).w
            bsr.w    WaitForVint
            lea    Normal_palette+$04,a1
            bsr    Palcycle_Sega
            tst.w    (Demo_Time_left).w
            beq.s    Sega_GotoTitle
                move.b    (Ctrl_1_Press).w,d0    ; is Start button pressed?
                or.b    (Ctrl_2_Press).w,d0    ; (either player)
                andi.b    #button_start_mask,d0
            beq.s    NewSega_WaitEnd            ; if not, branch
    
    NewSega_GotoTitle:
            move.b    #GameModeID_SSRGScreen,(Game_Mode).w
            rts
    
    Palcycle_Sega:
            subq.w    #1,PalCycle_Timer
            bne.s    Palcycle_Sega_return
            move.w    #3,PalCycle_Timer
            addq.w    #2,PalCycle_Frame
            cmpi.w    #Palcycle_Sega_cycle_size,PalCycle_Frame    ; past cycle's size?
            bne.s    Palcycle_Sega_jmp0                ; if not, branch
            move.w    #0,PalCycle_Frame            ; if yes, reset
    Palcycle_Sega_jmp0:
            move.w    PalCycle_Frame,d0
            lea    Palcycle_Sega_cycle(pc,d0.w),a0
            rept    4                ; repeat next line 4 times        ; --> transfer 9 colors in total
                move.l    (a0)+,(a1)+        ; copy 2 colors and increment pointers
            endr
            move.w    (a0),(a1)            ; copy last color
    Palcycle_Sega_return:    rts
    
    Palcycle_Sega_cycle:        dc.w    $EC0
            dc.w    $EA0, $E80, $E60, $E40, $E20, $E00
            dc.w    $C00
            dc.w    $E00, $E20, $E40, $E60, $E80, $EA0
    Palcycle_Sega_cycle_end:    ; remaining half copy before loop. Making it CPU-friendly
            dc.w    $EC0
            dc.w    $EA0, $E80, $E60, $E40, $E20, $E00
            dc.w    $C00
    Palcycle_Sega_cycle_size:=    Palcycle_Sega_cycle_end-Palcycle_Sega_cycle
     
  2. DeltaWooloo

    DeltaWooloo The noob next door Member

    Joined:
    Aug 7, 2019
    Messages:
    373
    Hey there,

    Is there an easy way to port Sonic 3's elemental shields to Sonic 1 using the 2005 Hivebrain disassembly?
     
  3. Sinkdude

    Sinkdude He looked much leaner on TV Member

    Joined:
    May 6, 2008
    Messages:
    41
    Location:
    Michigan
    ProjectFM and Inferno like this.
  4. Chainspike

    Chainspike Newcomer Trialist

    Joined:
    May 9, 2017
    Messages:
    8
    Hello. I have a problem after adding vladikcomper's error handler in the Sonic 3 (alone) Github disassembly:
    [​IMG]
    I followed the steps for adding the error handler to S3K while making the relevant changes for sonic 3. The result is that the error handler does work, but gives an illegal instruction instantly upon loading the game. I know that there isn't an issue with loc_1FA6 as the game will load and play on real hardware without the error handler. The problem might be caused by Sonic 3's inability to read any data past ROM address $200000. Most emulators will ignore this but the problem persists on original hardware (Ex. levels and graphics located over this address fail to load). Part of the code for error handler is located at the end of ROM pointer (over $200000) which leads me to believe that this is the case.

    I usually don't ask questions, but I have not been able to solve this.

    EDIT: After disabling SRAM access (allowing $200000+ to read) the error handler still crashes the same way.
     
    Last edited: Jan 22, 2020
    Inferno and vladikcomper like this.
  5. penPhobic

    penPhobic Everything's all topsy-turvy now. Member

    Joined:
    Dec 11, 2016
    Messages:
    67
    Location:
    Basement
    Speaking of the error handler, I can't find it because the Dropbox link is dead. Is everybody have it?
     
  6. Inferno

    Inferno Rom Hacker Member

    Joined:
    Oct 27, 2015
    Messages:
    132
    Location:
    Sky Base Zone, South Island
    Here you go, dude, good thing I have these saved:
     

    Attached Files:

    vladikcomper, ProjectFM and penPhobic like this.
  7. Ashuro

    Ashuro Anti-Cosmic Metal Of Death Member

    Joined:
    Sep 27, 2014
    Messages:
    550
    Location:
    France
    My God... (Sighs) It's been so long since I've come here for help... I really hate coming here anymore.
    But this is a bad time.

    The question is simple: How the hell do you import music into Sonic 2????

    After spending 3 whole days searching here and on Sonic Retro if someone had my problem and was fixed but nothing. Tried to import:
    _the Sonic 2 Clone Driver v2 (abandoned after a mutlitude of unrecoverable build errors)
    Flamewing's s3K sound driver (abandoned after a mutlitude of unrecoverable build errors)
    _the Sonic 1 sound driver (abandoned after a mutlitude of unrecoverable build errors).

    Used SMPSOpt.exe + Saxman compression, or a whole bunch of "systems" like that, even if I know that it was basically a waste of time (I managed to build it anyway, but the level completely bugged, or the music made a horrible high-pitched whistle, as I remember)...

    Or to use SMPS2ASM , after these threads messages:

    There and There

    Even though I understood absolutely nothing, and I can't find any tutorials worthy of the name, anyway ... There's really nothing about it, and I'm starting to have a nice headache that tells me to stop everything and come back again after a 2 years break, like I just did... Haha.

    So please, if someone has a method and can take the time to explain to me so that I can finally get something done and go back to work in my corner quietly, it would be great.

    I already have my music ready. They work in Sonic 1 and Sonic 3K after conversion.

    On the other hand, Sonic 2 is starting to seriously disgust me to hack hahaha!
    I'm using the latest GitHub version of Sonic 2.

    Apart from that, I'd like to say hello to all of you, and happy new year, I haven't seen some of you in... well, two years now, again. It's good to be back here!
     
  8. Kurk

    Kurk Oh Yeah Member

    Joined:
    Jul 30, 2016
    Messages:
    99
    Location:
    Kurkistan
  9. Ashuro

    Ashuro Anti-Cosmic Metal Of Death Member

    Joined:
    Sep 27, 2014
    Messages:
    550
    Location:
    France
    Thank you.

    I've tried that before, but I think I'll try it again then.

    Nevertheless, SMPS2ASM seems a bit mysterious to me. Because I know that you don't just convert your .bin, you also have to edit things in it, and that's what I have a problem with, because it seems blurry to me.
     
  10. AURORA☆FIELDS

    AURORA☆FIELDS so uh yes Exiled

    Joined:
    Oct 7, 2011
    Messages:
    759
    I believe the Flamewing's SMPS2ASM should work by default in Sonic 2, so long as you add the appropriate files into your disassembly (e.g. the _smps2asm_inc.asm file, idk if anything else is needed). Additionally, you need to tell the driver to use uncompressed music correctly. I have never edited music in Sonic 2, so I am not sure if anything else is involved, but I thought that was all you'd have to do. There is also a preview version of AMPS in Sonic 2, where you can use my SMPS2ASM converter to convert Sonic 1 (called MegaPCM in the source...) format to SMPS2ASM format. There is just a problem where you have to do some manual edits to get it building in AMPS, but the document here gives you most of the steps to do it. There are few missing parts, such as having to multiply PSG volume by 8. Unfortunately, I have not finished this part of the new documentation yet. However, that is something I will be working on the following weeks actually. AMPS in Sonic 2 is still work in progress, so it is not quite ready for a proper release and may still suffer from issues. Of course, if you have previously edited custom music already in, well, you will have to convert it all to AMPS format as well. Unfortunately there is not yet a solution for this.

    I unfortunately can't really recommend tools to fix it for any other drivers, since I rarely work with them. I am extremely familiar with AMPS related tools but not much else.
     
    ProjectFM and Ashuro like this.
  11. vladikcomper

    vladikcomper Well-Known Member Member

    Joined:
    Dec 2, 2009
    Messages:
    415
    I've restored all the dead links in Error Handler and Mega PCM threads a few months ago. Illustrations and any extra downloadable files should also be up (mostly), so give it a try.
    As a reminder, Error Handler is fully open-source, so it can also be downloaded from its GitHub releases page. I may release some more stuff on GitHub in the future.

    P.S.: I regret not using my own servers from the start and sticking to Dropbox for so long, as it used to break all my links once in a while, rendering many of my releases abandoned (and now it cannot even generate working links on my account).

    First of all, if you're building Sonic 3 alone, which means you're compiling the code from s3.asm file, make sure your vectors table at the beginning of it as follows:
    Code:
    Vectors:   dc.l   Vectors,   EntryPoint,   BusError, AddressError   ; 0
           dc.l   IllegalInstr, ZeroDivide, ChkInstr, TrapvInstr   ; 4
           dc.l   PrivilegeViol, Trace, Line1010Emu,   Line1111Emu   ; 8
           dc.l   ErrorExcept, ErrorExcept, ErrorExcept, ErrorExcept   ; 12
           dc.l   ErrorExcept, ErrorExcept, ErrorExcept, ErrorExcept   ; 16
           dc.l   ErrorExcept, ErrorExcept, ErrorExcept, ErrorExcept   ; 20
           dc.l   ErrorExcept, ErrorTrap,   ErrorTrap,   ErrorTrap   ; 24
           dc.l   JmpTo_HInt,   ErrorTrap,   VInt,   ErrorTrap   ; 28
           dc.l   ErrorTrap,   ErrorTrap,   ErrorTrap,   ErrorTrap   ; 32
           dc.l   ErrorTrap,   ErrorTrap,   ErrorTrap,   ErrorTrap   ; 36
           dc.l   ErrorTrap,   ErrorTrap,   ErrorTrap,   ErrorTrap   ; 40
           dc.l   ErrorTrap,   ErrorTrap,   ErrorTrap,   ErrorTrap   ; 44
           dc.l   ErrorTrap,   ErrorTrap,   ErrorTrap,   ErrorTrap   ; 48
           dc.l   ErrorTrap,   ErrorTrap,   ErrorTrap,   ErrorTrap   ; 52
           dc.l   ErrorTrap,   ErrorTrap,   ErrorTrap,   ErrorTrap   ; 56
           dc.l   ErrorTrap,   ErrorTrap,   ErrorTrap,   ErrorTrap   ; 60
    
    Pay special attention to this line:
    Code:
           dc.l   JmpTo_HInt,   ErrorTrap,   VInt,   ErrorTrap   ; 28
    
    Sonic 3 uses "JmpTo_HInt" (jump opcode loaded in RAM) and "VInt" (subroutine in ROM) as horizontal and vertical interrupts handlers respectively, while S3K uses "JmpTo_HInt" and "JmpTo_VInt", both being jump opcodes initialized in RAM.

    If you followed Error Handler installation guide for S3K, chances are, you've overwritten vertical interrupt handler in S3's ROM header with S3K-exclusive location. "JmpTo_VInt" is never initialized in plain Sonic 3, which is why the first vertical interrupt to fire most likely fails.

    S3K uses "JmpTo_VInt" to store a jump opcode (in the RAM), which allows to switch between different VInt subroutines dynamically depending on the currently running game (SK, S3, S2K, Blue Spheres).

    At least, since you're seeing the error near "loc_1FA6", which is a location of vertical interrupt waiting loop, the error occrus just when vertical interrupt handler execution is about to start. So, I believe, the Error Handler works as intended, telling you the correct about the crash.

    * * *

    Regarding your thoughts on SRAM mapping interfering with access to any locations above $200000, you're absolutely right. This indeed will prevent error handler from working properly, once you get the get to load past that first crash (the SRAM isn't enabled at this point, which is why error handler works in just fine).

    Compared to S3, S3K has an improved SRAM-related routines, which work safely around the issue, by enabling SRAM just when the access is needed and disabling it right after read/write operations are complete (vanilla S3, on the contrary, just enables SRAM on the first access, never disables again).
    Various emulators handle SRAM mapping behavior in S3K and similar games slightly differently: some would allow only the first 64kb after the $200000 offset to be mapped into SRAM, while others would remap all the available ROM space from $200000 onward.

    As a workaround, I suggest you to replace all the SRAM-related code in s3.asm, starting from "SRAM_Load:" right to the "SaveGame_NextLevel:" with the following snippet (note that the code now starts with "SaveData_GeneralDefault:", which was moved to the top as an optimization):
    Code:
    ; ---------------------------------------------------------------------------
    SaveData_GeneralDefault:
           dc.w  $8000,     0, $8000,     0, $8000,     0,     1,  $200
           dc.w  $8000,     0, $8000,     0, $8000,     0,     1,  $200
           dc.w  $8000,     0, $8000,     0, $8000,     0,     1,  $200
           dc.w  $8000,     0, $8000,     0, $8000,     0,     1,  $200
           dc.w  $8000,     0, $8000,     0, $8000,     0,     1,  $200
           dc.w  $4C44
    SaveData_GameDefault:
           dc.w  $8000,     0,     0,     0, $8000,     0,     0,     0
           dc.w  $8000,     0,     0,     0, $8000,     0,     0,     0
           dc.w  $8000,     0,     0,     0, $8000,     0,     0,     0
           dc.w  $4244
    
    ; =============== S U B R O U T I N E =======================================
    
    
    SRAM_Load:
           lea   ($200011).l,a0
           lea   ($2000BD).l,a1
           lea   (Competition_saved_data).w,a2
           moveq   #$29,d0
           move.w   #$4C44,d1
           bsr.s   Get_From_SRAM
           beq.s   loc_B674
           lea   SaveData_GeneralDefault(pc),a0
           lea   (Competition_saved_data).w,a1
           moveq   #$28,d0
    
    loc_B66A:
           move.w   (a0)+,(a1)+
           dbf   d0,loc_B66A
           jsr   Write_SaveGeneral(pc)
    
    loc_B674:
           lea   ($200169).l,a0
           lea   ($2001F5).l,a1
           lea   (Saved_data).w,a2
           moveq   #$19,d0
           move.w   #$4244,d1
           bsr.s   Get_From_SRAM
           beq.s   loc_B6A4
           lea   SaveData_GameDefault(pc),a0
           lea   (Saved_data).w,a1
           moveq   #$18,d0
    
    loc_B69A:
           move.w   (a0)+,(a1)+
           dbf   d0,loc_B69A
           jsr   Write_SaveGame(pc)
    
    loc_B6A4:
           clr.w   ($FFFFEF4C).w
           move.b   #1,($FFFFEF4B).w
           rts
    ; End of function SRAM_Load
    
    
    ; =============== S U B R O U T I N E =======================================
    
    
    Get_From_SRAM:
           move.b   #1,($A130F1).l
           movea.l   a2,a3
           move.w   d0,d2
           bsr.s   Read_SRAM
           beq.s   SRAM_Disable
           movea.l   a1,a0
           movea.l   a3,a2
           move.w   d2,d0
           bsr.s   Read_SRAM
    
    SRAM_Disable:
           move.b   #0,($A130F1).l
           rts
    ; End of function Get_From_SRAM
    
    
    ; =============== S U B R O U T I N E =======================================
    
    
    Read_SRAM:
           movea.l   a2,a6
           move.w   d0,d6
    
    loc_B74A:
           movep.w   0(a0),d3
           move.w   d3,(a2)+
           addq.w   #4,a0
           dbf   d0,loc_B74A
           subq.w   #1,d6
           bsr.s   Create_SRAMChecksum
           cmp.w   (a6),d7
           bne.s   locret_B762
           cmp.w   -2(a6),d1
    
    locret_B762:
           rts
    ; End of function Read_SRAM
    
    
    ; =============== S U B R O U T I N E =======================================
    
    
    Create_SRAMChecksum:
           moveq   #0,d7
    
    loc_B766:
           move.w   (a6)+,d5
           eor.w   d5,d7
           lsr.w   #1,d7
           bcc.s   loc_B772
           eori.w   #$8810,d7
    
    loc_B772:
           dbf   d6,loc_B766
           rts
    ; End of function Create_SRAMChecksum
    
    
    ; =============== S U B R O U T I N E =======================================
    
    
    Write_SRAM:
           move.b   #1,($A130F1).l
           movea.l   a2,a6
           move.w   d0,d6
           subq.w   #1,d6
           bsr.s   Create_SRAMChecksum
           move.w   d7,(a6)
           movea.l   a2,a3
           move.w   d0,d1
    
    loc_B786:
           move.w   (a2)+,d2
           movep.w   d2,0(a0)
           addq.w   #4,a0
           dbf   d0,loc_B786
    
    loc_B792:
           move.w   (a3)+,d2
           movep.w   d2,0(a1)
           addq.w   #4,a1
           dbf   d1,loc_B792
           bra.s   SRAM_Disable
    ; End of function Write_SRAM
    
    
    ; =============== S U B R O U T I N E =======================================
    
    
    Write_SaveGeneral:
           move.l   a0,-(sp)
           move.w   d7,-(sp)
           lea   ($200011).l,a0
           lea   $2000BD-$200011(a0),a1       ; essentially "lea ($2000BD).l,a1", but 2 bytes shorter
           lea   (Competition_saved_data).w,a2
           moveq   #$29,d0
           bra.s   Write_SaveGame_2
    ; End of function Write_SaveGeneral
    
    
    ; =============== S U B R O U T I N E =======================================
    
    
    Write_SaveGame:
           move.l   a0,-(sp)
           move.w   d7,-(sp)
           lea   ($200169).l,a0
           lea   $2001F5-$200169(a0),a1   ; essentially "lea ($2001F5).l,a1", but 2 bytes shorter
           lea   (Saved_data).w,a2
           moveq   #$19,d0
    
    Write_SaveGame_2:
           bsr.s   Write_SRAM
           move.w   (sp)+,d7
           movea.l   (sp)+,a0
           rts
    ; End of function Write_SaveGame
    
    
    ; =============== S U B R O U T I N E =======================================
    
    
    SaveGame:
           tst.b   (Apparent_act).w
           beq.s   locret_B80E
           move.l   (Save_pointer).w,d0
           beq.s   loc_B80A
           movea.l   d0,a1
           cmpi.b   #6,3(a1)
           bhi.s   loc_B80A
           moveq   #0,d0
           move.b   (Apparent_zone).w,d0
           move.b   SaveGame_NextLevel(pc,d0.w),3(a1)
           clr.b   7(a1)
           clr.b   1(a1)
           bsr.s   Write_SaveGame
    
    loc_B80A:
           clr.l   (Collected_special_ring_array).w
    
    locret_B80E:
           rts
    ; End of function SaveGame
    
    ; ---------------------------------------------------------------------------
    SaveGame_NextLevel:dc.b    1,   2,   3,   5,   5,   6,   7,   0
    
    This is just slightly reorganized version of the same code that now safely disables SRAM after accessing it (but it doesn't include some S3K improvements, like disabling interrupts during SRAM access to avoid near-impossible race conditions).
    I optimized the code to be the same size as the original one, just to avoid any possible disassembly-related errors which may popup if you shift the data right at the beginning of the ROM.

    If you wonder, one such error was right in the "Obj_SaveScreen_Selector" object.
    In order to fix it, find the following line:
    Code:
           move.l   #$C0AC,(a0)
    and replace it with...
    Code:
           move.l   #loc_C0AC,(a0)
    loc_C0AC:
    As you see, it's incorrectly represented opcode in the disassembly, which should operate label pointer (the label itself was completely missed) instead of a raw offset. If you add or remove any data above the $C0AC offset, the object controlling the save screen menu will glitch out.

    EDIT: You may want to do the same trick with the line:
    Code:
    move.l   #$C284,(a0)
    i.e. modify it as follows:
    Code:
           move.l   #loc_C284,(a0)
    loc_C284:
    This is another disassembly error I've just discovered.

    EDIT 2:
    I created pull-request which fixes the above errors and changes have already been merged with the latest version of S3K disassembly on github; shortly afterwards, more instances of misidentified offsets were found and fixed in the following commit by the creator of S3 disassembly itself (if I'm not mistaken).
    You may want to pull these commits in order to make the game more or less sustainable to moving code and data around.
     
    Last edited: Jan 25, 2020
    Chainspike, ProjectFM and penPhobic like this.
  12. Angel X

    Angel X Well-Known Member Member

    Joined:
    Sep 15, 2017
    Messages:
    291
    Location:
    Italy
    Hey ashuro, how long!
    I wondered where you were over ...
    In any case, welcome back:D
     
    Ashuro likes this.
  13. DeltaWooloo

    DeltaWooloo The noob next door Member

    Joined:
    Aug 7, 2019
    Messages:
    373
    Hey there (again)

    This is really annoying. After me adding the code to allow Sonic to be Super even though he hit either the shoes or invincible monitor, it still wears out, is there a proper fix? Here are the codes for help.
    Screenshot 2020-01-26 at 21.30.52.png Screenshot 2020-01-26 at 21.31.01.png Sonic_CheckGoSuper: v
    Screenshot 2020-01-26 at 21.31.55.png
     
  14. Inferno

    Inferno Rom Hacker Member

    Joined:
    Oct 27, 2015
    Messages:
    132
    Location:
    Sky Base Zone, South Island
    You also have to add similar checks in Obj01_ChkInvinc and Obj01_ChkShoes.
     
    DeltaWooloo likes this.
  15. DeltaWooloo

    DeltaWooloo The noob next door Member

    Joined:
    Aug 7, 2019
    Messages:
    373
    Another question:

    How can I make custom extra life jungles? I'm saying this because when created and play, it'll go silent until something else happens rather than a resume music.
     
  16. MainMemory

    MainMemory Well-Known Member Member

    Joined:
    Mar 29, 2011
    Messages:
    922
    You have to put a fade command at the end of the DAC track (smpsFade in Flamewing's SMPS2ASM).
     
  17. ProfessorRenderer

    ProfessorRenderer Certified Bear Scientist Member

    Joined:
    Sep 28, 2011
    Messages:
    102
    Location:
    Willoughby, Ohio
    I've been meaning to get back into Sonic hacking for some time, and a question that I had was how would you go about making a custom Sega sound effect in Sonic 1 with just the default sound driver?
     
  18. Kilo

    Kilo Foxy Fren Exiled

    Joined:
    Oct 9, 2017
    Messages:
    391
    Location:
    A warm and lovely place~
  19. Ashuro

    Ashuro Anti-Cosmic Metal Of Death Member

    Joined:
    Sep 27, 2014
    Messages:
    550
    Location:
    France
    All right, I think I'm really rusty from that two-year break.

    I'm working on Sonic 2 Git Hub. I remember a MarkeyJester job a long time ago because I had the same problem:

    http://sonicresearch.org/community/index.php?threads/sonmaped-problem.3962/#post-57250


    If I was on Sonic 1, I could have avoided posting, but here's my problem.

    I've imported my well known Ashuro into Sonic 2, I'm extremely comfortable with SonMapEd, animations etc... So far, no worries.

    But in fact these images will clearly explain why I'm here.

    [​IMG]

    As you can see, the current frame is cut with a tile from another sprite.
    [​IMG]
    Same problem here.

    For your information, here is the number of sprites, frames and tiles that make up the character:

    [​IMG]
    Does anyone have any idea how this problem happens?

    Thank you very much!
     
  20. vladikcomper

    vladikcomper Well-Known Member Member

    Joined:
    Dec 2, 2009
    Messages:
    415
    This is a bug with DMA transfers on the Mega Drive's VDP because of how its counters that track the offset of currently transferred word work.
    All tile transfers that cross 128kb boundary within the M68K address space (e.g. offsets $20000, $40000, $60000 and so on) will wrap to the beginning of that 128kb segment, causing VDP to read random code or data instead of the wanted tiles.
    This is unlikely to happen in Sonic 1, because it DMA-transfers from RAM (unless you backport Sonic 2's DPLC system by following the Spin Dash guide); but it's quite likely to happen in S2, S3, S3K since all DMA transfers occur from the ROM.

    The easiest and the most straight-forward way to fix the issue (but certainly not the optimal one) would be just to pad your art to start at beginning of the nearest 128kb boundary, something like:
    Code:
       align $20000
    
    Art_Ashuro:
       binclude "artunc\your_ashuro_art.bin"
    
    The downside of this method, is that in worst case scenario you may get up to (128kb - 2bytes) of padding, which is basically the wasted space in your ROM.
    If you're aiming to optimize ROM space, or your tileset itself happens to exceed 128kb, a more careful placing is needed, which usually involves analyzing offsets of large data chunks and trying to manually figure out the best order to lay them down in the ROM.

    If you're looking for a more advanced solution, check out flamewing's Ultra DMA queue, which is much better optimized and also splits DMA requests if they cross the 128kb boundary.