home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
sampler0
/
newinit.asm
< prev
next >
Wrap
Assembly Source File
|
1987-05-05
|
18KB
|
574 lines
title newinit.asm
comment |--------------------------------------------------------------
In text modes the active page can be switched between 1-4 (80-col) or
1-8 (40-col) by pressing ALT and the corresponding # on the TOP ROW. This
feature can only be used to view the other pages. Results of all CON I/O
while paging are unpredictable and messy.
As protection against duplicate installation, INT 15h with AX = X'FF00'
returns AX = X'ABCD'.
The keypad "5" key will toggle processing. While paused, a flashing,
highlighted "P" will appear in the lower-right corner (not graphics).
If Numlock is on, shift-"5" is required. If Alt or Ctrl are pressed, nothing
changes. Scroll Lock, Caps Lock, and Ins are irrelevant.
This program sets the video mode to 80 col monochrome.
The enhanced keyboard can be toggled on/off with Alt-PrtSc, and a 1/8 sec
2000 Hz tone will sound when toggled on. (The PrtSc modification cannot
be turned off.)
NOTE: If both shift keys are depressed at installation time, the
installation will be cancelled, with errorlevel set to X'AB'.
------------------------------------------------------------------------|
bios_data segment at 0040h
org 17h
kb_flag db ? ; keyboard status byte
kb_flag_1 db ?
org 49h
v_mode db ? ; BIOS video mode
v_width db ? ; BIOS screen width
org 62h
v_page db ? ; BIOS video page
mystery_w dw ? ; word used by pause routine
mystery_b db ? ; byte used by pause routine
bios_data ends
cseg segment
assume cs:cseg
org 80h
parm_cnt db ? ; parameter count
parm_data db ? ; start of parameter data space
org 100h ; .COM file
begin: jmp init_vectors ; initialize and attach to DOS
; addresses of video and keyboard I/O ROM routines
prtsc dd 0 ; INT 5
kybd dd 0 ; INT 9
cass dd 0 ; INT 15h
kybd_io dd 0 ; INT 16h
; constants and segments
bios_dat dw 40h ; bios_data segment
mono_seg dw 0b000h ; segment of MGA
color_seg dw 0b800h ; segment of CGA
datatbl db 2,3,0,1,6,4,5 ; scan-code to video mode data
indicator equ "P"+256*10001111b ; an highlighted, flashing "P"
row equ 24 ; position of indicator for mono moniter
col equ 79
mono_point equ 2*((row*80)+col) ; offset in mono segment
; variable data
vdata db 0 ; current video mode or page
code_seg dw 0 ; CS of resident routines
graph_bit db 0 ; flag to signal graphics mode
toggle db 1 ; enables/disables enhanced keyboard
prtsc_int: sti ; enable interrupts
push ax ; save regs
push dx
mov ah,2 ; read printer status
xor dx,dx ; zero DX - LPT1
int 17h ; printer I/O
xor ah,30h ; check for OFFLINE
jnz chk_shft ; skip beep, prepare for exit
pop dx
no_dump: pop ax
iret
chk_shft: pop dx
push ds
mov ds,bios_dat ; set DS = X'40'
assume ds:bios_data
test kb_flag,00000010b ; check for LEFT shift key
pop ds ; restore regs
jz no_dump ; skip screen dump if no LEFT shift
pop ax
jmp prtsc ; print screen routine
calculate: assume ds:bios_data
xor ax,ax ; zero AX
xor cx,cx ; likewise
mov al,v_width ; AX = 00 width
mov cl,v_page ; save for later multiply
mov bx,25 ; calculate offset into page
mul bl
dec ax ; = (25*width)-1
shl ax,1 ; MUL AX,2 - skip attribute bytes
mov bx,ax ; save in BX
mov ax,2048 ; byte length of 40 column page
cmp v_width,40 ; check for 40 column screen
je multiply ; if yes, leave AX alone
shl ax,1 ; if no, change to 80 column offset
multiply: mul cx ; multiply by page number
add bx,ax ; sum buffer offset with page offset
mov es,color_seg ; load ES with CGA segment
assume es:nothing
skip_cga: mov cx,es:[bx] ; save screen data in CX
mov word ptr es:[bx],indicator ; store flashing "P" on screen
rejoin: ; branch made if graphics mode - skip indicator
mov dx,mystery_w ; load mystery word
add dx,4 ; more mysterious code
mov al,mystery_b ; load mystery byte
out dx,al ; I have no clue what this does
call reset
or kb_flag_1,00001000b ; turn ctrl-num-lock on
sti ; enable interrupts
again: test kb_flag_1,00001000b ; check if ctrl-num-lock on
jnz again ; if on, check again
cli ; disable interrupts (play it safe)
test graph_bit,1 ; check if graphics mode
mov graph_bit,0 ; reset graphics flag
jnz skip_mov ; skip restoration of screen data
mov es:[bx],cx ; restore screen data
skip_mov: pop es ; restore regs
pop dx
pop cx
pop bx
pop ds
pop ax
iret
pause: assume ds:bios_data ; DS set in FIVE: routine
push bx ; save BX (for active page)
push cx ; save CX to use as scratch register
push dx
push es
cmp v_mode,4 ; check for text mode
jb calculate ; continue if yes
cmp v_mode,7 ; check for monochrome buffer
jne no_p ; skip "P" if graphics
mov es,cs:mono_seg ; point ES to segment at 0b000h
mov bx,mono_point ; offset into monochrome segment
jmp short skip_cga ; skip color setup
no_p: mov graph_bit,1 ; set graphics mode flag
jmp short rejoin ; rejoin main code
yes: and kb_flag_1,11110111b ; turn ctrl-num-lock off
call reset ; reset keyboard
pop ds
pop ax
iret
assume ds:nothing
five: push ds ; save data segment
mov ds,cs:bios_dat ; point to keyboard data
assume ds:bios_data
test kb_flag_1,00001000b ; check if Ctrl-NumLock on
jnz yes ; if yes, unpause
mov al,kb_flag ; get shift key status byte
test al,00001100b ; check for Alt or Ctrl pressed
jnz quit ; exit if so
and al,00100011b ; isolate NumLock and Shift bits
jz pause ; if zero (none pressed) then go!
cmp al,00100000b
ja pause ; both NumLock & Shift must be pressed
; if not, then end
assume ds:nothing
quit: pop ds ; restore regs
pop ax
jmp kybd ; goto BIOS
assume ds:nothing
; intercepts INT 9
kybd_int: push ax ; save reg
in al,60h ; get scan code
cmp al,37h ; scan code of PrtSc key
je tog_chk ; check for Alt pressed before toggling
test toggle,1 ; check if enhanced keyboard enabled
jz off ; if not, skip enhanced processing
cmp al,4ch ; scan code of keypad "5" ?
je five ; if yes, check further
cmp al,46h ; check for Scroll-Lock (Break) key
je break ; if so, look for Ctrl-Shift
off: pop ax ; if not, restore reg and
jmp kybd ; goto BIOS
; check for right-shift-Ctrl
break: push ds ; save reg
mov ds,bios_dat ; set DS to bios data segment
assume ds:bios_data
test kb_flag_1,00001000b ; check if ctrl-num-lock on
jnz quit ; goto BIOS if yes
test kb_flag,00000001b ; right shift key pressed?
jz quit
test kb_flag,00000100b ; check for Ctrl key pressed
jz quit
call reset
mov ax,4ccah ; DOS EXIT function 4C
; ErrorLevel = 202
int 21h
pop ds ; restore regs
pop ax
iret ; return from key interrupt
tog_chk: push ds ; save DS
mov ds,bios_dat ; point DS to bios data segment
assume ds:bios_data
test kb_flag_1,00001000b ; check for Ctrl-NumLock pause on
jnz quit ; goto BIOS if yes
test kb_flag,00000111b ; check for Ctrl or L/R shift pressed
jnz quit ; don't toggle if yes - send key to bios
test kb_flag,00001000b ; check for Alt pressed
jz quit ; don't toggle if no - send key to bios
xor toggle,1 ; toggle
jz skip_beep ; skip beep if toggled off
push cx ; save count reg for delay
; beep
; Step 1 -- prepare the timer to receive its divisor
mov al,0b6h ; timer mode register signal
out 67,al ; output to timer control port
; Step 2 -- send the divisor count to the timer
; Divisor = (1,190,000 / desired frequency)
mov ax,595 ; divisor for 2000 Hz
out 66,al ; output low-order byte of divisor
mov al,ah ; high-order byte to output reg
out 66,al ; output high-order byte of divisor
; Step 3 -- turn on the two bits which activate the speaker, and the
; timer's control of the speaker
in al,97 ; get current bit settings - port 97
mov ah,al ; save port 97 to turn sound off
or al,03 ; turn on last two bits
out 97,al ; send back the new value
mov cx,8000h ; approx 1/8 second
delay: loop delay ; sounding tone while counting
mov al,ah ; restore original port 97
out 97,al ; stop tone
pop cx ; restore count reg
skip_beep: call reset ; reset kybd and interrupt controller
pop ds ; restore regs
assume ds:nothing
pop ax
iret
reset proc
in al,61h ; reset keyboard
mov ah,al
or al,80h
out 61h,al
mov al,ah
out 61h,al
mov al,20h ; send end-of-interrupt signal
out 20h,al ; to interrupt controller
ret
reset endp
assume ds:nothing
cass_int: cmp ax,0ff00h ; duplicate installation protection
je duped ; yes
jmp cass ; no, goto BIOS
duped: mov ax,0abcdh
iret
nope: jmp kybd_io ; goto BIOS
assume ds:nothing
kybd_io_int:
test toggle,1 ; check if enhanced keyboard enabled
jz nope ; if not, goto bios
test ah,ah ; check for AH = 0 (read key)
jnz nope ; if not, goto bios
pushf ; simulate INT 16h
call kybd_io
test al,al ; check for zero char code
jz extend ; continue if extended character
iret ; return if not
extend: cmp ah,53h ; skip predefined ext. functions
ja ext ; extended function routine(s)
back: iret ; return if predefined
; branch made if code greater than predefined (3-53h)
ext: cmp ah,94 ; check for F21 (CTRL-F1)
jb back ; end if below
cmp ah,103 ; CTRL-F10 - 67h
ja next ; goto next function
push dx ; save DX
push ax ; save scan code
mov ah,2 ; read printer status
xor dx,dx ; zero DX - LPT1
int 17h ; printer I/O
xor ah,30h ; check for OFFLINE
jz offline ; skip beep, prepare for exit
pop ax ; retrieve scan code
push bx
push cx
sub ah,94 ; bring scan code down to 0-9
; mult AH by 3
mov bl,ah ; save ah
shl ah,1 ; mult by 2
add bl,ah ; mult by 3
xor bh,bh ; zero BH
add bx,offset PRNT_BUF ; add mem loc to offset
mov cx,3 ; 3-char printer output
xor dx,dx ; printer zero
loop1: mov al,3 ; full offset
sub al,cl ; sub count from full offset
xlat cs:prnt_buf ; get data in AL
cmp al,0ffh ; check for end-of-string
je beep ; beep if EOS
xor ah,ah ; zero AH - print char
int 17h ; BIOS printer I/O
loop loop1 ; next char
beep: cmp cl,3 ; check for null string
je p_end ; skip beep if null
mov ax,0007 ; printer output / BEL
int 17h ; BIOS printer I/O
mov ax,000dh ; printer output / CR
int 17h ; BIOS printer I/O
p_end: pop cx
pop bx
sub sp,2 ; fool next POP
offline: pop ax
pop dx
xor ax,ax ; zero AX (read_char)
back3: jmp kybd_io_int ; goto BIOS for next key
next: cmp ah,113 ; code > Alt-F10 ?
ja next1 ; yes - goto
je cls ; if code = Alt-F10 - execute CLS
cmp ah,110 ; Alt-F7 < code < Alt-F10 ?
ja back3 ; null processing
push bx ; save base reg for XLAT
mov al,ah ; copy key code into AL for XLAT
sub al,104 ; bring key-code to 0-6
mov bx,offset datatbl ; look-up table of video modes
xlat cs:datatbl
xor ah,ah ; zero AH for INT 10h
int 10h
pop bx ; restore BX
; AH already zero - read_key
jmp kybd_io_int ; goto bios
cls: push bx
push cx
push dx
push ds
mov ds,bios_dat
assume ds:bios_data
mov bh,7 ; attribute to use on blank window
xor cx,cx ; upper left corner = 0,0
mov dh,24 ; bottom row to clear
mov dl,v_width ; bios video width byte
dec dx ; bios byte is either 40/80
mov ax,600h ; AH=6 (scroll up) AL=0 (blank window)
int 10h
mov bh,v_page ; get current video page
xor dx,dx ; upper left corner
mov ah,2 ; position cursor
int 10h
assume ds:nothing
pop ds ; restore regs
pop dx
pop cx
pop bx
xor ax,ax ; read_key
jmp kybd_io_int ; get next key
; code greater than 110, ALT-F7
next1: cmp ah,78h ; ALT-1 (top row)
jb end_ext ; end routine
cmp ah,127 ; check code > ALT-8
ja end_ext
push bx ; save regs
push ax
mov ah,15 ; read video state
int 10h
mov vdata,al ; save current mode
cmp al,3 ; check for graphics modes
ja back1 ; end if graphics
pop ax ; retrieve char code
mov al,ah ; char code into page result reg
sub al,78h ; bring char code down to page code
cmp al,4 ; check for valid code 80 or 40
jb skip1 ; change if valid unconditionally
cmp vdata,1 ; check for 40 col display
ja back2 ; end if 80 col
skip1: mov ah,5 ; select active display page
int 10h
jmp short back2 ; finished
end_ext: ; if key code not defined here,
iret ; give other routines a chance
back1: add sp,2 ; skip AX on stack
back2: pop bx ; restore BX
xor ax,ax ; zero AH - read key
jmp kybd_io_int ; get another char
; control codes for Gemini (Epson compatible)
prnt_buf db 27,"V",1 ; slashed-zero F1
db 27,"@",0ffh ; power-on reset F2
db 27,"B",1 ; 10 cpi (80 col) F3
db 15,0ffh,00 ; 17 cpi (132 col) F4
db 27,"E",0ffh ; emphasized on F5
db 27,"F",0ffh ; emphasized off F6
db 27,"S",0 ; superscript mode F7
db 27,"S",1 ; subscript mode F8
db 27,"U",1 ; unidirectional F9
db 27,"U",0 ; bidirectional F10
end_of_resident:
print_help:
xor cx,cx ; upper left row/column
mov dx,184fh ; lower right row/column
mov bh,7 ; attribute for blank region
mov ax,600h ; scroll up/blank entire window
int 10h
mov ah,15 ; get video data
int 10h ; active page in BH
xor dx,dx ; upper left row/column
mov ah,2 ; set cursor position
int 10h
mov dx,offset help_text ; get address of help screen
mov ah,9 ; DOS print string
int 21h
mov ax,0ff00h ; check (again) for duplicate installation
int 15h
cmp ax,0abcdh
je skip_prnt ; if yes, skip printing install instructions
mov dx,offset not_yet ; message - type newinit install
mov ah,9 ; DOS print string
int 21h
skip_prnt: int 20h ; terminate
init_vectors:
mov ds,bios_dat
assume ds:bios_data
mov al,kb_flag ; get keyboard status byte
xor al,00000011b ; check if both shift keys pressed
jnz continue ; if not, continue with installation
mov ax,4cabh ; DOS EXIT function, ERRORLEVEL = X'AB'
int 21h
continue: mov ax,cs ; set data segment to code segment
mov ds,ax
assume ds:cseg
mov code_seg,ax ; save code segment for resident routine
xor cx,cx ; zero CX
mov cl,parm_cnt ; get number of parameters
jcxz print_help ; print help screen
mov si,offset parm_data ; start of parameter line
cld ; clear DF to increment SI
loop2: lods parm_data ; get byte from parm_data
cmp al,"Z"+1 ; check if lower case
jb lp2
sub al,"a"-"A" ; convert to lower case
mov [si-1],al ; put back into param line
lp2: loop loop2 ; get next char
check: mov di,offset parm_data
mov al,"I" ; search for "I"
mov cl,parm_cnt ; number of characters to search
repne scasb ; scan parameter line
jne print_help ; print help screen if not found
mov si,1 + offset key ; "INSTALL" but past the "I"
assume es:cseg
repne cmps parm_data,key ; check for key in parameter line
jne print_help ; if not found, print help screen
mov ax,0ff00h ; if found, check for prev install
int 15h ; cassette (snicker!) interrupt
cmp ax,0abcdh ; duplicate installation code
jne install ; full speed ahead
mov dx,offset already ; error message
mov ah,9 ; DOS print string
int 21h
int 20h ; bye-bye
install: mov ax,2 ; AH=0 - set video mode
; AL=2 - 80 col mono
int 10h
mov ax,3505h ; get int vector for INT 5
int 21h
mov word ptr prtsc,bx ; save routine offset
mov word ptr prtsc[2],es ; save routine segment
mov dx,offset prtsc_int ; offset of new routine
; DS = CS above
mov ah,25h ; set int vector for INT 5
int 21h
mov ax,3509h ; get int vector for INT 9
int 21h
mov word ptr kybd,bx ; save offset
mov word ptr kybd[2],es ; save segment
mov dx,offset kybd_int ; offset of user routine
mov ah,25h ; set int vector
int 21h
mov ax,3515h ; get int vector for INT 15h
int 21h
mov word ptr cass,bx ; save offset
mov word ptr cass[2],es ; save segment
mov dx,offset cass_int ; offset of user routine
mov ah,25h ; set int vector
int 21h
mov ax,3516h ; get int vector for INT 16h
int 21h
mov word ptr kybd_io,bx ; save offset
mov word ptr kybd_io[2],es ; save segment
mov dx, offset kybd_io_int ; offset of user routine
mov ah,25h ; set int vector
int 21h
mov dx,offset installed ; completed message
mov ah,9 ; DOS print string
int 21h
mov dx,offset end_of_resident
int 27h ; terminate, remain resident
key db "INSTALL" ; installation text key
already db 13,10,10,9,9
db "This utility already resident.",13,7,10,10,"$"
installed db 9,9,"NEWINIT is up and running.",10,10,"$"
help_text: db "This resident program modifies certain key combinations:",13,10
db "1) PrtSc will only work if the left shift key is used.",13,10
db "2) Ctrl-Right-Shift-Break forces a DOS function call X'4C' (EXIT) which will"
db 13,10
db " exit the current program. This avoids much of the need for Ctrl-Alt-Del."
db 13,10
db " If exit is forced in this manner, errorlevel is set to X'CA' (202).",13,10
db "3) Alt-1 thru Alt-8 (top row) will VIEW that display page (I/O not reliable)."
db 13,10
db "4) Alt-F1 thru Alt-F7 change the video mode.",13,10
db " F1 = 80 col mono (at startup) F2 = 80 col color",13,10
db " F3 = 40 col mono F4 = 40 col color",13,10
db " F5 = med res mono graphics F6 = medium res color graphics",13,10
db " F7 = high res graphics F10 = clears the current display page"
db 13,10
db "5) Ctrl-F1 thru Ctrl-F10 send (Epson) control codes to the printer.",13,10
db " F1 = slashed-zero F2 = power-on reset",13,10
db " F3 = 10 cpi (80 col) F4 = 17 cpi (132 col)",13,10
db " F5 = emphasized on F6 = emphasized off",13,10
db " F7 = superscript mode F8 = subscript mode",13,10
db " F9 = unidirectional F10 = bidirectional",13,10
db "6) The keypad '5' key is a toggle pause key. While on, the letter P is"
db 13,10
db " displayed, flashing and highlighted, in the lower right corner.",13,10
db "7) Alt-PrtSc will toggle the enhanced keyboard on/off. A beep signals on."
db 13,10,10,"$"
not_yet db 9,"To make NEWINIT resident, type: newinit install",13,10,10,"$"
cseg ends
end begin
move alt-fn and ctrl-fn to int-9