Light pen
This page was last modified 03:01, 13 October 2020 by Mars2000you. Based on work by Sd snatcher and Gdx and others.
Sanyo MPC-10 with Light pen

A light pen is an old form of touch screen technology, meant to be used with CRT screens.

The MSX supports this form of input device as a standard since the MSX2, up to the MSX2+ generation.

The MSX1 was released before this standard was adopted, and on MSX Turbo R the drivers for the light pen were removed from its BIOS as it was declared obsolete. To support the MSX1, each application must embed its own drivers for those machines, and use the BIOS for newer generations. On MSX Turbo R it's possible to load a driver directly in RAM and patch the BIOS calls to support it.


MSX-BIOS programmer interface

It's easy to read the Light pen using the MSX-BIOS. The programmer just need the following functions and variables:

  • GTPAD (00DBh)
    • Function 8 = Fetch data from the 1st light pen port (Sanyo standard). Return FFh if the pen was touching the screen, thus valid data was read. And 0 otherwise
    • Function 9 = 1st light pen X coordinate
    • Function 10 = 1st light pen Y coordinate
    • Function 11 = 1st light pen button status. FF=pressed, 0=not pressed.
    • Function 20 = Fetch data from the 2nd light pen port (V9938 internal). Return FFh if the pen was touching the screen, thus valid data was read. And 0 otherwise
    • Function 21 = 2nd light pen X coordinate
    • Function 22 = 2nd light pen Y coordinate
    • Function 23 = 2nd light pen button status. FF=pressed, 0=not pressed.
  • System variables
    • XSAVE (FAFEh): X coordinate fetched by NEWPAD
    • YSAVE (FB00h): Y coordinate fetched by NEWPAD
    • XOFFS (FAFFh)
      • b6~b0: Light pen X calibration offset
      • b7: A light pen interrupt occurred. Used internally by the MSX-BIOS
    • YOFFS (FB01h):
      • b6~b0: Light pen Y calibration offset
      • b7: reserved for future use. Do not set. Must be masked out from readings.

The calibration offsets are used to adjust the readings of the light pen to the correct screen coordinates. The software must offer an option to allow the user to do the calibration. It can be done easily by showing a point on the screen, asking the user to click over it, then calculate the offsets from the value read and set XOFFS/YOFFS accordingly. XOFFS and YOFFS are also shared by the two light pen interfaces. This means that if the programmer wants to support two simultaneous light-pens, he'll have to swap the values between readings.


  • GTPAD will internally redirect these functions to the routine NEWPAD (01ADh) in the subROM.
  • XSAVE and YSAVE are caches for used by NEWPAD to fetch coordinates from any devices it handles. They'll be overwritten by every call to a function of NEWPAD that fetches coordinates from the devices.
  • For external interfaces, YOFFS will be specific for vertical resolution settings (192 vs 212) and both XOFFS/YOFFS will be specific by frame rate settings (60Hz vs 50Hz). The possible combinations should always result in the same offsets for a given computer/TV set though.
  • The two light pens ports will share the same calibration variables: XOFFS and YOFFS. This means that to support two light pens simultaneously, you'll have to store the calibration values elsewhere, then load them each time before calling GTPAD.
  • On INIT, YOFFS for the Sanyo Lightpen will always be configured for a 60Hz/192 lines mode. When a different mode is selected, the programmer must adjust YOFFS according to this table:
    • 60Hz/212 lines: subtract 10 to YOFFS
    • 50Hz/192 lines: add 27 to YOFFS
    • 50Hz/212 lines: add 17 to YOFFS
    • When the program quits, be courteous and restore the original YOFFS value
  • The YOFFS behaviour for the internal V9938 light-pen interface must still be determined. On theory, the YOFFS value shouldn't need to be changed.

User interface design considerations

As you can notice from above, the light pen works just like an on-screen touchpad, and applications should be interchangeable between it and the MSX-Touchpad. The only subtle differences that applications developers should take into account are:

  1. While the light pen works over the real screen, the touchpad is a "blind" device. Thus, the light pen will not require any kind of "mouse pointer" , while the touchpad will require one.
  2. The light pen is designed to force the user to click the button to get a reading, while on the touchpad the user get a reading simply by touching the pad and the button can be pressed independently. On the light pen, to click the button without touching the screen the user must literally do that: click the light pen outside of the CRT glass area.

Underlying hardware

There are two standards for the light pen interface. The MSX BIOS abstracts the differences in their hardware.

User software programmers *must* read the touchpad only by using the BIOS GTPAD call as described in the beginning of the article. The low-level implementation details listed bellow are explained just to provide information for hardware designers, emulator programmers and the programmers of the C-BIOS.

MSX2 Internal interface

The internal light pen interface uses the V9938 VDP built-in interface for this kind of device. It's well documented on the V9938 Technical Handbook, by Yamaha.

Devices that feature this interface

With exception of the Sanyo devices, all these machines have been manufactured by Daewoo.

