	 page	 ,132
         title   *** SLIDE SHOW ***
;***************************************************************
;                                                              *
;                         Jay Kadashaw  1984                   *
;                                                              *
;***************************************************************


;***************************************************************
;                                                              *
;               8088 interrupt locations                       *
;                                                              *
;***************************************************************
vectors  segment at  0h
         org     9h*4
keyboard_int_vector   label  dword
         org     10h*4
video_int_vector   label  dword
         org     24h*4
error_int_vector      label  dword
vectors  ends


;***************************************************************
; This is the data area starting at 400h used by the ROM BIOS  *
;routines.  ADDR_6845 contains the base address, 3x4, of the   *
;current display adapter and CRT_MODE_SET contains the current *
;setting of the display mode -- the 3x8 register.  Here x B    *
;for the monochrome display adapter, and D for the             *
;color-graphics adapter.                                       *
;***************************************************************

rom_bios_data   segment at 40h
         org    10h
;***************************************************************
;                                                              *
;          - - - - - - - - I - - - - - - - - equip_flag        *
;                                ^ ^ -- display type           *               *
;  display type 1 - color card 40x25                           *
;               2 - color card 80x25                           *
;               3 - monochrome display                         *
;                                                              *
;  see p. A-73 of the Ref. Manual for a definition of          *
;  equip_flag                                                  *
;                                                              *
;***************************************************************

equip_flag      dw     ?     ;Used to determine display type
                org    17h
kb_flag         db     ?
alt_shift       equ    08h   ;alternate shift key depressed
ctl_shift       equ    04h   ;control shift key depressed
left_shift      equ    02h   ;left shift key depressed
right_shift     equ    01h   ;right shift key depressed
                org    49h
crt_mode        db     ?     ;current crt mode
crt_cols        dw     ?     ;number of columns on screen
crt_len         dw     ?     ;length of regen in bytes
crt_start       dw     ?     ;starting address in crt buffer
cursor_posn     dw     8 dup(?) ;curson for each of up to 8 pages
cursor_mode     dw     ?     ;Current cursor mode(start, stop line)
active_page     db     ?
addr_6845       dw     ?     ;Base address for active display card
crt_mode_set    db     ?     ;current setting of 3x8 register
crt_palette     db     ?
rom_bios_data  ends


graphics_memory	segment at 0b800h
graphics_word	dw	?
graphics_memory	ends

               page
	 subttl  DEFINITION OF MACROS
scroll	 macro
         mov     ah,6        ;scroll to clear screen
         mov     al,0        ;clear screen
         mov     bh,7        ;normal attribute
         mov     cx,0        ;row,column of upper left corner of
;                             scroll
         mov     dh,24       ;row of lower right corner
         mov     dl,79       ;column of lower right corner
	 bioscall	     ;invoke bios to scroll window
	 endm
;
bioscall macro
	 int   10h	     ;request bios service, id in ah
	 endm
;
locate	 macro row,col
;        call BIOS to do LOCATE
         mov   dh,row        ;row
         mov   dl,col        ;column
         mov   bh,0          ;screen number
	 mov   ah,2	     ;function selected = locate
	 bioscall	     ;invoke bios to move the cursor
	 endm
;
doscall  macro
	 int   21h	     ;request dos service, id in ah
	 endm
;
display  macro text
	 mov   dx,offset text ;Point to message to print.
	 mov   ah,9	      ;Function selected = console output
	 doscall
	 endm
;
keyboard macro  response
	 mov	ah,10	      ;Function selected = read keyboard
	 lea	 dx,response
	 doscall
	 endm
;
setdta	 macro	our_dta
	 mov	ah,01ah       ;Function selected = set dta
	 lea	dx,our_dta
	 doscall
	 endm
;
create	 macro	fcb
	 mov	ah,016h       ;Function selected = create fcb
	 lea	dx,fcb
	 doscall
	 endm
;
delete	 macro	fcb
	 mov	ah,013h       ;Function selected = delete file
	 lea	dx,fcb
	 doscall
	 endm
;
srch_dir macro	fcb
	 mov	ah,011h       ;Function selected = search unopened
	 lea	dx,fcb        ; directory
	 doscall
	 endm
