Extensions, Shaders, Timelines format - UnderminersTeam/UndertaleModTool GitHub Wiki

Most of this research was done by @colinator27

EXTN

https://github.com/krzys-h/UndertaleModTool/issues/4#issue-360661852

EXTN: ListChunk
---
<normal FourCC and chunk length in every chunk>

Int32 - Count of (used) extensions
<normal list of 32-bit int pointers to item data, like other ListChunks, using count of used extensions>

Each item:
 32-bit string pointer to empty string: literally "" (just a null terminator), always (hardcoded seemingly)
 32-bit string pointer to extension name (Name)
 32-bit string pointer to class name (ClassName)
 
 List of "extension includes" (files), takes format of List<T>:
  Int32 - Count
  <list of 32-bit pointers to each item, as in List<T> format>
  
  Each item:
   32-bit string pointer to filename (Filename)
   32-bit string pointer to name of function called when game ends, as stored in the extension file, not as referenced in GameMaker, unless they are the same (Final)
   32-bit string pointer to name of function called when extension initializes, as stored in the extension file, not as referenced in GameMaker, unless they are the same (Init)
   Int32 - extension type/kind, value taken directly from project file (Kind)
    0 -> unknown; likely unused
    1 -> DLL
    2 -> GML "placeholder"
    3 -> unknown, but potentially used before GM:S
    4 -> either an included data file, or a "generic placeholder" file
    5 -> JS "placeholder"
    
   List of functions in the include file (if Kind is 2 [which is "GML placeholder"], then this is always empty):
    Int32 - Count
    <list of 32-bit pointers to each item, as in List<T> format>
    
    Each item:
     32-bit string pointer to function name, as referenced in GameMaker (Name)
     Int32 - function ID (Id) - just a unique ID of some kind (very likely based on code analysis, incrementing)
     Int32 - function type/kind (Kind)
      
     Int32 - function return type (ReturnType). Value taken directly from project file:
      1 -> string
      2 -> double
     
     32-bit string pointer to external function name (in the external file); not as it is referenced in GameMaker code, unless they are identical (ExtName)
     
     Int32 - Count of arguments
     Array (NOT a List-type thing) of Int32, count of items is the "Count of arguments" just stated - represents each argument's type. Value taken directly from project file:
      1 -> string
      2 -> double

SHDR

https://github.com/krzys-h/UndertaleModTool/issues/13

SHDR: ListChunk
This chunk seems pretty strange and complex in some places, and I tried my best to document it (somewhat) clearly.
---
<normal FourCC and chunk length>

