Пример #1
0
    ///////////////////////////////////////////////////////////
    // Member functions
    //
    ///////////////////////////////////////////////////////////
    const QString String::read(const qboy::Rom &rom, UInt32 offset)
    {
        // Firstly, determines whether the given rom is valid
        Q_ASSERT(rom.info().isLoaded() && rom.info().isValid());

        // Declares needed variables for the decoding process
        QList<UInt8> encoded;
        QString decoded;
        UInt8 readByte;

        // Declares the different dynamic tables (some are the same across all roms)
        QMap<UInt32, QString> *mapBuffers = NULL;
        QMap<UInt32, QString> *mapFunctions = NULL;

        // Determines the rom version and depending on that, loads the tables
        if (CONFIG(RomType) == RT_FRLG)
        {
            mapBuffers = &BufferSequencesFRLG;
            mapFunctions = &FunctionSequencesFRLG;
        }
        else if (CONFIG(RomType) == RT_RS)
        {
            mapBuffers = &BufferSequencesRSE;
            mapFunctions = &FunctionSequencesRS;
        }
        else
        {
            mapBuffers = &BufferSequencesRSE;
            mapFunctions = &FunctionSequencesE;
        }


        // Reads the whole Pokémon string, terminated by 0xFF
        if (!rom.seek(offset))
            Q_ASSERT(false);

        while ((readByte = rom.readByte()) != 0xFF)
            encoded.push_back(readByte);

        // Iterates through every encoded character and interprets it
        int length = encoded.size();
        for (int i = 0; i < length;)
        {
            // Fetches the char at the current position
            UInt8 currentChar = encoded.at(i++);
            if (currentChar == 0xF8 || currentChar == 0xF9)
            {
                // Character might be a symbol
                UInt8 arg1 = encoded[i++];
                UInt32 search = ((currentChar << 8) | arg1);

                // Searches for the sequence in the symbol-map
                auto searchResult = SymbolSequences.find(search);
                if (searchResult != SymbolSequences.end())
                    decoded.push_back(searchResult.value());
                else
                    decoded.push_back(convertRaw(search));
            }
            else if (currentChar == 0xFD)
            {
                // Character might be a buffer
                UInt8 arg1 = encoded.at(i++);
                UInt32 search = ((currentChar << 8) | arg1);

                // Searches for the sequence in the dynamic buffer-map
                auto searchResult = mapBuffers->find(search);
                if (searchResult != mapBuffers->end())
                    decoded.push_back(searchResult.value());
                else
                    decoded.push_back(convertRaw(search));
            }
            else if (currentChar == 0xFC)
            {
                // Character might be an escape sequence
                UInt8 arg1 = encoded.at(i++);
                UInt32 search = 0;
                if (arg1 >= 1 && arg1 <= 6)
                {
                    // Might be a multi-byte function
                    UInt8 arg2 = encoded[i++];
                    search = ((currentChar << 16) | (arg1 << 8) | arg2);
                }
                else
                {
                    // Might be a single-byte function
                    search = ((currentChar << 8) | arg1);
                }

                // Searches for the sequence in the dynamic escape-map
                auto searchResult = mapFunctions->find(search);
                if (searchResult != mapFunctions->end())
                    decoded.push_back(searchResult.value());
                else
                    decoded.push_back(convertRaw(search));
            }
            else
            {
                // Is a single character for sure (exception-safe!)
                decoded.push_back(SingleSequences.value(currentChar));
            }
        }

        // Finished
        return decoded;
    }
Пример #2
0
    ///////////////////////////////////////////////////////////
    // Function type:  I/O
    // Contributors:   Pokedude
    // Last edit by:   Pokedude
    // Date of edit:   6/11/2016
    //
    ///////////////////////////////////////////////////////////
    bool MapHeader::read(const qboy::Rom &rom, UInt32 offset)
    {
        if (!rom.seek(offset))
            AME_THROW(HDR_ERROR_OFFSET, rom.redirected());


        // Reads the map's dimensions
        m_Width = rom.readWord();
        m_Height = rom.readWord();

        // Reads all the pointers within the structure
        m_PtrBorder = rom.readPointerRef();
        m_PtrBlocks = rom.readPointer();
        m_PtrPrimary = rom.readPointerRef();
        m_PtrSecondary = rom.readPointerRef();

        // Determines whether these pointers are valid
        if (!rom.checkOffset(m_PtrBorder))
            AME_THROW(HDR_ERROR_BORDER, offset + 8);
        if (!rom.checkOffset(m_PtrBlocks))
            AME_THROW(HDR_ERROR_BLOCKS, offset + 12);
        if (!rom.checkOffset(m_PtrPrimary))
            AME_THROW(HDR_ERROR_PRIMARY, offset + 16);
        if (!rom.checkOffset(m_PtrSecondary))
            AME_THROW(HDR_ERROR_SECONDARY, offset + 20);


        // Retrieves the border (different between games!)
        if (rom.info().isFRLG())
        {
            QSize borderSize(rom.readByte(), rom.readByte());
            m_Border.read(rom, m_PtrBorder, borderSize);
        }
        else
        {
            m_Border.read(rom, m_PtrBorder, QSize(2, 2));
        }

        // Retrieves the map block data
        rom.seek(m_PtrBlocks);
        for (unsigned i = 0; i < m_Width * m_Height; i++)
        {
            MapBlock *block = new MapBlock;
            UInt16 data = rom.readHWord();

            block->block = (data & 0x3FF);
            block->permission = (data >> 0xA);
            m_Blocks.push_back(block);
        }

        // Loads the tilesets, if necessary
        if ((m_Primary = TilesetManager::get(m_PtrPrimary)) == NULL)
        {
            m_Primary = new Tileset;
            m_Primary->read(rom, m_PtrPrimary);
            TilesetManager::add(m_Primary);
        }
        if ((m_Secondary = TilesetManager::get(m_PtrSecondary)) == NULL)
        {
            m_Secondary = new Tileset;
            m_Secondary->read(rom, m_PtrSecondary);
            TilesetManager::add(m_Secondary);
        }


        // Loading successful
        return true;
    }
