temp - Lavesiime/lavesiime.github.io GitHub Wiki

RetroScript V4 Handbook

This is a handbook that details RSDK's RetroScript, more specifically the version found in RSDK V4. Please note that this wiki is always in-progress, so some things may be incomplete or otherwise lacking.

This wiki has been split into several sections for ease of reading. Please use the table of contents to navigate through this wiki in order to find what you need.

Introduction to RSDK and RetroScript

About RSDK

The Retro Engine Software Development Kit (Retro-Engine or RSDK) is a primarily 2D game engine with many “old-school” graphics effects, including palette-based graphics and functionality akin to “Mode 7” on the SNES. The dubbed the Retro Sonic Engine, the first game made with the RSDK was Retro-Sonic in 2002. Then, the engine was later upgraded in 2008 to be used in Sonic Nexus. RSDKv3, the 3rd version which was previously thought to be RSDKv2, was only used in the Sonic CD (2011) remaster. From there, the engine was then upgraded to RSDKv4, previously thought to be RSDKvB, for the Sonic 1 and 2 mobile remasters and likely the Sonic 3 proof-of-concept, using an updated version of RetroScript with more built-ins. Mania uses RSDKv5, the latest officially used version of RSDK, which uses a transpilable version of RetroScript. Versioning for RSDK has followed the editor’s version since v3. RetroScript remains officially unnamed, though it was previously confused with TaxReciept, which is Retro-Sonic's bytecode.

About RetroScript

RetroScript V4 is the scripting language used in RSDKv4, or the version of the Retro Engine to first be released in 2013. It is a simple object-oriented language with a somewhat syntax similar to that of Visual Basic or Python. Because of it being a scripting language, it offers many benefits compared to a typical language such like C:

  • Scripts are recompiled when a stage is loaded/restarted
    • Changes are incredibly easy to make and test almost instantly
  • Specifically designed to create object code, making it easy to create objects

As with any programming language, it is important to know the formatting of RetroScript and how the syntax works. Although it is similar to other programming languages, there are also small things to note, such as:

  • Line breaks are regarded as the end of a code line
    • Semicolons are only to be used in static variable declarations, using them as a line break will not work
  • CRLF line endings are used, not LF
  • Custom variables cannot be defined. One must use the temporary built-in variables (discussed later in the handbook)
  • There are no data types other than integers. No decimal places (floats) or strings can be stored, except for passing some string constants to some built-in functions
  • User-defined functions cannot be passed any parameters. All variables are however kept the same, so it is possible to use the built-in variables as a “passing” method
  • You cannot have multiple expressions on one line. For example, A = B + C is invalid, but A = B then A += C is valid (discussed more on the next page)

Arithmetic

Mathematics

As previously mentioned, you can only have 1 single arithmetic expression in a line. There can only ever be 1 variable on the right and another on the left. This means that, for complex calculations, each operation must all be done one by one. The list of mathematical arithmetic operators is limited to the following assignment operators:

  • = - regular assignment
  • 4-function
    • += -- addition
    • -= - subtraction
    • *= - multiplication
    • /= - division, rounding down (flooring)
  • Bit math
    • <<= - shift left
    • >>= - shift right
    • &= - AND
    • |= - OR
    • ^= - XOR
  • Unary
    • ++ - used as Variable++, equivalent to Variable += 1
    • -- - used as Variable--, equivalent to Variable -= 1

Examples

Pseudo-code RetroScript (with custom variables)
i = 0;
j = 15;
i++; //i is 1
i = j + 2; //i is 17
i = 0
j = 15
i++ //i is 1
i = j //i is 15
i += 2 //i is 17
x = 19;
y = 3;
d = 5;
x -= d-- //x subtracted by 4
y -= d-- //y subtracted by 4
//d is already 3
x = 19
y = 3
d = 5
d--
x -= d //x subtracted by 4
y -= d //y subtracted by 4
d-- //d is now 3

Conditionals and Statements

Control Statements

Since RetroScript does not use braces, there are specific keyword pairs that get used, along with small specifics for each:

  • If statements:
    • if [statement] - [statement] is a single boolean expression
    • else
    • endif - use as the “ending brace”
    • There is no such thing as a direct else-if in RetroScript. To achieve an else-if, one must make a new if statement on a new line and close it properly
  • While statements:
    • while [statement] - [statement] is a single boolean expression as shown above
    • loop - used as the “ending brace”
  • Switch statements:
    • switch [variable] - [variable] is the variable to check for
    • case [int/alias] - [int/alias] is an integer or alias to check if the variable is equal to
    • endswitch - use as the “ending brace”
    • Switches behave similarly as they do in C; default is optional and break is used in cases to stop fallthrough
  • Foreach statements:
    • foreach (objectGroup, store, type)
      • iterates every object of in group objectGroup and sets store to the object’s slotID
        • recommended to use TypeName[objectName]rather than numerical types
        • objectGroup can be GROUP_ALL go through all objects
      • type is either ALL_ENTITIES or ACTIVE_ENTITIES
    • next - use as the “ending brace"

Boolean Logic

Boolean operation is also possible but can only be used in control statements, and thus why they are in this section. There is no such boolean “or” or boolean “and” operator (|| and && respectively). The list of operators are as follows:

  • == - equal to (not = on its own)
  • > - greater than
  • >= - greater than or equal to
  • < - less than
  • <= - less than or equal to
  • != - not equal to

There are, however, some functions that you can use to assign variables boolean expressions:

  • CheckEqual(A, B)
  • CheckNotEqual(A, B)
  • CheckGreater(A, B)
  • CheckLower(A, B)

All these set CheckResult to either 0 or 1 based on the result of the function, which can later be checked and ORed/ANDed with. An example can be seen below

Examples

Pseudo-code RetroScript (with custom variables)
if (x == 0) {
     y = 15;
     z = 3;
} else {
     y = 3;
     z = 15;
}
if x == 0
     y = 15
     z = 3
else
     y = 3
     z = 15
