# Ogre Package Archive (.package)

A simple uncompressed indexed file container format for OGRE3D, similar to Unity asset bundles.

## Format

The `.package` format stores files sequentially with a file index at the end:

```
[File 1 Data]
[File 2 Data]
...
[File N Data]
[Index Block]
  - Number of files (uint32_t)
  - For each file:
    - Filename length (uint32_t)
    - Filename data (UTF-8)
    - Offset in file (uint64_t)
    - Size in bytes (uint64_t)
    - Timestamp (int64_t)
[Footer]
  - Index offset (uint64_t) - points to start of Index Block
  - Magic number "PACK" (uint32_t) = 0x4B434150
```

## Features

- **No compression** - Files are stored as-is for fast access
- **Indexed** - O(1) lookup by filename via in-memory index
- **Random access** - Files can be read individually without scanning
- **Persistent** - Index is stored in the file footer for fast loading
- **Mutable** - Supports add, remove, and replace operations
- **OGRE Archive interface** - Usable from `resources.cfg` like Zip archives

## Usage from resources.cfg

```
[General]
Package=path/to/resources.package
```

The archive type is registered as `"Package"`.

## PackageTool CLI

The `PackageTool` executable provides command-line management of `.package` files:

```
PackageTool create <package.package> <file1> [file2 ...]
    Create a new package containing the specified files.

PackageTool add <package.package> <file1> [file2 ...]
    Add files to an existing package.

PackageTool remove <package.package> <file1> [file2 ...]
    Remove files from a package.

PackageTool extract <package.package> <file1> [dest]
    Extract a single file from a package. If dest is omitted,
    the file is extracted to the current directory with its
    original filename.

PackageTool extract-all <package.package> [dest-dir]
    Extract all files from a package. If dest-dir is omitted,
    files are extracted to the current directory.

PackageTool list <package.package>
    List all files in a package.

PackageTool info <package.package>
    Show detailed information about a package.
```

### Notes

- For `create` and `add`, if a source path is a directory, its contents are added recursively.
- Files are stored with their relative path when added from subdirectories.
- If a file with the same name already exists in the package, it is replaced.

## C++ API

```cpp
#include "OgrePackageArchive.h"

// Create or open a package
Ogre::PackageArchive archive("my.package", "Package");
archive.load();

// Add a file from memory
const char *data = "Hello, World!";
archive.addFile("hello.txt", data, strlen(data));

// Add a file from disk
archive.addFileFromDisk("stored.txt", "/path/to/source.txt");

// Open and read a file
auto stream = archive.open("hello.txt");
std::vector<char> buf(stream->size());
stream->read(buf.data(), stream->size());

// List files
auto files = archive.list(true, false);  // recursive, no dirs
for (const auto &f : *files) {
    std::cout << f << std::endl;
}

// Find files by pattern
auto found = archive.find("*.txt", true, false);

// Check if file exists
bool exists = archive.exists("hello.txt");

// Remove a file
archive.remove("hello.txt");

// Extract to disk
archive.extractFile("hello.txt", "/tmp/hello.txt");

// Get modification time
time_t mtime = archive.getModifiedTime("hello.txt");

// Unload
archive.unload();
```

## Building

The library is built as a static library target `PackageArchive`:

```cmake
target_link_libraries(my_target PackageArchive OgreMain)
```

The `PackageTool` executable is built as a separate target.
