Actions

SCHG How-to

Extend the level index past $10 in Sonic 2

From Sonic Retro

Revision as of 13:01, 15 December 2010 by Silent.creature (talk | contribs)

Authoring Notes

(Original guide by kram, current revision that fixes major bugs and extends properly by GARY 'M 9)

(Updated again by kram, adding back custom titlecard mappings howto, due to guide being unfinished, thus finally fixing the "ZONE ZONE" bug. Replace all the empty levels with your new ones.)

(Some implementations by silent.creature. More fixes about level crashes)

Introduction

WARNING: Unless you are working with Xenowhirl's 2007 Sonic 2 disassembly, I [b]strongly[/b] recommend you port the Sonic 1 sound driver first before proceeding. There will be a lot of shifting data and data addition here, and this may even break any array built under Sonic 2 or Sonic 2 Beta sound driver. In Xenowhirl's disassembly, the Sound Driver is assembled within the ROM, so it can handle a massive data shift. This time, I will leave for the reader the option to add data as long as necessary, instead of labeling and inserting all data (maybe not everyone has all the data done, right?)

You probably noticed that all the indexes in the game stop at $10 and when you try to extend it, by extending the MLLB (Main Level Load Blocks), you get weird glitches or even crashes, that is because you haven't extended all the indexes that need to be extended.

Extending the Titlecard index

First we find:

<asm> Obj34_TitleCardData:

   dc.b    8,    0, $80, $1B
   dc.w $240, $120, $B8
   dc.b   $A,  $11, $40, $1C
   dc.w  $28, $148, $D0
   dc.b   $C,  $12, $18, $1C
   dc.w  $68, $188, $D0
   dc.b    2,    0,   0,   0
   dc.w    0,    0,   0
   dc.b    4,  $15, $48,   8
   dc.w $2A8, $168,$120
   dc.b    6,  $16,   8, $15
   dc.w  $80,  $F0, $F0

</asm>

and change it to: <asm> Obj34_TitleCardData:

   dc.b    8,    0, $80, $1B ; this is the zone string start index and  placement
   dc.w $240, $120, $B8
   dc.b   $A,  $21, $40, $1C ; "ZONE" string index number and placement
   dc.w  $28, $148, $D0
   dc.b   $C,  $22, $18, $1C ; act number start index and placement
   dc.w  $68, $188, $D0
   dc.b    2,    0,   0,   0 ; this part of the titlecard is totally unknown, colored backdrop possibly
   dc.w    0,    0,   0
   dc.b    4,  $25, $48,   8 ; red strip edge index and placement
   dc.w $2A8, $168,$120
   dc.b    6,  $26,   8, $15 ; red "Sonic The Hedgehog" string and placement
   dc.w  $80,  $F0, $F0

</asm>

next, find: <asm> loc_13DEE:

   jsr       sub_13D10(pc)
   move.b    (Current_Zone).w,d0
   cmpi.b    #$10,d0
   beq.s     BranchTo9_DeleteObject
   cmpi.b    #6,d0
   beq.s     BranchTo9_DeleteObject
   cmpi.b    #$E,d0
   beq.s     BranchTo9_DeleteObject
   move.b    (Current_Act).w,d1
   addi.b    #$12,d1
   cmpi.b    #5,d0
   bne.s     loc_13E18
   moveq     #$14,d1

loc_13E18:

   (...)

</asm>

and change it to: <asm> loc_13DEE:

   jsr       sub_13D10(pc)
   move.b    (Current_Zone).w,d0
   cmpi.b    #$10,d0
   beq.s     BranchTo9_DeleteObject
   cmpi.b    #6,d0
   beq.s     BranchTo9_DeleteObject
   cmpi.b    #$E,d0
   beq.s     BranchTo9_DeleteObject
   cmpi.b    #5,d0
   beq.s     loc_13E17
   move.b    (Current_Act).w,d1
   addi.b    #$22,d1                  ; Act number mappings (Act 1)
   bra.w    loc_13E18

loc_13E17:

   moveq     #$24,d1                  ; Act number mappings (Act 3).  Used for drawing MTZ (0x05) titlecard only

loc_13E18:

   (...)

</asm>

In order to easily fix title cards of added 3-acted zones, we inverted the data using the label loc_13E17.

Now we have the offset data of where to load the mappings for the titlecards shifted so that we can now start working on updating the mappings and not have that strange "ZONE ZONE" bug that GARY 'M 9 left behind and I intended to correct.

Next off, in this part of the hack the first thing before converting to a better manageable datatype, we want to replace the byte_15820 handler with a better one. The original pointer format posted here doesn't fit correctly. We need to adjust the pointers to fit data as it was before. The routine itself works, but its data references, not. Let's work on this.

look for: <asm>

loc_157D2

LoadTitleCard:

   bsr.s    LoadTitleCard0
   moveq    #0,d0
   move.b    (Current_Zone).w,d0
   move.b    byte_15820(pc,d0.w),d0
   lea    word_15832(pc),a0
   lea    (a0,d0.w),a0
   move.l    #$7BC00002,d0

</asm>

and we want to replace it with: <asm>

loc_157D2

LoadTitleCard:

   bsr.s    LoadTitleCard0
   moveq    #0,d0
   move.b    (Current_Zone).w,d0
   add.w    d0,d0
   move.w    Off_Titlecardtext(pc,d0.w),d0
   lea    Off_Titlecardtext(pc,d0.w),a0
   move.l    #$7BC00002,d0

</asm>

That takes care of the loader, now time to update the string data.

find: <asm>

unknown

byte_15820:

   dc.b   0,  0,  0,  0,$10,$10,$98,$20,$2C,  0,$3C,$46,$58,$68,$A8,$7A
   dc.b $8A,  0    ; 16
unknown

word_15832:

   dc.w $2A06,$3804,    4,$2604, $C04,$1804,$1C02,$FFFF
   dc.w $2A06,$4004,$3804,$3004,$2604,$1C02,$3C04,$FFFF; 8
   dc.w $1804,$1C02,$2604,$4004,$3004,$FFFF,$1804,$1C02; 16
   dc.w  $C04,$3004,    4,$2604, $804,$FFFF,$1C02,$2604; 24
   dc.w  $804,    4,$FFFF,$2A06,$5604,$3C04,$4004,$1C02; 32
   dc.w  $804,    4,$4804,$FFFF, $804,    4,$3C04,$1C02; 40
   dc.w $1404,$1804,$4004,$FFFF, $804,$1804,$2A06,$1C02; 48
   dc.w     4,$2604,$3004,$4004,$FFFF,    4,$3404,$4404; 56
   dc.w $4004,$1C02, $804,$3804,$FFFF,$3C04,$2204,$5604; 64
   dc.w  $804,$1804,    4,$FFFF,$4C06,$1C02,$1404,$1004; 72
   dc.w $3804,$4004,$3C04,$FFFF, $C04,    4,$4004,$1804; 80
   dc.w $1404,$FFFF    ; 88

</asm>

and replace it with: <asm>

byte_15820

Off_Titlecardtext:

   dc.w   Text_EHZ-Off_Titlecardtext ; EHZ Titlecard 00
   dc.w   Text_LZ-Off_Titlecardtext  ;  LZ Titlecard 01
   dc.w   Text_WZ-Off_Titlecardtext  ;  WZ Titlecard 02
   dc.w   Text_DHZ-Off_Titlecardtext ; DHZ Titlecard 03
   dc.w   Text_MTZ-Off_Titlecardtext ; MTZ Titlecard 04
   dc.w   Text_MTZ-Off_Titlecardtext ; MTZ Titlecard 05
   dc.w   Text_WFZ-Off_Titlecardtext ; WFZ Titlecard 06
   dc.w   Text_HTZ-Off_Titlecardtext ; HTZ Titlecard 07
   dc.w   Text_HPZ-Off_Titlecardtext ; HPZ Titlecard 08
   dc.w   Text_GCZ-Off_Titlecardtext ; GCZ Titlecard 09
   dc.w   Text_OOZ-Off_Titlecardtext ; OOZ Titlecard 0A
   dc.w   Text_MCZ-Off_Titlecardtext ; MCZ Titlecard 0B
   dc.w   Text_CNZ-Off_Titlecardtext ; CNZ Titlecard 0C
   dc.w   Text_CPZ-Off_Titlecardtext ; CPZ Titlecard 0D
   dc.w   Text_DEZ-Off_Titlecardtext ; DEZ Titlecard 0E
   dc.w   Text_ARZ-Off_Titlecardtext ; ARZ Titlecard 0F
   dc.w   Text_SCZ-Off_Titlecardtext ; SCZ Titlecard 10
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 11
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 12
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 13
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 14
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 15
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 16
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 17
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 18
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 19
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 1A
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 1B
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 1C
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 1D
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 1E
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 1F
   dc.w   Text_NZ-Off_Titlecardtext  ;  NZ Titlecard 20
word_15832

Text_EHZ:

   dc.w    $2A06,$3804,    4,$2604, $C04,$1804,$1C02    ;'MRALDHI'
   dc.w    $FFFF

Text_MTZ:

   dc.w    $2A06,$4004,$3804,$3004,$2604,$1C02,$3C04    ;'MTRPLIS'
   dc.w    $FFFF

Text_HTZ:

   dc.w    $1804,$1C02,$2604,$4004,$3004    ;'HILTP'
   dc.w    $FFFF
   

Text_HPZ:

   dc.w    $1804,$1C02, $C04,$3004,    4,$2604, $804    ;'HIDPALC'
   dc.w    $FFFF

Text_OOZ:

   dc.w    $1C02,$2604, $804,    4    ;'ILCA'
   dc.w    $FFFF
   

Text_MCZ:

   dc.w    $2A06,$5604,$3C04,$4004,$1C02, $804,    4,$4804    ;'MYSTICAV'
   dc.w    $FFFF

Text_CNZ:

   dc.w     $804,    4,$3C04,$1C02,$1404,$1804,$4004    ;'CASIGHT'
   dc.w    $FFFF
   

Text_CPZ:

   dc.w     $804,$1804,$2A06,$1C02,    4,$2604,$3004,$4004    ;'CHMIALPT'
   dc.w    $FFFF

Text_ARZ:

   dc.w        4,$3404,$4404,$4004,$1C02, $804,$3804    ;'AQUTICR'
   dc.w    $FFFF

Text_SCZ:

   dc.w    $3C04,$2204,$5604, $804,$1804,    4    ;'SKYCHA'
   dc.w    $FFFF

Text_WFZ:

   dc.w    $4C06,$1C02,$1404,$1004,$3804,$4004,$3C04    ;'WIGFRTS'
   dc.w    $FFFF

Text_DEZ:

   dc.w     $C04,    4,$4004,$1804,$1404    ;'DATHG'
   dc.w    $FFFF

Text_NZ: dc.b $4C06 ; 'W'

     dc.w $FFFF ; '<EOF>'

</asm>

This extends the title card index to $20, adds titlecards for Wood Zone, Labyrinth Zone, Dust Hill Zone, Genocide City Zone, and an empty New Zone titlecard for every single level above SCZ, compacts the titlecard text data for all titlecards, and makes it more easier to manage. you will be wondering probably what to do with the mappings. Well that is what is next. find: <asm>

-------------------------------------------------------------------------------
sprite mappings
-------------------------------------------------------------------------------

Obj34_MapUnc_147BA: BINCLUDE "mappings/sprite/obj34.bin"

-------------------------------------------------------------------------------

</asm>

This label is dynamically called. It means we can move this pointer everywhere in the disassembly. So, we will put this in the disassembly's end. Replace it with this: <asm>

-------------------------------------------------------------------------------
sprite mappings
-------------------------------------------------------------------------------

Obj34_MapUnc_147BA: dc.w Titlecard_EHZ-Obj34_MapUnc_147BA ; EHZ 00

           dc.w Titlecard_LZ-Obj34_MapUnc_147BA  ; LZ  01
           dc.w Titlecard_WZ-Obj34_MapUnc_147BA  ; WZ  02
           dc.w Titlecard_DHZ-Obj34_MapUnc_147BA ; DHZ 03
           dc.w Titlecard_MTZ-Obj34_MapUnc_147BA ; MTZ 04
           dc.w Titlecard_MTZ-Obj34_MapUnc_147BA ; MTZ 05
           dc.w Titlecard_WFZ-Obj34_MapUnc_147BA ; WFZ 06
           dc.w Titlecard_HTZ-Obj34_MapUnc_147BA ; HTZ 07
           dc.w Titlecard_HPZ-Obj34_MapUnc_147BA ; HPZ 08
           dc.w Titlecard_GCZ-Obj34_MapUnc_147BA ; GCZ 09 
           dc.w Titlecard_OOZ-Obj34_MapUnc_147BA ; OOZ 0A
           dc.w Titlecard_MCZ-Obj34_MapUnc_147BA ; MCZ 0B
           dc.w Titlecard_CNZ-Obj34_MapUnc_147BA ; CNZ 0C
           dc.w Titlecard_CPZ-Obj34_MapUnc_147BA ; CPZ 0D
           dc.w Titlecard_DEZ-Obj34_MapUnc_147BA ; DEZ 0E
           dc.w Titlecard_ARZ-Obj34_MapUnc_147BA ; ARZ 0F
           dc.w Titlecard_SCZ-Obj34_MapUnc_147BA ; SCZ 10
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  11
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  12
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  13
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  14
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  15
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  16
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  17
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  18
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  19 
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  1A
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  1B
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  1C
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  1D
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  1E
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  1F
           dc.w Titlecard_NZ-Obj34_MapUnc_147BA  ; NZ  20
           dc.w T_ZONE-Obj34_MapUnc_147BA        ; "ZONE"
           dc.w T_ACT1-Obj34_MapUnc_147BA        ; "1"
           dc.w T_ACT2-Obj34_MapUnc_147BA        ; "2"
           dc.w T_ACT3-Obj34_MapUnc_147BA        ; "3"
           dc.w T_STH-Obj34_MapUnc_147BA         ; "SONIC THE HEDGEHOG"
           dc.w T_STRIPEDGE-Obj34_MapUnc_147BA   ; ">"

Titlecard_EHZ: dc.w $b ; number of letters

           dc.w $0005, $8580, $82C0, $FFC0 ;E
           dc.w $0009, $85DE, $82EF, $FFD0 ;M
           dc.w $0005, $8580, $82C0, $FFE8 ;E
           dc.w $0005, $85E4, $82F2, $FFF8 ;R
           dc.w $0005, $85E8, $82F4, $0008 ;A
           dc.w $0005, $85EC, $82F6, $0018 ;L
           dc.w $0005, $85F0, $82F8, $0028 ;D
           dc.w $0005, $85F4, $82FA, $0048 ;H
           dc.w $0001, $85F8, $82F2, $0058 ;I
           dc.w $0005, $85EC, $82F6, $0060 ;L
           dc.w $0005, $85EC, $82F6, $0070 ;L

Titlecard_LZ: dc.w $9 ; number of letters

           dc.w $0005, $85DE, $82EF, $FFE8 ;L
           dc.w $0005, $85E2, $82F1, $FFF8 ;A
           dc.w $0005, $85E6, $82F3, $0008 ;B
           dc.w $0005, $85EA, $82F5, $0018 ;Y
           dc.w $0005, $85EE, $82F7, $0028 ;R
           dc.w $0001, $85F2, $82F9, $0038 ;I
           dc.w $0005, $8584, $82C2, $0040 ;N
           dc.w $0005, $85F4, $82FA, $0050 ;T
           dc.w $0005, $85F8, $82FC, $0060 ;H

Titlecard_WZ: dc.w $4 ; number of letters

           dc.w $0009, $85DE, $82EF, $0008 ;W
           dc.w $0005, $8588, $82C4, $0010 ;O
           dc.w $0005, $8588, $82C4, $0020 ;O
           dc.w $0005, $85E4, $82F2, $0030 ;D


Titlecard_DHZ: dc.w $8 ; number of letters

           dc.w $0005, $85DE, $82EF, $FFE8 ;D
           dc.w $0005, $85E2, $82F1, $FFF8 ;U
           dc.w $0005, $85E6, $82F3, $0008 ;S
           dc.w $0005, $85EA, $82F5, $0018 ;T
           dc.w $0005, $85EE, $82F7, $0038 ;H
           dc.w $0001, $85F2, $82F9, $0048 ;I
           dc.w $0005, $85F4, $82FA, $0050 ;L
           dc.w $0005, $85F4, $82FA, $0060 ;L

Titlecard_MTZ: dc.w $a ; number of letters

           dc.w $0009, $85DE, $82EF, $FFE8 ;M
           dc.w $0005, $8580, $82C0, $FFF8 ;E
           dc.w $0005, $85E4, $82F2, $0008 ;T
           dc.w $0005, $85E8, $82F4, $0018 ;R
           dc.w $0005, $8588, $82C4, $0028 ;O
           dc.w $0005, $85EC, $82F6, $0038 ;P
           dc.w $0005, $8588, $82C4, $0048 ;O
           dc.w $0005, $85F0, $82F8, $0058 ;L
           dc.w $0001, $85F4, $82FA, $0068 ;I
           dc.w $0005, $85F6, $82FB, $0070 ;S

Titlecard_WFZ: dc.w $c ; number of letters

           dc.w $0009, $85DE, $82EF, $FFB0 ;W
           dc.w $0001, $85E4, $82F2, $FFC8 ;I
           dc.w $0005, $8584, $82C2, $FFD0 ;N
           dc.w $0005, $85E6, $82F3, $FFE0 ;G
           dc.w $0005, $85EA, $82F5, $0000 ;F
           dc.w $0005, $8588, $82C4, $0010 ;O
           dc.w $0005, $85EE, $82F7, $0020 ;R
           dc.w $0005, $85F2, $82F9, $0030 ;T
           dc.w $0005, $85EE, $82F7, $0040 ;R
           dc.w $0005, $8580, $82C0, $0050 ;E
           dc.w $0005, $85F6, $82FB, $0060 ;S
           dc.w $0005, $85F6, $82FB, $0070 ;S

Titlecard_HTZ: dc.w $7 ; number of letters

           dc.w $0005, $85DE, $82EF, $0008 ;H
           dc.w $0001, $85E2, $82F1, $0018 ;I
           dc.w $0005, $85E4, $82F2, $0020 ;L
           dc.w $0005, $85E4, $82F2, $0030 ;L
           dc.w $0005, $85E8, $82F4, $0050 ;T
           dc.w $0005, $8588, $82C4, $0060 ;O
           dc.w $0005, $85EC, $82F6, $0070 ;P

Titlecard_HPZ: dc.w $c ; number of letters

           dc.w $0005, $85DE, $82EF, $FFB8 ;H
           dc.w $0001, $85E2, $82F1, $FFC8 ;I
           dc.w $0005, $85E4, $82F2, $FFD0 ;D
           dc.w $0005, $85E4, $82F2, $FFE0 ;D
           dc.w $0005, $8580, $82C0, $FFF0 ;E
           dc.w $0005, $8584, $82C4, $0000 ;N
           dc.w $0005, $85E8, $82F4, $0020 ;P
           dc.w $0005, $85EC, $82F6, $0030 ;A
           dc.w $0005, $85F0, $82F8, $0040 ;L
           dc.w $0005, $85EC, $82F6, $0050 ;A
           dc.w $0005, $85F4, $82FA, $0060 ;C
           dc.w $0005, $8580, $82C0, $0070 ;E

Titlecard_GCZ: dc.w $c ; number of letters

           dc.w $0005, $85DE, $82EF, $FFB8 ;G
           dc.w $0005, $8580, $82C0, $FFC8 ;E
           dc.w $0005, $8584, $82C2, $FFD8 ;N
           dc.w $0005, $8588, $82C4, $FFE8 ;O
           dc.w $0005, $85E2, $82F1, $FFF8 ;C
           dc.w $0001, $85E6, $82F3, $0008 ;I
           dc.w $0005, $85E8, $82F4, $0010 ;D
           dc.w $0005, $8580, $82C0, $0020 ;E
           dc.w $0005, $85E2, $82F1, $0040 ;C
           dc.w $0001, $85E6, $82F3, $0050 ;I
           dc.w $0005, $85EC, $82F6, $0058 ;T
           dc.w $0005, $85F0, $82F8, $0068 ;Y

Titlecard_OOZ: dc.w $8 ; number of letters

           dc.w $0005, $8588, $82C4, $FFF8 ;O
           dc.w $0001, $85DE, $82EF, $0008 ;I
           dc.w $0005, $85E0, $82F0, $0010 ;L
           dc.w $0005, $8588, $82C4, $0030 ;O
           dc.w $0005, $85E4, $82F2, $0040 ;C
           dc.w $0005, $8580, $82C0, $0050 ;E
           dc.w $0005, $85E8, $82F4, $0060 ;A
           dc.w $0005, $8584, $82C2, $0070 ;N

Titlecard_MCZ: dc.w $a ; number of letters

           dc.w $0009, $85DE, $82EF, $FFD0 ;M
           dc.w $0005, $85E4, $82F2, $FFE8 ;Y
           dc.w $0005, $85E8, $82F4, $FFF8 ;S
           dc.w $0005, $85EC, $82F6, $0008 ;T
           dc.w $0001, $85F0, $82F8, $0018 ;I
           dc.w $0005, $85F2, $82F9, $0020 ;C
           dc.w $0005, $85F2, $82F9, $0040 ;C
           dc.w $0005, $85F6, $82FB, $0050 ;A
           dc.w $0005, $85FA, $82FD, $0060 ;V
           dc.w $0005, $8580, $82C0, $0070 ;E

Titlecard_CNZ: dc.w $b ; number of letters

           dc.w $0005, $85DE, $82EF, $FFD0 ;C
           dc.w $0005, $85E2, $82F1, $FFE0 ;A
           dc.w $0005, $85E6, $82F3, $FFF0 ;S
           dc.w $0001, $85EA, $82F5, $0000 ;I
           dc.w $0005, $8584, $82C2, $0008 ;N
           dc.w $0005, $8588, $82C4, $0018 ;O
           dc.w $0005, $8584, $82C2, $0038 ;N
           dc.w $0001, $85EA, $82F5, $0048 ;I
           dc.w $0005, $85EC, $82F6, $0050 ;G
           dc.w $0005, $85F0, $82F8, $0060 ;H
           dc.w $0005, $85F4, $82FA, $0070 ;T

Titlecard_CPZ: dc.w $d ; number of letters

           dc.w $0005, $85DE, $82EF, $FFA0 ;C
           dc.w $0005, $85E2, $82F1, $FFB0 ;H
           dc.w $0005, $8580, $82C0, $FFC0 ;E
           dc.w $0009, $85E6, $82F3, $FFD0 ;M
           dc.w $0001, $85EC, $82F6, $FFE8 ;I
           dc.w $0005, $85DE, $82EF, $FFF0 ;C
           dc.w $0005, $85EE, $82F7, $0000 ;A
           dc.w $0005, $85F2, $82F9, $0010 ;L
           dc.w $0005, $85F6, $82FB, $0030 ;P
           dc.w $0005, $85F2, $82F9, $0040 ;L
           dc.w $0005, $85EE, $82F7, $0050 ;A
           dc.w $0005, $8584, $82C2, $0060 ;N
           dc.w $0005, $85FA, $82FD, $0070 ;T

Titlecard_DEZ: dc.w $8 ; number of letters

           dc.w $0005, $85DE, $82EF, $FFF0 ;D
           dc.w $0005, $8580, $82C0, $0000 ;E
           dc.w $0005, $85E2, $82F1, $0010 ;A
           dc.w $0005, $85E6, $82F3, $0020 ;T
           dc.w $0005, $85EA, $82F5, $0030 ;H
           dc.w $0005, $8580, $82C0, $0050 ;E
           dc.w $0005, $85EE, $82F7, $0060 ;G
           dc.w $0005, $85EE, $82F7, $0070 ;G

Titlecard_ARZ: dc.w $c ; number of letters

           dc.w $0005, $85DE, $82EF, $FFD0 ;A
           dc.w $0005, $85E2, $82F1, $FFE0 ;Q
           dc.w $0005, $85E6, $82F3, $FFF0 ;U
           dc.w $0005, $85DE, $82EF, $0000 ;A
           dc.w $0005, $85EA, $82F5, $0010 ;T
           dc.w $0001, $85EE, $82F7, $0020 ;I
           dc.w $0005, $85F0, $82F8, $0028 ;C
           dc.w $0005, $85F4, $82FA, $0048 ;R
           dc.w $0005, $85E6, $82F3, $0058 ;U
           dc.w $0001, $85EE, $82F7, $0068 ;I
           dc.w $0005, $8584, $82C2, $0070 ;N

Titlecard_SCZ: dc.w $8 ; number of letters

           dc.w $0005, $85DE, $82EF, $FFF0 ;S
           dc.w $0005, $85E2, $82F1, $0000 ;K
           dc.w $0005, $85E6, $82F3, $0010 ;Y
           dc.w $0005, $85EA, $82F5, $0030 ;C
           dc.w $0005, $85EE, $82F7, $0040 ;H
           dc.w $0005, $85F2, $82F7, $0050 ;A
           dc.w $0005, $85DE, $82EF, $0060 ;S
           dc.w $0005, $8580, $82C0, $0070 ;E

Titlecard_NZ: dc.w $3 ; number of letters

           dc.w $0005, $8584, $82C2, $0048 ;N
           dc.w $0005, $8580, $82C0, $0058 ;E
           dc.w $0009, $85DE, $82EF, $0068 ;W

T_ZONE: dc.w $4 ; number of letters

           dc.w $0005, $858C, $82C6, $0000 ;Z
           dc.w $0005, $8588, $82C4, $0010 ;O
           dc.w $0005, $8584, $82C2, $0020 ;N
           dc.w $0005, $8580, $82C0, $0030 ;E


T_ACT1: dc.w $1 ; number of letters

           dc.w $0007, $A590, $A2C8, $0000 ;1

T_ACT2: dc.w $1 ; number of letters

           dc.w $000B, $A598, $A2CC, $0000 ;2

T_ACT3: dc.w $1 ; number of letters

           dc.w $000B, $A5A4, $A2D2, $0000 ;3

T_STH: dc.w $5 ; number of letters

           dc.w $000D, $85B0, $82DE, $FFB8 ;SONI
           dc.w $000D, $85B8, $82DC, $FFD8 ;C TH
           dc.w $000D, $85C0, $82E0, $FFF8 ;E HE
           dc.w $000D, $85C8, $82E4, $0018 ;DGEH
           dc.w $0005, $85D0, $82E8, $0038 ;OG

T_STRIPEDGE: dc.w $7 ; number of letters

           dc.w $9003, $85D4, $82EA, $0000 ;>
           dc.w $B003, $85D4, $82EA, $0000 ;>
           dc.w $D003, $85D4, $82EA, $0000 ;>
           dc.w $F003, $85D4, $82EA, $0000 ;>
           dc.w $1003, $85D4, $82EA, $0000 ;>
           dc.w $3003, $85D4, $82EA, $0000 ;>
           dc.w $5003, $85D4, $82EA, $0000 ;>
-------------------------------------------------------------------------------

</asm>

Extending the cycling palette information

Now we want to locate: <asm>

off_19F4

PalCycle:

   dc.w PalCycle_EHZ - PalCycle    ; 0
   dc.w PalCycle_Null - PalCycle    ; 1
   dc.w PalCycle_Level2 - PalCycle    ; 2
   dc.w PalCycle_Null - PalCycle    ; 3
   dc.w PalCycle_MTZ - PalCycle    ; 4
   dc.w PalCycle_MTZ - PalCycle    ; 5
   dc.w PalCycle_WFZ - PalCycle    ; 6
   dc.w PalCycle_HTZ - PalCycle    ; 7
   dc.w PalCycle_HPZ - PalCycle    ; 8
   dc.w PalCycle_Null - PalCycle    ; 9
   dc.w PalCycle_OOZ - PalCycle    ; 10
   dc.w PalCycle_MCZ - PalCycle    ; 11
   dc.w PalCycle_CNZ - PalCycle    ; 12
   dc.w PalCycle_CPZ - PalCycle    ; 13
   dc.w PalCycle_CPZ - PalCycle    ; 14
   dc.w PalCycle_ARZ - PalCycle    ; 15
   dc.w PalCycle_WFZ - PalCycle    ; 16

</asm>

and replace it with: <asm>

off_19F4

PalCycle:

   dc.w PalCycle_EHZ - PalCycle    ; 00
   dc.w PalCycle_Null - PalCycle    ; 01
   dc.w PalCycle_Level2 - PalCycle    ; 02
   dc.w PalCycle_Null - PalCycle    ; 03
   dc.w PalCycle_MTZ - PalCycle    ; 04
   dc.w PalCycle_MTZ - PalCycle    ; 05
   dc.w PalCycle_WFZ - PalCycle    ; 06
   dc.w PalCycle_HTZ - PalCycle    ; 07
   dc.w PalCycle_HPZ - PalCycle    ; 08
   dc.w PalCycle_Null - PalCycle    ; 09
   dc.w PalCycle_OOZ - PalCycle    ; 0A
   dc.w PalCycle_MCZ - PalCycle    ; 0B
   dc.w PalCycle_CNZ - PalCycle    ; 0C
   dc.w PalCycle_CPZ - PalCycle    ; 0D
   dc.w PalCycle_CPZ - PalCycle    ; 0E
   dc.w PalCycle_ARZ - PalCycle    ; 0F
   dc.w PalCycle_WFZ - PalCycle    ; 10
   dc.w PalCycle_Null - PalCycle    ; 11
   dc.w PalCycle_Null - PalCycle    ; 12
   dc.w PalCycle_Null - PalCycle    ; 13
   dc.w PalCycle_Null - PalCycle    ; 14
   dc.w PalCycle_Null - PalCycle    ; 15
   dc.w PalCycle_Null - PalCycle    ; 16
   dc.w PalCycle_Null - PalCycle    ; 17
   dc.w PalCycle_Null - PalCycle    ; 18
   dc.w PalCycle_Null - PalCycle    ; 19
   dc.w PalCycle_Null - PalCycle    ; 1A
   dc.w PalCycle_Null - PalCycle    ; 1B
   dc.w PalCycle_Null - PalCycle    ; 1C
   dc.w PalCycle_Null - PalCycle    ; 1D
   dc.w PalCycle_Null - PalCycle    ; 1E
   dc.w PalCycle_Null - PalCycle    ; 1F
   dc.w PalCycle_Null - PalCycle    ; 20

</asm>

That inserts empty slots for the cycling palettes of out new levels.

Extending the static palette list

The [b]PalPointers[/b] coordinate is dynamically called, so we can move this table to the end of the disassembly. We can also move the palette data below it. <asm> PalPointers:

   palptr Pal_SEGA,  Normal_palette, $1F
   palptr Pal_Title, Normal_palette_line2, 7
   palptr Pal_UNK1,  Normal_palette, $1F
   palptr Pal_BGND,  Normal_palette, $F
   palptr Pal_EHZ,   Normal_palette_line2, $17
   palptr Pal_EHZ,   Normal_palette_line2, $17
   palptr Pal_WZ,    Normal_palette_line2, $17
   palptr Pal_EHZ,   Normal_palette_line2, $17
   palptr Pal_MTZ,   Normal_palette_line2, $17
   palptr Pal_MTZ,   Normal_palette_line2, $17
   palptr Pal_WFZ,   Normal_palette_line2, $17
   palptr Pal_HTZ,   Normal_palette_line2, $17
   palptr Pal_HPZ,   Normal_palette_line2, $17
   palptr Pal_EHZ,   Normal_palette_line2, $17
   palptr Pal_OOZ,   Normal_palette_line2, $17
   palptr Pal_MCZ,   Normal_palette_line2, $17
   palptr Pal_CNZ,   Normal_palette_line2, $17
   palptr Pal_CPZ,   Normal_palette_line2, $17
   palptr Pal_DEZ,   Normal_palette_line2, $17
   palptr Pal_ARZ,   Normal_palette_line2, $17
   palptr Pal_SCZ,   Normal_palette_line2, $17
   palptr Pal_HPZ_U, Normal_palette, $1F
   palptr Pal_CPZ_U, Normal_palette, $1F
   palptr Pal_ARZ_U, Normal_palette, $1F
   palptr Pal_SS,    Normal_palette, $17
   palptr Pal_UNK2,  Normal_palette_line2, 7
   palptr Pal_UNK3,  Normal_palette_line2, 7
   palptr Pal_SS1,   Normal_palette_line4, 7
   palptr Pal_SS2,   Normal_palette_line4, 7
   palptr Pal_SS3,   Normal_palette_line4, 7
   palptr Pal_SS4,   Normal_palette_line4, 7
   palptr Pal_SS5,   Normal_palette_line4, 7
   palptr Pal_SS6,   Normal_palette_line4, 7
   palptr Pal_SS7,   Normal_palette_line4, 7
   palptr Pal_UNK4,  Normal_palette_line4, 7
   palptr Pal_UNK5,  Normal_palette_line4, 7
   palptr Pal_UNK6,  Normal_palette_line4, 7
   palptr Pal_OOZ_B, Normal_palette_line2, 7
   palptr Pal_Menu,  Normal_palette, $1F
   palptr Pal_UNK7,  Normal_palette, $1F
----------------------------------------------------------------------------

Pal_SEGA: BINCLUDE "art/palettes/Sega screen.bin" ; SEGA screen palette (Sonic and initial background) Pal_Title: BINCLUDE "art/palettes/Title screen.bin" ; Title screen Palette Pal_UNK1: BINCLUDE "art/palettes/Unknown 1.bin" ; Unknown palette 1 (leftover S1 level select palette?) Pal_BGND: BINCLUDE "art/palettes/SonicAndTails.bin" ; "Sonic and Miles" background palette (also usually the primary palette line) Pal_EHZ: BINCLUDE "art/palettes/EHZ.bin" ; Emerald Hill Zone palette Pal_WZ: BINCLUDE "art/palettes/Wood Zone.bin" ; Wood Zone palette Pal_MTZ: BINCLUDE "art/palettes/MTZ.bin" ; Metropolis Zone palette Pal_WFZ: BINCLUDE "art/palettes/WFZ.bin" ; Wing Fortress Zone palette Pal_HTZ: BINCLUDE "art/palettes/HTZ.bin" ; Hill Top Zone palette Pal_HPZ: BINCLUDE "art/palettes/HPZ.bin" ; Hidden Palace Zone palette Pal_HPZ_U: BINCLUDE "art/palettes/HPZ underwater.bin" ; Hidden Palace Zone underwater palette Pal_OOZ: BINCLUDE "art/palettes/OOZ.bin" ; Oil Ocean Zone palette Pal_MCZ: BINCLUDE "art/palettes/MCZ.bin" ; Mystic Cave Zone palette Pal_CNZ: BINCLUDE "art/palettes/CNZ.bin" ; Casino Night Zone palette Pal_CPZ: BINCLUDE "art/palettes/CPZ.bin" ; Chemical Plant Zone palette Pal_CPZ_U: BINCLUDE "art/palettes/CPZ underwater.bin" ; Chemical Plant Zone underwater palette Pal_DEZ: BINCLUDE "art/palettes/DEZ.bin" ; Death Egg Zone palette Pal_ARZ: BINCLUDE "art/palettes/ARZ.bin" ; Aquatic Ruin Zone palette Pal_ARZ_U: BINCLUDE "art/palettes/ARZ underwater.bin" ; Aquatic Ruin Zone underwater palette Pal_SCZ: BINCLUDE "art/palettes/SCZ.bin" ; Sky Chase Zone palette Pal_UNK2: BINCLUDE "art/palettes/Unknown 2.bin" ; Unknown palette 2 Pal_UNK3: BINCLUDE "art/palettes/Unknown 3.bin" ; Unknown palette 3 Pal_OOZ_B: BINCLUDE "art/palettes/OOZ Boss.bin" ; Oil Ocean Zone boss palette Pal_Menu: BINCLUDE "art/palettes/Menu.bin" ; Menu palette Pal_SS: BINCLUDE "art/palettes/Special Stage Main.bin" ; Special Stage palette Pal_SS1: BINCLUDE "art/palettes/Special Stage 1.bin" ; Special Stage 1 palette Pal_SS2: BINCLUDE "art/palettes/Special Stage 2.bin" ; Special Stage 2 palette Pal_SS3: BINCLUDE "art/palettes/Special Stage 3.bin" ; Special Stage 3 palette Pal_SS4: BINCLUDE "art/palettes/Special Stage 4.bin" ; Special Stage 4 palette Pal_SS5: BINCLUDE "art/palettes/Special Stage 5.bin" ; Special Stage 5 palette Pal_SS6: BINCLUDE "art/palettes/Special Stage 6.bin" ; Special Stage 6 palette Pal_SS7: BINCLUDE "art/palettes/Special Stage 7.bin" ; Special Stage 7 palette Pal_UNK4: BINCLUDE "art/palettes/Special Stage 1 2p.bin" ; Special Stage 1 2p palette Pal_UNK5: BINCLUDE "art/palettes/Special Stage 2 2p.bin" ; Special Stage 2 2p palette Pal_UNK6: BINCLUDE "art/palettes/Special Stage 3 2p.bin" ; Special Stage 3 2p palette Pal_UNK7: BINCLUDE "art/palettes/Special Stage Results Screen.bin" ; Special Stage Results Screen palette </asm>

Once moved, you can simply attach new indexes to it. An example is shown below: <asm> PalPointers:

   palptr Pal_SEGA,  Normal_palette, $1F
   palptr Pal_Title, Normal_palette_line2, 7
   palptr Pal_UNK1,  Normal_palette, $1F
   palptr Pal_BGND,  Normal_palette, $F
   palptr Pal_EHZ,   Normal_palette_line2, $17
   palptr Pal_EHZ,   Normal_palette_line2, $17
   palptr Pal_WZ,    Normal_palette_line2, $17
   palptr Pal_EHZ,   Normal_palette_line2, $17
   palptr Pal_MTZ,   Normal_palette_line2, $17
   palptr Pal_MTZ,   Normal_palette_line2, $17
   palptr Pal_WFZ,   Normal_palette_line2, $17
   palptr Pal_HTZ,   Normal_palette_line2, $17
   palptr Pal_HPZ,   Normal_palette_line2, $17
   palptr Pal_EHZ,   Normal_palette_line2, $17
   palptr Pal_OOZ,   Normal_palette_line2, $17
   palptr Pal_MCZ,   Normal_palette_line2, $17
   palptr Pal_CNZ,   Normal_palette_line2, $17
   palptr Pal_CPZ,   Normal_palette_line2, $17
   palptr Pal_DEZ,   Normal_palette_line2, $17
   palptr Pal_ARZ,   Normal_palette_line2, $17
   palptr Pal_SCZ,   Normal_palette_line2, $17
   palptr Pal_HPZ_U, Normal_palette, $1F
   palptr Pal_CPZ_U, Normal_palette, $1F
   palptr Pal_ARZ_U, Normal_palette, $1F
   palptr Pal_SS,    Normal_palette, $17
   palptr Pal_UNK2,  Normal_palette_line2, 7
   palptr Pal_UNK3,  Normal_palette_line2, 7
   palptr Pal_SS1,   Normal_palette_line4, 7
   palptr Pal_SS2,   Normal_palette_line4, 7
   palptr Pal_SS3,   Normal_palette_line4, 7
   palptr Pal_SS4,   Normal_palette_line4, 7
   palptr Pal_SS5,   Normal_palette_line4, 7
   palptr Pal_SS6,   Normal_palette_line4, 7
   palptr Pal_SS7,   Normal_palette_line4, 7
   palptr Pal_UNK4,  Normal_palette_line4, 7
   palptr Pal_UNK5,  Normal_palette_line4, 7
   palptr Pal_UNK6,  Normal_palette_line4, 7
   palptr Pal_OOZ_B, Normal_palette_line2, 7
   palptr Pal_Menu,  Normal_palette, $1F
   palptr Pal_UNK7,  Normal_palette, $1F
index $28 to... >>>
   palptr Pal_Lev11,   Normal_palette_line2, $17
   palptr Pal_Lev12,   Normal_palette_line2, $17
   palptr Pal_Lev13,   Normal_palette_line2, $17
   palptr Pal_Lev14,   Normal_palette_line2, $17
   palptr Pal_Lev15,   Normal_palette_line2, $17
   palptr Pal_Lev16,   Normal_palette_line2, $17
   palptr Pal_Lev17,   Normal_palette_line2, $17
   palptr Pal_Lev18,   Normal_palette_line2, $17
   palptr Pal_Lev19,   Normal_palette_line2, $17
   palptr Pal_Lev1A,   Normal_palette_line2, $17
   palptr Pal_Lev1B,   Normal_palette_line2, $17
   palptr Pal_Lev1C,   Normal_palette_line2, $17
   palptr Pal_Lev1D,   Normal_palette_line2, $17
   palptr Pal_Lev1E,   Normal_palette_line2, $17
   palptr Pal_Lev1F,   Normal_palette_line2, $17
   palptr Pal_Lev20,   Normal_palette_line2, $17
----------------------------------------------------------------------------

Pal_SEGA: BINCLUDE "art/palettes/Sega screen.bin" ; SEGA screen palette (Sonic and initial background) Pal_Title: BINCLUDE "art/palettes/Title screen.bin" ; Title screen Palette Pal_UNK1: BINCLUDE "art/palettes/Unknown 1.bin" ; Unknown palette 1 (leftover S1 level select palette?) Pal_BGND: BINCLUDE "art/palettes/SonicAndTails.bin" ; "Sonic and Miles" background palette (also usually the primary palette line) Pal_EHZ: BINCLUDE "art/palettes/EHZ.bin" ; Emerald Hill Zone palette Pal_WZ: BINCLUDE "art/palettes/Wood Zone.bin" ; Wood Zone palette Pal_MTZ: BINCLUDE "art/palettes/MTZ.bin" ; Metropolis Zone palette Pal_WFZ: BINCLUDE "art/palettes/WFZ.bin" ; Wing Fortress Zone palette Pal_HTZ: BINCLUDE "art/palettes/HTZ.bin" ; Hill Top Zone palette Pal_HPZ: BINCLUDE "art/palettes/HPZ.bin" ; Hidden Palace Zone palette Pal_HPZ_U: BINCLUDE "art/palettes/HPZ underwater.bin" ; Hidden Palace Zone underwater palette Pal_OOZ: BINCLUDE "art/palettes/OOZ.bin" ; Oil Ocean Zone palette Pal_MCZ: BINCLUDE "art/palettes/MCZ.bin" ; Mystic Cave Zone palette Pal_CNZ: BINCLUDE "art/palettes/CNZ.bin" ; Casino Night Zone palette Pal_CPZ: BINCLUDE "art/palettes/CPZ.bin" ; Chemical Plant Zone palette Pal_CPZ_U: BINCLUDE "art/palettes/CPZ underwater.bin" ; Chemical Plant Zone underwater palette Pal_DEZ: BINCLUDE "art/palettes/DEZ.bin" ; Death Egg Zone palette Pal_ARZ: BINCLUDE "art/palettes/ARZ.bin" ; Aquatic Ruin Zone palette Pal_ARZ_U: BINCLUDE "art/palettes/ARZ underwater.bin" ; Aquatic Ruin Zone underwater palette Pal_SCZ: BINCLUDE "art/palettes/SCZ.bin" ; Sky Chase Zone palette

Pal_Lev11: BINCLUDE "art/palettes/Lev11.bin" ; New Level palette Pal_Lev12: BINCLUDE "art/palettes/Lev12.bin" ; New Level palette Pal_Lev13: BINCLUDE "art/palettes/Lev13.bin" ; New Level palette Pal_Lev14: BINCLUDE "art/palettes/Lev14.bin" ; New Level palette Pal_Lev15: BINCLUDE "art/palettes/Lev15.bin" ; New Level palette Pal_Lev16: BINCLUDE "art/palettes/Lev16.bin" ; New Level palette Pal_Lev17: BINCLUDE "art/palettes/Lev17.bin" ; New Level palette Pal_Lev18: BINCLUDE "art/palettes/Lev18.bin" ; New Level palette Pal_Lev19: BINCLUDE "art/palettes/Lev19.bin" ; New Level palette Pal_Lev1A: BINCLUDE "art/palettes/Lev1A.bin" ; New Level palette Pal_Lev1B: BINCLUDE "art/palettes/Lev1B.bin" ; New Level palette Pal_Lev1C: BINCLUDE "art/palettes/Lev1C.bin" ; New Level palette Pal_Lev1D: BINCLUDE "art/palettes/Lev1D.bin" ; New Level palette Pal_Lev1E: BINCLUDE "art/palettes/Lev1E.bin" ; New Level palette Pal_Lev1F: BINCLUDE "art/palettes/Lev1F.bin" ; New Level palette Pal_Lev20: BINCLUDE "art/palettes/Lev20.bin" ; New Level palette Pal_UNK2: BINCLUDE "art/palettes/Unknown 2.bin" ; Unknown palette 2 Pal_UNK3: BINCLUDE "art/palettes/Unknown 3.bin" ; Unknown palette 3 Pal_OOZ_B: BINCLUDE "art/palettes/OOZ Boss.bin" ; Oil Ocean Zone boss palette Pal_Menu: BINCLUDE "art/palettes/Menu.bin" ; Menu palette Pal_SS: BINCLUDE "art/palettes/Special Stage Main.bin" ; Special Stage palette Pal_SS1: BINCLUDE "art/palettes/Special Stage 1.bin" ; Special Stage 1 palette Pal_SS2: BINCLUDE "art/palettes/Special Stage 2.bin" ; Special Stage 2 palette Pal_SS3: BINCLUDE "art/palettes/Special Stage 3.bin" ; Special Stage 3 palette Pal_SS4: BINCLUDE "art/palettes/Special Stage 4.bin" ; Special Stage 4 palette Pal_SS5: BINCLUDE "art/palettes/Special Stage 5.bin" ; Special Stage 5 palette Pal_SS6: BINCLUDE "art/palettes/Special Stage 6.bin" ; Special Stage 6 palette Pal_SS7: BINCLUDE "art/palettes/Special Stage 7.bin" ; Special Stage 7 palette Pal_UNK4: BINCLUDE "art/palettes/Special Stage 1 2p.bin" ; Special Stage 1 2p palette Pal_UNK5: BINCLUDE "art/palettes/Special Stage 2 2p.bin" ; Special Stage 2 2p palette Pal_UNK6: BINCLUDE "art/palettes/Special Stage 3 2p.bin" ; Special Stage 3 2p palette Pal_UNK7: BINCLUDE "art/palettes/Special Stage Results Screen.bin" ; Special Stage Results Screen palette </asm>

That inserts our new palettes, which we will be using when we start on the main level load block.

Extending Zone Procedures and Scripts

Now we need to add the zone scripts.

Find: <asm> PLC_DYNANM:  ; Zone ID

   dc.w Dynamic_Normal-PLC_DYNANM    ; $00
   dc.w Animated_EHZ-PLC_DYNANM
   dc.w Dynamic_Null-PLC_DYNANM    ; $01
   dc.w Animated_Null-PLC_DYNANM
   dc.w Dynamic_Null-PLC_DYNANM    ; $02
   dc.w Animated_Null-PLC_DYNANM
   dc.w Dynamic_Null-PLC_DYNANM    ; $03
   dc.w Animated_Null-PLC_DYNANM
   dc.w Dynamic_Normal-PLC_DYNANM    ; $04
   dc.w Animated_MTZ-PLC_DYNANM
   dc.w Dynamic_Normal-PLC_DYNANM    ; $05
   dc.w Animated_MTZ-PLC_DYNANM
   dc.w Dynamic_Null-PLC_DYNANM    ; $06
   dc.w Animated_Null-PLC_DYNANM
   dc.w Dynamic_HTZ-PLC_DYNANM    ; $07
   dc.w Animated_HTZ-PLC_DYNANM
   dc.w Dynamic_Normal-PLC_DYNANM    ; $08
   dc.w Animated_OOZ-PLC_DYNANM
   dc.w Dynamic_Null-PLC_DYNANM    ; $09
   dc.w Animated_Null-PLC_DYNANM
   dc.w Dynamic_Normal-PLC_DYNANM    ; $0A
   dc.w Animated_OOZ2-PLC_DYNANM
   dc.w Dynamic_Null-PLC_DYNANM    ; $0B
   dc.w Animated_Null-PLC_DYNANM
   dc.w Dynamic_CNZ-PLC_DYNANM    ; $0C
   dc.w Animated_CNZ-PLC_DYNANM
   dc.w Dynamic_Normal-PLC_DYNANM    ; $0D
   dc.w Animated_CPZ-PLC_DYNANM
   dc.w Dynamic_Normal-PLC_DYNANM    ; $0F
   dc.w Animated_DEZ-PLC_DYNANM
   dc.w Dynamic_ARZ-PLC_DYNANM    ; $10
   dc.w Animated_ARZ-PLC_DYNANM
   dc.w Dynamic_Null-PLC_DYNANM    ; $11
   dc.w Animated_Null-PLC_DYNANM    ; yes, level $11

</asm>

Since this may be confusing, and to better organize our data, change this to: <asm> PLC_DYNANM:  ; Zone ID

   dc.w    Dynamic_Normal - PLC_DYNANM,    Animated_EHZ  - PLC_DYNANM    ;00
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;01
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;02
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;03
   dc.w    Dynamic_Normal - PLC_DYNANM,    Animated_MTZ  - PLC_DYNANM    ;04
   dc.w    Dynamic_Normal - PLC_DYNANM,    Animated_MTZ  - PLC_DYNANM    ;05
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;06
   dc.w    Dynamic_HTZ    - PLC_DYNANM,    Animated_HTZ  - PLC_DYNANM    ;07
   dc.w    Dynamic_Normal - PLC_DYNANM,    Animated_OOZ  - PLC_DYNANM    ;08
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;09
   dc.w    Dynamic_Normal - PLC_DYNANM,    Animated_OOZ2 - PLC_DYNANM    ;0A
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;0B
   dc.w    Dynamic_CNZ    - PLC_DYNANM,    Animated_CNZ  - PLC_DYNANM    ;0C
   dc.w    Dynamic_Normal - PLC_DYNANM,    Animated_CPZ  - PLC_DYNANM    ;0D
   dc.w    Dynamic_Normal - PLC_DYNANM,    Animated_DEZ  - PLC_DYNANM    ;0E
   dc.w    Dynamic_ARZ    - PLC_DYNANM,    Animated_ARZ  - PLC_DYNANM    ;0F
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;10
   
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;11
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;12
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;13
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;14
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;15
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;16
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;17
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;18
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;19
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;1A
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;1B
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;1C
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;1D
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;1E
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;1F
   dc.w    Dynamic_Null   - PLC_DYNANM,    Animated_Null - PLC_DYNANM    ;20

</asm>

This calls scripts for the new levels. To make complex animations (like the HPZ pulsing ball) you will need to create a Anim*level*.bin and add it to the Anim*level*.bin files and add it to the animated pattern mappings. See the section below.

Extending Animated Pattern Mappings

Find: <asm> AnimPatMaps:

   dc.w APM16_EHZ - AnimPatMaps ;  0
   dc.w APM_Null - AnimPatMaps  ;  1
   dc.w APM_Null - AnimPatMaps  ;  2
   dc.w APM_Null - AnimPatMaps  ;  3
   dc.w APM16_MTZ - AnimPatMaps ;  4
   dc.w APM16_MTZ - AnimPatMaps ;  5
   dc.w APM_Null - AnimPatMaps  ;  6
   dc.w APM16_EHZ - AnimPatMaps ;  7
   dc.w APM_HPZ - AnimPatMaps   ;  8
   dc.w APM_Null - AnimPatMaps  ;  9
   dc.w APM_OOZ - AnimPatMaps   ; $A
   dc.w APM_Null - AnimPatMaps  ; $B
   dc.w APM_CNZ - AnimPatMaps   ; $C
   dc.w APM_CPZ - AnimPatMaps   ; $D
   dc.w APM_DEZ - AnimPatMaps   ; $E
   dc.w APM_ARZ - AnimPatMaps   ; $F
   dc.w APM_Null - AnimPatMaps  ;$10

</asm>

And change it to: <asm> AnimPatMaps:

   dc.w APM16_EHZ - AnimPatMaps    ;  0
   dc.w APM_Null  - AnimPatMaps    ;  1
   dc.w APM_Null  - AnimPatMaps    ;  2
   dc.w APM_Null  - AnimPatMaps    ;  3
   dc.w APM16_MTZ - AnimPatMaps    ;  4
   dc.w APM16_MTZ - AnimPatMaps    ;  5
   dc.w APM_Null  - AnimPatMaps    ;  6
   dc.w APM16_EHZ - AnimPatMaps    ;  7
   dc.w APM_HPZ   - AnimPatMaps    ;  8
   dc.w APM_Null  - AnimPatMaps    ;  9
   dc.w APM_OOZ   - AnimPatMaps    ; $A
   dc.w APM_Null  - AnimPatMaps    ; $B
   dc.w APM_CNZ   - AnimPatMaps    ; $C
   dc.w APM_CPZ   - AnimPatMaps    ; $D
   dc.w APM_DEZ   - AnimPatMaps    ; $E
   dc.w APM_ARZ   - AnimPatMaps    ; $F
   dc.w APM_Null  - AnimPatMaps    ;$10
   
   dc.w APM_Null  - AnimPatMaps    ;$11
   dc.w APM_Null  - AnimPatMaps    ;$12
   dc.w APM_Null  - AnimPatMaps    ;$13
   dc.w APM_Null  - AnimPatMaps    ;$14
   dc.w APM_Null  - AnimPatMaps    ;$15
   dc.w APM_Null  - AnimPatMaps    ;$16
   dc.w APM_Null  - AnimPatMaps    ;$17
   dc.w APM_Null  - AnimPatMaps    ;$18
   dc.w APM_Null  - AnimPatMaps    ;$19
   dc.w APM_Null  - AnimPatMaps    ;$1A
   dc.w APM_Null  - AnimPatMaps    ;$1B
   dc.w APM_Null  - AnimPatMaps    ;$1C
   dc.w APM_Null  - AnimPatMaps    ;$1D
   dc.w APM_Null  - AnimPatMaps    ;$1E
   dc.w APM_Null  - AnimPatMaps    ;$1F
   dc.w APM_Null  - AnimPatMaps    ;$20

</asm>

then edit and change as needed.

Extending the 1 Player and 2 Player music playlists

Instead of doing this here, we should take this procedure to a better place, since any table data addition here will cause a crash during building. Find this: <asm>

loc_40AE

Level_GetBgm:

   tst.w    (Demo_mode_flag).w
   bmi.s    loc_4114
   moveq    #0,d0
   move.b    (Current_Zone).w,d0
   lea    MusicList(pc),a1
   tst.w    (Two_player_mode).w
   beq.s    Level_PlayBgm
   lea    MusicList2(pc),a1

</asm>

and replace it with: <asm>

loc_40AE

Level_GetBgm:

   tst.w    (Demo_mode_flag).w
   bmi.s    loc_4114
   jmp    BuscarMusica
   rts

</asm>

Then, add this to the end of the disassembly: <asm>

   align    $10

BuscarMusica:

   moveq    #0,d0
   move.w    (Current_Zone).w,d0
   ror.b    #1,d0
   lsr.w    #6,d0
   lea    (NormalGameMusic).l,a1
   move.w    (a1,d0.w),d0
   tst.b    (Two_Player_Mode).w
   beq.s    Level_Music_Done
   lea    (GameMusic2P).l,a1
   move.w    (a1,d0.w),d0

Level_Music_Done:

   move.w    d0,(Level_Music).w    ; store level music
   bsr.w    J_F100_PlayMusic    ; play level music
   move.b    #$34,(Object_RAM+$80).w ; load Obj34 (level title card) at $FFFFB080
   jmp    Level_TtlCard
   rts
   

J_F100_PlayMusic:

   jmp    PlayMusic
   rts
   

NormalGameMusic:

   dc.w    $82, $82    ;00
   dc.w    $82, $82    ;01
   dc.w    $82, $82    ;02
   dc.w    $82, $82    ;03
   dc.w    $85, $85    ;04
   dc.w    $85, $85    ;05
   dc.w    $8F, $8F    ;06
   dc.w    $86, $86    ;07
   dc.w    $82, $82    ;08
   dc.w    $82, $82    ;09
   dc.w    $84, $84    ;0A
   dc.w    $8B, $8B    ;0B
   dc.w    $89, $89    ;0C
   dc.w    $8E, $8E    ;0D
   dc.w    $8A, $8A    ;0E
   dc.w    $87, $87    ;0F
   dc.w    $8D, $8D    ;10
   dc.w    $01, $02    ;11
   dc.w    $03, $03    ;12
   dc.w    $87, $87    ;13
   dc.w    $82, $82    ;14
   dc.w    $82, $82    ;15
   dc.w    $82, $82    ;16
   dc.w    $82, $82    ;17
   dc.w    $82, $82    ;18
   dc.w    $82, $82    ;19
   dc.w    $82, $82    ;1A
   dc.w    $82, $82    ;1B
   dc.w    $82, $82    ;1C
   dc.w    $82, $82    ;1D
   dc.w    $82, $82    ;1E
   dc.w    $82, $82    ;1F
   dc.w    $82, $82    ;20

GameMusic2P:

   dc.w    $8C, $8C    ;00
   dc.w    $8C, $8C    ;01
   dc.w    $8C, $8C    ;02
   dc.w    $8C, $8C    ;03
   dc.w    $85, $85    ;04
   dc.w    $85, $85    ;05
   dc.w    $8F, $8F    ;06
   dc.w    $86, $86    ;07
   dc.w    $8C, $8C    ;08
   dc.w    $8C, $8C    ;09
   dc.w    $84, $84    ;0A
   dc.w    $83, $83    ;0B
   dc.w    $88, $88    ;0C
   dc.w    $8E, $8E    ;0D
   dc.w    $8A, $8A    ;0E
   dc.w    $87, $87    ;0F
   dc.w    $8D, $8D    ;10
   dc.w    $8C, $8C    ;11
   dc.w    $8C, $8C    ;12
   dc.w    $8C, $8C    ;13
   dc.w    $8C, $8C    ;14
   dc.w    $8C, $8C    ;15
   dc.w    $8C, $8C    ;16
   dc.w    $8C, $8C    ;17
   dc.w    $8C, $8C    ;18
   dc.w    $8C, $8C    ;19
   dc.w    $8C, $8C    ;1A
   dc.w    $8C, $8C    ;1B
   dc.w    $8C, $8C    ;1C
   dc.w    $8C, $8C    ;1D
   dc.w    $8C, $8C    ;1E
   dc.w    $8C, $8C    ;1F
   dc.w    $8C, $8C    ;20

</asm>

If you noticed, we changed the data table, allowing it to load a music per act, although its main identifier is "Current_Zone". That updates our music list for both 2 player and 1 player modes, and fixes an error that sometimes occurs during the build process relating to somwthing not fitting in a signed byte, which can easily happen when you have a lot of added zones.

Branch fixes

We should not have any kind of build errors here, since we moved most of our routines to the end of the disassembly. Anyway, if you got some "jump distance too big" errors, fix them:.

Fixing Addressing

Because of our work being put mostly at the end of the disassembly, I really don't know what routines could claim for an addressing issue. You should look for the errors shown in your disassembly after all the work already done.

Extending the demo list

now we will prepare everything so that we can put in new demo files for our new levels.

find: <asm>; off_4948: DemoScriptPointers:

   dc.l Demo_EHZ    ; $00
   dc.l Demo_EHZ    ; $01
   dc.l Demo_EHZ    ; $02
   dc.l Demo_EHZ    ; $03
   dc.l Demo_EHZ    ; $04
   dc.l Demo_EHZ    ; $05
   dc.l Demo_EHZ    ; $06
   dc.l Demo_EHZ    ; $07
   dc.l Demo_EHZ    ; $08
   dc.l Demo_EHZ    ; $09
   dc.l Demo_EHZ    ; $0A
   dc.l Demo_EHZ    ; $0B
   dc.l Demo_CNZ    ; $0C
   dc.l Demo_CPZ    ; $0D
   dc.l Demo_EHZ    ; $0E
   dc.l Demo_ARZ    ; $0F
   dc.l Demo_EHZ    ; $10

</asm>

and insert after it: <asm>

   dc.l Demo_EHZ    ; $11
   dc.l Demo_EHZ    ; $12
   dc.l Demo_EHZ    ; $13
   dc.l Demo_EHZ    ; $14
   dc.l Demo_EHZ    ; $15
   dc.l Demo_EHZ    ; $16
   dc.l Demo_EHZ    ; $17
   dc.l Demo_EHZ    ; $18
   dc.l Demo_EHZ    ; $19
   dc.l Demo_EHZ    ; $1A
   dc.l Demo_EHZ    ; $1B
   dc.l Demo_EHZ    ; $1C
   dc.l Demo_EHZ    ; $1D
   dc.l Demo_EHZ    ; $1E
   dc.l Demo_EHZ    ; $1F
   dc.l Demo_EHZ    ; $20

</asm>

Extending the Collision index

You would want solidity in your new zones, wouldn't you? Here we will extend the solidity list so that our extra levels can have solid ground for that blue hedgehog to walk on. We will develop here another way of loading those collisions. Find: <asm> LoadCollisionIndexes:

   moveq    #0,d0
   move.b    (Current_Zone).w,d0
   lsl.w    #2,d0
   move.l    #Primary_Collision,(Collision_addr).w
   move.w    d0,-(sp)
   movea.l    Off_ColP(pc,d0.w),a0
   lea    (Primary_Collision).w,a1
   bsr.w    KosDec
   move.w    (sp)+,d0
   movea.l    Off_ColS(pc,d0.w),a0
   lea    (Secondary_Collision).w,a1
   bra.w    KosDec
End of function LoadCollisionIndexes

</asm>

And change this to: <asm> LoadCollisionIndexes:

   jmp    CarregarColisoes
   rts

</asm>

Then, add this routine to the end of your disassembly (or everywhere you think this won't give trouble): <asm>

   align    $10
   

CarregarColisoes:

   move.w  (Current_ZoneAndAct).w,d0
   ror.b   #1,d0
   lsr.w   #4,d0
   move.l    #Primary_Collision,(Collision_addr).w

LoadPrimaryCollisionData:

   movea.l CollisionData(pc,d0.w),a0
   lea     (Primary_Collision).w,a1
   bsr.w    Jump_KosDec_X0
   

LoadSecondaryCollisionData:

   movea.l CollisionData+4(pc,d0.w),a0
   lea     (Secondary_Collision).w,a1
   bsr.w    Jump_KosDec_X0
       
   rts
   align 4

Jump_KosDec_X0:

   jmp    KosDec
   rts


CollisionData:

   ; FORMAT: dc.l PrimaryCollision, SecondaryCollision
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;00-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;00-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;01-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;01-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;02-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;02-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;03-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;03-01
   dc.l    ColP_MTZ, ColP_MTZ    ;04-00
   dc.l    ColP_MTZ, ColP_MTZ    ;04-01
   dc.l    ColP_MTZ, ColP_MTZ    ;05-00
   dc.l    ColP_MTZ, ColP_MTZ    ;05-01
   dc.l    ColP_WFZSCZ, ColS_WFZSCZ    ;06-00
   dc.l    ColP_WFZSCZ, ColS_WFZSCZ    ;06-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;07-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;07-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;08-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;08-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;09-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;09-01
   dc.l    ColP_OOZ, ColP_OOZ    ;0A-00
   dc.l    ColP_OOZ, ColP_OOZ    ;0A-01
   dc.l    ColP_MCZ, ColP_MCZ    ;0B-00
   dc.l    ColP_MCZ, ColP_MCZ    ;0B-01
   dc.l    ColP_CNZ, ColS_CNZ    ;0C-00
   dc.l    ColP_CNZ, ColS_CNZ    ;0C-01
   dc.l    ColP_CPZDEZ, ColS_CPZDEZ    ;0D-00
   dc.l    ColP_CPZDEZ, ColS_CPZDEZ    ;0D-01
   dc.l    ColP_CPZDEZ, ColS_CPZDEZ    ;0E-00
   dc.l    ColP_CPZDEZ, ColS_CPZDEZ    ;0E-01
   dc.l    ColP_ARZ, ColS_ARZ    ;0F-00
   dc.l    ColP_ARZ, ColS_ARZ    ;0F-01
   dc.l    ColP_WFZSCZ, ColS_WFZSCZ    ;10-00
   dc.l    ColP_WFZSCZ, ColS_WFZSCZ    ;10-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;11-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;11-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;12-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;12-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;13-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;13-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;14-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;14-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;15-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;15-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;16-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;16-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;17-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;17-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;18-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;18-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;19-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;19-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;1A-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;1A-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;1B-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;1B-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;1C-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;1C-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;1D-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;1D-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;1E-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;1E-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;1F-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;1F-01
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;20-00
   dc.l    ColP_EHZHTZ, ColS_EHZHTZ    ;20-01

</asm>

This way, we can simply fix the indexes to suit our needs. If you want to work with decompressed collision indexes, you can change the lines <asm>

   bsr.w    Jump_KosDec_X0

</asm>

to <asm>

   move.w  #$180,d7

-

   move.w  (a0)+,(a1)+
   dbf     d7,-

</asm>

And get rid of that KosDec jump.