Category : Assembly Language Source Code
Archive   : D86BIOS4.ZIP
Filename : ZBIOS1.8

 
Output of file : ZBIOS1.8 contained in archive : D86BIOS4.ZIP
;------------------
; WANG INTERFACE
;------------------

; Thanks to Alan Tschetter for providing the information necessary for me
; to program this interface.

WANG_KEYS:
DB 0E1 ; HELP key value
DB 07F-FUNC ; add-quantity for FUNC
L1:
DB 0C2,0C9,0C0,0C8,0C4 ; DOWN, NEXT, UP, PREV, HOME
DB 097,097 ; shift-F7 key, disabled Alt-F9 key
N_CONTROL_KEYS EQU $-L1

DW HELP_HELP ; pointer to "HELP" message, the name of Wang's HELP key

L2:
DW WANG_COPY ; VID_COPY routine
DW WANG_ATTR ; VID_ATTR routine
DW RET ; there is no VID_FIX necessary on the Wang
DW WANG_BELL ; BIOS_BELL routine
DW WANG_KEY ; BIOS_KEY routine
DW RET
DW RET
DW 0F000 ; new value for VIDEO_SEG
DB 0 ; normal-video attribute for the Wang PC
DB 2 ; reverse-video attribute for the Wang PC
N_BIOS_CALLS EQU ($-L2)/2


; Other Wang keycodes: F1--F16 80--8F
; Prev C8 Erase CB
; Insert C6 Delete C7
; <--- C3 ---> C1
; EXEC C5
; All the above codes add 010 for SHIFT versions.
; NO ALT KEY!!!
; Print E3 Back Tab CD
; Cancel E0 Shift Cancel 03


; WANG_CONFIG is the BIOS initialization routine for a Wang PC. We copy the
; values of WANG_KEYS to various locations, then we fetch the value of
; ENABLE_PORT, that lets us access Wang's video memory, then we move the
; user's cursor to the lower left corner.

L1: ; console codes to move cursor to lower left corner
DB 01B,'[25;1H' ; row 25, column 1
L2 EQU $-L1 ; L2 is the count of bytes

WANG_CONFIG:
MOV SI,WANG_KEYS ; point to Wang's table of key codes and other values
CALL NEW_KEYS ; plug the new values into our program's data structures
MOV AL,1 ; function code for GET BIOS ENVIRONMENT
INT 088 ; sets ES to a segment where we'll find port #
ES MOV BX,[BX+10] ; fetch a pointer
ES MOV AH,[BX+19] ; use the pointer to fetch the high of the port #
MOV AL,010 ; low of the port # is always 010
MOV ENABLE_PORT,AX ; store the port number
MOV DS,CS ; point DS to our program, for console sequence
MOV DX,L1 ; point DX to the "go to lower left" console sequence
MOV CX,L2 ; load the number of bytes in the sequence
MOV BH,0 ; device number, maybe? I don't know for sure
MOV AL,0D ; function number, maybe? I don't know for sure
INT 088 ; output escape string, user's cursor goes to lower left
RET


; WANG_COPY is the Wang-PC version of the VID_COPY routine. The character
; and attribute bytes are reversed from what they are on the IBM-PC, so
; AH and AL are swapped before and after every word output. There are no
; snow problems; so we can get away with copying everything every time.
; We do need to enable the video memory, though.

WANG_COPY:
MOV DX,ENABLE_PORT ; fetch the port number for enabling video memory
MOV AL,1 ; value 1 causes memory to be enabled
OUT DX,AL ; we can now access the video memory
L1: ; loop here for each character to be copied
LODSB ; fetch the next character
XCHG AH,AL ; swap character into AH, attribute byte into AL
STOSW ; output the word to video memory
MOV AH,AL ; copy the attribute byte back to AH, for next char
LOOP L1 ; loop to copy the next character
L2: ; common exit with WANG_ATTR
MOV AL,0 ; value 0 shuts off access to video memory
OUT DX,AL ; video access is now disabled
RET


; WANG_ATTR is the Wang-PC version of the VID_ATTR routine. The attribute
; byte is the low byte of the DI-pointed video memory. Also, to access it,
; we must send the code that enables Wang video memory.

WANG_ATTR:
PUSH AX ; preserve the attribute code
MOV DX,ENABLE_PORT ; fetch the port number for enabling video memory
MOV AL,1 ; value 1 causes memory to be enabled
OUT DX,AL ; we can now access the video memory
POP AX ; restore the attribute code
STOSB ; output the attribute byte to the LOW byte of video word
JMP L2 ; join common code to disable video access


; WANG_KEY is the Wang-PC version of the BIOS_KEY routine.

