tuxanci2-engine
Game engine for tuxanci2
Log | Files | Refs | README | LICENSE

tab.c (2877B)


      1 #include <stdint.h>
      2 #include <stdbool.h>
      3 #include <stddef.h>
      4 #include "tab.h"
      5 #include "fs.h"
      6 #include "api.h"
      7 
      8 typedef struct {
      9     uint32_t offset;
     10     uint32_t size;
     11     bool present;
     12 } ta_tab_entry;
     13 
     14 #ifdef TA_EMBED_GAME
     15 extern unsigned char ta_game_tab[];
     16 extern unsigned int ta_game_tab_len;
     17 #endif
     18 
     19 #ifdef TA_EMBED_GAME
     20 extern unsigned char ta_game_tab[];
     21 extern unsigned int ta_game_tab_len;
     22 #endif
     23 
     24 static ta_fs_file tab_file;
     25 static bool embedded;
     26 static ta_tab_entry entries[TA_TAB_MAX_FILES + 1];
     27 static bool loaded;
     28 
     29 static uint32_t read_le32(const uint8_t *data) {
     30     return (uint32_t)data[0] | ((uint32_t)data[1] << 8) | ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24);
     31 }
     32 
     33 static bool parse(const uint8_t *data, size_t length) {
     34     if (length < TA_TAB_HEADER_SIZE + TA_TAB_ENTRY_SIZE) {
     35         return false;
     36     }
     37 
     38     if (data[0] != TA_TAB_MAGIC_0 || data[1] != TA_TAB_MAGIC_1 || data[2] != TA_TAB_MAGIC_2 || data[3] != TA_TAB_MAGIC_3) {
     39         return false;
     40     }
     41 
     42     if (data[4] != TA_TAB_VERSION) {
     43         return false;
     44     }
     45 
     46     size_t position = TA_TAB_HEADER_SIZE;
     47 
     48     while (1) {
     49         if (length - position < TA_TAB_ENTRY_SIZE) {
     50             return false;
     51         }
     52 
     53         uint8_t file = data[position];
     54 
     55         if (file == TA_TAB_END) {
     56             break;
     57         }
     58 
     59         uint32_t size = read_le32(data + position + 1);
     60         uint32_t offset = read_le32(data + position + 5);
     61 
     62         if (entries[file].present || offset > length || size > length - offset) {
     63             return false;
     64         }
     65 
     66         entries[file].offset = offset;
     67         entries[file].size = size;
     68         entries[file].present = true;
     69 
     70         position += TA_TAB_ENTRY_SIZE;
     71     }
     72 
     73     return entries[TA_TAB_MAIN_PROGRAM].present;
     74 }
     75 
     76 bool ta_tab_load(const char *path) {
     77     ta_tab_unload();
     78 
     79 #ifdef TA_EMBED_GAME
     80     (void)path;
     81 
     82     tab_file.data = (char *)ta_game_tab;
     83     tab_file.size = ta_game_tab_len;
     84     embedded = true;
     85 #else
     86     tab_file = ta_read_file(path);
     87 #endif
     88 
     89     if (tab_file.data == NULL) {
     90         return false;
     91     }
     92 
     93     if (!parse((const uint8_t *)tab_file.data, tab_file.size)) {
     94         ta_tab_unload();
     95 
     96         return false;
     97     }
     98 
     99     loaded = true;
    100 
    101     return true;
    102 }
    103 
    104 void ta_tab_unload(void) {
    105     if (tab_file.data != NULL && !embedded) {
    106         ta_close_file(&tab_file);
    107     }
    108 
    109     embedded = false;
    110 
    111     tab_file.data = NULL;
    112     tab_file.size = 0;
    113 
    114     for (uint32_t i = 0; i <= TA_TAB_MAX_FILES; i++) {
    115         entries[i].offset = 0;
    116         entries[i].size = 0;
    117         entries[i].present = false;
    118     }
    119 
    120     loaded = false;
    121 }
    122 
    123 bool ta_tab_find(uint8_t file, const uint8_t **data, uint32_t *size) {
    124     if (!loaded || file == TA_TAB_END || !entries[file].present) {
    125         return false;
    126     }
    127 
    128     *data = (const uint8_t *)tab_file.data + entries[file].offset;
    129     *size = entries[file].size;
    130 
    131     return true;
    132 }