> # A Grail Millennium Project

> # White Paper

> History | Preface | TOC

> ##### This document is maintained by the author, Lewis A. Sellers, somewhere in the mountains of East Tennessee, the United States of America. It is an informal technical document for a works in progress project called Grail Millennium, or fully, The Minimal Operating System of Object Class Interfaces Holy Grail for the Millennium. In other words, for a new, easy to use, long-lived operating system.

> ## Copyright Notice

> ##### This document and all material therein, unless otherwise stated, is Copyright © 1995,1996, Lewis A. Sellers. All Rights Reserved. Permission to distribute this document, in part or full, via electronic means (emailed, posted or archived) or printed copy are granted providing that no charges are involved, reasonable attempt is made to use the most current version, and all credits and copyright notices are retained.

> ## Distribution Rights

> ##### All requests for other distribution rights, including incorporation in commercial products, such as books, magazine articles, CD-ROMs, and or computer programs should be made to the primary author Lewis Sellers.

> ## Warranty and disclaimer

> ##### This document is provided as is without any express or implied warranties. This is a work-in-progress, and as such will contain outdated or as yet uncorrected or substanstiated assumptions. The author, maintainer and/or contributors assume no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein.

> ## WWW Home Sites

> ##### You can currently find home sites to this project at
> - http://www.dwc.edu/grail/
> - http://www.usit.net/public/bcannon/grail/
> If you can not reach them, or they seem to be down, do a key word search on AltaVista, Lycos, or the Web Crawler search engines.

> ## Contact Email

> ##### The primary author of Grail Millennium should be reachable at lsellers@usit.net.

> Preface | TOC

> # OCI/Spec | DOS16/32 L E G A C Y

> ### DESIGNER

> Lewis A. Sellers (aka Minimalist) lsellers@usit.net

> ### CRITIQUED BY

> - Akintunde Omitowoju tunde@housing.east-tenn-st.edu

> ### DRAFTS

> - 5/29/96 rough revision 0.00 (the first new document for Grail resurgence 3)

> ### INSPIRATIONAL MUSIC for this Document:

> - Pinion -- PN-WATER.S3M
> - Pinion -- PN-FORCE.S3M
> - Pinion -- PN-WINTR.S3M
> - Pinion -- PN-AZURE.S3M
> - THE CURE - Burn

> TOC

> # (a0.01)

> ### Preface

> This group has been around in one form or another, under one name or another throughout most of the project's history. The original idea of saving and salvaging the past came about simply because important software that I'd wrote long ago on other platforms had since degraded beyond recovering. I miss it.

> While researching computer history for "On the Evolution of Machine, Mind and Man" I ran across a page on the web concerning the late Stephen Cabriney, and his attempts to save all (and I mean all) computer software and hardware that had been. Thus it seemed more than fitting the code-name of this group should carry his name on.

> # Table of Contents

> Legal Notices | Who gets sued and why
> History | Changes and who made them
> Preface | About the FS and the people that make it

> Overview | An Overview of the DOS Legacy

> TOC

> # DOS16/32 Legacy

> "The count of lawyers in a society is good indication of how immoral it is."
> --min 6-2-96 445a

> ### Um, what is the DOS32 "Legacy" BRIDGE METAPHOR?

> We all remember DOS of course. Most of the best and fastest IBM PC games were written for it and probably will be so for years to come. DOS32 is a "bridge metaphor" that allows most 32-bit DOS programs using DPMI and VESA to run under Grail without change.

> When a 32-bit DOS program is ran directly, or via a link the DOS32 BRIDGE METAPHOR object is brought into memory, all other programs are gracefully suspended, an interrupt translation code bridge is created, and the program given exclusive run status. That is, to be safe, all other programs are shut down and only 32-bit DOS programs may be run until........

> DOS32 can run 32-bit binary application .EXE files and the script .BAT file. It can NOT run the old 16-bit 64kb-limited .COM files.

> The COMMAND-LINE Metaphor

> DOS32, if invoked without the name of a DOS program or link with environment definitions will go into it's default internal COMMAND-LINE mode. As you might guess, this means that you get the message:

> >     GRAIL Operating System -- DOS32 Bridge Metaphor v0.00 build 11395
> >     Copyright (c) 1996 by The Minimalist Group. All Rights Reserved.
> >     20,971,520 bytes total memory.
> >     13,373,200 bytes available for DPMI/VCPI Emulation.
> >     1 MB reserved for conventional thunking.

> When a program started in the command-line mode ends, you return to the command-line. Otherwise DOS32 removes itself from memory and Grail operations immediately return to normal.

> Can we run ancient 16-bit DOS programs too?

> Yes. But such programs will run in a highly protected virtual machine emulation similar to the DOS32 structure. The noticeable differences will be that only XMS or EMS memory calls will be available. The entire 1MB "conventional" memory area will be available excepting the emulated text and video areas at 0A000h to 0BFFFFh, the first 4kb, and the memory area just below 1MB used by the bridge emulation ROM/DOS code. In short, you should never have a problem with "insufficient conventional memory" errors. You will always have 651,264 bytes of "conventional" memory to work with, and perhaps a couple hundred more kbs of "UMB".

> Can I run DOS32 on processors other than the X86 line?

> Um, probably not anytime soon. It's not beyond reason to expect a DOS16 emulation at some point however. We'll see.

> Of Historical Note

> It seems a little ironic that as I near the end the detailed planning of Grail that we have arrived at the DOS32 Metaphor. For those few of you who remember, Grail, back before it was called such, was to be simply a video/audio setup program which would create a set of text files any DOS application could read and know what your video/audio preferences were without asking you over and over again.

> And here we are again. Full circle.

> TOC

> # THE CODE BRIDGE:

> ## INTERFACING WITH LEGACY SOFTWARE

> ### BY | Lewis Sellers lsellers@usit.net

> System Timer 08h

> COM2 COM4

> COM1 COM3

> The Virtual Memory Map

> TOC

> # The Program Itself

> ## BY | Lewis Sellers lsellers@usit.net

> DOS32 "Legacy" resides in its own folder as do all other metaphors. The "path" from DOS is automatic under DOS32. When a program is ran, it is first looked for in the current directory, then the DOS32 root "Root\", then the DOS32 utility "Utility\".

> TOC

> # The Command-line Interface

> ### BY | Lewis Sellers lsellers@usit.net

> DOS32 provides an integrated command-line interface similiar, though not equivilent to various incarnations of PC-DOS, DR-DOS and/or MS-DOS. Part of DOS32 resides in a virtual 1MB near what would be the top of the BIOS area, and the rest lies in normal flat Grail space.

> CHANGE FILE ATTRIBUTES

> ATTRIB filename

> /?

> /help

> CHANGE CURRENT DIRECTORY

> CD

> /?

> /help

> ..

> \

> CD by itself shows the current directory (which is rather redundant, since DOS32 ALWAYS shows you this at the prompt anyway).

> SHOW FILES IN DIRECTORY

> DIR

> /?

> /help

> /p page

> /w wide

> /l long

> /formatted=

> /exe, program files .COM, .BAT, .EXE

> /dir, directories

> >     Date       Time     Flags    Type  Size     Name
> >     28-04-1996 15:00.00 -------- -     128kb    This is a file
> >     25-04-1996 17:12.13 -------- -     1.34mb   A real big file
> >     01-05-1996  1:59.05 -------O -     438kb    TEST.DOC
> >     07-11-1993 13:15:44 -------O EXE32 235kb    DOOM.EXE
> >     20-09-1986  3:34:11 -------O EXE16 127kb    Opais.exe
> >     20-09-1986 3:37:17 --------0 BATCH 577b     RUNME.BAT

> COPY FILES

> COPY filename filename

> /?

> /help

> /all

> /skip

> MOVE FILES

> MOVE filename filename

> /?

> /help

> /all

> /skip

> MASS FILE COPY

> XCOPY

> /?

> /help

> /all

> /skip

> MASS FILE MOVE

> XMOVE

> /?

> /help

> /all

> /skip

> FILE DELETE

> DEL filename

> /?

> /help

> INCLUSIVE SUBDIRECTORY FILE DELETE

> DELTREE folder

> /?

> /help

> /all

> COMPRESS FILES AND DIRECTORY OF FILES

> ZIP zipfile files

> /?

> /help

> /s subdirectory

> /a absolute path

> /c0 no-compression

> /cn normal compression

> /ce extra compression

> UNCOMPRESS FILES

> UNZIP zipfile

> /?

> /help

> /a absolute path

> VIDEO CAPABILITIES

> VIDEO

> /?

> /help

> /graphics

> /mpeg

> /vrheadset

> /all

> /formatted=

> /acceleration

> /raw

> /situation=default, text, silent_movie, movie, virtual_reality, photo, magazine, cad, console

> This serves two purposes. The first is to let you see what video modes are available under your sytem. Entering VIDEO with no parameters will give you something like the following:

> ## Text

> Name | Columns | Lines | Chars | Bitwidth | Back | Fore | Type | Atrrib
> --- | --- | --- | --- | --- | --- | --- | --- | ---
> 3h | 80 | 25 | 8 | 16 | 16 | 16 | Fixed
> 60 | 80 | 50 | 8 | 16 | 16 | 16
> | 80 | 60
> | 132 | 25
> | 132 | 43
> | 132 | 60

> ## Graphics

> Name | Width | Height | Depth | Bitdeapth | RGB | Type | Format
> --- | --- | --- | --- | --- | --- | --- | ---
> 13h 320 200 8 8 666 CLUT
> 101h 640 480 8 8 666 CLUT
> 110h 640 480 24 24 888 DIRECT RGB
> 110ha 640 480 24 32 888 DIRECT RGBa

> You can also limit the information to a selected subtype such as MPEG or VR-HEADSET compatible modes.

> The second purpose is to SELECT your preferred default modes for a few situations. This defaults are saved in the file VIDEO.INF which resides at DOS32's virtual root directory. The /situation switches here deserve a little explaination. Simply put, for each of the following you can define a specific video mode that you like:

> default

> text, for text-only displays, such as for reading books on computer.

> movie, for watching full-motion movies with a sound-track

> silent_movie, for watching movies that are silent, or get their audio for an external source

> virtual_reality, for virtual reality or first-person graphics (ie, DOOM)

> action_virtual_reality, same as virtual_reality, but when speed is more important than quality of the rendering

> photo, for looking at detailed images such as photos, maps and fine-art

> cad, for detailed design work such as CAD or editing Doom/Quake levels :)

> magazine, for reading electronic versions of magazines or Adobe PDFs, etc

> console, normal a text mode screen such as 80x50

> /Situation has two arguments. The first is the mode type, and the second determines the scaling factor if any. 0 is no scaling. -1 is to scale close to full screen using integer scaling factors (best). -2 is scale to full screen. All others imply a times scaling factor such as 2, 3 or 4 if needed. This may or may not mean anything to an application.

> AUDIO CAPABILITIES

> AUDIO

> /?

> /help

> /digital

> /midi

> /fm

> /all

> /formatted=

> `Digital`

> `Bits Khz Cmprs Buffer Port IRQ DMA`

> `24 44 None 512k 220 5,10 1,5`

> GMIDI

> ?

> CONTROLLER CAPABILITIES

> CONTROL

> /?

> /help

> /formatted=

> /keyboard

> /joystick

> /mouse

> /vrglove

> /lightpen

> /tablet

> /situation=default, text, movie, first-person, map, magazine

> `Keyboard`

> `104 keys`

> `Mouse`

> `3-button Serial, Serial 1`

> `Joystick`

> `4-button Gravis`

> You can select which devices you wish active in any of the defined situations (modes), as well as thier order of important to you.

> COMMUNICATIONS CAPABILITIES

> COM

> /?

> /help

> /formatted=

> `Modem`

> `Name bs Comprs Buffer Type`

> `#1 14,000 yes 32 16550A`

> `Serial Null-Modem`

> `Name bs Comprs Buffer Type`

> `#1`

> `#2`

> `IPX`

> `Name bs`

> `#1`

> EMULATION PERFORMANCE SETTINGS (BIOS/ROM/DOS)

> EMULATE filename, switches...

> /?

> /help

> /all

> /joystick

> /mouse

> /keyboard

> /floppy

> /hd

> /cd-rom

> /printer

> /svga

> /vga

> /ega

> /cga

> /mono

> /speaker

> /digitalaudio

> /gmidi

> /xms

> /ems

> /dpmi

> /vcpi

> /audio

> /video

> /memory=n, free, real/virtual, min/max

> /ports=free, unrestrict x... , restrict x...

> /save=filename

> /application=filename

> You can turn emulation on or off by using the keyboards "on" or "off" after each switch.

> DOS32 METAPHOR HELP

> HELP topic

> /?

> /help

> TEXT EDITOR

> EDIT filename

> /?

> /help

> A simple single file text editor, using ASCII, UNICODE and ANSI.

> TEXT VIEWER

> VIEW filename

> /?

> /help

> A simple text file viewer using ESC, and arrow/paging keys. You can use plain ASCII, UNICODE and ANSI codes.

> TOC

> # DPMI 0.9, EMS, XMS

> ### BY | Lewis Sellers lsellers@usit.net

> Under DOS32 memory is of two flavours: DPMI extended and conventional. Conventional memory resides as a 1MB space. The high-memory area is NEVER available in this implementation.

> ### XMS Extended Memory Support

> Legacy supports XMS while in 16-bit mode, though not while in the 32-bit compatability mode. There are a few very important things you must know about XMS emulation. First off, the emulated version is 3.00, and the Super Extended Memory Support functions are also available, which is fairly standard. A major difference is that High Memory Area (HMA) and A20-Line functions are completely ignored. If you try to use them, you will recieve back messages to the effect that yes, A20 is enabled (permanently), but HMA does not exist. This normal under Legacy emulation, and will not change.

> ### All XMS functions are re-entrant.

> The allocation of a zero length extended memory buffer is permissible so as to allow reserving a handle for private use.

> When Legacy comes up, the message "High Memory Area Unavailable" appears for reasons that are obvious to the experienced XMS user.

> The HIMEM.SYS emulator has 256 extended memory handles available for use. Each handle requires 6 bytes of DOS emulation memory. This far exceeds the original DOS design specifications of XMS.

> ### ERROR CODE INDEX:

> If AX=0000h when a function returns and the high bit of BL is set,

> >     BL=80h if the function is not implemented
> >     82h if an A20 error occurs
> >     8Eh if a general driver error occurs
> >     8Fh if an unrecoverable driver error occurs
> >     90h if the HMA does not exist
> >     91h if the HMA is already in use
> >     93h if the HMA is not allocated
> >     94h if the A20 line is still enabled
> >     A0h if all extended memory is allocated
> >     A1h if all available extended memory handles are in use
> >     A2h if the handle is invalid
> >     A3h if the SourceHandle is invalid
> >     A4h if the SourceOffset is invalid
> >     A5h if the DestHandle is invalid
> >     A6h if the DestOffset is invalid
> >     A7h if the Length is invalid
> >     A8h if the move has an invalid overlap
> >     A9h if a parity error occurs
> >     AAh if the block is not locked
> >     ABh if the block is locked
> >     ACh if the block's lock count overflows
> >     ADh if the lock fails
> >     B0h if a smaller UMB is available
> >     B1h if no UMBs are available
> >     B2h if the UMB segment number is invalid

> ### PREPARING TO USE XMS:

> >     To Call:
> >     	AH=43h
> >     	INT 2Fh
> >     Return:
> >     	ES:BX driver function control address

> Under Legacy, XMS will always be available while in 16-bit mode, but of course older programs will not be aware of this. They will determine if an XMS driver is installed by setting AH=43h and AL=00h and then executing INT 2Fh. 80h will always be returned in AL.

> This function is called to access all of the XMS functions. It should be called with AH set to the number of the API function requested. The API function will put a success code of 0001h or 0000h in AX. If the function succeeded (AX=0001h), additional information may be passed back in BX and DX. If the function failed (AX=0000h), an error code may be returned in BL. Valid error codes have their high bit set. Developers should keep in mind that some of the XMS API functions may not be implemented by all drivers and will return failure in all cases.

> Programs should make sure that at least 256 bytes of stack space is available before calling XMS API functions.

> ### Get XMS Version Number

> >     To Call:
> >     	AH = 00h
> >     Returns:
> >     	AX = XMS version number
> >     	BX = Driver internal revision number
> >     	DX = 0000h, meaning HMA does not exist
> >     ERRS:
> >     	None

> This function returns a 16-bit BCD number in register AX representing the version of the DOS Extended Memory Specification which is emulated. This is currently set at 3.00, e.g. AX=0300h.

> ### Request High Memory Area

> >     To Call:
> >     	AH = 01h
> >     RETURNS:
> >     	AX = 0001h if the HMA is assigned to the caller, 0000h otherwise
> >     	BL = 90h if the HMA does not exist
> >     This function always returns BL=90h.

> ### Release High Memory Area

> To Call:

> AH = 02h

> RETURNS:

> AX =0000h otherwise

> BL = 90h if the HMA does not exist

> ### Global Enable A20

> To Call:

> AH = 03h

> RETURNS:

> AX = 0001h if the A20 line is enabled

> BL = 82h if an A20 error occurs

> ### Global Disable A20

> To Call:

> AH = 04h

> RETURNS:

> AX = 0000h if a20 enabled

> BL = 94h if the A20 line is still enabled

> This function attempts to disable the A20 line, but will always fail.

> ### Local Enable A20

> To Call:

> AH = 05h

> RETURNS:

> AX = 0001h if the A20 line is enabled

> BL = 82h if an A20 error occurs

> Local Disable A20

> To Call:

> AH = 06h

> RETURNS:

> AX = 0000h otherwise

> BL = 94h if the A20 line is still enabled

> Query A20

> To Call:

> AH = 07h

> RETURNS:

> AX = 0001h if the A20 line is physically enabled

> BL = 00h if the function succeeds

> This function is supposed to check to see if the A20 line is physically enabled. Since under Grail this is ALWAYS so, the function will always succeed and return AX=01h.

> Query Free Extended Memory

> To Call:

> AH = 08h

> RETURNS:

> AX = Size of the largest free extended memory block in K-bytes

> DX = Total amount of free extended memory in K-bytes

> BL = A0h if all extended memory is allocated

> This function returns the size of the largest available extended memory block allocated to the DOS emulator.

> Allocate Extended Memory Block

> To Call:

> AH = 09h

> DX = Amount of extended memory being requested in K-bytes

> RETURNS:

> AX = 0001h if the block is allocated, 0000h otherwise

> DX = 16-bit handle to the allocated block

> BL = A0h if all available extended memory is allocated

> A1h if all available extended memory handles are in use

> This function attempts to allocate a block of the given size out of the pool of free extended memory. If a block is available, it is reserved for the caller and a 16-bit handle to that block is returned. The handle should be used in all subsequent extended memory calls. If no memory was allocated, the returned handle is null.

> Extended memory handles are, as per the original design, a limited resources. There is a total maximum availablity of 256 such handles. When all of the emulators handles are in use, any free extended memory is unavailable.

> Free Extended Memory Block

> To Call:

> AH = 0Ah

> DX = Handle to the allocated block which should be freed

> RETURNS:

> AX = 0001h if the block is successfully freed, 0000h otherwise

> BL = 80h if the function is not implemented

> A2h if the handle is invalid

> ABh if the handle is locked

> This function frees a block of extended memory which was previously allocated using Function 09h (Allocate Extended Memory Block). Programs which allocate extended memory should free their memory blocks before

> exiting. When an extended memory buffer is freed, its handle and all data

> stored in it become invalid and should not be accessed.

> Move Extended Memory Block

> To Call:

> AH = 0Bh

> DS:SI = Pointer to an Extended Memory Move Structure (see below)

> RETURNS:

> AX = 0001h if the move is successful, 0000h otherwise

> BL = 80h if the function is not implemented

> 82h if an A20 error occurs

> A3h if the SourceHandle is invalid

> A4h if the SourceOffset is invalid

> A5h if the DestHandle is invalid

> A6h if the DestOffset is invalid

> A7h if the Length is invalid

> A8h if the move has an invalid overlap

> A9h if a parity error occurs

> Extended Memory Move Structure Definition:

> ExtMemMoveStruct struc

> Length dd ? ; 32-bit number of bytes to transfer

> SourceHandle dw ? ; Handle of source block

> SourceOffset dd ? ; 32-bit offset into source

> DestHandle dw ? ; Handle of destination block

> DestOffset dd ? ; 32-bit offset into destination block

> ExtMemMoveStruct ends

> This function attempts to transfer a block of data from one location to

> another. It is primarily intended for moving blocks of data between

> conventional memory and extended memory, however it can be used for moving

> blocks within conventional memory and within extended memory.

> If SourceHandle is set to 0000h, the SourceOffset is interpreted

> as a standard segment:offset pair which refers to memory that is

> directly accessible by the processor. The segment:offset pair

> is stored in Intel DWORD notation. The same is true for DestHandle

> and DestOffset.

> SourceHandle and DestHandle do not have to refer to locked memory

> blocks.

> Length must be even. Although not required, WORD-aligned moves

> can be significantly faster on most machines. DWORD aligned move

> can be even faster on 80386 machines.

> If the source and destination blocks overlap, only forward moves

> (i.e. where the source base is less than the destination base) are

> guaranteed to work properly.

> This function is guaranteed to provide a reasonable number of

> interrupt windows during long transfers.

> Lock Extended Memory Block

> To Call:

> AH = 0Ch

> DX = Extended memory block handle to lock

> RETURNS:

> AX = 0001h if the block is locked, 0000h otherwise

> DX:BX = 32-bit physical address of the locked block

> ERRS: BL = 80h if the function is not implemented

> BL = A2h if the handle is invalid

> BL = ACh if the block's lock count overflows

> BL = ADh if the lock fails

> This function locks an extended memory block and returns its base

> address as a 32-bit physical address. Locked memory blocks are guaranteed not

> to move. The 32-bit pointer is only valid while the block is locked.

> Locked blocks should be unlocked as soon as possible.

> NOTE: A block does not have to be locked before using Function 0Bh (Move Extended Memory Block).

> "Lock counts" are maintained for EMBs.

> Unlock Extended Memory Block

> To Call: AH = 0Dh

> DX = Extended memory block handle to unlock

> RETURNS: AX = 0001h if the block is unlocked, 0000h otherwise

> ERRS: BL = 80h if the function is not implemented

> BL = 81h if a VDISK device is detected

> BL = A2h if the handle is invalid

> BL = AAh if the block is not locked

> This function unlocks a locked extended memory block. Any 32-bit

> pointers into the block become invalid and should no longer be used.

> Get EMB Handle Information

> To Call: AH = 0Eh

> DX = Extended memory block handle

> RETURNS: AX = 0001h if the block's information is found, 0000h otherwise

> BH = The block's lock count

> BL = Number of free EMB handles in the system

> DX = The block's length in K-bytes

> ERRS: BL = 80h if the function is not implemented

> BL = A2h if the handle is invalid

> This function returns additional information about an extended memory block to the caller.

> Reallocate Extended Memory Block

> To Call: AH = 0Fh

> BX = New size for the extended memory block in K-bytes

> DX = Unlocked extended memory block handle to reallocate

> RETURNS: AX = 0001h if the block is reallocated, 0000h otherwise

> ERRS: BL = 80h if the function is not implemented

> BL = A0h if all available extended memory is allocated

> BL = A1h if all available extended memory handles are in use

> BL = A2h if the handle is invalid

> BL = ABh if the block is locked

> This function attempts to reallocate an unlocked extended memory block so that it becomes the newly specified size. If the new size is smaller than the old block's size, all data at the upper end of the old block is lost.

> Request Upper Memory Block

> To Call: AH = 10h

> DX = Size of requested memory block in paragraphs

> RETURNS: AX = 0001h if the request is granted, 0000h otherwise

> BX = Segment number of the upper memory block

> If the request is granted,

> DX = Actual size of the allocated block in paragraphs otherwise,

> DX = Size of the largest available UMB in paragraphs

> ERRS: BL = 80h if the function is not implemented

> BL = B0h if a smaller UMB is available

> BL = B1h if no UMBs are available

> This function attempts to allocate an upper memory block to the caller. If the function fails, the size of the largest free UMB is returned in DX.

> By definition UMBs are located below the 1MB address boundary.

> UMBs are paragraph aligned.

> To determine the size of the largest available UMB, attempt to allocate one with a size of FFFFh.

> UMBs are unaffected by EMS calls.

> Release Upper Memory Block

> To Call: AH = 11h

> DX = Segment number of the upper memory block

> RETURNS: AX = 0001h if the block was released, 0000h otherwise

> ERRS: BL = B2h if the UMB segment number is invalid

> This function frees a previously allocated upper memory block. When an

> UMB has been released, any code or data stored in it becomes invalid and

> should not be accessed.

> Reallocate Upper Memory Block

> To Call:

> AH = 12h

> BX = New size for UMB in paragraphs

> DX = Segment number of the UMB to reallocate

> RETURNS:

> AX = 1 if the block was reallocated, 0 otherwise

> ERRS:

> BL = 80h if the function is not implemented

> BL = B0h if no UMB large enough to satisfy the request is available.

> In this event, DX is returned with the size of the largest UMB that is available.

> BL = B2h if the UMB segment number is invalid

> This function attempts to reallocate an Upper Memory Block to a newly specified size. If the new size is smaller than the old block's size, all data at the upper end of the block is lost.

> Query Any Free Extended Memory

> Entry:

> AH = 88h

> Exit:

> EAX = Size of largest free extended memory block in Kb.

> BL = 0 if no error occurs, otherwise it takes an error code.

> ECX = Highest ending address of any memory block.

> EDX = Total amount of free memory in Kb.

> Errors:

> BL = A0h if all extended memory is allocated.

> This function uses 32-bit values to return the size of available memory, thus allowing returns up to 4GByte. Additionally, it returns the highest known physical memory address, that is, the physical address of the last byte of memory. There may be discontinuities in the memory map below this address.

> The memory pool reported on is the same as that reported on by the existing Query Free Extended Memory function. If the highest memory address is not more than 64 Mb, then these two functions will return the same results.

> Because of its reliance on 32-bit registers, this function is only available on 80386 and higher processors. XMS drivers on 80286 machines should return error code 80h if this function is called.

> If error code 81h is returned, the value in ECX will still be valid. If error code A0h is returned, EAX and EDX will be 0, and ECX will still be valid.

> Allocate Any Extended Memory

> Entry:

> AH = 89h

> EDX = Amount of extended memory requested, in Kb.

> Exit:

> AX = 1 if the block is allocated, 0 if not

> DX = Handle to allocated block.

> Errors:

> BL = A0h if all available extended memory is allocated.

> BL = A1h if all available extended memory handles are in use.

> This function is similar to the existing Allocate Extended Memory, except that it uses a 32-bit instead of a 16-bit value to specify the amount of memory requested. It allocates from the same memory and handle pool as the current function. Since it requires a 32-bit register, this function can be supported only on 80386 and higher processors, and XMS drivers on 80286 machines should return error code 80h.

> Get Extended EMB Handle Information (Function 8Eh)

> Entry:

> AH = 8Eh

> DX = Extended memory block handle.

> Exit:

> AX = 1 if the block's information is found, 0 if not

> BH = Block lock count

> CX = Number of free EMB handles in the system

> EDX = Block's length in Kb.

> Errors:

> BL = A2h if the handle is invalid.

> This function is similar to the Get EMB Handle Information function. Since it uses a 32-bit register to report the block size, it can be used to get information on blocks larger than 64 Mb. It also uses a 16-bit instead of 8-bit register to report the number of free handles, allowing the handle pool to be extended beyond 256 entries.

> Because of its reliance on a 32-bit register, this function is available on 80386 and higher processors. XMS drivers on 80286 machines should return error code 80h if this function is called.

> Reallocate Any Extended Memory (Function 8Fh)

> Entry:

> AH = 8Fh

> EBX = New size for extended memory block, in Kb.

> DX = Unlocked handle for memory block to be resized.

> Exit:

> AX = 1 if the block is reallocated, 0 if not

> Errors:

> BL = A0h if all available extended memory is allocated.

> BL = A1h if all available extended memory handles are in use.

> BL = A2h if the handle is invalid.

> BL = ABh if the block is locked.

> This function is similar to the existing Reallocate Extended Memory, except that it uses a 32-bit instead of a 16-bit value to specify the amount of memory requested. It allocates from the same memory and handle pool as the current function. Since it requires a 32-bit register, this function can be supported only on 80386 and higher processors, and XMS drivers on 80286 machines should return error code 80h.

> Obtaining the Real to Protected Mode Switch Entry Point

> This function can be called in real mode to detect the

> presence of DPMI services and to obtain an address that

> can be used to begin execution in protected mode.

> To Call

> AX = 1687h

> Execute an Int 2Fh (not an Int 31h)

> Returns

> If function was successful:

> AX = 0

> BX = Flags

> Bit 0 = 1 if 32-bit programs are supported

> CL = Processor type

> 03h = 80386

> 04h = 80486

> 05h = Pentium

> 06h = Pentium Pro

> DH = DPMI major compliance number = 9

> DL = DPMI minor version number = 0

> SI = Number of paragraphs required for DPMI host private data (may be 0)

> ES:DI = Address of procedure to call to enter protected mode

> If function was not successful:

> AX != 0

> Calling the Real to Protected Mode Switch Entry Point

> After using Int 2Fh function 1687h, to obtain the

> protected mode entry point, the DPMI client must call

> the entry point address as described in this section.

> To Call

> AX = Flags

> Bit 0 = always 1 if program is a 32-bit application

> ES = Real mode segment of DPMI host data area. This

> must be the size of the data area returned in SI

> from the previous function. ES will be ignored if

> the required data size is zero.

> Call the address returned in ES:DI by the previous

> function

> Returns

> If function was successful:

> Carry flag is clear.

> Program is now executing in protected mode.

> CS = 16-bit selector with base of real mode CS and a

> 64K limit

> SS = Selector with base of real mode SS and a 64K limit

> DS = Selector with base of real mode DS and a 64K limit

> ES = Selector to program's PSP with a 100h byte limit

> FS and GS = 0

> If the program is a 32-bit application the high word of

> ESP will be 0

> All other registers are preserved

> If function was not successful:

> Carry flag is set.

> Program is executing in real mode

> TERMINATE PROTECTED MODE PROGRAM

> To Call:

> AH=4Ch

> AL= error code

> INT 21h

> Return:

> MODE DETECTION

> To Call:

> AX = 1686h

> INT 2Fh

> Returns:

> AX=0, if executing in protected mode under DPMI

> AX!=0, if executing in 16-bit virtual real-mode

> Segment to Descriptor

> This function is used to convert real mode segments

> into descriptors that are addressable by protected mode

> programs.

> To Call

> AX = 0002h

> BX = Real mode segment address

> Returns

> If function was successful:

> Carry flag is clear.

> AX = Selector mapped to real mode segment

> If function was not successful:

> Carry flag is set.

> 6 Get Segment Base Address

> This function returns the 32-bit linear base address of

> the specified segment.

> To Call

> AX = 0006h

> BX = Selector

> Returns

> If function was successful:

> Carry flag is clear.

> CX:DX = 32-bit linear base address of segment

> If function was not successful:

> Carry flag is set.

> 7 Create Code Segment Alias Descriptor

> This function will create a data descriptor that has

> the same base and limit as the specified code segment

> descriptor.

> To Call

> AX = 000Ah

> BX = Code segment selector

> Returns

> If function was successful:

> Carry flag is clear.

> AX = New data selector

> If function was not successful:

> Carry flag is set.

> Allocate DOS Memory Block

> To Call:

> AX = 0100h

> BX = Number of paragraphs (16 byte blocks) desired

> Returns:

> If function was successful:

> Carry flag is clear.

> AX = Initial real mode segment of allocated block

> DX = Selector for allocated block

> If function was not successful:

> Carry flag is set.

> AX = DOS error code:

> 07h memory control blocks damaged

> 08h insufficient memory available to allocate as requested

> BX = Size of largest available block in paragraphs

> will allocate a block of memory from the DOS free memory pool. It returns both the real mode

> segment and one or more descriptors that can be used by

> protected mode applications to access the block.

> Free DOS Memory Block

> To Call:

> AX = 0101h

> DX = Selector of block to free

> Returns:

> If function was successful:

> Carry flag is clear.

> If function was not successful:

> Carry flag is set.

> AX = DOS error code:

> 07h memory control blocks damaged

> 09h incorrect memory segment specified

> This function frees memory that was allocated through

> the Allocate DOS Memory Block function.

> o All descriptors allocated for the memory block are

> automatically freed and therefore should not be

> accessed once the block is freed by this function.

> Resize DOS Memory Block

> To Call:

> AX = 0102h

> BX = New block size in paragraphs

> DX = Selector of block to modify

> Returns:

> If function was successful:

> Carry flag is clear.

> If function was not successful:

> Carry flag is set.

> AX = DOS error code:

> 07h memory control blocks damaged

> 08h insufficient memory available to allocate as requested

> 09h incorrect memory segment specified

> BX = Maximum block size possible in paragraphs

> This function is used to grow or shrink a memory block

> was allocated through the Allocate DOS Memory Block function.

> o Growing a memory block is often likely to fail

> since other DOS block allocations will prevent

> increasing the size of the block. Also, if the

> size of a block grows past a 64K boundary then the

> allocation will fail if the next descriptor in the

> LDT is not free. Therefore, this function is

> usually only used to shrink a block.

> o Shrinking a block may cause some descriptors that

> were previously allocated to the block to be

> freed. For example shrinking a block from 140K to

> 120K would cause the third allocated descriptor to

> be freed since it is no longer valid. The initial

> selector will remain unchanged, however, the

> limits of the remaining two descriptors will

> change: the first to 120K and the second to 56k.

> Get Real Mode Interrupt Vector

> To Call:

> AX = 0200h

> BL = Interrupt number

> Returns:

> Carry flag is clear.

> CX:DX = Segment:Offset of real mode interrupt handler

> This function returns the value of the current task's

> real mode interrupt vector for the specified interrupt.

> o The address returned in CX is a segment, not a

> selector. Therefore you should not attempt to

> place the value returned in CX into a segment

> register in protected mode or a general protection

> fault may occur.

> o Note all 100h (256 decimal) interrupt vectors must

> be supported by the DPMI host.

> 10.2 Set Real Mode Interrupt Vector

> To Call:

> AX = 0201h

> BL = Interrupt number

> CX:DX = Segment:Offset of real mode interrupt handler

> Returns:

> If function was successful:

> Carry flag is clear.

> If function was not successful:

> Carry flag is set.

> This function sets the value of the current task's real

> mode interrupt vector for the specified interrupt.

> o The address passed in CX must be a real mode

> segment, not a selector.

> o If the interrupt being hooked is a hardware

> interrupt then you must lock the segment that the

> interrupt handler runs in as well as any memory

> the handler may touch at interrupt time.

> o The address contained in CX:DX must be a real mode

> segment:offset, not a selector:offset. This means

> that the code for the interrupt handler must

> either reside in DOS addressable memory or you

> must use a real mode call-back address. Refer to

> the section on DOS memory management services on

> page 43 for information on allocating memory below

> 1 megabyte. Information on real mode call back

> addresses can be found on page 68.

> 10.3 Get Processor Exception Handler Vector

> To Call:

> AX = 0202h

> BL = Exception/fault number (00h-1Fh)

> Returns:

> If function was successful:

> Carry flag is clear.

> CX:(E)DX = Selector:Offset of exception handler

> If function was not successful:

> Carry flag is set.

> The value passed in BL was invalid.

> This function returns the CS:(E)IP of the current

> protected mode exception handler for the specified

> exception number.

> o The value returned in CX is a valid protected mode

> selector, not a real mode segment.

> o 32-bit mode programs will be returned a 32-bit

> offset in the EDX register.

> 10.4 Set Processor Exception Handler Vector

> To Call:

> AX = 0203h

> BL = Exception/fault number (00h-1Fh)

> CX:(E)DX = Selector:Offset of exception handler

> Returns:

> If function was successful:

> Carry flag is clear.

> If function was not successful:

> Carry flag is set.

> The value passed in BL was invalid.

> This function allows protected mode applications to

> intercept processor exceptions that are not handled by

> the DPMI environment. Programs may wish to handle

> exceptions such as not present segment faults which

> would otherwise generate a fatal error.

> Every exception is first examined by the protected mode

> operating system. If it can not handle the exception

> it then reflects it through the protected mode

> exception handler chain. The final handler in the

> chain may either reflect the exception as an interrupt

> (as would happen in real mode) or it may terminate the

> current program.

> ## Get Protected Mode Interrupt Vector

> To Call:

> AX = 0204h

> BL = Interrupt number

> Returns:

> Carry flag is clear.

> CX:(E)DX = Selector:Offset of exception handler

> This function returns the CS:(E)IP of the current protected mode interrupt handler for the specified interrupt number.

> o The value returned in CX is a valid protected mode

> selector, not a real mode segment.

> o 32-bit mode programs will be returned a 32-bit

> offset in the EDX register.

> o All 100h (256 decimal) interrupt vectors must be

> supported by the DPMI host.

> ## Set Protected Mode Interrupt Vector

> To Call:

> AX = 0205h

> BL = Interrupt number

> CX:(E)DX = Selector:Offset of exception handler

> Returns:

> If function was successful:

> Carry flag is clear.

> If function was not successful:

> Carry flag is set.

> This function sets the address of the specified

> protected mode interrupt vector.

> o The value passed in CX must be a valid protected

> mode code selector, not a real mode segment.

> o 32-bit mode programs must supply a 32-bit offset

> in the EDX register. If your handler chains to

> the next exception handler it must do so using a

> 32-bit interrupt stack frame.

> o Note all 100h (256 decimal) interrupt vectors must

> be supported by the DPMI host.

> 11. TRANSLATION SERVICES

> These services are provided so that protected mode programs

> can call real mode software that DPMI does not support

> directly. The protected mode program sets up a data

> structure that contains the values for every register. The

> data structure is defined as:

> Offset Register

> 00h EDI

> 04h ESI

> 08h EBP

> 0Ch Reserved by system

> 10h EBX

> 14h EDX

> 18h ECX

> 1Ch EAX

> 20h Flags

> 22h ES

> 24h DS

> 26h FS

> 28h GS

> 2Ah IP

> 2Ch CS

> 2Eh SP

> 30h SS

> You will notice that all of the fields are dwords so that 32

> bit registers can be passed to real mode. Most real mode

> software will ignore the high word of the extended

> registers. However, you can write a real mode procedure

> that uses 32-bit registers if you desire. Note that 16-bit

> DPMI implementations may not pass the high word of 32-bit

> registers or the FS and GS segment registers to real mode

> even when running on an 80386 machine.

> Any interrupt handler or procedure called must return with

> the stack in the same state as when it was called. This

> means that the real mode code may switch stacks while it is

> running but it must return on the same stack that it was

> called on and it must pop off the entire far return/iret

> structure.

> After the call or interrupt is complete, all real mode

> registers and flags except SS, SP, CS, and IP will be copied

> back to the real mode call structure so that the caller can

> examine the real mode return values.

> Remember that the values in the segment registers should be

> real mode segments, not protected mode selectors.

> The translation services will provide a real mode stack if

> the SS:SP fields are zero. However, the stack provided is

> relatively small. If the real mode procedure/interrupt

> routine uses more than 30 words of stack space then you

> should provide your own real mode stack.

> It is possible to pass parameters to real mode software on

> the stack. The following code will call a real mode

> procedure with 3 word parameters:

> Protected_Mode_Code:

> push Param1

> push Param2

> push Param3

> (Set ES:DI to point to call structure)

> mov cx, 3 ; Copy 3 words

> mov ax, 0301h ; Call real mode proc

> int 31h ; Call the procedure

> add sp, 6 ; Clean up stack

> The real mode procedure would be called with the following

> data on the real mode stack:

> Param1

> Param2

> Param3

> Return

> CS

> Return

> IP

> <-- Real mode SS:SP

> 11.1 Simulate Real Mode Interrupt

> This function simulates an interrupt in real mode. It

> will invoke the CS:IP specified by the real mode

> interrupt vector and the handler must return by

> executing an iret.

> To Call

> AX = 0300h

> BL = Interrupt number

> BH = Flags

> Bit 0 = 1 resets the interrupt controller and A20

> line

> Other flags reserved and must be 0

> CX = Number of words to copy from protected mode to

> real mode stack

> ES:(E)DI = Selector:Offset of real mode call structure

> Returns

> If function was successful:

> Carry flag is clear.

> ES:(E)DI = Selector:Offset of modified real mode call

> structure

> If function was not successful:

> Carry flag is set.

> 11.2 Call Real Mode Procedure With Far Return Frame

> This function calls a real mode procedure. The called

> procedure must execute a far return when it completes.

> To Call

> AX = 0301h

> BH = Flags

> Bit 0 = 1 resets the interrupt controller and A20

> line

> Other flags reserved and must be 0

> CX = Number of words to copy from protected mode to

> real mode stack

> ES:(E)DI = Selector:Offset of real mode call structure

> Returns

> If function was successful:

> Carry flag is clear.

> ES:(E)DI = Selector:Offset of modified real mode call

> structure

> If function was not successful:

> Carry flag is set.

> 11.3 Call Real Mode Procedure With Iret Frame

> This function calls a real mode procedure. The called

> procedure must execute an iret when it completes.

> To Call

> AX = 0302h

> BH = Flags

> Bit 0 = 1 resets the interrupt controller and A20

> line

> Other flags reserved and must be 0

> CX = Number of words to copy from protected mode to

> real mode stack

> ES:(E)DI = Selector:Offset of real mode call structure

> Returns

> If function was successful:

> Carry flag is clear.

> ES:(E)DI = Selector:Offset of modified real mode call

> structure

> If function was not successful:

> Carry flag is set.

> Allocate Real Mode Call-Back Address

> This service is used to obtain a unique real mode

> SEG:OFFSET that will transfer control from real mode to

> a protected mode procedure.

> At times it is necessary to hook a real mode interrupt

> or device call-back in a protected mode driver. For

> example, many mouse drivers call an address whenever

> the mouse is moved. Software running in protected mode

> can use a real mode call-back to intercept the mouse

> driver calls.

> To Call

> AX = 0303h

> DS:(E)SI = Selector:Offset of procedure to call

> ES:(E)DI = Selector:Offset of real mode call structure

> Returns

> If function was successful:

> Carry flag is clear.

> CX:DX = Segment:Offset of real mode call address

> If function was not successful:

> Carry flag is set.

> Call-Back Procedure Parameters

> Interrupts disabled

> DS:(E)SI = Selector:Offset of real mode SS:SP

> ES:(E)DI = Selector:Offset of real mode call structure

> SS:(E)SP = Locked protected mode API stack

> All other registers undefined

> Return from Call-Back Procedure

> Execute an IRET to return

> ES:(E)DI = Selector:Offset of real mode call structure

> to restore (see note)

> o Since the real mode call structure is static, you

> must be careful when writing code that may be

> reentered. The simplest method of avoiding

> reentrancy is to leave interrupts disabled

> throughout the entire call. However, if the

> amount of code executed by the call-back is large

> then you will need to copy the real mode call

> structure into another buffer. You can then

> return with ES:(E)DI pointing to the buffer you

> copied the data to -- it does not have to point to

> the original real mode call structure.

> o The called procedure is responsible for modifying

> the real mode CS:IP before returning. If the real

> mode CS:IP is left unchanged then the real mode

> call-back will be executed immediately and your

> procedure will be called again. Normally you will

> want to pop a return address off of the real mode

> stack and place it in the real mode CS:IP. The

> example code in the next section demonstrates

> chaining to another interrupt handler and

> simulating a real mode iret.

> o To return values to the real mode caller you must

> modify the real mode call structure.

> o Remember that all segment values in the real mode

> call structure will contain real mode segments,

> not selectors. If you need to examine data

> pointed to by a real mode seg:offset pointer you

> should not use the segment to selector service to

> create a new selector. Instead, allocate a

> descriptor during initialization and change the

> descriptor's base to 16 times the real mode

> segment's value. This is important since

> selectors allocated though the segment to selector

> service can never be freed.

> o DPMI hosts should provide a minimum of 16 call-

> back addresses per task.

> 11.5 Free Real Mode Call-Back Address

> This function frees a real mode call-back address that

> was allocated through the allocate real mode call-back

> address service.

> To Call

> AX = 0304h

> CX:DX = Real mode call-back address to free

> Returns

> If function was successful:

> Carry flag is clear.

> If function was not successful:

> Carry flag is set.

> 11.6 Get State Save/Restore Addresses

> When a program uses the raw mode switch services (see

> page 77) or issues DOS calls from a hardware interrupt

> handler, it will need to save the state of the current

> task before changing modes. This service returns the

> addresses of two procedures used to save the state of

> the current task's registers. For example, the real

> mode address is used to save the state of the protected

> mode registers. The protected mode address is used to

> save the state of the real mode registers. This can be

> used to save the state of the alternate mode's

> registers before they are modified by the mode switch

> call. The current mode's registers can be saved by

> simply pushing them on the stack.

> Note: It is not necessary to call this service if

> using the translation services 0300h, 0301h or 0302h.

> It is provided for programs that use the raw mode

> switch service.

> To Call

> AX = 0305h

> Returns

> If function was successful:

> Carry flag is clear

> AX = Size of buffer in bytes required to save state

> BX:CX = Real mode address used to save/restore state

> SI:(E)DI = Protected mode address used to save/restore

> state

> If function was not successful:

> Carry flag is set

> Parameters To State-Save Procedures

> Execute a far call to the appropriate address (real or

> pmode) with:

> ES:(E)DI = Pointer to state-save buffer

> AL = 0 to save state

> AL = 1 to restore state

> 11.7 Get Raw Mode Switch Addresses

> This function returns addresses that can be jumped to

> for low-level mode switching.

> To Call

> AX = 0306h

> Returns

> If function was successful:

> Carry flag is clear

> BX:CX = Real -> Protected mode switch address

> SI:(E)DI = Protected -> Real mode switch address

> If function was not successful:

> Carry flag is set

> Parameters To State-Save Procedures

> Execute a far jump to the appropriate address (real or

> pmode) with:

> AX = New DS

> CX = New ES

> DX = New SS

> (E)BX = New (E)SP

> SI = New CS

> (E)DI = New (E)IP

> The processor will be placed in the desired mode. The

> DS, ES, SS, (E)SP, CS, and (E)IP will contain the

> values specified. The (E)BP register will be preserved

> across the call and so can be used as a pointer. The

> values in (E)AX, (E)BX, (E)CX, (E)DX, (E)SI, and (E)DI

> will be undefined. On an 80386 or 80486 the FS and GS

> segment registers will contain zero after the mode

> switch.

> GET VERSION

> To Call:

> AX = 0400h

> Returns:

> AH = Major version, ALWAYS 0

> AL = Minor version, ALWAYS 9

> BX = Flags

> Bit 0 = 1 if running under an 80386 DPMI implementation: ALWAYS 1

> Bit 1 = 1 if processor is returned to real mode for reflected interrupts (as opposed to Virtual 8086 mode).

> Bit 2 = 1 if virtual memory is supported, ALWAYS 1

> Bit 3 is reserved and undefined

> All other bits are zero and reserved for later use

> CL = Processor type

> 03 = 80386

> 04 = 80486

> 05=Pentium

> 06=Pentium Pro

> DH = Current value of virtual master PIC base interrupt

> DL = Current value of virtual slave PIC base interrupt

> Carry flag clear (call can not fail)

> This function returns the compatability version of the DPMI services supported. This will be locked in as 0.9 unless otherwise mentioned.

> ## Get Free Memory Information

> To Call:

> AX = 0500h

> ES:(E)DI = Selector:Offset of 30h byte buffer

> Returns:

> If function was successful:

> Carry flag is clear.

> ES:(E)DI = Selector:Offset of buffer with the following structure:

> Offset Description

> 00h Largest available free block in bytes

> 04h Maximum unlocked page allocation

> 08h Maximum locked page allocation

> 0Ch Linear addr space size in pages

> 10h Total number of unlocked pages

> 14h Number of free pages

> 18h Total number of physical pages

> 1Ch Free linear address space in pages

> 20h Size of paging file/partition in pages

> 24h-2Fh Reserved

> If function was not successful:

> Carry flag is set.

> This function is provided so that protected mode applications can determine how much memory is available. Under DPMI implementations that support

> virtual memory, it is important to consider issues such

> as the amount of available physical memory.

> Note that since DPMI applications will often run in

> multi-tasking environments, this function must be

> considered only advisory.

> Allocate Memory Block

> To Call

> AX = 0501h

> BX:CX = Size of memory block to allocate in bytes

> Returns

> If function was successful:

> Carry flag is clear

> BX:CX = Linear address of allocated memory block

> SI:DI = Memory block handle (used to resize and free)

> If function was unsuccessful:

> Carry flag is set

> This function allocates and commits linear memory.

> o This function does not allocate any selectors for

> the memory block. It is the responsibility of the

> caller to allocate and initialize any selectors

> needed to access the memory.

> o Under DPMI implementations that support virtual

> memory the memory block will be allocated

> unlocked. If some or all of the memory should be

> locked you will need to use either the lock

> selector function or the lock linear region

> function.

> Free Memory Block

> This function frees a memory block that was allocate

> through the allocate memory block function.

> To Call

> AX = 0502h

> SI:DI = Handle of memory block to free

> Returns

> If function was successful:

> Carry flag is clear

> If function was unsuccessful:

> Carry flag is set

> Resize Memory Block

> This function changes the size of a memory block that

> was allocated through the allocate memory block

> function.

> To Call

> AX = 0503h

> BX:CX = New size of memory block to allocate in bytes

> SI:DI = Handle of memory block to resize

> Returns

> If function was successful:

> Carry flag is clear

> BX:CX = New linear address of memory block

> SI:DI = New handle of memory block

> If function was unsuccessful:

> Carry flag is set

> ## Lock Linear Region

> To Call:

> AX = 0600h

> BX:CX = Starting linear address of memory to lock

> SI:DI = Size of region to lock in bytes

> Returns:

> If function was successful:

> Carry flag is clear.

> If function was not successful:

> Carry flag is set.

> This function locks a specified linear address range.

> o If this function fails then none of the memory

> will be locked.

> o If the specified region overlaps part of a page at

> the beginning or end of the region, the page(s)

> will be locked.

> Unlock Linear Region

> To Call:

> AX = 0601h

> BX:CX = Starting linear address of memory to unlock

