{"id":50299642,"url":"https://github.com/statico/gbhack","last_synced_at":"2026-05-28T11:32:23.484Z","repository":{"id":351916307,"uuid":"1212980500","full_name":"statico/gbhack","owner":"statico","description":"🎮 A NetHack-inspired roguelike dungeon crawler for the Game Boy Color, written in C with GBDK and generated with Claude Code","archived":false,"fork":false,"pushed_at":"2026-04-17T04:13:50.000Z","size":796,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-17T04:21:04.663Z","etag":null,"topics":["claude-code","gameboy","gameboy-color","gbc","gbdk","homebrew","nethack","retro-game","roguelike"],"latest_commit_sha":null,"homepage":"https://gbhack.statico.io/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/statico.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-16T23:36:26.000Z","updated_at":"2026-04-17T04:13:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/statico/gbhack","commit_stats":null,"previous_names":["statico/gbhack"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/statico/gbhack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/statico%2Fgbhack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/statico%2Fgbhack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/statico%2Fgbhack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/statico%2Fgbhack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/statico","download_url":"https://codeload.github.com/statico/gbhack/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/statico%2Fgbhack/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33607334,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-28T02:00:06.440Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude-code","gameboy","gameboy-color","gbc","gbdk","homebrew","nethack","retro-game","roguelike"],"created_at":"2026-05-28T11:32:22.711Z","updated_at":"2026-05-28T11:32:23.471Z","avatar_url":"https://github.com/statico.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GBHack\n\nA roguelike dungeon crawler for the Game Boy Color, inspired by NetHack. Written\nin C using GBDK (Game Boy Development Kit) and generated with\n[Claude Code](https://claude.ai/code).\n\n\u003cp\u003e\n  \u003cimg src=\"screenshots/gbhack-title.png\" alt=\"Title screen\" width=\"320\"\u003e\n  \u003cimg src=\"screenshots/gbhack-screenshot.png\" alt=\"Gameplay\" width=\"320\"\u003e\n\u003c/p\u003e\n\n## Overview\n\nGBHack adapts the core loop of NetHack to the constraints of the Game Boy Color:\nprocedurally generated dungeons, permadeath, unidentified items, hunger\nmechanics, pets, shops, and the Amulet of Yendor as the ultimate goal. The game\nruns on original GBC hardware as well as any accurate emulator.\n\n## Building\n\n### Prerequisites\n\nDownload the [GBDK](https://github.com/gbdk-2020/gbdk-2020) toolchain and\nextract it so that a `gbdk/` directory sits alongside the `gbhack/` project\ndirectory (i.e. `../gbdk/` relative to this repo root). The Makefile expects to\nfind `bin/lcc` and `bin/png2asset` inside that directory.\n\nTested with GBDK 4.3.0 on macOS (ARM64). Other platforms supported by GBDK\nshould work with no changes.\n\n### Build\n\n```\nmake\n```\n\nThis produces `build/gbhack.gbc`, a 256 KB ROM suitable for any Game Boy Color\nemulator or flash cart. The ROM uses MBC5 with battery-backed SRAM (32 KB across\n4 banks).\n\n### Run\n\n```\nmake run\n```\n\nOpens the ROM in [SameBoy](https://sameboy.github.io/) on macOS. Substitute\nyour preferred emulator if needed.\n\n### Clean\n\n```\nmake clean\n```\n\n## Gameplay\n\nYou descend through 15 procedurally generated dungeon levels. Each level\ncontains rooms connected by corridors, with doors, traps, fountains, altars, and\nshops scattered throughout. Your goal is to reach the bottom, retrieve the Amulet\nof Yendor, and escape back to the surface.\n\n### Controls\n\n| Button | Action |\n|--------|--------|\n| D-pad | Move (8 directions with diagonals via B+D-pad) |\n| A | Action menu (eat, quaff, read, zap, pick up, drop, wait, save) |\n| B | Context action (pick up item on ground, or rest) |\n| START | Character sheet |\n| SELECT | System menu (sound toggle, help, save and quit) |\n\n### Features\n\n- 15 dungeon levels with increasing difficulty\n- 8 monster types with distinct AI behaviors (aggressive, passive, erratic, wandering, fleeing)\n- Monster special abilities: poison, paralysis, teleportation, theft, drain, petrification\n- Items across 9 categories: weapons, armor, potions, scrolls, wands, food, gold, tools, amulets\n- Unidentified item appearances that shuffle each game\n- BUC (blessed/uncursed/cursed) item status\n- Pet companion (cat or dog) with loyalty and feral mechanics\n- Shopkeepers who track debt and turn hostile if you steal\n- Hunger system with six states from satiated to starved\n- Permadeath with bones files (encounter your previous character's remains)\n- Battery-backed save with auto-save every 50 turns\n- High score tracking across runs\n- Six music tracks and 13 sound effects\n\n## Architecture\n\n### Memory Layout\n\nThe Game Boy Color has 32 KB of address space with bank switching. GBHack uses\n16 ROM banks (256 KB total) and 4 SRAM banks (32 KB) via the MBC5 mapper:\n\n| Bank | Contents |\n|------|----------|\n| ROM 0 | Main loop, input, RNG, sound driver, player, UI |\n| ROM 2 | Renderer, tileset data |\n| ROM 3 | Dungeon generator, field of view |\n| ROM 4 | Monster AI, pet system |\n| ROM 5 | Inventory, shop |\n| ROM 6 | Item logic, save/load |\n| ROM 7 | Title screen background image |\n| ROM 8 | Music data (title, dungeon, death, victory) |\n| ROM 9 | Music data (boss theme) |\n| SRAM 0 | Save data (dungeon map, player state, entity state) |\n\nBank assignments are managed in the Makefile via SDCC's `-Wf-bo` flag. Functions\nin banked code are declared with the `BANKED` keyword, which generates far-call\ntrampolines automatically.\n\n### Source Organization\n\n```\nsrc/\n  main.c          Game state machine, intro/title/game over screens\n  common.h        Shared types, constants, macros (Room, Monster, Item, Player)\n  dungeon.c/h     BSP-based room generation, corridor carving, door placement\n  render.c/h      Viewport camera, tile rendering, palette management, VFX\n  fov.c/h         Shadowcasting field of view (1200-bit visibility bitmap)\n  player.c/h      Stats, movement, combat, hunger, leveling\n  monsters.c/h    Spawn tables, AI dispatch, melee combat, special abilities\n  monsters_data.c ROM-resident monster type definitions\n  items.c/h       Item type system, randomized appearances, floor item tracking\n  items_data.c    ROM-resident item type definitions\n  inventory.c/h   Inventory management, equip/use/drop logic\n  shop.c/h        Shop room detection, pricing, debt tracking, theft\n  pet.c/h         Pet companion AI, loyalty, feeding, feral transition\n  save.c/h        SRAM save/load with magic-number validation, bones files\n  save_data.c     SRAM-resident save buffer (pinned to SRAM bank 0)\n  ui.c/h          Text rendering, menus, message log, prompts\n  input.c/h       Joypad polling with press/hold detection\n  rng.c/h         16-bit xorshift PRNG seeded from hardware divider\n  sound.c/h       hUGEDriver music playback, CBT-FX sound effects\n  music/          Compiled music data (hUGE format tracker output)\nres/\n  tiles.c/h       Gameplay tileset (terrain, entities, UI glyphs)\n  title_bg.c/h    Title screen background image (GBC format with palettes)\n  title_bg.png    Source PNG for the title screen\n  tile_quantize.py   Color quantization tool for GBC tile constraints\n  kenney_to_gb.py    Converter for Kenney sprite sheets to GB 2bpp format\nlib/\n  hUGEDriver.h/lib   Music playback driver for hUGE tracker format\n  cbtfx.c/h          CBT-FX sound effect engine\n```\n\n### Technical Decisions\n\n**Language**: C via SDCC (Small Device C Compiler) through GBDK. The SM83 CPU\nin the Game Boy is an 8-bit processor with a 16-bit address bus and no hardware\nmultiply or divide. All game logic uses fixed-point integer arithmetic with\nuint8_t and uint16_t types.\n\n**Dungeon generation**: Rooms are placed with random positions and sizes (up to\n8 per level), then connected with L-shaped corridors. Special room types (shops,\naltar rooms) are assigned probabilistically based on dungeon depth. The generator\nruns in ROM bank 3 alongside FOV to keep bank 0 small enough for the core loop.\n\n**Field of view**: A bitpacked visibility array (150 bytes for 40x30 map)\ntracks which cells the player can currently see. Shadowcasting runs each time\nthe player moves, marking cells as visible or not. Previously seen cells are\nrendered dimmed; unseen cells are black.\n\n**Rendering**: The GBC background layer displays a 20x15 viewport into the\n40x30 map. The camera follows the player with clamping at map edges. Tiles are\nrendered using VRAM bank 0 for tile data and bank 1 for attribute maps\n(palette assignment, flip flags). The status bar uses the GBC window layer. A\nfull redraw writes 300 tiles; incremental updates minimize VRAM writes per\nframe.\n\n**Sound**: Music uses [hUGEDriver](https://github.com/SuperDisk/hUGEDriver),\na tracker-based playback engine that runs from the VBlank interrupt handler.\nSound effects use [CBT-FX](https://github.com/datmobiledev/cbtfx), which\ntemporarily takes over audio channels for short one-shot effects. The two\nsystems coexist by restoring music channel state after each SFX completes.\n\n**Save system**: Game state is serialized to battery-backed SRAM with a magic\nnumber for validation. The dungeon map (1200 bytes), player struct, monster\narray, floor items, and inventory are packed across SRAM banks. Bones files\npreserve a dead character's dungeon level and items so future runs can encounter\nthem. Auto-save runs every 50 turns; the save is deleted on death (permadeath).\n\n**Item identification**: Following NetHack tradition, potions, scrolls, and\nwands have randomized appearance names that shuffle each new game. Players must\nuse items or find scrolls of identify to learn what they do. The BUC\n(blessed/uncursed/cursed) system adds another layer of uncertainty.\n\n**RNG**: A 16-bit xorshift generator seeded from the Game Boy's hardware\ndivider register. Additional entropy is mixed in after the player presses START\non the title screen, using the timing of human input to decorrelate runs.\n\n### Art Direction\n\nThe tileset draws from [Kenney's](https://kenney.nl/) micro-roguelike and 1-bit\npixel art packs, converted to Game Boy Color's 2bpp (4 colors per tile) format\nusing custom Python tooling. Each 8x8 tile uses two bitplanes to encode four\nshades, mapped to GBC palettes with up to 8 palettes of 4 colors each on\nscreen simultaneously.\n\nThe visual style aims for readability on the GBC's 160x144 display. Terrain\nuses muted earth tones, monsters and items use distinct palette assignments for\nquick identification (hostile monsters in reds, consumable items in greens,\nequipment in blues), and the UI palette reserves high-contrast white-on-dark for\ntext.\n\nThe title screen background was created as a full-color image, then processed\nthrough a custom tile-aware color quantization pipeline (`tile_quantize.py`)\nthat enforces the GBC's hardware constraints: a maximum of 4 colors per 8x8\ntile region and 8 palettes globally.\n\n## Development Process\n\nGBHack was developed iteratively over multiple sessions using Claude Code as the\nprimary development tool. The workflow was conversational: describing desired\nfeatures, reviewing generated code, testing in emulators (SameBoy and Gearboy\nwith MCP debugging), and refining based on observed behavior.\n\nThe project started from a blank GBDK template and grew system by system. The\ndungeon generator came first, then rendering, then player movement, then\nmonsters, items, and UI. Each system was developed and tested in isolation before\nintegration. Bank overflow was the most recurring constraint, requiring code to\nbe split across ROM banks whenever bank 0 exceeded its 16 KB limit.\n\nTile art was adapted from Kenney's CC0 asset packs using Python scripts that\nread PNG files (without any image library dependencies, using only stdlib struct\nand zlib) and convert them to the Game Boy's native 2bpp tile format. Several\nrounds of manual iteration refined the palette choices and tile designs to work\nwithin the severe color and resolution constraints.\n\nMusic was composed by Beatscribe and Yoki (Trominal) in hUGE tracker format and\ncompiled to C data arrays for inclusion in the ROM. Integrating the music driver\nwith the sound effect engine required careful channel management to avoid audio\nglitches when both systems access the same hardware registers.\n\nDebugging leaned heavily on [Gearboy](https://github.com/drhelius/Gearboy) and\nits MCP server, which exposes the emulator's state (CPU registers, memory,\ndisassembly, breakpoints, the LCD, the APU) as tool calls. That let Claude Code\ndrive a running build directly — setting breakpoints, stepping through SM83\ninstructions, inspecting VRAM and OAM when a tile or sprite rendered wrong,\nand taking screenshots to verify what the player would actually see. Most\nrendering, FOV, and save-system bugs were diagnosed this way instead of through\nprint-logging a ROM build.\n\n## Credits\n\n- Code by [@statico](https://github.com/statico) and\n  [Claude Code](https://claude.ai/code)\n- Based on [NetHack](https://nethack.org/)\n- Music by [Beatscribe](https://www.beatscribe.com/) and Yoki\n  ([Trominal](https://trominal.itch.io/))\n- Art by [Kenney](https://kenney.nl/) (CC0)\n- Built with [GBDK](https://github.com/gbdk-2020/gbdk-2020),\n  [hUGEDriver](https://github.com/SuperDisk/hUGEDriver), and\n  [CBT-FX](https://github.com/datmobiledev/cbtfx)\n- Debugged with [Gearboy](https://github.com/drhelius/Gearboy) and its MCP\n  server\n\n## License\n\nThe source code in this repository is released under the MIT License. See\n[LICENSE](LICENSE) for details.\n\nArt assets from Kenney are licensed under\n[CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/). Music\ntracks should be credited per their original license terms.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstatico%2Fgbhack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstatico%2Fgbhack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstatico%2Fgbhack/lists"}