WANG_KEY:
PUSH BX ; preserve register across call
L1: ; loop here to wait for a key to become ready
MOV AL,15 ; Wang BIOS function code for GET KEY STATUS
MOV BL,2 ; another parameter for Wang BIOS - I'm not sure which
INT 088 ; call Wang BIOS to get the status and maybe the key
TEST AL ; do we have a key?
JNZ L1 ; loop if not, to try again
XCHG AX,BX ; we do: swap the key code into AL for return
POP BX ; restore clobbered register
RET


; WANG_BELL is the Wang-PC version of the BIOS_BELL routine.

WANG_BELL:
MOV BX,7 ; BL=7 is the BELL code; the BIOS also wants BH=0
MOV AL,6 ; Wang BIOS function code for CONSOLE OUTPUT
INT 088 ; output the BELL control code to the Wang console
RET


;------------------
; TI-PC INTERFACE
;------------------

; Thanks to David R. Cook for writing the following code. I have reformatted
; it to look like the rest of my code, and made optimizations.

TIPC_KEYS:
DB 0B5 ; key code for F11 - the help key
DB 0AA-FUNC ; F1 is code 0AB on the TI-PC
L1:
DB 0C0 ; down-arrow key
DB 0C1 ; no PgDn key on the TI-PC, so we use alt-down-arrow code
DB 0B8 ; up-arrow key
DB 0B9 ; no PgUp key on the TI-PC, so we use alt-up-arrow code
DB 0B7 ; HOME key
DB 0CA ; shift-F7 key
DB 0E0 ; alt-F9 key
N_CONTROL_KEYS equ $-L1

DW F11_HELP ; pointer to help message

L2:
DW TIPC_COPY ; VID_COPY routine
DW TIPC_ATTR ; VID_ATTR routine
DW TIPC_FIX ; VID_FIX routine
DW TIPC_BELL ; BIOS_BELL routine
DW TIPC_KEY ; BIOS_KEY routine
DW RET
DW RET
DW 0DE00 ; new value for VIDEO_SEG
DB 0F ; normal-video attribute for the TI-PC
DB 01F ; reverse-video attribute for the TI-PC
N_BIOS_CALLS equ ($-L2)/2

; Other TI keycodes:

; key +shift +alt +ctrl plain
; ----------------------------------
; F1 0C4 0D8 0CE 0AB
; ...
; F10 0CD 0E1 0D7 0B4
; F11 "x" "|" "z" 0B5
; F12 "y" "}" "{" 0B6
;
; PRNT 0E2
; INS 098 09A 099 0C2
; DEL 0A8 0AA 0A9 0C3
; UP AR 0F8 0B9 0F4
; DN AR 0F9 0C1 0E6
; LT AR 0FB 0BC 0E3 0BB
; RT AR 0FA 0BE 0E4 0BD
; HOME 0F6 0F5 0E7
; TAB 07F ignored ignored 09



; TIPC_CONFIG is the BIOS initialization routine for the TI-PC. We copy the
; values in TIPC_KEYS to various locations, then we drop into TIPC_FIX,
; to reset the cursor.

TIPC_CONFIG:
MOV SI,TIPC_KEYS ; point to configuration-table for TI-PC's BIOS
CALL NEW_KEYS ; copy the values to our tables
TIPC_FIX:
MOV AH,014 ; BIOS function code for "clear graphics screen"
INT 049 ; clear the graphics screen
MOV AH,013 ; BIOS function code for "clear text screen"
INT 049 ; clear the text screen
MOV AH,2 ; BIOS function code for "position the cursor"
MOV DX,1 BY 24 ; first column, 24th row
INT 049 ; move the user's cursor to the bottom left corner
RET


; TIPC_COPY is the VID_COPY routine for the TIPC video board. The attribute
; AH is written to a single memory-mapped latch in the video segment.
; Then the text bytes can be copied as-is.

TIPC_COPY:
ES MOV B[01801],AH ; set the attribute latch
SHR DI,1 ; adjust the video address for bytes, not words
REP MOVSB ; copy the text as-is
SHL DI,1 ; restore the video address to words, not bytes
RET


; TIPC_ATTR is the VID_ATTR routine for TI-PC computer. We change the
; attribute latch to the one provided in AL, then we add 0 to the video
; character in memory, causing the new latch value to take effect.

TIPC_ATTR:
SHR DI,1 ; adjust video address for bytes, not words
ES MOV AH,B[DI] ; fetch the character
ES MOV B[01801],AL ; rewrite the latch with the caller's value
ES MOV B[DI],AH ; re-write the value already there, to effect the latch
SHL DI,1 ; restore DI
RET


; TIPC_KEY is the BIOS_KEY routine for TI_PC computer. We must transform the
; two-byte code returned by the TIPC BIOS into the single code AL expected by
; the rest of the debugger. The only differences to IBM_KEY are the interrupt
; number, and the mapping of the codes received and returned.

