codeslinger.co.uk

Sega Master System - Joypads.

Joypads:

This is one of the easiest devices to emulate on the SMS. Each joypad button on the joypad will have its own bit in a Joypad status register. There are two joypad status registers which the game can read by reading their appropriate port numbers. These ports are write protected so you will only ever get games trying to read from them not write to them. PortA is port number 0xDC and is mirrored at 0xC0. PortB is port number 0xDD and is mirrored at 0xC1. This is what the bits for each of the two bytes representing the states mean

PortA:
Bit 7: Joypads 2 down button
Bit 6: Joypads 2 up button
Bit 5: Joypads 1 Fire B
Bit 4: Joypads 1 Fire A
Bit 3: Joypads 1 Right Button
Bit 2: Joypads 1 Left Button
Bit 1: Joypads 1 Down Button
Bit 0: Joypads 1 Up Button

PortB:
Bit 7: Unused... Lightgun?
Bit 6: Unused... Lightgun?
Bit 5: Unused
Bit 4: Reset Button
Bit 3: Joypads 2 Fire B
Bit 2: Joypads 2 Fire A
Bit 1: Joypads 2 Right Button
Bit 0: Joypads 2 Left Button

However each bit of these two bytes is 1 when a button is NOT pressed. When a button is pressed the bit is 0. Also notice how Joypad2 has states in both PortA and PortB. The best way to emulate the joypads is to have two BYTE variables which is initially set to 0xFF (all the 1s will be set meaning that no buttons are pressed). Then whenever a keyboard button is pressed change the corresponding bit in either PortA or PortB to be 0 and when the key is released change it back to 1. Then whenever the game wishes to check joypad input it will read either IO port 0xDC or 0xDD and the emulator will return either the PortA byte or PortB byte respectively.

Reset Button:

The last part of joypad emulation is the Reset button. The reset button triggers a none maskable interrupt, which means there is no way the game can prevent this interrupt from being registered. Even if all interrupts are disabled a none maskable interrupt will still get serviced. I will explain in greater detail the interrupt system in the next section of the tutorials, so for now just set a flag whenever the reset button is pressed (but not released). This will signal to the emulator that a reset interrupt must be serviced asap.