end if
if ((x == 1) || (y == 2) || (z == 3)) {
     a = 7;
}
CheckEqual(x, 1)
temp0 = checkResult
CheckEqual(y, 2)
temp0 |= checkResult
CheckEqual(z, 3)
temp0 |= checkResult
if temp0 == true
     a = 7
end if
while (x < 10) {
     x++;
     if (y == 5) break;
}
while x < 10
      x++
      if y == 5
          break
      end if
loop
switch (x) {
case 1:
case 2:
     y++;
case 3:
     x++;
     break;
default:
     z++;
     break;
}
switch x
case 1
case 2
     y++
case 3
     x++
     break
default
     z++
     break
endswitch

Events and Functions

Events

Events are easily thought of as “default functions” and are all called periodically during gameplay. To define events, you can use event [name] as the start and end event as the “closing brace”. The definable game events are as follows:

  • ObjectMain - Called once every frame per object if priority allows for it, see priority notes
  • ObjectDraw - Called once every frame per object if priority allows for it, see priority notes. The ordering is based on the value of object.drawOrder
  • ObjectStartup - Called once per object type and once when the stage loads. Used for loading assets and sprite frames

There are also a couple of editor-related events available. They are never called in-game and are only used by external editors, such as RetroED or the official RSDK editor. It is not necessary to have these present in objects, but it is highly recommended.

  • RSDKDraw - Similar to ObjectDraw, used by the program to draw each object
  • RSDKLoad - Similar to ObjectStartup, used by the program to load any assets and sprite frames needed in order to draw the object

Functions

Custom functions are defined by using function [name] to start a function and end function as the “closing brace.” Functions can be forward declared using the preprocessor directive reserve function [name]. To call functions, you use CallFunction([name]). This means functions cannot have built in parameters, but there are ways to get around it as seen in the example below. return can be used to preemptively end a function.

Examples

Pseudo-code RetroScript (with custom variables)
MyFunc(y);

ObjectMain() {
     x = 5; // x is 5
     x = MyFunc(x) // Pass x (not it’s value)
     // x is 7
}

MyFunc(y) {
     x += 2; // Increase x by 2
     return;
     x += 5; // This line doesn’t hit
}
reserve function MyFunc

event ObjectMain
     x = 5
     CallFunction(MyFunc)
     // x is 7
end event

function MyFunc
     x += 2
     return
     x += 5 // This line doesn’t hit
end function

Preprocessor Directives

RetroScript v4 has 1 preprocessor directive that is available to use. The preprocessor directive format for it is as follows:

  • #platform: [type] [...] #endplatform This will skip over any lines of code inbetween the two statements if the type does does match what the code is being compiled for.

The types for it are the following

STANDARD | MOBILE

The only type that truly is for platforms, this is used to differentiate between different platforms the game may be running on. This can be used for things such as handling input, where it's necesary to decide whether to take touchscreen or gamepad input.

It's recommended to use engine.deviceType with RETRO_STANDARD/RETRO_MOBILE instead, as that runs via normal code and will run across different systems correctly, even after compilation.

SW_RENDERING | HW_RENDERING

For software rendering and hardware rendering, respectively. It is normally not needed to change things based on current renderer, as even mobile phones are now powerful enough to run software rendering. However, these platform flags are still here, just in case.

USE_F_FEEDBACK | NO_F_FEEDBACK

For whether haptic feedback is enabled or not. Although these exist, there isn't much use to these, either, as there are no haptic feedback functions actually available.

USE_NETWORKING

Used to determine if RSDK networking is enabled or not. Normally used for multiplayer, although it can also be used for other things.

USE_DECOMP

A platform flag for code meant to be used specifically for the Retro Engine V4 decompilation. Currently, this is the only public place with the RetroScript V4 compiler, but this platform flag is here in case another compiler comes in the future.

USE_MOD_LOADER

A platform flag also meant for the Retro Engine V4 decompilation, this one is used set to true if the mod loader is enabled. The mod loader being enabled itself isn't too major of a thing, but it also brings several features of its own which are discussed later in this document.

Variables

RetroScript v4 has 3 formats for extra variables that are available to use. These use the keywords public and private. public means this variable can be accessed by any script compiled after the current one, while private means the variable can only be accessed by the script it was created in. the formats for the variables are as follows:

  • [public]/[private] alias [val] : [name] - Creates a new alias that gets replaced by val on compile time
    • Example: private alias 1 : myAlias would make the compiler treat all instances of myAlias as simply being the number 1 instead
  • [public]/[private] value [name] = [val]; - Creates a new static variable with the value of val. Static variables are not tied to an object and thus should not be used when a value is needed for every instance of an object. Instead, they are regular values that can be accessed the same as any other built-in one
    • Example: public value myValue = 0; would create the value myValue with a default value of 0 and allow any other objects compiled after this one to access the value
  • [public]/[private] table [name] [values] [...] end table - Creates a new table and fills it up with values from values
    • For more information, see below

Tables

One of RetroScript V4's additions from its V3 counterpart is the addition of tables. The format of a table is described above, with [values] holding all the values the table should have, with the end being signified by an end table keyword. Values should be separated by either a , character or a newline. Having both after an entry will cause an empty entry in between.

To interact with tables, the [G/S]etTableValue functions exist. Their arguments are as follows:

GetTableValue(var store, int index, arr array)

  • Gets a value from table array at position index and stores the result in store
    • Used for reading from tables

SetTableValue(int value, int index, arr array)

  • Sets the value in table array at position index to value
    • Used for writing to tables

Just like any other language, tables can be used for a variety of purposes. One example can be seen below, where a table is being used to hold frame durations used in the animation of an object.

RetroScript (with custom variables)
private table Object_dummyTable
	64, 1, 1, 1, 1, 1, 2, 1, 2, 1, 234
end table

event ObjectMain
  GetTableValue(temp0, object.frame, Object_dummyTable)
  object.timer++
  if object.timer == temp0
    object.timer = 0
    object.frame++
  end if
end event

Audio

Music is in the stored in ogg format, with a sample rate of 44100. In order to use a custom music track during gameplay, all that is needed is for the file to be present in the Data/Music/ directory. Only one music track can play at a time, but operations such as fading out, stopping, or swapping can be preformed during playback.