TIPC_KEY:
MOV AH,0 ; function code for GET KEY
INT 04A ; get the keystroke from the TIPC BIOS
TEST AL ; is the return AL nonzero?
JNZ RET ; if yes then AL is our return code
MOV AL,AH ; AL is zero, so AH determines the return code
ADD AL,080-16 ; shift the values into a range not seen directly in AL
RET


; TIPC_BELL is the BIOS_BELL routine for TIPC-PC computer. We output the code
; 07 to the BIOS's console output routine. The only difference to IBM_KEY is
; the interrupt number.

TIPC_BELL:
MOV AX,0E07 ; AH= console out function number; AL="BELL" control code
INT 049 ; output BELL to the console
RET


;------------------
; SANYO INTERFACE
;------------------

; Thanks to Jerry Farnsworth for providing the information necessary for me
; to program this interface.

SANYO_KEYS:
DB 0DC ; key code for Ctrl-PF5 -- the help key
DB 0 ; same function codes as IBM-PC
L1:
DB 0C0 ; down-arrow key
DB 0C1 ; PgDn key
DB 0B8 ; up-arrow key
DB 0B9 ; PgUp key
DB 0B7 ; HOME key
DB 0CA ; shift-F7 key is Ctrl 7 on the Sanyo
DB ALT_F 9 ; Ctrl-Shift-PF4 will restore a trashed screen
N_CONTROL_KEYS equ $-L1

DW PF5_HELP ; pointer to help message

L2:
DW SANYO_COPY ; VID_COPY routine
DW SANYO_ATTR ; VID_ATTR routine
DW NO_ACTUAL ; VID_FIX routine
DW IBM_BELL ; BIOS_BELL routine
DW IBM_KEY ; BIOS_KEY routine
DW SANYO_SAVE ; we must save the BIOS cursor position
DW SANYO_RESTORE ; we must restore the BIOS cursor position
DW 07C00 ; new value for VIDEO_SEG
DB 07 ; normal-video attribute for the Sanyo-PC
DB 0F0 ; reverse-video attribute for the Sanyo-PC
N_BIOS_CALLS equ ($-L2)/2


; Other Sanyo keycodes:

; IBM Sanyo IBM Sanyo

