MSX Assembly Page

MSX I/O ports overview

Here’s an overview of all used I/O ports on MSX as far as I could find out at the moment. Some entries will contain a link to a more specific description on how to use those ports.

More detailed port descriptions will be added later when I have more time. And a request: if you have more details about devices where I put a note, or if you see an error, then please mail us (email address can be found on the main page).

Port range Description
#00-#01 Music Module MIDI, output ports
#00-#03 FAC MIDI interface
#00-#02 MIDI Saurus
#04-#05 Music Module MIDI, input ports
#18-#19 Philips Barcode Reader NMS1170/20
#20-#28 Second setting Philips NMS1251 modem
#20-#28 Second setting Miniware M4000 modem
#28-#2F Second setting Philips NMS1210 RS232 interface
#2E-#2F openMSX debug device (default address)
#30-#38 Philips NMS1251 modem
#30-#38 Miniware M4000 modem
#30-#38 GREEN/MAK SCSI-interface
#30-#38 CD-ROM interface
#40-#4F Switched I/O ports
#60-#6F Graphics9000 / v9990
#70 MIDI Saurus (wasn’t it on #00-#02 already?)
#7C-#7D MSX-Music / FM-Pac / OPLL
#7E-#7F MSX 2 key cartridge (what is it?)
#7E-#7F MoonSound / OPL4 - WAVE-bank
#80-#83 RS232C UART / 8251 (only Spectravideo?)
#84-#87 RS232C programmable timer / 8253 (only Spectravideo?)
#88-#8B Alternate VDP v9938 ports for MSX1 to MSX2 adaptor
#8C-#8D Sony MSX Modem (HBI-1200? “TELECOM BIOS” what does it mean?)
#8E-#8F MegaRAM / MegaRAM Disk
#90-#91 Printer port interface
#93 Printer port bus direction (does it exist?)
#98-#9B VDP / Video Display Processor / TMS9918A / v9938 / v9958
#A0-#A3 PSG / AY-3-8910 - PSG I/O ports
#A4-#A5 PCM controller (turboR)
#A7 Pause / R800 info (turboR)
#A8-AB PPI / Programmable Peripheral Interface / 8255
#AC-AF MSX-Engine / S3527 / S1985
#B0-B3 Sony HBI-55 data cartridge (4kB SRAM) (‘External memory’? 8255??)
#B4-B5 Clock chip / RP-5C01
#B8-BB Card Reader (maybe the Softcard adaptor or Bee Pack???)
#B8-BB Sanyo lightpen interface
#BC-BF JVC video controller
#C0-#C1 MSX-Audio / Music Module / OPL1
#C0-#C1 MoonSound / OPL4 - FM-bank 1 alternate addressing mode
#C2-#C3 MSX-Audio / Music Module / OPL1 - 2nd cartridge
#C2-#C3 MoonSound / OPL4 - FM-bank 2 alternate addressing mode
#C4-#C5 MoonSound / OPL4 - FM-bank 1
#C6-#C7 MoonSound / OPL4 - FM-bank 2
#C8-#CF MSX Interface
#D0-#D7 FDC / Floppy Disk Controller (which types?)
#D8-#D9 Kanji ROM, JIS 1
#DA-#DB Kanji ROM, JIS 2
#DC-#DD Kanji ROM, 24-dots
#E0-#E2 External MIDI interface (micro pack)
#E4-#E7 S1990 controller (turboR)
#E8-#EF Internal MIDI interface (turboR GT)
#F4 System flags
#F5 System control
#F6 Reserved for color bus I/O
#F7 A/V controller
#F8 Optional A/V controller for PAL version
#F8-#FB Memory Mapper controller (in 16-bit mappers, contains MSB)
#FC-#FF Memory Mapper registers

Here are also some memory-mapped I/O areas:

Address Range Description
#7FC0-#7FCF Panasonic FS-A1FM Modem ROM
#FFFF Secondary slot select register

Information collected from various sources. Special thanks go to Alex Wulms for the nice overview published in MCCM 75.

Switched I/O ports

According to the MSX2 Hardware Specification, ports #40-#4F are forming the so-called ‘switched I/O ports’. With these the limitation of a maximum number of 256 I/O ports can be overcome, although it does require a little additional logic on the hardware’s behalf. The port numbers #41-#4F are the actual switched ports, and the device ‘connected’ (e.g. listening to) to those ports is determined by the device ID written to port #40. This device ID can be a number from 1-254, and when port #40 is read it returns the complement of the current device ID.