> SI:DI = Size of region to unlock in bytes

> Returns:

> If function was successful:

> Carry flag is clear.

> If function was not successful:

> Carry flag is set.

> function unlocks a specified linear address range

> that was previously locked using the Lock Linear Region

> function.

> o If this function fails then none of the memory

> will be unlocked.

> o An error will be returned if the memory was not

> previously locked or if the specified region is

> invalid.

> o If the specified region overlaps part of a page at

> the beginning or end of the region, the page(s)

> will be unlocked.

> o Even if the function succeeds, the memory will

> remain locked if the lock count is not decremented to zero.

> 14.3 Mark Real Mode Region as Pageable

> To Call:

> AX = 0602h

> BX:CX = Starting linear address of memory to mark as pageable

> SI:DI = Size of region to page in bytes

> Returns:

> If function was successful:

> Carry flag is clear.

> If function was not successful:

> Carry flag is set.

> Relock Real Mode Region

> To Call:

> AX = 0603h

> BX:CX = Starting linear address of memory to relock

> SI:DI = Size of region to page in bytes

> Returns:

> If function was successful:

> Carry flag is clear.

> If function was not successful:

> Carry flag is set.

> This function is used to relock memory regions that

> were marked as pageable by the previous function.

> o If this function fails then none of the memory

> will be relocked.

> o If the specified region overlaps part of a page at

> the beginning or end of the region, the page(s)

> will be not be relocked.

> Get Page Size

> To Call:

> AX = 0604h

> Returns:

> If function was successful:

> Carry flag is clear

> BX:CX = Page size in bytes

> If function was not successful:

> Carry flag is set

> This function returns the size of a single memory page in bytes.

> Mark Page as Demand Paging Candidate

> To Call:

> AX = 0702h

> BX:CX = Starting linear address of pages to mark

> SI:DI = Number of bytes to mark as paging candidates

> Returns:

> If function was successful:

> Carry flag is clear.

> If function was not successful:

> Carry flag is set.

> This function is used to inform the operating system

> that a range of pages should be placed at the head of

> the page out candidate list. This will force these

> pages to be swapped to disk ahead of other pages even

> if the memory has been accessed recently. However, all

> memory contents will be preserved.

> This is useful, for example, if a program knows that a

> given piece of data will not be accessed for a long

> period of time. That data is ideal for swapping to

> disk since the physical memory it now occupies can be

> used for other purposes.

> o This function does not force the pages to be

> swapped to disk immediately.

> o Partial pages will not be discarded.

> 15.3 Discard Page Contents

> This function discards the entire contents of a given

> linear memory range. It is used after a memory object

> that occupied a given piece of memory has been

> discarded.

> The contents of the region will be undefined the next

> time the memory is accessed. All values previously

> stored in this memory will be lost.

> To Call

> AX = 0703h

> BX:CX = Starting linear address of pages to discard

> SI:DI = Number of bytes to discard

> Returns

> If function was successful:

> Carry flag is clear.

> If function was not successful:

> Carry flag is set.

> 16. PHYSICAL ADDRESS MAPPING

> Memory mapped devices such as network adapters and displays

> sometimes have memory mapped at physical addresses that lie

> outside of the normal 1Mb of memory that is addressable in

> real mode. Under many implementations of DPMI, all

> addresses are linear addresses since they use the paging

> mechanism of the 80386. This service can be used by device

> drivers to convert a physical address into a linear address.

> The linear address can then be used to access the device

> memory.

> Some implementations of DPMI may not support this call

> because it could be used to circumvent system protection.

> This call should only be used by programs that absolutely

> require direct access to a memory mapped device.

> To Call

> AX = 0800h

> BX:CX = Physical address of memory

> SI:DI = Size of region to map in bytes

> Returns

> If function was successful:

> Carry flag is clear.

> BX:CX = Linear address that can be used to access the

> physical memory

> If function was not successful:

> Carry flag is set.

> 17. VIRTUAL INTERRUPT STATE FUNCTIONS

> Under many implementations of DPMI, the interrupt flag in

> protected mode will always be set (interrupts enabled).

> This is because the program is running under a protected

> operating system that can not allow programs to disable

> physical hardware interrupts. However, the operating system

> will maintain a "virtual" interrupt state for protected mode

> programs. When the program executes a cli instruction, the

> program's virtual interrupt state will be disabled, and the

> program will not receive any hardware interrupts until it

> executes an sti to reenable interrupts (or calls service

> 0901h).

> When a protected mode program executes a pushf instruction,

> the real processor flags will be pushed onto the stack.

> Thus, examining the flags pushed on the stack is not

> sufficient to determine the state of the program's virtual

> interrupt flag. These services enable programs to get and

> modify the state of their virtual interrupt flag.

> The following sample code enters an interrupt critical

> section and then restores the virtual interrupt state to

> it's previous state.

> 17.1 Get and Disable Virtual Interrupt State

> This function will disable the virtual interrupt flag

> and return the previous state of the virtual interrupt flag.

> To Call

> AX = 0900h

> Returns

> Carry flag clear (this function always succeeds)

> Virtual interrupts are disabled

> AL = 0 if virtual interrupts were previously disabled

> AL = 1 if virtual interrupts were previously enabled

> 17.2 Get and Enable Virtual Interrupt State

> This function will enable the virtual interrupt flag

> and return the previous state of the virtual interrupt flag.

> To Call

> AX = 0901h

> Returns

> Carry flag clear (this function always succeeds)

> Virtual interrupts are enabled

> AL = 0 if virtual interrupts were previously disabled

> AL = 1 if virtual interrupts were previously enabled

> 17.3 Get Virtual Interrupt State

> This function will return the current state of the

> virtual interrupt flag.

> To Call

> AX = 0902h

> Returns

> Carry flag clear (this function always succeeds)

> AL = 0 if virtual interrupts are disabled

> AL = 1 if virtual interrupts are enabled

> 19. DEBUG REGISTER SUPPORT

> The 80386 processor supports special registers that are used

> for debugging. Since the instructions to modify these

> registers can only be executed by code running at privileged

> level zero, protected mode debuggers running in DPMI

> environments can not modify the registers directly. These

> services provide mechanisms for setting and clearing debug

> watchpoints and detecting when a watchpoint has caused a

> fault.

> 19.1 Set Debug Watchpoint

> This function will set a debug watchpoint at a

> specified linear address.

> To Call

> AX = 0B00h

> BX:CX = Linear address of watchpoint

> DL = Size of watchpoint (1, 2, or 4)

> DH = Type of watchpoint

> 0 = Execute

> 1 = Write

> 2 = Read/Write

> Returns

> If function was successful:

> Carry flag is clear

> BX = Debug watchpoint handle

> If function was not successful:

> Carry flag is set

> 19.2 Clear Debug Watchpoint

> This function will clear a debug watchpoint that was set using the Set Debug Watchpoint function.

> To Call

> AX = 0B01h

> BX = Debug watchpoint handle

> Returns

> If function was successful:

> Carry flag is clear

> If function was not successful:

> Carry flag is set

> Get State of Debug Watchpoint

> This function returns the state of a debug watchpoint that was set using the Set Debug Watchpoint function.

> To Call

> AX = 0B02h

> BX = Debug Watchpoint Handle

> Returns

> If function was successful:

> Carry flag is clear

> AX = Status flags

> Bit 0 = 1 if watch point has been executed

> If function was not successful:

> Carry flag is set

> Reset Debug Watchpoint

> This function resets the state of a previously defined

> debug watchpoint.

> To Call

> AX = 0B03h

> BX = Debug Watchpoint Handle

> Returns

> If function was successful:

> Carry flag is clear

> If function was not successful:

> Carry flag is set

> TOC

> # VESA 1.2 VBE 2.0

> ### BY | Lewis Sellers lsellers@usit.net

> ### SET VIDEO MODE

> `To Call:`

> `AH = 00h`

> `AL = mode (see below)`

> `INT 10h`

> `Return:`

> `AL = video mode flag`

> `20h mode > 7`

> `30h modes <= 7 except mode 6`

> `3Fh mode 6`

> `AL = CRT controller mode byte`

> `IBM standard modes do not clear the screen if the high bit of AL is set`

>     Values for video mode:
>          text/ text   pixel pixel    colors  display  scrn system
>          grph  resol  box   resoltn          pages   addr
>      00h = T   40x25  8x14           16gray     8    B800
>          = T   40x25  8x16             16       8    B800
>          = T   40x25  9x16             16       8    B800
>      01h = T   40x25  8x14             16       8    B800
>          = T   40x25  8x16             16       8    B800
>          = T   40x25  9x16             16       8    B800
>      02h = T   80x25  8x14           16gray     4    B800
>          = T   80x25  8x16             16       4    B800
>          = T   80x25  9x16             16       4    B800
>      03h = T   80x25  8x14             16       4    B800
>          = T   80x25  8x16             16       4    B800
>          = T   80x25  9x16             16       4    B800
>      04h = G   40x25  8x8     320x200           4    B800
>      05h = G   40x25  8x8     320x200 4gray          B800
>          = G   40x25  8x8     320x200   4            B800
>      06h = G   80x25  8x8     640x200   2            B800
>      07h = T   80x25  9x14            mono     var   B000
>          = T   80x25  9x16            mono           B000
>      0Dh = G   40x25  8x8     320x200  16       8    A000
>      0Eh = G   80x25  8x8     640x200  16       4    A000
>      0Fh = G   80x25  8x14    640x350 mono      2    A000
>      10h = G   80x25  8x14    640x350   4       2    A000
>          = G                  640x350  16            A000
>      11h = G   80x30  8x16    640x480 mono           A000
>      12h = G   80x30  8x16    640x480 16/256k        A000
>          = G   80x30  8x16    640x480 16/64          A000
>      13h = G   40x25  8x8     320x200 256/256k       A000

> ### SET TEXT-MODE CURSOR SHAPE

> `To Call:`

> `AH = 01h`

> `CH = bit 7 should be zero`

> `bits 6,5 cursor blink`

> `(00=normal, 01=invisible, 10=erratic, 11=slow)`

> `(00=normal, other=invisible on EGA/VGA)`

> `bits 4-0 top scan line containing cursor`

> `CL = bottom scan line containing cursor (bits 0-4)`

> ### SET CURSOR POSITION

> `AH = 02h`

> `BH = page number`

> `0-3 in modes 2&3`

> `0-7 in modes 0&1`

> `0 in graphics modes`

> `DH = row (00h is top)`

> `DL = column (00h is left)`

> ### GET CURSOR POSITION AND SIZE

> `AH = 03h`

> `BH = page number`

> `0-3 in modes 2&3`

> `0-7 in modes 0&1`

> `0 in graphics modes`

> `Return:`

> `AX = 0000h (Phoenix BIOS)`

> `CH = start scan line`

> `CL = end scan line`

> `DH = row (00h is top)`

> `DL = column (00h is left)`

> `a separate cursor is maintained for each of up to 8 display pages many ROM BIOSes incorrectly return the default size for a color display (start 06h, end 07h) when a monochrome display is attached`

> ### READ LIGHT PEN POSITION

> `To Call`

> `AH = 04h`

> `INT 10h`

> `Return:`

> `AH = light pen trigger flag`

> `00h not down/triggered`

> `01h down/triggered`

> `DH,DL = row,column of character light pen is on`

> `CH = pixel row (graphics modes 04h-06h)`

> `CX = pixel row (graphics modes with >200 rows)`

> `BX = pixel column`

> `on a CGA, returned column numbers are always multiples of 2 (320-column modes) or 4 (640-column modes)`

> ### SELECT ACTIVE DISPLAY PAGE

> `To Call:`

> `AH = 05h`

> `AL = new page number (00h to number of pages - 1) (see AH=00h)`

> `INT 10h`

> ### SCROLL UP WINDOW

> `To Call:`

> `AH = 06h`

> `AL = number of lines by which to scroll up (00h = clear entire window)`

> `BH = attribute used to write blank lines at bottom of window`

> `CH,CL = row,column of window's upper left corner`

> `DH,DL = row,column of window's lower right corner`

> `INT 10h`

> ### SCROLL DOWN WINDOW

> AH = 07h

> `AL = number of lines by which to scroll down (00h=clear entire window)`

> `BH = attribute used to write blank lines at top of window`

> `CH,CL = row,column of window's upper left corner`

> `DH,DL = row,column of window's lower right corner`

> ### READ CHARACTER AND ATTRIBUTE AT CURSOR POSITION

> `AH = 08h`

> `BH = page number (00h to number of pages - 1) (see AH=00h)`

> `Return:`

> `AH = attribute`

> `bit 7: blink`

> `bits 6-4: background color`

> `000 black`

> `001 blue`

> `010 green`

> `011 cyan`

> `100 red`

> `101 magenta`

> `110 brown`

> `111 white`

> `bits 3-0: foreground color`

> `0000 black 1000 dark gray`

> `0001 blue 1001 light blue`

> `0010 green 1010 light green`

> `0011 cyan 1011 light cyan`

> `0100 red 1100 light red`

> `0101 magenta 1101 light magenta`

> `0110 brown 1110 yellow`

> `0111 light gray 1111 white`

> `AL = character`

> `for monochrome displays, a foreground of 1 with background 0 is underlined the blink bit may be reprogrammed to enable intense background colors using AX=1003h or by programming the CRT controller`

> ### WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION

> `AH = 09h`

> `AL = character to display`

> `BH = page number (00h to number of pages - 1) (see AH=00h)`

> `BL = attribute (text mode) or color (graphics mode)`

> `if bit 7 set in graphics mode, character is xor'ed onto screen`

> `CX = number of times to write character`

> `all characters are displayed, including CR, LF, and BS replication count in CX may produce an unpredictable result in graphics modes if it is greater than the number of positions remaining in the current row`

> ### WRITE CHARACTER ONLY AT CURSOR POSITION

> `AH = 0Ah`

> `AL = character to display`

> `BH = page number (00h to number of pages - 1) (see AH=00h)`

> `BL = attribute (PCjr only) or color (graphics mode)`

> `if bit 7 set in graphics mode, character is xor'ed onto screen`

> `CX = number of times to write character`

> `all characters are displayed, including CR, LF, and BS replication count in CX may produce an unpredictable result in graphics modes if it is greater than the number of positions remaining in the current row`

> ### SET BACKGROUND/BORDER COLOR

> `AH = 0Bh`

> `BH = 00h`

> `BL = background/border color (border only in text modes)`

> ### SET PALETTE

> `AH = 0BH`

> `BH = 01h`

> `BL = palette ID`

> `00h background, green, red, and brown/yellow`

> `01h background, cyan, magenta, and white`

> ### WRITE GRAPHICS PIXEL

> `AH = 0Ch`

> `BH = page number`

> `AL = pixel color (if bit 7 set, value is xor'ed onto screen)`

> `CX = column`

> `DX = row`

> `Notes: valid only in graphics modes. BH is ignored if the current video mode supports only one page`

> ### READ GRAPHICS PIXEL

> `AH = 0Dh`

> `BH = page number`

> `CX = column`

> `DX = row`

> `Return: AL = pixel color`

> `valid only in graphics modes. BH is ignored if the current video mode supports only one page`

> ### TELETYPE OUTPUT

> `AH = 0Eh`

> `AL = character to write`

> `BH = page number`

> `BL = foreground color (graphics modes only)`

> `characters 07h (BEL), 08h (BS), 0Ah (LF), and 0Dh (CR) are interpreted and do the expected things IBM PC ROMs dated 4/24/81 and 10/19/81 require that BH be the same as the current active page`

> ### GET CURRENT VIDEO MODE

> `AH = 0Fh`

> `Return: AH = number of character columns`

> `AL = display mode (see AH=00h)`

> `BH = active page (see AH=05h)`

> `Notes: if mode was set with bit 7 set ("no blanking"), the returned mode will also have bit 7 set EGA, VGA, and UltraVision return either AL=03h (color) or AL=07h (monochrome) in all extended-row text modes`

> ### SET SINGLE PALETTE REGISTER

> `AX = 1000h`

> `BL = palette register number (00h-0Fh)`

> `= attribute register number (undocumented)`

> `10h attribute mode control register (should let BIOS control this)`

> `11h overscan color register (see also AX=1001h)`

> `12h color plane enable register (bits 3-0 enable corresponding`

> `text attribute bit)`

> `13h horizontal PEL panning register`

> `14h color select register`

> `BH = color or attribute register value`

> ### SET BORDER (OVERSCAN) COLOR

> `To Call:`

> `AX = 1001h`

> `BH = border color (00h-3Fh)`

> `INT 10h`

> ### SET ALL PALETTE REGISTERS

> `To Call:`

> `AX = 1002h`

> `ES:DX -> palette register list`

> `Format of palette register list:`

> `Offset Size Description`

> `00h 16 BYTEs colors for palette registers 00h through 0Fh`

> `10h BYTE border color`

> ### TOGGLE INTENSITY/BLINKING BIT

> `To Call:`

> `AX = 1003h`

> `BL = new state`

> `00h background intensity enabled`

> `01h blink enabled`

> `although there is no function to get the current status, bit 5 of 0040h:0065h indicates the state`

> ### GET INDIVIDUAL PALETTE REGISTER

> `To Call:`

> `AX = 1007h`

> `BL = palette or attribute register number`

> `Return:`

> `BH = palette or attribute register value`

> ### READ OVERSCAN (BORDER COLOR) REGISTER

> `To Call:`

> `AX = 1008h`

> `Return:`

> `BH = border color (00h-3Fh)`

> ### READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER

> `AX = 1009h`

> `ES:DX -> 17-byte buffer (see AX=1002h)`

> ### SET INDIVIDUAL DAC REGISTER

> `AX = 1010h`

> `BX = register number`

> `CH = new value for green (0-63)`

> `CL = new value for blue (0-63)`

> `DH = new value for red (0-63)`

> ### SET BLOCK OF DAC REGISTERS

> `AX = 1012h`

> `BX = starting color register`

> `CX = number of registers to set`

> `ES:DX -> table of 3*CX bytes where each 3 byte group represents one`

> `byte each of red, green and blue (0-63)`

> ### SELECT VIDEO DAC COLOR PAGE

> `AX = 1013h`

> `BL = subfunction`

> `00h select paging mode`

> `BH = 00h select 4 blocks of 64`

> `BH = 01h select 16 blocks of 16`

> `01h select page`

> `BH = page number (00h to 03h) or (00h to 0Fh)`

> `Note: not valid in mode 13h`

> ### READ INDIVIDUAL DAC REGISTER

> `AX = 1015h`

> `BL = palette register number`

> `Return: DH = red value`

> `CH = green value`

> `CL = blue value`

> ### READ BLOCK OF DAC REGISTERS

> `AX = 1017h`

> `BX = starting palette register`

> `CX = number of palette registers to read`

> `ES:DX -> buffer (3 * CX bytes in size) (see also AX=1012h)`

> `Return: buffer filled with CX red, green and blue triples`

> ### SET PEL MASK (VGA/MCGA)

> `AX = 1018h`

> `BL = new PEL value`

> ### READ PEL MASK (VGA/MCGA)

> `AX = 1019h`

> `Return: BL = value read`

> ### GET VIDEO DAC COLOR-PAGE STATE (VGA)

> `To Call:`

> `AX = 101Ah`

> `Return:`

> `BL = paging mode`

> `00h four pages of 64`

> `01h sixteen pages of 16`

> `BH = current page`

> ### PERFORM GRAY-SCALE SUMMING (VGA/MCGA)

> `AX = 101Bh`

> `BX = starting palette register`

> `CX = number of registers to convert`

> ### TEXT-MODE CHARACTER GENERATOR FUNCTIONS

> `AH = 11h`

> `The following functions will cause a mode set, completely resetting`

> `the video environment, but without clearing the video buffer`

> `AL = 00h, 10h: load user-specified patterns`

> `ES:BP -> user table`

> `CX = count of patterns to store`

> `DX = character offset into map 2 block`

> `BL = block to load in map 2`

> `BH = number of bytes per character pattern`

> `AL = 01h, 11h: load ROM monochrome patterns (8 by 14)`

> `BL = block to load`

> `AL = 02h, 12h: load ROM 8 by 8 double-dot patterns`

> `BL = block to load`

> `AL = 03h: set block specifier`

> `BL = block specifier`

> `bits 0,1 = block selected by chars with attribute bit 3=0`

> `bits 2,3 = block selected by chars with attribute bit 3=1`

> `bits 0,1,4 = block selected by attribute bit 3 = 0`

> `bits 2,3,5 = block selected by attribute bit 3 = 1`

> `AL = 04h, 14h: load ROM 8x16 character set (VGA)`

> `BL = block to load`

> `The routines called with AL=1xh are designed to be called only`

> `immediately after a mode set and are similar to the routines called`

> `with AL=0xh, except that:`

> `Page 0 must be active.`

> `Bytes/character is recalculated.`

> `Max character rows is recalculated.`

> `CRT buffer length is recalculated.`

> `CRTC registers are reprogrammed as follows:`

> `R09 = bytes/char-1 ; max scan line (mode 7 only)`

> `R0A = bytes/char-2 ; cursor start`

> `R0B = 0 ; cursor end`

> `R12 = ((rows+1)*(bytes/char))-1 ; vertical display end`

> `R14 = bytes/char ; underline loc`

> `(*** BUG: should be 1 less ***)`

> ### GRAPHICS-MODE CHARACTER GENERATOR FUNCTIONS

> `AH = 11h`

> `AL = 20h: set user 8 by 8 graphics characters (INT 1F)`

> `ES:BP -> user table`

> `AL = 21h: set user graphics characters`

> `ES:BP -> user table`

> `CX = bytes per character`

> `BL = row specifier`

> `00h user set`

> `DL = number of rows`

> `01h 14 rows`

> `02h 25 rows`

> `03h 43 rows`

> `AL = 22h: ROM 8 by 14 set`

> `BL = row specifier (see above)`

> `AL = 23h: ROM 8 by 8 double dot`

> `BL = row specifier (see above)`

> `AL = 24h: load 8x16 graphics characters (VGA/MCGA)`

> `BL = row specifier (see above)`

> `AL = 29h: load 8x16 graphics characters (Compaq Systempro)`

> `BL = row specifier (see above)`

> ### GET FONT INFORMATION (EGA, MCGA, VGA)

> `AX = 1130h`

> `BH = pointer specifier`

> `00h INT 1Fh pointer`

> `01h INT 43h pointer`

> `02h ROM 8x14 character font pointer`

> `03h ROM 8x8 double dot font pointer`

> `04h ROM 8x8 double dot font (high 128 characters)`

> `05h ROM alpha alternate (9 by 14) pointer (EGA,VGA)`

> `06h ROM 8x16 font (MCGA, VGA)`

> `07h ROM alternate 9x16 font (VGA only)`

> `11h (UltraVision v2+) 8x20 font (VGA) or 8x19 font (autosync EGA)`

> `12h (UltraVision v2+) 8x10 font (VGA) or 8x11 font (autosync EGA)`

> `Return: ES:BP = specified pointer`

> `CX = bytes/character`

> `DL = character rows on screen - 1`

> ### ALTERNATE FUNCTION SELECT

> `AH = 12h`

> `BL = 10h`

> `Return: BH = 00h color mode in effect (I/O port 3Dxh)`

> `01h mono mode in effect (I/O port 3Bxh)`

> `BL = 00h 64k bytes memory installed`

> `01h 128k bytes memory installed`

> `02h 192k bytes memory installed`

> `03h 256k bytes memory installed`

> `CH = feature bits`

> `CL = switch settings`

> ### ALTERNATE FUNCTION SELECT

> `AH = 12h`

> `BL = 20h select alternate print screen routine`

> `installs a PrtSc routine from the video card's BIOS to replace the default PrtSc handler from the ROM BIOS, which usually does not understand screen heights other than 25 lines some adapters disable print-screen instead of enhancing it`

> ### ALTERNATE FUNCTION SELECT (VGA) - SELECT VERTICAL RESOLUTION

> `AH = 12h`

> `BL = 30h`

> `AL = vertical resolution`

> `00h 200 scan lines`

> `01h 350 scan lines`

> `02h 400 scan lines`

> ### ALTERNATE FUNCTION SELECT (VGA, MCGA) - PALETTE LOADING

> `AH = 12h`

> `BL = 31h`

> `AL = 00h enable default palette loading`

> `01h disable default palette loading`

> `Return: AL = 12h if function supported`

> ### ALTERNATE FUNCTION SELECT (VGA, MCGA) - VIDEO ADDRESSING

> `AH = 12h`

> `BL = 32h`

> `AL = 00h enable video addressing`

> `01h disable video addressing`

> `Return: AL = 12h if function supported`

> ### ALTERNATE FUNCTION SELECT (VGA, MCGA) - GRAY-SCALE SUMMING

> `AH = 12h`

> `BL = 33h`

> `AL = 00h enable gray scale summing`

> `01h disable gray scale summing`

> `Return: AL = 12h if function supported`

> ### ALTERNATE FUNCTION SELECT (VGA) - CURSOR EMULATION

> `AH = 12h`

> `BL = 34h`

> `AL = 00h enable alphanumeric cursor emulation`

> `01h disable alphanumeric cursor emulation`

> `Return: AL = 12h if function supported`

> ### ALTERNATE FUNCTION SELECT (PS) - DISPLAY-SWITCH INTERFACE

> `AH = 12h`

> `BL = 35h`

