Actions

SCHG

Difference between revisions of "Sonic Generations"

From Sonic Retro

Line 18: Line 18:
 
=File Specifications=
 
=File Specifications=
 
Over the past few months, several files have had their formats cracked thanks to community member DarioFF. Here are some of the cracked format specifications:
 
Over the past few months, several files have had their formats cracked thanks to community member DarioFF. Here are some of the cracked format specifications:
 +
==.instanceinfo==
 +
<pre>
 +
// All offsets not specified as absolute needs to be added 0x18(dec 24) to reach the right referenced address
 +
 +
 +
struct header {
 +
  uint32_be file_size;
 +
  uint32_be root_node_type; (likely 5)
 +
  uint32_be sub_offset_to_offset_table;
 +
  uint32_be offset_to_root; (absolute)
 +
  uint32_be offset_to_offset_table; (absolute)
 +
  uint32_be offset_to_eof; (absolute)
 +
}
 +
 +
 +
struct root_node {
 +
  uint32_be offset_model_filename;
 +
  uint32_be offset_matrix;
 +
  uint32_be offset_filename;
 +
  uint32_be instance_total; // Unknown what's this total used for?
 +
  uint32_be offset_filename_end;
 +
}
 +
 +
 +
 +
struct instance_matrix {
 +
  float32_be m[16]; // 4x4 matrix, has position, scale, and rotation info
 +
}
 +
 +
 +
 +
struct filename {
 +
  char name[]; // Use as many characters are needed, must be null terminated,
 +
              // add extra padding to align the end to a 0x4 address
 +
}
 +
 +
 +
// Write after filename
 +
 +
// Code names for mesh loaders: alpha, beta, gamma
 +
 +
struct face_loader {
 +
  uint32_be loader_offset; // offset to this struct + 4, points to the next value
 +
 +
  uint32_be alpha_mesh_loader_total;
 +
  uint32_be alpha_mesh_loader_offset; // If loader total is 0, use the biggest address out of the 3 offsets
 +
 +
  uint32_be beta_mesh_loader_total;
 +
  uint32_be beta_mesh_loader_offset;  // Same case as with alpha
 +
 +
  uint32_be gamma_mesh_loader_total;
 +
  uint32_be gamma_mesh_loader_offset; // Same case as with alpha
 +
}
 +
 +
 +
@alpha_mesh_loader_offset
 +
 +
// Follow each of these offsets to reach yet another loader
 +
uint32_be alpha_mesh_offset[alpha_mesh_loader_total];
 +
 +
 +
struct alpha_mesh_loader {
 +
  uint32_be alpha_mesh_total;
 +
  uint32_be alpha_mesh_offset; // Leads to sub_alpha_mesh_offset
 +
}
 +
 +
// Follow these to reach a sub_loader_alpha_mesh_offset
 +
uint32_be sub_alpha_mesh_offset[alpha_mesh_total];
 +
 +
// Offset to sub_alpha_mesh
 +
uint32_be sub_loader_alpha_mesh_offset;
 +
 +
struct sub_alpha_mesh {
 +
  uint32_be unknown_total;
 +
  uint32_be unknown_offset;
 +
  uint32_be face_count;
 +
  uint32_be face_data_start_offset;
 +
  uint32_be unknown_value; // Most of the time 4. unknown_offset points to it
 +
 +
  // Read new faces as triangle strips, each 65535 value means a new strip starts
 +
  uint16_be face_data[face_count];
 +
 
 +
  uint16_be optional_padding; // Add if face_count is an odd value so the structure aligns to 0x4
 +
}
 +
 +
// *  Repeat the above structures for beta and gamma mesh loaders  *
 +
 +
struct final_offset_table {
 +
  uint32_be offset_count;
 +
  uint32_be offset_table[offset_count];
 +
  uint32_be padding=0; // Marks end of file
 +
}
 +
 +
Offset table contents:
 +
[Addresses to any declared offset in any structure whatsoever in order of writing]
 +
</pre>
  
  
Line 23: Line 119:
 
{{SCHGuides}}
 
{{SCHGuides}}
 
[[Category:Sonic Community Hacking Guide]]
 
[[Category:Sonic Community Hacking Guide]]
 +
 +