Port range Description
#40 Device ID register
#41-#4F Switched I/O ports

ID numbers between 1 and 127 are manufacturer ID numbers, and ID numbers 128 to 254 are device IDs. As a basic rule, those devices which are designed specifically for one machine should contain the manufacturer’s company ID, while periperhal devices which can be used on all MSX computers should have a device ID number. Also, the Z80 actually has a 16-bit I/O addressing space so it is recommended to access in 16-bit by decoding the upper 8 bits for those IDs which might be expanded in the future (although I have personally only seen this done in the ADVRAM hardware). Especially for devices which are connected with their make ID it can be expected that they might eventually need more addressing space, and with this it will be future-proofed.

List of BIOS extension device ID’s:

IDMaker/device
1ASCII/Microsoft
2Canon
3Casio
4Fujitsu
5General
6Hitachi
7Kyocera
8Matsushita (Panasonic)
9Mitsubishi
10NEC
11Nippon Gakki
12JVC
13Philips
14Pioneer
15Sanyo
16Sharp
17SONY
18Spectravideo
19Toshiba
20Mitsumi
128Image Scanner (Matsushita)
254MPS2 (ASCII)

Some example code, this enables the 6MHz mode on Panasonic FS-A1WX/WSX/FX computers:

PortPanasonic extensions
#40 = 8 (Panasonic manufacturer ID)
#41 Available on FS-A1FX/WX/WSX only:
bit 0: CPU speed mode (0=5.37MHz, 1=3.57MHz)
Available on FS-A1FX/WX/WSX/ST/GT only:
bit 7: Firmware switch status (0=on, 1=off) (read-only)
	LD	A,8
	OUT 	(040H),A	;out the manufacturer code 8 (Panasonic) to I/O port 40h
	IN	A,(040H)	;read the value you have just written
	CPL			;complement all bits of the value
	CP	8		;if it does not match the value you originally wrote,
	JR	NZ,Not_WX	;it is not a WX/WSX/FX.
	XOR	A		;write 0 to I/O port 41h
	OUT	(041H),A	;and the mode changes to high-speed clock
So you can check if certain extensions are available and ready to be accessed by reading back the value you just wrote to the device ID register. If that value is not the complement of what you wrote, then the extensions are not present.

Graphics9000 / v9990

The v9990 has 16 registers in total, covering the range #60-#6F. Only the first eight are used in the Graphics9000, ports #68-#6B are used in combination with an optional Kanji ROM extension, and the rest is left as reserve. In the Graphics9000, port #6F is mapped to the v7040 superimpose chip.

Port range Description
#60 VRAM data port
#61 Palette data port
#62 Command data port
#63 Register data port
#64 Register select port (write only)
#65 Status port (read only)
#66 Interrupt flag port
#67 System control port (write only)
#68-#69 Primary standard Kanji ROM address port (write only) (not used in Gfx9000)
#69 Primary standard Kanji ROM data port (read only) (not used in Gfx9000)
#6A-#6B Secondary standard Kanji ROM address port (write only) (not used in Gfx9000)
#6B Secondary standard Kanji ROM data port (read only) (not used in Gfx9000)
#6C-#6E Reserved
#6F v7040 superimpose chip (write only) (both Gfx9000 and Video9000)

Important note: for correct behaviour, all Gfx9000 applications should initialize by writing 0 to port #6F (the v7040 superimpose chip), and then wait a frame before accessing the Gfx9000 again. Not ensuring this register has the value 0 written to it will cause the Gfx9000 output to be blurred occasionally. On exit, Gfx9000 applications should write #10 to port #6F as a courtesy to Video9000 owners.

Refer to the Video9000 manual, page 13, for more (Video9000-specific) details about the v7040 chip.

VDP / Video Display Processor / TMS9918A / v9938 / v9958

These are the I/O registers for accessing the standard MSX VDPs:

Port range Description
#98 VRAM data read/write port
#99 (write) VDP register write port (bit 7=1 in second write)
VRAM address register (bit 7=0 in second write, bit 6: read/write access (0=read))
#99 (read) Status register read port
#9A Palette access port (only v9938/v9958)
#9B Indirect register access port (only v9938/v9958)

