<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://sadocs.unreliable.network/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=PkR</id>
	<title>SA Docs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://sadocs.unreliable.network/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=PkR"/>
	<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/wiki/Special:Contributions/PkR"/>
	<updated>2026-05-01T14:06:52Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/Contributing_to_the_tools&amp;diff=733</id>
		<title>SA Tools/Contributing to the tools</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/Contributing_to_the_tools&amp;diff=733"/>
		<updated>2026-03-15T02:10:51Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Building SA Tools =&lt;br /&gt;
Prerequisites:&lt;br /&gt;
* Visual Studio 2022&lt;br /&gt;
* .NET 8.0 Desktop runtime&lt;br /&gt;
&lt;br /&gt;
To produce a package, build the &amp;lt;code&amp;gt;SA Tools.sln&amp;lt;/code&amp;gt; file in Visual Studio and run &amp;lt;code&amp;gt;buildSATools.exe&amp;lt;/code&amp;gt; in the solution&#039;s root folder. The package is placed in the &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; folder by default. Run &amp;lt;code&amp;gt;buildSATools.exe&amp;lt;/code&amp;gt; with the &amp;lt;code&amp;gt;-help&amp;lt;/code&amp;gt; command line switch for additional build settings.&lt;br /&gt;
&lt;br /&gt;
= Contributing to SA Tools =&lt;br /&gt;
There are many ways to contribute to the development of SA Tools, some of which don&#039;t require any programming knowledge.&lt;br /&gt;
&lt;br /&gt;
== Updating Game Templates ==&lt;br /&gt;
Game [[Project Templates|templates]] used by the tools contain information on how to extract levels, models, animations and other data from the games. Work has been done to identify this data and extract it in a way that could resemble the original source assets. &lt;br /&gt;
&lt;br /&gt;
=== Object Definitions ===&lt;br /&gt;
For [[SA Tools/SALVL|SALVL]] to display objects in the editor, [[SA Tools/SALVL/Object Definitions|Object Definitions]] are required. A lot of definitions are currently missing, and any contributions of definitions to cover vanilla game objects are highly appreciated.&lt;br /&gt;
&lt;br /&gt;
=== Metadata Fields ===&lt;br /&gt;
To make it easier for the end users to find the assets they want, most data in mod projects has meta sections that contains descriptions, texture files to use etc. This is used in the menu in [[SA Tools/SAMDL|SAMDL]] that appears when you load a project file. However, not all models have descriptions or texture files defined at the moment.&lt;br /&gt;
&lt;br /&gt;
Any help on updating the metadata is appreciated. The metadata is stored as additional fields in INI files for each template in the &amp;lt;code&amp;gt;GameConfig&amp;lt;/code&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
If you want to update existing labels, please focus on PC ports of SA1 and SA2 as these have the most complete split data, and the labels can be transferred to different versions without redoing them all over.&lt;br /&gt;
&lt;br /&gt;
=== Split Data ===&lt;br /&gt;
You can add more data to existing templates, or make new templates for other versions of SA1 and SA2 on different platforms, including prototypes, region exclusive trial versions etc.&lt;br /&gt;
&lt;br /&gt;
If you know the location of a model, animation, texture list etc. that isn&#039;t included in a game template&#039;s split configuration, please add it to the template. If you are working with a console version of the game, make sure asset filenames match those of their PC counterparts.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
Documentation for some tools is lacking or missing entirely. If you have learned how to use a certain tool or feature and want to make it more accessible for others, you can update this wiki to share your knowledge with others!&lt;br /&gt;
&lt;br /&gt;
== Bug Reports ==&lt;br /&gt;
Any well-structured bug report for a reproducible issue is an important contribution to the development of SA Tools. While there is no guarantee that all issues will be resolved, a reported bug has a higher chance of being fixed than an unreported one.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=732</id>
		<title>SA Tools/SALVL/Object Definitions</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=732"/>
		<updated>2026-03-14T14:22:09Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction to Object Definitions ==&lt;br /&gt;
An object definition is a part of a [[SA Tools/Project Template|project template]] that enables [[SA Tools/SALVL|SALVL]] to display [[SET File|SET objects]] in the editor. The object definition sets up the object&#039;s model and textures, provides the position, rotation and scale routines to make the object look like it does ingame, and optionally converts SET data into customizable variables used to pick variations of the object or alter its behavior ingame.&lt;br /&gt;
&lt;br /&gt;
At the moment, SALVL is lacking object definitions for most stages in both SADX and SA2, and contributions are highly appreciated.&lt;br /&gt;
&lt;br /&gt;
=== Types of Object Definitions ===&lt;br /&gt;
Depending on the complexity of the object&#039;s rendering, object definitions can be either of the following two types:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;The default definition&#039;&#039;&#039; (also known as &amp;quot;script&amp;quot;, &amp;quot;codeless&amp;quot; or &amp;quot;simple&amp;quot; definition) provides basic functionality to load and render a model. Many objects in the game will display in the editor with a properly configured default definition. For example, a ring or a stage decoration can work with the default definition.&lt;br /&gt;
# &#039;&#039;&#039;Custom definitions&#039;&#039;&#039; (also known as &amp;quot;code&amp;quot; definitions) provide custom code for loading the object, rendering its model(s) in the editor and collision checks. These definitions supply separate &amp;lt;code&amp;gt;.cs&amp;lt;/code&amp;gt; files which are compiled by SALVL when it loads a stage.&lt;br /&gt;
&lt;br /&gt;
=== Creating Object Definitions ===&lt;br /&gt;
The following is a list of steps to go through to get a SET object to display in SALVL.&lt;br /&gt;
&lt;br /&gt;
==== Setting up stage properties ====&lt;br /&gt;
&#039;&#039;Note: For PC versions of SADX and SA2 the work on this step has already been done for all stages. The information below is provided for reference.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note 2: The file &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; is found in two locations. The file in &amp;lt;code&amp;gt;SA Tools\GameConfig\PC_SADX&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;PC_SA2&amp;lt;/code&amp;gt;) is copied to the project folder when you make a new mod project. If you are adding custom objects in your mod, edit the file in your mod project folder. If you are making object definitions for vanilla game objects, edit the main file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; file should have an entry for the stage you need that defines level textures, object textures, the location of the object list INI file and the object definition list INI file. Here is an example for Emerald Coast Act 3.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;[Action Stages\\Emerald Coast 3]&lt;br /&gt;
LevelGeometry=stg01_beach/landtable0102.c.sa1lvl&lt;br /&gt;
LevelID=0102&lt;br /&gt;
Textures=BEACH03&lt;br /&gt;
ObjectList=stg01_beach/objList.ini&lt;br /&gt;
ObjectTextureList=stg01_beach/objTextures.ini&lt;br /&gt;
DeathZones=stg01_beach/killcolli/act3/killZones.ini&lt;br /&gt;
Effects=objdefs/Level Effects/EmeraldCoast.cs&lt;br /&gt;
ObjectDefinition=objdefs/stg01.ini&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;LevelGeometry&#039;&#039; is the relative path to the [[LandTable]] file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LevelID&#039;&#039; is the internal ID used by the stage. The first two digits are level ID and the second two digits are act ID. For SA1, see [[Sonic Adventure/Level List]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Textures&#039;&#039; is the name of the texture file (usually PVM, GVM, PRS or PAK) &#039;&#039;&#039;without extension&#039;&#039;&#039; used for level textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectList&#039;&#039; is the relative path to the [[Object List]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DeathZones&#039;&#039; is the relative path to the [[Death Zones]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Effects&#039;&#039; is the relative path to the [[SA Tools/SALVL/Level Definition|Level Definition]] .cs file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectDefinition&#039;&#039; is the relative path to the Object Definition list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Editing the object&#039;s entry in the object definition list&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The objdefs folder can be found in two locations. See the note about &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; in Step 1, it&#039;s the same principle.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The text below describes manual editing of object definition entries in the INI file. If you prefer a GUI editor, you can use the Object Definition Editor in SALVL. Editing object definitions in SALVL will save them to your mod&#039;s project.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Each entry in the object definition list should begin with the object&#039;s internal name in square brackets, which represents the INI section for the entry. All internal names are already filled in at the moment, so you only need to edit the parameters.&lt;br /&gt;
[[File:SA Tools SALVL Object Definitions 1773488122468.png|thumb|SALVL Object Editor that includes the Object Definition Editor.]]&lt;br /&gt;
Here is an example of a &#039;&#039;&#039;custom&#039;&#039;&#039; object definition for the jump panel (internal name &amp;lt;code&amp;gt;O JPanel&amp;lt;/code&amp;gt;). Assuming we&#039;re still working with Emerald Coast, its entry will be in &amp;lt;code&amp;gt;objdefs/stg01.ini&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O JPanel]&lt;br /&gt;
codefile=objdefs/Common/JumpPanel.cs&lt;br /&gt;
codetype=SADXObjectDefinitions.Common.JumpPanel&lt;br /&gt;
Name=Jump Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codefile&#039;&#039; is the relative path to the .cs file containing the code of the custom definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codetype&#039;&#039; is the name of the class used by the definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: codefile and codetype are spelled in all lowercase.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For a tutorial on creating code for a custom object definition, see [[SA Tools/SALVL/Object Definitions/Creating a Custom Object Definition|Creating a Custom Object Definition]].&lt;br /&gt;
&lt;br /&gt;
However, many objects don&#039;t need a custom definition. For example, if the object only displays one model (as in, loaded from a single model file) and doesn&#039;t exhibit any complex behavior that needs to be accounted for in the editor, you can use the default object definition. In many cases, all you have to do is fill in a few parameters for its entry in the INI file to get the object to show up in the editor.&lt;br /&gt;
&lt;br /&gt;
For an example of a codeless object definition, let&#039;s examine the entry for the Master Emerald shard (internal name &amp;lt;code&amp;gt;O EME P&amp;lt;/code&amp;gt;):&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O EME P]&lt;br /&gt;
Name=Emerald Shard&lt;br /&gt;
Model=object/obj_emekakera.nja.sa1mdl&lt;br /&gt;
Texture=OBJ_REGULAR&lt;br /&gt;
RotType=None&lt;br /&gt;
SclType=None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Model&#039;&#039; is the relative path to the object&#039;s model file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texture&#039;&#039; is the filename (without extension) of the texture archive used for loading the object&#039;s textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;RotType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;rotated&#039;&#039;&#039; when the editor renders it. It can be &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; if the object is only rotated on the Y axis (which is the most common), or &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; if all axes are used for rendering. Any other combination of &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; can also be used. If the object model doesn&#039;t need to be rotated at all, use &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SclType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;scaled&#039;&#039;&#039; when the editor renders it. Most objects do not scale, so &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; is often used. The following values are possible:&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;None, // Default scale (X=1.0, Y=1.0, Z=1.0)&lt;br /&gt;
XYZ, // Scale X, Y and Z&lt;br /&gt;
X, // Scale only by the X axis using the X Scale value&lt;br /&gt;
Y, // Scale only by the Y axis using the Y Scale value&lt;br /&gt;
Z, // Scale only by the Z axis using the Z Scale value&lt;br /&gt;
XY, // Scale the X axis using the X Scale value and then by the Y axis using the Y Scale value&lt;br /&gt;
XZ, // Scale the X axis using the X Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
YZ, // Scale the Y axis using the Y Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
AllX, // All axes are scaled by the X Scale value&lt;br /&gt;
AllY, // All axes are scaled by the Y Scale value&lt;br /&gt;
AllZ // All axes are scaled by the Z Scale value&amp;lt;/syntaxhighlight&amp;gt;For the most part, filling in the above parameters (particularly &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039;) is enough for the object to appear in SALVL. For slightly more complex objects the following additional parameters are available:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TexturePacks&#039;&#039; is a comma-separated list of texture files without extension for objects in SA2 that use multiple [[Texture List|texture lists]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texlist&#039;&#039; is the name of the texture list file (&amp;lt;code&amp;gt;.tls&amp;lt;/code&amp;gt;) loaded by the object. This is required for objects that use multiple or partial texture lists.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; are floating point values that offset the model&#039;s initial transformation for rendering. For example, if your object sinks into the ground, it might need a positive &#039;&#039;AddYPos&#039;&#039;, and if it appears higher than it should be it might need a negative &#039;&#039;AddYPos&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXRot&#039;&#039;, &#039;&#039;DefYRot&#039;&#039; and &#039;&#039;DefZRot&#039;&#039; are initial rotations for objects that have a fixed rotation different from the one specified in the SET file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; and &#039;&#039;AddZRot&#039;&#039; are rotation offsets that work just like &#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; but for rotations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: Rotation values are hexadecimal.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039;, &#039;&#039;DefZScl&#039;&#039; are initial scale values, and &#039;&#039;AddXScl&#039;&#039;, &#039;&#039;AddYScl&#039;&#039; and &#039;&#039;AddZScl&#039;&#039; are offset scale values that work under the same principle as the other offsets mentioned above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;GndDst&#039;&#039; is &amp;quot;distance from the ground&amp;quot;, a vertical offset used for placing objects on the ground in SALVL.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IgnorePos&#039;&#039; is a boolean value (&amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;) that tells the renderer and collision checks to ignore the object&#039;s model (&amp;lt;code&amp;gt;NJS_OBJECT&amp;lt;/code&amp;gt;)&#039;s position.&lt;br /&gt;
&lt;br /&gt;
=== Testing Object Definitions ===&lt;br /&gt;
To test an update to object definitions, copy the modified files in the &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder to your mod project&#039;s &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder, (re)start SALVL, open your mod project and load the stage. The following is a list of common errors with object definitions and potential solutions.&lt;br /&gt;
&lt;br /&gt;
==== Object displays as a box with a question mark ====&lt;br /&gt;
In most cases this means that the object definition is missing or incomplete. If you are using the default definition, make sure at least the &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039; fields are specified in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== SALVL Error: &amp;quot;SET objects failed to load their model(s). Please check SET object load errors in the log for details.&amp;quot; ====&lt;br /&gt;
The most likely cause of the error is the model or texture file missing. In SALVL, select &#039;&#039;Help&amp;gt;View Log&#039;&#039; in the top menu and scroll to the bottom of the log to find the error. If you see &amp;quot;Exists: False&amp;quot;, it means the model or texture file was not found. Make sure the path to the model or texture file is correct. Use &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths. If the model does not use textures, do not specify the texture file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears misrotated ====&lt;br /&gt;
Rotate the object using the editor&#039;s rotation gizmo to find the rotation values that make it look correct. Add the difference between these values as &#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; or &#039;&#039;AddZRot&#039;&#039; values in the object definition list INI file. Some objects are rotated on the Y axis by &amp;lt;code&amp;gt;4000&amp;lt;/code&amp;gt; (16384 in decimal), see &amp;lt;code&amp;gt;O STATION BACK&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;adv00.ini&amp;lt;/code&amp;gt; for an example. Alternatively, experiment with default rotations.&lt;br /&gt;
&lt;br /&gt;
==== Object appears too small or too large ====&lt;br /&gt;
Set &#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039; and/or &#039;&#039;DefZScl&#039;&#039;, or add scale offsets in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears in the wrong place ====&lt;br /&gt;
If there is a fixed difference (always 10 units above or below etc.), add a position offset. Alternatively, add &#039;&#039;IgnorePos=True&#039;&#039; in the object definition list INI file. If that doesn&#039;t help, try a different rotation order or experiment with a combination of all of the above.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=731</id>
		<title>SA Tools/SALVL/Object Definitions</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=731"/>
		<updated>2026-03-14T12:19:59Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction to Object Definitions ==&lt;br /&gt;
An object definition is a part of a [[SA Tools/Project template|project template]] that enables [[SA Tools/SALVL|SALVL]] to display [[SET Object|SET objects]] in the editor. The object definition sets up the object&#039;s model and textures, provides the position, rotation and scale routines to make the object look like it does ingame, and optionally converts SET data into customizable variables used to pick variations of the object or alter its behavior ingame.&lt;br /&gt;
&lt;br /&gt;
At the moment, SALVL is lacking object definitions for most stages in both SADX and SA2, and contributions are highly appreciated.&lt;br /&gt;
&lt;br /&gt;
=== Types of Object Definitions ===&lt;br /&gt;
Depending on the complexity of the object&#039;s rendering, object definitions can be either of the following two types:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;The default definition&#039;&#039;&#039; (also known as &amp;quot;script&amp;quot;, &amp;quot;codeless&amp;quot; or &amp;quot;simple&amp;quot; definition) provides basic functionality to load and render a model. Many objects in the game will display in the editor with a properly configured default definition. For example, a ring or a stage decoration can work with the default definition.&lt;br /&gt;
# &#039;&#039;&#039;Custom definitions&#039;&#039;&#039; (also known as &amp;quot;code&amp;quot; definitions) provide custom code for loading the object, rendering its model(s) in the editor and collision checks. These definitions supply separate &amp;lt;code&amp;gt;.cs&amp;lt;/code&amp;gt; files which are compiled by SALVL when it loads a stage.&lt;br /&gt;
&lt;br /&gt;
=== Creating Object Definitions ===&lt;br /&gt;
The following is a list of steps to go through to get a SET object to display in SALVL.&lt;br /&gt;
&lt;br /&gt;
==== Setting up stage properties ====&lt;br /&gt;
&#039;&#039;Note: For PC versions of SADX and SA2 the work on this step has already been done for all stages. The information below is provided for reference.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note 2: The file &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; is found in two locations. The file in &amp;lt;code&amp;gt;SA Tools\GameConfig\PC_SADX&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;PC_SA2&amp;lt;/code&amp;gt;) is copied to the project folder when you make a new mod project. If you are adding custom objects in your mod, edit the file in your mod project folder. If you are making object definitions for vanilla game objects, edit the main file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; file should have an entry for the stage you need that defines level textures, object textures, the location of the object list INI file and the object definition list INI file. Here is an example for Emerald Coast Act 3.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;[Action Stages\\Emerald Coast 3]&lt;br /&gt;
LevelGeometry=stg01_beach/landtable0102.c.sa1lvl&lt;br /&gt;
LevelID=0102&lt;br /&gt;
Textures=BEACH03&lt;br /&gt;
ObjectList=stg01_beach/objList.ini&lt;br /&gt;
ObjectTextureList=stg01_beach/objTextures.ini&lt;br /&gt;
DeathZones=stg01_beach/killcolli/act3/killZones.ini&lt;br /&gt;
Effects=objdefs/Level Effects/EmeraldCoast.cs&lt;br /&gt;
ObjectDefinition=objdefs/stg01.ini&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;LevelGeometry&#039;&#039; is the relative path to the [[LandTable]] file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LevelID&#039;&#039; is the internal ID used by the stage. The first two digits are level ID and the second two digits are act ID. For SA1, see [[Sonic Adventure/Level List]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Textures&#039;&#039; is the name of the texture file (usually PVM, GVM, PRS or PAK) &#039;&#039;&#039;without extension&#039;&#039;&#039; used for level textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectList&#039;&#039; is the relative path to the [[Object List]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DeathZones&#039;&#039; is the relative path to the [[Death Zones]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Effects&#039;&#039; is the relative path to the [[SA Tools/SALVL/Level Definition|Level Definition]] .cs file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectDefinition&#039;&#039; is the relative path to the Object Definition list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Editing the object&#039;s entry in the object definition list&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The objdefs folder can be found in two locations. See the note about &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; in Step 1, it&#039;s the same principle.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The text below describes manual editing of object definition entries in the INI file. If you prefer a GUI editor, you can use the Object Definition Editor in SALVL. Editing object definitions in SALVL will save them to your mod&#039;s project.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Each entry in the object definition list should begin with the object&#039;s internal name in square brackets, which represents the INI section for the entry. All internal names are already filled in at the moment, so you only need to edit the parameters.&lt;br /&gt;
[[File:SA Tools SALVL Object Definitions 1773488122468.png|thumb|SALVL Object Editor that includes the Object Definition Editor.]]&lt;br /&gt;
Here is an example of a &#039;&#039;&#039;custom&#039;&#039;&#039; object definition for the jump panel (internal name &amp;lt;code&amp;gt;O JPanel&amp;lt;/code&amp;gt;). Assuming we&#039;re still working with Emerald Coast, its entry will be in &amp;lt;code&amp;gt;objdefs/stg01.ini&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O JPanel]&lt;br /&gt;
codefile=objdefs/Common/JumpPanel.cs&lt;br /&gt;
codetype=SADXObjectDefinitions.Common.JumpPanel&lt;br /&gt;
Name=Jump Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codefile&#039;&#039; is the relative path to the .cs file containing the code of the custom definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codetype&#039;&#039; is the name of the class used by the definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: codefile and codetype are spelled in all lowercase.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For a tutorial on creating code for a custom object definition, see [[SA Tools/SALVL/Object Definitions/Creating a Custom Object Definition|Creating a Custom Object Definition]].&lt;br /&gt;
&lt;br /&gt;
However, many objects don&#039;t need a custom definition. For example, if the object only displays one model (as in, loaded from a single model file) and doesn&#039;t exhibit any complex behavior that needs to be accounted for in the editor, you can use the default object definition. In many cases, all you have to do is fill in a few parameters for its entry in the INI file to get the object to show up in the editor.&lt;br /&gt;
&lt;br /&gt;
For an example of a codeless object definition, let&#039;s examine the entry for the Master Emerald shard (internal name &amp;lt;code&amp;gt;O EME P&amp;lt;/code&amp;gt;):&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O EME P]&lt;br /&gt;
Name=Emerald Shard&lt;br /&gt;
Model=object/obj_emekakera.nja.sa1mdl&lt;br /&gt;
Texture=OBJ_REGULAR&lt;br /&gt;
RotType=None&lt;br /&gt;
SclType=None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Model&#039;&#039; is the relative path to the object&#039;s model file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texture&#039;&#039; is the filename (without extension) of the texture archive used for loading the object&#039;s textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;RotType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;rotated&#039;&#039;&#039; when the editor renders it. It can be &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; if the object is only rotated on the Y axis (which is the most common), or &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; if all axes are used for rendering. Any other combination of &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; can also be used. If the object model doesn&#039;t need to be rotated at all, use &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SclType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;scaled&#039;&#039;&#039; when the editor renders it. Most objects do not scale, so &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; is often used. The following values are possible:&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;None, // Default scale (X=1.0, Y=1.0, Z=1.0)&lt;br /&gt;
XYZ, // Scale X, Y and Z&lt;br /&gt;
X, // Scale only by the X axis using the X Scale value&lt;br /&gt;
Y, // Scale only by the Y axis using the Y Scale value&lt;br /&gt;
Z, // Scale only by the Z axis using the Z Scale value&lt;br /&gt;
XY, // Scale the X axis using the X Scale value and then by the Y axis using the Y Scale value&lt;br /&gt;
XZ, // Scale the X axis using the X Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
YZ, // Scale the Y axis using the Y Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
AllX, // All axes are scaled by the X Scale value&lt;br /&gt;
AllY, // All axes are scaled by the Y Scale value&lt;br /&gt;
AllZ // All axes are scaled by the Z Scale value&amp;lt;/syntaxhighlight&amp;gt;For the most part, filling in the above parameters (particularly &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039;) is enough for the object to appear in SALVL. For slightly more complex objects the following additional parameters are available:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TexturePacks&#039;&#039; is a comma-separated list of texture files without extension for objects in SA2 that use multiple [[Texture List|texture lists]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texlist&#039;&#039; is the name of the texture list file (&amp;lt;code&amp;gt;.tls&amp;lt;/code&amp;gt;) loaded by the object. This is required for objects that use multiple or partial texture lists.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; are floating point values that offset the model&#039;s initial transformation for rendering. For example, if your object sinks into the ground, it might need a positive &#039;&#039;AddYPos&#039;&#039;, and if it appears higher than it should be it might need a negative &#039;&#039;AddYPos&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXRot&#039;&#039;, &#039;&#039;DefYRot&#039;&#039; and &#039;&#039;DefZRot&#039;&#039; are initial rotations for objects that have a fixed rotation different from the one specified in the SET file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; and &#039;&#039;AddZRot&#039;&#039; are rotation offsets that work just like &#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; but for rotations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: Rotation values are hexadecimal.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039;, &#039;&#039;DefZScl&#039;&#039; are initial scale values, and &#039;&#039;AddXScl&#039;&#039;, &#039;&#039;AddYScl&#039;&#039; and &#039;&#039;AddZScl&#039;&#039; are offset scale values that work under the same principle as the other offsets mentioned above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;GndDst&#039;&#039; is &amp;quot;distance from the ground&amp;quot;, a vertical offset used for placing objects on the ground in SALVL.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IgnorePos&#039;&#039; is a boolean value (&amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;) that tells the renderer and collision checks to ignore the object&#039;s model (&amp;lt;code&amp;gt;NJS_OBJECT&amp;lt;/code&amp;gt;)&#039;s position.&lt;br /&gt;
&lt;br /&gt;
=== Testing Object Definitions ===&lt;br /&gt;
To test an update to object definitions, copy the modified files in the &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder to your mod project&#039;s &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder, (re)start SALVL, open your mod project and load the stage. The following is a list of common errors with object definitions and potential solutions.&lt;br /&gt;
&lt;br /&gt;
==== Object displays as a box with a question mark ====&lt;br /&gt;
In most cases this means that the object definition is missing or incomplete. If you are using the default definition, make sure at least the &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039; fields are specified in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== SALVL Error: &amp;quot;SET objects failed to load their model(s). Please check SET object load errors in the log for details.&amp;quot; ====&lt;br /&gt;
The most likely cause of the error is the model or texture file missing. In SALVL, select &#039;&#039;Help&amp;gt;View Log&#039;&#039; in the top menu and scroll to the bottom of the log to find the error. If you see &amp;quot;Exists: False&amp;quot;, it means the model or texture file was not found. Make sure the path to the model or texture file is correct. Use &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths. If the model does not use textures, do not specify the texture file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears misrotated ====&lt;br /&gt;
Rotate the object using the editor&#039;s rotation gizmo to find the rotation values that make it look correct. Add the difference between these values as &#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; or &#039;&#039;AddZRot&#039;&#039; values in the object definition list INI file. Some objects are rotated on the Y axis by &amp;lt;code&amp;gt;4000&amp;lt;/code&amp;gt; (16384 in decimal), see &amp;lt;code&amp;gt;O STATION BACK&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;adv00.ini&amp;lt;/code&amp;gt; for an example. Alternatively, experiment with default rotations.&lt;br /&gt;
&lt;br /&gt;
==== Object appears too small or too large ====&lt;br /&gt;
Set &#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039; and/or &#039;&#039;DefZScl&#039;&#039;, or add scale offsets in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears in the wrong place ====&lt;br /&gt;
If there is a fixed difference (always 10 units above or below etc.), add a position offset. Alternatively, add &#039;&#039;IgnorePos=True&#039;&#039; in the object definition list INI file. If that doesn&#039;t help, try a different rotation order or experiment with a combination of all of the above.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=730</id>
		<title>SA Tools/SALVL/Object Definitions</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=730"/>
		<updated>2026-03-14T12:19:17Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction to Object Definitions ==&lt;br /&gt;
An object definition is a part of a [[SA Tools/Project template|project template]] that enables [[SA Tools/SALVL|SALVL]] to display [[SET Object|SET objects]] in the editor. The object definition sets up the object&#039;s model and textures, provides the position, rotation and scale routines to make the object look like it does ingame, and optionally converts SET data into customizable variables used to pick variations of the object or alter its behavior ingame.&lt;br /&gt;
&lt;br /&gt;
At the moment, SALVL is lacking a lot of object definitions for many stages in both SADX and SA2, and contributions are highly appreciated.&lt;br /&gt;
&lt;br /&gt;
=== Types of Object Definitions ===&lt;br /&gt;
Depending on the complexity of the object&#039;s rendering, object definitions can be either of the following two types:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;The default definition&#039;&#039;&#039; (also known as &amp;quot;script&amp;quot;, &amp;quot;codeless&amp;quot; or &amp;quot;simple&amp;quot; definition) provides basic functionality to load and render a model. Many objects in the game will display in the editor with a properly configured default definition. For example, a ring or a stage decoration can work with the default definition.&lt;br /&gt;
# &#039;&#039;&#039;Custom definitions&#039;&#039;&#039; (also known as &amp;quot;code&amp;quot; definitions) provide custom code for loading the object, rendering its model(s) in the editor and collision checks. These definitions supply separate &amp;lt;code&amp;gt;.cs&amp;lt;/code&amp;gt; files which are compiled by SALVL when it loads a stage.&lt;br /&gt;
&lt;br /&gt;
=== Creating Object Definitions ===&lt;br /&gt;
The following is a list of steps to go through to get a SET object to display in SALVL.&lt;br /&gt;
&lt;br /&gt;
==== Setting up stage properties ====&lt;br /&gt;
&#039;&#039;Note: For PC versions of SADX and SA2 the work on this step has already been done for all stages. The information below is provided for reference.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note 2: The file &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; is found in two locations. The file in &amp;lt;code&amp;gt;SA Tools\GameConfig\PC_SADX&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;PC_SA2&amp;lt;/code&amp;gt;) is copied to the project folder when you make a new mod project. If you are adding custom objects in your mod, edit the file in your mod project folder. If you are making object definitions for vanilla game objects, edit the main file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; file should have an entry for the stage you need that defines level textures, object textures, the location of the object list INI file and the object definition list INI file. Here is an example for Emerald Coast Act 3.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;[Action Stages\\Emerald Coast 3]&lt;br /&gt;
LevelGeometry=stg01_beach/landtable0102.c.sa1lvl&lt;br /&gt;
LevelID=0102&lt;br /&gt;
Textures=BEACH03&lt;br /&gt;
ObjectList=stg01_beach/objList.ini&lt;br /&gt;
ObjectTextureList=stg01_beach/objTextures.ini&lt;br /&gt;
DeathZones=stg01_beach/killcolli/act3/killZones.ini&lt;br /&gt;
Effects=objdefs/Level Effects/EmeraldCoast.cs&lt;br /&gt;
ObjectDefinition=objdefs/stg01.ini&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;LevelGeometry&#039;&#039; is the relative path to the [[LandTable]] file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LevelID&#039;&#039; is the internal ID used by the stage. The first two digits are level ID and the second two digits are act ID. For SA1, see [[Sonic Adventure/Level List]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Textures&#039;&#039; is the name of the texture file (usually PVM, GVM, PRS or PAK) &#039;&#039;&#039;without extension&#039;&#039;&#039; used for level textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectList&#039;&#039; is the relative path to the [[Object List]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DeathZones&#039;&#039; is the relative path to the [[Death Zones]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Effects&#039;&#039; is the relative path to the [[SA Tools/SALVL/Level Definition|Level Definition]] .cs file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectDefinition&#039;&#039; is the relative path to the Object Definition list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Editing the object&#039;s entry in the object definition list&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The objdefs folder can be found in two locations. See the note about &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; in Step 1, it&#039;s the same principle.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The text below describes manual editing of object definition entries in the INI file. If you prefer a GUI editor, you can use the Object Definition Editor in SALVL. Editing object definitions in SALVL will save them to your mod&#039;s project.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Each entry in the object definition list should begin with the object&#039;s internal name in square brackets, which represents the INI section for the entry. All internal names are already filled in at the moment, so you only need to edit the parameters.&lt;br /&gt;
[[File:SA Tools SALVL Object Definitions 1773488122468.png|thumb|SALVL Object Editor that includes the Object Definition Editor.]]&lt;br /&gt;
Here is an example of a &#039;&#039;&#039;custom&#039;&#039;&#039; object definition for the jump panel (internal name &amp;lt;code&amp;gt;O JPanel&amp;lt;/code&amp;gt;). Assuming we&#039;re still working with Emerald Coast, its entry will be in &amp;lt;code&amp;gt;objdefs/stg01.ini&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O JPanel]&lt;br /&gt;
codefile=objdefs/Common/JumpPanel.cs&lt;br /&gt;
codetype=SADXObjectDefinitions.Common.JumpPanel&lt;br /&gt;
Name=Jump Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codefile&#039;&#039; is the relative path to the .cs file containing the code of the custom definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codetype&#039;&#039; is the name of the class used by the definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: codefile and codetype are spelled in all lowercase.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For a tutorial on creating code for a custom object definition, see [[SA Tools/SALVL/Object Definitions/Creating a Custom Object Definition|Creating a Custom Object Definition]].&lt;br /&gt;
&lt;br /&gt;
However, many objects don&#039;t need a custom definition. For example, if the object only displays one model (as in, loaded from a single model file) and doesn&#039;t exhibit any complex behavior that needs to be accounted for in the editor, you can use the default object definition. In many cases, all you have to do is fill in a few parameters for its entry in the INI file to get the object to show up in the editor.&lt;br /&gt;
&lt;br /&gt;
For an example of a codeless object definition, let&#039;s examine the entry for the Master Emerald shard (internal name &amp;lt;code&amp;gt;O EME P&amp;lt;/code&amp;gt;):&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O EME P]&lt;br /&gt;
Name=Emerald Shard&lt;br /&gt;
Model=object/obj_emekakera.nja.sa1mdl&lt;br /&gt;
Texture=OBJ_REGULAR&lt;br /&gt;
RotType=None&lt;br /&gt;
SclType=None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Model&#039;&#039; is the relative path to the object&#039;s model file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texture&#039;&#039; is the filename (without extension) of the texture archive used for loading the object&#039;s textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;RotType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;rotated&#039;&#039;&#039; when the editor renders it. It can be &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; if the object is only rotated on the Y axis (which is the most common), or &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; if all axes are used for rendering. Any other combination of &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; can also be used. If the object model doesn&#039;t need to be rotated at all, use &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SclType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;scaled&#039;&#039;&#039; when the editor renders it. Most objects do not scale, so &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; is often used. The following values are possible:&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;None, // Default scale (X=1.0, Y=1.0, Z=1.0)&lt;br /&gt;
XYZ, // Scale X, Y and Z&lt;br /&gt;
X, // Scale only by the X axis using the X Scale value&lt;br /&gt;
Y, // Scale only by the Y axis using the Y Scale value&lt;br /&gt;
Z, // Scale only by the Z axis using the Z Scale value&lt;br /&gt;
XY, // Scale the X axis using the X Scale value and then by the Y axis using the Y Scale value&lt;br /&gt;
XZ, // Scale the X axis using the X Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
YZ, // Scale the Y axis using the Y Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
AllX, // All axes are scaled by the X Scale value&lt;br /&gt;
AllY, // All axes are scaled by the Y Scale value&lt;br /&gt;
AllZ // All axes are scaled by the Z Scale value&amp;lt;/syntaxhighlight&amp;gt;For the most part, filling in the above parameters (particularly &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039;) is enough for the object to appear in SALVL. For slightly more complex objects the following additional parameters are available:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TexturePacks&#039;&#039; is a comma-separated list of texture files without extension for objects in SA2 that use multiple [[Texture List|texture lists]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texlist&#039;&#039; is the name of the texture list file (&amp;lt;code&amp;gt;.tls&amp;lt;/code&amp;gt;) loaded by the object. This is required for objects that use multiple or partial texture lists.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; are floating point values that offset the model&#039;s initial transformation for rendering. For example, if your object sinks into the ground, it might need a positive &#039;&#039;AddYPos&#039;&#039;, and if it appears higher than it should be it might need a negative &#039;&#039;AddYPos&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXRot&#039;&#039;, &#039;&#039;DefYRot&#039;&#039; and &#039;&#039;DefZRot&#039;&#039; are initial rotations for objects that have a fixed rotation different from the one specified in the SET file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; and &#039;&#039;AddZRot&#039;&#039; are rotation offsets that work just like &#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; but for rotations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: Rotation values are hexadecimal.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039;, &#039;&#039;DefZScl&#039;&#039; are initial scale values, and &#039;&#039;AddXScl&#039;&#039;, &#039;&#039;AddYScl&#039;&#039; and &#039;&#039;AddZScl&#039;&#039; are offset scale values that work under the same principle as the other offsets mentioned above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;GndDst&#039;&#039; is &amp;quot;distance from the ground&amp;quot;, a vertical offset used for placing objects on the ground in SALVL.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IgnorePos&#039;&#039; is a boolean value (&amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;) that tells the renderer and collision checks to ignore the object&#039;s model (&amp;lt;code&amp;gt;NJS_OBJECT&amp;lt;/code&amp;gt;)&#039;s position.&lt;br /&gt;
&lt;br /&gt;
=== Testing Object Definitions ===&lt;br /&gt;
To test an update to object definitions, copy the modified files in the &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder to your mod project&#039;s &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder, (re)start SALVL, open your mod project and load the stage. The following is a list of common errors with object definitions and potential solutions.&lt;br /&gt;
&lt;br /&gt;
==== Object displays as a box with a question mark ====&lt;br /&gt;
In most cases this means that the object definition is missing or incomplete. If you are using the default definition, make sure at least the &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039; fields are specified in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== SALVL Error: &amp;quot;SET objects failed to load their model(s). Please check SET object load errors in the log for details.&amp;quot; ====&lt;br /&gt;
The most likely cause of the error is the model or texture file missing. In SALVL, select &#039;&#039;Help&amp;gt;View Log&#039;&#039; in the top menu and scroll to the bottom of the log to find the error. If you see &amp;quot;Exists: False&amp;quot;, it means the model or texture file was not found. Make sure the path to the model or texture file is correct. Use &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths. If the model does not use textures, do not specify the texture file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears misrotated ====&lt;br /&gt;
Rotate the object using the editor&#039;s rotation gizmo to find the rotation values that make it look correct. Add the difference between these values as &#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; or &#039;&#039;AddZRot&#039;&#039; values in the object definition list INI file. Some objects are rotated on the Y axis by &amp;lt;code&amp;gt;4000&amp;lt;/code&amp;gt; (16384 in decimal), see &amp;lt;code&amp;gt;O STATION BACK&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;adv00.ini&amp;lt;/code&amp;gt; for an example. Alternatively, experiment with default rotations.&lt;br /&gt;
&lt;br /&gt;
==== Object appears too small or too large ====&lt;br /&gt;
Set &#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039; and/or &#039;&#039;DefZScl&#039;&#039;, or add scale offsets in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears in the wrong place ====&lt;br /&gt;
If there is a fixed difference (always 10 units above or below etc.), add a position offset. Alternatively, add &#039;&#039;IgnorePos=True&#039;&#039; in the object definition list INI file. If that doesn&#039;t help, try a different rotation order or experiment with a combination of all of the above.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=729</id>
		<title>SA Tools/SALVL/Object Definitions</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=729"/>
		<updated>2026-03-14T12:12:35Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction to Object Definitions ==&lt;br /&gt;
An object definition is a part of a [[SA Tools/Project template|project template]] that enables [[SA Tools/SALVL|SALVL]] to display [[SET Object|SET objects]] in the editor. The object definition sets up the object&#039;s model and textures, provides the position, rotation and scale routines to make the object look like it does ingame, and optionally converts SET data into customizable variables used to pick variations of the object or alter its behavior ingame.&lt;br /&gt;
&lt;br /&gt;
=== Types of Object Definitions ===&lt;br /&gt;
Depending on the complexity of the object&#039;s rendering, object definitions can be either of the following two types:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;The default definition&#039;&#039;&#039; (also known as &amp;quot;script&amp;quot;, &amp;quot;codeless&amp;quot; or &amp;quot;simple&amp;quot; definition) provides basic functionality to load and render a model. Many objects in the game will display in the editor with a properly configured default definition. For example, a ring or a stage decoration can work with the default definition.&lt;br /&gt;
# &#039;&#039;&#039;Custom definitions&#039;&#039;&#039; (also known as &amp;quot;code&amp;quot; definitions) provide custom code for loading the object, rendering its model(s) in the editor and collision checks. These definitions supply separate &amp;lt;code&amp;gt;.cs&amp;lt;/code&amp;gt; files which are compiled by SALVL when it loads a stage.&lt;br /&gt;
&lt;br /&gt;
=== Creating Object Definitions ===&lt;br /&gt;
The following is a list of steps to go through to get a SET object to display in SALVL.&lt;br /&gt;
&lt;br /&gt;
==== Setting up stage properties ====&lt;br /&gt;
&#039;&#039;Note: For PC versions of SADX and SA2 the work on this step has already been done for all stages. The information below is provided for reference.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note 2: The file &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; is found in two locations. The file in &amp;lt;code&amp;gt;SA Tools\GameConfig\PC_SADX&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;PC_SA2&amp;lt;/code&amp;gt;) is copied to the project folder when you make a new mod project. If you are adding custom objects in your mod, edit the file in your mod project folder. If you are making object definitions for vanilla game objects, edit the main file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; file should have an entry for the stage you need that defines level textures, object textures, the location of the object list INI file and the object definition list INI file. Here is an example for Emerald Coast Act 3.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;[Action Stages\\Emerald Coast 3]&lt;br /&gt;
LevelGeometry=stg01_beach/landtable0102.c.sa1lvl&lt;br /&gt;
LevelID=0102&lt;br /&gt;
Textures=BEACH03&lt;br /&gt;
ObjectList=stg01_beach/objList.ini&lt;br /&gt;
ObjectTextureList=stg01_beach/objTextures.ini&lt;br /&gt;
DeathZones=stg01_beach/killcolli/act3/killZones.ini&lt;br /&gt;
Effects=objdefs/Level Effects/EmeraldCoast.cs&lt;br /&gt;
ObjectDefinition=objdefs/stg01.ini&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;LevelGeometry&#039;&#039; is the relative path to the [[LandTable]] file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LevelID&#039;&#039; is the internal ID used by the stage. The first two digits are level ID and the second two digits are act ID. For SA1, see [[Sonic Adventure/Level List]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Textures&#039;&#039; is the name of the texture file (usually PVM, GVM, PRS or PAK) &#039;&#039;&#039;without extension&#039;&#039;&#039; used for level textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectList&#039;&#039; is the relative path to the [[Object List]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DeathZones&#039;&#039; is the relative path to the [[Death Zones]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Effects&#039;&#039; is the relative path to the [[SA Tools/SALVL/Level Definition|Level Definition]] .cs file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectDefinition&#039;&#039; is the relative path to the Object Definition list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Editing the object&#039;s entry in the object definition list&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The objdefs folder can be found in two locations. See the note about &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; in Step 1, it&#039;s the same principle.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The text below describes manual editing of object definition entries in the INI file. If you prefer a GUI editor, you can use the Object Definition Editor in SALVL. Editing object definitions in SALVL will save them to your mod&#039;s project.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Each entry in the object definition list should begin with the object&#039;s internal name in square brackets, which represents the INI section for the entry. All internal names are already filled in at the moment, so you only need to edit the parameters.&lt;br /&gt;
[[File:SA Tools SALVL Object Definitions 1773488122468.png|thumb|SALVL Object Editor that includes the Object Definition Editor.]]&lt;br /&gt;
Here is an example of a &#039;&#039;&#039;custom&#039;&#039;&#039; object definition for the jump panel (internal name &amp;lt;code&amp;gt;O JPanel&amp;lt;/code&amp;gt;). Assuming we&#039;re still working with Emerald Coast, its entry will be in &amp;lt;code&amp;gt;objdefs/stg01.ini&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O JPanel]&lt;br /&gt;
codefile=objdefs/Common/JumpPanel.cs&lt;br /&gt;
codetype=SADXObjectDefinitions.Common.JumpPanel&lt;br /&gt;
Name=Jump Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codefile&#039;&#039; is the relative path to the .cs file containing the code of the custom definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codetype&#039;&#039; is the name of the class used by the definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: codefile and codetype are spelled in all lowercase.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For a tutorial on creating code for a custom object definition, see [[SA Tools/SALVL/Object Definitions/Creating a Custom Object Definition|Creating a Custom Object Definition]].&lt;br /&gt;
&lt;br /&gt;
However, many objects don&#039;t need a custom definition. For example, if the object only displays one model (as in, loaded from a single model file) and doesn&#039;t exhibit any complex behavior that needs to be accounted for in the editor, you can use the default object definition. In many cases, all you have to do is fill in a few parameters for its entry in the INI file to get the object to show up in the editor.&lt;br /&gt;
&lt;br /&gt;
For an example of a codeless object definition, let&#039;s examine the entry for the Master Emerald shard (internal name &amp;lt;code&amp;gt;O EME P&amp;lt;/code&amp;gt;):&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O EME P]&lt;br /&gt;
Name=Emerald Shard&lt;br /&gt;
Model=object/obj_emekakera.nja.sa1mdl&lt;br /&gt;
Texture=OBJ_REGULAR&lt;br /&gt;
RotType=None&lt;br /&gt;
SclType=None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Model&#039;&#039; is the relative path to the object&#039;s model file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texture&#039;&#039; is the filename (without extension) of the texture archive used for loading the object&#039;s textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;RotType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;rotated&#039;&#039;&#039; when the editor renders it. It can be &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; if the object is only rotated on the Y axis (which is the most common), or &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; if all axes are used for rendering. Any other combination of &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; can also be used. If the object model doesn&#039;t need to be rotated at all, use &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SclType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;scaled&#039;&#039;&#039; when the editor renders it. Most objects do not scale, so &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; is often used. The following values are possible:&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;None, // Default scale (X=1.0, Y=1.0, Z=1.0)&lt;br /&gt;
XYZ, // Scale X, Y and Z&lt;br /&gt;
X, // Scale only by the X axis using the X Scale value&lt;br /&gt;
Y, // Scale only by the Y axis using the Y Scale value&lt;br /&gt;
Z, // Scale only by the Z axis using the Z Scale value&lt;br /&gt;
XY, // Scale the X axis using the X Scale value and then by the Y axis using the Y Scale value&lt;br /&gt;
XZ, // Scale the X axis using the X Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
YZ, // Scale the Y axis using the Y Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
AllX, // All axes are scaled by the X Scale value&lt;br /&gt;
AllY, // All axes are scaled by the Y Scale value&lt;br /&gt;
AllZ // All axes are scaled by the Z Scale value&amp;lt;/syntaxhighlight&amp;gt;For the most part, filling in the above parameters (particularly &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039;) is enough for the object to appear in SALVL. For slightly more complex objects the following additional parameters are available:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TexturePacks&#039;&#039; is a comma-separated list of texture files without extension for objects in SA2 that use multiple [[Texture List|texture lists]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texlist&#039;&#039; is the name of the texture list file (&amp;lt;code&amp;gt;.tls&amp;lt;/code&amp;gt;) loaded by the object. This is required for objects that use multiple or partial texture lists.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; are floating point values that offset the model&#039;s initial transformation for rendering. For example, if your object sinks into the ground, it might need a positive &#039;&#039;AddYPos&#039;&#039;, and if it appears higher than it should be it might need a negative &#039;&#039;AddYPos&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXRot&#039;&#039;, &#039;&#039;DefYRot&#039;&#039; and &#039;&#039;DefZRot&#039;&#039; are initial rotations for objects that have a fixed rotation different from the one specified in the SET file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; and &#039;&#039;AddZRot&#039;&#039; are rotation offsets that work just like &#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; but for rotations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: Rotation values are hexadecimal.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039;, &#039;&#039;DefZScl&#039;&#039; are initial scale values, and &#039;&#039;AddXScl&#039;&#039;, &#039;&#039;AddYScl&#039;&#039; and &#039;&#039;AddZScl&#039;&#039; are offset scale values that work under the same principle as the other offsets mentioned above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;GndDst&#039;&#039; is &amp;quot;distance from the ground&amp;quot;, a vertical offset used for placing objects on the ground in SALVL.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IgnorePos&#039;&#039; is a boolean value (&amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;) that tells the renderer and collision checks to ignore the object&#039;s model (&amp;lt;code&amp;gt;NJS_OBJECT&amp;lt;/code&amp;gt;)&#039;s position.&lt;br /&gt;
&lt;br /&gt;
=== Testing Object Definitions ===&lt;br /&gt;
To test an update to object definitions, copy the modified files in the &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder to your mod project&#039;s &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder, (re)start SALVL, open your mod project and load the stage. The following is a list of common errors with object definitions and potential solutions.&lt;br /&gt;
&lt;br /&gt;
==== Object displays as a box with a question mark ====&lt;br /&gt;
In most cases this means that the object definition is missing or incomplete. If you are using the default definition, make sure at least the &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039; fields are specified in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== SALVL Error: &amp;quot;SET objects failed to load their model(s). Please check SET object load errors in the log for details.&amp;quot; ====&lt;br /&gt;
The most likely cause of the error is the model or texture file missing. In SALVL, select &#039;&#039;Help&amp;gt;View Log&#039;&#039; in the top menu and scroll to the bottom of the log to find the error. If you see &amp;quot;Exists: False&amp;quot;, it means the model or texture file was not found. Make sure the path to the model or texture file is correct. Use &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths. If the model does not use textures, do not specify the texture file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears misrotated ====&lt;br /&gt;
Rotate the object using the editor&#039;s rotation gizmo to find the rotation values that make it look correct. Add the difference between these values as &#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; or &#039;&#039;AddZRot&#039;&#039; values in the object definition list INI file. Some objects are rotated on the Y axis by &amp;lt;code&amp;gt;4000&amp;lt;/code&amp;gt; (16384 in decimal), see &amp;lt;code&amp;gt;O STATION BACK&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;adv00.ini&amp;lt;/code&amp;gt; for an example. Alternatively, experiment with default rotations.&lt;br /&gt;
&lt;br /&gt;
==== Object appears too small or too large ====&lt;br /&gt;
Set &#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039; and/or &#039;&#039;DefZScl&#039;&#039;, or add scale offsets in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears in the wrong place ====&lt;br /&gt;
If there is a fixed difference (always 10 units above or below etc.), add a position offset. Alternatively, add &#039;&#039;IgnorePos=True&#039;&#039; in the object definition list INI file. If that doesn&#039;t help, try a different rotation order or experiment with a combination of all of the above.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=728</id>
		<title>SA Tools/SALVL/Object Definitions</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=728"/>
		<updated>2026-03-14T12:11:16Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction to Object Definitions ==&lt;br /&gt;
An object definition is a part of a [[SA Tools/Project template|project template]] that enables [[SA Tools/SALVL|SALVL]] to display [[SET Object|SET objects]] in the editor. The object definition sets up the object&#039;s model and textures, provides the position, rotation and scale routines to make the object look like it does ingame, and optionally converts SET data into customizable variables used to pick variations of the object or alter its behavior ingame.&lt;br /&gt;
&lt;br /&gt;
=== Types of Object Definitions ===&lt;br /&gt;
Depending on the complexity of the object&#039;s rendering, object definitions can be either of the following two types:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;The default definition&#039;&#039;&#039; (also known as &amp;quot;script&amp;quot;, &amp;quot;codeless&amp;quot; or &amp;quot;simple&amp;quot; definition) provides basic functionality to load and render a model. Many objects in the game will display in the editor with a properly configured default definition. For example, a ring or a stage decoration can work with the default definition.&lt;br /&gt;
# &#039;&#039;&#039;Custom definitions&#039;&#039;&#039; (also known as &amp;quot;code&amp;quot; definitions) provide custom code for loading the object, rendering its model(s) in the editor and collision checks. These definitions supply separate &amp;lt;code&amp;gt;.cs&amp;lt;/code&amp;gt; files which are compiled by SALVL when it loads a stage.&lt;br /&gt;
&lt;br /&gt;
=== Creating Object Definitions ===&lt;br /&gt;
The following is a list of steps to go through to get a SET object to display in SALVL.&lt;br /&gt;
&lt;br /&gt;
==== Setting up stage properties ====&lt;br /&gt;
&#039;&#039;Note: For PC versions of SADX and SA2 the work on this step has already been done for all stages. The information below is provided for reference.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note 2: The file &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; is found in two locations. The file in &amp;lt;code&amp;gt;SA Tools\GameConfig\PC_SADX&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;PC_SA2&amp;lt;/code&amp;gt;) is copied to the project folder when you make a new mod project. If you are adding custom objects in your mod, edit the file in your mod project folder. If you are making object definitions for vanilla game objects, edit the main file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; file should have an entry for the stage you need that defines level textures, object textures, the location of the object list INI file and the object definition list INI file. Here is an example for Emerald Coast Act 3.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;[Action Stages\\Emerald Coast 3]&lt;br /&gt;
LevelGeometry=stg01_beach/landtable0102.c.sa1lvl&lt;br /&gt;
LevelID=0102&lt;br /&gt;
Textures=BEACH03&lt;br /&gt;
ObjectList=stg01_beach/objList.ini&lt;br /&gt;
ObjectTextureList=stg01_beach/objTextures.ini&lt;br /&gt;
DeathZones=stg01_beach/killcolli/act3/killZones.ini&lt;br /&gt;
Effects=objdefs/Level Effects/EmeraldCoast.cs&lt;br /&gt;
ObjectDefinition=objdefs/stg01.ini&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;LevelGeometry&#039;&#039; is the relative path to the [[LandTable]] file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LevelID&#039;&#039; is the internal ID used by the stage. The first two digits are level ID and the second two digits are act ID. For SA1, see [[Sonic Adventure/Level List]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Textures&#039;&#039; is the name of the texture file (usually PVM, GVM, PRS or PAK) &#039;&#039;&#039;without extension&#039;&#039;&#039; used for level textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectList&#039;&#039; is the relative path to the [[Object List]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DeathZones&#039;&#039; is the relative path to the [[Death Zones]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Effects&#039;&#039; is the relative path to the [[SA Tools/SALVL/Level Definition|Level Definition]] .cs file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectDefinition&#039;&#039; is the relative path to the Object Definition list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Editing the object&#039;s entry in the object definition list&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The objdefs folder can be found in two locations. See the note about &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; in Step 1, it&#039;s the same principle.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The text below describes manual editing of object definition entries in the INI file. If you prefer a GUI editor, you can use the Object Definition Editor in SALVL. Editing object definitions in SALVL will save them to your mod&#039;s project.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Each entry in the object definition list should begin with the object&#039;s internal name in square brackets, which represents the INI section for the entry. All internal names are already filled in at the moment, so you only need to edit the parameters.&lt;br /&gt;
[[File:SA Tools SALVL Object Definitions 1773488122468.png|thumb|SALVL Object Editor that includes the Object Definition Editor.]]&lt;br /&gt;
Here is an example of a &#039;&#039;&#039;custom&#039;&#039;&#039; object definition for the jump panel (internal name &amp;lt;code&amp;gt;O JPanel&amp;lt;/code&amp;gt;). Assuming we&#039;re still working with Emerald Coast, its entry will be in &amp;lt;code&amp;gt;objdefs/stg01.ini&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O JPanel]&lt;br /&gt;
codefile=objdefs/Common/JumpPanel.cs&lt;br /&gt;
codetype=SADXObjectDefinitions.Common.JumpPanel&lt;br /&gt;
Name=Jump Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codefile&#039;&#039; is the relative path to the .cs file containing the code of the custom definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codetype&#039;&#039; is the name of the class used by the definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: codefile and codetype are spelled in all lowercase.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For a tutorial on creating code for a custom object definition, see [[SA Tools/SALVL/Object Definitions/Creating a Custom Object Definition|Creating a Custom Object Definition]].&lt;br /&gt;
&lt;br /&gt;
However, many objects don&#039;t need a custom definition. For example, if the object only displays one model (as in, loaded from a single model file) and doesn&#039;t exhibit any complex behavior that needs to be accounted for in the editor, you can use the default object definition. In many cases, all you have to do is fill in a few parameters in the its entry to get the object to show up in the editor.&lt;br /&gt;
&lt;br /&gt;
For an example of a codeless object definition, let&#039;s examine the entry for the Master Emerald shard (internal name &amp;lt;code&amp;gt;O EME P&amp;lt;/code&amp;gt;):&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O EME P]&lt;br /&gt;
Name=Emerald Shard&lt;br /&gt;
Model=object/obj_emekakera.nja.sa1mdl&lt;br /&gt;
Texture=OBJ_REGULAR&lt;br /&gt;
RotType=None&lt;br /&gt;
SclType=None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Model&#039;&#039; is the relative path to the object&#039;s model file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texture&#039;&#039; is the filename (without extension) of the texture archive used for loading the object&#039;s textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;RotType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;rotated&#039;&#039;&#039; when the editor renders it. It can be &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; if the object is only rotated on the Y axis (which is the most common), or &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; if all axes are used for rendering. Any other combination of &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; can also be used. If the object model doesn&#039;t need to be rotated at all, use &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SclType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;scaled&#039;&#039;&#039; when the editor renders it. Most objects do not scale, so &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; is often used. The following values are possible:&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;None, // Default scale (X=1.0, Y=1.0, Z=1.0)&lt;br /&gt;
XYZ, // Scale X, Y and Z&lt;br /&gt;
X, // Scale only by the X axis using the X Scale value&lt;br /&gt;
Y, // Scale only by the Y axis using the Y Scale value&lt;br /&gt;
Z, // Scale only by the Z axis using the Z Scale value&lt;br /&gt;
XY, // Scale the X axis using the X Scale value and then by the Y axis using the Y Scale value&lt;br /&gt;
XZ, // Scale the X axis using the X Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
YZ, // Scale the Y axis using the Y Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
AllX, // All axes are scaled by the X Scale value&lt;br /&gt;
AllY, // All axes are scaled by the Y Scale value&lt;br /&gt;
AllZ // All axes are scaled by the Z Scale value&amp;lt;/syntaxhighlight&amp;gt;For the most part, filling in the above parameters (particularly &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039;) is enough for the object to appear in SALVL. For slightly more complex objects the following additional parameters are available:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TexturePacks&#039;&#039; is a comma-separated list of texture files without extension for objects in SA2 that use multiple [[Texture List|texture lists]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texlist&#039;&#039; is the name of the texture list file (&amp;lt;code&amp;gt;.tls&amp;lt;/code&amp;gt;) loaded by the object. This is required for objects that use multiple or partial texture lists.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; are floating point values that offset the model&#039;s initial transformation for rendering. For example, if your object sinks into the ground, it might need a positive &#039;&#039;AddYPos&#039;&#039;, and if it appears higher than it should be it might need a negative &#039;&#039;AddYPos&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXRot&#039;&#039;, &#039;&#039;DefYRot&#039;&#039; and &#039;&#039;DefZRot&#039;&#039; are initial rotations for objects that have a fixed rotation different from the one specified in the SET file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; and &#039;&#039;AddZRot&#039;&#039; are rotation offsets that work just like &#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; but for rotations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: Rotation values are hexadecimal.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039;, &#039;&#039;DefZScl&#039;&#039; are initial scale values, and &#039;&#039;AddXScl&#039;&#039;, &#039;&#039;AddYScl&#039;&#039; and &#039;&#039;AddZScl&#039;&#039; are offset scale values that work under the same principle as the other offsets mentioned above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;GndDst&#039;&#039; is &amp;quot;distance from the ground&amp;quot;, a vertical offset used for placing objects on the ground in SALVL.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IgnorePos&#039;&#039; is a boolean value (&amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;) that tells the renderer and collision checks to ignore the object&#039;s model (&amp;lt;code&amp;gt;NJS_OBJECT&amp;lt;/code&amp;gt;)&#039;s position.&lt;br /&gt;
&lt;br /&gt;
=== Testing Object Definitions ===&lt;br /&gt;
To test an update to object definitions, copy the modified files in the &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder to your mod project&#039;s &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder, (re)start SALVL, open your mod project and load the stage. The following is a list of common errors with object definitions and potential solutions.&lt;br /&gt;
&lt;br /&gt;
==== Object displays as a box with a question mark ====&lt;br /&gt;
In most cases this means that the object definition is missing or incomplete. If you are using the default definition, make sure at least the &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039; fields are specified in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== SALVL Error: &amp;quot;SET objects failed to load their model(s). Please check SET object load errors in the log for details.&amp;quot; ====&lt;br /&gt;
The most likely cause of the error is the model or texture file missing. In SALVL, select &#039;&#039;Help&amp;gt;View Log&#039;&#039; in the top menu and scroll to the bottom of the log to find the error. If you see &amp;quot;Exists: False&amp;quot;, it means the model or texture file was not found. Make sure the path to the model or texture file is correct. Use &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths. If the model does not use textures, do not specify the texture file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears misrotated ====&lt;br /&gt;
Rotate the object using the editor&#039;s rotation gizmo to find the rotation values that make it look correct. Add the difference between these values as &#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; or &#039;&#039;AddZRot&#039;&#039; values in the object definition list INI file. Some objects are rotated on the Y axis by &amp;lt;code&amp;gt;4000&amp;lt;/code&amp;gt; (16384 in decimal), see &amp;lt;code&amp;gt;O STATION BACK&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;adv00.ini&amp;lt;/code&amp;gt; for an example. Alternatively, experiment with default rotations.&lt;br /&gt;
&lt;br /&gt;
==== Object appears too small or too large ====&lt;br /&gt;
Set &#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039; and/or &#039;&#039;DefZScl&#039;&#039;, or add scale offsets in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears in the wrong place ====&lt;br /&gt;
If there is a fixed difference (always 10 units above or below etc.), add a position offset. Alternatively, add &#039;&#039;IgnorePos=True&#039;&#039; in the object definition list INI file. If that doesn&#039;t help, try a different rotation order or experiment with a combination of all of the above.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=727</id>
		<title>SA Tools/SALVL/Object Definitions</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=727"/>
		<updated>2026-03-14T12:09:58Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction to Object Definitions ==&lt;br /&gt;
An object definition is a part of a [[SA Tools/Project template|project template]] that enables [[SA Tools/SALVL|SALVL]] to display [[SET Object|SET objects]] in the editor. The object definition sets up the object&#039;s model and textures, provides the position, rotation and scale routines to make the object look like it does ingame, and optionally converts SET data into customizable variables used to pick variations of the object or alter its behavior ingame.&lt;br /&gt;
&lt;br /&gt;
=== Types of Object Definitions ===&lt;br /&gt;
Depending on the complexity of the object&#039;s rendering, object definitions can be either of the following two types:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;The default definition&#039;&#039;&#039; (also known as &amp;quot;script&amp;quot;, &amp;quot;codeless&amp;quot; or &amp;quot;simple&amp;quot; definition) provides basic functionality to load and render a model. Many objects in the game will display in the editor with a properly configured default definition. For example, a ring or a stage decoration can work with the default definition.&lt;br /&gt;
# &#039;&#039;&#039;Custom definitions&#039;&#039;&#039; (also known as &amp;quot;code&amp;quot; definitions) provide custom code for loading the object, rendering its model(s) in the editor and collision checks. These definitions supply separate &amp;lt;code&amp;gt;.cs&amp;lt;/code&amp;gt; files which are compiled by SALVL when it loads a stage.&lt;br /&gt;
&lt;br /&gt;
=== Creating Object Definitions ===&lt;br /&gt;
The following is a list of steps to go through to get a SET object to display in SALVL.&lt;br /&gt;
&lt;br /&gt;
==== Setting up stage properties ====&lt;br /&gt;
&#039;&#039;Note: For PC versions of SADX and SA2 the work on this step has already been done for all stages. The information below is provided for reference.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note 2: The file &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; is found in two locations. The file in &amp;lt;code&amp;gt;SA Tools\GameConfig\PC_SADX&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;PC_SA2&amp;lt;/code&amp;gt;) is copied to the project folder when you make a new mod project. If you are adding custom objects in your mod, edit the file in your mod project folder. If you are making object definitions for vanilla game objects, edit the main file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; file should have an entry for the stage you need that defines level textures, object textures, the location of the object list INI file and the object definition list INI file. Here is an example for Emerald Coast Act 3.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;[Action Stages\\Emerald Coast 3]&lt;br /&gt;
LevelGeometry=stg01_beach/landtable0102.c.sa1lvl&lt;br /&gt;
LevelID=0102&lt;br /&gt;
Textures=BEACH03&lt;br /&gt;
ObjectList=stg01_beach/objList.ini&lt;br /&gt;
ObjectTextureList=stg01_beach/objTextures.ini&lt;br /&gt;
DeathZones=stg01_beach/killcolli/act3/killZones.ini&lt;br /&gt;
Effects=objdefs/Level Effects/EmeraldCoast.cs&lt;br /&gt;
ObjectDefinition=objdefs/stg01.ini&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;LevelGeometry&#039;&#039; is the relative path to the [[LandTable]] file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LevelID&#039;&#039; is the internal ID used by the stage. The first two digits are level ID and the second two digits are act ID. For SA1, see [[Sonic Adventure/Level List]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Textures&#039;&#039; is the name of the texture file (usually PVM, GVM, PRS or PAK) &#039;&#039;&#039;without extension&#039;&#039;&#039; used for level textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectList&#039;&#039; is the relative path to the [[Object List]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DeathZones&#039;&#039; is the relative path to the [[Death Zones]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Effects&#039;&#039; is the relative path to the [[SA Tools/SALVL/Level Definition|Level Definition]] .cs file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectDefinition&#039;&#039; is the relative path to the Object Definition list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Editing the object&#039;s entry in the object definition list&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The objdefs folder can be found in two locations. See the note about &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; in Step 1, it&#039;s the same principle.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The text below describes manual editing of object definition entries in the INI file. If you prefer a GUI editor, you can use the Object Definition Editor in SALVL. Editing object definitions in SALVL will save them to your mod&#039;s project.&#039;&#039;&lt;br /&gt;
[[File:SA Tools SALVL Object Definitions 1773488122468.png|thumb|SALVL Object Editor that includes the Object Definition Editor.]]&lt;br /&gt;
Here is an example of a &#039;&#039;&#039;custom&#039;&#039;&#039; object definition for the jump panel (internal name &amp;lt;code&amp;gt;O JPanel&amp;lt;/code&amp;gt;). Assuming we&#039;re still working with Emerald Coast, its entry will be in &amp;lt;code&amp;gt;objdefs/stg01.ini&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Each entry should begin with the object&#039;s internal name in square brackets, which represents the INI section for the entry. All internal names are already filled in at the moment, so you only need to edit the parameters.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O JPanel]&lt;br /&gt;
codefile=objdefs/Common/JumpPanel.cs&lt;br /&gt;
codetype=SADXObjectDefinitions.Common.JumpPanel&lt;br /&gt;
Name=Jump Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codefile&#039;&#039; is the relative path to the .cs file containing the code of the custom definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codetype&#039;&#039; is the name of the class used by the definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: codefile and codetype are spelled in all lowercase.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For a tutorial on creating code for a custom object definition, see [[SA Tools/SALVL/Object Definitions/Creating a Custom Object Definition|Creating a Custom Object Definition]].&lt;br /&gt;
&lt;br /&gt;
However, many objects don&#039;t need a custom definition. For example, if the object only displays one model (as in, loaded from a single model file) and doesn&#039;t exhibit any complex behavior that needs to be accounted for in the editor, you can use the default object definition. In many cases, all you have to do is fill in a few parameters in the its entry to get the object to show up in the editor.&lt;br /&gt;
&lt;br /&gt;
For an example of a codeless object definition, let&#039;s examine the entry for the Master Emerald shard (internal name &amp;lt;code&amp;gt;O EME P&amp;lt;/code&amp;gt;):&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O EME P]&lt;br /&gt;
Name=Emerald Shard&lt;br /&gt;
Model=object/obj_emekakera.nja.sa1mdl&lt;br /&gt;
Texture=OBJ_REGULAR&lt;br /&gt;
RotType=None&lt;br /&gt;
SclType=None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Model&#039;&#039; is the relative path to the object&#039;s model file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texture&#039;&#039; is the filename (without extension) of the texture archive used for loading the object&#039;s textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;RotType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;rotated&#039;&#039;&#039; when the editor renders it. It can be &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; if the object is only rotated on the Y axis (which is the most common), or &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; if all axes are used for rendering. Any other combination of &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; can also be used. If the object model doesn&#039;t need to be rotated at all, use &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SclType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;scaled&#039;&#039;&#039; when the editor renders it. Most objects do not scale, so &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; is often used. The following values are possible:&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;None, // Default scale (X=1.0, Y=1.0, Z=1.0)&lt;br /&gt;
XYZ, // Scale X, Y and Z&lt;br /&gt;
X, // Scale only by the X axis using the X Scale value&lt;br /&gt;
Y, // Scale only by the Y axis using the Y Scale value&lt;br /&gt;
Z, // Scale only by the Z axis using the Z Scale value&lt;br /&gt;
XY, // Scale the X axis using the X Scale value and then by the Y axis using the Y Scale value&lt;br /&gt;
XZ, // Scale the X axis using the X Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
YZ, // Scale the Y axis using the Y Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
AllX, // All axes are scaled by the X Scale value&lt;br /&gt;
AllY, // All axes are scaled by the Y Scale value&lt;br /&gt;
AllZ // All axes are scaled by the Z Scale value&amp;lt;/syntaxhighlight&amp;gt;For the most part, filling in the above parameters (particularly &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039;) is enough for the object to appear in SALVL. For slightly more complex objects the following additional parameters are available:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TexturePacks&#039;&#039; is a comma-separated list of texture files without extension for objects in SA2 that use multiple [[Texture List|texture lists]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texlist&#039;&#039; is the name of the texture list file (&amp;lt;code&amp;gt;.tls&amp;lt;/code&amp;gt;) loaded by the object. This is required for objects that use multiple or partial texture lists.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; are floating point values that offset the model&#039;s initial transformation for rendering. For example, if your object sinks into the ground, it might need a positive &#039;&#039;AddYPos&#039;&#039;, and if it appears higher than it should be it might need a negative &#039;&#039;AddYPos&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXRot&#039;&#039;, &#039;&#039;DefYRot&#039;&#039; and &#039;&#039;DefZRot&#039;&#039; are initial rotations for objects that have a fixed rotation different from the one specified in the SET file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; and &#039;&#039;AddZRot&#039;&#039; are rotation offsets that work just like &#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; but for rotations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: Rotation values are hexadecimal.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039;, &#039;&#039;DefZScl&#039;&#039; are initial scale values, and &#039;&#039;AddXScl&#039;&#039;, &#039;&#039;AddYScl&#039;&#039; and &#039;&#039;AddZScl&#039;&#039; are offset scale values that work under the same principle as the other offsets mentioned above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;GndDst&#039;&#039; is &amp;quot;distance from the ground&amp;quot;, a vertical offset used for placing objects on the ground in SALVL.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IgnorePos&#039;&#039; is a boolean value (&amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;) that tells the renderer and collision checks to ignore the object&#039;s model (&amp;lt;code&amp;gt;NJS_OBJECT&amp;lt;/code&amp;gt;)&#039;s position.&lt;br /&gt;
&lt;br /&gt;
=== Testing Object Definitions ===&lt;br /&gt;
To test an update to object definitions, copy the modified files in the &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder to your mod project&#039;s &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder, (re)start SALVL, open your mod project and load the stage. The following is a list of common errors with object definitions and potential solutions.&lt;br /&gt;
&lt;br /&gt;
==== Object displays as a box with a question mark ====&lt;br /&gt;
In most cases this means that the object definition is missing or incomplete. If you are using the default definition, make sure at least the &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039; fields are specified in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== SALVL Error: &amp;quot;SET objects failed to load their model(s). Please check SET object load errors in the log for details.&amp;quot; ====&lt;br /&gt;
The most likely cause of the error is the model or texture file missing. In SALVL, select &#039;&#039;Help&amp;gt;View Log&#039;&#039; in the top menu and scroll to the bottom of the log to find the error. If you see &amp;quot;Exists: False&amp;quot;, it means the model or texture file was not found. Make sure the path to the model or texture file is correct. Use &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths. If the model does not use textures, do not specify the texture file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears misrotated ====&lt;br /&gt;
Rotate the object using the editor&#039;s rotation gizmo to find the rotation values that make it look correct. Add the difference between these values as &#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; or &#039;&#039;AddZRot&#039;&#039; values in the object definition list INI file. Some objects are rotated on the Y axis by &amp;lt;code&amp;gt;4000&amp;lt;/code&amp;gt; (16384 in decimal), see &amp;lt;code&amp;gt;O STATION BACK&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;adv00.ini&amp;lt;/code&amp;gt; for an example. Alternatively, experiment with default rotations.&lt;br /&gt;
&lt;br /&gt;
==== Object appears too small or too large ====&lt;br /&gt;
Set &#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039; and/or &#039;&#039;DefZScl&#039;&#039;, or add scale offsets in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears in the wrong place ====&lt;br /&gt;
If there is a fixed difference (always 10 units above or below etc.), add a position offset. Alternatively, add &#039;&#039;IgnorePos=True&#039;&#039; in the object definition list INI file. If that doesn&#039;t help, try a different rotation order or experiment with a combination of all of the above.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=726</id>
		<title>SA Tools/SALVL/Object Definitions</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=726"/>
		<updated>2026-03-14T12:09:24Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction to Object Definitions ==&lt;br /&gt;
An object definition is a part of a [[SA Tools/Project template|project template]] that enables [[SA Tools/SALVL|SALVL]] to display [[SET Object|SET objects]] in the editor. The object definition sets up the object&#039;s model and textures, provides the position, rotation and scale routines to make the object look like it does ingame, and optionally converts SET data into customizable variables used to pick variations of the object or alter its behavior ingame.&lt;br /&gt;
&lt;br /&gt;
=== Types of Object Definitions ===&lt;br /&gt;
Depending on the complexity of the object&#039;s rendering, object definitions can be either of the following two types:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;The default definition&#039;&#039;&#039; (also known as &amp;quot;script&amp;quot;, &amp;quot;codeless&amp;quot; or &amp;quot;simple&amp;quot; definition) provides basic functionality to load and render a model. Many objects in the game will display in the editor with a properly configured default definition. For example, a ring or a stage decoration can work with the default definition.&lt;br /&gt;
# &#039;&#039;&#039;Custom definitions&#039;&#039;&#039; (also known as &amp;quot;code&amp;quot; definitions) provide custom code for loading the object, rendering its model(s) in the editor and collision checks. These definitions supply separate &amp;lt;code&amp;gt;.cs&amp;lt;/code&amp;gt; files which are compiled by SALVL when it loads a stage.&lt;br /&gt;
&lt;br /&gt;
=== Creating Object Definitions ===&lt;br /&gt;
To display a SET object in SALVL, several things are required. The following is a list of steps to go through to get an object working in the editor.&lt;br /&gt;
&lt;br /&gt;
==== Setting up stage properties ====&lt;br /&gt;
&#039;&#039;Note: For PC versions of SADX and SA2 the work on this step has already been done for all stages. The information below is provided for reference.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note 2: The file &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; is found in two locations. The file in &amp;lt;code&amp;gt;SA Tools\GameConfig\PC_SADX&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;PC_SA2&amp;lt;/code&amp;gt;) is copied to the project folder when you make a new mod project. If you are adding custom objects in your mod, edit the file in your mod project folder. If you are making object definitions for vanilla game objects, edit the main file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; file should have an entry for the stage you need that defines level textures, object textures, the location of the object list INI file and the object definition list INI file. Here is an example for Emerald Coast Act 3.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;[Action Stages\\Emerald Coast 3]&lt;br /&gt;
LevelGeometry=stg01_beach/landtable0102.c.sa1lvl&lt;br /&gt;
LevelID=0102&lt;br /&gt;
Textures=BEACH03&lt;br /&gt;
ObjectList=stg01_beach/objList.ini&lt;br /&gt;
ObjectTextureList=stg01_beach/objTextures.ini&lt;br /&gt;
DeathZones=stg01_beach/killcolli/act3/killZones.ini&lt;br /&gt;
Effects=objdefs/Level Effects/EmeraldCoast.cs&lt;br /&gt;
ObjectDefinition=objdefs/stg01.ini&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;LevelGeometry&#039;&#039; is the relative path to the [[LandTable]] file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LevelID&#039;&#039; is the internal ID used by the stage. The first two digits are level ID and the second two digits are act ID. For SA1, see [[Sonic Adventure/Level List]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Textures&#039;&#039; is the name of the texture file (usually PVM, GVM, PRS or PAK) &#039;&#039;&#039;without extension&#039;&#039;&#039; used for level textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectList&#039;&#039; is the relative path to the [[Object List]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DeathZones&#039;&#039; is the relative path to the [[Death Zones]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Effects&#039;&#039; is the relative path to the [[SA Tools/SALVL/Level Definition|Level Definition]] .cs file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectDefinition&#039;&#039; is the relative path to the Object Definition list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Editing the object&#039;s entry in the object definition list&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The objdefs folder can be found in two locations. See the note about &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; in Step 1, it&#039;s the same principle.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The text below describes manual editing of object definition entries in the INI file. If you prefer a GUI editor, you can use the Object Definition Editor in SALVL. Editing object definitions in SALVL will save them to your mod&#039;s project.&#039;&#039;&lt;br /&gt;
[[File:SA Tools SALVL Object Definitions 1773488122468.png|thumb|SALVL Object Editor that includes the Object Definition Editor.]]&lt;br /&gt;
Here is an example of a &#039;&#039;&#039;custom&#039;&#039;&#039; object definition for the jump panel (internal name &amp;lt;code&amp;gt;O JPanel&amp;lt;/code&amp;gt;). Assuming we&#039;re still working with Emerald Coast, its entry will be in &amp;lt;code&amp;gt;objdefs/stg01.ini&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Each entry should begin with the object&#039;s internal name in square brackets, which represents the INI section for the entry. All internal names are already filled in at the moment, so you only need to edit the parameters.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O JPanel]&lt;br /&gt;
codefile=objdefs/Common/JumpPanel.cs&lt;br /&gt;
codetype=SADXObjectDefinitions.Common.JumpPanel&lt;br /&gt;
Name=Jump Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codefile&#039;&#039; is the relative path to the .cs file containing the code of the custom definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codetype&#039;&#039; is the name of the class used by the definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: codefile and codetype are spelled in all lowercase.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For a tutorial on creating code for a custom object definition, see [[SA Tools/SALVL/Object Definitions/Creating a Custom Object Definition|Creating a Custom Object Definition]].&lt;br /&gt;
&lt;br /&gt;
However, many objects don&#039;t need a custom definition. For example, if the object only displays one model (as in, loaded from a single model file) and doesn&#039;t exhibit any complex behavior that needs to be accounted for in the editor, you can use the default object definition. In many cases, all you have to do is fill in a few parameters in the its entry to get the object to show up in the editor.&lt;br /&gt;
&lt;br /&gt;
For an example of a codeless object definition, let&#039;s examine the entry for the Master Emerald shard (internal name &amp;lt;code&amp;gt;O EME P&amp;lt;/code&amp;gt;):&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O EME P]&lt;br /&gt;
Name=Emerald Shard&lt;br /&gt;
Model=object/obj_emekakera.nja.sa1mdl&lt;br /&gt;
Texture=OBJ_REGULAR&lt;br /&gt;
RotType=None&lt;br /&gt;
SclType=None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Model&#039;&#039; is the relative path to the object&#039;s model file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texture&#039;&#039; is the filename (without extension) of the texture archive used for loading the object&#039;s textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;RotType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;rotated&#039;&#039;&#039; when the editor renders it. It can be &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; if the object is only rotated on the Y axis (which is the most common), or &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; if all axes are used for rendering. Any other combination of &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; can also be used. If the object model doesn&#039;t need to be rotated at all, use &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SclType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;scaled&#039;&#039;&#039; when the editor renders it. Most objects do not scale, so &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; is often used. The following values are possible:&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;None, // Default scale (X=1.0, Y=1.0, Z=1.0)&lt;br /&gt;
XYZ, // Scale X, Y and Z&lt;br /&gt;
X, // Scale only by the X axis using the X Scale value&lt;br /&gt;
Y, // Scale only by the Y axis using the Y Scale value&lt;br /&gt;
Z, // Scale only by the Z axis using the Z Scale value&lt;br /&gt;
XY, // Scale the X axis using the X Scale value and then by the Y axis using the Y Scale value&lt;br /&gt;
XZ, // Scale the X axis using the X Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
YZ, // Scale the Y axis using the Y Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
AllX, // All axes are scaled by the X Scale value&lt;br /&gt;
AllY, // All axes are scaled by the Y Scale value&lt;br /&gt;
AllZ // All axes are scaled by the Z Scale value&amp;lt;/syntaxhighlight&amp;gt;For the most part, filling in the above parameters (particularly &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039;) is enough for the object to appear in SALVL. For slightly more complex objects the following additional parameters are available:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TexturePacks&#039;&#039; is a comma-separated list of texture files without extension for objects in SA2 that use multiple [[Texture List|texture lists]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texlist&#039;&#039; is the name of the texture list file (&amp;lt;code&amp;gt;.tls&amp;lt;/code&amp;gt;) loaded by the object. This is required for objects that use multiple or partial texture lists.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; are floating point values that offset the model&#039;s initial transformation for rendering. For example, if your object sinks into the ground, it might need a positive &#039;&#039;AddYPos&#039;&#039;, and if it appears higher than it should be it might need a negative &#039;&#039;AddYPos&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXRot&#039;&#039;, &#039;&#039;DefYRot&#039;&#039; and &#039;&#039;DefZRot&#039;&#039; are initial rotations for objects that have a fixed rotation different from the one specified in the SET file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; and &#039;&#039;AddZRot&#039;&#039; are rotation offsets that work just like &#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; but for rotations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: Rotation values are hexadecimal.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039;, &#039;&#039;DefZScl&#039;&#039; are initial scale values, and &#039;&#039;AddXScl&#039;&#039;, &#039;&#039;AddYScl&#039;&#039; and &#039;&#039;AddZScl&#039;&#039; are offset scale values that work under the same principle as the other offsets mentioned above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;GndDst&#039;&#039; is &amp;quot;distance from the ground&amp;quot;, a vertical offset used for placing objects on the ground in SALVL.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IgnorePos&#039;&#039; is a boolean value (&amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;) that tells the renderer and collision checks to ignore the object&#039;s model (&amp;lt;code&amp;gt;NJS_OBJECT&amp;lt;/code&amp;gt;)&#039;s position.&lt;br /&gt;
&lt;br /&gt;
=== Testing Object Definitions ===&lt;br /&gt;
To test an update to object definitions, copy the modified files in the &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder to your mod project&#039;s &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder, (re)start SALVL, open your mod project and load the stage. The following is a list of common errors with object definitions and potential solutions.&lt;br /&gt;
&lt;br /&gt;
==== Object displays as a box with a question mark ====&lt;br /&gt;
In most cases this means that the object definition is missing or incomplete. If you are using the default definition, make sure at least the &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039; fields are specified in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== SALVL Error: &amp;quot;SET objects failed to load their model(s). Please check SET object load errors in the log for details.&amp;quot; ====&lt;br /&gt;
The most likely cause of the error is the model or texture file missing. In SALVL, select &#039;&#039;Help&amp;gt;View Log&#039;&#039; in the top menu and scroll to the bottom of the log to find the error. If you see &amp;quot;Exists: False&amp;quot;, it means the model or texture file was not found. Make sure the path to the model or texture file is correct. Use &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths. If the model does not use textures, do not specify the texture file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears misrotated ====&lt;br /&gt;
Rotate the object using the editor&#039;s rotation gizmo to find the rotation values that make it look correct. Add the difference between these values as &#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; or &#039;&#039;AddZRot&#039;&#039; values in the object definition list INI file. Some objects are rotated on the Y axis by &amp;lt;code&amp;gt;4000&amp;lt;/code&amp;gt; (16384 in decimal), see &amp;lt;code&amp;gt;O STATION BACK&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;adv00.ini&amp;lt;/code&amp;gt; for an example. Alternatively, experiment with default rotations.&lt;br /&gt;
&lt;br /&gt;
==== Object appears too small or too large ====&lt;br /&gt;
Set &#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039; and/or &#039;&#039;DefZScl&#039;&#039;, or add scale offsets in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears in the wrong place ====&lt;br /&gt;
If there is a fixed difference (always 10 units above or below etc.), add a position offset. Alternatively, add &#039;&#039;IgnorePos=True&#039;&#039; in the object definition list INI file. If that doesn&#039;t help, try a different rotation order or experiment with a combination of all of the above.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=725</id>
		<title>SA Tools/SALVL/Object Definitions</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=725"/>
		<updated>2026-03-14T12:05:29Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction to Object Definitions ==&lt;br /&gt;
An object definition is a part of a [[SA Tools/Project template|project template]] that enables [[SA Tools/SALVL|SALVL]] to display [[SET Object|SET objects]] in the editor. The object definition sets up the object&#039;s model and textures, provides the position, rotation and scale routines to make the object look like it does ingame, and optionally converts SET data into customizable variables used to pick variations of the object or alter its behavior ingame.&lt;br /&gt;
&lt;br /&gt;
=== Types of Object Definitions ===&lt;br /&gt;
Depending on the complexity of the object&#039;s rendering, object definitions can be either of the following two types:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;The default definition&#039;&#039;&#039; (also known as &amp;quot;script&amp;quot;, &amp;quot;codeless&amp;quot; or &amp;quot;simple&amp;quot; definition) provides basic functionality to load and render a model. Many objects in the game will display in the editor with a properly configured default definition. For example, a ring or a stage decoration can work with the default definition.&lt;br /&gt;
# &#039;&#039;&#039;Custom definitions&#039;&#039;&#039; (also known as &amp;quot;code&amp;quot; definitions) that provide their own code for loading the object, rendering its model(s) in the editor and collision checks. These definitions supply their own code in separate .cs files which are compiled by SALVL when it loads a stage.&lt;br /&gt;
&lt;br /&gt;
=== Creating Object Definitions ===&lt;br /&gt;
To display a SET object in SALVL, several things are required. The following is a list of steps to go through to get an object working in the editor.&lt;br /&gt;
&lt;br /&gt;
==== Setting up stage properties ====&lt;br /&gt;
&#039;&#039;Note: For PC versions of SADX and SA2 the work on this step has already been done for all stages. The information below is provided for reference.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note 2: The file &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; is found in two locations. The file in &amp;lt;code&amp;gt;SA Tools\GameConfig\PC_SADX&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;PC_SA2&amp;lt;/code&amp;gt;) is copied to the project folder when you make a new mod project. If you are adding custom objects in your mod, edit the file in your mod project folder. If you are making object definitions for vanilla game objects, edit the main file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; file should have an entry for the stage you need that defines level textures, object textures, the location of the object list INI file and the object definition list INI file. Here is an example for Emerald Coast Act 3.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;[Action Stages\\Emerald Coast 3]&lt;br /&gt;
LevelGeometry=stg01_beach/landtable0102.c.sa1lvl&lt;br /&gt;
LevelID=0102&lt;br /&gt;
Textures=BEACH03&lt;br /&gt;
ObjectList=stg01_beach/objList.ini&lt;br /&gt;
ObjectTextureList=stg01_beach/objTextures.ini&lt;br /&gt;
DeathZones=stg01_beach/killcolli/act3/killZones.ini&lt;br /&gt;
Effects=objdefs/Level Effects/EmeraldCoast.cs&lt;br /&gt;
ObjectDefinition=objdefs/stg01.ini&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;LevelGeometry&#039;&#039; is the relative path to the [[LandTable]] file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LevelID&#039;&#039; is the internal ID used by the stage. The first two digits are level ID and the second two digits are act ID. For SA1, see [[Sonic Adventure/Level List]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Textures&#039;&#039; is the name of the texture file (usually PVM, GVM, PRS or PAK) &#039;&#039;&#039;without extension&#039;&#039;&#039; used for level textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectList&#039;&#039; is the relative path to the [[Object List]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DeathZones&#039;&#039; is the relative path to the [[Death Zones]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Effects&#039;&#039; is the relative path to the [[SA Tools/SALVL/Level Definition|Level Definition]] .cs file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectDefinition&#039;&#039; is the relative path to the Object Definition list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Editing the object&#039;s entry in the object definition list&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The objdefs folder can be found in two locations. See the note about &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; in Step 1, it&#039;s the same principle.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The text below describes manual editing of object definition entries in the INI file. If you prefer a GUI editor, you can use the Object Definition Editor in SALVL. Editing object definitions in SALVL will save them to your mod&#039;s project.&#039;&#039;&lt;br /&gt;
[[File:SA Tools SALVL Object Definitions 1773488122468.png|thumb|SALVL Object Editor that includes the Object Definition Editor.]]&lt;br /&gt;
Here is an example of a &#039;&#039;&#039;custom&#039;&#039;&#039; object definition for the jump panel (internal name &amp;lt;code&amp;gt;O JPanel&amp;lt;/code&amp;gt;). Assuming we&#039;re still working with Emerald Coast, its entry will be in &amp;lt;code&amp;gt;objdefs/stg01.ini&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Each entry should begin with the object&#039;s internal name in square brackets, which represents the INI section for the entry. All internal names are already filled in at the moment, so you only need to edit the parameters.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O JPanel]&lt;br /&gt;
codefile=objdefs/Common/JumpPanel.cs&lt;br /&gt;
codetype=SADXObjectDefinitions.Common.JumpPanel&lt;br /&gt;
Name=Jump Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codefile&#039;&#039; is the relative path to the .cs file containing the code of the custom definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codetype&#039;&#039; is the name of the class used by the definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: codefile and codetype are spelled in all lowercase.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For a tutorial on creating code for a custom object definition, see [[SA Tools/SALVL/Object Definitions/Creating a Custom Object Definition|Creating a Custom Object Definition]].&lt;br /&gt;
&lt;br /&gt;
However, many objects don&#039;t need a custom definition. For example, if the object only displays one model (as in, loaded from a single model file) and doesn&#039;t exhibit any complex behavior that needs to be accounted for in the editor, you can use the default object definition. In many cases, all you have to do is fill in a few parameters in the its entry to get the object to show up in the editor.&lt;br /&gt;
&lt;br /&gt;
For an example of a codeless object definition, let&#039;s examine the entry for the Master Emerald shard (internal name &amp;lt;code&amp;gt;O EME P&amp;lt;/code&amp;gt;):&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O EME P]&lt;br /&gt;
Name=Emerald Shard&lt;br /&gt;
Model=object/obj_emekakera.nja.sa1mdl&lt;br /&gt;
Texture=OBJ_REGULAR&lt;br /&gt;
RotType=None&lt;br /&gt;
SclType=None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Model&#039;&#039; is the relative path to the object&#039;s model file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texture&#039;&#039; is the filename (without extension) of the texture archive used for loading the object&#039;s textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;RotType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;rotated&#039;&#039;&#039; when the editor renders it. It can be &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; if the object is only rotated on the Y axis (which is the most common), or &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; if all axes are used for rendering. Any other combination of &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; can also be used. If the object model doesn&#039;t need to be rotated at all, use &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SclType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;scaled&#039;&#039;&#039; when the editor renders it. Most objects do not scale, so &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; is often used. The following values are possible:&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;None, // Default scale (X=1.0, Y=1.0, Z=1.0)&lt;br /&gt;
XYZ, // Scale X, Y and Z&lt;br /&gt;
X, // Scale only by the X axis using the X Scale value&lt;br /&gt;
Y, // Scale only by the Y axis using the Y Scale value&lt;br /&gt;
Z, // Scale only by the Z axis using the Z Scale value&lt;br /&gt;
XY, // Scale the X axis using the X Scale value and then by the Y axis using the Y Scale value&lt;br /&gt;
XZ, // Scale the X axis using the X Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
YZ, // Scale the Y axis using the Y Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
AllX, // All axes are scaled by the X Scale value&lt;br /&gt;
AllY, // All axes are scaled by the Y Scale value&lt;br /&gt;
AllZ // All axes are scaled by the Z Scale value&amp;lt;/syntaxhighlight&amp;gt;For the most part, filling in the above parameters (particularly &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039;) is enough for the object to appear in SALVL. For slightly more complex objects the following additional parameters are available:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TexturePacks&#039;&#039; is a comma-separated list of texture files without extension for objects in SA2 that use multiple [[Texture List|texture lists]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texlist&#039;&#039; is the name of the texture list file (&amp;lt;code&amp;gt;.tls&amp;lt;/code&amp;gt;) loaded by the object. This is required for objects that use multiple or partial texture lists.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; are floating point values that offset the model&#039;s initial transformation for rendering. For example, if your object sinks into the ground, it might need a positive &#039;&#039;AddYPos&#039;&#039;, and if it appears higher than it should be it might need a negative &#039;&#039;AddYPos&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXRot&#039;&#039;, &#039;&#039;DefYRot&#039;&#039; and &#039;&#039;DefZRot&#039;&#039; are initial rotations for objects that have a fixed rotation different from the one specified in the SET file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; and &#039;&#039;AddZRot&#039;&#039; are rotation offsets that work just like &#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; but for rotations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: Rotation values are hexadecimal.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039;, &#039;&#039;DefZScl&#039;&#039; are initial scale values, and &#039;&#039;AddXScl&#039;&#039;, &#039;&#039;AddYScl&#039;&#039; and &#039;&#039;AddZScl&#039;&#039; are offset scale values that work under the same principle as the other offsets mentioned above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;GndDst&#039;&#039; is &amp;quot;distance from the ground&amp;quot;, a vertical offset used for placing objects on the ground in SALVL.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IgnorePos&#039;&#039; is a boolean value (&amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;) that tells the renderer and collision checks to ignore the object&#039;s model (&amp;lt;code&amp;gt;NJS_OBJECT&amp;lt;/code&amp;gt;)&#039;s position.&lt;br /&gt;
&lt;br /&gt;
=== Testing Object Definitions ===&lt;br /&gt;
To test an update to object definitions, copy the modified files in the &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder to your mod project&#039;s &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder, (re)start SALVL, open your mod project and load the stage. The following is a list of common errors with object definitions and potential solutions.&lt;br /&gt;
&lt;br /&gt;
==== Object displays as a box with a question mark ====&lt;br /&gt;
In most cases this means that the object definition is missing or incomplete. If you are using the default definition, make sure at least the &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039; fields are specified in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== SALVL Error: &amp;quot;SET objects failed to load their model(s). Please check SET object load errors in the log for details.&amp;quot; ====&lt;br /&gt;
The most likely cause of the error is the model or texture file missing. In SALVL, select &#039;&#039;Help&amp;gt;View Log&#039;&#039; in the top menu and scroll to the bottom of the log to find the error. If you see &amp;quot;Exists: False&amp;quot;, it means the model or texture file was not found. Make sure the path to the model or texture file is correct. Use &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths. If the model does not use textures, do not specify the texture file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears misrotated ====&lt;br /&gt;
Rotate the object using the editor&#039;s rotation gizmo to find the rotation values that make it look correct. Add the difference between these values as &#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; or &#039;&#039;AddZRot&#039;&#039; values in the object definition list INI file. Some objects are rotated on the Y axis by &amp;lt;code&amp;gt;4000&amp;lt;/code&amp;gt; (16384 in decimal), see &amp;lt;code&amp;gt;O STATION BACK&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;adv00.ini&amp;lt;/code&amp;gt; for an example. Alternatively, experiment with default rotations.&lt;br /&gt;
&lt;br /&gt;
==== Object appears too small or too large ====&lt;br /&gt;
Set &#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039; and/or &#039;&#039;DefZScl&#039;&#039;, or add scale offsets in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears in the wrong place ====&lt;br /&gt;
If there is a fixed difference (always 10 units above or below etc.), add a position offset. Alternatively, add &#039;&#039;IgnorePos=True&#039;&#039; in the object definition list INI file. If that doesn&#039;t help, try a different rotation order or experiment with a combination of all of the above.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=724</id>
		<title>SA Tools/SALVL/Object Definitions</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=724"/>
		<updated>2026-03-14T12:04:36Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction to Object Definitions ==&lt;br /&gt;
An object definition is a part of a [[SA Tools/Project template|project template]] that enables [[SA Tools/SALVL|SALVL]] to display [[SET Object|SET objects]] in the editor. The object definition sets up the object&#039;s model and textures, provides the position, rotation and scale routines to make the object look like it does ingame, and optionally converts SET data into customizable variables used to pick variations of the object or alter its behavior ingame.&lt;br /&gt;
&lt;br /&gt;
=== Types of Object Definitions ===&lt;br /&gt;
Depending on the complexity of the object&#039;s rendering, object definitions can be one of the following two types:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;The default definition&#039;&#039;&#039; (also known as &amp;quot;script&amp;quot;, &amp;quot;codeless&amp;quot; or &amp;quot;simple&amp;quot; definition) provides basic functionality to load and render a model. Many objects in the game will display in the editor with a properly configured default definition. For example, a ring or a stage decoration can work with the default definition.&lt;br /&gt;
# &#039;&#039;&#039;Custom definitions&#039;&#039;&#039; (also known as &amp;quot;code&amp;quot; definitions) that provide their own code for loading the object, rendering its model(s) in the editor and collision checks. These definitions supply their own code in separate .cs files which are compiled by SALVL when it loads a stage.&lt;br /&gt;
&lt;br /&gt;
=== Creating Object Definitions ===&lt;br /&gt;
To display a SET object in SALVL, several things are required. The following is a list of steps to go through to get an object working in the editor.&lt;br /&gt;
&lt;br /&gt;
==== Setting up stage properties ====&lt;br /&gt;
&#039;&#039;Note: For PC versions of SADX and SA2 the work on this step has already been done for all stages. The information below is provided for reference.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note 2: The file &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; is found in two locations. The file in &amp;lt;code&amp;gt;SA Tools\GameConfig\PC_SADX&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;PC_SA2&amp;lt;/code&amp;gt;) is copied to the project folder when you make a new mod project. If you are adding custom objects in your mod, edit the file in your mod project folder. If you are making object definitions for vanilla game objects, edit the main file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; file should have an entry for the stage you need that defines level textures, object textures, the location of the object list INI file and the object definition list INI file. Here is an example for Emerald Coast Act 3.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;[Action Stages\\Emerald Coast 3]&lt;br /&gt;
LevelGeometry=stg01_beach/landtable0102.c.sa1lvl&lt;br /&gt;
LevelID=0102&lt;br /&gt;
Textures=BEACH03&lt;br /&gt;
ObjectList=stg01_beach/objList.ini&lt;br /&gt;
ObjectTextureList=stg01_beach/objTextures.ini&lt;br /&gt;
DeathZones=stg01_beach/killcolli/act3/killZones.ini&lt;br /&gt;
Effects=objdefs/Level Effects/EmeraldCoast.cs&lt;br /&gt;
ObjectDefinition=objdefs/stg01.ini&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;LevelGeometry&#039;&#039; is the relative path to the [[LandTable]] file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LevelID&#039;&#039; is the internal ID used by the stage. The first two digits are level ID and the second two digits are act ID. For SA1, see [[Sonic Adventure/Level List]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Textures&#039;&#039; is the name of the texture file (usually PVM, GVM, PRS or PAK) &#039;&#039;&#039;without extension&#039;&#039;&#039; used for level textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectList&#039;&#039; is the relative path to the [[Object List]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DeathZones&#039;&#039; is the relative path to the [[Death Zones]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Effects&#039;&#039; is the relative path to the [[SA Tools/SALVL/Level Definition|Level Definition]] .cs file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectDefinition&#039;&#039; is the relative path to the Object Definition list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Editing the object&#039;s entry in the object definition list&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The objdefs folder can be found in two locations. See the note about &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; in Step 1, it&#039;s the same principle.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The text below describes manual editing of object definition entries in the INI file. If you prefer a GUI editor, you can use the Object Definition Editor in SALVL. Editing object definitions in SALVL will save them to your mod&#039;s project.&#039;&#039;&lt;br /&gt;
[[File:SA Tools SALVL Object Definitions 1773488122468.png|thumb|SALVL Object Editor that includes the Object Definition Editor.]]&lt;br /&gt;
Here is an example of a &#039;&#039;&#039;custom&#039;&#039;&#039; object definition for the jump panel (internal name &amp;lt;code&amp;gt;O JPanel&amp;lt;/code&amp;gt;). Assuming we&#039;re still working with Emerald Coast, its entry will be in &amp;lt;code&amp;gt;objdefs/stg01.ini&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Each entry should begin with the object&#039;s internal name in square brackets, which represents the INI section for the entry. All internal names are already filled in at the moment, so you only need to edit the parameters.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O JPanel]&lt;br /&gt;
codefile=objdefs/Common/JumpPanel.cs&lt;br /&gt;
codetype=SADXObjectDefinitions.Common.JumpPanel&lt;br /&gt;
Name=Jump Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codefile&#039;&#039; is the relative path to the .cs file containing the code of the custom definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codetype&#039;&#039; is the name of the class used by the definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: codefile and codetype are spelled in all lowercase.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For a tutorial on creating code for a custom object definition, see [[SA Tools/SALVL/Object Definitions/Creating a Custom Object Definition|Creating a Custom Object Definition]].&lt;br /&gt;
&lt;br /&gt;
However, many objects don&#039;t need a custom definition. For example, if the object only displays one model (as in, loaded from a single model file) and doesn&#039;t exhibit any complex behavior that needs to be accounted for in the editor, you can use the default object definition. In many cases, all you have to do is fill in a few parameters in the its entry to get the object to show up in the editor.&lt;br /&gt;
&lt;br /&gt;
For an example of a codeless object definition, let&#039;s examine the entry for the Master Emerald shard (internal name &amp;lt;code&amp;gt;O EME P&amp;lt;/code&amp;gt;):&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O EME P]&lt;br /&gt;
Name=Emerald Shard&lt;br /&gt;
Model=object/obj_emekakera.nja.sa1mdl&lt;br /&gt;
Texture=OBJ_REGULAR&lt;br /&gt;
RotType=None&lt;br /&gt;
SclType=None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Model&#039;&#039; is the relative path to the object&#039;s model file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texture&#039;&#039; is the filename (without extension) of the texture archive used for loading the object&#039;s textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important! Use forward slash &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of backslash &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;RotType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;rotated&#039;&#039;&#039; when the editor renders it. It can be &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; if the object is only rotated on the Y axis (which is the most common), or &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; if all axes are used for rendering. Any other combination of &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; can also be used. If the object model doesn&#039;t need to be rotated at all, use &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SclType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;scaled&#039;&#039;&#039; when the editor renders it. Most objects do not scale, so &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; is often used. The following values are possible:&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;None, // Default scale (X=1.0, Y=1.0, Z=1.0)&lt;br /&gt;
XYZ, // Scale X, Y and Z&lt;br /&gt;
X, // Scale only by the X axis using the X Scale value&lt;br /&gt;
Y, // Scale only by the Y axis using the Y Scale value&lt;br /&gt;
Z, // Scale only by the Z axis using the Z Scale value&lt;br /&gt;
XY, // Scale the X axis using the X Scale value and then by the Y axis using the Y Scale value&lt;br /&gt;
XZ, // Scale the X axis using the X Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
YZ, // Scale the Y axis using the Y Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
AllX, // All axes are scaled by the X Scale value&lt;br /&gt;
AllY, // All axes are scaled by the Y Scale value&lt;br /&gt;
AllZ // All axes are scaled by the Z Scale value&amp;lt;/syntaxhighlight&amp;gt;For the most part, filling in the above parameters (particularly &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039;) is enough for the object to appear in SALVL. For slightly more complex objects the following additional parameters are available:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TexturePacks&#039;&#039; is a comma-separated list of texture files without extension for objects in SA2 that use multiple [[Texture List|texture lists]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texlist&#039;&#039; is the name of the texture list file (&amp;lt;code&amp;gt;.tls&amp;lt;/code&amp;gt;) loaded by the object. This is required for objects that use multiple or partial texture lists.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; are floating point values that offset the model&#039;s initial transformation for rendering. For example, if your object sinks into the ground, it might need a positive &#039;&#039;AddYPos&#039;&#039;, and if it appears higher than it should be it might need a negative &#039;&#039;AddYPos&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXRot&#039;&#039;, &#039;&#039;DefYRot&#039;&#039; and &#039;&#039;DefZRot&#039;&#039; are initial rotations for objects that have a fixed rotation different from the one specified in the SET file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; and &#039;&#039;AddZRot&#039;&#039; are rotation offsets that work just like &#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; but for rotations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: Rotation values are hexadecimal.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039;, &#039;&#039;DefZScl&#039;&#039; are initial scale values, and &#039;&#039;AddXScl&#039;&#039;, &#039;&#039;AddYScl&#039;&#039; and &#039;&#039;AddZScl&#039;&#039; are offset scale values that work under the same principle as the other offsets mentioned above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;GndDst&#039;&#039; is &amp;quot;distance from the ground&amp;quot;, a vertical offset used for placing objects on the ground in SALVL.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IgnorePos&#039;&#039; is a boolean value (&amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;) that tells the renderer and collision checks to ignore the object&#039;s model (&amp;lt;code&amp;gt;NJS_OBJECT&amp;lt;/code&amp;gt;)&#039;s position.&lt;br /&gt;
&lt;br /&gt;
=== Testing Object Definitions ===&lt;br /&gt;
To test an update to object definitions, copy the modified files in the &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder to your mod project&#039;s &amp;lt;code&amp;gt;objdefs&amp;lt;/code&amp;gt; folder, (re)start SALVL, open your mod project and load the stage. The following is a list of common errors with object definitions and potential solutions.&lt;br /&gt;
&lt;br /&gt;
==== Object displays as a box with a question mark ====&lt;br /&gt;
In most cases this means that the object definition is missing or incomplete. If you are using the default definition, make sure at least the &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039; fields are specified in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== SALVL Error: &amp;quot;SET objects failed to load their model(s). Please check SET object load errors in the log for details.&amp;quot; ====&lt;br /&gt;
The most likely cause of the error is the model or texture file missing. In SALVL, select &#039;&#039;Help&amp;gt;View Log&#039;&#039; in the top menu and scroll to the bottom of the log to find the error. If you see &amp;quot;Exists: False&amp;quot;, it means the model or texture file was not found. Make sure the path to the model or texture file is correct. Use &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for all paths. If the model does not use textures, do not specify the texture file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears misrotated ====&lt;br /&gt;
Rotate the object using the editor&#039;s rotation gizmo to find the rotation values that make it look correct. Add the difference between these values as &#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; or &#039;&#039;AddZRot&#039;&#039; values in the object definition list INI file. Some objects are rotated on the Y axis by &amp;lt;code&amp;gt;4000&amp;lt;/code&amp;gt; (16384 in decimal), see &amp;lt;code&amp;gt;O STATION BACK&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;adv00.ini&amp;lt;/code&amp;gt; for an example. Alternatively, experiment with default rotations.&lt;br /&gt;
&lt;br /&gt;
==== Object appears too small or too large ====&lt;br /&gt;
Set &#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039; and/or &#039;&#039;DefZScl&#039;&#039;, or add scale offsets in the object definition list INI file.&lt;br /&gt;
&lt;br /&gt;
==== Object appears in the wrong place ====&lt;br /&gt;
If there is a fixed difference (always 10 units above or below etc.), add a position offset. Alternatively, add &#039;&#039;IgnorePos=True&#039;&#039; in the object definition list INI file. If that doesn&#039;t help, try a different rotation order or experiment with a combination of all of the above.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=723</id>
		<title>SA Tools/SALVL/Object Definitions</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=723"/>
		<updated>2026-03-14T11:42:18Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction to Object Definitions ==&lt;br /&gt;
An object definition is a part of a [[SA Tools/Project template|project template]] that enables [[SA Tools/SALVL|SALVL]] to display [[SET Object|SET objects]] in the editor. The object definition sets up the object&#039;s model and textures, provides the position, rotation and scale routines to make the object look like it does ingame, and optionally converts SET data into customizable variables used to pick variations of the object or alter its behavior ingame.&lt;br /&gt;
&lt;br /&gt;
=== Types of Object Definitions ===&lt;br /&gt;
Depending on the complexity of the object&#039;s rendering, object definitions can be one of the following two types:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;The default definition&#039;&#039;&#039; (also known as &amp;quot;script&amp;quot;, &amp;quot;codeless&amp;quot; or &amp;quot;simple&amp;quot; definition) provides basic functionality to load and render a model. Many objects in the game will display in the editor with a properly configured default definition. For example, a ring or a stage decoration can work with the default definition.&lt;br /&gt;
# &#039;&#039;&#039;Custom definitions&#039;&#039;&#039; (also known as &amp;quot;code&amp;quot; definitions) that provide their own code for loading the object, rendering its model(s) in the editor and collision checks. These definitions supply their own code in separate .cs files which are compiled by SALVL when it loads a stage.&lt;br /&gt;
&lt;br /&gt;
=== Creating Object Definitions ===&lt;br /&gt;
To display a SET object in SALVL, several things are required. The following is a list of steps to go through to get an object working in the editor.&lt;br /&gt;
&lt;br /&gt;
==== Setting up stage properties ====&lt;br /&gt;
&#039;&#039;Note: For PC versions of SADX and SA2 the work on this step has already been done for all stages. The information below is provided for reference.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note 2: The file &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; is found in two locations. The file in &amp;lt;code&amp;gt;SA Tools\GameConfig\PC_SADX&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;PC_SA2&amp;lt;/code&amp;gt;) is copied to the project folder when you make a new mod project. If you are adding custom objects in your mod, edit the file in your mod project folder. If you are making object definitions for vanilla game objects, edit the main file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; file should have an entry for the stage you need that defines level textures, object textures, the location of the object list INI file and the object definition list INI file. Here is an example for Emerald Coast Act 3.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;[Action Stages\\Emerald Coast 3]&lt;br /&gt;
LevelGeometry=stg01_beach/landtable0102.c.sa1lvl&lt;br /&gt;
LevelID=0102&lt;br /&gt;
Textures=BEACH03&lt;br /&gt;
ObjectList=stg01_beach/objList.ini&lt;br /&gt;
ObjectTextureList=stg01_beach/objTextures.ini&lt;br /&gt;
DeathZones=stg01_beach/killcolli/act3/killZones.ini&lt;br /&gt;
Effects=objdefs/Level Effects/EmeraldCoast.cs&lt;br /&gt;
ObjectDefinition=objdefs/stg01.ini&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;LevelGeometry&#039;&#039; is the relative path to the [[LandTable]] file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LevelID&#039;&#039; is the internal ID used by the stage. The first two digits are level ID and the second two digits are act ID. For SA1, see [[Sonic Adventure/Level List]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Textures&#039;&#039; is the name of the texture file (usually PVM, GVM, PRS or PAK) &#039;&#039;&#039;without extension&#039;&#039;&#039; used for level textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectList&#039;&#039; is the relative path to the [[Object List]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DeathZones&#039;&#039; is the relative path to the [[Death Zones]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Effects&#039;&#039; is the relative path to the [[SA Tools/SALVL/Level Definition|Level Definition]] .cs file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectDefinition&#039;&#039; is the relative path to the Object Definition split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Editing the object&#039;s entry in the object definition list&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The objdefs folder can be found in two locations. See the note about &amp;lt;code&amp;gt;sadxlvl.ini&amp;lt;/code&amp;gt; in Step 1, it&#039;s the same principle.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The text below describes manual editing of object definition entries in the INI file. If you prefer a GUI editor, you can use the Object Definition Editor in SALVL. Editing object definitions in SALVL will save them to your mod&#039;s project.&#039;&#039;&lt;br /&gt;
[[File:SA Tools SALVL Object Definitions 1773488122468.png|thumb|SALVL Object Editor that includes the Object Definition Editor.]]&lt;br /&gt;
Here is an example of a &#039;&#039;&#039;custom&#039;&#039;&#039; object definition for the jump panel (internal name &amp;lt;code&amp;gt;O JPanel&amp;lt;/code&amp;gt;). Assuming we&#039;re still working with Emerald Coast, its entry will be in &amp;lt;code&amp;gt;objdefs/stg01.ini&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Each entry should begin with the object&#039;s internal name in square brackets, which represents the INI section for the entry. All internal names are already filled in at the moment, so you only need to edit the parameters.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O JPanel]&lt;br /&gt;
codefile=objdefs/Common/JumpPanel.cs&lt;br /&gt;
codetype=SADXObjectDefinitions.Common.JumpPanel&lt;br /&gt;
Name=Jump Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codefile&#039;&#039; is the relative path to the .cs file containing the code of the custom definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codetype&#039;&#039; is the name of the class used by the definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: codefile and codetype are spelled in all lowercase.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For a tutorial on creating code for a custom object definition, see [[SA Tools/SALVL/Object Definitions/Creating a Custom Object Definition|Creating a Custom Object Definition]].&lt;br /&gt;
&lt;br /&gt;
However, many objects don&#039;t need a custom definition. For example, if the object only displays one model (as in, loaded from a single model file) and doesn&#039;t exhibit any complex behavior that needs to be accounted for in the editor, you can use the default object definition. In many cases, all you have to do is fill in a few parameters in the its entry to get the object to show up in the editor.&lt;br /&gt;
&lt;br /&gt;
For an example of a codeless object definition, let&#039;s examine the entry for the Master Emerald shard (internal name &amp;lt;code&amp;gt;O EME P&amp;lt;/code&amp;gt;):&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O EME P]&lt;br /&gt;
Name=Emerald Shard&lt;br /&gt;
Model=object/obj_emekakera.nja.sa1mdl&lt;br /&gt;
Texture=OBJ_REGULAR&lt;br /&gt;
RotType=None&lt;br /&gt;
SclType=None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Model&#039;&#039; is the relative path to the object&#039;s model file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texture&#039;&#039; is the filename (without extension) of the texture archive used for loading the object&#039;s textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;RotType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;rotated&#039;&#039;&#039; when the editor renders it. It can be &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; if the object is only rotated on the Y axis (which is the most common), or &amp;lt;code&amp;gt;XYZ&amp;lt;/code&amp;gt; if all axes are used for rendering. Any other combination of &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;Z&amp;lt;/code&amp;gt; can also be used. If the object model doesn&#039;t need to be rotated at all, use &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SclType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;scaled&#039;&#039;&#039; when the editor renders it. Most objects do not scale, so &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; is often used. The following values are possible:&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;None, // Default scale (X=1.0, Y=1.0, Z=1.0)&lt;br /&gt;
XYZ, // Scale X, Y and Z&lt;br /&gt;
X, // Scale only by the X axis using the X Scale value&lt;br /&gt;
Y, // Scale only by the Y axis using the Y Scale value&lt;br /&gt;
Z, // Scale only by the Z axis using the Z Scale value&lt;br /&gt;
XY, // Scale the X axis using the X Scale value and then by the Y axis using the Y Scale value&lt;br /&gt;
XZ, // Scale the X axis using the X Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
YZ, // Scale the Y axis using the Y Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
AllX, // All axes are scaled by the X Scale value&lt;br /&gt;
AllY, // All axes are scaled by the Y Scale value&lt;br /&gt;
AllZ // All axes are scaled by the Z Scale value&amp;lt;/syntaxhighlight&amp;gt;For the most part, filling in the above parameters (particularly &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039;) is enough for the object to appear in SALVL. For slightly more complex objects the following additional parameters are available:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TexturePacks&#039;&#039; is a comma-separated list of texture files without extension for objects in SA2 that use multiple [[Texture List|texture lists]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texlist&#039;&#039; is the name of the texture list file (&amp;lt;code&amp;gt;.tls&amp;lt;/code&amp;gt;) loaded by the object. This is required for objects that use multiple or partial texture lists.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; are floating point values that offset the model&#039;s initial transformation for rendering. For example, if your object sinks into the ground, it might need a positive &#039;&#039;AddYPos&#039;&#039;, and if it appears higher than it should be it might need a negative &#039;&#039;AddYPos&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXRot&#039;&#039;, &#039;&#039;DefYRot&#039;&#039; and &#039;&#039;DefZRot&#039;&#039; are initial rotations for objects that have a fixed rotation different from the one specified in the SET file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; and &#039;&#039;AddZRot&#039;&#039; are rotation offsets that work just like &#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; but for rotations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039;, &#039;&#039;DefZScl&#039;&#039; are initial scale values, and &#039;&#039;AddXScl&#039;&#039;, &#039;&#039;AddYScl&#039;&#039; and &#039;&#039;AddZScl&#039;&#039; are offset scale values that work under the same principle as the other offsets mentioned above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;GndDst&#039;&#039; is &amp;quot;distance from the ground&amp;quot;, a vertical offset used for placing objects on the ground in SALVL.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IgnorePos&#039;&#039; is a boolean value (&amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;) that tells the renderer and collision checks to ignore the object&#039;s model (&amp;lt;code&amp;gt;NJS_OBJECT&amp;lt;/code&amp;gt;)&#039;s position.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=722</id>
		<title>SA Tools/SALVL/Object Definitions</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL/Object_Definitions&amp;diff=722"/>
		<updated>2026-03-14T11:38:52Z</updated>

		<summary type="html">&lt;p&gt;PkR: Created page with &amp;quot;== Introduction to Object Definitions == An object definition is a part of a project template that enables SALVL to display SET objects in the editor. The object definition sets up the object&amp;#039;s model and textures, provides the position, rotation and scale routines to make the object look like it does ingame, and optionally converts SET data into customizable variables used to pick variations of the object or...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction to Object Definitions ==&lt;br /&gt;
An object definition is a part of a [[SA Tools/Project template|project template]] that enables [[SA Tools/SALVL|SALVL]] to display [[SET Object|SET objects]] in the editor. The object definition sets up the object&#039;s model and textures, provides the position, rotation and scale routines to make the object look like it does ingame, and optionally converts SET data into customizable variables used to pick variations of the object or alter its behavior ingame.&lt;br /&gt;
&lt;br /&gt;
=== Types of Object Definitions ===&lt;br /&gt;
Depending on the complexity of the object&#039;s rendering, object definitions can be one of the following two types:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;The default definition&#039;&#039;&#039; (also known as &amp;quot;script&amp;quot;, &amp;quot;codeless&amp;quot; or &amp;quot;simple&amp;quot; definition) provides basic functionality to load and render a model. Many objects in the game will display in the editor with a properly configured default definition. For example, a ring or a stage decoration can work with the default definition.&lt;br /&gt;
# &#039;&#039;&#039;Custom definitions&#039;&#039;&#039; (also known as &amp;quot;code&amp;quot; definitions) that provide their own code for loading the object, rendering its model(s) in the editor and collision checks. These definitions supply their own code in separate .cs files which are compiled by SALVL when it loads a stage.&lt;br /&gt;
&lt;br /&gt;
=== Creating Object Definitions ===&lt;br /&gt;
To display a SET object in SALVL, several things are required. The following is a list of steps to go through to get an object working in the editor.&lt;br /&gt;
&lt;br /&gt;
==== Setting up stage properties ====&lt;br /&gt;
&#039;&#039;Note: For PC versions of SADX and SA2 the work on this step has already been done for all stages. The information below is provided for reference.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note 2: The file `sadxlvl.ini` is found in two locations. The file in `SA Tools\GameConfig\PC_SADX` (or `PC_SA2`) is copied to the project folder when you make a new mod project. If you are adding custom objects in your mod, edit the file in your mod project folder. If you are making object definitions for vanilla game objects, edit the main file.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The file `sadxlvl.ini` should have an entry for the stage you need that defines level textures, object textures, the location of the object list INI file and the object definition list INI file. Here is an example for Emerald Coast Act 3.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;[Action Stages\\Emerald Coast 3]&lt;br /&gt;
LevelGeometry=stg01_beach/landtable0102.c.sa1lvl&lt;br /&gt;
LevelID=0102&lt;br /&gt;
Textures=BEACH03&lt;br /&gt;
ObjectList=stg01_beach/objList.ini&lt;br /&gt;
ObjectTextureList=stg01_beach/objTextures.ini&lt;br /&gt;
DeathZones=stg01_beach/killcolli/act3/killZones.ini&lt;br /&gt;
Effects=objdefs/Level Effects/EmeraldCoast.cs&lt;br /&gt;
ObjectDefinition=objdefs/stg01.ini&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;LevelGeometry&#039;&#039; is the relative path to the [[LandTable]] file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LevelID&#039;&#039; is the internal ID used by the stage. The first two digits are level ID and the second two digits are act ID. For SA1, see [[Sonic Adventure/Level List]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Textures&#039;&#039; is the name of the texture file (usually PVM, GVM, PRS or PAK) &#039;&#039;&#039;without extension&#039;&#039;&#039; used for level textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectList&#039;&#039; is the relative path to the [[Object List]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DeathZones&#039;&#039; is the relative path to the [[Death Zones]] split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Effects&#039;&#039; is the relative path to the [[SA Tools/SALVL/Level Definition|Level Definition]] .cs file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;ObjectDefinition&#039;&#039; is the relative path to the Object Definition split file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Editing the object&#039;s entry in the object definition list&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The objdefs folder can be found in two locations. See the note about `sadxlvl.ini` in Step 1, it&#039;s the same principle.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The text below describes manual editing of object definition entries in the INI file. If you prefer a GUI editor, you can use the Object Definition Editor in SALVL. Editing object definitions in SALVL will save them to your mod&#039;s project.&#039;&#039;&lt;br /&gt;
[[File:SA Tools SALVL Object Definitions 1773488122468.png|thumb|SALVL Object Editor that includes the Object Definition Editor.]]&lt;br /&gt;
Here is an example of a &#039;&#039;&#039;custom&#039;&#039;&#039; object definition for the jump panel (internal name `O JPanel`). Assuming we&#039;re still working with Emerald Coast, its entry will be in `objdefs/stg01.ini`.&lt;br /&gt;
&lt;br /&gt;
Each entry should begin with the object&#039;s internal name in square brackets, which represents the INI section for the entry. All internal names are already filled in at the moment, so you only need to edit the parameters.&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O JPanel]&lt;br /&gt;
codefile=objdefs/Common/JumpPanel.cs&lt;br /&gt;
codetype=SADXObjectDefinitions.Common.JumpPanel&lt;br /&gt;
Name=Jump Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codefile&#039;&#039; is the relative path to the .cs file containing the code of the custom definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;codetype&#039;&#039; is the name of the class used by the definition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: codefile and codetype are spelled in all lowercase.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For a tutorial on creating code for a custom object definition, see [[SA Tools/SALVL/Object Definitions/Creating a Custom Object Definition|Creating a Custom Object Definition]].&lt;br /&gt;
&lt;br /&gt;
However, many objects don&#039;t need a custom definition. For example, if the object only displays one model (as in, loaded from a single model file) and doesn&#039;t exhibit any complex behavior that needs to be accounted for in the editor, you can use the default object definition. In many cases, all you have to do is fill in a few parameters in the its entry to get the object to show up in the editor.&lt;br /&gt;
&lt;br /&gt;
For an example of a codeless object definition, let&#039;s examine the entry for the Master Emerald shard (internal name `O EME P`):&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[O EME P]&lt;br /&gt;
Name=Emerald Shard&lt;br /&gt;
Model=object/obj_emekakera.nja.sa1mdl&lt;br /&gt;
Texture=OBJ_REGULAR&lt;br /&gt;
RotType=None&lt;br /&gt;
SclType=None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;Name&#039;&#039; is the name you would like the object to have when it appears on the SET item list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Model&#039;&#039; is the relative path to the object&#039;s model file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texture&#039;&#039; is the filename (without extension) of the texture archive used for loading the object&#039;s textures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;RotType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;rotated&#039;&#039;&#039; when the editor renders it. It can be `Y` if the object is only rotated on the Y axis (which is the most common), or `XYZ` if all axes are used for rendering. Any other combination of `X`, `Y` and/or `Z` can also be used. If the object model doesn&#039;t need to be rotated at all, use `None`.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SclType&#039;&#039; is the order in which the object&#039;s model should be &#039;&#039;&#039;scaled&#039;&#039;&#039; when the editor renders it. Most objects do not scale, so `None` is often used. The following values are possible:&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;None, // Default scale (X=1.0, Y=1.0, Z=1.0)&lt;br /&gt;
XYZ, // Scale X, Y and Z&lt;br /&gt;
X, // Scale only by the X axis using the X Scale value&lt;br /&gt;
Y, // Scale only by the Y axis using the Y Scale value&lt;br /&gt;
Z, // Scale only by the Z axis using the Z Scale value&lt;br /&gt;
XY, // Scale the X axis using the X Scale value and then by the Y axis using the Y Scale value&lt;br /&gt;
XZ, // Scale the X axis using the X Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
YZ, // Scale the Y axis using the Y Scale value and then by the Z axis using the Z Scale value&lt;br /&gt;
AllX, // All axes are scaled by the X Scale value&lt;br /&gt;
AllY, // All axes are scaled by the Y Scale value&lt;br /&gt;
AllZ // All axes are scaled by the Z Scale value&amp;lt;/syntaxhighlight&amp;gt;For the most part, filling in the above parameters (particularly &#039;&#039;Model&#039;&#039; and &#039;&#039;Texture&#039;&#039;) is enough for the object to appear in SALVL. For slightly more complex objects the following additional parameters are available:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;TexturePacks&#039;&#039; is a comma-separated list of texture files without extension for objects in SA2 that use multiple [[Texture List|texture lists]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Texlist&#039;&#039; is the name of the texture list file (.tls) loaded by the object. This is required for objects that use multiple or partial texture lists.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; are floating point values that offset the model&#039;s initial transformation for rendering. For example, if your object sinks into the ground, it might need a positive &#039;&#039;AddYPos&#039;&#039;, and if it appears higher than it should be it might need a negative &#039;&#039;AddYPos&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXRot&#039;&#039;, &#039;&#039;DefYRot&#039;&#039; and &#039;&#039;DefZRot&#039;&#039; are initial rotations for objects that have a fixed rotation different from the one specified in the SET file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;AddXRot&#039;&#039;, &#039;&#039;AddYRot&#039;&#039; and &#039;&#039;AddZRot&#039;&#039; are rotation offsets that work just like &#039;&#039;AddXPos&#039;&#039;, &#039;&#039;AddYPos&#039;&#039; and &#039;&#039;AddZPos&#039;&#039; but for rotations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;DefXScl&#039;&#039;, &#039;&#039;DefYScl&#039;&#039;, &#039;&#039;DefZScl&#039;&#039; are initial scale values, and &#039;&#039;AddXScl&#039;&#039;, &#039;&#039;AddYScl&#039;&#039; and &#039;&#039;AddZScl&#039;&#039; are offset scale values that work under the same principle as the other offsets mentioned above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;GndDst&#039;&#039; is &amp;quot;distance from the ground&amp;quot;, a vertical offset used for placing objects on the ground in SALVL.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IgnorePos&#039;&#039; is a boolean value (`True` or `False`) that tells the renderer and collision checks to ignore the object&#039;s model (NJS_OBJECT)&#039;s position.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:SA_Tools_SALVL_Object_Definitions_1773488122468.png&amp;diff=721</id>
		<title>File:SA Tools SALVL Object Definitions 1773488122468.png</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:SA_Tools_SALVL_Object_Definitions_1773488122468.png&amp;diff=721"/>
		<updated>2026-03-14T11:35:22Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SALVL&amp;diff=720</id>
		<title>SALVL</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SALVL&amp;diff=720"/>
		<updated>2026-03-14T09:45:50Z</updated>

		<summary type="html">&lt;p&gt;PkR: PkR moved page SALVL to SA Tools/SALVL&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[SA Tools/SALVL]]&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL&amp;diff=719</id>
		<title>SA Tools/SALVL</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=SA_Tools/SALVL&amp;diff=719"/>
		<updated>2026-03-14T09:45:50Z</updated>

		<summary type="html">&lt;p&gt;PkR: PkR moved page SALVL to SA Tools/SALVL&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SALVL is a level editor for the Sonic Adventure games. It is primarily meant for editing SADX PC (2004) layouts, with limited support for other games.&lt;br /&gt;
&lt;br /&gt;
== Navigating the Editor ==&lt;br /&gt;
[[File:Labeled SALVL Interface.png|thumb|443x443px|The interface of SALVL, with the individual windows highlighted.]]&lt;br /&gt;
&lt;br /&gt;
=== 3D Viewport ===&lt;br /&gt;
The &#039;&#039;3D Viewport&#039;&#039; (highlighted in yellow) is the primary window for the interface. You can use it to fly around and view the stage from various angles, select, move, and rotate objects within the scene; and various other tasks.&lt;br /&gt;
&lt;br /&gt;
See [[3D Editor Controls]] for default camera controls.&lt;br /&gt;
&lt;br /&gt;
=== Scene Graph ===&lt;br /&gt;
The Scene graph (highlighted in blue) shows a list of everything inside of the level that can be edited, sorted by type. You can select items here and it will function in exactly the same way as if you had clicked the item inside of the viewport. The Scene graph supports multi-select by holding the SHIFT key.&lt;br /&gt;
&lt;br /&gt;
=== Inspector ===&lt;br /&gt;
Every object in the game world has many properties associated with it, and many times the game have properties that cannot be manipulated directly in 3D space via the viewport. For this reason, the Inspector (highlighted in green) will display as much information as possible about the currently selected object (&#039;&#039;In the case of multiple selected objects at once, it will display information that is common across the entire selection&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Character Select ===&lt;br /&gt;
The character select (highlighted in purple) behaves exactly like you expect it would. Click on a character&#039;s icon to switch their version of the stage. Note that this only changes the currently loaded SET and CAM layouts, as all characters share stage geometry.&lt;br /&gt;
&lt;br /&gt;
=== Model/SET Library (Unfinished) ===&lt;br /&gt;
The model library (highlighted in red) is a palette that contains a series of 3d models, stored in memory until you decide to add them to the stage. You can add a model from the model library to the stage by clicking on it and dragging the icon into the 3d viewport. You can import external 3d model files (obj and sa1mdl formats supported) into the Model Library by using the File-&amp;gt;Import-&amp;gt;To Model Library menu option. It is currently unfinished and is disabled by default. You can enable it by unchecking View-&amp;gt;Disable Model Library.&lt;br /&gt;
&lt;br /&gt;
=== Transform Handle Tools ===&lt;br /&gt;
[[File:SALVL_Transform_Handles.png|thumb|The following menu buttons alter the behavior of the transform handle.]]&lt;br /&gt;
SALVL uses a feature called a Transform Handle for manipulating the selected stage objects. The transform handle resides in the 3D viewport and is directly manipulated by the mouse, using a click and drag action.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Lights Editor ===&lt;br /&gt;
SADX has two types of light data: Stage Lights (&amp;lt;code&amp;gt;LE_LIGHT_ENV&amp;lt;/code&amp;gt;) and Character Lights (&amp;lt;code&amp;gt;LE_PALIGHT_ENV&amp;lt;/code&amp;gt;). Stage Lights are used for level and object models, while Character Lights are used for characters, some specific enemies and bosses. You can edit both types of lights and preview changes in the editor. If a light of a selected type is not present in the selected level, click the &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; button to create it (if a light already exists, it will be overwritten with default data). To clear the current light, click the &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt; button. Click &amp;lt;code&amp;gt;Apply&amp;lt;/code&amp;gt; to update the lights in the main editor.&lt;br /&gt;
&lt;br /&gt;
==== Stage Lights ====&lt;br /&gt;
[[File:SALVL_Stage_Lights_Editor.png|thumb|313x313px]]&lt;br /&gt;
Each act in a level can have up to four Stage Lights. You can switch between the four lights using the Light Index control. Each light has the following parameters:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Diffuse Color&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Ambient Color&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Diffuse&#039;&#039;&#039;: Directional light intensity&lt;br /&gt;
* &#039;&#039;&#039;Specular&#039;&#039;&#039;: Unused&lt;br /&gt;
* &#039;&#039;&#039;Use Direction&#039;&#039;&#039;: Indicates a directional light; if this flag is disabled, only ambient lighting will be used&lt;br /&gt;
* &#039;&#039;&#039;Light Direction&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Character Lights ====&lt;br /&gt;
[[File:SALVL_Character_Lights_Editor.png|thumb]]&lt;br /&gt;
Each act in a level has three types of Character Lights:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Character&#039;&#039;&#039;: Used for most playable characters and NPCs, as well as some enemies such as the Spinners&lt;br /&gt;
* &#039;&#039;&#039;Character Alt.&#039;&#039;&#039;: Additional light type used for Super Sonic, E-102 Gamma and some Egg Carrier NPCs&lt;br /&gt;
* &#039;&#039;&#039;Boss&#039;&#039;&#039;: Used for boss models&lt;br /&gt;
&lt;br /&gt;
Each Character Light can be configured with the following parameters:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Enabled&#039;&#039;&#039;: If this flag is off, the game will use the light from the previous act, or a default one if it doesn&#039;t exist or is disabled&lt;br /&gt;
* &#039;&#039;&#039;Use Direction&#039;&#039;&#039;: If this flag is enabled, the game will use this light&#039;s direction; if this flag is disabled, the game will use the Stage Light&#039;s direction&lt;br /&gt;
* &#039;&#039;&#039;Ignore Direction&#039;&#039;&#039;: If this flag is enabled, light direction will not be set&lt;br /&gt;
* &#039;&#039;&#039;Double&#039;&#039;&#039;: If this flag is enabled, an additional light will be created with an inverted direction&lt;br /&gt;
* &#039;&#039;&#039;Diffuse&#039;&#039;&#039;: Unused&lt;br /&gt;
* &#039;&#039;&#039;Light Direction&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Ambient Color&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Color 1 RGB and Power&#039;&#039;&#039;: First component used for diffuse palette generation (see notes)&lt;br /&gt;
* &#039;&#039;&#039;Color 2 RGB and Power&#039;&#039;&#039;: Second component used for diffuse palette generation (see notes)&lt;br /&gt;
* &#039;&#039;&#039;Specular 1 RGB and Power&#039;&#039;&#039;: First component used for specular palette generation (see notes)&lt;br /&gt;
* &#039;&#039;&#039;Specular 2 RGB and Power&#039;&#039;&#039;: Second component used for specular palette generation (see notes)&lt;br /&gt;
&lt;br /&gt;
==== Notes on Lights ====&lt;br /&gt;
&lt;br /&gt;
* The lighting system described above is used in SADX Gamecube and later ports. The original Dreamcast version uses a different system that loads lighting data from PL and SL files. Use PLTool to edit those.&lt;br /&gt;
* The lights are applied differently in the Gamecube version, so the same values will produce different results in the PC version.&lt;br /&gt;
* The Gamecube version generates 256-color palettes for diffuse (Color 1 and Color 2) and specular (Specular 1 and Specular 2) character lighting, which are used as a lookup texture in a way similar to the palettes in the original Dreamcast game&#039;s lighting system. However, in all later ports (including the PC version) there is no palette generation, and only Ambient Color and Specular 1 RGB have any meaningful effect.&lt;br /&gt;
* Specular lighting is disabled for Stage Lights, and the &amp;lt;code&amp;gt;Specular&amp;lt;/code&amp;gt; value has no effect.&lt;br /&gt;
* The &amp;lt;code&amp;gt;Diffuse&amp;lt;/code&amp;gt; value has no effect on Character Lights.&lt;br /&gt;
* For Station Square and the Mystic Ruins, Act 0 is Day, Act 1 is Evening and Act 2 is Night. Sky Deck Act 3 and Twinkle Park entrance area in Station Square use hardcoded lighting that cannot be edited in SALVL. Casinopolis has hardcoded light rotation. Some other levels have hardcoded ambient color or light direction overrides.&lt;br /&gt;
&lt;br /&gt;
=== Fog Editor ===&lt;br /&gt;
[[File:SALVL_Fog_Editor.png|thumb|454x454px]]&lt;br /&gt;
SADX PC has fog settings for each detail (clip) level. Since lower clip settings were meant for underpowered machines by 2004 standards, in the majority of cases there is no point in using anything other than High (Far). If a selected act in a stage does not have fog data, click the &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; button to create it (if fog data already exists, it will be overwritten with default data). To remove current fog data, click the &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt; button. Click &amp;lt;code&amp;gt;Apply&amp;lt;/code&amp;gt; to update fog in the main editor.&lt;br /&gt;
&lt;br /&gt;
The following fog parameters can be adjusted:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Fog Toggle&#039;&#039;&#039;: Enables or disables fog for this act and detail setting.&lt;br /&gt;
* &#039;&#039;&#039;Fog Start&#039;&#039;&#039;: Distance from camera where fog starts.&lt;br /&gt;
* &#039;&#039;&#039;Fog End&#039;&#039;&#039;: Distance from camera where fog ends.&lt;br /&gt;
* &#039;&#039;&#039;Fog Color&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Notes on Fog ====&lt;br /&gt;
&lt;br /&gt;
* Positive and negative values for Fog Start and Fog End produce the same results.&lt;br /&gt;
* The game uses default fog settings if the difference between Fog Start and Fog End is too small. This behavior is replicated in the editor.&lt;br /&gt;
* The A value in Fog Color is ignored.&lt;br /&gt;
* In some areas, such as Lost World Act 2, there are hardcoded fog overrides that cannot be edited in SALVL.&lt;br /&gt;
* In the Mystic Ruins, the following Acts are used for different times of day:&lt;br /&gt;
** Day: Level act number matches fog act number&lt;br /&gt;
** Evening: Act 0 (Station) is 4, Acts 1 (Angel Island) and 2 (Jungle) are 5&lt;br /&gt;
** Night: Act 0 (Station) is 6, Acts 1 (Angel Island) and 2 (Jungle) are 7&lt;br /&gt;
** Act 3 (Mystic Ruins Base) always uses 3&lt;br /&gt;
&lt;br /&gt;
{{SAToolsNavbox}}&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=MediaWiki:Common.css&amp;diff=716</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=MediaWiki:Common.css&amp;diff=716"/>
		<updated>2026-03-11T04:02:47Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;img {&lt;br /&gt;
    filter: none !important;&lt;br /&gt;
    background-color: transparent !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.thumbinner {&lt;br /&gt;
    filter: none !important;&lt;br /&gt;
    background-color: transparent !important;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=MediaWiki:Common.css&amp;diff=715</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=MediaWiki:Common.css&amp;diff=715"/>
		<updated>2026-03-11T03:57:28Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;img {&lt;br /&gt;
    filter: none !important;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=MediaWiki:Common.css&amp;diff=714</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=MediaWiki:Common.css&amp;diff=714"/>
		<updated>2026-03-11T03:52:59Z</updated>

		<summary type="html">&lt;p&gt;PkR: Created page with &amp;quot;/* CSS placed here will be applied to all skins */ /* Remove gray filter/dimming from images in Vector 2022 dark mode */ html.skin-theme-client-night .mw-page-container img, html.skin-theme-client-night .mw-page-container video {     filter: none !important; }&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
/* Remove gray filter/dimming from images in Vector 2022 dark mode */&lt;br /&gt;
html.skin-theme-client-night .mw-page-container img,&lt;br /&gt;
html.skin-theme-client-night .mw-page-container video {&lt;br /&gt;
    filter: none !important;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=709</id>
		<title>Sonic Adventure Autodemo/Restoration</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=709"/>
		<updated>2026-03-02T04:51:51Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is dedicated to projects that restore content and functionality in the Autodemo prototype of Sonic Adventure (Dreamcast). For Sonic Adventure DX (PC) mods that implement Autodemo features, see [[SADX Autodemo Mods|this page]] instead.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When the [[Sonic Adventure Autodemo]] was first dumped in 2013, it was soon discovered that it was a semi-functional build of the full game. The Autodemo was quickly hacked to unlock player controls and load stages manually so that they could be explored freely. However, many stages did not load because the binaries containing them were originally compiled for an older version of the game&#039;s main executable.&lt;br /&gt;
&lt;br /&gt;
The Autodemo has been researched ever since it was dumped, and the non-functional stages were eventually extracted using [[SA Tools]] and ported to the PC version. However, being able to play them in the Autodemo itself was desirable in order to see differences in the game&#039;s code, which couldn&#039;t be exported by the tools.&lt;br /&gt;
&lt;br /&gt;
Initial work on restoring Autodemo functionality ingame was done back in 2015, when the user &#039;&#039;evilhamwizard&#039;&#039; posted their findings in the [https://forums.sonicretro.org/posts/846056/ Autodemo discussion thread on Sonic Retro]. The work focused primarily on restoring the original Windy Valley, and a number of GIFs of the level running on the emulator [https://forums.sonicretro.org/posts/867245/ were posted in 2016]. Some updates were posted on [https://forums.sonicretro.org/posts/937406/ booting Sky Deck] as well.&lt;br /&gt;
&lt;br /&gt;
In 2024, based on &#039;&#039;evilhamwizard&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;s initial research, a new restoration project was started by [[x-hax]] (primarily by &#039;&#039;Speeps&#039;&#039;), aiming to make other stages bootable, as well as improving the original Windy Valley restoration. This project is a collaboration between x-hax users, using symbol information acquired from the leaked Xbox 360 SADX prototype. The project is [https://github.com/X-Hax/dreamcast-mods available as a GitHub repository].&lt;br /&gt;
&lt;br /&gt;
==Background and Method==&lt;br /&gt;
The files included on the Autodemo disc come from different builds of the game that were at different stages of development. When the Autodemo was put together, only the stages that were meant to be shown in the demo were recompiled, and the other stages were left over from older builds (for most of these, textures and lighting files were also missing). We can tell which binaries were recompiled by looking at file dates on the Autodemo GD-ROM. Only the files dated October 15 work ingame as-is, and other files cause the game to crash. The crash happens because the functions in the game&#039;s updated main binary (1ST_READ.BIN) are at different memory addresses from those expected by the code in stage binaries which were compiled for the older version of the game. &lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot;&lt;br /&gt;
!&#039;&#039;&#039;October 15, 1998 (working)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;October 7, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;September 24, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|STG01 (Emerald Coast)&lt;br /&gt;
|AL_GARDEN01 (Egg Carrier/Beta Windy Valley Chao Garden) &lt;br /&gt;
|STG00 (&amp;quot;Practice&amp;quot; Stages)&lt;br /&gt;
|-&lt;br /&gt;
|STG04 (Speed Highway)&lt;br /&gt;
|AL_GARDEN02 (Mystic Ruins Chao Garden)&lt;br /&gt;
|STG02 (Windy Valley)&lt;br /&gt;
|-&lt;br /&gt;
|STG05 (Red Mountain)&lt;br /&gt;
|AL_RACE (Chao Race)&lt;br /&gt;
|STG03 (Twinkle Park)&lt;br /&gt;
|-&lt;br /&gt;
|STG08 (Ice Cap)&lt;br /&gt;
|&lt;br /&gt;
|STG06 (Sky Deck)&lt;br /&gt;
|-&lt;br /&gt;
|STG10 (Final Egg)&lt;br /&gt;
|&lt;br /&gt;
|STG07 (Lost World)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00 (Station Square)&lt;br /&gt;
|&lt;br /&gt;
|STG09 (Casinopolis)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00OBJ (Station Square objects)&lt;br /&gt;
|&lt;br /&gt;
|ADV02 (Mystic Ruins)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0100 (Egg Carrier Outside)&lt;br /&gt;
|&lt;br /&gt;
|ADV02OBJ (Mystic Ruins objects)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0130 (Egg Carries Inside)&lt;br /&gt;
|&lt;br /&gt;
|SHOOTING (Sky Chase)&lt;br /&gt;
|-&lt;br /&gt;
|ADV01OBJ (Egg Carrier objects)&lt;br /&gt;
|&lt;br /&gt;
|MINICART (Twinkle Circuit)&lt;br /&gt;
|-&lt;br /&gt;
|AL_GARDEN00 (Station Square Chao Garden)&lt;br /&gt;
|&lt;br /&gt;
|B_E101_R (E-101 MK2)&lt;br /&gt;
|-&lt;br /&gt;
|AL_MAIN (Chao)&lt;br /&gt;
|&lt;br /&gt;
|B_ROBO (ZERO)&lt;br /&gt;
|-&lt;br /&gt;
|B_CHAOS2 (Chaos 2)&lt;br /&gt;
|&lt;br /&gt;
|B_EGM1 (Egg Hornet)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_EGM3 (Egg Viper)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|SBOARD (Sand Hill)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS0 (Chaos 0)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS4 (Chaos 4)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS6 (Chaos 6)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS7 (Perfect Chaos)&lt;br /&gt;
|}&lt;br /&gt;
However, as originally demonstrated by &#039;&#039;evilhamwizard&#039;&#039;, it’s possible to find the functions and data they were meant to point to by comparing the pointers to known functions and data between these files and the files that boot. In 2024, &#039;&#039;Speeps&#039;&#039; started putting together a new [https://github.com/X-Hax/dreamcast-mods/raw/refs/heads/main/AutoDemoPointers.xlsx spreadsheet] of known broken pointers and their correct counterparts. As the pointer list grew, more levels became functional when known pointers were replaced.&lt;br /&gt;
&lt;br /&gt;
The exact pointer matching procedure involved in stage restoration is as follows:&lt;br /&gt;
#Get the address of all pointers that read the stage&#039;s file from 1ST_READ. These are the Round Manager, Background Manager, Object List and Path List.&lt;br /&gt;
# Using IDA&#039;s graph view, gather all pointers to 1ST_READ (8Cxxxxxx).&lt;br /&gt;
# Using Ghidra, identify an object (using its name string) and check if the same code exists in SADX, where its symbol information can be taken from the 360 symbols.&lt;br /&gt;
# For all references to broken pointers in the object, attempt to find a working reference in a functional AutoDemo stage, such as Speed Highway.&lt;br /&gt;
# Replace the broken pointer with the working one.&lt;br /&gt;
All pointers were added to a [https://github.com/X-Hax/dreamcast-mods/raw/refs/heads/main/AutoDemoPointers.xlsx spreadsheet] along with their fixed version.&lt;br /&gt;
&lt;br /&gt;
For any code that didn&#039;t have a matching reference in the PC version or a functional Autodemo stage file, such as code for objects that didn&#039;t exist in the final game, the original byte difference method was used instead. Using Ghidra, the resulting pointer was checked to ensure it led to an appropriate address (The beginning of a function etc.). Any pointers &amp;quot;fixed&amp;quot; with this method were marked in the table as unsure.&lt;br /&gt;
&lt;br /&gt;
Stages that were similar enough to their final counterparts to share a lot of code (Twinkle Park, Lost World) were repaired first to build the database of known pointers, as stages with larger changes (Windy Valley) consisted almost entirely of code that didn&#039;t exist in the final game.&lt;br /&gt;
&lt;br /&gt;
Early hacks by &#039;&#039;Speeps&#039;&#039; were using simple patches to the executables applied through a hex editor. To facilitate mass pointer replacement and game testing, &#039;&#039;PkR&#039;&#039; reworked his SA1-DC-HD tool (originally meant to build GDIs of the final version of SA1 with enhancements) and created the [[Dreamcast Image Builder]]. The image builder uses a &amp;quot;mods&amp;quot; system that makes it easier to replace pointers, do all sorts of patching of game binaries and build a modified game image containing all of the selected hacks. In addition, some other tools on the [https://github.com/X-Hax/sa_tools_research SA Tools Research] repository were repurposed to add missing textures to the Autodemo by matching the names in the Autodemo’s texture lists against textures in the final version, the E3 build, the Autodemo Windy Valley mod for the PC version (where missing textures were recreated by its developers) and Dreamcast SDKs (which surprisingly have some early SA1 textures). Apart from making stages bootable and readding textures, the mods include various experiments with controls, framerate, lighting, skipping the intro movie, restoring debug functionality etc.&lt;br /&gt;
&lt;br /&gt;
The restoration was primarily discussed in a series of threads on x-hax Discord, which have been archived below: &lt;br /&gt;
&lt;br /&gt;
[https://dcmods.unreliable.network/owncloud/data/PiKeyAr/files/SA1%20research/autodemo/threads/sa1-modding%20-%20New%20Autodemo%20research.html Thread 1: New Autodemo Research (May 10, 2024)] &lt;br /&gt;
&lt;br /&gt;
[https://dcmods.unreliable.network/owncloud/data/PiKeyAr/files/SA1%20research/autodemo/threads/sa1-modding%20-%20Autodemo%20research.html Thread 2: Autodemo Research (Private Version, May 10 - June 18, 2024)] &lt;br /&gt;
&lt;br /&gt;
[https://dcmods.unreliable.network/owncloud/data/PiKeyAr/files/SA1%20research/autodemo/threads/game-research%20-%20Sonic%20Adventure%20Autodemo.html Thread 3: Game Research: Sonic Adventure Autodemo (Public Version, June 7, 2024 - February 28, 2026)] &lt;br /&gt;
&lt;br /&gt;
== Restoration Details ==&lt;br /&gt;
&lt;br /&gt;
=== Twinkle Park ===&lt;br /&gt;
Twinkle Park was the first stage restored by &#039;&#039;Speeps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Stage Select ===&lt;br /&gt;
The Stage Select screen is similar to the final version. &#039;&#039;woofmute&#039;&#039; and &#039;&#039;PkR&#039;&#039; found out that the texture error at the bottom right was caused by the game trying to load character pictures, which were added back afterwards.&amp;lt;gallery mode=&amp;quot;nolines&amp;quot;&amp;gt;&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772422970977.png|Autodemo Stage Select with the texture error (&#039;&#039;MainJP&#039;&#039;)&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772422993825.png|Autodemo Stage Select with character pictures (&#039;&#039;woofmute&#039;&#039;)&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debug Functionality ===&lt;br /&gt;
The SET Editor was restored by &#039;&#039;woofmute&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Ninja Lights ===&lt;br /&gt;
&lt;br /&gt;
=== Practice Stages ===&lt;br /&gt;
&#039;&#039;Speeps&#039;&#039;: It turned out Practice 1 could load by just removing its SET File (Object Layout) because it only references 1ST_READ through that.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;PkR&#039;&#039;: Practice 2 did not load because one of the meshes is too big for the game&#039;s [[Sonic Adventure/Lantern Engine|LANTERN lighting system]] to handle. However, it boots if [[Ninja Lights]] are used instead.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Autodemo Practice Stages&lt;br /&gt;
![[File:Sonic Adventure Autodemo Restoration 1772347046976.mp4|none|thumb|Gamma in Practice Stage (&#039;&#039;Speeps&#039;&#039;)]]&lt;br /&gt;
![[File:Pinball mode practice.mp4|thumb|Pinball mode in Practice Stage (&#039;&#039;MainJP&#039;&#039;)|none]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;nolines&amp;quot; caption=&amp;quot;Practice Stages with Ninja Lights (images by &#039;&#039;MainJP&#039;&#039;)&amp;quot;&amp;gt;&lt;br /&gt;
File:Practice.webp|alt=&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772203956319.png&lt;br /&gt;
File:Screenshot 2024-08-30 15-59-50.webp&lt;br /&gt;
File:Screenshot 2024-08-30 16-15-14.webp&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windy Valley ===&lt;br /&gt;
&lt;br /&gt;
=== Sky Deck ===&lt;br /&gt;
&lt;br /&gt;
=== Lost World ===&lt;br /&gt;
&lt;br /&gt;
=== Casinopolis ===&lt;br /&gt;
&lt;br /&gt;
=== Station Square ===&lt;br /&gt;
&lt;br /&gt;
=== Mystic Ruins ===&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=708</id>
		<title>Sonic Adventure Autodemo/Restoration</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=708"/>
		<updated>2026-03-02T03:46:59Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is dedicated to projects that restore content and functionality in the Autodemo prototype of Sonic Adventure (Dreamcast). For Sonic Adventure PX (PC) mods that implement Autodemo features, see [[SADX Autodemo Mods|this page]] instead.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When the [[Sonic Adventure Autodemo]] was first dumped in 2013, it was soon discovered that it was a semi-functional build of the full game. The Autodemo was quickly hacked to unlock player controls and load stages manually so that they could be explored freely. However, many stages did not load because the binaries containing them were originally compiled for an older version of the game&#039;s main executable.&lt;br /&gt;
&lt;br /&gt;
The Autodemo has been researched ever since it was dumped, and the non-functional stages were eventually extracted using [[SA Tools]] and ported to the PC version. However, being able to play them in the Autodemo itself was desirable in order to see differences in the game&#039;s code, which couldn&#039;t be exported by the tools.&lt;br /&gt;
&lt;br /&gt;
Initial work on restoring Autodemo functionality ingame was done back in 2015, when the user &#039;&#039;evilhamwizard&#039;&#039; posted their findings in the [https://forums.sonicretro.org/posts/846056/ Autodemo discussion thread on Sonic Retro]. The work focused primarily on restoring the original Windy Valley, and a number of GIFs of the level running on the emulator [https://forums.sonicretro.org/posts/867245/ were posted in 2016]. Some updates were posted on [https://forums.sonicretro.org/posts/937406/ booting Sky Deck] as well.&lt;br /&gt;
&lt;br /&gt;
In 2024, based on &#039;&#039;evilhamwizard&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;s initial research, a new restoration project was started by [[x-hax]] (primarily by &#039;&#039;Speeps&#039;&#039;), aiming to make other stages bootable, as well as improving the original Windy Valley restoration. This project is a collaboration between x-hax users, using symbol information acquired from the leaked Xbox 360 SADX prototype. The project is [https://github.com/X-Hax/dreamcast-mods available as a GitHub repository].&lt;br /&gt;
&lt;br /&gt;
==Background and Method==&lt;br /&gt;
The files included on the Autodemo disc come from different builds of the game that were at different stages of development. When the Autodemo was put together, only the stages that were meant to be shown in the demo were recompiled, and the other stages were left over from older builds (for most of these, textures and lighting files were also missing). We can tell which binaries were recompiled by looking at file dates on the Autodemo GD-ROM. Only the files dated October 15 work ingame as-is, and other files cause the game to crash. The crash happens because the functions in the game&#039;s updated main binary (1ST_READ.BIN) are at different memory addresses from those expected by the code in stage binaries which were compiled for the older version of the game. &lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot;&lt;br /&gt;
!&#039;&#039;&#039;October 15, 1998 (working)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;October 7, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;September 24, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|STG01 (Emerald Coast)&lt;br /&gt;
|AL_GARDEN01 (Egg Carrier/Beta Windy Valley Chao Garden) &lt;br /&gt;
|STG00 (&amp;quot;Practice&amp;quot; Stages)&lt;br /&gt;
|-&lt;br /&gt;
|STG04 (Speed Highway)&lt;br /&gt;
|AL_GARDEN02 (Mystic Ruins Chao Garden)&lt;br /&gt;
|STG02 (Windy Valley)&lt;br /&gt;
|-&lt;br /&gt;
|STG05 (Red Mountain)&lt;br /&gt;
|AL_RACE (Chao Race)&lt;br /&gt;
|STG03 (Twinkle Park)&lt;br /&gt;
|-&lt;br /&gt;
|STG08 (Ice Cap)&lt;br /&gt;
|&lt;br /&gt;
|STG06 (Sky Deck)&lt;br /&gt;
|-&lt;br /&gt;
|STG10 (Final Egg)&lt;br /&gt;
|&lt;br /&gt;
|STG07 (Lost World)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00 (Station Square)&lt;br /&gt;
|&lt;br /&gt;
|STG09 (Casinopolis)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00OBJ (Station Square objects)&lt;br /&gt;
|&lt;br /&gt;
|ADV02 (Mystic Ruins)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0100 (Egg Carrier Outside)&lt;br /&gt;
|&lt;br /&gt;
|ADV02OBJ (Mystic Ruins objects)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0130 (Egg Carries Inside)&lt;br /&gt;
|&lt;br /&gt;
|SHOOTING (Sky Chase)&lt;br /&gt;
|-&lt;br /&gt;
|ADV01OBJ (Egg Carrier objects)&lt;br /&gt;
|&lt;br /&gt;
|MINICART (Twinkle Circuit)&lt;br /&gt;
|-&lt;br /&gt;
|AL_GARDEN00 (Station Square Chao Garden)&lt;br /&gt;
|&lt;br /&gt;
|B_E101_R (E-101 MK2)&lt;br /&gt;
|-&lt;br /&gt;
|AL_MAIN (Chao)&lt;br /&gt;
|&lt;br /&gt;
|B_ROBO (ZERO)&lt;br /&gt;
|-&lt;br /&gt;
|B_CHAOS2 (Chaos 2)&lt;br /&gt;
|&lt;br /&gt;
|B_EGM1 (Egg Hornet)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_EGM3 (Egg Viper)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|SBOARD (Sand Hill)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS0 (Chaos 0)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS4 (Chaos 4)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS6 (Chaos 6)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS7 (Perfect Chaos)&lt;br /&gt;
|}&lt;br /&gt;
However, as originally demonstrated by &#039;&#039;evilhamwizard&#039;&#039;, it’s possible to find the functions and data they were meant to point to by comparing the pointers to known functions and data between these files and the files that boot. In 2024, &#039;&#039;Speeps&#039;&#039; started putting together a new [https://github.com/X-Hax/dreamcast-mods/raw/refs/heads/main/AutoDemoPointers.xlsx spreadsheet] of known broken pointers and their correct counterparts. As the pointer list grew, more levels became functional when known pointers were replaced.&lt;br /&gt;
&lt;br /&gt;
The exact pointer matching procedure involved in stage restoration is as follows:&lt;br /&gt;
#Get the address of all pointers that read the stage&#039;s file from 1ST_READ. These are the Round Manager, Background Manager, Object List and Path List.&lt;br /&gt;
# Using IDA&#039;s graph view, gather all pointers to 1ST_READ (8Cxxxxxx).&lt;br /&gt;
# Using Ghidra, identify an object (using its name string) and check if the same code exists in SADX, where its symbol information can be taken from the 360 symbols.&lt;br /&gt;
# For all references to broken pointers in the object, attempt to find a working reference in a functional AutoDemo stage, such as Speed Highway.&lt;br /&gt;
# Replace the broken pointer with the working one.&lt;br /&gt;
All pointers were added to a [https://github.com/X-Hax/dreamcast-mods/raw/refs/heads/main/AutoDemoPointers.xlsx spreadsheet] along with their fixed version.&lt;br /&gt;
&lt;br /&gt;
For any code that didn&#039;t have a matching reference in the PC version or a functional Autodemo stage file, such as code for objects that didn&#039;t exist in the final game, the original byte difference method was used instead. Using Ghidra, the resulting pointer was checked to ensure it led to an appropriate address (The beginning of a function etc.). Any pointers &amp;quot;fixed&amp;quot; with this method were marked in the table as unsure.&lt;br /&gt;
&lt;br /&gt;
Stages that were similar enough to their final counterparts to share a lot of code (Twinkle Park, Lost World) were repaired first to build the database of known pointers, as stages with larger changes (Windy Valley) consisted almost entirely of code that didn&#039;t exist in the final game.&lt;br /&gt;
&lt;br /&gt;
Early hacks by &#039;&#039;Speeps&#039;&#039; were using simple patches to the executables applied through a hex editor. To facilitate mass pointer replacement and game testing, &#039;&#039;PkR&#039;&#039; reworked his SA1-DC-HD tool (originally meant to build GDIs of the final version of SA1 with enhancements) and created the [[Dreamcast Image Builder]]. The image builder uses a &amp;quot;mods&amp;quot; system that makes it easier to replace pointers, do all sorts of patching of game binaries and build a modified game image containing all of the selected hacks. In addition, some other tools on the [https://github.com/X-Hax/sa_tools_research SA Tools Research] repository were repurposed to add missing textures to the Autodemo by matching the names in the Autodemo’s texture lists against textures in the final version, the E3 build, the Autodemo Windy Valley mod for the PC version (where missing textures were recreated by its developers) and Dreamcast SDKs (which surprisingly have some early SA1 textures). Apart from making stages bootable and readding textures, the mods include various experiments with controls, framerate, lighting, skipping the intro movie, restoring debug functionality etc.&lt;br /&gt;
&lt;br /&gt;
The restoration was primarily discussed in a series of threads on x-hax Discord, which have been archived below: &lt;br /&gt;
&lt;br /&gt;
[https://dcmods.unreliable.network/owncloud/data/PiKeyAr/files/SA1%20research/autodemo/threads/sa1-modding%20-%20New%20Autodemo%20research.html Thread 1: New Autodemo Research (May 10, 2024)] &lt;br /&gt;
&lt;br /&gt;
[https://dcmods.unreliable.network/owncloud/data/PiKeyAr/files/SA1%20research/autodemo/threads/sa1-modding%20-%20Autodemo%20research.html Thread 2: Autodemo Research (Private Version, May 10 - June 18, 2024)] &lt;br /&gt;
&lt;br /&gt;
[https://dcmods.unreliable.network/owncloud/data/PiKeyAr/files/SA1%20research/autodemo/threads/game-research%20-%20Sonic%20Adventure%20Autodemo.html Thread 3: Game Research: Sonic Adventure Autodemo (Public Version, June 7, 2024 - February 28, 2026)] &lt;br /&gt;
&lt;br /&gt;
== Restoration Details ==&lt;br /&gt;
&lt;br /&gt;
=== Twinkle Park ===&lt;br /&gt;
Twinkle Park was the first stage restored by &#039;&#039;Speeps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Stage Select ===&lt;br /&gt;
The Stage Select screen is similar to the final version. &#039;&#039;woofmute&#039;&#039; and &#039;&#039;PkR&#039;&#039; found out that the texture error at the bottom right was caused by the game trying to load character pictures, which were added back afterwards.&amp;lt;gallery mode=&amp;quot;nolines&amp;quot;&amp;gt;&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772422970977.png|Autodemo Stage Select with the texture error (&#039;&#039;MainJP&#039;&#039;)&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772422993825.png|Autodemo Stage Select with character pictures (&#039;&#039;woofmute&#039;&#039;)&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debug Functionality ===&lt;br /&gt;
The SET Editor was restored by &#039;&#039;woofmute&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Ninja Lights ===&lt;br /&gt;
&lt;br /&gt;
=== Practice Stages ===&lt;br /&gt;
&#039;&#039;Speeps&#039;&#039;: It turned out Practice 1 could load by just removing its SET File (Object Layout) because it only references 1ST_READ through that.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;PkR&#039;&#039;: Practice 2 did not load because one of the meshes is too big for the game&#039;s [[Sonic Adventure/Lantern Engine|LANTERN lighting system]] to handle. However, it boots if [[Ninja Lights]] are used instead.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Autodemo Practice Stages&lt;br /&gt;
![[File:Sonic Adventure Autodemo Restoration 1772347046976.mp4|none|thumb|Gamma in Practice Stage (&#039;&#039;Speeps&#039;&#039;)]]&lt;br /&gt;
![[File:Pinball mode practice.mp4|thumb|Pinball mode in Practice Stage (&#039;&#039;MainJP&#039;&#039;)|none]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;nolines&amp;quot; caption=&amp;quot;Practice Stages with Ninja Lights (images by &#039;&#039;MainJP&#039;&#039;)&amp;quot;&amp;gt;&lt;br /&gt;
File:Practice.webp|alt=&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772203956319.png&lt;br /&gt;
File:Screenshot 2024-08-30 15-59-50.webp&lt;br /&gt;
File:Screenshot 2024-08-30 16-15-14.webp&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windy Valley ===&lt;br /&gt;
&lt;br /&gt;
=== Sky Deck ===&lt;br /&gt;
&lt;br /&gt;
=== Lost World ===&lt;br /&gt;
&lt;br /&gt;
=== Casinopolis ===&lt;br /&gt;
&lt;br /&gt;
=== Station Square ===&lt;br /&gt;
&lt;br /&gt;
=== Mystic Ruins ===&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=707</id>
		<title>Sonic Adventure Autodemo/Restoration</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=707"/>
		<updated>2026-03-02T03:45:22Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is dedicated to projects that restore content and functionality in the Autodemo prototype of Sonic Adventure (Dreamcast). For Sonic Adventure PX (PC) mods that implement Autodemo features, see [[SADX Autodemo Mods|this page]] instead.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When the [[Sonic Adventure Autodemo]] was first dumped in 2013, it was soon discovered that it was a semi-functional build of the full game. The Autodemo was quickly hacked to unlock player controls and load stages manually so that they could be explored freely. However, many stages did not load because the binaries containing them were originally compiled for an older version of the game&#039;s main executable.&lt;br /&gt;
&lt;br /&gt;
The Autodemo has been researched ever since it was dumped, and the non-functional stages were eventually extracted using [[SA Tools]] and ported to the PC version. However, being able to play them in the Autodemo itself was desirable in order to see differences in the game&#039;s code, which couldn&#039;t be exported by the tools.&lt;br /&gt;
&lt;br /&gt;
Initial work on restoring Autodemo functionality ingame was done back in 2015, when the user &#039;&#039;evilhamwizard&#039;&#039; posted their findings in the [https://forums.sonicretro.org/posts/846056/ Autodemo discussion thread on Sonic Retro]. The work focused primarily on restoring the original Windy Valley, and a number of GIFs of the level running on the emulator [https://forums.sonicretro.org/posts/867245/ were posted in 2016]. Some updates were posted on [https://forums.sonicretro.org/posts/937406/ booting Sky Deck] as well.&lt;br /&gt;
&lt;br /&gt;
In 2024, based on &#039;&#039;evilhamwizard&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;s initial research, a new restoration project was started by [[x-hax]] (primarily by &#039;&#039;Speeps&#039;&#039;), aiming to make other stages bootable, as well as improving the original Windy Valley restoration. This project is a collaboration between x-hax users, using symbol information acquired from the leaked Xbox 360 SADX prototype. The project is [https://github.com/X-Hax/dreamcast-mods available as a GitHub repository].&lt;br /&gt;
&lt;br /&gt;
==Background and Method==&lt;br /&gt;
The files included on the Autodemo disc come from different builds of the game that were at different stages of development. When the Autodemo was put together, only the stages that were meant to be shown in the demo were recompiled, and the other stages were left over from older builds (for most of these, textures and lighting files were also missing). We can tell which binaries were recompiled by looking at file dates on the Autodemo GD-ROM. Only the files dated October 15 work ingame as-is, and other files cause the game to crash. The crash happens because the functions in the game&#039;s updated main binary (1ST_READ.BIN) are at different memory addresses from those expected by the code in stage binaries which were compiled for the older version of the game. &lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot;&lt;br /&gt;
!&#039;&#039;&#039;October 15, 1998 (working)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;October 7, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;September 24, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|STG01 (Emerald Coast)&lt;br /&gt;
|AL_GARDEN01 (Egg Carrier/Beta Windy Valley Chao Garden) &lt;br /&gt;
|STG00 (&amp;quot;Practice&amp;quot; Stages)&lt;br /&gt;
|-&lt;br /&gt;
|STG04 (Speed Highway)&lt;br /&gt;
|AL_GARDEN02 (Mystic Ruins Chao Garden)&lt;br /&gt;
|STG02 (Windy Valley)&lt;br /&gt;
|-&lt;br /&gt;
|STG05 (Red Mountain)&lt;br /&gt;
|AL_RACE (Chao Race)&lt;br /&gt;
|STG03 (Twinkle Park)&lt;br /&gt;
|-&lt;br /&gt;
|STG08 (Ice Cap)&lt;br /&gt;
|&lt;br /&gt;
|STG06 (Sky Deck)&lt;br /&gt;
|-&lt;br /&gt;
|STG10 (Final Egg)&lt;br /&gt;
|&lt;br /&gt;
|STG07 (Lost World)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00 (Station Square)&lt;br /&gt;
|&lt;br /&gt;
|STG09 (Casinopolis)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00OBJ (Station Square objects)&lt;br /&gt;
|&lt;br /&gt;
|ADV02 (Mystic Ruins)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0100 (Egg Carrier Outside)&lt;br /&gt;
|&lt;br /&gt;
|ADV02OBJ (Mystic Ruins objects)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0130 (Egg Carries Inside)&lt;br /&gt;
|&lt;br /&gt;
|SHOOTING (Sky Chase)&lt;br /&gt;
|-&lt;br /&gt;
|ADV01OBJ (Egg Carrier objects)&lt;br /&gt;
|&lt;br /&gt;
|MINICART (Twinkle Circuit)&lt;br /&gt;
|-&lt;br /&gt;
|AL_GARDEN00 (Station Square Chao Garden)&lt;br /&gt;
|&lt;br /&gt;
|B_E101_R (E-101 MK2)&lt;br /&gt;
|-&lt;br /&gt;
|AL_MAIN (Chao)&lt;br /&gt;
|&lt;br /&gt;
|B_ROBO (ZERO)&lt;br /&gt;
|-&lt;br /&gt;
|B_CHAOS2 (Chaos 2)&lt;br /&gt;
|&lt;br /&gt;
|B_EGM1 (Egg Hornet)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_EGM3 (Egg Viper)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|SBOARD (Sand Hill)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS0 (Chaos 0)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS4 (Chaos 4)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS6 (Chaos 6)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS7 (Perfect Chaos)&lt;br /&gt;
|}&lt;br /&gt;
However, as originally demonstrated by &#039;&#039;evilhamwizard&#039;&#039;, it’s possible to find the functions and data they were meant to point to by comparing the pointers to known functions and data between these files and the files that boot. In 2024, &#039;&#039;Speeps&#039;&#039; started putting together a new [https://github.com/X-Hax/dreamcast-mods/raw/refs/heads/main/AutoDemoPointers.xlsx spreadsheet] of known broken pointers and their correct counterparts. As the pointer list grew, more levels became functional when known pointers were replaced.&lt;br /&gt;
&lt;br /&gt;
The exact pointer matching procedure involved in stage restoration is as follows:&lt;br /&gt;
#Get the address of all pointers that read the stage&#039;s file from 1ST_READ. These are the Round Manager, Background Manager, Object List and Path List.&lt;br /&gt;
# Using IDA&#039;s graph view, gather all pointers to 1ST_READ (8Cxxxxxx).&lt;br /&gt;
# Using Ghidra, identify an object (using its name string) and check if the same code exists in SADX, where its symbol information can be taken from the 360 symbols.&lt;br /&gt;
# For all references to broken pointers in the object, attempt to find a working reference in a functional AutoDemo stage, such as Speed Highway.&lt;br /&gt;
# Replace the broken pointer with the working one.&lt;br /&gt;
All pointers were added to a [https://github.com/X-Hax/dreamcast-mods/raw/refs/heads/main/AutoDemoPointers.xlsx spreadsheet] along with their fixed version.&lt;br /&gt;
&lt;br /&gt;
For any code that didn&#039;t have a matching reference in the PC version or a functional Autodemo stage file, such as code for objects that didn&#039;t exist in the final game, the original byte difference method was used instead. Using Ghidra, the resulting pointer was checked to ensure it led to an appropriate address (The beginning of a function etc.). Any pointers &amp;quot;fixed&amp;quot; with this method were marked in the table as unsure.&lt;br /&gt;
&lt;br /&gt;
Stages that were similar enough to their final counterparts to share a lot of code (Twinkle Park, Lost World) were repaired first to build the database of known pointers, as stages with larger changes (Windy Valley) consisted almost entirely of code that didn&#039;t exist in the final game.&lt;br /&gt;
&lt;br /&gt;
Early hacks by &#039;&#039;Speeps&#039;&#039; were using simple patches to the executables applied through a hex editor. To facilitate mass pointer replacement and game testing, &#039;&#039;PkR&#039;&#039; reworked his SA1-DC-HD tool (originally meant to build GDIs of the final version of SA1 with enhancements) and created the [[Dreamcast Image Builder]]. The image builder uses a &amp;quot;mods&amp;quot; system that makes it easier to replace pointers, do all sorts of patching of game binaries and build a modified game image containing all of the selected hacks. In addition, some other tools on the [https://github.com/X-Hax/sa_tools_research SA Tools Research] repository were repurposed to add missing textures to the Autodemo by matching the names in the Autodemo’s texture lists against textures in the final version, the E3 build, the Autodemo Windy Valley mod for the PC version (where missing textures were recreated by its developers) and Dreamcast SDKs (which surprisingly have some early SA1 textures). Apart from making stages bootable and readding textures, the mods include various experiments with controls, framerate, lighting, skipping the intro movie, restoring debug functionality etc.&lt;br /&gt;
&lt;br /&gt;
The restoration was primarily discussed in a series of threads on x-hax Discord, which have been archived below: &lt;br /&gt;
&lt;br /&gt;
[https://dcmods.unreliable.network/owncloud/data/PiKeyAr/files/SA1%20research/autodemo/threads/sa1-modding%20-%20New%20Autodemo%20research.html Thread 1: New Autodemo Research (May 10, 2024)] &lt;br /&gt;
&lt;br /&gt;
[https://dcmods.unreliable.network/owncloud/data/PiKeyAr/files/SA1%20research/autodemo/threads/sa1-modding%20-%20Autodemo%20research.html Thread 2: Autodemo Research (Private Version, May 10 - June 18, 2024)] &lt;br /&gt;
&lt;br /&gt;
[https://dcmods.unreliable.network/owncloud/data/PiKeyAr/files/SA1%20research/autodemo/threads/game-research%20-%20Sonic%20Adventure%20Autodemo.html Thread 3: Game Research: Sonic Adventure Autodemo (Public Version, June 7, 2024 - February 28, 2026)] &lt;br /&gt;
&lt;br /&gt;
== Restoration Details ==&lt;br /&gt;
&lt;br /&gt;
=== Twinkle Park ===&lt;br /&gt;
Twinkle Park was the first stage restored by &#039;&#039;Speeps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Stage Select ===&lt;br /&gt;
The Stage Select screen is similar to the final version. &#039;&#039;woofmute&#039;&#039; and &#039;&#039;PkR&#039;&#039; found out that the texture error at the bottom right was caused by the game trying to load character pictures, which were added back afterwards.&lt;br /&gt;
&lt;br /&gt;
[[File:Sonic Adventure Autodemo Restoration 1772422970977.png|left|Autodemo Stage Select with the texture error (&#039;&#039;MainJP&#039;&#039;)]]&lt;br /&gt;
[[File:Sonic Adventure Autodemo Restoration 1772422993825.png|right|Autodemo Stage Select with character pictures (&#039;&#039;woofmute&#039;&#039;)]]&lt;br /&gt;
&lt;br /&gt;
=== Debug Functionality ===&lt;br /&gt;
The SET Editor was restored by &#039;&#039;woofmute&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Ninja Lights ===&lt;br /&gt;
&lt;br /&gt;
=== Practice Stages ===&lt;br /&gt;
&#039;&#039;Speeps&#039;&#039;: It turned out Practice 1 could load by just removing its SET File (Object Layout) because it only references 1ST_READ through that.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;PkR&#039;&#039;: Practice 2 did not load because one of the meshes is too big for the game&#039;s [[Sonic Adventure/Lantern Engine|LANTERN lighting system]] to handle. However, it boots if [[Ninja Lights]] are used instead.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Autodemo Practice Stages&lt;br /&gt;
![[File:Sonic Adventure Autodemo Restoration 1772347046976.mp4|none|thumb|Gamma in Practice Stage (&#039;&#039;Speeps&#039;&#039;)]]&lt;br /&gt;
![[File:Pinball mode practice.mp4|thumb|Pinball mode in Practice Stage (&#039;&#039;MainJP&#039;&#039;)|none]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;nolines&amp;quot; caption=&amp;quot;Practice Stages with Ninja Lights (images by &#039;&#039;MainJP&#039;&#039;)&amp;quot;&amp;gt;&lt;br /&gt;
File:Practice.webp|alt=&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772203956319.png&lt;br /&gt;
File:Screenshot 2024-08-30 15-59-50.webp&lt;br /&gt;
File:Screenshot 2024-08-30 16-15-14.webp&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windy Valley ===&lt;br /&gt;
&lt;br /&gt;
=== Sky Deck ===&lt;br /&gt;
&lt;br /&gt;
=== Lost World ===&lt;br /&gt;
&lt;br /&gt;
=== Casinopolis ===&lt;br /&gt;
&lt;br /&gt;
=== Station Square ===&lt;br /&gt;
&lt;br /&gt;
=== Mystic Ruins ===&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:Sonic_Adventure_Autodemo_Restoration_1772422993825.png&amp;diff=706</id>
		<title>File:Sonic Adventure Autodemo Restoration 1772422993825.png</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:Sonic_Adventure_Autodemo_Restoration_1772422993825.png&amp;diff=706"/>
		<updated>2026-03-02T03:43:16Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:Sonic_Adventure_Autodemo_Restoration_1772422970977.png&amp;diff=705</id>
		<title>File:Sonic Adventure Autodemo Restoration 1772422970977.png</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:Sonic_Adventure_Autodemo_Restoration_1772422970977.png&amp;diff=705"/>
		<updated>2026-03-02T03:42:53Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=704</id>
		<title>Sonic Adventure Autodemo/Restoration</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=704"/>
		<updated>2026-03-01T16:10:25Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is dedicated to projects that restore content and functionality in the Autodemo prototype of Sonic Adventure (Dreamcast). For Sonic Adventure PX (PC) mods that implement Autodemo features, see [[SADX Autodemo Mods|this page]] instead.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When the Sonic Adventure Autodemo was first dumped in 2013, it was soon discovered that it was a semi-functional build of the full game. The Autodemo was quickly hacked to unlock player controls and load stages manually so that they could be explored freely. However, many stages did not load because the binaries containing them were originally compiled for an older version of the game&#039;s main executable.&lt;br /&gt;
&lt;br /&gt;
The Autodemo has been researched ever since it was dumped, and the non-functional stages were eventually extracted using [[SA Tools]] and ported to the PC version. However, being able to play them in the Autodemo itself was desirable in order to see differences in the game&#039;s code, which couldn&#039;t be exported by the tools.&lt;br /&gt;
&lt;br /&gt;
Initial work on restoring Autodemo functionality ingame was done back in 2015, when the user &#039;&#039;evilhamwizard&#039;&#039; posted their findings in the [https://forums.sonicretro.org/posts/846056/ Autodemo discussion thread on Sonic Retro]. The work focused primarily on restoring the original Windy Valley, and a number of GIFs of the level running on the emulator [https://forums.sonicretro.org/posts/867245/ were posted in 2016]. Some updates were posted on booting Sky Deck as well.&lt;br /&gt;
&lt;br /&gt;
In 2024, based on &#039;&#039;evilhamwizard&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;s initial research, a new restoration project was started by [[x-hax]] (primarily by &#039;&#039;Speeps&#039;&#039;), aiming to make other stages bootable, as well as improving the original Windy Valley restoration. This restoration was achieved in 2024 through a collaboration of x-hax users and symbol information acquired from the leaked Xbox 360 SADX prototype. The project is [https://github.com/X-Hax/dreamcast-mods available as a GitHub repository].&lt;br /&gt;
&lt;br /&gt;
==Background and Method==&lt;br /&gt;
The files included on the Autodemo disc come from different builds of the game that were at different stages of development. When the Autodemo was put together, only the stages that were meant to be shown in the demo were recompiled, and the other stages were left over from older builds (for most of these, textures and lighting files were also missing). We can tell which binaries were recompiled by looking at file dates on the Autodemo GD-ROM. Only the files dated October 15 work ingame as-is, and other files cause the game to crash. The crash happens because the functions in the game&#039;s updated main binary (1ST_READ.BIN) are at different memory addresses from those expected by the code in stage binaries which were compiled for the older version of the game. &lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot;&lt;br /&gt;
!&#039;&#039;&#039;October 15, 1998 (working)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;October 7, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;September 24, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|STG01 (Emerald Coast)&lt;br /&gt;
|AL_GARDEN01 (Egg Carrier/Beta Windy Valley Chao Garden) &lt;br /&gt;
|STG00 (&amp;quot;Practice&amp;quot; Stages)&lt;br /&gt;
|-&lt;br /&gt;
|STG04 (Speed Highway)&lt;br /&gt;
|AL_GARDEN02 (Mystic Ruins Chao Garden)&lt;br /&gt;
|STG02 (Windy Valley)&lt;br /&gt;
|-&lt;br /&gt;
|STG05 (Red Mountain)&lt;br /&gt;
|AL_RACE (Chao Race)&lt;br /&gt;
|STG03 (Twinkle Park)&lt;br /&gt;
|-&lt;br /&gt;
|STG08 (Ice Cap)&lt;br /&gt;
|&lt;br /&gt;
|STG06 (Sky Deck)&lt;br /&gt;
|-&lt;br /&gt;
|STG10 (Final Egg)&lt;br /&gt;
|&lt;br /&gt;
|STG07 (Lost World)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00 (Station Square)&lt;br /&gt;
|&lt;br /&gt;
|STG09 (Casinopolis)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00OBJ (Station Square objects)&lt;br /&gt;
|&lt;br /&gt;
|ADV02 (Mystic Ruins)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0100 (Egg Carrier Outside)&lt;br /&gt;
|&lt;br /&gt;
|ADV02OBJ (Mystic Ruins objects)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0130 (Egg Carries Inside)&lt;br /&gt;
|&lt;br /&gt;
|SHOOTING (Sky Chase)&lt;br /&gt;
|-&lt;br /&gt;
|ADV01OBJ (Egg Carrier objects)&lt;br /&gt;
|&lt;br /&gt;
|MINICART (Twinkle Circuit)&lt;br /&gt;
|-&lt;br /&gt;
|AL_GARDEN00 (Station Square Chao Garden)&lt;br /&gt;
|&lt;br /&gt;
|B_E101_R (E-101 MK2)&lt;br /&gt;
|-&lt;br /&gt;
|AL_MAIN (Chao)&lt;br /&gt;
|&lt;br /&gt;
|B_ROBO (ZERO)&lt;br /&gt;
|-&lt;br /&gt;
|B_CHAOS2 (Chaos 2)&lt;br /&gt;
|&lt;br /&gt;
|B_EGM1 (Egg Hornet)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_EGM3 (Egg Viper)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|SBOARD (Sand Hill)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS0 (Chaos 0)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS4 (Chaos 4)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS6 (Chaos 6)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS7 (Perfect Chaos)&lt;br /&gt;
|}&lt;br /&gt;
However, as originally demonstrated by &#039;&#039;evilhamwizard&#039;&#039;, it’s possible to find the functions and data they were meant to point to by comparing the pointers to known functions and data between these files and the files that boot. In 2024, &#039;&#039;Speeps&#039;&#039; started putting together a new spreadsheet of known broken pointers and their correct counterparts. As the pointer list grew, more levels became functional when known pointers were replaced.&lt;br /&gt;
&lt;br /&gt;
Early hacks by &#039;&#039;Speeps&#039;&#039; were using simple patches to the executables applied through a hex editor. To facilitate mass pointer replacement and game testing, &#039;&#039;PkR&#039;&#039; reworked his SA1-DC-HD tool (originally meant to build GDIs of the final version of SA1 with enhancements) and created the [[Dreamcast Image Builder]]. The image builder uses a &amp;quot;mods&amp;quot; system that makes it easier to replace pointers, do all sorts of patching of game binaries and build a modified game image containing all of the selected hacks. In addition, some other tools on the [https://github.com/X-Hax/sa_tools_research SA Tools Research] repository were repurposed to find missing textures in the Autodemo by matching the names in the Autodemo’s texture lists against textures in the final version, the E3 build, the Autodemo Windy Valley mod for the PC version, where missing textures were recreated by its developers, and Dreamcast SDKs, which surprisingly have some early SA1 textures.&lt;br /&gt;
&lt;br /&gt;
Apart from making stages bootable, the mods include various experiments with controls, framerate, lighting, skipping the intro movie, adding textures that are missing on the disc, restoring debug functionality etc.&lt;br /&gt;
&lt;br /&gt;
The exact pointer matching procedure involved in stage restoration is as follows:&lt;br /&gt;
#Get the address of all pointers that read the stage&#039;s file from 1ST_READ. These are the Round Manager, Background Manager, Object List and Path List.&lt;br /&gt;
# Using IDA&#039;s graph view, gather all pointers to 1ST_READ (8Cxxxxxx).&lt;br /&gt;
# Using Ghidra, identify an object (using its name string) and check if the same code exists in SADX, where its symbol information can be taken from the 360 symbols.&lt;br /&gt;
# For all references to broken pointers in the object, attempt to find a working reference in a functional AutoDemo stage, such as Speed Highway.&lt;br /&gt;
# Replace the broken pointer with the working one.&lt;br /&gt;
All pointers were added to a spreadsheet along with their fixed version.&lt;br /&gt;
&lt;br /&gt;
For any code that didn&#039;t have a matching reference in the PC version or a functional Autodemo stage file, such as code for objects that didn&#039;t exist in the final game, the original byte difference method was used instead. Using Ghidra, the resulting pointer was checked to ensure it led to an appropriate address (The beginning of a function etc.). Any pointers &amp;quot;fixed&amp;quot; with this method were marked in the table as unsure.&lt;br /&gt;
&lt;br /&gt;
Stages that were similar enough to their final counterparts to share a lot of code (Twinkle Park, Lost World) were repaired first to build the database of known pointers, as stages with larger changes (Windy Valley) consisted almost entirely of code that didn&#039;t exist in the final game.&lt;br /&gt;
&lt;br /&gt;
The restoration was primarily discussed in a series of threads on x-hax Discord. An archive of the discussion will be available for download at a later date. &lt;br /&gt;
&lt;br /&gt;
== Restoration Details ==&lt;br /&gt;
&lt;br /&gt;
=== Stage Select ===&lt;br /&gt;
&lt;br /&gt;
=== Debug Functionality ===&lt;br /&gt;
&lt;br /&gt;
=== Ninja Lights ===&lt;br /&gt;
&lt;br /&gt;
=== Practice Stages ===&lt;br /&gt;
&#039;&#039;Speeps&#039;&#039;: It turned out Practice 1 could load by just removing its SET File (Object Layout) because it only references 1ST_READ through that.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;PkR&#039;&#039;: Practice 2 did not load because one of the meshes is too big for the game&#039;s [[Sonic Adventure/Lantern Engine|LANTERN lighting system]] to handle. However, it boots if [[Ninja Lights]] are used instead.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Autodemo Practice Stages&lt;br /&gt;
![[File:Sonic Adventure Autodemo Restoration 1772347046976.mp4|none|thumb|Gamma in Practice Stage (&#039;&#039;Speeps&#039;&#039;)]]&lt;br /&gt;
![[File:Pinball mode practice.mp4|thumb|Pinball mode in Practice Stage (&#039;&#039;MainJP&#039;&#039;)|none]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;nolines&amp;quot; caption=&amp;quot;Practice Stages with Ninja Lights (images by &#039;&#039;MainJP&#039;&#039;)&amp;quot;&amp;gt;&lt;br /&gt;
File:Practice.webp|alt=&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772203956319.png&lt;br /&gt;
File:Screenshot 2024-08-30 15-59-50.webp&lt;br /&gt;
File:Screenshot 2024-08-30 16-15-14.webp&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windy Valley ===&lt;br /&gt;
&lt;br /&gt;
=== Twinkle Park ===&lt;br /&gt;
&lt;br /&gt;
=== Sky Deck ===&lt;br /&gt;
&lt;br /&gt;
=== Lost World ===&lt;br /&gt;
&lt;br /&gt;
=== Casinopolis ===&lt;br /&gt;
&lt;br /&gt;
=== Station Square ===&lt;br /&gt;
&lt;br /&gt;
=== Mystic Ruins ===&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=703</id>
		<title>Sonic Adventure Autodemo/Restoration</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=703"/>
		<updated>2026-03-01T06:56:26Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is dedicated to projects that restore content and functionality in the Autodemo prototype of Sonic Adventure (Dreamcast). For Sonic Adventure PX (PC) mods that implement Autodemo features, see [[SADX Autodemo Mods|this page]] instead.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When the Sonic Adventure Autodemo was first dumped in 2013, it was soon discovered that it was a semi-functional build of the full game. The Autodemo was quickly hacked to unlock player controls and load stages manually so that they could be explored freely. However, many stages did not load because the binaries containing them were originally compiled for an older version of the game&#039;s main executable.&lt;br /&gt;
&lt;br /&gt;
The Autodemo has been researched ever since it was dumped, and the non-functional stages were eventually extracted using [[SA Tools]] and ported to the PC version. However, being able to play them in the Autodemo itself was desirable in order to see differences in the game&#039;s code, which couldn&#039;t be exported by the tools.&lt;br /&gt;
&lt;br /&gt;
Initial work on restoring Autodemo functionality ingame was done back in 2015, when the user &#039;&#039;evilhamwizard&#039;&#039; posted their findings in the [https://forums.sonicretro.org/posts/846056/ Autodemo discussion thread on Sonic Retro]. The work focused primarily on restoring the original Windy Valley, and a number of GIFs of the level running on the emulator [https://forums.sonicretro.org/posts/867245/ were posted in 2016]. Some updates were posted on booting Sky Deck as well.&lt;br /&gt;
&lt;br /&gt;
In 2024, based on &#039;&#039;evilhamwizard&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;s initial research, a new restoration project was started by [[x-hax]] (primarily by &#039;&#039;Speeps&#039;&#039;), aiming to make other stages bootable, as well as improving the original Windy Valley restoration. This restoration was achieved in 2024 through a collaboration of x-hax users and symbol information acquired from the leaked Xbox 360 SADX prototype. The project is [https://github.com/X-Hax/dreamcast-mods available as a GitHub repository].&lt;br /&gt;
&lt;br /&gt;
==Background and Method==&lt;br /&gt;
The files included on the Autodemo disc come from different builds of the game that were at different stages of development. When the Autodemo was put together, only the stages that were meant to be shown in the demo were recompiled, and the other stages were left over from older builds (for most of these, textures and lighting files were also missing). We can tell which binaries were recompiled by looking at file dates on the Autodemo GD-ROM. Only the files dated October 15 work ingame as-is, and other files cause the game to crash. The crash happens because the functions in the game&#039;s updated main binary (1ST_READ.BIN) are at different memory addresses from those expected by the code in stage binaries which were compiled for the older version of the game. &lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot;&lt;br /&gt;
!&#039;&#039;&#039;October 15, 1998 (working)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;October 7, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;September 24, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|STG01 (Emerald Coast)&lt;br /&gt;
|AL_GARDEN01 (Egg Carrier/Beta Windy Valley Chao Garden) &lt;br /&gt;
|STG00 (&amp;quot;Practice&amp;quot; Stages)&lt;br /&gt;
|-&lt;br /&gt;
|STG04 (Speed Highway)&lt;br /&gt;
|AL_GARDEN02 (Mystic Ruins Chao Garden)&lt;br /&gt;
|STG02 (Windy Valley)&lt;br /&gt;
|-&lt;br /&gt;
|STG05 (Red Mountain)&lt;br /&gt;
|AL_RACE (Chao Race)&lt;br /&gt;
|STG03 (Twinkle Park)&lt;br /&gt;
|-&lt;br /&gt;
|STG08 (Ice Cap)&lt;br /&gt;
|&lt;br /&gt;
|STG06 (Sky Deck)&lt;br /&gt;
|-&lt;br /&gt;
|STG10 (Final Egg)&lt;br /&gt;
|&lt;br /&gt;
|STG07 (Lost World)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00 (Station Square)&lt;br /&gt;
|&lt;br /&gt;
|STG09 (Casinopolis)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00OBJ (Station Square objects)&lt;br /&gt;
|&lt;br /&gt;
|ADV02 (Mystic Ruins)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0100 (Egg Carrier Outside)&lt;br /&gt;
|&lt;br /&gt;
|ADV02OBJ (Mystic Ruins objects)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0130 (Egg Carries Inside)&lt;br /&gt;
|&lt;br /&gt;
|SHOOTING (Sky Chase)&lt;br /&gt;
|-&lt;br /&gt;
|ADV01OBJ (Egg Carrier objects)&lt;br /&gt;
|&lt;br /&gt;
|MINICART (Twinkle Circuit)&lt;br /&gt;
|-&lt;br /&gt;
|AL_GARDEN00 (Station Square Chao Garden)&lt;br /&gt;
|&lt;br /&gt;
|B_E101_R (E-101 MK2)&lt;br /&gt;
|-&lt;br /&gt;
|AL_MAIN (Chao)&lt;br /&gt;
|&lt;br /&gt;
|B_ROBO (ZERO)&lt;br /&gt;
|-&lt;br /&gt;
|B_CHAOS2 (Chaos 2)&lt;br /&gt;
|&lt;br /&gt;
|B_EGM1 (Egg Hornet)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_EGM3 (Egg Viper)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|SBOARD (Sand Hill)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS0 (Chaos 0)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS4 (Chaos 4)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS6 (Chaos 6)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS7 (Perfect Chaos)&lt;br /&gt;
|}&lt;br /&gt;
However, as originally demonstrated by &#039;&#039;evilhamwizard&#039;&#039;, it’s possible to find the functions and data they were meant to point to by comparing the pointers to known functions and data between these files and the files that boot. In 2024, &#039;&#039;Speeps&#039;&#039; started putting together a new spreadsheet of known broken pointers and their correct counterparts. As the pointer list grew, more levels became functional when known pointers were replaced.&lt;br /&gt;
&lt;br /&gt;
Early hacks by &#039;&#039;Speeps&#039;&#039; were using simple patches to the executables applied through a hex editor. To facilitate mass pointer replacement and game testing, &#039;&#039;PkR&#039;&#039; reworked his SA1-DC-HD tool (originally meant to build GDIs of the final version of SA1 with enhancements) and created the [[Dreamcast Image Builder]]. The image builder uses a &amp;quot;mods&amp;quot; system that makes it easier to replace pointers, do all sorts of patching of game binaries and build a modified game image containing all of the selected hacks. In addition, some other tools on the [https://github.com/X-Hax/sa_tools_research SA Tools Research] repository were repurposed to find missing textures in the Autodemo by matching the names in the Autodemo’s texture lists against textures in the final version, the E3 build, the Autodemo Windy Valley mod for the PC version, where missing textures were recreated by its developers, and Dreamcast SDKs, which surprisingly have some early SA1 textures.&lt;br /&gt;
&lt;br /&gt;
Apart from making stages bootable, the mods include various experiments with controls, framerate, lighting, skipping the intro movie, adding textures that are missing on the disc, restoring debug functionality etc.&lt;br /&gt;
&lt;br /&gt;
The exact pointer matching procedure involved in stage restoration is as follows:&lt;br /&gt;
#Get the address of all pointers that read the stage&#039;s file from 1ST_READ. These are the Round Manager, Background Manager, Object List and Path List.&lt;br /&gt;
# Using IDA&#039;s graph view, gather all pointers to 1ST_READ (8Cxxxxxx).&lt;br /&gt;
# Using Ghidra, identify an object (using its name string) and check if the same code exists in SADX, where its symbol information can be taken from the 360 symbols.&lt;br /&gt;
# For all references to broken pointers in the object, attempt to find a working reference in a functional AutoDemo stage, such as Speed Highway.&lt;br /&gt;
# Replace the broken pointer with the working one.&lt;br /&gt;
All pointers were added to a spreadsheet along with their fixed version.&lt;br /&gt;
&lt;br /&gt;
For any code that didn&#039;t have a matching reference in the PC version or a functional Autodemo stage file, such as code for objects that didn&#039;t exist in the final game, the original byte difference method was used instead. Using Ghidra, the resulting pointer was checked to ensure it led to an appropriate address (The beginning of a function etc.). Any pointers &amp;quot;fixed&amp;quot; with this method were marked in the table as unsure.&lt;br /&gt;
&lt;br /&gt;
Stages that were similar enough to their final counterparts to share a lot of code (Twinkle Park, Lost World) were repaired first to build the database of known pointers, as stages with larger changes (Windy Valley) consisted almost entirely of code that didn&#039;t exist in the final game.&lt;br /&gt;
&lt;br /&gt;
The restoration was primarily discussed in a series of threads on x-hax Discord. An archive of the discussion will be available for download at a later date. &lt;br /&gt;
&lt;br /&gt;
== Restoration Details ==&lt;br /&gt;
&lt;br /&gt;
=== Stage Select ===&lt;br /&gt;
&lt;br /&gt;
=== Debug Functionality ===&lt;br /&gt;
&lt;br /&gt;
=== Ninja Lights ===&lt;br /&gt;
&lt;br /&gt;
=== Practice Stages ===&lt;br /&gt;
&#039;&#039;Speeps&#039;&#039;: It turned out Practice 1 could load by just removing its SET File (Object Layout) because it only references 1ST_READ through that.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;PkR&#039;&#039;: Practice 2 did not load because one of the meshes is too big for the game&#039;s [[Sonic Adventure/Lantern Engine|LANTERN lighting system]] to handle. However, it boots if [[Ninja Lights]] are used instead.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Autodemo Practice Stages&lt;br /&gt;
![[File:Sonic Adventure Autodemo Restoration 1772347046976.mp4|none|thumb|Gamma in Practice Stage (shared by &#039;&#039;Speeps&#039;&#039;)]]&lt;br /&gt;
![[File:Pinball mode practice.mp4|thumb|Pinball mode in Practice Stage (shared by &#039;&#039;MainJP&#039;&#039;)|none]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;nolines&amp;quot; caption=&amp;quot;Practice Stages with Ninja Lights (images by &#039;&#039;MainJP&#039;&#039;)&amp;quot;&amp;gt;&lt;br /&gt;
File:Practice.webp|alt=&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772203956319.png&lt;br /&gt;
File:Screenshot 2024-08-30 15-59-50.webp&lt;br /&gt;
File:Screenshot 2024-08-30 16-15-14.webp&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windy Valley ===&lt;br /&gt;
&lt;br /&gt;
=== Twinkle Park ===&lt;br /&gt;
&lt;br /&gt;
=== Sky Deck ===&lt;br /&gt;
&lt;br /&gt;
=== Lost World ===&lt;br /&gt;
&lt;br /&gt;
=== Casinopolis ===&lt;br /&gt;
&lt;br /&gt;
=== Station Square ===&lt;br /&gt;
&lt;br /&gt;
=== Mystic Ruins ===&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=702</id>
		<title>Sonic Adventure Autodemo/Restoration</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=702"/>
		<updated>2026-03-01T06:38:49Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is dedicated to projects that restore content and functionality in the Autodemo prototype of Sonic Adventure (Dreamcast). For Sonic Adventure PX (PC) mods that implement Autodemo features, see [[SADX Autodemo Mods|this page]] instead.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When the Sonic Adventure Autodemo was first dumped in 2013, it was soon discovered that it was a semi-functional build of the full game. The Autodemo was quickly hacked to unlock player controls and load stages manually so that they could be explored freely. However, many stages did not load because the binaries containing them were originally compiled for an older version of the game&#039;s main executable.&lt;br /&gt;
&lt;br /&gt;
The Autodemo has been researched ever since it was dumped, and the non-functional stages were eventually extracted using [[SA Tools]] and ported to the PC version. However, being able to play them in the Autodemo itself was desirable in order to see differences in the game&#039;s code, which couldn&#039;t be exported by the tools.&lt;br /&gt;
&lt;br /&gt;
Initial work on restoring Autodemo functionality ingame was done back in 2015, when the user &#039;&#039;evilhamwizard&#039;&#039; posted their findings in the [https://forums.sonicretro.org/posts/846056/ Autodemo discussion thread on Sonic Retro]. The work focused primarily on restoring the original Windy Valley, and a number of GIFs of the level running on the emulator [https://forums.sonicretro.org/posts/867245/ were posted in 2016]. Some updates were posted on booting Sky Deck as well.&lt;br /&gt;
&lt;br /&gt;
In 2024, based on &#039;&#039;evilhamwizard&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;s initial research, a new restoration project was started by [[x-hax]] (primarily by &#039;&#039;Speeps&#039;&#039;), aiming to make other stages bootable, as well as improving the original Windy Valley restoration. This restoration was achieved in 2024 through a collaboration of x-hax users and symbol information acquired from the leaked Xbox 360 SADX prototype. The project is [https://github.com/X-Hax/dreamcast-mods available as a GitHub repository].&lt;br /&gt;
&lt;br /&gt;
==Background and Method==&lt;br /&gt;
The files included on the Autodemo disc come from different builds of the game that were at different stages of development. When the Autodemo was put together, only the stages that were meant to be shown in the demo were recompiled, and the other stages were left over from older builds (for most of these, textures and lighting files were also missing). We can tell which binaries were recompiled by looking at file dates on the Autodemo GD-ROM. Only the files dated October 15 work ingame as-is, and other files cause the game to crash. The crash happens because the functions in the game&#039;s updated main binary (1ST_READ.BIN) are at different memory addresses from those expected by the code in stage binaries which were compiled for the older version of the game. &lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot;&lt;br /&gt;
!&#039;&#039;&#039;October 15, 1998 (working)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;October 7, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;September 24, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|STG01 (Emerald Coast)&lt;br /&gt;
|AL_GARDEN01 (Egg Carrier/Beta Windy Valley Chao Garden) &lt;br /&gt;
|STG00 (&amp;quot;Practice&amp;quot; Stages)&lt;br /&gt;
|-&lt;br /&gt;
|STG04 (Speed Highway)&lt;br /&gt;
|AL_GARDEN02 (Mystic Ruins Chao Garden)&lt;br /&gt;
|STG02 (Windy Valley)&lt;br /&gt;
|-&lt;br /&gt;
|STG05 (Red Mountain)&lt;br /&gt;
|AL_RACE (Chao Race)&lt;br /&gt;
|STG03 (Twinkle Park)&lt;br /&gt;
|-&lt;br /&gt;
|STG08 (Ice Cap)&lt;br /&gt;
|&lt;br /&gt;
|STG06 (Sky Deck)&lt;br /&gt;
|-&lt;br /&gt;
|STG10 (Final Egg)&lt;br /&gt;
|&lt;br /&gt;
|STG07 (Lost World)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00 (Station Square)&lt;br /&gt;
|&lt;br /&gt;
|STG09 (Casinopolis)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00OBJ (Station Square objects)&lt;br /&gt;
|&lt;br /&gt;
|ADV02 (Mystic Ruins)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0100 (Egg Carrier Outside)&lt;br /&gt;
|&lt;br /&gt;
|ADV02OBJ (Mystic Ruins objects)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0130 (Egg Carries Inside)&lt;br /&gt;
|&lt;br /&gt;
|SHOOTING (Sky Chase)&lt;br /&gt;
|-&lt;br /&gt;
|ADV01OBJ (Egg Carrier objects)&lt;br /&gt;
|&lt;br /&gt;
|MINICART (Twinkle Circuit)&lt;br /&gt;
|-&lt;br /&gt;
|AL_GARDEN00 (Station Square Chao Garden)&lt;br /&gt;
|&lt;br /&gt;
|B_E101_R (E-101 MK2)&lt;br /&gt;
|-&lt;br /&gt;
|AL_MAIN (Chao)&lt;br /&gt;
|&lt;br /&gt;
|B_ROBO (ZERO)&lt;br /&gt;
|-&lt;br /&gt;
|B_CHAOS2 (Chaos 2)&lt;br /&gt;
|&lt;br /&gt;
|B_EGM1 (Egg Hornet)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_EGM3 (Egg Viper)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|SBOARD (Sand Hill)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS0 (Chaos 0)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS4 (Chaos 4)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS6 (Chaos 6)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS7 (Perfect Chaos)&lt;br /&gt;
|}&lt;br /&gt;
However, as originally demonstrated by &#039;&#039;evilhamwizard&#039;&#039;, it’s possible to find the functions and data they were meant to point to by comparing the pointers to known functions and data between these files and the files that boot. In 2024, &#039;&#039;Speeps&#039;&#039; started putting together a new spreadsheet of known broken pointers and their correct counterparts. As the pointer list grew, more levels became functional when known pointers were replaced.&lt;br /&gt;
&lt;br /&gt;
Early hacks by &#039;&#039;Speeps&#039;&#039; were using simple patches to the executables applied through a hex editor. To facilitate mass pointer replacement and game testing, &#039;&#039;PkR&#039;&#039; reworked his SA1-DC-HD tool (originally meant to build GDIs of the final version of SA1 with enhancements) and created the [[Dreamcast Image Builder]]. The image builder uses a &amp;quot;mods&amp;quot; system that makes it easier to replace pointers, do all sorts of patching of game binaries and build a modified game image containing all of the selected hacks. In addition, some other tools on the [https://github.com/X-Hax/sa_tools_research SA Tools Research] repository were repurposed to find missing textures in the Autodemo by matching the names in the Autodemo’s texture lists against textures in the final version, the E3 build, the Autodemo Windy Valley mod for the PC version, where missing textures were recreated by its developers, and Dreamcast SDKs, which surprisingly have some early SA1 textures.&lt;br /&gt;
&lt;br /&gt;
Apart from making stages bootable, the mods include various experiments with controls, framerate, lighting, skipping the intro movie, adding textures that are missing on the disc, restoring debug functionality etc.&lt;br /&gt;
&lt;br /&gt;
The exact pointer matching procedure involved in stage restoration is as follows:&lt;br /&gt;
#Get the address of all pointers that read the stage&#039;s file from 1ST_READ. These are the Round Manager, Background Manager, Object List and Path List.&lt;br /&gt;
# Using IDA&#039;s graph view, gather all pointers to 1ST_READ (8Cxxxxxx).&lt;br /&gt;
# Using Ghidra, identify an object (using its name string) and check if the same code exists in SADX, where its symbol information can be taken from the 360 symbols.&lt;br /&gt;
# For all references to broken pointers in the object, attempt to find a working reference in a functional AutoDemo stage, such as Speed Highway.&lt;br /&gt;
# Replace the broken pointer with the working one.&lt;br /&gt;
All pointers were added to a spreadsheet along with their fixed version.&lt;br /&gt;
&lt;br /&gt;
For any code that didn&#039;t have a matching reference in the PC version or a functional Autodemo stage file, such as code for objects that didn&#039;t exist in the final game, the original byte difference method was used instead. Using Ghidra, the resulting pointer was checked to ensure it led to an appropriate address (The beginning of a function etc.). Any pointers &amp;quot;fixed&amp;quot; with this method were marked in the table as unsure.&lt;br /&gt;
&lt;br /&gt;
Stages that were similar enough to their final counterparts to share a lot of code (Twinkle Park, Lost World) were repaired first to build the database of known pointers, as stages with larger changes (Windy Valley) consisted almost entirely of code that didn&#039;t exist in the final game.&lt;br /&gt;
&lt;br /&gt;
The restoration was primarily discussed in a series of threads on x-hax Discord. An archive of the discussion will be available for download at a later date. &lt;br /&gt;
&lt;br /&gt;
== Restoration Details ==&lt;br /&gt;
&lt;br /&gt;
=== Stage Select ===&lt;br /&gt;
&lt;br /&gt;
=== Debug Functionality ===&lt;br /&gt;
&lt;br /&gt;
=== Ninja Lights ===&lt;br /&gt;
&lt;br /&gt;
=== Practice Stages ===&lt;br /&gt;
&#039;&#039;Speeps&#039;&#039;: It turned out Practice 1 could load by just removing its SET File (Object Layout) because it only references 1ST_READ through that.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;PkR&#039;&#039;: Practice 2 did not load because one of the meshes is too big for the game&#039;s [[Sonic Adventure/Lantern Engine|LANTERN lighting system]] to handle. However, it boots if [[Ninja Lights]] are used instead.&lt;br /&gt;
[[File:Sonic Adventure Autodemo Restoration 1772347046976.mp4|none|thumb|Gamma in Practice Stage (shared by &#039;&#039;Speeps&#039;&#039;)]]&lt;br /&gt;
[[File:Pinball mode practice.mp4|thumb|Pinball mode in Practice Stage (shared by &#039;&#039;MainJP&#039;&#039;)|none]]&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;nolines&amp;quot; caption=&amp;quot;Practice Stages with Ninja Lights (images by &#039;&#039;MainJP&#039;&#039;)&amp;quot;&amp;gt;&lt;br /&gt;
File:Practice.webp|alt=&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772203956319.png&lt;br /&gt;
File:Screenshot 2024-08-30 15-59-50.webp&lt;br /&gt;
File:Screenshot 2024-08-30 16-15-14.webp&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windy Valley ===&lt;br /&gt;
&lt;br /&gt;
=== Twinkle Park ===&lt;br /&gt;
&lt;br /&gt;
=== Sky Deck ===&lt;br /&gt;
&lt;br /&gt;
=== Lost World ===&lt;br /&gt;
&lt;br /&gt;
=== Casinopolis ===&lt;br /&gt;
&lt;br /&gt;
=== Station Square ===&lt;br /&gt;
&lt;br /&gt;
=== Mystic Ruins ===&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:Sonic_Adventure_Autodemo_Restoration_1772347046976.mp4&amp;diff=701</id>
		<title>File:Sonic Adventure Autodemo Restoration 1772347046976.mp4</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:Sonic_Adventure_Autodemo_Restoration_1772347046976.mp4&amp;diff=701"/>
		<updated>2026-03-01T06:37:32Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=700</id>
		<title>Sonic Adventure Autodemo/Restoration</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=700"/>
		<updated>2026-03-01T06:35:07Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is dedicated to projects that restore content and functionality in the Autodemo prototype of Sonic Adventure (Dreamcast). For Sonic Adventure PX (PC) mods that implement Autodemo features, see [[SADX Autodemo Mods|this page]] instead.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When the Sonic Adventure Autodemo was first dumped in 2013, it was soon discovered that it was a semi-functional build of the full game. The Autodemo was quickly hacked to unlock player controls and load stages manually so that they could be explored freely. However, many stages did not load because the binaries containing them were originally compiled for an older version of the game&#039;s main executable.&lt;br /&gt;
&lt;br /&gt;
The Autodemo has been researched ever since it was dumped, and the non-functional stages were eventually extracted using [[SA Tools]] and ported to the PC version. However, being able to play them in the Autodemo itself was desirable in order to see differences in the game&#039;s code, which couldn&#039;t be exported by the tools.&lt;br /&gt;
&lt;br /&gt;
Initial work on restoring Autodemo functionality ingame was done back in 2015, when the user &#039;&#039;evilhamwizard&#039;&#039; posted their findings in the [https://forums.sonicretro.org/posts/846056/ Autodemo discussion thread on Sonic Retro]. The work focused primarily on restoring the original Windy Valley, and a number of GIFs of the level running on the emulator [https://forums.sonicretro.org/posts/867245/ were posted in 2016]. Some updates were posted on booting Sky Deck as well.&lt;br /&gt;
&lt;br /&gt;
In 2024, based on &#039;&#039;evilhamwizard&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;s initial research, a new restoration project was started by [[x-hax]] (primarily by &#039;&#039;Speeps&#039;&#039;), aiming to make other stages bootable, as well as improving the original Windy Valley restoration. This restoration was achieved in 2024 through a collaboration of x-hax users and symbol information acquired from the leaked Xbox 360 SADX prototype. The project is [https://github.com/X-Hax/dreamcast-mods available as a GitHub repository].&lt;br /&gt;
&lt;br /&gt;
==Background and Method==&lt;br /&gt;
The files included on the Autodemo disc come from different builds of the game that were at different stages of development. When the Autodemo was put together, only the stages that were meant to be shown in the demo were recompiled, and the other stages were left over from older builds (for most of these, textures and lighting files were also missing). We can tell which binaries were recompiled by looking at file dates on the Autodemo GD-ROM. Only the files dated October 15 work ingame as-is, and other files cause the game to crash. The crash happens because the functions in the game&#039;s updated main binary (1ST_READ.BIN) are at different memory addresses from those expected by the code in stage binaries which were compiled for the older version of the game. &lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot;&lt;br /&gt;
!&#039;&#039;&#039;October 15, 1998 (working)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;October 7, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;September 24, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|STG01 (Emerald Coast)&lt;br /&gt;
|AL_GARDEN01 (Egg Carrier/Beta Windy Valley Chao Garden) &lt;br /&gt;
|STG00 (&amp;quot;Practice&amp;quot; Stages)&lt;br /&gt;
|-&lt;br /&gt;
|STG04 (Speed Highway)&lt;br /&gt;
|AL_GARDEN02 (Mystic Ruins Chao Garden)&lt;br /&gt;
|STG02 (Windy Valley)&lt;br /&gt;
|-&lt;br /&gt;
|STG05 (Red Mountain)&lt;br /&gt;
|AL_RACE (Chao Race)&lt;br /&gt;
|STG03 (Twinkle Park)&lt;br /&gt;
|-&lt;br /&gt;
|STG08 (Ice Cap)&lt;br /&gt;
|&lt;br /&gt;
|STG06 (Sky Deck)&lt;br /&gt;
|-&lt;br /&gt;
|STG10 (Final Egg)&lt;br /&gt;
|&lt;br /&gt;
|STG07 (Lost World)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00 (Station Square)&lt;br /&gt;
|&lt;br /&gt;
|STG09 (Casinopolis)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00OBJ (Station Square objects)&lt;br /&gt;
|&lt;br /&gt;
|ADV02 (Mystic Ruins)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0100 (Egg Carrier Outside)&lt;br /&gt;
|&lt;br /&gt;
|ADV02OBJ (Mystic Ruins objects)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0130 (Egg Carries Inside)&lt;br /&gt;
|&lt;br /&gt;
|SHOOTING (Sky Chase)&lt;br /&gt;
|-&lt;br /&gt;
|ADV01OBJ (Egg Carrier objects)&lt;br /&gt;
|&lt;br /&gt;
|MINICART (Twinkle Circuit)&lt;br /&gt;
|-&lt;br /&gt;
|AL_GARDEN00 (Station Square Chao Garden)&lt;br /&gt;
|&lt;br /&gt;
|B_E101_R (E-101 MK2)&lt;br /&gt;
|-&lt;br /&gt;
|AL_MAIN (Chao)&lt;br /&gt;
|&lt;br /&gt;
|B_ROBO (ZERO)&lt;br /&gt;
|-&lt;br /&gt;
|B_CHAOS2 (Chaos 2)&lt;br /&gt;
|&lt;br /&gt;
|B_EGM1 (Egg Hornet)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_EGM3 (Egg Viper)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|SBOARD (Sand Hill)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS0 (Chaos 0)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS4 (Chaos 4)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS6 (Chaos 6)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS7 (Perfect Chaos)&lt;br /&gt;
|}&lt;br /&gt;
However, as originally demonstrated by &#039;&#039;evilhamwizard&#039;&#039;, it’s possible to find the functions and data they were meant to point to by comparing the pointers to known functions and data between these files and the files that boot. In 2024, &#039;&#039;Speeps&#039;&#039; started putting together a new spreadsheet of known broken pointers and their correct counterparts. As the pointer list grew, more levels became functional when known pointers were replaced.&lt;br /&gt;
&lt;br /&gt;
Early hacks by &#039;&#039;Speeps&#039;&#039; were using simple patches to the executables applied through a hex editor. To facilitate mass pointer replacement and game testing, &#039;&#039;PkR&#039;&#039; reworked his SA1-DC-HD tool (originally meant to build GDIs of the final version of SA1 with enhancements) and created the [[Dreamcast Image Builder]]. The image builder uses a &amp;quot;mods&amp;quot; system that makes it easier to replace pointers, do all sorts of patching of game binaries and build a modified game image containing all of the selected hacks. In addition, some other tools on the [https://github.com/X-Hax/sa_tools_research SA Tools Research] repository were repurposed to find missing textures in the Autodemo by matching the names in the Autodemo’s texture lists against textures in the final version, the E3 build, the Autodemo Windy Valley mod for the PC version, where missing textures were recreated by its developers, and Dreamcast SDKs, which surprisingly have some early SA1 textures.&lt;br /&gt;
&lt;br /&gt;
Apart from making stages bootable, the mods include various experiments with controls, framerate, lighting, skipping the intro movie, adding textures that are missing on the disc, restoring debug functionality etc.&lt;br /&gt;
&lt;br /&gt;
The exact pointer matching procedure involved in stage restoration is as follows:&lt;br /&gt;
#Get the address of all pointers that read the stage&#039;s file from 1ST_READ. These are the Round Manager, Background Manager, Object List and Path List.&lt;br /&gt;
# Using IDA&#039;s graph view, gather all pointers to 1ST_READ (8Cxxxxxx).&lt;br /&gt;
# Using Ghidra, identify an object (using its name string) and check if the same code exists in SADX, where its symbol information can be taken from the 360 symbols.&lt;br /&gt;
# For all references to broken pointers in the object, attempt to find a working reference in a functional AutoDemo stage, such as Speed Highway.&lt;br /&gt;
# Replace the broken pointer with the working one.&lt;br /&gt;
All pointers were added to a spreadsheet along with their fixed version.&lt;br /&gt;
&lt;br /&gt;
For any code that didn&#039;t have a matching reference in the PC version or a functional Autodemo stage file, such as code for objects that didn&#039;t exist in the final game, the original byte difference method was used instead. Using Ghidra, the resulting pointer was checked to ensure it led to an appropriate address (The beginning of a function etc.). Any pointers &amp;quot;fixed&amp;quot; with this method were marked in the table as unsure.&lt;br /&gt;
&lt;br /&gt;
Stages that were similar enough to their final counterparts to share a lot of code (Twinkle Park, Lost World) were repaired first to build the database of known pointers, as stages with larger changes (Windy Valley) consisted almost entirely of code that didn&#039;t exist in the final game.&lt;br /&gt;
&lt;br /&gt;
The restoration was primarily discussed in a series of threads on x-hax Discord. An archive of the discussion will be available for download at a later date. &lt;br /&gt;
&lt;br /&gt;
== Restoration Details ==&lt;br /&gt;
&lt;br /&gt;
=== Stage Select ===&lt;br /&gt;
&lt;br /&gt;
=== Debug Functionality ===&lt;br /&gt;
&lt;br /&gt;
=== Ninja Lights ===&lt;br /&gt;
&lt;br /&gt;
=== Practice Stages ===&lt;br /&gt;
It turned out Practice 1 could load by just removing its SET File (Object Layout) because it only references 1ST_READ through that.&lt;br /&gt;
&lt;br /&gt;
Practice 2 does not load because one of the meshes is too big for the game&#039;s [[Sonic Adventure/Lantern Engine|LANTERN lighting system]] to handle. However, it boots if [[Sonic Adventure/Ninja Lights|Ninja Lights]] are used instead.&lt;br /&gt;
[[File:Pinball mode practice.mp4|thumb|Pinball mode in Practice Stage (shared by &#039;&#039;MainJP&#039;&#039;)|none]]&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;nolines&amp;quot; caption=&amp;quot;Practice Stages with Ninja Lights (images by &#039;&#039;MainJP&#039;&#039;)&amp;quot;&amp;gt;&lt;br /&gt;
File:Practice.webp|alt=&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772203956319.png&lt;br /&gt;
File:Screenshot 2024-08-30 15-59-50.webp&lt;br /&gt;
File:Screenshot 2024-08-30 16-15-14.webp&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windy Valley ===&lt;br /&gt;
&lt;br /&gt;
=== Twinkle Park ===&lt;br /&gt;
&lt;br /&gt;
=== Sky Deck ===&lt;br /&gt;
&lt;br /&gt;
=== Lost World ===&lt;br /&gt;
&lt;br /&gt;
=== Casinopolis ===&lt;br /&gt;
&lt;br /&gt;
=== Station Square ===&lt;br /&gt;
&lt;br /&gt;
=== Mystic Ruins ===&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=699</id>
		<title>Sonic Adventure Autodemo/Restoration</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=699"/>
		<updated>2026-03-01T06:34:39Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is dedicated to projects that restore content and functionality in the Autodemo prototype of Sonic Adventure (Dreamcast). For Sonic Adventure PX (PC) mods that implement Autodemo features, see [[SADX Autodemo Mods|this page]] instead.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When the Sonic Adventure Autodemo was first dumped in 2013, it was soon discovered that it was a semi-functional build of the full game. The Autodemo was quickly hacked to unlock player controls and load stages manually so that they could be explored freely. However, many stages did not load because the binaries containing them were originally compiled for an older version of the game&#039;s main executable.&lt;br /&gt;
&lt;br /&gt;
The Autodemo has been researched ever since it was dumped, and the non-functional stages were eventually extracted using [[SA Tools]] and ported to the PC version. However, being able to play them in the Autodemo itself was desirable in order to see differences in the game&#039;s code, which couldn&#039;t be exported by the tools.&lt;br /&gt;
&lt;br /&gt;
Initial work on restoring Autodemo functionality ingame was done back in 2015, when the user &#039;&#039;evilhamwizard&#039;&#039; posted their findings in the [https://forums.sonicretro.org/posts/846056/ Autodemo discussion thread on Sonic Retro]. The work focused primarily on restoring the original Windy Valley, and a number of GIFs of the level running on the emulator [https://forums.sonicretro.org/posts/867245/ were posted in 2016]. Some updates were posted on booting Sky Deck as well.&lt;br /&gt;
&lt;br /&gt;
In 2024, based on &#039;&#039;evilhamwizard&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;s initial research, a new restoration project was started by [[x-hax]] (primarily by &#039;&#039;Speeps&#039;&#039;), aiming to make other stages bootable, as well as improving the original Windy Valley restoration. This restoration was achieved in 2024 through a collaboration of x-hax users and symbol information acquired from the leaked Xbox 360 SADX prototype. The project is [https://github.com/X-Hax/dreamcast-mods available as a GitHub repository].&lt;br /&gt;
&lt;br /&gt;
==Background and Method==&lt;br /&gt;
The files included on the Autodemo disc come from different builds of the game that were at different stages of development. When the Autodemo was put together, only the stages that were meant to be shown in the demo were recompiled, and the other stages were left over from older builds (for most of these, textures and lighting files were also missing). We can tell which binaries were recompiled by looking at file dates on the Autodemo GD-ROM. Only the files dated October 15 work ingame as-is, and other files cause the game to crash. The crash happens because the functions in the game&#039;s updated main binary (1ST_READ.BIN) are at different memory addresses from those expected by the code in stage binaries which were compiled for the older version of the game. &lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot;&lt;br /&gt;
!&#039;&#039;&#039;October 15, 1998 (working)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;October 7, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;September 24, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|STG01 (Emerald Coast)&lt;br /&gt;
|AL_GARDEN01 (Egg Carrier/Beta Windy Valley Chao Garden) &lt;br /&gt;
|STG00 (&amp;quot;Practice&amp;quot; Stages)&lt;br /&gt;
|-&lt;br /&gt;
|STG04 (Speed Highway)&lt;br /&gt;
|AL_GARDEN02 (Mystic Ruins Chao Garden)&lt;br /&gt;
|STG02 (Windy Valley)&lt;br /&gt;
|-&lt;br /&gt;
|STG05 (Red Mountain)&lt;br /&gt;
|AL_RACE (Chao Race)&lt;br /&gt;
|STG03 (Twinkle Park)&lt;br /&gt;
|-&lt;br /&gt;
|STG08 (Ice Cap)&lt;br /&gt;
|&lt;br /&gt;
|STG06 (Sky Deck)&lt;br /&gt;
|-&lt;br /&gt;
|STG10 (Final Egg)&lt;br /&gt;
|&lt;br /&gt;
|STG07 (Lost World)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00 (Station Square)&lt;br /&gt;
|&lt;br /&gt;
|STG09 (Casinopolis)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00OBJ (Station Square objects)&lt;br /&gt;
|&lt;br /&gt;
|ADV02 (Mystic Ruins)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0100 (Egg Carrier Outside)&lt;br /&gt;
|&lt;br /&gt;
|ADV02OBJ (Mystic Ruins objects)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0130 (Egg Carries Inside)&lt;br /&gt;
|&lt;br /&gt;
|SHOOTING (Sky Chase)&lt;br /&gt;
|-&lt;br /&gt;
|ADV01OBJ (Egg Carrier objects)&lt;br /&gt;
|&lt;br /&gt;
|MINICART (Twinkle Circuit)&lt;br /&gt;
|-&lt;br /&gt;
|AL_GARDEN00 (Station Square Chao Garden)&lt;br /&gt;
|&lt;br /&gt;
|B_E101_R (E-101 MK2)&lt;br /&gt;
|-&lt;br /&gt;
|AL_MAIN (Chao)&lt;br /&gt;
|&lt;br /&gt;
|B_ROBO (ZERO)&lt;br /&gt;
|-&lt;br /&gt;
|B_CHAOS2 (Chaos 2)&lt;br /&gt;
|&lt;br /&gt;
|B_EGM1 (Egg Hornet)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_EGM3 (Egg Viper)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|SBOARD (Sand Hill)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS0 (Chaos 0)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS4 (Chaos 4)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS6 (Chaos 6)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS7 (Perfect Chaos)&lt;br /&gt;
|}&lt;br /&gt;
However, as originally demonstrated by &#039;&#039;evilhamwizard&#039;&#039;, it’s possible to find the functions and data they were meant to point to by comparing the pointers to known functions and data between these files and the files that boot. In 2024, &#039;&#039;Speeps&#039;&#039; started putting together a new spreadsheet of known broken pointers and their correct counterparts. As the pointer list grew, more levels became functional when known pointers were replaced.&lt;br /&gt;
&lt;br /&gt;
Early hacks by &#039;&#039;Speeps&#039;&#039; were using simple patches to the executables applied through a hex editor. To facilitate mass pointer replacement and game testing, &#039;&#039;PkR&#039;&#039; reworked his SA1-DC-HD tool (originally meant to build GDIs of the final version of SA1 with enhancements) and created the [[Dreamcast Image Builder]]. The image builder uses a &amp;quot;mods&amp;quot; system that makes it easier to replace pointers, do all sorts of patching of game binaries and build a modified game image containing all of the selected hacks. In addition, some other tools on the [https://github.com/X-Hax/sa_tools_research SA Tools Research] repository were repurposed to find missing textures in the Autodemo by matching the names in the Autodemo’s texture lists against textures in the final version, the E3 build, the Autodemo Windy Valley mod for the PC version, where missing textures were recreated by its developers, and Dreamcast SDKs, which surprisingly have some early SA1 textures.&lt;br /&gt;
&lt;br /&gt;
Apart from making stages bootable, the mods include various experiments with controls, framerate, lighting, skipping the intro movie, adding textures that are missing on the disc, restoring debug functionality etc.&lt;br /&gt;
&lt;br /&gt;
The exact pointer matching procedure involved in stage restoration is as follows:&lt;br /&gt;
#Get the address of all pointers that read the stage&#039;s file from 1ST_READ. These are the Round Manager, Background Manager, Object List and Path List.&lt;br /&gt;
# Using IDA&#039;s graph view, gather all pointers to 1ST_READ (8Cxxxxxx).&lt;br /&gt;
# Using Ghidra, identify an object (using its name string) and check if the same code exists in SADX, where its symbol information can be taken from the 360 symbols.&lt;br /&gt;
# For all references to broken pointers in the object, attempt to find a working reference in a functional AutoDemo stage, such as Speed Highway.&lt;br /&gt;
# Replace the broken pointer with the working one.&lt;br /&gt;
All pointers were added to a spreadsheet along with their fixed version.&lt;br /&gt;
&lt;br /&gt;
For any code that didn&#039;t have a matching reference in the PC version or a functional Autodemo stage file, such as code for objects that didn&#039;t exist in the final game, the original byte difference method was used instead. Using Ghidra, the resulting pointer was checked to ensure it led to an appropriate address (The beginning of a function etc.). Any pointers &amp;quot;fixed&amp;quot; with this method were marked in the table as unsure.&lt;br /&gt;
&lt;br /&gt;
Stages that were similar enough to their final counterparts to share a lot of code (Twinkle Park, Lost World) were repaired first to build the database of known pointers, as stages with larger changes (Windy Valley) consisted almost entirely of code that didn&#039;t exist in the final game.&lt;br /&gt;
&lt;br /&gt;
The restoration was primarily discussed in a series of threads on x-hax Discord. An archive of the discussion will be available for download at a later date. &lt;br /&gt;
&lt;br /&gt;
== Restoration Details ==&lt;br /&gt;
&lt;br /&gt;
=== Stage Select ===&lt;br /&gt;
&lt;br /&gt;
=== Debug Functionality ===&lt;br /&gt;
&lt;br /&gt;
=== Ninja Lights ===&lt;br /&gt;
&lt;br /&gt;
=== Practice Stages ===&lt;br /&gt;
It turned out Practice 1 could load by just removing its SET File (Object Layout) because it only references 1ST_READ through that.&lt;br /&gt;
&lt;br /&gt;
Practice 2 does not load because one of the meshes is too big for the game&#039;s [[Sonic Adventure/Lantern Engine|LANTERN lighting system]] to handle. However, it boots if [[Sonic Adventure/Ninja Lights|Ninja Lights]] are used instead.&lt;br /&gt;
[[File:Pinball mode practice.mp4|thumb|left|Pinball mode in Practice Stage (shared by &#039;&#039;MainJP&#039;&#039;)]]&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;nolines&amp;quot; caption=&amp;quot;Practice Stages with Ninja Lights (images by &#039;&#039;MainJP&#039;&#039;)&amp;quot;&amp;gt;&lt;br /&gt;
File:Practice.webp|alt=&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772203956319.png&lt;br /&gt;
File:Screenshot 2024-08-30 15-59-50.webp&lt;br /&gt;
File:Screenshot 2024-08-30 16-15-14.webp&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windy Valley ===&lt;br /&gt;
&lt;br /&gt;
=== Twinkle Park ===&lt;br /&gt;
&lt;br /&gt;
=== Sky Deck ===&lt;br /&gt;
&lt;br /&gt;
=== Lost World ===&lt;br /&gt;
&lt;br /&gt;
=== Casinopolis ===&lt;br /&gt;
&lt;br /&gt;
=== Station Square ===&lt;br /&gt;
&lt;br /&gt;
=== Mystic Ruins ===&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:SAAD_CurrentMRTextureWork.mp4&amp;diff=698</id>
		<title>File:SAAD CurrentMRTextureWork.mp4</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:SAAD_CurrentMRTextureWork.mp4&amp;diff=698"/>
		<updated>2026-03-01T05:52:22Z</updated>

		<summary type="html">&lt;p&gt;PkR: Created blank page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:2025-12-14_13-49-20.mp4&amp;diff=697</id>
		<title>File:2025-12-14 13-49-20.mp4</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:2025-12-14_13-49-20.mp4&amp;diff=697"/>
		<updated>2026-03-01T05:51:47Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:2024-07-27_14-59-17.mp4&amp;diff=696</id>
		<title>File:2024-07-27 14-59-17.mp4</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:2024-07-27_14-59-17.mp4&amp;diff=696"/>
		<updated>2026-03-01T05:50:40Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:SAAD_BGMCasinopolis_edit.mp4&amp;diff=695</id>
		<title>File:SAAD BGMCasinopolis edit.mp4</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:SAAD_BGMCasinopolis_edit.mp4&amp;diff=695"/>
		<updated>2026-03-01T05:50:10Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:2024-07-16_22-31-49.mp4&amp;diff=694</id>
		<title>File:2024-07-16 22-31-49.mp4</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:2024-07-16_22-31-49.mp4&amp;diff=694"/>
		<updated>2026-03-01T05:50:02Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:2026-01-18_07-38-23_edit.mp4&amp;diff=693</id>
		<title>File:2026-01-18 07-38-23 edit.mp4</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:2026-01-18_07-38-23_edit.mp4&amp;diff=693"/>
		<updated>2026-03-01T05:49:38Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:2024-06-18_10-59-18_edit.mp4&amp;diff=692</id>
		<title>File:2024-06-18 10-59-18 edit.mp4</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:2024-06-18_10-59-18_edit.mp4&amp;diff=692"/>
		<updated>2026-03-01T05:49:17Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Ninja_Lights&amp;diff=691</id>
		<title>Ninja Lights</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Ninja_Lights&amp;diff=691"/>
		<updated>2026-03-01T03:10:20Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;quot;Ninja Lights&amp;quot; refers to the lighting used by the Ninja library of the [[Katana SDK]].&lt;br /&gt;
&lt;br /&gt;
== Ninja Lights in Sonic Adventure ==&lt;br /&gt;
&#039;&#039;&#039;Note: Ninja Lights are not implemented in the Lantern Engine mod, so the information below is irrelevant to the PC version.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sonic Adventure (Dreamcast) uses two lighting systems: the palette-based [[Sonic Adventure/Lantern Engine|LANTERN system]] and the Ninja Lights. The game&#039;s model rendering functions have &amp;quot;Lantern&amp;quot; and &amp;quot;Ninja&amp;quot; variants, and depending on the function used the game can either draw the model with palette lighting or use Ninja Lights.&lt;br /&gt;
&lt;br /&gt;
The SL file contains data for setting up the Ninja lights. This information consists of: light color (three floats for R/G/B), diffuse multiplier, specular power and ambient multiplier. Both diffuse and specular components are the same color. The “ignore specular” material flag disables the specular component per mesh.&lt;br /&gt;
&lt;br /&gt;
=== Types of Ninja Lights Setup ===&lt;br /&gt;
There are three types of lights used for non-palettized models in the game:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Lighting Setup&lt;br /&gt;
!Description&lt;br /&gt;
!Used by&lt;br /&gt;
|-&lt;br /&gt;
|Two Ninja Lights&lt;br /&gt;
|Non-palettized lighting that uses two Ninja Lights. These lights use &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; structures described in the Katana SDK. One is set up using the parameters in the SL file (let’s call it the &amp;lt;code&amp;gt;ENV&amp;lt;/code&amp;gt; Light), and the other is set up in code, usually in level binaries (let’s call it the &amp;lt;code&amp;gt;DIR&amp;lt;/code&amp;gt; light). The &amp;lt;code&amp;gt;ENV&amp;lt;/code&amp;gt; light has one configurable color that is shared for diffuse and specular, the &amp;lt;code&amp;gt;DIR&amp;lt;/code&amp;gt; light can have different diffuse and specular color (though the game doesn’t seem to use that). It can also have a different light direction.&lt;br /&gt;
|Common switch, Hint monitor, OEggKanban (glowing Eggman logo in Final Egg, tube parts only), Chaos puddle in some cutscenes, Aoki Switch (top)&lt;br /&gt;
|-&lt;br /&gt;
|Simple Ninja Light&lt;br /&gt;
|Non-palettized lighting that uses one Ninja Light using the parameters from the SL file except the color, which is always white.&lt;br /&gt;
|Rock bits in Red Mountain, non-Jewel Chao, Master Emerald pieces, Froggy in Gamma’s Emerald Coast&lt;br /&gt;
|-&lt;br /&gt;
|Easy Light&lt;br /&gt;
|Non-palettized lighting that sets up the Easy Light (not &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;) using the parameters from the SL file. The Easy light is described in the Katana SDK. It doesn’t support specular lighting.&lt;br /&gt;
|Snowboard, OSandSwitch (Sand Hill switch), shadow blob, Chambr (chambers with opening doors in Sky Deck), debug objects, Aoki Switch (bottom), E101’s missiles, Hedgehog Hammer targets&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rendering Functions and their SADX Counterparts ===&lt;br /&gt;
In SA1, most models were rendered with palette lighting using the game&#039;s custom function, but some models were rendered by calling Ninja drawing functions directly, which made them use the Ninja lights system. There are three light setups depending on the specific variation of the Ninja draw function:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Light setup&lt;br /&gt;
!Functions in SADX (PC, 2004)&lt;br /&gt;
!Comment&lt;br /&gt;
|-&lt;br /&gt;
|Regular&lt;br /&gt;
|&amp;lt;code&amp;gt;njDrawModel&amp;lt;/code&amp;gt; (0077EF70)&lt;br /&gt;
|Allows to use multiple &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;s of various types (directional, point, spot). Specular is supported.&lt;br /&gt;
|-&lt;br /&gt;
|Simple&lt;br /&gt;
|&amp;lt;code&amp;gt;___SAnjSimpleDrawModel&amp;lt;/code&amp;gt; (00408520), &amp;lt;code&amp;gt;__SAnjSimpleDrawObject&amp;lt;/code&amp;gt; (0040A130)&lt;br /&gt;
|Only the first registered &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; can be used. It is set up as a directional light, and intensity and color settings cannot be adjusted. Specular is supported.&lt;br /&gt;
|-&lt;br /&gt;
|Easy&lt;br /&gt;
|&amp;lt;code&amp;gt;njEasyDrawObject&amp;lt;/code&amp;gt; (0040A100), &amp;lt;code&amp;gt;njEasyDrawModel&amp;lt;/code&amp;gt; (004084F0), &amp;lt;code&amp;gt;njEasyDrawMotion&amp;lt;/code&amp;gt; (00406FA0), &amp;lt;code&amp;gt;njEasyDrawShapeMotion&amp;lt;/code&amp;gt; (00406FE0)&lt;br /&gt;
|Uses one &amp;quot;easy&amp;quot; light (not &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;).  Specular is not supported. From the SDK: The light vector uses the screen space coordinate system. E.g. if set up like &amp;lt;code&amp;gt;njSetEasyLight( 0.0f, 0.0f, 1.0f );&amp;lt;/code&amp;gt;, the light source will always be in front of the screen. To set the light source in 3D space, they must be converted with the current matrix:&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
light.x = LIGHT3D_X;&lt;br /&gt;
light.y = LIGHT3D_Y;&lt;br /&gt;
light.z = LIGHT3D_Z;&lt;br /&gt;
njCalcVector( NULL, &amp;amp;light, &amp;amp;lwork );&lt;br /&gt;
njSetEasyLight( lwork.x, lwork.y, lworkz );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;After this, the Easy light source will be at &amp;lt;code&amp;gt;LIGHT3D_X, LIGHT3D_Y, LIGHT3D_Z&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
The SADX functions are a rough match since SADX changed draw functions for a lot of objects, and all that is left is some wrapper functions that call a more generic draw function:&lt;br /&gt;
&lt;br /&gt;
# The Regular functions are difficult to tell from the paletted functions, so the above table is an approximation.&lt;br /&gt;
# The Easy functions are mostly still there.&lt;br /&gt;
# The Simple functions only have two stubs which aren&#039;t called by anything other than the Chao Name Machine, which doesn&#039;t match SA1.&lt;br /&gt;
&lt;br /&gt;
=== Lighting Data ===&lt;br /&gt;
The data sources for the lights are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Light&lt;br /&gt;
!Type&lt;br /&gt;
!Direction&lt;br /&gt;
!Color&lt;br /&gt;
!Diffuse, specular, ambient intensity&lt;br /&gt;
|-&lt;br /&gt;
|Regular - light 1&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|-&lt;br /&gt;
|Regular - light 2&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightDirection&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightColor&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightIntensity&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|-&lt;br /&gt;
|Simple&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|White (in SA1 anyway)&lt;br /&gt;
|From the SL file&lt;br /&gt;
|-&lt;br /&gt;
|Easy&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|From the SL file, no specular&lt;br /&gt;
|}&lt;br /&gt;
In addition to these lights, there can be custom lights set up by objects&#039; code, which will affect all objects rendered with Regular functions. These custom lights can be directional, spot or point, with or without specular. The custom lights are created with the function &amp;lt;code&amp;gt;le_CreateLight&amp;lt;/code&amp;gt; (0040A510 in SADX) and deleted with the function &amp;lt;code&amp;gt;le_DeleteLight&amp;lt;/code&amp;gt; (0040A550 in SADX).&lt;br /&gt;
&lt;br /&gt;
In the Dreamcast version, these functions use pointers to actual &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;s. In SADX, the Ninja Lights system appears to have been replaced by a system using the structure &amp;lt;code&amp;gt;LE_LIGHT_ENV&amp;lt;/code&amp;gt; (what is also known as &amp;quot;Stage lights&amp;quot;). Instead of specific pointers, there is now an array of four &amp;quot;current stage lights&amp;quot; called &amp;lt;code&amp;gt;le_env&amp;lt;/code&amp;gt; at 03ABD9F8. It also has a corresponding array of four Ninja light flags &amp;lt;code&amp;gt;le_env_typ&amp;lt;/code&amp;gt; at 03ABDBB8. So instead of &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; pointers, the light create/delete functions manipulate data in these arrays in SADX.&lt;br /&gt;
&lt;br /&gt;
Interestingly enough, the data for the light &amp;quot;Regular- light 2&amp;quot; is completely the same in SADX. It&#039;s still set up by the skybox display functions which call &amp;lt;code&amp;gt;njSetLightColor&amp;lt;/code&amp;gt; etc. with the same arguments as the Dreamcast version, so basically we don&#039;t need the data from this post. However, now that these functions are redirected to modify the first entry in the &amp;lt;code&amp;gt;le_env&amp;lt;/code&amp;gt; array, this data is overwritten every time a stage loads. That is happening because the function &amp;lt;code&amp;gt;le_set_env&amp;lt;/code&amp;gt; (0040A95) copies over all light data from the SADX stage lights array (00900E88), which happens every time a light type is set and whenever a new level loads.&lt;br /&gt;
&lt;br /&gt;
The following behavior of Ninja Lights is different from palette lighting:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;NJD_FLAG_IGNORE_SPECULAR&amp;lt;/code&amp;gt; disables specular lighting &#039;&#039;completely&#039;&#039; (per material).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;NJD_FLAG_USE_FLAT&amp;lt;/code&amp;gt; enables flat shading (used by Master Emerald pieces).&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Custom&#039;&#039;&#039; &#039;&#039;&#039;Lights&#039;&#039;&#039; ===&lt;br /&gt;
There&#039;s a leftover function in SADX that creates custom lights associated with specific objects: &amp;lt;code&amp;gt;asSetLight&amp;lt;/code&amp;gt; at 0040ADC0. It uses a &amp;lt;code&amp;gt;taskwk&amp;lt;/code&amp;gt; pointer, an &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; pointer and a pointer to a structure called &amp;lt;code&amp;gt;LightInfo&amp;lt;/code&amp;gt;:&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct LightInfo &lt;br /&gt;
{&lt;br /&gt;
int lsrc; // Ninja light flags &lt;br /&gt;
float spc; &lt;br /&gt;
float dif; &lt;br /&gt;
float amb; &lt;br /&gt;
NJS_ARGB argb; &lt;br /&gt;
NJS_POINT3 pos; // Light position (for spot and point lights) &lt;br /&gt;
NJS_POINT3 vec; // Light direction &lt;br /&gt;
float nrang; // Distance at which light source attenuation begins &lt;br /&gt;
float frang; // Distance to cut the effect of the light source (range) &lt;br /&gt;
int iang; // The angle at which the specular or spotlight is at maximum intensity &lt;br /&gt;
int oang; // The angle at which the specular or spotlight effect ceases &lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;The following Ninja light flags can be used. The ones in bold are used in SA1, and the ones crossed out are unlikely to have been used in SA1.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Flags&lt;br /&gt;
!Flag name&lt;br /&gt;
!Light type&lt;br /&gt;
!Ambient&lt;br /&gt;
!Diffuse&lt;br /&gt;
!Specular&lt;br /&gt;
|-&lt;br /&gt;
|0x01&lt;br /&gt;
|NJD_AMBIENT&lt;br /&gt;
|Ambient&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x02&lt;br /&gt;
|NJD_DIR_LIGHT&lt;br /&gt;
|Directional&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x03&lt;br /&gt;
|&#039;&#039;&#039;NJD_LAMBERT_DIR&#039;&#039;&#039;&lt;br /&gt;
|Directional&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x04&lt;br /&gt;
|&#039;&#039;&#039;NJD_POINT_LIGHT&#039;&#039;&#039;&lt;br /&gt;
|Point&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x05&lt;br /&gt;
|NJD_LAMBERT_POINT&lt;br /&gt;
|Point&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x08&lt;br /&gt;
|NJD_SPOT_LIGHT&lt;br /&gt;
|Spot&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x10&lt;br /&gt;
|NJD_SPEC_DIR&lt;br /&gt;
|Directional&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x13&lt;br /&gt;
|NJD_PHONG_DIR&lt;br /&gt;
|Directional&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x20&lt;br /&gt;
|NJD_SPEC_POINT&lt;br /&gt;
|Point&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x25&lt;br /&gt;
|&#039;&#039;&#039;NJD_PHONG_POINT&#039;&#039;&#039;&lt;br /&gt;
|Point&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x40&lt;br /&gt;
|&amp;lt;del&amp;gt;NJD_USER_LIGHT&amp;lt;/del&amp;gt;&lt;br /&gt;
|Call a custom callback function&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|0x80&lt;br /&gt;
|&#039;&#039;&#039;NJD_SIMPLE_LIGHT&#039;&#039;&#039;&lt;br /&gt;
|Simplified lighting calculations (NOT the &amp;quot;Simple light&amp;quot; described earlier)&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|0xC0&lt;br /&gt;
|&amp;lt;del&amp;gt;NJD_BLOCK_LIGHT&amp;lt;/del&amp;gt;&lt;br /&gt;
|Simplified lighting calculations&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
The following custom lights have some leftover code and data in SADX. These also exist in SA1 but they aren&#039;t visible normally because the models that were supposed to be lit by them are rendered with palette lighting.&lt;br /&gt;
&lt;br /&gt;
# Ice Cap background light: &amp;lt;code&amp;gt;NJD_PHONG_POINT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LightInfo&amp;lt;/code&amp;gt; structure at 00C67FA0. Uses angles.&lt;br /&gt;
# &amp;quot;Chaos underlight&amp;quot;: &amp;lt;code&amp;gt;NJD_POINT_LIGHT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; structure at 03D0D5B8. The light is initialized using the function &amp;lt;code&amp;gt;ChaosUnderLightInit&amp;lt;/code&amp;gt; (007AD250) that has a &amp;quot;radius&amp;quot; argument which goes unused in SADX but in SA1 it should be the light range. In Chaos&#039; main functions, the light&#039;s matrix is transformed to match Chaos&#039; position.&lt;br /&gt;
# Some light in Knuckles&#039; story cutscene: &amp;lt;code&amp;gt;NJD_SIMPLE_LIGHT | NJD_LAMBERT_DIR&amp;lt;/code&amp;gt;, function at 006868F0.&lt;br /&gt;
# Lights in Gamma&#039;s briefing cutscene: &amp;lt;code&amp;gt;NJD_SIMPLE_LIGHT | NJD_LAMBERT_DIR&amp;lt;/code&amp;gt;, function at 006F4570. The light is a leftover, but this effect was adapted to palette lighting, and palette-related functions are called here too.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Specular&#039;&#039;&#039; &#039;&#039;&#039;Lighting&#039;&#039;&#039; ===&lt;br /&gt;
The Specular calculation formula for the Ninja Lights is currently unknown for Basic models. For Chunk models (which SA1 DC doesn&#039;t use), the formula was reversed by &#039;&#039;Exant&#039;&#039; for Simple and Easy lights:&lt;br /&gt;
[[File:Ninja Lights 1772333955721.png|none]]&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Ninja_Lights&amp;diff=690</id>
		<title>Ninja Lights</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Ninja_Lights&amp;diff=690"/>
		<updated>2026-03-01T03:09:28Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;quot;Ninja Lights&amp;quot; refers to the lighting used by the Ninja library of the [[Katana SDK]].&lt;br /&gt;
&lt;br /&gt;
== Ninja Lights in Sonic Adventure ==&lt;br /&gt;
&#039;&#039;&#039;Note: Ninja Lights are not implemented in the Lantern Engine mod, so the information below is irrelevant to the PC version.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sonic Adventure (Dreamcast) uses two lighting systems: the palette-based [[Sonic Adventure/Lantern Engine|LANTERN system]] and the Ninja Lights. The game&#039;s model rendering functions have &amp;quot;Lantern&amp;quot; and &amp;quot;Ninja&amp;quot; variants, and depending on the function used the game can either draw the model with palette lighting or use Ninja Lights.&lt;br /&gt;
&lt;br /&gt;
The SL file contains data for setting up the Ninja lights. This information consists of: light color (three floats for R/G/B), diffuse multiplier, specular power and ambient multiplier. Both diffuse and specular components are the same color. The “ignore specular” material flag disables the specular component per mesh.&lt;br /&gt;
&lt;br /&gt;
=== Types of Ninja Lights Setup ===&lt;br /&gt;
There are three types of lights used for non-palettized models in the game:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Lighting Setup&lt;br /&gt;
!Description&lt;br /&gt;
!Used by&lt;br /&gt;
|-&lt;br /&gt;
|Two Ninja Lights&lt;br /&gt;
|Non-palettized lighting that uses two Ninja Lights. These lights use &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; structures described in the Katana SDK. One is set up using the parameters in the SL file (let’s call it the &amp;lt;code&amp;gt;ENV&amp;lt;/code&amp;gt; Light), and the other is set up in code, usually in level binaries (let’s call it the &amp;lt;code&amp;gt;DIR&amp;lt;/code&amp;gt; light). The &amp;lt;code&amp;gt;ENV&amp;lt;/code&amp;gt; light has one configurable color that is shared for diffuse and specular, the &amp;lt;code&amp;gt;DIR&amp;lt;/code&amp;gt; light can have different diffuse and specular color (though the game doesn’t seem to use that). It can also have a different light direction.&lt;br /&gt;
|Common switch, Hint monitor, OEggKanban (glowing Eggman logo in Final Egg, tube parts only), Chaos puddle in some cutscenes, Aoki Switch (top)&lt;br /&gt;
|-&lt;br /&gt;
|Simple Ninja Light&lt;br /&gt;
|Non-palettized lighting that uses one Ninja Light using the parameters from the SL file except the color, which is always white.&lt;br /&gt;
|Rock bits in Red Mountain, non-Jewel Chao, Master Emerald pieces, Froggy in Gamma’s Emerald Coast&lt;br /&gt;
|-&lt;br /&gt;
|Easy Light&lt;br /&gt;
|Non-palettized lighting that sets up the Easy Light (not &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;) using the parameters from the SL file. The Easy light is described in the Katana SDK. It doesn’t support specular lighting.&lt;br /&gt;
|Snowboard, OSandSwitch (Sand Hill switch), shadow blob, Chambr (chambers with opening doors in Sky Deck), debug objects, Aoki Switch (bottom), E101’s missiles, Hedgehog Hammer targets&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rendering Functions and their SADX Counterparts ===&lt;br /&gt;
In SA1, most models were rendered with palette lighting using the game&#039;s custom function, but some models were rendered by calling Ninja drawing functions directly, which made them use the Ninja lights system. There are three light setups depending on the specific variation of the Ninja draw function:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Light setup&lt;br /&gt;
!Functions in SADX (PC, 2004)&lt;br /&gt;
!Comment&lt;br /&gt;
|-&lt;br /&gt;
|Regular&lt;br /&gt;
|&amp;lt;code&amp;gt;njDrawModel&amp;lt;/code&amp;gt; (0077EF70)&lt;br /&gt;
|Allows to use multiple &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;s of various types (directional, point, spot). Specular is supported.&lt;br /&gt;
|-&lt;br /&gt;
|Simple&lt;br /&gt;
|&amp;lt;code&amp;gt;___SAnjSimpleDrawModel&amp;lt;/code&amp;gt; (00408520), &amp;lt;code&amp;gt;__SAnjSimpleDrawObject&amp;lt;/code&amp;gt; (0040A130)&lt;br /&gt;
|Only the first registered &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; can be used. It is set up as a directional light, and intensity and color settings cannot be adjusted. Specular is supported.&lt;br /&gt;
|-&lt;br /&gt;
|Easy&lt;br /&gt;
|&amp;lt;code&amp;gt;njEasyDrawObject&amp;lt;/code&amp;gt; (0040A100), &amp;lt;code&amp;gt;njEasyDrawModel&amp;lt;/code&amp;gt; (004084F0), &amp;lt;code&amp;gt;njEasyDrawMotion&amp;lt;/code&amp;gt; (00406FA0), &amp;lt;code&amp;gt;njEasyDrawShapeMotion&amp;lt;/code&amp;gt; (00406FE0)&lt;br /&gt;
|Uses one &amp;quot;easy&amp;quot; light (not &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;).  Specular is not supported. From the SDK: The light vector uses the screen space coordinate system. E.g. if set up like &amp;lt;code&amp;gt;njSetEasyLight( 0.0f, 0.0f, 1.0f );&amp;lt;/code&amp;gt;, the light source will always be in front of the screen. To set the light source in 3D space, they must be converted with the current matrix:&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
light.x = LIGHT3D_X;&lt;br /&gt;
light.y = LIGHT3D_Y;&lt;br /&gt;
light.z = LIGHT3D_Z;&lt;br /&gt;
njCalcVector( NULL, &amp;amp;light, &amp;amp;lwork );&lt;br /&gt;
njSetEasyLight( lwork.x, lwork.y, lworkz );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;After this, the Easy light source will be at &amp;lt;code&amp;gt;LIGHT3D_X,&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;LIGHT3D_Y, LIGHT3D_Z&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
The SADX functions are a rough match since SADX changed draw functions for a lot of objects, and all that is left is some wrapper functions that call a more generic draw function:&lt;br /&gt;
&lt;br /&gt;
# The Regular functions are difficult to tell from the paletted functions, so the above table is an approximation.&lt;br /&gt;
# The Easy functions are mostly still there.&lt;br /&gt;
# The Simple functions only have two stubs which aren&#039;t called by anything other than the Chao Name Machine, which doesn&#039;t match SA1.&lt;br /&gt;
&lt;br /&gt;
=== Lighting Data ===&lt;br /&gt;
The data sources for the lights are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Light&lt;br /&gt;
!Type&lt;br /&gt;
!Direction&lt;br /&gt;
!Color&lt;br /&gt;
!Diffuse, specular, ambient intensity&lt;br /&gt;
|-&lt;br /&gt;
|Regular - light 1&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|-&lt;br /&gt;
|Regular - light 2&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightDirection&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightColor&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightIntensity&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|-&lt;br /&gt;
|Simple&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|White (in SA1 anyway)&lt;br /&gt;
|From the SL file&lt;br /&gt;
|-&lt;br /&gt;
|Easy&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|From the SL file, no specular&lt;br /&gt;
|}&lt;br /&gt;
In addition to these lights, there can be custom lights set up by objects&#039; code, which will affect all objects rendered with Regular functions. These custom lights can be directional, spot or point, with or without specular. The custom lights are created with the function &amp;lt;code&amp;gt;le_CreateLight&amp;lt;/code&amp;gt; (0040A510 in SADX) and deleted with the function &amp;lt;code&amp;gt;le_DeleteLight&amp;lt;/code&amp;gt; (0040A550 in SADX).&lt;br /&gt;
&lt;br /&gt;
In the Dreamcast version, these functions use pointers to actual &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;s. In SADX, the Ninja Lights system appears to have been replaced by a system using the structure &amp;lt;code&amp;gt;LE_LIGHT_ENV&amp;lt;/code&amp;gt; (what is also known as &amp;quot;Stage lights&amp;quot;). Instead of specific pointers, there is now an array of four &amp;quot;current stage lights&amp;quot; called &amp;lt;code&amp;gt;le_env&amp;lt;/code&amp;gt; at 03ABD9F8. It also has a corresponding array of four Ninja light flags &amp;lt;code&amp;gt;le_env_typ&amp;lt;/code&amp;gt; at 03ABDBB8. So instead of &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; pointers, the light create/delete functions manipulate data in these arrays in SADX.&lt;br /&gt;
&lt;br /&gt;
Interestingly enough, the data for the light &amp;quot;Regular- light 2&amp;quot; is completely the same in SADX. It&#039;s still set up by the skybox display functions which call &amp;lt;code&amp;gt;njSetLightColor&amp;lt;/code&amp;gt; etc. with the same arguments as the Dreamcast version, so basically we don&#039;t need the data from this post. However, now that these functions are redirected to modify the first entry in the &amp;lt;code&amp;gt;le_env&amp;lt;/code&amp;gt; array, this data is overwritten every time a stage loads. That is happening because the function &amp;lt;code&amp;gt;le_set_env&amp;lt;/code&amp;gt; (0040A95) copies over all light data from the SADX stage lights array (00900E88), which happens every time a light type is set and whenever a new level loads.&lt;br /&gt;
&lt;br /&gt;
The following behavior of Ninja Lights is different from palette lighting:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;NJD_FLAG_IGNORE_SPECULAR&amp;lt;/code&amp;gt; disables specular lighting &#039;&#039;completely&#039;&#039; (per material).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;NJD_FLAG_USE_FLAT&amp;lt;/code&amp;gt; enables flat shading (used by Master Emerald pieces).&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Custom&#039;&#039;&#039; &#039;&#039;&#039;Lights&#039;&#039;&#039; ===&lt;br /&gt;
There&#039;s a leftover function in SADX that creates custom lights associated with specific objects: &amp;lt;code&amp;gt;asSetLight&amp;lt;/code&amp;gt; at 0040ADC0. It uses a &amp;lt;code&amp;gt;taskwk&amp;lt;/code&amp;gt; pointer, an &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; pointer and a pointer to a structure called &amp;lt;code&amp;gt;LightInfo&amp;lt;/code&amp;gt;:&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct LightInfo &lt;br /&gt;
{&lt;br /&gt;
int lsrc; // Ninja light flags &lt;br /&gt;
float spc; &lt;br /&gt;
float dif; &lt;br /&gt;
float amb; &lt;br /&gt;
NJS_ARGB argb; &lt;br /&gt;
NJS_POINT3 pos; // Light position (for spot and point lights) &lt;br /&gt;
NJS_POINT3 vec; // Light direction &lt;br /&gt;
float nrang; // Distance at which light source attenuation begins &lt;br /&gt;
float frang; // Distance to cut the effect of the light source (range) &lt;br /&gt;
int iang; // The angle at which the specular or spotlight is at maximum intensity &lt;br /&gt;
int oang; // The angle at which the specular or spotlight effect ceases &lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;The following Ninja light flags can be used. The ones in bold are used in SA1, and the ones crossed out are unlikely to have been used in SA1.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Flags&lt;br /&gt;
!Flag name&lt;br /&gt;
!Light type&lt;br /&gt;
!Ambient&lt;br /&gt;
!Diffuse&lt;br /&gt;
!Specular&lt;br /&gt;
|-&lt;br /&gt;
|0x01&lt;br /&gt;
|NJD_AMBIENT&lt;br /&gt;
|Ambient&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x02&lt;br /&gt;
|NJD_DIR_LIGHT&lt;br /&gt;
|Directional&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x03&lt;br /&gt;
|&#039;&#039;&#039;NJD_LAMBERT_DIR&#039;&#039;&#039;&lt;br /&gt;
|Directional&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x04&lt;br /&gt;
|&#039;&#039;&#039;NJD_POINT_LIGHT&#039;&#039;&#039;&lt;br /&gt;
|Point&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x05&lt;br /&gt;
|NJD_LAMBERT_POINT&lt;br /&gt;
|Point&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x08&lt;br /&gt;
|NJD_SPOT_LIGHT&lt;br /&gt;
|Spot&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x10&lt;br /&gt;
|NJD_SPEC_DIR&lt;br /&gt;
|Directional&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x13&lt;br /&gt;
|NJD_PHONG_DIR&lt;br /&gt;
|Directional&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x20&lt;br /&gt;
|NJD_SPEC_POINT&lt;br /&gt;
|Point&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x25&lt;br /&gt;
|&#039;&#039;&#039;NJD_PHONG_POINT&#039;&#039;&#039;&lt;br /&gt;
|Point&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x40&lt;br /&gt;
|&amp;lt;del&amp;gt;NJD_USER_LIGHT&amp;lt;/del&amp;gt;&lt;br /&gt;
|Call a custom callback function&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|0x80&lt;br /&gt;
|&#039;&#039;&#039;NJD_SIMPLE_LIGHT&#039;&#039;&#039;&lt;br /&gt;
|Simplified lighting calculations (NOT the &amp;quot;Simple light&amp;quot; described earlier)&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|0xC0&lt;br /&gt;
|&amp;lt;del&amp;gt;NJD_BLOCK_LIGHT&amp;lt;/del&amp;gt;&lt;br /&gt;
|Simplified lighting calculations&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
The following custom lights have some leftover code and data in SADX. These also exist in SA1 but they aren&#039;t visible normally because the models that were supposed to be lit by them are rendered with palette lighting.&lt;br /&gt;
&lt;br /&gt;
# Ice Cap background light: &amp;lt;code&amp;gt;NJD_PHONG_POINT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LightInfo&amp;lt;/code&amp;gt; structure at 00C67FA0. Uses angles.&lt;br /&gt;
# &amp;quot;Chaos underlight&amp;quot;: &amp;lt;code&amp;gt;NJD_POINT_LIGHT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; structure at 03D0D5B8. The light is initialized using the function &amp;lt;code&amp;gt;ChaosUnderLightInit&amp;lt;/code&amp;gt; (007AD250) that has a &amp;quot;radius&amp;quot; argument which goes unused in SADX but in SA1 it should be the light range. In Chaos&#039; main functions, the light&#039;s matrix is transformed to match Chaos&#039; position.&lt;br /&gt;
# Some light in Knuckles&#039; story cutscene: &amp;lt;code&amp;gt;NJD_SIMPLE_LIGHT | NJD_LAMBERT_DIR&amp;lt;/code&amp;gt;, function at 006868F0.&lt;br /&gt;
# Lights in Gamma&#039;s briefing cutscene: &amp;lt;code&amp;gt;NJD_SIMPLE_LIGHT | NJD_LAMBERT_DIR&amp;lt;/code&amp;gt;, function at 006F4570. The light is a leftover, but this effect was adapted to palette lighting, and palette-related functions are called here too.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Specular&#039;&#039;&#039; &#039;&#039;&#039;Lighting&#039;&#039;&#039; ===&lt;br /&gt;
The Specular calculation formula for the Ninja Lights is currently unknown for Basic models. For Chunk models (which SA1 DC doesn&#039;t use), the formula was reversed by &#039;&#039;Exant&#039;&#039; for Simple and Easy lights:&lt;br /&gt;
[[File:Ninja Lights 1772333955721.png|none]]&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Ninja_Lights&amp;diff=689</id>
		<title>Ninja Lights</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Ninja_Lights&amp;diff=689"/>
		<updated>2026-03-01T03:08:57Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;quot;Ninja Lights&amp;quot; refers to the lighting used by the Ninja library of the [[Katana SDK]].&lt;br /&gt;
&lt;br /&gt;
== Ninja Lights in Sonic Adventure ==&lt;br /&gt;
&#039;&#039;&#039;Note: Ninja Lights are not implemented in the Lantern Engine mod, so the information below is irrelevant to the PC version.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sonic Adventure (Dreamcast) uses two lighting systems: the palette-based [[Sonic Adventure/Lantern Engine|LANTERN system]] and the Ninja Lights. The game&#039;s model rendering functions have &amp;quot;Lantern&amp;quot; and &amp;quot;Ninja&amp;quot; variants, and depending on the function used the game can either draw the model with palette lighting or use Ninja Lights.&lt;br /&gt;
&lt;br /&gt;
The SL file contains data for setting up the Ninja lights. This information consists of: light color (three floats for R/G/B), diffuse multiplier, specular power and ambient multiplier. Both diffuse and specular components are the same color. The “ignore specular” material flag disables the specular component per mesh.&lt;br /&gt;
&lt;br /&gt;
=== Types of Ninja Lights Setup ===&lt;br /&gt;
There are three types of lights used for non-palettized models in the game:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Lighting Setup&lt;br /&gt;
!Description&lt;br /&gt;
!Used by&lt;br /&gt;
|-&lt;br /&gt;
|Two Ninja Lights&lt;br /&gt;
|Non-palettized lighting that uses two Ninja Lights. These lights use &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; structures described in the Katana SDK. One is set up using the parameters in the SL file (let’s call it the &amp;lt;code&amp;gt;ENV&amp;lt;/code&amp;gt; Light), and the other is set up in code, usually in level binaries (let’s call it the &amp;lt;code&amp;gt;DIR&amp;lt;/code&amp;gt; light). The &amp;lt;code&amp;gt;ENV&amp;lt;/code&amp;gt; light has one configurable color that is shared for diffuse and specular, the &amp;lt;code&amp;gt;DIR&amp;lt;/code&amp;gt; light can have different diffuse and specular color (though the game doesn’t seem to use that). It can also have a different light direction.&lt;br /&gt;
|Common switch, Hint monitor, OEggKanban (glowing Eggman logo in Final Egg, tube parts only), Chaos puddle in some cutscenes, Aoki Switch (top)&lt;br /&gt;
|-&lt;br /&gt;
|Simple Ninja Light&lt;br /&gt;
|Non-palettized lighting that uses one Ninja Light using the parameters from the SL file except the color, which is always white.&lt;br /&gt;
|Rock bits in Red Mountain, non-Jewel Chao, Master Emerald pieces, Froggy in Gamma’s Emerald Coast&lt;br /&gt;
|-&lt;br /&gt;
|Easy Light&lt;br /&gt;
|Non-palettized lighting that sets up the Easy Light (not &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;) using the parameters from the SL file. The Easy light is described in the Katana SDK. It doesn’t support specular lighting.&lt;br /&gt;
|Snowboard, OSandSwitch (Sand Hill switch), shadow blob, Chambr (chambers with opening doors in Sky Deck), debug objects, Aoki Switch (bottom), E101’s missiles, Hedgehog Hammer targets&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rendering Functions and their SADX Counterparts ===&lt;br /&gt;
In SA1, most models were rendered with palette lighting using the game&#039;s custom function, but some models were rendered by calling Ninja drawing functions directly, which made them use the Ninja lights system. There are three light setups depending on the specific variation of the Ninja draw function:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Light setup&lt;br /&gt;
!Functions in SADX (PC, 2004)&lt;br /&gt;
!Comment&lt;br /&gt;
|-&lt;br /&gt;
|Regular&lt;br /&gt;
|&amp;lt;code&amp;gt;njDrawModel&amp;lt;/code&amp;gt; (0077EF70)&lt;br /&gt;
|Allows to use multiple &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;s of various types (directional, point, spot). Specular is supported.&lt;br /&gt;
|-&lt;br /&gt;
|Simple&lt;br /&gt;
|&amp;lt;code&amp;gt;___SAnjSimpleDrawModel&amp;lt;/code&amp;gt; (00408520), &amp;lt;code&amp;gt;__SAnjSimpleDrawObject&amp;lt;/code&amp;gt; (0040A130)&lt;br /&gt;
|Only the first registered &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; can be used. It is set up as a directional light, and intensity and color settings cannot be adjusted. Specular is supported.&lt;br /&gt;
|-&lt;br /&gt;
|Easy&lt;br /&gt;
|&amp;lt;code&amp;gt;njEasyDrawObject&amp;lt;/code&amp;gt; (0040A100), &amp;lt;code&amp;gt;njEasyDrawModel&amp;lt;/code&amp;gt; (004084F0), &amp;lt;code&amp;gt;njEasyDrawMotion&amp;lt;/code&amp;gt; (00406FA0), &amp;lt;code&amp;gt;njEasyDrawShapeMotion&amp;lt;/code&amp;gt; (00406FE0)&lt;br /&gt;
|Uses one &amp;quot;easy&amp;quot; light (not &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;).  Specular is not supported. From the SDK: The light vector uses the screen space coordinate system. E.g. if set up like &amp;lt;code&amp;gt;njSetEasyLight( 0.0f, 0.0f, 1.0f );&amp;lt;/code&amp;gt;, the light source will always be in front of the screen. To set the light source in 3D space, they must be converted with the current matrix:&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
light.x = LIGHT3D_X; light.y = LIGHT3D_Y;&lt;br /&gt;
light.z = LIGHT3D_Z; njCalcVector( NULL, &amp;amp;light, &amp;amp;lwork );&lt;br /&gt;
njSetEasyLight( lwork.x, lwork.y, lworkz );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;After this, the Easy light source will be at &amp;lt;code&amp;gt;LIGHT3D_X,&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;LIGHT3D_Y, LIGHT3D_Z&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
The SADX functions are a rough match since SADX changed draw functions for a lot of objects, and all that is left is some wrapper functions that call a more generic draw function:&lt;br /&gt;
&lt;br /&gt;
# The Regular functions are difficult to tell from the paletted functions, so the above table is an approximation.&lt;br /&gt;
# The Easy functions are mostly still there.&lt;br /&gt;
# The Simple functions only have two stubs which aren&#039;t called by anything other than the Chao Name Machine, which doesn&#039;t match SA1.&lt;br /&gt;
&lt;br /&gt;
=== Lighting Data ===&lt;br /&gt;
The data sources for the lights are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Light&lt;br /&gt;
!Type&lt;br /&gt;
!Direction&lt;br /&gt;
!Color&lt;br /&gt;
!Diffuse, specular, ambient intensity&lt;br /&gt;
|-&lt;br /&gt;
|Regular - light 1&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|-&lt;br /&gt;
|Regular - light 2&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightDirection&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightColor&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightIntensity&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|-&lt;br /&gt;
|Simple&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|White (in SA1 anyway)&lt;br /&gt;
|From the SL file&lt;br /&gt;
|-&lt;br /&gt;
|Easy&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|From the SL file, no specular&lt;br /&gt;
|}&lt;br /&gt;
In addition to these lights, there can be custom lights set up by objects&#039; code, which will affect all objects rendered with Regular functions. These custom lights can be directional, spot or point, with or without specular. The custom lights are created with the function &amp;lt;code&amp;gt;le_CreateLight&amp;lt;/code&amp;gt; (0040A510 in SADX) and deleted with the function &amp;lt;code&amp;gt;le_DeleteLight&amp;lt;/code&amp;gt; (0040A550 in SADX).&lt;br /&gt;
&lt;br /&gt;
In the Dreamcast version, these functions use pointers to actual &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;s. In SADX, the Ninja Lights system appears to have been replaced by a system using the structure &amp;lt;code&amp;gt;LE_LIGHT_ENV&amp;lt;/code&amp;gt; (what is also known as &amp;quot;Stage lights&amp;quot;). Instead of specific pointers, there is now an array of four &amp;quot;current stage lights&amp;quot; called &amp;lt;code&amp;gt;le_env&amp;lt;/code&amp;gt; at 03ABD9F8. It also has a corresponding array of four Ninja light flags &amp;lt;code&amp;gt;le_env_typ&amp;lt;/code&amp;gt; at 03ABDBB8. So instead of &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; pointers, the light create/delete functions manipulate data in these arrays in SADX.&lt;br /&gt;
&lt;br /&gt;
Interestingly enough, the data for the light &amp;quot;Regular- light 2&amp;quot; is completely the same in SADX. It&#039;s still set up by the skybox display functions which call &amp;lt;code&amp;gt;njSetLightColor&amp;lt;/code&amp;gt; etc. with the same arguments as the Dreamcast version, so basically we don&#039;t need the data from this post. However, now that these functions are redirected to modify the first entry in the &amp;lt;code&amp;gt;le_env&amp;lt;/code&amp;gt; array, this data is overwritten every time a stage loads. That is happening because the function &amp;lt;code&amp;gt;le_set_env&amp;lt;/code&amp;gt; (0040A95) copies over all light data from the SADX stage lights array (00900E88), which happens every time a light type is set and whenever a new level loads.&lt;br /&gt;
&lt;br /&gt;
The following behavior of Ninja Lights is different from palette lighting:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;NJD_FLAG_IGNORE_SPECULAR&amp;lt;/code&amp;gt; disables specular lighting &#039;&#039;completely&#039;&#039; (per material).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;NJD_FLAG_USE_FLAT&amp;lt;/code&amp;gt; enables flat shading (used by Master Emerald pieces).&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Custom&#039;&#039;&#039; &#039;&#039;&#039;Lights&#039;&#039;&#039; ===&lt;br /&gt;
There&#039;s a leftover function in SADX that creates custom lights associated with specific objects: &amp;lt;code&amp;gt;asSetLight&amp;lt;/code&amp;gt; at 0040ADC0. It uses a &amp;lt;code&amp;gt;taskwk&amp;lt;/code&amp;gt; pointer, an &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; pointer and a pointer to a structure called &amp;lt;code&amp;gt;LightInfo&amp;lt;/code&amp;gt;:&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct LightInfo &lt;br /&gt;
{&lt;br /&gt;
int lsrc; // Ninja light flags &lt;br /&gt;
float spc; &lt;br /&gt;
float dif; &lt;br /&gt;
float amb; &lt;br /&gt;
NJS_ARGB argb; &lt;br /&gt;
NJS_POINT3 pos; // Light position (for spot and point lights) &lt;br /&gt;
NJS_POINT3 vec; // Light direction &lt;br /&gt;
float nrang; // Distance at which light source attenuation begins &lt;br /&gt;
float frang; // Distance to cut the effect of the light source (range) &lt;br /&gt;
int iang; // The angle at which the specular or spotlight is at maximum intensity &lt;br /&gt;
int oang; // The angle at which the specular or spotlight effect ceases &lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;The following Ninja light flags can be used. The ones in bold are used in SA1, and the ones crossed out are unlikely to have been used in SA1.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Flags&lt;br /&gt;
!Flag name&lt;br /&gt;
!Light type&lt;br /&gt;
!Ambient&lt;br /&gt;
!Diffuse&lt;br /&gt;
!Specular&lt;br /&gt;
|-&lt;br /&gt;
|0x01&lt;br /&gt;
|NJD_AMBIENT&lt;br /&gt;
|Ambient&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x02&lt;br /&gt;
|NJD_DIR_LIGHT&lt;br /&gt;
|Directional&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x03&lt;br /&gt;
|&#039;&#039;&#039;NJD_LAMBERT_DIR&#039;&#039;&#039;&lt;br /&gt;
|Directional&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x04&lt;br /&gt;
|&#039;&#039;&#039;NJD_POINT_LIGHT&#039;&#039;&#039;&lt;br /&gt;
|Point&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x05&lt;br /&gt;
|NJD_LAMBERT_POINT&lt;br /&gt;
|Point&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x08&lt;br /&gt;
|NJD_SPOT_LIGHT&lt;br /&gt;
|Spot&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x10&lt;br /&gt;
|NJD_SPEC_DIR&lt;br /&gt;
|Directional&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x13&lt;br /&gt;
|NJD_PHONG_DIR&lt;br /&gt;
|Directional&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x20&lt;br /&gt;
|NJD_SPEC_POINT&lt;br /&gt;
|Point&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x25&lt;br /&gt;
|&#039;&#039;&#039;NJD_PHONG_POINT&#039;&#039;&#039;&lt;br /&gt;
|Point&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x40&lt;br /&gt;
|&amp;lt;del&amp;gt;NJD_USER_LIGHT&amp;lt;/del&amp;gt;&lt;br /&gt;
|Call a custom callback function&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|0x80&lt;br /&gt;
|&#039;&#039;&#039;NJD_SIMPLE_LIGHT&#039;&#039;&#039;&lt;br /&gt;
|Simplified lighting calculations (NOT the &amp;quot;Simple light&amp;quot; described earlier)&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|0xC0&lt;br /&gt;
|&amp;lt;del&amp;gt;NJD_BLOCK_LIGHT&amp;lt;/del&amp;gt;&lt;br /&gt;
|Simplified lighting calculations&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
The following custom lights have some leftover code and data in SADX. These also exist in SA1 but they aren&#039;t visible normally because the models that were supposed to be lit by them are rendered with palette lighting.&lt;br /&gt;
&lt;br /&gt;
# Ice Cap background light: &amp;lt;code&amp;gt;NJD_PHONG_POINT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LightInfo&amp;lt;/code&amp;gt; structure at 00C67FA0. Uses angles.&lt;br /&gt;
# &amp;quot;Chaos underlight&amp;quot;: &amp;lt;code&amp;gt;NJD_POINT_LIGHT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; structure at 03D0D5B8. The light is initialized using the function &amp;lt;code&amp;gt;ChaosUnderLightInit&amp;lt;/code&amp;gt; (007AD250) that has a &amp;quot;radius&amp;quot; argument which goes unused in SADX but in SA1 it should be the light range. In Chaos&#039; main functions, the light&#039;s matrix is transformed to match Chaos&#039; position.&lt;br /&gt;
# Some light in Knuckles&#039; story cutscene: &amp;lt;code&amp;gt;NJD_SIMPLE_LIGHT | NJD_LAMBERT_DIR&amp;lt;/code&amp;gt;, function at 006868F0.&lt;br /&gt;
# Lights in Gamma&#039;s briefing cutscene: &amp;lt;code&amp;gt;NJD_SIMPLE_LIGHT | NJD_LAMBERT_DIR&amp;lt;/code&amp;gt;, function at 006F4570. The light is a leftover, but this effect was adapted to palette lighting, and palette-related functions are called here too.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Specular&#039;&#039;&#039; &#039;&#039;&#039;Lighting&#039;&#039;&#039; ===&lt;br /&gt;
The Specular calculation formula for the Ninja Lights is currently unknown for Basic models. For Chunk models (which SA1 DC doesn&#039;t use), the formula was reversed by &#039;&#039;Exant&#039;&#039; for Simple and Easy lights:&lt;br /&gt;
[[File:Ninja Lights 1772333955721.png|none]]&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=PL_Tool&amp;diff=688</id>
		<title>PL Tool</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=PL_Tool&amp;diff=688"/>
		<updated>2026-03-01T03:06:36Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;PL Tool is an editor for Sonic Adventure lighting files (PL and SL files) used by [[Sonic Adventure/Lantern Engine|Lantern Engine]].&lt;br /&gt;
= Using the Editor =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;figure&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pltool.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
== Palette List ==&lt;br /&gt;
&lt;br /&gt;
PLTool’s main window lists diffuse and specular palettes in the PL file. Click the palette to select it. Right click a palette for a list of options to edit it. You can create palettes with sliders like gradients in Photoshop, generate them like in the Preview prototype of SADX, fill them with a specific color (or a combination of colors), import and export palettes as PNG files, as well as copy and paste them. The &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; palette pair is not stored in the PL file and can be used for backing up palettes before editing them.&lt;br /&gt;
&lt;br /&gt;
* Note: Color Alpha is ignored in the game.&lt;br /&gt;
=== Create Gradient ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;figure&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Creategrad.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
This window lets you create gradients from four colors and an ambient color. Click each color box to set the color and drag the sliders to adjust the position of the two colors in the middle.&lt;br /&gt;
=== Generate Gradient (SADX Preview) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;figure&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Gengrad.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
The [https://hiddenpalace.org/Sonic_Adventure_DX_(Preview_prototype) SADX Preview prototype] has a debug menu that creates gradients. This feature is recreated in PL Tool. The gradients are generated using the following formula:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Result = Ambient + CO1 * Pow((1 - Index / 256), CO1Pow / 100.0) + CO2 * Pow((Index / 256), CO2Pow / 100)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Ambient is the Ambient color R/G/B.&lt;br /&gt;
* CO1 is Color 1 R/G/B.&lt;br /&gt;
* CO2 is Color 2 R/G/B.&lt;br /&gt;
* CO1Pow and CO2Pow are Color 1 and Color 2 power values respectively.&lt;br /&gt;
* Index is the color index in the gradient (0 to 255).&lt;br /&gt;
== Color Selector ==&lt;br /&gt;
&lt;br /&gt;
The trackbar is used to select a specific color in the palette. Its index and R/G/B values are shown on the right side of the status bar. Click the small colored box in the status bar to edit the color.&lt;br /&gt;
&lt;br /&gt;
* Note: Color Alpha is ignored in the game.&lt;br /&gt;
== Menu bar ==&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;&#039;File&#039;&#039;&#039; menu lets you import or export the entire palette list as a single PNG file.&lt;br /&gt;
* The &#039;&#039;&#039;Options&#039;&#039;&#039; menu lets you set a background color for the editor to make it easier to work with light or dark palettes.&lt;br /&gt;
* The &#039;&#039;&#039;Level Select&#039;&#039;&#039; menu allows you to locate the PL file by selecting a stage. If you have opened a PL file previously, the tool will look for PL files in the same folder without an open file dialog.&lt;br /&gt;
* The &#039;&#039;&#039;Format&#039;&#039;&#039; menu allows you to toggle the Endianness of PL and SL files. Leave it on Dreamcast for the Lantern Engine mod.&lt;br /&gt;
* The &#039;&#039;&#039;Tools&#039;&#039;&#039; menu opens the editor for SL files (see below).&lt;br /&gt;
== SL Editor ==&lt;br /&gt;
&lt;br /&gt;
The SL Editor lets you edit light direction and Ninja Lights configuration. &lt;br /&gt;
&lt;br /&gt;
[[File:Sleditor.png]]&lt;br /&gt;
&lt;br /&gt;
* The Environment Data box has the parameters for the Ninja lights. You can click the color box to select the color. &lt;br /&gt;
* The Light Direction box has light rotation Y and Z values. These are used to rotate the default light direction vector. This light direction is used by palette lights and Ninja lights except the DIR light which has a hardcoded light direction. &lt;br /&gt;
* The Free/Slave Data box has additional lighting data. This data doesn’t seem to be used by the game. It may be left over from the Saturn because a menu with similar data was found in a [https://hiddenpalace.org/News/Angels_with_Burning_Hearts:_Burning_Rangers_Prototype Burning Rangers prototype].&lt;br /&gt;
&lt;br /&gt;
{{SAToolsNavbox}}&lt;br /&gt;
&lt;br /&gt;
[[Category:SA1 tools]]&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Ninja_Lights&amp;diff=687</id>
		<title>Ninja Lights</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Ninja_Lights&amp;diff=687"/>
		<updated>2026-03-01T03:06:16Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;quot;Ninja Lights&amp;quot; refers to the lighting used by the Ninja library of the [[Katana SDK]].&lt;br /&gt;
&lt;br /&gt;
== Ninja Lights in Sonic Adventure ==&lt;br /&gt;
&#039;&#039;&#039;Note: Ninja Lights are not implemented in the Lantern Engine mod, so the information below is irrelevant to the PC version.&#039;&#039;&#039;&lt;br /&gt;
Sonic Adventure (Dreamcast) uses two lighting systems: the palette-based [[Sonic Adventure/Lantern Engine|LANTERN system]] and the Ninja Lights. The game&#039;s model rendering functions have &amp;quot;Lantern&amp;quot; and &amp;quot;Ninja&amp;quot; variants, and depending on the function used the game can either draw the model with palette lighting or use Ninja Lights.&lt;br /&gt;
&lt;br /&gt;
The SL file contains data for setting up the Ninja lights. This information consists of: light color (three floats for R/G/B), diffuse multiplier, specular power and ambient multiplier. Both diffuse and specular components are the same color. The “ignore specular” material flag disables the specular component per mesh.&lt;br /&gt;
&lt;br /&gt;
=== Types of Ninja Lights Setup ===&lt;br /&gt;
There are three types of lights used for non-palettized models in the game:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Lighting Setup&lt;br /&gt;
!Description&lt;br /&gt;
!Used by&lt;br /&gt;
|-&lt;br /&gt;
|Two Ninja Lights&lt;br /&gt;
|Non-palettized lighting that uses two Ninja Lights. These lights use &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; structures described in the Katana SDK. One is set up using the parameters in the SL file (let’s call it the &amp;lt;code&amp;gt;ENV&amp;lt;/code&amp;gt; Light), and the other is set up in code, usually in level binaries (let’s call it the &amp;lt;code&amp;gt;DIR&amp;lt;/code&amp;gt; light). The &amp;lt;code&amp;gt;ENV&amp;lt;/code&amp;gt; light has one configurable color that is shared for diffuse and specular, the &amp;lt;code&amp;gt;DIR&amp;lt;/code&amp;gt; light can have different diffuse and specular color (though the game doesn’t seem to use that). It can also have a different light direction.&lt;br /&gt;
|Common switch, Hint monitor, OEggKanban (glowing Eggman logo in Final Egg, tube parts only), Chaos puddle in some cutscenes, Aoki Switch (top)&lt;br /&gt;
|-&lt;br /&gt;
|Simple Ninja Light&lt;br /&gt;
|Non-palettized lighting that uses one Ninja Light using the parameters from the SL file except the color, which is always white.&lt;br /&gt;
|Rock bits in Red Mountain, non-Jewel Chao, Master Emerald pieces, Froggy in Gamma’s Emerald Coast&lt;br /&gt;
|-&lt;br /&gt;
|Easy Light&lt;br /&gt;
|Non-palettized lighting that sets up the Easy Light (not &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;) using the parameters from the SL file. The Easy light is described in the Katana SDK. It doesn’t support specular lighting.&lt;br /&gt;
|Snowboard, OSandSwitch (Sand Hill switch), shadow blob, Chambr (chambers with opening doors in Sky Deck), debug objects, Aoki Switch (bottom), E101’s missiles, Hedgehog Hammer targets&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rendering Functions and their SADX Counterparts ===&lt;br /&gt;
In SA1, most models were rendered with palette lighting using the game&#039;s custom function, but some models were rendered by calling Ninja drawing functions directly, which made them use the Ninja lights system. There are three light setups depending on the specific variation of the Ninja draw function:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Light setup&lt;br /&gt;
!Functions in SADX (PC, 2004)&lt;br /&gt;
!Comment&lt;br /&gt;
|-&lt;br /&gt;
|Regular&lt;br /&gt;
|&amp;lt;code&amp;gt;njDrawModel&amp;lt;/code&amp;gt; (0077EF70)&lt;br /&gt;
|Allows to use multiple &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;s of various types (directional, point, spot). Specular is supported.&lt;br /&gt;
|-&lt;br /&gt;
|Simple&lt;br /&gt;
|&amp;lt;code&amp;gt;___SAnjSimpleDrawModel&amp;lt;/code&amp;gt; (00408520), &amp;lt;code&amp;gt;__SAnjSimpleDrawObject&amp;lt;/code&amp;gt; (0040A130)&lt;br /&gt;
|Only the first registered &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; can be used. It is set up as a directional light, and intensity and color settings cannot be adjusted. Specular is supported.&lt;br /&gt;
|-&lt;br /&gt;
|Easy&lt;br /&gt;
|&amp;lt;code&amp;gt;njEasyDrawObject&amp;lt;/code&amp;gt; (0040A100), &amp;lt;code&amp;gt;njEasyDrawModel&amp;lt;/code&amp;gt; (004084F0), &amp;lt;code&amp;gt;njEasyDrawMotion&amp;lt;/code&amp;gt; (00406FA0), &amp;lt;code&amp;gt;njEasyDrawShapeMotion&amp;lt;/code&amp;gt; (00406FE0)&lt;br /&gt;
|Uses one &amp;quot;easy&amp;quot; light (not &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;).  Specular is not supported. From the SDK: The light vector uses the screen space coordinate system. E.g. if set up like &amp;lt;code&amp;gt;njSetEasyLight( 0.0f, 0.0f, 1.0f );&amp;lt;/code&amp;gt;, the light source will always be in front of the screen. To set the light source in 3D space, they must be converted with the current matrix:&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
light.x = LIGHT3D_X; light.y = LIGHT3D_Y;&lt;br /&gt;
light.z = LIGHT3D_Z; njCalcVector( NULL, &amp;amp;light, &amp;amp;lwork );&lt;br /&gt;
njSetEasyLight( lwork.x, lwork.y, lworkz );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;After this, the Easy light source will be at &amp;lt;code&amp;gt;LIGHT3D_X,&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;LIGHT3D_Y, LIGHT3D_Z&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
The SADX functions are a rough match since SADX changed draw functions for a lot of objects, and all that is left is some wrapper functions that call a more generic draw function:&lt;br /&gt;
&lt;br /&gt;
# The Regular functions are difficult to tell from the paletted functions, so the above table is an approximation.&lt;br /&gt;
# The Easy functions are mostly still there.&lt;br /&gt;
# The Simple functions only have two stubs which aren&#039;t called by anything other than the Chao Name Machine, which doesn&#039;t match SA1.&lt;br /&gt;
&lt;br /&gt;
=== Lighting Data ===&lt;br /&gt;
The data sources for the lights are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Light&lt;br /&gt;
!Type&lt;br /&gt;
!Direction&lt;br /&gt;
!Color&lt;br /&gt;
!Diffuse, specular, ambient intensity&lt;br /&gt;
|-&lt;br /&gt;
|Regular - light 1&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|-&lt;br /&gt;
|Regular - light 2&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightDirection&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightColor&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightIntensity&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|-&lt;br /&gt;
|Simple&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|White (in SA1 anyway)&lt;br /&gt;
|From the SL file&lt;br /&gt;
|-&lt;br /&gt;
|Easy&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|From the SL file, no specular&lt;br /&gt;
|}&lt;br /&gt;
In addition to these lights, there can be custom lights set up by objects&#039; code, which will affect all objects rendered with Regular functions. These custom lights can be directional, spot or point, with or without specular. The custom lights are created with the function &amp;lt;code&amp;gt;le_CreateLight&amp;lt;/code&amp;gt; (0040A510 in SADX) and deleted with the function &amp;lt;code&amp;gt;le_DeleteLight&amp;lt;/code&amp;gt; (0040A550 in SADX).&lt;br /&gt;
&lt;br /&gt;
In the Dreamcast version, these functions use pointers to actual &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;s. In SADX, the Ninja Lights system appears to have been replaced by a system using the structure &amp;lt;code&amp;gt;LE_LIGHT_ENV&amp;lt;/code&amp;gt; (what is also known as &amp;quot;Stage lights&amp;quot;). Instead of specific pointers, there is now an array of four &amp;quot;current stage lights&amp;quot; called &amp;lt;code&amp;gt;le_env&amp;lt;/code&amp;gt; at 03ABD9F8. It also has a corresponding array of four Ninja light flags &amp;lt;code&amp;gt;le_env_typ&amp;lt;/code&amp;gt; at 03ABDBB8. So instead of &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; pointers, the light create/delete functions manipulate data in these arrays in SADX.&lt;br /&gt;
&lt;br /&gt;
Interestingly enough, the data for the light &amp;quot;Regular- light 2&amp;quot; is completely the same in SADX. It&#039;s still set up by the skybox display functions which call &amp;lt;code&amp;gt;njSetLightColor&amp;lt;/code&amp;gt; etc. with the same arguments as the Dreamcast version, so basically we don&#039;t need the data from this post. However, now that these functions are redirected to modify the first entry in the &amp;lt;code&amp;gt;le_env&amp;lt;/code&amp;gt; array, this data is overwritten every time a stage loads. That is happening because the function &amp;lt;code&amp;gt;le_set_env&amp;lt;/code&amp;gt; (0040A95) copies over all light data from the SADX stage lights array (00900E88), which happens every time a light type is set and whenever a new level loads.&lt;br /&gt;
&lt;br /&gt;
The following behavior of Ninja Lights is different from palette lighting:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;NJD_FLAG_IGNORE_SPECULAR&amp;lt;/code&amp;gt; disables specular lighting &#039;&#039;completely&#039;&#039; (per material).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;NJD_FLAG_USE_FLAT&amp;lt;/code&amp;gt; enables flat shading (used by Master Emerald pieces).&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Custom&#039;&#039;&#039; &#039;&#039;&#039;Lights&#039;&#039;&#039; ===&lt;br /&gt;
There&#039;s a leftover function in SADX that creates custom lights associated with specific objects: &amp;lt;code&amp;gt;asSetLight&amp;lt;/code&amp;gt; at 0040ADC0. It uses a &amp;lt;code&amp;gt;taskwk&amp;lt;/code&amp;gt; pointer, an &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; pointer and a pointer to a structure called &amp;lt;code&amp;gt;LightInfo&amp;lt;/code&amp;gt;:&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct LightInfo &lt;br /&gt;
{&lt;br /&gt;
int lsrc; // Ninja light flags &lt;br /&gt;
float spc; &lt;br /&gt;
float dif; &lt;br /&gt;
float amb; &lt;br /&gt;
NJS_ARGB argb; &lt;br /&gt;
NJS_POINT3 pos; // Light position (for spot and point lights) &lt;br /&gt;
NJS_POINT3 vec; // Light direction &lt;br /&gt;
float nrang; // Distance at which light source attenuation begins &lt;br /&gt;
float frang; // Distance to cut the effect of the light source (range) &lt;br /&gt;
int iang; // The angle at which the specular or spotlight is at maximum intensity &lt;br /&gt;
int oang; // The angle at which the specular or spotlight effect ceases &lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;The following Ninja light flags can be used. The ones in bold are used in SA1, and the ones crossed out are unlikely to have been used in SA1.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Flags&lt;br /&gt;
!Flag name&lt;br /&gt;
!Light type&lt;br /&gt;
!Ambient&lt;br /&gt;
!Diffuse&lt;br /&gt;
!Specular&lt;br /&gt;
|-&lt;br /&gt;
|0x01&lt;br /&gt;
|NJD_AMBIENT&lt;br /&gt;
|Ambient&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x02&lt;br /&gt;
|NJD_DIR_LIGHT&lt;br /&gt;
|Directional&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x03&lt;br /&gt;
|&#039;&#039;&#039;NJD_LAMBERT_DIR&#039;&#039;&#039;&lt;br /&gt;
|Directional&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x04&lt;br /&gt;
|&#039;&#039;&#039;NJD_POINT_LIGHT&#039;&#039;&#039;&lt;br /&gt;
|Point&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x05&lt;br /&gt;
|NJD_LAMBERT_POINT&lt;br /&gt;
|Point&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x08&lt;br /&gt;
|NJD_SPOT_LIGHT&lt;br /&gt;
|Spot&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x10&lt;br /&gt;
|NJD_SPEC_DIR&lt;br /&gt;
|Directional&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x13&lt;br /&gt;
|NJD_PHONG_DIR&lt;br /&gt;
|Directional&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x20&lt;br /&gt;
|NJD_SPEC_POINT&lt;br /&gt;
|Point&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x25&lt;br /&gt;
|&#039;&#039;&#039;NJD_PHONG_POINT&#039;&#039;&#039;&lt;br /&gt;
|Point&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x40&lt;br /&gt;
|&amp;lt;del&amp;gt;NJD_USER_LIGHT&amp;lt;/del&amp;gt;&lt;br /&gt;
|Call a custom callback function&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|0x80&lt;br /&gt;
|&#039;&#039;&#039;NJD_SIMPLE_LIGHT&#039;&#039;&#039;&lt;br /&gt;
|Simplified lighting calculations (NOT the &amp;quot;Simple light&amp;quot; described earlier)&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|0xC0&lt;br /&gt;
|&amp;lt;del&amp;gt;NJD_BLOCK_LIGHT&amp;lt;/del&amp;gt;&lt;br /&gt;
|Simplified lighting calculations&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
The following custom lights have some leftover code and data in SADX. These also exist in SA1 but they aren&#039;t visible normally because the models that were supposed to be lit by them are rendered with palette lighting.&lt;br /&gt;
&lt;br /&gt;
# Ice Cap background light: &amp;lt;code&amp;gt;NJD_PHONG_POINT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LightInfo&amp;lt;/code&amp;gt; structure at 00C67FA0. Uses angles.&lt;br /&gt;
# &amp;quot;Chaos underlight&amp;quot;: &amp;lt;code&amp;gt;NJD_POINT_LIGHT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; structure at 03D0D5B8. The light is initialized using the function &amp;lt;code&amp;gt;ChaosUnderLightInit&amp;lt;/code&amp;gt; (007AD250) that has a &amp;quot;radius&amp;quot; argument which goes unused in SADX but in SA1 it should be the light range. In Chaos&#039; main functions, the light&#039;s matrix is transformed to match Chaos&#039; position.&lt;br /&gt;
# Some light in Knuckles&#039; story cutscene: &amp;lt;code&amp;gt;NJD_SIMPLE_LIGHT | NJD_LAMBERT_DIR&amp;lt;/code&amp;gt;, function at 006868F0.&lt;br /&gt;
# Lights in Gamma&#039;s briefing cutscene: &amp;lt;code&amp;gt;NJD_SIMPLE_LIGHT | NJD_LAMBERT_DIR&amp;lt;/code&amp;gt;, function at 006F4570. The light is a leftover, but this effect was adapted to palette lighting, and palette-related functions are called here too.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Specular&#039;&#039;&#039; &#039;&#039;&#039;Lighting&#039;&#039;&#039; ===&lt;br /&gt;
The Specular calculation formula for the Ninja Lights is currently unknown for Basic models. For Chunk models (which SA1 DC doesn&#039;t use), the formula was reversed by &#039;&#039;Exant&#039;&#039; for Simple and Easy lights:&lt;br /&gt;
[[File:Ninja Lights 1772333955721.png|none]]&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=PL_Tool&amp;diff=686</id>
		<title>PL Tool</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=PL_Tool&amp;diff=686"/>
		<updated>2026-03-01T03:05:34Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;PL Tool is an editor for Sonic Adventure lighting files (PL and SL files) used by [[Lantern Engine]].&lt;br /&gt;
= Using the Editor =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;figure&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pltool.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
== Palette List ==&lt;br /&gt;
&lt;br /&gt;
PLTool’s main window lists diffuse and specular palettes in the PL file. Click the palette to select it. Right click a palette for a list of options to edit it. You can create palettes with sliders like gradients in Photoshop, generate them like in the Preview prototype of SADX, fill them with a specific color (or a combination of colors), import and export palettes as PNG files, as well as copy and paste them. The &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; palette pair is not stored in the PL file and can be used for backing up palettes before editing them.&lt;br /&gt;
&lt;br /&gt;
* Note: Color Alpha is ignored in the game.&lt;br /&gt;
=== Create Gradient ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;figure&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Creategrad.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
This window lets you create gradients from four colors and an ambient color. Click each color box to set the color and drag the sliders to adjust the position of the two colors in the middle.&lt;br /&gt;
=== Generate Gradient (SADX Preview) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;figure&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Gengrad.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
The [https://hiddenpalace.org/Sonic_Adventure_DX_(Preview_prototype) SADX Preview prototype] has a debug menu that creates gradients. This feature is recreated in PL Tool. The gradients are generated using the following formula:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Result = Ambient + CO1 * Pow((1 - Index / 256), CO1Pow / 100.0) + CO2 * Pow((Index / 256), CO2Pow / 100)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Ambient is the Ambient color R/G/B.&lt;br /&gt;
* CO1 is Color 1 R/G/B.&lt;br /&gt;
* CO2 is Color 2 R/G/B.&lt;br /&gt;
* CO1Pow and CO2Pow are Color 1 and Color 2 power values respectively.&lt;br /&gt;
* Index is the color index in the gradient (0 to 255).&lt;br /&gt;
== Color Selector ==&lt;br /&gt;
&lt;br /&gt;
The trackbar is used to select a specific color in the palette. Its index and R/G/B values are shown on the right side of the status bar. Click the small colored box in the status bar to edit the color.&lt;br /&gt;
&lt;br /&gt;
* Note: Color Alpha is ignored in the game.&lt;br /&gt;
== Menu bar ==&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;&#039;File&#039;&#039;&#039; menu lets you import or export the entire palette list as a single PNG file.&lt;br /&gt;
* The &#039;&#039;&#039;Options&#039;&#039;&#039; menu lets you set a background color for the editor to make it easier to work with light or dark palettes.&lt;br /&gt;
* The &#039;&#039;&#039;Level Select&#039;&#039;&#039; menu allows you to locate the PL file by selecting a stage. If you have opened a PL file previously, the tool will look for PL files in the same folder without an open file dialog.&lt;br /&gt;
* The &#039;&#039;&#039;Format&#039;&#039;&#039; menu allows you to toggle the Endianness of PL and SL files. Leave it on Dreamcast for the Lantern Engine mod.&lt;br /&gt;
* The &#039;&#039;&#039;Tools&#039;&#039;&#039; menu opens the editor for SL files (see below).&lt;br /&gt;
== SL Editor ==&lt;br /&gt;
&lt;br /&gt;
The SL Editor lets you edit light direction and Ninja Lights configuration. &lt;br /&gt;
&lt;br /&gt;
[[File:Sleditor.png]]&lt;br /&gt;
&lt;br /&gt;
* The Environment Data box has the parameters for the Ninja lights. You can click the color box to select the color. &lt;br /&gt;
* The Light Direction box has light rotation Y and Z values. These are used to rotate the default light direction vector. This light direction is used by palette lights and Ninja lights except the DIR light which has a hardcoded light direction. &lt;br /&gt;
* The Free/Slave Data box has additional lighting data. This data doesn’t seem to be used by the game. It may be left over from the Saturn because a menu with similar data was found in a [https://hiddenpalace.org/News/Angels_with_Burning_Hearts:_Burning_Rangers_Prototype Burning Rangers prototype].&lt;br /&gt;
&lt;br /&gt;
{{SAToolsNavbox}}&lt;br /&gt;
&lt;br /&gt;
[[Category:SA1 tools]]&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Sonic_Adventure/Lantern_Engine&amp;diff=685</id>
		<title>Sonic Adventure/Lantern Engine</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Sonic_Adventure/Lantern_Engine&amp;diff=685"/>
		<updated>2026-03-01T03:04:35Z</updated>

		<summary type="html">&lt;p&gt;PkR: Created page with &amp;quot;Lantern (stylized LANTERN) Engine is the internal name of the lighting system used in Sonic Adventure (Dreamcast). It is also the name of a mod that restores said lighting system in the PC version of Sonic Adventure DX.  = Overview of the SA1 Lighting System = The Dreamcast version of Sonic Adventure has a lighting system (referred to internally as “LANTERN”) that consists of two modes:  # Palette lighting using a series of 256-color palettes. # Lights set up by...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lantern (stylized LANTERN) Engine is the internal name of the lighting system used in [[Sonic Adventure]] (Dreamcast). It is also the name of a mod that restores said lighting system in the PC version of Sonic Adventure DX.&lt;br /&gt;
&lt;br /&gt;
= Overview of the SA1 Lighting System =&lt;br /&gt;
The Dreamcast version of Sonic Adventure has a lighting system (referred to internally as “LANTERN”) that consists of two modes:&lt;br /&gt;
&lt;br /&gt;
# Palette lighting using a series of 256-color palettes.&lt;br /&gt;
# Lights set up by the Dreamcast’s Ninja library ([[Ninja Lights|Ninja]] [[Ninja Lights|Lights]]).&lt;br /&gt;
&lt;br /&gt;
Lighting information for each level is stored in a pair of files: the PL file (PL_....BIN) contains the palettes, and the SL file (SL_....bin) contains light direction and data for setting up the Ninja Lights.&lt;br /&gt;
&lt;br /&gt;
The [https://github.com/michael-fadely/sadx-dc-lighting Lantern Engine mod] for Sonic Adventure DX PC is a reimplementation of palette lighting for the PC port of SADX. At the moment it does not implement the Ninja Lights.&lt;br /&gt;
&lt;br /&gt;
== Palette Lighting ==&lt;br /&gt;
&lt;br /&gt;
=== Brightness Index Calculation ===&lt;br /&gt;
The palette-based system gives each vertex in the scene a “brightness index”, which is a value in the range of 0 to 255 used to select a color in a palette to set as vertex color. The brightness index is calculated using the following formula:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;1 - ((dot(normal, light direction) + 1) / 2)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;dot&amp;lt;/code&amp;gt; is dot product and &amp;lt;code&amp;gt;normal&amp;lt;/code&amp;gt; is vertex normal.&lt;br /&gt;
&lt;br /&gt;
The result is multiplied by 255 to get the color index in the palette. If we visualized brightness indices (from white being maximum brightness to black being completely unlit), it would look something like this:&lt;br /&gt;
[[File:Brightness.png|none|thumb|Brightness indices visualized: from white (fullbright) to black (fully dark).]]&lt;br /&gt;
&lt;br /&gt;
=== Diffuse and Specular Lighting ===&lt;br /&gt;
LANTERN palettes are applied in pairs to create diffuse and specular lighting.&lt;br /&gt;
&lt;br /&gt;
* Diffuse color is the color that is calculated by multiplying the original color with the color in the diffuse palette. It works like the “Multiply” blending mode in Photoshop.&lt;br /&gt;
* Specular color is additive, so it works like the “Add” blending mode in Photoshop.&lt;br /&gt;
&lt;br /&gt;
Making the diffuse color brighter makes the result closer to the original texture’s color. Making the specular color brighter adds to the brightness of the resulting color directly, so white diffuse + black specular is effectively the same as not applying any lighting at all, and white specular would make the vertex completely white regardless of the texture and diffuse color. Normally diffuse lighting is used to give the entire model or area a “base” color, while specular lighting is used to add gloss.&lt;br /&gt;
[[File:Palettesample.png|none|thumb|Diffuse palette samples (image by Speeps)]]&lt;br /&gt;
&lt;br /&gt;
=== Palette Selection ===&lt;br /&gt;
The PL file can store up to eight pairs of diffuse/specular palettes, although only up to six pairs are used normally. There are several variables the game relies on to select which palettes to apply to a specific model:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1. Light type&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a variable set in code before rendering the model. The light type value determines which diffuse palette is used by the model:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Value&lt;br /&gt;
!Description&lt;br /&gt;
!Diffuse Palette&lt;br /&gt;
!Specular Palette&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Used by the majority of models in the game except characters and bosses.&lt;br /&gt;
|0&lt;br /&gt;
|0 or 1&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Used by characters and cutscene models.&lt;br /&gt;
|2&lt;br /&gt;
|2 or 3&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Used by some bosses and for blending effects.&lt;br /&gt;
|4&lt;br /&gt;
|4 or 5&lt;br /&gt;
|}&lt;br /&gt;
The majority of models in the game outside cutscenes use the level/object light type 0. These are the palettes you see on level pieces and most objects.&lt;br /&gt;
&lt;br /&gt;
Character/NPC models and models used in cutscenes generally use the character/event light type 2, although there are some exceptions. For example, Amy’s Warrior Feather and some parts of Gamma’s body that are rendered as separate models (such as the Laser Scope) use the level/object light type 0 outside cutscenes. The gameplay models in Sky Chase use the level/object light type 0 despite being character-related; however, models involving the Tornado in Sky Chase cutscenes use the character light type 2. It happens the other way around as well: some non-character objects that would normally be using level/object palettes (such as floating meteors near the end of Twinkle Park Act 1) set the character light type so they also get character lighting, but this is uncommon.&lt;br /&gt;
&lt;br /&gt;
The boss light type 4 is only used by a few models in the game. Diffuse 4 and Specular 5 are used by Chaos 2, Chaos 6 and Perfect Chaos. Diffuse 4/Specular 4 and Diffuse 5/Specular 5 are also used by the transition effect in Mystic Ruins Past when the Emerald Altar is on fire. The palettes blend between each other to create a burning fire effect.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2. Material flags&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Material flags influence palette selection in the following ways:&lt;br /&gt;
&lt;br /&gt;
* If a mesh’s material has the “ignore lighting” flag (&amp;lt;code&amp;gt;NJD_FLAG_IGNORE_LIGHT&amp;lt;/code&amp;gt;), the mesh is not palettized and the fullbright texture is used as-is. Neither the diffuse nor the specular palette is applied to the mesh, but the rest of the meshset may be palettized depending on whether or not the remaining materials have the “ignore lighting” flag.&lt;br /&gt;
* If the model’s first material has the “ignore specular” flag (&amp;lt;code&amp;gt;NJD_FLAG_IGNORE_SPECULAR&amp;lt;/code&amp;gt;), the entire model’s specular palette index is the same as the diffuse palette index (e.g. Diffuse 0, Specular 0).&lt;br /&gt;
* If the model’s first material doesn’t have “ignore specular”, the specular palette index is the diffuse index + 1 (e.g. Diffuse 0, Specular 1).&lt;br /&gt;
&lt;br /&gt;
Note that only the first mesh’s material in the model affects specular palette selection, and all other meshes follow it regardless of whether they have “ignore specular” or not. Specular palette selection is consistent within a single model, but if the model has child or sibling models those are processed separately unlike the light type. So it is possible to have a model (e.g. Tails) that has child models with a different specular palette (Tails’ shoes). They would still use the same diffuse palette, however, as they would have the same light type as the parent model.&lt;br /&gt;
&lt;br /&gt;
Sometimes the game forcibly adds or removes the “ignore specular” flag or sets a specific light type when rendering certain models. If you want to change palette selection in these cases, you would need to change/disable the code doing that, or use Lantern API to register those models’ materials for arbitrary palette selection.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;3. White diffuse&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In the Dreamcast version of SA1, if a mesh in a model has a material with the “ignore lighting” flag, the remaining meshes after it may get the fullbright diffuse palette (as if they were ignoring lighting), but keep the specular palette. The Lantern Engine mod does not do this by default. Dreamcast Conversion has an option to enable white diffuse.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;4. Palette blending&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are cases when the game swaps or mixes different palettes for some special effects:&lt;br /&gt;
&lt;br /&gt;
* The Past fire effect creates the level/object palettes (Diffuse 0/Specular 0) by mixing Diffuse 4/Specular 4 and Diffuse 5/Specular 5 using a blending coefficient. The Lantern Engine mod blends between Diffuse 0/Specular 0 and Diffuse 5/Specular 5 instead, which are identical to Diffuse 0/Specular 0 in the PL file anyway.&lt;br /&gt;
* Sky Deck Acts 1 and 2 swap palettes when the Egg Carrier changes altitude. Palettes in &amp;lt;code&amp;gt;PL_60B&amp;lt;/code&amp;gt; are used normally, and palettes from &amp;lt;code&amp;gt;PL_61B&amp;lt;/code&amp;gt; are used when the Egg Carrier descends into the clouds. While the original game only swaps the palettes, the Lantern Engine mod actually blends between them.&lt;br /&gt;
* The Egg Viper boss fight blends palettes in &amp;lt;code&amp;gt;PL_M0B.BIN&amp;lt;/code&amp;gt; with specific colors (white, red and cyan).&lt;br /&gt;
* In Casinopolis Act 1, when Sonic goes to pinball areas the character specular palette blends with white, making character lighting brighter as Sonic is floating before getting teleported to the pinball field.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;5. Palette selection example&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Here is a simple example of palette selection based on Emerald Coast. Color-coded specular palettes are used to tell which light type is being used by the model:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Palette masks ingame&lt;br /&gt;
![[File:Mask_test.png]]&lt;br /&gt;
![[File:Mask_edit.png|none|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== List of PL files ===&lt;br /&gt;
The game loads PL/SL files using a naming scheme that roughly matches the game’s internal level list. The first number/letter after “PL_” is the level ID, the number after that is usually act number, but there are some exceptions. Here is a list of PL files and stages that load them:&lt;br /&gt;
&lt;br /&gt;
==== Action Stages ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Filename&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|PL_10B.BIN&lt;br /&gt;
|Emerald Coast (all acts), Egg Carrier Outside when the Egg Carrier has sunk&lt;br /&gt;
|-&lt;br /&gt;
|PL_20B.BIN&lt;br /&gt;
|Windy Valley Act 1&lt;br /&gt;
|-&lt;br /&gt;
|PL_21B.BIN&lt;br /&gt;
|Windy Valley Act 2&lt;br /&gt;
|-&lt;br /&gt;
|PL_22B.BIN&lt;br /&gt;
|Windy Valley Act 3&lt;br /&gt;
|-&lt;br /&gt;
|PL_30B.BIN&lt;br /&gt;
|Twinkle Park Act 1&lt;br /&gt;
|-&lt;br /&gt;
|PL_31B.BIN&lt;br /&gt;
|Twinkle Park Act 2&lt;br /&gt;
|-&lt;br /&gt;
|PL_32B.BIN&lt;br /&gt;
|Twinkle Park Act 3&lt;br /&gt;
|-&lt;br /&gt;
|PL_40B.BIN&lt;br /&gt;
|Speed Highway Act 1&lt;br /&gt;
|-&lt;br /&gt;
|PL_41B.BIN&lt;br /&gt;
|Speed Highway Act 2&lt;br /&gt;
|-&lt;br /&gt;
|PL_42B.BIN&lt;br /&gt;
|Speed Highway Act 3&lt;br /&gt;
|-&lt;br /&gt;
|PL_50B.BIN&lt;br /&gt;
|Red Mountain Act 1&lt;br /&gt;
|-&lt;br /&gt;
|PL_51B.BIN&lt;br /&gt;
|Red Mountain Act 2&lt;br /&gt;
|-&lt;br /&gt;
|PL_52B.BIN&lt;br /&gt;
|Red Mountain Act 3 (Knuckles)&lt;br /&gt;
|-&lt;br /&gt;
|PL_60B.BIN&lt;br /&gt;
|Character select screen, Sky Deck normal (Acts 1 and 2), Sky Deck Act 3&lt;br /&gt;
|-&lt;br /&gt;
|PL_61B.BIN&lt;br /&gt;
|Sky Deck dark (Acts 1 and 2)&lt;br /&gt;
|-&lt;br /&gt;
|PL_70B.BIN&lt;br /&gt;
|Lost World Act 1&lt;br /&gt;
|-&lt;br /&gt;
|PL_71B.BIN&lt;br /&gt;
|Lost World Acts 2 and 3&lt;br /&gt;
|-&lt;br /&gt;
|PL_80B.BIN&lt;br /&gt;
|Ice Cap Act 1&lt;br /&gt;
|-&lt;br /&gt;
|PL_81B.BIN&lt;br /&gt;
|Ice Cap Act 2&lt;br /&gt;
|-&lt;br /&gt;
|PL_82B.BIN&lt;br /&gt;
|Ice Cap Act 3&lt;br /&gt;
|-&lt;br /&gt;
|PL_83B.BIN&lt;br /&gt;
|Ice Cap Act 4 (Big)&lt;br /&gt;
|-&lt;br /&gt;
|PL_90B.BIN&lt;br /&gt;
|Casinopolis Act 1&lt;br /&gt;
|-&lt;br /&gt;
|PL_91B.BIN&lt;br /&gt;
|Casinopolis Act 2 (Sewers)&lt;br /&gt;
|-&lt;br /&gt;
|PL_92B.BIN&lt;br /&gt;
|Casinopolis Act 3 (Sonic pinball)&lt;br /&gt;
|-&lt;br /&gt;
|PL_93B.BIN&lt;br /&gt;
|Casinopolis Act 4 (NiGHTS pinball)&lt;br /&gt;
|-&lt;br /&gt;
|PL_A0B.BIN&lt;br /&gt;
|Final Egg Act 1&lt;br /&gt;
|-&lt;br /&gt;
|PL_A1B.BIN&lt;br /&gt;
|Final Egg Act 2&lt;br /&gt;
|-&lt;br /&gt;
|PL_A2B.BIN&lt;br /&gt;
|Final Egg Act 3 (Sonic/Gamma)&lt;br /&gt;
|-&lt;br /&gt;
|PL_C0B.BIN&lt;br /&gt;
|Hot Shelter Act 1&lt;br /&gt;
|-&lt;br /&gt;
|PL_C1B.BIN&lt;br /&gt;
|Hot Shelter Act 2&lt;br /&gt;
|-&lt;br /&gt;
|PL_C2B.BIN&lt;br /&gt;
|Hot Shelter Act 3 (Gamma)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Bosses ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Filename&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|PL_F0B.BIN&lt;br /&gt;
|Chaos 0&lt;br /&gt;
|-&lt;br /&gt;
|PL_G0B.BIN&lt;br /&gt;
|Chaos 2&lt;br /&gt;
|-&lt;br /&gt;
|PL_H0B.BIN&lt;br /&gt;
|Chaos 4&lt;br /&gt;
|-&lt;br /&gt;
|PL_I0B.BIN&lt;br /&gt;
|Chaos 6&lt;br /&gt;
|-&lt;br /&gt;
|PL_J0B.BIN&lt;br /&gt;
|Perfect Chaos (first 3 hits)&lt;br /&gt;
|-&lt;br /&gt;
|PL_J1B.BIN&lt;br /&gt;
|Perfect Chaos 2nd phase&lt;br /&gt;
|-&lt;br /&gt;
|PL_K0B.BIN&lt;br /&gt;
|Egg Hornet&lt;br /&gt;
|-&lt;br /&gt;
|PL_M0B.BIN&lt;br /&gt;
|Egg Viper&lt;br /&gt;
|-&lt;br /&gt;
|PL_N0B.BIN&lt;br /&gt;
|Zero&lt;br /&gt;
|-&lt;br /&gt;
|PL_O0B.BIN&lt;br /&gt;
|E-101 Beta&lt;br /&gt;
|-&lt;br /&gt;
|PL_P0B.BIN&lt;br /&gt;
|E-101R&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Adventure Fields ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Filename&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|PL_Q1B.BIN&lt;br /&gt;
|Station Square Evening (All acts)&lt;br /&gt;
|-&lt;br /&gt;
|PL_Q3B.BIN&lt;br /&gt;
|Egg Walker, Station Square Night (All acts)&lt;br /&gt;
|-&lt;br /&gt;
|PL_Q4B.BIN&lt;br /&gt;
|Station Square Day (All acts)&lt;br /&gt;
|-&lt;br /&gt;
|PL_T0B.BIN&lt;br /&gt;
|Egg Carrier Outside (before the Egg Carrier sinks)&lt;br /&gt;
|-&lt;br /&gt;
|PL_T2B.BIN&lt;br /&gt;
|Egg Carrier Private Room&lt;br /&gt;
|-&lt;br /&gt;
|PL_T3B.BIN&lt;br /&gt;
|Egg Carrier Captain’s Room&lt;br /&gt;
|-&lt;br /&gt;
|PL_T5B.BIN&lt;br /&gt;
|Egg Carrier Pool&lt;br /&gt;
|-&lt;br /&gt;
|PL_W0B.BIN&lt;br /&gt;
|Egg Carrier Ammunition Room&lt;br /&gt;
|-&lt;br /&gt;
|PL_W1B.BIN&lt;br /&gt;
|Egg Carrier Bridge&lt;br /&gt;
|-&lt;br /&gt;
|PL_W2B.BIN&lt;br /&gt;
|Egg Carrier Hedgehog Hammer Room&lt;br /&gt;
|-&lt;br /&gt;
|PL_W3B.BIN&lt;br /&gt;
|Egg Carrier Prison&lt;br /&gt;
|-&lt;br /&gt;
|PL_W4B.BIN&lt;br /&gt;
|Egg Carrier Reservoir Room&lt;br /&gt;
|-&lt;br /&gt;
|PL_W5B.BIN&lt;br /&gt;
|Egg Carrier Chao Garden transporter&lt;br /&gt;
|-&lt;br /&gt;
|PL_X0B.BIN&lt;br /&gt;
|Mystic Ruins Day (Station, Angel Island and Jungle)&lt;br /&gt;
|-&lt;br /&gt;
|PL_X1B.BIN&lt;br /&gt;
|Mystic Ruins Evening (Station, Angel Island and Jungle)&lt;br /&gt;
|-&lt;br /&gt;
|PL_X2B.BIN&lt;br /&gt;
|Mystic Ruins Night (Station, Angel Island and Jungle)&lt;br /&gt;
|-&lt;br /&gt;
|PL_X3B.BIN&lt;br /&gt;
|Mystic Ruins Eggman’s Base&lt;br /&gt;
|-&lt;br /&gt;
|PL_Y0B.BIN&lt;br /&gt;
|Past Act 1 (Echidna City)&lt;br /&gt;
|-&lt;br /&gt;
|PL_Y1B.BIN&lt;br /&gt;
|Past Act 2 (Emerald Altar)&lt;br /&gt;
|-&lt;br /&gt;
|PL_Y2B.BIN&lt;br /&gt;
|Past Act 3 (Emerald Altar on fire)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Subgames ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Filename&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|PL_Z0B.BIN&lt;br /&gt;
|Twinkle Circuit&lt;br /&gt;
|-&lt;br /&gt;
|PL1A0B.BIN&lt;br /&gt;
|Sky Chase Act 1&lt;br /&gt;
|-&lt;br /&gt;
|PL1B0B.BIN&lt;br /&gt;
|Sky Chase Act 2&lt;br /&gt;
|-&lt;br /&gt;
|PL1C0B.BIN&lt;br /&gt;
|Sand Hill&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Chao ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Filename&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|PL1D0B.BIN&lt;br /&gt;
|Station Square Chao Garden&lt;br /&gt;
|-&lt;br /&gt;
|PL1E0B.BIN&lt;br /&gt;
|Egg Carrier Chao Garden&lt;br /&gt;
|-&lt;br /&gt;
|PL1F0B.BIN&lt;br /&gt;
|Mystic Ruins Chao Garden Day&lt;br /&gt;
|-&lt;br /&gt;
|PL1F1B.BIN&lt;br /&gt;
|Mystic Ruins Chao Garden Evening (unused in the original game, used in SADX Lantern Engine)&lt;br /&gt;
|-&lt;br /&gt;
|PL1F2B.BIN&lt;br /&gt;
|Mystic Ruins Chao Garden Night (unused in the original game, used in SADX Lantern Engine)&lt;br /&gt;
|-&lt;br /&gt;
|PL1G0B.BIN&lt;br /&gt;
|Chao Stadium&lt;br /&gt;
|-&lt;br /&gt;
|PL1G1B.BIN&lt;br /&gt;
|Chao Race&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Unused ====&lt;br /&gt;
The following files are present on the disk, but not used by the game:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Filename&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|PL_9MB.BIN&lt;br /&gt;
|An alternative version of the Casinopolis sewers palette that is never applied.&lt;br /&gt;
It was originally supposed to be used by an object called MUD. The object would gradually change character palettes to make them darker.&lt;br /&gt;
|-&lt;br /&gt;
|PL_MRD.BIN&lt;br /&gt;
|Possibly alternative Mystic Ruins Day palette&lt;br /&gt;
|-&lt;br /&gt;
|PL_MRE.BIN&lt;br /&gt;
|Possibly alternative Mystic Ruins Evening palette&lt;br /&gt;
|-&lt;br /&gt;
|PL_MRN.BIN&lt;br /&gt;
|Possibly alternative Mystic Ruins Night palette&lt;br /&gt;
|-&lt;br /&gt;
|PL_T1B.BIN&lt;br /&gt;
|Egg Carrier related, might have been used in the early transformation cutscene&lt;br /&gt;
|-&lt;br /&gt;
|PL_T4B.BIN&lt;br /&gt;
|Egg Carrier related, possibly the lighting used for some endgame credits images&lt;br /&gt;
|-&lt;br /&gt;
|PL1D1B.BIN&lt;br /&gt;
|Possibly Station Square Chao Garden Night&lt;br /&gt;
|-&lt;br /&gt;
|PL1E1B.BIN&lt;br /&gt;
|Egg Carrier Chao Garden Evening&lt;br /&gt;
|-&lt;br /&gt;
|PL1E2B.BIN&lt;br /&gt;
|Egg Carrier Chao Garden Night&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== SL Files ==&lt;br /&gt;
SL files use the same naming scheme as the PL files. They store the following data:&lt;br /&gt;
&lt;br /&gt;
* Light rotation: Y and Z rotation values that are applied to the default light direction, which is a downward facing vector (0, -1, 0).&lt;br /&gt;
* Lighting configuration for models that use [[Ninja Lights|Ninja]] [[Ninja Lights|Lights]] instead of palette lighting.&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Ninja_Lights&amp;diff=684</id>
		<title>Ninja Lights</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Ninja_Lights&amp;diff=684"/>
		<updated>2026-03-01T03:03:52Z</updated>

		<summary type="html">&lt;p&gt;PkR: Created page with &amp;quot;&amp;quot;Ninja Lights&amp;quot; refers to the lighting used by the Ninja library of the Katana SDK.  == Ninja Lights in Sonic Adventure == &amp;#039;&amp;#039;&amp;#039;Note: Ninja Lights are not implemented in the Lantern Engine mod, so the information below is irrelevant to the PC version.&amp;#039;&amp;#039;&amp;#039; Sonic Adventure (Dreamcast) uses two lighting systems: the palette-based LANTERN system and the Ninja Lights. The game&amp;#039;s model rendering functions have &amp;quot;Lantern&amp;quot; and &amp;quot;Ninja&amp;quot; variants, and depending on...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;quot;Ninja Lights&amp;quot; refers to the lighting used by the Ninja library of the [[Katana SDK]].&lt;br /&gt;
&lt;br /&gt;
== Ninja Lights in Sonic Adventure ==&lt;br /&gt;
&#039;&#039;&#039;Note: Ninja Lights are not implemented in the Lantern Engine mod, so the information below is irrelevant to the PC version.&#039;&#039;&#039;&lt;br /&gt;
Sonic Adventure (Dreamcast) uses two lighting systems: the palette-based [[Lantern Engine|LANTERN system]] and the Ninja Lights. The game&#039;s model rendering functions have &amp;quot;Lantern&amp;quot; and &amp;quot;Ninja&amp;quot; variants, and depending on the function used the game can either draw the model with palette lighting or use Ninja Lights.&lt;br /&gt;
&lt;br /&gt;
The SL file contains data for setting up the Ninja lights. This information consists of: light color (three floats for R/G/B), diffuse multiplier, specular power and ambient multiplier. Both diffuse and specular components are the same color. The “ignore specular” material flag disables the specular component per mesh.&lt;br /&gt;
&lt;br /&gt;
=== Types of Ninja Lights Setup ===&lt;br /&gt;
There are three types of lights used for non-palettized models in the game:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Lighting Setup&lt;br /&gt;
!Description&lt;br /&gt;
!Used by&lt;br /&gt;
|-&lt;br /&gt;
|Two Ninja Lights&lt;br /&gt;
|Non-palettized lighting that uses two Ninja Lights. These lights use &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; structures described in the Katana SDK. One is set up using the parameters in the SL file (let’s call it the &amp;lt;code&amp;gt;ENV&amp;lt;/code&amp;gt; Light), and the other is set up in code, usually in level binaries (let’s call it the &amp;lt;code&amp;gt;DIR&amp;lt;/code&amp;gt; light). The &amp;lt;code&amp;gt;ENV&amp;lt;/code&amp;gt; light has one configurable color that is shared for diffuse and specular, the &amp;lt;code&amp;gt;DIR&amp;lt;/code&amp;gt; light can have different diffuse and specular color (though the game doesn’t seem to use that). It can also have a different light direction.&lt;br /&gt;
|Common switch, Hint monitor, OEggKanban (glowing Eggman logo in Final Egg, tube parts only), Chaos puddle in some cutscenes, Aoki Switch (top)&lt;br /&gt;
|-&lt;br /&gt;
|Simple Ninja Light&lt;br /&gt;
|Non-palettized lighting that uses one Ninja Light using the parameters from the SL file except the color, which is always white.&lt;br /&gt;
|Rock bits in Red Mountain, non-Jewel Chao, Master Emerald pieces, Froggy in Gamma’s Emerald Coast&lt;br /&gt;
|-&lt;br /&gt;
|Easy Light&lt;br /&gt;
|Non-palettized lighting that sets up the Easy Light (not &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;) using the parameters from the SL file. The Easy light is described in the Katana SDK. It doesn’t support specular lighting.&lt;br /&gt;
|Snowboard, OSandSwitch (Sand Hill switch), shadow blob, Chambr (chambers with opening doors in Sky Deck), debug objects, Aoki Switch (bottom), E101’s missiles, Hedgehog Hammer targets&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rendering Functions and their SADX Counterparts ===&lt;br /&gt;
In SA1, most models were rendered with palette lighting using the game&#039;s custom function, but some models were rendered by calling Ninja drawing functions directly, which made them use the Ninja lights system. There are three light setups depending on the specific variation of the Ninja draw function:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Light setup&lt;br /&gt;
!Functions in SADX (PC, 2004)&lt;br /&gt;
!Comment&lt;br /&gt;
|-&lt;br /&gt;
|Regular&lt;br /&gt;
|&amp;lt;code&amp;gt;njDrawModel&amp;lt;/code&amp;gt; (0077EF70)&lt;br /&gt;
|Allows to use multiple &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;s of various types (directional, point, spot). Specular is supported.&lt;br /&gt;
|-&lt;br /&gt;
|Simple&lt;br /&gt;
|&amp;lt;code&amp;gt;___SAnjSimpleDrawModel&amp;lt;/code&amp;gt; (00408520), &amp;lt;code&amp;gt;__SAnjSimpleDrawObject&amp;lt;/code&amp;gt; (0040A130)&lt;br /&gt;
|Only the first registered &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; can be used. It is set up as a directional light, and intensity and color settings cannot be adjusted. Specular is supported.&lt;br /&gt;
|-&lt;br /&gt;
|Easy&lt;br /&gt;
|&amp;lt;code&amp;gt;njEasyDrawObject&amp;lt;/code&amp;gt; (0040A100), &amp;lt;code&amp;gt;njEasyDrawModel&amp;lt;/code&amp;gt; (004084F0), &amp;lt;code&amp;gt;njEasyDrawMotion&amp;lt;/code&amp;gt; (00406FA0), &amp;lt;code&amp;gt;njEasyDrawShapeMotion&amp;lt;/code&amp;gt; (00406FE0)&lt;br /&gt;
|Uses one &amp;quot;easy&amp;quot; light (not &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;).  Specular is not supported. From the SDK: The light vector uses the screen space coordinate system. E.g. if set up like &amp;lt;code&amp;gt;njSetEasyLight( 0.0f, 0.0f, 1.0f );&amp;lt;/code&amp;gt;, the light source will always be in front of the screen. To set the light source in 3D space, they must be converted with the current matrix:&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
light.x = LIGHT3D_X; light.y = LIGHT3D_Y;&lt;br /&gt;
light.z = LIGHT3D_Z; njCalcVector( NULL, &amp;amp;light, &amp;amp;lwork );&lt;br /&gt;
njSetEasyLight( lwork.x, lwork.y, lworkz );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;After this, the Easy light source will be at &amp;lt;code&amp;gt;LIGHT3D_X,&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;LIGHT3D_Y, LIGHT3D_Z&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
The SADX functions are a rough match since SADX changed draw functions for a lot of objects, and all that is left is some wrapper functions that call a more generic draw function:&lt;br /&gt;
&lt;br /&gt;
# The Regular functions are difficult to tell from the paletted functions, so the above table is an approximation.&lt;br /&gt;
# The Easy functions are mostly still there.&lt;br /&gt;
# The Simple functions only have two stubs which aren&#039;t called by anything other than the Chao Name Machine, which doesn&#039;t match SA1.&lt;br /&gt;
&lt;br /&gt;
=== Lighting Data ===&lt;br /&gt;
The data sources for the lights are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Light&lt;br /&gt;
!Type&lt;br /&gt;
!Direction&lt;br /&gt;
!Color&lt;br /&gt;
!Diffuse, specular, ambient intensity&lt;br /&gt;
|-&lt;br /&gt;
|Regular - light 1&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|-&lt;br /&gt;
|Regular - light 2&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightDirection&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightColor&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|&amp;lt;code&amp;gt;njSetLightIntensity&amp;lt;/code&amp;gt; called in the skybox display function&lt;br /&gt;
|-&lt;br /&gt;
|Simple&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|White (in SA1 anyway)&lt;br /&gt;
|From the SL file&lt;br /&gt;
|-&lt;br /&gt;
|Easy&lt;br /&gt;
|Directional&lt;br /&gt;
|&amp;lt;code&amp;gt;(0, -1, 0)&amp;lt;/code&amp;gt; rotated using &amp;lt;code&amp;gt;RY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RZ&amp;lt;/code&amp;gt; values from the SL file&lt;br /&gt;
|From the SL file&lt;br /&gt;
|From the SL file, no specular&lt;br /&gt;
|}&lt;br /&gt;
In addition to these lights, there can be custom lights set up by objects&#039; code, which will affect all objects rendered with Regular functions. These custom lights can be directional, spot or point, with or without specular. The custom lights are created with the function &amp;lt;code&amp;gt;le_CreateLight&amp;lt;/code&amp;gt; (0040A510 in SADX) and deleted with the function &amp;lt;code&amp;gt;le_DeleteLight&amp;lt;/code&amp;gt; (0040A550 in SADX).&lt;br /&gt;
&lt;br /&gt;
In the Dreamcast version, these functions use pointers to actual &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt;s. In SADX, the Ninja Lights system appears to have been replaced by a system using the structure &amp;lt;code&amp;gt;LE_LIGHT_ENV&amp;lt;/code&amp;gt; (what is also known as &amp;quot;Stage lights&amp;quot;). Instead of specific pointers, there is now an array of four &amp;quot;current stage lights&amp;quot; called &amp;lt;code&amp;gt;le_env&amp;lt;/code&amp;gt; at 03ABD9F8. It also has a corresponding array of four Ninja light flags &amp;lt;code&amp;gt;le_env_typ&amp;lt;/code&amp;gt; at 03ABDBB8. So instead of &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; pointers, the light create/delete functions manipulate data in these arrays in SADX.&lt;br /&gt;
&lt;br /&gt;
Interestingly enough, the data for the light &amp;quot;Regular- light 2&amp;quot; is completely the same in SADX. It&#039;s still set up by the skybox display functions which call &amp;lt;code&amp;gt;njSetLightColor&amp;lt;/code&amp;gt; etc. with the same arguments as the Dreamcast version, so basically we don&#039;t need the data from this post. However, now that these functions are redirected to modify the first entry in the &amp;lt;code&amp;gt;le_env&amp;lt;/code&amp;gt; array, this data is overwritten every time a stage loads. That is happening because the function &amp;lt;code&amp;gt;le_set_env&amp;lt;/code&amp;gt; (0040A95) copies over all light data from the SADX stage lights array (00900E88), which happens every time a light type is set and whenever a new level loads.&lt;br /&gt;
&lt;br /&gt;
The following behavior of Ninja Lights is different from palette lighting:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;NJD_FLAG_IGNORE_SPECULAR&amp;lt;/code&amp;gt; disables specular lighting &#039;&#039;completely&#039;&#039; (per material).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;NJD_FLAG_USE_FLAT&amp;lt;/code&amp;gt; enables flat shading (used by Master Emerald pieces).&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Custom&#039;&#039;&#039; &#039;&#039;&#039;Lights&#039;&#039;&#039; ===&lt;br /&gt;
There&#039;s a leftover function in SADX that creates custom lights associated with specific objects: &amp;lt;code&amp;gt;asSetLight&amp;lt;/code&amp;gt; at 0040ADC0. It uses a &amp;lt;code&amp;gt;taskwk&amp;lt;/code&amp;gt; pointer, an &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; pointer and a pointer to a structure called &amp;lt;code&amp;gt;LightInfo&amp;lt;/code&amp;gt;:&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct LightInfo &lt;br /&gt;
{&lt;br /&gt;
int lsrc; // Ninja light flags &lt;br /&gt;
float spc; &lt;br /&gt;
float dif; &lt;br /&gt;
float amb; &lt;br /&gt;
NJS_ARGB argb; &lt;br /&gt;
NJS_POINT3 pos; // Light position (for spot and point lights) &lt;br /&gt;
NJS_POINT3 vec; // Light direction &lt;br /&gt;
float nrang; // Distance at which light source attenuation begins &lt;br /&gt;
float frang; // Distance to cut the effect of the light source (range) &lt;br /&gt;
int iang; // The angle at which the specular or spotlight is at maximum intensity &lt;br /&gt;
int oang; // The angle at which the specular or spotlight effect ceases &lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;The following Ninja light flags can be used. The ones in bold are used in SA1, and the ones crossed out are unlikely to have been used in SA1.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Flags&lt;br /&gt;
!Flag name&lt;br /&gt;
!Light type&lt;br /&gt;
!Ambient&lt;br /&gt;
!Diffuse&lt;br /&gt;
!Specular&lt;br /&gt;
|-&lt;br /&gt;
|0x01&lt;br /&gt;
|NJD_AMBIENT&lt;br /&gt;
|Ambient&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x02&lt;br /&gt;
|NJD_DIR_LIGHT&lt;br /&gt;
|Directional&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x03&lt;br /&gt;
|&#039;&#039;&#039;NJD_LAMBERT_DIR&#039;&#039;&#039;&lt;br /&gt;
|Directional&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x04&lt;br /&gt;
|&#039;&#039;&#039;NJD_POINT_LIGHT&#039;&#039;&#039;&lt;br /&gt;
|Point&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x05&lt;br /&gt;
|NJD_LAMBERT_POINT&lt;br /&gt;
|Point&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x08&lt;br /&gt;
|NJD_SPOT_LIGHT&lt;br /&gt;
|Spot&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|×&lt;br /&gt;
|-&lt;br /&gt;
|0x10&lt;br /&gt;
|NJD_SPEC_DIR&lt;br /&gt;
|Directional&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x13&lt;br /&gt;
|NJD_PHONG_DIR&lt;br /&gt;
|Directional&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x20&lt;br /&gt;
|NJD_SPEC_POINT&lt;br /&gt;
|Point&lt;br /&gt;
|×&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x25&lt;br /&gt;
|&#039;&#039;&#039;NJD_PHONG_POINT&#039;&#039;&#039;&lt;br /&gt;
|Point&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|〇&lt;br /&gt;
|-&lt;br /&gt;
|0x40&lt;br /&gt;
|&amp;lt;del&amp;gt;NJD_USER_LIGHT&amp;lt;/del&amp;gt;&lt;br /&gt;
|Call a custom callback function&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|0x80&lt;br /&gt;
|&#039;&#039;&#039;NJD_SIMPLE_LIGHT&#039;&#039;&#039;&lt;br /&gt;
|Simplified lighting calculations (NOT the &amp;quot;Simple light&amp;quot; described earlier)&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|0xC0&lt;br /&gt;
|&amp;lt;del&amp;gt;NJD_BLOCK_LIGHT&amp;lt;/del&amp;gt;&lt;br /&gt;
|Simplified lighting calculations&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
The following custom lights have some leftover code and data in SADX. These also exist in SA1 but they aren&#039;t visible normally because the models that were supposed to be lit by them are rendered with palette lighting.&lt;br /&gt;
&lt;br /&gt;
# Ice Cap background light: &amp;lt;code&amp;gt;NJD_PHONG_POINT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LightInfo&amp;lt;/code&amp;gt; structure at 00C67FA0. Uses angles.&lt;br /&gt;
# &amp;quot;Chaos underlight&amp;quot;: &amp;lt;code&amp;gt;NJD_POINT_LIGHT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NJS_LIGHT&amp;lt;/code&amp;gt; structure at 03D0D5B8. The light is initialized using the function &amp;lt;code&amp;gt;ChaosUnderLightInit&amp;lt;/code&amp;gt; (007AD250) that has a &amp;quot;radius&amp;quot; argument which goes unused in SADX but in SA1 it should be the light range. In Chaos&#039; main functions, the light&#039;s matrix is transformed to match Chaos&#039; position.&lt;br /&gt;
# Some light in Knuckles&#039; story cutscene: &amp;lt;code&amp;gt;NJD_SIMPLE_LIGHT | NJD_LAMBERT_DIR&amp;lt;/code&amp;gt;, function at 006868F0.&lt;br /&gt;
# Lights in Gamma&#039;s briefing cutscene: &amp;lt;code&amp;gt;NJD_SIMPLE_LIGHT | NJD_LAMBERT_DIR&amp;lt;/code&amp;gt;, function at 006F4570. The light is a leftover, but this effect was adapted to palette lighting, and palette-related functions are called here too.&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;Specular&#039;&#039;&#039; &#039;&#039;&#039;Lighting&#039;&#039;&#039; ===&lt;br /&gt;
The Specular calculation formula for the Ninja Lights is currently unknown for Basic models. For Chunk models (which SA1 DC doesn&#039;t use), the formula was reversed by &#039;&#039;Exant&#039;&#039; for Simple and Easy lights:&lt;br /&gt;
[[File:Ninja Lights 1772333955721.png|none]]&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:Ninja_Lights_1772333955721.png&amp;diff=683</id>
		<title>File:Ninja Lights 1772333955721.png</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:Ninja_Lights_1772333955721.png&amp;diff=683"/>
		<updated>2026-03-01T02:59:17Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=682</id>
		<title>Sonic Adventure Autodemo/Restoration</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=682"/>
		<updated>2026-02-28T10:19:06Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is dedicated to projects that restore content and functionality in the Autodemo prototype of Sonic Adventure (Dreamcast). For Sonic Adventure PX (PC) mods that implement Autodemo features, see [[SADX Autodemo Mods|this page]] instead.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When the Sonic Adventure Autodemo was first dumped in 2013, it was soon discovered that it was a semi-functional build of the full game. The Autodemo was quickly hacked to unlock player controls and load stages manually so that they could be explored freely. However, many stages did not load because the binaries containing them were originally compiled for an older version of the game&#039;s main executable.&lt;br /&gt;
&lt;br /&gt;
The Autodemo has been researched ever since it was dumped, and the non-functional stages were eventually extracted using [[SA Tools]] and ported to the PC version. However, being able to play them in the Autodemo itself was desirable in order to see differences in the game&#039;s code, which couldn&#039;t be exported by the tools.&lt;br /&gt;
&lt;br /&gt;
Initial work on restoring Autodemo functionality ingame was done back in 2015, when the user &#039;&#039;evilhamwizard&#039;&#039; posted their findings in the [https://forums.sonicretro.org/posts/846056/ Autodemo discussion thread on Sonic Retro]. The work focused primarily on restoring the original Windy Valley, and a number of GIFs of the level running on the emulator [https://forums.sonicretro.org/posts/867245/ were posted in 2016]. Some updates were posted on booting Sky Deck as well.&lt;br /&gt;
&lt;br /&gt;
In 2024, based on &#039;&#039;evilhamwizard&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;s initial research, a new restoration project was started by [[x-hax]] (primarily by &#039;&#039;Speeps&#039;&#039;), aiming to make other stages bootable, as well as improving the original Windy Valley restoration. This restoration was achieved in 2024 through a collaboration of x-hax users and symbol information acquired from the leaked Xbox 360 SADX prototype. The project is [https://github.com/X-Hax/dreamcast-mods available as a GitHub repository].&lt;br /&gt;
&lt;br /&gt;
==Background and Method==&lt;br /&gt;
The files included on the Autodemo disc come from different builds of the game that were at different stages of development. When the Autodemo was put together, only the stages that were meant to be shown in the demo were recompiled, and the other stages were left over from older builds (for most of these, textures and lighting files were also missing). We can tell which binaries were recompiled by looking at file dates on the Autodemo GD-ROM. Only the files dated October 15 work ingame as-is, and other files cause the game to crash. The crash happens because the functions in the game&#039;s updated main binary (1ST_READ.BIN) are at different memory addresses from those expected by the code in stage binaries which were compiled for the older version of the game. &lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot;&lt;br /&gt;
!&#039;&#039;&#039;October 15, 1998 (working)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;October 7, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;September 24, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|STG01 (Emerald Coast)&lt;br /&gt;
|AL_GARDEN01 (Egg Carrier/Beta Windy Valley Chao Garden) &lt;br /&gt;
|STG00 (&amp;quot;Practice&amp;quot; Stages)&lt;br /&gt;
|-&lt;br /&gt;
|STG04 (Speed Highway)&lt;br /&gt;
|AL_GARDEN02 (Mystic Ruins Chao Garden)&lt;br /&gt;
|STG02 (Windy Valley)&lt;br /&gt;
|-&lt;br /&gt;
|STG05 (Red Mountain)&lt;br /&gt;
|AL_RACE (Chao Race)&lt;br /&gt;
|STG03 (Twinkle Park)&lt;br /&gt;
|-&lt;br /&gt;
|STG08 (Ice Cap)&lt;br /&gt;
|&lt;br /&gt;
|STG06 (Sky Deck)&lt;br /&gt;
|-&lt;br /&gt;
|STG10 (Final Egg)&lt;br /&gt;
|&lt;br /&gt;
|STG07 (Lost World)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00 (Station Square)&lt;br /&gt;
|&lt;br /&gt;
|STG09 (Casinopolis)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00OBJ (Station Square objects)&lt;br /&gt;
|&lt;br /&gt;
|ADV02 (Mystic Ruins)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0100 (Egg Carrier Outside)&lt;br /&gt;
|&lt;br /&gt;
|ADV02OBJ (Mystic Ruins objects)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0130 (Egg Carries Inside)&lt;br /&gt;
|&lt;br /&gt;
|SHOOTING (Sky Chase)&lt;br /&gt;
|-&lt;br /&gt;
|ADV01OBJ (Egg Carrier objects)&lt;br /&gt;
|&lt;br /&gt;
|MINICART (Twinkle Circuit)&lt;br /&gt;
|-&lt;br /&gt;
|AL_GARDEN00 (Station Square Chao Garden)&lt;br /&gt;
|&lt;br /&gt;
|B_E101_R (E-101 MK2)&lt;br /&gt;
|-&lt;br /&gt;
|AL_MAIN (Chao)&lt;br /&gt;
|&lt;br /&gt;
|B_ROBO (ZERO)&lt;br /&gt;
|-&lt;br /&gt;
|B_CHAOS2 (Chaos 2)&lt;br /&gt;
|&lt;br /&gt;
|B_EGM1 (Egg Hornet)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_EGM3 (Egg Viper)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|SBOARD (Sand Hill)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS0 (Chaos 0)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS4 (Chaos 4)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS6 (Chaos 6)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS7 (Perfect Chaos)&lt;br /&gt;
|}&lt;br /&gt;
However, as originally demonstrated by &#039;&#039;evilhamwizard&#039;&#039;, it’s possible to find the functions and data they were meant to point to by comparing the pointers to known functions and data between these files and the files that boot. In 2024, &#039;&#039;Speeps&#039;&#039; started putting together a new spreadsheet of known broken pointers and their correct counterparts. As the pointer list grew, more levels became functional when known pointers were replaced.&lt;br /&gt;
&lt;br /&gt;
Early hacks by &#039;&#039;Speeps&#039;&#039; were using simple patches to the executables applied through a hex editor. To facilitate mass pointer replacement and game testing, &#039;&#039;PkR&#039;&#039; reworked his SA1-DC-HD tool (originally meant to build GDIs of the final version of SA1 with enhancements) and created the [[Dreamcast Image Builder]]. The image builder uses a &amp;quot;mods&amp;quot; system that makes it easier to replace pointers, do all sorts of patching of game binaries and build a modified game image containing all of the selected hacks. In addition, some other tools on the [https://github.com/X-Hax/sa_tools_research SA Tools Research] repository were repurposed to find missing textures in the Autodemo by matching the names in the Autodemo’s texture lists against textures in the final version, the E3 build, the Autodemo Windy Valley mod for the PC version, where missing textures were recreated by its developers, and Dreamcast SDKs, which surprisingly have some early SA1 textures.&lt;br /&gt;
&lt;br /&gt;
Apart from making stages bootable, the mods include various experiments with controls, framerate, lighting, skipping the intro movie, adding textures that are missing on the disc, restoring debug functionality etc.&lt;br /&gt;
&lt;br /&gt;
The exact pointer matching procedure involved in stage restoration is as follows:&lt;br /&gt;
#Get the address of all pointers that read the stage&#039;s file from 1ST_READ. These are the Round Manager, Background Manager, Object List and Path List.&lt;br /&gt;
# Using IDA&#039;s graph view, gather all pointers to 1ST_READ (8Cxxxxxx).&lt;br /&gt;
# Using Ghidra, identify an object (using its name string) and check if the same code exists in SADX, where its symbol information can be taken from the 360 symbols.&lt;br /&gt;
# For all references to broken pointers in the object, attempt to find a working reference in a functional AutoDemo stage, such as Speed Highway.&lt;br /&gt;
# Replace the broken pointer with the working one.&lt;br /&gt;
All pointers were added to a spreadsheet along with their fixed version.&lt;br /&gt;
&lt;br /&gt;
For any code that didn&#039;t have a matching reference in the PC version or a functional Autodemo stage file, such as code for objects that didn&#039;t exist in the final game, the original byte difference method was used instead. Using Ghidra, the resulting pointer was checked to ensure it led to an appropriate address (The beginning of a function etc.). Any pointers &amp;quot;fixed&amp;quot; with this method were marked in the table as unsure.&lt;br /&gt;
&lt;br /&gt;
Stages that were similar enough to their final counterparts to share a lot of code (Twinkle Park, Lost World) were repaired first to build the database of known pointers, as stages with larger changes (Windy Valley) consisted almost entirely of code that didn&#039;t exist in the final game.&lt;br /&gt;
&lt;br /&gt;
The restoration was primarily discussed in a series of threads on x-hax Discord. An archive of the discussion will be available for download at a later date. &lt;br /&gt;
&lt;br /&gt;
== Restoration Details ==&lt;br /&gt;
&lt;br /&gt;
=== Stage Select ===&lt;br /&gt;
&lt;br /&gt;
=== Debug Functionality ===&lt;br /&gt;
&lt;br /&gt;
=== Ninja Lights ===&lt;br /&gt;
&lt;br /&gt;
=== Practice Stages ===&lt;br /&gt;
It turned out Practice 1 could load by just removing its SET File (Object Layout) because it only references 1ST_READ through that.&lt;br /&gt;
&lt;br /&gt;
Practice 2 does not load because one of the meshes is too big for the game&#039;s [[Sonic Adventure/Lantern Engine|LANTERN lighting system]] to handle. However, it boots if [[Sonic Adventure/Ninja Lights|Ninja Lights]] are used instead.&lt;br /&gt;
[[File:Pinball mode practice.mp4|thumb]]&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;nolines&amp;quot; caption=&amp;quot;Practice Stages with Ninja Lights (images by &#039;&#039;MainJP&#039;&#039;)&amp;quot;&amp;gt;&lt;br /&gt;
File:Practice.webp|alt=&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772203956319.png&lt;br /&gt;
File:Screenshot 2024-08-30 15-59-50.webp&lt;br /&gt;
File:Screenshot 2024-08-30 16-15-14.webp&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windy Valley ===&lt;br /&gt;
&lt;br /&gt;
=== Twinkle Park ===&lt;br /&gt;
&lt;br /&gt;
=== Sky Deck ===&lt;br /&gt;
&lt;br /&gt;
=== Lost World ===&lt;br /&gt;
&lt;br /&gt;
=== Casinopolis ===&lt;br /&gt;
&lt;br /&gt;
=== Station Square ===&lt;br /&gt;
&lt;br /&gt;
=== Mystic Ruins ===&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=681</id>
		<title>Sonic Adventure Autodemo/Restoration</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=Sonic_Adventure_Autodemo/Restoration&amp;diff=681"/>
		<updated>2026-02-28T06:57:53Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is dedicated to projects that restore content and functionality in the Autodemo prototype of Sonic Adventure (Dreamcast). For Sonic Adventure PX (PC) mods that implement Autodemo features, see [[SADX Autodemo Mods|this page]] instead.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When the Sonic Adventure Autodemo was first dumped in 2013, it was soon discovered that it was a semi-functional build of the full game. The Autodemo was quickly hacked to unlock player controls and load stages manually so that they could be explored freely. However, many stages did not load because the binaries containing them were originally compiled for an older version of the game&#039;s main executable.&lt;br /&gt;
&lt;br /&gt;
The Autodemo has been researched ever since it was dumped, and the non-functional stages were eventually extracted using [[SA Tools]] and ported to the PC version. However, being able to play them in the Autodemo itself was desirable in order to see differences in the game&#039;s code, which couldn&#039;t be exported by the tools.&lt;br /&gt;
&lt;br /&gt;
Initial work on restoring Autodemo functionality ingame was done back in 2015, when the user &#039;&#039;evilhamwizard&#039;&#039; posted their findings in the [https://forums.sonicretro.org/posts/846056/ Autodemo discussion thread on Sonic Retro]. The work focused primarily on restoring the original Windy Valley, and a number of GIFs of the level running on the emulator [https://forums.sonicretro.org/posts/867245/ were posted in 2016]. Some updates were posted on booting Sky Deck as well.&lt;br /&gt;
&lt;br /&gt;
In 2024, based on &#039;&#039;evilhamwizard&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;s initial research, a new restoration project was started by [[x-hax]] (primarily by &#039;&#039;Speeps&#039;&#039;), aiming to make other stages bootable, as well as improving the original Windy Valley restoration. This restoration was achieved in 2024 through a collaboration of x-hax users and symbol information acquired from the leaked Xbox 360 SADX prototype. The project is [https://github.com/X-Hax/dreamcast-mods available as a GitHub repository].&lt;br /&gt;
&lt;br /&gt;
==Background and Method==&lt;br /&gt;
The files included on the Autodemo disc come from different builds of the game that were at different stages of development. When the Autodemo was put together, only the stages that were meant to be shown in the demo were recompiled, and the other stages were left over from older builds (for most of these, textures and lighting files were also missing). We can tell which binaries were recompiled by looking at file dates on the Autodemo GD-ROM. Only the files dated October 15 work ingame as-is, and other files cause the game to crash. The crash happens because the functions in the game&#039;s updated main binary (1ST_READ.BIN) are at different memory addresses from those expected by the code in stage binaries which were compiled for the older version of the game. &lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot;&lt;br /&gt;
!&#039;&#039;&#039;October 15, 1998 (working)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;October 7, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
!&#039;&#039;&#039;September 24, 1998 (broken)&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|STG01 (Emerald Coast)&lt;br /&gt;
|AL_GARDEN01 (Egg Carrier/Beta Windy Valley Chao Garden) &lt;br /&gt;
|STG00 (&amp;quot;Practice&amp;quot; Stages)&lt;br /&gt;
|-&lt;br /&gt;
|STG04 (Speed Highway)&lt;br /&gt;
|AL_GARDEN02 (Mystic Ruins Chao Garden)&lt;br /&gt;
|STG02 (Windy Valley)&lt;br /&gt;
|-&lt;br /&gt;
|STG05 (Red Mountain)&lt;br /&gt;
|AL_RACE (Chao Race)&lt;br /&gt;
|STG03 (Twinkle Park)&lt;br /&gt;
|-&lt;br /&gt;
|STG08 (Ice Cap)&lt;br /&gt;
|&lt;br /&gt;
|STG06 (Sky Deck)&lt;br /&gt;
|-&lt;br /&gt;
|STG10 (Final Egg)&lt;br /&gt;
|&lt;br /&gt;
|STG07 (Lost World)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00 (Station Square)&lt;br /&gt;
|&lt;br /&gt;
|STG09 (Casinopolis)&lt;br /&gt;
|-&lt;br /&gt;
|ADV00OBJ (Station Square objects)&lt;br /&gt;
|&lt;br /&gt;
|ADV02 (Mystic Ruins)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0100 (Egg Carrier Outside)&lt;br /&gt;
|&lt;br /&gt;
|ADV02OBJ (Mystic Ruins objects)&lt;br /&gt;
|-&lt;br /&gt;
|ADV0130 (Egg Carries Inside)&lt;br /&gt;
|&lt;br /&gt;
|SHOOTING (Sky Chase)&lt;br /&gt;
|-&lt;br /&gt;
|ADV01OBJ (Egg Carrier objects)&lt;br /&gt;
|&lt;br /&gt;
|MINICART (Twinkle Circuit)&lt;br /&gt;
|-&lt;br /&gt;
|AL_GARDEN00 (Station Square Chao Garden)&lt;br /&gt;
|&lt;br /&gt;
|B_E101_R (E-101 MK2)&lt;br /&gt;
|-&lt;br /&gt;
|AL_MAIN (Chao)&lt;br /&gt;
|&lt;br /&gt;
|B_ROBO (ZERO)&lt;br /&gt;
|-&lt;br /&gt;
|B_CHAOS2 (Chaos 2)&lt;br /&gt;
|&lt;br /&gt;
|B_EGM1 (Egg Hornet)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_EGM3 (Egg Viper)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|SBOARD (Sand Hill)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS0 (Chaos 0)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS4 (Chaos 4)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS6 (Chaos 6)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|B_CHAOS7 (Perfect Chaos)&lt;br /&gt;
|}&lt;br /&gt;
However, as originally demonstrated by &#039;&#039;evilhamwizard&#039;&#039;, it’s possible to find the functions and data they were meant to point to by comparing the pointers to known functions and data between these files and the files that boot. In 2024, &#039;&#039;Speeps&#039;&#039; started putting together a new spreadsheet of known broken pointers and their correct counterparts. As the pointer list grew, more levels became functional when known pointers were replaced.&lt;br /&gt;
&lt;br /&gt;
Early hacks by &#039;&#039;Speeps&#039;&#039; were using simple patches to the executables applied through a hex editor. To facilitate mass pointer replacement and game testing, &#039;&#039;PkR&#039;&#039; reworked his SA1-DC-HD tool (originally meant to build GDIs of the final version of SA1 with enhancements) and created the [[Dreamcast Image Builder]]. The image builder uses a &amp;quot;mods&amp;quot; system that makes it easier to replace pointers, do all sorts of patching of game binaries and build a modified game image containing all of the selected hacks. In addition, some other tools on the [https://github.com/X-Hax/sa_tools_research SA Tools Research] repository were repurposed to find missing textures in the Autodemo by matching the names in the Autodemo’s texture lists against textures in the final version, the E3 build, the Autodemo Windy Valley mod for the PC version, where missing textures were recreated by its developers, and Dreamcast SDKs, which surprisingly have some early SA1 textures.&lt;br /&gt;
&lt;br /&gt;
Apart from making stages bootable, the mods include various experiments with controls, framerate, lighting, skipping the intro movie, adding textures that are missing on the disc, restoring debug functionality etc.&lt;br /&gt;
&lt;br /&gt;
The exact pointer matching procedure involved in stage restoration is as follows:&lt;br /&gt;
#Get the address of all pointers that read the stage&#039;s file from 1ST_READ. These are the Round Manager, Background Manager, Object List and Path List.&lt;br /&gt;
# Using IDA&#039;s graph view, gather all pointers to 1ST_READ (8Cxxxxxx).&lt;br /&gt;
# Using Ghidra, identify an object (using its name string) and check if the same code exists in SADX, where its symbol information can be taken from the 360 symbols.&lt;br /&gt;
# For all references to broken pointers in the object, attempt to find a working reference in a functional AutoDemo stage, such as Speed Highway.&lt;br /&gt;
# Replace the broken pointer with the working one.&lt;br /&gt;
All pointers were added to a spreadsheet along with their fixed version.&lt;br /&gt;
&lt;br /&gt;
For any code that didn&#039;t have a matching reference in the PC version or a functional Autodemo stage file, such as code for objects that didn&#039;t exist in the final game, the original byte difference method was used instead. Using Ghidra, the resulting pointer was checked to ensure it led to an appropriate address (The beginning of a function etc.). Any pointers &amp;quot;fixed&amp;quot; with this method were marked in the table as unsure.&lt;br /&gt;
&lt;br /&gt;
Stages that were similar enough to their final counterparts to share a lot of code (Twinkle Park, Lost World) were repaired first to build the database of known pointers, as stages with larger changes (Windy Valley) consisted almost entirely of code that didn&#039;t exist in the final game.&lt;br /&gt;
&lt;br /&gt;
The restoration was primarily discussed in a series of threads on x-hax Discord. An archive of the discussion will be available for download at a later date. &lt;br /&gt;
&lt;br /&gt;
== Restoration Details ==&lt;br /&gt;
&lt;br /&gt;
=== Stage Select ===&lt;br /&gt;
&lt;br /&gt;
=== Debug Functionality ===&lt;br /&gt;
&lt;br /&gt;
=== Ninja Lights ===&lt;br /&gt;
&lt;br /&gt;
=== Practice Stages ===&lt;br /&gt;
It turned out Practice 1 could load by just removing its SET File (Object Layout) because it only references 1ST_READ through that.&lt;br /&gt;
&lt;br /&gt;
Practice 2 does not load because one of the meshes is too big for the game&#039;s [[Sonic Adventure/Lantern Engine|LANTERN lighting system]] to handle. However, it boots if [[Sonic Adventure/Ninja Lights|Ninja Lights]] are used instead.&amp;lt;gallery mode=&amp;quot;nolines&amp;quot; caption=&amp;quot;Practice Stages with Ninja Lights (images by &#039;&#039;MainJP&#039;&#039;)&amp;quot;&amp;gt;&lt;br /&gt;
File:Practice.webp|alt=&lt;br /&gt;
File:Sonic Adventure Autodemo Restoration 1772203956319.png&lt;br /&gt;
File:Screenshot 2024-08-30 15-59-50.webp&lt;br /&gt;
File:Screenshot 2024-08-30 16-15-14.webp&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windy Valley ===&lt;br /&gt;
&lt;br /&gt;
=== Twinkle Park ===&lt;br /&gt;
&lt;br /&gt;
=== Sky Deck ===&lt;br /&gt;
&lt;br /&gt;
=== Lost World ===&lt;br /&gt;
&lt;br /&gt;
=== Casinopolis ===&lt;br /&gt;
&lt;br /&gt;
=== Station Square ===&lt;br /&gt;
&lt;br /&gt;
=== Mystic Ruins ===&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:Pinball_mode_practice.mp4&amp;diff=680</id>
		<title>File:Pinball mode practice.mp4</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:Pinball_mode_practice.mp4&amp;diff=680"/>
		<updated>2026-02-28T06:54:54Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:Screenshot_2024-08-30_15-59-35.webp&amp;diff=679</id>
		<title>File:Screenshot 2024-08-30 15-59-35.webp</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:Screenshot_2024-08-30_15-59-35.webp&amp;diff=679"/>
		<updated>2026-02-28T06:47:23Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
	<entry>
		<id>https://sadocs.unreliable.network/index.php?title=File:Screenshot_2024-08-30_16-15-04.webp&amp;diff=678</id>
		<title>File:Screenshot 2024-08-30 16-15-04.webp</title>
		<link rel="alternate" type="text/html" href="https://sadocs.unreliable.network/index.php?title=File:Screenshot_2024-08-30_16-15-04.webp&amp;diff=678"/>
		<updated>2026-02-28T06:47:22Z</updated>

		<summary type="html">&lt;p&gt;PkR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>PkR</name></author>
	</entry>
</feed>