{
    "archive_path": "archive/1785872306.900695",
    "base_url": "phoboslab.org/log/2026/08/xibalba64-making-of",
    "basename": "xibalba64-making-of",
    "bookmarked_date": "2026-08-04 19:38",
    "canonical": {
        "archive_org_path": "https://web.archive.org/web/phoboslab.org/log/2026/08/xibalba64-making-of",
        "dom_path": "output.html",
        "favicon_path": "favicon.ico",
        "git_path": "git/",
        "google_favicon_path": "https://www.google.com/s2/favicons?domain=phoboslab.org",
        "headers_path": "headers.json",
        "htmltotext_path": "htmltotext.txt",
        "index_path": "index.html",
        "media_path": "media/",
        "mercury_path": "mercury/content.html",
        "pdf_path": "output.pdf",
        "readability_path": "readability/content.html",
        "screenshot_path": "screenshot.png",
        "singlefile_path": "singlefile.html",
        "warc_path": "warc/",
        "wget_path": "phoboslab.org/log/2026/08/xibalba64-making-of.html"
    },
    "domain": "phoboslab.org",
    "extension": "",
    "hash": "KN5HRWJ9Z928JM7D62YM",
    "history": {
        "archive_org": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--head",
                    "--max-time",
                    "60",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.3 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.10.1 (x86_64-pc-linux-gnu)",
                    "https://web.archive.org/save/https://phoboslab.org/log/2026/08/xibalba64-making-of"
                ],
                "cmd_version": "curl 8.10.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-08-04T19:39:56.148623+00:00",
                "index_texts": null,
                "output": "https://web.archive.org/web/20260804193928/https://phoboslab.org/log/2026/08/xibalba64-making-of",
                "pwd": "/data/archive/1785872306.900695",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-04T19:39:13.517077+00:00",
                "status": "succeeded"
            }
        ],
        "dom": [
            {
                "cmd": [
                    "/usr/bin/chromium-browser",
                    "--headless=new",
                    "--no-sandbox",
                    "--no-zygote",
                    "--disable-dev-shm-usage",
                    "--disable-software-rasterizer",
                    "--run-all-compositor-stages-before-draw",
                    "--hide-scrollbars",
                    "--window-size=1440,2000",
                    "--autoplay-policy=no-user-gesture-required",
                    "--no-first-run",
                    "--use-fake-ui-for-media-stream",
                    "--use-fake-device-for-media-stream",
                    "--disable-sync",
                    "--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.3 (+https://github.com/ArchiveBox/ArchiveBox/)",
                    "--window-size=1440,2000",
                    "--dump-dom",
                    "https://phoboslab.org/log/2026/08/xibalba64-making-of"
                ],
                "cmd_version": "Chromium 131.0.6778.33",
                "end_ts": "2026-08-04T19:38:58.064628+00:00",
                "index_texts": null,
                "output": "output.html",
                "pwd": "/data/archive/1785872306.900695",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-04T19:38:52.967477+00:00",
                "status": "succeeded"
            }
        ],
        "favicon": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "60",
                    "--output",
                    "favicon.ico",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.3 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.10.1 (x86_64-pc-linux-gnu)",
                    "https://www.google.com/s2/favicons?domain=phoboslab.org"
                ],
                "cmd_version": "curl 8.10.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-08-04T19:38:27.382331+00:00",
                "index_texts": null,
                "output": "favicon.ico",
                "pwd": "/data/archive/1785872306.900695",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-04T19:38:26.975655+00:00",
                "status": "succeeded"
            }
        ],
        "git": [],
        "headers": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--head",
                    "--max-time",
                    "60",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.3 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.10.1 (x86_64-pc-linux-gnu)",
                    "https://phoboslab.org/log/2026/08/xibalba64-making-of"
                ],
                "cmd_version": "curl 8.10.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-08-04T19:38:28.094019+00:00",
                "index_texts": null,
                "output": "headers.json",
                "pwd": "/data/archive/1785872306.900695",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-04T19:38:27.390973+00:00",
                "status": "succeeded"
            }
        ],
        "htmltotext": [],
        "media": [
            {
                "cmd": [
                    "yt-dlp",
                    "--write-description",
                    "--write-info-json",
                    "--write-annotations",
                    "--write-thumbnail",
                    "--no-call-home",
                    "--write-sub",
                    "--write-auto-subs",
                    "--convert-subs=srt",
                    "--yes-playlist",
                    "--continue",
                    "--no-abort-on-error",
                    "--ignore-errors",
                    "--geo-bypass",
                    "--add-metadata",
                    "--format=(bv*+ba/b)[filesize<=750m][filesize_approx<=?750m]/(bv*+ba/b)",
                    "https://phoboslab.org/log/2026/08/xibalba64-making-of"
                ],
                "cmd_version": "2024.12.13",
                "end_ts": "2026-08-04T19:39:13.419596+00:00",
                "index_texts": [],
                "output": "media",
                "pwd": "/data/archive/1785872306.900695",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-04T19:39:07.160606+00:00",
                "status": "succeeded"
            }
        ],
        "mercury": [
            {
                "cmd": [
                    "/app/node_modules/@postlight/parser/cli.js",
                    "https://phoboslab.org/log/2026/08/xibalba64-making-of"
                ],
                "cmd_version": "1.0.0",
                "end_ts": "2026-08-04T19:39:07.148225+00:00",
                "index_texts": null,
                "output": "mercury",
                "pwd": "/data/archive/1785872306.900695",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-04T19:39:05.018529+00:00",
                "status": "succeeded"
            }
        ],
        "pdf": [
            {
                "cmd": [
                    "/usr/bin/chromium-browser",
                    "--headless=new",
                    "--no-sandbox",
                    "--no-zygote",
                    "--disable-dev-shm-usage",
                    "--disable-software-rasterizer",
                    "--run-all-compositor-stages-before-draw",
                    "--hide-scrollbars",
                    "--window-size=1440,2000",
                    "--autoplay-policy=no-user-gesture-required",
                    "--no-first-run",
                    "--use-fake-ui-for-media-stream",
                    "--use-fake-device-for-media-stream",
                    "--disable-sync",
                    "--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.3 (+https://github.com/ArchiveBox/ArchiveBox/)",
                    "--window-size=1440,2000",
                    "--print-to-pdf",
                    "https://phoboslab.org/log/2026/08/xibalba64-making-of"
                ],
                "cmd_version": "Chromium 131.0.6778.33",
                "end_ts": "2026-08-04T19:38:47.122409+00:00",
                "index_texts": null,
                "output": "output.pdf",
                "pwd": "/data/archive/1785872306.900695",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-04T19:38:39.179699+00:00",
                "status": "succeeded"
            }
        ],
        "readability": [
            {
                "cmd": [
                    "/app/node_modules/readability-extractor/readability-extractor",
                    "/tmp/tmp9nfg0jpu",
                    "https://phoboslab.org/log/2026/08/xibalba64-making-of"
                ],
                "cmd_version": "0.0.11",
                "end_ts": "2026-08-04T19:39:04.999687+00:00",
                "index_texts": [
                    "\u2014 Tuesday, August 4th 2026\n\t\n\t\n\n\tTwo years ago, I was Porting my JavaScript Game Engine to C for No Reason.\nI have since found a reason: making a new N64 game!\n\nThe result is Xibalba 64 \u2013 a Wolfenstein\n3D-like FPS. Modretro agreed to publish the game as a physical launch title for their M64\n(a modern N64 clone), complete with cartridge, packaging and manual!\n\nXibalba 64 on Modretro.com\nThis, to my knowledge, is only the second physical release of any new N64 game since\nthe end of the console's original commercial life. The infamous Xeno Crisis\nby Bitmap Bureau \u2013\noriginally a new game for the Sega Mega Drive and subsequently released on many,\nmany more consoles \u2013 came to the N64 in 2023. No other new games have been\npublished for the N64 since Tony Hawk's Pro Skater 3 in 2002.\nThe Engine\nImpact was a JavaScript game engine I developed back in 2010.\nIt was tailored for 2D action games, handling tile sheets, background maps, sprites\nand collision detection. It's very simple, but still a sound foundation for\nwhatever you want to throw at it.\nTwo years ago I rewrote Impact in C. Why? I don't know. It was fun.\nThis C port, high_impact, has a notion of a\n\u201cplatform backend\u201d. The platform handles the low-level plumbing \u2013 opening a\nwindow, creating a drawing surface, reading input, etc. Out of the box, high_impact\ncomes with two platform backends (SDL2 and Sokol), and you can compile your game\nfor either one. This already enables high_impact games to run on many different\ndevices.\nThe rendering backend in high_impact is also modular. You can compile your game\nwith a software renderer, OpenGL or Metal (for iOS/macOS). Support for new\nplatform backends or rendering backends can be added without modifying\nany other part of the engine.\nA perfect starting point for an N64 game.\nN64 Hardware and Platform Library\nThe N64 is a quirky beast. In addition to the 93 MHz MIPS CPU (big-endian!), it has two\ncoprocessors for handling graphics, sound and more:\n\n\u201cReality Display Processor\u201d (RDP) \u2013 a fixed-function graphics processor\n\u201cReality Signal Processor\u201d (RSP) \u2013 a programmable vector processor\n\nBoth of these live in the same physical package, commonly called the \u201cReality Coprocessor\u201d\n(RCP).\n\nImage from the N64Brew Wiki\nFor the first few years of the N64's life, Nintendo closely guarded access to the\nRSP. It was exclusively used by Nintendo's officially sanctioned platform library, \u201clibultra\u201d.\nOnly later did Nintendo allow game studios to write custom \u201cmicrocode\u201d (actually just\nMIPS assembly) for the RSP.\nKeeping the hardware happy is no simple feat, and the instructions for the RDP are\nquirky and complicated. Programming your game on bare metal is pretty much\nout of the question. In recent years, Nintendo's official \u201clibultra\u201d has made its\nway onto the internet, but using it would risk a copyright lawsuit.\nLuckily, the N64 homebrew scene has picked up a lot of steam in the last few\nyears and we have a very capable alternative now: Libdragon.\nLibdragon is basically SDL for the N64. It provides facilities for drawing\nsprites and triangles, sound output, controller input and much more.\nIt took me only a few evenings to build a new platform backend for high_impact on\ntop of libdragon. I tested this with Biolab Disaster.\nThe game code remained unmodified; performance was meh, but I was using the\nN64 hardware in the most naive way possible.\n\n\nDev Environment\nLibdragon provides the compilers and everything else that's necessary to build a ROM\nfile for the N64. The installation instructions\nand all other documentation are comprehensive and well-written. The library comes\nwith many examples to get you started.\nIn general, it was a pleasure to work with Libdragon. Just a heads up: you\nprobably want to use the preview branch as the \u201cstable\u201d trunk branch has\nhopelessly fallen behind.\nFor testing, a good emulator is invaluable. For the longest time, N64 emulation\nwas extremely inaccurate. Lackluster emulation of the RSP and RDP coprocessors,\nin particular, was the cause of most problems.\nMost emulators just emulated Nintendo's platform library, libultra. They emulated\nthe intent to draw a triangle, not what the hardware would actually do. While\ninaccurate, this made emulation possible at all in the early\ndays. Famously, UltraHLE\n(\u201cUltra High Level Emulator\u201d) was released well within the lifetime of the N64\nand caused a lot of headaches and subsequent lawsuits.\nThese days the N64 core in Ares is much closer to the\nactual hardware \u2013 the RDP and RSP are fully emulated, including accurate timing\nfor the RSP. The infamous slow memory bandwidth of the N64, however, can still only\nbe tested on real hardware (which recently caused me some disappointment).\nSo you need a real N64 and a cartridge that lets you play arbitrary .z64 ROM files.\nThe open-source SummerCart64\nis excellent and available from many different manufacturers. Be aware:\nsome manufacturers (especially on AliExpress) cheap out on the components of\nthe board.\nSummerCart64 has the usual SD card slot to store your ROMs, but what makes it\ngreat for development is its USB-C port: you can directly connect it to your PC\nand upload a ROM as part of your build process using sc64deployer.\nI ended up with the N64 next to my PC, connected via USB, and used a cheap $10\nUSB analog capture card to display its video output in a window on my desktop.\nOn Linux, it took some fiddling with mpv to get low-latency output; here's the\nscript I used.\nWith this setup, iterating on real hardware was just a matter of compiling and pushing the N64\nreset button.\nThe Game\nI originally made Xibalba\nas a demo for my JavaScript game engine in 2014. WebGL was still the hot new\nthing back then; a 3D game in a browser was quite a novelty. The game was very\nshort, featuring only a handful of levels, weapons and enemy types.\nIn contrast, I wanted Xibalba 64 to be a real game, not just a demo. So I not\nonly needed to port the game to C and high_impact, but also expand on it with\nmore levels, more enemy types and more weapons.\nhigh_impact is a 2D game engine, but Xibalba 64 is clearly 3D. Well, not quite.\nSince the game has no elevation, it can be mostly treated as 2D. You could\nconceptually play Xibalba 64 from a 2D top-down perspective. Of course, that\nwouldn't be as exciting, but all the physics, movement and shooting would work the\nsame way. In this regard, the game is very similar to Wolfenstein 3D.\nMany of high_impact's physics functions expect a vec2_t argument with .x\nand .y components. But for drawing, I absolutely needed a 3D position, so I\ncame up with this definition for a vec3_t type and changed the entity_t type:\ntypedef struct {\n    float x, y;\n} vec2_t;\n\ntypedef union {\n    vec2_t xy;\n    struct {\n        float x, y, z;\n    };\n} vec3_t;\n\ntypedef struct {\n    // ...\n    vec3_t pos;\n    vec3_t vel;\n    // ...\n} entity_t;\nNow, whenever I need to call a function that accepts a vec2_t, I can\n\u201cconvert\u201d from vec3_t for free:\ntrace_t res = trace(collision_map, entity->pos.xy, entity->vel.xy);\nSince the inner vec3_t struct is \u201canonymous\u201d, I can still access all values\ndirectly; i.e., entity->pos.z works just fine.\nThe initial port of the existing levels and enemy types went quite smoothly and\nwas finished in about two weeks. I then spent another few months on extending\nthe game and optimizing the renderer.\nMost of Libdragon's functions fit naturally into a new platform and rendering\nbackend, though I had to change some other parts of high_impact to bypass its\nmixer (Libdragon has its own, accelerated by the RSP) and image loader.\nThroughout the whole process, I retained the ability to build the\ngame with the SDL2 or Sokol backends. This was great for playtesting game logic\nand enemy behavior. To make levels, I also implemented a simple hot-reload\nmechanism triggered whenever a level file changed.\n\n\nThe level editor, bundled with high_impact, is a single self-contained HTML file.\nI ended up extending it quite a bit to add better support for lightmaps,\ndisplay actual sprites for entities (instead of just boxes), add descriptions\nfor entity settings and provide other small features. The single source of truth is still\nthe C source code \u2013 the level editor reads it and extracts the entity types and\nsupported settings automatically.\n\nSince the level editor still works with JSON files, I built a small map compiler\nthat reads the JSON and emits binary data. While loading JSON on the N64 is\nof course possible, it added some unnecessary ~100 ms of load time. So during the\nbuild process, each JSON level file is converted into a struct that essentially\nlooks like this:\ntypedef struct {\n    uint16_t magic;\n    uint16_t entities_len;\n    uint16_t map_width;\n    uint16_t map_height;\n\n    struct {\n        uint16_t type_id;\n        uint16_t x;\n        uint16_t y;\n        uint16_t settings_len;\n        struct {\n            uint16_t setting_type; // such as \"name\", \"target\", \"size\", ...\n            union {\n                float16_t float_value;\n                int16_t int_value;\n                struct {\n                    int16_t string_len;\n                    char string_value;\n                };\n            } value;\n        } settings[settings_len];\n    } entities[entities_len];\n\n    uint16_t collision_map[map_width * map_height];\n    uint16_t floor_map[map_width * map_height];\n    uint16_t wall_map[map_width * map_height];\n    uint16_t ceiling_map[map_width * map_height];\n    uint16_t light_map[map_width * map_height];\n} level_t;\nThe level compiler writes those values in big-endian format for the N64 and\nlittle-endian format for x86 (SDL2, Sokol, WASM), so we can easily read everything on\nall platforms without byte swapping.\nRendering\nLibdragon itself has a function for drawing triangles: rdpq_triangle() inserts a\nsingle triangle draw call into the RDP queue. While this works, what you really\nwant to do is submit your draw calls to the RSP, have some custom microcode to\nperform transformations, lighting, depth calculations, etc., and then let the RSP\ninstruct the RDP to ultimately draw the triangle.\nThe intricacies of the RDP and RSP were still new to me, but luckily another\noutstanding open-source library, Tiny3D,\nhandles all this and more with a simple-to-use API. Getting something on the\nscreen was the easy part; making it performant was a whole other endeavor.\nThe N64 infamously only has 4 KB of texture memory. The largest textures you can\nupload are just a meager 64\u00d764 pixels. Even worse, the memory latency for a\ntexture upload is atrocious. One solution, used by Mario 64 and many other\ntitles, is to render untextured polygons whenever you can.\nThis wouldn't really fly with the style of my game, so instead I had to be\nreally careful with the draw order of level tiles to minimize texture uploads.\nOn top of that, Tiny3D can load and submit up to 17 quads at once, and it would\nbe wasteful not to use that. So I ended up collecting batches of triangles with\nthe same texture in 64-bit draw calls:\ntypedef union render_call {\n    uint64_t packed;\n    uint32_t hashable;\n    uint64_t ident : 46;\n    struct {\n        uint64_t translucent : 1;\n        uint64_t texture_index : 9;\n        uint64_t x : 10;\n        uint64_t y : 10;\n        uint64_t w : 8;\n        uint64_t h : 8;\n        uint64_t vbi : 14;\n        uint64_t len : 4;\n    };\n} render_call_t;\nHere vbi is the accompanying vertex buffer index, and len is the number of quads\nin this call. Since every call is just 64 bits wide, we can efficiently sort them\nat the end of the frame and issue them to Tiny3D.\nBut before I could do all this, I had to first figure out which parts of a level\nare actually visible. The original JavaScript Xibalba used a portal system,\ndividing each level into sectors and precomputing which sectors were visible from\nthe current one. This worked fine, but produced a bit more overdraw\nthan I would have liked.\nSo I opted for another approach: raycasting. Yes, the game is just casting 320\nrays into the scene, covering the whole field of view. Each ray marks traversed\ntiles in a bitmap for submission to the renderer.\nLater, I optimized the raycasting a bit more by recursively dividing the 320-pixel\nfield of view until two rays hit the same tile. In this process, I also check whether\nany of the traversed tiles are missing a ceiling \u2013 if so, we have to draw\na skybox.\nFun fact: the skybox in Xibalba 64 is just a single 32\u00d732-pixel texture that is\nbeautifully smeared across the horizon.\n\nAs another optimization, I arranged each tile sheet that wouldn't fit in a single\nupload into a single column and tried to use just 4-bit indexed colors wherever\npossible. Using fewer colors allowed more pixels to fit into texture memory,\nand the column layout ensured that each tile could be uploaded as a single,\ncontinuous chunk of memory.\n\nWith all of this, the game runs at a stable 60 FPS. Something not many other N64\ngames can claim!\nThe four-player split-screen mode doesn't quite hit the 60 FPS mark at all times, but\nstill remains fluid. In contrast, GoldenEye 007 infamously often dropped into\nsingle-digit frame rates here.\n\nSound & Music\nAs with all my other games, my good friend Andreas L\u00f6sch produced some\noutstanding music. You can listen to the whole\nXibalba 64 Soundtrack on Bandcamp.\nThe game itself also has a built-in music player that you can unlock in the\nsingle-player campaign.\n\nCartridge space is tight, and even compressed audio is typically either quite large\nor too expensive to decode.\nIn a heroic effort, Giovanni Bajo \u2013 one of the maintainers of Libdragon and an\nabsolute wizard when it comes to anything N64 \u2013 implemented an RSP-accelerated Opus decoder.\nFor context: Opus is an audio codec first published in 2012. That's 16 years(!)\nafter the N64. It's a marvel that it works at all, but sadly it's still a bit too\ncomputationally expensive to be used during gameplay.\n(Aside: Giovanni Bajo went on to implement a real-time H.264 decoder for the N64, too.)\nThe better option for now is a simple 4-bit VADPCM format that Libdragon\ntransparently decodes on the RSP during playback. The compression ratio, of course,\nisn't great, but it's way better than uncompressed WAV. About 31 MB of the 32 MB\nROM is used by sound and music.\nAfter the release of Xibalba 64, I started to implement another audio\ncompression format that would better address the space/quality/complexity trade-off. More on\nthat in the next blog post!\nPublishing & Sales\nModretro previously made a Game Boy Color clone \u2013 the Chromatic \u2013\ncompatible with all existing Game Boy and Game Boy Color games, and they were quite\neager to publish many new games by hobbyist developers, too.\nWhen they announced the M64, I thought this would be a great chance to get on board.\nAs soon as I had a working prototype ready and was confident that I would be\nable to build the whole game (and make it good), I wrote an email to the\ngeneric Modretro customer service address and, to my surprise, heard back from the head\nof publishing within a day.\n\nBureaucracy was minimal and the contract was straightforward. I requested some\nchanges that would allow me to release the game engine as open source later on, which\nModretro was happy to accommodate.\nOf course, as it goes with these projects, there were some delays and I only\nreceived a pre-production M64 late in the development process. But it didn't\nmatter \u2013 the M64 worked as advertised; no changes to the game for the M64\nwere necessary.\nModretro also offered help with the box art, but another friend of mine was\neager to do this instead. He later told me that, back in the '90s, he was\nresponsible for the packaging of many titles published by Sierra in Germany,\nincluding Half-Life. So it's no surprise that the Xibalba 64 box art turned out\ngreat!\nFor the manual, I supplied text and illustrations to Modretro, and they laid it\nout for print. Smooth sailing. You can have a look at the PDF\nmanual on the Xibalba 64 store page.\nI'm not able to talk about sales numbers or my contract with Modretro in detail,\nand the game was released only a few days ago, but so far it's looking\nquite good. Of course, making N64 games will probably not let you quit your job,\nbut it looks like it will pay for a few nice holidays.\nHuge thanks to Giovanni Bajo of Libdragon, Max Beb\u00f6k\nof Tiny3D, the entire\nN64brew Discord community and, of course, the Modretro\nteam for pulling this off!\nHere's the final trailer for the game.\n\nResources\nIf you're looking to get started with N64 development, these resources may help:\n\nn64.dev \u2013 a collection of everything related to N64 development\nN64brew Discord \u2013 a very friendly and helpful community; many of the library developers are here\nLibdragon \u2013 the system library for the N64\nTiny3D \u2013 a simple and fast 3D graphics library\nPyrite64 \u2013 a visual editor and runtime for creating 3D games"
                ],
                "output": "readability",
                "pwd": "/data/archive/1785872306.900695",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-04T19:39:04.024516+00:00",
                "status": "succeeded"
            }
        ],
        "screenshot": [
            {
                "cmd": [
                    "/usr/bin/chromium-browser",
                    "--headless=new",
                    "--no-sandbox",
                    "--no-zygote",
                    "--disable-dev-shm-usage",
                    "--disable-software-rasterizer",
                    "--run-all-compositor-stages-before-draw",
                    "--hide-scrollbars",
                    "--window-size=1440,2000",
                    "--autoplay-policy=no-user-gesture-required",
                    "--no-first-run",
                    "--use-fake-ui-for-media-stream",
                    "--use-fake-device-for-media-stream",
                    "--disable-sync",
                    "--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.3 (+https://github.com/ArchiveBox/ArchiveBox/)",
                    "--window-size=1440,2000",
                    "--screenshot",
                    "https://phoboslab.org/log/2026/08/xibalba64-making-of"
                ],
                "cmd_version": "Chromium 131.0.6778.33",
                "end_ts": "2026-08-04T19:38:52.963179+00:00",
                "index_texts": null,
                "output": "screenshot.png",
                "pwd": "/data/archive/1785872306.900695",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-04T19:38:47.126885+00:00",
                "status": "succeeded"
            }
        ],
        "singlefile": [
            {
                "cmd": [
                    "/app/node_modules/single-file-cli/single-file",
                    "--browser-executable-path=chromium-browser",
                    "--browser-args=[\"--headless=new\", \"--no-sandbox\", \"--no-zygote\", \"--disable-dev-shm-usage\", \"--disable-software-rasterizer\", \"--run-all-compositor-stages-before-draw\", \"--hide-scrollbars\", \"--window-size=1440,2000\", \"--autoplay-policy=no-user-gesture-required\", \"--no-first-run\", \"--use-fake-ui-for-media-stream\", \"--use-fake-device-for-media-stream\", \"--disable-sync\", \"--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.3 (+https://github.com/ArchiveBox/ArchiveBox/)\", \"--window-size=1440,2000\"]",
                    "https://phoboslab.org/log/2026/08/xibalba64-making-of",
                    "singlefile.html"
                ],
                "cmd_version": "1.1.54",
                "end_ts": "2026-08-04T19:38:39.175025+00:00",
                "index_texts": null,
                "output": "singlefile.html",
                "pwd": "/data/archive/1785872306.900695",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-04T19:38:28.102250+00:00",
                "status": "succeeded"
            }
        ],
        "title": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "60",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.3 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.10.1 (x86_64-pc-linux-gnu)",
                    "https://phoboslab.org/log/2026/08/xibalba64-making-of"
                ],
                "cmd_version": "curl 8.10.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-08-04T19:39:04.021562+00:00",
                "index_texts": null,
                "output": "PhobosLab",
                "pwd": "/data/archive/1785872306.900695",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-04T19:39:04.011717+00:00",
                "status": "succeeded"
            }
        ],
        "wget": [
            {
                "cmd": [
                    "wget",
                    "--no-verbose",
                    "--adjust-extension",
                    "--convert-links",
                    "--force-directories",
                    "--backup-converted",
                    "--span-hosts",
                    "--no-parent",
                    "-e",
                    "robots=off",
                    "--timeout=60",
                    "--restrict-file-names=windows",
                    "--warc-file=/data/archive/1785872306.900695/warc/1785872338",
                    "--page-requisites",
                    "--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.3 (+https://github.com/ArchiveBox/ArchiveBox/) wget/GNU Wget 1.21.3",
                    "--compression=auto",
                    "https://phoboslab.org/log/2026/08/xibalba64-making-of"
                ],
                "cmd_version": "GNU Wget 1.21.3",
                "end_ts": "2026-08-04T19:39:03.999066+00:00",
                "index_texts": null,
                "output": "phoboslab.org/log/2026/08/xibalba64-making-of.html",
                "pwd": "/data/archive/1785872306.900695",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-04T19:38:58.070906+00:00",
                "status": "succeeded"
            }
        ]
    },
    "icons": null,
    "is_archived": true,
    "is_static": false,
    "latest": {
        "archive_org": "https://web.archive.org/web/20260804193928/https://phoboslab.org/log/2026/08/xibalba64-making-of",
        "dom": "output.html",
        "favicon": "favicon.ico",
        "git": null,
        "media": "media",
        "pdf": "output.pdf",
        "screenshot": "screenshot.png",
        "singlefile": "singlefile.html",
        "title": "PhobosLab",
        "warc": null,
        "wget": "phoboslab.org/log/2026/08/xibalba64-making-of.html"
    },
    "link_dir": "/data/archive/1785872306.900695",
    "newest_archive_date": "2026-08-04T19:39:13.517077+00:00",
    "num_failures": 0,
    "num_outputs": 12,
    "oldest_archive_date": "2026-08-04T19:38:26.975655+00:00",
    "path": "/log/2026/08/xibalba64-making-of",
    "schema": "Link",
    "scheme": "https",
    "snapshot_id": "df198483-c5e0-43eb-8bdd-963b561b2d70",
    "sources": [
        "/data/sources/1785872306-import.txt"
    ],
    "tags": null,
    "tags_str": "",
    "timestamp": "1785872306.900695",
    "title": "PhobosLab",
    "updated": "2026-08-04T19:38:26.974202+00:00",
    "updated_date": "2026-08-04 19:38",
    "url": "https://phoboslab.org/log/2026/08/xibalba64-making-of"
}