{"id":13528914,"url":"https://github.com/wernsey/chip8","last_synced_at":"2025-04-01T14:33:36.534Z","repository":{"id":43412383,"uuid":"48369292","full_name":"wernsey/chip8","owner":"wernsey","description":"A CHIP-8 interpreter, assembler and disassembler in C","archived":false,"fork":false,"pushed_at":"2023-09-10T17:54:17.000Z","size":396,"stargazers_count":92,"open_issues_count":0,"forks_count":9,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-08-02T07:08:16.575Z","etag":null,"topics":["chip-8","chip8","chip8-emulator","disassembler","emulator","sdl"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wernsey.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}},"created_at":"2015-12-21T11:57:28.000Z","updated_at":"2024-07-22T11:27:00.000Z","dependencies_parsed_at":"2024-01-03T03:59:08.138Z","dependency_job_id":"c2dd44a5-8e5c-46eb-9794-12520d11ec3a","html_url":"https://github.com/wernsey/chip8","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wernsey%2Fchip8","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wernsey%2Fchip8/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wernsey%2Fchip8/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wernsey%2Fchip8/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wernsey","download_url":"https://codeload.github.com/wernsey/chip8/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222735279,"owners_count":17030816,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["chip-8","chip8","chip8-emulator","disassembler","emulator","sdl"],"created_at":"2024-08-01T07:00:28.243Z","updated_at":"2024-11-02T15:31:36.794Z","avatar_url":"https://github.com/wernsey.png","language":"C","readme":"# CHIP-8 Interpreter, Assembler and Disassembler\n\nThis package contains an interpreter for [CHIP-8][wikipedia] as well as a\ncommand-line assembler and disassembler.\n\nIt also supports the SuperChip instructions.\n\nThe syntax of the assembler and disassembler is based on the syntax described\nin [Cowgod's Chip-8 Technical Reference v1.0][cowgod], by Thomas P. Greene\n\nFrédéric Devernay's [SVision-8 website](http://devernay.free.fr/hacks/chip8/)\nhas a wealth of information. He also has a collection of CHIP-8 games and\nprograms in his [GAMES.zip](http://devernay.free.fr/hacks/chip8/GAMES.zip).\n\n## Compilation and Usage\n\n* Linux: Type `make` from the shell.\n* Windows: The system was built and tested with the\n  [MinGW](http://www.mingw.org/) tools. To compile it type `make` from the MSYS\n  shell.\n\nTo use the emulator:\n\n* Under Linux: Type `./chip8 game.ch8` where game.ch8 is the binary CHIP-8 file.\n* Under Windows: Type `chip8 game.ch8` or `chip8-gdi game.ch8` depending on\n  which of the implementations (see below) you want to use.\n\nThe assembler and disassemblers are simple command line applications and\nplatform independent.\n\nTo use the assembler, type\n\n    $ ./c8asm -o file.c8h file.asm\n\nThis will assemble `file.asm` into a binary `file.c8h`. If the `-o` is not\nspecified it will default to `a.c8h`.\n\nTo use the disassembler, run the command\n\n    $ ./c8dasm a.ch8 \u003e outfile.asm\n\nwhere `a.ch8` is the file you want to disassemble.\n\n## Interpreter Implementations\n\nThe core of the emulator is in `chip8.c`. The idea is that this core be\nplatform independent and then hooks are provided for platform specific\nimplementations.\n\nThe API is described in `chip8.h`. The `docs` target in the Makefile generates\nHTML documentation from it.\n\nTwo implementations are provided in this repository:\n\n1. A SDL-based implentation (\u003chttps://www.libsdl.org/\u003e) which is intended for\n  portability, and\n2. a native Windows implementation which is intended for small size and\n  requires no third party dependencies.\n\nIn both versions\n\n* `bmp.h` and `bmp.c` (together with the `fonts/` directory) is used to draw\n  and manipulate the bitmap graphics. See also\n  https://github.com/wernsey/bitmap\n* `render.c` implements the `init_game()`, `deinit_game()` and `render()`\n  functions that forms the core of both implementations and demonstrates how\n  the interpreter's API works.\n\nThe `render()` function checks the keyboard and executes the interpreter a\ncouple of times by calling `c8_step()` and redraws the screen if it changed.\nThe SDL and Win32 frameworks were written in such a way that the `render()`\nfunction works with both with only a couple of minor modifications.\n\nThe implementations feature a rudimentary debugger: Press F5 to pause a running\ngame. The program counter and the current instruction will be displayed at the\nbottom of the screen, along with the values of the 16 Vx registers. Press F6 to\nstep through the program to the next instruction and F8 to resume the program.\n\nThe `Makefile` will build the SDL version by default, and build the GDI version\nunder Windows.\n\n### SDL Implementation\n\nThe SDL-based implementation is intended for portability. The files `pocadv.c`\nand `pocadv.h` implement a wrapper around the SDL that contains the `main()`\nfunction, the SDL event loops and so on.\n\nThe included `emscripten.mak` file is used to compile the SDL implementation to\nJavaScript with [Emscripten](http://emscripten.org/) for running the\ninterpreter in a web browser. The `chip8.html` is a wrapper around the\nEmscripten-generated JavaScript. If you want to use this implementation:\n\n1. You need to put your CHIP-8 binary file in a `./GAMES/` directory\n2. Run `make -f emscripten.mak`\n3. Change the `Module.arguments` variable in the JavaScript in `chip8.html`\n4. Serve `chip8.html` in a web server.\n\nI built the emscripten version through the emscripten SDK installed\naccording to the [installation instructions][emscripten-install]. I had\nsome linker errors with Ubuntu's `emscripten` package that I couldn't\nresolve.\n\n[emscripten-install]: http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html#sdk-download-and-install\n\n### Win32/GDI Implementation\n\nThe native Windows version uses a simple hook around the Win32 GDI and requires\nno third party dependencies.\n\n`gdi.h` and `gdi.c` implements the native Windows code. It implements a\n`WinMain` function with the main Win32 events processing loop. It binds the\nwindow's GDI context to a `Bitmap` object so that a render function can draw\nonto it and fires off periodic `WM_PAINT` messages which calls the `render()`\nfunction to draw the screen.\n\n## Implementation Notes\n\nI've consulted several sources for my implementation (see references below),\nand there were some discrepancies. This is how I handled them:\n\n* Regarding `2nnn`, [cowgod][] says the stack pointer is incremented first (i.e.\n  `stack[++SP]`), but that skips `stack[0]`. My implementation does it the\n  other way round.\n* ~~The `Fx55` and `Fx65` instructions doesn't change `I` in my implementation:~~\n  * This is a known [quirk][langhoff].\n  * The interpreter now provides `QUIRKS_MEM_CHIP8` to control this\n* I've read [David Winter's emulator][winter]'s documentation when I started, but I\n  implemented things differently:\n  * His emulator scrolls only 2 pixels if it is in low-res mode, but 4 pixels\n    is consistent with [Octo][].\n  * His emulator's `Dxy0` instruction apparently also works differently in\n    lo-res mode.\n* ~~[instruction-draw][] says that images aren't generally wrapped, but\n  [muller][] and [Octo][] seems to think differently.~~\n  * This is alsp known [quirk][langhoff].\n  * The interpreter now provides `QUIRKS_CLIPPING` to control this\n* According to [chip8-wiki][], the upper 256 bytes of RAM is used for the display, but it\n  seems that modern interpreters don't do that. Besides, you'd need 1024 bytes\n  to store the SCHIP's hi-res mode.\n* `hp48_flags` is not cleared between runs (See [octo-superchip]); I don't make any effort\n  to persist them, though.\n* Apparently there are CHIP-8 interpreters out there that don't use the\n  standard 64x32 and 128x64 resolutions, but I don't support those.\n* As far as I can tell, there is not much in terms of standard timings on\n  CHIP-8 implementations. My implementation allows you to specify the speed as\n  the number of instructions to execute per second (through the global variable\n  `speed` in `render.c`). The value of 1200 instructions per second seems like\n  a good value to start with.\n\n## References and Links\n\n* [Wikipedia entry][wikipedia]\n* [Cowgod's Chip-8 Technical Reference v1.0][cowgod], by Thomas P. Greene,\n* [How to write an emulator (CHIP-8 interpreter)][muller] by Laurence Muller (archived)\n* [CHIP8 A CHIP8/SCHIP emulator Version 2.2.0][winter], by David Winter\n* [Chip 8 instruction set][chip8def], author unknown(?)\n* [Byte Magazine Volume 03 Number 12 - Life pp. 108-122. \"An Easy\n  Programming System,\"][byte] by Joseph Weisbecker\n* [chip8.wikia.com][chip8-wiki]\n  * Their page on the [Draw instruction][instruction-draw]\n* [Mastering CHIP-8][mikolay] by Matthew Mikolay\n* [Octo][], John Earnest\n* The [Octo SuperChip document][octo-superchip], by John Earnest\n* [codeslinger.co.uk](http://www.codeslinger.co.uk/pages/projects/chip8/primitive.html)\n* [CHIP‐8 Technical Reference](https://github.com/mattmikolay/chip-8/wiki/CHIP%E2%80%908-Technical-Reference), by Matthew Mikolay\n* [corax89' chip8-test-rom](https://github.com/corax89/chip8-test-rom)\n* [Timendus' chip8-test-suite][Timendus] was extremely useful to help clarify and fix the quirks.\n  * Timendus' [Silicon8](https://github.com/Timendus/silicon8/) CHIP8 implementation\n* Tobias V. Langhoff's [Guide to making a CHIP-8 emulator][langhoff]\n  * This one is very useful for explaining the various quirks\n* [Chip-8 on the COSMAC VIP: Drawing Sprites](https://web.archive.org/web/20200925222127if_/https://laurencescotford.com/chip-8-on-the-cosmac-vip-drawing-sprites/), by Laurence Scotford (archive link)\n* [CHIP-8 extensions and compatibility](https://chip-8.github.io/extensions/) -\nexplains several of the variants out there\n* \u003chttps://github.com/zaymat/super-chip8\u003e\n  * The [load_quirk and shift_quirk](https://github.com/zaymat/super-chip8#load_quirk-and-shift_quirk)\n    section of that README has another explaination of some of the\n    quirks, along with a list of known games that need them.\n\n* \u003chttps://github.com/dario-santos/Super-Chip-Emulator\u003e has a collection of ROMs I used for testing\n* \u003chttps://github.com/JohnEarnest/chip8Archive\u003e - Archive of CHIP8 programs.\n* \u003chttps://github.com/tobiasvl/awesome-chip-8\u003e\n\n[wikipedia]: https://en.wikipedia.org/wiki/CHIP-8\n[cowgod]: http://devernay.free.fr/hacks/chip8/C8TECH10.HTM\n[muller]: https://web.archive.org/web/20110426134039if_/http://www.multigesture.net/articles/how-to-write-an-emulator-chip-8-interpreter/\n[winter]: http://devernay.free.fr/hacks/chip8/CHIP8.DOC\n[chip8def]: http://devernay.free.fr/hacks/chip8/chip8def.htm\n[byte]: https://archive.org/details/byte-magazine-1978-12\n[chip8-wiki]: \u003chttp://chip8.wikia.com/wiki/Chip8\u003e\n[instruction-draw]: http://chip8.wikia.com/wiki/Instruction_Draw\n[mikolay]: \u003chttp://mattmik.com/chip8.html\u003e\n[octo]: https://github.com/JohnEarnest/Octo\n[octo-superchip]: https://github.com/JohnEarnest/Octo/blob/gh-pages/docs/SuperChip.md\n[langhoff]: https://tobiasvl.github.io/blog/write-a-chip-8-emulator/\n[Timendus]: https://github.com/Timendus/chip8-test-suite\n\n## License\n\nThis code is licensed under the [Apache license version 2](http://www.apache.org/licenses/LICENSE-2.0):\n\n```\n    Copyright 2015-2016 Werner Stoop\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n```\n\n## TODO/Roadmap/Ideas\n\n* [ ] I really need to fix the \"Display wait\" quirk. See [Timendus][]'s `5-quirks.ch8` test.\n* [x] The quirks need to be in a flags variable so that they can be controlled at runtime\n* [x] The runtime should have a `-q` command line option to control the quirks\n* [x] The assembler needs an `include \"file.asm\"` directive.\n  * [x] You need a way to specify how to do the include, because the assembler must be\n    usable even if you're not loading the source from files. I suggest a function pointer\n    that points to `c8_load_txt()` by default, but can be made to point elsewhere (or set to\n    `NULL` and disable includes completely)\n* [x] I should consider a `text \"hello\"` directive in the assembler, that places a null\n      terminated string in the bytecode. Users might be able to display the text at some point\n      if you have the right sprites; [Octo][] does it.\n* [x] Allow for some hooks in the library to let the `SYS nnn` (`0nnn`) instructions break\n      out into the environment outside.\n      * It's meant as a bit of a joke, might be neat if you embed a CHIP-8 interpreter\n        in another program and call out to it as a sort of scripting language.\n* [x] Command line option, like `-m addr=val`, that will set the byte at `addr` to `val` in the\n      RAM before running the interpreter.\n      * A immediate use case is for, example, [Timendus][]'s `5-quirks.ch8` test that allows you\n        to write a value between 1 and 3 to `0x1FF` and then the program will bypass the initial\n        menu and skip directly to the corresponding test. I imagine that while developing and\n        debugging CHIP-8 programs it might be useful to have such a mechanism.\n* [x] Fix the assembler that doesn't do any bounds checks on `stepper-\u003etoken`\n* [ ] Breakpoints in the debugger\n* [ ] ~~A `.map` file output by the assembler...~~\n\nPorting to the Amiga 500 might be an interesting challenge to get it truly portable:\nThe Amiga's bus is word aligned, so if the program counter is ever an odd number then\nthe system might crash when it tries to retrieve an instruction. Also, the Amiga is big\nendian, so that might reveal some problems as well.\n\n[XO-Chip compatibility](http://johnearnest.github.io/Octo/docs/XO-ChipSpecification.html) seems\nlike something worth striving for. [Here](https://chip-8.github.io/extensions/#xo-chip)'s a\nshort checklist of the changes. Also look at how [Octo](https://chip-8.github.io/extensions/#octo)\nmodifies some instructions.\n","funding_links":[],"categories":["C","Software development"],"sub_categories":["Tools"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwernsey%2Fchip8","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwernsey%2Fchip8","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwernsey%2Fchip8/lists"}