i have been writing a gameboy emulator for the last year (with short bursts of work where i implement some module), and it's been very challanging and fun, i recommend everyone to try it.
it has a very simple 8-bit (risc) architecture, but obviously tailored for games (for example, it has a dedicated sprite memory sector). i recommend people to try it out because it is has fun quirks compared with "regular" architectures, like arm and x86, for example in the way it handles cartridges, or in that some cartridges actually had non-trivial logic inside them and weren't just a rom.
it always amazes me how active gameboy research and development is still today, for example there's a very recent gameboy emulator / research project done in rust https://github.com/Gekkio/mooneye-gb
there are even test roms with which you can test your emulator to see if it implements all opcodes, interrupts and whatnot correctly (where correctly not only means "with respect to the effects" but also with respect to how many cycles everything should take). example of these test roms: http://gbdev.gg8.se/files/roms/blargg-gb-tests/
The 8080/Z80 variant that is used in the Game Boy is not a RISC architecture - it is a processor architecture from a time long before the term "RISC" was even used the first time.
While the terms RISC/CISC are defined somewhat vaguely, there are still some common properties of architectures that are considered RISC:
- Load-store architecture:
Counterexample: ADD A,(HL)
- Lots of general purpose registers:
The 8080 has rather few:
B,C,D,E,H,L,A as 8 bit registers and BC,DE,HL,SP as 16 bit registers
- Very orthogonal instruction set:
Counterexample: AND has always destination A
- Often pipelined architecture (though this is not very specific to RISC)
- Instructions typically aim to be run in one cycle (when pipelined)
Counterexample: Look at the instruction timing tables
The instruction encoding is quite regular -- it follows the 2-3-3 pattern that came from the 8008 (if not earlier), and thus looks much better in octal than hex:
> The instruction encoding is quite regular -- it follows the 2-3-3 pattern that came from the 8008 (if not earlier)
While it is true (and I am aware of it) that the Z80 instructions follow the 2-3-3 pattern, it is nevertheless not that regular. Best look at the "purest example" for this that is referred in the literature all the time and acted as a model for the criterion that in RISC the instruction format is very regular: the instruction format(s) used by MIPS. Here there only exist 3 different types of instruction (R-type, I-type and J-type) and all have a very regular pattern. One can find very suggestive pictures at
I did something similar with NES; built an emulator, and come back to it every couple of years. It's had 2 CPU cores (2nd added recognition of idle loops, and runs instructions in chunks instead of 1 at a time), 3 PPU implementations (each iteration emulated at a higher level, adding caching and hardware compositing), and 2 implementations of the ROM subsystem (adding caching and multiple memory mappers the second time around).
There are similar testing ROMs for NES emulators, too. My emulator tends to pass the CPU tests and fail some of the PPU ones; guess I need to write a 4th implementation of that chip!
Cartiridges being more than just ROM has been a staple of Nintendo designs all the way back to the NES.
A common trick was to have a logic chip sit between the ROM and the console, doing bank switching. This allowed a game to consist of much more data than could be fitting directly on the data lines provided.
Some games, particularly those sold in Japan, had improved sound chips for example.
And by the time we reach the SNES, Nintendo used this to even introduce rudimentary 3D acceleration in the form of the SuperFX chip.
For NES, another cool approach takes advantage of the fact that the cartridge is natively split between CPU memory and PPU memory. This means that it's possible to make a cartridge with RAM instead of ROM for the tile pattern data ("CHR" in NES jargon), thus enabling things like pseudo-framebuffer operation, compressed/generated graphics, and animations that work by modifying the tile data or depend on its organization in memory [1]. Strictly speaking, there's no reason that RAM and ROM couldn't be combined in this address space with a mapper, but I haven't heard of any cartridges that do so.
it has a very simple 8-bit (risc) architecture, but obviously tailored for games (for example, it has a dedicated sprite memory sector). i recommend people to try it out because it is has fun quirks compared with "regular" architectures, like arm and x86, for example in the way it handles cartridges, or in that some cartridges actually had non-trivial logic inside them and weren't just a rom.
it always amazes me how active gameboy research and development is still today, for example there's a very recent gameboy emulator / research project done in rust https://github.com/Gekkio/mooneye-gb
there are even test roms with which you can test your emulator to see if it implements all opcodes, interrupts and whatnot correctly (where correctly not only means "with respect to the effects" but also with respect to how many cycles everything should take). example of these test roms: http://gbdev.gg8.se/files/roms/blargg-gb-tests/
also for example this disasm of pokemon red: https://github.com/pret/pokered
if you want to write an emulator or a game and you have basic computer organization knowledge, i'd start with the famous pandocs.