; Alt Ctrl Shift DOWN numeric pad 5
; Alt Fn Ctrl Fn END numeric pad 2
; Shift Fn Ctrl n
; Ctrl 2 Ctrl ` Ctrl F12345 Ctrl ={}:"
; Ctrl 6 Ctrl tilde Ctrl F678910 Ctrl ;',./



; SANYO_CONFIG is the BIOS initialization routine for a Sanyo 55x. We copy the
; values of SANYO_KEYS to various locations, fetch and store the current
; video page, and set the user cursor to the lower left of the screen.

; SANYO_FIX insures a screen refresh by filling the "actual" buffers of SCREEN_P
; with impossible FF-values.

SANYO_CONFIG:
MOV SI,SANYO_KEYS ; point to configuration-table for SANYO's BIOS
CALL NEW_KEYS ; copy the values to our tables
MOV AH,15 ; function number for fetching the video page
INT 010 ; set BH to the current video page
MOV SANYO_PAGE,BH ; store the page throughout the debugging session
MOV DX,24 BY 0 ; load coordinates for the lower left corner
CALL SET_SANYO_POS ; store this position
CALL SANYO_RESTORE ; this call causes the user cursor to move there
NO_ACTUAL:
MOV AX,0FFFF ; load AH and AL with the 0FF impossible-value
FILL_ACTUAL:
MOV ES,SS ; destination segment is our stack, for buffer-fill
XCHG DI,AX ; save fill-value in DI
SS MOV AX,SCREEN_P ; point to the screen buffer
MOV AL,80 ; advance AX to the actual buffer for the first line
XCHG AX,DI ; swap actual pointer to DI, restore fill value to AX
MOV DL,24 ; load the count of actual lines to fill
L2:
MOV CX,40 ; number of words in the actual buffer
REP STOSW ; fill the buffer with the words
ADD DI,256-80 ; advance output pointer to the next line's actual buff.
DEC DL ; count down lines
JNZ L2 ; loop to fill the next line
RET


; SANYO_COPY is the VID_COPY routine for the Sanyo. The Sanyo does not have
; a hardware character generator, so we call the BIOS to copy bit-patterns
; to the screen.

SANYO_COPY:
PUSH BX,BP ; preserve caller's BX and return DI value
MOV BP,>L3
MOV BH,0 ; load the page number
SANYO_PAGE EQU B[$-1] ; previous immediate value is plugged in
BP_VID_COPY:
MOV AX,DI ; fetch the output character number
ADD DI,CX ; add the character count
ADD DI,CX ; add it twice, to advance by words not bytes
PUSH DI
CALL GET_ROWCOL ; convert character number AX into row-and-column DX
DEC DX ; cancel the following first INC DX
L1: ; loop here for every character already out there
INC DX ; advance the column number DL to the next position
LODSB ; fetch the next character
MOV BL,AL ; save the character in BL
XCHG AL,[SI+79] ; swap it with the already-out-there value
CMP AL,BL ; is the character already out there?
LOOPE L1 ; loop if it is
JE >L2 ; jump if the characters are exhausted
INC CX ; undo the previous LOOPE's decrement of CX
CALL BP
LOOP L1 ; loop to check for another output character
L2:
POP DI,BP,BX ; restore clobbered registers
RET

L3:
CALL SET_IBM_CURSOR ; move the cursor to the indicated position
MOV AL,BL ; fetch the character to be output
MOV BL,7 ; load the attribute code, always 7 in Sanyo's case
PUSH CX ; save the character count
MOV CX,1 ; we are outputting 1 character in this call
MOV AH,9 ; BIOS function number for WRITE_CHAR
INT 010 ; write the character to the screen
POP CX ; restore the character count
RET


; SANYO_ATTR is the VID_ATTR routine for the Sanyo. We use the BIOS to
; move the cursor to the current position, read the character that is
; already there, and rewrite the character with the new attribute.


SANYO_ATTR:
PUSH BX,CX,DX,DI ; save registers across call
PUSH AX ; save the attribute across the repositioning
MOV AX,DI ; fetch the character number
CALL GET_ROWCOL ; convert the character number AX to row-and-column DX
CS MOV BH,SANYO_PAGE ; load the current page number
CALL SET_IBM_CURSOR ; move the cursor to the required location
MOV AH,8 ; function number for READ_CHARACTER
INT 010 ; set AL to the character already there
POP DX ; restore DL = new attribute byte
MOV BL,DL ; copy the attribute to BL where the BIOS expects it
MOV CX,1 ; we are writing one character only
MOV AH,9 ; BIOS function number for WRITE_CHAR
INT 010 ; write the character to the screen
POP DI,DX,CX,BX ; restore clobbered registers
RET


; GET_ROWCOL an address AX into a row number DH and column number DL. The input
; AX address is twice the number of characters from the start of the screen
; to the current cursor position.

GET_ROWCOL:
SHR AX,1 ; convert the word index into a byte index
MOV DL,80 ; there are 80 characters in a line
DIV DL ; compute the column number AH, row number AL
XCHG AL,AH ; swap so AH is row, AL is column
XCHG DX,AX ; swap so DH is row, DL is column
RET


; SANYO_SAVE is the BIOS_SAVE routine for the Sanyo. We record the user's
; cursor position, so that it can be restored by BIOS_RESTORE.

SANYO_SAVE:
MOV AH,3 ; BIOS function number for READ_CURSOR_POSITION
INT 010 ; set DX to the current user cursor position
SET_SANYO_POS:
CS MOV SANYO_POS,DX ; store the cursor position DX
RET


; SANYO_RESTORE is the BIOS_RESTORE routine for the Sanyo. We set the
; user's sursor position to the place previously stored.

SANYO_RESTORE:
MOV DX,0 ; fetch the cursor position
SANYO_POS EQU W[$-2] ; the above immedaite operand has been plugged
JMP SET_IBM_CURSOR ; jump to set the user's cursor


;------------------------
; TANDY 2000 INTERFACE
;------------------------

; Thanks to John B. Harrell, Contributing Editor PC Resuorce, for writing
; the following code. I have made minor code optimizations.

TANDY_KEYS:
DB ALT_F 10 ; code for Alt-F10 -- the HELP key
DB 0 ; F1 code same as on IBM-PC
L1:
DB 0C0 ; Down Arrow
DB 0C1 ; PgDn
DB 0B8 ; Up Arrow
DB 0B9 ; PgUp
DB 0B7 ; Home
DB 0CA ; Shift F7
DB ALT_F 9 ; Alt-F9 fixes a trashed screen
N_CONTROL_KEYS EQU $-L1

DW ALTF10_HELP ; pointer to help message

L2:
DW MONO_COPY ; VID_COPY routine
DW IBM_ATTR ; VID_ATTR routine
DW TANDY_FIX ; VID_FIX routine
DW IBM_BELL ; BIOS_BELL routine
DW IBM_KEY ; BIOS_KEY routine
DW RET ; BIOS_SAVE routine needed for Sanyo only
DW RET ; BIOS_RESTORE routine needed for Sanyo only
TANDY_VSEG DW ? ; Tandy 2000 floating video segment address = VIDEO_SEG
DB 0A ; normal video attribute on Tandy 2000
DB 0CA ; reverse video attribute on Tandy 2000
N_BIOS_CALLS EQU ($-L2)/2

; Other Tandy 2000 keycodes:

; key +shift +alt +ctrl plain
; ----------------------------------
; F1 0C4 0D8 0CE 0AB
; ...
; F10 0CD 0E1 0D7 0B4
; F11 012 "&" 01C 008
; F12 013 "`" 01D 009
;
; PRNT --- 0B6 0E2 010
; INS 0F9 010 00F 0C2
; DEL 0FA 00E 00D 0C3
; UP AR 0F5 001 000
; DN AR 0F6 007 006
; LT AR 0F7 002 0E3 0BB
; RT AR 0F8 --- 0E4 0BD
; HOME 0BA 016 0E7
; TAB 07F 0FE 0FD 009
; BKSP 008 0FC 07F 008
; TAB 07F 0FE 0FD 009
; ESC 01B 0FB 01B 01B
; END --- --- 0E5 0BF
; PGUP --- --- 0F4 0B9
; PGDN --- --- 0E6

