Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Giga Entergram .arc extractor
- Copyright (C) 2024 rahcchi (https://github.com/rahcchi)
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <iostream>
- #include <vector>
- #include <fstream>
- #include <cstring> // For memcpy and memset
- #include <cstdio> // For sprintf
- #include <cstdlib> // For setlocale
- #include <sys/stat.h> // For stat() to check file existence
- #ifdef _WIN32
- #include <direct.h> // For _mkdir on Windows
- #define mkdir(F, A) _mkdir(F) // Redefine mkdir for Windows compatibility
- #endif
- // Function to check if a file exists
- bool file_exists(const char* filename) {
- struct stat buffer;
- return (stat(filename, &buffer) == 0);
- }
- // Struct for archive header
- typedef struct header {
- uint32_t unk;
- uint32_t file_number;
- } header;
- // Struct for individual file entry in the archive
- typedef struct entry_header {
- char file_name[64];
- uint32_t size;
- uint32_t offset;
- } entry_header;
- // Template function to extract data of a given type (T) from a byte array
- template<typename T>
- T get(const uint8_t* data, int offset) {
- return *(T*)&data[offset]; // Cast the data at offset to type T
- }
- int main(int argc, char* argv[]) {
- // Set locale to support file names with special characters
- setlocale(LC_ALL, "");
- // Check if input file is provided and exists
- if (argc < 2 || !file_exists(argv[1])) {
- std::cerr << "Usage: " << argv[0] << " <input.arc>" << std::endl;
- return -1;
- }
- // Read the file into a byte vector
- std::vector<uint8_t> filedata;
- std::ifstream is(argv[1], std::ios::binary);
- // Get the file size
- is.seekg(0, std::ios_base::end);
- std::size_t filesize = is.tellg();
- is.seekg(0, std::ios_base::beg);
- // Resize the vector to fit the file data
- filedata.resize(filesize);
- is.read(reinterpret_cast<char*>(&filedata[0]), static_cast<std::streamsize>(filesize));
- is.close();
- // Initialize offset and read the archive header
- int global_offset = 0;
- header file;
- file.unk = get<uint32_t>(filedata.data(), global_offset);
- global_offset += sizeof(uint32_t);
- file.file_number = get<uint32_t>(filedata.data(), global_offset);
- global_offset += sizeof(uint32_t);
- // Read file entries from the archive
- std::vector<entry_header> files;
- for (uint32_t i = 0; i < file.file_number; i++) {
- entry_header f;
- memcpy(&f.file_name, filedata.data() + global_offset, 64); // Copy file name
- global_offset += 64;
- f.size = get<uint32_t>(filedata.data(), global_offset); // Read file size
- global_offset += sizeof(uint32_t);
- f.offset = get<uint32_t>(filedata.data(), global_offset); // Read file offset
- global_offset += sizeof(uint32_t);
- files.push_back(f);
- }
- // Output number of files found
- printf("FOUND %d FILES\n", file.file_number);
- // Create output directory
- mkdir("out", 0777); // On Windows, this uses _mkdir
- // Extract each file
- for (size_t i = 0; i < files.size(); i++) {
- char buffer[256];
- memset(buffer, 0, 256);
- sprintf(buffer, "./out/%s", files[i].file_name); // Define output path
- // Open the file for writing
- FILE* f = fopen(buffer, "wb");
- if (f != NULL) {
- fwrite(filedata.data() + files[i].offset, files[i].size, 1, f);
- fclose(f);
- printf("EXTRACTED %s\n", files[i].file_name);
- } else {
- printf("FAILED TO EXTRACT %s\n", files[i].file_name);
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement