GEM pages
Home -> GEM -> VDI

The Virtual Device Interface

In this document, I list assembly language and C interfaces to the VDI. The C prototypes are similar to those provided by the GEM Developer's Kit, version 3.0. Most of the C interfaces are declared to return WORDs, but in practice only a few of them return meaningful values. The symbol [!] indicates that a function behaves differently in different GEM versions.

Many of the low-numbered functions (eg: the "Cell array" functions, and the "locator/valuator/choice" input devices) are not implemented in most GEM drivers; they are relics of GSX and GKS.

This is still a work in progress. Some information is missing or requires additional explanation.

The VDI is used by GEM to communicate with its graphics drivers. It is used for all drawing functions.

The VDI is a superset of the Graphics System eXtension interface. GEM/2 for the PC provides a GSX interface; GEM/3 does not. It is made up of the GDOS, which loads drivers and performs Bezier drawing functions and coordinate transformations, and the drivers. Nearly all VDI functions passed to the drivers.

The GDOS lives in the file GEMVDI.EXE (in ViewMAX, VIEWMAX.EXE). GEM (but not ViewMAX) allows the VDI to use alternative AES modules:

GEMVDI /aesfile
This can be used to load the VDI without the AES:
GEMVDI /C:\COMMAND.COM
will load COMMAND.COM and wait until it terminates (ie, EXIT is typed).

The VDI is accessed by using INT 0EFh with CX=0473h and DS:DX=address of parameter block. The value in CX is not checked by the VDI, but should be used to ensure that the AES - or any other program chaining this interrupt - does not attempt to handle the call.

The parameter block format is:

        DD        CONTRL      ;Address of control array
        DD        INTIN       ;Address of integer input array
        DD        PTSIN       ;Address of pixel input array
        DD        INTOUT      ;Address of integer output array
        DD        PTSOUT      ;Address of pixel output array

The control array is:

CONTRL: 
        DEFW      function    ;Input:  Function number
        DEFW      #ptsin      ;Input:  Number of points in PTSIN array.
        DEFW      #ptsout     ;Output: Number of points in PTSOUT array.
        DEFW      #intin      ;Input:  Number of integers in INTIN array.
        DEFW      #intout     ;Output: Number of integers in INTOUT array.
XCTRL:  
        DEFW      special     ;Input:  For special uses.
        DEFW      handle      ;GEM driver handle
        DD        ptr1        ;First far pointer value
        DD        ptr2        ;Second far pointer value

[!] GEM/5 copies an additional word from CONTRL. I do not know which, if any, function uses this.

The coordinates used in PTSIN and PTSOUT are signed 16-bit integer values, 0-7FFFh - The x value comes first. Normally these are device units - the actual pixels on the screen, printer etc. GEM can also be set to scale the coordinates, so that 0-7FFFh is the full height or width of the screen (as in GSX).

In all calls except those where it is explicitly stated otherwise, handle is passed to the VDI on entry. If values for #ptsin and #intin are not supplied, these should be set to 0 on entry.


Function 1 - Open workstation

C Interface: Entered with:

Note: The supplied bindings set #intin to 103. But the sample programs only supply 11 values.

Returns:

This loads a device driver and initialises it. Valid device driver numbers are found in the ASSIGN.SYS file (GEM/1 or 2; they are assigned automatically in GEM/3 and later), and follow this pattern:

 1- 9: Screen
11-19: Plotter
21-29: Printer
31-39: GEM metafile.
The format of the INTIN array is:
INTIN:  DEFW        device_number
        DEFW        line_style
        DEFW        line_colour
        DEFW        marker_style
        DEFW        marker_colour
        DEFW        text_style
        DEFW        text_colour
        DEFW        fill_style
        DEFW        fill_index
        DEFW        fill_colour
        DEFW        pixel_mode  ;1 to use NDCs, 2 to use pixels
The INTOUT return array gives:
INTOUT: DEFW        [0] Screen width, device units
        DEFW        [1] Screen height, device units
        DEFW        [2] 0 if device can produce a precisely scaled image,
                        1 if it can't
        DEFW        [3] Width of a pixel, in thousandths of a millimetre.
        DEFW        [4] Height of a pixel, in thousandths of a millimetre.
        DEFW        [5] Number of character sizes, 0 for continuous sizing.
        DEFW        [6] Number of line styles.
        DEFW        [7] Number of line widths, 0 for continuous scaling.
        DEFW        [8] Number of marker styles.
        DEFW        [9] Number of marker sizes, 0 for continuous scaling.
        DEFW        [10] Number of fonts.
        DEFW        [11] Number of patterns.
        DEFW        [12] Number of hatch styles.
        DEFW        [13] Number of colours displayable at once.
        DEFW        [14] Number of General Drawing Primitives
        DEFS        [15] 20  ;General Drawing Primitive list.
                        ;-1 => End of list
                        ; 1 => Bar
                        ; 2 => Arc
                        ; 3 => Pie slice
                        ; 4 => Circle
                        ; 5 => Ellipse
                        ; 6 => Elliptical arc
                        ; 7 => Elliptical pie slice
                        ; 8 => Rounded rectangle
                        ; 9 => Filled rounded rectangle
                        ;10 => Justified graphic text
        DEFS        [25] 20        ;General Drawing Primitive attributes
                        ;-1 => End of list
                        ; 0 => Polyline
                        ; 1 => Polymarker
                        ; 2 => Text
                        ; 3 => Filled area
                        ; 4 => None
        DEFW        [35] 0 for black/white, 1 for colour.
        DEFW        [36] 0 if text rotation is not possible, 1 if it is.
        DEFW        [37] 0 if filled areas are not possible, 1 if they are.
        DEFW        [38] 0 if cannot read cell array, 1 if can.
        DEFW        [39] Number of colours in the palette.
                        ; 0 => More than 32767
                        ; 2 => Black and white
        DEFW        [40] Number of locator devices (mice, tablets, lightpens)
        DEFW        [41] Number of valuator devices (eg: a joystick throttle)
	DEFW        [42] Number of choice devices (eg: function keys on a 
                         keyboard)
        DEFW        [43] Number of string devices (ie: keyboards)
        DEFW        [44] Workstation type
                        ; 0 => Output only
                        ; 1 => Input only
                        ; 2 => Input and output
                        ; 3 => Segment storage
                        ; 4 => GEM metafile output.
The PTSOUT return array gives:
        
        DEFW        minimum character width, minimum character height
        DEFW        maximum character width, maximum character height
        DEFW        minimum line width,0
        DEFW        maximum line width,0
        DEFW        minimum marker width, minimum marker height
        DEFW        maximum marker width, maximum marker height.

(trust marker and character heights rather than widths).


Function 2 - Close workstation

C Interface: Entered with: Returns:

Function 3 - Clear picture

C Interface: Entered with:

Empties the buffer containing the current picture. This may be the screen, or buffered data for something like a printer.


Function 4 - Output graphics

C Interface: Entered with:

Ensures that all graphics have been displayed which should be displayed. On a device such as a printer, this will cause the picture to be printed.


Function 5 - Escape

Entered with: Returns: values vary.

Escapes are described in their own listing.


Function 6 - Draw a polyline

C Interface: Entered with: Returns: Nothing.

This draws a sequence of lines on the current device. It does not join the first and last point.


Function 7 - Plot a group of markers

C Interface: Entered with: Returns: Nothing.

Function 8 - Draw text

C Interface: Entered with: Returns: Nothing.

Function 9 - Draw a filled polygon.

C Interface: Entered with: Returns: Nothing.

This function does join the first and last points it is given (unlike the polyline).


Function 10 - Output colour index array.

C Interface: Entered with:
The ptr1 and ptr2 areas of CONTRL hold:
            DEFW    length of each row
            DEFW    number of elements used in each row
            DEFW    number of rows
            DEFW    mode
Mode is:
  1. replace
  2. OR
  3. XOR
  4. erase
Returns: Nothing.

This function is not implemented in any of the GEM drivers I have seen.


Function 11 - General Drawing Primitive

Entered with:

General Drawing Primitives are operations such as ellipses and rectangles.

