• The trilogy Godot Edition - Part 1 - Model loading

    In this first part of the series we discuss model loading. Nothing more visual than rendering our first GTA model.

    To load a GTA model we first need to understand the original engine this game used. The original trilogy was based on the RenderWare engine (RW from now on), an engine that was very popular during the time. Many games by different developers where created on this engine, think about titles like Burnout, Tony Hawks Pro Skater 3 and Bully. It was the Unreal Engine of that era.

    Lucky for us this means a lot is known about the file formats used by RW based games. Entire tools and libraries where build to inspect the contents of RW files. One of which is called RwAnalyze, this is still one of the best tools (22 years old by now!) to get a grasp of the basic structure of RW files.

    Screenshot of RW Analyze 0.4

    As you can see in the above screenshot a dff file is simply 3D data stored in a tree like structure.

    An example

    Let’s take a closer look at a pretty basic dff file. We can use Vice City’s arrow.dff which can be found in the /models/generic/ directory. This model has only a single mesh, no textures and is pretty much as basic as it gets.

    ℹ️ You might notice that there are not that many dff files in the models directory, which might seem odd for a game with hundreds of models. This is because most models are packed into the gta3.img archive file. We’ll get to the details of that file in another part.

    The structure

    The following tree shows the structure of the dff file.

    RwClump
    ├── RwFrameList
    │   └── RwFrame
    ├── RwGeometryList
    │   └── RwGeometry
    │       ├── RwMaterialList
    │       │   └── RwMaterial
    │       ├── RwBinMeshPlg
    │       └── RwMorphPlg
    └── RwAtomic
        ├── RwParticlesPLG
        └── RwMatEffectsPlg
    

    Let’s have a look at the sections and how they relate to Godot.

    RwClump

    A container of a frame hierarchy and 3D data. We could create something similar using a Node3D with child nodes.

    RwFrameList

    List of Frames.

    RwFrame

    A frame has a name, positioning data and a parent ID. Frames are used to build up the hierarchy of the model. Frames can be used to position geometry, dummies or bones from a skeleton. In Godot this is again similar to a Node3D.

    In our case of arrow.dff this frame contains the name “arrow”.

    RwGeometryList

    List of Geometry

    RwGeometry

    The visual representation of the model. Contains the vertex, polygon and material data. The Godot equivalent of a Mesh.

    RwMaterialList

    List of materials

    RwMaterial

    Material definition, contains the texture name, colors, alpha name etc.

    RwBinMeshPlg

    Plugin that defines how the geometry is split by materials. Which vertices / polygons use which material. Similar to a Surface on a Mesh in Godot.

    RwMorphPlg

    I currently don’t support this in my parser, if we need it we’ll probably get to it at some point.

    RwAtomic

    An atomic matches geometries to a frame. Making it possible to create a hierarchy of geometry. We’ll need this info to setup the mesh / node hierarchy in Godot.

    RwMatEffectsPlg

    I currently don’t support this in my parser, if we need it we’ll probably get to it at some point.

    Godot

    If we take the above arrow.dff example and map that to Godot we can imagine this would end up something like:

    Node3D
    └── MeshInstance3D (arrow)
    

    Meshes

    The first step to create this scene is by converting all RwGeometry sections to a Godot Mesh. Godot offers multiple API’s to create meshes at runtime. In my case I ended up using ArrayMesh. By going through all material splits we can create Surfaces using the AddSurfaceFromArrays method and assign a Material to the Surface by using SurfaceSetMaterial

    Hierarchy

    Once all meshes and materials are created we have to reconstruct the hierarchy. For this we’ll use the RwFrameList and RwAtomic sections. When a frame is connected to a geometry as indicated by the RwAtomic section we can create a new MeshInstance3D and assign it the Mesh that we created from the geometry. In case no geometry is connected to the frame we’ll just create a simple Node3D node. We’ll hook those nodes up according to the parent / child information of the RwFrame.

    The result

    With some trial and error this is the result:

    Screenshot of the GTA: VC arrow model inside Godot

    I hope you enjoyed this first part of the series. In the next part we’ll take a look at loading more advanced models.

  • The trilogy Godot Edition - Intro

    As mentioned in my last post (which I apparently posted over a year ago!) I’ve gotten interested in the awesome open source game engine Godot.

    In the past year I’ve done some simple projects with Godot, but now it’s time to pick up something bigger. As you might know I’ve worked on a project called OASE in the past. This project aimed to create an Open Source implementation of the GTA Trilogy. It was able to load the map and some missions pretty decently, but it always felt I had to do everything from scratch, writing a graphics engine, an audio engine and all the other things that make up an engine. The engine became a big mess, had a lot of memory issues (in the current state it basically crashes after running for 30 seconds) and whenever I wanted to work on something I had to work my way through the spaghetti. It’s time to leave the OASE mess behind and create a new mess… in Godot.

    The goal: Get the GTA Trilogy running in Godot.

    Of-course we have multiple similar projects these days, one of which is a completely reverse engineered implementation, which is basically the real deal and nothing can beat that. This project is not meant as a perfect recreation of the trilogy, it’s meant as a learning exercise, sharing my journey towards implementing a full 3D open world game (by 2001 standards).

    The plan

    The idea is to share the steps I take to get to a playable result. A step can be anything from loading models, playing audio or scripting.

    I’ll be using code I’ve written for OASE as a basis. This means that I’ve got parsers ready for most of the file formats. I might still go more in depth in the file formats when I use them in a post.

    There are some things to keep in mind.

    1. This is not going to be a tutorial. The post will merely give you some ideas of how the GTA internals work (or at least how I interpret them) and how this can be applied in a modern engine like Godot.
    2. This won’t be a one to one implementation, the goal is to get something playable, this probably means this will end up as the “We got GTA at home” version of the trilogy.
    3. There are currently no plans to open source this project.
    4. Last but not least, this project won’t be vibe coded. I want this to be a learning experience.

    With all that said, I hope you are as excited about this as I am!

    Let the journey begin

  • 2024 in review

    The end of 2024 is approaching rapidly and that’s a good moment to take a step back and look what I’ve done in 2024.

    Last year’s ambitions

    But first lets go back to the end of last year, where I actually wrote a blog post with possible projects for 2024.

    Game using OASE

    I can be short about this one, there is no game using the OASE engine, nor is there a game using any other engine. Those game projects still live somewhere in my mind…

    Elevating OASE VC to the Next Level

    The year started great for OASE VC with support for wav and MP3 playback and even radio stations. The model loading and rendering code also got a complete overhaul, sadly this triggerred unexplainable crashes that eventually drained my OASE energy. Maybe next year will be the year of OASE?

    Wake-Up Light

    The wake up light is a project where I did make progress.

    • Arduino hardware ✅
    • Arduino software ✅
    • Mobile app (Android & iOS) ✅

    That looks like a finished project doesn’t it? Sadly the last step isn’t done yet, actually putting the hardware inside a kid friendly case. I’ve been contemplating between buying an of the shelf light and designing / 3D printing something myself, currently leaning towards the latter to make it as personal as possible.

    III Era Modding YouTube Channel

    I still think this is a great idea, now if I would just put some effort into this…

    So, what did I end up doing in 2024?

    You never know what life will bring you. One thing I did notice was the lack of energy and time to work on my side projects, who thought having a second kid would have this impact?

    Even though most of the ideas I had for 2024 did not become reality, I still got some stuff done. Lets take a look.

    Chip-8 emulator for the N64

    In the past I’ve created a Kotlin multiplatform emulator for Chip-8, for some reason I thought it was a fun idea to build a Chip-8 emulator for N64. The basics are working, rom loading, opcode interpreter and even basic key binding.

    Shadow-MSP - gta3sc support

    The Intellij plugin that I wrote to create and compile missions scripts got support for gta3sc, an awesome open source compiler that is able to compile the original mission script sources to the well known main.scm file. The plugin adds syntax highlighting, refactoring and find usages support for .sc files. As a bonus I’ve also contributed MacOS support in gta3sc.

    Game development

    Godot engine has peaked my interest this year. It seems to be a very capable engine, is open source and has support for C# besides GDScript. I’ve created a little playground project and have been following some tutorials. Nothing interesting came out of this yet, but you never know what I might end up creating.

    Exploring Kotlin multiplatform for Web

    I’ve been playing around with Kotlin / Compose multiplatform, my personal website is now build using this tech. It has some downsides, but has potential for certain usecases. I should probably write a dedicated blog post about this.

    Final thoughts

    Looking back, 2024 was a good year. Even though I did not work on the projects I planned, some projects got some nice updates and I learned some new tricks that I can use for 2025!

  • Shadow-MSP gets gta3sc support

    I already mentioned it in my previous post, but I am tired of the Chip-8 on N64 project… I got distracted once again.

    This time by an old favorite of mine; Shadow-MSP. The Intellij plugin that I build to support GTA 3D mission scripting.

    A couple of years ago the original mission script sources got leaked (thanks Grovestreet games!) which helped understand the original SCM structure. TheLink2012 build an amazing toolchain and compiler called gta3sc. This can be used to compile the original sources to the main.scm as we know it.

    There is a plugin for VSCode, but nothing for Intellij. Luckily I already had a plugin lying around for exactly this purpose, mission script support in Intellij. So I started adding support for the original GTA 3D scripting languages using gta3sc as the compiler.

    Of course, we are not there yet; the plugin is very slow, and it’s missing some key features like compiling. Features I am working on as we speak. Expect more details soon!

  • Chip-8 64 Update

    I’ve found this amazing Chip-8 database that contains a huge set of rom info; this info includes common button mappings, color mappings and supported platforms. I am planning to use this database to provide pre-build button configs for all original Chip-8 roms in the database.

    If I am being honest, I am a little bit tired of this project. Chip-8 doesn’t interest me at all, the only part I enjoy is the emulation and N64 part. Still, I’m determined to push through and wrap something up this year.