home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frostbyte's 1980s DOS Shareware Collection
/
floppyshareware.zip
/
floppyshareware
/
VORX
/
EM15DM11.ARC
/
IBM.ASM
< prev
next >
Wrap
Assembly Source File
|
1989-08-18
|
25KB
|
1,156 lines
;ibm.asm - last modified Fri Aug 18 23:00:56 1989 PDT - mbf
;History:3,1
;Tue Aug 01 01:36:27 1989 Added cc primitive for setting cursor type (lines
; 798-814; see also emacs.asm) [mbf]
;Thu May 25 23:36:48 1989 Added bp variable (0..1) for toggling beep timeout
; (lines 322, 710-18, 723; see also emacs.asm) [mbf]
;Wed May 24 14:46:14 1989 Added xychrout_ins to display 00h as a reverse video
; '@' (lines 1018-19, 1040-48) [mbf]
;Mon May 22 22:53:38 1989 Fixed control character display problem; to display
; ctrl chars in reverse video or bold, uncomment the appropriate code
; (reverse video: 1027-33; bold: 1035, 1051); also made ctrl chars
; display in actual ascii representation (i.e., ctrl-z now displays as a
; right arrow, not a Z) 1037 [mbf]
;Sat May 20 19:34:33 1989 Changed uninit_exit_1 to cls to first, rather than
; last, line on exiting emacs (lines 499) [mbf]
;Sat May 20 19:18:41 1989 Changed visi space to 0b1h (from 07h) and visi tab
; to 0b0h (from 04h) (lines 306-7) [mbf]
;08-25-88 23:37:09 Create two new keycodes, "C- " and "M- ".
;05-30-88 22:27:44 fix a small problem in save/restore screen
;05-29-88 22:49:48 try getting the attributes from lower left.
;05-29-88 22:42:39 get the attributes from the lower right corner rather than upper right.
;05-27-88 23:25:34 fix a problem in putch where it put garbage characters up.
;05-27-88 00:09:00 read_ibm_cga sometimes gets called with ds=bufseg, not data.
;05-27-88 00:07:02 move_line didn't respect ibm_cga flag--it was always set.
;05-17-88 20:33:20 Add support for hardware scrolls (should work for all displays) [kdb]
;05-17-88 20:02:45 Make move_line wait while reading cga screen [kdb]
;05-17-88 19:35:35 Remove all reference to scrwait function [kdb]
;05-17-88 19:03:22 Macroize scrwait for single char [kdb]
;05-15-88 19:16:51 add scrwait in scrolls [kdb]
;05-15-88 18:58:45 Make move_line wait for each character [kdb]
;05-07-88 22:07:59 implement a swap_screen_flag.
;05-03-88 23:54:55 add more extended keys.
;04-17-88 19:22:28 add some extended keycodes.
;04-16-88 13:13:01 add extended keyboard support.
;04-14-88 22:51:58 If ibm_cga, don't store_debug.
;04-01-88 23:08:28 respond to mouse keys with M-, S-, and C-
;03-31-88 22:02:25 use C-break for the break character (duh)
;03-28-88 19:19:14 just clear the screen on a MDA.
;03-28-88 19:09:19 don't save and restore video memory on an MDA.
;03-28-88 18:28:50 remove block_cursor and under_cursor
;03-26-88 21:59:07 change back to bios calls to read the keyboard.
;03-24-88 00:02:13 add fore_original and back_original.
;02-21-88 12:24:50 make control be bright, meta inverse video.
;02-13-88 18:22:56 use the 18.2 ms timer tick to time the beep.
;02-13-88 16:43:45 don't map Timeout using M-, C-, or S-
;12-07-87 20:07:29 add store_debug
;12-05-87 11:23:35 make the color default to the current color.
;12-05-87 11:20:13 clear the screen on init_entry.
;12-05-87 11:16:53 save dos's screen and restore it when finished.
;07-05-87 22:14:22 caps lock shouldn't apply to M- and C- keys.
page ,132
comment /
Porting EMACS and Percival to MS-DOS computers other than the Z-100:
This entire file (Z-100.ASM) needs to be re-written, since it contains
all the Z-100 dependencies. The following conventions must be maintained:
1) Never leave this module with DF=1.
2) Never destroy ES.
3) Never MOV AX,DATA, always use the copy in the appropriate segment register.
4) Return NC if a routine succeeds, or fulfills its goals.
/
.xlist
include memory.def
data segment byte public
public max_screen_line
max_screen_line db 22 ;number of last text row on screen.
public num_screen_cols
num_screen_cols db ?
db 0 ;in case they access it as a word.
public fore_original, back_original
fore_original db ?
back_original db ?
public scan_lines_per_char
scan_lines_per_char db 8
public computer_name, computer_name_len
computer_name db 'IBM-PC'
computer_name_len equ $-computer_name
public swap_screen_flag
swap_screen_flag dw 1 ;=1 if we should swap screens.
old_cursor dw ? ;old cursor position from the swapped
; screen.
key_names label byte
db ',','Comma',0
db '(','LPar',0
db ')','RPar',0
db 7fh,'Delete',0
db -1,'Timeout',0
db -2,'Left Down',0 ;mouse button key names.
db -3,'Right Down',0
db -4,'Left Up',0
db -5,'Right Up',0
db -6,'Middle Down',0
db -7,'Middle Up',0
db 0
key_others label byte
db 14,'Back Space',0
db 15,'Tab',0
db 28,'Return',0
db 1,'Escape',0
db 0
key_special label byte
db 127,'C-Back Space',0
db 10,'C-Return',0
db 0
key_table label byte
db 1,'M-Esc',0 ;extended
db 3,'C-@',0
db 14,'M-Back Space',0 ;extended
db 15,'S-Tab',0
db 16,'M-q',0
db 17,'M-w',0
db 18,'M-e',0
db 19,'M-r',0
db 20,'M-t',0
db 21,'M-y',0
db 22,'M-u',0
db 23,'M-i',0
db 24,'M-o',0
db 25,'M-p',0
db 26,'M-{',0 ;extended
db 27,'M-}',0 ;extended
db 28,'M-Return',0 ;extended
db 30,'M-a',0
db 31,'M-s',0
db 32,'M-d',0
db 33,'M-f',0
db 34,'M-g',0
db 35,'M-h',0
db 36,'M-j',0
db 37,'M-k',0
db 38,'M-l',0
db 39,'M-;',0 ;extended
db 40,"M-'",0 ;extended
db 41,'M-`',0 ;extended
db 43,'M-\',0 ;extended
db 44,'M-z',0
db 45,'M-x',0
db 46,'M-c',0
db 47,'M-v',0
db 48,'M-b',0
db 49,'M-n',0
db 50,'M-m',0
db 51,'M-Comma',0 ;extended
db 52,'M-.',0 ;extended
db 53,'M-/',0 ;extended
db 55,'M-Asterisk',0
db 59,'F1',0
db 60,'F2',0
db 61,'F3',0
db 62,'F4',0
db 63,'F5',0
db 64,'F6',0
db 65,'F7',0
db 66,'F8',0
db 67,'F9',0
db 68,'F10',0
db 71,'Home',0
db 72,'Up Arrow',0
db 73,'Pg Up',0
db 74,'M-Minus',0
db 75,'Left Arrow',0
db 76,'Five',0
db 77,'Right Arrow',0
db 78,'M-Plus',0
db 79,'End',0
db 80,'Down Arrow',0
db 81,'Pg Dn',0
db 82,'Ins',0
db 83,'Del',0
db 84,'S-F1',0
db 85,'S-F2',0
db 86,'S-F3',0
db 87,'S-F4',0
db 88,'S-F5',0
db 89,'S-F6',0
db 90,'S-F7',0
db 91,'S-F8',0
db 92,'S-F9',0
db 93,'S-F10',0
db 94,'C-F1',0
db 95,'C-F2',0
db 96,'C-F3',0
db 97,'C-F4',0
db 98,'C-F5',0
db 99,'C-F6',0
db 100,'C-F7',0
db 101,'C-F8',0
db 102,'C-F9',0
db 103,'C-F10',0
db 104,'M-F1',0
db 105,'M-F2',0
db 106,'M-F3',0
db 107,'M-F4',0
db 108,'M-F5',0
db 109,'M-F6',0
db 110,'M-F7',0
db 111,'M-F8',0
db 112,'M-F9',0
db 113,'M-F10',0
db 114,'C-PrtSc',0
db 115,'C-Left Arrow',0
db 116,'C-Right Arrow',0
db 117,'C-End',0
db 118,'C-Pg Dn',0
db 119,'C-Home',0
db 120,'M-1',0
db 121,'M-2',0
db 122,'M-3',0
db 123,'M-4',0
db 124,'M-5',0
db 125,'M-6',0
db 126,'M-7',0
db 127,'M-8',0
db 128,'M-9',0
db 129,'M-0',0
db 130,'M--',0
db 131,'M-=',0
db 132,'C-Pg Up',0
;all of the following are extended.
db 133,'F11',0
db 134,'F12',0
db 135,'S-F11',0
db 136,'S-F12',0
db 137,'C-F11',0
db 138,'C-F12',0
db 139,'M-F11',0
db 140,'M-F12',0
db 141,'C-Up Arrow',0
db 142,'C-Minus',0
db 143,'C-Five',0
db 144,'C-Plus',0
db 145,'C-Down Arrow',0
db 146,'C-Ins',0
db 147,'C-Del',0
db 148,'C-Tab',0
db 149,'C-Slash',0
db 150,'C-Asterisk',0
db 151,'M-Home',0
db 152,'M-Up Arrow',0
db 153,'M-Pg Up',0
db 155,'M-Left Arrow',0
db 157,'M-Right Arrow',0
db 159,'M-End',0
db 160,'M-Down Arrow',0
db 161,'M-Pg Dn',0
db 162,'M-Ins',0
db 163,'M-Del',0
db 164,'M-Slash',0
db 165,'M-Tab',0
db 166,'M-Return',0
db 167,'C- ',0
db 168,'M- ',0
; db 224,'Slash',0
; db 224,'Return',0
db 0,'Unknown',0
one_key_string db ?,0
ctrl_key_string db 'C-'
ctrl_key_char db ?,0
left_flag equ 1
right_flag equ 2
ctrl_flag equ 4
alt_flag equ 8
all_flags equ left_flag + right_flag + ctrl_flag + alt_flag
shift_flags db ?
bios_seg segment at 40h
org 17h
bios_shifts db ?
bios_seg ends
key_buffer label byte ;this is where we put the ASCII
db 26 dup(?) ; representation of the key.
extrn inversing: word ;if we're inverse videoing.
public color
color db 0fh ;xbbbifff bbb=background, ifff=fore.
font_8_table label byte
db 0b1h ;visi space; mbf: was 007h
db 0b0h ;visi tab; mbf: was 004h
db ? ;del
db ? ;eof
db ? ;visi newline
db 01ah ;visi rgt mrgn
db ? ;random char.
db 01fh ;visible newline.
ibm_cga db 0 ;=0 if we can write to screen anytime,
;=1 if we should wait for retrace.
have_ega db 0 ;=0 if we don't have an EGA.
int_16_input db 0 ;function code for keyboard input
int_16_status db 1 ;function code for keyboard status
dobeep db 0 ;beep toggle variable [mbf]
data ends
code segment byte public
assume cs:code, ds:data, es:nothing
;all of the code in this segment is called with the above assumes.
break_flag db ?
their_1b dd ?
our_1b:
mov cs:break_flag,1
iret
public init_entry
init_entry:
push es ;get their C-break.
mov ax,351bh
int 21h
mov word ptr their_1b+0,bx
mov word ptr their_1b+2,es
pop es
push ds ;set our C-break.
mov ax,cs
mov ds,ax
mov dx,offset our_1b
mov ax,251bh
int 21h
pop ds
;
;Determine whether or not the BIOS supports extended keyboard functions.
;
mov ah,5 ;write FFFFh to keyboard buffer
mov cx,0FFFFh
int 16h
mov ah,10h ;then read it back
int 16h
cmp ax,0FFFFh ;is AX set correctly?
jne init_entry_0 ;no - they don't have an extended kbd.
mov int_16_input,10h ;yes - use extended keyboard function codes.
mov int_16_status,11h
init_entry_0:
;
;Now set the video mode to one that we can use.
;
mov ah,15
int 10h ;get video state of the PC
mov num_screen_cols,40
cmp al,1 ;40 column text mode?
jbe init_entry_1 ;Yes, ok.
mov num_screen_cols,80
cmp al,3 ;Is screen CGA Text?
jbe init_entry_1 ;Yes, ok.
cmp al,7 ;Is screen MDA?
je init_entry_5 ;Yes, ok - but we can't have an EGA.
mov ax,0*256 + 3 ;use 25x80 color if some strange mode.
int 10h
init_entry_1:
mov ax,1200h ;test for an EGA
mov bx,10h
mov cx,-1
int 10h
cmp cx,-1
je init_entry_2 ;no EGA.
mov have_ega,1 ;remember that we have an EGA.
push ds ;get the max scanlines.
xor ax,ax
mov ds,ax
mov al,ds:[484h]
mov ah,ds:[485h]
mov cl,ds:[44ah]
pop ds
mov num_screen_cols,cl ;remember how wide it is.
sub al,2 ;leave room for a status and minibuffer line.
mov max_screen_line,al
init_entry_2:
cmp swap_screen_flag,0 ;should we swap the screen?
jne init_entry_4 ;yes.
ret ;no.
init_entry_4:
mov bh,0
mov ah,3 ;get cursor position
int 10h
mov old_cursor,dx
mov dl,max_screen_line ;copy the page zero to page one.
add dl,2
mov al,dl
inc al
add al,dl
init_entry_3:
call move_line ;enter with dl=source, al=destination.
dec al
dec dl
jns init_entry_3
init_entry_5:
push es
if 0
mov dh,num_screen_cols
dec dh
else
mov dh,0
endif
mov dl,max_screen_line
add dl,2
call get_video_ptr
mov ax,es:[di] ;get the attributes from the lower right.
pop es
mov fore_original,ah
and fore_original,0fh
mov cl,4 ;rotate the background to where we
shr ah,cl ; want it.
and ah,7
mov back_original,ah
clear_screen:
mov dh,0 ;clear the screen.
mov dl,max_screen_line
add dl,2
clear_screen_1:
call clear_to_eol ;enter with dl=row, dh=column.
dec dl
jns clear_screen_1
ret
public uninit_exit
uninit_exit:
;called when exiting. May destroy any but seg-regs.
push ds ;restore C-break.
lds dx,their_1b
mov ax,251bh
int 21h
pop ds
cmp swap_screen_flag,0 ;should we swap the screen?
jne uninit_exit_4 ;yes.
ret ;no.
uninit_exit_4:
mov ah,15
int 10h ;get video state of the PC
cmp al,7 ;don't restore the memory on an MDA
je uninit_exit_1 ; 'cuz it ain't there.
mov dx,old_cursor
mov bh,0
mov ah,2 ;set cursor position
int 10h
mov al,max_screen_line ;copy the page one to page zero.
add al,2
mov dl,al
add dl,dl
uninit_exit_3:
call move_line ;enter with dl=source, al=destination.
dec dl
dec al
jns uninit_exit_3
ret
uninit_exit_1:
mov dl,0
mov dh,0 ;mbf: was max_screen_line
;add dh,2
mov bh,0
mov ah,2 ;set cursor position
int 10h
call clear_screen
ret
public store_ibm_cga
store_ibm_cga:
cmp have_ega,0 ;do we have an EGA?
jne store_ibm_cga_1 ;yes - ignore them.
mov ibm_cga,al
store_ibm_cga_1:
ret
public store_debug
store_debug:
if 0
cmp ibm_cga,0 ;don't do this on an IBM CGA.
jne store_debug_1
push ds
push es
push ax
mov ax,data
mov ds,ax
mov es,ax
mov dh,num_screen_cols
sub dh,2
mov dl,max_screen_line
inc dl
call get_video_ptr ;enter with dl=current row, dh=current column.
;return with es:di->character position.
pop ax
mov es:[di],al
mov es:[di+2],ah
pop es
pop ds
store_debug_1:
endif
ret
;this routine should check for a break character. Return cy if none,
; nc if we should break.
public check_breakchar
check_breakchar:
cmp cs:break_flag,0 ;test the break flag.
mov cs:break_flag,0 ;clear the break flag.
stc
je check_breakchar_1
clc
check_breakchar_1:
ret
public check_for_key
check_for_key:
;return zr,ax=0 if no key is waiting.
;return nz,ax=key if a key is waiting, but don't input the key yet.
mov ah,int_16_status ;check for a key.
int 16h
jne check_for_key_1 ;go if we got a key.
mov ax,0 ;return ax=0 if we didn't.
check_for_key_1:
ret
public get_key_value
get_key_value:
;exit with ax=keycode.
mov ah,int_16_input
int 16h
ret
public decode_key
decode_key:
;enter with ax=key value.
;exit with si,cx -> the key's name in ASCII.
mov di,offset key_buffer
cmp ax,0f9h ;one of the mouse buttons?
jb decode_key_7
cmp ax,0feh
ja decode_key_7
push ax
push ds
mov ax,bios_seg
mov ds,ax
assume ds:bios_seg
mov ah,bios_shifts
and ah,all_flags ;isolate the flags we're interested in.
pop ds
assume ds:data
mov shift_flags,ah
call decode_meta
call decode_ctrl
call decode_shift
pop ax
decode_key_7:
or al,al ;extended function key?
je decode_key_5
cmp al,0e0h
je decode_key_5
push ax ;now we look for ASCII keys that
mov si,offset key_others ; have dedicated keys.
call decode_search ;search for the scan code names.
pop ax
jne decode_key_2 ;go if we found it.
mov ah,al
mov si,offset key_names ;now search for the ASCII keys that
; we don't (or can't) represent.
call decode_search ;search for the literal names.
jne decode_key_1 ;copy it in.
mov al,ah
cmp al,' ' ;control char?
jae decode_key_6 ;no
add al,'`' ;yes - convert into letter.
mov ctrl_key_char,al
mov si,offset ctrl_key_string
cmp al,'z' ;control character > 'C-z'?
jbe decode_key_1 ;no.
sub ctrl_key_char,'`'-'@' ;yes - make it C-[, not C-{
jmp short decode_key_1
decode_key_2:
push si
mov si,offset key_special
mov ah,al ;now see if it's one of the ones we
call decode_search ; know are special.
pop ax
jne decode_key_1 ;yes - it is.
mov si,ax
jmp short decode_key_1
decode_key_6:
mov one_key_string,al
mov si,offset one_key_string
jmp short decode_key_1
decode_key_5:
mov si,offset key_table ;search for the extended functions.
call decode_search
decode_key_1:
lodsb ;copy to the next null.
stosb
or al,al
jne decode_key_1
dec di ;don't include the null.
mov si,offset key_buffer
mov cx,di
sub cx,si
ret
decode_ctrl:
test shift_flags,ctrl_flag
je decode_ctrl_1
mov ax,'C' + '-'*256
stosw
decode_ctrl_1:
ret
decode_shift:
test shift_flags,left_flag + right_flag
je decode_shift_1
mov ax,'S' + '-'*256
stosw
decode_shift_1:
ret
decode_meta:
test shift_flags,alt_flag
je decode_meta_1
mov ax,'M' + '-'*256
stosw
decode_meta_1:
ret
decode_search:
;enter with ah=key to search for, si->table.
;exit with al=key, nz if found, al=0, zr if not found.
lodsb
or al,al ;end of table?
je decode_search_2 ;yes - try shifted values.
cmp al,ah ;is this the key?
je decode_search_2 ;yes.
decode_search_1:
lodsb ;skip to the next null.
or al,al
jne decode_search_1
jmp decode_search
decode_search_2:
or al,al
ret
public store_beep ;mbf
store_beep:
mov dobeep,al
ret
public read_beep ;mbf
read_beep:
mov al,dobeep
ret
public ring_the_bell
ring_the_bell:
cmp dobeep,0 ;mbf
je short ring_the_bell_exit
mov bx,6779
mov cx,2
call beep
ring_the_bell_exit:
ret
;Beep procedure count values
;---------------------------
;To generate a given freqency note out of the speaker with the Beep procedure
;on the PC using Channel 2 of the 8253 timer, the channel 2 count register
;must be loaded with a value such that the 8253 input clock frequency
;(1.19318 MHz) divided by the count figure equals the audio frequency.
;enter with bx=count figure for frequency to be generated.
beep:
push ds ; make ds = bios.
mov ax,40h
mov ds,ax
mov al,0b6h ; Channel 2, LSB then MSB, Square Wave, Binary
out 43h,al ; Program 8253 command register
mov ax,bx ; Get the frequency to be generated
out 42h,al ; Load Channel 2 count register LSB
mov al,ah
out 42h,al ; Load Channel 2 count register MSB
in al,61h ; Read settings from 8255 PPI I/O Port "PB"
mov ah,al ; Save original settings in AH
or al,3 ; Enable Timer Channel 2 & Speaker data
out 61h,al ; program the 8255 with new setting-speaker on
wait2:
mov bx,ds:[6ch] ; Get the current timer value.
wait1:
cmp bx,ds:[6ch] ; Did the timer value "tick"?
je wait1 ; No - keep waiting for a tick.
loop wait2 ; LOOP is first executed
mov al,ah ; Get original 8255 Port "PB" settings
out 61h,al ; Reset port to original values-speaker off
pop ds
ret
code ends
code segment byte public
assume cs:code, ds:nothing, es:data, ss:data
;all of the code in this segment is called with the above assumes.
public read_ibm_cga
read_ibm_cga:
mov al,ibm_cga
ret
public position_cursor
position_cursor:
;enter with dh=col (0...80), dl=row (0..max_screen_line)
;exit with cursor set to that position.
push si
push di
push bp
push bx
xchg dh,dl
mov bh,0
mov ah,2 ;set cursor position
int 10h
cld
xchg dh,dl
pop bx
pop bp
pop di
pop si
ret
;in mintscan [mbf]
extrn getarg: near
extrn get_number: near
extrn return_null: near
;set cursor type [mbf]
public cc_prim
cc_prim:
mov cx,1
mov bx,16
call getarg
call get_number
mov cx,ax
mov ah,01h
int 10h
call return_null
ret
crt_status equ 3dah ; crt status port
disp_enb equ 1 ; display enable bit
putch macro
local nowait,loop1,loop2
push bx
push dx
mov bx,ax
cmp ibm_cga,0
je nowait
mov dx,crt_status
loop1:
in al,dx
test al,disp_enb ; display enabled?
jnz loop1 ; yes, keep waiting
loop2:
in al,dx
test al,disp_enb ; now wait for it to go off
jz loop2 ; so can have whole cycle
nowait:
mov ax,bx
stosw
pop dx
pop bx
endm
public move_line
move_line:
;enter with dl=source row, al=destination row.
push ax
push bx
push cx
push dx
push si
push di
push bp
push ds
push es
push ax ;compute the source byte.
mov al,num_screen_cols
shl dl,1
mul dl
mov si,ax
pop ax
mov ah,num_screen_cols ;compute the destination byte.
shl al,1
mul ah
mov di,ax
mov cx,word ptr num_screen_cols ;move the line.
call get_video_seg ;get the video card plane.
mov ds,ax
assume ds:nothing, es:nothing
cmp ibm_cga,0
je move_line_2
move_line_1:
push dx
mov dx,crt_status
move_line_loop1:
in al,dx
test al,disp_enb ; display enabled?
jnz move_line_loop1 ; yes, keep waiting
move_line_loop2:
in al,dx
test al,disp_enb ; now wait for it to go off
jz move_line_loop2 ; so can have whole cycle
lodsw
pop dx
putch
loop move_line_1
jmp short move_line_3
move_line_2:
rep movsw
move_line_3:
pop es
pop ds
assume ds:nothing, es:data
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
public clear_to_eol
clear_to_eol:
;enter with dl=current row, dh=current column.
push bx
mov bl,num_screen_cols
call clear_count
pop bx
ret
public clear_count
clear_count:
;enter with dl=current row, dh=current column, bl=column to clear to.
push ax
push bx
push cx
push si
push di
push bp
push es
clear_count_0:
cmp dh,bl ;already past it?
jae clear_count_3 ;yes.
mov ah,color
mov al,' ' ;clear to the background color.
push ax
call get_video_ptr
assume ds:nothing, es:nothing
pop ax
mov cl,bl ;compute the number of chars to clear.
sub cl,dh
mov ch,0
cmp ibm_cga,0 ;slow refresh?
je clear_count_2
clear_count_1:
putch
loop clear_count_1
jmp short clear_count_3
clear_count_2:
rep stosw
clear_count_3:
pop es
assume ds:nothing, es:data
pop bp
pop di
pop si
pop cx
pop bx
pop ax
ret
get_video_ptr:
;enter with dl=current row, dh=current column.
;return with es:di->character position.
mov al,num_screen_cols ;compute the offset of the char.
mul dl
add al,dh
adc ah,0
shl ax,1
mov di,ax
get_video_seg:
;return with es,ax=video segment.
xor ax,ax
mov es,ax
mov ax,0b000h
cmp byte ptr es:[449h],7 ;MDA?
je get_video_seg_1 ;yes - we have the segment already.
mov ax,0b800h ;no - segment at b800h.
get_video_seg_1:
mov es,ax
ret
public xychrout
xychrout:
;enter with dh=col, dl=row, al=character to print, ah=font to print it in.
push ax ;save everything that we might need.
push bx
push cx
push dx
push di
push si
push es
push ds
mov bx,es
mov ds,bx
cmp dh,num_screen_cols ;past the right margin?
jae xychrout_3 ;yes - don't print.
cmp ah,0 ;font zero?
jne xychrout_5 ;no - print specially.
mov ah,color ;assume no inverse video
if 0
cmp al,80h ;meta char?
jb xychrout_nometa ;no
mov cl,4 ;yes, inverse video
rol ah,cl
and al,7fh ;but move into normal char range
xychrout_nometa:
endif
cmp al,00h ;mbf: print 00h specially
je xychrout_ins
cmp al,20h ;print control chars specially.
jb xychrout_control
cmp al,0ffh ;print 255 specially
je xychrout_del
jmp short xychrout_1
xychrout_control:
mov ah,color
;mbf: fix for rv video; uncmt if want rv
;mov bl,color ; sv it for new attr
;and bl,088h ; turn off color bits
;and ah,077h ; get colors only
;mov cl,4
;ror ah,cl ; exch backgr and foregr
;or bl,ah ; new attr: rv vid
;;or ah,08h ;mbf: fix for bold (was 10h); uncmt if want bold
;;;add al,'@' ;mbf: so that ctrl chars now show as ctrl chars
jmp short xychrout_1
xychrout_ins: ;mbf: make 00h look like a rv vid '@'
mov bl,color ; sv it for new attr
and bl,088h ; turn off color bits
and ah,077h ; get colors only
mov cl,4
ror ah,cl ; exch backgr and foregr
or bl,ah ; new attr: rv vid
mov al,40h
jmp short xychrout_1
xychrout_del:
mov ah,color
;;or ah,08h ;mbf: fix for bold (was 10h); uncmt if want bold
mov al,7fh ;bold del.
jmp short xychrout_1
xychrout_5:
mov ah,color
mov bx,offset font_8_table
sub al,4dh ;first character in font 8.
xlat
xychrout_1:
mov bx,inversing ;set the inverse video flag.
and bl,77h ;strip out just the color.
xor ah,bl ;now flip the colors (if desired).
push ax
call get_video_ptr
assume ds:nothing, es:nothing
pop ax
putch
xychrout_3:
pop ds
pop es
assume ds:nothing, es:data
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ret
public hardware_roll_down
hardware_roll_down:
;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
; otherwise, exit with cy=1. The hardware roll must leave the last line
; on the screen as the last line.
;preserve bx.
cmp ibm_cga,0
je no_roll_down
push bx
push cx
push dx
mov ch,ah
mov cl,0
mov dh,al
mov dl,num_screen_cols
dec dl
mov bh,color
mov ax,701h
int 10h
pop dx
pop cx
pop bx
clc
ret
no_roll_down:
stc
ret
public hardware_roll_up
hardware_roll_up:
;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
; otherwise, exit with cy=1. The hardware roll must leave the last line
; on the screen as the last line.
;preserve bx.
cmp ibm_cga,0
je no_roll_up
push bx
push cx
push dx
mov ch,ah
mov cl,0
mov dh,al
mov dl,num_screen_cols
dec dl
mov bh,color
mov ax,601h
int 10h
pop dx
pop cx
pop bx
clc
ret
no_roll_up:
stc
ret
public set_screen_color
set_screen_color:
;enter with al=fore color, ah=back color
shl ah,1
shl ah,1
shl ah,1
shl ah,1
or al,ah
mov color,al
ret
code ends
end