ID=1: void v_bar(WORD handle, WORD xy[4]);
Filled bar. #ptsin=2; PTSIN gives diagonally opposite corners.
ID=2: void v_arc(WORD handle, WORD xc, WORD yc, WORD radius, WORD start_angle, WORD end_angle);
Arc. #ptsin=4, #intin=2. INTIN holds start angle and end angle in 10ths of a degree; PTSIN[0-1] holds coords of centre; PTSIN[6-7] holds (radius, 0). PTSIN[2-5] are zero.
ID=3: void v_pieslice(WORD handle, WORD xc, WORD yc, WORD radius, WORD start_angle, WORD end_angle);
Pie slice. As for arc.
ID=4: WORD v_circle(WORD handle, WORD xc, WORD yc, WORD radius)
Filled circle. #ptsin=3; PTSIN[0-1] hold coordinates of the centre; PTSIN[4-5] hold (radius, 0). PTSIN[2-3] hold (0,0).
ID=5: WORD v_ellipse(WORD handle, WORD xc, WORD yc, WORD xrad, WORD yrad);
Draw ellipse. #ptsin=2; PTSIN[0-1] hold coordinates of the centre, and PTSIN[2-3] holds (xradius, yradius).
ID=6: WORD v_ellarc(WORD handle, WORD xc, WORD yc, WORD xrad, WORD yrad, WORD sang, WORD eang);
Draw elliptical arc segment. As for the ellipse above, except that INTIN[0] holds start angle and INTIN[1] holds end angle.
ID=7: WORD v_ellpie(WORD handle, WORD xc, WORD yc, WORD xrad, WORD yrad, WORD sang, WORD eang);
Draw elliptical pie slice. Parameters as for the elliptical arc segment.
ID=8: void v_rbox( WORD handle, WORD xy[4]);
Rectangle with rounded corners. #ptsin=2; PTSIN gives diagonally opposite corners.
ID=9: void v_rfbox( WORD handle, WORD xy[4]);
Filled rectangle with rounded corners. #ptsin=2; PTSIN gives diagonally opposite corners.
ID=10: void v_justified( WORD handle, WORD x, WORD y, BYTE *string, WORD length, WORD word_space, WORD char_space)
Justified text. PTSIN[0-1] = coordinates at which to draw text; PTSIN[2-3] = (length, 0). INTIN[0] holds word spacing and INTIN[1] holds character spacing; INTIN[2] holds the text, one character per word. Thus #ptsin=2 and #intin = 2 + length of text.
ID=11: void v_etext( WORD handle, WORD x, WORD y, BYTE *string, offsets)
Exact parameters and effects are not known.
ID=12:
Non-filled bezier.
ID=13:
Enable/disable Beziers (v_bez_on() / v_bez_off()).

If #ptsin = 0, disable Bezier functions; else enable.

If enabled, this affects Escape 99 and functions 6 and 9.


Function 12 - Set text size

C Interface: Entered with: Returns:

Function 13 - Set text direction

C Interface: Entered with:

In practice many drivers only like their text at right-angles.


Function 14 - Set colour index (palette registers)

C Interface: Entered with:

Function 15 - Set line style

C interface: Entered with: Returns:

Function 16 - Set line width

C interface: Entered with: Returns:

Function 17 - Set line colour

C interface: Entered with: Returns:

Function 18 - Set marker type

C interface: Entered with: Returns:

Function 19 - Set marker height

C interface: Entered with: Returns:

Function 20 - Set marker colour

C interface: Entered with: Returns:

Function 21 - Set text font

C interface: Entered with: Returns:

Function 22 - Set text colour

C interface: Entered with: Returns:

Function 23 - Set fill style

C interface: Entered with: Returns: Fill style is 0-3: 0=transparent, 1=solid, 2=Pattern, 3=Hatch.

Function 24 - Set fill index

C interface: Entered with: Returns:

The fill index is used only with styles 2 & 3. Most GEM drivers support 12 hatches (1-12) and 24 patterns (1-24).


Function 25 - Set fill colour

C interface: Entered with: Returns:

Function 26 - Inquire colour representation (read palette)

C interface: Entered with:

Returns INTOUT[0]=Colour value, INTOUT[1-3]=RGB values 0-1000. The C binding stores the three RGB values in rgb[0-2].


Function 27 - Inquire cell array

C interface: Entered with:

Returns:

If INTOUT[x]=-1, the corresponding pixel could not be read.
The next few functions can be operated in Request mode or Sample mode. The information given for them is rather hypothetical, as GEM drivers don't tend to implement these calls (except for the String input, which is used to reaad the keyboard).

Function 28 - Read locator (eg tablet or mouse)

In Request mode:

C interface: Entered with:

Returns:

In Sample mode:

C interface: Entered with:

Returns:

If coordinates changed:
#ptsout=1 if coordinates changed; new coordinates in PTSOUT[0] [C returns this in *xout, *yout];
If key or button pressed:
#intout=1 if key or button pressed; and key or button in INTOUT[0] [C returns this in *term].
The C function call returns bit 0 set if the coordinates changed, and bit 1 set if a key or button was pressed.

Function 29 - Read valuator

A valuator is a device like a mouse, except that it only operates in one dimension - for example, a volume control or a throttle.

In Request mode:

C interface: Entered with: Returns:

In Sample mode:

C interface: Entered with:

Returns:

If value changed:
#intout=1; new value in INTOUT[0].
If key or button pressed:
#intout=2 if key or button pressed; final value in INTOUT[0] and key or button in INTOUT[1].

The C binding returns INTOUT[0] in *val_out, INTOUT[1] in *term, and #intout in *status.


Function 30 - Read choice

In Request mode:

C interface: Entered with:

Returns #intout=1, INTOUT[0]=choice (1-n) [C stores this in *out_choice].

In Sample mode:

C interface: Entered with:

Returns:

The C binding returns #intout, and sets *choice to INTOUT[0].


Function 31 - Read string

In Request mode:

C interface: Entered with:

Returns #intout=length of string returned, string in INTOUT.

The C binding returns the string as series of bytes, 0-terminated, at "string".

In GEM, if the device number is negative, then keyboard scancodes are returned as well as ASCII. In each INTOUT word, the high byte is the scancode and the low byte is the ASCII value.

In Sample mode:

C interface: Entered with:

Returns #intout=length of string returned, string in INTOUT. The C binding returns a 0-terminated string at "string", and its length as a word.

In GEM, if the device number is negative, then keyboard scancodes are returned as well as ASCII. In each INTOUT word, the high byte is the scancode and the low byte is the ASCII value.


Function 32 - Set writing mode

C interface: Entered with:

Note: "background" is the second colour used in dashed lines etc. When such a line is being drawn, the dashes are drawn as "foreground" areas and the gaps as "background" areas. Modes are:

  1. Replace. "Foreground" and "background" areas are replaced ("background" areas with colour 0).
  2. Transparent. "Foreground" areas are replaced but "background" areas stay the same.
  3. XOR. "Foreground" areas are XOR'ed with previous colour; "background" areas stay the same.
  4. Erase. "Foreground" areas are written in GSX colour 0; "background" areas stay the same.
Returns the previous mode in INTOUT[0]. [C returns this from the function call].

Function 33 - Set input mode

C interface: Entered with:

GSX stopped here. Calls from here are only present in the VDI, though the next few calls can be accessed from the GSX-86 interface present in GEM/1 and GEM/2.


Function 34

This function is a no-op in all GEM drivers that I have examined.


Function 35 - Get line attributes

C interface: Entered with: Returns:

[The C binding returns these values in attributes[], with line width in attributes[3]. You would need to write a modified binding to get at the line start and end styles.]


Function 36 - Get marker attributes

C interface: Entered with: Returns:

[The C binding returns these values in attributes[], with marker height in attributes[3]].


Function 37 - Get fill attributes

C interface: Entered with: Returns:

[The C binding returns these values in attributes[].]


Function 38 - Get text attributes

C interface: Entered with: Returns:

[The C binding returns these values in attributes[], with the minimum and maximum character sizes in attributes[7] and attributes[9] respectively.]

[!] The ViewMAX VGA driver does not support this call; you can check for this by seeing if it returned any integers. The normal call returns 6 integers but ViewMAX returns 0. This missing call will cause some programs (eg: RCS.APP) to crash with Divide by Zero errors when the ViewMAX driver is used.


Function 39 - Set text alignment

C interface: Entered with: Returns:

VDI calls after this point should not be accessed from the GSX-86 interface (INT E0). The VDI interface (INT EF) should be used.


Function 100 - Open virtual workstation

C Interface: Entered with:

Returns:

This is used to create a second and subsequent graphics context for an already- open driver. Typically, GEM will open the screen device using function 1, and the applications and desk accessories running under it will use this function to have their own graphics context for the display.

Current VDIs allow eight graphics contexts to be open at a time.

Virtual workstations opened with this call must be closed using function 101.


Function 101 - Close virtual workstation

C Interface: Entered with: Returns:

Function 102 - Query extended information

