Skip to content

[TOOLS] GenBIG - A CLI Tool for BIG Archives #535

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

DevGeniusCode
Copy link

This PR introduces a CLI tool for handling BIG archives used in the Generals Zero Hour game. The tool leverages existing classes in the source code to work with BIG archives and files.

Note

The tool is heavily a work in progress and under investigation.

Features:

  • List files in an archive
  • Add files to a new or existing archive
  • Extract file(s) from an existing archive
  • Remove file(s) from an existing archive

The initial focus is on the simplest feature: listing the files in an archive. This will help to understand how to utilize the existing classes in the source code.

Relevant Classes in the Source Code:

  1. ArchiveFile: Represents a general archive file containing multiple subfiles, providing methods for interacting with and accessing the files inside the archive.

  2. ArchiveFileSystem: Manages a collection of archive files, enabling operations such as opening, closing, and searching for files across multiple archives.

  3. Win32BIGFile: A specific implementation of ArchiveFile for handling BIG archive files, with methods tailored for this file format.

  4. Win32BIGFileSystem: A specialized implementation of ArchiveFileSystem designed to manage and operate on multiple BIG archive files.

Known Issues:

  1. The tool is heavily a work in progress and under investigation. At this stage, it seems that extracting archives is already implemented in the source code, but we need to create and implement a new class for creating BIG archives.

  2. In the CMakeLists.txt file, I linked to z_gameengine and z_gameenginedevice to include the necessary classes from the source code. However, these libraries also include external symbols, which required me to add them in the main file as well. There is still one additional symbol I haven't figured out how to link.

  3. Due to point 2, I am unable to compile the project and test the code. Any help with this issue would be greatly appreciated.

@DevGeniusCode DevGeniusCode added Minor Severity: Minor < Major < Critical < Blocker Tools Affects Tools only labels Mar 29, 2025
@@ -3,6 +3,7 @@
# Build useful tool binaries.
if(GENZH_BUILD_ZEROHOUR_TOOLS)
add_subdirectory(DebugWindow)
add_subdirectory(GenBIG)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest call it BigArchiver or similar.

case '-':
switch (argv[i][1]) {
case 'a': // Add file or directory to the archive
case 'd': // Delete file from archive
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we use cxxopts for command line, to standardize setups. You can see example how it is used in https://github.com/xezon/unassemblize

m_outputDir = nullptr;
}
if (m_archiveName != nullptr) {
delete[] m_archiveName;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer to not use new/delete where so possible and use things like STL containers (std::string for strings) and smart pointers (std::unique_ptr, std::shared_ptr).

When interfacing with Engine, can also use AsciiString and UnicodeString.

//

#ifndef GENZH_BIGFILE_H
#define GENZH_BIGFILE_H
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use #pragma once instead of header include guards.

// Handle archive operations
bool addToArchive();
bool addDirectoryToArchive(const char* path);
bool deleteFromArchive(const char* name = NULL);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use nullptr for non-vs6 code.

bool setPaths(const char* path);

private:
Win32BIGFileSystem * m_archiveFileSystem; // or Win32BIGFileSystem?
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks odd that this class derives from Win32BIGFileSystem, but also owns a pointer to Win32BIGFileSystem.

Before jumping into big implementations, I suggest to take a moment and think carefully about the design.

Upon a first look, we could try to have something like:

class Win32BIGFileRW : public Win32BIGFile

class Win32BIGFileSystemRW : public Win32BIGFileSystem

You would just need to find an elegant way to make Win32BIGFileSystem use Win32BIGFileRW as well, probably with a template.

This could allow making a new Read Write version of the archive and its system, while reusing what is already there for opening and reading archives.

But perhaps the design of the Win32BIGFile and Win32BIGFileSystem make it hard to fit in the write functionality nicely. In that case a different strategy may be better.

Please also be mindful about performance when implementing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Minor Severity: Minor < Major < Critical < Blocker Tools Affects Tools only
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement BIG archive packer/unpacker
2 participants