;
close	 macro	fcb
	 mov	ah,010h       ;Function selected = close fcb
	 lea	dx,fcb
	 doscall
	 endm
;
rwrite	 macro	fcb
	 mov	ah,022h       ;Function selected = random write
	 lea	dx,fcb
	 doscall
	 endm
;
default  macro	drive
	 mov	ah,019h       ;read default drive
	 doscall
         inc    al
	 mov	drive,al
	 endm
;
biosprnt macro   what
         local   next
         mov     si,offset what
next:
         mov     ah,14
         mov     bh,0
         mov     al,byte ptr [si]
         push    cx
         mov     cx,1
         int     10h
         pop     cx
         inc     si
         cmp     byte ptr [si],'$'
         jne     next
         endm
;
biosread macro
         mov     ah,0
         int     16h
         endm
;
set_background macro  color
         mov      bh,0              ;set backround
         mov      bl,color
         and      bl,1fh
         mov      ah,11
         int      10h
         endm
;
set_palette macro  color
         mov      bh,1              ;set pallete
         mov      bl,color
         mov      cl,5              ;shift right 5 bits
         shr      bl,cl
         mov      ah,11
         int      10h
         endm
;
set_mode macro   mode
         mov     ah,0         ;set graphics mode
         mov     al,mode
         int     10h
         endm
	 page
         SUBTTL  MAIN LINE CODE
code	 segment
         assume    cs:code
         org       80h
parmlen  db        ?
         db        ?
parm1    db        ?
parm2    db        ?
         org       100h
begin:   jmp       init     ;initialize vectors and attach to DOS
;
;
slide      db   0
fcb	   db	2,'slide   '
file_ascii db   '000'
           db   2 dup (0)
recd_size  dw	1
	   db	17 dup (0)
recd_num   dw	0
	   dw	0
;
screen	   db	4000h dup (0)
;**************************************************************
;      a copy of the video display data area                  *
;                                                             *
;      This copy is filled in each time int 10h is called.    *
;**************************************************************
crt_mode_2      db     ?     ;current crt mode
crt_cols_2      dw     ?     ;number of columns on screen
crt_len_2       dw     ?     ;length of regen in bytes
crt_start_2     dw     ?     ;starting address in crt buffer
cursor_posn_2   dw     8 dup(?) ;curson for each of up to 8 pages
cursor_mode_2   dw     ?     ;Current cursor mode(start, stop line)
active_page_2   db     ?
addr_6845_2     dw     ?     ;Base address for active display card
mode_reg	   db  ?     ;current setting of the 3x8 register
;                             port address 3d8
color_select_reg   db	 0   ;current color setting pallete card
;                             port address 3d9h


;**************************************************************
;      a second copy of the video display data area           *
;**************************************************************
video_state     db     ?     ;current crt mode
                dw     ?     ;number of columns on screen
                dw     ?     ;length of regen in bytes
                dw     ?     ;starting address in crt buffer
                dw     8 dup(?) ;curson for each of up to 8 pages
                dw     ?     ;Current cursor mode(start, stop line)
                db     ?
                dw     ?     ;Base address for active display card
           	   db  ?     ;current setting of the 3x8 register
;                             port address 3d8
                   db	 0   ;current color setting pallete card
;                             port address 3d9h
screen_loc dw	0b800h
message1   db	'filename=$'
message2   db	'Invalid file name!  Re-enter$'
no_space   db	'Insufficient space to add file!$'
newdisk    db	'Insert a new disk$'
proceed    db   "Proceed (y/n)? $"
proceed2   db   'Press any key to continue $'
badparms   db   'Invalid parameter(s)!!!$'
file_exists db  'Re-use existing file (y/n)? $'
abort_or_retry db  'Abort, or Retry?$'
err0	db	'Attempt to write on write-protected disk$'
err1	db	'Unknown unit$'
err2	db	'Drive not ready$'
err3	db	'Unknown command$'
err4	db	'Data error (CRC)$'
err5	db	'Bad request structure length$'
err6	db	'Seek error$'
err7	db	'Unknown media type$'
err8	db	'Sector not found$'
err9	db	'Printer out of paper$'
erra 	db	'Write fault$'
errb	db	'Read fault$'
errc	db	'General failure$'
x_err   dw	err0
	dw	err1
	dw	err2
	dw	err3
	dw	err4
	dw	err5
	dw	err6
	dw	err7
	dw	err8
	dw	err9
	dw	erra
	dw	errb
	dw	errc
