Load 16x16 Blocks From ROM Instead of RAM (Sonic 1, GitHub)

Discussion in 'Tutorials' started by Filter, Dec 22, 2022.

  1. Filter

    Filter Newcomer Member

    Joined:
    Jul 28, 2021
    Messages:
    24
    Location:
    Canada
    So quite recently I was looking at the tutorial for making chunks in Sonic 1 load from ROM instead of RAM, which was smart but it was only made for Green Hill Zone and nowhere else. So I came up with an idea that branched from there, what if we loaded blocks without RAM and instead loaded them from ROM? Well, let's dive in.

    How Much RAM Gets Freed
    Considering that in Sonic 1 blocks are normally loaded from LevelHeaders and then decompressed from Enigma, the estimated RAM you will be freeing is shown below.
    Code:
    v_16x16 RAM Usage = $1FFF
    Yeah, that's a lot of RAM freed. There's enough RAM there to import a lot of things into your hacks.

    Installation
    So first we want to decompress the blocks, firstly go ahead and grab FW-KENSC and once that's done installing then go into the folder labelled map16 and select all files in there. Now right click and decompress all the files from Enigma (if you aren't using Enigma in your hack, then use the compression you used to decompress it). Once that is complete, you should be left with *.unc files left in the folder and you can go ahead and delete the other files. Remember to go into your main assembly file (sonic.asm) and fix the pointers to the contents in map16 to point to the uncompressed ones.

    Now that the blocks are uncompressed, it's time to make them load! But first, we need to make sure they aren't being decompressed, so go to LevelDataLoad and get rid of this:
    Code:
            movea.l    (a2)+,a0
            lea    (v_16x16).w,a1    ; RAM address for 16x16 mappings
            move.w    #0,d0
            bsr.w    EniDec
    And change this above the previous code:
    Code:
            addq.l    #4,a2
    To this:
    Code:
            addq.l    #8,a2
    There, that skips the blocks from being pointlessly decompressed.

    Here's the part where we actually load the blocks, go to GetBlockData and replace this:
    Code:
            lea    (v_16x16).w,a1
    With this:
    Code:
            move.w  (v_zone).w,d0
            lsl.w   #2,d0 ; change this to lsr.w   #6,d0 if using 128x128 chunks
            move.l    BlockList(pc,d0.w),a1
    And then place this above GetBlockData:
    Code:
    BlockList:
                    dc.l Blk16_GHZ
                    dc.l Blk16_LZ
                    dc.l Blk16_MZ
                    dc.l Blk16_SLZ
                    dc.l Blk16_SYZ
                    dc.l Blk16_SBZ
                    dc.l Blk16_GHZ
    What this does is that it loads the blocks depending on the zone, so it's not hard coded to load just in Green Hill Zone.

    We're almost done here, just need to do one more thing. Go to Tit_LoadText, and delete this:
    Code:
            lea    (v_16x16).w,a1
            lea    (Blk16_GHZ).l,a0 ; load    GHZ 16x16 mappings
            move.w    #0,d0
            bsr.w    EniDec
    There! Now you can go to Variables.asm and you can completely get rid of the v_16x16 label as it is now useless. Hopefully you find this tutorial useful in your hacks, no credit is required but it would be appreciated.
     
  2. faith

    faith Well-Known Member Member

    Joined:
    Aug 26, 2013
    Messages:
    1,213
    Your guide has a flaw in it that prevents it from working 100%, and it has to do with this tidbit of code:
    Code:
            move.w  (v_zone).w,d0
            lsl.w   #2,d0 ; change this to lsr.w   #6,d0 if using 128x128 chunks
            move.l    BlockList(pc,d0.w),a1
    "BlockList" only has 1 entry per zone, and yet, you are using both the zone and act IDs to calculate the index of it by reading a word. As a result, Green Hill Act 2 ($0001) will load Labyrinth's blocks, and zone past Green Hill will try to load a pointer past the table (i.e. Labyrinth Act 1's zone/act ID is $0100, which is not valid for the table). To fix that, you need to change the first line to
    Code:
            moveq    #0,d0
            move.b    (v_zone).w,d0
    Which will clear d0 to prevent trash data from messing with it, and then just loading the zone ID. Also, for REV01, make sure that this is placed under GetBlockData_2 instead, or it'll get skipped whenever GetBlockData_2 gets called instead.

    Make sure you test beyond Green Hill Act 1 for stuff like this.
     
    ProjectFM likes this.
  3. Filter

    Filter Newcomer Member

    Joined:
    Jul 28, 2021
    Messages:
    24
    Location:
    Canada
    Thanks, oddly enough this problem never occurred for me, even with the code the way it was. Anyways, thanks for doing this.
     
  4. JGamer2151

    JGamer2151 Active Member Member

    Joined:
    Dec 1, 2020
    Messages:
    36
    I do like the fact that you can now load 16x16 blocks for every level in ROM; I just wish that the same can be done for the 256x256/128x128 chunks as well, as the chunks for all levels can also be loaded into ROM alongside with the blocks (assuming you have enough ROM space). If only the chunks guide on the Retro SCHG How-to page can be updated to expand to all levels as opposed to just GHZ (the guide only uses GHZ as an example of how to use uncompressed chunks, as I think the guide expects those with enough care can adapt the code for GHZ to other levels)…

    Aside from that, this guide would also benefit Sonic 2, and Sonic 3K as well, since the blocks can also be uncompressed and put into ROM, eventually freeing up more RAM, especially for Sonic 3K. The only issues with this are within the disassemblies made for those games, which could have made porting this guide for use with those games a bit tedious. However, with enough patience, it can be done.
     
    Last edited: Dec 23, 2022
  5. faith

    faith Well-Known Member Member

    Joined:
    Aug 26, 2013
    Messages:
    1,213
    That... doesn't make any sense. It should have broke in stages past Green Hill Act 1.

    GHZ2:
    [​IMG]

    MZ1:
    [​IMG]

    LZ1:
    [​IMG]
     
  6. NayTheGamer

    NayTheGamer next release coming on 3rd of November 2023 In Limbo

    Joined:
    Sep 30, 2022
    Messages:
    83
    those are some interesting + weird results
     
  7. TheInvisibleSun

    TheInvisibleSun Visible Member

    Joined:
    Jul 2, 2013
    Messages:
    413
    Location:
    Buffalo, NY, USA
    I think it's good practice to post a built rom incorporating the completed tutorial for situations like this, in case there's a misunderstanding