In all mentioned machines manufactured by Daewoo, the V9938 light pen interface is assigned to the BIOS 2nd light pen port, while an external MLP-01 or MLP-001, when connected, is assigned to the BIOS 1st light pen port. Both light pens can be used simultaneously.

The internal light pen interface is disabled by default can be enabled with CALL ADJUST, an MSX-BASIC instruction that seems to be exclusive to the MSX2 machines manufactured by Daewoo. This will enable the interface and set the calibration system variables XOFFS=0 and YOFFS=23, but will not enable the light-pen interrupts. Before the PAD()/GTPAD functions can be used, the light-pen interrupts will have to be enabled by setting the IE2 bit on VDP R#0.

Assembly programs can't rely on the CALL ADJUST instuction and will have themselves to enable the interface, its interrupts and set the XOFFS/YOFFS system variables accordingly.

It's recommended that the software disables the light-pen interface and interrupts again before quitting to the MSX-DOS or BASIC, otherwise the VDP status registers S#3 to S#6 won't be available to detect sprite collision coordinates, and that might cause other software to malfunction.

The Daewoo CPC-300E has the same motherboard as the CPC-300, but lacks both joystick port connectors and the light pen connector. They can be installed afterwards to enable those features.

It's said that the Sanyo MPC-X Graphic Expander Unit and the Sanyo MPC-27 computer also have the V9938 light pen interface, but this is yet to be confirmed. Maybe CALL ADJUST is also available with these Sanyo products.

External interface

The external interface has its own circuitry for scanning the light pen coordinates, regardless of the VDP used. In this context, "external" interface means "external to the VDP", as some MSX1 models feature this interface built-in.

Low-level protocol

The interface is controlled by four I/O ports, as follows:

I/O port Direction Description
B8h read

Light pen coordinate

  • b7~b0: Y coordinate b7~b0

Square sprite coordinate

  • b7~b0: Y coordinate b7~b0
B9h read

Light pen coordinate

  • b0  : Y coordinate b8
  • b7~b1: X coordinate b6~b0

Square sprite coordinate

  • b0  : Y coordinate b8
  • b7~b1: X coordinate b6~b0
  • b2~b0: X coordinate b9~b7
  • b3: Light pen button. 0=pressed
  • b4: Light pen interrupt flag. 0=Interrupt requested. Cleared by writing 0 to the bit3 of port BBh.
  • b5: Odd/even field (frame) indicator. Not in sync with the VDP even/odd frames. When 0, the Y coordinate must be decremented by 1.
  • b6: always 1
  • b7: Touch screen detection. 1=screen is touched

Square sprite coordinate

  • b2~b0: X coordinate b9~b7
BBhread Always 00h
  • b5  : 1=enable the square sprite
  • b3  : 1=enable interrupts, 0=disable. Default on wake up=1. isn't affected by a hard reset. Must be disabled and re-enabled again to aknowledge an interrupt.


1) Image boundaries at 60Hz on a CRT TV calibrated with very little overscan:

  • X full range is 40 to 308
  • Y full range is 24 to 252

2) Image boundaries at 50Hz on a CRT TV calibrated with very little overscan:

  • X full range is 43 to 312
  • Y full range is 28 to 302

3) Image boundaries for many VDPs (IOW, excluding the borders):

  • V99x8 image boundaries @60Hz with SETADJUST 0,0:
    • X range: 41 to 297
    • Y range:
      • 256x192 resolution: 37 to 229
      • 256x212 resolution: 27 to 239
  • V99x8 image boundaries @50Hz with SETADJUST 0,0:
    • X range: 42 to 298
    • Y range:
      • 256x192 resolution: 63 to 255
      • 256x212 resolution: 53 to 265
  • TMS9128 image boundaries:
    • X range: 41 to 297
    • Y range: 42 to 298
  • T6950 @50Hz image boundaries:
    • X range: 48 to 298
    • Y range: 62 to 254

5) Touch screen detection is implemented by detecting the passing CRT beam with a light sensor.

6) Interrupt requests are sent when the lightpen button is pressed.

7) The device powers-up completely disabled. Reading any of the device I/O ports wakes it up. This means that at this point a MSX1 or Turbo-R will freeze when you press the light pen against the CRT, because they have no light pen interrupt handler by default. To avoid this, the programmer must disable the interrupts on I/O port BBh. The device is kept awake after a hard reset.

8) The MSX2/2+ BIOS discards the coordinates read on even numbered frames.

9) The interface keeps the last valid read coordinates if the pen button is pressed and the beam isn't detected.

10) The "square sprite" is a 16x16 pixels white square bitmap generated by the MLP-001 that is superimposed over the MSX image only when the light-pen button is pressed. It's not related to the MSX VDP sprites, and its purpose is to enhance the light pen coordinates detection in dark areas of the screen. The sprite is only overlaid over the CVBS video output, which means that if the MSX RGB output is used, it won't be shown.

11) Korean MSX2s (CPC-300 & CPC400) do not use these I/O ports but use the penlight function of V9938.

Devices that feature this interface