[Sonic 1]How to Fix Slow boot processing/Checksum Check

Discussion in 'Approved' started by Viva La Luna, Jul 31, 2014.

Thread Status:
Not open for further replies.
  1. Viva La Luna

    Viva La Luna A.K.A. crypt0nymous Member

    Joined:
    Jun 7, 2012
    Messages:
    82
    Location:
    Istanbul
    I'm sure most of the people knows the fix. But this tutorial was needed to be here. :p


    I'll be showing you my first tutorial; FIXING DA SLOW BOOTING PROCESS!


    Currently working on a sonic 1 hack? Did you do something big so that the rom takes a lot of time to load? No, Don't give up! Every issue has a fix!

    So, all of this problem stands on that goddamned "Checksum Check" option. Here we go!

    DELETING THE CHECKSUM CHECK ROUTINE


    PLEASE NOTE THAT THE CHECKSUM CHECK ROUTINE IS NOT IMPORTANT, BUT USEFUL FOR EASILY UNDERSTANDING THE DATA OF YOUR ROM IS NOT CORRECTLY TRANSFERED(ESPECIALLY USEFUL FOR REAL HARDWARE TRANSFERING). SO DELETING THE CHECKSUM ROUTINE WILL MAKE YOUR ROM BOOT FASTER, BUT INSTEAD OF GETTING RED SCREEN YOU WOULD ENCOUNTER SOME BUGS, GLITCHES CAUSED BY INCORRECTLY TRANSFERING/DOWNLOADING ISSUES. BUT IT'S RATHER USELESS IF YOU ARE USING EMULATORS (like KEGA), SINCE THEY HAVE "CHECKSUM INCORRECT" WARNING AT THE BEGINNING. BUT IF YOU WANT TO BE SURE ABOUT SOME BUGS ARE CAUSED BY DATA TRANSFERRING ISSUES, I WOULD ADVISE DOING NOTHING.


    More information is given by MarkeyJester :p

    Method 1; Deleting some asm codes (for hivebrain Disassembly):


    Step 1: Find the label GameProgram:


    GameProgram:
    tst.w ($C00004).l
    btst #6,($A1000D).l
    beq.s ChecksumCheck
    cmpi.l #'init',($FFFFFFFC).w ; has checksum routine already run?
    beq.w GameInit ; if yes, branch

    CheckSumCheck:
    movea.l #ErrorTrap,a0 ; start checking bytes after the header ($200)
    movea.l #RomEndLoc,a1 ; stop at end of ROM
    move.l (a1),d0
    moveq #0,d1

    loc_32C:
    add.w (a0)+,d1
    cmp.l a0,d0
    bcc.s loc_32C
    movea.l #Checksum,a1 ; read the checksum
    cmp.w (a1),d1 ; compare correct checksum to the one in ROM
    bne.w CheckSumError ; if they don't match, branch
    lea ($FFFFFE00).w,a6
    moveq #0,d7
    move.w #$7F,d6

    Delete or comment all below the code "btst #6,($A1000D).l".

    Step 2: Find the label ChecksumError:


    CheckSumError:
    bsr.w VDPSetupGame
    move.l #$C0000000,($C00004).l ; set VDP to CRAM write
    moveq #$3F,d7

    CheckSum_Red:
    move.w #$E,($C00000).l ; fill screen with colour red
    dbf d7,CheckSum_Red ; repeat $3F more times


    CheckSum_Loop:
    bra.s CheckSum_Loop

    These codes are showing the colour red and freezes the game, is referenced at codes in first step; which branches these codes if checksum was incorrect. You can delete these labels, since we don't need it anymore.

    Save, exit and build!

    Method 2; Using Hex Editor:


    Use this method if you are using another disassembly or not using any disassembly or if you want to do it in a harder way. :p


    NOTE: In this guide you need a hex editor. Hex Workshop is recommended.


    Checksum checking sub is always the same:


    CheckSumCheck:
    movea.l #ErrorTrap,a0 ; start checking bytes after the header ($200)
    movea.l #RomEndLoc,a1 ; stop at end of ROM
    move.l (a1),d0 moveq #0,d1
    loc_32C:
    add.w (a0)+,d1
    cmp.l a0,d0
    bcc.s loc_32C
    movea.l #Checksum,a1 ; read the checksum
    cmp.w (a1),d1 ; compare correct checksum to the one in ROM
    bne.w CheckSumError ; if they don't match, branch

    which equals to this in machine code:

    Code:
    207C 0000 0200 
    227C 0000 01A4
    2011 7200
    D258 
    B088 
    64FA
    227C 0000 018E 
    B251
    6600 00xx (xx is random)
    So, open your ROM through a hex editor and find these lines(typed in hex values, of course):

    64FA227C0000018EB251660000


    Let's get a look at our target codes:


    64FA 227C 0000 018E B251 6600 00xx (xx is random, again :p)


    Now change all of these to:


    4E71 4E71 4E71 4E71 4E71 4E71 4E71 (4E71 equals as nop, of course!)


    OPTIONAL: Because of you edited some hex codes, the emulator will show "Checksum Incorrect" warning.


    The only need for fixing the checksum is dragging and dropping your ROM into fixheadr.exe.


    If you don't have fixheadr: https://docs.google.com/uc?authuser=0&id=0B0I5iTe7zcuwQmlYOTQ2c1E5bWM&export=download


    Congratulations! Now your rom should be opened in half-a-second time!


    Special thanks to nineko and drx, by the way.


    If I did something wrong, please post it here.


    Also sorry for bad English. :p


    EDIT: some fixes


    EDIT2: bobesh8 and MarkeyJester's suggestions


    EDIT3: additional links
     
    Last edited by a moderator: Jul 31, 2014
  2. Bobesh8

    Bobesh8 Well-Known Member Member

    Joined:
    Aug 20, 2009
    Messages:
    74
    The removal of this code below, is unnecessary.


            move.b    ($A10001).l,d0
            andi.b    #$C0,d0
            move.b    d0,($FFFFFFF8).w
            move.l    #'init',($FFFFFFFC).w ; set flag so checksum won't be run again

    It is not part of the Checksum Check routine. This just sets it's console's region number to a RAM location.
     
    Last edited by a moderator: Jul 31, 2014
  3. MarkeyJester

    MarkeyJester ! % # @ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,668
    I want to congratulate you on your tutorial, it is very informal, well writen, and functions as stated. Well done!

    ...

    But... As you know, some things are often understated. I don't wish to sound like a cunt, but I believe understanding the purpose behind the checksum is an important role, that of which renders your guide here to be irresponsible.

    One of the fundamentals of digital data, is the ability to copy and transfer data from one machine to another, however, since you are dealing with electrical pulses of extreme speed and delicacy, it is unformidable that the data can easily be disrupted during the transfer process, leaving incorrect binary data on the other end, thereby resulting in errors.

    A "Checksum" is designed specifically for detecting these possible errors by using one of several mathematical computational algorithms, this allows the recieving machine to analyse the data ensuring the transfer occured correctly. While most checksums are not without their flaws, they generally perform their verification task accurately enough for practical use.

    Sonic games specifically use a "modular checksum" by means of adding all words of the ROM from offset 000200 to the end of the ROM, and comparing it with what it "should" add up to (which is stored in the header). If one were to transfer the ROM to a cartridge (or download the ROM) without the checksum routine in place, any errors, bugs, major mishaps that occur in the game caused by interrupts during the transfer/download, could be assumed as an in-game bugs instead. The red screen is there to clearly indicate that the data was not transfered correctly, anyone seeing that screen would immediately know that the ROM needs to be retransfered, thus, ruling it out from being an in-game bug, furthermore, saving the programmers time from searching for a bug that does not exist.

    I would strongly advise optimising the checksum routine for speed rather than simply removing it, it is true that the ROM does not rely on it entirely, but accidents involving the transfer of data can (and do) happen from time to time for various reasons.
     
    FireRat likes this.
  4. Viva La Luna

    Viva La Luna A.K.A. crypt0nymous Member

    Joined:
    Jun 7, 2012
    Messages:
    82
    Location:
    Istanbul
    Thanks for suggestions, MarkeyJester. I agree with you, but from another point, this feature is quite useless if we use the ROM in most of emulators(especially KEGA), since they have a "Incorrect checksum" warning at the beginning. But it could be useful if we try transferring data to play it on real hardware.
     
    Last edited by a moderator: Jul 31, 2014
  5. MarkeyJester

    MarkeyJester ! % # @ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,668
    You cannot be sure that everyone will use KEGA.
     
    Last edited by a moderator: Jul 31, 2014
  6. N30member

    N30member non-pro user btw Member

    Joined:
    Feb 15, 2014
    Messages:
    216
    Location:
    Kazakhstan
    My main emulator is Regen, but Kega is very useful for ROMs that doesn't launch in Regen. =/

    UPD 01.08.14: Removed quoting because of rules.
     
    Last edited by a moderator: Aug 1, 2014
  7. Viva La Luna

    Viva La Luna A.K.A. crypt0nymous Member

    Joined:
    Jun 7, 2012
    Messages:
    82
    Location:
    Istanbul
    Uh, I did not say something like that, already. :/ I also said it would be useful for testing on real hardware, I forget to include the other emulators, pardon me :p

    By the way, Some games like Sonic 3&K, Sonic 3D blast and newer genesis games lack checksum checks, possibly because of this issue. I don't think if there was a possibility to optimize the checksum routine speed. They would do it in earlier time to Sonic 3&K,3D. I'll try it, anyway.
     
    Last edited by a moderator: Jul 31, 2014
  8. Irixion

    Irixion Well-Known Member Member

    Joined:
    Aug 11, 2007
    Messages:
    670
    Location:
    Ontario, Canada
    Waiting a second or two is slow bootup? Man you guys are impatient.
     
    HackGame likes this.
  9. MarkeyJester

    MarkeyJester ! % # @ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,668
    When the ROM is as big as 4MB, the original checksum routine takes just over 7 seconds to complete, here's a replacement:

    CheckSumCheck:
    movea.w #$0200,a0 ; prepare start address
    move.l (RomEndLoc).w,d7 ; load size
    sub.l a0,d7 ; minus start address
    move.b d7,d5 ; copy end nybble
    andi.w #$000F,d5 ; get only the remaining nybble
    lsr.l #$04,d7 ; divide the size by 20
    move.w d7,d6 ; load lower word size
    swap d7 ; get upper word size
    moveq #$00,d0 ; clear d0

    CS_MainBlock:
    add.w (a0)+,d0 ; modular checksum (8 words)
    add.w (a0)+,d0 ; ''
    add.w (a0)+,d0 ; ''
    add.w (a0)+,d0 ; ''
    add.w (a0)+,d0 ; ''
    add.w (a0)+,d0 ; ''
    add.w (a0)+,d0 ; ''
    add.w (a0)+,d0 ; ''
    dbf d6,CS_MainBlock ; repeat until all main block sections are done
    dbf d7,CS_MainBlock ; ''
    subq.w #$01,d5 ; decrease remaining nybble for dbf
    bpl.s CS_Finish ; if there is no remaining nybble, branch

    CS_Remains:
    add.w (a0)+,d0 ; add remaining words
    dbf d5,CS_Remains ; repeat until the remaining words are done

    CS_Finish:
    cmp.w (Checksum).w,d0 ; does the checksum match?
    bne.w CheckSumError ; if not, branchThis one is optimised on the basis of speed, so rather than adding a single word segment at a time and comparing the address for completion each time, it'll add multiple word segments within the loop and the completion detection is handled by a decrementing counter.
    This reduces the time by just over half the original, now only taking 3 seconds to check a 4MB ROM. It could probably be taken a step further by performing a long-word modular checksum rather than word, and that may very well shave off an addition second. But you'd need a replacement tool for the "fixheadr.exe" tool, of course, I don't think many people care, so it wouldn't really be worth making.
     
    Last edited by a moderator: Aug 3, 2014
    Nat The Porcupine likes this.
  10. Bobesh8

    Bobesh8 Well-Known Member Member

    Joined:
    Aug 20, 2009
    Messages:
    74
    Applied the new code to Sonic 3 and Knuckles, but gave me a red screen, even when the AutoFix CheckSum is checked on.

    I used Kega Fusion 3.64.
     
  11. MarkeyJester

    MarkeyJester ! % # @ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,668
    There are several reasons why it will not work:

    The first is to do with the fact that the checksum value in the header is automatically wrong as soon as you make any changes. Sonic 3 & Knuckles did not come packed with a tool to automatically set the checksum value in the header after being built. So 99% of the time, the checksum reads wrong.

    The second is likely to do with the ROM end position inside the header, remember, the game is technically Sonic & Knuckles, even with Sonic 3 on top it is still Sonic & Knuckles, the title is still Sonic & Knuckles, the header info is still Sonic & Knuckles. The checksum routine therefore reads the ROM from 000200 to 1FFFFF. If you have attempted to use the checksum fix tool used in other disassemblies (known as "fixheadr.exe" iirc), it will try to autofix the entire 4MB space as it does not read the header.

    One final issue is, because the end offset in the header of S3&K is forced as -1, the subtraction of 1 in the routine (subq.l #$01,d7) redeems useless.

    You need a tool that can fix the checksum value of Sonic & Knuckles independantly. Remember, anything can be plugged onto Sonic & Knuckles, so a checksum routine to check the entire 4MB space is not such a clever idea. If you plan on having a full hack/project of Sonic 3 & Knuckles with no other plugins, then perhaps it's best to remove the lock on software, and hard lock it as a full, proper 4MB ROM with one header, and one set of code.
     
    Last edited by a moderator: Aug 3, 2014
Thread Status:
Not open for further replies.