1903 lines
67 KiB
NASM
1903 lines
67 KiB
NASM
; =====> REALIO.ASM
|
||
;*****************************************************
|
||
;* TIPC Scheme Runtime Support *
|
||
;* Real Mode I/O Routines *
|
||
;* *
|
||
;* (C) Copyright 1985 by Texas *
|
||
;* Instruments Incorporated. *
|
||
;* All rights reserved. *
|
||
;* *
|
||
;* Date Written: November 1987 (tc) *
|
||
;* Last Modification: *
|
||
;*****************************************************
|
||
include schemed.equ ;for port defs
|
||
include screen.equ
|
||
.286c
|
||
;
|
||
; Local equates
|
||
;
|
||
|
||
RETURN equ 0Dh ; Carriage Return Character
|
||
LINEFEED equ 0Ah ; Line Feed Character
|
||
DOS equ 021h ; Dos function request
|
||
WRITEFILE equ 040h ; Write Fiel function request
|
||
DISK_FULL equ -1 ; Disk full error designator
|
||
|
||
TIPC equ 1 ; Designates machine type as TIPC
|
||
|
||
TI_CRT equ 049h
|
||
IBM_CRT equ 010h
|
||
|
||
;
|
||
; Segment Definitions
|
||
;
|
||
|
||
PGROUP group PROG
|
||
DGROUP group DATA
|
||
|
||
; This stack is used for the standard XLI interface. However, a different
|
||
; stack (i.e. PCS's) is used during calls to a graphics driver.
|
||
STACK segment word stack 'STACK'
|
||
stackstart = $
|
||
dw 16 dup (?)
|
||
stacksize = $ - stackstart
|
||
STACK ends
|
||
|
||
;
|
||
; Data definitions
|
||
;
|
||
DATA segment byte public 'DATA'
|
||
assume DS:DGROUP
|
||
datastart = $
|
||
|
||
callers_ds dw ?
|
||
callers_es dw ?
|
||
|
||
;-----------------------------------------------------------------------------
|
||
; Type/Monitor info
|
||
;-----------------------------------------------------------------------------
|
||
PC_MAKE dw 0
|
||
VID_MODE dw 3
|
||
MAX_ROWS db DEFAULT_NUM_ROWS
|
||
MAX_COLS db DEFAULT_NUM_COLS
|
||
CHAR_HGT dw 8
|
||
|
||
;-----------------------------------------------------------------------------
|
||
; Jump table for handler based on op_code
|
||
;-----------------------------------------------------------------------------
|
||
OP_CODE dw BELL ; 0 - Sound Bell
|
||
dw CLEAR ; 1 - Clear Screen
|
||
dw BORDER ; 2 - Draw Border
|
||
dw SAVE_SCR ; 3 - Save Screen
|
||
dw REST_SCR ; 4 - Restore Screen
|
||
dw ? ; 5 - was turn cursor on
|
||
dw ? ; 6 - was turn cursor off
|
||
dw ? ; 7 - was position cursor
|
||
dw PUTCHAR ; 8 - Put Character on screen
|
||
dw SCROLLUP ; 9 - Scroll Screen Up 1 Line
|
||
dw SCROLLDN ; 10 - Scroll Screen Dn 1 Line
|
||
dw ? ; 11 - was ega cursor emulation
|
||
dw CHGMODE ; 12 - Note Change to Video Mode
|
||
dw WSTRING ; 13 - Write string to output port
|
||
dw WBLOCK ; 14 - Write string to display
|
||
table_len equ $ - OP_CODE
|
||
|
||
;-----------------------------------------------------------------------------
|
||
; XLI Setup
|
||
;-----------------------------------------------------------------------------
|
||
;;; ----- Equates -----
|
||
; offsets into the PSP
|
||
term_addr equ 0Ah
|
||
fb_addr equ 5Ch
|
||
;;; ----- Data structures -----
|
||
; file block
|
||
file_block label word
|
||
dw 4252h
|
||
dw 10011b ;flags = sysint,0,0,16-bit,near
|
||
dw offset lookup_table, seg lookup_table
|
||
dw offset parm_block, seg parm_block
|
||
; reserved area of file block
|
||
dw 100h ;sysint# (256=%graphics)
|
||
dw offset handler, seg handler ;ISR entry point
|
||
dw 0,0,0,0,0
|
||
; parameter block
|
||
parm_block label word ;not used
|
||
dw 0
|
||
; lookup table
|
||
lookup_table label word
|
||
db '//' ;not used
|
||
; other needed values
|
||
psp dw ? ;PSP segment address
|
||
psize dw ? ;size of program in paragraphs
|
||
xwait dw 2 dup (?) ;XLI wait address
|
||
xbye dw 2 dup (?) ;XLI bye address
|
||
|
||
; ___ __ __
|
||
; + -| |- _|_ | -- | __| |__ | | (extra)
|
||
map_tab db 0c5h,0b4h,0c3h,0c1h,0c2h,0c4h,0b3h,0d9h,0c0h,0bfh,0dah,0dah
|
||
map_tabx equ $
|
||
|
||
trns_tab db 0dah,0c2h,0c3h,0c5h,0c3h,0c2h,0c2h,0c5h,0c3h,0c5h,0c5h
|
||
db 0c2h,0bfh,0c5h,0b4h,0b4h,0c2h,0c2h,0c5h,0c5h,0b4h,0c5h
|
||
db 0c3h,0c5h,0c0h,0c1h,0c3h,0c1h,0c5h,0c1h,0c3h,0c5h,0c5h
|
||
db 0c5h,0b4h,0c1h,0d9h,0b4h,0c1h,0c5h,0c1h,0c5h,0b4h,0c5h
|
||
db 0c3h,0b4h,0c3h,0b4h,0b3h,0c5h,0c5h,0c5h,0c3h,0b4h,0c5h
|
||
db 0c2h,0c2h,0c1h,0c1h,0c5h,0c4h,0c2h,0c1h,0c5h,0c5h,0c5h
|
||
|
||
m14_attr equ $
|
||
;33-60 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; <
|
||
db 1,0,2,2,1,4,2,0,0,3,3,7,3,5,6,2,6,6,5,3,5,2,1,2,2,1,7,3
|
||
|
||
;61-88 = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X
|
||
db 2,6,1,2,2,0,3,0,0,0,3,1,0,4,0,0,1,1,3,0,3,0,2,0,1,3,1,1
|
||
|
||
;89-116 Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t
|
||
db 0,1,0,0,0,3,7,1,5,0,3,4,3,3,3,0,6,6,0,0,2,2,3,2,3,2,3,2
|
||
|
||
;117-126 u v w x y z { | } ~
|
||
db 2,3,3,2,2,2,3,1,0,1
|
||
|
||
;127-191
|
||
db 64 dup (0)
|
||
|
||
;192-197
|
||
db 5,2,0,0,0,4
|
||
|
||
;198-218
|
||
db 20 dup (0)
|
||
;219-220
|
||
db 2,5
|
||
|
||
m16_attr equ $
|
||
;33-60 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; <
|
||
db 3,1,4,4,4,7,4,2,2,6,6,11,6,9,9,4,10,10,9,6,9,4,2,4,4,3,10,6
|
||
|
||
;61-88 = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X
|
||
db 5,10,3,4,5,2,5,2,2,2,5,2,2,8,2,2,2,2,5,2,5,2,4,2,2,5,2,2
|
||
|
||
;89-116 Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t
|
||
db 2,2,2,2,2,3,12,2,9,2,6,7,6,6,6,2,10,11,2,2,5,5,6,5,6,5,6,4
|
||
|
||
;117-126 u v w x y z { | } ~
|
||
db 5,5,5,5,5,5,6,2,2,3
|
||
db 64 dup (0)
|
||
db 7,2,0,0,0,7
|
||
db 20 dup (0)
|
||
db 2,7
|
||
|
||
public m18_attr
|
||
m18_attr equ $
|
||
;33-60 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; <
|
||
db 2,1,4,4,8,8,4,2,2,6,6,10,9,10,05,4,10,10,10,6,10,4,2,4,4,10,10,6
|
||
|
||
;61-88 = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X
|
||
db 9,06,2,4,4,2,6,2,2,2,6,2,2,8,2,2,2,2,6,2,6,2,4,2,2,6,2,2
|
||
|
||
;89-116 Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t
|
||
db 2,2,2,3,2,3,13,2,10,2,6,8,6,6,6,2,10,12,2,2,5,5,6,5,6,5,6,4
|
||
|
||
;117-126 u v w x y z { | } ~
|
||
db 5,6,6,5,5,5,6,2,2,2
|
||
db 64 dup (0)
|
||
db 10,4,0,0,0,8
|
||
db 20 dup (0)
|
||
db 8,8
|
||
|
||
;
|
||
; The following jump table is used wstring to handle control characters
|
||
; written to the screen.
|
||
;
|
||
wn_handle dw wwin_default ;00 - Null character
|
||
dw wwin_default ;01 -
|
||
dw wwin_default ;02 -
|
||
dw wwin_default ;03 -
|
||
dw wwin_default ;04 -
|
||
dw wwin_default ;05 -
|
||
dw wwin_default ;06 -
|
||
dw wwin_bell ;07 - Bell
|
||
dw wwin_backspace ;08 - Backspace
|
||
dw wwin_tab ;09 - Tab
|
||
dw wwin_linefeed ;0A - Linefeed
|
||
dw wwin_default ;0B -
|
||
dw wwin_default ;0C -
|
||
dw wwin_creturn ;0C - Carriage Return
|
||
|
||
;
|
||
; The following jump table is used by wstring to handle control characters
|
||
; written to disk.
|
||
;
|
||
ds_handle dw wfil_default ;00 - Null character
|
||
dw wfil_default ;01 -
|
||
dw wfil_default ;02 -
|
||
dw wfil_default ;03 -
|
||
dw wfil_default ;04 -
|
||
dw wfil_default ;05 -
|
||
dw wfil_default ;06 -
|
||
dw wfil_default ;07 -
|
||
dw wfil_backspace ;08 - Backspace
|
||
dw wfil_tab ;09 - Tab
|
||
dw wfil_newline ;0A - Linefeed
|
||
dw wfil_default ;0B -
|
||
dw wfil_default ;0C -
|
||
dw wfil_newline ;0D - Carriage Return
|
||
|
||
|
||
last_char db 0dbh
|
||
|
||
c_col dw 0
|
||
c_row dw 0
|
||
c_len dw 0
|
||
c_nrows dw 0
|
||
|
||
sav_di dw 0
|
||
|
||
datasize = $-datastart
|
||
DATA ends
|
||
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
PROG segment byte public 'PROG'
|
||
assume CS:PGROUP,DS:DGROUP
|
||
progstart = $
|
||
|
||
;-----------------------------------------------------------------------------
|
||
; name HANDLER -- Interface Handler to IO routines
|
||
;
|
||
; AX will contain error indicator (-1) if error encountered
|
||
;
|
||
hand_args struc
|
||
dw ? ; callers bp
|
||
dd ? ; return address (far)
|
||
opcode dw ? ; IO operation to perform
|
||
hand_args ends
|
||
|
||
public handler
|
||
handler proc far
|
||
mov BX,DS ; temp save caller's DS
|
||
mov AX,data
|
||
mov DS,AX ; establish local data segment
|
||
mov callers_ds,bx ; save callers data seg
|
||
mov callers_es,es ; and extra seg
|
||
mov ES,AX
|
||
; Load sub opcode
|
||
push bp
|
||
mov bp,sp
|
||
mov BX,[BP].opcode ; load operation code
|
||
pop bp
|
||
add BX,BX ; adjust for index into jump table
|
||
cmp BX,table_len ; bad op_code?
|
||
jae bad_op
|
||
|
||
; Jump desired IO handler
|
||
call OP_CODE[BX]
|
||
jmp short hand_ret
|
||
|
||
bad_op: mov AX,-1
|
||
|
||
; Return to caller
|
||
hand_ret:
|
||
push callers_ds
|
||
pop ds ; restore caller's data seg
|
||
push callers_es
|
||
pop es ; restore caller's data seg
|
||
ret ; return to caller
|
||
handler endp
|
||
|
||
|
||
;************************************************************************
|
||
;* Generate a Bell Character *
|
||
;* *
|
||
;* Purpose: To generate a "bell character" (i.e., make a noise) to *
|
||
;* simulate the effect of outputting a bell character *
|
||
;* (control-G) in the output stream. *
|
||
;* *
|
||
;* Calling Sequence: zbell(); *
|
||
;* *
|
||
;* Input Parameters: None. *
|
||
;* *
|
||
;* Output Parameters: None. *
|
||
;* *
|
||
;************************************************************************
|
||
public bell
|
||
bell proc near
|
||
cmp PC_MAKE,TIPC ; If not tipc
|
||
jne zbmbell ; then jump
|
||
zbwait: mov AH,1 ; Get speaker status
|
||
int 48h
|
||
jnz zbwait ; wait for bell to turn off
|
||
mov AH,2 ; Set speaker frequency
|
||
mov CX,1563 ; Value for 1.25MHz/800Hz (system beep)
|
||
int 48h
|
||
mov AX,000Ah ; Turn speaker on for AL*25-ms. 0Ah = .25-sec
|
||
int 48h
|
||
xor ax,ax
|
||
ret ; return to caller
|
||
;
|
||
zbmbell: mov BX,080h ; ****Copied from IBM-PC/XT BIOS listing****
|
||
in AL,61h
|
||
push AX ; Save
|
||
beep_cycle: and AL,0FCh ; Turn off timer gate and speaker data
|
||
out 61h,AL ; output to control
|
||
mov CX,48h ; Half cycle time for TONE
|
||
here: loop here ; speaker off
|
||
or AL,2 ; Turn speaker on
|
||
out 61h,AL
|
||
mov CX,48h
|
||
here2: loop here2
|
||
dec BX ; Decrease cycle count
|
||
jnz beep_cycle
|
||
pop AX
|
||
out 61h,AL
|
||
xor ax,ax
|
||
ret
|
||
bell endp
|
||
|
||
;************************************************************************
|
||
;* Clear a Window *
|
||
;************************************************************************
|
||
cl_args struc
|
||
dw ? ; caller's BP
|
||
dw ? ; return address
|
||
dd ? ; caller's return address
|
||
cl_op dw ? ; clear window op code
|
||
cl_row dw ? ; upper left hand corner row number
|
||
cl_col dw ? ; upper left hand corner column number
|
||
cl_nrows dw ? ; number of rows
|
||
cl_len dw ? ; line length (number of characters)
|
||
cl_attrib dw ? ; character attributes
|
||
cl_args ends
|
||
|
||
public clear
|
||
clear proc near
|
||
push BP ; save caller's BP
|
||
mov BP,SP
|
||
; Put cursor at beginning of next row
|
||
c_loop: mov DL,byte ptr [BP].cl_row ; load current row number
|
||
mov DH,byte ptr [BP].cl_col ; load starting column number
|
||
xor BH,BH ; page number (0 if in graphics mode)
|
||
mov AH,02H ; load "put cursor" code
|
||
call crt_dsr ; position the cursor
|
||
; Write line of blanks at current cursor position
|
||
mov AX,0920h ; load write char/attr code + blank (= 20h)
|
||
xor BH,BH ; (for IBM-PC BH=display page #)
|
||
mov BL,byte ptr [BP].cl_attrib ; load attribute flag
|
||
|
||
cmp vid_mode,14 ; IBM EGA modes?
|
||
jl c_01
|
||
cmp BL,87h ; attribute is rv white?
|
||
jne c_22
|
||
mov AX,09dbh ; use the block character not the blank
|
||
and BL,7fh ; strip off the xor bit
|
||
|
||
c_01: mov CX,[BP].cl_len ; load number of times to write the blank
|
||
call crt_dsr ; perform the write
|
||
; Increment row number, decrement row count, test, loop
|
||
inc [BP].cl_row ; increment row number
|
||
dec [BP].cl_nrows ; decrement row count
|
||
jg c_loop ; if more rows, loop (jump)
|
||
; Return to caller
|
||
c_end: pop BP ; restore caller's BP
|
||
xor ax,ax ; return status
|
||
ret ; return
|
||
|
||
; clear out the line by writing directly to the graphics planes
|
||
c_22:
|
||
mov AX,[BP].cl_nrows
|
||
mov c_nrows,ax
|
||
mov AX,[BP].cl_row ; set AX to the row
|
||
mov c_row,AX
|
||
mov AX,[BP].cl_col ; add in the starting column
|
||
mov c_col,AX
|
||
mov AX,[BP].cl_len ; number of columns to blank
|
||
mov c_len,AX
|
||
call z_ega ; restore counter
|
||
|
||
jmp c_end ; return
|
||
|
||
clear endp
|
||
|
||
;************************************************************************
|
||
;* Draw Border *
|
||
;************************************************************************
|
||
b_args struc
|
||
dw ? ; caller's BP
|
||
dw ? ; return address
|
||
dd ? ; caller's return address
|
||
b_opcode dw ? ; border opcode
|
||
b_line dw ? ; upper left corner line number
|
||
b_col dw ? ; upper left corner column number
|
||
b_nlines dw ? ; number of lines
|
||
b_ncols dw ? ; number of columns
|
||
b_battr dw ? ; border attributes
|
||
b_label dw ? ; pointer to label text
|
||
b_args ends
|
||
|
||
public border
|
||
border proc near
|
||
;;; int 3
|
||
push BP ; save caller's BP
|
||
mov BP,SP
|
||
|
||
; output corners
|
||
mov BL,byte ptr [BP].b_battr ; load attribute bits
|
||
mov DH,byte ptr [BP].b_col ; load left column number
|
||
mov DL,byte ptr [BP].b_line ; load left line number
|
||
dec DL
|
||
dec DH
|
||
mov AL,0DAh ; load upper left corner character
|
||
call zcorner
|
||
inc DH
|
||
add DH,byte ptr [BP].b_ncols
|
||
mov AL,0BFh ; load upper right corner character
|
||
call zcorner
|
||
inc DL
|
||
add DL,byte ptr [BP].b_nlines
|
||
mov AL,0D9h ; load lower right corner character
|
||
call zcorner
|
||
dec DH
|
||
sub DH,byte ptr [BP].b_ncols
|
||
mov AL,0C0h ; load lower left corner character
|
||
call zcorner
|
||
|
||
; output sides
|
||
mov DH,byte ptr [BP].b_col ; reload upper left column number
|
||
mov DL,byte ptr [BP].b_line ; and line number
|
||
dec DH ; decrement column number
|
||
mov CX,[BP].b_nlines
|
||
call zside ; draw the left hand border
|
||
mov DH,byte ptr [BP].b_col ; reload upper left column number
|
||
mov DL,byte ptr [BP].b_line ; and line number
|
||
add DH,byte ptr [BP].b_ncols ; add in line length
|
||
mov CX,[BP].b_nlines
|
||
call zside ; draw the right hand border
|
||
|
||
; Output the top of the border
|
||
mov DL,byte ptr [BP].b_line ; load upper left row number
|
||
dec DL
|
||
jl z_no_top ; if row negative, skip write
|
||
mov DH,byte ptr [BP].b_col ; load upper left column number
|
||
mov CX,[BP].b_ncols
|
||
call ztop
|
||
; Put the label in the top left corner of the border, if it'll fit
|
||
mov BX,[BP].b_label ; get segment of label
|
||
cmp BX,0
|
||
je z_no_top ; jump, if NULL pointer
|
||
mov ES,BX
|
||
mov BX,0 ; ES:BX => label
|
||
mov DX,[BP].b_ncols ; load window width
|
||
xor CX,CX ; zero the character counter
|
||
b_loop: cmp byte ptr ES:[BX],0 ; end of string?
|
||
je b_eos ; if end of string, jump
|
||
inc CX ; increment the character count
|
||
inc BX ; increment the character string pointer
|
||
cmp CX,DX ; compare to window width
|
||
jl b_loop ; if label still shorter than window, loop
|
||
b_eos: jcxz z_no_top ; if no label, jump
|
||
push CX ; save label length
|
||
; Write the label
|
||
mov DL,byte ptr [BP].b_line ; load upper left row number
|
||
mov DH,byte ptr [BP].b_col ; load upper left column number
|
||
dec DL ; decrement row number
|
||
xor BH,BH ; IBMism (page 0 for text-mode)
|
||
mov AH,02h ; load "put cursor" code
|
||
call CRT_DSR ; put cursor in upper left corner of border
|
||
pop CX ; restore label's character count
|
||
cmp PC_MAKE,TIPC
|
||
jne ibm_cblk
|
||
mov AH,011h ; load "write block of characters" code
|
||
mov DX,ES ; load segment address
|
||
mov BX,0 ; load label offset
|
||
int TI_CRT ; write the label
|
||
jmp short z_no_top
|
||
;
|
||
ibm_cblk: mov AL,byte ptr [BP].b_col
|
||
add AL,CL
|
||
cmp AL,MAX_COLS
|
||
jle b_sml ; jump if label length is OK
|
||
sub AL,MAX_COLS
|
||
sub CL,AL ; force label to remain within 80-col screen
|
||
b_sml: mov DI,0 ; load label offset
|
||
lbl_loop: mov AH,0Eh ; Write ASCII Teletype
|
||
mov AL,byte ptr ES:[DI]
|
||
mov BL,byte ptr [BP].b_battr ; load attribute bits just in case
|
||
xor BH,BH ; page # for alpha mode
|
||
push CX
|
||
push DI
|
||
int IBM_CRT
|
||
pop DI
|
||
pop CX
|
||
inc DI
|
||
loop lbl_loop ; DECrement CX and jump if != 0
|
||
; Output the bottom of the border
|
||
z_no_top:
|
||
mov dx,ds
|
||
mov es,dx
|
||
mov BL,byte ptr [BP].b_battr ; load attribute bits
|
||
mov DL,byte ptr [BP].b_line
|
||
add DL,byte ptr [BP].b_nlines
|
||
mov DH,byte ptr [BP].b_col ; load upper left column number
|
||
mov CX,[BP].b_ncols
|
||
call ztop
|
||
|
||
; return to caller
|
||
pop BP ; restore caller's BP
|
||
xor ax,ax
|
||
ret ; return
|
||
border endp
|
||
|
||
;************************************************************************
|
||
;* Local Support: Draw a single character at cursor position *
|
||
;* *
|
||
;* Input Registers: AL - the character to be output *
|
||
;* BL - the character attributes for the write *
|
||
;* DH - column *
|
||
;* DL - row *
|
||
;* *
|
||
;* Registers Modified: AX,CX,SI,DI *
|
||
;************************************************************************
|
||
zcorner proc near ; draw a single corner character
|
||
cmp DH,MAX_COLS
|
||
jae zcornret
|
||
cmp DL,MAX_ROWS
|
||
jae zcornret
|
||
push DX ; save cursor coordinates
|
||
push AX ; save character to be output
|
||
xor BH,BH ; page number (=0 for graphics mode also)
|
||
mov AH,02h ; load "put cursor" code
|
||
call CRT_DSR ; position the cursor
|
||
; read the character in this screen position
|
||
; ** This is tricky 'cause DH/DL are correct but
|
||
; ** will be swapped back (to incorrect) by CRT_DSR proc
|
||
; ** if using an IBM!!!
|
||
cmp PC_MAKE,TIPC
|
||
je no_swap
|
||
xchg DH,DL
|
||
xor BH,BH ; IBM display page
|
||
no_swap: mov AH,08h
|
||
call CRT_DSR
|
||
; see if it's one of the borderline characters
|
||
call map_char
|
||
mov SI,AX
|
||
pop AX ; recover character to be output
|
||
cmp SI,0
|
||
jl zcornput
|
||
; map corner to border character
|
||
call map_char
|
||
mov DL,map_tabx-map_tab-1
|
||
mul DL
|
||
add SI,AX
|
||
mov AL,trns_tab+[SI]
|
||
; output the corner character
|
||
zcornput: mov AH,09h ; load "write character/attribute" code
|
||
mov CX,1 ; number of characters = 1
|
||
xor BH,BH ; Display page for IBM text mode (=0)
|
||
call CRT_DSR ; write it to the screen at cursor position
|
||
pop DX ; restore cursor coordinates
|
||
zcornret: ret ; return
|
||
zcorner endp
|
||
|
||
;************************************************************************
|
||
;* Local Support: Draw a border sides *
|
||
;* *
|
||
;* Input Registers: DH - column *
|
||
;* DL - row *
|
||
;* CX - number of rows *
|
||
;* *
|
||
;* Registers Modified: AX,CX,DL *
|
||
;************************************************************************
|
||
zside proc near
|
||
cmp DH,MAX_COLS ; is column within the CRT's boundaries?
|
||
jae zsideret ; if not, jump
|
||
zside_lp: mov AL,0B3h ; load "|" border character
|
||
push CX ; save line count
|
||
push DX ; save next cursor position
|
||
call zcorner ; output the border character
|
||
pop DX ; restore current cursor position
|
||
pop CX ; restore line counter
|
||
inc DL ; increment the row number
|
||
loop zside_lp ; loop until side is drawn
|
||
zsideret: ret
|
||
zside endp
|
||
|
||
;************************************************************************
|
||
;* Local Support: Draw a border - Top or Bottom *
|
||
;* *
|
||
;* Input Registers: DH - column *
|
||
;* DL - row *
|
||
;* CX - number of columns *
|
||
;* *
|
||
;* Registers Modified: AX,CX *
|
||
;************************************************************************
|
||
ztop proc near
|
||
cmp DL,MAX_ROWS ; is row within the CRT's boundaries?
|
||
jae ztopret ; if not, jump
|
||
ztop_lp: mov AL,0C4h ; load "-" border character
|
||
push CX ; save line count
|
||
push DX ; save next cursor position
|
||
call zcorner ; output the border character
|
||
pop DX ; restore current cursor position
|
||
pop CX ; restore line counter
|
||
inc DH ; increment the column number
|
||
loop ztop_lp ; loop until top/bottom is drawn
|
||
ztopret: ret
|
||
ztop endp
|
||
|
||
;************************************************************************
|
||
;* Local Support: return character mapping *
|
||
;* *
|
||
;* Input Registers: AL = character *
|
||
;* *
|
||
;* Registers Modified: CX,DI *
|
||
;************************************************************************
|
||
map_char proc near
|
||
mov CX,map_tabx-map_tab
|
||
mov DI,offset map_tab
|
||
repne scasb
|
||
mov AX,CX
|
||
dec AX
|
||
ret
|
||
map_char endp
|
||
|
||
;************************************************************************
|
||
;* Save Screen Contents *
|
||
;* *
|
||
;* Purpose: To save a rectangular region of the CRT in a string data *
|
||
;* object. *
|
||
;* *
|
||
;* Calling Sequence: save_scr(str_reg, ul_row, ul_col, n_rows, ncols) *
|
||
;* where str_reg - pointer to string data object *
|
||
;* which is to receive the screen *
|
||
;* contents *
|
||
;* ul_row - row number of the upper left *
|
||
;* corner of the region to be *
|
||
;* saved *
|
||
;* ul_col - column number of the upper left *
|
||
;* corner of the region to be *
|
||
;* saved *
|
||
;* n_rows - number of rows in the region to *
|
||
;* be saved *
|
||
;* n_cols - number of columns in the region *
|
||
;* to be saved *
|
||
;************************************************************************
|
||
sv_args struc
|
||
dw ? ; caller's BP
|
||
dw ? ; caller's ES
|
||
dw ? ; return address
|
||
dd ? ; caller's return address
|
||
sv_op dw ? ; save screen opcode
|
||
sv_str dw ? ; address of register pointing to string
|
||
sv_ulrow dw ? ; upper left hand corner's row number
|
||
sv_ulcol dw ? ; upper left hand corner's column number
|
||
sv_nrow dw ? ; number of rows
|
||
sv_ncol dw ? ; number of columns
|
||
sv_args ends
|
||
|
||
public save_scr
|
||
save_scr proc near
|
||
;;; int 3
|
||
push ES
|
||
push BP ; save the caller's BP register
|
||
mov BP,SP ; and establish local addressability
|
||
; create a pointer to the string object
|
||
;;; mov BX,[BP].sv_str ; load address of register
|
||
;;; mov DI,[BX].C_disp ; load the string
|
||
;;; mov BX,[BX].C_page ; pointer
|
||
;;; %LoadPage ES,BX ; load string page's paragraph address
|
||
;;; mov ES,pagetabl+[BX] ; load string page's paragraph address
|
||
;;; add DI,BLK_OVHD ; advance pointer past string header
|
||
|
||
mov ES,[BP].sv_str
|
||
xor DI,DI ;ES:DI => string
|
||
|
||
; store number of rows and columns into the first two bytes of the string
|
||
mov AL,byte ptr [BP].sv_nrow
|
||
stosb
|
||
mov AL,byte ptr [BP].sv_ncol
|
||
stosb
|
||
; adjust number of lines/columns for test conditions
|
||
mov AX,[BP].sv_ulrow
|
||
add [BP].sv_nrow,AX
|
||
mov AX,[BP].sv_ulcol
|
||
add [BP].sv_ncol,AX
|
||
; loop until all rows processed
|
||
mov DL,byte ptr [BP].sv_ulrow
|
||
rw_loop: mov DH,byte ptr [BP].sv_ulcol
|
||
; position cursor
|
||
cl_loop: push DX ; save current position
|
||
mov AH,02h ; load "put cursor" function id
|
||
xor BH,BH ; IBMism (page number for cursor)
|
||
call crt_dsr ; position the cursor
|
||
; read character/attributes at current screen position
|
||
mov AH,08h ; load "read char/attribute" function id
|
||
xor BH,BH ; IBMism (display page #)
|
||
call crt_dsr ; read said
|
||
;*******
|
||
cmp vid_mode,14
|
||
jl sav_01 ; not graphics modes
|
||
cmp AL,0 ; don't bother with attributes if nul
|
||
je sav_01
|
||
; cmp AL,07fh ; is it above the first 128 characters ?
|
||
; jno sav_00 ; no
|
||
cmp AL,0dah
|
||
jbe sav_00
|
||
; test AL,010h ; look for D0-DF
|
||
; je sav_00
|
||
xor AL,AL ; set to nul
|
||
jmp sav_01
|
||
sav_00: call graph_attr ; mode 14 and 16 attribute function
|
||
;******
|
||
sav_01: stosw ; store char/attr into output string
|
||
; increment column number, test, branch
|
||
pop DX
|
||
inc DH
|
||
cmp DH,byte ptr [BP].sv_ncol
|
||
jl cl_loop
|
||
; increment row number, test, branch
|
||
inc DL
|
||
cmp DL,byte ptr [BP].sv_nrow
|
||
jl rw_loop
|
||
|
||
; return to caller
|
||
pop BP
|
||
pop ES
|
||
xor ax,ax
|
||
ret ; return to caller
|
||
save_scr endp
|
||
|
||
;************************************************************************
|
||
;* Restore Screen Contents *
|
||
;* *
|
||
;* Purpose: To restore a rectangular region of the CRT from a string *
|
||
;* data object. *
|
||
;* *
|
||
;* Calling Sequence: rest_scr(str_reg, ul_row, ul_col) *
|
||
;* where str_reg - pointer to string data object *
|
||
;* which contains the screen *
|
||
;* contents *
|
||
;* ul_row - row number of the upper left *
|
||
;* corner of the region to be *
|
||
;* restored *
|
||
;* ul_col - column number of the upper left *
|
||
;* corner of the region to be *
|
||
;* restored *
|
||
;************************************************************************
|
||
rs_args struc
|
||
rs_nrow dw ? ; number of rows in saved data
|
||
rs_ncol dw ? ; number of columns in saved data
|
||
rs_BP dw ? ; caller's BP
|
||
dw ? ; caller's ES
|
||
dw ? ; return address
|
||
dd ? ; callers return address
|
||
rs_op dw ? ; restore screen opcode
|
||
rs_str dw ? ; segment address of string
|
||
rs_ulrow dw ? ; upper left hand corner's row number
|
||
rs_ulcol dw ? ; upper left hand corner's column number
|
||
rs_mrow dw ? ; number of rows in new window
|
||
rs_mcol dw ? ; number of columns in new window
|
||
rs_args ends
|
||
|
||
public rest_scr
|
||
rest_scr proc near
|
||
int 3
|
||
push ES
|
||
push BP ; save the caller's BP register
|
||
sub SP,offset rs_BP
|
||
mov BP,SP ; and establish local addressability
|
||
|
||
; address the string
|
||
|
||
mov ES,[BP].rs_str
|
||
xor SI,SI ; ES:SI => string
|
||
|
||
; get number of rows and columns from screen object
|
||
xor AH,AH
|
||
lods byte ptr ES:[SI]
|
||
add AX,[BP].rs_ulrow
|
||
mov [BP].rs_nrow,AX
|
||
xor AH,AH
|
||
lods byte ptr ES:[SI]
|
||
add AX,[BP].rs_ulcol
|
||
mov [BP].rs_ncol,AX
|
||
; adjust number of lines/columns for test conditions
|
||
mov AX,[BP].rs_ulrow
|
||
add [BP].rs_mrow,AX
|
||
mov AX,[BP].rs_ulcol
|
||
add [BP].rs_mcol,AX
|
||
; loop until all rows processed
|
||
mov DL,byte ptr [BP].rs_ulrow
|
||
xw_loop: mov DH,byte ptr [BP].rs_ulcol
|
||
; position cursor
|
||
xl_loop: cmp DH,byte ptr [BP].rs_mcol ; column too long for new window?
|
||
jge x_long ; if too long, jump
|
||
push DX ; save current position
|
||
mov AH,02h ; load "put cursor" function id
|
||
xor BH,BH ; IBMism (page number/0 in graphic mode)
|
||
call crt_dsr ; position the cursor
|
||
; read character/attributes at current screen position
|
||
lods word ptr ES:[SI] ; fetch the character and attribute
|
||
|
||
;;;;;;;; cmp AL,20h
|
||
;;;;;;;; je x_sp ; if a space skip
|
||
|
||
mov BL,AH ; and copy attribute to BL
|
||
mov AH,09h ; load "write char/attribute" function id
|
||
xor BH,BH ; IBMism (page number)
|
||
mov CX,1 ; character count = 1
|
||
call crt_dsr ; read said
|
||
; increment column number, test, branch
|
||
x_sp: pop DX ; recover the row/column coordinates
|
||
x_more: inc DH ; increment the column number
|
||
cmp DH,byte ptr [BP].rs_ncol ; more characters in this row?
|
||
jl xl_loop ; if so, jump
|
||
; increment row number, test, branch
|
||
inc DL ; increment the row number
|
||
cmp DL,byte ptr [BP].rs_mrow ; check against new window boundary
|
||
jge rs_fin ; if all rows filled, jump
|
||
cmp DL,byte ptr [BP].rs_nrow ; check against saved data
|
||
jl xw_loop ; if more lines, jump
|
||
|
||
; return to caller
|
||
rs_fin: add SP,offset rs_BP ; deallocate local storage
|
||
pop BP ; restore the caller's BP register
|
||
pop ES ; restore the caller's ES register
|
||
xor ax,ax
|
||
ret ; return to caller
|
||
;
|
||
x_long: inc SI ; increment index into saved screen
|
||
inc SI ; buffer
|
||
jmp short x_more ; continue processing row
|
||
rest_scr endp
|
||
|
||
|
||
;************************************************************************
|
||
;* Output Character To Window *
|
||
;************************************************************************
|
||
pch_args struc
|
||
dw ? ; caller's BP
|
||
dw ? ; return address
|
||
dd ? ; caller's return address
|
||
p_op dw ? ; putchar opcode
|
||
p_line dw ? ; cursor position - line number
|
||
p_col dw ? ; cursor position - column number
|
||
p_char dw ? ; character to write
|
||
p_attr dw ? ; character's attributes
|
||
pch_args ends
|
||
|
||
public putchar
|
||
putchar proc near
|
||
push BP ; save caller's BP
|
||
mov BP,SP
|
||
; position cursor for write
|
||
mov DL,byte ptr [BP].p_line ; load line number
|
||
mov DH,byte ptr [BP].p_col ; load column number
|
||
xor BH,BH ; IBMism
|
||
mov AH,02h ; load "put cursor" code
|
||
call crt_dsr ; positio the cursor
|
||
|
||
mov BL,byte ptr [BP].p_attr ; load its attributes
|
||
cmp vid_mode,14 ; only attribute for EGA modes is a
|
||
jl pchar_1 ; simulated reverse video
|
||
|
||
mov BH,BL ; save the attribute
|
||
and BH,80h ; reverse video?
|
||
jz pchar_1 ; zero indicates bit 8 not set
|
||
|
||
pchar_2: and BL,7fh ; strip off high bit
|
||
mov CX,1 ; character count
|
||
xor BH,BH ; video page number
|
||
mov AL,0dbh ; block character
|
||
mov AH,09h
|
||
call crt_dsr
|
||
or BL,80h ; set xor bit
|
||
; write the characters with attributes
|
||
pchar_1: mov AL,byte ptr [BP].p_char ; load the character
|
||
xor BH,BH ; IBMism
|
||
mov CX,1 ; repeat count = 1
|
||
mov AH,09h ; load write char/attribute code
|
||
call crt_dsr
|
||
; return to caller
|
||
xor ax,ax
|
||
pop BP
|
||
ret
|
||
putchar endp
|
||
|
||
;************************************************************************
|
||
;* Scroll Window Up one line *
|
||
;************************************************************************
|
||
su_args struc
|
||
dw ? ; caller's BP
|
||
dw ? ; return address
|
||
dd ? ; caller's return address
|
||
su_op dw ? ; scroll opcode
|
||
su_line dw ? ; upper left hand corner line number
|
||
su_col dw ? ; upper left hand corner column number
|
||
su_nline dw ? ; number of lines
|
||
su_ncols dw ? ; number of columns
|
||
su_attr dw ? ; text attributes (used for blanking)
|
||
su_args ends
|
||
|
||
public scrollup
|
||
scrollup proc near
|
||
push BP ; save caller's BP
|
||
mov BP,SP
|
||
; scroll window's text up one line
|
||
mov CL,byte ptr [BP].su_nline ; load number of lines
|
||
dec CL ; decrease number of lines by one
|
||
jz blank1 ; Jump if scrolling 1-line and just blank it
|
||
mov CH,byte ptr [BP].su_ncols ; load number of columns
|
||
mov DL,byte ptr [BP].su_line ; load upper left line number
|
||
mov DH,byte ptr [BP].su_col ; load upper left column number
|
||
mov AX,0601h ; load "scroll text" code with no blanking
|
||
cmp DGROUP:PC_MAKE,TIPC
|
||
je ti_scrl
|
||
cmp vid_mode,4 ; Are we in graphics mode?
|
||
jl txt_mod ; If we are then fix blank fill attributes
|
||
cmp vid_mode,7 ; so that the bar characters don't show up
|
||
je txt_mod
|
||
xor BH,BH ; zero attribute for fill blanks
|
||
jmp short rite_atr
|
||
txt_mod: mov BH,byte ptr [BP].su_attr ; Blanked lines' attribute txt mode
|
||
rite_atr: xchg CX,DX ; CX=Upper left corner
|
||
xchg CH,CL ; Row,column instead of TI's column,row
|
||
xchg DH,DL ; ditto
|
||
add DX,CX ; DX=Lower right corner
|
||
dec DL ; adjust column count (0 is first column)
|
||
int IBM_CRT
|
||
jmp short z_quit ; IFF IBM is in graphics mode weird char's
|
||
; are used for blanks when scrolling. Do
|
||
; as TIPC does and "manual" blank 'em.
|
||
;
|
||
ti_scrl: mov BX,DX ; copy destination coordinates
|
||
inc DL ; compute source by incrementing line number
|
||
int TI_CRT ; perform block move
|
||
; paint the last line of the window with blank of proper attributes
|
||
blank1: mov DH,byte ptr [BP].su_col ; load starting column number
|
||
mov DL,byte ptr [BP].su_line ; load upper line number
|
||
add DL,byte ptr [BP].su_nline ; add the number of lines and
|
||
dec DL ; subtract offf one
|
||
mov AH,02h ; load "put cursor" code
|
||
xor BH,BH ; IBMism
|
||
call crt_dsr ; position cursor for write
|
||
mov AX,0920h ; load "write char/attr" code, write a blank
|
||
mov BL,byte ptr [BP].su_attr ; load attribute bit setting
|
||
|
||
cmp vid_mode,14 ; ega mode?
|
||
jl z_scr01
|
||
mov BH,BL
|
||
and BH,80h
|
||
cmp BH,80h ; reverse video?
|
||
jne z_scr01
|
||
mov AX,09dbh ; change for block character
|
||
and BL,7fh ; strip off xor bit
|
||
z_scr01: xor BH,BH ; IBMism
|
||
mov CX,[BP].su_ncols ; load line length
|
||
call crt_dsr ; write a line of blanks
|
||
; return to caller
|
||
z_quit: pop BP
|
||
xor ax,ax
|
||
ret
|
||
scrollup endp
|
||
|
||
|
||
;************************************************************************
|
||
;* Scroll Window Down one line *
|
||
;************************************************************************
|
||
sd_args struc
|
||
dw ? ; caller's BP
|
||
dw ? ; return address
|
||
dd ? ; caller's return address
|
||
sd_op dw ? ; op code
|
||
sd_line dw ? ; upper left hand corner line number
|
||
sd_col dw ? ; upper left hand corner column number
|
||
sd_nline dw ? ; number of lines
|
||
sd_ncols dw ? ; number of columns
|
||
sd_attr dw ? ; text attributes (used for blanking)
|
||
sd_args ends
|
||
|
||
scrolldn proc near
|
||
push BP ; save caller's BP
|
||
mov BP,SP
|
||
; scroll window's text down one line
|
||
mov CL,byte ptr [BP].sd_nline ; load number of lines
|
||
dec CL ; decrease number of lines by one
|
||
jz blank ; Jump if scrolling 1-line and just blank it
|
||
mov CH,byte ptr [BP].sd_ncols ; load number of columns
|
||
mov DL,byte ptr [BP].sd_line ; load upper left line number
|
||
mov DH,byte ptr [BP].sd_col ; load upper left column number
|
||
mov AX,0701h ; load "scroll text" code with no blanking
|
||
cmp DGROUP:PC_MAKE,TIPC
|
||
je ti_down
|
||
|
||
push AX ; else
|
||
mov AH,0Fh
|
||
int IBM_CRT ; Are we in graphics mode?
|
||
cmp AL,4 ; If we are then fix blank fill attributes
|
||
jl text_m ; so that the bar characters don't show up
|
||
cmp AL,7
|
||
je text_m
|
||
xor BH,BH ; zero attribute for fill blanks
|
||
jmp short wrte_atr
|
||
text_m: mov BH,byte ptr [BP].sd_attr ; Blanked lines' attribute txt mode
|
||
|
||
wrte_atr: pop AX
|
||
xchg CX,DX ; CX=Upper left corner
|
||
xchg CH,CL ; Row,column instead of TI's column,row
|
||
xchg DH,DL ; ditto
|
||
add DX,CX ; DX=Lower right corner
|
||
dec DL ; adjust column count (0 is first column)
|
||
int IBM_CRT
|
||
jmp short quit ; IFF IBM is in graphics mode weird char's
|
||
; are used for blanks when scrolling. Do
|
||
; as TIPC does and "manual" blank 'em.
|
||
;
|
||
ti_down: mov BX,DX ; copy destination coordinates
|
||
inc BL ; compute dest by incrementing line number
|
||
int TI_CRT ; perform the block move
|
||
; paint the first line of the window with blank of proper attributes
|
||
blank: mov DH,byte ptr [BP].sd_col ; load starting column number
|
||
mov DL,byte ptr [BP].sd_line ; load upper line number
|
||
mov AH,02h ; load the "put cursor" code
|
||
xor BH,BH ; IBMism
|
||
call crt_dsr ; position cursor for write
|
||
mov AX,0920h ; load "write char/attr" code, write a blank
|
||
mov BL,byte ptr [BP].sd_attr ; load attribute bit setting
|
||
xor BH,BH ; IBMism
|
||
mov CX,[BP].sd_ncols ; load line length
|
||
call crt_dsr ; write a line of blanks
|
||
; return to caller
|
||
quit: pop BP ; restore caller's BP
|
||
xor ax,ax
|
||
ret
|
||
scrolldn endp
|
||
|
||
;****************************************************************************
|
||
;* *
|
||
;* Change Video Mode *
|
||
;* *
|
||
;* Purpose: to note changes to video mode. *
|
||
;* *
|
||
;****************************************************************************
|
||
chgvmode struc
|
||
dw ? ; caller's BP
|
||
dw ? ; return address
|
||
dd ? ; caller's return address
|
||
chg_op dw ? ; op code
|
||
chg_chgt dw ? ; new character height
|
||
chg_mode dw ? ; new video mode
|
||
chg_rows dw ? ; new max rows for screen
|
||
chgvmode ends
|
||
|
||
public chgmode
|
||
chgmode proc near
|
||
int 3
|
||
push bp
|
||
mov bp,sp
|
||
mov ax,[bp].chg_mode
|
||
mov VID_MODE,ax
|
||
mov ax,[bp].chg_chgt
|
||
mov CHAR_HGT,ax
|
||
mov ax,[bp].chg_rows
|
||
mov MAX_ROWS,al
|
||
pop bp
|
||
xor ax,ax
|
||
ret
|
||
chgmode endp
|
||
|
||
|
||
|
||
;****************************************************************************
|
||
;* *
|
||
;* WRITE BLOCK OF CHARACTERS *
|
||
;* *
|
||
;* Purpose: Write a character string to the display *
|
||
;* *
|
||
;****************************************************************************
|
||
wblk_args struc
|
||
dw ? ;caller's BP
|
||
dw ? ;return address
|
||
dd ? ;caller's return address
|
||
blk_op dw ? ;op code
|
||
blk_len dw ? ;length of block to write
|
||
blk_buf db 100 dup (?) ;buffer to write
|
||
blk_txt dw ? ;text attributes
|
||
blk_cur dw ? ;cursor position
|
||
wblk_args ends
|
||
|
||
public wblock
|
||
wblock proc near
|
||
int 3
|
||
push bp
|
||
mov bp,sp
|
||
|
||
mov ah,02h ;load "put cursor" code
|
||
xor bh,bh ;IBMism - page 0 for text mode
|
||
mov dx,[bp].blk_cur ;dx = cursor coordinates
|
||
call crt_dsr ;position the cursor
|
||
|
||
mov cx,[bp].blk_len ;cx = number of characters
|
||
|
||
cmp PC_MAKE,TIPC ;on what flavor PC are we running?
|
||
jne blk_ibm ;if an IBM, jump
|
||
; Write line to TIPC's screen
|
||
mov al,byte ptr [bp].blk_txt ;load text attributes
|
||
mov ah,010h ;load "write block w/ attr" code
|
||
mov dx,ss ;load segment address
|
||
mov bx,bp ;load buffer offset in segment
|
||
add bx,blk_buf
|
||
int TI_CRT
|
||
jmp blk_end
|
||
|
||
; Write line to IBM's screen
|
||
blk_ibm: mov di,bp
|
||
add di,blk_buf ;load buffer offset
|
||
mov dx,[bp].blk_cur ;reverse row/column coordinates
|
||
xchg dl,dh
|
||
mov [bp].blk_cur,dx
|
||
push cx ; save
|
||
jmp short blk_imidl ;jump into middle of loop
|
||
|
||
blk_iloop:
|
||
push cx ;save the character counter
|
||
mov dx,[bp].blk_cur ;load the previous cursor coordinates,
|
||
inc dl ;increment the column number
|
||
mov [bp].blk_cur,dx ;and save new coordinates
|
||
xor bh,bh ;page number (0 for graphics mode) IBMism
|
||
mov ah,02h ;load "put cursor" code
|
||
push di
|
||
int IBM_CRT ;position the cursor
|
||
pop di
|
||
blk_imidl:
|
||
mov ah,09h ;load "write char w/ attributes" code
|
||
mov al,byte ptr ss:[di] ;load character from buffer
|
||
mov BL,byte ptr [bp].blk_txt ;load attribute bits
|
||
xor bh,bh ;page # for alpha mode
|
||
mov cx,1 ;load repeat count = 1
|
||
pop dx ;restore character count
|
||
; test to see if we buy anything by using a repeat count
|
||
blk_imore:
|
||
cmp dx,1 ;more characters to display?
|
||
jle blk_ibotm ;if no more characters, jump
|
||
cmp al,byte ptr ss:[di]+1 ;is next character the same as previous?
|
||
jne blk_ibotm ;if not same character, jump
|
||
inc cx ;increment the repeat count
|
||
inc di ;increment the output buffer index
|
||
inc byte ptr [bp].blk_cur ;increment the cursor position
|
||
dec dx ;decrement the character count
|
||
jmp blk_imore ;try for another
|
||
blk_ibotm:
|
||
; output the character(s)
|
||
push dx ;save the adjusted character count
|
||
push di ;save the output buffer index
|
||
int IBM_CRT ;output the char(s)
|
||
pop di ;restore the output buffer index
|
||
pop cx ;restore character counter
|
||
inc di ;increment buffer pointer
|
||
loop blk_iloop ;continue 'til all characters output
|
||
|
||
blk_end:
|
||
pop bp ;restore stack
|
||
ret ; and return
|
||
wblock endp
|
||
|
||
;****************************************************************************
|
||
;* *
|
||
;* WRITE CHARACTER STRING *
|
||
;* *
|
||
;* Purpose: Write a character string to the given port object *
|
||
;* *
|
||
;****************************************************************************
|
||
wstr_args struc
|
||
dw ? ; caller's BP
|
||
dw ? ; return address
|
||
dd ? ; caller's return address
|
||
wrt_op dw ? ; op code
|
||
;;; wrt_newl dw ? ; newline before writing
|
||
wrt_wrap dw ? ; check wrap before writing string
|
||
wrt_offs dw ? ; string offset
|
||
wrt_seg dw ? ; string segment
|
||
wrt_len dw ? ; # characters
|
||
wrt_port dw ? ; port object
|
||
wstr_args ends
|
||
|
||
public wstring
|
||
wstring proc near
|
||
int 3
|
||
push bp
|
||
mov bp,sp
|
||
cmp [bp].wrt_len,0 ;anything to write?
|
||
jg wst_10 ; yes, continue
|
||
jmp wst_fin
|
||
wst_10:
|
||
|
||
cmp [bp+wrt_wrap],0 ;check wrap before writing?
|
||
je wst_15 ; no, continue
|
||
xor ax,ax ;ax = wrap indicator (0 = no)
|
||
mov bx,[bp+wrt_port].pt_ncols ;bx = line length
|
||
cmp bx,0 ;maintaining line length?
|
||
je wst_15 ; no, jump
|
||
mov cx,[bp+wrt_port].pt_ccol ;cx = current column
|
||
cmp cx,1 ;in first column already?
|
||
jle wst_15 ; yes, jump
|
||
sub bx,cx ;determine space remaining
|
||
cmp bx,[bp+wrt_len] ;room left on current line?
|
||
jge wst_15 ; yes, jump
|
||
inc ax ;set wrap indicator
|
||
wst_15:
|
||
mov [bp+wrt_wrap],ax ;update wrap indicator
|
||
mov bx,[bp+wrt_port].pt_pflgs ;get window flags
|
||
test bx,OPEN ;is port open for writing?
|
||
jz wst_esc ; no, get outa here
|
||
test bx,STRIO ;is port a string?
|
||
jnz wst_esc ; yes, return
|
||
test bx,WINDOW ;is port a window?
|
||
jnz wst_win ; yes, go to window code
|
||
jmp wst_fil ; no, go to file code
|
||
wst_esc: jmp wst_fin
|
||
;*****************************************************************************
|
||
; We have a valid window port. Write the string to the display.
|
||
;*****************************************************************************
|
||
wst_win:
|
||
les di,dword ptr [bp+wrt_offs] ;es:di => string buffer
|
||
|
||
mov bx,[bp+wrt_port].pt_cline ;bx = current line
|
||
mov ax,[bp+wrt_port].pt_ccol ;ax = current column
|
||
mov dx,[bp+wrt_port].pt_ullin ;dx = upper left line #
|
||
cmp [bp+wrt_wrap],0 ;wrap before writing string?
|
||
je wwin_start ; no, jump
|
||
xor ax,ax ;clear current column
|
||
inc bx ;bump current line
|
||
cmp bx,[bp+wrt_port].pt_nline ;exceeded number of lines?
|
||
jl wwst_w10 ;no, skip scroll
|
||
int 3
|
||
call scrollit ;scroll the display
|
||
wwst_w10:
|
||
push ax
|
||
push di
|
||
push es:[di] ;next character
|
||
call isspace ;determine if whitespace
|
||
pop di
|
||
or ax,ax ;is it?
|
||
pop ax
|
||
jz wwin_start ; no, jump
|
||
inc di
|
||
dec [bp+wrt_len] ;decrement string length
|
||
jnz wwin_start ;if non-zero, go
|
||
mov [bp+wrt_port].pt_cline,bx ;save current cursor line number
|
||
mov [bp+wrt_port].pt_ccol,ax ;save current cursor column number
|
||
jmp wst_fin ; else return
|
||
wwin_start:
|
||
mov cx,[bp+wrt_len]
|
||
;
|
||
; loop through the chars, writing them to the display
|
||
;
|
||
wwin_loop:
|
||
push cx
|
||
push di
|
||
|
||
mov cl,es:[di]
|
||
cmp cl,RETURN ;if char = carriage return
|
||
;;;;;;;; je wwin_creturn ; then jump
|
||
ja wwin_default ;if not control char, jump
|
||
xor ch,ch
|
||
mov si,cx
|
||
shl si,1 ;get index into jump table
|
||
jmp [wn_handle+si] ;go to handler
|
||
|
||
; default character handler
|
||
;
|
||
wwin_default:
|
||
cmp ax,[bp+wrt_port].pt_ncols ;are we in the last column?
|
||
jl wwin_linechk ; no, jump
|
||
test [bp+wrt_port].pt_wflgs,W_WRAP ;wrap option on?
|
||
jnz wwin_scrl ; yes, jump
|
||
inc ax ;clip - bump column
|
||
jmp wwin_100 ; continue
|
||
wwin_linechk:
|
||
cmp bx,[bp+wrt_port].pt_nline ;out of lines?
|
||
jl wwin_wchar ;no, return
|
||
wwin_scrl:
|
||
inc bx ;bump current line
|
||
xor ax,ax ;clear column
|
||
cmp bx,[bp+wrt_port].pt_nline ;exceeded number of lines?
|
||
jl wwin_wchar ; no, jump
|
||
call scrollit
|
||
wwin_wchar:
|
||
push ax ;save current column
|
||
push bx ;save current line
|
||
|
||
cmp vid_mode,3
|
||
jne wwin_gen
|
||
cmp pc_make,1
|
||
je wwin_gen
|
||
|
||
xchg ax,bx
|
||
add ax,[bp+wrt_port].pt_ullin
|
||
mov ah,80
|
||
mul ah
|
||
add ax,bx
|
||
add ax,[bp+wrt_port].pt_ulcol
|
||
shl ax,1
|
||
mov si,ax
|
||
mov ch,byte ptr [bp+wrt_port].pt_text
|
||
push ds
|
||
push 0B800h
|
||
pop ds
|
||
mov [si],cx
|
||
pop ds
|
||
jmp wwin_nxt
|
||
wwin_go:
|
||
jmp wwin_loop
|
||
wwin_gen:
|
||
push [bp+wrt_port].pt_text ;push text character attribute
|
||
push es:[di] ;push the character
|
||
add ax,[bp+wrt_port].pt_ulcol
|
||
push ax ;column number to console
|
||
add bx,[bp+wrt_port].pt_ullin
|
||
push bx ;line number to console
|
||
sub sp,6
|
||
call putchar ;display character
|
||
add sp,14 ;dump args off stack
|
||
wwin_nxt:
|
||
pop bx ;restore current line
|
||
pop ax ;restore current column
|
||
inc ax ;increment current column
|
||
wwin_100: mov [bp+wrt_port].pt_cline,bx ;save current cursor line number
|
||
wwin_120: mov [bp+wrt_port].pt_ccol,ax ;save current cursor column number
|
||
pop di
|
||
inc di
|
||
pop cx
|
||
loop wwin_go
|
||
;;;; loop wwin_loop ;if more chars, loop
|
||
jmp wst_fin ; else go home
|
||
|
||
;
|
||
; Handlers for special characters (RETURN,LINEFEED,TAB,BACKSPACE)
|
||
;
|
||
|
||
; Carriage return character handler
|
||
wwin_creturn:
|
||
mov cl,LINEFEED ;fall thru to linefeed handler
|
||
; Line Feed character handler
|
||
wwin_linefeed:
|
||
xor ax,ax ;clear column
|
||
inc bx ;bump line number
|
||
cmp bx,[bp+wrt_port].pt_nline ;exceeded number of lines?
|
||
jl wwin_100 ; no, jump
|
||
call scrollit ; yes, scroll
|
||
jmp wwin_100
|
||
; Backspace character handler
|
||
wwin_backspace:
|
||
dec AX ;decrement current column
|
||
cmp AX,0 ;if column now positive
|
||
jge wwin_120 ; then return
|
||
xor AX,AX ;cur_col = 0
|
||
jmp wwin_120 ;return
|
||
; Bell character handler
|
||
wwin_bell:
|
||
push ax
|
||
push bx
|
||
call bell ;sound the alarm
|
||
pop bx
|
||
pop ax
|
||
jmp wwin_120 ;and return
|
||
; Tab character handler
|
||
wwin_tab:
|
||
mov cx,ax ;cx = current column
|
||
mov dx,8 ;dl = 8
|
||
div dl ;ah = (cur_col % 8)
|
||
sub dl,ah
|
||
add cx,dx
|
||
mov ax,cx ;update current column
|
||
jmp wwin_120 ;and return
|
||
|
||
;*****************************************************************************
|
||
; We have a valid file port. Write the string to the disk.
|
||
;*****************************************************************************
|
||
wst_fil:
|
||
int 3
|
||
xor ax,ax ;clear ax for char later
|
||
les di,dword ptr [bp+wrt_offs] ;es:di => string buffer
|
||
|
||
test [bp+wrt_port].pt_pflgs,BINARY ;binary file?
|
||
jnz wfil_start ; yes, skip newline
|
||
cmp [bp+wrt_wrap],0 ;wrap before writing string?
|
||
je wfil_start ; no, go write chars to disk
|
||
mov al,RETURN ; yes, write CR/LF to file
|
||
call write_char
|
||
xor ax,ax ;set current column to 0
|
||
call upd_port ;update port object
|
||
mov al,LINEFEED
|
||
call write_char
|
||
xor ax,ax ;set current column to 0
|
||
call upd_port ;update port object
|
||
push di
|
||
push es:[di]
|
||
call isspace ;determine next char whitespace
|
||
pop di
|
||
or ax,ax ;is it?
|
||
jz wfil_start ; no, jump
|
||
inc di ;
|
||
dec [bp+wrt_len] ;decrement string length
|
||
jnz wfil_start ;if non-zero, continue
|
||
jmp wst_fin ; else return
|
||
wfil_start:
|
||
mov cx,[bp+wrt_len]
|
||
;
|
||
; loop through the chars, writing them to the display
|
||
;
|
||
wfil_loop:
|
||
push cx ;save length
|
||
push di ;save index to string
|
||
|
||
mov cl,es:[di] ;get character just written
|
||
cmp cl,RETURN ;test for control char
|
||
ja wfil_default ; if not, handle as default case
|
||
je wfil_newline ; if return, go handle
|
||
xor ch,ch ;clear high byte
|
||
mov si,cx ;move char to index reg
|
||
shl si,1 ;get index into jump table
|
||
jmp [ds_handle+si] ;go to handler
|
||
|
||
wfil_default:
|
||
mov cx,1 ;cx = length
|
||
mov bx,[bp+wrt_port].pt_handl ;bx = handle
|
||
mov dx,di ;dx = offset
|
||
mov ax,es ;ax = segment
|
||
call diskout
|
||
mov ax,[bp+wrt_port].pt_ccol ;ax = current column
|
||
cmp ax,[bp+wrt_port].pt_ncols ;have we exceeded line length
|
||
jl wfil_10 ; no, jump
|
||
xor ax,ax ;clear current column
|
||
jmp wfil_upd ;go update port data
|
||
wfil_10: inc ax ;bump current column
|
||
wfil_upd: call upd_port
|
||
pop di ;restore string index
|
||
inc di ;and increment
|
||
pop cx ;restore length
|
||
loop wfil_loop ;loop if more
|
||
wst_fin:
|
||
xor ax,ax
|
||
pop bp
|
||
ret ;return to caller
|
||
|
||
;
|
||
; Handlers for special characters (RETURN,LINEFEED,TAB,BACKSPACE)
|
||
;
|
||
|
||
; Carriage return or linefeed character handler
|
||
wfil_newline:
|
||
test [bp+wrt_port].pt_pflgs,BINARY ;binary file?
|
||
jnz wfil_default ; yes, output char
|
||
mov al,RETURN ; no, output cr/lf
|
||
call write_char
|
||
xor ax,ax ;set current column to 0
|
||
call upd_port ;update port object
|
||
mov al,LINEFEED
|
||
call write_char
|
||
xor ax,ax
|
||
jmp wfil_upd
|
||
|
||
; backspace character handler
|
||
wfil_backspace:
|
||
test [bp+wrt_port].pt_pflgs,BINARY ;binary file?
|
||
jnz wfil_10 ;yes, output char
|
||
mov al,byte ptr es:[di] ;al = backspace char
|
||
call write_char ;write it out
|
||
mov ax,[bp+wrt_port].pt_ccol ;ax = current column
|
||
dec ax ;decrement it
|
||
cmp ax,0
|
||
jge wfil_upd
|
||
xor ax,ax
|
||
jmp wfil_upd
|
||
; tab character handler
|
||
wfil_tab:
|
||
test [bp+wrt_port].pt_pflgs,BINARY ;binary file?
|
||
jnz wfil_10 ;yes, jump
|
||
mov al,byte ptr es:[di] ;al = tab char
|
||
call write_char ;write it out
|
||
mov ax,[bp+wrt_port].pt_ccol ;ax = current column
|
||
mov cx,ax
|
||
mov dx,8
|
||
div dl ; ah = (cur_col % 8)
|
||
sub dl,ah
|
||
add cx,dx
|
||
mov ax,cx
|
||
jmp wfil_upd
|
||
|
||
|
||
;*****************************************************************************
|
||
; Utilty routines for writing characters to display or disk
|
||
;*****************************************************************************
|
||
|
||
;UPD_PORT - update port object
|
||
; entry: ax = current column
|
||
upd_port proc near
|
||
cmp [bp+wrt_port].pt_ncols,0 ;if line length = 0
|
||
je upd_05 ; then don't maintain column
|
||
mov [bp+wrt_port].pt_ccol,ax ;save current column
|
||
upd_05:
|
||
mov ax,[bp+wrt_port].pt_bfpos ;get current buffer position
|
||
inc ax ;bump the position
|
||
cmp ax,256 ;crossed chunk boundary?
|
||
jle upd_10 ; no, jump
|
||
sub ax,256 ;ax=excess above chunk
|
||
inc [bp+wrt_port].pt_chunk ;update chunk number
|
||
upd_10: mov [bp+wrt_port].pt_bfpos,ax ;update buffer position
|
||
ret
|
||
upd_port endp
|
||
|
||
;WRITE_CHAR - write character to port
|
||
; entry: ax = character to write to port
|
||
write_char proc near
|
||
mov cx,1 ;length
|
||
mov bx,[bp+wrt_port].pt_handl ;handle
|
||
push ax
|
||
mov dx,sp
|
||
mov ax,ss
|
||
call diskout
|
||
pop ax
|
||
ret
|
||
write_char endp
|
||
|
||
|
||
;DISKOUT - output char(s) to disk
|
||
; entry: ax=segment, bx=handle, cx=buffer length, dx=offset
|
||
; exit: carry set = error, ax=status
|
||
; errors will return to the caller of wstring
|
||
diskout proc near
|
||
push ds
|
||
mov ds,ax
|
||
mov ah,WRITEFILE
|
||
int DOS ;perform disk write
|
||
pop ds
|
||
jc diskerr
|
||
cmp ax,cx ;everything written?
|
||
je diskret ; yes, return
|
||
mov ax,DISK_FULL ;note disk full error
|
||
jmp derr_ret
|
||
diskerr:
|
||
int 3
|
||
;;;
|
||
;;; For some reason, the following doesn't work. Must be a failure by
|
||
;;; AI Architects support of Get Extended Error. In the interim, just
|
||
;;; use the return value in ax. Returning is easy, just dump local
|
||
;;; storage from the stack, pop the callers bp, and return.
|
||
;;;
|
||
;;; xor bx,bx
|
||
;;; mov AH,059h ;GET_EXTENDED_ERROR
|
||
;;; int DOS ;Extended error code in AX
|
||
derr_ret: mov sp,bp ;dump everything off stack
|
||
pop bp ;return to handler, error in ax
|
||
diskret:
|
||
ret
|
||
diskout endp
|
||
|
||
;ISSPACE - determine if character is whitespace
|
||
;
|
||
isspace proc near
|
||
pop di
|
||
pop ax
|
||
cmp al,' '
|
||
je issp
|
||
cmp al,9
|
||
jb isntsp
|
||
cmp al,13
|
||
jbe issp
|
||
isntsp: xor ax,ax
|
||
issp: jmp di
|
||
isspace endp
|
||
|
||
|
||
;Scrollit - local support to scroll window
|
||
; entry: ax = column, bx = line
|
||
; exit: ax = column, bx = line
|
||
scrollit proc near
|
||
cmp bx,[bp+wrt_port].pt_nline ;out of lines?
|
||
jl scrl_ret ;no, return
|
||
push [bp+wrt_port].pt_text
|
||
push [bp+wrt_port].pt_ncols
|
||
push [bp+wrt_port].pt_nline
|
||
push [bp+wrt_port].pt_ulcol
|
||
push [bp+wrt_port].pt_ullin
|
||
sub sp,6 ;dummy args for scroll
|
||
call scrollup ;scroll window up one line
|
||
add sp,16 ;dump args off stack
|
||
mov bx,[bp+wrt_port].pt_nline ;bx = number of lines
|
||
dec bx ;bx = line number
|
||
xor ax,ax ;ax = column
|
||
scrl_ret:
|
||
ret
|
||
scrollit endp
|
||
|
||
wstring endp
|
||
|
||
;************************************************************************
|
||
;* Perform appropriate VIDEO I/O interrupt *
|
||
;* Any difference in register definition should be handled by *
|
||
;* the caller except where DH,DL contain row,col information. *
|
||
;************************************************************************
|
||
public crt_dsr
|
||
crt_dsr proc near
|
||
cmp PC_MAKE,TIPC
|
||
jne ibm_dsr
|
||
int TI_CRT
|
||
ret
|
||
ibm_dsr: xchg DH,DL ; Do this now instead of making special checks
|
||
int IBM_CRT ; IBM's row,col is diff'rnt from TI's col,row
|
||
ret
|
||
crt_dsr endp
|
||
|
||
z_ega proc near
|
||
|
||
mov AX,0A000h
|
||
mov ES,AX ; set ES to the video plane
|
||
mov AX,c_row ; set AX to the row
|
||
mul char_hgt ; multiply by the character height
|
||
mov BX,80 ; multiply by 80 bytes per line
|
||
mul BX
|
||
add AX,c_col ; add in the starting column
|
||
mov sav_di,AX ; save the starting value
|
||
xor BX,BX ; use BX as a counter
|
||
mov DX,c_len ; number of columns to blank
|
||
|
||
zc_03: mov CX,DX ; restore counter
|
||
mov DI,sav_di ; restore index
|
||
mov AH,0fh
|
||
xor AX,AX ; clear AX
|
||
cld
|
||
rep stosb
|
||
|
||
add sav_di,80 ; next line
|
||
inc BX ; increment counter
|
||
cmp BX,char_hgt ; done with this row?
|
||
jne zc_03
|
||
|
||
xor BX,BX ; clear counter
|
||
dec c_nrows ; decrement row count
|
||
jg zc_03 ; if more rows, loop (jump)
|
||
ret
|
||
z_ega endp
|
||
|
||
;************************************************************************
|
||
;* Graphics Character Attribute *
|
||
;* *
|
||
;* Purpose: To retrieve the attribute of a character on an IBM screen *
|
||
;* in a graphics mode, either 14 or 16. *
|
||
;* *
|
||
;************************************************************************
|
||
|
||
public graph_attr
|
||
graph_attr proc near
|
||
|
||
cmp AL,20h ; skip if a space
|
||
je grphend
|
||
|
||
cmp AL,00h ; skip if a null
|
||
je grphend
|
||
|
||
cmp AL,0dbh ; block character?
|
||
je grphend
|
||
|
||
push ES
|
||
push SI
|
||
push AX ; save character
|
||
push DX ; save row and column
|
||
xor AH,AH ; clear AH
|
||
mov SI,AX ; use SI as an index
|
||
sub SI,21h
|
||
|
||
mov AL,DL ; row
|
||
mul char_hgt ; pixels per character
|
||
xor BX,BX
|
||
|
||
mov BL,byte ptr m18_attr[SI] ; default mode 18 adjustment
|
||
cmp vid_mode,18 ; are we in mode 18?
|
||
je grph_02 ; yes, jump
|
||
mov BL,byte ptr m16_attr[SI] ; default mode 16 adjustment
|
||
cmp vid_mode,16 ; are we in mode 16?
|
||
je grph_02 ; yes, jump
|
||
mov BL,byte ptr m14_attr[SI] ; must be mode 14
|
||
grph_02:
|
||
add AX,BX
|
||
mov BX,80 ; 80 bytes per line
|
||
mul BX
|
||
|
||
pop DX ; restore the column
|
||
xor DL,DL ; clear the row
|
||
xchg DH,DL ; set AX to the row
|
||
add AX,DX
|
||
mov SI,AX ; put result in SI
|
||
|
||
mov AX,0a000h ; load in graphics plane
|
||
mov ES,AX
|
||
|
||
xor CX,CX ; clear CX
|
||
|
||
mov CH,01
|
||
mov AH,0
|
||
grph_03: call get_val
|
||
|
||
shl CH,1 ; shift mask one bit to the left
|
||
inc AH ; next plane
|
||
cmp AH,3
|
||
jbe grph_03
|
||
|
||
pop AX ; retrieve character
|
||
mov AH,CL ; set attribute byte
|
||
pop SI
|
||
pop ES
|
||
grphend: ret
|
||
graph_attr endp
|
||
|
||
get_val proc near
|
||
push AX ; save AH
|
||
mov DX,3ceh ; port addr of sequencer
|
||
mov AL,04h ; index to other map mask register
|
||
out DX,AL ; set index register
|
||
inc DX
|
||
xchg AL,AH
|
||
out DX,AL ; enable bank
|
||
pop AX ; restore AH
|
||
mov AL,ES:[SI]
|
||
or AL,AL
|
||
jz get_end
|
||
or CL,CH ; set attribute bit
|
||
get_end: ret
|
||
get_val endp
|
||
|
||
; PCTYPE
|
||
; Determine type of PC we are running on and initialize screen.
|
||
;
|
||
; Returns upon exit:
|
||
; Machine Type
|
||
; 1 for TIPC or Business Pro in TI mode
|
||
; FF for IBM-PC
|
||
; FE for IBM-PC/XT
|
||
; FD for IBM-PC/jr
|
||
; FC for IBM-PC/AT or B-P in IBM mode
|
||
; F8 for PS2 Model 80
|
||
; 0 for undeterminable
|
||
; Video Mode
|
||
; Character Height
|
||
;
|
||
pctype proc near
|
||
push es ; preserve regs for later
|
||
push ds
|
||
|
||
mov ax,0FC00h ; move paragraph address of copyright
|
||
pc_002: mov es,ax ; notice into ES
|
||
xor di,di ; Clear DI; 0 is lowest address in ROM @ES:
|
||
xor bx,bx ; Flag for "PC_MAKE"
|
||
mov cx,40h ; This'll be as far as I go...
|
||
mov al,'T' ; look for beginning of "Texas Instruments"
|
||
cli ; Stop interrupts - bug in old 8088's
|
||
again:
|
||
repne scas byte ptr es:[di] ; SEARCH
|
||
or cx,cx ; Reach my limit?
|
||
jz short pc_005 ; quit if we've exhausted search
|
||
cmp byte ptr es:[di],'e' ; make sure this is it
|
||
jne again ; use defaults if not found
|
||
cmp byte ptr es:[di]+1,'x' ; really make sure this is it
|
||
jne again
|
||
|
||
push ds
|
||
mov ds,bx ; 0->DS for addressing low mem.
|
||
|
||
inc bx ; BX==1 => TIPC
|
||
mov ax,ds:word ptr [01A2h] ; If TIPC then what kind?
|
||
pop ds ; get DS back
|
||
|
||
add al,ah ; checkout vector 68 bytes 2 & 3
|
||
cmp al,0F0h ; if AL==F0 then TIPC=Business Pro
|
||
jne pc_010 ; jump if not a B-P
|
||
|
||
in al,068h ; Read from port
|
||
push ax ; Save for later
|
||
and al,0FBh ; Enable CMOS
|
||
out 068h,al ; Write back out
|
||
mov dx,8296h ; I/O address for B-P's mode byte
|
||
in al,dx ; TI or IBM Mode on the B-P?
|
||
cmp al,0 ; if not zero then B-P emulates a TIPC
|
||
pop ax ; Restore original port value
|
||
out 068h,al ; and write back out
|
||
jne pc_010 ; jump if TIPC else IBM machine code is
|
||
; where it should be.
|
||
jmp short pc_007
|
||
pc_005: mov ax,es
|
||
cmp ah,0FEh ; test for segment offset FE00
|
||
jae pc_007 ; two checks made? if so, jump
|
||
add ah,2 ; go back and check segment offset
|
||
jmp pc_002 ; FE00
|
||
pc_007: mov ax,0F000h
|
||
|
||
mov es,ax
|
||
mov al,byte ptr es:0FFFEh ; IBM's machine code is @F000:FFFE
|
||
cmp al,0f0h ; Is this suckah an IBM?
|
||
jb pc_010 ; Jump if AL is below F0 (BX will be 0)
|
||
mov bl,al
|
||
pc_010:
|
||
sti ; Turn interrups back on
|
||
cmp bx,1 ; TIPC?
|
||
jne not_ti ; no, jump
|
||
; tipc, initialize graphics
|
||
mov di,0DF01h
|
||
mov es,di ; clear graphics planes
|
||
xor di,di
|
||
mov byte ptr es:[di],0AAh ; set red palette
|
||
mov byte ptr es:[di]+16,0CCh ; set green palette
|
||
mov byte ptr es:[di]+32,0F0h ; set blue palette
|
||
|
||
mov ax,0DF82h
|
||
mov es,ax
|
||
mov byte ptr es:[di],040h ; turn text on
|
||
|
||
mov ax,3 ; ax = video mode
|
||
; bx = pc type code
|
||
mov cx,8 ; cx = character height
|
||
jmp pc_020
|
||
; ibm, (assumed) get current video mode
|
||
not_ti:
|
||
push bx ; save pc type code around bios calls
|
||
mov ax,0500h ; set active display page (for alpha modes)
|
||
int 10h ; bios int
|
||
mov ah,15 ; get current video mode
|
||
int 10h ; bios int
|
||
xor ah,ah ; ax = video mode
|
||
pop bx ; bx = pc type code
|
||
mov cx,8 ; cx = character height
|
||
cmp ax,16 ; if video mode = 16
|
||
jle pc_020 ; then
|
||
mov cx,14 ; reset character height
|
||
pc_020:
|
||
pop ds ; restore local data seg
|
||
pop es ; es:di addresses transaction buffer
|
||
xor di,di
|
||
|
||
mov PC_MAKE,bx ; put PC_MAKE in transaction buffer
|
||
mov VID_MODE,ax ; ditto video mode
|
||
mov CHAR_HGT,cx ; ditto char height
|
||
ret
|
||
pctype endp
|
||
|
||
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
; The XLI interface.
|
||
;-----------------------------------------------------------------------------
|
||
|
||
main proc far ;this file's initial entry point
|
||
mov AX,data
|
||
mov DS,AX
|
||
; mov AX,stack ;establish local stack
|
||
; mov SS,AX
|
||
|
||
call pctype ;initialize type/monitor info
|
||
|
||
mov psp,ES ;save PSP@
|
||
mov word ptr ES:fb_addr,offset file_block ;poke file block@
|
||
mov word ptr ES:fb_addr+2,seg file_block ;into PSP
|
||
mov AX,ES:term_addr ;calc ptrs in PCS to jump to
|
||
add AX,3
|
||
mov xwait,AX
|
||
add AX,3
|
||
mov xbye,AX
|
||
mov AX,ES:term_addr+2
|
||
mov xwait+2,AX
|
||
mov xbye+2,AX
|
||
mov psize,plen ;calc program size
|
||
push psp
|
||
push psize
|
||
call dword ptr [xwait] ;connect with PCS
|
||
; Since this is a XLI SYSINT routine, no XCALL's ever cause a return.
|
||
; The only time we return is to terminate.
|
||
pop AX
|
||
pop AX
|
||
call dword ptr [xbye] ;disconnect from PCS
|
||
main endp
|
||
|
||
progsize = $-progstart
|
||
plen equ (progsize+datasize+stacksize+100h+10h)/16
|
||
PROG ends
|
||
end main
|
||
|