home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 11 Util
/
11-Util.zip
/
KBRATE2.ZIP
/
KBRATE.ASM
next >
Wrap
Assembly Source File
|
1991-04-28
|
14KB
|
360 lines
; Modified 4/28/91 for OS/2 1.3
; (needed more stack space)
; also reformatted usage blurb
; and said what AT default is.
;
; Joel Apisdorf
;
; P.S. I did not write this in the first place
;;
NAME KBRATE
.286p
_DATA SEGMENT WORD PUBLIC 'DATA'
_DATA ENDS
STACK SEGMENT PARA STACK 'STACK'
STACK ENDS
_TEXT SEGMENT BYTE PUBLIC 'CODE'
_TEXT ENDS
KBDIO SEGMENT BYTE PUBLIC 'CODE'
KBDIO ENDS
DGROUP GROUP _DATA,STACK
_DATA SEGMENT
ASSUME DS:DGROUP
intro DB "KBRATE -- Set PC-AT keyboard repeat rate [OS/2 Version 1.03]",13,10
DB 10,10,"$"
INTROLEN EQU $-intro-1
invletter DB " Invalid letter for repeat rate",13,10,"$"
INVLETTERLEN EQU $-invletter-1
invnumeral DB " Invalid numeral for delay time",13,10,"$"
INVNUMERALLEN EQU $-invnumeral-1
kbrateusage DB "Usage: KBRATE xy",13,10
DB 13,10
DB "Where: 'x' is a letter A..Z which gives the repetition rate",13,10
DB " in characters per second (A = fastest)",13,10
DB 13,10
DB " Some useful values are:",13,10
DB " A = 30, C = 24, E = 20",13,10
DB " I = 15, M = 10, Q = 7.5",13,10
DB 13,10
DB " 'y' is a numeral 1..4 which gives the time delay",13,10
DB " between a key's first depression",13,10
DB " and the start of its repetition,",13,10
DB " in units of a quarter of a second",13,10
DB 13,10
DB " The OS/2 default on my machine is:",13,10
DB " KBRATE M2",13,10
DB 13,10,"$"
KBRATEUSAGELEN EQU $-kbrateusage-1
kbrateset DB " Keyboard rate set",13,10,"$"
KBRATESETLEN EQU $-kbrateset-1
notset DB " I/O error: Keyboard rate not set",13,10,"$"
NOTSETLEN EQU $-notset-1
cmdlineseg DW 0 ; selector for command line
cmdlineoff DW 0 ; offset of command line in segment
saveoffset DW 0000h
savesegment DW 0000h
savebyte DB 00h
savebyte2 DB 00h
savebyte3 DB 00h
_DATA ENDS
STACK SEGMENT
ASSUME SS:STACK
mystack DW 100h DUP (?)
stacktop DW 0000
STACK ENDS
_TEXT SEGMENT
ASSUME CS:_TEXT,DS:DGROUP
; +-------------------------------------------------------------------+
; | Symbols |
; +-------------------------------------------------------------------+
keyboard_cmd equ 064h ; keyboard command register
keyboard_status equ 064h ; same register for status
keyboard_data equ 060h ; port to write data to
kbd_inbuf_full equ 02h ; bit mask for kbd ibf
kbd_outbuf_full equ 01h ; bit mask for kbd obf
std_mode_cmd equ 0ADh ; command for i-s mode
dec_mode_cmd equ 0ACh ; command for DEC mode
kbd_ack equ 0FAH ; acknowledge from keyboard
;
; +-------------------------------------------------------------------------+
; | Variables |
; +-------------------------------------------------------------------------+
;
PRTMSG MACRO msg,msglen
XOR AX,AX ; handle of stdout for OS/2
PUSH AX
MOV AX,msglen ; the length of the message
PUSH AX
MOV AX,OFFSET msg ; the message
PUSH DS
PUSH AX
CALL DOSPUTMESSAGE
ENDM
IFREAL MACRO target
PUSH AX ; create stack space for answer
MOV AX,SP ; prepare pointer to this byte
PUSH SS ; push ptr to this byte SS:AX
PUSH AX
CALL DOSGETMACHINEMODE
POP AX ; adjust stack & get result into AL
CMP AL,00h ; real mode?
JZ target
ENDM
IFPROT MACRO target
PUSH AX ; create stack space for 1 byte
MOV AX,SP ; prepare pointer to this byte
PUSH SS ; push ptr to this byte SS:AX
PUSH AX
CALL DOSGETMACHINEMODE
POP AX ; adjust stack & get result into AL
CMP AL,01h ; prot mode?
JZ target
ENDM
EXTRN DOSPUTMESSAGE:FAR
EXTRN DOSEXIT:FAR
EXTRN DOSGETMACHINEMODE:FAR
main PROC NEAR
; AX:BX points to the command line under OS/2
; AX:0000h is our environment under OS/2
; ES:0080h is length of arguments under DOS
; ES:0081h is start of command line under DOS
MOV WORD PTR cmdlineseg,AX ; save ptr to command line
MOV WORD PTR cmdlineoff,BX ; (even if not under OS/2)
; display our welcome message
PRTMSG intro,INTROLEN
;
;
; In OS/2, the command line is at AX:BX (cmdlineseg:cmdlineoff)
; In DOS, the command line is at ES:0081h (length at ES:0080h)
dosparse: ; parse command line under MS-DOS
CALL NEAR PTR getinit ; set up for parsing
; CX now has the # of bytes
OR CX,CX ; JCXZ usage
JNZ dosparse1
JMP usage
dosparse1: CALL NEAR PTR getchar
CMP AL,20h ; is it a space?
JZ dosskipwhite
CMP AL,09h ; is it a <tab>?
JZ dosskipwhite
CMP AL,00h ; null (end of cmd line)?
JNZ doseval ; no: evaluate
JMP usage ; yes: no arguments present
dosskipwhite: LOOP dosparse1
JMP usage
doseval: ; check for a valid letter A..Z (after capitalizing)
AND AL,0DFh
SUB AL,41h ;'A'
CMP AL,19h
JBE goodletter
PRTMSG invletter,INVLETTERLEN ; bad letter
JMP badness
goodletter: MOV BYTE PTR savebyte,AL
CALL NEAR PTR getchar
SUB AL,31h ;'1'
CMP AL,03h ; in 1..4?
JBE goodnumber
PRTMSG invnumeral,INVNUMERALLEN
JMP badness
goodnumber: MOV BYTE PTR savebyte2,AL ; now compute magic #
MOV AL,BYTE PTR savebyte2 ;
MOV CL,05h ;
SHL AL,CL ;
OR AL,BYTE PTR savebyte ;;
PUSH AX ; save the speed
; AL now has the speed byte that we want (also on stack)
; Now that we have our magic number for the keyboard in AL
; and on top of the stack, lets send out the commands!
mov al,0F3h ; set rate command
call FAR PTR send_cmd ;
pop ax ; restore the speed into AX
jc badness2 ;;
call FAR PTR send_cmd ; now send out the speed
jc badness2 ;;
mov al,0F4h ; enable keyboard
call FAR PTR send_cmd ;
jc badness2 ;;
PRTMSG kbrateset,KBRATESETLEN
goodness: ; terminate w/no error
XOR AX,AX
PUSH AX
PUSH AX
CALL DOSEXIT
usage: PRTMSG kbrateusage,KBRATEUSAGELEN
JMP badness
badness2: PRTMSG notset,NOTSETLEN
badness: ; terminate with error
MOV AX,0001h
PUSH AX
PUSH AX
CALL DOSEXIT
main ENDP
; +-------------------------------------------------------------------+
; | getinit - initialize for getting characters from command line. |
; | Set up ES:SI to point to the command line. |
; | Also, skip program name when under OS/2. |
; | CX is set to the length of the command line arguments. |
; +-------------------------------------------------------------------+
getinit PROC NEAR
getinitp: ; protected mode init
MOV AX,WORD PTR cmdlineseg
MOV ES,AX
MOV SI,WORD PTR cmdlineoff
; now ES:SI points to program name (which we must skip)
CMP BYTE PTR ES:[SI],00h ; special case (no args)
JZ giend
giskip: MOV AL,BYTE PTR ES:[SI] ; look at next character
CMP AL,20h ; a space?
JZ giend ; yes: exit
CMP AL,00h ; a separator (or end)?
JZ giend ; yes: exit
INC SI ; no: loop
JMP giskip ;;
giend: SMSW AX ; get machine status word -> AX
TEST AX,0001h ; in protected mode?
JZ skiplsl ; no: skip LSL instruction
MOV AX,ES ; get selector in AX
LSL CX,AX ; get segment limit
;; Special code to ensure last byte is 00h in command line
; PUSH BX
; MOV BX,CX
; MOV BYTE PTR ES:[BX],00h ; make sure last byte is 00h
; POP BX
JMP postlsl
skiplsl: MOV CX,0010h ; lie about # of bytes there
postlsl: SUB CX,SI ; subtract start
SUB CX,0002h ; less null terminators
RET
getinit ENDP
; +-------------------------------------------------------------------+
; | getchar - return the next character in AL at ES:SI. |
; +-------------------------------------------------------------------+
getchar PROC NEAR
MOV AL,BYTE PTR ES:[SI] ; get the byte
INC SI
CMP AL,00h ; arg separator?
JNZ getend ; no: return
MOV AH,BYTE PTR ES:[SI] ; peek at next char
CMP AH,00h ; is next char null?
JZ getend ; yes: return null
MOV AL,20h ; no: return a space
getend: RET
getchar ENDP
_TEXT ENDS
KBDIO SEGMENT
ASSUME CS:KBDIO,DS:DGROUP
send_cmd proc far
mov bx,ax ; save command
xor cx,cx ; wait a long time
cli ; so BIOS can't get in the way
in al,keyboard_data ; clear outbut buffer
wait_kbd: in al,keyboard_status ; read status
test al,kbd_inbuf_full ; is input buffer full?
loopnz wait_kbd ; keep waiting
jcxz timeout ; if timeout
mov al,bl ; get back command
out keyboard_data,al ;
; now, wait for the acknowledge
xor cx,cx ; timeout
wait_ack: in al,keyboard_status ; read status
test al,kbd_outbuf_full
loopz wait_ack ; wait for ACK
jcxz timeout ; timed out
in al,keyboard_data ; read byte
cmp al,kbd_ack ; is it an ACK?
jnz wait_ack ; nope.
sti ; ok to use port now
clc ; no errors
ret
timeout: sti ; ok to use port now
stc ; error waiting for kbd
ret
send_cmd ENDP
KBDIO ENDS
END main