IO subsystem

Input/output devices for NES, Famicom and Dendy: real and virtual controllers, and the architecture that binds them to the motherboard

This section contains the implementation of logic for various I/O devices for NES/Famicom/Dendy, expansion ports and accompanying chips.

TBD: expansion ports are not yet implemented and are not considered.

Overview

As it may seem - what could be complicated in an ordinary controller? However...

And how to generalize all this nicely? :-)

IO Subsystem Architecture

Configuring IO Devices

On the emulator side, the setup simply involves binding IOState to some API for working with input devices on the PC side. The associative link is then used to set the SetState of the connected device.

The emulator contains a pool of registered devices with DeviceID (devices are added and removed by the user).

Then each device can be configured (roughly speaking to make binding IOState to DirectInput/XInput or some other API). Each device type has its own bindings dialog for buttons/other actuators.

After configuration, the device can be attached or detached to the specified motherboard model (Attach / Detach). After starting the emulation for the IO subsystem will be created instances of connected devices, connected to the ports and then the emulator can call SetState from its side, so that the native implementation will convert IOState into specific signals for IO ports.

Again the description is very abstract, it will crystallize into particular classes/methods as the work progresses.

Abstract Device

DeviceID: 0x00000000

Does not contain any IOState.

Famicom Controller (Port1)

Famicom Controller (Port1)

DeviceID: 0x00000001

IOStateActuatorValues
0Up0/1
1Down0/1
2Left0/1
3Right0/1
4Select0/1
5Start0/1
6B0/1
7A0/1

Although Famicom controllers are not removable, they can be detached inside the case, so for the sake of code unification we will consider them removable.

Famicom Controller (Port2)

Famicom Controller (Port2)

DeviceID: 0x00000002

IOStateActuatorValues
0Up0/1
1Down0/1
2Left0/1
3Right0/1
4B0/1
5A0/1
6Volume0...255
7MicLevel0...255

Volume and mic level values are in the UInt8 range so far, we'll see how good this model is in the process.

NES Controller (Port1/2)

NES Controller (Port1/2)

DeviceID: 0x00000003

IOStateActuatorValues
0Up0/1
1Down0/1
2Left0/1
3Right0/1
4Select0/1
5Start0/1
6B0/1
7A0/1

Dendy Turbo Controller (Port1/2)

Dendy Turbo Controller (Port1/2)

DeviceID: 0x00000004

IOStateActuatorValues
0Up0/1
1Down0/1
2Left0/1
3Right0/1
4Select0/1
5Start0/1
6TurboB0/1
7TurboA0/1
8B0/1
9A0/1

Virtual Famicom Controller (Port1)

Virtual Famicom Controller (Port1)

DeviceID: 0x00010001

IOStateActuatorValues
0Up0/1
1Down0/1
2Left0/1
3Right0/1
4Select0/1
5Start0/1
6B0/1
7A0/1

Virtual Famicom Controller (Port2)

Virtual Famicom Controller (Port2)

DeviceID: 0x00010002

IOStateActuatorValues
0Up0/1
1Down0/1
2Left0/1
3Right0/1
4B0/1
5A0/1
6Volume0...255
7MicLevel0...255

Virtual NES Controller (Port1/2)

Virtual NES Controller (Port1/2)

DeviceID: 0x00010003

IOStateActuatorValues
0Up0/1
1Down0/1
2Left0/1
3Right0/1
4Select0/1
5Start0/1
6B0/1
7A0/1

Virtual Dendy Turbo Controller (Port1/2)

Virtual Dendy Turbo Controller (Port1/2)

DeviceID: 0x00010004

IOStateActuatorValues
0Up0/1
1Down0/1
2Left0/1
3Right0/1
4Select0/1
5Start0/1
6TurboB0/1
7TurboA0/1
8B0/1
9A0/1