SetMusicTrack(string filePath, int trackID, int loopPoint)

  • Takes the music track located at filePath and assigns it to ID trackID with a loop point of loopPoint
  • loopPoint is track loop point
    • 0 is used to signify no loop, 1 is used to loop from the begining of the track, any other values are the point to loop from in samples
  • This will only set the music track to the track ID, it will not play the music
    • In order to play it, PlayMusic is needed

PlayMusic(int trackID)

  • Plays the music track loaded into the slot at trackID
  • trackID music information needs to be set with SetMusicTrack beforehand, see previous entry

StopMusic()

  • Stops the currently playing music

PauseMusic()

  • Pauses the currently playing music
    • Can be resumed with ResumeMusic later

ResumeMusic()

  • Resumes the music formerly paused by StopMusic

SwapMusicTrack(string filePath, int trackID, int loopPoint, int ratio)

  • Works similar to SetMusicTrack() & PlayMusic() but starts at a position based on ratio
    • ratio is using an 8000-based value, so 8000 = 1.0 music speed, 4000 = 0.5, etc

music.volume

  • The volume of the currently playing music
    • Can be manipulated in order to fade in/out music

music.currentTrack

  • ID of the currently playing music track
    • Read only, but new music can be played via PlayMusic

music.position

  • The position of the currently playing music track
    • Stored in sample number
    • Read only

engine.bgmVolume

  • The master volume for all music
    • Ranges from 0-100
    • Combined with music.volume to get the final output volume
  • Changing this often is not recommended
    • music.volume should be changed, instead

Sound effects are stored in the wav format and have to be present in the Data/SoundFX/ directory. In order to use them during gameplay, they need to be present in either the global sound effects list or the scene-specific sound effects list. Once added, a name can be entered for them in order to use SFXName. This isn't necessary, but it's highly recommended. Without a name, sound effects can only be played with numerical ID's.

PlaySfx(int sfx, int loopCnt)

  • Plays SFX sfx loopCnt times
    • sfx is ID of SFX, SFX ID can be found by looking at the by looking at GameConfig + StageConfig
    • Using SfxName is recomended

SetSfxAttributes(int sfx, int loopCnt, int pan)

  • Changes the properties of SFX sfx
    • sfx is ID of SFX, see above for more info
      • Using SfxName is recomended
    • loopCnt is the amount of times for the sound to loop. Use -1 in order to leave it unchanged
    • pan is how much the sound should be panned. -100 is to the left, while 100 is to the right. 0 can be used in order to balance it

StopSfx(int sfx)

  • Stops the sound effect sfx
    • sfx is ID of SFX
    • Using SfxName is recomended

engine.sfxVolume

  • The master volume for all SFX
    • Changing this often is not recommended

placeholder stuff pretend there's nothing below here

Drawing

If the same sheet is loaded twice, it doesn't load again and returns the I'd of the existing sheet Sheets are cleared upon scene load

Sprites are stored in the gif format in the Data/Sprites/ directory. The sheet's dimensions must be a power of two, but it is not required to be a square. For example, sprite sheets with dimensions of 256x512 and 64x64 could work, but one that has a size of 300x300 wouldn't. Sheets can be loaded via LoadSpriteSheet, at which point they get assigned a sprite sheet ID. Up to 24 different sheets can be loaded at once, although one can be removed from memory at any time with RemoveSpriteSheet. Additionally, loaded sheets are cleared upon a scene reset, so it is not nesecary to manually remove sheets from memory.

LoadSpriteSheet(string path)

  • Loads the sprite sheet from path and assigns it to the current object
    • path is based off Data/Sprites/ directory, not RSDK root

RemoveSpriteSheet(string path)

  • Removes the sprite sheet at patch from memory
    • path is based off Data/Sprites/ directory, not RSDK root
    • This doesn't delete any files; the actual file will remain untouched

SpriteFrame(int pivotX, int pivotY, int width, int height, int sprX, int sprY)

  • Creates a spriteframe with the specified values
    • pivotX and pivotY are where the center of the sprite is
    • width and height are how wide and tall the sprite is
    • sprX and sprY are the location of the sprite on the loaded sprite sheet

EditFrame(int frame, int pivotX, int pivot, int width, int height, int sprX, int sprY)

  • Edits spriteframe frame of the current object to use the new values specified
    • Values follow same format as SpriteFrame, see above

DrawSprite(int frame)

  • Draws sprite frame at the object's current X and Y position

DrawSpriteXY(int frame, int XPos, int YPos)

  • Draws sprite frame at XPos and YPos
    • Uses world-space position instead of screen space (0, 0 is top left, 0x10000, 0 is 1 px to the right)

DrawSpriteScreenXY(int frame, int XPos, int YPos)

  • Draws sprite frame at XPos and YPos
    • Uses screen-space position (0, 0 is top left, 1, 0 is 1 px to the right)

DrawSpriteFX(int frame, int fx, int XPos, int YPos)

  • Draws sprite frame at XPos and YPos with fx effects
    • Uses world-space positioning (0, 0 is top left, 0x10000, 0 is 1 px to the right)

DrawSpriteScreenFX(int frame, int fx, int XPos, int YPos)

  • Draws sprite frame at XPos and YPos with fx effects
    • Uses screen-space positioning (0, 0 is top left, 1, 0 is 1 px to the right)

FX_FLIP | FX_SCALE | FX_ROTATE | FX_ROTOZOOM | FX_INK

  • Effect ID's to be used for DrawSpriteFX and DrawSpriteScreenFX.
    • FX_FLIP allows for sprite flipping
    • FX_SCALE allows for sprite scaling
    • FX_ROTATE allows for sprite rotation
    • FX_ROTOZOOM allows for sprite scaling and rotation at the same time
    • FX_INK allows for different ink effects (see INK_ section for more details)

DrawRect(int XPos, int YPos, int width, int height, int R, int G, int B, int A)

  • Draws a rectangle with the specified values
    • Xpos and YPos are the position to draw it in screen-space (0, 0 is top left, 1, 0 is 1 px to the right)
    • width and height are the dimensions for the rectangle
    • R, G, and B determine what color the rectanlge should be following the RGB format
    • A is the alpha, or transparency, to draw it at

