This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 15k traffic Daily!!!

Embedding Files in an Executable – SDL/Windows – Part 5


On this instance we are going to take a look at this method utilizing the SDL library.

Let’s change the patch.

If utilizing solely 2 arguments it should get the dimensions of the file itself

patch primary.exe knowledge.txt
Enter fullscreen mode

Exit fullscreen mode

If we use 3 arguments we are able to return to the unique file dimension

patch primary.exe knowledge.txt 246784
Enter fullscreen mode

Exit fullscreen mode

1) Let’s replace the patch:

#embody <fstream>
#embody <iostream>
#embody <string> 
#embody <vector>
#embody <sstream>

std::vector<char> file_read_bin(const std::string& fileName) {
  std::string filePath = fileName;
  std::ifstream file(filePath, std::ios::binary);
  if (file.fail()) {
    std::cerr << "Open file error " << filePath << std::endl;
   } 
 // Learn bytes 
  std::vector<char> bytFile((std::istreambuf_iterator<char>(file)),
                             std::istreambuf_iterator<char>());
  file.shut(); 
  return bytFile;
}

void file_write_bin(const std::string& filePath, std::vector<char> bytFile) { 
  // Write bytes
  std::ofstream outFile(filePath, std::ios::binary);
  if (outFile.fail()) {
    std::cerr << "Open file error " << filePath << " to put in writing" << std::endl;  
  } 
  outFile.write(bytFile.knowledge(), bytFile.dimension());
  outFile.shut();

  std::cout << "File sucessfull up to date" << std::endl;
} 

int primary(int argc, char *argv[]){   

  int correctSize = 0;

  if (argc < 2) {
      std::cout << "Require 2 or 3 args: program.exe knowledge.txt 163857n";
      return 1;
  }

  const char* program_file = argv[1];
  const char* data_file = argv[2];

  std::vector<char> bytFile = file_read_bin( program_file );
  std::vector<char> bytText = file_read_bin( data_file );

  int dimension = bytFile.dimension(); 

  if(argc == 3) {
    correctSize = dimension;    
  }else if(argc == 4) {
    correctSize = std::stoi(argv[3]);
  }

  int diff = dimension - correctSize;

  // Logs
  std::cout << "dimension: " << dimension << "n";
  std::cout << "correctSize: " << correctSize << "n";

  // Take away previous code
  if(dimension > correctSize ){
    bytFile.erase(bytFile.finish() - diff, bytFile.finish() );
  }

  // Add content material
  bytFile.insert(bytFile.finish(), bytText.start(), bytText.finish());

  // Add content material dimension
  bytFile.insert(bytFile.finish(), {
    static_cast<char>((bytText.dimension() >> 24) & 0xFF),
    static_cast<char>((bytText.dimension() >> 16) & 0xFF),
    static_cast<char>((bytText.dimension() >> 8) & 0xFF),
    static_cast<char>((bytText.dimension() >> 0) & 0xFF)
  });

  // Add file title
  std::string data_filename_str(data_file);
  data_filename_str+="";
  bytFile.insert(bytFile.finish(), data_filename_str.c_str(), data_filename_str.c_str() + data_filename_str.dimension() );

  // Add title dimension
  bytFile.insert( bytFile.finish(), data_filename_str.dimension() );  

  // Add image exist new file
  std::string image = "^";
  bytFile.insert(bytFile.finish(), image.c_str(), image.c_str() + image.dimension() );

  // Rewrite 
  file_write_bin(program_file, bytFile);

  return 0;
}
Enter fullscreen mode

Exit fullscreen mode

2) Compile

g++ patch.cpp -o patch
Enter fullscreen mode

Exit fullscreen mode

3) Create patchFiles lib

Now separate that system. Put in a file “patchFiles.h”

We would like it to be insanely easy to make use of.

patch! patch! finish!

With few traces:

#embody "./patchFiles.h"

// Get recordsdata
std::map<std::string, FileInfo> recordsdata = getFiles(); 

//Use
std::cout << recordsdata["data.txt"].contentString;  
Enter fullscreen mode

Exit fullscreen mode

For this we are going to use a map:

struct FileInfo {
    int fileNameSize;
    std::string fileName;
    int contentSize;
    int contentStart;
    int hole;
    std::string contentString;
    std::vector<char> contentVector;    
};

std::map<std::string, FileInfo> recordsdata; 
Enter fullscreen mode

Exit fullscreen mode

patchFiles.h

#embody <map>
#embody <string>
#embody <vector>
#embody <filesystem>

#embody <fstream>
#embody <iostream>
#embody <home windows.h>
#embody <sstream>
#embody <string> 
#embody <locale>

struct FileInfo {
    int fileNameSize;
    std::string fileName;
    int contentSize;
    int contentStart;
    int hole;
    std::string contentString;
    std::vector<char> contentVector;    
};

int assetsCount = 0;
std::map<std::string, FileInfo> recordsdata; 

