home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
screen
/
screen.asm
< prev
next >
Wrap
Assembly Source File
|
1992-09-08
|
15KB
|
493 lines
page 64,132
title screen - IBM Display Enhancement Dec 1983
.radix 10
;***************************************************************
; Typed in by Greg Glass - gjg@cmu-cs-cad from Byte - Nov. 1983
; NOTE: if you have a color card this will shift over to it
; (even if the monitor is turned off)
; hit Alt F7 to switch to the Mono monitor.
; To build this program:
; 1> masm screen; /* assemble the code */
; 2> link screen; /* link it - will get no stack seg. message */
; 3> exe2bin screen /* convert the format */
; 4> rename screen.bin screen.com /* make the new format executable*/
; 5> del screen.exe /* don't need this anymore */
;
; To use program: just run it or place in autoexec.bat
;
; COMMANDS:
; <alt>F1 - increment the text color
; <alt>F3 - increment the background color
; <alt>F5 - toggle modes co80/co40
; <alt>F7 - toggle between color and mono display
; <alt>F9 - redraw display - reset colors
;***************************************************************
;***************************************************************
;
; Define interrupt vectors for both keyboard interrupt 16H and
; screen interrupt 10H. Both in segment 0.
;
;***************************************************************
keyvect segment at 0 ; define keyboard interrupt vector
org 16h*4
KEYINT label dword
keyvect ends
scrvect segment at 0 ; define screen interrupt vector
org 10h*4
SCRINT label dword
scrvect ends
;***************************************************************
;
; define constants
;
;***************************************************************
bw_val equ 07h ; standard b&w attibute sent to monitor
equip_flag equ 410h ; area in RAM that contains equipment status
chk_mode equ 15 ; screen interrupt function to check mode
mono_mode equ 7 ; screen mode of 7 indicates monochrome
color_adpt equ 3 ;modes from 0 to 3 are non-graphics color
;***************************************************************
;
; start code area
;
;***************************************************************
code segment para
assume cs:code
org 100h ; start code offset 100h from starting segment
; (this leaves room for DOS's work areas)
KEY proc far
START:
; Initialization code...used only once, on system startup
jmp init_code ; call initialization routine
even
validchk db 'FCP!' ; used by INSTALL to check for valid SCREEN
; program
;***************************************************************
;
; Define storage areas and data structures
;
;***************************************************************
; define keystroke scan codes for the five SCREEN functions
fore_inc dw 6800h ; foreground increment
back_inc dw 6a00h ; background increment
c80_40 dw 6c00h ; 80x25 to 40x25 flip-flop key
col_mon dw 6e00h ; color/mono flip-flop key
repaint dw 7000h ; repaint screen using current mode
cur_mode dw col80_area ; Initialize starting mode
mono_set dw mono_area ; pointer to monochrome area
color_set dw col80_area ; pointer to "active" color area
scrn_attr db 70h ; current screen attribute
scrn_mode db 255 ; saves current screen mode
; define structure used to contain information about 40 and 80
; column color modes as well as monochrome mode.
s struc
corner dw 0 ; defines COL/ROW count of characters for mon
bf dw 0 ; Colors of fore and back
equip dw 0 ; equipment settings
mode dw 0 ; AX value for setting mode of monitor
s ends
; Now, set up three screen structures with default conditions
col80_area s <5019h,0107h,20h,3> ; 80x25, white FORE blue BACK
col40_area s <2819h,0107h,10h,1> ; 40x25, Brown FORE black BACK
mono_area s <5019h,0007h,30h,7> ; monochrome, reverse video
;NOTE: The standard BIOS ROM KEYBOARD interrupt routine is
; executed as a subroutine ( using CALL DWORD PTR) if
; the interrupt was invoked to return a keystroke. Any
; other execution KEYBOARD_IO can be called as a simple
; inline FAR JMP instruction. NOTE: the CALL instruction
; (see just after INT_LOOP label below) uses the
; address stored here at KEY_CALL to KEYBOARD_IO.
KEY_CALL :
db 0eah ; far JMP address to KEYBOARD interrupt
dw 0,0 ;
;***************************************************************
;
; procedure KEY_RTNE - Intercepts keyboard interrupt and
; determines if the keystroke is one of the five SCREEN ones.
;
;***************************************************************
KEY_RTNE:
assume ds:code
sti ; turn on interrupts
cmp ah,0 ; call as subroutine if keyfetch
jne KEY_CALL ; jump to KEYBOARD_IO if not
push ds ; save ds and bx from destruction
push bx ;
push cx
push dx
push es
push di
mov bx,cs ; move cs segment into ds
mov ds,bx ;
INT_LOOP:
pushf ; IBM keyboard proc exports interrupt call
mov bx,offset KEY_CALL + 1 ;Get address to ROM code for keyboard
call dword ptr[bx] ; call keyboard routine
mov bx, cur_mode ; get current mode address
cmp ax, col_mon ; see if COLOR<->MONO flip-flop key
jne TEST_FORE ; exit if not
; otherwise, flip-flop screen mode
cmp bx, mono_set ; are we looking at monochrome?
je set_color ; swap in color if yes
cmp mono_set,0 ; see if monochrome monitor enabled
je next_key ; ignore command if not
mov bx,mono_set ; otherwise set up monochrome
jmp short DO_CHG ;
SET_COLOR:
cmp color_set,0 ; see if COLOR monitor enabled
je NEXT_KEY ; skip if not
mov bx,color_set ; set up for color
DO_CHG:
call SCREEN_CHG ; implement screen change
NEXT_KEY:
mov ah,0 ; set up to fetch keystroke
jmp INT_LOOP ; fetch next key input
TEST_FORE:
push ax ; save registers.
push bx ; see if in graphics mode
mov ah,chk_mode ;
int 10h ;
pop bx ; restore bx register
cmp al,color_adpt ; if between 0 and 3, not graphics mode
jle NOT_GRAF ;
cmp al,mono_mode ; monochrome mode
jge NOT_GRAF ; restore stack
pop ax ; if color-graphics mode, do not change
jmp DONE ; modes
NOT_GRAF:
pop ax ; restore ax
cmp ax,fore_inc ; is this key to increment FORE ?
jne TEST_BACK ; skip if not
cmp bx,color_set ; see if currently using color
jne BW_FLOP ; if not, go deal with B & W
mov ax,[bx].bf ; gets BACK in al, FORE in ah
EQ_FORE:
inc al ; increment FOREGROUND color
and al,7 ; keep it within bounds (chg. for more colors)
cmp al,ah ; see if same as background
je EQ_FORE ; increment againt if yes
mov [bx].bf,ax ; save back to structure
jmp DO_CHG ; redraw display
TEST_BACK:
cmp ax,back_inc ; is this key to increment BACK?
jne TEST_REPAINT ; skip if not
cmp bx,color_set ; see if currently using color
jne BW_FLOP ; if not, go deal with B&W
mov ax,[bx].bf ; gets BACK in al, FORE in ah
EQ_BACK:
inc ah ; increment background color
and ah,7 ; keep in bounds
cmp ah,al ; see if same as foreground
je EQ_BACK ; increment again if yes
mov [bx].bf,ax ; save back to structure
jmp DO_CHG ; redraw the screen
BW_FLOP: ; flip-flop B&W screen
mov ax,[bx].bf ; BACK in ah, FORE in al
xchg ah,al ; swap
mov [bx].bf,ax ; save back to structure
jmp DO_CHG ; redraw the screen
TEST_REPAINT:
cmp ax,repaint ; is this the key to redraw the screen ?
je DO_CHG ; if yes then repaint
TEST_80_40:
cmp ax,c80_40 ; is this the key to flop 80 / 40 ?
jne DONE ; exit if not
cmp bx,offset col40_area ; is current pointer area 40x25 ?
jne TST80 ; skip if not
mov bx,offset col80_area ; otherwise flip to 80x25
jmp short SAVE_COL ; save to color_set
TST80:
cmp bx,offset col80_area ; is current 80x25 color ?
jne NEXT_KEY ; ignore key if not
mov bx,offset col40_area ;
SAVE_COL:
mov color_set,bx ; sat to color_set
jmp SET_COLOR ; implement
DONE:
pop di
pop es
pop dx
pop cx
pop bx
pop ds
iret ; return from interrupt
KEY endp ; done with main routine !
;***************************************************************
;
; SCREEN_CHG - Changes current monitor screen mode
;
; Inputs: bx points to current monitor structure
;
;***************************************************************
SCREEN_CHG proc near
mov ax,0 ; get segment address to equip_flag
mov es,ax ; in RAM memory
mov ax,es:equip_flag ; get set of equip flag
and al,0CFh ; get rid of current monitor flag
or ax,[bx].equip ; set up new monitor flag
mov es:equip_flag,ax ; save back in RAM
mov cur_mode,bx ; indicate new mode
; now, set up attribute for background and foreground
mov dx,[bx].bf ; get both FORE and BACK in dx
mov cl,4 ; shift count
shl dh,cl ; shift BACK into upper nibble
or dh,dl ; move FORE into lower nibble
mov scrn_attr,dh ; save result
; see if we need to reset monitor (switching to new monitor?)
mov ax,[bx].mode ; get mode
cmp al,scrn_mode ; compare with current mode
je SET_ATTR ; skip if same
mov scrn_mode,al ; otherwise, save current mode
int 10h ; and reset to new monitor
SET_ATTR: ; change attributes of current screen
call CH_ATTR ; changes attributes
ret
SCREEN_CHG endp
;***************************************************************
;
; CH_ATTR - repaints acctive screen so that every character on
; current screen is displayed with the new attributes
;
; Inputs: bx points to current monitor structure
;
;***************************************************************
CH_ATTR proc near
; see if we need to draw in border for color mode
cmp bx,offset mono_set ; in color?
je NO_BORDER ; do not worry about border if not
push ax ; save registers
push bx ;
mov bx,[bx].bf ; get background color in bx
mov bl,bh ;
mov bh,0 ; select border color
mov ah,11 ; interface to set color palette
int 10h
pop bx ; restore registers
pop ax
NO_BORDER:
mov ax,[bx].corner ; get COL and ROW for current
mov cornr,ax ; save in temporary
mov ah,chk_mode ; get page number
int 10h ;
; bh contains active page
mov ah,3 ; save current cursor posn
int 10h
push dx ; save position in stack
xor dx,dx ; load dx with 0
mov cx,1 ; set up replication count
mov bl,scrn_attr ; get current attribute
REP_ATTR:
mov ah,2 ; set cursor position
int 10h
mov ah,8 ; read next character
int 10h
; ah contains current character attribute
and ah,88h ; get intensity bit
and bl,77h ; make sore attribute intensity off
or bl,ah ; combine to get current attribute
mov ah,9 ; write out char with new attribute
int 10h ;
inc dl ;
cmp dl,tcol ; are we done with this column?
jle REP_ATTR
xor dl,dl ; otherwise zero out DL
inc dh ; move to next row
cmp dh,trow ; done with screen ?
jle REP_ATTR ; loop until done
pop dx ; restore original cursor position
mov ah,2
int 10h
ret
cornr label word
trow db 0 ; temporary store for ROW
tcol db 0 ; temp store for COL
CH_ATTR endp
;***************************************************************
;
; SCR_RTNE - Replaces SCREEN interrupt so that it can intercept
; B&W character writes and change attributes
;
;***************************************************************
SCR_RTNE proc near
assume ds: code
sti
push ds ; save data segment register
push cs ; move CS segment into DS
pop ds ; this is a funny way to do that (gjg)
cmp ah,6 ; Spot SCROLL UP and SCROLL DOWN calls
jl NORMAL_SCR ;
cmp ah,6
jg NOT_SCROLL ;
SCROLL:
call GET_CH ; for scrolling, update attribute
jmp NORMAL_SCR ; now, execute scroll
NOT_SCROLL:
cmp ah,9 ; check for "WRITE ATTRIBUTE/CHAR" cmd
jne NORMAL_SCR ; send out any other command as normal
xchg bh,bl ; get attribute for command
call GET_CH ; update attribute for command
xchg bh,bl ; move attribute back to bh for cmd
NORMAL_SCR:
pop ds ; restore ds segment register
;
; NOTE: We are now ready to invoke the BIOS screen interrupt.
; Since the ROM code includes an IRET interrupt return call,
; all we need to do is to jump to the start of the ROM code
; and all will be well. Since the initialization code set
; up the address to the screen interrupt code below, we can
; set up a forced jump to that address.
JMP_SCR: ; Address to SCREEN interrupt
db 0EAh ; force a FAR JMP but do not set up dest-
dw 0,0 ; ination address at assembly time.
; (INIT routine will set this address)
SCR_RTNE endp
;***************************************************************
;
; GET_CH - subroutine replaces B&W character with current replacement
; attributes and allows for intensity bit setting
;
; Inputs : bh contains attribute to be modified
;
;***************************************************************
GET_CH proc near
mov savech,bh ; save character
and bh,77h ; Remove intensity and blink bits
cmp bh,bw_val ; see if currently defined B&W value
mov bh,savech ; otherwise, modify to current attribute
jne OUT ; exit if not
and bh,88h ; get rid of B&W part
or bh,scrn_attr ; move in current attribute part
OUT:
ret ; done
savech db 0 ; temporary character store
GET_CH endp
LASTONE: ; all code after this label is freed to DOS use after
; initialization of the program.
;***************************************************************
;
; INIT_CODE - Code to load and initialize the SCREEN program..
; sets up DOS to keep all code before "LASTONE" label
; safe from overlaying during system operation.
;
;***************************************************************
COPYRT: db 'SCREEN Version 1.20 Copyright 1983 Tim Field',13,10,'$'
INIT_CODE proc near
; Initialize KEYBOARD intercept code
assume es:keyvect ;'vectors' is interrupt segment 0
mov ax,keyvect ; get address to interrupt vector
mov es,ax ; save in es
mov ax,es:keyint ; get address to interrupt
mov bx,offset key_call+1 ; address to place to save vector
mov [bx],ax ; save interrupt address
mov ax,es:keyint[2] ; get interrupt segment for rtne
mov [bx+2],ax ; save it too
mov es:keyint,offset key_rtne ; now replace with own address
mov ax,cs ; save segment in interrupt vector
mov es:keyint[2],ax ;
; initialize SCREEN intercept code
assume es:scrvect ;'vectors' is interrupt segment 0
mov ax,scrvect ; get address to interrupt vector
mov es,ax ; save in es
mov ax,es:scrint ; get address to interrupt
mov bx,offset jmp_scr+1 ; address to place to save vector
mov [bx],ax ; save interrupt address
mov ax,es:scrint[2] ; get interrupt segment for rtne
mov [bx+2],ax ; save it too
mov es:scrint,offset scr_rtne ; now replace with own address
mov ax,cs ; save segment in interrupt vector
mov es:scrint[2],ax ;
; Initialize screen
mov bx,cur_mode ; set up initial mode
call SCREEN_CHG ; initialize
; Now print out acknowledgement to user monitor and exit
mov ax,cs ; set up segment to routine
mov ds,ax
mov dx,offset copyrt ; now print out copyright message
mov ah,9 ; DOS function to print string
int 21h ; execute function interrupt
mov dx,offset lastone ; save all code up to "LASTONE" label
int 27h ; no return needed
INIT_CODE endp
code ends
end start