Português English

Game

Open Asset Package feature
2026.06.16

Open Asset Package

Games ship an astonishing number of files. Textures, meshes, audio, shaders, scenes, scripts — a single modern title can easily contain tens of thousands of individual assets. Managing this “asset tax” is one of the quiet challenges of game development.

Traditional archive formats such as Tar and ZIP remain common fallbacks, but they were designed for very different environments. Tar originated in the late 1970s for magnetic tape systems, while ZIP was introduced in the late 1980s to improve storage efficiency on floppy disks. Both remain useful general-purpose formats, yet neither was designed around the way modern game engines load and stream assets.

As projects grow, engines frequently adopt specialized packaging systems of their own. Unreal Engine uses .pak files, Unity relies on Asset Bundles, Godot distributes exported projects using .pck archives, and raylib provides the open rres format. Each addresses a subset of the same problems, but they are typically tied to specific ecosystems, tooling, or assumptions about how assets should be organized.

Open Asset Package (OAP) is an attempt to address these challenges with an open, engine-agnostic format designed specifically for modern game asset workflows.

The core problem

Game engines typically need three capabilities from an asset container:

  1. Random access, allowing a single asset to be located quickly without scanning through an entire archive.
  2. Streaming support, enabling assets to be fetched incrementally using HTTP range requests rather than downloading large monolithic files.
  3. Stable identity, ensuring that asset references remain valid even when filenames, directory structures, or packaging strategies evolve.

Traditional archive formats only partially address these requirements.

Tar was designed for sequential media. Finding a particular file requires traversing archive entries one after another, resulting in linear lookup times. When combined with stream compression such as tar.gz, extracting a single asset requires decompressing the entire archive.

ZIP improves substantially by introducing a central directory that allows direct lookups. However, the directory resides at the end of the archive, local headers duplicate metadata, and encryption support has evolved through multiple extensions over the years. ZIP remains a flexible general-purpose archive format rather than a system optimized for asset streaming and stable asset identities.

Game engine formats often solve these limitations in ways that reflect the priorities of their respective ecosystems.

Unity Asset Bundles prioritize integration with Unity’s editor and runtime. Early implementations relied heavily on monolithic LZMA compression, while newer versions introduced chunked LZ4 compression to improve loading behavior. Despite these advances, the format remains closely tied to Unity itself.

Unreal’s PAK format is among the most feature-rich approaches, supporting advanced compression methods, encryption, and layered package mounting. However, it is deeply integrated into Unreal’s virtual file system and asset pipeline.

Godot’s PCK format focuses on simplicity and seamless engine integration. Assets are primarily identified by path, and the packaging system is designed around Godot’s export process rather than general-purpose asset management.

Raylib’s rres is perhaps philosophically the closest relative to OAP. It offers an open specification with support for compression and encryption while maintaining a lightweight implementation. It intentionally leaves concerns such as dependency management and large-scale asset identity to higher-level systems.

OAP was designed to address these requirements directly: fast random access, efficient streaming, stable asset identities, and explicit dependency relationships in a format that is independent of any particular engine.

Design highlights

Fixed-size header: OAP organizes packages using a straightforward index-last layout. A fixed-size header is stored at the beginning of the file, while a sorted index resides at a known offset near the end. Asset data occupies the space in between. Opening a package therefore becomes a simple process: read the header, jump directly to the index, and perform a binary search to locate the desired asset. No scanning through asset contents is required. When packages are hosted remotely, locating an asset typically requires only two HTTP range requests: one to retrieve the header and another to access the index.

Independent asset features: Compression and encryption are defined on a per-asset basis rather than at the package level. One asset may be stored without compression for fast loading, while another may use DEFLATE compression and ChaCha20 encryption. Reading a single asset never requires decompressing or decrypting the entire archive. Encryption keys are intentionally excluded from the package itself, providing protection against casual extraction without attempting to function as a digital rights management system.

Asset identity: OAP separates asset identity from filesystem organization. Assets are identified using stable 128-bit identifiers, while human-readable paths are treated as metadata rather than primary keys. This enables practical workflows for patches and downloadable content. A small package containing only modified assets can be mounted alongside an existing package, and lookups resolve using asset identifiers rather than filenames. Renaming or reorganizing files no longer invalidates references throughout a project.