==.material==
 +
<pre>
 +
// Material files
 +
 +
// Any offsets not declared as absolute must be added 0x18(dec 24) to reach the proper referenced address
 +
 +
struct header {
 +
  uint32_be file_size;
 +
  uint32_be root_node_type; // Most of the time 3 for Generations
 +
                            // 1 for Unleashed
 +
 +
  uint32_be offset_final_table;
 +
  uint32_be root_node_offset; // Always 24
 +
  uint32_be offset_final_table_abs; // (Absolute)
 +
  uint32_be padding=0;
 +
}
 +
 +
 +
struct root_node {
 +
  uint32_be offset_type_string;
 +
  uint32_be offset_type_string_2;
 +
 +
  uint32_be texset_offset;
 +
  uint32_be texture_offset;
 +
 
 +
  uint32_be unknown_value; // Probably 2 short ints, or 1 byte multipler/scale uv components
 +
 +
  uint8 total_material_definitions;
 +
  uint8 unknown_ints[2]={0,0};
 +
  uint8 total_texture_info; // Used for texset and texture tables
 +
 
 +
  uint32_be offset_to_material_offset_table;
 +
  uint32_be unknown_value_2=0;
 +
  uint32_be unknown_value_3=0;
 +
 +
  char type_string_1[]; // Null terminated, no padding needed
 +
  char type_string_2[]; // Null terminated, add padding to reach 0x4 address at the end
 +
 +
 
 +
  uint32_be material_definition_offset_table[total_material_definitions];
 +
}
 +
 +
// Write this structure total_material_definitions times, fill with 0s and null strings
 +
// the marked values if not used
 +
 +
struct material_definition {
 +
  uint16_be map_size_width;
 +
  uint16_be map_size_height;
 +
  uint32_be offset_mat_name;
 +
  uint32_be offset_rgba;
 +
 
 +
  char mat_name[]; // Null terminated, add padding to reach 0x4 address at the end
 +
                    // Write 4 null bytes in case there's no name
 +
 
 +
  float32_be rgba_values[4]; // 4th value is 0 most of the time
 +
                              // Fill with 0s if not used
 +
}
 +
 +
 +
// Read at texset_offset, only 1 structure
 +
uint32_be texset_name_offset_table[total_texture_info];
 +
 +
 +
// Read on each offset a null terminated string
 +
// last string adds padding to reach a 0x4 address
 +
char texset_name[total_texture_info][];
 +
 +
 +
 +
 +
uint32_be texture_offset_table[total_texture_info];
 +
 +
 +
struct texture_info {
 +
  uint32_be offset_tex_name;
 +
  uint32_be unknown_total=0;
 +
  uint32_be offset_tex_type_name;
 +
  char tex_name[]; // Null terminated, no padding needed
 +
  char tex_type_name[]; // Null terminated, add padding to reach a 0x4 address at the end
 +
}
 +
 +
 +
// Final offset table
 +
 +
struct final_offset_table {
 +
  uint32_be offset_total;
 +
  uint32_be offset_table[offset_total];
 +
}
 +
 +
// Since the first EOF offset in the header is 0, there's no need to write an extra 0 value at the end
 +
// of the offset table
 +
 +
Offset table contents:
 +
[Addresses to any declared offset in any structure whatsoever in order of writing the file(non-absolute)]
 +
</pre>

Revision as of 15:44, 24 February 2012

SCHG: Sonic Generations
Main Article

Objects
Collision Properties

File Index
BB

BB2
BB3

How-To
Import Levels

Create Breakable Objects
Create Splines

This is the Sonic Community Hacking Guide for the 2011 US/European PC version of Sonic Generations

Hacking Tools

QuickBMS

  • QuickBMS is used to extract files from Sonic Generations.
  • Primarily it is used to unpack .CPK files with this script (right click => save as).
  • However, it can also be used to unpack .ar.** files with this script. For editing purposes, it is best not to use QuickBMS to hack .ar.** files.