PSG / AY-3-8910

These are the I/O registers for accessing the MSX PSG (Programmable Sound Generator):

Port range Description
#A0 (write) Register write port
#A1 (write) Value write port
#A2 (read) Value read port

The following table describes the registers of the PSG:

Register(s) Description
0-5 Tone generator control
6 Noise generator control
7 Mixer control-I/O enable
Important note: bit 6 must be 0, and bit 7 must be 1. Setting different values can cause damage on some systems. Safest approach is to just not touch them and read them first before writing a new value.
8-10 Amplitude control
11-13 Envelope generator control
14-15 I/O ports A & B

Additional PSG I/O ports A & B

The PSG has two additional I/O ports in registers 14 and 15. They are used by the MSX standard for several device I/O related tasks, comparable with the PPI and working more or less in conjunction with it. These are the functions:

PSG I/O port A (r#14) – read-only

Bit Description Comment
0 Input joystick pin 1 (up)
1 Input joystick pin 2 (down)
2 Input joystick pin 3 (left)
3 Input joystick pin 4 (right)
4 Input joystick pin 6 (trigger A)
5 Input joystick pin 7 (trigger B)
6 Japanese keyboard layout bit (1=JIS, 0=ANSI)
7 Cassette input signal  

PSG I/O port B (r#15) – write/read

Bit Description Comment
0 Output joystick port 1, pin 6 (set 1 for input)
1 Output joystick port 1, pin 7 (set 1 for input)
2 Output joystick port 2, pin 6 (set 1 for input)
3 Output joystick port 2, pin 7 (set 1 for input)
4 Output joystick port 1, pin 8
5 Output joystick port 2, pin 8
6 Joystick input selection, for r#14 inputs (1=port 2)
7 Kana led control (1=off)

Pause / R800 info (turboR)

This I/O register is only present on MSX turboR computers. Its function differs depending on whether you are reading or writing.

Port range Description
#A7 (read) bit 0: pause switch (1=on)
Works only in R800 mode (connected to WAIT of Z80)
#A7 (write) bit 0: pause LED (1=on)
bit 7: R800 LED (1=on)
Mirror address is #FCB1 in the system RAM.

PPI / Programmable Peripheral Interface / 8255

The PPI controls a number of things in the MSX system, ranging from slot selection through cassette output to interfacing with the keyboard.

Port range Description
#A8 PPI-register A
Primary slot select register.
#A9 (read) PPI-register B
Keyboard matrix row input register.
#AA PPI-register C
Keyboard and cassette interface.
#AB (write) Command register.

Below, we will describe the registers in more detail.

Primary slot select register

The 64k of MSX main memory is divided into four blocks of 16k, referred to as pages. This register controls which primary slot will be mapped to each page of memory.

PPI-register A (#A8)
Bits Description
0-1 Slot for page 0 (#0000-#3FFF)
2-3 Slot for page 1 (#4000-#7FFF)
4-5 Slot for page 2 (#8000-#BFFF)
6-7 Slot for page 3 (#C000-#FFFF)

This register can both be written and be read.

Additionally, each primary slot can and often will be expanded into four secondary slots, also known as subslots. The subslot select register can be found at memory address #FFFF. For more details, go to the secondary slot select register.

Misc PPI controls

With PPI register C you can access the keyboard (including CAPS LED and key click), and control the cassette interface. The precise function of each bit is described in the table below:

PPI-register C (#AA)
Bits Description
0-3 Keyboard matrix row select register.
Matrix row can be read from PPI-register B (#A9).
4 Cassette motor control. 1 = off.
5 Cassette write signal. 1 = high.
6 Keyboard CAPS LED. 1 = off.
7 1-bit key click sound output. 1 = high.

More information about keyboard matrices can be found in the keyboard matrices article.

PPI command register

With this write-only register you can set or reset individual bits in PPI-register C. This is the recommended (fastest) method to use when you want to modify bits 4-7.

PPI command register (#AB)
Bits Description
0 Value to set.
1-3 Bit no. within PPI-register C.
4-6 Not used.
7 Must be 0.

S1990 controller (turboR)

Through these ports you can access the turboR’s S1990 bus controller.

Port range Description
#E4 Register select port
#E5 Register access port
#E6-#E7 (read) 16-bit counter, little endian, running at 255682 Hz
#E6 (write) 16-bit counter reset (write to reset)

S1990 registers
Register Description
5 bit 6: Switch (0=right, 1=left)
6 bit 5: Processor mode (0=R800, 1=Z80)
bit 6: ROM mode (0=DRAM, 1=ROM)
14 Contains last but one byte written to memory
15 Contains last byte written to memory

It is rumoured the turboR R800 mode’s VDP slowdown can be disabled through one of the S1990’s registers. How, however, is still a mystery ^_^.

System flags

This register is basically a simple memory cell which is preserved after a reset. It is used on the MSX2+ to differentiate between a hard boot (power on) and a soft boot (reset button) by writing a value to it during the boot routine, and check for that value everytime the computer starts. On the turboR, it also indicates whether the Z80 or the R800 has to boot.

Port range Description
#F4 System flags, preserved after reset
bit 5: CPU boot mode (1=R800)
bit 7: Boot method (1=soft boot, doesn’t show start logo)

Memory Mapper registers

The Z80 used in the MSX has 64k of addressable memory. To be able to use more memory, memory mappers are used in MSX2 computers and above. A memory mapper divides the 64k of RAM into four 16k blocks called pages, into which up to 256 different memory segments can be mapped. Note that these segments are shared – it is possible to map a segment used in page 0 into page 1 as well.

Port range Description
#FC (write) Mapper segment for page 0 (#0000-#3FFF)
#FD (write) Mapper segment for page 1 (#4000-#7FFF)
#FE (write) Mapper segment for page 2 (#8000-#BFFF)
#FF (write) Mapper segment for page 3 (#C000-#FFFF)

Note that reading those registers is not reliable, and should not be done.

Detecting the amount of available memory can be done by writing a unique value into all mapper pages and iterating through them until you see repetition. If the repetition e.g. occurs after 8 pages, there is 128k of RAM available. Usually, you will want to do this with interrupts disabled and also want to restore the original values.

Note about DOS2: MSX-DOS2 provides a set of convenient memory management routines. In a DOS2 environment, you should not access the mapper registers directly, as this will cause various problems. The routines DOS2 offers are very fast, and there should be no reason not to use them.

Panasonic FS-A1FM Modem ROM

The Panasonic FS-A1FM computer has a built-in modem with firmware. On the back of the computer, there is a switch to enable the modem software. This firmware, including a memory-mapped I/O area in the #7FC0-#7FFF range, is located in slot 3-1. I do not know if there is a detection method.

Address range Description
#7FC4 bits 0-3: mapper for #4000-#5FFF area (uses slot 3-3 ROM pages #00-#0F)
bits 4-7: mapper for #6000-#7FFF area (RAM, don’t know how much)
#7FC6 bit 2: modem switch on back of case setting
#7FF9 bit 2: set activates ports 7FF0-7FF7

Secondary slot select register

Each primary slot can and often will be expanded into four secondary slots, also known as subslots. Just like a primary slot, a subslot can also be mapped to one of the four pages in main memory.

The subslot select register can be found at memory address #FFFF, and looks as follows:

Bits Description
0-1 Subslot for page 0 (#0000-#3FFF)
2-3 Subslot for page 1 (#4000-#7FFF)
4-5 Subslot for page 2 (#8000-#BFFF)
6-7 Subslot for page 3 (#C000-#FFFF)

When this register is read, it returns the complement of the previous value written.

It is important to note that the subslot register only affects the primary slot which is selected in page 3 (which the #FFFF address is in). This makes selecting a different subslot in e.g. page 1 a little less than trivial when page 1 doesn’t have the same primary slot as page 3. This involves switching page 1’s slot into page 3, selecting the desired subslot, and switching back the original slot into page 3. All this must be done with interrupts disabled and, logically, from an address not in the #C000-#FFFF range. Don’t forget to take care of the stack as well.

Usually it will be easier to use the BIOS-provided slot select routines (e.g. ENASLT or its DOS equivalent). While on the subject of the BIOS, the easiest method to determine whether a slot is expanded is to read out the EXPTBL system variables. Also, the BIOS maintains a mirror of the value of each primary slot’s subslot register in the SLTTBL system variables.

Grauw