AgentSkillsCN

S3k Disasm Guide

S3k disasm 指南

SKILL.md

s3k-disasm Navigation Guide

This skill provides guidance on finding, identifying, and interpreting items in the Sonic 3 & Knuckles disassembly (docs/skdisasm/).

Directory Structure

S3K is organized very differently from S1/S2 — per-zone directories under Levels/:

DirectoryContentsNotes
Levels/{ZONE}/Per-zone dataAIZ, HCZ, MGZ, CNZ, FBZ, ICZ, LBZ, MHZ, SOZ, LRZ, HPZ, SSZ, DEZ, DDZ
Levels/{ZONE}/KosinskiM Art/Kosinski Moduled compressed artPrimary art compression type
Levels/{ZONE}/Nemesis Art/Nemesis compressed artSecondary art compression
Levels/{ZONE}/Tiles/Raw tile patternsUncompressed tile data
Levels/{ZONE}/Blocks/16x16 block mappingsPer-zone chunk definitions
Levels/{ZONE}/Chunks/128x128 chunk mappingsPer-zone block definitions
Levels/{ZONE}/Layout/Level layouts1.bin, 2.bin per act
Levels/{ZONE}/Object Pos/Object placementPer-act object positions
Levels/{ZONE}/Ring Pos/Ring placementPer-act ring positions
Levels/{ZONE}/Palettes/Zone palettesZone-specific color data
Levels/{ZONE}/Collision/Collision dataZone collision indices
Levels/{ZONE}/Misc Object Data/Zone-specific object maps/animsMap - Name.asm, Anim - Name.asm
General/Sprites/{NAME}/Shared sprite dataArt/, Map, DPLC, Anim files
Sound/Z80 sound driverSMPS audio data

Key Source Files

FileContents
sonic3k.asmMain assembly source (~203K lines, all object code inline)
sonic3k.constants.asmRAM addresses, object field names
sonic3k.macros.asmAssembly macros
s3.asmSonic 3 standalone variant

Compression Types

TypeDirectory/Label SuffixTool FlagDescription
Kosinski ModuledKosinskiM Art/, _KosM suffixkosmPrimary art compression (dominant in S3K)
NemesisNemesis Art/, ArtNem_ prefixnemSecondary art compression
KosinskiArtKos_ prefixkosUsed for some shared data
UncompressedVarious .binbinRaw tile data, palettes

Note: S3K encodes compression type in the label suffix (e.g., AIZ1_8x8_Primary_KosM) rather than the file extension. The RomOffsetFinder tool auto-infers the correct type from the label when the file extension is .bin.

Finding Items with RomOffsetFinder

Important: All RomOffsetFinder commands for Sonic 3 & Knuckles require the --game s3k flag.

Search Command (Most Common)

bash
# Search by partial name
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k search AIZ" -q

# Search for zone-specific items
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k search MHZ" -q

# Search for palettes
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k search Pal_" -q

# Search for specific object art
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k search ArtKosM_" -q

List Command

bash
# List all Nemesis-compressed items
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k list nem" -q

# List all Kosinski Moduled items
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k list kosm" -q

# List all compression types
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k list" -q

Verify and Export

bash
# Verify a single offset
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k verify ArtNem_TitleScreenText" -q

# Batch verify all Nemesis items
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k verify-batch nem" -q

# Export as Java constants
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k export nem ART_" -q

Label Naming Conventions

S3K uses different label prefixes from S1 and S2:

S3K PrefixMeaningExample
ArtKosM_Kosinski Moduled artArtKosM_AIZEndBoss
ArtNem_Nemesis artArtNem_TitleScreenText
ArtKos_Kosinski artArtKos_LevelResults
Pal_PalettePal_AIZ1, Pal_Sonic
AnPal_Animated paletteAnPal_AIZ1
Obj_Object codeObj_AIZEndBoss
Map_ / Map -Sprite mappingsIn General/Sprites/ or Misc Object Data/
DPLC_Dynamic Pattern Load CueIn General/Sprites/
Anim_ / Anim -Animation scriptsIn General/Sprites/ or Misc Object Data/
PLC_Pattern Load CuePLC_AIZ

Comparison with S1 and S2