std::string getFileName(){
    char filename[MAX_PATH];
    GetModuleFileNameA(NULL, filename, MAX_PATH);
    std::string filepath(filename);
    std::string basename = filepath.substr(filepath.find_last_of("/") + 1);
    return filename;
}

std::vector<char> file_read_bin(const std::string& fileName) {
  std::string filePath = fileName;
  std::ifstream file(filePath, std::ios::binary);
  if (file.fail()) {
    std::cerr << "Erro ao abrir o arquivo " << filePath << std::endl;
   } 
 // Learn bytes 
  std::vector<char> bytFile((std::istreambuf_iterator<char>(file)),
                             std::istreambuf_iterator<char>());
  file.shut(); 
  return bytFile;
}

std::string getHexValue(const std::vector<char>& bytFile, int dimension, int byteCount) {
    std::stringstream ss;
    ss << std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned int>(static_cast<unsigned char>(bytFile[size - byteCount]));
    return ss.str();
}

int hexToInt(std::string hexStr) {
    return std::stoi(hexStr, nullptr, 16);
}

int getFileNamesize(std::vector<char> bytFile, int dimension){

    std::string sizeHex = getHexValue(bytFile, dimension, 2); 
    return hexToInt( sizeHex );
}

std::string getFileName(std::vector<char> bytFile, int dimension, int fileNameSize){

    std::string fileName = "";
    int startfileName = fileNameSize + 2;
    for (int i = startfileName; i > 2; i--) { 
        std::string byteInStringFormat;
        byteInStringFormat.push_back(static_cast<char>(bytFile[size - i])); // convert byte to char
        fileName += byteInStringFormat;
    } 
    return fileName;
}

int getContentSize(std::vector<char> bytFile, int dimension, int fileNameSize){

    std::string byte_24 = getHexValue(bytFile, dimension, fileNameSize + 3);
    std::string byte_16 = getHexValue(bytFile, dimension, fileNameSize + 4);
    std::string byte_08 = getHexValue(bytFile, dimension, fileNameSize + 5);
    std::string byte_00 = getHexValue(bytFile, dimension, fileNameSize + 6);

    std::stringstream ss;   
    ss << std::hex << byte_00 << byte_08 << byte_16 << byte_24;
    int contentSize;
    ss >> contentSize;
    return contentSize;
}

std::string getContent(std::vector<char> bytFile, int dimension, int fileNameSize, int contentSize, int contentStart){

    std::string content material = "";

    for (int i = contentStart; i > fileNameSize+3+3; i--) { 
        std::string byteInStringFormat;
        byteInStringFormat.push_back(static_cast<char>(bytFile[size - i])); // convert byte to char 
        content material += byteInStringFormat;
    }

    return content material;
}

int getContent(std::map<std::string, FileInfo>& recordsdata, const std::vector<char>& bytFile, int dimension) {

    if( bytFile[size - 1] != '^') { // Exist new file?
        std::cout << "finish" << "n";    
        return 0; 
    }

    std::cout << assetsCount << "-----------------" << "n"; 

    // Get file title dimension in final byte 
    int fileNameSize = getFileNamesize(bytFile, dimension);
    std::cout << "content material title dimension: " << fileNameSize << "n";

    // Get file title in final byte 
    std::string fileName = getFileName(bytFile, dimension, fileNameSize);
    std::cout << "content material title: " << fileName << "n"; 

    // Get content material dimension in 4 bytes
    int contentSize = getContentSize(bytFile, dimension, fileNameSize);
    std::cout << "content material dimension: " << contentSize << "n";   


    // Get contentStart from last of file 
    int contentStart = contentSize+fileNameSize+3+3;
    int hole = contentStart - contentSize;

    // Get content material
    std::string contentString = "";   
    std::vector<char> contentVector;

    if(fileName.discover(".txt") != fileName.npos){

      contentString = getContent(bytFile, dimension, fileNameSize, contentSize, contentStart);

    }else if(fileName.discover(".png") != fileName.npos){

        for(int i = bytFile.dimension() - contentSize - hole; i < bytFile.dimension() + hole; i++) {
            contentVector.push_back(bytFile[i]);
        }
    }

    recordsdata[ fileName ] = {fileNameSize, fileName, contentSize, contentStart, hole, contentString, contentVector};
    assetsCount+=1;

    // Finish
    int last = dimension - (contentStart + 1);
    std::cout << "-----------------" << "n"; 

    getContent(recordsdata, bytFile, last+1); // get new file

    return 0;
}

std::map<std::string, FileInfo> getFiles() {

    // Learn file  
    std::string filename = getFileName();
    std::vector<char> bytFile = file_read_bin( filename ); 
    int dimension = bytFile.dimension(); 

    // Logs
    std::cout << "file dimension: " << dimension << std::endl;
    std::cout << "final byte: " << getHexValue(bytFile, dimension, 1) << std::endl;

    getContent(recordsdata, bytFile, dimension); 

    return recordsdata;
}
Enter fullscreen mode