DrawTintRect(int XPos, int YPos, int width, int height)

  • Draws a tint rectangle with the dimensions of width and height at XPos and YPos, relative to screen-space

DrawNumbers(int startingFrame, int XPos, int YPos, int value, int digitCnt, int spacing, int showAllDigits)

  • Draws the provided numbers to the screen
    • startingFrame is the first frame the numbers start from
      • Starts at 0, then assumes following numbers will be 1-9
    • XPos and YPos are the position to starting drawing from in screen-space (0, 0 is top left, 1, 0 is 1 px to the right)
    • value is the value to draw to the screen
    • digitCnt is the
    • spacing is how many pixels should be between each number
    • If showAllDigits is 0, then only valid digits will be drawn
      • Otherwise, digitCnt digits will be drawn, with extras being 0

DrawActName(int startingFrame, int XPos, int YPos, int align, int unknown, int unknown2, int spacing)

  • Draws the loaded stage’s act name
    • Uses 26 frames, starting from startingFrame
    • XPos and YPos are position to draw it at in screen-space (0, 0 is top left, 1, 0 is 1 px to the right)
    • Only uppercase english letters are supported
    • alignment is used to determine where the text center is (0 = left, 1 = middle, 2 = right)
    • spacing pixels are placed between each letter

AddDrawListEntityRef(int layer, int objectPos)

  • Adds objectPos to the drawList layer

SetDrawListEntityRef(int value, int layer, int objectPos)

  • Sets the value in drawList layer at objectPos to the value of value

GetDrawListEntityRef(var store, int layer, int objectPos)

  • Gets the value in drawList layer at objectPos and stores it in store

ClearDrawList(int layer)

  • Removes all entries in drawList layer

Animations

Although there aren't many animation-related commands available for use, animations as a whole are still an important part of RSDK. It allows objects to be animated independantly of their object scripts, although said object's animations can still be manually controlled via scripts if needed. When using animations, sprite sheets and sprite frames don't need to be done via script, as they are all handled via the animation file instead.

LoadAnimation(string filePath)

  • Loads the animation file at Data/Animations/[filePath] for the current object to use

GetAnimationByName(var store, string animationName)

  • Cycles through all animations in the currently loaded animation file to find what animation ID correspongs to with animationName and sets the result to store
    • store will be set to 0 if animation can't be found

ProcessAnimation()

  • Updates the current object's animation based on the object's various values such as:
    • object.animation
    • object.animationSpeed
    • object.animationTimer
    • object.frame

DrawObjectAnimation()

  • Draws the object at its XPos and YPos based on the currently loaded animation file and object.animation/object.frame

Palettes

Palettes are stored within the Data/Palettes/ directory. Palettes should be in the act file format, which stands for for Adobe Color Table. The format itself is very simple; it is just a series of RGB colors stored as RR GG BB in bytes with no header or otherwise padding information. RSDK can only hold 255 colors in a single palette, although there can be up to 8 separate palettes at once, combining up to a total of 2040 available colors at once. The first color in each palette is reserved for transparency.

LoadPalette(string filePath, int palID, int startPalIndex, int startIndex, int endIndex)

  • Loads the palette from Data/Palettes/[filePath] into palID
    • startPalIndex is used to signify where to start from in the game's current palette
    • startIndex is used to signify where to start from in the externally loaded palette
    • endIndex is used to signify where to stop reading from the externally loaded palette

RotatePalette(int palID, int startIndex, int endIndex, int right)

  • Rotates all colours palID starting from startIndex through to endIndex
    • Rotates one to the left if right is 0, otherwise rotates one right

SetScreenFade(int r, int g, int b, in a)

  • Sets a global fade-out effect based on r, g, b and a

SetActivePalette(int palID, int startLine, int endLine)

  • Sets the active palette to palID for all lines from startLine though endLine
    • startLine and endLine are based on screen-space position

SetPaletteEntry(int palID, int index, int colour)

  • Sets the palette entry at index in palID to the value of colour
    • colour is packed RGB value, of 0xRRGGBB

GetPaletteEntry(int palID, int index, var store)

  • Gets the palette entry at index from palID and sets it to store
    • Color set to store is packed RGB value, format of 0xRRGGBB

SetPaletteFade(int dstPal, int srcPalA, int srcPalB, int blendAmount, int startIndex, int endIndex)

  • Blends srcPalA with srcPalB by blendAmount, starting from startIndex and continuing though to endIndex, storing the resulting colors in dstPal

CopyPalette(int srcPal, int srcPalStart, int dstPal, int dstPalStart, int count)

  • Copies count colors from srcPal at srcPalStart index to dstPal at dstPalStart

ClearScreen(int index)

  • Clears all pixels on screen with the colour from index in the active palette

Object

RetroScript is an object-oriented programming langauge, and as such, code cannot be run from outside an object. Each object has about a hundred values available for use, a far step up from RSDKv3's mere 25 or so.

index is the index of the target object. Appending + or - to a number will instead look at the object based on an offset from the current object's position. Additionally, index is optional, not including it will refrence the current object.

object[index].type

  • The object's type
    • Corresponds to an object script path from which the object's code is run

object[index].groupID

  • The object's type group
    • By default, this matches the object's type, but it can be set to another value by script
      • 0x1000 upwards are never assigned by default, so they can work just fine for custom groups
    • Commonly used in foreach statements

object[index].propertyValue

  • The object's property value, or a variation value to indicate which version of an object to use
    • Comparable to "subtypes"

object[index].state

  • The object's current state
    • Can be used in any way by the object, whether it be a numbered state, a function pointer, or etc.

object[index].angle

  • The object's tile angle
    • Usually set via ProcessObjectMovement()
    • Not to be confused with object.rotation, which is how much to rotate the object when drawing

object[index].rotation

  • The object's rotation
    • Used with DrawSprite[Screen]FX and FX_ROTATE or FX_ROTOZOOM
    • Meant for visual effects