Cri Packed File Maker

  • Crifilesystem has a tool used specifically for hacking Sonic Generations; CriPackedFileMaker.exe
  • While QuickBMS is the best tool for extracting .CPK files, CRI Packed File Maker is the best tool for repacking (or making, rather) .CPK files.
  • Do not pack .cpk files with compression; it is unnecessary and takes extra time out of your life.
  • Data alignment is usually set to 64. Presumably this is unnecessary, but for precautionary purposes, it's best to just leave data alignment at 64.

Generations Archive Editor

  • Community member MainMemory has adapted his tool SADXsndSharp to work with Generations' .ar.** files, available here.
  • Generally this can be considered an easier way to edit .ar.** files, since individual files can be brought out for editing and put back in without having to make new .ar.** files.

File Specifications

Over the past few months, several files have had their formats cracked thanks to community member DarioFF. Here are some of the cracked format specifications:

.instanceinfo

// All offsets not specified as absolute needs to be added 0x18(dec 24) to reach the right referenced address


struct header {
  uint32_be file_size; 
  uint32_be root_node_type; (likely 5)
  uint32_be sub_offset_to_offset_table;
  uint32_be offset_to_root; (absolute)
  uint32_be offset_to_offset_table; (absolute)
  uint32_be offset_to_eof; (absolute)
}


struct root_node {
  uint32_be offset_model_filename;
  uint32_be offset_matrix;
  uint32_be offset_filename;
  uint32_be instance_total; // Unknown what's this total used for?
  uint32_be offset_filename_end;
}



struct instance_matrix {
  float32_be m[16]; // 4x4 matrix, has position, scale, and rotation info
}



struct filename {
  char name[]; // Use as many characters are needed, must be null terminated, 
               // add extra padding to align the end to a 0x4 address
}


// Write after filename

// Code names for mesh loaders: alpha, beta, gamma

struct face_loader {
  uint32_be loader_offset; // offset to this struct + 4, points to the next value

  uint32_be alpha_mesh_loader_total;
  uint32_be alpha_mesh_loader_offset; // If loader total is 0, use the biggest address out of the 3 offsets

  uint32_be beta_mesh_loader_total;
  uint32_be beta_mesh_loader_offset;  // Same case as with alpha

  uint32_be gamma_mesh_loader_total;
  uint32_be gamma_mesh_loader_offset; // Same case as with alpha
}


@alpha_mesh_loader_offset

// Follow each of these offsets to reach yet another loader
uint32_be alpha_mesh_offset[alpha_mesh_loader_total];


struct alpha_mesh_loader {
   uint32_be alpha_mesh_total;
   uint32_be alpha_mesh_offset; // Leads to sub_alpha_mesh_offset
}

// Follow these to reach a sub_loader_alpha_mesh_offset
uint32_be sub_alpha_mesh_offset[alpha_mesh_total];

// Offset to sub_alpha_mesh
uint32_be sub_loader_alpha_mesh_offset;

struct sub_alpha_mesh {
  uint32_be unknown_total;
  uint32_be unknown_offset;
  uint32_be face_count;
  uint32_be face_data_start_offset;
  uint32_be unknown_value; // Most of the time 4. unknown_offset points to it

  // Read new faces as triangle strips, each 65535 value means a new strip starts
  uint16_be face_data[face_count];
  
  uint16_be optional_padding; // Add if face_count is an odd value so the structure aligns to 0x4
} 

// *  Repeat the above structures for beta and gamma mesh loaders  *

struct final_offset_table {
   uint32_be offset_count;
   uint32_be offset_table[offset_count];
   uint32_be padding=0; // Marks end of file
}

Offset table contents:
[Addresses to any declared offset in any structure whatsoever in order of writing]


