diff --git a/include/exhparser.h b/include/exhparser.h index fbed322..479f626 100644 --- a/include/exhparser.h +++ b/include/exhparser.h @@ -8,7 +8,7 @@ // taken from https://xiv.dev/game-data/file-formats/excel struct ExhHeader { char magic[0x4]; - uint16_t unknown; + uint16_t version; uint16_t dataOffset; uint16_t columnCount; uint16_t pageCount; diff --git a/src/exdparser.cpp b/src/exdparser.cpp index f9cabb5..2572ab8 100644 --- a/src/exdparser.cpp +++ b/src/exdparser.cpp @@ -9,11 +9,11 @@ #include "utility.h" struct ExcelDataHeader { - char magic[0x4]; + char magic[4]; uint16_t version; uint16_t unknown1; uint32_t indexSize; - uint32_t unknown2[5]; + uint16_t unknown2[10]; }; struct ExcelDataOffset { @@ -63,7 +63,7 @@ EXD readEXD(EXH& exh, std::string_view path, ExcelDataPagination& page) { endianSwap(&header.indexSize); std::vector dataOffsets; - dataOffsets.resize(header.indexSize / sizeof( ExcelDataOffset )); + dataOffsets.resize(header.indexSize / sizeof(ExcelDataOffset)); fread(dataOffsets.data(), sizeof(ExcelDataOffset) * dataOffsets.size(), 1, file); @@ -72,106 +72,124 @@ EXD readEXD(EXH& exh, std::string_view path, ExcelDataPagination& page) { endianSwap(&offset.rowId); } - for(auto& offset : dataOffsets) { - Row row; + for(int i = 0; i < exh.header.rowCount; i++) { + for(auto& offset : dataOffsets) { + if (offset.rowId == i) { + fseek(file, offset.offset, SEEK_SET); - fseek(file, exh.header.dataOffset + offset.offset, SEEK_SET); + ExcelDataRowHeader rowHeader; + fread(&rowHeader, sizeof(ExcelDataRowHeader), 1, file); - ExcelDataRowHeader rowHeader; - fread(&rowHeader, sizeof(ExcelDataRowHeader), 1, file); + endianSwap(&rowHeader.dataSize); + endianSwap(&rowHeader.rowCount); - endianSwap(&rowHeader.dataSize); - endianSwap(&rowHeader.rowCount); + const int headerOffset = offset.offset + 6; - const int rowOffset = offset.offset + 6; + const auto readRow = [&exd, &exh, file, rowHeader](int offset) { + Row row; - for(auto column : exh.columnDefinitions) { - Column c; + for (auto column: exh.columnDefinitions) { + Column c; - switch(column.type) { - case String: - { - fseek(file, rowOffset + column.offset, SEEK_SET); + switch (column.type) { + case String: { + fseek(file, offset + column.offset, SEEK_SET); - uint32_t stringLength; - fread(&stringLength, sizeof(uint32_t), 1, file); + uint32_t stringLength = 0; // this is actually offset? + fread(&stringLength, sizeof(uint32_t), 1, file); - fseek(file, rowOffset + exh.header.dataOffset + stringLength, SEEK_SET); + endianSwap(&stringLength); - std::string string; + fseek(file, offset + exh.header.dataOffset + stringLength, SEEK_SET); - int ch; - while ((ch = fgetc(file)) != '\0' && ch != '\377') { - string.push_back((char)ch); + std::string string; + + uint8_t byte; + fread(&byte, sizeof(uint8_t), 1, file); + while(byte != 0) { + string.push_back(byte); + fread(&byte, sizeof(uint8_t), 1, file); + } + + fmt::print("read {}\n", string); + + c.data = string; + c.type = "String"; + } + break; + case Int8: + c.data = readData(file, offset + column.offset); + c.type = "Int"; + break; + case UInt8: + c.data = readData(file, offset + column.offset); + c.type = "Unsigned Int"; + break; + case Int16: + c.data = readData(file, offset + column.offset); + c.type = "Int"; + break; + case UInt16: + c.data = readData(file, offset + column.offset); + c.type = "Unsigned Int"; + break; + case Int32: + c.data = readData(file, offset + column.offset); + c.type = "Int"; + break; + case UInt32: + c.data = readData(file, offset + column.offset); + c.type = "Unsigned Int"; + break; + case Float32: + c.data = readData(file, offset + column.offset); + c.type = "Float"; + break; + case Int64: + c.data = readData(file, offset + column.offset); + c.type = "Int"; + break; + case UInt64: + c.data = readData(file, offset + column.offset); + c.type = "Unsigned Int"; + break; + case PackedBool0: + case PackedBool1: + case PackedBool2: + case PackedBool3: + case PackedBool4: + case PackedBool5: + case PackedBool6: + case PackedBool7: { + int shift = (int) column.type - (int) PackedBool0; + int bit = 1 << shift; + int32_t data = readDataRaw(file, offset + column.offset); + c.data = std::to_string((data & bit) == bit); + c.type = "Boolean"; + } + break; + default: + c.data = "undefined"; + c.type = "Unknown"; + break; + } + + row.data.push_back(c); } - fmt::print("{}\n", string.data()); + exd.rows.push_back(row); + }; - c.data = string; - c.type = "String"; + if (rowHeader.rowCount > 1) { + for (int i = 0; i < rowHeader.rowCount; i++) { + int subrowOffset = headerOffset + (i * exh.header.dataOffset + 2 * (i + 1)); + readRow(subrowOffset); + } + } else { + readRow(headerOffset); } - break; - case Int8: - c.data = readData(file, rowOffset + column.offset); - c.type = "Int"; - break; - case UInt8: - c.data = readData(file, rowOffset + column.offset); - c.type = "Unsigned Int"; - break; - case Int16: - c.data = readData(file, rowOffset + column.offset); - c.type = "Int"; - break; - case UInt16: - c.data = readData(file, rowOffset + column.offset); - c.type = "Unsigned Int"; - break; - case Int32: - c.data = readData(file, rowOffset + column.offset); - c.type = "Int"; - break; - case UInt32: - c.data = readData(file, rowOffset + column.offset); - c.type = "Unsigned Int"; - break; - case Float32: - c.data = readData(file, rowOffset + column.offset); - c.type = "Float"; - break; - case Int64: - c.data = readData(file, rowOffset + column.offset); - c.type = "Int"; - break; - case UInt64: - c.data = readData(file, rowOffset + column.offset); - c.type = "Unsigned Int"; - break; - case PackedBool0: - case PackedBool1: - case PackedBool2: - case PackedBool3: - case PackedBool4: - case PackedBool5: - case PackedBool6: - case PackedBool7: { - int shift = (int)column.type - (int)PackedBool0; - int bit = 1 << shift; - int32_t data = readDataRaw(file, rowOffset + column.offset); - c.data = std::to_string((data & bit) == bit); - c.type = "Boolean"; - } - break; - default: - c.data = "undefined"; - c.type = "Unknown"; - break; } - - row.data.push_back(c); } - - exd.rows.push_back(row); } return exd; diff --git a/src/exhparser.cpp b/src/exhparser.cpp index cb007d3..bb93826 100644 --- a/src/exhparser.cpp +++ b/src/exhparser.cpp @@ -17,6 +17,8 @@ EXH readEXH(const std::string_view path) { fread(&exh.header, sizeof(ExhHeader), 1, file); + fseek(file, 0x20, SEEK_SET); + endianSwap(&exh.header.dataOffset); endianSwap(&exh.header.columnCount); endianSwap(&exh.header.pageCount);