object[index].scale

  • The object's scale
    • Used with DrawSprite[Screen]FX and FX_SCALE, FX_ROTOZOOM, or FX_TINT
    • Uses a 9-bit bitshifted value, so 0x200 (512) == 1.0

object[index].alpha

  • The object's transparency
    • Between 0 and 255

object[index].animation

  • The object's current animation
    • Used by ProcessAnimation()
    • Between 0 and 255

object[index].prevAnimation

  • The object's animation from the previous frame
    • Used by ProcessAnimation()
    • Between 0 and 255, same range as object.animation

object[index].animationTimer

  • A timer used in processing animations for the object
    • Used by ProcessAnimation()

object[index].animationSpeed

  • The object's animation speed
    • Used by ProcessAnimation()

object[index].xpos | object[index].ypos

  • The object's X and Y position
    • Uses world-space position (0, 0 is top left, 0x10000, 0 is 1 px to the right)

object[index].ixpos | object[index].iypos

  • The object's X and Y position, but truncated to screen-space position (0, 0 is top left, 1, 0 is 1 px to the right)

object[index].lookPosX | object[index].lookPosY

  • The camera offset from the player's position

object[index].xvel | object[index].yvel

  • The object's X and Y velocities
    • World-space

object[index].speed

  • The object's speed
    • World-space

object[index].priority

  • The object’s priority value, determines how the engine handles object activity
    • Set to PRIORITY_ACTIVE_BOUNDS by default

object[index].drawOrder

  • The object's drawing layer
    • Manages what drawList the object is placed in
    • 3 is default

object[index].direction

  • The object's direction
    • Determines which way to flip the sprite if using DrawSprite[Screen]FX

FLIP_NONE | FLIP_X | FLIP_Y | FLIP_XY

  • ID's for object.direction

object[index].inkEffect

  • Determines the blending mode used by DrawSprite[Screen]FX with FX_INK

object[index].value0 | object[index].value1 ... object[index].value47

  • 47 integer variables used for long-term storage. What they are used for varies between every object.
  • Individual values can be retrieved via GetObjectValue and set via SetObjectValue

GetObjectValue(int store, int index, int objectPos)

  • Gets object[objectPos].value[index] and sets it to store

SetObjectValue(int value, int index, int objectPos)

  • Sets object[objectPos].value[index] to the value of value

object[index].collisionMode

  • The object's collision mode

CMODE_FLOOR | CMODE_LWALL | CMODE_ROOF | CMODE_RWALL

  • ID's for object.collisionMode

object[index].collisionPlane

  • The object's collision plane
    • Either 0 or 1

object[index].controlMode

  • The object's control mode
    • 0 by default

object[index].controlLock

  • The object's control lock timer

object[index].pushing

  • The object's pushing flag
    • Usually set by collision functions

object[index].visible

  • Determines if the object is visible or not
    • Object's draw event is only called if this is true

object[index].tileCollisions

  • Determines if the object will interact with tiles or not

object[index].objectInteractions

  • Determines if the object will interact with other objects

object[index].gravity

  • The object's gravity state

GRAVITY_GROUND | GRAVITY_AIR

  • ID's for object.gravity

object[index].up | object[index].down | object[index].left

object[index].right | object[index].jumpPress | object[index].jumpHold

  • Object input buffer values
    • Generally set via ProcessPlayerControl()
    • Per-object values, not to be confused with inputDown.up or inputPress.left and such

object[index].scrollTracking

  • Determines if the object will track the object's position or simply follow it instead

object[index].floorSensorL | object[index].floorSensorC | object[index].floorSensorR

object[index].floorSensorLC | object[index].floorSensorRC

  • Object collision censors for when on the ground
    • True if there was collision, false if there wasn't

object[index].collisionLeft | object[index].collisionTop

object[index].collisionRight | object[index].collisionBottom

  • The object's active hitbox based on the loaded animation file and object.animation/object.frame values

SetObjectRange(int range)

  • Sets the update ranges for all objects
    • range is how wide the“screen range should be
    • The default values are the same as SetObjectRange(424)

CopyObject(int destSlot, int srcSlot, int count)

  • Copies count objects starting from srcSlot into slot destSlot in the entity list
    • The active object list has 1184 slots. However, after that, there are anther 1184 slots meant to be used for storage.
    • These storage slots are kept the same between scene reloads, meaning that they can be used to keep an object between different scenes
    • EX: CopyObject(1200, 0, 5) will copy objects from slot 0-4 into slots 1200-1204

Stages

Stages themselves are unable to have code attached to them, but there are several variables that are associated with stages nonetheless. Additionally, stages can have an object specific to them created in order to run code specific to this stage, as well as a global object having code that should be shared between all stages. Things that would normally need to be done by specific stages include palette cycles and animated tiles, but there is also much more.

stage.state

  • The stage's current state

STAGE_RUNNING | STAGE_PAUSED | STAGE_FROZEN | STAGE_2P

  • ID's for stage.state

stage.milliSeconds

stage.seconds

stage.minutes

  • Timer values for the current stage
    • These are automatically set by the engine if stage.TimeEnabled is true

stage.timeEnabled

  • Determines whether time should increase or not

stage.listPos

  • The ID of the next stage to load
    • Based on, as the name implies, the stage's position on the stage list

stage.activeList

  • The active list to load stages from, ID's are below

PRESENTATION_STAGE | REGULAR_STAGE | BONUS_STAGE | SPECIAL_STAGE

  • List ID's for stage.activeList

stage.listSize[index]

  • The amount of stages in stage list index
    • ID's for use are provided above

LoadStage()

  • Loads a stage with an ID of stage.listPos from stage.activeList
    • All objects and their object values will be refreshed, although global variables will remain
    • In order to keep an object between different scenes, CopyObject can be used

stage.actNum

  • The act number of the currently loaded stage

stage.pauseEnabled

  • Determines whether or not the game can be paused

stage.curXBoundary1

stage.curXBoundary2

stage.curYBoundary1

stage.curYBoundary2

  • The stage’s main camera boundaries, the camera will not go beyond these

stage.newXBoundary1