S3K PrefixS2 EquivalentS1 Equivalent
ArtKosM_(no equivalent)(no equivalent)
ArtNem_ArtNem_Nem_
ArtKos_ArtKos_Kos_
Pal_Pal_Pal_
AnPal_(inline cycling)(inline cycling)
Obj_Obj_ObjXX / Obj_
Map_MapUnc_Map_
DPLC_(inline)DPLC_

Zone Abbreviations

AbbrevFull NameZone ID
AIZAngel Island Zone0x00
HCZHydrocity Zone0x01
MGZMarble Garden Zone0x02
CNZCarnival Night Zone0x03
FBZFlying Battery Zone0x04
ICZIcecap Zone0x05
LBZLaunch Base Zone0x06
MHZMushroom Hill Zone0x07
SOZSandopolis Zone0x08
LRZLava Reef Zone0x09
SSZSky Sanctuary Zone0x0A
DEZDeath Egg Zone0x0B
DDZDoomsday Zone0x0C
HPZHidden Palace Zone0x0D

Bonus/Special Zones

AbbrevFull NameNotes
GumballGumball MachineBonus stage
PachinkoPachinkoBonus stage
SlotsSlot MachineBonus stage
CGZChrome Gadget ZoneS3-only
BPZBalloon Park ZoneS3-only
DPZDesert Palace ZoneS3-only
EMZEndless Mine ZoneS3-only
ALZAzure Lake ZoneS3-only competition

Object Code Organization

Unlike S1 (separate files per object) and S2 (inline in s2.asm), S3K objects are:

  • Inline in sonic3k.asm as Obj_ routines
  • Zone-specific objects appear near their zone's code section
  • Shared sprites have data in General/Sprites/{Name}/ (Art, Map, DPLC, Anim)
  • Zone-specific maps/anims are in Levels/{ZONE}/Misc Object Data/

Finding Object Code

bash
# Search for object by name in the main ASM
grep -n "Obj_AIZEndBoss" docs/skdisasm/sonic3k.asm

# Search for all objects in a zone
grep -n "Obj_AIZ" docs/skdisasm/sonic3k.asm

# Find object sprite data
ls docs/skdisasm/General/Sprites/
ls "docs/skdisasm/Levels/AIZ/Misc Object Data/"

Object File Locations

Data TypeLocationExample
Object codesonic3k.asm (inline)Obj_AIZEndBoss:
Shared sprite artGeneral/Sprites/{Name}/Art/General/Sprites/Rhinobot/Art/
Shared sprite mapsGeneral/Sprites/{Name}/MapGeneral/Sprites/Rhinobot/Map - Rhinobot.asm
Shared sprite DPLCGeneral/Sprites/{Name}/DPLCGeneral/Sprites/Rhinobot/DPLC - Rhinobot.asm
Shared sprite animGeneral/Sprites/{Name}/AnimGeneral/Sprites/Rhinobot/Anim - Rhinobot.asm
Zone-specific mapsLevels/{ZONE}/Misc Object Data/Levels/AIZ/Misc Object Data/Map - Zipline.asm
Zone-specific animLevels/{ZONE}/Misc Object Data/Levels/AIZ/Misc Object Data/Anim - Zipline.asm

Object System Reference

Object Status Table Offsets

S3K uses S2-style field names (same as S2, different from S1):

FieldOffsetSizeDescription
code0x00longObject code pointer
render_flags0x04byteRender flags
routine0x05byteCurrent routine
height_pixels0x06byteSprite height
width_pixels0x07byteSprite width
x_pos0x10word/longX position
y_pos0x14word/longY position
x_vel0x18wordX velocity
y_vel0x1AwordY velocity
mapping_frame0x22byteCurrent frame
routine0x24byteCurrent routine (alternate ref)
collision_flags0x28byteTT SSSSSS (type + size)
collision_property0x29byteHit count for bosses
shield_reaction0x2BbyteShield-specific reactions (S3K-only)
subtype0x2CbyteObject subtype
routine_secondary0x3CbyteSecondary routine
parent0x42wordParent object address