re_try     db   "Enter 'y' to re-try $"
file	   db	15,0,15 dup (' ')
	   db	0dh
pri        db   0
ext        db   0
search     db   0
row        db   24
col        db   0
flag       db   0
test1      db   02h          ;left shift key depressed
test2      db   01h          ;right shift key depressed
rom_keyboard_int dd          ;address of rom keyboard interrupt
rom_video_int    dd          ;address of rom video interrupt
rom_error_int	dd	;address of rom error interrupt
cr	      equ   0dh      ;carriage return
drive	      equ   fcb
file_name     equ   fcb+01h
file_ext      equ   fcb+09h
current_block equ   fcb+0ch
record_size   equ   fcb+0eh
pfks   db  '1 Mode   2 Background   3 Palette   4 Replace   5 Save'
       db  '  [Esc]=[Exit]$'
replace	db	's'
graphics   db   1
color_original db 0
back_ground db   0
equip_save dw   0
         page
kbint	 proc	near
         assume ds:nothing
         jmp     tst_flgs
kbint2:
         pop     ds
         pop     ax
;        pushf                         ;simulate int 09h
         call    rom_keyboard_int
         iret
;
tst_flgs:
	pushf                         ;save flags
         push    ax
         push    ds
       	 mov     ax,cs                  ;addressability to data
	 mov	 ds,ax                  ;segment
         cmp     slide,1                ;in slide show
         jne     tst_flgs2              ;no, test if we should be
         jmp     short kbint2           ;yes ==> get out
tst_flgs2:
         mov     ax,rom_bios_data
         mov     ds,ax
         assume  ds:rom_bios_data
         mov     al,kb_flag
         push    ax
         mov     ax,cs
         mov     ds,ax
         assume  ds:code
         pop     ax
         and     al,test1               ;left shift depressed
         jz      kbint2                 ;no get out
         mov     ax,rom_bios_data
         mov     ds,ax
         assume  ds:rom_bios_data
         mov     al,kb_flag
         push    ax
         mov     ax,cs
         mov     ds,ax
         assume  ds:code
         pop     ax
         and     al,test2	;right shift depressed
         jz      kbint2 	;no get out
         mov     slide,1	;indicate within slide show code
         sti			;enable interrupts

	push	ds		;save equip_flag upon entry
	mov    bx,rom_bios_data
	mov    ds,bx
	assume ds:rom_bios_data
	mov    ax,equip_flag
	assume  ds:code
	pop    ds
	mov    equip_save,ax

         pushf
         call    rom_keyboard_int
         push    bx
         push    cx
         push    dx
         push    si
         push    di
         push    es

;	The video state at entry to Slide is saved.  note: this
;	may be different than that saved by int 10h, since the
;	extension to int 10h only save the video state if the
;	monochrome monitor is not being used.

	lea	 di,video_state  ;offset of mode register
         call	 save_screen

	mov    al,color_select_reg
	mov    color_original,al
         call	 save_screen_memory

;	change equip_flag if necessary to indicate graphics board

         mov    ax,equip_save
         and    ax,30h                     ;turn off all but display
         cmp    ax,30h                     ;monochrome
         jne    not_mono                   ;no ==> don't change
         push   ds
         mov    bx,rom_bios_data
         mov    ds,bx
         assume ds:rom_bios_data
         and    byte ptr equip_flag,0cfh    ;turn off display bits
         or     byte ptr equip_flag,10h     ;color card 40x25
         pop    ds
         assume ds:code
not_mono:

save_file:

;        set mode - 80x25 Color, Alpha

         push    ax
         mov     al,3
         mov     ah,0
         int     10h
         pop     ax

         mov     row,24            ;force scroll
 	 call	 get_file_name
         cmp     ax,2              ;Esc?
         jnz     not_esc
     	 jmp 	 rest
not_esc:
         call    loc_proc
         biosprnt proceed
 	 biosread          	   ;read response from keyboard
         mov  ah,14                ;display the character
         int  10h
	 cmp  al,'Y'
         je   do_wrt
         cmp  al,'y'
         je   do_wrt
	 cmp  al,'N'
         je   rest
         cmp  al,'n'
         je   rest
         jmp  not_esc