stage.newXBoundary2

stage.newYBoundary1

stage.newYBoundary2

  • The stage’s other camera boundaries, the camera will not go beyond these, either
    • These are used when setting new camera boundaries

stage.deformationData0[index]

stage.deformationData1[index]

stage.deformationData2[index]

stage.deformationData3[index]

  • The layer deformation data arrays
    • 0 & 1 are used for the FG Layer (0 being for above water, 1 being for below water)
    • 2 & 3 are used for the BG Layers (2 being for above water, 3 being for below water)

stage.waterLevel

  • The stage's current water level

stage.activeLayer[index]

  • Drawable layer ID's, with index 0 being the lowest and index 3 being the highest
    Any layers that are not set with this array or are set to 9 will not be drawn

stage.midPoint

  • Any active layers above this value will draw only tiles on the high Visual Plane
    • Otherwise only tiles on the low Visual Plane will be drawn

stage.playerListPos

  • The current player selection
    • Persists between scene reloads

stage.debugMode

  • Whether debug mode is enabled or not

stage.entityPos

  • Exact purpose unknown, seems to be a misnomer
    • Looks to be the same as object.entityPos

SetLayerDeformation(int deformID, int deformA, int deformB, int type, int offset, int count)

  • Sets the deformation of the deformation data array of deformID based on the deform values

GetTileLayerEntry(var store, int layer, int chunkX, int chunkY)

  • Gets the chunkID of the chunk at chunkX, chunkY on tileLayer layer and stores it in store

SetTileLayerEntry(int value,<br>int layer, int chunkX, int chunkY)

  • Sets the chunkID of the chunk at chunkX, chunkY on tileLayer layer and sets the index to value

Get16x16TileInfo(int store, int tileX, int tileY, int infoType)

  • Gets the info of infoType of the tile at tileX, tileY and stores it in store

Set16x16TileInfo(int value, int tileX, int tileY, int infoType)

  • Sets the info of infoType of the tile at tileX, tileY and sets it to value

TILEINFO_INDEX | TILEINFO_DIRECTION TILEINFO_VISUALPLANE

TILEINFO_SOLIDITYA | TILEINFO_SOLIDITYB | TILEINFO_FLAGSA

TILEINFO_ANGLEA | TILEINFO_FLAGSB | TILEINFO_ANGLEB

  • ID's for infoType for [G/S]et16x16TileInfo
    • TILEINFO_FLAGSB & TILEINFO_ANGLEB are read-only and can only be used with Get16x16TileInfo()

Copy16x16Tile(int dst, int src)

  • Copies the tileset image data from src to dst
    • Used for animated tiles

CheckCurrentStageFolder(string folder)

  • If the loaded stage's folder matches folder, CheckResult is set to true
    • Otherwise, it is set to false

tileLayer[index].xsize | tileLayer[index].ysize

  • The size of tile layer index in chunks

tileLayer[index].type

  • The type of rendering that the tile layer index uses

TILELAYER_NOSCROLL | TILELAYER_HSCROLL | TILELAYER_VSCROLL

TILELAYER_3DFLOOR | TILELAYER_3DSKY

  • ID's for tileLayer.type

tileLayer[index].angle

  • The angle of the tile layer
    • Used for 3DFLOOR and 3DSKY rotations

tileLayer[index].xpos | tileLayer[index].ypos | tileLayer[index].zpos

  • The position of the tile layer
    • Used for 3DFLOOR and 3DSKY rotations

tileLayer[index].parallaxFactor | tileLayer[index].scrollSpeed | tileLayer[index].scrollPos

  • The parallax values of the tile layer

tileLayer[index].deformationOffset | tileLayer[index].deformationOffsetW

  • The offset for the deformation data arrays when rendering

hParallax[index].parallaxFactor | vParallax[index].parallaxFactor

  • The scroll info’s parallax factor, or relative speed, which determines how many pixels the parallax moves per pixel move of the camera

hParallax[index].scrollSpeed | vParallax[index].scrollSpeed

  • The scroll info’s scroll constant speed which determines how many pixels the parallax moves per frame

hParallax[index].scrollPos | vParallax[index].scrollPos

  • The scroll info’s scroll position, which is how many pixels the parallax is offset from the starting position

StageName[list - name]

  • Used to get the ID of a stage/scene based on its name
    • EX: GREEN HILL ZONE 1 has an stgID of 0 in Sonic 1, so using StageName[R - GREEN HILL ZONE 1] would be the same as using 0

Input

Variables Description
inputDown.up
inputDown.down
inputDown.left
inputDown.right
inputDown.buttonA
inputDown.buttonB
inputDown.buttonC
inputDown.buttonX
inputDown.buttonY
inputDown.buttonZ
inputDown.buttonL
inputDown.buttonR
inputDown.start
inputDown.select

True if the corresponding button/key has been held
inputDown.buttonX through Z and L/R are both mapped to A/B/C

inputPress.up
inputPress.down
inputPress.left
inputPress.right
inputPress.buttonA
inputPress.buttonB
inputPress.buttonC
inputPress.buttonX
inputPress.buttonY
inputPress.buttonZ
inputPress.buttonL
inputPress.buttonR
inputPress.start
inputPress.select

True if the corresponding button/key was pressed on this frame
Same note as above

CheckTouchRect(int x1, int y1, int x2, int y2)

  • Checks if a touch input was detected between the inputted coordinates and sets CheckResult accordingly
    • Based on screen position

Math

Sin(int store, int angle)

Cos(int store, int angle)

  • Gets the value from the sin/cos512 lookup table based on angle and sets it in store

Sin256(int store, int angle)

Cos256(int store, int angle)

  • Gets the value from the sin/cos256 lookup table based on angle and sets it in store

ATan2(int store, int x, int y)

  • Performs an arctan operation using x and y and stores the result in store

GetBit(var store, int value, int pos)

  • Gets bit at index pos from value and stores it in store

SetBit(int value, int pos, int set)

  • Sets bit at index pos to set and updates value accordingly

Rand(var store, int max)

  • Gets a random value from 0 to max and stores it in store

