Subversion Repositories Games.Carmageddon

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include "datafile.h"
  2. #include "CORE/FW/bswap.h"
  3. #include "CORE/FW/diag.h"
  4. #include "CORE/FW/file.h"
  5. #include "CORE/FW/fwsetup.h"
  6. #include "CORE/FW/resource.h"
  7. #include "CORE/FW/scratch.h"
  8. #include "CORE/MATH/fixed.h"
  9. #include "CORE/STD/brstdlib.h"
  10. #include "harness/trace.h"
  11.  
  12. #if BR_ENDIAN_BIG
  13.  
  14. #define BR_HTON_32(b) (b)
  15. #define BR_HTON_16(b) (b)
  16. #define BR_HTON_F(b) (b)
  17. #define BR_HTON_D(b) (b)
  18.  
  19. #define BR_NTOH_32(b) (b)
  20. #define BR_NTOH_16(b) (b)
  21. #define BR_NTOH_F(b) (b)
  22. #define BR_NTOH_D(b) (b)
  23.  
  24. #else
  25.  
  26. #define BR_HTON_32(b) (3-(b))
  27. #define BR_HTON_16(b) (1-(b))
  28. #define BR_HTON_F(b) (3-(b))
  29. #define BR_HTON_D(b) (7-(b))
  30.  
  31. #define BR_NTOH_32(b) (3-(b))
  32. #define BR_NTOH_16(b) (1-(b))
  33. #define BR_NTOH_F(b) (3-(b))
  34. #define BR_NTOH_D(b) (7-(b))
  35.  
  36. #endif
  37.  
  38. br_file_primitives _BrFilePrimsNull = {
  39.     "NULL",
  40.     (int (*)(br_datafile*, br_uint_32)) & BrNullOther,
  41.     (int (*)(br_datafile*, br_uint_32, br_uint_32)) & BrNullOther,
  42.     (int (*)(br_datafile*, br_uint_32*)) & BrNullOther,
  43.     (void (*)(br_datafile*, br_uint_32)) & BrNullOther,
  44.     (br_uint_32(*)(br_datafile*)) & BrNullOther,
  45.     (int (*)(br_datafile*)) & BrNullOther,
  46.     (br_uint_32(*)(br_datafile*, br_file_struct*, void*)) & BrNullOther,
  47.     (br_uint_32(*)(br_datafile*, br_file_struct*, void*)) & BrNullOther,
  48.     (int (*)(br_datafile*, br_file_struct*, void*)) & BrNullOther,
  49.     (int (*)(br_datafile*, void*, int, int, int, int)) & BrNullOther,
  50.     (void* (*)(br_datafile*, void*, int*, int, int)) & BrNullOther,
  51.     (int (*)(br_datafile*, void*, int, int, int, int)) & BrNullOther,
  52.     (int (*)(br_datafile*, char*)) & BrNullOther,
  53.     (char* (*)(br_datafile*, char*)) & BrNullOther,
  54.     (int (*)(br_datafile*, char*)) & BrNullOther,
  55. };
  56.  
  57. br_file_primitives _BrFilePrimsReadBinary = {
  58.     "Read Binary",
  59.     &DfSkipBinary,
  60.     (int (*)(br_datafile*, br_uint_32, br_uint_32)) & BrNullOther,
  61.     &DfChunkReadBinary,
  62.     (void (*)(br_datafile*, br_uint_32)) & BrNullOther,
  63.     &DfCountReadBinary,
  64.     &DfCountSizeBinary,
  65.     (br_uint_32(*)(br_datafile*, br_file_struct*, void*)) & BrNullOther,
  66.     &DfStructReadBinary,
  67.     &DfStructSizeBinary,
  68.     (int (*)(br_datafile*, void*, int, int, int, int)) & BrNullOther,
  69.     &DfBlockReadBinary,
  70.     &DfBlockSizeBinary,
  71.     (int (*)(br_datafile*, char*)) & BrNullOther,
  72.     &DfNameReadBinary,
  73.     &DfNameSizeBinary,
  74. };
  75.  
  76. br_file_primitives _BrFilePrimsWriteBinary = {
  77.     "Write Binary",
  78.     &DfSkipBinary,
  79.     &DfChunkWriteBinary,
  80.     (int (*)(br_datafile*, br_uint_32*)) & BrNullOther,
  81.     &DfCountWriteBinary,
  82.     (br_uint_32(*)(br_datafile*)) & BrNullOther,
  83.     &DfCountSizeBinary,
  84.     &DfStructWriteBinary,
  85.     (br_uint_32(*)(br_datafile*, br_file_struct*, void*)) & BrNullOther,
  86.     &DfStructSizeBinary,
  87.     &DfBlockWriteBinary,
  88.     (void* (*)(br_datafile*, void*, int*, int, int)) & BrNullOther,
  89.     &DfBlockSizeBinary,
  90.     &DfNameWriteBinary,
  91.     (char* (*)(br_datafile*, char*)) & BrNullOther,
  92.     &DfNameSizeBinary,
  93. };
  94.  
  95. br_file_primitives _BrFilePrimsReadText = {
  96.     "Read Text",
  97.     &DfSkipText,
  98.     (int (*)(br_datafile*, br_uint_32, br_uint_32)) & BrNullOther,
  99.     &DfChunkReadText,
  100.     (void (*)(br_datafile*, br_uint_32)) & BrNullOther,
  101.     &DfCountReadText,
  102.     &DfCountSizeText,
  103.     (br_uint_32(*)(br_datafile*, br_file_struct*, void*)) & BrNullOther,
  104.     &DfStructReadText,
  105.     &DfStructSizeText,
  106.     (int (*)(br_datafile*, void*, int, int, int, int)) & BrNullOther,
  107.     &DfBlockReadText,
  108.     &DfBlockSizeText,
  109.     (int (*)(br_datafile*, char*)) & BrNullOther,
  110.     &DfNameReadText,
  111.     &DfNameSizeText,
  112. };
  113.  
  114. br_file_primitives _BrFilePrimsWriteText = {
  115.     "Write Text",
  116.     &DfSkipText,
  117.     &DfChunkWriteText,
  118.     (int (*)(br_datafile*, br_uint_32*)) & BrNullOther,
  119.     &DfCountWriteText,
  120.     (br_uint_32(*)(br_datafile*)) & BrNullOther,
  121.     &DfCountSizeText,
  122.     &DfStructWriteText,
  123.     (br_uint_32(*)(br_datafile*, br_file_struct*, void*)) & BrNullOther,
  124.     &DfStructSizeText,
  125.     &DfBlockWriteText,
  126.     (void* (*)(br_datafile*, void*, int*, int, int)) & BrNullOther,
  127.     &DfBlockSizeText,
  128.     &DfNameWriteText,
  129.     (char* (*)(br_datafile*, char*)) & BrNullOther,
  130.     &DfNameSizeText,
  131. };
  132.  
  133. char* member_type_names[32] = {
  134.     "int_8",
  135.     "uint_8",
  136.     "int_16",
  137.     "uint_16",
  138.     "int_32",
  139.     "uint_32",
  140.     "fixed",
  141.     "angle",
  142.     "float",
  143.     "double",
  144.     "scalar",
  145.     "fraction",
  146.     "ufraction",
  147.     "enum_8",
  148.     "enum_16",
  149.     "enum_32",
  150.     "struct",
  151.     "asciz",
  152.     "colour",
  153.     "vector2",
  154.     "vector3",
  155.     "vector4",
  156.     "fixed_fraction",
  157.     "fixed_ufraction",
  158.     "float_fraction",
  159.     "float_ufraction",
  160.     "fixed_vector2",
  161.     "fixed_vector3",
  162.     "fixed_vector4",
  163.     "float_vector2",
  164.     "float_vector3",
  165.     "float_vector4",
  166. };
  167.  
  168. struct {
  169.     int type;
  170.     void* value;
  171.     int count;
  172. } DatafileStack[1024];
  173.  
  174. #ifdef BRENDER_FIX_BUGS
  175. char* ChunkNames[62] = {
  176. #else
  177. char* ChunkNames[61] = {
  178. #endif
  179.     "END",
  180.     "IMAGE_PLANE",
  181.     "RLE_IMAGE_PLANE",
  182. #ifdef BRENDER_FIX_BUGS
  183.     "PIXELMAP_OLD",
  184. #else
  185.     "PIXELMAP",
  186. #endif
  187.     "MATERIAL_OLD",
  188.     "ADD_MATERIAL",
  189.     "OLD_ACTOR",
  190.     "OLD_ADD_SIBLING",
  191.     "OLD_ADD_CHILD",
  192.     "OLD_MATERIAL_INDEX",
  193.     "OLD_VERTICES",
  194.     "OLD_VERTICES_UV",
  195.     "OLD_FACES",
  196.     "OLD_MODEL",
  197.     "ADD_MODEL",
  198.     "ANIM",
  199.     "ANIM_TRANSFORM",
  200.     "ANIM_RATE",
  201.     "FILE_INFO",
  202.     "OLD_LIGHT",
  203.     "OLD_CAMERA",
  204.     "PIVOT",
  205.     "MATERIAL_INDEX",
  206.     "VERTICES",
  207.     "VERTEX_UV",
  208.     "OLD_FACES_1",
  209.     "FACE_MATERIAL",
  210.     "OLD_MODEL_1",
  211.     "COLOUR_MAP_REF",
  212.     "OPACITY_MAP_REF",
  213.     "INDEX_BLEND_REF",
  214.     "INDEX_SHADE_REF",
  215.     "SCREENDOOR_REF",
  216.     "PIXELS",
  217.     "ADD_MAP",
  218.     "ACTOR",
  219.     "ACTOR_MODEL",
  220.     "ACTOR_TRANSFORM",
  221.     "ACTOR_MATERIAL",
  222.     "ACTOR_LIGHT",
  223.     "ACTOR_CAMERA",
  224.     "ACTOR_BOUNDS",
  225.     "ACTOR_ADD_CHILD",
  226.     "TRANSFORM_MATRIX34",
  227.     "TRANSFORM_MATRIX34_LP",
  228.     "TRANSFORM_QUAT",
  229.     "TRANSFORM_EULER",
  230.     "TRANSFORM_LOOK_UP",
  231.     "TRANSFORM_TRANSLATION",
  232.     "TRANSFORM_IDENTITY",
  233.     "BOUNDS",
  234.     "LIGHT",
  235.     "CAMERA",
  236.     "FACES",
  237.     "MODEL",
  238.     "ACTOR_CLIP_PLANE",
  239.     "PLANE",
  240.     "SATURN_FACES",
  241.     "SATURN_MODEL",
  242.     "INDEX_FOG_REF",
  243. #ifdef BRENDER_FIX_BUGS
  244.     "MATERIAL",
  245.     "PIXELMAP",
  246. #else
  247.     "MATERIAL_OLD",
  248. #endif
  249. };
  250.  
  251. int DatafileStackTop;
  252.  
  253. // IDA: void __usercall DfPush(int type@<EAX>, void *value@<EDX>, int count@<EBX>)
  254. void DfPush(int type, void* value, int count) {
  255.     LOG_TRACE9("(%d, %p, %d)", type, value, count);
  256.  
  257.     if (DatafileStackTop >= BR_ASIZE(DatafileStack)) {
  258.         BrFailure("DatafileStack Overflow");
  259.     }
  260.     DatafileStack[DatafileStackTop].type = type;
  261.     DatafileStack[DatafileStackTop].count = count;
  262.     DatafileStack[DatafileStackTop].value = value;
  263.     DatafileStackTop++;
  264. }
  265.  
  266. // IDA: void* __usercall DfPop@<EAX>(int type@<EAX>, int *countp@<EDX>)
  267. void* DfPop(int type, int* countp) {
  268.     LOG_TRACE9("(%d, %p)", type, countp);
  269.  
  270.     if (DatafileStackTop <= 0) {
  271.         BrFailure("DatafileStack Underflow");
  272.     }
  273.     DatafileStackTop--;
  274.     if (type != DatafileStack[DatafileStackTop].type) {
  275.         BrFailure("DatafileStack type mismatch, wanted %d, got %d", type, DatafileStack[DatafileStackTop].type);
  276.     }
  277.     if (countp != NULL) {
  278.         *countp = DatafileStack[DatafileStackTop].count;
  279.     }
  280.     return DatafileStack[DatafileStackTop].value;
  281. }
  282.  
  283. // IDA: void* __usercall DfTop@<EAX>(int type@<EAX>, int *countp@<EDX>)
  284. void* DfTop(int type, int* countp) {
  285.     LOG_TRACE9("(%d, %p)", type, countp);
  286.     if (DatafileStackTop <= 0)
  287.         BrFailure("DatafileStack Underflow");
  288.     if (type != DatafileStack[DatafileStackTop - 1].type)
  289.         BrFailure("DatafileStack type mismatch, wanted %d, got %d", type, DatafileStack[DatafileStackTop].type);
  290.     if (countp != NULL)
  291.         *countp = DatafileStack[DatafileStackTop - 1].count;
  292.     return DatafileStack[DatafileStackTop - 1].value;
  293. }
  294.  
  295. // IDA: int __cdecl DfTopType()
  296. int DfTopType(void) {
  297.     LOG_TRACE9("()");
  298.     if (DatafileStackTop > 0) {
  299.         return DatafileStack[DatafileStackTop - 1].type;
  300.     } else {
  301.         return 0;
  302.     }
  303. }
  304.  
  305. // IDA: int __usercall TextReadLine@<EAX>(br_datafile *df@<EAX>, char **ident@<EDX>, char **data@<EBX>)
  306. int TextReadLine(br_datafile* df, char** ident, char** data) {
  307.     char* cp;
  308.     LOG_TRACE9("(%p, %p, %p)", df, ident, data);
  309.  
  310.     while (1) {
  311.         //int a; // Pierre-Marie Baty -- unused variable
  312.         cp = BrScratchString();
  313.         BrFileGetLine(cp, 256, df->h);
  314.         if (BrFileEof(df->h) != 0) {
  315.             return 0;
  316.         }
  317.         for (; (*cp == ' ') || (*cp == '\t'); cp++) {
  318.         }
  319.         if (*cp != '\0') {
  320.             break;
  321.         }
  322.     }
  323.     *ident = cp;
  324.     while ((*cp != ' ') && (*cp != '\t') && (*cp != '\0')) {
  325.         cp++;
  326.     }
  327.     *cp = '\0';
  328.     cp++;
  329.     while ((*cp == ' ') || (*cp == '\t')) {
  330.         cp++;
  331.     }
  332.     *data = cp;
  333.     if (*cp == '\"') {
  334.         cp++;
  335.         while ((*cp != '\0') && (*cp != '\"')) {
  336.             cp++;
  337.         }
  338.     } else {
  339.         while ((*cp != ' ') && (*cp != '\t') && (*cp != '\0')) {
  340.             cp++;
  341.         }
  342.     }
  343.     *cp = '\0';
  344.     return 1;
  345. }
  346.  
  347. // IDA: br_uint_16 __usercall scalarTypeConvert@<AX>(br_datafile *df@<EAX>, br_uint_16 t@<EDX>)
  348. br_uint_16 scalarTypeConvert(br_datafile* df, br_uint_16 t) {
  349.     LOG_TRACE9("(%p, %d)", df, t);
  350.  
  351.     if (df->scalar_type == BRT_FIXED) {
  352.         switch (t) {
  353.         case DF_TYPE_BR_SCALAR:
  354.             return DF_TYPE_BR_FIXED;
  355.         case DF_TYPE_BR_FRACTION:
  356.             return DF_TYPE_BR_FRACTION_X;
  357.         case DF_TYPE_BR_UFRACTION:
  358.             return DF_TYPE_BR_UFRACTION_X;
  359.         case DF_TYPE_BR_VECTOR2:
  360.             return DF_TYPE_BR_VECTOR2_X;
  361.         case DF_TYPE_BR_VECTOR3:
  362.             return DF_TYPE_BR_VECTOR3_X;
  363.         case DF_TYPE_BR_VECTOR4:
  364.             return DF_TYPE_BR_VECTOR4_X;
  365.         }
  366.     } else if (df->scalar_type == BRT_FLOAT) {
  367.         switch (t) {
  368.         case DF_TYPE_BR_SCALAR:
  369.             return DF_TYPE_FLOAT;
  370.         case DF_TYPE_BR_UFRACTION:
  371.             return DF_TYPE_BR_FRACTION_F;
  372.         case DF_TYPE_BR_FRACTION:
  373.             return DF_TYPE_BR_UFRACTION_F;
  374.         case DF_TYPE_BR_VECTOR2:
  375.             return DF_TYPE_BR_VECTOR2_F;
  376.         case DF_TYPE_BR_VECTOR3:
  377.             return DF_TYPE_BR_VECTOR3_F;
  378.         case DF_TYPE_BR_VECTOR4:
  379.             return DF_TYPE_BR_VECTOR4_F;
  380.         }
  381.     } else if ((t == DF_TYPE_BR_SCALAR) || ((DF_TYPE_BR_VECTOR2 <= t) && (t <= DF_TYPE_BR_VECTOR4))) {
  382.         BrFailure("Incorrect scalar type");
  383.     }
  384.     return t;
  385. }
  386.  
  387. // IDA: br_uint_32 __usercall DfStructWriteBinary@<EAX>(br_datafile *df@<EAX>, br_file_struct *str@<EDX>, void *base@<EBX>)
  388. br_uint_32 DfStructWriteBinary(br_datafile* df, br_file_struct* str, void* base) {
  389.     unsigned int m;
  390.     int i;
  391.     int n;
  392.     unsigned char* mp;
  393.     br_file_struct_member* sm;
  394.     union { // size: 0x8
  395.         unsigned char b[8]; // @0x0
  396.         float f; // @0x0
  397.         double d; // @0x0
  398.     } conv;
  399.     LOG_TRACE("(%p, %p, %p)", df, str, base);
  400.  
  401.     for (m = 0; m < str->nmembers; m++) {
  402.         sm = &str->members[m];
  403.         mp = ((unsigned char*)base) + sm->offset;
  404.  
  405.         switch (scalarTypeConvert(df, sm->type)) {
  406.         case DF_TYPE_BR_INT_8:
  407.         case DF_TYPE_BR_UINT_8:
  408.         case DF_TYPE_ENUM_8:
  409.             BrFilePutChar(((br_uint_8*)mp)[0], df->h);
  410.             break;
  411.         case DF_TYPE_BR_ANGLE:
  412.         case DF_TYPE_BR_INT_16:
  413.         case DF_TYPE_BR_UINT_16:
  414.         case DF_TYPE_ENUM_16:
  415.             BrFilePutChar(mp[BR_HTON_16(0)], df->h);
  416.             BrFilePutChar(mp[BR_HTON_16(1)], df->h);
  417.             break;
  418.         case DF_TYPE_BR_INT_32:
  419.         case DF_TYPE_BR_UINT_32:
  420.         case DF_TYPE_ENUM_32:
  421.             BrFilePutChar(mp[BR_HTON_32(0)], df->h);
  422.             BrFilePutChar(mp[BR_HTON_32(1)], df->h);
  423.             BrFilePutChar(mp[BR_HTON_32(2)], df->h);
  424.             BrFilePutChar(mp[BR_HTON_32(3)], df->h);
  425.             break;
  426.         case DF_TYPE_FLOAT:
  427.         case DF_TYPE_BR_FRACTION_F:
  428.         case DF_TYPE_BR_UFRACTION_F:
  429.             conv.f = *(float*)mp;
  430.             BrFilePutChar(conv.b[BR_HTON_32(0)], df->h);
  431.             BrFilePutChar(conv.b[BR_HTON_32(1)], df->h);
  432.             BrFilePutChar(conv.b[BR_HTON_32(2)], df->h);
  433.             BrFilePutChar(conv.b[BR_HTON_32(3)], df->h);
  434.             break;
  435.         case DF_TYPE_DOUBLE:
  436.             conv.d = *(double*)mp;
  437.             BrFilePutChar(conv.b[BR_HTON_D(0)], df->h);
  438.             BrFilePutChar(conv.b[BR_HTON_D(1)], df->h);
  439.             BrFilePutChar(conv.b[BR_HTON_D(2)], df->h);
  440.             BrFilePutChar(conv.b[BR_HTON_D(3)], df->h);
  441.             BrFilePutChar(conv.b[BR_HTON_D(4)], df->h);
  442.             BrFilePutChar(conv.b[BR_HTON_D(5)], df->h);
  443.             BrFilePutChar(conv.b[BR_HTON_D(6)], df->h);
  444.             BrFilePutChar(conv.b[BR_HTON_D(7)], df->h);
  445.             break;
  446.         case DF_TYPE_STRUCT:
  447.             DfStructWriteBinary(df, sm->extra, mp);
  448.             break;
  449.         case DF_TYPE_ASCIZ:
  450.             if (*(char**)mp != NULL) {
  451.                 BrFileWrite(*(char**)mp, 1, BrStrLen(*(char**)mp), df->h);
  452.             }
  453.             BrFilePutChar('\0', df->h);
  454.             break;
  455.         case DF_TYPE_BR_COLOUR:
  456.             BrFilePutChar(mp[BR_HTON_32(1)], df->h);
  457.             BrFilePutChar(mp[BR_HTON_32(2)], df->h);
  458.             BrFilePutChar(mp[BR_HTON_32(3)], df->h);
  459.             break;
  460.         case DF_TYPE_BR_FIXED:
  461.             conv.f = BrFixedToFloat(*(br_fixed_ls*)mp);
  462.             BrFilePutChar(conv.b[BR_HTON_32(0)], df->h);
  463.             BrFilePutChar(conv.b[BR_HTON_32(1)], df->h);
  464.             BrFilePutChar(conv.b[BR_HTON_32(2)], df->h);
  465.             BrFilePutChar(conv.b[BR_HTON_32(3)], df->h);
  466.             break;
  467.         case DF_TYPE_BR_FRACTION_X:
  468.             conv.f = BrFixedFractionToFloat(*(br_fraction_x*)mp);
  469.             BrFilePutChar(conv.b[BR_HTON_32(0)], df->h);
  470.             BrFilePutChar(conv.b[BR_HTON_32(1)], df->h);
  471.             BrFilePutChar(conv.b[BR_HTON_32(2)], df->h);
  472.             BrFilePutChar(conv.b[BR_HTON_32(3)], df->h);
  473.             break;
  474.         case DF_TYPE_BR_UFRACTION_X:
  475.             conv.f = BrFixedUFractionToFloat(*(br_fraction_x*)mp);
  476.             BrFilePutChar(conv.b[BR_HTON_32(0)], df->h);
  477.             BrFilePutChar(conv.b[BR_HTON_32(1)], df->h);
  478.             BrFilePutChar(conv.b[BR_HTON_32(2)], df->h);
  479.             BrFilePutChar(conv.b[BR_HTON_32(3)], df->h);
  480.             break;
  481.         case DF_TYPE_BR_VECTOR2_X:
  482.             n = 2;
  483.             goto copy_fixed_vector;
  484.         case DF_TYPE_BR_VECTOR3_X:
  485.             n = 3;
  486.             goto copy_fixed_vector;
  487.         case DF_TYPE_BR_VECTOR4_X:
  488.             n = 4;
  489.         copy_fixed_vector:
  490.             for (i = 0; i < n; i++) {
  491.                 conv.f = BrFixedToFloat(*(br_fixed_ls*)mp);
  492.                 BrFilePutChar(conv.b[BR_HTON_32(0)], df->h);
  493.                 BrFilePutChar(conv.b[BR_HTON_32(1)], df->h);
  494.                 BrFilePutChar(conv.b[BR_HTON_32(2)], df->h);
  495.                 BrFilePutChar(conv.b[BR_HTON_32(3)], df->h);
  496.                 mp += sizeof(br_fixed_ls);
  497.             }
  498.             break;
  499.         case DF_TYPE_BR_VECTOR2_F:
  500.             n = 2;
  501.             goto copy_float_vector;
  502.         case DF_TYPE_BR_VECTOR3_F:
  503.             n = 3;
  504.             goto copy_float_vector;
  505.         case DF_TYPE_BR_VECTOR4_F:
  506.             n = 4;
  507.         copy_float_vector:
  508.             for (i = 0; i < n; i++) {
  509.                 conv.f = *(float*)mp;
  510.                 BrFilePutChar(conv.b[BR_HTON_32(0)], df->h);
  511.                 BrFilePutChar(conv.b[BR_HTON_32(1)], df->h);
  512.                 BrFilePutChar(conv.b[BR_HTON_32(2)], df->h);
  513.                 BrFilePutChar(conv.b[BR_HTON_32(3)], df->h);
  514.                 mp += sizeof(br_fixed_ls);
  515.             }
  516.             break;
  517.         }
  518.     }
  519.     return 1;
  520. }
  521.  
  522. // IDA: br_uint_32 __usercall DfStructReadBinary@<EAX>(br_datafile *df@<EAX>, br_file_struct *str@<EDX>, void *base@<EBX>)
  523. br_uint_32 DfStructReadBinary(br_datafile* df, br_file_struct* str, void* base) {
  524.     char tmp_string[256];
  525.     unsigned int m;
  526.     int i;
  527.     int c;
  528.     int n;
  529.     unsigned char* mp;
  530.     br_file_struct_member* sm;
  531.     union {
  532.         unsigned char b[8];
  533.         float f;
  534.         double d;
  535.     } conv;
  536.  
  537.     LOG_TRACE9("(%p, %p, %p)", df, str, base);
  538.  
  539.     for (m = 0; m < str->nmembers; m++) {
  540.         sm = &str->members[m];
  541.  
  542.         c = scalarTypeConvert(df, sm->type);
  543.         mp = ((unsigned char*)base) + sm->offset;
  544.  
  545.         switch (c) {
  546.         case DF_TYPE_BR_INT_8:
  547.         case DF_TYPE_BR_UINT_8:
  548.         case DF_TYPE_ENUM_8:
  549.             mp[0] = BrFileGetChar(df->h);
  550.             break;
  551.         case DF_TYPE_BR_INT_16:
  552.         case DF_TYPE_BR_UINT_16:
  553.         case DF_TYPE_BR_ANGLE:
  554.         case DF_TYPE_ENUM_16:
  555.             mp[BR_NTOH_16(0)] = BrFileGetChar(df->h);
  556.             mp[BR_NTOH_16(1)] = BrFileGetChar(df->h);
  557.             break;
  558.         case DF_TYPE_BR_INT_32:
  559.         case DF_TYPE_BR_UINT_32:
  560.         case DF_TYPE_FLOAT:
  561.         case DF_TYPE_ENUM_32:
  562.         case DF_TYPE_BR_FRACTION_F:
  563.         case DF_TYPE_BR_UFRACTION_F:
  564.             mp[BR_NTOH_32(0)] = BrFileGetChar(df->h);
  565.             mp[BR_NTOH_32(1)] = BrFileGetChar(df->h);
  566.             mp[BR_NTOH_32(2)] = BrFileGetChar(df->h);
  567.             mp[BR_NTOH_32(3)] = BrFileGetChar(df->h);
  568.             break;
  569.         case DF_TYPE_BR_FIXED:
  570.             conv.b[BR_NTOH_F(0)] = BrFileGetChar(df->h);
  571.             conv.b[BR_NTOH_F(1)] = BrFileGetChar(df->h);
  572.             conv.b[BR_NTOH_F(2)] = BrFileGetChar(df->h);
  573.             conv.b[BR_NTOH_F(3)] = BrFileGetChar(df->h);
  574.             *(br_fixed_ls*)mp = BrFloatToFixed(conv.f);
  575.             break;
  576.         case DF_TYPE_DOUBLE:
  577.             conv.b[BR_NTOH_D(0)] = BrFileGetChar(df->h);
  578.             conv.b[BR_NTOH_D(1)] = BrFileGetChar(df->h);
  579.             conv.b[BR_NTOH_D(2)] = BrFileGetChar(df->h);
  580.             conv.b[BR_NTOH_D(3)] = BrFileGetChar(df->h);
  581.             conv.b[BR_NTOH_D(4)] = BrFileGetChar(df->h);
  582.             conv.b[BR_NTOH_D(5)] = BrFileGetChar(df->h);
  583.             conv.b[BR_NTOH_D(6)] = BrFileGetChar(df->h);
  584.             conv.b[BR_NTOH_D(7)] = BrFileGetChar(df->h);
  585.             *(double*)mp = conv.d;
  586.             break;
  587.         case DF_TYPE_STRUCT:
  588.             DfStructReadBinary(df, sm->extra, mp);
  589.             break;
  590.         case DF_TYPE_ASCIZ:
  591.             for (n = 0; n < 255; n++) {
  592.                 c = BrFileGetChar(df->h);
  593.                 if (c == '\0' || c == -1)
  594.                     break;
  595.                 tmp_string[n] = c;
  596.             }
  597.             tmp_string[n] = 0;
  598.             *(char**)mp = (char*)BrResStrDup(df->res ? df->res : fw.res, tmp_string);
  599.             break;
  600.         case DF_TYPE_BR_COLOUR:
  601.             mp[BR_NTOH_32(1)] = BrFileGetChar(df->h);
  602.             mp[BR_NTOH_32(2)] = BrFileGetChar(df->h);
  603.             mp[BR_NTOH_32(3)] = BrFileGetChar(df->h);
  604.             break;
  605.         case DF_TYPE_BR_FRACTION_X:
  606.             conv.b[BR_NTOH_F(0)] = BrFileGetChar(df->h);
  607.             conv.b[BR_NTOH_F(1)] = BrFileGetChar(df->h);
  608.             conv.b[BR_NTOH_F(2)] = BrFileGetChar(df->h);
  609.             conv.b[BR_NTOH_F(3)] = BrFileGetChar(df->h);
  610.             *((br_fraction_x*)mp) = BrFloatToFixedFraction(conv.f);
  611.             break;
  612.         case DF_TYPE_BR_UFRACTION_X:
  613.             conv.b[BR_NTOH_F(0)] = BrFileGetChar(df->h);
  614.             conv.b[BR_NTOH_F(1)] = BrFileGetChar(df->h);
  615.             conv.b[BR_NTOH_F(2)] = BrFileGetChar(df->h);
  616.             conv.b[BR_NTOH_F(3)] = BrFileGetChar(df->h);
  617.             *(br_ufraction_x*)mp = BrFloatToFixedUFraction(conv.f);
  618.             break;
  619.         case DF_TYPE_BR_VECTOR2_X:
  620.             n = 2;
  621.             goto copy_fixed_vector;
  622.         case DF_TYPE_BR_VECTOR3_X:
  623.             n = 3;
  624.             goto copy_fixed_vector;
  625.         case DF_TYPE_BR_VECTOR4_X:
  626.             n = 4;
  627.         copy_fixed_vector:
  628.             for (i = 0; i < n; i++) {
  629.                 conv.b[BR_NTOH_F(0)] = BrFileGetChar(df->h);
  630.                 conv.b[BR_NTOH_F(1)] = BrFileGetChar(df->h);
  631.                 conv.b[BR_NTOH_F(2)] = BrFileGetChar(df->h);
  632.                 conv.b[BR_NTOH_F(3)] = BrFileGetChar(df->h);
  633.                 *(br_fixed_ls*)mp = BrFloatToFixed(conv.f);
  634.                 mp += sizeof(br_fixed_ls);
  635.             }
  636.             break;
  637.         case DF_TYPE_BR_VECTOR2_F:
  638.             n = 2;
  639.             goto copy_float_vector;
  640.             break;
  641.         case DF_TYPE_BR_VECTOR3_F:
  642.             n = 3;
  643.             goto copy_float_vector;
  644.             break;
  645.         case DF_TYPE_BR_VECTOR4_F:
  646.             n = 4;
  647.         copy_float_vector:
  648.             for (i = 0; i < n; i++) {
  649.                 conv.b[BR_NTOH_F(0)] = BrFileGetChar(df->h);
  650.                 conv.b[BR_NTOH_F(1)] = BrFileGetChar(df->h);
  651.                 conv.b[BR_NTOH_F(2)] = BrFileGetChar(df->h);
  652.                 conv.b[BR_NTOH_F(3)] = BrFileGetChar(df->h);
  653.                 *(float*)mp = conv.f;
  654.                 mp += sizeof(float);
  655.             }
  656.             break;
  657.         }
  658.     }
  659.  
  660.     return 1;
  661. }
  662.  
  663. // IDA: int __usercall DfStructSizeBinary@<EAX>(br_datafile *df@<EAX>, br_file_struct *str@<EDX>, void *base@<EBX>)
  664. int DfStructSizeBinary(br_datafile* df, br_file_struct* str, void* base) {
  665.     unsigned char* mp;
  666.     unsigned int m;
  667.     br_file_struct_member* sm;
  668.     int bytes;
  669.     LOG_TRACE("(%p, %p, %p)", df, str, base);
  670.  
  671.     bytes = 0;
  672.     for (m = 0; m < str->nmembers; m++) {
  673.         sm = &str->members[m];
  674.  
  675.         mp = ((unsigned char*)base) + sm->offset;
  676.  
  677.         switch (scalarTypeConvert(df, sm->type)) {
  678.         case DF_TYPE_BR_INT_8:
  679.         case DF_TYPE_BR_UINT_8:
  680.         case DF_TYPE_ENUM_8:
  681.             bytes += 1;
  682.             break;
  683.         case DF_TYPE_BR_INT_16:
  684.         case DF_TYPE_BR_UINT_16:
  685.         case DF_TYPE_BR_ANGLE:
  686.         case DF_TYPE_ENUM_16:
  687.             bytes += 2;
  688.             break;
  689.         case DF_TYPE_BR_COLOUR:
  690.             bytes += 4;
  691.             break;
  692.         case DF_TYPE_BR_INT_32:
  693.         case DF_TYPE_BR_UINT_32:
  694.         case DF_TYPE_FLOAT:
  695.         case DF_TYPE_ENUM_32:
  696.         case DF_TYPE_BR_FRACTION_F:
  697.         case DF_TYPE_BR_UFRACTION_F:
  698.         case DF_TYPE_BR_FIXED:
  699.         case DF_TYPE_BR_FRACTION_X:
  700.         case DF_TYPE_BR_UFRACTION_X:
  701.             bytes += 4;
  702.             break;
  703.         case DF_TYPE_DOUBLE:
  704.             bytes += 8;
  705.             break;
  706.         case DF_TYPE_STRUCT:
  707.             bytes += DfStructSizeBinary(df, sm->extra, mp);
  708.             break;
  709.         case DF_TYPE_ASCIZ:
  710.             if (*(char**)mp != NULL) {
  711.                 bytes += BrStrLen(*(char**)mp);
  712.             }
  713.             break;
  714.         case DF_TYPE_BR_VECTOR2_X:
  715.         case DF_TYPE_BR_VECTOR2_F:
  716.             bytes += 8;
  717.             break;
  718.         case DF_TYPE_BR_VECTOR3_X:
  719.         case DF_TYPE_BR_VECTOR3_F:
  720.             bytes += 12;
  721.             break;
  722.         case DF_TYPE_BR_VECTOR4_X:
  723.         case DF_TYPE_BR_VECTOR4_F:
  724.             bytes += 16;
  725.             break;
  726.         }
  727.     }
  728.  
  729.     return bytes;
  730. }
  731.  
  732. // IDA: int __usercall EnumFromString@<EAX>(br_file_enum *e@<EAX>, char *str@<EDX>)
  733. int EnumFromString(br_file_enum* e, char* str) {
  734.     unsigned int m;
  735.     LOG_TRACE9("(%p, \"%s\")", e, str);
  736.  
  737.     if (e == NULL) {
  738.         BrFailure("Unknown enum string: %s", str);
  739.     }
  740.     for (m = 0; m < e->nmembers; m++) {
  741.         if (BrStrCmp(str, e->members[m].name) == 0) {
  742.             return e->members[m].value;
  743.         }
  744.     }
  745.     BrFailure("Unknown enum string: %s", str);
  746.     return 0; // Pierre-Marie Baty -- make compiler happy
  747. }
  748.  
  749. // IDA: char* __usercall EnumToString@<EAX>(br_file_enum *e@<EAX>, int num@<EDX>)
  750. char* EnumToString(br_file_enum* e, int num) {
  751.     unsigned int m;
  752.     LOG_TRACE9("(%p, %d)", e, num);
  753.  
  754.     if (e == NULL) {
  755.         goto fail;
  756.     }
  757.     for (m = 0; m < e->nmembers; m++) {
  758.         if (e->members[m].value == num) {
  759.             return e->members[m].name;
  760.         }
  761.     }
  762. fail:
  763.     BrFailure("Unknown enum %d", num);
  764.     return NULL; // Pierre-Marie Baty -- make compiler happy
  765. }
  766.  
  767. // IDA: br_uint_32 __usercall DfStructWriteText@<EAX>(br_datafile *df@<EAX>, br_file_struct *str@<EDX>, void *base@<EBX>)
  768. br_uint_32 DfStructWriteText(br_datafile* df, br_file_struct* str, void* base) {
  769.     LOG_TRACE("(%p, %p, %p)", df, str, base);
  770.  
  771.     BrFilePrintf(df->h, "  struct    %s\n", str->name);
  772.     StructWriteTextSub(df, str, base, 4);
  773.     return 1;
  774. }
  775.  
  776. // IDA: br_uint_32 __usercall StructWriteTextSub@<EAX>(br_datafile *df@<EAX>, br_file_struct *str@<EDX>, void *base@<EBX>, int indent@<ECX>)
  777. br_uint_32 StructWriteTextSub(br_datafile* df, br_file_struct* str, void* base, int indent) {
  778.     unsigned int m;
  779.     int i;
  780.     int w;
  781.     int add_comment;
  782.     void* mp;
  783.     br_file_struct_member* sm;
  784.     LOG_TRACE("(%p, %p, %p, %d)", df, str, base, indent);
  785.  
  786.     for (m = 0; m < str->nmembers; m++) {
  787.         sm = &str->members[m];
  788.         mp = ((unsigned char*)base) + sm->offset;
  789.         w = 0;
  790.         add_comment = 1;
  791.  
  792.         for (i = 0; i < indent; i++) {
  793.             BrFilePutChar(' ', df->h);
  794.         }
  795.  
  796.         // Modified from "%-10s", to ensure space after long type names
  797.         BrFilePrintf(df->h, "%-9s ", member_type_names[sm->type]);
  798.  
  799.         switch (scalarTypeConvert(df, sm->type)) {
  800.         case DF_TYPE_BR_INT_8:
  801.             w = BrFilePrintf(df->h, "%d", *(br_int_8*)mp);
  802.             break;
  803.         case DF_TYPE_BR_UINT_8:
  804.             w = BrFilePrintf(df->h, "%u", *(br_uint_8*)mp);
  805.             break;
  806.         case DF_TYPE_BR_INT_16:
  807.             w = BrFilePrintf(df->h, "%d", *(br_int_16*)mp);
  808.             break;
  809.         case DF_TYPE_BR_UINT_16:
  810.             w = BrFilePrintf(df->h, "%u", *(br_uint_16*)mp);
  811.             break;
  812.         case DF_TYPE_BR_INT_32:
  813.             w = BrFilePrintf(df->h, "%d", *(br_int_32*)mp);
  814.             break;
  815.         case DF_TYPE_BR_UINT_32:
  816.             w = BrFilePrintf(df->h, "%u", *(br_uint_32*)mp);
  817.             break;
  818.         case DF_TYPE_BR_FIXED:
  819.             w = BrFilePrintf(df->h, "%g", BrFixedToFloat(*(br_fixed_ls*)mp));
  820.             break;
  821.         case DF_TYPE_BR_ANGLE:
  822.             w = BrFilePrintf(df->h, "%g", BrFixedToFloat(BrFixedMul(*(br_angle*)mp, BrIntToFixed(360))));
  823.             break;
  824.         case DF_TYPE_FLOAT:
  825.         case DF_TYPE_BR_FRACTION_F:
  826.         case DF_TYPE_BR_UFRACTION_F:
  827.             w = BrFilePrintf(df->h, "%g", (double)*(float*)mp);
  828.             break;
  829.         case DF_TYPE_DOUBLE:
  830.             w = BrFilePrintf(df->h, "%g", *(double*)mp);
  831.             break;
  832.         case DF_TYPE_ENUM_8:
  833.             w = BrFilePrintf(df->h, "%s", EnumToString(sm->extra, *(br_uint_8*)mp));
  834.             break;
  835.         case DF_TYPE_ENUM_16:
  836.             w = BrFilePrintf(df->h, "%s", EnumToString(sm->extra, *(br_uint_16*)mp));
  837.             break;
  838.         case DF_TYPE_ENUM_32:
  839.             w = BrFilePrintf(df->h, "%s", EnumToString(sm->extra, *(br_uint_32*)mp));
  840.             break;
  841.         case DF_TYPE_STRUCT:
  842.             add_comment = 0;
  843.             w = BrFilePrintf(df->h, "%s", ((br_file_struct*)sm->extra)->name);
  844.             if (sm->name != NULL) {
  845.                 if (w < 40) {
  846.                     for (i = 40 - w; i != 0; i--) {
  847.                         BrFilePutChar(' ', df->h);
  848.                     }
  849.                 }
  850.                 BrFilePrintf(df->h, " # %s", sm->name);
  851.             }
  852.             BrFilePutChar('\n', df->h);
  853.             StructWriteTextSub(df, sm->extra, mp, indent + 2);
  854.             break;
  855.         case DF_TYPE_ASCIZ:
  856.             if (*(char**)mp == NULL) {
  857.                 w = BrFilePrintf(df->h, "NULL");
  858.             } else {
  859.                 w = BrFilePrintf(df->h, "\"%s\"", *(char**)mp);
  860.             }
  861.             break;
  862.         case DF_TYPE_BR_COLOUR:
  863.             w = BrFilePrintf(df->h, "%d,%d,%d", (br_uint_8)((*(br_uint_32*)mp) >> 16), (br_uint_8)((*(br_uint_32*)mp) >> 8), (br_uint_8)((*(br_uint_32*)mp)));
  864.             break;
  865.         case DF_TYPE_BR_FRACTION_X:
  866.             w = BrFilePrintf(df->h, "%g", (double)BrFixedFractionToFloat(*(br_fraction_x*)mp));
  867.             break;
  868.         case DF_TYPE_BR_UFRACTION_X:
  869.             w = BrFilePrintf(df->h, "%g", (double)BrFixedUFractionToFloat(*(br_fraction_x*)mp));
  870.             break;
  871.         case DF_TYPE_BR_VECTOR2_X:
  872.             w = BrFilePrintf(df->h, "%g,%g", BrFixedToFloat(((br_fixed_ls*)mp)[0]), BrFixedToFloat(((br_fixed_ls*)mp)[1]));
  873.             break;
  874.         case DF_TYPE_BR_VECTOR3_X:
  875.             w = BrFilePrintf(df->h, "%g,%g,%g", BrFixedToFloat(((br_fixed_ls*)mp)[0]), BrFixedToFloat(((br_fixed_ls*)mp)[1]), BrFixedToFloat(((br_fixed_ls*)mp)[2]));
  876.             break;
  877.         case DF_TYPE_BR_VECTOR4_X:
  878.             w = BrFilePrintf(df->h, "%g,%g,%g,%g", BrFixedToFloat(((br_fixed_ls*)mp)[0]), BrFixedToFloat(((br_fixed_ls*)mp)[1]), BrFixedToFloat(((br_fixed_ls*)mp)[2]), BrFixedToFloat(((br_fixed_ls*)mp)[3]));
  879.             break;
  880.         case DF_TYPE_BR_VECTOR2_F:
  881.             w = BrFilePrintf(df->h, "%g,%g", ((float*)mp)[0], ((float*)mp)[1]);
  882.             break;
  883.         case DF_TYPE_BR_VECTOR3_F:
  884.             w = BrFilePrintf(df->h, "%g,%g,%g", ((float*)mp)[0], ((float*)mp)[1], ((float*)mp)[2]);
  885.             break;
  886.         case DF_TYPE_BR_VECTOR4_F:
  887.             w = BrFilePrintf(df->h, "%g,%g,%g,%g", ((float*)mp)[0], ((float*)mp)[1], ((float*)mp)[2], ((float*)mp)[3]);
  888.             break;
  889.         }
  890.         if ((add_comment != 0) && (sm->name != NULL)) {
  891.             if (w < 40) {
  892.                 for (i = 40 - w; i != 0; i--) {
  893.                     BrFilePutChar(' ', df->h);
  894.                 }
  895.             }
  896.             BrFilePrintf(df->h, " # %s\n", sm->name);
  897.         }
  898.     }
  899.  
  900.     return 1;
  901. }
  902.  
  903. // IDA: br_uint_32 __usercall DfStructReadText@<EAX>(br_datafile *df@<EAX>, br_file_struct *str@<EDX>, void *base@<EBX>)
  904. br_uint_32 DfStructReadText(br_datafile* df, br_file_struct* str, void* base) {
  905.     char* id;
  906.     char* data;
  907.     LOG_TRACE9("(%p, %p, %p)", df, str, base);
  908.  
  909.     TextReadLine(df, &id, &data);
  910.     if (BrStrCmp(id, "struct") != 0) {
  911.         BrFailure("Unknown text identifer \"%s\"", id);
  912.     }
  913.     if (BrStrCmp(data, str->name) != 0) {
  914.         BrFailure("Incorrect structure name \"%s\"", data);
  915.     }
  916.     StructReadTextSub(df, str, base);
  917.     return 1;
  918. }
  919.  
  920. // IDA: br_uint_32 __usercall StructReadTextSub@<EAX>(br_datafile *df@<EAX>, br_file_struct *str@<EDX>, void *base@<EBX>)
  921. br_uint_32 StructReadTextSub(br_datafile* df, br_file_struct* str, void* base) {
  922.     unsigned int m;
  923.     unsigned int r;
  924.     unsigned int g;
  925.     unsigned int b;
  926.     int i;
  927.     int n;
  928.     void* mp;
  929.     br_file_struct_member* sm;
  930.     char* id;
  931.     char* data;
  932.     char* ep;
  933.     LOG_TRACE9("(%p, %p, %p)", df, str, base);
  934.  
  935.     for (m = 0; m < str->nmembers; m++) {
  936.         sm = &str->members[m];
  937.         mp = ((unsigned char*)base) + sm->offset;
  938.  
  939.         if (TextReadLine(df, &id, &data) == 0) {
  940.             BrFailure("Unexpected EOF in strructure");
  941.         }
  942.         if (BrStrCmp(id, member_type_names[sm->type]) != 0) {
  943.             BrFailure("Unknown member identifer \"%s\"", id);
  944.         }
  945.  
  946.         switch (scalarTypeConvert(df, sm->type)) {
  947.         case DF_TYPE_BR_INT_8:
  948.             *(br_int_8*)mp = (br_int_8)BrStrToL(data, NULL, 0);
  949.             break;
  950.         case DF_TYPE_BR_UINT_8:
  951.             *(br_uint_8*)mp = (br_uint_8)BrStrToL(data, NULL, 0);
  952.             break;
  953.         case DF_TYPE_BR_INT_16:
  954.             *(br_int_16*)mp = (br_int_16)BrStrToL(data, NULL, 0);
  955.             break;
  956.         case DF_TYPE_BR_UINT_16:
  957.             *(br_uint_16*)mp = (br_uint_16)BrStrToL(data, NULL, 0);
  958.             break;
  959.         case DF_TYPE_BR_INT_32:
  960.             *(br_int_32*)mp = (br_int_32)BrStrToL(data, NULL, 0);
  961.             break;
  962.         case DF_TYPE_BR_UINT_32:
  963.             *(br_uint_32*)mp = (br_uint_32)BrStrToUL(data, NULL, 0);
  964.             break;
  965.         case DF_TYPE_BR_FIXED:
  966.             *(br_fixed_ls*)mp = BrFloatToFixed(BrStrToD(data, NULL));
  967.             break;
  968.         case DF_TYPE_BR_ANGLE:
  969.             *(br_angle*)mp = BrFixedMulDiv(BrFloatToFixed(BrStrToF(data, NULL)), BrIntToFixed(1), BrIntToFixed(360));
  970.             break;
  971.         case DF_TYPE_FLOAT:
  972.         case DF_TYPE_BR_FRACTION_F:
  973.         case DF_TYPE_BR_UFRACTION_F:
  974.             *(float*)mp = BrStrToF(data, NULL);
  975.             break;
  976.         case DF_TYPE_DOUBLE:
  977.             *(double*)mp = BrStrToD(data, NULL);
  978.             break;
  979.         case DF_TYPE_ENUM_8:
  980.             *(br_uint_8*)mp = EnumFromString(sm->extra, data);
  981.             break;
  982.         case DF_TYPE_ENUM_16:
  983.             *(br_uint_16*)mp = EnumFromString(sm->extra, data);
  984.             break;
  985.         case DF_TYPE_ENUM_32:
  986.             *(br_uint_32*)mp = EnumFromString(sm->extra, data);
  987.             break;
  988.         case DF_TYPE_STRUCT:
  989.             if (BrStrCmp(data, ((br_file_struct*)sm->extra)->name) != 0) {
  990.                 BrFailure("Incorrect structure name \"%s\"", data);
  991.             }
  992.             StructReadTextSub(df, sm->extra, mp);
  993.             break;
  994.         case DF_TYPE_ASCIZ:
  995.             if (BrStrCmp(data, "NULL") == 0) {
  996.                 *(char**)mp = NULL;
  997.             } else {
  998.                 *(char**)mp = BrResStrDup(df->res == NULL ? fw.res : df->res, data + 1);
  999.             }
  1000.             break;
  1001.         case DF_TYPE_BR_COLOUR:
  1002.             r = BrStrToUL(data, &ep, 0);
  1003.             if (*ep != ',') {
  1004.                 BrFailure("Incorrect colour");
  1005.             }
  1006.             g = BrStrToUL(ep + 1, &ep, 0);
  1007.             if (*ep != ',') {
  1008.                 BrFailure("Incorrect colour");
  1009.             }
  1010.             b = BrStrToUL(ep + 1, &ep, 0);
  1011.             *(br_colour*)mp = BR_COLOUR_RGB(r, g, b);
  1012.             break;
  1013.         case DF_TYPE_BR_FRACTION_X:
  1014.             *(br_fixed_ss*)mp = BrFloatToFixedFraction(BrStrToD(data, NULL));
  1015.             break;
  1016.         case DF_TYPE_BR_UFRACTION_X:
  1017.             *(br_fixed_su*)mp = BrFloatToFixedUFraction(BrStrToD(data, NULL));
  1018.             break;
  1019.         case DF_TYPE_BR_VECTOR2_X:
  1020.             n = 2;
  1021.             goto copy_fixed_vector;
  1022.         case DF_TYPE_BR_VECTOR3_X:
  1023.             n = 3;
  1024.             goto copy_fixed_vector;
  1025.         case DF_TYPE_BR_VECTOR4_X:
  1026.             n = 4;
  1027.         copy_fixed_vector:
  1028.             for (i = 0; i < n; i++) {
  1029.                 while (1) {
  1030.                     if ((*data != ',') && (*data != ' ') && (*data != '\t')) {
  1031.                         break;
  1032.                     }
  1033.                     data++;
  1034.                 }
  1035.                 if (*data == '\0') {
  1036.                     BrFailure("Incorrect vector");
  1037.                 }
  1038.                 *(br_fixed_ls*)mp = BrFloatToFixed(BrStrToF(data, NULL));
  1039.                 while ((*data != ' ' && *data != ',' && *data != ' ' && *data != '\t')) {
  1040.                     data++;
  1041.                 }
  1042.                 mp = (char*)mp + sizeof(br_fixed_ls);
  1043.             }
  1044.             break;
  1045.         case DF_TYPE_BR_VECTOR2_F:
  1046.             n = 2;
  1047.             goto copy_float_vector;
  1048.         case DF_TYPE_BR_VECTOR3_F:
  1049.             n = 3;
  1050.             goto copy_float_vector;
  1051.         case DF_TYPE_BR_VECTOR4_F:
  1052.             n = 4;
  1053.         copy_float_vector:
  1054.             for (i = 0; i < n; i++) {
  1055.                 while (1) {
  1056.                     if ((*data != ',') && (*data != ' ') && (*data != '\t')) {
  1057.                         break;
  1058.                     }
  1059.                     data++;
  1060.                 }
  1061.                 if (*data == '\0') {
  1062.                     BrFailure("Incorrect vector");
  1063.                 }
  1064.                 *(float*)mp = BrStrToF(data, NULL);
  1065.                 while ((*data != ' ' && *data != ',' && *data != ' ' && *data != '\t')) {
  1066.                     data++;
  1067.                 }
  1068.                 mp = (char*)mp + sizeof(float);
  1069.             }
  1070.             break;
  1071.         }
  1072.     }
  1073.  
  1074.     return 1;
  1075. }
  1076.  
  1077. // IDA: int __usercall DfStructSizeText@<EAX>(br_datafile *df@<EAX>, br_file_struct *str@<EDX>, void *base@<EBX>)
  1078. int DfStructSizeText(br_datafile* df, br_file_struct* str, void* base) {
  1079.     unsigned int m;
  1080.     br_file_struct_member* sm;
  1081.     int lines;
  1082.     LOG_TRACE("(%p, %p, %p)", df, str, base);
  1083.  
  1084.     lines = 1;
  1085.     for (m = 0; m < str->nmembers; m++) {
  1086.         sm = &str->members[m];
  1087.         if (sm->type == DF_TYPE_STRUCT) {
  1088.             lines += DfStructSizeText(df, sm->extra, (br_uint_8*)base + sm->offset);
  1089.         } else {
  1090.             lines++;
  1091.         }
  1092.     }
  1093.     return lines;
  1094. }
  1095.  
  1096. // IDA: br_uint_32 __usercall DfStructWriteArray@<EAX>(br_datafile *df@<EAX>, br_file_struct *str@<EDX>, void *base@<EBX>, int n@<ECX>)
  1097. br_uint_32 DfStructWriteArray(br_datafile* df, br_file_struct* str, void* base, int n) {
  1098.     char* cp;
  1099.     int i;
  1100.     LOG_TRACE("(%p, %p, %p, %d)", df, str, base, n);
  1101.  
  1102.     cp = (char*)base;
  1103.     for (i = 0; i < n; i++) {
  1104.         df->prims->struct_write(df, str, cp);
  1105.         cp += str->mem_size;
  1106.     }
  1107.     return i;
  1108. }
  1109.  
  1110. // IDA: br_uint_32 __usercall DfStructReadArray@<EAX>(br_datafile *df@<EAX>, br_file_struct *str@<EDX>, void *base@<EBX>, int n@<ECX>)
  1111. br_uint_32 DfStructReadArray(br_datafile* df, br_file_struct* str, void* base, int n) {
  1112.     char* cp;
  1113.     int i;
  1114.     LOG_TRACE9("(%p, %p, %p, %d)", df, str, base, n);
  1115.  
  1116.     cp = (char*)base;
  1117.     for (i = 0; i < n; i++) {
  1118.         if (BrFileEof(df->h) != 0) {
  1119.             break;
  1120.         }
  1121.         df->prims->struct_read(df, str, cp);
  1122.         cp += str->mem_size;
  1123.     }
  1124.     return i;
  1125. }
  1126.  
  1127. // IDA: int __usercall DfChunkWriteText@<EAX>(br_datafile *df@<EAX>, br_uint_32 id@<EDX>, br_uint_32 length@<EBX>)
  1128. int DfChunkWriteText(br_datafile* df, br_uint_32 id, br_uint_32 length) {
  1129.     int i;
  1130.     LOG_TRACE("(%p, %d, %d)", df, id, length);
  1131.  
  1132.     if (id < BR_ASIZE(ChunkNames)) {
  1133.         i = BrFilePrintf(df->h, "*%-16s %d\n", ChunkNames[id], length);
  1134.     } else {
  1135.         i = BrFilePrintf(df->h, "*0x%08x %d\n", id, length);
  1136.     }
  1137.     return i; // Pierre-Marie Baty -- must return a value
  1138. }
  1139.  
  1140. // IDA: int __usercall DfChunkReadText@<EAX>(br_datafile *df@<EAX>, br_uint_32 *plength@<EDX>)
  1141. int DfChunkReadText(br_datafile* df, br_uint_32* plength) {
  1142.     int i;
  1143.     char* id;
  1144.     char* data;
  1145.     LOG_TRACE9("(%p, %p)", df, plength);
  1146.  
  1147.     if (TextReadLine(df, &id, &data) == 0) {
  1148.         return -1;
  1149.     }
  1150.     if (*id != '*') {
  1151.         BrFailure("Chunk ID not found");
  1152.     }
  1153.     id++;
  1154.     if (*id == '0') {
  1155.         i = BrStrToUL(id, NULL, 0);
  1156.     } else {
  1157.         for (i = 0; i < BR_ASIZE(ChunkNames); i++) {
  1158.             if (BrStrCmp(ChunkNames[i], id) == 0) {
  1159.                 break;
  1160.             }
  1161.         }
  1162.         if (i >= BR_ASIZE(ChunkNames)) {
  1163.             BrFailure("Chunk ID not known: %s", id);
  1164.         }
  1165.     }
  1166.     if (plength != NULL) {
  1167.         *plength = BrStrToUL(data, NULL, 0);
  1168.     }
  1169.     return i;
  1170. }
  1171.  
  1172. // IDA: int __usercall DfChunkWriteBinary@<EAX>(br_datafile *df@<EAX>, br_uint_32 id@<EDX>, br_uint_32 length@<EBX>)
  1173. int DfChunkWriteBinary(br_datafile* df, br_uint_32 id, br_uint_32 length) {
  1174.     br_uint_32 l;
  1175.     LOG_TRACE("(%p, %d, %d)", df, id, length);
  1176.  
  1177.     l = BrHtoNL(id);
  1178.     BrFileWrite(&l, sizeof(br_uint_32), 1, df->h);
  1179.     l = BrHtoNL(length);
  1180.     BrFileWrite(&l, sizeof(br_uint_32), 1, df->h);
  1181.     return 0;
  1182. }
  1183.  
  1184. // IDA: int __usercall DfChunkReadBinary@<EAX>(br_datafile *df@<EAX>, br_uint_32 *plength@<EDX>)
  1185. int DfChunkReadBinary(br_datafile* df, br_uint_32* plength) {
  1186.     br_uint_32 id;
  1187.     br_uint_32 l;
  1188.     LOG_TRACE9("(%p, %p)", df, plength);
  1189.  
  1190.     if (BrFileEof(df->h) != 0) {
  1191.         return -1;
  1192.     }
  1193.     BrFileRead(&id, sizeof(br_uint_32), 1, df->h);
  1194.     if (BrFileEof(df->h) != 0) {
  1195.         return -1;
  1196.     }
  1197.     id = BrHtoNL(id);
  1198.     BrFileRead(&l, sizeof(br_uint_32), 1, df->h);
  1199.     if (BrFileEof(df->h) != 0) {
  1200.         return -1;
  1201.     }
  1202.     if (plength != NULL) {
  1203.         *plength = BrHtoNL(l);
  1204.     }
  1205.     return id;
  1206. }
  1207.  
  1208. // IDA: void __usercall DfCountWriteText(br_datafile *df@<EAX>, br_uint_32 count@<EDX>)
  1209. void DfCountWriteText(br_datafile* df, br_uint_32 count) {
  1210.     LOG_TRACE("(%p, %d)", df, count);
  1211.  
  1212.     BrFilePrintf(df->h, " count %d\n", count);
  1213. }
  1214.  
  1215. // IDA: br_uint_32 __usercall DfCountReadText@<EAX>(br_datafile *df@<EAX>)
  1216. br_uint_32 DfCountReadText(br_datafile* df) {
  1217.     char* id;
  1218.     char* data;
  1219.     LOG_TRACE("(%p)", df);
  1220.  
  1221.     TextReadLine(df, &id, &data);
  1222.     if (BrStrCmp(id, "count") != 0) {
  1223.         BrFailure("no element count for chunk");
  1224.     }
  1225.     return BrStrToUL(data, NULL, 0);
  1226. }
  1227.  
  1228. // IDA: void __usercall DfCountWriteBinary(br_datafile *df@<EAX>, br_uint_32 count@<EDX>)
  1229. void DfCountWriteBinary(br_datafile* df, br_uint_32 count) {
  1230.     br_uint_32 l;
  1231.  
  1232.     l = BrHtoNL(count);
  1233.     BrFileWrite(&l, sizeof(l), 1, df->h);
  1234. }
  1235.  
  1236. // IDA: br_uint_32 __usercall DfCountReadBinary@<EAX>(br_datafile *df@<EAX>)
  1237. br_uint_32 DfCountReadBinary(br_datafile* df) {
  1238.     br_uint_32 l;
  1239.     LOG_TRACE9("(%p)", df);
  1240.  
  1241.     BrFileRead(&l, sizeof(br_uint_32), 1, df->h);
  1242.     return BrHtoNL(l);
  1243. }
  1244.  
  1245. // IDA: int __usercall DfCountSizeText@<EAX>(br_datafile *df@<EAX>)
  1246. int DfCountSizeText(br_datafile* df) {
  1247.     LOG_TRACE("(%p)", df);
  1248.  
  1249.     return 1;
  1250. }
  1251.  
  1252. // IDA: int __usercall DfCountSizeBinary@<EAX>(br_datafile *df@<EAX>)
  1253. int DfCountSizeBinary(br_datafile* df) {
  1254.     LOG_TRACE("(%p)", df);
  1255.  
  1256.     return sizeof(br_uint_32);
  1257. }
  1258.  
  1259. // IDA: br_uint_8* __usercall BlockWriteSetup@<EAX>(void *base@<EAX>, int block_size@<EDX>, int block_stride@<EBX>, int block_count@<ECX>, int size)
  1260. br_uint_8* BlockWriteSetup(void* base, int block_size, int block_stride, int block_count, int size) {
  1261.     //int b; // Pierre-Marie Baty -- unused variable
  1262.     //br_uint_8* block; // Pierre-Marie Baty -- unused variable
  1263.     //br_uint_8* sp; // Pierre-Marie Baty -- unused variable
  1264.     //br_uint_8* dp; // Pierre-Marie Baty -- unused variable
  1265.     LOG_TRACE("(%p, %d, %d, %d, %d)", base, block_size, block_stride, block_count, size);
  1266.     NOT_IMPLEMENTED();
  1267. }
  1268.  
  1269. // IDA: int __usercall DfBlockWriteText@<EAX>(br_datafile *df@<EAX>, void *base@<EDX>, int block_size@<EBX>, int block_stride@<ECX>, int block_count, int size)
  1270. int DfBlockWriteText(br_datafile* df, void* base, int block_size, int block_stride, int block_count, int size) {
  1271.     int i;
  1272.     //br_uint_8* cp; // Pierre-Marie Baty -- unused variable
  1273.     br_uint_8* block;
  1274.     int count;
  1275.     LOG_TRACE("(%p, %p, %d, %d, %d, %d)", df, base, block_size, block_stride, block_count, size);
  1276.  
  1277.     if (block_stride == block_size) {
  1278.         block_size = block_count * block_size;
  1279.         block_count = 1;
  1280.     }
  1281.     block = base;
  1282. #if !BR_ENDIAN_BIG
  1283.     if ((size != 1) || (block_count != 1)) {
  1284. #else
  1285.     if (block_count != 1) {
  1286. #endif
  1287.         block = BrScratchAllocate(block_count * block_size * size);
  1288.         for (count = 0; count < block_count; count++) {
  1289.             BrMemCpy(block + count * block_size * size, (br_uint_8*)base + count * block_stride * size, block_size * size);
  1290.         }
  1291. #if !BR_ENDIAN_BIG
  1292.         BrSwapBlock(block, block_count * block_size, size);
  1293. #endif
  1294.     }
  1295.     BrFilePrintf(df->h, "  block %d\n", block_count * block_size);
  1296.     BrFilePrintf(df->h, "  size %d\n", size);
  1297.     for (i = 0; i < block_count * block_size * size; i++) {
  1298.         if ((i & 0x1f) == 0) {
  1299.             BrFilePrintf(df->h, "    %08x: %02x", i, block[i]);
  1300.         } else {
  1301.             BrFilePrintf(df->h, "%02x", block[i]);
  1302.         }
  1303.         if ((i & 0x1f) == 0x1f) {
  1304.             BrFilePutChar('\n', df->h);
  1305.         }
  1306.     }
  1307.     if ((i & 0x1f) != 0x0) {
  1308.         BrFilePutChar('\n', df->h);
  1309.     }
  1310.     if (block != base) {
  1311.         BrScratchFree(block);
  1312.     }
  1313.     return 0;
  1314. }
  1315.  
  1316. // IDA: void* __usercall DfBlockReadText@<EAX>(br_datafile *df@<EAX>, void *base@<EDX>, int *count@<EBX>, int size@<ECX>, int mtype)
  1317. void* DfBlockReadText(br_datafile* df, void* base, int* count, int size, int mtype) {
  1318.     char* id;
  1319.     char* data;
  1320.     int l;
  1321.     int s;
  1322.     int a;
  1323.     char b[3];
  1324.     LOG_TRACE9("(%p, %p, %p, %d, %d)", df, base, count, size, mtype);
  1325.  
  1326.     TextReadLine(df, &id, &data);
  1327.     if (BrStrCmp(id, "block") != 0) {
  1328.         BrFailure("no block");
  1329.     }
  1330.     l = BrStrToUL(data, NULL, 0);
  1331.     TextReadLine(df, &id, &data);
  1332.     if (BrStrCmp(id, "size") != 0) {
  1333.         BrFailure("no size");
  1334.     }
  1335.     s = BrStrToUL(data, NULL, 0);
  1336.     if (s != size) {
  1337.         BrFailure("block size mismatch");
  1338.     }
  1339.     if (base == NULL) {
  1340.         base = BrResAllocate(df->res ? df->res : fw.res, l * size, mtype);
  1341.     } else {
  1342.         if (*count < l) {
  1343.             BrFailure("DfBlockReadText: block too long: %d", l);
  1344.         }
  1345.     }
  1346.     *count = l;
  1347.     for (a = 0; a < l * size;) {
  1348.         TextReadLine(df, &id, &data);
  1349.         if (a != BrStrToL(id, NULL, 16)) {
  1350.             BrFailure("block address mismatch");
  1351.         }
  1352.         while ((data[0] != '\0') && (data[1] != '\0')) {
  1353.             b[0] = data[0];
  1354.             b[1] = data[1];
  1355.             b[2] = '\0';
  1356.             ((br_uint_8*)base)[a] = (br_uint_8)BrStrToUL(b, NULL, 16);
  1357.             data += 2;
  1358.             a++;
  1359.         }
  1360.     }
  1361. #if !BR_ENDIAN_BIG
  1362.     BrSwapBlock(base, l, size);
  1363. #endif
  1364.     return base;
  1365. }
  1366.  
  1367. // IDA: int __usercall DfBlockWriteBinary@<EAX>(br_datafile *df@<EAX>, void *base@<EDX>, int block_size@<EBX>, int block_stride@<ECX>, int block_count, int size)
  1368. int DfBlockWriteBinary(br_datafile* df, void* base, int block_size, int block_stride, int block_count, int size) {
  1369.     int count;
  1370.     br_uint_32 l;
  1371.     br_uint_32 s;
  1372.     void* block;
  1373.     LOG_TRACE("(%p, %p, %d, %d, %d, %d)", df, base, block_size, block_stride, block_count, size);
  1374.  
  1375.     l = BrHtoNL(block_count * block_size);
  1376.     s = BrHtoNL(size);
  1377.     if (block_stride == block_size) {
  1378.         block_size = block_count * block_size;
  1379.         block_count = 1;
  1380.     }
  1381.     block = base;
  1382. #if !BR_ENDIAN_BIG
  1383.     if ((size != 1) || (block_count != 1)) {
  1384. #else
  1385.     if (block_count != 1) {
  1386. #endif
  1387.         block = BrScratchAllocate(block_count * block_size * size);
  1388.         for (count = 0; count < block_count; count++) {
  1389.             BrMemCpy((br_uint_8*)block + count * block_size * size, (br_uint_8*)base + count * block_stride * size, block_size * size);
  1390.         }
  1391. #if !BR_ENDIAN_BIG
  1392.         BrSwapBlock(block, block_count * block_size, size);
  1393. #endif
  1394.     }
  1395.     BrFileWrite(&l, sizeof(l), 1, df->h);
  1396.     BrFileWrite(&s, sizeof(s), 1, df->h);
  1397.     BrFileWrite(block, block_count * block_size, size, df->h);
  1398.     if (block != base) {
  1399.         BrScratchFree(block);
  1400.     }
  1401.     return 0;
  1402. }
  1403.  
  1404. // IDA: void* __usercall DfBlockReadBinary@<EAX>(br_datafile *df@<EAX>, void *base@<EDX>, int *count@<EBX>, int size@<ECX>, int mtype)
  1405. void* DfBlockReadBinary(br_datafile* df, void* base, int* count, int size, int mtype) {
  1406.     int l;
  1407.     int s;
  1408.     LOG_TRACE9("(%p, %p, %p, %d, %d)", df, base, count, size, mtype);
  1409.  
  1410.     BrFileRead(&l, 4, 1, df->h);
  1411.     l = BrHtoNL(l);
  1412.     BrFileRead(&s, 4, 1, df->h);
  1413.     s = BrHtoNL(s);
  1414.     if (s != size) {
  1415.         BrFailure("block size mismatch");
  1416.     }
  1417.     if (base != NULL) {
  1418.         if (l > *count) {
  1419.             BrFailure("DfBlockReadBinary: block too long: %d", l);
  1420.         }
  1421.     } else {
  1422.         base = BrResAllocate(df->res != NULL ? df->res : fw.res, size * l, mtype);
  1423.     }
  1424.     *count = l;
  1425.     BrFileRead(base, l, size, df->h);
  1426. #if !BR_ENDIAN_BIG
  1427.     BrSwapBlock(base, l, size);
  1428. #endif
  1429.     return base;
  1430. }
  1431.  
  1432. // IDA: int __usercall DfBlockSizeText@<EAX>(br_datafile *df@<EAX>, void *base@<EDX>, int block_size@<EBX>, int block_stride@<ECX>, int block_count, int size)
  1433. int DfBlockSizeText(br_datafile* df, void* base, int block_size, int block_stride, int block_count, int size) {
  1434.     LOG_TRACE("(%p, %p, %d, %d, %d, %d)", df, base, block_size, block_stride, block_count, size);
  1435.  
  1436.     return ((size * block_count * block_size + (32 - 1)) >> 5) + 2;
  1437. }
  1438.  
  1439. // IDA: int __usercall DfBlockSizeBinary@<EAX>(br_datafile *df@<EAX>, void *base@<EDX>, int block_size@<EBX>, int block_stride@<ECX>, int block_count, int size)
  1440. int DfBlockSizeBinary(br_datafile* df, void* base, int block_size, int block_stride, int block_count, int size) {
  1441.     LOG_TRACE("(%p, %p, %d, %d, %d, %d)", df, base, block_size, block_stride, block_count, size);
  1442.  
  1443.     return size * block_count * block_size + 8;
  1444. }
  1445.  
  1446. // IDA: char* __usercall DfNameReadText@<EAX>(br_datafile *df@<EAX>, char *name@<EDX>)
  1447. char* DfNameReadText(br_datafile* df, char* name) {
  1448.     char* id;
  1449.     char* data;
  1450.     LOG_TRACE("(%p, \"%s\")", df, name);
  1451.  
  1452.     TextReadLine(df, &id, &data);
  1453.     if (BrStrCmp(id, "name") != 0) {
  1454.         BrFailure("no name");
  1455.     }
  1456.     if ((data != NULL) && (*data == '\"')) {
  1457.         BrStrNCpy(name, data + 1, 0xff);
  1458.         name[0xff] = '\0';
  1459.         return data;
  1460.     }
  1461.     BrFailure("no name string");
  1462.     return NULL; // Pierre-Marie Baty -- make compiler happy
  1463. }
  1464.  
  1465. // IDA: int __usercall DfNameWriteText@<EAX>(br_datafile *df@<EAX>, char *name@<EDX>)
  1466. int DfNameWriteText(br_datafile* df, char* name) {
  1467.     LOG_TRACE("(%p, \"%s\")", df, name);
  1468.  
  1469.     if (name == NULL) {
  1470.         name = "NULL";
  1471.     }
  1472.     BrFilePrintf(df->h, "  name \"%s\"\n", name);
  1473.     return 0;
  1474. }
  1475.  
  1476. // IDA: int __usercall DfNameSizeText@<EAX>(br_datafile *df@<EAX>, char *name@<EDX>)
  1477. int DfNameSizeText(br_datafile* df, char* name) {
  1478.     LOG_TRACE("(%p, \"%s\")", df, name);
  1479.  
  1480.     return 1;
  1481. }
  1482.  
  1483. // IDA: char* __usercall DfNameReadBinary@<EAX>(br_datafile *df@<EAX>, char *name@<EDX>)
  1484. char* DfNameReadBinary(br_datafile* df, char* name) {
  1485.     int c;
  1486.     int i;
  1487.     LOG_TRACE9("(%p, \"%s\")", df, name);
  1488.  
  1489.     for (i = 0; i < 255; i++) {
  1490.         c = BrFileGetChar(df->h);
  1491.         if ((c == 0) || (c == -1)) {
  1492.             break;
  1493.         }
  1494.         name[i] = c;
  1495.     }
  1496.     name[i] = '\0';
  1497.     return name;
  1498. }
  1499.  
  1500. // IDA: int __usercall DfNameWriteBinary@<EAX>(br_datafile *df@<EAX>, char *name@<EDX>)
  1501. int DfNameWriteBinary(br_datafile* df, char* name) {
  1502.     LOG_TRACE("(%p, \"%s\")", df, name);
  1503.  
  1504.     if (name != NULL) {
  1505.         BrFileWrite(name, 1, BrStrLen(name), df->h);
  1506.     }
  1507.     BrFilePutChar('\0', df->h);
  1508.     return 0;
  1509. }
  1510.  
  1511. // IDA: int __usercall DfNameSizeBinary@<EAX>(br_datafile *df@<EAX>, char *name@<EDX>)
  1512. int DfNameSizeBinary(br_datafile* df, char* name) {
  1513.     LOG_TRACE("(%p, \"%s\")", df, name);
  1514.  
  1515.     if (name != NULL) {
  1516.         return BrStrLen(name) + 1;
  1517.     }
  1518.     return 1;
  1519. }
  1520.  
  1521. // IDA: int __usercall DfSkipText@<EAX>(br_datafile *df@<EAX>, br_uint_32 length@<EDX>)
  1522. int DfSkipText(br_datafile* df, br_uint_32 length) {
  1523.     char* id;
  1524.     char* data;
  1525.     LOG_TRACE("(%p, %d)", df, length);
  1526.  
  1527.     while ((BrFileEof(df->h) == 0) && (length != 0)) {
  1528.         TextReadLine(df, &data, &id);
  1529.         length--;
  1530.     }
  1531.     return 0;
  1532. }
  1533.  
  1534. // IDA: int __usercall DfSkipBinary@<EAX>(br_datafile *df@<EAX>, br_uint_32 length@<EDX>)
  1535. int DfSkipBinary(br_datafile* df, br_uint_32 length) {
  1536.     LOG_TRACE9("(%p, %d)", df, length);
  1537.     BrFileAdvance(length, df->h);
  1538.     return 0;
  1539. }
  1540.  
  1541. // IDA: int __usercall DfChunksInterpret@<EAX>(br_datafile *df@<EAX>, br_chunks_table *table@<EDX>)
  1542. int DfChunksInterpret(br_datafile* df, br_chunks_table* table) {
  1543.     br_uint_32 length;
  1544.     br_uint_32 count;
  1545.     br_uint_32 id;
  1546.     int r;
  1547.     int i;
  1548.     LOG_TRACE9("(%p, %p)", df, table);
  1549.  
  1550.     while (1) {
  1551.         id = df->prims->chunk_read(df, &length);
  1552.         // LOG_DEBUG("chunk id=%d, len=%d", id, length);
  1553.         if (id == (br_uint_32)-1) {
  1554.             break;
  1555.         }
  1556.         for (i = 0; i < table->nentries; i++) {
  1557.             if (table->entries[i].id == id) {
  1558.                 break;
  1559.             }
  1560.         }
  1561.         if (i >= table->nentries) {
  1562.             df->prims->skip(df, length);
  1563.         } else {
  1564.             if (table->entries[i].has_count != 0) {
  1565.                 count = df->prims->count_read(df);
  1566.             } else {
  1567.                 count = 0;
  1568.             }
  1569.             r = table->entries[i].handler(df, id, length, count);
  1570.             if (r != 0) {
  1571.                 return r;
  1572.             }
  1573.         }
  1574.     }
  1575.     return 0;
  1576. }
  1577.  
  1578. // IDA: void __cdecl BrNullOther()
  1579. void BrNullOther(void) {
  1580.     LOG_TRACE("()");
  1581.  
  1582.     // Yes, "invalid" is misspelled.
  1583.     BrFatal("datafile.c", 1825, "Invald file primitive call");
  1584. }
  1585.  
  1586. // IDA: int __cdecl DfFileIdentify(br_uint_8 *magics, br_size_t n_magics)
  1587. int DfFileIdentify(br_uint_8* magics, br_size_t n_magics) {
  1588.     static char text_magics[8] = { '*', 'F', 'I', 'L', 'E', '_', 'I', 'N' };
  1589.     static char binary_magics[8] = { '\0', '\0', '\0', '\x12', '\0', '\0', '\0', '\b' };
  1590.  
  1591.     if (BrMemCmp(magics, text_magics, sizeof(magics)) == 0) {
  1592.         return BR_FS_MODE_TEXT;
  1593.     }
  1594.     if (BrMemCmp(magics, binary_magics, sizeof(magics)) == 0) {
  1595.         return BR_FS_MODE_BINARY;
  1596.     }
  1597.     LOG_WARN("file does not match magics");
  1598.     return BR_FS_MODE_UNKNOWN;
  1599. }
  1600.  
  1601. // IDA: br_datafile* __usercall DfOpen@<EAX>(char *name@<EAX>, int write@<EDX>, br_token scalar_type@<EBX>)
  1602. br_datafile* DfOpen(char* name, int write, br_token scalar_type) {
  1603.     int mode;
  1604.     //char c; // Pierre-Marie Baty -- unused variable
  1605.     br_datafile* df;
  1606.     void* h;
  1607.     LOG_TRACE9("(\"%s\", %d, %d)", name, write, scalar_type);
  1608.  
  1609.     mode = fw.open_mode;
  1610.     if (write != 0) {
  1611.         h = BrFileOpenWrite(name, fw.open_mode);
  1612.     } else {
  1613.         h = BrFileOpenRead(name, 8u, DfFileIdentify, &mode);
  1614.     }
  1615.     if (h == NULL) {
  1616.         return NULL;
  1617.     }
  1618.     df = BrResAllocate(fw.res, sizeof(br_datafile), BR_MEMORY_DATAFILE);
  1619.     df->prims = &_BrFilePrimsNull;
  1620.     df->h = h;
  1621.     df->scalar_type = scalar_type;
  1622.  
  1623.     if (mode == BR_FS_MODE_BINARY) {
  1624.         if (write != 0) {
  1625.             df->prims = &_BrFilePrimsWriteBinary;
  1626.         } else {
  1627.             df->prims = &_BrFilePrimsReadBinary;
  1628.         }
  1629.     } else {
  1630.         if (write != 0)
  1631.             df->prims = &_BrFilePrimsWriteText;
  1632.         else
  1633.             df->prims = &_BrFilePrimsReadText;
  1634.     }
  1635.     DfPush(BR_MEMORY_FILE, df, 1); // Wrong enum -> should be DF_STACK_FILE (see comment in src/BRSRC13/CORE/V1DB/v1dbfile.c)
  1636.     return df;
  1637. }
  1638.  
  1639. // IDA: void __usercall DfClose(br_datafile *df@<EAX>)
  1640. void DfClose(br_datafile* df) {
  1641.     br_datafile* dfp;
  1642.     LOG_TRACE("(%p)", df);
  1643.  
  1644.     // TODO: this is not quite right according to IDA
  1645.  
  1646.     while (1) {
  1647.         if (DatafileStackTop > 0) {
  1648.             if (DatafileStack[DatafileStackTop - 1].type == BR_MEMORY_FILE) {
  1649.                 break;
  1650.             }
  1651.             DfPop(DatafileStack[DatafileStackTop - 1].type, NULL);
  1652.         }
  1653.     }
  1654.     dfp = DfPop(BR_MEMORY_FILE, NULL);
  1655.     BrFileClose(dfp->h);
  1656.     BrResFree(dfp);
  1657. }
  1658.  
  1659. // IDA: int __cdecl BrWriteModeSet(int mode)
  1660. int BrWriteModeSet(int mode) {
  1661.     int old;
  1662.     LOG_TRACE("(%d)", mode);
  1663.  
  1664.     old = fw.open_mode;
  1665.     fw.open_mode = mode;
  1666.     return old;
  1667. }
  1668.