Light pen
This page was last modified 02:20, 9 April 2019 by Gdx. Based on work by Mars2000you and Sd snatcher 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. 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. 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. This one is used internally by the MSX-BIOS. User software mustn't set it.
    • 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.


  • 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.

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 can be enabled with CALL ADJUST, an MSX-BASIC instruction that seems to be exclusive to the MSX2 machines manufactured by Daewoo. Similarly, PAD() will use the values 20 to 23 in this case (in stead of values 8 to 11 that are for an external light pen interface).

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
  • 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:

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

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

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

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, you 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