Not(var value)

  • Performs a NOT operation on value and updates it
    • (value = ~value)

Abs(var value)

  • Sets value to the absolute version of it

Interpolate(var store, int x, int y, int percent)

InterpolateXY(var storeX, var storeY, int aX, int aY, int bX, int bY, int percent)

  • Linearly interpolates (LERPs) x and y by percent and stores the result in store
    • percent is 0 through 255.
  • InterpolateXY does 2 at once for points (aX, aY) and (bX, bY)

3D

Although the Retro Engine is primarily a 2d-based engine, it also has a robust 3d system. Although this system doesn't allow for custom model loading, it still allows for a great deal of things to be done.

MAT_WORLD | MAT_VIEW | MAT_TEMP

  • RSDKv4 only allow use of 3 matrices: world, view & temp.
    • Passing these should only be done to parameters of type mat.
    • Matrix values are shifted 8 bits, so 0x100 (starting vals) is 1.0

scene3D.vertexCount

scene3D.faceCount

  • Amount of active faces/vertices in each buffer respectively
    • Max of 1024 faces and 4096 vertices

scene3D.projectionX

scene3D.projectionY

  • The width (X) and height (Y) of the 3DScene draw buffer.
    • These values determine what base resolution to use for drawing functions

scene3D.fogColor

scene3D.fogStrength

  • The colour of the fog in RGB format and the strength of the fog (0-255)
    • Used with FADE_FADED flag

faceBuffer[index].a | faceBuffer[index].b

faceBuffer[index].c | faceBuffer[index].d

  • The vertex indices to use to control this face’s drawing

FACE_TEXTURED_3D | FACE_TEXTURED_2D

FACE_COLOURED_3D | FACE_COLOURED_2D

FACE_FADED | FACE_TEXTURED_C

FADE_TEXTURED_D | FACE_SPRITE3D

  • The different face drawing flags that can be used with faceBuffer.flag

faceBuffer[index].flag

  • The active drawing flag for this face

faceBuffer[index].color

  • The colour to draw the face when drawing with FACE_COLOURED_2D or FACE_COLOURED_3D flags

vertexBuffer[index].x | vertexBuffer[index].y

vertexBuffer[index].z | vertexBuffer[index].u

vertexBuffer[index].v

  • The vertex coordinates for the specified vertex

SetIdentityMatrix(mat matrix)

  • Sets the matrix of matrix to the identity state

MatrixMultiply(mat matrixA, mat matrixB)

  • Multiplies matrixA by matrixB and stores the result in matrixA

MatrixTranslateXYZ(mat matrix, int x, int y, int z)

  • Translates matrix to x, y, z, all shifted 8 bits (0x100 = 1.0)

MatrixScaleXYZ(int matrix, int x, int y, int z)

  • Scales matrix by x, y, z, all shifted 8 bits (0x100 = 1.0)

MatrixRotateX(mat matrix, int angle)

MatrixRotateY(mat matrix, int angle)

MatrixRotateZ(mat matrix, int angle)

MatrixRotateXYZ(mat matrix, int x, int y, int z)

  • Rotates matrix to angle on the specified axis, or all if using MatrixRotateXYZ
    • Angles are 512-based, similar to sin/cos

MatrixInverse(int matrix)

  • Performs an inversion on the values of matrix

TransformVertices(mat matrix, int startIndex, int endIndex)

  • Transforms all vertices from startIndex to endIndex using matrix

Draw3DScene()

  • Draws the active 3DScene data to the screen

Menus

Menus are primarily used to display large amounts of text. The font is locked to an 8x8 size, with there being no way to change it. Custom fonts are loaded via LoadSpriteSheet(). Text positions are the same as the default system font found in Data/Game/SystemText.gif.

Although unconventional, menus can also be used to load raw data which can then be read from via GetTextInfo(). If doing this, then note that attempting to draw the menu may result in garbage text being drawn to the screen

MENU_1 | MENU_2

  • Menu ID's used for menu parameters

menu1.Selection | menu2.Selection

  • The current row selection for MENU_1 and MENU_2, respectively

LoadTextFile(int menu, string filePath)

  • Loads the file from filePath and appends it to menu
    • filePath is from executable directory, or Data/..

SetupMenu(int menu, int rowCount, int selectionCount, int alignment)

  • Sets up menu with rowCount rows, selectionCount active selections, and aligning it to alignment
    • alignment values are:
      • 0 - left alignment
      • 1 - right alignment
      • 2 - center alignment

AddMenuEntry(int menu, string text, int highlightEntry)

  • Adds a menu entry to menu with the contents of text and highlighting it if highlightEntry is set to true

EditMenuEntry(int menu, string text, int rowID, int highlightEntry)

  • Edits the entry at rowID in menu to have the contents of text, highlighting it if highlightEntry is set to true

GetTextInfo(var store, int menu, int type, int index, int offset)

  • Gets text info of type from menu at row index and stores it in store
    • offset is only used if type is TEXTINFO_TEXTDATA, where offset is which character to read from

TEXTINFO_TEXTDATA | TEXTINFO_TEXTSIZE | TEXTINFO_ROWCOUNT

  • The types of data that can be fetched via GetTextInfo

DrawMenu(int menu, int XPos, int YPos)

  • Draws menu menu at XPos and YPos using screen-space position (0, 0 is top left, 1, 0 is 1 px to the right)

GetVersionNumber(int menu, int highlight)

  • A rather specialised function that adds the game's verion number as text to menu, highlighted if highlight is set to true

Example

RetroScript (with custom variables)
event ObjectMain
  // Act on input
  if inputPress.up == true
    menu1.selection++
  else
    if inputPress.down == true
      menu1.selection--
    end if
  end if

  // Limit selections to 0-3
  if menu1.selection < 0
    menu1.selection = 0
  else
    if menu1.selection > 3
      menu1.selection = 3
    end if
  end if
end event

event ObjectDraw
  // Draw MENU_1 20 px from the top of the screen and at the middle of the screen
  DrawMenu(MENU_1, screen.xcenter, 20)
end event