do_wrt:	mov 	replace,'s'
	call    dsk_write
rest:	 call	 restore_screen
	 biosread         	   ;read response from keyboard
	 page
;*******************************************************************
;                                                                  *
;        F1 is used to set the graphics mode                       *
;                                                                  *
;        F2 is used to set the back ground color                   *
;                                                                  *
;        F3 is used to set the medium resolution palette           *
;                                                                  *
;        F4 is used to replace the file (under the same name).     *
;                                                                  *
;        F5 is used to save the file.                              *
;                                                                  *
;*******************************************************************
;
         cmp    ah,3bh             ;F1?
         jne    not_f1             ;no ==> jmp
         mov    al,color_original
         mov    color_select_reg,al
         cmp    graphics,7
         jb     graphics_ok
         mov    graphics,1
;        mov    graphics,0
graphics_ok:
	cmp	graphics,2	;80x25 B/W, Alpha
	jne	graphics_ok_2
	inc	graphics
graphics_ok_2:
	cmp	graphics,5	;320x200 B/W, Graphics
	jne	graphics_ok_3
	inc	graphics
graphics_ok_3:
         mov    al,graphics
         mov    crt_mode_2,al
         inc    graphics
         jmp    rest
not_f1:
         cmp    ah,3ch             ;F2?
         jne    not_f2             ;no ==> jmp
;
;        set back ground color
;
         cmp    back_ground,32
         jb     do_f2
         mov    back_ground,0
do_f2:
         and    color_select_reg,0e0h
         mov    al,color_select_reg
         or     al,back_ground
         or     color_select_reg,al
         inc    back_ground
         jmp    rest
not_f2:
         cmp    ah,3Dh             ;F3?
         jne    not_f3             ;no ==> jmp
         xor    color_select_reg,20h
         jmp    rest
not_f3:
         cmp    ah,3eh             ;F4?
         jne    not_f4             ;no ==> jmp
	mov	replace,'r'
	call	dsk_write
	jmp    rest
not_f4:
         cmp    ah,3fh             ;F5?
         jne    not_f5             ;no ==> jmp
	jmp    save_file
not_f5:
         page
         cmp     crt_mode_2,3      ;a text mode?
         ja      not_text          ;no ==> branch
         mov     al,active_page_2  ;reset active page
         mov     ah,5
         int     10h
;
         mov     dx,cursor_posn_2  ;reset cursor position
         mov     bh,active_page_2  ;set active page
         mov     ah,2
         int     10h
;
         mov     cx,cursor_mode_2  ;set cursor lines
         mov     ah,1
         int     10h
not_text:

;	restore equip_flag

         mov    ax,equip_save
         and    ax,30h                     ;turn off all but display
         cmp    ax,30h                     ;monochrome
         jne    not_mono_2                 ;no ==> don't change
         push   ds
         mov    bx,rom_bios_data
         mov    ds,bx
         assume ds:rom_bios_data
         and    byte ptr equip_flag,0cfh    ;turn off display bits
         or     byte ptr equip_flag,10h     ;color card 40x25
         pop    ds
         assume ds:code
not_mono_2:

;	 restore video display data area

	 mov	 di,0449h
 	 lea	 si,video_state
	 mov	 ax,0	     ;point es to segment 0000h
	 mov	 es,ax
         mov     cx,30
	 rep     movsb

         mov     slide,0           ;screen image created
         pop     es
         pop     di
         pop     si
         pop     dx
         pop     cx
         pop     bx
         pop     ds
         pop     ax
         popf
	 iret
kbint    endp
	 page
	 subttl  save_screen procedure
save_screen proc near
	push	ax
	push	si	;save registers modified by save screen
	push	es
	push	cx

;	 save video display data area

;        offset to DOS's copy of mode register
	 mov	 si,0449h
	 mov	 ax,ds	     ;addressability to destination string
	 mov	 es,ax

;	The destination is established by the calling routine

;	 lea	 di,crt_mode_2   ;offset of mode register
	 push	 ds	     ;save ds
	 mov	 ax,0	     ;point ds to segment 0000h
	 mov	 ds,ax
         mov     cx,30
	 rep     movsb
	 pop	 ds	     ;restore ds

	pop 	cx	;restore registers modified by save screen
	pop 	es
	pop 	si
	pop	ax
	 ret