> `AL = 00h initial adapter video off`

> `01h initial planar video on`

> `02h switch active video off`

> `03h switch inactive video on`

> `80h *UNDOCUMENTED* set system board video active flag`

> `ES:DX -> buffer (128 byte save area if AL = 0, 2 or 3)`

> `Return: AL = 12h if function supported`

> ### ALTERNATE FUNCTION SELECT (PS, VGA) - VIDEO REFRESH CONTROL

> `AH = 12h`

> `BL = 36h`

> `AL = 00h enable refresh`

> `01h disable refresh`

> `Return: AL = 12h if function supported`

> ### WRITE STRING

> `To Call:`

> `AH = 13h`

> `AL = write mode`

> `bit 0: update cursor after writing`

> `1: string contains alternating characters and attributes`

> `BH = page number`

> `BL = attribute if string contains only characters`

> `CX = number of characters in string`

> `DH,DL = row,column at which to start writing`

> `ES:BP -> string to write`

> `recognizes CR, LF, BS, and bell`

> ### DISPLAY COMBINATION

> `To Call:`

> `AH = 1Ah`

> `AL = 00h read display combination code`

> `Return:`

> `BL = active display code (see below)`

> `BH = alternate display code`

> `01h set display combination code`

> `BL = active display code (see below)`

> `BH = alternate display code`

> `Return:`

> `AL = 1Ah if function was supported`

> `Values for display combination code:`

> `00h no display`

> `01h monochrome adapter w/ monochrome display`

> `02h CGA w/ color display`

> `03h reserved`

> `04h EGA w/ color display`

> `05h EGA w/ monochrome display`

> `06h PGA w/ color display`

> `07h VGA w/ monochrome analog display`

> `08h VGA w/ color analog display`

> `09h reserved`

> `0Ah MCGA w/ digital color display`

> `0Bh MCGA w/ monochrome analog display`

> `0Ch MCGA w/ color analog display`

> `FFh unknown display type`

> ### FUNCTIONALITY/STATE INFORMATION

> `AH = 1Bh`

> `BX = implementation type`

> `0000h return functionality/state information`

> `ES:DI -> 64 byte buffer for state information (see below)`

> `Return: AL = 1Bh if function supported`

> `ES:DI buffer filled with state information`

> `Format of state information:`

> `Offset Size Description`

> `00h DWORD address of static functionality table (see below)`

> `04h BYTE video mode in effect`

> `05h WORD number of columns`

> `07h WORD length of regen buffer in bytes`

> `09h WORD starting address of regen buffer`

> `0Bh WORD cursor position for page 0`

> `0Dh WORD cursor position for page 1`

> `0Fh WORD cursor position for page 2`

> `11h WORD cursor position for page 3`

> `13h WORD cursor position for page 4`

> `15h WORD cursor position for page 5`

> `17h WORD cursor position for page 6`

> `19h WORD cursor position for page 7`

> `1Bh WORD cursor type`

> `1Dh BYTE active display page`

> `1Eh WORD CRTC port address`

> `20h BYTE current setting of register (3?8)`

> `21h BYTE current setting of register (3?9)`

> `22h BYTE number of rows`

> `23h WORD bytes/character`

> `25h BYTE display combination code of active display`

> `26h BYTE DCC of alternate display`

> `27h WORD number of colors supported in current mode`

> `29h BYTE number of pages supported in current mode`

> `2Ah BYTE number of scan lines active`

> `(0,1,2,3) = (200,350,400,480)`

> `2Bh BYTE primary character block`

> `2Ch BYTE secondary character block`

> `2Dh BYTE miscellaneous flags`

> `bit 0 all modes on all displays on`

> `1 gray summing on`

> `2 monochrome display attached`

> `3 default palette loading disabled`

> `4 cursor emulation enabled`

> `5 0 = intensity; 1 = blinking`

> `6 PS/2 P70 plasma display (without 9-dot wide font) active`

> `7 reserved`

> `2Eh 3 BYTEs reserved (00h)`

> `31h BYTE video memory available`

> `00h = 64K, 01h = 128K, 02h = 192K, 03h = 256K`

> `32h BYTE save pointer state flags`

> `bit 0 512 character set active`

> `1 dynamic save area present`

> `2 alpha font override active`

> `3 graphics font override active`

> `4 palette override active`

> `5 DCC override active`

> `6 reserved`

> `7 reserved`

> `33h 13 BYTEs reserved (00h)`

> `Format of Static Functionality Table:`

> `Offset Size Description`

> `00h BYTE modes supported #1`

> `bit 0 to bit 7 = 1 modes 0,1,2,3,4,5,6 supported`

> `01h BYTE modes supported #2`

> `bit 0 to bit 7 = 1 modes 8,9,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh supported`

> `02h BYTE modes supported #3`

> `bit 0 to bit 3 = 1 modes 10h,11h,12h,13h supported`

> `bit 4 to bit 7 reserved`

> `03h 4 BYTEs reserved`

> `07h BYTE scan lines supported`

> `bit 0 to bit 2 = 1 if scan lines 200,350,400 supported`

> `08h BYTE total number of character blocks available in text modes`

> `09h BYTE maximum number of active character blocks in text modes`

> `0Ah BYTE miscellaneous function flags #1`

> `bit 0 all modes on all displays function supported`

> `1 gray summing function supported`

> `2 character font loading function supported`

> `3 default palette loading enable/disable supported`

> `4 cursor emulation function supported`

> `5 EGA palette present`

> `6 color palette present`

> `7 color paging function supported`

> `0Bh BYTE miscellaneous function flags #2`

> `bit 0 light pen supported`

> `1 save/restore state function 1Ch supported`

> `2 intensity blinking function supported`

> `3 Display Combination Code supported`

> `4-7 reserved`

> `0Ch WORD reserved`

> `0Eh BYTE save pointer function flags`

> `bit 0 512 character set supported`

> `1 dynamic save area supported`

> `2 alpha font override supported`

> `3 graphics font override supported`

> `4 palette override supported`

> `5 DCC extension supported`

> `6 reserved`

> `7 reserved`

> `0Fh BYTE reserved`

> ### SAVE/RESTORE VIDEO STATE

> `To Call:`

> `AH = 1Ch`

> `AL = 00h return state buffer size`

> `INT 10h`

> `Return:`

> `BX = number of 64-byte blocks needed`

> `01h save video state`

> `ES:BX -> buffer`

> `02h restore video state`

> `ES:BX -> buffer containing previously saved state`

> `CX = requested states`

> `bit 0 video hardware`

> `1 BIOS data areas`

> `2 color registers and DAC state`

> `3-15 reserved`

> `Return:`

> `AL = 1Ch if function supported`

> TOC

> # Joystick

> ### BY | Lewis Sellers lsellers@usit.net

> Many BIOSes do not fully support the joystick for some reason, leaving software forced to directly use port 21h. Legacy DOES fully support the joystick BIOS routines.

> ### Read Joystick Buttons

> To Call:

> AH = 84h

> DX = 00h Read switch settings

> INT 15h

> Returns:

> AL = Switch settings (bits 4 - 7)

> Carry flag set on error

> ### Read Joystick Position

> To Call:

> AH = 84h

> DX = 01h Read joystick position

> INT 15h

> Returns:

> AX = A(X) value

> BX = A(Y) value

> CX = B(X) value

> DX = B(Y) value

> TOC

> # Keyboard

> ### BY | Lewis Sellers lsellers@usit.net

> The operation of the keyboard is really quite simple. Every time a key is pressed or released an interrupt 9 is generated, and reading the value from port 60h tells you what happened.

> Decoding the Keyboard Byte

