← index
JavaScript.Projects/source/apps/WebAssembly_Ports/emx/src/gfx_file.cpp
Source: JavaScript.Projects/source/apps/WebAssembly_Ports/emx/src/gfx_file.cpp
#include "gfx_file.hpp"

namespace game {

    // gfx table add item to list
     void GfxTable::addItem(const GfxItem &item) {
        table.push_back(item);
     }
     // gfx table add item with parameters to list
     void GfxTable::addItem(uint32_t index, uint32_t solid, uint32_t obj, const std::string &filename) {
        std::cout << filename << " of type: " << obj << "\n";
        table.push_back( {index, solid, obj, filename });
     }

    // build table from text file
    bool GfxTable::buildTable(const std::string &cfg) {
        clear();
        std::fstream file;
        file.open(cfg, std::ios::in);
        if(!file.is_open())
            return false;
        int type = 0;
        int line_num = 0;
        while(!file.eof()) {
            std::string line;
            std::getline(file, line);
            if(file) {
                if(line == "[tiles]") {
                    type = 0;
                } else if(line == "[objects]") {
                    type = 1;
                } else if(line == "[hero:right]") {
                    type = 2;
                } else if(line == "[hero:left]") {
                    type = 3;
                } else if(line == "[bg1]") {
                    type = 4;    
                 } else if(line == "[e:right]") {
                    type = 5;
                 } else if(line == "[e:left]") {
                    type = 6;
                } else if(line.find("#") != std::string::npos) {
                    auto pos = line.find("#");
                    std::string right;
                    right = line.substr(pos+1, line.length()-1);
                    type = atoi(right.c_str());
                    if(type <= 6) {
                        std::cerr << "Error invalid type..\n";
                    }
                    std::cout << "Setting custom type: " << type << " on line: " << line_num << "\n";
                } 
                else {
                    std::string tokens[3];
                    auto pos = line.find(":");
                    if(pos == std::string::npos) {
                        std::cerr << "missing colon 1 on type: " << type << " on line: " << line_num << "\n";
                        return false;
                    }
                    tokens[0] = line.substr(0, pos);
                    std::string right;
                    right = line.substr(pos+1, line.length());
                    pos = right.find(":");
                    if(pos == std::string::npos) {
                        std::cerr << "missing colon 2 on type: " << type << " on line: " << line_num <<"\n";
                        return false;
                    }
                    tokens[1] = right.substr(0, pos);
                    tokens[2] = right.substr(pos+1, right.length());
                    addItem(atoi(tokens[0].c_str()), atoi(tokens[1].c_str()), type, tokens[2]);
                }
            }
            line_num++;
        }
        file.close();
        return true;
    }

    // clear table
    void GfxTable::clear() {
        if(!table.empty()) {
            table.erase(table.begin(), table.end());
        }
    }

    // compress ( concat ) table 
    bool GfxCompress::open(const std::string &text) {
        file.open(text, std::ios::out | std::ios::binary);

        if(!file.is_open())
            return false;

        uint32_t gfx_file = 0x421;
        file.write(reinterpret_cast<char*>(&gfx_file), sizeof(uint32_t));
        return true;     
    }

    // concat table 
    bool GfxCompress::compress(const GfxTable &t) {

        if(!file.is_open())
            return false;

         for(std::vector<GfxItem>::size_type i = 0; i < t.table.size(); ++i) {
            auto pos = t.table[i].filename.rfind("/");
            std::string id;
            if(pos == std::string::npos) 
                id = t.table[i].filename;
            else
                id = t.table[i].filename.substr(pos+1, t.table[i].filename.length());
            std::cout << "gfx-cmp: adding: " << t.table[i].filename << " as " << id << "\n";
            write_string(id);
            file.write(reinterpret_cast<const char*>(&t.table[i].index), sizeof(uint32_t));
            file.write(reinterpret_cast<const char*>(&t.table[i].solid), sizeof(uint32_t));
            file.write(reinterpret_cast<const char*>(&t.table[i].obj), sizeof(uint32_t));
            std::fstream in_file;
            in_file.open(t.table[i].filename, std::ios::in | std::ios::binary);
            if(!in_file.is_open()) {
                std::cerr << "Error could not open file: " << t.table[i].filename << "\n";
                return false;
            }
            in_file.seekg(0, std::ios::end);
            uint32_t len = in_file.tellg();
            file.write(reinterpret_cast<char*>(&len), sizeof(uint32_t));
            in_file.seekg(std::ios::beg);
            while(!in_file.eof()) {
                char buf[1024];
                in_file.read(reinterpret_cast<char*>(buf), sizeof(buf));
                file.write(reinterpret_cast<char*>(buf), in_file.gcount());                
            }
            in_file.close(); 
        }
        return true;
    }