event ObjectMain
  LoadSpriteSheet("UI/MenuFont.gif")
  SetupMenu(MENU_1, 0, 3, 2)
  AddMenuEntry(MENU_1, "PLAYER 1", 1)
  AddMenuEntry(MENU_1, "PLAYER 2", 1)
  AddMenuEntry(MENU_1, "SETTINGS", 1)
  AddMenuEntry(MENU_1, "EXIT", 1)
  menu1.selection = 0
end event

Engine

The engine has several variables of its own, mostly to control game flow and other engine-level things.

engine.state

  • The current engine game loop state, can be set to RESET_GAME in order to restart the game

engine.language

  • The language the engine is actively using

engine.onlineActive

  • Whether or not online functionality is enabled for the engine
    • Can be used in conjunction with #platform: USE_NETWORKING

engine.trialMode

  • Whether or not the game is built as a "trial version"
    • Basically always false

engine.deviceType

  • The current device type the game is currently running on

RETRO_STANDARD | RETRO_MOBILE

  • Device types for engine.deviceType

Misc

Things that don't really fit into any other category but are still nonetheless very important.

temp0 ... temp7

  • Temporary values used to store things operations

arrayPos0 ... arrayPos7

  • Variables used for storing indexes to be used with arrays

Print(message, bool isInt, bool addNewLine)

  • Prints a message to the console & the log
    • If isInt is set then message will be treated as an int, otherwise it will be treated as a string.
    • If addNewLine is set a \n character will be added to the end of the message when printed.

ReadSaveRAM()

  • Reads the contents of the save file and stores it into SaveRAM

WriteSaveRAM()

  • Writes the contents of SaveRAM to the save file

saveRAM[index]

  • An array of data capable set with ReadSaveRAM() and saved with WriteSaveRAM()

CallNativeFunction(int functionID)

CallNativeFunction2(int functionID, int param1, int param2)

CallNativeFunction4(int functionID, int param1, int param2, int param3, int param4)

  • Calls the native engine function with the ID of callbackFuncID using no params, 2 params, or 4 params respectively.
    • Adding a global variable with a name that matches any of the valid function names will result in its value being set to the function id internally
      • EX: A global variable with the name “SetAchievement” will have its value set to the function ID of the “SetAchievement” function
    • Valid function names are shown below.

Native functions present are as follows:

Function Description
SetAchievement(int id, int status)

Sets an achievement’s status to Status. Status 100 is achieved, anything else is unachieved.
Recomended to use AchievementName[] to get achievement IDs.

Connect2PVS(int gameLength, int itemMode)

Initializes a 2P VS session
gameLength and itemMode are how many matches there will be and what type of item boxes to use, respectively

Disconnect2PVS()

Ends the currently active 2P VS session

SendEntity(int entityID, int unused)

Sends the entity in slot entityID to the other player in the VS session.

SendValue(int value, int unused)

Sends value to the other player in the VS session

ReceiveEntity(int entityID, bool incrementSlot)

Receives (and loads) the next entity in the stack from the other player.
If incrementSlot is true then the entity is removed from the stack.

ReceiveValue(int value, bool incrementSlot)

Receives the next value in the stack from the other player.
If incrementSlot is true then the value is removed from the stack.

TransmitGlobal(int value, string name)

Sends a global value to the other player in the VS session.
In most cases Value should be the global variable and name should be the name of the variable.
The other player does not have to manually receive this value as it will be set automatically based on the name.

ShowPromoPopup(int id, string promoName)

Attempts to display a promotional popup.
Note: This function does nothing in the decompilation version, as it has no advertisements.

HapticEffect(int id, int unknown1, int unknown2, int unknown3)

Plays a haptic effect on the controller/mobile device.
The parameters of this function are unknown and therefore this does nothing in the decompilation version.

SetNetworkGameName(int unused, string name)

Sets the game name of the network to name.

ExitGame()

Simply exits the game

OpenModMenu()

Opens the dev-menu based mod menu

AddAchievement(int unused, string name)

Adds a new achievement with the name name.

SetAchievementDescription(int id, string description)

Sets the description of the achievement with id, to description
Use AchievementName[] to get achievement IDs

ClearAchievements()

Clears all loaded achievements

GetAchievementCount()

Gets the amount of loaded achievements and stores the value in checkResult

GetAchievement(int id, int unused)

Gets the status of achievement id and stores the value in checkResult
Use AchievementName[] to get achievement IDs

GetAchievementName(int id, int textMenu)

Gets the name of the achievement id and adds it as a new row to textMenu
Use AchievementName[] to get achievement IDs

GetAchievementDescription(int id, int textMenu)

Gets the description of the achievement id and adds it as a new row to textMenu
Use AchievementName[] to get achievement IDs

SetScreenWidth(int width, int unused)

Sets the internal screen width of the game to be width

SetWindowScale(int scale, int unused)

Sets the scale of the window size to scale
Any value below 1 is invalid and will break the window

SetWindowFullScreen(bool fullscreen, int unused)

Sets the window to fullscreen or windowed, depending on the value of fullscreen

GetModCount()

Gets the amount of loaded mods (not active) and stores the value in checkResult

GetModName(int textMenu, bool highlight, int id, int unused)

Gets the name of the mod id and adds it as a new row to textMenu
If highlight is set, the row will be highlighted

GetModDescription(int textMenu, bool highlight, int id, int unused)

Gets the description of the mod id and adds it as a new row to textMenu
If highlight is set, the row will be highlighted

GetModAuthor(int textMenu, bool highlight, int id, int unused)

Gets the author of the mod id and adds it as a new row to textMenu
If highlight is set, the row will be highlighted

GetModVersion(int textMenu, bool highlight, int id, int unused)

Gets the version of the mod id and adds it as a new row to textMenu
If highlight is set, the row will be highlighted

GetModActive(int id, int unused)

Gets the active flag of mod id and stores the value in checkResult

SetModActive(int id, bool active)

Sets the active flag of mod id to active
(0/false or 1/true)

RefreshEngine()

Reloads the engine.
Must be called in order for any mod active related changes to take effect

⚠️ **GitHub.com Fallback** ⚠️