TANDY_CONFIG:
INT 012 ; get reported memory size in KBytes
MOV CL,6 ; shift count = * 64 for Kbytes to paragraphs
SHL AX,CL ; convert to paragraphs
ADD AX,0080 ; point to starting location of monochrome video buffer
CS MOV TANDY_VSEG,AX ; save in data structure
MOV SI,TANDY_KEYS ; point to configuration table for Tandy 2000
CALL NEW_KEYS ; copy the value into BIOS tables
TANDY_FIX:
MOV AX,0 BY 2 ; AH= BIOS function code for SET_VIDEO_MODE; AL = mode 0
INT 16 ; force a monochrome video mode
JMP SET_IBM_LOW_LEFT ; move the cursor to the lower left corner


;-----------------------
; SIRIUS INTERFACE
;-----------------------

; BIOS interface routines for the ACT Sirius/DRG Victor 9000. Thanks to
; Frank Peelo, Dublin, Rep. of Ireland, for writing this code. I
; have made format changes and minor optimizations.

SIRIUS_KEYS:
DB 0A ; ALT-J for help, to duplicate Wordstar
DB 0F0-FUNC ; The function keys return F0 to F8 - I don't have 9 or 10!

L1:
DB 0A1 ; Down Arrow
DB 03 ; PgDn -- must use Ctrl-C as there's no PgDn
DB 0A0 ; Up Arrow
DB 012 ; PgUp -- must use Ctrl-R as there's no PgUp
DB 0B ; Home -- Ctrl-K
DB 01A ; Shift F7
DB 0 ; no fixup needed on Sirius
N_CONTROL_KEYS EQU $-L1

DW ALTJ_HELP

L2:
DW SIRIUS_COPY ; Offsets of subroutines.
DW SIRIUS_ATTR ; For the do-nothing routines, I'll let you put in
DW RET ; no SIRIUS_FIX needed
DW SIRIUS_BELL
DW SIRIUS_KEY
DW RET ; no SIRIUS_SAVE needed
DW RET ; no SIRIUS_RESTORE needed

DW 0F000 ; segment address of the Video RAM.
DB 040 ; attribute for normal-intensity, positive video.
DB 060 ; attribute for normal-intensity, underlined video
; (reverse video is 0C0)
N_BIOS_CALLS EQU ($-L2)/2

T1: DB 01B,'Y',' '+23,' ' ; ÷ Text of VT52 escape code to move
T2 EQU $-T1 ; ÷ cursor to row 23, col 0.


; SIRIUS_BLOCK is a control block passed to INT 0DF, to get the pointer
; to the console handler routine.

SIRIUS_BLOCK:
DW 1 ; first parameter - device number (1=CON device)
SIRIUS_BIOS DD ? ; second parameter - the vector is returned here


SIRIUS_CONFIG:
MOV SI,SIRIUS_KEYS ; Point to configuration table for the Sirius
CALL NEW_KEYS ; Copy the data into D86's tables
MOV BX,SIRIUS_BLOCK
MOV AX,14 ; BIOS function 14 = Get Device Vector
INT 0DF ; The variable Sirius_BIOS_Vector is now set
MOV BX,T1 ; There is only one screen, so move the cursor
MOV CX,T2 ; I use an escape code, through Int 29h, to skip
L1: ; redirection, if it's in use
MOV AL,[BX]
PUSH BX,CX ; preserve registers across interrupt
INT 029
POP CX,BX ; restore clobbered registers
INC BX
LOOP L1
RET