Sonic Community Hacking Guide
General
SonED2 Manual | Subroutine Equivalency List
Game-Specific
Sonic the Hedgehog (16-bit) | Sonic the Hedgehog (8-bit) | Sonic CD (prototype 510) | Sonic CD | Sonic CD (PC) | Sonic CD (2011) | Sonic 2 (Simon Wai prototype) | Sonic 2 (16-bit) | Sonic 2 (Master System) | Sonic 3 | Sonic 3 & Knuckles | Chaotix | Sonic Jam | Sonic Jam 6 | Sonic Adventure | Sonic Adventure DX: Director's Cut | Sonic Adventure DX: PC | Sonic Adventure (2010) | Sonic Adventure 2 | Sonic Adventure 2: Battle | Sonic Adventure 2 (PC) | Sonic Heroes | Sonic Riders | Sonic the Hedgehog (2006) | Sonic & Sega All-Stars Racing | Sonic Unleashed (Xbox 360/PS3) | Sonic Colours | Sonic Generations | Sonic Forces
Technical information
Sonic Eraser | Sonic 2 (Nick Arcade prototype) | Sonic CD (prototype; 1992-12-04) | Dr. Robotnik's Mean Bean Machine | Sonic Triple Trouble | Tails Adventures | Sonic Crackers | Sonic 3D: Flickies' Island | Sonic & Knuckles Collection | Sonic R | Sonic Shuffle | Sonic Advance | Sonic Advance 3 | Sonic Battle | Shadow the Hedgehog | Sonic Rush | Sonic Classic Collection | Sonic Free Riders | Sonic Lost World
Legacy Guides
The Nemesis Hacking Guides The Esrael Hacking Guides
ROM: Sonic 1 | Sonic 2 | Sonic 2 Beta | Sonic 3

Savestate: Sonic 1 | Sonic 2 Beta/Final | Sonic 3

Sonic 1 (English / Portuguese) | Sonic 2 Beta (English / Portuguese) | Sonic 2 and Knuckles (English / Portuguese)
Move to Sega Retro
Number Systems (or scrap) | Assembly Hacking Guide | 68000 Instruction Set | 68000 ASM-to-Hex Code Reference | SMPS Music Hacking Guide | Mega Drive technical information

.material

// Material files

// Any offsets not declared as absolute must be added 0x18(dec 24) to reach the proper referenced address

struct header {
   uint32_be file_size;
   uint32_be root_node_type; // Most of the time 3 for Generations
                             // 1 for Unleashed

   uint32_be offset_final_table;
   uint32_be root_node_offset; // Always 24
   uint32_be offset_final_table_abs; // (Absolute)
   uint32_be padding=0;
}


struct root_node {
   uint32_be offset_type_string;
   uint32_be offset_type_string_2;

   uint32_be texset_offset;
   uint32_be texture_offset;
   
   uint32_be unknown_value; // Probably 2 short ints, or 1 byte multipler/scale uv components
 
   uint8 total_material_definitions;
   uint8 unknown_ints[2]={0,0};
   uint8 total_texture_info; // Used for texset and texture tables
   
   uint32_be offset_to_material_offset_table;
   uint32_be unknown_value_2=0;
   uint32_be unknown_value_3=0;

   char type_string_1[]; // Null terminated, no padding needed
   char type_string_2[]; // Null terminated, add padding to reach 0x4 address at the end

   
   uint32_be material_definition_offset_table[total_material_definitions];
}

// Write this structure total_material_definitions times, fill with 0s and null strings
// the marked values if not used

struct material_definition {
   uint16_be map_size_width;
   uint16_be map_size_height;
   uint32_be offset_mat_name;
   uint32_be offset_rgba;
   
   char mat_name[]; // Null terminated, add padding to reach 0x4 address at the end
                    // Write 4 null bytes in case there's no name
   
   float32_be rgba_values[4]; // 4th value is 0 most of the time
                              // Fill with 0s if not used
}


// Read at texset_offset, only 1 structure
uint32_be texset_name_offset_table[total_texture_info];


// Read on each offset a null terminated string
// last string adds padding to reach a 0x4 address
char texset_name[total_texture_info][];




uint32_be texture_offset_table[total_texture_info];


struct texture_info {
   uint32_be offset_tex_name;
   uint32_be unknown_total=0;
   uint32_be offset_tex_type_name;
   char tex_name[]; // Null terminated, no padding needed
   char tex_type_name[]; // Null terminated, add padding to reach a 0x4 address at the end
}


// Final offset table

struct final_offset_table {
  uint32_be offset_total;
  uint32_be offset_table[offset_total];
}

// Since the first EOF offset in the header is 0, there's no need to write an extra 0 value at the end
// of the offset table

Offset table contents: 
[Addresses to any declared offset in any structure whatsoever in order of writing the file(non-absolute)]