Asset dependency graph: OAP allows assets to declare dependencies directly within the package index. Materials can reference textures, scenes can reference meshes, and prefabs can reference supporting resources. By making these relationships explicit, engines can construct loading graphs, perform dependency analysis, and implement more sophisticated streaming strategies without relying on separate metadata systems.

Technical specification

The OAP format is documented independently in SPEC.md. The specification is language-agnostic and intentionally small: a conforming reader requires only little-endian integer parsing, a CRC-32/ISO-HDLC implementation, and a raw DEFLATE decoder — all of which ship in every major standard library. A minimal reader is a few hundred lines in any language with byte-buffer access. Alternative implementations in other languages are explicitly welcome; the repository includes a porting guide (docs/implementing.md) and a canonical test fixture (testdata/sample.oap) to validate against.

How it compares

General-purpose archive formats

Feature tar.gz ZIP OAP
Open specification Yes Yes Yes
Asset lookup Sequential O(n) Central directory O(1) Sorted binary-search index O(log n)
HTTP range-friendly Poor Limited Excellent
Per-asset compression No (whole-archive only) Yes Yes
Per-asset encryption External only Legacy / AES extensions ChaCha20 per asset
Stable asset identity No No Yes (128-bit ID)
Integrity checking None Optional CRC-32 Mandatory CRC-32
Dependency tracking No No Yes
Typical entry overhead 512 bytes ~76+ bytes 64 bytes fixed

Game engine asset formats

Feature Unity
Asset Bundles
raylib
rres
Godot
PCK
Unreal
PAK
OAP
Open specification No Yes Yes No Yes
Asset lookup Indexed O(1) Sequential O(n) Sequential O(n) Indexed Sorted binary-search O(log n)
HTTP range-friendly Limited Moderate Limited Moderate Excellent
Per-asset compression Chunk-based (LZ4) Yes No Yes Yes
Per-asset encryption No Yes Package-level Yes Yes (ChaCha20)
Stable asset identity No 32-bit IDs Path-based Path hashes 128-bit IDs
Integrity checking Yes Yes Yes Yes Mandatory CRC-32
Dependency tracking External (Addressables) No External External Built-in
Engine-independent tooling No Yes Limited No Yes

OAP does not attempt to replace engine-specific asset pipelines. Instead, it focuses on providing a portable packaging format that incorporates capabilities commonly found in specialized solutions while remaining straightforward to implement and independent of any particular engine ecosystem.

Performance

The following table compares OAP against tar and tar.gz on a synthetic game asset workload: 360 assets totalling approximately 114 MB of raw data, mixing compressible content (scripts, configuration, scene descriptions) with incompressible blobs (pre-compressed audio and textures). All OAP figures use a ReleaseFast-optimised build on x86_64 Linux; tar figures include subprocess spawn overhead.

Format Pack time Archive size vs raw Sequential read Random access
OAP — auto (deflate where beneficial) 153 ms 89.6 MB −21.8% 72 ms 71 ms
OAP — store (no compression) 100 ms 114.6 MB +0.0% 65 ms 66 ms
tar 155 ms 114.9 MB +0.2% 80 ms N/A
tar.gz 1 399 ms 89.6 MB −21.8% 123 ms N/A

OAP with automatic compression packs in the same time as plain tar while matching tar.gz’s compression ratio — which takes nine times as long to produce and nearly twice as long to read. Sequential read is faster than both tar variants. Random access — unavailable for tar formats without full extraction — completes in roughly the same time as a full sequential scan, owing to the O(log n) binary search over the sorted index.

Reference implementation CLI tool

The reference implementation ships as a single executable named oap, intended both as a practical utility and as an example of how the format is used in real applications.

The core library consists of approximately 500 lines of code and relies exclusively on Zig’s standard library for compression and cryptographic functionality. The build process produces both a static library (liboap.a) and the oap command-line utility. Applications written in C, C++, C#, or other FFI-friendly languages can integrate OAP without requiring Zig throughout the rest of the codebase.

PACK: Creating packages is performed using the pack command, which recursively scans a directory and produces an .oap archive: oap pack assets/ game.oap. Compression can be enabled or disabled as needed, package metadata can be customized, and assets may optionally be encrypted using ChaCha20. By default, asset identifiers are generated deterministically from virtual paths, ensuring consistent identities across builds.