save_screen endp



save_screen_memory	proc	near
	 mov	 ax,ds
	 mov	 es,ax	   ;addressability to destination string
	 push	 ds	   ;save ds reg.
	 mov	 di,offset screen ;destination offset

; establish addressability to screen memory

	 mov	 ax,screen_loc
	 mov	 ds,ax
;
	 mov	 si,0	   ;source offset
	 mov	 cx,4000h  ; length of move
	 rep	 movsb	   ;move it
	 pop	 ds	   ;restore ds reg.
	ret
save_screen_memory	endp
         page
	 subttl   GET_FILE_NAME PROCEDURE
get_file_name proc near
new_scrn:
         mov  col,0
loc:     call loc_proc
         biosprnt message1

; clear file_name field in fcb

ask_file: clc
	 mov  di,offset file_name
	 mov  ax,ds
	 mov  es,ax
	 mov  al,' '
	 mov  cx,13
	 rep  stosb
	 call get_file
         cmp  ax,1           ;Valid file name?
         jnz  val_2
         jmp  loc
val_2:   cmp  ax,2           ;Esc?
         jnz  val_3
         ret
val_3:
	 cmp  ax,0	     ;Valid file name?
	 jnz  loc            ;no ==> branch
	 ret                 ;return if valid file name
get_file_name endp
         page
	 subttl  GET_FILE PROCEDURE
get_file proc	 near
	 default drive

;	 get filename

         mov  di,0
         mov  cx,15
	mov	col,9
	locate	row,col
once_more:
         biosread
         cmp  ah,1                 ;Scan code for Esc?
         jne  not_esc_2
         mov  ax,2                 ;indicate Esc
         ret
not_esc_2:
	cmp	al,0		;extended code?
	jne	not_extended
	cmp	ah,4dh		;scroll right?
	je	once_more	;yes ==> ignore it
	cmp	ah,4bh		;scroll left
	jne	not_extended
is_back:
	cmp	col,10
	jb	once_more
	dec	col
	locate	row,col
	mov	al,' '		;print a blank
	push	cx
	mov	cx,1		;number of characters to write
         mov  ah,10                ;display the character
         int  10h
	dec	di
	mov  file+2[di],al        ;store the code
	pop	cx
	inc	cx
	jmp	once_more
not_extended:
	cmp	ah,0eh		;backspace?
	je	is_back
         cmp  al,0dh               ;Carriage return?
         je   save_cnt             ;if so, finish up
         mov  file+2[di],al        ;store the code
         inc  di
	push	cx
	mov	cx,1		;number of characters to write
         mov  ah,10                ;display the character
         int  10h
	inc	col
	locate	row,col
	pop	cx
         loop once_more
save_cnt:
         mov   cx,di               ;save character count
         mov   col,0

;	 move file to file_name

	 mov  bx,offset file+2
	 cmp  byte ptr [bx]+1,':'
	 jne  no_device
	 cmp  byte ptr [bx],'A'       ;drive must be between A and B
	 jb   invalid_file2
	 cmp  byte ptr [bx],'D'
	 ja   short check_lower    ;maybe lower case?
	 mov  al,[bx]	     ;put in proper format for fcb
	 sub  al,64
	 jmp  drive2	     ;go insert drive no. in fcb
check_lower:  cmp  byte ptr [bx],'a'
	 jb   invalid_file2
	 cmp  byte ptr [bx],'d'
	 ja   invalid_file2
	 mov  al,[bx]	     ;put in proper format for fcb
	 sub  al,96
drive2:  mov  drive,al	     ;insert drive no. in fcb
	 add  bx,2	     ;point past ':'
	 sub  cx,2
no_device:
         mov  pri,0
         mov  ext,0
         mov  search,0       ;looking at primary name
	mov  di,offset file_name
	mov	al,[bx]

;        check first character of file name

         cmp  al,'A'
         jb   invalid_file2
         cmp  al,'Z'
         ja   chka
         jmp  good_char
chka:    cmp  al,'a'
         jb   invalid_file2
         cmp  al,'z'
         ja   invalid_file2
         jmp  good_char
