It starts out with just wires, switches, and relays, and as the book progresses he goes through the process of building up a simple CPU and RAM one step at a time. The book even walks you through coming up with opcodes and assembly language.
Even if you already know this stuff, I found the book was helpful in developing an intuitive feel for how everything works and fits together.
After reading it, you'd probably have a good mental model of how you'd want to approach writing an emulator.
The Nand to Tetris courses and their accompanying textbook would probably be helpful here too[1][2].
[0] https://www.amazon.com/Code-Language-Computer-Hardware-Softw... [1] https://www.coursera.org/learn/build-a-computer [2] https://www.coursera.org/learn/nand2tetris2
Once you start on the emulator, the first thing you'll do is emulate the CPU, which can be done as a big switch statement inside of a loop. Knowing how to code each instruction is easy when you have an instruction listing handy.
Here's a quick example of how I would write an emulator, with 2 opcodes already implemented (6502 assembly): https://pastebin.com/raw/PhCEqh35
And the instruction listing I used: http://obelisk.me.uk/6502/reference.html#AND
The compiler probably optimizes the condition check out, so I doubt it really matters.
The "for(;;)" loop is easier and faster for the human to parse. It stands out in source code.
With the "while(true)", you have to pay attention. It could be "while(tnie)" or "while(trua)". Whenever you see it, you have to read carefully.
I've seen it said that "The most optimizing compiler is the most normalizing compiler." [1] The infinite loop structure is pretty easy to normalize.
The only real difference that I saw was that some compiler front ends would produce warnings that the condition in the while loop was always true, where they seemed to assume the empty for must be intentional.
http://www.codeslinger.co.uk/pages/basics.html
In addition to having source code for several different emulators, they've written a ~150 page document about emulator development. It's easily the best resource I've seen on the subject.
It seems like people have put together a lot of good documentation for old systems though, which could at least be a good place to start reading:
https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/
It has enough for doing 2D games bare metal on ARM.
And then you can jump into PiFox.
https://www.raspberrypi.org/blog/pifox-bare-metal-arm-assemb...
The downside is that you'll need to emulate 4 cores plus a GPU. Guest software (the stuff being emulated) may fail if the cores aren't decently fast. You may also need to do USB, audio, wireless LAN, and Ethernet.
Hence the idea of learning ARM Assembly, I guess I got it wrong.
ARM Cortex-M cores are also a bit different from the Application-class processors used in boards like the Raspberry Pi. They are closer to an Arduino than a "real computer".
That is how we did 8 and 16 bit coding on home micros back in the day. :)
My favourite SOC is the ESP32, but I guess it already has too much hardware to emulate and isn't an ARM anyway.
Yeah, I've wanted to learn more about the ESP32 - it seems like people have done some really cool stuff with it and it looks like you get a lot of power and connectivity.
But I'll bet you can empathize with not having enough hours in the day!
Cool idea using VGA as the output; was that hard, or could you just use the DACs normally? I was looking into parallel LCD interfaces for awhile - some F4 cores have a 24-bit RGB LCD peripheral - but they look complicated and I'm still puttering around with SPI OLED/TFT displays.
Anyways, looks like a really cool project!
i wrote a 6800 emulator just from having this background knowledge and no reference in my college years. I did it because I didn't want to go to the labs early saturday morning to fight over the few 6800 hardware. I could write my code, run, debug, show up just as the lab is ending and hand in my work and go home.
https://github.com/Klaus2m5/6502_65C02_functional_tests is what I used.