In general: There are many ways and it's not trivial. You will need to design something yourself.
If the amount of data is very small (like controller inputs) you could use a register which stores the latest data. The input side of the register connects (somehow - you'll need to design some logic) to the interface CPU's memory bus, and the output side connects (somehow) to the main CPU's memory bus. Apart from this register, the two CPUs have entirely separate memory. Done. (It seems like a waste of a CPU though)
Most CPUs don't access the memory every single cycle, so you can make them take turns. When the main CPU wants to access memory, let it access the memory bus. When the interface CPU wants to access memory and the main CPU doesn't, let it access the memory bus. When the interface CPU wants to access memory and the main CPU does, pause the interface CPU. You'll still need to design some logic.
You could give each CPU its own memory bus, but design some logic (see the pattern?) to allow the main CPU to access some of the interface CPU's memory (or vice versa). You could pause the interface CPU whenever the main CPU accesses its memory (easier) or only when the main CPU tries to access the shared memory at the same time as the interface CPU (harder, but still doable).
In any case, the specific logic circuit can't be designed without knowing all the details of how the RAM and CPUs need to connect. "Assume we have a Z80 or 6502" is not enough information to actually design the circuit. We can only make approximations and draw block diagrams.
Here are some general tips:
- You can pause a "retro" CPU by stopping its clock signal. (This is not always true for modern CPUs)
- In order to connect/disconnect part of a bus, you want to search for a "bidirectional bus transceiver" chip, such as a 74xx245.
- Feel free to do the above things as often as you want. If you had shared memory, you could disconnect it and reconnect it every single cycle, and the RAM won't care. (connecting it at the correct time is where the complexity is)
- CPUs only access a specific address at a time. They don't care what other addresses are doing. Don't feel bad about disconnecting RAM from a CPU - as long as the RAM is there when the CPU actually accesses it, it won't care.
- Dual port RAM, which has two busses, exists. I don't know how common dual port RAM chips are. It's pretty standard for FPGAs to have some dual port RAM inside them, so if you're building your console on an FPGA, this is a non-problem.
- (thanks to Richard the Spacecat) Many CPUs are designed to share their bus already. With a Z80 you can use the /BUSREQ signal to ask the CPU to pause itself and electrically disconnect itself from the bus (so you don't need a bus transceiver). It runs for a few cycles first, and it tells you when it's disconnected by using the /BUSACK signal.