Exit fullscreen mode

4) Obtain SDL

Obtain and export contained in the undertaking folder:

SDL2_image-devel-2.6.3-mingw.zip
https://github.com/libsdl-org/SDL_image/releases/download/release-2.6.3/SDL2_image-devel-2.6.3-mingw.zip

SDL2-devel-2.26.4-mingw.zip
https://github.com/libsdl-org/SDL/releases/download/release-2.26.4/SDL2-devel-2.26.4-mingw.zip

You may go away the folders with these similar names.

SDL2_image-devel-2.6.3-mingw
SDL2-devel-2.26.4-mingw
Enter fullscreen mode

Exit fullscreen mode

We’re not even going to put in it. Let’s use it anyway.

Simply seize these two recordsdata from bin folders and drop them within the undertaking listing:

SDL2.dll
SDL2_image.dll
Enter fullscreen mode

Exit fullscreen mode

5) Present pictures

I took two free pictures from Pexels and adjusted the dimensions: 1280×720

Image app

Image app

Obtain these pictures. Rename one of many pictures to “bg.png”
https://dev-to-uploads.s3.amazonaws.com/uploads/articles/899pvtvcwx2zney81vr4.png
https://dev-to-uploads.s3.amazonaws.com/uploads/articles/agy0ayu8ul5xl78k8yzh.png

Additionally create a file: knowledge.txt
Content material: 123

Now simply import our lib and use:

primary.cpp


#embody <SDL.h>
#embody <SDL_image.h>

#embody "./patchFiles.h"

int primary(int argc, char *argv[]){    

    // Get belongings
    std::map<std::string, FileInfo> recordsdata = getFiles(); 

    // Use
    std::vector<char> bytImage = recordsdata["bg.png"].contentVector;
    std::cout << recordsdata["data.txt"].contentString; 

    SDL_Init(SDL_INIT_VIDEO);

    SDL_Window* window = SDL_CreateWindow("App", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_SHOWN);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_RWops* rwops = SDL_RWFromMem(bytImage.knowledge(), bytImage.dimension());
    SDL_Surface* floor = IMG_Load_RW(rwops, 1);  
    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, floor);

    SDL_FreeSurface(floor);

    bool stop = false;
    whereas (!stop) {
        SDL_Event occasion;
        whereas (SDL_PollEvent(&occasion)) {
            swap (occasion.sort) {
                case SDL_QUIT:
                    stop = true;
                    break;
                case SDL_KEYDOWN:
                    if (occasion.key.keysym.sym == SDLK_ESCAPE) {
                        stop = true;
                        break;
                    }
            }
        }

        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, texture, NULL, NULL);
        SDL_RenderPresent(renderer);
    }

    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;  
}

Enter fullscreen mode

Exit fullscreen mode

6) Compile

Let’s compile utilizing all of that, no makefile or something:

g++ -std=c++17 primary.cpp -o primary.exe -I. -I.SDL2-devel-2.26.4-mingwSDL2-2.26.4x86_64-w64-mingw32includeSDL2 -I.SDL2_image-devel-2.6.3-mingwSDL2_image-2.6.3x86_64-w64-mingw32includeSDL2 -L.SDL2_image-devel-2.6.3-mingwSDL2_image-2.6.3x86_64-w64-mingw32lib -L.SDL2-devel-2.26.4-mingwSDL2-2.26.4x86_64-w64-mingw32lib -w -Wl,-subsystem,console -lmingw32 -lSDL2main -lSDL2 -lSDL2_image
Enter fullscreen mode

Exit fullscreen mode

7) Now Patch

Now let’s add the belongings on this recipe:

patch primary.exe knowledge.txt
patch primary.exe bg.png
Enter fullscreen mode

Exit fullscreen mode

8) Run
Run this system:

primary
Enter fullscreen mode

Exit fullscreen mode

Image app

9) Check
Now let’s take a look at if this all actually works.
Let’s change the belongings with out having to compile.

Create a folder and drop the picture there or delete it.
Rename the opposite picture to “bg.png”
Change the content material of knowledge.txt to “0987654321” or no matter.

There within the immediate you may learn what was the primary file dimension.

> patch primary.exe knowledge.txt
dimension: 246784
correctSize: 246784
Enter fullscreen mode

Exit fullscreen mode

Let’s make the executable return to this dimension utilizing a 3rd argument:

patch primary.exe knowledge.txt 246784
patch primary.exe bg.png
Enter fullscreen mode

Exit fullscreen mode

8) Run
Run this system:

primary
Enter fullscreen mode

Exit fullscreen mode

Image app

The Article was Inspired from tech community site.
Contact us if this is inspired from your article and we will give you credit for it for serving the community.

This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 10k Tech related traffic daily !!!

Leave a Reply

Your email address will not be published. Required fields are marked *

Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?