List<T> format beginning:
 Int32 - count
 <list of 32-bit pointers to each item>
 
 For each item:
  32-bit string pointer to shader name
  
  Int32 - shader type with a bitwise OR against -0x80000000 (in big endian here, also it's signed and negative), as a number it is -2147483648
   Basically, in this case, this just changes the last byte of the little-endian Int32 to 0x80. For what reason is unknown?
   Little-endian-formatted types that are known, total of seven:
    0x01000080 (1) -> GLSL ES
    0x01000080 (2) -> GLSL
    0x03000080 (3) -> Unknown
    0x04000080 (4) -> HLSL
    0x05000080 to 0x07000080 (5 to 7) -> Unknown
   Missing from this list (the "unknown" types) are PSSL (PlayStation Shader Language), Cg, and Cg_PS3 (for PS3 seemingly)
    Also potentially a difference between HLSL9 and HLSL11
    I was unable to test these
  
  <note: many of the strings and pointers in this chunk will be null>
  32-bit string pointer to GLSL ES vertex shader code
  32-bit string pointer to GLSL ES fragment shader code
  32-bit string pointer to GLSL vertex shader code
  32-bit string pointer to GLSL fragment shader code
  32-bit string pointer to HLSL9 vertex shader code
  32-bit string pointer to HLSL9 fragment shader code
  
  <note: I'm going to give some pointers ID numbers so it's easy to tell where they go in the chunk>
  32-bit pointer to HLSL11 vertex shader string/bytes (ID #1)
  32-bit pointer to HLSL11 pixel shader string/bytes (ID #2)
  
  Int32 - count of vertex shader attributes
  Array (NOT a List<T>) of 32-bit string pointers, using the count specified on the last line, each representing a vertex shader attribute
  
  Int32 - literally just the number 2
  
  32-bit pointer to PSSL vertex shader string/bytes (ID #3)
  Int32 - length of PSSL vertex shader string/bytes
  32-bit pointer to PSSL pixel shader string/bytes (ID #4)
  Int32 - length of PSSL pixel shader string/bytes
  
  32-bit pointer to Cg vertex shader string/bytes (ID #5)
  Int32 - length of Cg vertex shader string/bytes
  32-bit pointer to Cg pixel shader string/bytes (ID #6)
  Int32 - length of Cg pixel shader string/bytes
  
  32-bit pointer to Cg_PS3 vertex shader string/bytes (ID #7)
  Int32 - length of Cg_PS3 vertex shader string/bytes
  32-bit pointer to Cg_PS3 pixel shader string/bytes (ID #8)
  Int32 - length of Cg_PS3 pixel shader string/bytes
  
  <note: Here's where everything starts to get complicated. I will do my best to represent if statements and loops used>
  <note2: This part contains a lot of actual shader data, but not all of it>
  <note3: There is a lot of strange padding involved, but it's probably unnecessary when re-compiling because of pointers?>
  
  If there is HLSL11 vertex shader data:
   While (Int64 stream position/position in file) bitwise AND (Int32 number 7) is not 0:
    Byte - number 0
   <pointer ID #1 leads here>
   The buffer/bytes/string for the shader data - the length is found nowhere else, maybe?
    Or it's a possibility that you read until you hit the necessary zero padding before the location the next pointer points to (for the next shader data)?
    Or you just continually read through the zeros until you hit the next shader data (using the pointers)?
  
  If there is HLSL11 pixel shader data:
   While (Int64 stream position/position in file) bitwise AND (Int32 number 7) is not 0:
    Byte - number 0
   <pointer ID #2 leads here>
   The buffer/bytes/string for the shader data - the length is found nowhere else, maybe?
    (same thoughts as above)
    
  If there is PSSL vertex shader data:
   While (Int64 stream position/position in file) bitwise AND (Int32 number 7) is not 0:
    Byte - number 0
   <pointer ID #3 leads here>
   The buffer/bytes/string for the shader data - the length is found nowhere else, maybe?
    (same thoughts as above)
    
  If there is PSSL pixel shader data:
   While (Int64 stream position/position in file) bitwise AND (Int32 number 7) is not 0:
    Byte - number 0
   <pointer ID #4 leads here>
   The buffer/bytes/string for the shader data - the length is found nowhere else, maybe?
    (same thoughts as above)
    
  If there is Cg vertex shader data:
   While (Int64 stream position/position in file) bitwise AND (Int32 number 7) is not 0:
    Byte - number 0
   <pointer ID #5 leads here>
   The buffer/bytes/string for the shader data - the length is found nowhere else, maybe?
    (same thoughts as above)
    
  If there is Cg pixel shader data:
   While (Int64 stream position/position in file) bitwise AND (Int32 number 7) is not 0:
    Byte - number 0
   <pointer ID #6 leads here>
   The buffer/bytes/string for the shader data - the length is found nowhere else, maybe?
    (same thoughts as above)
    
  <note: Take care of the next two: it uses the number 15 for its bitwise AND operation instead of 7)
  
  If there is Cg_PS3 vertex shader data:
   While (Int64 stream position/position in file) bitwise AND (Int32 number 15) is not 0:
    Byte - number 0
   <pointer ID #7 leads here>
   The buffer/bytes/string for the shader data - the length is found nowhere else, maybe?
    (same thoughts as above)
    
  If there is Cg_PS3 pixel shader data:
   While (Int64 stream position/position in file) bitwise AND (Int32 number 15) is not 0:
    Byte - number 0
   <pointer ID #8 leads here>
   The buffer/bytes/string for the shader data - the length is found nowhere else, maybe?
    (same thoughts as above)

TMLN

https://github.com/krzys-h/UndertaleModTool/issues/31#issuecomment-427948887

TMLN: ListChunk
---
<normal FourCC and chunk length in every chunk>

List<T> format beginning:
 Int32 - count
 <list of 32-bit pointers to each item>
 
 For each item:
  32-bit string pointer to timeline name
  
  Int32 - count/length of following array
  Array of events and "subtypes". each item:
   Int32 - the time point of the moment/event in the timeline
   32-bit pointer to event data in the next array
  
  Another array of event data, using the same count as the previous array. each item:
   <pointers from previous array lead to each item in this array, right here>
   
   List<T> to each action in the event, same exact format as actions in objects (EventAction in UndertaleModLib code)
⚠️ **GitHub.com Fallback** ⚠️