; SIRIUS_COPY is the VID_COPY routine for the Sirius. On the Sirius,
; video memory consists of 2k of 16-bit words, wherein the top 5 bits
; are the attributes, and the bottom 11 a pointer to the font cell. The
; 11 bits are multiplied by 2 to give the paragraph address, since each
; character definition takes 32 bytes (16x16 pixels); the font is
; therefore in the bottom 128k of RAM. To arrive at the standard video
; font address, 100xd is added to the ASCII code using 16-bit
; arithmetic. Note that the low 3 bits of the attribute byte are 0, so
; this can occupy the high byte throughout the addition without any
; Carry-through problems.

SIRIUS_COPY:
CALL SIRIUS_ADDR ; fix ES:DI for the Sirius
MOV BH,AH ; store the attribute - calculating font addr clobbers AH
L1:
LODSB
MOV AH,BH ; the addition of 100 can't carry into the attributes
ADD AX,100 ; calculate the font address
STOSW ; save the character to the screen
LOOP L1
SUB DI,DX ; convert DI back from memory to virtual screen offset
RET


SIRIUS_ATTR: ; VID_ATTR for the Sirius
CALL SIRIUS_ADDR ; fix ES:DI for the Sirius
ES MOV BX,W[DI] ; get the character
AND BX,07FF ; mask off the attribute bits
OR BH,AL ; and put in the new value
ES MOV W[DI],BX ; put the character back
SUB DI,DX ; restore DI
RET


SIRIUS_BELL: ; BIOS_BELL for the Sirius
PUSH ES,SI,DI
MOV CL,7 ; BIOS outputs the character in CL
MOV AX,1 ; BIOS call 1 = output char
CS CALL SIRIUS_BIOS
POP DI,SI,ES
RET


; SIRIUS_KEY is the BIOS_KEY routine for the Sirius. We find the next key
; pressed, and we translate F8 into F10, and the arrow keys into single
; codes.

SIRIUS_KEY:
PUSH ES,SI,DI ; registers might be clobbered by the BIOS
SUB AX,AX ; BIOS call 0 = Console Input
CS CALL SIRIUS_BIOS
CMP AL,0F8 ; is it Fn key 8?
JNZ >L1
MOV AL,0FA ; if so, pretend it was F10
JMP >L0 ; L0 pops registers & returns

; Escape codes. The Arrow keys return A-up, B-down, C-right & D-left
; I will use Right & Left as Page Up & Page Down, respectively.

C1:
DB 0A0,0A1,0A2,0A3 ; Codes that up, down, right & left get translated to.