INSPECT: Several commands are available for inspecting package contents. The inspect command displays package metadata such as the format version, manifest information, asset count, index location, and encryption status. The list command provides a more detailed inventory of packaged assets, including their identifiers, compression methods, encryption methods, sizes, and virtual paths.

UNPACK: Packages can be extracted using the unpack command, restoring assets according to their virtual paths. Encrypted packages can be unpacked by supplying the appropriate encryption key.

VALIDATE: For automated workflows, the validate command verifies both package metadata and the CRC-32 checksum of every asset contained within the archive: oap validate game.oap. This makes it suitable for use in continuous integration pipelines or for validating packages distributed through content delivery networks.

Part of Turian

OAP originated within the Turian game engine ecosystem but was designed as a standalone format suitable for any engine or application that requires efficient asset packaging.

Source code and the complete specification

Open Asset Package
Launching Turian feature
2026.06.13

Launching Turian

It’s finally time to talk about what I’ve been cooking. After a massive technical pivot and a lot of “mad scientist” hours in the lab, I am super excited to announce that Turian is officially live.

Turian is a 3D game engine built entirely in Zig. But to understand why it exists, we have to look back at where I was just a few months ago.

The Road Through C#

If you’ve followed my work, you know I’m incredibly proud of Guinevere, the C# GUI library I designed. I love that project. But as I tried to use it to build a full-blown engine studio, things got… complicated. I even tried a hybrid approach using Avalonia—which is a rock-solid piece of tech—but it just didn’t feel right for what I wanted to achieve. Plus, let’s be honest, the C# game engine scene is pretty crowded already.

When I started my “side quest” into Zig, something clicked. Programming in Zig was just fun. I found an existing Zig IMGUI library that let me start building the Turian Studio from day one. It’s not as powerful as I want it to be yet—I’ll probably end up forking it or investing heavily in enhancing it—but it got the ball rolling.

Some Technical Magic