Пример #3
0
    ///////////////////////////////////////////////////////////
    // Function type:  I/O
    // Contributers:   Pokedude
    // Last edit by:   Pokedude
    // Date of edit:   6/5/2016
    //
    ///////////////////////////////////////////////////////////
    bool Tileset::read(const qboy::Rom &rom, UInt32 offset)
    {
        if (!rom.seek(offset))
            AME_THROW(SET_ERROR_OFFSET, rom.redirected());


        // Reads the first two properties for the following determination
        m_IsCompressed = rom.readByte();
        m_IsPrimary = rom.readByte();
        rom.readHWord(); // padding


        // Determines all differences between FRLG and RSE
        int countPal;
        int countBlock;
        int palAdjustment;
        int uncompSize;
        if (rom.info().isFRLG())
        {
            if (!m_IsPrimary) // = 0 in the games -.-
            {
                countPal = 7;
                countBlock = 640;
                palAdjustment = 0;
                uncompSize = 40960;
            }
            else
            {
                countPal = 6;
                countBlock = 384;
                palAdjustment = 224;
                uncompSize = 24576;
            }
        }
        else
        {
            if (!m_IsPrimary) // = 0 in the games -.-
            {
                countPal = 6;
                countBlock = 512;
                palAdjustment = 0;
                uncompSize = 32768;
            }
            else
            {
                countPal = 7;
                countBlock = 512;
                palAdjustment = 192;
                uncompSize = 32768;
            }
        }


        // Reads all pointers within the tileset structure
        m_PtrImage = rom.readPointer();
        m_PtrPalette = rom.readPointer();
        m_PtrBlocks = rom.readPointer();

        if (rom.info().isFRLG()) // pointers reversed
        {
            m_PtrAnimations = rom.readPointer();
            m_PtrBehaviour = rom.readPointer();
        }
        else
        {
            m_PtrBehaviour = rom.readPointer();
            m_PtrAnimations = rom.readPointer();
        }


        // Determines whether all read pointers are valid
        if (!rom.checkOffset(m_PtrImage))
            AME_THROW(SET_ERROR_IMAGE, offset + 4);
        if (!rom.checkOffset(m_PtrPalette))
            AME_THROW(SET_ERROR_PALETTE, offset + 8);
        if (!rom.checkOffset(m_PtrBlocks))
            AME_THROW(SET_ERROR_BLOCKS, offset + 12);
        if (!rom.checkOffset(m_PtrAnimations))
            AME_THROW(SET_ERROR_ANIM, offset + 16);
        if (!rom.checkOffset(m_PtrBehaviour))
            AME_THROW(SET_ERROR_PROP, offset + 20);


        // Attempts to load the image
        if (m_IsCompressed)
        {
            if (!m_Image->readCompressed(rom, m_PtrImage, 128, true))
                AME_THROW(SET_ERROR_IMGDATA, m_PtrImage);
        }
        else
        {
            if (!m_Image->readUncompressed(rom, m_PtrImage, uncompSize, 128, true))
                AME_THROW(SET_ERROR_IMGDATA, m_PtrImage);
        }

        // Attempts to load the palettes
        for (int i = 0; i < countPal; i++)
        {
            qboy::Palette *pal = new qboy::Palette;
            pal->readUncompressed(rom, m_PtrPalette + palAdjustment + i * 32, 16);
            m_Pals.push_back(pal);
        }

        // Attempts to load the blocks
        rom.seek(m_PtrBlocks);
        for (int i = 0; i < countBlock; i++)
        {
            Block *block = new Block;
            m_Blocks.push_back(block);

            // Each block has 2 layers á 4 tiles
            for (int j = 0; j < 8; j++)
            {
                Tile tile;
                UInt16 data = rom.readHWord();

                // Extracts information from the hword
                tile.tile = (data & 0x3FF);
                tile.palette = ((data & 0xF800) >> 0xC);
                tile.flipX = ((data & 0x400) == 0x400);
                tile.flipY = ((data & 0x800) == 0x800);
                block->tiles[j] = tile;
            }
        }


        // Attempts to load the block properties
        m_Properties->read(rom, m_PtrBehaviour, countBlock);


        // Loading successful
        m_Offset = offset;
        return true;
    }