    // close files     
    void GfxCompress::close() {
        file.close();
    }

    // write string to stream
    void GfxCompress::write_string(const std::string &item) {
        uint32_t len = static_cast<uint32_t>(item.length());
        file.write(reinterpret_cast<char*>(&len), sizeof(len));
        file.write(reinterpret_cast<const char*>(item.c_str()), len);
    }

    // open file to extract
    bool GfxExtract::open(const std::string &filename) {
        file.open(filename, std::ios::in | std::ios::binary);
        if(!file.is_open())
            return false;
        uint32_t magic = 0;
        file.read(reinterpret_cast<char*>(&magic), sizeof(magic));
        if(magic != 0x421) {
            file.close();
            return false;
        }
        return true;
    }

    // extract to location    
    bool GfxExtract::extract(GfxTable &table, const std::string &directory) {

        if(!file.is_open())
            return false;

        while(!file.eof()) {
            uint32_t len;
            file.read(reinterpret_cast<char*>(&len), sizeof(len));
            if(file) {
                char *tmp = new char [len+1];
                file.read(reinterpret_cast<char*>(tmp), len);
                tmp[len] = 0;
                std::string filename;
                filename = tmp;
                delete [] tmp;
                std::string path;
                path = directory + "/";
                path += filename;
                uint32_t index = 0, solid = 0, obj = 0, length = 0;
                file.read(reinterpret_cast<char*>(&index), sizeof(uint32_t));
                file.read(reinterpret_cast<char*>(&solid), sizeof(uint32_t));
                file.read(reinterpret_cast<char*>(&obj), sizeof(uint32_t));
                file.read(reinterpret_cast<char*>(&length), sizeof(uint32_t));
                std::cout << "reading file: " << filename  << " of size: " << length << " index: " << index << " solid: " << solid << " obj: " << obj << "\n";
                table.addItem(index, solid, obj, filename);
                char *buffer = new char [ length + 1 ];
                file.read(buffer, length);
                std::fstream fout;
                fout.open(path, std::ios::out | std::ios::binary);
                if(!fout.is_open()) {
                    std::cerr << "Error extracting could not open file: " << path << "\n";
                    return false;
                }
                fout.write(buffer, length);
                fout.close();
                std::cout << "wrote: " << path << "\n";
                delete [] buffer;
            }
        } 
        file.close();
        return true;
    }
    // list to gfx table
    bool GfxExtract::list(GfxTable &table) {

        if(!file.is_open())
            return false;

        while(!file.eof()) {
            uint32_t len;
            file.read(reinterpret_cast<char*>(&len), sizeof(len));
            if(file) {
                char *tmp = new char [len+1];
                file.read(reinterpret_cast<char*>(tmp), len);
                tmp[len] = 0;
                std::string filename;
                filename = tmp;
                delete [] tmp;
                uint32_t index = 0, solid = 0, obj = 0, length = 0;
                file.read(reinterpret_cast<char*>(&index), sizeof(uint32_t));
                file.read(reinterpret_cast<char*>(&solid), sizeof(uint32_t));
                file.read(reinterpret_cast<char*>(&obj), sizeof(uint32_t));
                file.read(reinterpret_cast<char*>(&length), sizeof(uint32_t));
                table.addItem(index, solid, obj, filename);
                file.seekg(length, std::ios::cur);
            }
        } 
        file.close();
        return true;
    }
}