Supposing it's any contribution, these are my direct notes on the machines for which I have written emulators, in approximate launch chronological order, hopefully to offer some colour on file formats, etc:
Atari 2600
The distinguishing feature of the Atari 2600 is the synergy between processor and graphics output; games are implemented a real-time function that supplies graphical components to the video output as the raster runs. So I think this is a bad choice for the purpose stated — the real hard work of writing a 2600 emulator is the timing and interplay outside the microprocessor.
Apple II
Relatively simple hardware, but very nuanced, with multiple graphics modes, and you need to edge towards teaching NTSC video to be able to decode its colour output. Emulating the Disk II is also pretty much a must, but that's a bit of a quest in itself as the most common file formats expect you to provide an Apple GCR encoder.
ZX80/81
Also probably overly-complicated for the stated purpose, the central conceit is repurposing the CPU's refresh cycle and a subset of instruction fetches in order to scan video. If you chose not to reimplement that mechanism like the original, you'd end up with only the ROM-default text mode.
Commodore Vic-20
This is a plain bitmapped machine with a simple processor in the 6502 and a decent quantity of games, some of which were supplied on cartridge, absolving you from the need to emulate a tape or disk drive. The only fly in the ointment is its 6522s; these are combination timer/shifter/input/output chips with a whole bunch of quirks. But a neat advantage of the Vic-20 is that it will boot as far as the BASIC prompt without functioning 6522s, and BASIC itself will function with only the timers of the 6522 implemented, even inexactly.
Its short time as the market leader before the arrival of the C64 also limits the number of titles that make advanced use of the hardware — there are contemporaneous examples of raster racing such as the Imagic titles, but they're in the minority.
The file formats that data is preserved in are a mess, but limiting yourself to cartridge support and being careful to use only those titles that were supplied on cartridge should obviate that problem.
ZX Spectrum
Covered elsewhere; I think a good choice. Especially if you stick to the snapshot file formats.
Oric 1/Atmos
Covered elsewhere; a decent choice, but there's another of those pesky 6522s in there. Most games are available on tape, you'll need to support all that.
Acorn Electron
Bitmapped, a 6502 plus relatively simple external logic, but six different graphics modes and timing would be a hassle — the cost of each cycle is a function of the area being accessed (ROM versus RAM), the graphics mode (40-column versus 80-column modes) and possibly the current graphics output state (80-column modes block RAM accesses during the pixel region; 40-column modes don't). But you can just model it as a 1Mhz machine for most games, and mostly get away with a line-centric version of graphics output.
There are a slender number of games available on ROM but luckily the tape hardware will mostly permit a very low-quality emulation: it's of the ilk that raises an interrupt upon byte receipt, with only two titles that I can think of doing deeper introspection than that.
Amstrad CPC
Probably one to avoid for the stated purpose — it has a 6845 CRTC, which makes for very configurable graphics output and therefore lots of titles that race the raster. Disk usage was also fairly pervasive, but its 8272 disk controller is a whole additional level of headaches compared to the WD1770 you'll often see elsewhere.
MSX and/or ColecoVision/SG1000
Different sound chips, same CPU and video. I actually think you can get pretty far ignoring timing interplay because the video chip keeps its own RAM at arm's length. But it's tiles and sprites, and four different graphics modes, for probably too substantial an undertaking for a microprocessing course.
Master System
Technically an enhanced SG1000, being everything that machine does plus an extra graphics mode, but the extra graphics mode is so much better than the others that only one title uses anything else. So it actually simplifies things somewhat if you're happy within the realm of mostly ignoring timing.
But you're still talking about factoring in sprite priorities, checking for per-pixel collisions, etc. Probably too much.
Footnote: cheating with tape access
For a bunch of the home computers mentioned above, you can actually skip tape emulation for anything that is encoded in the default ROM format by just inserting an appropriate trap into the system ROM and spooling in from the source file. Many, but not all, titles rely entirely on the built-in ROM for tape IO so that can get many titles loaded with no real attempt at hardware.
In every case it's a bodge-job hack, but it'll do if that side of emulation isn't important to you — you'd rather just remove it from the equation and ignore what doesn't work.
Specifically:
Vic-20:
- if the program counter gets to 0xf7b2, copy the next tape header to the location indicated by b3:b2, zero out 0x90 and 0x93, and continue from 0xf7b5 (as you're avoid a JSR);
- trap 0xf90b, check for X = 0xe, if so then get the next tape data body and write to emulated memory from c2:c1 but no further than af:ae regardless of the size of the body, then set bit 6 at 0x90, clear the carry and interrupt flags, and continue from 0xfccf.
Oric:
For ROM 1.0, trap the PC at address 0xe630. For 1.1, watch for address 0xe6c9.
Upon catching that, load A with the next byte from the tape, and set the zero flag according to its value.
Then RTS.
There's also a flag at 0x67 on the original ROM, or 0x24d which discerns between the machine's fast and slow tape encodings, but the usual tape file format just has the decoded bytes so for a quick and dirty emulation don't worry about it.
Electron:
Install NOPs at 0xf4e5, 0xf6de, 0xf6fa and 0xfa51 to disable the tape branches. The OS will now try to load tape data as if it were on a serial ROM.
Cat the PC at 0xf0a8 and check that the X register is equal to 14 and the value at address 0x247 is zero. Then you'll know that the ROM is trying to fetch the next byte from tape.
Put the next byte in Y, set A to 0 and RTS.
The primary tape file format mostly allows you to spool bytes directly from the file (after some trivial chunk navigation, and via ZLib or another GZ decompressor, though you could just gunzip in advance).
ZX Spectrum:
(This one is transcribed from very old notes; it might be worth confirming against a ROM disassembly)
Trap the PC reaching 0x056c in the 48kb ROM. Grab the next block from tape (if you use a TAP file, you'll be directly given it; I'd argue you shouldn't bother trying to support TZX in this sort of project).
If its length is less than the value in DE, reset carry and return.
Compare the first byte of the block to the value of B. If they don't match, reset carry and return.
Otherwise spool the first DE bytes you did get to the address pointed to by IX and set the low bit of C and set carry.
Then either directly perform a RET or else just skip the PC ahead to 0x05e2, which is the RET that normally ends tape loading.
The 128kb machines segue into the 48kb ROM for tape loading so the same hack applies subject to checking what's paged.