invalid_file2: jmp invalid_file
nxt_char: mov  al,[bx]
	 cmp  byte ptr [bx],'.'
	 jne  notdot
         cmp  pri,0          ;Was there a primary?
         je invalid_file     ;no ==> branch
         mov  search,1       ;looking at extension
	 inc  bx
	 dec  cx
         mov  di,offset file_ext
	 jmp  nxt_char
notdot:
	 cmp  byte ptr [bx],cr	      ;carriage return?
	 je   got_em2
         cmp  al,'#'
         jb   invalid_file
         cmp  al,')'
         ja   chk2
         jmp  good_char
chk2:    cmp  al,'0'
         jb   invalid_file
         cmp  al,'9'
         ja   chk3
         jmp  good_char
chk3:    cmp  al,'A'
         jb   invalid_file
         cmp  al,'Z'
         ja   chk4
         jmp  good_char
chk4:    cmp  al,'a'
         jb   invalid_file
         cmp  al,'z'
         ja   chk5
         jmp  good_char
chk5:    cmp  al,'{'
         je   good_char
         cmp  al,'}'
         je   good_char
         jmp  invalid_file
good_char:
	 mov  [di],al
	 inc  bx	     ;get next character
	 inc  di
         cmp  search,0       ;primary?
         jne  not_pri
         inc  pri
         jmp  short loopit
not_pri: inc  ext
loopit:	 loop nxt_char
got_em2: cmp  pri,9      ;check length of primary and
         jb   chk_ext        ;extension
         jmp  short invalid_file
chk_ext: cmp  ext,4
         jae  short invalid_file
         mov  ax,0	     ;indicate valid filename found
	 ret
invalid_file:
         call loc_proc
         biosprnt  message2
	 mov  ax,1	   ;indicate invalid file
	 ret
get_file endp
;
         page
         subttl  SUB-ROUTINE TO CREATE DISK FILE
DSK_WRITE PROC NEAR

;        determine if file already exists
srch:
       	cmp replace,'r'
	je	newfile
         srch_dir fcb
         cmp     al,0ffh           ;branch if new file
         je      newfile
ask_again:
         call    loc_proc
         biosprnt file_exists
	 biosread        	   ;read response from keyboard
         mov  ah,14
         int  10h
	 cmp  al,'Y'
         je   newfile
         cmp  al,'y'
         je   newfile
	 cmp  al,'N'
         je   go_back
         cmp  al,'n'
         je   go_back
	jmp	ask_again
go_back:
         ret
newfile: setdta  screen

;	before issueing an rwrite set error interrupt (int 24h)
;       to point to error_handler

;        save original segment and offset addresses for int 24h

         mov     ax,vectors
         mov     es,ax
         assume es:vectors
         mov     ax,error_int_vector
         mov     rom_error_int,ax
         mov     ax,error_int_vector[2]
         mov     rom_error_int[2],ax

;        setup our own error interrupt routine

         mov     error_int_vector,offset error_handler
         mov     error_int_vector[2],cs
         assume  es:nothing
         create  fcb


	push	ax	;save ax - return code from create

;        reset pointer to interrupt 24h

         mov     ax,vectors
         mov     es,ax
         assume es:vectors
         mov     ax,rom_error_int
         mov     error_int_vector,ax
         mov     ax,rom_error_int[2]
         mov     error_int_vector[2],ax
        pop	ax	;restore ax
         assume  es:nothing


	 cmp	 al,0	     ;open ok?
	 jz	 open_ok
	 biosprnt newdisk
open_ok: mov	 recd_size,401eh ;record size
	 mov	 cx,01h ;number of records

	 rwrite  fcb
	 cmp	 al,0	   ;ok? 				       
         jne     close_fcb
	 jmp	 write2
close_fcb:
         close   fcb
         delete  fcb
         call    loc_proc
         biosprnt no_space
         call    loc_proc
         biosprnt re_try
         biosread                  ;read & display response
         mov  ah,14
         int  10h
 	 cmp  al,'Y'               ;retry?
         jne  tryy
         jmp  srch
tryy:
         cmp  al,'y'
         jne  back                 ;no ==> return
back2:   jmp  srch
back:    ret
write2:  close   fcb
         ret