Object size: $4A bytes (larger than S2's $4A).

S3K-Specific Features

Shield reactions (shield_reaction at offset 0x2B):

BitShieldEffect
3BounceBounce shield attack reaction
4FireFire shield immunity/reaction
5LightningLightning shield reaction
6BubbleBubble shield negation

Child sprite system via mainspr_childsprites at offset +$16:

  • Up to 8 inline child sprites per object
  • Children share the parent object's RAM slot
  • Used for multi-piece visual objects (e.g., boss segments)

Character ID (character_id field):

ValueCharacter
0Sonic
1Tails
2Knuckles

Object Routine Pattern

asm
Obj_Example:
    moveq   #0,d0
    move.b  routine(a0),d0
    move.w  Obj_Example_Index(pc,d0.w),d1
    jmp     Obj_Example_Index(pc,d1.w)

Obj_Example_Index:
    dc.w Obj_Example_Init - Obj_Example_Index   ; routine 0
    dc.w Obj_Example_Main - Obj_Example_Index   ; routine 2

Sprite Mappings Format (S2/S3K Format)

S3K uses the same 6-byte per piece format as S2 (not S1's 5-byte):

code
Frame header:
  dc.w  <piece_count>              ; Word header (same as S2)

Per piece (6 bytes):
  dc.b  <y_offset>                 ; Signed byte
  dc.b  <size>                     ; bits 0-1: width-1, bits 2-3: height-1
  dc.w  <pattern>                  ; Pattern index + flags (priority, palette, flip)
  dc.w  <x_offset>                 ; Signed word (S1 uses byte)

Size byte encoding (same as S1/S2):

  • 0x00 = 1x1 (8x8 pixels)
  • 0x05 = 2x2 (16x16 pixels)
  • 0x0F = 4x4 (32x32 pixels)

Common Search Patterns

Finding Badnik Art

bash
# Search for specific badnik
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k search Rhinobot" -q

# Find all Kosinski Moduled art
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k search ArtKosM_" -q

# Find all Nemesis art
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k search ArtNem_" -q

Finding Zone Data

bash
# All AIZ resources
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k search AIZ" -q

# Zone palette
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k search Pal_AIZ" -q

# Animated palette
mvn exec:java -Dexec.mainClass="uk.co.jamesj999.sonic.tools.disasm.RomOffsetFinder" -Dexec.args="--game s3k search AnPal_AIZ" -q

Finding Object Code

bash
# Search for object in main ASM
grep -n "Obj_Rhinobot" docs/skdisasm/sonic3k.asm

# Find all boss objects
grep -n "Obj_.*Boss" docs/skdisasm/sonic3k.asm

# Find sprite data directory
ls "docs/skdisasm/General/Sprites/Rhinobot/"

RAM Address Reference

Key RAM addresses from sonic3k.constants.asm:

AddressNameDescription
(dynamic)Object_RAMObject status table (dynamically allocated)
Current_zoneCurrent zoneCurrent zone ID
Current_zone_and_actZone and actCombined zone/act value
Camera_X_posCamera XCamera X position
Camera_Y_posCamera YCamera Y position
Ring_countRingsCurrent ring count

Zone-specific variables exist for special mechanics:

  • AIZ1_palette_cycle_flag - AIZ fire palette cycling
  • SOZ_darkness_level - SOZ Act 2 darkness
  • MHZ_pollen_counter - MHZ pollen effect

Quick Reference Card

code
Search:  --game s3k search <pattern>      Find items by name
List:    --game s3k list [type]           List items (nem/kos/kosm/bin)
Test:    --game s3k test <offset> <type>  Test decompression
Verify:  --game s3k verify <label>        Check calculated offset
Export:  --game s3k export <type> [prefix] Generate Java constants

Troubleshooting

Address Verification

Like S1, addresses derived from skdisasm labels may not always match the compiled ROM binary exactly. Use verify to check calculated offsets against the actual ROM data.

"Item not found"

  • Check spelling and case sensitivity
  • Try partial names (e.g., "Rhino" instead of "Rhinobot")
  • S3K labels use ArtKosM_ for Kosinski Moduled, ArtNem_ for Nemesis
  • Compression type is encoded in the label suffix for some items
  • Use list command to see all items of a type

Compression Detection

  • S3K primarily uses Kosinski Moduled (kosm) rather than regular Kosinski
  • Label suffix _KosM indicates Kosinski Moduled compression
  • ArtNem_ prefix indicates Nemesis compression
  • ArtKos_ prefix indicates regular Kosinski compression
  • When the file extension is .bin, the tool infers compression from the label