C Interface: Entered with: Returns:

If INTIN[0] was 0, this returns the same data as function 1. If INTIN[0] was 1, it returns a different set of data:

INTOUT: DEFW    Type of alpha/graphic controllers
                0 => Not a screen
                1 => Separate text/graphic controllers and
                    separate screens (eg: CGA+MDA dualhead)
                2 => Separate controllers, common screen 
                3 => One controller, separate screen buffers
                4 => One controller, one screen buffer
        DEFW    No. of background colours (always 1?)
        DEFW    Text styles supported (0Fh for printers, 1 for screen)
        DEFW    1 if can scale rasters, else 0
        DEFW    No. of planes
        DEFW    1 if palette based, 0 if true colour
        DEFW    Number of 16x16 raster operations per second
        DEFW    1 if v_contourfill() is provided, else 0
        DEFW    Character rotation capability
                0 => No
                1 => 90 degree angles only
                2 => Any angle
        DEFW    No. of writing modes
        DEFW    Highest input mode
                0 => No input
                1 => Request only
                2 => Request and sample
        DEFW    1 if text alignment is possible, else 0
        DEFW    1 if device can ink, else 0
        DEFW    Rubber banding
                0 => No rubberbanding
                1 => Lines only
                2 => Lines and rectangles
        DEFW    Maximum size of PTSIN (in vertices); -1 for unlimited
        DEFW    Max size of INTIN (in words); -1 for unlimited
        DEFW    No. of buttons on mouse
        DEFW    1 if styles are available for wide lines
        DEFW    1 if writing modes are available for wide lines
        DEFW    1 if clip rectangle set, else 0
        DEFW    ?   ;[20] Unknown
        DEFW    ?   ;[21] Unknown
        DEFW    ?   ;[22] Unknown
        DEFW    ?   ;[23] Unknown
        DEFW    ?   ;[24] Unknown
        DEFW    ?   ;[25] Unknown
        DD          Size of offscreen backing buffer. If this is nonzero, then 
                    the graphics card is assumed to have a buffer outside 
                    conventional memory, which can be used by vro_cpyfm(). 
                    The GEM 3.x AES supports this buffer mechanism and will 
                    use it in preference to allocating a buffer in main memory.
;
PTSOUT: DEFW    x,y ;Top left-hand corner of clip rectangle
        DEFW    x,y ;Bottom right-hand corner of clip rectangle

Function 103 - Contour fill

C Interface: Entered with: Returns: Nothing.

This function is not implemented in any of the GEM/3 screen or printer drivers.


Function 104 - Enable/disable fill perimeter

C Interface: Entered with: Returns: Nothing.

Function 105 - Get pixel value

C Interface: Entered with: Returns:

This function is not implemented in any of the GEM/3 screen or printer drivers.


Function 106 - Set text effects

C Interface: Entered with: Returns: The actual effect bits that were used.

Function 107 - Set text size in points

C Interface: Entered with: Returns:

Function 108 - Set line end style

C Interface: Entered with: Returns: Actual styles selected in INTOUT.

Styles should be 0 (square), 1 (arrow) or 2 (circle).


Function 109 - Copy raster opaque

C Interface: Entered with: Returns: Nothing.

This will copy a rectangular area from the source bitmap to the destination bitmap. It should be used for copying between bitmaps with the same colour depth.


Function 110 - Transform bitmap

C Interface: Entered with: Returns: Nothing.

This will transform a bitmap from device-independent format to device - dependent, or vice versa.


Function 111 - Set cursor shape

C Interface: Entered with: Returns: Nothing.

Function 112 - Create user-defined pattern

C Interface: Entered with: Returns: Nothing.

Function 113 - Create user-defined line style

C Interface: Entered with: Returns: Nothing.

Function 114 - Draw a filled rectangle

C Interface: Entered with: Returns: Nothing.

No border will be drawn round the rectangle.


Function 115 - Query input mode

C Interface: Entered with: Returns: INTOUT[0] = mode (0=request 1=sample)

Function 116 - Get text extent

C Interface: Entered with: Returns: PTSOUT[0] = (X, Y) size of string.

Function 117 - Get character size

C Interface: Entered with: Returns:

Function 118 - Exchange timer vector

C Interface: Entered with: Returns:

On a PC, this sets the INT 0x1C handler.


Function 119 - Load fonts

C Interface: Entered with: Returns:

The "Select" parameter to the C interface does not appear to be used.


Function 120 - Unload fonts

C Interface: Entered with: Returns: Nothing.

Function 121 - Copy raster transparent

C Interface: Entered with: Returns: Nothing.

This will copy a rectangular area from the source (mono) bitmap to the destination bitmap, drawing it in the colours provided.


Function 122 - Show mouse pointer

C Interface: Entered with: Returns: Nothing.

If the "reset flag" is nonzero, displays the cursor and sets the "hide count" to 0. If not, decrements the "hide count" and if it is 0, shows the cursor.


Function 123 - Hide mouse pointer

C Interface: Entered with: Returns: Nothing.

Hides the cursor and increases the "hide count".


Function 124 - Get mouse position

C Interface: Entered with: Returns:

Function 125 - Exchange button vector

C Interface: Entered with: Returns:

The button code will be called when a mouse button is clicked. The mouse button status is passed to it in AX (x86) / D0 (680x0); Bit 0 for the left button, bit 1 for the right, bit 2 for the middle.


Function 126 - Exchange motion vector

C Interface: Entered with: Returns:

The code will be called when the mouse pointer is moved. It is entered with BX = mouse X-coordinate and CX = mouse Y-coordinate (D0 and D1 for 680x0).


Function 127 - Exchange cursor draw vector

C Interface: Entered with: Returns:

The code is entered with BX = mouse X-coordinate and CX = mouse Y-coordinate (D0 and D1 for 680x0).


Function 128 - Get keyboard shift state

C Interface: Entered with: Returns:

Function 129 - Set clipping rectangle

C Interface: Entered with: Returns: Nothing.

Function 130 - Get font name

C Interface: Entered with: Returns:

[!] In GEM/5, this function returns nothing for font index 0 or 1; for other indices, the font scaler is used to return data. A good test for a GEM/5 VDI would be to do a vqt_name() on font 1, and see if it returned any values - if it did not, GEM/5 is running.


Function 131 - Get font info

C Interface: Entered with: Returns:

This returns information for the currently selected font.

"weight" (in PTSOUT[1]) is 0 if the font is not monospaced.

"left offset" and "right offset" are the amounts the character slants when it is skewed.

The C binding returns distances[] = {bottom, descent, half, ascent, top} and effects[] = {weight, left offset, right offset}.


Function 132 - Justified text

C Interface: Entered with: Returns:

Functions 133-135

These functions exist in the GEM/4 screen driver, but have no effect.

Function 136

GEM/4: Based on v_pline() but takes extra integer parameters.

Function 137

GEM/4: Based on v_fillarea() but takes extra integer parameters.

Function 142

GEM/4: Takes an integer parameter.

Function 143

GEM/4: Takes an integer parameter that is at most 100.


Function -1 - GDOS escape

These are functions handled by the GDOS, where no driver handle is required.

Entered with:

[!]GEM/2 only provides subfunction 1.

Subfunctions are

  1. Page out GEM to run a DOS (or CP/M-86) program. Only a stub of the VDI will remain in memory, and no VDI or AES functions will be available.
    Entered with INTIN[0-1] = far pointer to INT 21/AX=4B00 parameter block and INTIN[2-3] = address of 0-terminated error message.
  2. Font extension. Entered with 3 words in INTIN, which are the file type to use for fonts (normally 'F','N','T').
  3. PD list. Returns path to GDOS in INTOUT and driver paths at ptr1.
  4. Driver list. Enter with INTIN[0] = device ID and INTIN[1] = information requested:
    1. Full driver filename including path
    2. Short driver description
    3. Long driver description
    4. Driver font search path
    5. Driver patch bytes

    C interface: v_get_driver_info(WORD device_id, WORD info_select, BYTE *info_string);

    Returns information in INTOUT, and #intout set accordingly.

  5. Get font info. Returns INTOUT[0] = segment of font buffer and INTOUT[1] = size of font buffer in bytes.
  6. Set App buffer address and size. Entered with INTIN[0-1] = far pointer to buffer and INTIN[2] = buffer size in paragraphs. Used in GEM/3 for beziers.
  7. (GEM/4) Fill INTOUT with a 0-terminated ASCII string.
  8. (GEM/4) Fill INTOUT with a 0-terminated ASCII version number (for GEM/4, this is "3.91".

Return to archive listing