L1:
CMP AL,01B ; if not escape then we don't have this problem
JNZ >L0 ; L0 pops registers returns
MOV AX,2 ; BIOS call 2: is there any keyboard data pending?
CS CALL SIRIUS_BIOS
OR AL,AL ; AL=0 if no data pending, else AL=FF & AH=next char
JZ >L2 ; If no data pending, then it was the ESC key
CMP AH,'A' ; else check for valid code
JB >L2 ; If <'A' or >'D', then it was the ESC key
CMP AH,'D'
JA >L2
XOR AX,AX ; If we are to interpret the next key, we mustn't leave
CS CALL SIRIUS_BIOS ; it hanging. (It's returned in AL)
MOV BX,C1-'A' ; BX = offset of the Code table, with A=lower bound of AL
CS XLATB
JMP >L0

L2: ; It was only an ESC after all
MOV AL,01B
L0:
POP DI,SI,ES
RET


; SIRIUS_ADDR converts ES:DI from an offset that the caller recognizes,
; into an offset that the Sirius video recognizes. The mapping is
; variable to allow fast scrolling. Since the buffer repeats once
; in the memory map, the screen occupies contiguous memory, starting
; at an address 2047 or less. We also return DX set to the amount
; DI was changed, so that SUB DI,DX will restore DI.

SIRIUS_ADDR:
PUSH DS ; We have to ask the CRTC chip for the address
MOV DS,DX,0E800 ; of the first char on the screen
MOV B[0],12 ; Register 12 = high byte
MOV DH,B[1]
MOV B[0],13 ; Register 13 = low byte
MOV DL,B[1] ; Now ax = offset of line 0, col 0, in 16-bit words
AND DX,2047 ; It must be modulo-2048. This will always be the
; case anyway, unless the user's programme has screwed up the CRTC
SHL DX,1 ; now the offset is in bytes in DX
ADD DI,DX ; Now ES:DI points to the right address
POP DS ; DS is preserved
RET


;--------------------------
; DEC RAINBOW INTERFACE
;--------------------------

FUNC EQU 59+111

; BIOS interface routines for the DEC Rainbow A and B. Thanks to
; Vinzenz Esser, Moosburg, West Germany for writing this code.
; I have made format changes and minor optimizations.

DEC_KEYS: ; Key definition for DEC_RAINBOW_100
DB 0 ; Key code for Help key
#if IBMSIM
DB 0
#else
DB 097-FUNC ; Keypad_0 code is 097 (use instead of F1)
#endif

L1:
DB 094 ; Down Arrow key
DB 092 ; Next Screen key
DB 093 ; Up Arrow key
DB 091 ; Prev Screen key
DB 08D ; Find key (Home)
DB 090 ; Select key (Shift-F7)
DB 081 ; F2 Print Screen key (Alt-F9)
N_CONTROL_KEYS EQU $-L1

DW HELP_HELP ; Pointer to "HELP" message

L2:
DW DEC_COPY ; VID_COPY routine
DW DEC_ATTR ; VID_ATTR routine
DW RET ; VID_FIX not needed
#if IBMSIM
DW IBM_BELL,IBM_KEY
#else
DW DEC_BELL ; BIOS_BELL routine
DW DEC_KEY ; BIOS_KEY routine
#endif
DW RET ; BIOS_SAVE not needed
DW RET ; BIOS_RESTORE not needed
DW 0B800 ; VIDEO_SEG not needed but included for IBMSIM
DB 0E ; Normal-video attribute
DB 0F ; Reverse-video attribute
N_BIOS_CALLS EQU ($-L2)/2


; DEC_CONFIG is the BIOS initialization routine for the DEC RAINBOW 100

DEC_CONFIG:
SS DEC B[LAST_LINE+1] ; 24-line screen: move D86 command line up
CS DEC B[D86_LINES] ; also reduce the refresh lines count
MOV SI,DEC_KEYS ; Point to DEC's table of keycodes
CALL NEW_KEYS ; and plug these values into D86
MOV DX,DEC_INIT ; Clear screen
MOV AH,9
INT 021
RET


DEC_INIT:
DB 27,'[?3l' ; clear screen, reset all attributes, select 80 column mode
DB 27,'[24;1H$' ; position cursor to line 24, column 1


; DEC_KEY is the DEC RAINBOW 100 version of the BIOS_KEY routine.
;
; The BIOS call we use returns a character code in AL, and flag bits in AH:
; 01 for function key, 02 shift, 04 control key, 08 caps lock in effect.
;
; We remap the keys so that function keys return consecutive codes above 80H,
; according to the following chart:
;
; BIOS D86 Bios D86
; Key Code Code Key Code Code
; ------------------- ---- ---- ------------------- ---- ----
; F1 Hold Screen XXx n/a Prev Screen 23 91
; F2 Print Screen 03 81 Next Screen 25 92
; F3 Set-Up XXx n/a Up Arrow 27 93
; F4 05 82 Down Arrow 29 94
; F5 Break 65 A9 Right Arrow 2B 95
; F6 Interrupt 07 83 Left Arrow 2D 96
; F7 Resume 09 84 Keypad 0 2F 97
; F8 Cancel 0B 85 Keypad 1 32 98
; F9 Main Screen 0D 86 Keypad 2 35 99
; F10 Exit 0F 87 Keypad 3 38 9A
; F11 (ESC) XXx n/a Keypad 4 3B 9B
; F12 (BS) XXx n/a Keypad 5 3E 9C
; F13 (LF) XXx n/a Keypad 6 41 9D
; Addt'l Options 11 88 Keypad 7 44 9E
; Help 00 FF Keypad 8 47 9F
; Do 01 80 Keypad 9 4A A0
; F17 13 89 Keypad Dash 4D A1
; F18 15 8A Keypad Comma 50 A2
; F19 17 8B Keypad Period 53 A3
; F20 19 8C Keypad Enter 56 A4
; Find 1B 8D Keypad PF1 59 A5
; Insert Here 1D 8E Keypad PF2 5C A6
; Remove 1F 8F Keypad PF3 5F A7
; Select 21 90 Keypad PF4 62 A8
; Compose Character XXx n/a
;
; XXx These keys are trapped out for special processing by firmware:
; F1 Hold Screen Scroll lock toggle
; F3 Set-Up Enter SET-UP mode to change system parameters
; F11 (ESC) Always generates ESC character 1Bh
; F12 (BS) Always generates BS character 08
; F13 (LF) Always generates LF character 0Ah
; Compose Character Introduction key to a compose character
; sequence to generate characters from the
; DEC 8-bit multinational character set

; The code assigned to each function key is presented in the column 'D86' of
; the function key table above. Since on the DEC RAINBOW only 8 of the
; function keys F1-F10 are available to an application I had to remap the
; keys somewhat:
; IBM Key DEC Key
; F1 Keypad 0
; .. ..
; F10 Keypad 9
; Alt-F9 F2 Print Screen
; Shift-F7 Select
; Home Find
; Alt-F10 Help

; Since the following 3 'function keys' do not set the function key flag,
; they end up here too:
; F11 (ESC) Always generates ESC character 1Bh
; F12 (BS) Always generates BS character 08
; F13 (LF) Always generates LF character 0Ah
;


L0:
TEST AL ; Is this an 8-bit character?
JNS RET ; drop through if it is: we don't want it
DEC_KEY:
PUSH DI,ES ; save some registers
L1:
MOV DI,6 ; DEC BIOS function for GET KEY IF AVAILABLE
INT 24 ; do it
INC CL ; is a character available?
JNZ L1 ; keep looking, if not
POP ES,DI ; restore clobbered registers
TEST AH,1 ; Check function key flag
JZ L0 ; Go, if not a function key
TEST AL ; Check for help key
JZ RET ; Go, if help key
CMP AL,02F ; is the key in the divide-by-2 range?
JB >L2 ; jump if it is
MOV CL,3 ; key is in the divide-by-3 range: load divisor 3
MOV AH,0 ; extend keycode AL to AX
DIV CL ; divide by 3
ADD AL,088 ; add offset so that 2F,32,35,... becomes 97,98,99,...
CMP AL,097
IF E MOV AL,0A1
RET

L2: ; key code is in the divide-by-2 range
SHR AX,1 ; shift in low bit of AH: now 13,15,17... becomes 89,8A,8B...
RET


DEC_BELL: ; ring the bell on a DEC RAINBOW
PUSH DI,ES ; save registers
MOV AL,7 ; code 7 is BELL
MOV DI,0 ; function code for OUTPUT_AL
INT 24 ; output the bell code, to ring the bell
POP ES,DI ; restore trashed registers
RET


DEC_COPY: ; DEC RAINBOW 100 version of BIOS_COPY routine
PUSH BX,CX,SI,BP ; save registers across call
MOV AX,DI ; fetch starting output pointer
ADD AX,CX ; add in the number of characters
ADD AX,CX ; add twice, to reflect the output of words not bytes
PUSH AX ; simulated beyond-output is saved for return
MOV BP,DS ; Segment address in BP for function 14
CALL DEC_CONV_VIDEO ; convert DI from D86 value to line BL column BH
MOV AX,2 ; Set transfer type 2 = characters only
CALL DATA_TO_SCREEN ; Send data to screen
POP DI,BP,SI,CX,BX ; Restore registers
RET


DEC_ATTR: ; copy single attribute AL to screen at ES:DI
PUSH AX ; push the attribute byte AL onto the stack
CALL DEC_CONV_VIDEO ; Convert DI to line/column
MOV AX,1 ; Set transfer type 1 = attrib only
MOV CX,AX ; Transfer 1 character
MOV DX,SP ; Point to attribute byte
MOV BP,SS ; Segment address in BP
CALL DATA_TO_SCREEN ; send the attribute to the screen
POP AX ; pop attribute byte back off of stack
RET


; DATA_TO_SCREEN copies CX characters (no more than 80) from memory to the
; screen at column BH (1--80) line BL (1--24). Input AX tells whether to
; copy attributes from BP=DS:DX (AX=1), characters from DS:SI (AX=2) or both
; (AX=0).

DATA_TO_SCREEN:
#if IBMSIM
PUSH ES,DX,SI
CS MOV ES,VIDEO_SEG
ADD AX,AX
PUSH AX
MOV AL,BL
DEC AX
MOV AH,80
MUL AH
MOV BL,BH
DEC BX
MOV BH,0
ADD BX,AX
ADD BX,BX
MOV DI,BX
POP BX
CS CALL >L4[BX]
POP SI,DX,ES
RET

L4:
DW >L0,>L1,>L2

L0:
PUSH DI
CALL >L2
POP DI
L1:
XCHG SI,DX
L5:
INC DI
MOVSB
LOOP L5
XCHG DX,SI
RET

L2:
MOVSB
INC DI
LOOP L2
RET

#else
MOV DI,8 ; function number for DISABLE CURSOR
INT 24 ; call the DEC BIOS to disable the cursor
MOV DI,014 ; function number for WRITE TO SCREEN
INT 24 ; call the DEC BIOS to write to the screen
MOV DI,0A ; function number for ENABLE CURSOR
INT 24 ; call the DEC BIOS to enable the cursor
RET
#endif



; DEC_CONV_VIDEO converts the D86 video memory address in DI to line BL (1-24)
; and column BH (1-80)

DEC_CONV_VIDEO:
XCHG AX,DI ; swap the D86 address in AX
SHR AX,1 ; convert words to bytes
MOV BL,80 ; load the number of characters in a line
DIV BL ; compute column number AH, line number AL
MOV BX,0101 ; load offsets to convert first numbers from 0 to 1
ADD BX,AX ; add in the coordinates, for return in BH and BL
RET





  3 Responses to “Category : Assembly Language Source Code
Archive   : D86BIOS4.ZIP
Filename : ZBIOS1.8

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/