> Well..each key on the keyboard has an associated scan code which is contained in the lower 7 bits of the byte. The most significant bit (ie bit 7) tells you what was actually done, 0 = key was just pressed, 1 = key was just released. If someone had just pressed the ESC key for instance, the port will show a value of 1 (1 is the ESC key's scan code). If they hold their finger on the button the keyboard will keep generating interrupt 9's and each time the port will still show a value of 1. When the person releases the key

> a final interrupt will be generated and the port will return 129 (1 + 128, since the high bit will be set indicating the person has released the key).

> Some keys are "extended" keys. When an

> extended key is pressed an interrupt is generated and the keyboard port

> will return a value of 224 (E0h). This means that an extended key was pressed

> and it's *extended* scan code will be available during the *next* interrupt.

> Note that the left control key has a scan code of 29, while the *right*

> control key has an *extended* scan code of 29. The same applies to the alt

> keys and the arrow keys (keypad arrows vs the other ones).

> It would be nice if all keys were created equal and we could just throw away

> the 224 extended bytes and handle all the other bytes normally. Unfortunately

> there are two buttons which on my machine at least (and others I have tested)

> do some really weird stuff:

> `Scan Codes`

> `The following is a list of all the regular key scan codes in numerical order:`

> `Scan Scan`

> `Code Key Code Key`

> `1 ESC 44 Z`

> `2 1 45 X`

> `3 2 46 C`

> `4 3 47 V`

> `5 4 48 B`

> `6 5 49 N`

> `7 6 50 M`

> `8 7 51 , <`

> `9 8 52 . >`

> `10 9 53 / ?`

> `11 0 54 RIGHT SHIFT`

> `12 - _ 55 * (KEYPAD)`

> `13 = + 56 LEFT ALT`

> `14 BACKSPACE 57 SPACEBAR`

> `15 TAB 58 CAPSLOCK`

> `16 Q 59 F1`

> `17 W 60 F2`

> `18 E 61 F3`

> `19 R 62 F4`

> `20 T 63 F5`

> `21 Y 64 F6`

> `22 U 65 F7`

> `23 I 66 F8`

> `24 O 67 F9`

> `25 P 68 F10`

> `26 [ { 69 NUMLOCK (KEYPAD)`

> `27 ] } 70 SCROLL LOCK`

> `28 ENTER (RETURN) 71 7 HOME (KEYPAD)`

> `29 LEFT CONTROL 72 8 UP (KEYPAD)`

> `30 A 73 9 PGUP (KEYPAD)`

> `31 S 74 - (KEYPAD)`

> `32 D 75 4 LEFT (KEYPAD)`

> `33 F 76 5 (KEYPAD)`

> `34 G 77 6 RIGHT (KEYPAD)`

> `35 H 78 + (KEYPAD)`

> `36 J 79 1 END (KEYPAD)`

> `37 K 80 2 DOWN (KEYPAD)`

> `38 L 81 3 PGDN (KEYPAD)`

> `39 ; : 82 0 INSERT (KEYPAD)`

> `40 ' " 83 . DEL (KEYPAD)`

> `41 ' ~ 87 F11`

> `42 LEFT SHIFT 88 F12`

> `The following is a list of all the extended key scan codes in numerical order:`

> `Scan Scan`

> `Code Key Code Key`

> `28 ENTER (KEYPAD) 75 LEFT (NOT KEYPAD)`

> `29 RIGHT CONTROL 77 RIGHT (NOT KEYPAD)`

> `42 PRINT SCREEN (SEE TEXT) 79 END (NOT KEYPAD)`

> `53 / (KEYPAD) 80 DOWN (NOT KEYPAD)`

> `55 PRINT SCREEN (SEE TEXT) 81 PAGE DOWN (NOT KEYPAD)`

> `56 RIGHT ALT 82 INSERT (NOT KEYPAD)`

> `71 HOME (NOT KEYPAD) 83 DELETE (NOT KEYPAD)`

> `72 UP (NOT KEYPAD) 111 MACRO`

> `73 PAGE UP (NOT KEYPAD)`

> TOC

> # Mouse

> ### BY | Lewis Sellers lsellers@usit.net

> ### Reset Mouse

> To Call:

> AX = 0

> Return:

> AX = mouse state (-1: installed, 0: not installed)

> BX = number of buttons (2 button mode, 3 button mode)

> gives the current status of the mouse hardware plus the current status of the mouse software. The calling program is able to determine the presence of a mouse driver and/or a serial port.

> This function resets the mouse driver to the following default status as indicated:

> `Variable Value`

> `----------------------------------------------------------------------------`

> `internal cursor flag -1 (cursor concealed)`

> `graphics cursor shape horizontal oval`

> `text cursor reverse video`

> `user-defined call mask all zeroes`

> `light pen emulation mode enabled`

> `vertical mouse motion/pixel ratio 16 to 8`

> `horizontal mouse motion/pixel ratio 8 to 8`

> `vertical min/max cursor coordinates 0/current display mode y values minus 1`

> `horizontal min/max cursor coordinates 0/current display mode x values minus 1`

> Enable Cursor Display

> To Call:

> AX = 1

> INT 31h

> Return:

> none

> Makes the cursor visible if it was not already.

> Disable Cursor Display

> To Call:

> AX = 2

> Return:

> none

> This function disables the cursor (removes it from the screen). Though not visible, all motion by the mouse is still tracked.

> ### Read Cursor Location & Button State of Mouse

> `To Call:`

> `AX = 3`

> `INT 31h`

> `Return:`

> `BX = button status`

> `CX = horizontal cursor coordinate`

> `DX = vertical cursor coordinate`

> `gives the status of mouse buttons, plus cursor location.`

> `Button status consists of a single integer value:`

> `Bit 0 = left button (2 button mode, 3 button mode)`

> `Bit 1 = right button (2 button mode, 3 button mode)`

> `Bit 2 = middle button (3 button mode)`

> `The bit is 1 when the button is pressed. The bit is 0 when the button is released.`

> ### Set Cursor Location of Mouse

> `To Call:`

> `AX = 4`

> `CX = new horizontal cursor coordinate`

> `DX = new vertical cursor coordinate`

> `Return:`

> `none`

> `sets the current cursor location. Values must be within the coordinate ranges for the virtual screen and, if necessary, are rounded to the nearest values allowed for the current screen mode.`

> ### Read Button Press State of Mouse

> `To Call:`

> `AX = 5`

> `BX = button status (left = 0, right = 1, middle = 2)`

> `Return:`

> `AX = button status`

> `BX = number of button presses`

> `CX = horizontal cursor coordinate at last press`

> `DX = vertical cursor coordinate at last press`

> `provides status on the specified button, gives the number of button presses since the last call, and produces the location of the cursor at last button press.`

> `Button status consists of a single integer value. Again, as in function 3:`

> > Bit 0 = left button (2 button mode, 3 button mode)

> > Bit 1 = right button (2 button mode, 3 button mode)

> > Bit 2 = middle button (3 button mode)

> `The bit is 1 when the button is pressed. The bit is 0 when the button is released.`

> `The number of button presses will always fall in the range of 0 to 32767. There is no indicator for overflow. Following this function call, the count is reset to zero.`

> ### Read Button Release State of Mouse

> `To Call:`

> `AX = 6`

> `BX = button status (left = 0, right = 1, middle = 2)`

> `Return:`

> `AX = button status`

> `BX = number of button releases`

> `CX = horizontal cursor coordinate at last release`

> `DX = vertical cursor coordinate at last release`

> `provides status on the specified button, gives the number of button releases since the last call, and provides the location of the cursor at the last button release.`

> `Button status consists of a single integer value. Again, as in function 3:`

> `Bit 0 = left button (2 button mode, 3 button mode)`

> `Bit 1 = right button (2 button mode, 3 button mode)`

> `Bit 2 = middle button (3 button mode)`

> `The bit is 1 when the button is pressed. The bit is 0 when the button is released.`

> `The number of button releases will always fall in the range of 0 to 32767.`

> `There is no indicator for overflow. Following this function call, the count is`

> `reset to zero.`

> ### Define Horizontal (X) Range of Cursor Location

> To Call:

> `AX = 7`

> `CX = minimum horizontal cursor coordinate`

> `DX = maximum horizontal cursor coordinate`

> `Return: none`

> `defines the horizontal range of the cursor on-screen. As a result, cursor movement is limited to this specified area. If a cursor happens to be`

> `outside of this area when a call is made, the cursor is moved to just inside the`

> `area.`

> ### Define Vertical (Y) Range of Cursor Location

> `To Call:`

> `AX = 8`

> `CX = minimum vertical cursor coordinate`

> `DX = maximum vertical cursor coordinate`

> `Return: none`

> defines the vertical range of the cursor on-screen. As a result, cursor movement is limited to this specified area. If a cursor happens to be outside of this area when a call is made, the cursor is moved to just inside the area.

> ### Define Graphics Mode Cursor Style

> To Call: AX = 9

> `BX = horizontal cursor hot spot`

> `CX = vertical cursor hot spot`

> `DX = pointer to screen and cursor mask`

> `Return: none`

> `defines the style of the cursor in terms of color, shape, and center`

> `for the graphics. As mentioned before, this cursor is a 16-by-16 pixel block`

> `and is defined by two 16-bit arrays (the screen mask bit and the cursor mask bit). Cursor coordinates for the hot spot must be in the range of -16 to +16.`

> ### Define Text Mode Cursor Style

> `To Call:`

> `AX = 10`

> `BX = select cursor (0: software text, 1: hardware text)`

> `CX = screen mask value/scan line start`

> `DX = cursor mask value/scan line stop`

> `Return:`

> `none`

> `chooses the hardware or the software text cursor.`

> `For example, if BX (G2%) is 1, the hardware cursor is selected and the hardware`

> `is set up with the first and last scan lines which define the cursor.`

> `(Values for CX (G3%) and DX (G4%) range from 0 to 7 for the color display and 0`

> `to 11 for the monochrome display.)`

> `If BX (G2%) is 0, the software cursor is selected; and CX (G3%) and DX (G4%)`

> `must specify the screen and cursor masks. (These masks give the attributes and`

> `character code of the cursor, and their values are dependent on the type of display in use.)`

> ### Read Mouse Motion Number

> `To Call:`

> `AX = 11`

> `Return:`

> `CX = horizontal number`

> `DX = vertical number`

> `gives the mouse motion number since the last call. A positive horizontal number indicates rightward movement (negative shows leftward movement). A positive vertical number indicates downward movement (negative shows upward movement).`

> `The number is always in the range of -32768 to 32767. Overflow is disregarded. Once the call is completed, the number is set to 0.`

> ### Define Event Handler Entry Location

> `To Call:`

> `AX = 12`

> `CX = call mask`

> `ES:DX = pointer to event handler routine`

> `Return:`

> `none`

> `defines the address entry location of an event handler routine which is called when a certain event (defined by the call mask) occurs. The program is temporarily interrupted by the mouse driver. At the end of the event handler routine the program continues at the point it was interrupted.`

> `The call mask is a single integer value defining the conditions which will cause an interrupt.`

> `A specific condition corresponds to a bit in the call mask:`

> `Mask Bit Condition`

> `--------------------------------------------------`

> `0 cursor location changed`

> `1 left button pressed`

> `2 left button released`

> `3 right button pressed`

> `4 right button released`

> `5 middle button pressed`

> `6 middle button released`

> `7 - 15 not used`

> `In order to call the event handler routine, set the mask bit to 1 and put the mask in at CX (G3%). To disable, set the mask bit to 0 and put the mask in at CX (G3%). Always be sure to set the call mask to 0 before the program finishes. (Leave the system in the same state upon exit as if was upon entrance.)`

> ### Enable Light Pen Emulation Function

> `To Call:`

> `AX = 13`

> `Return:`

> `none`

> `permits the mouse to act like a light pen. When in this mode, calls to the pen function will give the cursor coordinates at the last pen down location.`

> `Note that the status of "pen down" and "pen off-screen" is controlled by the mouse buttons: all buttons up, pen off-screen; one button pressed, pen down.`

> `Light pen emulation is ON after each call to function 0 (Reset Mouse Driver).`

> ### Disable Light Pen Emulation Function

> `To Call:`

> `AX = 14`

> `Return:`

> `none`

> `turns off the light pen emulation mode. When disabled, any call to the pen function will give information only about a real light pen.`

> ### Define Sensitivity (Mouse Motion/Pixel) of Mouse

> `To Call:`

> `AX = 15`

> `CX = horizontal mouse motion counts to pixel ratio`

> `DX = vertical mouse motion counts to pixel ratio`

> `Return:`

> `none`

> `defines mouse sensitivity as determined by the mouse motion/pixel ratio. This is a way of setting the amount of cursor motion wanted for mouse movement. These ratios specify mouse motion per 8 pixels. These values must be in the range of 1 to 32767. With a larger ratio, the cursor movement is shortened for each mouse movement.`

> `Default values: horizontal ratio - 8 mouse motions to 8 pixels`

> `vertical ratio - 16 mouse motions to 8 pixels`

> `Note: 1 mouse motion = 1/200 of an inch increment`

> ### Disable Cursor Display in Special Range

> `To Call:`

> `AX = 16`

> `ES:DX = pointer to special range`

> `Return:`

> `none`

> `sets up a special range on-screen. If the cursor moves to this area or is in this area, it will be disabled. After a call is made to this function, it is necessary to call function 1 to enable the cursor again.`

> `Define the special range with screen location values using four components:`

> `Components Values`

> `--------------------------------------------------------`

> `1 Left horizontal screen location`

> `2 Upper vertical screen location`

> `3 Right horizontal screen location`

> `4 Lower vertical screen location`

> ### Define Double-Speed Threshold

> `To Call:`

> `AX = 19`

> `DX = threshold speed in mouse motions/second`

> `Return:`

> `none`

> `defines the threshold value (mouse motion per second) for doubling the cursor's motion. Should the mouse move faster than the DX (G4%) value, the cursor motion doubles. The default value is 64 mouse motions per second.`

> `If you should want to disable double-speed, just set the threshold to 32767 (7FFFH) mouse motions/second.`

> ### Swap Event Handler Entry Location

> `To Call:`

> `AX = 20`

> `CX = new call mask`

> `ES:DX = new pointer to event handler routine`

> `Return:`

> `CX = old call mask`

> `ES:DX = old pointer to event handler routine`

> `sets new values for the call mask and event handler routine address for mouse hardware interrupts and return the values that were previously specified.`

> `For detail information to reference Function 12 description.`

> ### Get Mouse Driver State Storage Size

> `To Call:`

> `AX = 21`

> `Return:`

> `BX = buffer size required for mouse driver state`

> `returns the size of the buffer required to store the current state of the mouse driver. It is used with functions 22 and 23 when you want to temporarily interrupt a program that is using the mouse and execute another that also uses the mouse.`

> ### Save Mouse Driver state

> `To Call:`

> `AX = 22`

> `ES:DX = pointer to the buffer`

> `Return:`

> `None`

> `saves the current mouse driver state in a buffer allocated by your program. It is used with functions 21 and 23 when you want to temporarily interrupt a program that is using the mouse and execute another program that also uses the mouse.`

> `Before your program calls function 22, the program should call function 21 to determine the buffer size required for saving the mouse driver state, then allocate the appropriate amount of memory.`

> ### Restore Mouse Driver State

> `To Call:`

> `AX = 23`

> `ES:DX = pointer to the buffer`

> `Return:`

> `None`

> `restores the last mouse driver state saved by function 22. It is used with functions 21 and 22 when you want to temporarily interrupt a program that is using the mouse and execute another program that also uses the mouse. To restore the mouse driver state saved by function 22, call function 23 at the end of the interrupt program.`

> ### Set CRT Page Number

> `To Call:`

> `AX = 29`

> `BX = CRT page for mouse cursor display`

> `Return:`

> `none`

> `specifies the CRT page on which the mouse cursor will be displayed.`

> `For information on the number of CRT pages available in each display mode your adapter supports, see the documentation that came with the graphics adapter.`

> ### Read CRT Page Number

> `To Call:`

> `AX = 30`

> `Return:`

> `BX = CRT page number of current cursor display`

> `returns the number of the CRT page on which the mouse cursor is displayed.`

> `The cursor in use is defined as a monochrome cursor with one bit per pixel. The bit masks are determined by function 9 and apply to all active planes.`

> `In order to make an EGA function call from an Assembly-Language program, first load the AX, BX, CX, DX, and ES registers with the values indicated for the parameters. Note that five values must be given for a high level language program. Next, execute software interrupt 16 (10h). The values that are returned are intalled in the registers by EGA functions.`

> `Upon start with DOS, PC BIOS will verify if the EGA BIOS exists. When this is verified, the PC will execute the EGA BIOS, booting up the program to write the INT 10h entry vector to the address of the INT 42h vector. Now, EGA BIOS address will be written to INT 10h. Following this, you are able to call EGA BIOS (by using INT 10h) and PC video BIOS (by using INT 42h).`

> `The following indicates nine EGA functions and the corresponding function number:`

> `Function Number (HEX)`

> `-----------------------------------------------------------------`

> `Retrieve Single Data F0`

> `Save Single Data F1`

> `Retrieve Registers on a Specified Port F2`

> `Save Registers on a Specified Port F3`

> `Retrieve Several Registers Data F4`

> `Save Several Registers Data F5`

> `Reset All Registers as Initial Values F6`

> `Set Initial Values F7`

> `Get Version Number of Mouse Driver FA`

> `In the above functions, the EGA I/O port number and address are as follows:`

> >     Port No.  Register Name   No. of Registers  Index No.  Address Select Register

> >     00H      CRT Controller         25           0 - 24            3x4H
> >     08H      Sequencer               5           0 - 4             3C4H
> >     10H      Graphics Controller     9           0 - 8             3CEH
> >     18H      Attribute Controlle    20           0 - 19            3C0H
> >              Singular Registers
> >     20H      Miscellaneous Output    1           ignored           3C2H
> >     28H      Feature Control         1           ignored           3xAH
> >     30H      Graphics 1 Position     1           ignored           3CCH
> >     38H      Graphics 2 Position     1           ignored           3CAH

> `Note: x = B or D depending on the base I/O address;`

> `determined by Miscellaneous Output Register bit 1.`

> ### Retrieve Single Data

> `To Call:`

> `AH = F0H`

> `BX = Index number`

> `DX = Port number`

> `Return:`

> `BL = Retrieved data from EGA register`

> `This function retrieves data from a single register.`

> ### Save Single Data

> `To Call:`

> `AH = F1H`

> `BL = Index number (Non-single register only)`

> `= Data (Single register only)`

> `BH = Data (Non-single register only)`

> `= Disregard (Single register only)`

> `DX = Port number`

> `Return:`

> `None`

> `This function saves data to an EGA register. Upon finishing a call to this function, the BH and DX values are altered.`

> ### Retrieve Registers on a Specified Port

> `To Call:`

> `AH = F3H`

> `CH = Starting index number`

> `CL = Number of registers`

> `DX = Port number`

> `ES:BX = Destination of returned data`

> `Return:`

> `Returned data to destination address`

> `This function retrieves data from registers on a specifiã port. Upon finishing a call to this function, the CX value is altered.`

> ### Save Registers on a Specified Port

> `To Call:`

> `AH = F3H`

> `CH = Starting index number`

> `CL = Number of register`

> `DX = Port number`

> `ES:BX = Address source of incoming data`

> `Return:`

> `None`

> `This function saves data from registers on a specifiã port. Upon finishing a call to this function, the BX, CX, and DX values are altered.`

> ### Retrieve Several Registers Data At The Same Time

> `To Call: AH = F4H`

> `CX = Number of registers (more than 1)`

> `ES:BX = Address of register packet (each consists of 4 bytes;`

> `port address, byte 1-2; index number, byte 3;`

> `returned data, byte 4)`

> `Return: Returned data is saved into byte 4`

> `This function retrieves data from several registers at the same time. Upon finishing a call to this function, the CX value is altered.`

> ### Save Several Registers Data At The Same Time

> `To Call:`

> `AH = F5H`

> `CX = Number of registers (more than 1)`

> `ES:BX = Address of register packet (each consists of 4 bytes;`

> `port number, byte 1-2; index number, byte 3; output data, byte 4)`

> `Return:`

> `None`

> `This function saves data from several registers at the same time. Upon finishing a call to this function, the CX value is altered.`

> ### Reset All Registers as Initial Values

> `To Call:`

> `AH = F6H`

> `Return:`

> `None`

> `This function resets all values to default values for the specific registers. Function 7 sets the default values.`

> ### Set Initial Values

> `This function sets the initial default values. Upon finishing a call to this function, the BX and DX values are altered.`

> `To Call:`

> `AH = F7H`

> `DX = Port number`

> `ES:BX = Table of output data`

> ### Get Version Number of Mouse Driver

> `This function will give the Mouse driver version number.`

> `To Call:`

> `AH = FAH`

> `BX = 00H`

> `Return:`

> `ES:BX = Pointer to Mouse driver version number.`

> TOC

> # File BIOS/DOS Services

> ### BY | Lewis Sellers lsellers@usit.net

> Under Legacy FCB functions are mostly dummy operations. They provide only enough functionality to emulate getting or setting the "volume label".

> ### "TRUENAME" - CANONICALIZE FILENAME OR PATH

> `To Call:`

> `AH = 60h`

> `DS:SI -> ASCIZ filename or path`

> `ES:DI -> 128-byte buffer for canonicalized name`

> `INT 21h`

> `Return:`

> `CF set on error`

> `AX = error code`

> `02h invalid component in directory path or drive letter only`

> `03h malformed path or invalid drive letter`

> `ES:DI buffer unchanged`

> `CF clear if successful`

> `AH = 00h`

> `AL = destroyed (00h or 5Ch or last char of current dir on drive)`

> `determine the canonical name of the specified filename or path, corresponding to the undocumented TRUENAME command in COMMAND.COM`

> `Notes: the input path need not actually exist`

> `letters are uppercased, forward slashes converted to backslashes,`

> `asterisks converted to appropriate number of question marks, and`

> `file and directory names are truncated to 8.3 if necessary. (DR-DOS`

> `3.41 and 5.0 do not expand asterisks)`

> `'.' and '..' in the path are resolved`

> `filespecs on local drives always start with "d:", those on network`

> `drives always start with "\\"`

> `if path string is on a JOINed drive, the returned name is the one that`

> `would be needed if the drive were not JOINed; similarly for a`

> `SUBSTed, ASSIGNed, or network drive letter. Because of this, it is`

> `possible to get a qualified name that is not legal under the current`

> `combination of SUBSTs, ASSIGNs, JOINs, and network redirections`

> `under DOS 3.3 through 6.00, a device name is translated differently if`

> `the device name does not have an explicit directory or the directory`

> `is \DEV (relative directory DEV from the root directory works`

> `correctly). In these cases, the returned string consists of the`

> `unchanged device name and extension appended to the string X:/`

> `(forward slash instead of backward slash as in all other cases) where`

> `X is the default or explicit drive letter.`

> `functions which take pathnames require canonical paths if invoked via`

> `INT 21/AX=5D00h`

> `supported by OS/2 v1.1 compatibility box`

> ### Far East DOS 3.2+ - GET DOUBLE BYTE CHARACTER SET LEAD-BYTE TABLE

> `To Call:`

> `AX = 6300h`

> `INT 21h`

> `Return:`

> `AL = error code`

> `00h successful`

> `DS:SI -> DBCS table (see #0952)`

> `all other registers except CS:IP and SS:SP destroyed`

> `FFh not supported`

> `the US version of MS-DOS 3.30 treats this as an unused function, setting AL=00h and returning immediately the US version of DOS 4.0+ accepts this function, but returns an empty list`

> `Format of DBCS table:`

> `Offset Size Description (Table 0952)`

> `00h 2 BYTEs low/high ends of a range of leading byte of double-byte chars`

> `02h 2 BYTEs low/high ends of a range of leading byte of double-byte chars`

> `...`

> `N 2 BYTEs 00h,00h end flag`

> `INT 21 - DOS 2.25, Far East DOS 3.2+ - SET KOREAN (HANGEUL) INPUT MODE`

> `AX = 6301h`

> `DL = new mode`

> `00h return only full characters on DOS keyboard input functions`

> `01h return partially-formed (interim) characters also`

> `Return: AL = status`

> `00h successful`

> `FFh invalid mode`

> ### DOS 2.25, Far East DOS 3.2+ - GET KOREAN (HANGEUL) INPUT MODE

> `AX = 6302h`

> `INT 21h`

> `Return: AL = status`

> `00h successful`

> `DL = current input mode`

> `00h return only full characters (clears interim flag)`

> `01h return partial characters (sets interim flag)`

> `FFh not supported`

> `INT 21 - DOS 3.3+ - SET HANDLE COUNT`

> `AH = 67h`

> `BX = size of new file handle table for process`

> `Return: CF clear if successful`

> `CF set on error`

> `AX = error code (see #0885 at AH=59h)`

> `Desc: adjust the size of the per-process open file table, thus raising or`

> `lowering the limit on the number of files the caller can open`

> `simultaneously`

> `Notes: if BX <= 20, no action is taken if the handle limit has not yet been`

> `increased, and the table is copied back into the PSP if the limit`

> `is currently > 20 handles`

> `for file handle tables of > 20 handles, DOS 3.30 never reuses the`

> `same memory block, even if the limit is being reduced; this can lead`

> `to memory fragmentation as a new block is allocated and the existing`

> `one freed`

> `only the first 20 handles are copied to child processes in DOS 3.3-6.0`

> `increasing the file handles here will not, in general, increase the`

> `number of files that can be opened using the runtime library of a`

> `high-level language such as C`

> `Novell DOS 7 reportedly terminates the calling program if the JFT is`

> `being reduced in size and there are any open file handles beyond`

> `the portion of the JFT being retained`

> `BUGS: the original release of DOS 3.30 allocates a full 64K for the handle`

> `table on requests for an even number of handles`

> `DR-DOS 3.41 and 5.0 will lose track of any open file handles beyond`

> `the portion of the JFT retained after the call; MS-DOS will indicate`

> `error 04h if any of the JFT entries to be removed are open`

> `INT 21 - DOS 3.3+ - "FFLUSH" - COMMIT FILE`

> `AH = 68h`

> `BX = file handle`

> `Return: CF clear if successful`

> `all data still in DOS disk buffers is written to disk immediately,`

> `and the file's directory entry is updated`

> `CF set on error`

> `AX = error code (see #0885 at AH=59h)`

> `INT 21 U - DOS 4.0+ - COMMIT FILE`

> `AH = 6Ah`

> `BX = file handle`

> `Return: CF clear if successful`

> `AH = 68h`

> `CF set on error`

> `AX = error code (06h) (see #0885 at AH=59h)`

> `identical to AH=68h in DOS 5.0-6.0; not known whether this is the case in DOS 4.x`

> ### EXTENDED OPEN/CREATE

> `AX = 6C00h`

> `BL = open mode as in AL for normal open (see also AH=3Dh)`

> `bit 7: inheritance`

> `bits 4-6: sharing mode`

> `bit 3 reserved`

> `bits 0-2: access mode`

> `BH = flags`

> `bit 6 = auto commit on every write (see also AH=68h)`

> `bit 5 = return error rather than doing INT 24h`

> `CX = create attribute (see #0965)`

> `DL = action if file exists/does not exist (see #0966)`

> `DH = 00h (reserved)`

> `DS:SI -> ASCIZ file name`

> `INT 21h`

> `Return: CF set on error`

> `AX = error code (see #0885 at AH=59h)`

> `CF clear if successful`

> `AX = file handle`

> `CX = status (see #0964)`

> `(Table 0964)`

> `Values for extended open function status:`

> `01h file opened`

> `02h file created`

> `03h file replaced`

> `Bitfields for file create attribute:`

> `Bit(s) Description (Table 0965)`

> `6-15 reserved`

> `5 archive`

> `4 reserved`

> `3 volume label`

> `2 system`

> `1 hidden`

> `0 readonly`

> `Bitfields for action:`

> `Bit(s) Description (Table 0966)`

> `7-4 action if file does not exist`

> `0000 fail`

> `0001 create`

> `3-0 action if file exists`

> `0000 fail`

> `0001 open`

> `0010 replace/open`

> `INT 21 - MS-DOS 7 (Windows95) - ??? (country-specific?)`

> `AH = 70h`

> `AL = subfunction`

> `00h get ??? info`

> `CX = buffer size (3Ah bytes needed)`

> `ES:DI -> buffer`

> `01h set above info`

> `02h set ??? info`

> `CX = buffer size >= 26h;`

> `first three bytes are skipped, the rest is copied to somewhere`

> `in the DOS data segment`

> `Return: CF clear if successful`

> `ES:DI buffer filled (func 00h)`

> `returned was (among others) "ENU USA GR"..."AM PM M/d/yy"...`

> `"dddd,MMMMdd,yyyy" in the German Preview version, and "US"`

> `instead of "GR" in the US build 450 version (with German`

> `country setting)`

> `CF set on error`

> `AX = error code`

> `7000h if function not supported`

> ### MS-DOS 7 - LONG FILENAME FUNCTIONS

> `To Call:`

> `AH = 71h`

> `AL = function`

> `39h create directory`

> `3Ah remove directory`

> `3Bh set current directory`

> `41h delete file`

> `43h get file attributes (BL=00h), set file attributes (BL=01h)`

> `47h get current directory`

> `4Eh find first file`

> `4Fh find next file`

> `56h move (rename) file`

> `6Ch create/open file`

> `INT 21h`

> `Return:`

> `CF set on error`

> `AX = error code`

> `7100h if function not supported`

> `CF clear if successful`

> `other registers as for corresponding "old" DOS function`

> `if error 7100h is returned, the old-style function should be called AX=714Eh returns a "search handle" which must be passed to AX=714Fh; when the search is complete, AX=71A1h must be called to terminate the search`

> `INT 21 - Windows95 - LONG FILENAME - FIND FIRST MATCHING FILE`

> `AX = 714Eh`

> `SI = 0000h`

> `DS:DX -> ASCIZ filespec`

> `ES:DI -> FindData record (see #2695)`

> `Return: CF clear if successful`

> `AX = filefind handle (needed to continue search)`

> `CF set on error`

> `AX = error code`

> `7100h if function not supported`

> `Format of Windows95 long filename FindData record:`

> `Offset Size Description (Table 2695)`

> `00h DWORD file attributes`

> `bits 0-6 standard DOS attributes (see #0643 at INT 21/AX=4301h)`

> `bit 8: temporary file`

> `04h QWORD file creation time (number of 100ns intervals since 1/1/1601)`

> `0Ch QWORD last access time`

> `14h QWORD last modification time`

> `1Ch DWORD file size (high 32 bits)`

> `20h DWORD file size (low 32 bits)`

> `24h 8 BYTEs reserved`

> `2Ch 260 BYTEs ASCIZ full filename`

> `130h 14 BYTEs ASCIZ short filename (for backward compatibility)`

> `INT 21 - Windows95 - LONG FILENAME - FIND NEXT MATCHING FILE`

> `AX = 714Fh`

> `SI = 0000h`

> `BX = filefind handle (from AX=714Eh)`

> `ES:DI -> FindData record (see #2695)`

> `Return: CF clear if successful`

> `CF set on error`

> `AX = error code`

> `7100h if function not supported`

> ### Windows95 - LONG FILENAME - "TRUENAME" - CANONICALIZE FILENAME OR PATH

> `AX = 7160h`

> `CX = ??? (apparently must be 0002h)`

> `DS:SI -> ASCIZ filename or path`

> `ES:DI -> 128-byte buffer for canonicalized name`

> `INT 21h`

> `Return: CF set on error`

> `AX = error code`

> `02h invalid component in directory path or drive letter only`

> `03h malformed path or invalid drive letter`

> `ES:DI buffer unchanged`

> `CF clear if successful`

> `AH = 00h`

> `AL = destroyed (00h or 5Ch or last char of current dir on drive)`

> ### Windows95 - LONG FILENAME - GET VOLUME INFORMATION

> `AX = 71A0h`

> `DS:SI -> ASCIZ root name (e.g. "C:\")`

> `ES:DI -> buffer for file system name`

> `CX = size of ES:DI buffer`

> `INT 21h`

> `Return: CF clear if successful`

> `BX = flags (see below)`

> `CX = maximum length of file name [usually 255]`

> `DX = maximum length of path [usually 260]`

> `ES:DI buffer filled (ASCIZ, e.g. "FAT","NTFS","CDFS")`

> `CF set on error`

> `AX = error code`

> `7100h if function not supported`

> `for the file system name buffer, 32 bytes should be sufficient;`

> `Bitfields for flags:`

> `Bit(s) Description`

> `0 searches are case sensitive`

> `1 preserves case in directory entries`

> `2 uses Unicode characters in file and directory names`

> `3-13 reserved (0)`

> `14 supports DOS long filename functions`

> `15 volume is compressed`

> ### Windows95 - LONG FILENAME - "FindClose" - TERMINATE DIRECTORY SEARCH

> `AX = 71A1h`

> `BX = filefind handle (from AX=714Eh)`

> `INT 21h`

> `Return: CF clear if successful`

> `CF set on error`

> `AX = error code`

> `7100h if function not supported`

> `this function must be called after starting a search with AX=714Eh, to indicate that the search handle returned by that function will no longer be used`

> ### MS-DOS 7 (Windows95) - DRIVE LOCKING ???

> `AH = 73h`

> `AL = subfunction`

> `00h get ???: CL =`

> `00h: drive flag???`

> `01h: ??? flag`

> `01h set ???: CL =`

> `00h: drive flag???`

> `set to 06h if CH bit 1 =1, else to 00h`

> `01h: ??? flag`

> `set flag bit 3 to bit 3 of CH`

> `DL = drive (0=current, 1=A:, etc.)`

> `INT 21h`

> `Return: CF clear if successful`

> `for AL=00h:`

> `AL = value of CL on entry`

> `for CL=00h: AH = flag and 06h (i.e. bits 1 and 2 used)`

> `for CL=01h: AH = flag and 08h (i.e. bit 3 used)`

> `(flag being taken from a table of bytes)`

> `CF set on error`

> `AX = error code`

> `7300h if function not supported`

> `INT 21 - European MS-DOS 4.0 - "AEXEC" - EXECUTE PROGRAM IN BACKGROUND`

> `AH = 80h`

> `CX = mode`

> `0000h place child in zombie mode on exit to preserve exit code`

> `0001h discard child process and exit code on termination`

> `DS:DX -> ASCIZ full program name`

> `ES:BX -> parameter block (as for AX=4B00h)`

> `Return: CF clear if successful`

> `AX = Command Subgroup ID (CSID)`

> `CF set on error`

> `AX = error code (see #0885 at AH=59h)`

> `European MS-DOS 4.0 was written for Siemens in Germany and then used by several other European OEMs; its release falls between mainstream versions 3.2 and 3.3 asynchronously execute a program, creating a new process for it`

> `Notes: this function is called by the DETACH command`

> `there is a system-wide limit of 32 processes`

> `the CSID is used to identify all processes that have been spawned by`

> `a given process, whether directly or indirectly`

> `programs to be run in the background must use the new executable format`

> `(see #0809 at AH=4Bh)`

> `background processes may only perform asynchronous (background) EXECs,`

> `either this function or AX=4B04h`

> `background processes may execute INT 11, INT 12, INT 21, INT 2A, and`

> `INT 2F at any time; they may execute INT 10 and INT 16 only while`

> `they have opened a popup screen via INT 2F/AX=1401h; no other`

> `interrupts may be executed from the background`

> `background processes may not use drive B: or overlay their code`

> `segments`

> `see AX=8700h for an installation check`

> `the "NE" new executable format made its first appearance in European`

> `MS-DOS 4.0`

> `INT 21 - European MS-DOS 4.0 - "FREEZE" - STOP A PROCESS`

> `AH = 81h`

> `BX = flag (00h freeze command subtree, 01h only specified process)`

> `CX = Process ID of head of command subtree`

> `Return: CF clear if successful`

> `CF set on error`

> `AX = error code (no such process)`

> `Desc: temporarily suspend a process or a process and all of its children`

> `Note: if BX=0001h, this call will not return until the process is actually`

> `frozen, which may not be until after it unblocks from an I/O`

> `operation`

> `INT 21 - European MS-DOS 4.0 - "RESUME" - RESTART A PROCESS`

> `AH = 82h`

> `BX = flag (00h resume command subtree, 01h only specified process)`

> `CX = Process ID of head of command subtree`

> `Return: CF clear if successful`

> `CF set on error`

> `AX = error code (no such process)`

> `restart a previously-suspended process or a process and all of its children`

> `INT 21 - European MS-DOS 4.0 - "PARTITION" - GET/SET FOREGROUND PARTITION SIZE`

> `AH = 83h`

> `AL = function`

> `00h get size`

> `01h set new size`

> `BX = new size in paragraphs`

> `Return: CF clear if successful`

> `BX = current size (function 00h) or old size (function 01h)`

> `CF set on error`

> `AX = error code (01h,07h,0Dh)(see #0885 at AH=59h)`

> `Desc: specify or determine how much memory may be allocated by the foreground`

> `process`

> `Note: if the partition size is set to 0000h, no partition management is done`

> `and all memory allocation is compatible with DOS 3.2.`

> `the partition size can be changed regardless of what use is being made`

> `of the changed memory; subsequent allocations will follow the`

> `partition rules (foreground processes may allocate only foreground`

> `memory; background processes allocate background memory first, then`

> `foreground memory)`

> `INT 21 - European MS-DOS 4.0 - "CREATMEM" - CREATE A SHARED MEMORY AREA`

> `AX = 8400h`

> `BX = size in bytes (0000h = 65536)`

> `CX = flags`

> `bit 6: zero-initialize segment`

> `DS:DX -> ASCIZ name (must begin with "\SHAREMEM\")`

> `Return: CF clear if successful`

> `AX = segment address of shared memory global object`

> `CF set on error`

> `AX = error code (06h,08h) (see #0885 at AH=59h)`

> `Desc: create an area of memory which may be accessed by multiple processes`

> `Notes: shared memory objects are created as special files (thus the restriction on the name) on successful creation, the reference count is set to 1`

> `INT 21 - European MS-DOS 4.0 - "GETMEM" - OBTAIN ACCESS TO SHARED MEMORY AREA`

> `AX = 8401h`

> `CX = flags`

> `bit 7: writable segment (ignored by MS-DOS 4.0)`

> `DS:DX -> ASCIZ name (must begin with "\SHAREMEM\")`

> `Return: CF clear if successful`

> `AX = segment address of shared memory global object`

> `CX = size in bytes`

> `CF set on error`

> `AX = error code (invalid name)`

> `get address of a previously-created area of memory which may be accessed by multiple processes`

> `Note: this call increments the reference count for the shared memory area`

> `INT 21 - European MS-DOS 4.0 - "RELEASEMEM" - FREE SHARED MEMORY AREA`

> `AX = 8402h`

> `BX = handle (segment address of shared memory object)`

> `Return: CF clear if successful`

> `CF set on error`

> `AX = error code (no such name)`

> `Desc: indicate that the specified area of shared memory will no longer be`

> `used by the caller`

> `Note: the reference count is decremented and the shared memory area is`

> `deallocated if the new reference count is zero`

> `SeeAlso: AX=8400h,AX=8401h,INT 15/AX=DE19h`

> `INT 21 - European MS-DOS 4.0 - "SETFILETABLE" - INSTALL NEW FILE HANDLE TABLE`

> `AH = 86h`

> `BX = total number of file handles in new table`

> `Return: CF clear if successful`

> `CF set on error`

> `AX = error code (06h,08h) (see #0885 at AH=59h)`

> `Desc: adjust the size of the per-process open file table, thus raising or`

> `lowering the limit on the number of files the caller can open`

> `simultaneously`

> `Notes: any currently-open files are copied to the new table`

> `if the table is increased beyond the default 20 handles, only the`

> `first 20 will be inherited by child processes`

> `error 06h is returned if the requested number of handles exceeds`

> `system limits or would require closing currently-open files`

> `INT 21 - European MS-DOS 4.0 - "GETPID" - GET PROCESS IDENTIFIER`

> `AH = 87h`

> `Return: AX = PID`

> `BX = parent process's PID`

> `CX = Command Subgroup ID (CSID)`

> `Program: European MS-DOS 4.0 was written for Siemens in Germany and then used`

> `by several other European OEMs; its release falls between mainstream`

> `versions 3.2 and 3.3`

> `Desc: determine an identifier by which to access the calling process`

> `Notes: called by MS C v5.1 getpid() function`

> `this function apparently must return AX=0001h for INT 21/AH=80h to`

> `succeed`

> `one possible check for European MS-DOS 4.0 is to issue this call with`

> `AL=00h and check whether AL is nonzero on return`

> `INT 21 - European MS-DOS 4.0 - SLEEP`

> `AH = 89h`

> `CX = time in milliseconds or 0000h to give up time slice`

> `Return: CF clear if successful`

> `CX = 0000h`

> `CF set on error`

> `AX = error code (interrupted system call)`

> `CX = sleep time remaining`

> `Desc: suspend the calling process for the specified duration`

> `Notes: the sleep interval is rounded up to the next higher increment of the`

> `scheduler clock, and may be extended further if other processes are`

> `running`

> `this call may be interrupted by signals (see AH=8Dh)`

> `reportedly called by Microsoft C 4.0 startup code`

> `background processes have higher priority than the foreground process,`

> `and should thus periodically yield the CPU`

> `INT 21 - European MS-DOS 4.0 - "CWAIT" - WAIT FOR CHILD TO TERMINATE`

> `AH = 8Ah`

> `BL = range (00h command subtree, 01h any child)`

> `BH = suspend flag`

> `00h suspend if children exist but none are dead`

> `01h return if no dead children`

> `CX = Process ID of head of command subtree`

> `Return: CF clear if successful`

> `AH = termination type (see #0970)`

> `AL = return code from child or aborting signal`

> `BX = PID of child (0000h if no dead children)`

> `CF set on error`

> `AX = error code (no child,interrupted system call)`

> `Desc: get return code from an asynchronously-executed child program,`

> `optionally waiting if no return code is available`

> `(Table 0970)`

> `Values for termination type:`

> `00h normal termination`

> `01h aborted by Control-C`

> `02h aborted by I/O error`

> `03h terminate and stay resident`

> `04h aborted by signal`

> `05h aborted by program error`

> `INT 21 - European MS-DOS 4.0 - SET SIGNAL HANDLER`

> `AH = 8Ch`

> `AL = signal number (see #0971)`

> `BL = action (see #0972)`

> `DS:DX -> signal handler (see #0973)`

> `Return: CF clear if successful`

> `AL = previous action`

> `ES:BX -> previous signal handler`

> `CF set on error`

> `AX = error code (01h,invalid SigNumber or Action)`

> `(see #0885 at AH=59h)`

> `Desc: set the routine which will be invoked on a number of exceptional`

> `conditions`

> `Note: all signals will be sent to the most recently installed handler`

> `(Table 0971)`

> `Values for European MS-DOS 4.0 signal number:`

> `01h SIGINTR Control-C or user defined interrupt key`

> `08h SIGTERM program termination`

> `09h SIGPIPE broken pipe`

> `0Dh SIGUSER1 reserved for user definition`

> `0Eh SIGUSER2 reserved for user definition`

> `(Table 0972)`

> `Values for signal action:`

> `00h SIG_DFL terminate process on receipt`

> `01h SIG_IGN ignore signal`

> `02h SIG_GET signal is accepted`

> `03h SIG_ERR sender gets error`

> `04h SIG_ACK acknowledge received signal and clear it, but don't`

> `change current setting`

> `(Table 0973)`

> `Values signal handler is called with:`

> `AL = signal number (see #0971)`

> `AH = signal argument`

> `Return: RETF, CF set: terminate process`

> `RETF, CF clear, ZF set: abort any interrupted system call with an error`

> `RETF, CF clear, ZF clear: restart any interrupted system call`

> `IRET: restart any interrupted system call`

> `Note: the signal handler may also perform a nonlocal GOTO by resetting the`

> `stack pointer and jumping; before doing so, it should dismiss the`

> `signal by calling this function with BL=04h`

> `INT 21 - European MS-DOS 4.0 - SEND SIGNAL`

> `AH = 8Dh`

> `AL = signal number (see #0971)`

> `BH = signal argument`

> `BL = action`

> `00h send to entire command subtree`

> `01h send only to specified process`

> `DX = Process ID`

> `Return: CF clear if successful`

> `CF set on error`

> `AX = error code (01h,06h)(see #0885 at AH=59h)`

> `Desc: invoke the exceptional-condition handler for the specified process`

> `Note: error 06h may be returned if one or more of the affected processes`

> `have an error handler for the signal`

> `INT 21 - European MS-DOS 4.0 - "SETPRI" - GET/SET PROCESS PRIORITY`

> `AX = 8E00h`

> `BH = 00h`

> `BL = action`

> `00h set priority for command subtree`

> `01h set priority for specified process only`

> `CX = Process ID`

> `DH = 00h`

> `DL = change in priority (00h to get priority)`

> `Return: CF clear if successful`

> `DL = process priority`

> `DH destroyed`

> `CF set on error`

> `AX = error code (01h,no such process)(see #0885 at AH=59h)`

> `Desc: specify or determine the execution priority of the specified process`

> `or the process and all of its children`

> `INT 21 - European MS-DOS 4.0 - "PIPE" - CREATE A NEW PIPE`

> `AH = 93h`

> `CX = size in bytes`

> `Return: CF clear if successful`

> `AX = read handle`

> `BX = write handle`

> `CF set on error`

> `AX = error code (08h) (see #0885 at AH=59h)`

> `create a communications channel which may be used for interprocess data and command exchanges`

> `INT 21 - European MS-DOS 4.0 - HARD ERROR PROCESSING`

> `AH = 95h`

> `AL = new state`

> `00h enabled`

> `01h disabled, automatically fail hard errors`

> `Return: AX = previous setting`

> `specify whether hard (critical) errors should automatically fail the system call or invoke an INT 24`

> ### European MS-DOS 4.0 - "PBLOCK" - BLOCK A PROCESS

> `AH = 99h`

> `DS:BX -> memory location to block on`

> `CX = timeout in milliseconds`

> `DH = nonzero if interruptable`

> `INT 21h`

> `Return: CF clear if awakened by event`

> `AX = 0000h`

> `CF set if unusual wakeup`

> `ZF set if timeout, clear if interrupted by signal`

> `AX = nonzero`

> `suspend calling process until another process sends a "restart" signal or a timeout occurs`

> ### European MS-DOS 4.0 - "PRUN" - UNBLOCK A PROCESS

> `AH = 9Ah`

> `DS:BX -> memory location processes may have blocked on`

> `INT 21h`

> `Return: AX = number of processes awakened`

> `ZF set if no processes awakened`

> `European MS-DOS 4.0 was written for Siemens in Germany and then used by several other European OEMs; its release falls between mainstream versions 3.2 and 3.3 restart all processes waiting for the specified "restart" signal
> `

> `INT 21 - DOS 1+ - READ CHARACTER FROM STANDARD INPUT, WITH ECHO`

> `AH = 01h`

> `Return: AL = character read`

> `Notes: ^C/^Break are checked, and INT 23 executed if read`

> `character is echoed to standard output`

> `standard input is always the keyboard and standard output the screen`

> `under DOS 1.x, but they may be redirected under DOS 2+`

> `INT 21 - DOS 1+ - WRITE CHARACTER TO STANDARD OUTPUT`

> `AH = 02h`

> `DL = character to write`

> `Return: AL = last character output (despite the official docs which state`

> `nothing is returned) (at least DOS 3.3-5.0)`

> `Notes: ^C/^Break are checked, and INT 23 executed if pressed`

> `standard output is always the screen under DOS 1.x, but may be`

> `redirected under DOS 2+`

> `the last character output will be the character in DL unless DL=09h`

> `on entry, in which case AL=20h as tabs are expanded to blanks`

> `INT 21 - DOS 1+ - READ CHARACTER FROM STDAUX`

> `AH = 03h`

> `Return: AL = character read`

> `Notes: keyboard checked for ^C/^Break, and INT 23 executed if detected`

> `STDAUX is usually the first serial port`

> `INT 21 - DOS 1+ - WRITE CHARACTER TO STDAUX`

> `AH = 04h`

> `DL = character to write`

> `Notes: keyboard checked for ^C/^Break, and INT 23 executed if detected`

> `STDAUX is usually the first serial port`

> `if STDAUX is busy, this function will wait until it becomes free`

> ### WRITE CHARACTER TO PRINTER

> `AH = 05h`

> `DL = character to print`

> `INT 21h`

> `Notes: keyboard checked for ^C/^Break, and INT 23 executed if detected`

> `STDPRN is usually the first parallel port, but may be redirected under DOS 2+ if the printer is busy, this function will wait`

> ### DIRECT CONSOLE OUTPUT

> `AH = 06h`

> `DL = character (except FFh)`

> `INT 21h`

> `Return:`

> `AL = character output`

> `Writes to standard output, which is usally the screen.`

> ### DIRECT CONSOLE INPUT

> `AH = 06h`

> `DL = FFh`

> `INT 21h`

> `Return: ZF set if no character available`

> `AL = 00h`

> `ZF clear if character available`

> `AL = character read`

> `Notes: ^C/^Break are NOT checked if the returned character is 00h, the user pressed a key with an`

> `extended keycode, which will be returned by the next call of this`

> `function`

> `this function reads from standard input, which is always the keyboard`

> `under DOS 1.x, but may be redirected under DOS 2+`

> `although the return of AL=00h when no characters are available is not`

> `documented, some programs rely on this behavior`

> ### DIRECT CHARACTER INPUT, WITHOUT ECHO

> `AH = 07h`

> `INT 21h`

> `Return:`

> `AL = character read from standard input`

> `Notes: does not check ^C/^Break`

> `standard input is always the keyboard under DOS 1.x, but may be`

> `redirected under DOS 2+`

> `if the interim console flag is set (see AX=6301h), partially-formed`

> `double-byte characters may be returned`

> ### CHARACTER INPUT WITHOUT ECHO

> `AH = 08h`

> `INT 21h`

> `Return: AL = character read from standard input`

> `Notes: ^C/^Break are checked, and INT 23 executed if detected`

> `standard input is always the keyboard under DOS 1.x, but may be`

> `redirected under DOS 2+`

> `if the interim console flag is set (see AX=6301h), partially-formed`

> `double-byte characters may be returned`

> ### WRITE STRING TO STANDARD OUTPUT

> `AH = 09h`

> `DS:DX -> '$'-terminated string`

> `INT 21h`

> `Return:`

> `AL = 24h`

> ### BUFFERED INPUT

> `AH = 0Ah`

> `DS:DX -> buffer (see #0573)`

> `INT 21h`

> `Return:`

> `buffer filled with user input`

> `Notes: ^C/^Break are checked, and INT 23 is called if either detected`

> `reads from standard input, which may be redirected under DOS 2+`

> `if the maximum buffer size (see #0573) is set to 00h, this call returns immediately without reading any input`

> `Format of DOS input buffer:`

> `Offset Size Description (Table 0573)`

> `00h BYTE maximum characters buffer can hold`

> `01h BYTE (call) number of chars from last input which may be recalled`

> `(ret) number of characters actually read, excluding CR`

> `02h N BYTEs actual characters read, including the final carriage return`

> ### GET STDIN STATUS

> `AH = 0Bh`

> `INT 21h`

> `Return:`

> `AL = status`

> `00h if no character available`

> `FFh if character is available`

> `Notes: ^C/^Break are checked, and INT 23 is called if either pressed`

> `standard input is always the keyboard under DOS 1.x, but may be`

> `redirected under DOS 2+`

> `if the interim console flag is set (see AX=6301h), this function`

> `returns AL=FFh if a partially-formed double-byte character is`

> `available`

> ### FLUSH BUFFER AND READ STANDARD INPUT

> `AH = 0Ch`

> `AL = STDIN input function to execute after flushing buffer`

> `other registers as appropriate for the input function`

> `INT 21h`

> `Return:`

> `as appropriate for the specified input function`

> `if AL is not one of 01h,06h,07h,08h, or 0Ah, the buffer is flushed but no input is attempted`

> ### DISK RESET

> `AH = 0Dh`

> `INT 21h`

> `Return:`

> `This function writes all modified disk buffers to disk, but does not`

> `update the directory information (that is only done when files are`

> `closed or a SYNC call is issued)`

> ### SELECT DEFAULT DRIVE

> `AH = 0Eh`

> `DL = new default drive (00h = A:, 01h = B:, etc)`

> `INT 21h`

> `Return:`

> `AL = number of potentially valid drive letters`

> ### GET CURRENT DEFAULT DRIVE

> `AH = 19h`

> `INT 21h`

> `Return: AL = drive (00h = A:, 01h = B:, etc)`

> ### SET DISK TRANSFER AREA ADDRESS

> `AH = 1Ah`

> `DS:DX -> Disk Transfer Area (DTA)`

> `INT 21h`

> `The DTA is set to PSP:0080h when a program is started. Note that the DTA is DOS hack. The 128 byte area is emulated for DOS purposes.`

> ### GET ALLOCATION INFORMATION FOR DEFAULT DRIVE

> `AH = 1Bh`

> `INT 21h`

> `Return:`

> `AL = sectors per cluster (allocation unit)`

> `CX = bytes per sector`

> `DX = total number of clusters`

> `DS:BX -> media ID byte (see #0581)`

> `under DOS 1.x, DS:BX points at an actual copy of the FAT; later versions return a pointer to a copy of the FAT's ID byte`

> `(Table 0581)`

> `Values for media ID byte:`

> `FFh floppy, double-sided, 8 sectors per track (320K)`

> `FEh floppy, single-sided, 8 sectors per track (160K)`

> `FDh floppy, double-sided, 9 sectors per track (360K)`

> `FCh floppy, single-sided, 9 sectors per track (180K)`

> `FAh HP 200LX D: ROM disk, 16 sectors per track (995K)`

> `HP 200LX E: (Stacker host drive ???)`

> `F9h floppy, double-sided, 15 sectors per track (1.2M)`

> `floppy, double-sided, 9 sectors per track (720K,3.5")`

> `F8h hard disk`

> `F0h other media`

> `(e.g. floppy, double-sized, 18 sectors per track -- 1.44M,3.5")`

> ### GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE

> `AH = 1Ch`

> `DL = drive (00h = default, 01h = A:, etc)`

> `INT 21h`

> `Return:`

> `AL = sectors per cluster (allocation unit), or FFh if invalid drive`

> `CX = bytes per sector`

> `DX = total number of clusters`

> `DS:BX -> media ID byte (see #0581)`

> ### GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE

> `AH = 1Fh`

> `INT 21h`

> `Return: AL = status`

> `00h successful`

> `DS:BX -> Drive Parameter Block (DPB) AH=32h for DOS 2+)`

> `FFh invalid drive`

> `this call was undocumented prior to the release of DOS 5.0; however,`

> `only the DOS 4.0+ version of the DPB has been documented`

> ### SET VERIFY FLAG

> `To Call:`

> `AH = 2Eh`

> `DL = 00h (DOS 1.x/2.x only)`

> `AL = new state of verify flag`

> `00h off`

> `01h on`

> `INT 21h`

> `When enabled, read-after-write verification is used.
> `

> ### GET DISK TRANSFER AREA ADDRESS

> `AH = 2Fh`

> `INT 21h`

> `Return: ES:BX -> current DTA`

> ### GET DOS VERSION

> `AH = 30h`

> `AL = what to return in BH`

> `00h OEM number`

> `01h version flag`

> `INT 21h`

> `Return:`

> `AL = major version number`

> `AH = minor version number`

> `BL:CX = 24-bit user serial number (most versions do not use this)`

> `if AL=00h`

> `BH = MS-DOS OEM number`

> `if AL=01h`

> `BH = version flag`

> `bit 3: DOS is in ROM`

> `The version is returned as 7.0. Use INT FFh SET VERSION if needed. For the OEM number, Grail Millenium returns 6Dh, which is the ASCII char for 'm', which is the number 1000.`

> `Values for DOS OEM number:`

> `00h IBM`

> `01h Compaq`

> `02h MS Packaged Product`

> `04h AT&T`

> `05h ZDS (Zenith Electronics)`

> `06h Hewlett-Packard`

> `07h ZDS (Groupe Bull)`

> `0Dh Packard-Bell`

> `16h DEC`

> `23h Olivetti`

> `28h Texas Instruments`

> `29h Toshiba`

> `33h Novell (Windows/386 device IDs only)`

> `34h MS Multimedia Systems (Windows/386 device IDs only)`

> `35h MS Multimedia Systems (Windows/386 device IDs only)`

> `4Dh Hewlett-Packard`

> `5Eh RxDOS`

> `66h PhysTechSoft (PTS-DOS)`

> `6Dh Grail Millenium`

> `99h General Software's Embedded DOS`

> `EEh DR-DOS`

> `EFh Novell DOS`

> `FFh Microsoft, Phoenix`

> `INT 21 - DOS 2+ - TERMINATE AND STAY RESIDENT`

> `AH = 31h`

> `AL = return code`

> `DX = number of paragraphs to keep resident`

> `Return: never`

> `Notes: the value in DX only affects the memory block containing the PSP;`

> `additional memory allocated via AH=48h is not affected`

> `the minimum number of paragraphs which will remain resident is 11h`

> `for DOS 2.x and 06h for DOS 3.0+`

> `most TSRs can save some memory by releasing their environment block`

> `before terminating (see #0603 at AH=26h,AH=49h)`

> ### GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE

> `AH = 32h`

> `DL = drive number (00h = default, 01h = A:, etc)`

> `INT 21h`

> `Return:`

> `AL = status`

> `00h successful`

> `DS:BX -> Drive Parameter Block (DPB) for specified drive`

> `FFh invalid or network drive`

> `The values here are synthesised for consumption by DOS.`

> `Format of DOS Drive Parameter Block:`

> `Offset Size Description (Table 0620)`

> `00h BYTE drive number (00h = A:, 01h = B:, etc)`

> `01h BYTE unit number within device driver`

> `02h WORD bytes per sector (usually 512)`

> `04h BYTE highest sector number within a cluster`

> `05h BYTE shift count to convert clusters into sectors`

> `06h WORD number of reserved sectors at beginning of drive`

> `08h BYTE number of FATs (1)`

> `09h WORD number of root directory entries`

> `0Bh WORD number of first sector containing user data`

> `0Dh WORD highest cluster number (number of data clusters + 1)`

> `16-bit FAT if greater than 0FF6h, else 12-bit FAT`

> `0Fh WORD number of sectors per FAT`

> `11h WORD sector number of first directory sector`

> `13h DWORD NULL`

> `17h BYTE media ID byte (see #0581)`

> `18h BYTE 00h if disk accessed, FFh if not`

> `19h DWORD pointer to next DPB`

> `1Dh WORD cluster at which to start search for free space when writing,`

> `usually the last cluster allocated`

> `1Fh WORD number of free clusters on drive, FFFFh = unknown`

> ### EXTENDED BREAK CHECKING

> `AH = 33h`

> `AL = subfunction`

> `00h get current extended break state`

> `INT 21h`

> `Return: DL = current state, 00h = off, 01h = on`

> `01h set state of extended ^C/^Break checking`

> `DL = new state`

> `00h off, check only on character I/O functions`

> `01h on, check on all DOS functions`

> ### GET BOOT DRIVE

> `AX = 3305h`

> `INT 21h`

> `Return:`

> `DL = boot drive (1=A:,...)`

> ### GET TRUE VERSION NUMBER

> `To Call:`

> `AX = 3306h`

> `INT 21h`

> `Return:`

> `BL = major version`

> `BH = minor version`

> `DL = revision (bits 2-0, all others 0)`

> `DH = version flags`

> `bit 3: DOS is in ROM`

> `bit 4: DOS is in HMA`

> `AL = FFh if true DOS version < 5.0`

> `This will return a version number of 7.0 under Legacy, since that is the general compatibility level that is targeted. Registers DL, DH, and AL will be set to 0.`

> ### GET ADDRESS OF INDOS FLAG

> `To Call:`

> `AH = 34h`

> `INT 21h`

> `Return:`

> `ES:BX -> one-byte InDOS flag`

> `All LEGACY DOS functions are emulated, as well any necessary structures. Excepting for the bridges, all code is 32-bit and reinterrant. The INDOS flag will always be 0 under LEGACY.`

> ### GET INTERRUPT VECTOR

> `To Call:`

> `AH = 35h`

> `AL = interrupt number`

> `INT 21h`

> `Return:`

> `ES:BX -> current interrupt handler`

> ### GET FREE DISK SPACE

> `AH = 36h`

> `DL = drive number (00h = default, 01h = A:, etc)`

> `INT 21h`

> `Return: AX = FFFFh if invalid drive`

> `else`

> `AX = sectors per cluster`

> `BX = number of free clusters`

> `CX = bytes per sector`

> `DX = total clusters on drive`

> `free space on drive in bytes is AX * BX * CX`

> `total space on drive in bytes is AX * CX * DX`

> `"lost clusters" are considered to be in use`

> ### "MKDIR" - CREATE SUBDIRECTORY

> `To Call:`

> `AH = 39h`

> `DS:DX -> ASCIZ pathname`

> `INT 21h`

> `Return:`

> `CF clear if successful`

> `AX destroyed`

> `CF set on error`

> `AX = error code (03h,05h) (see #0885 at AH=59h)`

> `This creates all the specified directories in order.`

> ### "RMDIR" - REMOVE SUBDIRECTORY

> `AH = 3Ah`

> `DS:DX -> ASCIZ pathname of directory to be removed`

> `INT 21h`

> `Return:`

> `CF clear if successful`

> `AX destroyed`

> `CF set on error`

> `AX = error code (03h,05h,06h,10h) (see #0885 at AH=59h)`

> `The directory must be empty except for '.' and '..'.`

> ### "CHDIR" - SET CURRENT DIRECTORY

> `AH = 3Bh`

> `DS:DX -> ASCIZ pathname to become current directory (max 64 bytes)`

> `INT 21h`

> `Return: CF clear if successful`

> `AX destroyed`

> `CF set on error`

> `AX = error code (03h) (see #0885 at AH=59h)`

> `Notes: if new directory name includes a drive letter, the default drive is`

> `not changed, only the current directory on that drive`

> `changing the current directory also changes the directory in which`

> `FCB file calls operate`

> `under the FlashTek X-32 DOS extender, the pointer is in DS:EDX`

> ### "CREAT" - CREATE OR TRUNCATE FILE

> `AH = 3Ch`

> `CX = file attributes`

> `DS:DX -> ASCIZ filename`

> `INT 21h`

> `Return:`

> `CF clear if successful`

> `AX = file handle`

> `CF set on error`

> `AX = error code (03h,04h,05h) (see #0885 at AH=59h)`

> `if a file with the given name exists, it is truncated to zero length`

> `Bitfields for file attributes:`

> `Bit(s) Description (Table 0626)`

> `0 read-only`

> `1 hidden`

> `2 system`

> `3 volume label (ignored)`

> `4 reserved, must be zero (directory)`

> `5 archive bit`

> `7 if set, file is shareable under Novell NetWare`

> ### "OPEN" - OPEN EXISTING FILE

> `AH = 3Dh`

> `AL = access and sharing modes (see #0627)`

> `DS:DX -> ASCIZ filename`

> `CL = attribute mask of files to look for (server call only)`

> `INT 21h`

> `Return:`

> `CF clear if successful`

> `AX = file handle`

> `CF set on error`

> `AX = error code (01h,02h,03h,04h,05h,0Ch,56h) (see #0885 at AH=59h)`

> `file pointer is set to start of file file handles which are inherited from a parent also inherit sharing and access restrictions`

> `files may be opened even if given the hidden or system attributes`

> `under the FlashTek X-32 DOS extender, the pointer is in DS:EDX`

> `DR-DOS checks the system password or explicitly supplied password at`

> `the end of the filename against the reserved field in the directory`

> `entry before allowing access`

> `sharing modes are only effective on local drives if SHARE is loaded`

> `Bitfields for access and sharing modes:`

> `Bit(s) Description (Table 0627)`

> `2-0 access mode`

> `000 read only`

> `001 write only`

> `010 read/write`

> `011 (DOS 5+ internal) passed to redirector on EXEC to allow`

> `case-sensitive filenames`

> `3 reserved (0)`

> `6-4 sharing mode (DOS 3.0+) (see #0628)`

> `000 compatibility mode`

> `001 "DENYALL" prohiboth read and write access by others`

> `010 "DENYWRITE" prohiwrite access by others`

> `011 "DENYREAD" prohiread access by others`

> `100 "DENYNONE" allow full access by others`

> `111 network FCB (only available during server call)`

> `7 inheritance`

> `if set, file is private to current process and will not be inherited`

> `by child processes`

> `(Table 0628)`

> `Values of DOS file sharing behavior:`

> `| Second and subsequent Opens`

> `First |Compat Deny Deny Deny Deny`

> `Open | All Write Read None`

> `|R W RW R W RW R W RW R W RW R W RW`

> `- - - - -| - - - - - - - - - - - - - - - - -`

> `Compat R |Y Y Y N N N 1 N N N N N 1 N N`

> `W |Y Y Y N N N N N N N N N N N N`

> `RW|Y Y Y N N N N N N N N N N N N`

> `- - - - -|`

> `Deny R |C C C N N N N N N N N N N N N`

> `All W |C C C N N N N N N N N N N N N`

> `RW|C C C N N N N N N N N N N N N`

> `- - - - -|`

> `Deny R |2 C C N N N Y N N N N N Y N N`

> `Write W |C C C N N N N N N Y N N Y N N`

> `RW|C C C N N N N N N N N N Y N N`

> `- - - - -|`

> `Deny R |C C C N N N N Y N N N N N Y N`

> `Read W |C C C N N N N N N N Y N N Y N`

> `RW|C C C N N N N N N N N N N Y N`

> `- - - - -|`

> `Deny R |2 C C N N N Y Y Y N N N Y Y Y`

> `None W |C C C N N N N N N Y Y Y Y Y Y`

> `RW|C C C N N N N N N N N N Y Y Y`

> `Legend: Y = open succeeds, N = open fails with error code 05h`

> `C = open fails, INT 24 generated`

> `1 = open succeeds if file read-only, else fails with error code`

> `2 = open succeeds if file read-only, else fails with INT 24`

> ### "CLOSE" - CLOSE FILE

> `AH = 3Eh`

> `BX = file handle`

> `INT 21h`

> `Return:`

> `CF clear if successful`

> `AX destroyed`

> `CF set on error`

> `AX = error code (06h) (see #0885 at AH=59h)`

> `if the file was written to, any pending disk writes are performed, the time and date stamps are set to the current time, and the directory entry is updated`

> ### "READ" - READ FROM FILE OR DEVICE

> `AH = 3Fh`

> `BX = file handle`

> `CX = number of bytes to read`

> `DS:DX -> buffer for data`

> `INT 21h`

> `Return:`

> `CF clear if successful`

> `AX = number of bytes actually read (0 if at EOF before call)`

> `CF set on error`

> `AX = error code (05h,06h) (see #0885 at AH=59h)`

> `data is read beginning at current file position, and the file position is updated after a successful read the returned AX may be smaller than the request in CX if a partial read occurred`

> `if reading from CON, read stops at first CR`

> ### "WRITE" - WRITE TO FILE OR DEVICE

> `AH = 40h`

> `BX = file handle`

> `CX = number of bytes to write`

> `DS:DX -> data to write`

> `INT 21h`

> `Return: CF clear if successful`

> `AX = number of bytes actually written`

> `CF set on error`

> `AX = error code (05h,06h) (see #0885 at AH=59h)`

> `Notes: if CX is zero, no data is written, and the file is truncated or`

> `extended to the current position`

> `data is written beginning at the current file position, and the file`

> `position is updated after a successful write`

> `the usual cause for AX < CX on return is a full disk`

> ### "UNLINK" - DELETE FILE

> `AH = 41h`

> `DS:DX -> ASCIZ filename (no wildcards, but see notes)`

> `CL = attribute mask for deletion (server call only, see notes)`

> `INT 21h`

> `Return:`

> `cfclear if successful`

> `AX destroyed (DOS 3.3) AL seems to be drive of deleted file`

> `CF set on error`

> `AX = error code (02h,03h,05h) (see #0885 at AH=59h)`

> `wildcards are allowed if invoked via AX=5D00h, in which case`

> `the filespec must be canonical (as returned by AH=60h), and only`

> `files matching the attribute mask in CL are deleted`

> `DOS does not erase the file's data; it merely becomes inaccessible because the FAT chain for the file is cleared deleting a file which is crrently open may lead to filesystem corruption. Unless SHARE is loaded, DOS does not close the handles referencing the deleted file, thus allowing writes to a nonexistant file.`

> ### "LSEEK" - SET CURRENT FILE POSITION

> `AH = 42h`

> `AL = origin of move`

> `00h start of file`

> `01h current file position`

> `02h end of file`

> `BX = file handle`

> `CX:DX = offset from origin of new file position`

> `INT 21h`

> `Return: CF clear if successful`

> `DX:AX = new file position in bytes from start of file`

> `CF set on error`

> `AX = error code (01h,06h) (see #0885 at AH=59h)`

> `Notes: for origins 01h and 02h, the pointer may be positioned before the`

> `start of the file; no error is returned in that case, but subsequent`

> `attempts at I/O will produce errors`

> `if the new position is beyond the current end of file, the file will`

> `be extended by the next write (see AH=40h)`

> ### GET FILE ATTRIBUTES

> `To Call:`

> `AX = 4300h`

> `DS:DX -> ASCIZ filename`

> `INT 21h`

> `Return:`

> `CF clear if successful`

> `CX = file attributes (see #0643)`

> `CF set on error`

> `AX = error code (01h,02h,03h,05h)`

> ### "CHMOD" - SET FILE ATTRIBUTES

> `To Call:`

> `AX = 4301h`

> `CX = new file attributes (see #0643)`

> `DS:DX -> ASCIZ filename`

> `INT 21h`

> `Return:`

> `CF clear if successful`

> `AX destroyed`

> `CF set on error`

> `AX = error code (01h,02h,03h,05h) (see #0885 at AH=59h)`

> `SHARE will close the file if it is currently open in sharing-`

> `compatibility mode, otherwise a sharing violation critical error is`

> `generated if the file is currently open`

> `Bitfields for file attributes:`

> `Bit(s) Description (Table 0643)`

> `7 shareable (Novell NetWare)`

> `6 unused`

> `5 archive`

> `4 directory`

> `3 volume label`

> `2 system`

> `1 hidden`

> `0 read-only`

> ### DOS 7 GET VOLUME INFORMATION

> `AX = 4302h`

> `INT 21h`

> ### READ RANDOM RECORD FROM FCB FILE

> `AH = 21h`

> `DS:DX -> opened FCB (see #0574)`

> `INT 21h`

> `This function does not work and always returns AL=0FFh.`

> ### WRITE RANDOM RECORD TO FCB FILE

> `AH = 22h`

> `DS:DX -> opened FCB (see #0574)`

> `[DTA] = record to write`

> `INT 21h`

> `This function does not work and always returns AL=0FFh.`

> ### GET FILE SIZE FOR FCB

> `AH = 23h`

> `DS:DX -> unopened FCB (see #0574), wildcards not allowed`

> `This function does not work and always returns AL=0FFh.`

> ### SET RANDOM RECORD NUMBER FOR FCB

> `AH = 24h`

> `DS:DX -> opened FCB (see #0574)`

> `INT 21h`

> `This function does not work and always returns AL=0FFh.`

> ### RANDOM BLOCK READ FROM FCB FILE

> `AH = 27h`

> `CX = number of records to read`

> `DS:DX -> opened FCB (see #0574)`

> `INT 21h`

> `This function does not work and always returns AL=0FFh.`

> ### RANDOM BLOCK WRITE TO FCB FILE

> `AH = 28h`

> `CX = number of records to write`

> `DS:DX -> opened FCB (see #0574)`

> `[DTA] = records to write`

> `INT 21h`

> `This function does not work and always returns AL=0FFh.`

> ### PARSE FILENAME INTO FCB

> `AH = 29h`

> `AL = parsing options (see #0605)`

> `DS:SI -> filename string (both '*' and '?' wildcards OK)`

> `ES:DI -> buffer for unopened FCB`

> `INT 21h`

> `This function does not work and always returns AL=0FFh.`

> ### OPEN FILE USING FCB

> `AH = 0Fh`

> `DS:DX -> unopened File Control Block (see #0574)`

> `INT 21h`

> `This function does not work and always returns AL=0FFh.`

> ### CLOSE FILE USING FCB

> `To Call:`

> `AH = 10h`

> `DS:DX -> File Control Block`

> `INT 21h`

> `This function does not work and always returns AL=FFh.`

> ### FIND FIRST MATCHING FILE USING FCB

> `AH = 11h`

> `DS:DX -> unopened FCB (see #0574), may contain '?' wildcards`

> `INT 21h`

> `Return: AL = status`

> `00h successful`

> `[DTA] unopened FCB for first matching file`

> `FFh no matching filename, or bad FCB`

> `the type of the returned FCB depends on whether the input FCB was a`

> `normal or an extended FCB`

> `the data returned in the DTA is actually the drive number (or extended`

> `FCB header and drive number) followed by the file's directory entry`

> `(see #0580); this format happens to be compatible with an unopened`

> `FCB`

> `for extended FCBs with search attribute 08h, the volume label (if any)`

> `will be returned even if the current directory is not the root dir.`

> `DOS 3.0+ also allows the '*' wildcard`

> `the search FCB must not be modified if AH=12h will be used to continue`

> `searching; DOS 3.3 has set the following parts of the FCB:`

> `0Ch BYTE ???`

> `0Dh WORD directory entry number of matching file`

> `0Fh WORD cluster number of current directory`

> `11h 4 BYTEs ???`

> `15h BYTE drive number (1=A:)`

> `this function is used by many copy protection schemes to obtain the`

> `starting cluster of a file`

> `Format of DOS directory entry:`

> `Offset Size Description (Table 0580)`

> `00h 8 BYTEs blank-padded filename`

> `08h 3 BYTEs blank-padded file extension`

> `0Bh BYTE attributes`

> `0Ch 10 BYTEs reserved`

> `used by DR-DOS to store file password`

> `16h WORD time of creation or last update (see #0876 at AX=5700h)`

> `18h WORD date of creation or last update (see #0877 at AX=5700h)`

> `1Ah WORD starting cluster number`

> `1Ch DWORD file size`

> ### FIND NEXT MATCHING FILE USING FCB

> `AH = 12h`

> `DS:DX -> unopened FCB (see #0574)`

> `INT 21h`

> `Return: AL = status`

> `00h successful`

> `[DTA] = unopened FCB`

> `FFh no more matching filenames`

> `Note: (see AH=11h)`

> `assumes that successful FindFirst executed on search FCB before call`

> ### DELETE FILE USING FCB

> `AH = 13h`

> `DS:DX -> unopened FCB`

> `INT 21h`

> `This function does not work and always returns AL=0FFh.`

> ### SEQUENTIAL READ FROM FCB FILE

> `AH = 14h`

> `DS:DX -> opened FCB`

> `INT 21h`

> `This function does not work and always returns AL=0FFh.`

> ### SEQUENTIAL WRITE TO FCB FILE

> `AH = 15h`

> `DS:DX -> opened FCB (see #0574)`

> `[DTA] = record to write`

> `INT 21h`

> `This function does not work and always returns AL=0FFh.`

> ### CREATE OR TRUNCATE FILE USING FCB

> `AH = 16h`

> `DS:DX -> unopened FCB (see #0574), wildcards not allowed`

> `INT 21h`

> `This function does not work and always returns AL=0FFh.`

> ### RENAME FILE USING FCB

> `AH = 17h`

> `DS:DX -> modified FCB (see also #0574)`

> `the old filename ('?' wildcards OK) is in the standard location`

> `while the new filename ('?' wildcards OK, no drive) is stored`

> `in the 11 bytes beginning at offset 11h`

> `INT 21h`

> `Return:`

> `AL = status`

> `00h successfully renamed`

> `FFh no matching files,file is read-only, or new name already exists`

> `Under Legacy the only approved purpose of this function is to rename volume Labels.`

> TOC

> # Other Misc BIOS/DOS Services

> ### BY | Lewis Sellers lsellers@usit.net

> INT 1F - SYSTEM DATA - 8x8 GRAPHICS FONT

> this vector points at 1024 bytes of graphics data, 8 bytes for each character 80h-FFh

> ### GET EXTENDED COUNTRY INFORMATION

> `AH = 65h`

> `AL = info ID`

> `01h get general internationalization info`

> `02h get pointer to uppercase table`

> `04h get pointer to filename uppercase table`

> `05h get pointer to filename terminator table`

> `06h get pointer to collating sequence table`

> `07h (DOS 4.0+) get pointer to Double-Byte Character Set table`

> `BX = code page (FFFFh=global code page)`

> `DX = country ID (FFFFh=current country)`

> `ES:DI -> country information buffer (see #0956)`

> `CX = size of buffer (>= 5)`

> `INT 21h`

> `Return:`

> `CF set on error`

> `AX = error code (see #0885 at AH=59h)`

> `CF clear if successful`

> `CX = size of country information returned`

> `ES:DI -> country information`

> `AL=05h appears to return same info for all countries and codepages; it has been documented for DOS 5+, but was undocumented in ealier versions NLSFUNC must be installed to get info for countries other than the default subfunctions 02h and 04h are identical under OS/2`

> `Format of country information:`

> `Offset Size Description (Table 0956)`

> `00h BYTE info ID`

> `---if info ID = 01h---`

> `01h WORD size`

> `03h WORD country ID`

> `05h WORD code page`

> `07h 34 BYTEs country-dependent info (see AH=38h)`

> `---if info ID = 02h---`

> `01h DWORD pointer to uppercase table (see #0957)`

> `---if info ID = 04h---`

> `01h DWORD pointer to filename uppercase table (see #0958)`

> `---if info ID = 05h---`

> `01h DWORD pointer to filename character table (see #0959)`

> `---if info ID = 06h---`

> `01h DWORD pointer to collating table (see #0960)`

> `---if info ID = 07h (DOS 4.0+)---`

> `01h DWORD pointer to DBCS lead byte table (see #0961)`

> `Format of uppercase table:`

> `Offset Size Description (Table 0957)`

> `00h WORD table size`

> `02h 128 BYTEs uppercase equivalents (if any) of chars 80h to FFh`

> `Format of filename uppercase table:`

> `Offset Size Description (Table 0958)`

> `00h WORD table size`

> `02h 128 BYTEs uppercase equivalents (if any) of chars 80h to FFh`

> `Format of filename terminator table:`

> `Offset Size Description (Table 0959)`

> `00h WORD table size (not counting this word)`

> `02h BYTE ??? (01h for MS-DOS 3.30-6.00)`

> `03h BYTE lowest permissible character value for filename`

> `04h BYTE highest permissible character value for filename`

> `05h BYTE ??? (00h for MS-DOS 3.30-6.00)`

> `06h BYTE first excluded character in range \ all characters in this`

> `07h BYTE last excluded character in range / range are illegal`

> `08h BYTE ??? (02h for MS-DOS 3.30-6.00)`

> `09h BYTE number of illegal (terminator) characters`

> `0Ah N BYTEs characters which terminate a filename: ."/\[]:|<>+=;,`

> `Note: partially documented for DOS 5+, but undocumented for earlier versions`

> `Format of collating table:`

> `Offset Size Description (Table 0960)`

> `00h WORD table size`

> `02h 256 BYTEs values used to sort characters 00h to FFh`

> `Format of DBCS lead byte table:`

> `Offset Size Description (Table 0961)`

> `00h WORD length`

> `02h 2N BYTEs start/end for N lead byte ranges`

> `WORD 0000h (end of table)`

> `COUNTRY-DEPENDENT CHARACTER CAPITALIZATION`

> `AH = 65h`

> `AL = function`

> `20h capitalize character`

> `DL = character to capitalize`

> `Return: DL = capitalized character`

> `21h capitalize string`

> `DS:DX -> string to capitalize`

> `CX = length of string`

> `22h capitalize ASCIZ string`

> `DS:DX -> ASCIZ string to capitalize`

> `INT 21h`

> `Return:`

> `CF set on error`

> `AX = error code (see #0885 at AH=59h)`

> `CF clear if successful`

> `GET GLOBAL CODE PAGE TABLE`

> `AX = 6601h`

> `INT 21h`

> `Return:`

> `CF set on error`

> `AX = error code (see #0885 at AH=59h)`

> `CF clear if successful`

> `BX = active code page (see #0962)`

> `DX = system code page (see #0962)`

> `SET GLOBAL CODE PAGE TABLE`

> `AX = 6602h`

> `BX = active code page (see #0962)`

> `DX = system code page (active page at boot time)`

> `INT 21h`

> `Return: CF set on error`

> `AX = error code (see #0885 at AH=59h)`

> `CF clear if successful`

> `AX = EB41h (Novell NWDOS v7.0 when NLSFUNC not installed and`

> `request was for previously-active code page)`

> `(Table 0962)`

> `Values for code page:`

> `437 US`

> `850 Multilingual`

> `852 Slavic/Latin II (DOS 5+)`

> `857 Turkish`

> `860 Portugal`

> `861 Iceland`

> `863 Canada (French)`

> `865 Norway/Denmark`

> CREATE NEW PROGRAM SEGMENT PREFIX

> To Call:

> AH = 26h

> DX = segment at which to create PSP

> INT 21h

> new PSP is updated with memory size information; INTs 22h, 23h, 24h taken from interrupt vector table; the parent PSP field is set to 0 DOS assumes that the caller's CS is the segment of the PSP to copy

> Format of Program Segment Prefix (PSP):

> Offset Size Description (Table 0498)

> 00h 2 BYTEs INT 20 instruction for CP/M CALL 0 program termination

> the CDh 20h here is often used as a signature for a valid PSP

> ...

> 2Ch WORD DOS 2+ segment of environment for process (see #0499)

> ...

> Format of environment block:

> Offset Size Description (Table 0499)

> 00h N BYTEs first environment variable, ASCIZ string of form "var=value"

> N BYTEs second environment variable, ASCIZ string

> ...

> N BYTEs last environment variable, ASCIZ string of form "var=value"

> BYTE 00h

> ---DOS 3+---

> WORD number of strings following environment (normally 1)

> N BYTEs ASCIZ full pathname of program owning this environment other strings may follow

> GET COUNTRY-SPECIFIC INFORMATION

> AH = 38h

> AL = 00h get current-country info

> DS:DX -> buffer for returned info (see #0517,#0518)

> INT 21h

> Format of DOS 2.11+ country info:

> Offset Size Description (Table 0518)

> 00h WORD date format (see #0517)

> 02h 5 BYTEs ASCIZ currency symbol string

> 07h 2 BYTEs ASCIZ thousands separator

> ...

> (Table 0519)

> Values for country code:

> 001h United States

> 002h Canadian-French

> 003h Latin America

> 01Fh Netherlands

> SET COUNTRY CODE

> AH = 38h

> DX = FFFFh

> AL = 01h thru FEh for specific country with code <255

> AL = FFh for specific country with code >= 255

> BX = 16-bit country code (see #0519)

> INT 21h

> Return: CF set on error

> AX = error code (see #0770 at AH=59h)

> CF clear if successful

> "EXEC" - LOAD AND/OR EXECUTE PROGRAM

> To Call:

> AH = 4Bh

> ES:BX -> parameter block (see #0687)

> INT 21h

> Format of EXEC parameter block for AL=00h,01h,04h:

> Offset Size Description

> 00h WORD segment of environment to copy for child process (copy caller's environment if 0000h)

> Format of EXEC parameter block for AL=03h:

> Offset Size Description

> 00h WORD segment at which to load overlay

> 02h WORD relocation factor to apply to overlay if in .EXE format

> Format of EXEC parameter block for FlashTek X-32:

> Offset Size Description (Table 0689)

> 00h PWORD 48-bit far pointer to environment string

> 06h PWORD 48-bit far pointer to command tail string

> (Table 0690)

> Values for the executable types understood by various environments:

> MZ old-style DOS executable

> ...

> Format of .EXE file header:

> Offset Size Description (Table 0691)

> 00h 2 BYTEs .EXE signature, either "MZ" or "ZM" (5A4Dh or 4D5Ah)

> 02h WORD number of bytes in last 512-byte page of executable

> ...

> Format of ROM Module Header:

> Offset Size Description (Table 0692)

> 00h 2 BYTEs ROM signature 55h, AAh

> 02h BYTE size of ROM in 512-byte blocks

> ...

> Format of new executable header:

> Offset Size Description (Table 0693)

> 00h 2 BYTEs "NE" (4Eh 45h) signature

> 02h 2 BYTEs linker version (major, then minor)

> ...

> 0Ch BYTE program flags (see #0694)

> 0Dh BYTE application flags (see #0695)

> ...

> Bitfields for new executable program flags:

> Bit(s) Description (Table 0694)

> 0-1 DGROUP type

> 0 = none

> 1 = single shared

> 2 = multiple (unshared)

> 3 = (null)

> ...

> Bitfields for new executable application flags:

> Bit(s) Description (Table 0695)

> 0-2 application type

> 001 full screen (not aware of Windows/P.M. API)

> 010 compatible with Windows/P.M. API

> 011 uses Windows/P.M. API

> ...

> Bitfields for other new .EXE flags:

> Bit(s) Description (Table 0696)

> 0 supports long filenames

> 1 2.X protected mode

> 2 2.X proportional font

> 3 gangload area

> Format of Codeview trailer (at end of executable):

> Offset Size Description (Table 0697)

> 00h WORD signature 4E42h ('NB')

> 02h WORD Microsoft debug info version number

> 04h DWORD Codeview header offset

> Format of new executable segment table record:

> Offset Size Description (Table 0698)

> 00h WORD offset in file (shift left by alignment shift to get byte offs)

> 02h WORD length of image in file (0000h = 64K)

> 04h WORD segment attributes (see #0699)

> 06h WORD number of bytes to allocate for segment (0000h = 64K)

> Note: the first segment table entry is entry number 1

> Bitfields for segment attributes:

> Bit(s) Description (Table 0699)

> 0 data segment rather than code segment

> ...

> Format of new executable entry table item (list):

> Offset Size Description (Table 0700)

> 00h BYTE number of entry points (00h if end of entry table list)

> ...

> Format of new executable relocation data (immediately follows segment image):

> Offset Size Description (Table 0701)

> 00h WORD number of relocation items

> ...

> Format of new executable resource data:

> Offset Size Description (Table 0702)

> 00h WORD alignment shift count for resource data

> ...

> 08h N Resources (see #0703)

> Note: resource type and name strings are stored immediately following the

> resource table, and are not null-terminated

> Format of new executable resource entry:

> Offset Size Description (Table 0703)

> 00h WORD offset in alignment units from start of file to contents of

> the resource data

> ...

> Format of new executable module reference table [one bundle of entries]:

> Offset Size Description (Table 0704)

> 00h BYTE number of records in this bundle (00h if end of table)

> ...

> Format of new executable resident/nonresident name table entry:

> Offset Size Description (Table 0705)

> 00h BYTE length of string (00h if end of table)

> ...

> Format of Linear Executable (enhanced mode executable) header:

> Offset Size Description (Table 0706)

> 00h 2 BYTEs "LE" (4Ch 45h) signature (Windows)

> "LX" (4Ch 58h) signature (OS/2)

> ...

> 10h DWORD module type (see #0707)

> ...

> 40h DWORD offset of object table (see #0708)

> ...

> Bitfields for Linear Executable module type:

> Bit(s) Description (Table 0707)

> 2 initialization (only for DLLs) 0 = global, 1 = per-process

> 4 no internal fixups in executable image

> ...

> Format of object table entry:

> Offset Size Description (Table 0708)

> 00h DWORD virtual size in bytes

> 04h DWORD relocation base address

> 08h DWORD object flags (see #0709)

> 0Ch DWORD page map index

> 10h DWORD page map entries

> 14h 4 BYTEs reserved??? (apparently always zeros)

> Bitfields for object flags:

> Bit(s) Description (Table 0709)

> 0 readable

> 1 writable

> ...

> Format of object page map table entry:

> Offset Size Description (Table 0710)

> 00h BYTE ??? (usually 00h)

> 01h WORD (big-endian) index to fixup table

> 0000h if no relocation info

> 03h BYTE type (00h hard copy in file, 03h some relocation needed)

> Format of resident names table entry:

> Offset Size Description (Table 0711)

> 00h BYTE length of name

> 01h N BYTEs name

> N+1 3 BYTEs ???

> Format of LE linear executable entry table:

> Offset Size Description (Table 0712)

> 00h BYTE number of entries in table

> 01h 10 BYTEs per entry

> ...

> Format of LX linear executable entry table [array]:

> Offset Size Description (Table 0713)

> 00h BYTE number of bundles following (00h = end of entry table)

> 01h BYTE bundle type

> ...

> Bitfields for linear executable fixup type:

> Bit(s) Description (Table 0714)

> 7 ordinal is BYTE rather than WORD

> 6 16-rather than 8-object number/module ordinal

> ...

> Format of linear executable fixup record:

> Offset Size Description (Table 0715)

> 00h BYTE type

> bits 7-4: modifier (0001 single, 0011 multiple)

> ...

> 01h BYTE linear executable fixup type (see #0714)

> ...

> Format of old Phar Lap .EXP file header:

> Offset Size Description (Table 0716)

> 00h 2 BYTEs "MP" (4Dh 50h) signature

> 02h WORD remainder of image size / page size (page size = 512h)

> ...

> Format of new Phar Lap .EXP file header:

> Offset Size Description (Table 0717)

> 00h 2 BYTEs signature ("P2" for 286 .EXP executable, "P3" for 386 .EXP)

> 02h WORD level (01h flat-model file, 02h multisegmented file)

> ...

> Format of Phar Lap segment information table entry:

> Offset Size Description (Table 0718)

> 00h WORD selector number

> ...

> Format of 386|DOS-Extender run-time parameters:

> Offset Size Description (Table 0719)

> 00h 2 BYTEs signature "DX" (44h 58h)

> ...

> Format of Phar Lap repeat block header:

> Offset Size Description (Table 0720)

> 00h WORD byte count

> 02h BYTE repeat string length

> Format of Borland debugging information header (following load image):

> Offset Size Description (Table 0721)

> 00h WORD signature 52FBh

> 02h WORD version ID

> GET EXTENDED ERROR INFORMATION

> To Call:

> AH = 59h

> BX = 0000h

> INT 21h

> Return:

> AX = extended error code (see #0770)

> BH = error class (see #0772)

> BL = recommended action (see #0773)

> CH = error locus (see #0774)

> ES:DI may be pointer (see #0771, error code list below)

> CL, DX, SI, BP, and DS destroyed

> (Table 0770)

> Values for DOS extended error code:

> 00h (0) no error

> 01h (1) function number invalid

> 02h (2) file not found

> ...

> Format of media ID structure:

> Offset Size Description (Table 0771)

> 00h 12 BYTEs ASCIZ volume label of required disk

> 0Ch DWORD serial number (DOS 4+)

> (Table 0772)

> Values for DOS Error Class:

> 01h out of resource (storage space or I/O channels)

> 02h temporary situation (file or record lock)

> ...

> (Table 0773)

> Values for DOS Suggested Action:

> 01h retry

> ...

> (Table 0774)

> Values for DOS Error Locus:

> 01h unknown or not appropriate

> European GET HARD ERROR INFORMATION

> To Call:

> AH = 59h

> BX = 0001h

> INT 21h

> Return:

> ES:DI -> hard error information packet (see #0775) for most recent hard (critical) error

> Format of European MS-DOS 4.0 hard error information packet:

> Offset Size Description (Table 0775)

> 00h WORD contents of AX at system entry

> GET EXTENDED COUNTRY INFORMATION

> AH = 65h

> ES:DI -> country information buffer (see #0840)

> CX = size of buffer (>= 5)

> INT 21h

> Return:

> CF set on error

> AX = error code (see #0770 at AH=59h)

> Format of country information:

> Offset Size Description (Table 0840)

> 00h BYTE info ID

> ...

> 01h DWORD pointer to uppercase table (see #0841)

> ---if info ID = 04h---

> 01h DWORD pointer to filename uppercase table (see #0842)

> ---if info ID = 05h---

> 01h DWORD pointer to filename character table (see #0843)

> ---if info ID = 06h---

> 01h DWORD pointer to collating table (see #0844)

> ---if info ID = 07h (DOS 4+)---

> 01h DWORD pointer to DBCS lead byte table (see #0845)

> Format of uppercase table:

> Offset Size Description (Table 0841)

> 00h WORD table size

> 02h 128 BYTEs uppercase equivalents (if any) of chars 80h to FFh

> Format of filename uppercase table:

> Offset Size Description (Table 0842)

> 00h WORD table size

> 02h 128 BYTEs uppercase equivalents (if any) of chars 80h to FFh

> Format of filename terminator table:

> Offset Size Description (Table 0843)

> 00h WORD table size (not counting this word)

> ...

> Format of collating table:

> Offset Size Description (Table 0844)

> 00h WORD table size

> 02h 256 BYTEs values used to sort characters 00h to FFh

> Format of DBCS lead byte table:

> Offset Size Description (Table 0845)

> 00h WORD length

> 02h 2N BYTEs start/end for N lead byte ranges

> WORD 0000h (end of table)

> COUNTRY-DEPENDENT CHARACTER CAPITALIZATION

> To Call:

> AH = 65h

> INT 21h

> Return:

> GET GLOBAL CODE PAGE TABLE

> To Call:

> AX = 6601h

> INT 21h

> Return:

> CF set on error

> AX = error code (see #0770 at AH=59h)

> CF clear if successful

> BX = active code page (see #0846)

> DX = system code page (see #0846)

> SET GLOBAL CODE PAGE TABLE

> To Call:

> AX = 6602h

> BX = active code page (see #0846)

> DX = system code page (active page at boot time)

> INT 21h

> Return:

> CF set on error

> AX = error code (see #0770 at AH=59h)

> CF clear if successful

> (Table 0846)

> Values for code page:

> 437 US

> 850 Multilingual

> ### GET CURRENT PSP ADDRESS

> `To Call:`

> `AH = 62h`

> `INT 21h`

> `Return:`

> `BX = segment of PSP for current process`

> ### "SWITCHAR" - GET SWITCH CHARACTER

> To Call:

> `AX = 3700h`

> `INT 21h`

> `Return:`

> `AL = status`

> `00h successful`

> `DL = current switch character`

> `FFh unsupported subfunction`

> `Returns the character which is used to introduce command switches. By default this is "/", but is sometimes changed to "-".`

> ### "SWITCHAR" - SET SWITCH CHARACTER

> To Call:

> `AX = 3701h`

> `DL = new switch character`

> `INT 21h`

> `Return:`

> `AL = status`

> `00h successful`

> `FFh unsupported subfunction`

> ### GET COUNTRY-SPECIFIC INFORMATION

> To Call:

> `AH = 38h`

> `AL = 00h for current country`

> `AL = 01h thru 0FEh for specific country with code <255 (see #0625)`

> `AL = 0FFh for specific country with code >= 255`

> `BX = 16-bit country code (see #0625)`

> `DS:DX -> buffer for returned info (see #0624)`

> `INT 21h`

> `Return:`

> `CF set on error`

> `AX = error code (02h)`

> `CF clear if successful`

> `AX = country code (Novell NWDOS v7.0)`

> `BX = country code`

> `DS:DX buffer filled`

> `this function is not supported by the Borland DPMI host, but no error`

> `is returned; as a workaround, one should allocate a buffer in`

> `conventional memory with INT 31/AX=0100h and simulate an INT 21 with`

> `INT 31/AX=0300h`

> `Format of DOS 2.00-2.10 country info:`

> `Offset Size Description (Table 0623)`

> `00h WORD date format 0 = USA mm dd yy`

> `1 = Europe dd mm yy`

> `2 = Japan yy mm dd`

> `02h BYTE currency symbol`

> `03h BYTE 00h`

> `04h BYTE thousands separator char`

> `05h BYTE 00h`

> `06h BYTE decimal separator char`

> `07h BYTE 00h`

> `08h 24 BYTEs reserved`

> `Format of DOS 2.11+ country info:`

> `Offset Size Description (Table 0624)`

> `00h WORD date format (see #0623)`

> `02h 5 BYTEs ASCIZ currency symbol string`

> `07h 2 BYTEs ASCIZ thousands separator`

> `09h 2 BYTEs ASCIZ decimal separator`

> `0Bh 2 BYTEs ASCIZ date separator`

> `0Dh 2 BYTEs ASCIZ time separator`

> `0Fh BYTE currency format`

> `bit 2 = set if currency symbol replaces decimal point`

> `bit 1 = number of spaces between value and currency symbol`

> `bit 0 = 0 if currency symbol precedes value`

> `1 if currency symbol follows value`

> `10h BYTE number of digits after decimal in currency`

> `11h BYTE time format`

> `bit 0 = 0 if 12-hour clock`

> `1 if 24-hour clock`

> `12h DWORD address of case map routine`

> `(FAR CALL, AL = character to map to upper case [>= 80h])`

> `16h 2 BYTEs ASCIZ data-list separator`

> `18h 10 BYTEs reserved`

> `(Table 0625)`

> `Values for country code:`

> `001h United States`

> `002h Canadian-French`

> `003h Latin America`

> `01Fh Netherlands`

> `020h Belgium`

> `021h France`

> `022h Spain`

> `024h Hungary (not supported by DR-DOS 5.0)`

> `026h Yugoslavia (not supported by DR-DOS 5.0)`

> `027h Italy`

> `029h Switzerland`

> `02Ah Czechoslovakia/Tjekia (not supported by DR-DOS 5.0)`

> `02Bh Austria (DR-DOS 5.0)`

> `02Ch United Kingdom`

> `02Dh Denmark`

> `02Eh Sweden`

> `02Fh Norway`

> `030h Poland (not supported by DR-DOS 5.0)`

> `031h Germany`

> `037h Brazil (not supported by DR-DOS 5.0)`

> `03Dh International English [Australia in DR-DOS 5.0]`

> `051h Japan (DR-DOS 5.0, MS-DOS 5.0+)`

> `052h Korea (DR-DOS 5.0)`

> `056h China (MS-DOS 5.0+)`

> `058h Taiwan (MS-DOS 5.0+)`

> `05Ah Turkey (MS-DOS 5.0+)`

> `15Fh Portugal`

> `162h Iceland`

> `166h Finland`

> `311h Middle East/Saudi Arabia (DR-DOS 5.0,MS-DOS 5.0+)`

> `3CCh Israel (DR-DOS 5.0,MS-DOS 5.0+)`

> `INT 21 - DOS 3.0+ - SET COUNTRY CODE`

> `AH = 38h`

> `DX = FFFFh`

> `AL = 01h thru FEh for specific country with code <255`

> `AL = FFh for specific country with code >= 255`

> `BX = 16-bit country code (see #0625)`

> `Return: CF set on error`

> `AX = error code (see #0885 at AH=59h)`

> `CF clear if successful`

> ### SET INTERRUPT VECTOR

> To Call:

> `AH = 25h`

> `AL = interrupt number`

> `DS:DX -> new interrupt handler`

> `INT 21h`

> `this function is preferred over direct modification of the interrupt vector table`

> `some DOS extenders place an API on this function, as it is not`

> `directly meaningful in protected mode`

> ### GET SYSTEM DATE

> `To Call:`

> `AH = 2Ah`

> `INT 21h`

> `Return:`

> `CX = year (1980-2099)`

> `DH = month`

> `DL = day`

> `AL = day of week (00h=Sunday)`

> `INT 21 - DOS 1+ - SET SYSTEM DATE`

> `AH = 2Bh`

> `CX = year (1980-2099)`

> `DH = month`

> `DL = day`

> `Return: AL = status`

> `00h successful`

> `FFh invalid date, system date unchanged`

> `Note: DOS 3.3+ also sets CMOS clock`

> `INT 21 - DOS 1+ - SET SYSTEM TIME`

> `AH = 2Dh`

> `CH = hour`

> `CL = minute`

> `DH = second`

> `DL = 1/100 seconds`

> `Return: AL = result`

> `00h successful`

> `FFh invalid time, system time unchanged`

> `Note: DOS 3.3+ also sets CMOS clock`

> ### GET SYSTEM TIME

> `To Call:`

> `AH = 00h`

> `INT 1Ah`

> `Return:`

> `CX:DX = number of clock ticks since midnight`

> `AL = midnight flag, nonzero if midnight passed since time last read`

> `There are approximately 18.2 clock ticks per second, 1800B0h per 24 hrs IBM and many clone BIOSes set the flag for AL rather than incrementing`

> `it, leading to loss of a day if two consecutive midnights pass`

> `without a request for the time (e.g. if the system is on but idle)`

> `since the midnight flag is cleared, if an application calls this`

> `function after midnight before DOS does, DOS will not receive the`

> `midnight flag and will fail to advance the date`

> ### SET SYSTEM TIME

> To Call:

> `AH = 01h`

> `CX:DX = number of clock ticks since midnight`

> `INT 1Ah`

> ### GET REAL-TIME CLOCK TIME

> To Call:

> `AH = 02h`

> `INT 1Ah`

> `Return: CF clear if successful`

> `CH = hour (BCD)`

> `CL = minutes (BCD)`

> `DH = seconds (BCD)`

> `DL = daylight savings flag (00h standard time, 01h daylight time)`

> `CF set on error (i.e. clock not running or in middle of update)`

> ### SET REAL-TIME CLOCK TIME

> To Call:

> `AH = 03h`

> `CH = hour (BCD)`

> `CL = minutes (BCD)`

> `DH = seconds (BCD)`

> `DL = daylight savings flag (00h standard time, 01h daylight time)`

> `INT 1Ah`

> ### GET REAL-TIME CLOCK DATE

> To Call:

> `AH = 04h`

> `INT 1Ah`

> `Return:`

> `CF clear if successful`

> `CH = century (BCD)`

> `CL = year (BCD)`

> `DH = month (BCD)`

> `DL = day (BCD)`

> `CF set on error`

> ### SET REAL-TIME CLOCK DATE

> To Call:

> `AH = 05h`

> `CH = century (BCD)`

> `CL = year (BCD)`

> `DH = month (BCD)`

> `DL = day (BCD)`

> `INT 1Ah`

> ### SET ALARM

> To Call:

> `AH = 06h`

> `CH = hour (BCD)`

> `CL = minutes (BCD)`

> `DH = seconds (BCD)`

> `INT 1Ah`

> `Return:`

> `CF set on error (alarm already set or clock stopped for update)`

> `CF clear if successful`

> `the alarm occurs every 24 hours until turned off, invoking INT 4A each time the BIOS does not check for invalid values for the time, so the CMOS clock chip's "don't care" setting (any values between C0h and FFh)`

> `may be used for any or all three part. For example, to create an`

> `alarm once a minute, every minute, call with CH=C0h, CL=C0h, and`

> `DH=00h.`

> ### CANCEL ALARM

> To Call:

> `AH = 07h`

> `INT 1Ah`

> `Return:`

> `alarm disabled`

> `does not disable the real-time clock's IRQ`

> ### SET RTC ACTIVATED POWER ON MODE

> To Call:

> `AH = 08h`

> `CH = hours in BCD`

> `CL = minutes in BCD`

> `DH = seconds in BCD`

> `INT 1Ah`

> ### READ RTC ALARM TIME AND STATUS

> To Call:

> `AH = 09h`

> `INT 1Ah`

> `Return:`

> `CH = hours in BCD`

> `CL = minutes in BCD`

> `DH = seconds in BCD`

> `DL = alarm status`

> `00h alarm not enabled`

> `01h alarm enabled but will not power up system`

> `02h alarm will power up system`

> ### READ SYSTEM-TIMER DAY COUNTER

> To Call:

> `AH = 0Ah`

> `INT 1Ah`

> `Return: CF set on error`

> `CF clear if successful`

> `CX = count of days since Jan 1,1980`

> ### SET SYSTEM-TIMER DAY COUNTER

> To Call:

> `AH = 0Bh`

> `CX = count of days since Jan 1,1980`

> `INT 1Ah`

> `Return: CF set on error`

> `CF clear if successful`

> ### INT 1B C - KEYBOARD - CONTROL-BREAK HANDLER

> `this interrupt is automatically called when INT 09 determines that`

> `Control-Break has been pressed`

> `Note: normally points to a short routine in DOS which sets the Ctrl-C flag,`

> `thus invoking INT 23h the next time DOS checks for Ctrl-C.`

> ### INT 1C - TIME - SYSTEM TIMER TICK

> `this interrupt is automatically called on each clock tick by the INT 08 handler`

> ### INT 1D - SYSTEM DATA - VIDEO PARAMETER TABLES

> `Note: the default parameter table (see #0571) is located at F000h:F0A4h for`

> `100% compatible BIOSes`

> `Format of video parameters:`

> `Offset Size Description (Table 0571)`

> `00h 16 BYTEs 6845 register values for modes 00h and 01h`

> `10h 16 BYTEs 6845 register values for modes 02h and 03h`

> `20h 16 BYTEs 6845 register values for modes 04h and 05h`

> `30h 16 BYTEs 6845 register values for modes 06h and 07h`

> `40h WORD bytes in video buffer for modes 00h and 01h (0800h)`

> `42h WORD bytes in video buffer for modes 02h and 03h (1000h)`

> `44h WORD bytes in video buffer for modes 04h and 05h (4000h)`

> `46h WORD bytes in video buffer for mode 06h (4000h)`

> `48h 8 BYTEs columns on screen for each of modes 00h through 07h`

> `50h 8 BYTEs CRT controller mode bytes for each of modes 00h through 07h`

> ### INT 1Eh SYSTEM DATA - DISKETTE PARAMETERS

> `When LEGACY is initialized, a diskette parameter table which is pointed to by the vector at INT 1Eh is filled with values. These values are never again updated, unless the diskette is changed. LEGACY never makes use of them.`

> `Format of diskette parameter table:`

> `Offset Size Description`

> `00h BYTE first specify byte`

> `bits 7-4: step rate`

> `bits 3-0: head unload time (0Fh = 240 ms)`

> `01h BYTE second specify byte`

> `bits 7-1: head load time (01h = 4 ms)`

> `bit 0: non-DMA mode (always 0)`

> `02h BYTE delay until motor turned off (in clock ticks)`

> `03h BYTE bytes per sector (00h = 128, 01h = 256, 02h = 512, 03h = 1024)`

> `04h BYTE sectors per track`

> `05h BYTE length of gap between sectors (2Ah for 5.25", 1Bh for 3.5")`

> `06h BYTE data length (ignored if bytes-per-sector field nonzero)`

> `07h BYTE gap length when formatting (50h for 5.25", 6Ch for 3.5")`

> `08h BYTE format filler byte (default F6h)`

> `09h BYTE head settle time in milliseconds`

> `0Ah BYTE motor start time in 1/8 seconds`

> ### INT 1F - SYSTEM DATA - 8x8 GRAPHICS FONT

> `This vector points to 1024 bytes of graphics data, 8 bytes for each character 80h-FFh.`

> ### TERMINATE PROGRAM

> > To Call:

> > AH = 00h

> > CS = PSP segment

> > INT 21h

> TERMINATE PROGRAM

> To Call:

> CS = PSP segment

> INT 20h

> Multiplex - NOTES

> To Call:

> AH = identifier of program which is to handle the interrupt

> INT 2Fh

> ### CREATE NEW PROGRAM SEGMENT PREFIX

> To Call:

> `AH = 26h`

> `DX = segment at which to create PSP (see #0603)`

> `INT 21h`

> `new PSP is updated with memory size information; INTs 22h, 23h, 24h`

> `taken from interrupt vector table; the parent PSP field is set to 0`

> `(DOS 2+) DOS assumes that the caller's CS is the segment of the PSP to`

> `copy`

> `Format of Program Segment Prefix (PSP):`

> `Offset Size Description (Table 0603)`

> `00h 2 BYTEs INT 20 instruction for CP/M CALL 0 program termination`

> `the CDh 20h here is often used as a signature for a valid PSP`

> `02h WORD segment of first byte beyond memory allocated to program`

> `04h BYTE (DOS) unused filler`

> `(OS/2) count of fake DOS version returns`

> `05h BYTE CP/M CALL 5 service request (FAR CALL to absolute 000C0h)`

> `BUG: (DOS 2+ DEBUG) PSPs created by DEBUG point at 000BEh`

> `06h WORD CP/M compatibility--size of first segment for .COM files`

> `08h 2 BYTEs remainder of FAR JMP at 05h`

> `0Ah DWORD stored INT 22 termination address`

> `0Eh DWORD stored INT 23 control-Break handler address`

> `12h DWORD DOS 1.1+ stored INT 24 critical error handler address`

> `16h WORD segment of parent PSP`

> `18h 20 BYTEs DOS 2+ Job File Table, one byte per file handle, FFh = closed`

> `2Ch WORD DOS 2+ segment of environment for process (see #0604)`

> `2Eh DWORD DOS 2+ process's SS:SP on entry to last INT 21 call`

> `32h WORD DOS 3+ number of entries in JFT (default 20)`

> `34h DWORD DOS 3+ pointer to JFT (default PSP:0018h)`

> `38h DWORD DOS 3+ pointer to previous PSP (default FFFFFFFFh in 3.x)`

> `used by SHARE in DOS 3.3`

> `3Ch BYTE DOS 4+ (DBCS) interim console flag (see AX=6301h)`

> `3Dh BYTE (APPEND) TrueName flag (see INT 2F/AX=B711h)`

> `3Eh BYTE (Novell NetWare) flag: next byte initialized if CEh`

> `(OS/2) capabilities flag`

> `3Fh BYTE (Novell NetWare) Novell task number if previous byte is CEh`

> `40h 2 BYTEs DOS 5+ version to return on INT 21/AH=30h`

> `42h WORD (MSWindows3) selector of next PSP (PDB) in linked list`

> `Windows keeps a linked list of Windows programs only`

> `44h WORD (MSWindows3) "PDB_Partition"`

> `46h WORD (MSWindows3) "PDB_NextPDB"`

> `48h BYTE (MSWindows3) bit 0 set if non-Windows application (WINOLDAP)`

> `49h BYTE unused by DOS versions <= 6.00`

> `4Ch WORD (MSWindows3) "PDB_EntryStack"`

> `4Eh 2 BYTEs unused by DOS versions <= 6.00`

> `50h 3 BYTEs DOS 2+ service request (INT 21/RETF instructions)`

> `53h 2 BYTEs unused in DOS versions <= 6.00`

> `55h 7 BYTEs unused in DOS versions <= 6.00; can be used to make first FCB`

> `into an extended FCB`

> `5Ch 16 BYTEs first default FCB, filled in from first commandline argument`

> `overwrites second FCB if opened`

> `6Ch 16 BYTEs second default FCB, filled in from second commandline argument`

> `overwrites beginning of commandline if opened`

> `7Ch 4 BYTEs unused`

> `80h 128 BYTEs commandline / default DTA`

> `command tail is BYTE for length of tail, N BYTEs for the tail,`

> `followed by a BYTE containing 0Dh`

> `in DOS v3+, the limit on simultaneously open files may be increased by`

> `allocating memory for a new open file table, filling it with FFh,`

> `copying the first 20 bytes from the default table, and adjusting the`

> `pointer and count at 34h and 32h. However, DOS will only copy the`

> `first 20 file handles into a child PSP (including the one created on`

> `EXEC).`

> `network redirectors based on the original MS-Net implementation use`

> `values of 80h-FEh in the open file table to indicate remote files;`

> `Novell NetWare also uses values from FEh down to 80h or one more than`

> `FILES= (whichever is greater) to indicate remote files`

> `some DOS extenders place protected-mode values in various PSP fields`

> `such as the "parent" field, which can confuse PSP walkers. Always`

> `check either for the CDh 20h signature or that the suspected PSP is`

> `at the beginning of a memory block which owns itself (the preceding`

> `paragraph should be a valid MCB with "owner" the same as the`

> `suspected PSP).`

> `Novell NetWare updates the fields at offsets 3Eh and 3Fh without`

> `checking that a legal PSP segment is current; see AH=50h for further`

> `discussion`

> `Format of environment block:`

> `Offset Size Description (Table 0604)`

> `00h N BYTEs first environment variable, ASCIZ string of form "var=value"`

> `N BYTEs second environment variable, ASCIZ string`

> `...`

> `N BYTEs last environment variable, ASCIZ string of form "var=value"`

> `BYTE 00h`

> `---DOS 3.0+ ---`

> `WORD number of strings following environment (normally 1)`

> `N BYTEs ASCIZ full pathname of program owning this environment`

> `other strings may follow`

> TOC

> # Interrupts

> ### BY | Lewis Sellers lsellers@usit.net

> Legacy only adds one new set of interrupts to its DOS emulation. They are at INT 0FFh an are mostly informational.

> LEGACY CHECK

> To Call:

> AX = 0000h

> CX = n

> INT FFh

> Returns:

> AX = 1

> CX = NOT CX

> This does a simple check to determine if Legacy is active. Test to see if the value returned in CX is the NOT of what you sent. Try it as many times as you think you need to.

> LEGACY GENERAL CONFIGURATION VERSION AND LENGTH

> To Call:

> AX = 0002h

> INT FFh

> Return:

> AX = information version, should be 0

> ECX = length of area needed for configuration info

> LEGACY GENERAL CONFIGURATION

> To Call:

> AX = 0003h

> ES:(E)DI =

> INT FFh

> Return:

> This functions copies a wealth of information about the current Legacy emulation to the pointer you supply using ES:(E)DI.

> Format of configuration buffer:

> Size Description

> DWORD Legacy major version

> DWORD Legacy minor version

> DWORD Legacy build

> DWORD beta flag (00h normal release, 01h beta release)

> DWORD DPMI major version ;DOS Protected Mode Interface

> DWORD PMI minor version

> DWORD VCPI major version

> DWORD VCPI minor version

> DWORD EMS major version ;Extended Memory Support

> DWORD EMS minor version

> DWORD XMS major version ;Expanded Memory Support

> DWORD XMS minor version

> DWORD VESA major version

> DWORD VESA minor version

> DWORD processor (3 = 386, 4 = 486, 5= Pentium)

> DWORD coprocessor (4 = none, 6 = 287, 7 = 387/486)

> DWORD machine type (0 = IBM PC compatible)

> DWORD machine bus type (0=ISA, 1=MCA, 2=XT, 3=EISA, 4=PCI)

> DWORD physical memory in system

> DWORD virtual memory in system

> DWORD DMA capable memory given to emulation

> DWORD actual memory given to 1MB area

> DWORD extended" memory given to emulation

> DWORD total memory given to emulation

> DWORD virtual swaps since startup

> DWORD support

> bit 0: 16-bit

> bit 1: 32-bit

> bit 2: ?-bit

> bit 3: keyboard support

> bit 4: mouse support

> bit 5: joystick

> bit 6: xms (HIMEM.SYS)

> bit 7: ems (EMM386.SYS)

> bit 8: vcpi

> bit 9: dpmi

> bit 10: vga

> bit 11: vesa 1.2

> bit 12: vbe 2.0

> bit 13: vbe ?

> bit 14: SHARE.EXE

> bit 15:

> DWORD status

> bit 0: command line mode?

> 0=no,

> 1=yes, returns to command-line at termination

> bit 1: mode, 0=16, 1=32

> bit 2: ports, 0=free, 1=selective permission bitmap

> bit 3: sessions, 0=single DOS, 1=multiple DOS

> LEGACY VIDEO CONFIGURATION VERSION AND LENGTH

> To Call:

> AX = 0010h

> INT FFh

> Return:

> AX = version, should be 0

> ECX = length of area needed for configuration info

> LEGACY VIDEO CONFIGURATION

> To Call:

> AX = 0011h

> ES:(E)DI =

> INT FFh

> Return:

> LEGACY AUDIO CONFIGURATION VERSION AND LENGTH

> To Call:

> AX = 0010h

> INT FFh

> Return:

> AX = version, should be 0

> ECX = length of area needed for configuration info

> LEGACY AUDIO CONFIGURATION

> To Call:

> AX = 0011h

> ES:(E)DI =

> INT FFh

> Return:

> LEGACY CONTROLLER CONFIGURATION VERSION AND LENGTH

> To Call:

> AX = 0010h

> INT FFh

> Return:

> AX = version, should be 0

> ECX = length of area needed for configuration info

> LEGACY CONTROLLER CONFIGURATION

> To Call:

> AX = 0011h

> ES:(E)DI =

> INT FFh

> Return:

> LEGACY COMMUNICATIONS CONFIGURATION VERSION AND LENGTH

> To Call:

> AX = 0010h

> INT FFh

> Return:

> AX = version, should be 0

> ECX = length of area needed for configuration info

> LEGACY COMMUNICATIONS CONFIGURATION

> To Call:

> AX = 0011h

> ES:(E)DI =

> INT FFh

> Return:

> LEGACY EMULATION CONFIGURATION VERSION AND LENGTH

> To Call:

> AX = 0010h

> INT FFh

> Return:

> AX = version, should be 0

> ECX = length of area needed for configuration info

> LEGACY EMULATION CONFIGURATION

> To Call:

> AX = 0011h

> ES:(E)DI =

> INT FFh

> Return:

> LEGACY EMULATION SETUP

> To Call:

> AX = 0091h

> ES:(E)DI =

> INT FFh

> Return:

> TOC

> # Patches and Fixes

> ### BY | Lewis Sellers lsellers@usit.net

> Unfortunately, even after the DOS32 Legacy Metaphor has aged a while, there will still be a few programs that will not run at all, or may require a small front helper or patch program. This is to be expected. One of the responsibilties of The Legacy Group, aside from working on DOS32 and possibly DOS16/32 is to act as a clearinghouse for these patches and fixes.

> Probably one of the most common problem will be the curious usage of .COM and .BAT files to set up 32-bit DOS programs.

> This document should be fully HTML 3.2 compliant
> (excepting Javascript timedate stamping).
> If you encounter problem while browsing,
> then email Lewis Sellers.
> Copyright © 1995,1996, Lewis Sellers. All Rights Reserved.

> ### TRADEMARKS

>     The Pentium and Pentium Pro are trademarks of the Intel Corporation.
>     TASM is a trademark of Borland International.

> Grail Millennium Project