ZQuestFile* ZQuestFileReader::read() { atUint32 magic, version, compressedLen, uncompressedLen; ZQuestFile::Game game = ZQuestFile::NoGame; std::string gameString; atUint16 BOM; atUint32 checksum = 0; magic = readUint32(); if ((magic & 0x00FFFFFF) != (ZQuestFile::Magic & 0x00FFFFFF)) { atError("Not a valid ZQuest file"); return nullptr; } version = readUint32(); if (version > ZQuestFile::Version) { atError("Unsupported ZQuest version"); return nullptr; } compressedLen = readUint32(); uncompressedLen = readUint32(); if (version >= ZQUEST_VERSION_CHECK(2, 0, 0)) { gameString = std::string((const char*)readBytes(0x0A).get(), 0x0A); for (size_t i = 0; i < ZQuestFile::gameStringList().size(); i++) { if (!ZQuestFile::gameStringList().at(i).substr(0, 0x0A).compare(gameString)) { gameString = ZQuestFile::gameStringList().at(i); game = (ZQuestFile::Game)i; break; } } BOM = readUint16(); checksum = readUint32(); } else { game = (ZQuestFile::Game)readUint32(); BOM = readUint16(); seek(0x0A); } std::unique_ptr<atUint8[]> data = readUBytes(compressedLen); // compressedLen is always the total file size if (version >= ZQUEST_VERSION_CHECK(2, 0, 0)) { if (checksum != athena::Checksums::crc32(data.get(), compressedLen)) { atError("Checksum mismatch, data corrupt"); return nullptr; } } else { std::clog << "ZQuest version 0x" << std::uppercase << std::setw(8) << std::setfill('0') << std::hex << athena::utility::swapU32(version); std::clog << " has no checksum field" << std::endl; } if (compressedLen != uncompressedLen) { atUint8* dst = new atUint8[uncompressedLen]; atUint32 dstLen = io::Compression::decompressZlib(data.get(), compressedLen, dst, uncompressedLen); if (dstLen != uncompressedLen) { delete[] dst; atError("Error decompressing data"); return nullptr; } data.reset(dst); } return new ZQuestFile(game, BOM == 0xFEFF ? Endian::BigEndian : Endian::LittleEndian, std::move(data), uncompressedLen, gameString); }
Map* MapFileReader::read() { Map* ret = new Map; Uint32 magic = base::readUInt32(); if (magic != Map::MAGIC_NUMBER) throw zelda::error::IOException("MapFileReader::read -> Not a valid zmap file"); Uint32 version = base::readUInt32(); if (version != Map::VERSION) throw zelda::error::IOException("MapFileReader::read -> Unsupported version"); Uint16 bom = readUInt16(); if (bom == 0xFFFE) base::setEndianess(zelda::BigEndian); ret->setName(base::readString()); int rgba = base::readUInt32(); ret->setBackgroundColor(*((RGBA*)&rgba)); ret->setWidth(base::readUInt32()); ret->setHeight(base::readUInt32()); ret->setTileWidth(base::readUInt16()); ret->setTileHeight(base::readUInt16()); Uint32 tilesetCount = base::readUInt32(); Uint32 layerCount = base::readUInt32(); base::seek((base::position() + 0x1F) & ~0x1F, base::Beginning); while ((tilesetCount--) > 0) { ret->addTileset(base::readString()); } // Align to 32bytes for Wii/GCN support base::seek((base::position() + 0x1F) & ~0x1F, base::Beginning); int compressedSize = base::readUInt32(); int uncompressedSize = base::readUInt32(); // data is compressed if the compressed size is smaller than // uncompressedSize if (compressedSize < uncompressedSize) { Uint8* data = readUBytes(compressedSize); Uint8* uncompData = new Uint8[uncompressedSize]; int ret = zelda::io::Compression::decompressZlib(data, compressedSize, uncompData, uncompressedSize); if (ret != uncompressedSize) throw zelda::error::IOException("MapReader::read -> Error decompressing data"); base::setData(uncompData, uncompressedSize); delete[] data; } for (Uint32 i = 0; i < layerCount; i++) { std::cout << "Layer " << (i + 1) << std::endl; Layer* layer = new Layer; layer->setVisible(base::readBool()); layer->setZOrder(base::readUInt32()); int tileCount = base::readUInt32(); std::vector<Tile*> tiles; base::seek((base::position() + 0x1F) & ~0x1F, base::Beginning); for (int j = 0; j < tileCount; j++) { Sakura::Core::Tile* tile = new Sakura::Core::Tile(); tile->setId(base::readUInt32()); tile->setTileset(base::readUInt32()); tile->setFlippedHor(base::readBit()); tile->setFlippedVer(base::readBit()); tile->setFlippedDiag(base::readBit()); tile->setPosition(base::readUInt16(), base::readUInt16()); tiles.push_back(tile); // layer->addTile(tile); } // this is the new method layer->setTiles(tiles); base::seek((base::position() + 0x1F) & ~0x1F, base::Beginning); ret->addLayer(layer); } std::unordered_map<int, std::unordered_map<int, Cell*> > collision; for (Uint32 y = 0; y < ret->height() / ret->tileHeight(); y++) { for (Uint32 x = 0; x < ret->width() / ret->tileWidth(); x++) { Cell* cell = new Cell; cell->CollisionType = base::readByte(); cell->FlippedAndDamage = base::readByte(); collision[x][y] = cell; } } ret->setCollisionData(collision); return ret; }