https://github.com/loadzero/si78c Skip to content Sign up * Why GitHub? + Features + Mobile + Actions + Codespaces + Packages + Security + Code review + Issues + Integrations + GitHub Sponsors + Customer stories * Team * Enterprise * Explore + Explore GitHub + Learn and contribute + Topics + Collections + Trending + Learning Lab + Open source guides + Connect with others + The ReadME Project + Events + Community forum + GitHub Education + GitHub Stars program * Marketplace * Pricing + Plans + Compare plans + Contact Sales + Education [ ] * # In this repository All GitHub | Jump to | * No suggested jump to results * # In this repository All GitHub | Jump to | * # In this user All GitHub | Jump to | * # In this repository All GitHub | Jump to | Sign in Sign up {{ message }} loadzero / si78c Public * Notifications * Fork 62 * Star 576 * si78c is a memory accurate reimplementation of Space Invaders in C. blog.loadzero.com/blog/si78c/ 576 stars 62 forks Star Notifications * Code * Pull requests 0 * Actions * Projects 0 * Security * Insights More * Code * Pull requests * Actions * Projects * Security * Insights master Switch branches/tags [ ] Branches Tags Could not load branches Nothing to show {{ refName }} default View all branches Could not load tags Nothing to show {{ refName }} default View all tags 1 branch 0 tags Code Latest commit @loadzero loadzero Correct processor name from 8085 -> 8080 (thanks mog!) ... 0b2b4f1 Dec 6, 2019 Correct processor name from 8085 -> 8080 (thanks mog!) 0b2b4f1 Git stats * 4 commits Files Permalink Failed to load latest commit information. Type Name Latest commit message Commit time Makefile si78c first release Dec 3, 2019 README.md Correct processor name from 8085 -> 8080 (thanks mog!) Dec 6, 2019 si78c.c si78c first release Dec 3, 2019 si78c_proto.h si78c first release Dec 3, 2019 View code [ ] si78c Project Scale Accuracy Audience Conventions Threading Limitations Porting Building and running README.md si78c si78c is a memory accurate reimplementation of the 1978 arcade game Space Invaders in C. It requires the original arcade ROM to function to load various sprites and other data, but does not use the original game code. It is not an emulation, but rather a restoration. It is however, accurate enough that it can be used to understand the inner workings of the original system, in a more accessible manner. Many thanks to Christopher Cantrell at computerarcheology.com. Without his painstaking work and excellent notes, this project would have taken a lot longer. Project Scale This was a reasonably large undertaking, requiring many iterations over several months, and I would conservatively estimate that around 200 hours of work have been put into the project so far. The original ROM is around 2000 lines of 8080 assembler, all of it game code. The final published version of si78c is around 1500 lines of game code, 500 lines of support code, and around 800 lines of comments. There are about twenty thousand more lines of unpublished code in the background consisting of the previous iterations and other support scripts and tools that needed to be written to get the job done. Accuracy When running, si78c produces identical memory states (apart from the stack) to the original version. As a natural side effect, it produces pixel accurate frames compared to the original. Cycle timing is not particularly accurate, but the game code is not particularly sensitive to this, as it uses interrupts for timing most things, instead of clock cycles. Audience The intended audience is hackers, enthusiasts, scholars, students, historians, and anyone else engaged in digital archaeology. The code is intended to be used as a more accessible guide to studying the original game, and learning about its inner workings. Conventions Where practical, I have used the same or similar function and variable names as Cantrell, to more easily aid people studying both versions. The code is also laid out in a similar order to the original. Every function with a matching analog in the original system is signposted with a comment like xref 028e, which gives the address of the matching routine in the original ROM. A few other places in the code like loops and branches are annotated similarly. To find more detail on code near an xref, you can use Cantrell's excellent notes here. Threading The original code is interrupt driven, and partially co-operatively multitasked. The game spends about a third of the time running the main thread, which gets pre-empted by the midscreen and vblank interrupts. The other two thirds of the time is split between those interrupt contexts, which are not pre-empted, but decide when to return to main. It also contains some interesting parts like this: 02D0: 31 00 24 LD SP,$2400 // wipe the stack 02D3: FB EI // drop isr context 02D4: CD D7 19 CALL DsableGameTasks // keep going from this point That code (running in an interrupt context) after detecting the player's death, essentially wipes out all thread contexts (including itself), and then becomes the new main context. To handle things like this in the this in si78c, I decided to use ucontext (user level threading) to give me more fine grained control over thread switching, creation and destruction. The equivalent piece of code in C to the above is a bit messier, and involves using swapcontext to swap to a scheduler context, which then resets all the contexts, and then swaps back and re-enters at the desired point. Limitations There is no sound, as the sound hardware is not emulated. Cycle timing is not particularly accurate, as mentioned, but its not very important in this case. The code will currently only work on little endian systems, as the original system (8080) was little endian, and we use the ROM data as is. Porting The game is known to build and run on Ubuntu 18.04 and MacOSX El Capitan, and will likely run on other x86 Unix systems, as long as they support ucontext and SDL2. Unfortunately, ucontext is deprecated on MacOSX, so it may not run on later versions. The game is written in the subset of C99 that is compatible with C++, and uses no compiler extensions apart from attribute packed. It will build fine on GCC 3 and above, and most likely any Unix C or C++ compiler newer than that. Porting to a non unix system like Windows would require changing out ucontext to use threads or fibers. Porting to a simpler system like DOS, or something bare metal will require writing some code to blit to the framebuffer, and adapting to whatever native interrupt facilities are available. In terms of CPU grunt required, the code isn't particularly optimized, and currently requires a 32-bit processor capable of at least 10 Mips. It could be made to fit on a smaller system with a bit of work. The code assumes little endian. To port to a big endian system would require further dissection of the ROM, to identify and swizzle any little endian data when it is loaded. Porting the code to another language would not be a small task, and would most likely require switching out the threading system, and converting the code to not use pointers. Building and running SDL2 is required as a dependency, to install on Ubuntu, do this: $ sudo apt-get install libsdl2-dev To grab the code and build the binary, do this: $ git clone https://github.com/loadzero/si78c.git && cd si78c $ make As mentioned, the original arcade ROM is required, invaders.zip from the MAME_078 set is known to work. The constituent parts must be placed in a folder called inv1, and have these checksums: $ md5sum inv1/* 7d3b201f3e84af3b4fcb8ce8619ec9c6 inv1/invaders.e 7709a2576adb6fedcdfe175759e5c17a inv1/invaders.f 9ec2dc89315a0d50c5e166f664f64a48 inv1/invaders.g e87815985f5208bfa25d567c3fb52418 inv1/invaders.h To run it: $ ./bin/si78c The keyboard controls are: a LEFT d RIGHT 1 1P 2 2P j FIRE 5 COIN t TILT About si78c is a memory accurate reimplementation of Space Invaders in C. blog.loadzero.com/blog/si78c/ Resources Readme Stars 576 stars Watchers 9 watching Forks 62 forks Releases No releases published Packages 0 No packages published Languages * C 99.7% * Makefile 0.3% * (c) 2022 GitHub, Inc. * Terms * Privacy * Security * Status * Docs * Contact GitHub * Pricing * API * Training * Blog * About You can't perform that action at this time. You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.