byte_2BDDA: dc.b 5, 1 dc.b 0, 3 dc.b 5, 1 dc.b 0, 5 dc.b 6, 5 dc.b 2, 3 dc.b 6, 1 dc.b 6, 5 dc.b 6, 5 dc.b 6, 5 dc.b 6, 5 dc.b 6, 5 dc.b 6, 5This is actually a very dangerous byte array! When the animal object is first initialized, it uses the value of the current zone, plus the value in register d0 (which is randomly set to either 0 or 1), to index the byte_2BDDA array, and put the resulting byte into offset $30 of its own SST:
loc_2BF4A: moveq #0,d1 move.b (Current_zone).w,d1 add.w d1,d1 add.w d0,d1 lea byte_2BDDA,a1 move.b (a1,d1.w),d0 move.b d0,$30(a0)Then at loc_2BFEA, after the animal first lands on the floor, it feeds this value into the routine counter at offset 5 of its own SST, in order to determine whether it should hop or fly away:
move.b $30(a0),d0 add.b d0,d0 addq.b #4,d0 move.b d0,5(a0)It is therefore vital that the byte_2BDDA array contain two entries for each level in the game, as these determine which two animals may spawn in any given stage. With Sonic 3 in particular, every stage past Launch Base Zone reuses the same animal combination as Flying Battery Zone. In Sonic & Knuckles, only Doomsday Zone retains this property.
byte_2BDDA: dc.b 5, 1 ; AIZ byte_2C7BA: dc.b 5, 1 ; AIZ dc.b 0, 3 ; HCZ dc.b 0, 3 ; HCZ dc.b 5, 1 ; MGZ dc.b 5, 1 ; MGZ dc.b 0, 5 ; CNZ dc.b 0, 5 ; CNZ dc.b 6, 5 ; FBZ dc.b 6, 5 ; FBZ dc.b 2, 3 ; ICZ dc.b 2, 3 ; ICZ dc.b 6, 1 ; LBZ dc.b 5, 1 ; LBZ dc.b 6, 5 ; MHZ dc.b 6, 1 ; MHZ dc.b 6, 5 ; SOZ dc.b 0, 1 ; SOZ dc.b 6, 5 ; LRZ dc.b 5, 1 ; LRZ dc.b 6, 5 ; SSZ dc.b 0, 5 ; SSZ dc.b 6, 5 ; DEZ dc.b 6, 1 ; DEZ dc.b 6, 5 ; DDZ dc.b 6, 5 ; DDZ dc.b 5, 1 ; Ending dc.b 5, 1 ; ALZ dc.b 5, 1 ; BPZ dc.b 5, 1 ; DPZ dc.b 5, 1 ; CGZ dc.b 5, 1 ; EMZ dc.b 5, 1 ; Gumball dc.b 5, 1 ; Pachinko dc.b 5, 1 ; Slots dc.b 5, 1 ; LRZ Boss dc.b 5, 1 ; DEZ BossInterestingly, in Sonic & Knuckles, the array was extended to cover every level slot, rather than stopping at Doomsday Zone. This was probably done for the sake of the Lava Reef Zone boss act, in which animals spawn from the capsule at the very end of the stage. Indeed, if we look at the numbers, all of the new entries in the array use the same animal combination as Lava Reef Zone.
The length of this array in Sonic 3 suggests that attempting to load any level slot beyond Doomsday Zone is inherently dangerous. But in reality, it only becomes a problem if an animal is spawned while playing the stage; it shouldn't affect whether the stage can load or not.
What does affect it are the animals' graphics, which are loaded by the PLCLoad_AnimalsAndExplosion function at $543F4 when the level starts. Much like the animal object, it uses the value of the current zone as an offset to an array, which contains pointers to the PLCs for each stage's combination of animals.
And therein lies the rub, because in Sonic 3, this array only goes up to Launch Base Zone:
off_54414: dc.w PLC_54422-off_54414 ; AIZ off_85FFE: dc.w PLC_8602E-off_85FFE ; AIZ dc.w PLC_54430-off_54414 ; HCZ dc.w PLC_8603C-off_85FFE ; HCZ dc.w PLC_5443E-off_54414 ; MGZ dc.w PLC_8604A-off_85FFE ; MGZ dc.w PLC_5444C-off_54414 ; CNZ dc.w PLC_86058-off_85FFE ; CNZ dc.w PLC_5445A-off_54414 ; FBZ dc.w PLC_86066-off_85FFE ; FBZ dc.w PLC_54468-off_54414 ; ICZ dc.w PLC_86074-off_85FFE ; ICZ dc.w PLC_54476-off_54414 ; LBZ dc.w PLC_86082-off_85FFE ; LBZ dc.w PLC_86090-off_85FFE ; MHZ dc.w PLC_8609E-off_85FFE ; SOZ dc.w PLC_860AC-off_85FFE ; LRZ dc.w PLC_860BA-off_85FFE ; SSZ dc.w PLC_860C8-off_85FFE ; DEZ dc.w PLC_860D6-off_85FFE ; DDZ dc.w PLC_860E4-off_85FFE ; Ending dc.w PLC_860E4-off_85FFE ; ALZ dc.w PLC_860E4-off_85FFE ; BPZ dc.w PLC_860E4-off_85FFE ; DPZ dc.w PLC_860E4-off_85FFE ; CGZ dc.w PLC_860E4-off_85FFE ; EMZ dc.w PLC_860E4-off_85FFE ; Gumball dc.w PLC_860E4-off_85FFE ; Pachinko dc.w PLC_860E4-off_85FFE ; Slots dc.w PLC_860E4-off_85FFE ; LRZ Boss dc.w PLC_860E4-off_85FFE ; DEZ Boss PLC_54422: dc.w 1 PLC_8602E: dc.w 1 dc.l ArtNem_BlueFlicky dc.l ArtNem_BlueFlicky dc.w $B000 dc.w $B000 dc.l ArtNem_Chicken dc.l ArtNem_Chicken dc.w $B240 dc.w $B240 PLC_54430: dc.w 1 PLC_8603C: dc.w 1 dc.l ArtNem_Rabbit dc.l ArtNem_Rabbit dc.w $B000 dc.w $B000 dc.l ArtNem_Seal dc.l ArtNem_Seal dc.w $B240 dc.w $B240 PLC_5443E: dc.w 1 PLC_8604A: dc.w 1 dc.l ArtNem_BlueFlicky dc.l ArtNem_BlueFlicky dc.w $B000 dc.w $B000 dc.l ArtNem_Chicken dc.l ArtNem_Chicken dc.w $B240 dc.w $B240 PLC_5444C: dc.w 1 PLC_86058: dc.w 1 dc.l ArtNem_Rabbit dc.l ArtNem_Rabbit dc.w $B000 dc.w $B000 dc.l ArtNem_BlueFlicky dc.l ArtNem_BlueFlicky dc.w $B240 dc.w $B240 PLC_5445A: dc.w 1 PLC_86066: dc.w 1 dc.l ArtNem_Squirrel dc.l ArtNem_Squirrel dc.w $B000 dc.w $B000 dc.l ArtNem_BlueFlicky dc.l ArtNem_BlueFlicky dc.w $B240 dc.w $B240 PLC_54468: dc.w 1 PLC_86074: dc.w 1 dc.l ArtNem_Penguin dc.l ArtNem_Penguin dc.w $B000 dc.w $B000 dc.l ArtNem_Seal dc.l ArtNem_Seal dc.w $B240 dc.w $B240 PLC_54476: dc.w 1 PLC_86082: dc.w 1 dc.l ArtNem_Squirrel dc.l ArtNem_BlueFlicky dc.w $B000 dc.w $B000 dc.l ArtNem_Chicken dc.l ArtNem_Chicken dc.w $B240 dc.w $B240 PLC_86090: dc.w 1 dc.l ArtNem_Squirrel dc.w $B000 dc.l ArtNem_Chicken dc.w $B240 PLC_8609E: dc.w 1 dc.l ArtNem_Rabbit dc.w $B000 dc.l ArtNem_Chicken dc.w $B240 PLC_860AC: dc.w 1 dc.l ArtNem_BlueFlicky dc.w $B000 dc.l ArtNem_Chicken dc.w $B240 PLC_860BA: dc.w 1 dc.l ArtNem_Rabbit dc.w $B000 dc.l ArtNem_Chicken dc.w $B240 PLC_860C8: dc.w 1 dc.l ArtNem_Squirrel dc.w $B000 dc.l ArtNem_Chicken dc.w $B240 PLC_860D6: dc.w 1 dc.l ArtNem_Squirrel dc.w $B000 dc.l ArtNem_Chicken dc.w $B240 PLC_860E4: dc.w 1 dc.l ArtNem_BlueFlicky dc.w $B000 dc.l ArtNem_Chicken dc.w $B240So even if we were to fix up the level load block for the Sonic & Knuckles stages, the PLCLoad_AnimalsAndExplosion function would then take the value of the current zone, go past the end of the pointer array straight into the actual PLC definitions, and eventually attempt to load a nonsensical PLC, which would most definitely crash the game. Huzzah!
PLC_54476: dc.w 1 PLC_86082: dc.w 1 dc.l ArtNem_Squirrel dc.l ArtNem_BlueFlicky dc.w $B000 dc.w $B000 dc.l ArtNem_Chicken dc.l ArtNem_Chicken dc.w $B240 dc.w $B240It was only by looking at the animal data side-by-side like this that I stumbled upon one of the most obscure differences between Sonic 3 and Sonic & Knuckles that I know of. In Sonic 3, the animals which appear in Launch Base Zone are Ricky (the squirrel) and Cucky (the chicken). In Sonic & Knuckles however, Ricky was replaced by Flicky (the flicky).
This wasn't an accident; if you check the byte_2BDDA array at the top of this post, you'll see that the animal type was changed from 6 to 5 there, too.
Finally, on the subject of animal types, here's something that always bugged me. In Sonic 1, there were seven different animals. From left to right, they are: Pocky, Cucky, Pecky, Rocky, Picky, Flicky and Ricky.
Sonic 2 then added five more, whose names I can't find a source for: an eagle, a mouse, a monkey, a turtle and a bear.
When it came time to make Sonic 3, the developers decided to scale back to the original cast of animals. Indeed, if you look at the byte_2BDDA array, you'll find that they're numbered 0 through 6... but animal 4 is nowhere to be seen.
Picky appears to have disappeared; not even his graphics can be found within the ROM. Maybe he's still hiding in the Casino Night Zone?
The Sonic 2 animals are, from left to right, Locky, Micky (this name only seems to exist in Sonic Mania's code), Wocky, Tocky, and Becky.
ReplyDeleteGiven the color differences between the Sonic 1 and 2 animals, I assume they couldn't get Picky to use a sensible color scheme.
Where do those names come from, though?
DeleteAnimals use the player palette in all three games; all of the necessary colors are right there. I mean, Ricky uses the same exact shades as Picky, for crying out loud.
well picky was technically unused in sonic 2 due to being in death egg zones code
DeleteI know you're busy, but I figured it can't hurt to ask. I can't remember if I did before but, can you possibly share any insight as to the crazy boss room behavior shown here? https://youtu.be/0Z1o6_fqGJE?t=5m49s
ReplyDeleteThere are no hacking solutions to add any missing animals from Sonic 1 and Sonic 2 in the Sonic 3 & Knuckles rom?
ReplyDeleteWhat do you mean, 'hacking solutions'? You can do whatever you want with a disassembly, but there is no tool that will help you write the necessary code.
DeleteAlso, an update: Picky is in the ROM after all! Turns out he was just hiding behind Rocky.
That's what I meant yes, write the code with a disassembly, thank you that means we can, but why no one tried with all that has been done in many rom-hacks ?
DeleteThere aren't that many S3 hacks to begin with! Off the top of my head:
Delete- S3K: The Challenges
- S3: D.A. Garden Edition
- Sonic 3 Complete, and more recently
- S3&K Battle Race
And I guess the creators behind those hacks simply never changed the animals in any meaningful way.
https://tcrf.net/File:Sonic3PickyUnused.png Looks like Picky sprites were in the Sonic 3 ROM. They STILL go unused
ReplyDelete