Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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;
}