home *** CD-ROM | disk | FTP | other *** search
- ;---------------
- ; BIOS module for the D86 debugger
- ;---------------
-
- ; Copyright 1987,88 Eric Isaacson. All rights reserved. Permission to
- ; copy and use this module is granted ONLY for machines registered for both
- ; the A86 assembler and the D86 debugger.
-
- ; Current support: IBM-PC, Wang PC, TI-PC, Sanyo 555, Tandy 2000,
- ; and Sirius/Victor 9000, DEC RAINBOW, and Zenith Z-100.
-
- ; This module defines the BIOS interface for my D86 debugger. I am publishing
- ; it to assist those who wish to assist me in implementing D86 on machines not
- ; BIOS-compatible with the IBM-PC. To support a non-standard BIOS, we must
- ; provide new keyboard codes, new action routines, and several other data
- ; quantities. This module provides a routine BIOS_INIT that sets everything
- ; up according to the machine being used. BIOS_INIT must do four things:
- ;
- ; 1. The routine must figure out what machine we are running on. The best
- ; way to do this is to find a machine-specific identifier in a fixed
- ; area of memory (ROM or the BIOS). If you can locate such an identifier,
- ; you can simply create an entry in the BIOS_SIGS structure below.
- ;
- ; 2. The routine must point SI to a special data structure (which I'll
- ; describe shortly), then call the routine NEW_KEYS, to propagate the
- ; items in the structure to the necessary places throughout the debugger.
- ;
- ; 3. The routine must perform any initializations necessary for this BIOS.
- ; For example, WANG_CONFIG locates and stores the port number for hardware
- ; that enables video access on the Wang.
- ;
- ; 4. The routine must decide if the debugger is running on the same screen as
- ; the user program. If it is, it must move the user's cursor to the lower
- ; left corner of the screen.
- ;
- ; The structure fed to NEW_KEYS contains all the data necessary for ongoing
- ; debugger execution under the new BIOS. See the structure WANG_KEYS for a
- ; prototype. The structure consists of the following:
- ;
- ; * a byte giving the keyboard code for the debugger's HELP key.
- ;
- ; * a byte declaring the difference between your BIOS's key codes for
- ; function keys, and the IBM BIOS's key codes. Your BIOS_KEY must return
- ; consecutive values for the function keys F1 through F10. You should
- ; declare this byte to be X - FUNC, where X is one less than the code
- ; returned by the F1 key. For example, since the Wang F1 key returns hex
- ; 080, the byte is declared 07F - FUNC.
-
- ; * a number of bytes giving code values for all the other control keys
- ; used by the debugger. This list will be expanding with new versions;
- ; see WANG_KEYS for the current version's list. You should precede the list
- ; with the L1 label, and follow it with the declaration N_CONTROL_KEYS EQU
- ; $-L1, exactly as shown. Don't change the name N_CONTROL_KEYS; the
- ; redeclaration of the same name insures that you've gotten the right number
- ; of codes into the table.
- ;
- ; * a word pointing to a message string with the name of the help-key. If your
- ; keyboard has a key labelled HELP, use the name HELP_HELP as in WANG_KEYS.
- ; If there is another key nonexistent on the IBM-PC (e.g. F11), then put
- ; a new name (e.g. F11_HELP) following DW; I'll supply the definition for
- ; the new name. If there is no extra key and no HELP key, use Alt-F10 as
- ; on the IBM-PC, and declare DW ALTF10_HELP here.
- ;
- ; * the label L2: to be used to verify the number of following bytes.
- ;
- ; * pointers to your BIOS's versions of the procedures VID_COPY, VID_ATTR,
- ; VID_FIX, BIOS_BELL, and BIOS_KEY, described shortly. Substitute the name
- ; of your machine for VID and BIOS in the generic names; e.g. the WANG_KEYS
- ; structure has WANG_COPY, WANG_ATTR, WANG_BELL, and WANG_KEY.
- ;
- ; * a word giving the segment register value for video memory on your machine.
- ; The debugger will supply this value in the ES register when it calls
- ; VID_COPY and VID_ATTR. That is all the debugger does with it; so this
- ; value can really be anything that the BIOS's versions of VID_COPY and
- ; VID_ATTR want.
- ;
- ; * a byte giving the attribute value for normal video. This attribute will
- ; be in effect for the entire debugger screen, except for the location of
- ; the debugger's cursor.
- ;
- ; * a byte giving the attribute value for reverse video. This attribute will
- ; be used to mark the debugger cursor.
- ;
- ; * the declaration N_BIOS_CALLS EQU ($-L2)/2 Again, don't change the name;
- ; the redeclaration of the name insures you didn't leave anything out.
- ;
- ; This completes the description of the structure fed to NEW_KEYS. After
- ; BIOS_INIT is called, the debugger will keep calling 7 action routines to
- ; perform its interactive I/O. The routines must perform actions as
- ; follows:
-
- ; VID_COPY copies CL bytes of characters from DS:SI to the video memory whose
- ; location is given by ES:DI. The characters should have the attribute
- ; NORM_ATTR, which the caller will place into AH for VID_COPY's convenience.
- ; VID_COPY must place the character byte and the attribute byte into each
- ; output video word. VID_COPY must return with BL preserved, the high byte
- ; of SI preserved (it will be if you leave SI pointing beyond the bytes
- ; copied), and DI advanced beyond the video memory just output. The caller
- ; assumes that video memory can be found at the value of VIDEO_SEG set by
- ; BIOS_INIT, starting at offset 0, and proceeding consecutively, one 16-bit
- ; memory word for every character. The caller will set CH=0 for its first
- ; call, so that VID_COPY can use CX as the count; but if it does, it must
- ; return CH=0 for subsequent calls.
-
- ; VID_ATTR places the attribute byte AL into the video word whose location is
- ; given by ES:DI. The character byte of the video word must not be disturbed.
-
- ; VID_FIX restores a video screen that might have been clobbered by programs
- ; external to the debugger. If VID_COPY copies all characters to video memory
- ; every time, then VID_FIX should RET without doing anything. If, however,
- ; VID_COPY tries to keep track of which characters are already on the screen,
- ; and suppress video output for those that are, then VID_FIX should disable
- ; the suppression feature, call the debugger's routine REFRESH to update the
- ; whole screen, then re-enable the suppression feature.
-
- ; BIOS_BELL rings the bell. NOTE that it is not acceptible for BIOS_BELL to
- ; use the MS-DOS write routine to send a bell control-code to standard output;
- ; if it did, then the debugger couldn't debug programs that have redirected
- ; their standard output-- the bell code would go to the user program's output
- ; file, and not be translated into a beep.
-
- ; BIOS_KEY returns in AL a code for a single keystroke. The code should be
- ; compatible with the values placed into the debugger's function tables by
- ; BIOS_INIT. If there is no keystroke available, BIOS_KEY should wait until
- ; there is one. BIOS_KEY should return on each individual key, and not wait
- ; for any line-editing to take place.
-
- ; BIOS_SAVE saves whatever there is about the user program's BIOS state that
- ; might be clobbered by the debugger. Currently, the only such thing is
- ; the user's cursor position on the Sanyo. So on all machines but the Sanyo,
- ; this is a "do-nothing" routine.
-
- ; BIOS_RESTORE restores the BIOS state saved by BIOS_SAVE. Again, this routine
- ; does nothing except on the Sanyo, on which it restores the user cursor
- ; position, clobbered because D86 must use BIOS calls to write to the Sanyo
- ; screen.
-
-
- BIOS_SIGNATURE MACRO
- DB #1 ; case number for the machine being sought
- DB #NL-2 ; number of far pointers to look at
- DB >M2 ; length byte for the following string
- M1:
- DB #2 ; BIOS signature string we are looking for
- M2 EQU $-M1 ; we calculate the forward-reference length byte here
- #RX3L ; loop for remaining macro operands
- DD #X ; far pointers to each place where the string might be found
- #ER
- #EM
-
- BIOS_SIGS:
- BIOS_SIGNATURE 6,'Texas I',0F400:0A022
- BIOS_SIGNATURE 7,'Tandy' ,0FC00:002F ,0FC00:0032
- BIOS_SIGNATURE 10,'Rainbow',0FE00:0166 ,0FC00:03F2, 0FE00:0163
- BIOS_SIGNATURE 12, 0E9 ,040:0
- DB 0FF ; terminator byte
-
- L0: ; jump table for each type of machine
- DW IBM_MONO_CONFIG ; 1
- DW IBM_CGA_CONFIG ; 2
- DW IBM_EGA_CONFIG ; 3
- DW IBM_CONFIG ; 4
- DW WANG_CONFIG ; 5
- DW TIPC_CONFIG ; 6
- DW TANDY_CONFIG ; 7
- DW SANYO_CONFIG ; 8
- DW SIRIUS_CONFIG ; 9
- DW DEC_CONFIG ; 10
- dw ibm_mono_config
- ; DW HP_CONFIG ; 11
- DW Z100_CONFIG ; 12
- L6 EQU ($-L0)/2
-
- L2: ; machine type AL is not 1
- CMP AL,0FF ; is it 0FF?
- JNZ >L7 ; jump if not -- we are on an IBM-PC
- MOV ES,AX,0FFFF ; it was-- address the end of ROM
- ES CMP AX,[6] ; are there FFFF's beyond the boot-JMP?
- MOV AL,8 ; load Sanyo index, in case there were
- JE >L1 ; jump if there were-- it is a Sanyo
- L7: ; all non-IBM tests fail: let's assume IBM compatibility
- MOV ES,CS ; point ES to CS, where IBM_CONFIG wants it
- MOV DH,0 ; the case number is zero-- no EGA vs. CGA decided yet
- JMP IBM_CONFIG ; jump to IBM-compatible configuration code
-
- BIOS_INIT:
- MOV DS,CS ; insure that DS points to our code segment
- MOV AL,SWITCH'B' ; fetch the BIOS switch setting if there was one
- DEC AX ; eliminate 0 setting from consideration
- CMP AL,L6 ; was there an explicit BIOS switch setting?
- JB >L5 ; jump if there was, to the matching case
- MOV SI,BIOS_SIGS ; point to the BIOS-signatures data structure
- LODSW ; fetch the first case number and far-pointer-count
- L3: ; loop here for each subsequent machine's record
- XCHG DX,AX ; swap the case number to DL, pointers count to DH
- LODSB ; fetch the length byte
- CBW ; extend the length AL to AX
- XCHG CX,AX ; swap the length into CX
- MOV BX,SI ; save the string pointer in BX
- ADD SI,CX ; advance SI beyond the string, to the far pointers
- L8: ; loop here for each far pointer
- LODSW ; fetch the offset of the pointer
- XCHG DI,AX ; swap the offset into DI
- LODSW ; fetch the segment of the pointer
- MOV ES,AX ; move the segment into ES
- XCHG BX,SI ; swap the string pointer into SI
- PUSH CX,SI ; save the count
- REPE CMPSB ; see if the string is at this far pointer
- POP SI,CX ; restore the count
- XCHG SI,BX ; swap string pointer to BX, template pointer to SI
- MOV AL,DL ; fetch the case number in case the string matched
- JE >L1 ; jump if the string matched to act upon the case
- DEC DH ; count down far pointers
- JNZ L8 ; loop if there is another far pointer
- LODSW ; fetch the next record's case number and pointers count
- CMP AL,0FF ; did we load the terminator byte instead?
- JNE L3 ; loop if not, to process the next machine record
- MOV AL,0 ; no string match: load the machine type, already plugged in
- MACHINE_TYPE EQU B[$-1]
- CMP AL,1 ; is it a Wang?
- JNE L2 ; jump if not
- MOV AL,5 ; load index for Wang
- L1: ; we will jump to case number AL
- DEC AX ; decrement so the first case is 0 not 1
- L5:
- CBW ; extend the case number from AL into AX
- MOV DH,AL ; save the case number in DH
- ADD AX,AX ; double the case number, to address a word pointer
- XCHG BX,AX ; swap the index into BX, for addressing
- MOV ES,CS ; restore ES=CS, for the benefit of the case code
- JMP L0[BX] ; jump to the appropriate case for this machine
-
-
- ; IBM_CONFIG is the BIOS_INIT routine for the IBM-PC. Since its NEW_KEY
- ; values are the defaults, we do not need to call NEW_KEY.
-
- IBM_MONO_CONFIG:
- IBM_CGA_CONFIG:
- IBM_EGA_CONFIG:
- IBM_CONFIG:
- MOV AH,15 ; function number for GET_VIDEO_MODE
- INT 16 ; call the BIOS to get the mode
- CMP AL,7 ; are we in monochrome mode?
- MOV AX,0B000 ; load monochrome map location in case yes
- IF B MOV AH,0B8 ; if not then load color map location
- MOV BL,0 ; initial BL set for non-screen-swapping
- TEST B SWITCH'V',1 ; is the V flag set?
- IF NZ MOV BL,8 ; if it is then we will swap screens
- XOR AH,BL ; switch interfaces if we saw a +V in invocation
- MOV VIDEO_SEG,AX ; store the location of physical video
- TEST AH,8 ; are we on a CGA or EGA video board?
- JZ >L1 ; skip if not
- CMP DH,1 ; have we already selected which, via the B case?
- JAE >L5 ; skip if we have
- PUSH BX ; we haven't selected CGA vs. EGA: save BX
- MOV AH,012 ; BIOS function code for GET_EGA_STATUS
- MOV BL,010 ; load an impossible status
- INT 16 ; set BL to the EGA status
- CMP BL,010 ; was there an EGA status?
- POP BX ; restore clobbered register
- L5: ; NE is set if we have an EGA
- MOV AX,EGA_ATTRS ; load EGA attributes in case we do have an EGA
- JNE >L2 ; jump if we do have an EGA
- MOV AX,CGA_ATTRS ; not an EGA: load CGA attributes
- TEST B SWITCH'F',1 ; is the FAST switch set?
- JNZ >L2 ; skip if it is
- MOV VID_COPY,COLOR_COPY ; CGA and no FAST switch: change copy routine
- MOV BIOS_RESTORE,COLOR_RESTORE ; activate the screen-restore function
- L2:
- MOV ATTR_BYTES,AX ; set the attribute bytes to AL and AH
- L1:
- TEST BL ; are we the same screen as the user program?
- JNZ RET ; return if we are not-- no need to move cursor
- SET_IBM_LOW_LEFT:
- MOV BH,0 ; page number is zero
- MOV DX,24 BY 0 ; we will move the cursor to row 24, column 0
- SET_IBM_CURSOR:
- MOV AH,2 ; video BIOS function number for SET CURSOR POSITION
- INT 16 ; call the BIOS to put user cursor in lower left corner
- RET
-
-
- ; IBM_FIX performs a fixup of a trashed screen on an IBM machine.
-
- ; COLOR_RESTORE checks to see if the debugger screen has been trashed. If it
- ; has, we restore the screen.
-
- COLOR_RESTORE:
- PUSH DS ; save register across call
- MOV DS,AX,0B800 ; point DS to the video screen
- MOV DX,03DA ; load the port number for reading the video status
- L2: ; loop here to wait for vertical retrace
- IN AL,DX ; input the status
- TEST AL,1 ; mask the retrace bit
- JZ L2 ; loop if we are not in vertical retrace
- CMP B[2400],'A' ; check the "A" of the fixed "AX" display
- POP DS ; restore clobbered register
- JE RET ; return if the "A" has not rolled away or been trashed
- IBM_FIX:
- CS PUSH VID_COPY ; save the old VID_COPY value
- CS MOV VID_COPY,MONO_COPY ; coerce it to MONO_COPY, to blindly copy all
- CALL REFRESH ; refresh the screen; let the snow scatter!
- CS POP VID_COPY ; restore the old VID_COPY value
- IBM_SAVE:
- IBM_RESTORE:
- RET
-
-
- ; MONO_COPY is the VID_COPY routine for an IBM monochrome video board. The
- ; characters occupy the lower byte of the DI-pointed words. We can afford
- ; to rewrite the entire screen on each refresh; so no special action needs to
- ; be taken. We do complicated looping to make the routine as fast as
- ; possible.
-
- MONO_COPY:
- SHR CX,1 ; is the character count odd?
- JC >L5 ; jump if yes, to special code
- L1:
- SHR CX,1 ; is the character count a multiple of 4?
- JC >L6 ; jump if not, to special code
- L2: ; loop here to copy every 4 bytes
- LODSB ; load the character from the source
- STOSW ; output the character, with the standard attribute byte
- LODSB ; char # 2
- STOSW
- LODSB ; char # 3
- STOSW
- LODSB ; char # 4
- STOSW
- LOOP L2 ; loop for the next 4 characters
- RET
-
- L5: ; the character count was odd
- MOVSB ; copy the odd character to the video buffer
- INC DI ; advance beyond the attribute byte
- JCXZ RET ; return if count is depleted
- JMP L1 ; join even code
-
- L6: ; the character count is 2 mod 4
- LODSB ; load one character
- STOSW ; output it and the attribute-- count now 1 mod 4
- LODSB ; load second character
- STOSW ; output it-- count now 0 mod 4
- JCXZ RET ; return if count is depleted
- JMP L2 ; join multiple-of-4 code
-
-
- ; COLOR_COPY is the VID_COPY routine for an IBM Color Graphics Adapter board.
- ; The characters occupy the lower byte of the DI-pointed words. We must wait
- ; for vertical retrace to output our data, to avoid annying "snow" on the
- ; screen. So we can't afford to output the entire buffer every time. So we
- ; maintain at [SI+81] a copy of what's already on the screen for [SI], and we
- ; output only if the buffer is new.
-
- COLOR_COPY:
- PUSH BX ; preserve BX across the call
- MOV DX,03DA ; load the port number for reading the video status
- SKIP2 ; skip to the LODSB instruction
- L0: ; loop here for every character that is already out there
- INC DI ; advance the output pointer beyond the character
- L1: ; loop here after a non-matching character was stored
- INC DI ; advance beyond the following attribute byte
- 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 L0 ; loop if it is
- JE >L4 ; jump if the characters are exhausted
- L2: ; loop here to wait for vertical retrace
- IN AL,DX ; input the status
- TEST AL,1 ; mask the retrace bit
- JZ L2 ; loop if we are not in vertical retrace
- MOV AL,BL ; re-fetch the character to be output
- STOSB ; output the character
- INC CX ; undo the previous LOOPE's decrement of CX
- LOOP L1 ; loop to check for another output character
- INC DI ; advance beyond the attribute byte of the last character
- POP BX ; restore clobbered register
- RET
-
- L4: ; matching character was the last in the buffer
- INC DI,2 ; advance beyond the output video word
- POP BX ; restore clobbered register
- RET
-
-
- ; IBM_ATTR is the VID_ATTR routine for IBM-PC compatible computers. The
- ; attribute byte is the high byte of the DI-pointed video word.
-
- IBM_ATTR:
- INC DI ; advance to the high, attribute byte
- STOSB ; output the attribute code AL to the byte
- RET
-
-
- ; IBM_KEY is the BIOS_KEY routine for IBM_PC compatible computers. We must
- ; transform the two-byte code returned by the IBM BIOS into the single
- ; code AL expected by the rest of the debugger.
-
- IBM_KEY:
- MOV AH,0 ; function code for GET KEY
- INT 016 ; get the keystroke from the IBM 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
-
-
- ; IBM_BELL is the BIOS_BELL routine for IBM-PC compatible computers. We
- ; output the code 07 to the BIOS's console output routine.
-
- IBM_BELL:
- MOV AX,0E07 ; AH= console out function number; AL="BELL" control code
- INT 010 ; output BELL to the console
- RET
-
-
- ; NEW_KEYS reassigns the keyboard codes and the action routines for a non-
- ; IBM-compatible BIOS. We are called with CS:SI pointing to a table of
- ; various new values, whose format is identical to the one given by
- ; WANG_KEYS below. The new values are plugged into the various tables
- ; in the debugger, so that correct actions are taken for the non-compatible
- ; machine.
-
- NEW_KEYS:
- LODSB ; load the first byte of the table
- MOV HELP_KEY,AL ; first byte is the code for HELP_KEY
- LODSB ; load the second byte
- ADD SWITCH_KEY,AL ; byte 2 is (new-IBM) function-key-codes-difference
- MOV DI,CTRL_JUMPS+2 ; point to the control-jumps table
- MOV CX,N_FUNCS ; load the number of function-keys in that table
- L1: ; loop here to adjust each function-key code
- ADD [DI],AL ; add the code into the table entry
- ADD DI,3 ; advance to the next table entry
- LOOP L1 ; loop to adjust the next table entry
- MOV CL,N_CONTROL_KEYS ; load the number of subsequent keys in the table
- L2: ; loop here to plug in the new value for each key
- MOVSB ; copy the new key code to the function table
- INC DI,2 ; advance output pointer to the next key code
- LOOP L2 ; loop to plug in the next key code
- LODSW ; fetch the message-pointer to the name of HELP key
- MOV HELP_MSG,AX ; plug the pointer into the messages-string
- MOV DI,BIOS_CALLS ; point to the table of action routines
- MOV CX,N_BIOS_CALLS ; load the count of words in action-routine-table
- REP MOVSW ; copy the new pointers to the table
- RET
-
-
- ; GET_MACHINE_TYPE sets the variables MACHINE_TYPE and SUBDIR_CHAR.
-
- GET_MACHINE_TYPE:
- MOV AH,030 ; MS-DOS function number for GET_DOS_VERSION
- INT 33 ; we call this to get the machine number in BH
- MOV MACHINE_TYPE,BH
- DEC BH ; are we on a Wang PC?
- IF Z MOV SUBDIR_CHAR,'/'; if yes then switch the subdirectory character
- RET
-
-
-