- Overview of emulation development: https://stackoverflow.com/a/448689
- Architecture overview of various consoles: https://copetti.org/projects/consoles
- An introduction: http://www.emulator101.com
- Docs for various systems: https://github.com/shonumi/Emu-Docs (combine with resources below)
- Emulation blogs: https://dolphin-emu.org/blog, [archived] byuu.net/, http://emudev.de, [archived] noxa.org/emulation/, http://melonds.kuribo64.net/, https://pcsx2.net/blog/tags/devblog, https://shonumi.github.io/articles.html, etc
- Subreddit: https://www.reddit.com/r/EmuDev
- Building a computer from scratch: https://www.nand2tetris.org
- Books (not necessary):
- Write & run 8-bit code in the browser: https://8bitworkshop.com
- Our website: https://emudev.org/ (in construction)
Most people start with a CHIP-8 emulator. As with any system, see <#482208284032499713> to get started. Note: A great guide that still keeps it challenging is https://tobiasvl.github.io/blog/write-a-chip-8-emulator/.
After that, you can pretty much move to whatever system you want to. You don't have to "work your way up" to it as many seem to think (relevant opinionated thread here: https://goo.gl/CAvrd4). Just make sure you have the basics down first, study the source code of existing emulators (super important) and if you get stuck, ask questions here or in the subreddit. If you contribute to a project that has its own community/resources, you should probably prioritize that.
Explanations for some terms you might come across. (for more info, look at source code of existing emulators, or ask others)
High Level Emulation vs Low Level Emulation
- https://alexaltea.github.io/blog/posts/2018-04-18-lle-vs-hle
- http://emulation.gametechwiki.com/index.php/High/Low_level_emulation
- Code Translation Techniques: [archived] noxa.org/building-an-xbox-360-emulator-part-6-code-translation-techniques/
- Writing a Cached Interpreter: https://emudev.org/2021/01/31/cached-interpreter.html
- Faster interpreters: http://www.emulators.com/docs/nx25_nostradamus.htm
- Computed goto: https://eli.thegreenplace.net/2012/07/12/computed-goto-for-efficient-dispatch-tables
Just-In-Time and Ahead-of-Time compilers.
- Wikipedia: https://www.wikiwand.com/en/Just-in-time_compilation (just for an overview of what it is)
- https://github.com/spencertipping/jit-tutorial
- http://blog.reverberate.org/2012/12/hello-jit-world-joy-of-simple-jits.html
- https://emudev.org/docs/1964-recompiling-engine-documentation.pdf
- https://bheisler.github.io/post/experiments-in-nes-jit-compilation
- https://andrewkelley.me/post/jamulator.html (AOT. most other links here are about JITing)
- https://www.davidsharp.com/tarmac/ (see pdf at the end)
Intermediate representation, which makes it easier to optimize and port to multiple host targets.
- Intermediate representation
- Three address code, common IR representation
- Static single assignment, property of IR that makes optimizations easier at the cost of difficulty in entering/exiting this form
- Dominance, important concept in SSA algorithms
- A Simple, Fast Dominance Algorithm
- Entering SSA:
- Exiting SSA:
- Parallel moves for breaking up phis
- Also check out: SSA book
- Register allocation
- Register Allocation And Spilling Via Graph Coloring, the classic way of register allocation in production compilers and some JITs
- Linear Scan Register Allocation, a faster and simpler register allocation algorithm that produces good results, favorable in JITs for it's linear time
Optimizations
- Common subexpression elimination
- Partial-redundancy elimination
- Global value numbering
- Copy propagation
- Constant propagation/folding
- Dead store
- Code motion
- Sparse conditional constant propagation
- Single Instruction Multiple Data: Processing large batches of data using vector operations. Useful for optimizing rendering, audio processing, vector unit emulation, and all sorts of parallelizable tasks.
- You'll find several helpful resources for writing SSE/AVX/etc (SIMD extensions for x86) and NEON (arm32/arm64) scattered through both resource channels. Make sure to check them out if writing SIMD code.
Fast memory accesses using host MMU.
- https://wheremyfoodat.github.io/software-fastmem
- https://dolphin-emu.org/blog/2016/09/06/booting-the-final-gc-game (mentioned in "Theory 3")
- Faster interpreters: https://www.alchemistowl.org/pocorgtfo/pocorgtfo06.pdf (Section 3.4)
- http://man7.org/linux/man-pages/man2/mprotect.2.html (Unix API)
- https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect (Windows API)
For emulating 3D systems.
- Basics of triangle rasterization (Recommend the barycentric rasterization section in particular)
- Attribute interpolation across a triangle (Recommend the barycentric coordinate approach discussed here)
- Introduction to compute rasterization
- https://fgiesen.wordpress.com/2013/02/17/optimizing-sw-occlusion-culling-index
- LearnOpenGL: OpenGL tutorial for beginners
- Vulkan-tutorial: Vulkan tutorial, prior GPU programming knowledge is advised.
- Renderdoc: Open source graphics debugger with support for OpenGL, DX11, DX12 and Vulkan. Highly recommended if you're doing any sort of GPU programming.
- Nvidia Nsight: Closed source, state-of-the-art graphics debugger by Nvidia. Works on non-Nvidia GPUs too, though some features (like performance monitors) won't be available
- Ubershaders: A Ridiculous Solution to an Impossible Problem
- Texture caching
- Metal API tutorial by Samuel Žúbor
- XCode offers an extraordinary Metal debugger, alongside a horrendous IDE and several other nauseating developer tools.
- https://nicolasallemand.com/2019/12/12/let-there-be-sound
- https://redream.io/posts/improving-audio-video-synchronization-multi-sync
- https://zipcpu.com
- https://www.walknsqualk.com/post/014-tiny-fpga-bx
- Short introduction on writing HDLs, with Verilog puzzles you can solve online
- https://www.icreversing.com/chips (IC library)
-
Multimedia libraries (For Audio/Video output, keyboard/controller input, etc)
- SDL2: C library for graphics, audio, input, threading, and more. Has bindings for several languages
- SFML: C++ library for video and input. Mostly aimed at gamedevs, but can be used for emudev too. Audio API generally considered unfit for emudev.
- Miniaudio: Single-header C audio library, supports all major desktop OSs + Android/iOS.
-
UI frameworks:
- Qt: C++ GUI framework with bindings in several languages.
- Dear ImGui: Immediate-mode GUI framework, focusing on ease-of-use
- ImGui Club: Collection of useful ImGui widgets, including a memory editor
- Avalonia: Portable .NET GUI framework
- GTK
- Nuklear: Single header C immediate mode GUI library
- WxWidgets
-
Runtime code generation (emitter) libraries for use in JITs and assemblers:
- Xbyak: Single header C++ x86-32 and x86-64 emitter
- Oaknut: Single header C++ arm64 emitter
- Dynasm: x86-32/x86-64/arm32/arm64/PowerPC/MIPS emitter written in C
- Luma: Single header C++ 32-bit PowerPC emitter, with support for the Paired Singles ISA in the Gamecube/Wii/Wii U CPUs
- Vixl: C++ arm32 and arm64 emitter for x86-32, x86-64 and arm64.
- asmjit: C++ emitter
- Dynasm-rs: A dynasm-like library for Rust, using proc-macros
- biscuit: RISC-V emitter
-
Libraries for handling configuration files, game databases, etc:
- nlohmann/json: JSON for modern C++
- toml11: TOML for modern C++
- mINI: Single header C++ library for manipulating INI files
-
Cryptography libraries for systems with crypto hardware:
-
Graphics:
- Vulkan-Hpp: C++ bindings for the Vulkan API
- Vulkan Memory Allocator (vma): Simple C++ Vulkan memory management library
- glslang: GLSL and HLSL shader validator and compiler, useful for compiling shaders to SPIR-V.
- shaderc: Wrapper around glslang, provides easy-to-use(™) online and offline shader compilation capabilities.
- sirit: SPIR-V emitter, useful for generating shaders at runtime in high-performance applications (eg shadergen on modern system emulators).
- A fork with some more niche instructions added can be found here
- PCSX-Redux/Panda3DS OpenGL wrapper: C++ abstraction layer over OpenGL
- Metal-cpp: Metal API bindings for C++.
- If you don't want to use a library distributed as a zip and instead want a Git repository, a Github mirror is hosted here
-
elfio: C++ library for reading and creating ELF files, useful for emulators that need to load ELFs or create ELFs for debugging purposes.
-
Capstone: C disassembler library with support for too many architectures to enumerate
-
Keystone: C assembler framework
-
glm: C++ library for faciliating vector, matrix and quaternion math. Particularly useful for graphics emulation.
-
Hips: Single header C++ library for applying IPS, BPS and UPS patches
-
Discord-RPC: C++ library for adding discord RPC to your emulator, because we all love free advertisements.
-
sse2neon: C/C++ library that implements SSE intrinsics on arm32/arm64 systems using NEON equivalents. Useful if you want to avoid manually rewriting all your SIMD code, or if writing NEON yourself.
In emulation, RE-ing is often needed for system BIOSes, operating systems, drivers, OS modules and games to aid in understanding of what the hardware does & emulate it properly when the documentation is insufficient or incomplete (ie. always). It's a huge area of expertise & there is no be-all end-all resource, but a decent starting point might be https://beginners.re (older but free mirror: https://mirrors.ocf.berkeley.edu/parrot/misc/openbooks/programming/ReverseEngineeringForBeginners.en.pdf)
- These videos from LiveOverflow & stacksmashing are a fun introduction to some fundamental concepts: https://www.youtube.com/playlist?list=PLniOzp3l9V82onKsktyyKlIenAAUj45Mk
- There are way too many resources about this. It's a skill used in many disciplines. Look around, find what you like (otherwise you might not be motivated for long).
The industry standard tools are:
- Ghidra: There are loaders/extensions for pretty much all consoles/processors, search for them.
- IDA Pro: Proprietary, paid, closed-source. Industry-standard for professionals - especially before Ghidra it was the only viable option. I don't personally recommend it, especially for architectures other than x86. Also if you want to get it legally, it costs multiple thousands of dollars vs. Ghidra being free & open source.
The standard tool that's cross-platform and supports many architectures is gdb.
- Many emulators implement "gdbstub"s that allow them to use a gdb client to debug guest code just like you would debug something running on the host. Meaning, you would be able to place breakpoints, step, etc via any gdb interface (ie. gdbgui), on GameBoy code or whatever you're emulating.
- IDA Pro has debugging support that works with gdbstubs.
- https://hugsy.github.io/gef/
- https://www.gdbgui.com
- Other projects choose to make their own integrated debuggers with (ie. https://github.com/ocornut/imgui). This is perhaps more work, but more flexible (and many people don't like gdb).
- For x86, the industry standard tool is https://github.com/x64dbg/x64dbg.
- Frida: https://frida.re
- http://reddit.com/r/ReverseEngineering and http://reddit.com/r/REGames
Contributing
Have something to add to this list? Submit a pull request here.
Note: If you're new here, scroll up to the top!