error_handler:
         push    es	;must preserve es
	push	ax
	push	ds
	push	bx
	push	dx
	push	cx
	mov	ax,cs
	mov	ds,ax
         mov     slide,0
  	inc 	row
	locate	row,col
	mov	cl,2
	shl	di,cl
	mov	si,[x_err+di]
next_char:
         mov     ah,14
         mov     bh,0
         mov     al,byte ptr [si]
         push    cx
         mov     cx,1
         int     10h
         pop     cx
         inc     si
         cmp     byte ptr [si],'$'
         jne     next_char
once_again:
  	inc 	row
	locate	row,col
	biosprnt	abort_or_retry
 	 biosread          	   ;read response from keyboard
         mov  ah,14                ;display the character
         int  10h
	 cmp  al,'a'
         je   abort_it
	 cmp  al,'A'
         je   abort_it
	 cmp  al,'r'
         je   retry_it
	 cmp  al,'R'
         je   retry_it
	jmp	once_again
retry_it:
	mov	slide,1	;reset slide
	pop	cx
	pop	dx
	pop	bx
	pop	ds
	pop	ax
	pop	es
	mov	al,1	;retry
	iret
abort_it:

;        reset pointer to interrupt 24h

         mov     ax,vectors
         mov     es,ax
         assume es:vectors
         mov     ax,rom_error_int
         mov     error_int_vector,ax
         mov     ax,rom_error_int[2]
         mov     error_int_vector[2],ax
         assume  es:nothing
	pop	cx
	pop	dx
	pop	bx
	pop	ds
	pop	ax
	pop	es
	mov	al,2	;terminate program
	iret
DSK_WRITE ENDP




loc_proc proc
         inc  row
         cmp  row,24
         jb   loc5
         scroll
         locate 24,0
         biosprnt pfks
         mov  row,1
loc5:    locate  row,col
         ret
loc_proc endp
         page
	 subttl  restore_screen procedure
restore_screen proc   near

         set_mode  crt_mode_2

;        disable video

         mov    ax,rom_bios_data
         push   ds
         mov    ds,ax
         assume ds:rom_bios_data
         mov    dx,addr_6845   ;get base address for display adapter
         add    dx,4           ;IO address for 3x8 register
         mov    al,crt_mode_set ;current setting
         and    al,0f7h         ;turn video off
         out    dx,al
         pop    ds
         assume ds:nothing

         set_background   color_select_reg

         set_palette      color_select_reg

;        move original graphics screen back to graphics memory

	 mov	 ax,screen_loc
	 mov	 es,ax	   ;addressability to destination string
	 lea	 si,screen ;load offset of source into si
	 mov	 di,0	   ;load offset of destination
	 mov	 cx,4000h  ; length of move
	 rep	 movsb	   ;move it

;        enable video

         mov    ax,rom_bios_data
         push   ds
         mov    ds,ax
         assume ds:rom_bios_data
         mov    dx,addr_6845   ;get base address for display adapter
         add    dx,4           ;IO address for 3x8 register
         mov    al,crt_mode_set ;current setting
         or     al,08h          ;turn video on
         out    dx,al
         pop    ds
         assume ds:nothing

	 ret               ; return
restore_screen endp
         page
	subttl	Video I/O Interrupt Routine
video_routine	 proc	near
         assume ds:nothing
	pushf				;simulate int 10h
	call    rom_video_int
	push    ax
	push	bx
	push    ds
	mov     ax,cs                  ;addressability to data
	mov	 ds,ax                  ;segment
	cmp     slide,1                ;in slide show
	jne     not_in_slide
is_mono:
	pop	ds
	pop	bx
	pop	ax
         iret
not_in_slide:

;	only save video information if configured for graphics.

	push	ds
	assume ds:nothing
	mov    bx,rom_bios_data
	mov    ds,bx
	assume ds:rom_bios_data
	mov    ax,equip_flag      ;save equip-flag upon entry
	assume ds:nothing
         and    ax,30h	;turn off all but display
         cmp    ax,30h	;monochrome
	pop	ds
         jne    not_mono_3
	jmp	is_mono
not_mono_3:
	push	di
	lea	 di,crt_mode_2   ;offset of mode register
	call	save_screen
	pop	di
	pop	ds
	pop	bx
	pop	ax
	iret
