The Philips :YES
Note: This document is a work in progress.
The :YES (a name that certainly wasn't chosen for being easily findable in a search engine) is one of those early PC clones that runs MSDOS but isn't compatible at a hardware level with the original IBM PC. Instead, the hardware differences are handled by the ROM BIOS and IO.SYS.
At a hardware level, the specification is roughly:
- 80186 processor (rather than IBM's 8088). As a rule, the 80186 wasn't used in true IBM clones because its onboard peripherals aren't compatible with the IBM PC chipset.
- Two 3.5" floppy drives, plus a socket allowing two further external floppy drives.
- Built-in video chipset supporting composite and SCART output. An extra video module added support for TTL monitors (giving video capabilities roughly similar to Plantronics or Hercules, depending on the monitor used).
- Digital Research DOS Plus in ROM.
I don't have a :YES, so all my information comes from the manuals, the BIOS ROM, and the system software.
Hardware
A :YES can have either 128k, 256k or 640k of memory. The BIOS detects this at boot time, and uses the 80186's memory mapping ability to place the video framebuffer at the end of memory, writing to the MMCS register (port 0FFA6h):
Memory size | Video segment | MMCS |
---|---|---|
128k | 1000h | 01F8h |
256k | 3000h | 21F8h |
640k | 9000h | 81F8h |
I/O ports used are:
0400-041E: Serial / parallel ports (I8256AH MUART): 0400 MUART Command Register 0: Bits 6-7: Data bits 00 => 8 01 => 7 10 => 6 11 => 5 Bits 5-4: Stop bits 00 => 1 01 => 1.5 10 => 2 11 => 0.75 Bit 3: Break-in Detect Enable Bit 2: Interrupt on bit change Bit 1: 8086 mode Bit 0: Timer frequency select 0402 MUART Command Register 2 Bit 7: Parity enable Bit 6: Even Parity Bits 5-4: System clock prescaler Bits 0-3: Data rate 0404 MUART Command Register 3 0406 MUART mode register 0408 MUART Port 1 Control register 040A MUART interrupt enable 040C MUART interrupt address 040E MUART transmit / receive buffer 0410 MUART Port 1: Serial / parallel port control (r/w) Bit 6: Normally 1, set to 0 to reset serial port Bit 4: Parallel port busy? Bit 1: Parallel port strobe Bit 0: Parallel port busy? 0412 MUART Port 2: Parallel port write character 0414 MUART Timer 1 0416 MUART Timer 2 0418 MUART Timer 3 041A MUART Timer 4 041C MUART Timer 5 041E Serial port status Bit 7: Interrupt pending Bit 6: Receive data ready Bit 5: Transmit holding register empty Bit 4: Transmit shift register empty Bit 3: Break Bit 2: Parity error Bit 1: Overrun Bit 0: Framing error 0480 WD2797 command / status register 0482 WD2797 track register 0484 WD2797 sector register 0486 WD2797 data register 0500 CRTC register select 0502 CRTC register value 0580 Floppy drive select (low 4 bits - bit 0 for first drive, 1 for second drive etc.) Bit 6 may be motor enable. 05A0 Last scancode from keyboard 05C0 Palette (16 entries at even-numbered addresses. Each entry holds .... a 4-bit IRGB value for the corresponding colour. 05DE 05E0 System / display control. On read: Bits 6-7 give monitor type. 0: ?Colour TTL 1: Mono TTL 2: ?Colour composite 3: ?Colour SCART Bit 0 set if Professional Expansion Board is present. (I don't know which colour monitor option is which; I'm simply guessing based on the initial video mode). On write: Bits 0-4 are the video mode control register. Bit 0 set for 40×25 text, 640×252 graphics and 160×252 graphics. Bit 1 set for text mode, clear for graphics modes Bit 2 set for the 640-pixel graphics modes Bit 3 set for the 320-pixel graphics mode Bit 4 always set (enable display?) Bit 5 is the beeper. Bit 7 is used in the floppy disk I/O functions. 066A Real-time clock 067A SASI data register 067C SASI status / control register FF00 80186 onboard peripherals. DMA0 is used for the hard drive, DMA1 for .... the floppy. Timers 0 and 1 are used as system timers. FFFF
Video modes
The BIOS contains timings for the following video modes. There are two sets of timings for most of the modes — presumably one for TTL monitors, the other for SCART / composite output.
Mode | Horizontal total | Horizontal displayed | Horizontal sync | Sync widths | Vertical total | Vertical adjust | Vertical displayed | Vertical sync | Interleave | Character height | Cursor shape | Display address | Cursor address | ||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
First set | |||||||||||||||||
40×25 | 54 | 40 | 44 | 67 | 27 | 3 | 25 | 26 | 2 | 9 | 0 | 0 | 0x39 | 0xD8 | 0 | 0 | |
80×25 | 54 | 40 | 44 | 67 | 27 | 3 | 25 | 26 | 2 | 9 | 0 | 0 | 0x39 | 0xD8 | 0 | 0 | |
80×25 mono | 48 | 40 | 42 | 84 | 25 | 16 | 25 | 26 | 2 | 13 | 0 | 0 | 0x39 | 0xD8 | 0 | 0 | |
320×252 | 54 | 40 | 44 | 67 | 69 | 0 | 63 | 64 | 2 | 3 | 0 | 0 | 0x00 | 0x00 | 0 | 0 | |
640×252 | 54 | 40 | 44 | 67 | 69 | 0 | 63 | 64 | 2 | 3 | 0 | 0 | 0x00 | 0x00 | 0 | 0 | |
640×352 | 48 | 40 | 42 | 84 | 94 | 2 | 88 | 88 | 2 | 3 | 0 | 0 | 0x00 | 0x00 | 0 | 0 | |
160×252 | 54 | 50 | 44 | 67 | 69 | 0 | 63 | 64 | 2 | 3 | 0 | 0 | 0x00 | 0x00 | 0 | 0 | |
Second set | |||||||||||||||||
40×25 | 56 | 40 | 44 | 68 | 30 | 2 | 25 | 27 | 2 | 9 | 0 | 0 | 0x39 | 0xD8 | 0 | 0 | |
80×25 | 56 | 40 | 44 | 68 | 30 | 2 | 25 | 27 | 2 | 9 | 0 | 0 | 0x39 | 0xD8 | 0 | 0 | |
80 ×25 mono | 48 | 40 | 42 | 84 | 25 | 16 | 25 | 26 | 2 | 13 | 0 | 0 | 0x39 | 0xD8 | 0 | 0 | |
320×252 | 56 | 40 | 44 | 68 | 77 | 0 | 63 | 68 | 2 | 3 | 0 | 0 | 0x00 | 0x00 | 0 | 0 | |
640×252 | 56 | 40 | 44 | 68 | 77 | 0 | 63 | 68 | 2 | 3 | 0 | 0 | 0x00 | 0x00 | 0 | 0 | |
640×352 | 48 | 40 | 42 | 84 | 94 | 2 | 88 | 88 | 2 | 3 | 0 | 0 | 0x00 | 0x00 | 0 | 0 | |
160×252 | 56 | 50 | 44 | 68 | 77 | 0 | 63 | 68 | 2 | 3 | 0 | 0 | 0x00 | 0x00 | 0 | 0 | |
40-column mode for mono monitor | |||||||||||||||||
40×25 mono | 48 | 40 | 42 | 84 | 25 | 16 | 25 | 25 | 2 | 13 | 0 | 0 | 0x39 | 0xD8 | 0 | 0 |
Terminal Emulation
Escape codes supported by the two built-in terminal emulations:
VT52
ESC A | Cursor up |
ESC B | Cursor down |
ESC C | Cursor left |
ESC D | Cursor right |
ESC E | Clear screen |
ESC H | Home cursor |
ESC I | Cursor up (scroll down if on top row) |
ESC J | Erase from cursor to bottom of screen |
ESC K | Erase from cursor to end of line |
ESC L | Insert a line |
ESC M | Delete current line |
ESC N | Delete character under cursor |
ESC Y row col | Set cursor position |
ESC a | Enable cursor |
ESC b colour | Set foreground colour |
ESC c colour | Set background colour |
ESC d | Delete from start of screen to cursor |
ESC e | Enable cursor |
ESC f | Disable cursor |
ESC j | Save cursor position |
ESC k | Restore cursor position |
ESC l | Erase characters on current line |
ESC o | Erase from start of line to cursor |
ESC p | Inverse video |
ESC q | Normal video |
ESC r | Bold text on |
ESC s | Blinking text on |
ESC t | Blinking text off |
ESC u | Bold text off |
ESC v | Enable wrapping at the end of the line. |
ESC w | Disable wrapping at the end of the line. |
ESC < | Switch to VT100 emulation |
ESC ? | Switch to dumb terminal emulation |
ESC 0 | Underlined text on |
ESC 1 | Underlined text off |
VT100
ESC [ count A | Cursor up by count lines | ||||||||||||||||||||||||||||
ESC [ count B | Cursor down by count lines | ||||||||||||||||||||||||||||
ESC [ count C | Cursor left by count lines | ||||||||||||||||||||||||||||
ESC [ count D | Cursor right by count lines | ||||||||||||||||||||||||||||
ESC [ count E | Cursor to beginning of row, count lines up | ||||||||||||||||||||||||||||
ESC [ count F | Cursor to beginning of row, count lines down | ||||||||||||||||||||||||||||
ESC [ col G | Move cursor to column col | ||||||||||||||||||||||||||||
ESC [ row ; col H | Move cursor to row row, column col | ||||||||||||||||||||||||||||
ESC [ n J | Clear part of the screen | ||||||||||||||||||||||||||||
ESC [ n K | Clear part of the line | ||||||||||||||||||||||||||||
ESC [ n L | Scroll down the area of the screen below the cursor by n lines | ||||||||||||||||||||||||||||
ESC [ n M | Scroll up the area of the screen below the cursor by n lines | ||||||||||||||||||||||||||||
ESC [ n P | Delete n characters to the right of the cursor | ||||||||||||||||||||||||||||
ESC [ n S | Scroll the screen up by n lines. | ||||||||||||||||||||||||||||
ESC [ n T | Scroll the screen down by n lines. | ||||||||||||||||||||||||||||
ESC [ col ` | Move cursor to column col | ||||||||||||||||||||||||||||
ESC [ d | |||||||||||||||||||||||||||||
ESC [ row ; col f | Move cursor to row row, column col | ||||||||||||||||||||||||||||
ESC [ n h | Turn on option | ||||||||||||||||||||||||||||
ESC [ n l | Turn off option | ||||||||||||||||||||||||||||
Options are:
| |||||||||||||||||||||||||||||
ESC [ n m | Select colours / attributes | ||||||||||||||||||||||||||||
ESC [ 6n | Get cursor position | ||||||||||||||||||||||||||||
ESC [ x ; y { | Plot a pixel | ||||||||||||||||||||||||||||
ESC [ x ; y | | Draw a line and update the last pixel position plotted | ||||||||||||||||||||||||||||
ESC [ x ; y } | Draw a line and don't update the last pixel position plotted | ||||||||||||||||||||||||||||
ESC [ n ~ | Set cursor blink rate to n | ||||||||||||||||||||||||||||
ESC [ n ^ | Set beeper pitch to n | ||||||||||||||||||||||||||||
ESC [ n _ | Set cursor row relative to character | ||||||||||||||||||||||||||||
ESC [ s | Save cursor position | ||||||||||||||||||||||||||||
ESC [ u | Restore cursor position | ||||||||||||||||||||||||||||
ESC [ n r | |||||||||||||||||||||||||||||
ESC [ n \ | Set line bitmap to n |
BIOS
The top 64k of memory contains the DOS Plus kernel, a boot menu, and a BIOS that attempts to be compatible with the IBM 5150, its heirs and successors.
The BIOS version can be found as a little-endian word at 00415h (0040:0015):
Bits 15-12: Gate array version Bits 11- 8: BIOS version major Bits 7- 0: BIOS version minor
The following services are provided:
- INT 5 (Print screen) is a simple IRET.
- INT 08h (Timer).
- INT 0Eh (Disk drive interrupt).
- INT 10h (Video output) presents an MDA / CGA level of functionality. It also has built-in VT52 and VT100 terminal emulation. The 'plot' functions (AH=0Ch, AH=0Dh) also work in text mode, using '*' as the pixel.
- INT 11h (Equipment list) is standard.
- INT 12h (Memory size) subtracts 57k from available memory if graphics modes are enabled.
- INT 13h (Disk access) supports the floppy drives, plus an optional SASI hard drive.
- INT 14h (Serial) supports the single serial port.
- INT 16h (Keyboard) supports the keyboard at an XT level of compatibility.
- INT 17h (Printer) supports the single printer port.
- INT 19h (System boot) attempts to start the :YES from, in order:
- The first floppy drive. The first four bytes of the OEM label in the boot sector must be ":YES".
- The first hard drive, if present.
- The second floppy drive.
- ROM at 0E0000h (if the byte at 0E0003h is 0Eh)
- ROM at 0D0000h (if the byte at 0D0003h is 0Eh)
- ROM at 0F0000h (unconditional - this starts DOS Plus and displays a boot menu)
- INT 1Ah (System clock) implements functions 0 and 1 only.
- INT 1Dh (Video timings). If the two bytes before the INT 1Dh handler are 53h, 48h ('S', 'H') then MODE.CMD is resident.
- INT 1Eh (Floppy parameters). On the :YES this is extended if a hard drive is present.
- INT 40h (IRQ0). Parallel port.
- INT 41h (IRQ1). Keyboard.
- INT 42h (IRQ2). Not used.
- INT 43h (IRQ3). Cursor update?
- INT 44h (IRQ4). Serial port?
- INT 45h (IRQ5). Serial port?
- INT 47h (IRQ7). Not used.
- INT 5Dh: Extended functionality (see below).
INT 5Dh
INT 5Dh is used to control the extra features of the :YES. In general it is used with AH = device class (10h for video, 13h for disk, 14h for serial etc) and AL = subfunction.
Video functions (AH=10h)
- AX = 1001h
Load character mapping table. Sets one of three DWORD address values.
DH = 0 for main set, 1 for secondary set.
DL = 0-2 for table within set.
ES:CX = value, 0000:0000 for default.Each table is a list of words terminated by 0000h. The low byte of each word is the character to match, the high byte is the character to replace it with.
When a character is substituted, its attribute is also altered. The first table resets bit 6 of the attribute; the second sets bit 6. The third table seems to match only on the top 4 bits of the character, and substitutes the top 4 bits. It also sets bit 6 of the attribute.
- AX = 1002h
- Copy the secondary set of character mapping tables to the main set.
- AX = 1003h
- Apply the mapping tables to character CL. Returns AL = resulting character, AH = 0-3 (top 2 bits of resulting attribute).
- AX = 1010h
Set video mode in CL:
Mode Resolution ======================================================= 0 40×25 text (BW40) 1 40×25 text (CO40) 2 80×25 text (BW40) 3 80×25 text (CO40) 4 320×252 graphics 5 320×252 graphics 6 640×252 graphics 7 80×25 text (MONO) 8 640×352 graphics 9 160×252 graphics =======================================================
- AX = 1011h
- Get current video mode and monitor type. Returns mode in low 4 bits of AL, monitor type in AH (top 2 bits of port 05E0h). Bit 4 of AL is set for modes 8 or 9.
- AX = 1012h
- Set colour / monochrome output: CL = 0 for mono, 1 for colour. Changing video mode will reset this to the default value for the selected mode.
- AX = 1013h
- Get colour / monochrome setting in AL.
- AX = 1020h
- Set beep pitch in CX.
- AX = 1021h
- Sound the beeper.
- AX = 1022h
- Set cursor flash rate in AL.
- AX = 1030h
- Select terminal emulation. AL = terminal: 0 for none, 1 for VT100, 2 for VT52.
- AX = 1031h
- Return terminal emulation in AL.
- AX = 1040h
- As INT 10h/AH=9, but bypassing the mapping tables set by INT 5Dh/AH=1001h.
- AX = 1041h
- Write a block of text to screen. BX gives width, CX gives height, ES:DX gives address.
- AX = 1042h
- Read a block of text from screen to memory. BX gives width, CX gives height, ES:DX gives address.
- AX = 1043h
- Set text output window. CL = left, BL = right, BH = top, CH = bottom
- AX = 1050h
Enable / disable graphics modes. CL = 0 to disable, 0FFh to enable.
Disabling graphics modes increases available program memory by 57k.
- AX = 1051h
- Get graphics mode availability. Returns AL = 0 (disabled) or 0FFh (avilable).
- AX = 1052h
- Get address of font for graphics modes in ES:BX, or 0 if graphics are not enabled. Unlike on a true blue PC, there is no graphics font in the BIOS so this would have to be provided by a utility like GRAFTABL.
- AX = 1053h
- Set graphics font address in ES:BX, 0000:0000 for none.
- AX = 1054h
- Get address of palette in ES:BX. Palette is 16 bytes long.
- AX = 1055h
- Change palette. BH = register, BL = value (both 0-0Fh).
- AX = 1060h
- Draw a line from the last plotted pixel to the given position. BH=bitmap pattern, BL=attribute, CX / DX are coordinates.
Disk functions (AH=13h)
- AX = 1301h
- Set INT13h hook function 1 in ES:BX (0000:0000 for none).
- AX = 1302h
- Set INT13h hook function 2 in ES:BX (0000:0000 for none).
Serial functions (AH=14h)
- AX = 1401h
- Set serial port callback in ES:BX.
- AX = 1402h
- Unknown.
- AX = 1403h
- Unknown.
- AX = 1404h
- Set a 32-bit value in BXCX.
- AX = 1405h
- Return serial port status (as INT 14h/AH=3).
Keyboard functions (AH=16h)
- AX = 1601h
- Set keyboard configuration table. DH = data set (0 for secondary, 1 for primary). DL = table to set, 0-6. ES:CX = table address, 0000:0000 to use default.
- AX = 1602h
- Copy secondary keyboard configuration addresses to primary.
- AX = 1603h
- Set keyboard callback in ES:BX. 0000:0000 for none.
Printer functions (AH=17h)
- AX = 1701h
- Enable / disable printer buffering. ES:BX = callback address, 0000:0000 to disable.
- AX = 1702h
- Set print spool timer as a 32-bit value in BXCX.
Special functions (AH=80h) and miscellany
- AX = 388Ch
- Cancel a one-shot timer. DL = timer number.
- AX = 8001h
- Get system memory size in paragraphs. Returns size in BX. If graphics modes are enabled, the system memory size will be reduced to make room for the graphical framebuffer.
- AX = 8002h
Set a one-shot timer. Pass DL = timer number, CX = countdown, ES:BX = function to call when the timer reaches zero.
Timer 4 is used by the serial port.
Timer 7 is used internally for print spooling. In this case countdown is 32 bits (high word in BP).
- AX = 8003h
- Returns last keypress in AL.
- AX = 8004h
- Set a callback when the INT 8 timer fires. ES:BX = callback, 0000:0000 for none.
- AX = 8005h
- Unknown, parameter in DX.
- AX = 8101h
-
Set / cancel mouse callback (implemented by the mouse driver, not the BIOS.
ES:BX = callback address (0 to cancel mouse callback).
Returns ES:BX = address of 3-byte mouse packet. On mouse move, callback code will be called, and the mouse packet will contain:
DB buttons DB delta_x DB delta_y
Mouse
A loadable mouse driver is provided. In BIOS versions later than 1.02, the mouse support is present in the BIOS and does not need to be loaded manually.
The mouse driver hooks two interrupts: INT 0Ch and INT 5Dh.
INT 0Ch: Mouse hardware interrupt. When triggered, the handler reads port 066Eh, bit 1. If it is nonzero, a byte is read from port 0676h and interpreted (presumably this is the input from the mouse).
(All values are speculative; I may well have transposed the buttons, the X and Y axes, or the directions). Bit 0: Button 2 Bit 1: X movement direction: 1=left 0=right Bit 2: 0 -> 1 transition indicates X movement, direction given by bit 1. Bit 3: Y movement direction: 1=up 0=down Bit 4: 0 -> 1 transition indicates Y movement, direction given by bit 3. Bit 5: Button 1
INT 5Dh: API. If called with AX=8101h, this is handled by the mouse driver:
- If ES:BX is 0, mouse interrupts will be disabled. The driver will then call INT 5Dh with AX=388Ch, DL=3.
- If ES:BX is nonzero, it is the address of a 'mouse changed' callback.
Mouse interrupts will be enabled. Internally, the driver calls INT 5Dh
with AX=8002h, CX=32h, DL=3, ES:BX=address of a function within the driver.
The function will return with ES:BX = address of
mouse positions within driver:
DB buttons DB delta_x DB delta_y
When mouse interrupts are enabled, the callback code checks if mouse coordinates have changed. If so it calls the user callback passed to INT 5Dh/AX=8101h in ES:BX.
Real-Time Clock
The real-time clock is provided by the Professional Expansion Board.
XCLOCK.EXE detects the presence of the Professional Expansion Board by reading port 05E0h. If the bottom bit is zero, the clock is considered to be present.
The RTC is accessed using a serial protocol, controlled through ports 066Eh and 067Ch. The latter appears to be shared with the SASI controller.
Port Bit Meaning 066Eh 0 Data received from RTC 067Ch 0 Data to write to RTC 067Ch 6 } 067Ch 7 } Purpose unknown, but probably govern data direction.
The last value written to port 067Ch is saved in memory at 004E4h, and should be kept up to date.
Depending whether the register select is big- or little- endian, RTC registers are either:
Register (if big-endian) (if little-endian) Meaning 0 0 Month 2 2 Day 4 1 Hour 6 3 Minute
XCLOCK doesn't access the hardware when manipulating the year, so possibly the RTC only supports month, day, hour and minute. Instead, when the clock is set, the date (as the number of days since 1 January 1980) is written to offset 6Dh of the first sector of the boot drive. This is then used to initialise the DOS date at next boot.
John Elliott 7 April 2019