One of the biggest hurdles in Zig (compared to C#) is the lack of reflection. I needed the editor to be able to “see” and manipulate the code. I’m happy to say I’ve mostly solved this! Now, the editor can inspect your structs and give you a proper UI to tweak them.

But the feature I’m most proud of? The In-Editor Play Mode. I managed to implement this by compiling the user’s game code into a library and loading it at runtime. It feels just like working in Unity or Godot—you hit play, and you’re in the game instantly. When you’re ready to ship, the final game is still compiled as a single, lean, native executable.

Right now, you can create a project from scratch, drop in your 3D models, add scripts, and “cook” the final game with just a few clicks.

The Roadmap

We are moving fast. The engine is evolving every day. Here’s the general plan for the near future:

  • Refining the 3D World: We’re currently deep into improving materials, lighting, and shadows.
  • Studio Power: Making the editor more robust, user-friendly, and powerful.
  • The Big Three: Soon, we’ll be investing heavily in Audio, Physics, and a proper In-Game GUI system.

The goal is to give you everything you need to build a complete, functional game without leaving the ecosystem.

A New MEGA4

This release marks a reset for the MEGA4 initiative. Like the original plan, we’re embracing the “One Language” philosophy, and, this time, Turian is our starting point. Instead of starting from the GUI and building upwards, we’re are jumping some steps and then go down to the bottom of the stack.

I’m definitively not an expert in Zig, and building a game engine is most definitely not an easy task, so there is not lack of excitement.

It’s totally open-source (GPLv3). I’m having a fun time coding this project. Check it out at turian.mass4.org!

A Zig-Zag Adventure feature
2026.06.10

A Zig-Zag Adventure

I’m a huge fan of C#. I’ve spent years mastering it, and honestly, quite good at it. And C# is better than ever: with every release, gets faster and more robust—at this point, rivaling C++ and Rust in many benchmarks with barely any difference. I still love it, and many of my projects are (and will continue to be) built with it. It’s my “home base.”

But lately, I felt like I needed a new challenge—something more “raw”. That’s when I started playing with Zig as a hobby/educational project. And well, things escalated.

Why Zig? (And why not Rust?)

I did try Rust, but honestly? It’s just not fun for me. It’s way too strict. Instead of focusing on the code logic or the “big picture”, I’d spend hours fighting the grammar and the borrow checker. And don’t even get me started on the syntax—it’s full of abbreviated commands and esoteric punctuation that makes my eyes hurt.

Zig, on the other hand, is simple, direct, and what you see is what you get. No hidden runtime, no heavy-handed rules. It respects your intelligence.

It’s Not All Sunshine and Rainbows

Let’s be real: moving to Zig has been a massive uphill battle in some ways. Coming from the luxury of C#, I really miss things like Attributes and Reflection. Yes, reflection is slower, but man, it is incredibly powerful for building tools. Zig’s comptime is amazing and covers a lot of ground, but it’s a different beast entirely.

Then there’s the ecosystem. Zig is still young, and the documentation is… let’s say “sparse.” Even LLMs, which are usually my go-to for quick answers, constantly struggle to give the right solutions because there just aren’t enough examples out there yet.

It’s ABI is not stable. Some things that would be trivial in C, are not possible in Zig.

And don’t get me started on the IDE support. I’ve moved most of my coding to the Zed editor lately. I love how fast it is, but it’s definitely not Rider. When you’re used to the deep, “knows-everything” intelligence of JetBrains tools for C#, coding in Zig feels a bit like flying a plane with half the instruments missing.

The Perfect Side Project

So why do it? Because it is an adventure. I feel exploring a brand new world, sharing my findings with the community, and pushing the boundaries. It is like planing a day-one-released game without any walkthrough - you’re just trying to figure things out on your own.

What started as a “let’s see how this works” weekend project has turned into something much bigger. It’s been an incredible learning experience that has forced me to sharpen my skills. And that hobby project? It actually turned into a full-blown engine. But I’ll save the details of that “accidental” release for the next post.

Expedition To A Dream feature
2026.05.07

Expedition To A Dream

Rarely does a debut title from a new studio land with such thunderous impact as Sandfall Interactive’s Clair Obscur: Expedition 33. It is a game that feels both nostalgic and fiercely modern, blending the deliberate pacing of classic JRPGs with a visual fidelity that pushes current-gen hardware to its absolute limits. Set in a world inspired by Belle Époque France, it tells a haunting story of a Paintress who wipes away ages with a stroke of her brush.

World map

Blueprints and Whispers

From a technical standpoint, this is a showcase for Unreal Engine 5. The implementation of Nanite and Lumen is among the best I’ve seen, allowing for environments that are densely packed with ornate architectural details without sacrificing performance. What is particularly impressive is that the team achieved this level of complexity almost entirely using Unreal’s visual scripting Blueprints, with very little C++ code—a significant feat for a project of this scale and visual fidelity.

The “Paintress” aesthetic is more than just a lore point; it informs the entire rendering pipeline, with certain effects and transitions looking like brushstrokes coming to life. However, while the levels are visually breathtaking, their layout can be deceptively labyrinthine. I often found myself inadvertently looping back to the start, lost in the sheer density of the ornate French-inspired architecture.

One stylistic choice that deserves special mention is the voice acting. Eschewing the typical high-octane shouting of action games, the cast often speaks in low, almost whispering tones—even in moments of despair or intense action. It gives the game a unique, somber atmosphere that feels distinctly deliberate and “stylish.”

Combat

The Combat Conundrum

The most significant design decision is the “Active Turn-Based” combat. Unlike traditional JRPGs where you might select a command and watch it play out, Expedition 33 requires constant player engagement. Every enemy attack can be dodged or parried in real-time, and your own attacks benefit from timed button presses.

A crucial piece of advice for any newcomer: test if you truly enjoy this combat loop early on. Because the game is a massive RPG, you will be engaging in these mechanics hundreds, if not thousands, of times throughout the journey. If the rhythm of parrying and dodging doesn’t click for you, the sheer frequency of combat might eventually feel like a hurdle rather than a highlight. For me, it added a layer of tension but I was exausted by the end.

Narrative and Character Depth

The story is a melancholic trek through a dying world, and for the most part, the writing is superb. It tackles heavy themes of grief, death, and the core of human existence with genuine maturity. The chemistry between the members of the expedition feels earned, and their individual motivations are slowly unpeeled like an onion.

However, by the third act, the narrative starts to lose its subtle touch. Themes that were previously explored through atmosphere and subtext begin to be discussed quite plainly and repetitively, making the existential weight feel a bit more forced than it was in the game’s earlier hours.

Cutscene

Rinse and Repeat

While the “active” nature of the combat is its soul, it can also lead to fatigue. Some late-game bosses have massive health pools, and maintaining perfect parry timing for 20+ minutes can be mentally draining. A bit more variety in encounter pacing—perhaps some “puzzles” within the combat system that don’t rely solely on reflexes—would have been a welcome addition.

Clair Obscur: Expedition 33 is a triumph of art and ambition. It proves that the turn-based genre still has plenty of room for innovation. Despite some third-act heavy-handedness and occasionally confusing level design, it is an essential experience for anyone who appreciates bold art direction and deep, challenging systems.

My Rating: 7★★★★★★★
Metacritic: 92
KDG2 is More of The Amazing Same feature
2026.03.05

KDG2 is More of The Amazing Same

Sequels often face the “sophomore slump,” but this sequel manages to dodge that trap by doubling down on everything that made its predecessor a cult classic. Kingdom Come: Deliverance II delivers on the original’s promises with newfound polish and ambition, making it easily my best experience of the year so far, as expected.

Kuttenberg Is the New Novigrad

From a technical standpoint, the leap in environmental density is staggering. The standout achievement is the city of Kuttenberg. Rendering a dense, medieval urban environment in CryEngine is a massive challenge. Unlike the small villages of the first game, this is a sprawling city with multi-story buildings, crowded marketplaces, and intricate alleyways. The developers had to significantly optimize their draw-call management and level-of-detail (LOD) systems to keep the frame rate stable while maintaining the gritty, lived-in aesthetic. The lighting system, particularly the way it handles interior shadows and cobblestone reflections, is a significant step up from the first title.

Kuttenberg

From Blacksmith to Ninja

As a developer, I’m always interested in the balance of progression systems. In this experience, the curve is somewhat front-loaded. By the time I moved to the second map and reached Kuttenberg, I was already a “super ninja.” This was largely because I took the first map very seriously, completing most of the side quests and engaging in every skirmish I could find. This provided enough opportunities to evolve Henry’s stats to a point where the quests in the second half of the game became a bit of a breeze.

While it feels rewarding to see Henry’s growth, from a design perspective, it highlights the difficulty of scaling content for a player who explores every corner. The combat, while refined and less “janky” than the original, can’t quite keep up with a fully leveled Henry, resulting in a power fantasy that contrasts sharply with the desperate survival of the early hours.

The Recurring Narrative Pacing Issue

On one hand, the amnesia setup is a clever narrative shortcut that sidesteps the “power creep” problem entirely. By stripping Henry back to a blank slate—forgetting combat techniques, alchemy recipes, and even basic survival skills—the developers justify the early-game fragility without having to invent a contrived injury or gear loss. It’s a diegetic reset button that feels surprisingly organic within the story’s opening chaos. That said, the trope wears thin quickly. The game hand-waves Henry forgetting everything—including how to hold a sword properly—while conveniently allowing him to remember key characters and plot-relevant details. It’s a functional solution to a difficult design problem, but one that lacks the elegance of the first game’s slower, more believable progression from village nobody to seasoned fighter. In trying to have it both ways, the amnesia framing occasionally feels less like storytelling and more like a designer’s duct tape.

Henry dueling

Unfortunately, some of the old ghosts still haunt the machine. Just like the first entry, the sequel struggles with its final chapters. The story, which builds so much momentum in its middle act, feels rushed and confusing as it reaches its climax. From a narrative design standpoint, it’s a bit disappointing to see the same pacing issues repeat themselves. A more focused third act could have easily pushed this into a perfect 10/10 territory. It seems the team prioritized the systemic complexity and world-building over a tightly woven conclusion.

Despite the narrative stumbles at the finish line, the moment-to-moment gameplay is unparalleled. The world is denser, the quests are more varied, and the sense of being part of 15th-century history is stronger than ever.

Kcd2 siege

A New Standard for Immersion

This title offers a level of immersive simulation that is hard to beat. It respects the player’s intelligence and rewards patience, even when its complex systems push back. If you loved the original, this is an essential experience. If you were put off by the previous entry’s rough edges, the added polish here might finally be enough to win you over. It’s a bold, ambitious, and deeply rewarding sequel that proves Warhorse Studios are masters of their craft, even if they still haven’t quite nailed the landing.

My Rating: 9★★★★★★★★★
Metacritic: 89
Bruno MASSA