video_routine	 endp
	page
         subttl  INITIALIZE INTERRUPT VECTORS
init     proc  near
         mov     ax,cs
         mov     ds,ax

	mov	es,ax
      	assume     es:code

;	verify that the graphics board is installed

	mov    bx,graphics_memory
	push   ds
	mov    ds,bx
	assume ds:graphics_memory
	mov	ax,graphics_word	;read word from memory
	inc	ax			;increment word
	mov	graphics_word,ax	;write word to memory
	mov	bx,graphics_word	;re-read word
	cmp	ax,bx			;changed?
	jne	not_graphics		;yes ==> jmp
	dec	ax			;restore original word
	mov	graphics_word,ax
	jmp	is_graphics
not_graphics:
	mov	ax,es
	mov	ds,ax
	display graphics_required
	int	20h
graphics_required db 'The graphics board is required for this '
		  db 'program!!!$'
is_graphics:
	pop	ds
         assume    ds:code
         cmp     parmlen,0         ;Any parms?
         je      install           ;No ==> jmp
         mov     al,parm1          ;check validity of 1st parm
         call    chk_parm
         cmp     al,00h
         je      bad_parm          ;1st parm bad ==> jmp
         mov     test1,al          ;replacement for left shift
         cmp     parmlen,2         ;Is there a second parm?
         je      install           ;No ==> jmp
         mov     al,parm2          ;check if second parm is valid
         call    chk_parm
         cmp     al,00h
         je      bad_parm          ;2nd parm bad ==> jmp
         mov     test2,al          ;replacement for right shift
         jmp     install
bad_parm:
         biosprnt badparms
         int      20h                   ;get out
install:
         assume ds:vectors

;        save original segment and offset addresses for int 09h

         mov     ax,vectors
         mov     ds,ax
         cli				;disable all interrupts

;	save the address of the original int 09h routine

         mov     ax,keyboard_int_vector
         mov     rom_keyboard_int,ax
         mov     ax,keyboard_int_vector[2]
         mov     rom_keyboard_int[2],ax

;        setup our own keyboard interrupt routine

         mov     keyboard_int_vector,offset kbint
         mov     keyboard_int_vector[2],cs

;	save the address of the original int 10h routine

         mov     ax,video_int_vector
         mov     rom_video_int,ax
         mov     ax,video_int_vector[2]
         mov     rom_video_int[2],ax

;        setup our own video I/O interrupt routine

         mov     video_int_vector,offset video_routine
         mov     video_int_vector[2],cs

         sti                            ;enable interrupts
         call    set_cursor_mode        ;set cursor mode to default

;        Terminate but stay resident.
;        dx is set to the last address + 1 to stay resident.

         lea     dx,init
         int     27h
init     endp


chk_parm   proc   near

;          a = <alt>, c = <ctrl>, l = <left shift>, r = <right shift>

           cmp    al,'a'
           je     is_alt
           cmp    al,'A'
           je     is_alt
           cmp    al,'c'
           je     is_cntl
           cmp    al,'C'
           je     is_cntl
           cmp    al,'l'
           je     is_lefts
           cmp    al,'L'
           je     is_lefts
           cmp    al,'r'
           je     is_rights
           cmp    al,'R'
           je     is_rights
           sub    al,al         ;error
           ret
is_alt:    mov    al,alt_shift
           ret
is_cntl:   mov    al,ctl_shift
           ret
is_lefts:  mov    al,left_shift
           ret
is_rights: mov    al,right_shift
           ret
chk_parm   endp



set_cursor_mode  proc  near
         push  ax
         push  cx
         push  ds
         mov   ax,rom_bios_data
         mov   ds,ax
         assume ds:rom_bios_data
         mov    ax,equip_flag      ;determine which adapter is active
         and    al,30h             ;isolate adapter information
         mov    cx,607h            ;set for color/graphics adapter
         cmp    al,30h             ;is monochrome display active
         jne    color_active       ;No, set cursor type
         mov    cx,0b0ch           ;cursor mode for monochrome display
color_active:
         mov    ah,1               ;set-cursor type
         int    10h
         pop    ds
         pop    cx
         pop    ax
         ret
set_cursor_mode endp
code	 ends
	end	 begin
                                                                                                                       begin
                                                                                                                      