Advertisement
liquidspark

extracthalotagdefs

Aug 28th, 2018
297
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 45.58 KB | None | 0 0
  1. //
  2. //  main.m
  3. //  extracthalotagdefs
  4. //
  5. //  Created by silent on 8/3/18.
  6. //  Copyright © 2018 haloserver. All rights reserved.
  7. //
  8.  
  9. #import <stdio.h>
  10. #import <stdlib.h>
  11. #import <string.h>
  12. #import <stdbool.h>
  13.  
  14. const uint8_t negone[] = { 0xFF, 0xFF, 0xFF, 0xFF };
  15. const char* hex = "0123456789abcdef";
  16. static uint32_t min_filesizes[83] = {0};
  17. static uint32_t max_filesizes[83] = {0};
  18. // used to store file data
  19. struct file_data
  20. {
  21.     size_t length;
  22.     //size_t* offset;   // dynamic number indicating offset from bytes, for "pointer math" during sequential parsing of bytes
  23.     void* bytes;
  24. };
  25. #define MEMREGION 0x400000  // subtract this from all pointer values to obtain file data offset
  26. #define GUERILLA_DEFS_INDEX 0x5b8d88    // the actual file data offset start for mode tag
  27. enum datatypes
  28. {
  29.     datatype_string = 0x00,
  30.     datatype_char_integer = 0x01,
  31.     datatype_short_integer = 0x02,
  32.     datatype_long_integer = 0x03,
  33.     datatype_angle = 0x04,
  34.     datatype_tag = 0x05,
  35.     datatype_enum = 0x06,
  36.     datatype_long_flags = 0x07,
  37.     datatype_word_flags = 0x08,
  38.     datatype_byte_flags = 0x09,
  39.     datatype_point_2d = 0x0A,
  40.     datatype_rectangle_2d = 0x0B,
  41.     datatype_rgb_color = 0x0C,
  42.     datatype_argb_color = 0x0D,
  43.     datatype_real = 0x0E,
  44.     datatype_real_fraction = 0x0F,
  45.     datatype_real_point_2d = 0x10,
  46.     datatype_real_point_3d = 0x11,
  47.     datatype_real_vector_2d = 0x12,
  48.     datatype_real_vector_3d = 0x13,
  49.     datatype_real_quaternion = 0x14,
  50.     datatype_real_euler_angles_2d = 0x15,
  51.     datatype_real_euler_angles_3d = 0x16,
  52.     datatype_real_plane_2d = 0x17,
  53.     datatype_real_plane_3d = 0x18,
  54.     datatype_real_rgb_color = 0x19,
  55.     datatype_real_argb_color = 0x1A,
  56.     datatype_real_hsv_color = 0x1B,
  57.     datatype_real_ahsv_color = 0x1C,
  58.     datatype_short_integer_bounds = 0x1D,
  59.     datatype_angle_bounds = 0x1E,
  60.     datatype_real_bounds = 0x1F,
  61.     datatype_fraction_bounds = 0x20,
  62.     datatype_tag_reference = 0x21,
  63.     datatype_block = 0x22,
  64.     datatype_short_block_index = 0x23,
  65.     datatype_long_block_index = 0x24,
  66.     datatype_data = 0x25,
  67.     datatype_array_start = 0x26,
  68.     datatype_array_end = 0x27,
  69.     datatype_pad = 0x28,
  70.     datatype_skip = 0x29,
  71.     datatype_explanation = 0x2A,
  72.     datatype_custom = 0x2B,
  73.     datatype_terminator_X = 0x2C
  74. };
  75. struct entry_number_field
  76. {
  77.     enum datatypes type;
  78.     char* name;
  79.     uint8_t pad[4];
  80. };
  81. struct entry_struct_field
  82. {
  83.     enum datatypes type;
  84.     char* name;
  85.     void* definition;
  86. };
  87. struct entry_pad_field
  88. {
  89.     enum datatypes type;
  90.     uint8_t pad[4];
  91.     uint32_t size;
  92. };
  93. struct entry_dependency_info
  94. {
  95.     uint32_t usage_flags;
  96.     char class[4];
  97.     uint8_t pad_2[4];
  98. };
  99. struct entry_dependency_field
  100. {
  101.     enum datatypes type;
  102.     char* name;
  103.     struct entry_dependency_info definition;    // pointer
  104. };
  105. struct entry_flags_info
  106. {
  107.     uint32_t count;
  108.     char* (*names)[];   // pointer to array of pointers
  109. };
  110. struct entry_flags_field
  111. {
  112.     enum datatypes type;
  113.     char* name;
  114.     struct entry_flags_info info;   // a pointer
  115. };
  116. struct entry_block
  117. {
  118.     char* name;
  119.     uint32_t min_count; // ???
  120.     uint32_t max_count;
  121.     uint32_t definition_size;
  122.     uint8_t pad[4];
  123.     uint32_t definition_offset; //void* definition; // this is a void pointer, but I use it for parsing purposes as a uint32_t static file offset
  124. };
  125. struct entry_block_field
  126. {
  127.     enum datatypes type;
  128.     char* label;
  129.     struct entry_block definition; // pointer
  130. };
  131. // This is an older interpretation I did from looking at guerilla.exe in memory. I don't use this in this program.
  132. struct entry_array_memory
  133. {
  134.     char* name;
  135.     uint32_t is_deep;   // (has sub-arrays, sub-data, or dependencies)
  136.     uint32_t max_count;
  137.     uint32_t max_bytes; // with tag class, excludes 64 bytes of header
  138.     uint8_t pad[4];
  139.     void* definition;
  140. };
  141. // Arrays here are repeated cells of data whose definitions consist of all fields between array_start and array_end fields. If the fields are presented at all, if they have a visible string, the group of intermediary fields is repeated the number of times stored in repetitions.
  142. struct entry_array_start_field
  143. {
  144.     enum datatypes type;
  145.     char* name;
  146.     uint32_t repetitions;
  147. };
  148. struct entry_array_end_field
  149. {
  150.     enum datatypes type;
  151.     uint8_t pad[8];
  152. };
  153. struct entry_data
  154. {
  155.     char* name;
  156.     uint32_t interface_flags;
  157.     uint32_t max_bytes; // with tag class, excludes 64 bytes of header
  158.     uint8_t pad[4];
  159. };
  160. struct entry_data_field
  161. {
  162.     enum datatypes type;
  163.     char* label;
  164.     struct entry_data definition; // pointer
  165. };
  166. struct entry_custom_field
  167. {
  168.     enum datatypes type;
  169.     uint8_t pad[4];
  170.     char field_class[4];
  171. };
  172. struct tag_block
  173. {
  174.     char* name;
  175.     uint8_t pad_1[4];
  176.     uint32_t count; // always 1?
  177.     uint32_t size;  // excludes 64 bytes of header
  178.     uint8_t pad_2[4];
  179.     uint32_t chunks_offset; //void* chunks; // this is a void pointer, but I use it for parsing purposes as a uint32_t static file offset
  180.     uint8_t pad_3[4];
  181.     uint32_t extra_data_1_offset;   //void* extra1;
  182.     uint8_t pad_4[4];
  183.     uint32_t extra_data_2_offset;   //void* extra2;
  184. };
  185. struct tag_info
  186. {
  187.     char* file_extension;
  188.     int32_t unknown;
  189.     char class[4];
  190.     char superclass[4];
  191.     int32_t version;
  192.     uint32_t extra_data_offset; //void* extra;  // pointer to some extra data
  193.     struct tag_block* definition;
  194. };
  195.  
  196. struct file_data store_file(const char *path)
  197. {
  198.     struct file_data result = { 0, calloc(1, sizeof(size_t)) };
  199.     if (path == NULL) return result;
  200.     FILE* file = fopen(path, "r");
  201.     if (file == NULL) return result;
  202.     if (fseek(file, 0, SEEK_END) != 0) { fclose(file); return result; }
  203.     long filesize = ftell(file);
  204.     if (filesize == -1 || filesize == 0) { fclose(file); return result; }
  205.     void *data = calloc(1, (size_t)filesize);
  206.     if (data == NULL)  { fclose(file); return result; }
  207.     rewind(file);
  208.     if (fread(data, (size_t)filesize, 1, file) != 1) { free(data); fclose(file); return result; }
  209.     fclose(file);
  210.     result.length = (size_t)filesize;
  211.     result.bytes = data;
  212.     return result;
  213. }
  214. // returns the number of equivalent bytes, unlike memcmp
  215. size_t compare_bytes(const void* given1, const void* given2, size_t length)
  216. {
  217.     if (given1 == NULL || given2 == NULL || length <= 0) return 0;
  218.     for (size_t i = 0; i < length; i++)
  219.     {
  220.         if (*(uint8_t*)(given1 + i) != *(uint8_t*)(given2 + i)) return i;
  221.     }
  222.     return length;
  223. }
  224.  
  225. bool contains_nonzero_bytes(const void* data, size_t data_length)
  226. {
  227.     if (data != NULL && data_length > 0)
  228.     {
  229.         for (size_t i = 0; i < data_length; i++)
  230.         {
  231.             if (*(uint8_t*)(data + i) != 0)
  232.                 return true;
  233.         }
  234.     }
  235.     return false;
  236. }
  237.  
  238. // based upon https://stackoverflow.com/a/785681/2846508
  239. // does not work with constant strings; will work with arrays (that are null-terminated) but not with this: char *s="actr"
  240. void reverse_string(char* s)
  241. {
  242.     if (s != NULL && *s != '\0')
  243.     {
  244.         char temp, *end = s + strlen(s);
  245.         while ( --end > s ) { temp = *s; *s++ = *end; *end=temp; }
  246.     }
  247. }
  248.  
  249. void reverse_bytes(void* data, size_t data_length)
  250. {
  251.     if (data != NULL && data_length > 1)
  252.     {
  253.         uint8_t temp, *point1 = data, *point2 = data + data_length;
  254.         while ( --point2 > point1 ) { temp = *point1; *(point1++) = *point2; *point2 = temp; }
  255.     }
  256. }
  257. // convert static pointer address to HEK program binary offset
  258. // this lets me interpret all pointers as file data offsets in the file data bytes array, or use pointer math with void* bytes
  259. uint32_t p2o(const void* given)
  260. {
  261.     if (given == NULL) return 0;
  262.     return *(uint32_t*)given - MEMREGION;
  263. }
  264. char* o2string(struct file_data file, uint32_t offset)
  265. {
  266.     return (char*)((uint8_t*)file.bytes + p2o((uint8_t*)file.bytes + offset));
  267. }
  268. char* o2directstring(struct file_data file, uint32_t offset)
  269. {
  270.     return (char*)((uint8_t*)file.bytes + (offset - MEMREGION));
  271. }
  272. void* o2pointer(struct file_data file, uint32_t offset)
  273. {
  274.     return (void*)((uint8_t*)file.bytes + p2o((uint8_t*)file.bytes + offset));
  275. }
  276. int32_t int32val(struct file_data file, uint32_t offset)
  277. {
  278.     int32_t result = 0;
  279.     if (file.bytes != NULL && (offset + sizeof(int32_t) <= file.length))
  280.         memcpy(&result, (uint8_t*)file.bytes + offset, sizeof(int32_t));
  281.     return result;
  282. }
  283. uint32_t uint32val(struct file_data file, uint32_t offset)
  284. {
  285.     uint32_t result = 0;
  286.     if (file.bytes != NULL && (offset + sizeof(uint32_t) <= file.length))
  287.         memcpy(&result, (uint8_t*)file.bytes + offset, sizeof(uint32_t));
  288.     return result;
  289. }
  290. void o2array(struct file_data file, uint32_t offset, void* array, size_t array_length, bool reverse)
  291. {
  292.     if (array == NULL)
  293.     {
  294.         array = calloc(1, array_length);
  295.     }
  296.     if ((file.bytes != NULL) && (offset + array_length <= file.length) && (array != NULL))
  297.     {
  298.         memcpy(array, (uint8_t*)file.bytes + offset, array_length);
  299.         if (reverse == true)
  300.             reverse_bytes(array, array_length);
  301.     }
  302. }
  303. void data_to_tagblock(struct file_data file, uint32_t offset, struct tag_block* destination)
  304. {
  305.     destination->name = o2string(file, offset);
  306.     offset += 4;
  307.     o2array(file, offset, destination->pad_1, sizeof(destination->pad_1), false);
  308.     offset += sizeof(destination->pad_1);
  309.     destination->count = uint32val(file, offset);
  310.     offset += 4;
  311.     destination->size = uint32val(file, offset);
  312.     offset += 4;
  313.     o2array(file, offset, destination->pad_2, sizeof(destination->pad_2), false);
  314.     offset += sizeof(destination->pad_2);
  315.     destination->chunks_offset = p2o((uint8_t*)file.bytes + offset);
  316.     offset += 4;
  317.     o2array(file, offset, destination->pad_3, sizeof(destination->pad_3), false);
  318.     offset += sizeof(destination->pad_3);
  319.     destination->extra_data_1_offset = uint32val(file, offset);
  320.     offset += 4;
  321.     o2array(file, offset, destination->pad_4, sizeof(destination->pad_4), false);
  322.     offset += sizeof(destination->pad_4);
  323.     destination->extra_data_2_offset = uint32val(file, offset);
  324. }
  325. void data_to_taginfo(struct file_data file, uint32_t offset, struct tag_info* destination, uint32_t entry_index)
  326. {
  327.     destination->file_extension = o2string(file, offset);
  328.     offset += 4;
  329.     destination->unknown = int32val(file, offset);
  330.     offset += 4;
  331.     o2array(file, offset, destination->class, sizeof(destination->class), true);
  332.     offset += 4;
  333.     o2array(file, offset, destination->superclass, sizeof(destination->superclass), true);
  334.     offset += 4;
  335.     destination->version = int32val(file, offset);
  336.     offset += 4;
  337.     destination->extra_data_offset = uint32val(file, offset);
  338.     offset += 4;
  339.     destination->definition = calloc(1, sizeof(struct tag_block));
  340.     data_to_tagblock(file, p2o((uint8_t*)file.bytes + offset), destination->definition);
  341.     min_filesizes[entry_index] = 64 + destination->definition->size;
  342.     max_filesizes[entry_index] = 64 + destination->definition->size;
  343. }
  344. struct entry_flags_info get_flags(struct file_data file, uint32_t offset)
  345. {
  346.     struct entry_flags_info result;
  347.     if (file.bytes != NULL && (offset + 8 <= file.length))
  348.     {
  349.         result.count = uint32val(file, offset);
  350.         result.names = (char*(*)[])((uint8_t*)file.bytes + offset + 4);
  351.     }
  352.     return result;
  353. }
  354. struct entry_block get_block(struct file_data file, uint32_t offset)
  355. {
  356.     struct entry_block result;
  357.     if (file.bytes != NULL && (offset + 24 <= file.length))
  358.     {
  359.         result.name = o2string(file, offset);
  360.         result.min_count = uint32val(file, offset + 4);
  361.         result.max_count = uint32val(file, offset + 8);
  362.         result.definition_size = uint32val(file, offset + 12);
  363.         o2array(file, offset + 16, result.pad, sizeof(result.pad), false);
  364.         result.definition_offset = uint32val(file, offset + 20) - MEMREGION;
  365.     }
  366.     return result;
  367. }
  368. void release(struct tag_info* taginfo)
  369. {
  370.     // free every use of calloc
  371.     free(taginfo->definition);
  372.     free(taginfo);
  373. }
  374. void indent(int levels)
  375. {
  376.     for (int i=0; i<levels; i++)
  377.     {
  378.         printf("\t");
  379.     }
  380. }
  381. void print_hex_string_from_bytes(const void* bytes, size_t length)
  382. {
  383.     if (bytes == NULL || length == 0)
  384.         return;
  385.     char* result = calloc(1, length*3 + 1);
  386.     if (result == NULL)
  387.         return;
  388.     size_t char_offset = 0;
  389.     for (size_t i = 0; i < length; i++)
  390.     {
  391.         // for each byte, set the two characters based upon hexadecimal string
  392.         result[char_offset] = hex[*((uint8_t*)bytes + i) >> 4 & 0xF];
  393.         char_offset += 1;
  394.         result[char_offset] = hex[*((uint8_t*)bytes + i) & 0xF];
  395.         char_offset += 1;
  396.         if (i + 1 < length)
  397.         {
  398.             result[char_offset] = ':';
  399.             char_offset += 1;
  400.         }
  401.     }
  402.     printf("%s\n",result);
  403.     free(result);
  404. }
  405. void describe_tagblock(struct tag_block* tagblock, int levels)
  406. {
  407.     indent(levels);
  408.     //printf("struct %s\n",tagblock->name);
  409.     //indent(levels);
  410.     printf("{\n");
  411.     levels += 1;
  412.    
  413.     indent(levels);
  414.     printf("Name: %s\n",tagblock->name);
  415.    
  416.     if (contains_nonzero_bytes(tagblock->pad_1, sizeof(tagblock->pad_1)))
  417.     {
  418.         indent(levels);
  419.         printf("Pad 1: ");
  420.         print_hex_string_from_bytes(tagblock->pad_1, sizeof(tagblock->pad_1));
  421.     }
  422.    
  423.     indent(levels);
  424.     printf("Count: %u\n",tagblock->count);
  425.    
  426.     indent(levels);
  427.     printf("Size: %u\n",tagblock->size);
  428.    
  429.     if (contains_nonzero_bytes(tagblock->pad_2, sizeof(tagblock->pad_2)))
  430.     {
  431.         indent(levels);
  432.         printf("Pad 2: ");
  433.         print_hex_string_from_bytes(tagblock->pad_2, sizeof(tagblock->pad_2));
  434.     }
  435.    
  436.     indent(levels);
  437.     printf("Chunks Offset: 0x%x\n",tagblock->chunks_offset);
  438.    
  439.     if (contains_nonzero_bytes(tagblock->pad_3, sizeof(tagblock->pad_3)))
  440.     {
  441.         indent(levels);
  442.         printf("Pad 3: ");
  443.         print_hex_string_from_bytes(tagblock->pad_3, sizeof(tagblock->pad_3));
  444.     }
  445.    
  446.     if (contains_nonzero_bytes(&tagblock->extra_data_1_offset, sizeof(tagblock->extra_data_1_offset)))
  447.     {
  448.         indent(levels);
  449.         printf("Dialog Data 1 Offset: 0x%x\n",tagblock->extra_data_1_offset);
  450.     }
  451.    
  452.     if (contains_nonzero_bytes(tagblock->pad_4, sizeof(tagblock->pad_4)))
  453.     {
  454.         indent(levels);
  455.         printf("Pad 4: ");
  456.         print_hex_string_from_bytes(tagblock->pad_4, sizeof(tagblock->pad_4));
  457.     }
  458.    
  459.     if (contains_nonzero_bytes(&tagblock->extra_data_2_offset, sizeof(tagblock->extra_data_2_offset)))
  460.     {
  461.         indent(levels);
  462.         printf("Dialog Data 2 Offset: 0x%x\n",tagblock->extra_data_2_offset);
  463.     }
  464.    
  465.     levels -= 1;
  466.     indent(levels);
  467.     printf("}\n");
  468. }
  469. void describe_taginfo(struct tag_info* taginfo)
  470. {
  471.     // print tag info using number of nested (indented) levels
  472.     printf("Extension: %s\n", taginfo->file_extension);
  473.     printf("Unknown: %i\n", taginfo->unknown);
  474.     printf("Class: %c%c%c%c\n", taginfo->class[0], taginfo->class[1], taginfo->class[2], taginfo->class[3]);
  475.     if (compare_bytes(taginfo->superclass, negone, 4) == 4)
  476.         printf("No superclass\n");
  477.     else
  478.         printf("Superclass: %c%c%c%c\n", taginfo->superclass[0], taginfo->superclass[1], taginfo->superclass[2], taginfo->superclass[3]);
  479.     printf("Version: %i\n", taginfo->version);
  480.     if (contains_nonzero_bytes(&taginfo->extra_data_offset, sizeof(taginfo->extra_data_offset)))
  481.     {
  482.         printf("Dialog Data Offset: 0x%x\n", taginfo->extra_data_offset);
  483.     }
  484.     printf("Definition Block:\n");
  485.     describe_tagblock(taginfo->definition, 0);
  486. }
  487. struct temp_entry
  488. {
  489.     enum datatypes type;
  490.     char* name;
  491.     uint32_t something;
  492. };
  493. struct temp_entry read_entry(struct file_data file, uint32_t offset)
  494. {
  495.     struct temp_entry result;
  496.     result.type = uint32val(file, offset);
  497.     result.name = o2string(file, offset + 4);
  498.     result.something = uint32val(file, offset + 8);
  499.     return result;
  500. }
  501. void print_fields_in_c(struct file_data file, uint32_t offset, int levels, uint32_t entry_index)
  502. {
  503.     //int entry_index = 0;
  504.     while (true)
  505.     {
  506.         if (offset + 12 > file.length)
  507.             return; // file data too short
  508.         struct temp_entry entry = read_entry(file, offset);
  509.         offset += 12;
  510.         switch (entry.type)
  511.         {
  512.             case datatype_string:
  513.             {
  514.                 struct entry_number_field number = { entry.type, entry.name };
  515.                 indent(levels);
  516.                 printf("string               %s\n", number.name);
  517.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  518.                 {
  519.                     indent(levels);
  520.                     printf("{\n");
  521.                     levels += 1;
  522.                     indent(levels);
  523.                     printf("Padding: ");
  524.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  525.                     levels -= 1;
  526.                     indent(levels);
  527.                     printf("}\n");
  528.                 }
  529.                
  530.                 break;
  531.             }
  532.             case datatype_char_integer:
  533.             {
  534.                 struct entry_number_field number = { entry.type, entry.name };
  535.                 indent(levels);
  536.                 printf("char_integer         %s\n", number.name);
  537.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  538.                 {
  539.                     indent(levels);
  540.                     printf("{\n");
  541.                     levels += 1;
  542.                     indent(levels);
  543.                     printf("Padding: ");
  544.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  545.                     levels -= 1;
  546.                     indent(levels);
  547.                     printf("}\n");
  548.                 }
  549.                
  550.                 break;
  551.             }
  552.             case datatype_short_integer:
  553.             {
  554.                 struct entry_number_field number = { entry.type, entry.name };
  555.                 indent(levels);
  556.                 printf("short_integer        %s\n", number.name);
  557.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  558.                 {
  559.                     indent(levels);
  560.                     printf("{\n");
  561.                     levels += 1;
  562.                     indent(levels);
  563.                     printf("(used as a short_block_index)\n");
  564.                     indent(levels);
  565.                     printf("Block Name: %s\n", o2string(file, entry.something - MEMREGION));
  566.                     levels -= 1;
  567.                     indent(levels);
  568.                     printf("}\n");
  569.                 }
  570.                
  571.                 break;
  572.             }
  573.             case datatype_long_integer:
  574.             {
  575.                 struct entry_number_field number = { entry.type, entry.name };
  576.                 indent(levels);
  577.                 printf("long_integer         %s\n", number.name);
  578.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  579.                 {
  580.                     indent(levels);
  581.                     printf("{\n");
  582.                     levels += 1;
  583.                     indent(levels);
  584.                     printf("(used as a long_block_index)\n");
  585.                     indent(levels);
  586.                     printf("Block Name: %s\n", o2string(file, entry.something - MEMREGION));
  587.                     levels -= 1;
  588.                     indent(levels);
  589.                     printf("}\n");
  590.                 }
  591.                
  592.                 break;
  593.             }
  594.             case datatype_angle:
  595.             {
  596.                 struct entry_number_field number = { entry.type, entry.name };
  597.                 indent(levels);
  598.                 printf("angle                %s\n", number.name);
  599.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  600.                 {
  601.                     indent(levels);
  602.                     printf("{\n");
  603.                     levels += 1;
  604.                     indent(levels);
  605.                     printf("Padding: ");
  606.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  607.                     levels -= 1;
  608.                     indent(levels);
  609.                     printf("}\n");
  610.                 }
  611.                
  612.                 break;
  613.             }
  614.             case datatype_tag:
  615.             {
  616.                 struct entry_number_field number = { entry.type, entry.name };
  617.                 indent(levels);
  618.                 printf("tag                  %s\n", number.name);
  619.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  620.                 {
  621.                     indent(levels);
  622.                     printf("{\n");
  623.                     levels += 1;
  624.                     indent(levels);
  625.                     printf("Padding: ");
  626.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  627.                     levels -= 1;
  628.                     indent(levels);
  629.                     printf("}\n");
  630.                 }
  631.                
  632.                 break;
  633.             }
  634.             case datatype_enum:
  635.             {
  636.                 struct entry_flags_field flags = { entry.type, entry.name };
  637.                 indent(levels);
  638.                 printf("enum                 %s\n", flags.name);
  639.                 indent(levels);
  640.                 printf("{\n");
  641.                 levels += 1;
  642.                
  643.                 flags.info = get_flags(file, entry.something - MEMREGION);
  644.                
  645.                 for (int i = 0; i < flags.info.count; i++)
  646.                 {
  647.                     indent(levels);
  648.                     printf("%s\n",o2string(file, p2o(flags.info.names) + (i * sizeof(uint32_t))));
  649.                 }
  650.                
  651.                 levels -= 1;
  652.                 indent(levels);
  653.                 printf("}\n");
  654.                
  655.                 break;
  656.             }
  657.             case datatype_long_flags:
  658.             {
  659.                 struct entry_flags_field flags = { entry.type, entry.name };
  660.                 indent(levels);
  661.                 printf("long_flags           %s\n", flags.name);
  662.                 indent(levels);
  663.                 printf("{\n");
  664.                 levels += 1;
  665.                
  666.                 flags.info = get_flags(file, entry.something - MEMREGION);
  667.                
  668.                 for (int i = 0; i < flags.info.count; i++)
  669.                 {
  670.                     indent(levels);
  671.                     printf("%s\n",o2string(file, p2o(flags.info.names) + (i * sizeof(uint32_t))));
  672.                 }
  673.                
  674.                 levels -= 1;
  675.                 indent(levels);
  676.                 printf("}\n");
  677.                
  678.                 break;
  679.             }
  680.             case datatype_word_flags:
  681.             {
  682.                 struct entry_flags_field flags = { entry.type, entry.name };
  683.                 indent(levels);
  684.                 printf("word_flags           %s\n", flags.name);
  685.                 indent(levels);
  686.                 printf("{\n");
  687.                 levels += 1;
  688.                
  689.                 flags.info = get_flags(file, entry.something - MEMREGION);
  690.                
  691.                 for (int i = 0; i < flags.info.count; i++)
  692.                 {
  693.                     indent(levels);
  694.                     printf("%s\n",o2string(file, p2o(flags.info.names) + (i * sizeof(uint32_t))));
  695.                 }
  696.                
  697.                 levels -= 1;
  698.                 indent(levels);
  699.                 printf("}\n");
  700.                
  701.                 break;
  702.             }
  703.             case datatype_byte_flags:
  704.             {
  705.                 struct entry_flags_field flags = { entry.type, entry.name };
  706.                 indent(levels);
  707.                 printf("byte_flags           %s\n", flags.name);
  708.                 indent(levels);
  709.                 printf("{\n");
  710.                 levels += 1;
  711.                
  712.                 flags.info = get_flags(file, entry.something - MEMREGION);
  713.                
  714.                 for (int i = 0; i < flags.info.count; i++)
  715.                 {
  716.                     indent(levels);
  717.                     printf("%s\n",o2string(file, p2o(flags.info.names) + (i * sizeof(uint32_t))));
  718.                 }
  719.                
  720.                 levels -= 1;
  721.                 indent(levels);
  722.                 printf("}\n");
  723.                
  724.                 break;
  725.             }
  726.             case datatype_point_2d:
  727.             {
  728.                 struct entry_number_field number = { entry.type, entry.name };
  729.                 indent(levels);
  730.                 printf("point_2d             %s\n", number.name);
  731.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  732.                 {
  733.                     indent(levels);
  734.                     printf("{\n");
  735.                     levels += 1;
  736.                     indent(levels);
  737.                     printf("Padding: ");
  738.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  739.                     levels -= 1;
  740.                     indent(levels);
  741.                     printf("}\n");
  742.                 }
  743.                
  744.                 break;
  745.             }
  746.             case datatype_rectangle_2d:
  747.             {
  748.                 struct entry_number_field number = { entry.type, entry.name };
  749.                 indent(levels);
  750.                 printf("rectangle_2d         %s\n", number.name);
  751.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  752.                 {
  753.                     indent(levels);
  754.                     printf("{\n");
  755.                     levels += 1;
  756.                     indent(levels);
  757.                     printf("Padding: ");
  758.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  759.                     levels -= 1;
  760.                     indent(levels);
  761.                     printf("}\n");
  762.                 }
  763.                
  764.                 break;
  765.             }
  766.             case datatype_rgb_color:
  767.             {
  768.                 struct entry_number_field number = { entry.type, entry.name };
  769.                 indent(levels);
  770.                 printf("rgb_color            %s\n", number.name);
  771.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  772.                 {
  773.                     indent(levels);
  774.                     printf("{\n");
  775.                     levels += 1;
  776.                     indent(levels);
  777.                     printf("Padding: ");
  778.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  779.                     levels -= 1;
  780.                     indent(levels);
  781.                     printf("}\n");
  782.                 }
  783.                
  784.                 break;
  785.             }
  786.             case datatype_argb_color:
  787.             {
  788.                 struct entry_number_field number = { entry.type, entry.name };
  789.                 indent(levels);
  790.                 printf("argb_color           %s\n", number.name);
  791.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  792.                 {
  793.                     indent(levels);
  794.                     printf("{\n");
  795.                     levels += 1;
  796.                     indent(levels);
  797.                     printf("Padding: ");
  798.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  799.                     levels -= 1;
  800.                     indent(levels);
  801.                     printf("}\n");
  802.                 }
  803.                
  804.                 break;
  805.             }
  806.             case datatype_real:
  807.             {
  808.                 struct entry_number_field number = { entry.type, entry.name };
  809.                 indent(levels);
  810.                 printf("real                 %s\n", number.name);
  811.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  812.                 {
  813.                     indent(levels);
  814.                     printf("{\n");
  815.                     levels += 1;
  816.                     indent(levels);
  817.                     // change this to be a comment (#) later
  818.                     printf("Hidden documentation: %s\n", o2directstring(file, entry.something));
  819.                    
  820.                     levels -= 1;
  821.                     indent(levels);
  822.                     printf("}\n");
  823.                 }
  824.                
  825.                 break;
  826.             }
  827.             case datatype_real_fraction:
  828.             {
  829.                 struct entry_number_field number = { entry.type, entry.name };
  830.                 indent(levels);
  831.                 printf("real_fraction        %s\n", number.name);
  832.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  833.                 {
  834.                     indent(levels);
  835.                     printf("{\n");
  836.                     levels += 1;
  837.                     indent(levels);
  838.                     printf("Padding: ");
  839.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  840.                     levels -= 1;
  841.                     indent(levels);
  842.                     printf("}\n");
  843.                 }
  844.                
  845.                 break;
  846.             }
  847.             case datatype_real_point_2d:
  848.             {
  849.                 struct entry_number_field number = { entry.type, entry.name };
  850.                 indent(levels);
  851.                 printf("real_point_2d        %s\n", number.name);
  852.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  853.                 {
  854.                     indent(levels);
  855.                     printf("{\n");
  856.                     levels += 1;
  857.                     indent(levels);
  858.                     printf("Padding: ");
  859.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  860.                     levels -= 1;
  861.                     indent(levels);
  862.                     printf("}\n");
  863.                 }
  864.                
  865.                 break;
  866.             }
  867.             case datatype_real_point_3d:
  868.             {
  869.                 struct entry_number_field number = { entry.type, entry.name };
  870.                 indent(levels);
  871.                 printf("real_point_3d        %s\n", number.name);
  872.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  873.                 {
  874.                     indent(levels);
  875.                     printf("{\n");
  876.                     levels += 1;
  877.                     indent(levels);
  878.                     printf("Padding: ");
  879.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  880.                     levels -= 1;
  881.                     indent(levels);
  882.                     printf("}\n");
  883.                 }
  884.                
  885.                 break;
  886.             }
  887.             case datatype_real_vector_2d:
  888.             {
  889.                 struct entry_number_field number = { entry.type, entry.name };
  890.                 indent(levels);
  891.                 printf("real_vector_2d       %s\n", number.name);
  892.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  893.                 {
  894.                     indent(levels);
  895.                     printf("{\n");
  896.                     levels += 1;
  897.                     indent(levels);
  898.                     printf("Padding: ");
  899.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  900.                     levels -= 1;
  901.                     indent(levels);
  902.                     printf("}\n");
  903.                 }
  904.                
  905.                 break;
  906.             }
  907.             case datatype_real_vector_3d:
  908.             {
  909.                 struct entry_number_field number = { entry.type, entry.name };
  910.                 indent(levels);
  911.                 printf("real_vector_3d       %s\n", number.name);
  912.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  913.                 {
  914.                     indent(levels);
  915.                     printf("{\n");
  916.                     levels += 1;
  917.                     indent(levels);
  918.                     printf("Padding: ");
  919.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  920.                     levels -= 1;
  921.                     indent(levels);
  922.                     printf("}\n");
  923.                 }
  924.                
  925.                 break;
  926.             }
  927.             case datatype_real_quaternion:
  928.             {
  929.                 struct entry_number_field number = { entry.type, entry.name };
  930.                 indent(levels);
  931.                 printf("real_quaternion      %s\n", number.name);
  932.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  933.                 {
  934.                     indent(levels);
  935.                     printf("{\n");
  936.                     levels += 1;
  937.                     indent(levels);
  938.                     printf("Padding: ");
  939.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  940.                     levels -= 1;
  941.                     indent(levels);
  942.                     printf("}\n");
  943.                 }
  944.                
  945.                 break;
  946.             }
  947.             case datatype_real_euler_angles_2d:
  948.             {
  949.                 struct entry_number_field number = { entry.type, entry.name };
  950.                 indent(levels);
  951.                 printf("real_euler_angles_2d %s\n", number.name);
  952.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  953.                 {
  954.                     indent(levels);
  955.                     printf("{\n");
  956.                     levels += 1;
  957.                     indent(levels);
  958.                     printf("Padding: ");
  959.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  960.                     levels -= 1;
  961.                     indent(levels);
  962.                     printf("}\n");
  963.                 }
  964.                
  965.                 break;
  966.             }
  967.             case datatype_real_euler_angles_3d:
  968.             {
  969.                 struct entry_number_field number = { entry.type, entry.name };
  970.                 indent(levels);
  971.                 printf("real_euler_angles_3d %s\n", number.name);
  972.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  973.                 {
  974.                     indent(levels);
  975.                     printf("{\n");
  976.                     levels += 1;
  977.                     indent(levels);
  978.                     printf("Padding: ");
  979.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  980.                     levels -= 1;
  981.                     indent(levels);
  982.                     printf("}\n");
  983.                 }
  984.                
  985.                 break;
  986.             }
  987.             case datatype_real_plane_2d:
  988.             {
  989.                 struct entry_number_field number = { entry.type, entry.name };
  990.                 indent(levels);
  991.                 printf("real_plane_2d        %s\n", number.name);
  992.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  993.                 {
  994.                     indent(levels);
  995.                     printf("{\n");
  996.                     levels += 1;
  997.                     indent(levels);
  998.                     printf("Padding: ");
  999.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  1000.                     levels -= 1;
  1001.                     indent(levels);
  1002.                     printf("}\n");
  1003.                 }
  1004.                
  1005.                 break;
  1006.             }
  1007.             case datatype_real_plane_3d:
  1008.             {
  1009.                 struct entry_number_field number = { entry.type, entry.name };
  1010.                 indent(levels);
  1011.                 printf("real_plane_3d        %s\n", number.name);
  1012.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  1013.                 {
  1014.                     indent(levels);
  1015.                     printf("{\n");
  1016.                     levels += 1;
  1017.                     indent(levels);
  1018.                     printf("Padding: ");
  1019.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  1020.                     levels -= 1;
  1021.                     indent(levels);
  1022.                     printf("}\n");
  1023.                 }
  1024.                
  1025.                 break;
  1026.             }
  1027.             case datatype_real_rgb_color:
  1028.             {
  1029.                 struct entry_number_field number = { entry.type, entry.name };
  1030.                 indent(levels);
  1031.                 printf("real_rgb_color       %s\n", number.name);
  1032.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  1033.                 {
  1034.                     indent(levels);
  1035.                     printf("{\n");
  1036.                     levels += 1;
  1037.                     indent(levels);
  1038.                     printf("Padding: ");
  1039.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  1040.                     levels -= 1;
  1041.                     indent(levels);
  1042.                     printf("}\n");
  1043.                 }
  1044.                
  1045.                 break;
  1046.             }
  1047.             case datatype_real_argb_color:
  1048.             {
  1049.                 struct entry_number_field number = { entry.type, entry.name };
  1050.                 indent(levels);
  1051.                 printf("real_argb_color      %s\n", number.name);
  1052.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  1053.                 {
  1054.                     indent(levels);
  1055.                     printf("{\n");
  1056.                     levels += 1;
  1057.                     indent(levels);
  1058.                     printf("Padding: ");
  1059.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  1060.                     levels -= 1;
  1061.                     indent(levels);
  1062.                     printf("}\n");
  1063.                 }
  1064.                
  1065.                 break;
  1066.             }
  1067.             case datatype_real_hsv_color:
  1068.             {
  1069.                 struct entry_number_field number = { entry.type, entry.name };
  1070.                 indent(levels);
  1071.                 printf("real_hsv_color       %s\n", number.name);
  1072.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  1073.                 {
  1074.                     indent(levels);
  1075.                     printf("{\n");
  1076.                     levels += 1;
  1077.                     indent(levels);
  1078.                     printf("Padding: ");
  1079.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  1080.                     levels -= 1;
  1081.                     indent(levels);
  1082.                     printf("}\n");
  1083.                 }
  1084.                
  1085.                 break;
  1086.             }
  1087.             case datatype_real_ahsv_color:
  1088.             {
  1089.                 struct entry_number_field number = { entry.type, entry.name };
  1090.                 indent(levels);
  1091.                 printf("real_ahsv_color      %s\n", number.name);
  1092.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  1093.                 {
  1094.                     indent(levels);
  1095.                     printf("{\n");
  1096.                     levels += 1;
  1097.                     indent(levels);
  1098.                     printf("Padding: ");
  1099.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  1100.                     levels -= 1;
  1101.                     indent(levels);
  1102.                     printf("}\n");
  1103.                 }
  1104.                
  1105.                 break;
  1106.             }
  1107.             case datatype_short_integer_bounds:
  1108.             {
  1109.                 struct entry_number_field number = { entry.type, entry.name };
  1110.                 indent(levels);
  1111.                 printf("short_integer_bounds %s\n", number.name);
  1112.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  1113.                 {
  1114.                     indent(levels);
  1115.                     printf("{\n");
  1116.                     levels += 1;
  1117.                     indent(levels);
  1118.                     printf("Padding: ");
  1119.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  1120.                     levels -= 1;
  1121.                     indent(levels);
  1122.                     printf("}\n");
  1123.                 }
  1124.                
  1125.                 break;
  1126.             }
  1127.             case datatype_angle_bounds:
  1128.             {
  1129.                 struct entry_number_field number = { entry.type, entry.name };
  1130.                 indent(levels);
  1131.                 printf("angle_bounds         %s\n", number.name);
  1132.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  1133.                 {
  1134.                     indent(levels);
  1135.                     printf("{\n");
  1136.                     levels += 1;
  1137.                     indent(levels);
  1138.                     printf("Padding: ");
  1139.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  1140.                     levels -= 1;
  1141.                     indent(levels);
  1142.                     printf("}\n");
  1143.                 }
  1144.                
  1145.                 break;
  1146.             }
  1147.             case datatype_real_bounds:
  1148.             {
  1149.                 struct entry_number_field number = { entry.type, entry.name };
  1150.                 indent(levels);
  1151.                 printf("real_bounds          %s\n", number.name);
  1152.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  1153.                 {
  1154.                     indent(levels);
  1155.                     printf("{\n");
  1156.                     levels += 1;
  1157.                     indent(levels);
  1158.                     printf("Padding: ");
  1159.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  1160.                     levels -= 1;
  1161.                     indent(levels);
  1162.                     printf("}\n");
  1163.                 }
  1164.                
  1165.                 break;
  1166.             }
  1167.             case datatype_fraction_bounds:
  1168.             {
  1169.                 struct entry_number_field number = { entry.type, entry.name };
  1170.                 indent(levels);
  1171.                 printf("fraction_bounds      %s\n", number.name);
  1172.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  1173.                 {
  1174.                     indent(levels);
  1175.                     printf("{\n");
  1176.                     levels += 1;
  1177.                     indent(levels);
  1178.                     printf("Padding: ");
  1179.                     print_hex_string_from_bytes(&entry.something, sizeof(uint32_t));
  1180.                     levels -= 1;
  1181.                     indent(levels);
  1182.                     printf("}\n");
  1183.                 }
  1184.                
  1185.                 break;
  1186.             }
  1187.             case datatype_tag_reference:
  1188.             {
  1189.                 struct entry_dependency_field dependency = { entry.type, entry.name };
  1190.                 indent(levels);
  1191.                 printf("tag reference        %s\n", dependency.name);
  1192.                
  1193.                 struct entry_dependency_info x;
  1194.                 x.usage_flags = uint32val(file, entry.something - MEMREGION);
  1195.                 o2array(file, entry.something - MEMREGION + 4, x.class, sizeof(x.class), true);
  1196.                 o2array(file, entry.something - MEMREGION + 8, x.pad_2, sizeof(x.pad_2), false);
  1197.                 dependency.definition = x;
  1198.                
  1199.                 indent(levels);
  1200.                 printf("{\n");
  1201.                 levels += 1;
  1202.                
  1203.                 bool explicit_types = false;
  1204.                
  1205.                 if (contains_nonzero_bytes(&dependency.definition.usage_flags, sizeof(dependency.definition.usage_flags)))
  1206.                 {
  1207.                     indent(levels);
  1208.                     printf("Usage flags value: %u\n", dependency.definition.usage_flags);
  1209.                 }
  1210.                
  1211.                 if (compare_bytes(dependency.definition.class, negone, 4) != 4)
  1212.                 {
  1213.                     indent(levels);
  1214.                     printf("Supported tag class category: %c%c%c%c\n", dependency.definition.class[0], dependency.definition.class[1], dependency.definition.class[2], dependency.definition.class[3]);
  1215.                 }
  1216.                 else
  1217.                 {
  1218.                     // if this is -1, then there is a specific list of supported tag classes
  1219.                     explicit_types = true;
  1220.                     uint32_t zero = 0;
  1221.                     if (compare_bytes(dependency.definition.pad_2, &zero, 4) == 4)
  1222.                     {
  1223.                         // if this is zero, then there is no given list, meaning all tag classes are listed as supported
  1224.                         indent(levels);
  1225.                         printf("Supports all tag classes\n");
  1226.                     }
  1227.                     else
  1228.                     {
  1229.                         uint32_t list_offset = 0;
  1230.                         memcpy(&list_offset, dependency.definition.pad_2, sizeof(uint32_t));
  1231.                         list_offset -= MEMREGION;
  1232.                         do
  1233.                         {
  1234.                             o2array(file, list_offset, dependency.definition.class, sizeof(dependency.definition.class), true);
  1235.                             if (compare_bytes(dependency.definition.class, negone, 4) == 4)
  1236.                                 break;
  1237.                             indent(levels);
  1238.                             printf("Supported tag class: %c%c%c%c\n", dependency.definition.class[0], dependency.definition.class[1], dependency.definition.class[2], dependency.definition.class[3]);
  1239.                             list_offset += 4;
  1240.                         } while (compare_bytes(dependency.definition.class, negone, 4) != 4);
  1241.                     }
  1242.                 }
  1243.                
  1244.                 if (explicit_types == false && contains_nonzero_bytes(dependency.definition.pad_2, sizeof(dependency.definition.pad_2)))
  1245.                 {
  1246.                     indent(levels);
  1247.                     printf("Padding 2: ");
  1248.                     print_hex_string_from_bytes(dependency.definition.pad_2, sizeof(dependency.definition.pad_2));
  1249.                 }
  1250.                
  1251.                 levels -= 1;
  1252.                 indent(levels);
  1253.                 printf("}\n");
  1254.                
  1255.                 max_filesizes[entry_index] += 255;  // for tpns of max length
  1256.                
  1257.                 break;
  1258.             }
  1259.             case datatype_block:
  1260.             {
  1261.                 struct entry_block_field block = { entry.type, entry.name, get_block(file, entry.something - MEMREGION) };
  1262.                 indent(levels);
  1263.                 printf("block                %s\n", block.label);
  1264.                 indent(levels);
  1265.                 printf("{\n");
  1266.                 levels += 1;
  1267.                
  1268.                 indent(levels);
  1269.                 printf("Name: %s\n", block.definition.name);
  1270.                
  1271.                 if (contains_nonzero_bytes(&block.definition.min_count, sizeof(block.definition.min_count)))
  1272.                 {
  1273.                     indent(levels);
  1274.                     printf("Unknown: ");
  1275.                     print_hex_string_from_bytes(&block.definition.min_count, sizeof(block.definition.min_count));
  1276.                 }
  1277.                
  1278.                 indent(levels);
  1279.                 printf("Max Chunks: %u\n", block.definition.max_count);
  1280.                
  1281.                 indent(levels);
  1282.                 printf("Chunk Size: %u\n", block.definition.definition_size);
  1283.                
  1284.                 indent(levels);
  1285.                 printf("Max Chunks x Chunk Size: %u\n", (block.definition.max_count * block.definition.definition_size));
  1286.                
  1287.                 max_filesizes[entry_index] += (block.definition.max_count * block.definition.definition_size);  // this might not work properly with nested blocks...
  1288.                
  1289.                 if (contains_nonzero_bytes(block.definition.pad, sizeof(block.definition.pad)))
  1290.                 {
  1291.                     indent(levels);
  1292.                     printf("Pad: ");
  1293.                     print_hex_string_from_bytes(block.definition.pad, sizeof(block.definition.pad));
  1294.                 }
  1295.                
  1296.                 indent(levels);
  1297.                 printf("Chunk Definition Offset: 0x%x\n", block.definition.definition_offset);
  1298.                
  1299.                 indent(levels);
  1300.                 printf("{\n");
  1301.                 levels += 1;
  1302.                 print_fields_in_c(file, block.definition.definition_offset, levels, entry_index);
  1303.                 levels -= 1;
  1304.                 indent(levels);
  1305.                 printf("}\n");
  1306.                
  1307.                 levels -= 1;
  1308.                 indent(levels);
  1309.                 printf("}\n");
  1310.                
  1311.                 break;
  1312.             }
  1313.             case datatype_short_block_index:
  1314.             {
  1315.                 struct entry_number_field number = { entry.type, entry.name };
  1316.                 indent(levels);
  1317.                 printf("short_block_index    %s\n", number.name);
  1318.                 // entry.something is a definition pointer (for parsing)
  1319.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  1320.                 {
  1321.                     indent(levels);
  1322.                     printf("{\n");
  1323.                     levels += 1;
  1324.                     indent(levels);
  1325.                     printf("Block Name: %s\n", o2string(file, entry.something - MEMREGION));
  1326.                     levels -= 1;
  1327.                     indent(levels);
  1328.                     printf("}\n");
  1329.                 }
  1330.                
  1331.                 break;
  1332.             }
  1333.             case datatype_long_block_index:
  1334.             {
  1335.                 struct entry_number_field number = { entry.type, entry.name };
  1336.                 indent(levels);
  1337.                 printf("long_block_index     %s\n", number.name);
  1338.                 // entry.something is a definition pointer (for parsing)
  1339.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  1340.                 {
  1341.                     indent(levels);
  1342.                     printf("{\n");
  1343.                     levels += 1;
  1344.                     indent(levels);
  1345.                     printf("Block Name: %s\n", o2string(file, entry.something - MEMREGION));
  1346.                     levels -= 1;
  1347.                     indent(levels);
  1348.                     printf("}\n");
  1349.                 }
  1350.                
  1351.                 break;
  1352.             }
  1353.             case datatype_data:
  1354.             {
  1355.                 struct entry_data_field data_field = { entry.type, entry.name };
  1356.                 struct entry_data x;
  1357.                 x.name = o2string(file, entry.something - MEMREGION);
  1358.                 x.interface_flags = uint32val(file, entry.something - MEMREGION + 4);
  1359.                 x.max_bytes = uint32val(file, entry.something - MEMREGION + 8);
  1360.                 o2array(file, entry.something - MEMREGION + 12, x.pad, sizeof(x.pad), false);
  1361.                 data_field.definition = x;
  1362.                
  1363.                 indent(levels);
  1364.                 printf("data                 %s\n", data_field.label);
  1365.                
  1366.                 indent(levels);
  1367.                 printf("{\n");
  1368.                 levels += 1;
  1369.                
  1370.                 indent(levels);
  1371.                 printf("Definition Name: %s\n", data_field.definition.name);
  1372.                
  1373.                 if (contains_nonzero_bytes(&data_field.definition.interface_flags, sizeof(uint32_t)))
  1374.                 {
  1375.                     indent(levels);
  1376.                     printf("Interface Flags: %u\n", data_field.definition.interface_flags);
  1377.                 }
  1378.                
  1379.                 indent(levels);
  1380.                 printf("Max Bytes: %u\n", data_field.definition.max_bytes);
  1381.                
  1382.                 if (contains_nonzero_bytes(data_field.definition.pad, sizeof(data_field.definition.pad)))
  1383.                 {
  1384.                     indent(levels);
  1385.                     printf("Extra Data Offset: 0x%x\n", *(uint32_t*)data_field.definition.pad - MEMREGION);
  1386.                 }
  1387.                
  1388.                 levels -= 1;
  1389.                 indent(levels);
  1390.                 printf("}\n");
  1391.                
  1392.                 max_filesizes[entry_index] += x.max_bytes;
  1393.                
  1394.                 break;
  1395.             }
  1396.             case datatype_array_start:
  1397.             {
  1398.                 struct entry_array_start_field array_start = { entry.type, entry.name, entry.something };
  1399.                 indent(levels);
  1400.                 printf("array_start          \"%s\" repeated %u time(s):\n", array_start.name, array_start.repetitions);
  1401.                 levels += 1;
  1402.                 break;
  1403.             }
  1404.             case datatype_array_end:
  1405.             {
  1406.                 struct entry_array_end_field array_end = { entry.type };
  1407.                 memcpy(array_end.pad, (uint8_t*)file.bytes + (offset - 8), sizeof(array_end.pad));
  1408.                
  1409.                 levels -= 1;
  1410.                 indent(levels);
  1411.                 printf("array_end            \n");
  1412.                
  1413.                 if (contains_nonzero_bytes(array_end.pad, sizeof(array_end.pad)))
  1414.                 {
  1415.                     indent(levels);
  1416.                     printf("{\n");
  1417.                     levels += 1;
  1418.                    
  1419.                     indent(levels);
  1420.                     printf("Padding: ");
  1421.                     print_hex_string_from_bytes(array_end.pad, sizeof(array_end.pad));
  1422.                    
  1423.                     levels -= 1;
  1424.                     indent(levels);
  1425.                     printf("}\n");
  1426.                 }
  1427.                
  1428.                 break;
  1429.             }
  1430.             case datatype_pad:
  1431.             {
  1432.                 struct entry_pad_field pad;
  1433.                 pad.type = entry.type;
  1434.                 memcpy(pad.pad, (uint8_t*)file.bytes + (offset - 8), sizeof(pad.pad));
  1435.                 pad.size = entry.something;
  1436.                
  1437.                 indent(levels);
  1438.                 printf("pad[%u]\n", pad.size);
  1439.                
  1440.                 if (contains_nonzero_bytes(pad.pad, sizeof(pad.pad)))
  1441.                 {
  1442.                     indent(levels);
  1443.                     printf("{\n");
  1444.                     levels += 1;
  1445.                     indent(levels);
  1446.                     // change this to be a comment (#) later
  1447.                     printf("Hidden documentation (field name?): %s\n", entry.name);
  1448.                    
  1449.                     levels -= 1;
  1450.                     indent(levels);
  1451.                     printf("}\n");
  1452.                 }
  1453.                
  1454.                 break;
  1455.             }
  1456.             case datatype_skip:
  1457.             {
  1458.                 struct entry_pad_field pad;
  1459.                 pad.type = entry.type;
  1460.                 memcpy(pad.pad, (uint8_t*)file.bytes + (offset - 8), sizeof(pad.pad));
  1461.                 pad.size = entry.something;
  1462.                
  1463.                 indent(levels);
  1464.                 printf("skip[%u]\n", pad.size);
  1465.                
  1466.                 if (contains_nonzero_bytes(pad.pad, sizeof(pad.pad)))
  1467.                 {
  1468.                     indent(levels);
  1469.                     printf("{\n");
  1470.                     levels += 1;
  1471.                     indent(levels);
  1472.                     // change this to be a comment (#) later
  1473.                     printf("Hidden documentation (field name?): %s\n", entry.name);
  1474.                    
  1475.                     levels -= 1;
  1476.                     indent(levels);
  1477.                     printf("}\n");
  1478.                 }
  1479.                
  1480.                 break;
  1481.             }
  1482.             case datatype_explanation:
  1483.             {
  1484.                 struct entry_number_field number = { entry.type, entry.name };
  1485.                 indent(levels);
  1486.                 printf("explanation          %s\n", number.name);
  1487.                 if (contains_nonzero_bytes(&entry.something, sizeof(uint32_t)))
  1488.                 {
  1489.                     indent(levels);
  1490.                     printf("{\n");
  1491.                     levels += 1;
  1492.                     indent(levels);
  1493.                     printf("Dialog Data Offset: 0x%x\n", entry.something - MEMREGION);
  1494.                    
  1495.                     indent(levels);
  1496.                     printf("{\n");
  1497.                     //levels += 1;
  1498.                     //indent(levels);
  1499.                     printf("%s\n", o2directstring(file, entry.something));
  1500.                     //levels -= 1;
  1501.                     indent(levels);
  1502.                     printf("}\n");
  1503.                    
  1504.                     levels -= 1;
  1505.                     indent(levels);
  1506.                     printf("}\n");
  1507.                 }
  1508.                
  1509.                 break;
  1510.             }
  1511.             case datatype_custom:
  1512.             {
  1513.                 struct entry_custom_field custom;
  1514.                 custom.type = entry.type;
  1515.                 memcpy(custom.pad, (uint8_t*)file.bytes + (offset - 8), sizeof(custom.pad));
  1516.                 memcpy(custom.field_class, (uint8_t*)file.bytes + (offset - 4), sizeof(custom.field_class));
  1517.                 reverse_bytes(custom.field_class, sizeof(custom.field_class));
  1518.                
  1519.                 indent(levels);
  1520.                 printf("custom\n");
  1521.                
  1522.                 indent(levels);
  1523.                 printf("{\n");
  1524.                 levels += 1;
  1525.                
  1526.                 if (contains_nonzero_bytes(custom.pad, sizeof(custom.pad)))
  1527.                 {
  1528.                     indent(levels);
  1529.                     printf("Padding: ");
  1530.                     print_hex_string_from_bytes(custom.pad, sizeof(custom.pad));
  1531.                    
  1532.                 }
  1533.                
  1534.                 if (contains_nonzero_bytes(custom.field_class, sizeof(custom.field_class)))
  1535.                 {
  1536.                     indent(levels);
  1537.                     printf("Field Class: %c%c%c%c\n", custom.field_class[0], custom.field_class[1], custom.field_class[2], custom.field_class[3]);
  1538.                 }
  1539.                
  1540.                 levels -= 1;
  1541.                 indent(levels);
  1542.                 printf("}\n");
  1543.                
  1544.                 break;
  1545.             }
  1546.             case datatype_terminator_X:
  1547.             {
  1548.                 return;
  1549.             }
  1550.             default:
  1551.             {
  1552.                 indent(levels);
  1553.                 printf("***UNKNOWN DATATYPE***\n");
  1554.                 break;
  1555.             }
  1556.         }
  1557.     }
  1558.    
  1559. }
  1560.  
  1561. // the purpose of this program is to output in C the tag file definitions from within an HEK program.
  1562. int main(int argc, const char * argv[])
  1563. {
  1564.     @autoreleasepool
  1565.     {
  1566.         if (argc < 2) return 0;
  1567.         struct file_data file = store_file(argv[1]);
  1568.         //NSFileManager *fm = [NSFileManager new];
  1569.         //NSData *filedata = [fm contentsAtPath:[NSString stringWithCString:argv[1] encoding:NSUTF8StringEncoding]];
  1570.         if (file.bytes == NULL) return 1;
  1571.         // get all the tag definition file data offsets
  1572.         if (file.length < GUERILLA_DEFS_INDEX + (83 * sizeof(uint32_t))) return 1;
  1573.         uint32_t tag_def_offsets[83] = { 0 };
  1574.         printf("extracthalotagdefs and its resulting file are by sparky (e-mail:galaxyverge+halo@pm.me discord:sparky#0343 chat:https://discord.gg/mcEzrrv)\ntetelestai\ntag definitions parsed from guerilla.exe\nmodify output to suit your source code syntax needs by modifying extracthalotagdefs\nall credit to Jesus Christ for anything that pleases His Majesty, King of Glory\nnote that these definitions do not fully equate to stored file data...\nrespect me and what I freely did for you by leaving this printf statement intact\n\n");
  1575.         for (uint32_t i = 0; i < 83; i++)
  1576.         {
  1577.             tag_def_offsets[i] = p2o((uint8_t*)file.bytes + GUERILLA_DEFS_INDEX + (i * sizeof(uint32_t)));
  1578.             printf("Tag Definition Offset: 0x%x\n",tag_def_offsets[i]);
  1579.             if (tag_def_offsets[i] >= file.length) return 1;    // unusable data offset check, in case the supplied file has unexpected data
  1580.            
  1581.             // parse and output into string
  1582.             struct tag_info *tagdef = calloc(1, sizeof(struct tag_info));
  1583.             if (tagdef == NULL)
  1584.                 return 2;   // couldn't allocate memory during calloc
  1585.             data_to_taginfo(file, tag_def_offsets[i], tagdef, i);
  1586.             describe_taginfo(tagdef);
  1587.             print_fields_in_c(file, tagdef->definition->chunks_offset, 1, i);
  1588.             printf("POORLY-DETERMINED MIN FILESIZE OF %c%c%c%c (including 64-byte header): %u\n", tagdef->class[0], tagdef->class[1], tagdef->class[2], tagdef->class[3], min_filesizes[i]);
  1589.             printf("POORLY-DETERMINED MAX FILESIZE OF %c%c%c%c (including 64-byte header): %u\n", tagdef->class[0], tagdef->class[1], tagdef->class[2], tagdef->class[3], max_filesizes[i]);
  1590.             printf("\n");
  1591.             release(tagdef);
  1592.         }
  1593.        
  1594.     }
  1595.     return 0;
  1596. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement