IIRC the cartridges were effectively just PROMs (I could be wrong and maybe they were fabbed / silicon and didn’t get programmed) which held the application code.
(The Genesis had a tiny ROM for the TMSS licensing check, but that was only 2KB, most of it image data -- and it was only used during system startup.)
On 8/16bit consoles everything was tied to the video chip. You essentially have to do your CPU work (including polling the controllers) during the vblank interval, a short time window that occurs 60 times per second on NTSC systems. This is essentially a zero-lag arrangement (max latency is 1/60th of a frame, average is 1/30th of a frame) but if you miss a controller input it's gone forever.
I'm not entirely sure how emulators handle this. They could deliver buffered controller inputs to the emulator on successive input polls for guaranteed delivery, but then the emulated software is going to see a lot of inputs with wacky timing that may or may not screw with game logic (think of a fighting game where you need to input specific things in sequence in specific time windows) so simply dropping inputs may be preferable to delivering a log jam of inputs.
As you are intuiting, this isn't generally an issue on modern hardware. Emulated games play fine. But, also... if you have a chance to sit down with real hardware connected to a CRT... it feels different. 1/30 frame of lag vs. multiple frames.
Emulators have tons of sync points, less than real hardware, but still plenty. The more sync points you add the slower emulation gets most of the time. Do we emulate transferring x length of bytes to a buffer in another part of hardware (video ram for example) one system bus wide word at a time or do we just cope it all at once and move on? etc.
Syncing aspects of the emulated hardware with each other is easy. You still have to count clock cycles somewhere. So you just execute the necessary number of CPU cycles while your DMA is running, then set the flag that it's done or whatever. And you have to do the same thing with hardware timers anyway — you trigger an interrupt after X clock cycles.
It's syncing the emulator itself to real time that's tricky.
It's also entirely possible to run an emulator at many times real-time and get the sound output correct, however you use it. You can use this to quickly get wav/mp3 copies of game music, for example.