home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
ASSEMBLE
/
BNUUTIL
/
FUTIL
/
FUTIL.ASM
next >
Wrap
Assembly Source File
|
1989-07-31
|
17KB
|
647 lines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; FOSSIL/Modem Testing Utility
;; Copyright (c) June, 1989
;; Unique Computing Pty Limited & David Nugent
;; FidoNet Node 3:632/348.0
;; Alternet Node 7:833/387.0
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; This utility is useful for testing various aspects of FOSSIL-aware software,
; by simulating a modem and enabling the user to set or reset certain status
; information returned by the FOSSIL to an application.
;
; It was created primarily to simulate a remote modem connect for testing
; purposes using a direct wire but allowing direct control from local keyboard.
;
; FUTIL installs as a TSR wedge between the FOSSIL and an application. It
; requires that a revision 5 FOSSIL driver be installed prior to it, and it
; will capture INT 14H (it looks like a FOSSIL to the application) and
; intercept certain FOSSIL calls in order to carry out its simulation.
;
; This utility is particularly useful because it is release WITH SOURCE.
; It can therefore be modified and re-assembled to carry out any simulation
; required, but this will take a little knowledge in how FOSSIL operates
; and some expertise in PC operations in general.
;
; Please read the accompanying documentation for license details and caveats.
;
; V1.00 June 1989 Original release
; V1.10 July 1989 Small bug fix: purging FOSSIL
; receive buffer now clears pending input
; status bit (previously this would look
; effectively hang a machine with some s/w).
;
; NOTE: MASM 5.10 or TASM 1.0 is required to assembly this program!
; Earlier versions of MASM will NOT work.
;
; Provides TASM->MASM compatibility
ifdef ??version
masm51
quirks
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Definitions/readability section
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CDSIG equ 0F23DH ; FUTIL's signature
MAGIC equ 01954H ; FOSSIL's magic number
DOS equ 021H ; DOS interrupt
TSR equ 027H ; .COM TSR call
; Keyboard shift key codes
CTRL equ 004H ; Ctrl key is down
SHIFTS equ 003H ; Any shift pressed
LSHIFT equ 002H ; Left shift
RSHIFT equ 001H ; Right shift
ALT equ 008h ; Alt key pressed
NUMLOCK equ 020H ; Numlock state
; BIOS ports, data area definitions
SH_STATE equ 0417H ; Shift state byte
KBD_PORT equ 060H ; Keyboard data port
KBD_CTRL equ 061h ; Keyboard control port
LSC equ (LSHIFT or CTRL) ; Shorthand for Ctrl-LShift
KUSED equ 0FH ; Bits used in shift mask
; FOSSIL status bits
PS_CARRIER equ 0080H ; Carrier signal from MSREG
PS_RXCHARS equ 0100H ; Characters in input buffer
;;;;;;;;;;;;;;;;
;;
;; Start program
;;
;;;;;;;;;;;;;;;;
_code segment para public 'code'
assume CS:_code
org 100h ; .COM start
; Jump to install (which is unloaded on TSR
start:
jmp install
;
; Int 14H entry point
;
even
Int_14:
jmp SHORT parse
;
; FOSSIL data section
;
oldvec dd 0 ; Old INT 14H vector
dw MAGIC ; Make it look like a FOSSIL
dw 001bH ; Revision 5 type
dw CDSIG
kbdvec dd 0 ; Old INT 09H vector
;
port dw 0 ; Port number
;
; Status information
;
; WARNING: DO NOT CHANGE THE ORDER AND CONTENTS OF THIS SECTION
; WITHOUT CONSIDERING THE 'HOTKEYS' SECTION BELOW. THESE
; VARIABLES CORRESPOND DIRECTLY TO THE HOKEY STRUCTURE!!
;
even
cstate dw 0 ; Carrier detect mask (default no extra)
cdmask dw -1 ; Status mask out bits (default leave alone)
tdata dw 0 ; Ignore transmit data flag
rdata dw 0 ; Receive data flag
isdata dw 0 ; Is data to send flag
strp dw 0 ; Pointer to current string
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; INT 14H handler
;; Only a subset of commands are intecepted
;; Tests code in AH, otherwise passes control
;; to the installed FOSSIL driver
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
parse PROC NEAR
sti
cld
cmp DL,BYTE PTR CS:[port] ; Select only for current port
je @F
jmp DWORD PTR CS:[oldvec]
@@:
cmp AH,01H ; Transmit data
je @istxch
cmp AH,02H ; Receive data
je @isrxch
cmp AH,03H ; Port status
jne @F
jmp @isstat
@@:
cmp AH,0AH ; Receive buffer purge
je @isrp
cmp AH,0BH ; Transmit no wait
je @istxnw
cmp AH,0CH ; Read, no wait
je @ispeek
cmp AH,18H ; Receive block
jne @F
jmp @isrxb
@@:
cmp AH,19H ; Transmit block
jne @norm
jmp @istxb
; ---------------------
; Read, non-destructive
; ---------------------
@ispeek:
cmp CS:[isdata],0 ; Is there data to be returned?
je @norm
push BX
mov BX,CS:[strp]
mov AL,CS:[BX] ; Get next character
pop BX
xor AH,AH
jmp @bye
; ---------------------
; Transmit no wait call
; ---------------------
@istxnw:
cmp CS:[tdata],0 ; Eat character
je @norm
mov AX,1 ; 1 = successfully sent
jmp @bye
; -----------------------------------------
; Purge receive buffers (and pending input)
; -----------------------------------------
@isrp:
mov CS:[isdata],0
mov CS:[strp],0
and CS:[cstate],not PS_RXCHARS ; Reset "chrs in rx buf" status bit
jmp SHORT @norm
; ------------------
; Transmit character
; ------------------
@istxch:
cmp CS:[tdata],0 ; Eat character
jne @F
jmp @isstat
@@:
mov AL,03H ; Force a status call
jmp @isstat
@norm:
jmp DWORD PTR CS:[oldvec] ; Jump straight to old vector
; -----------------
; Receive character
; -----------------
@isrxch:
cmp CS:[isdata],0 ; Is there data to be returned?
je @rch
@isrxch1:
push BX
mov BX,CS:[strp]
mov AX,CS:[BX] ; Get next character
pop BX
inc CS:[strp] ; Move pointer to next character
or AH,AH ; Test for end of string
jne @F
and CS:[cstate],not PS_RXCHARS ; Reset "chrs in rx buf" status bit
mov CS:[isdata],0
@@:
xor AH,AH
jmp SHORT @bye
@rch:
cmp CS:[rdata],0 ; Give control to FOSSIL?
je @norm
sti
push AX
mov AH,3 ; Else get status
int 14H
test AX,PS_RXCHARS ; Are there characters in buffer?
pop AX
je @isrxch
cmp CS:[isdata],0 ; Is there data to be returned?
jne @isrxch1
jmp SHORT @norm
; -------------------
; Transmit block data
; -------------------
@istxb:
cmp CS:[tdata],0 ; Eat character
je @norm
mov AX,CX ; Return number of characters 'sent'
jmp SHORT @bye
; ------------------
; Receive block data
; ------------------
@isrxb:
cmp CS:[isdata],0 ; Is there data to be returned?
je @norm
push DI ; Hmm, better get to work ...
push CX
push BX
cld ; Required for string opcodes
mov BX,CS:[strp] ; Get pointer to string
jcxz @up ; Opps, zero chrs requested
@@:
mov AX,CS:[BX] ; Get next character
inc BX
stosb ; Store it in user buffer
or AH,AH ; Test for end of string
je @F
loop @B ; Until user buffer full
jmp SHORT @up
@@: ; No more available at this point
and CS:[cstate],not PS_RXCHARS ; Reset "rx chrs avail" status bit
mov CS:[isdata],0
xor BX,BX
@up:
mov CS:[strp],BX ; Update string pointer
mov AX,CX ; Save remaining number of characters
pop BX ; Restore all registers
pop CX
pop DI
sub AX,CX ; Calculate/return # of bytes received
neg AX
jmp SHORT @bye
; -------------------
; Status call handler
; -------------------
@isstat:
pushf ; Simulate the old INT 14H
call DWORD PTR CS:[oldvec]
or AX,CS:[cstate] ; OR in set mask
and AX,CS:[cdmask] ; AND out reset mask
@bye:
iret ; Return to user
parse ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Configuration section
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; This section contains information which can be modified to suit.
;
;
; Modem control strings
; Various strings returned by a typical modem, available by 'hotkey'
;
; STATUS
nocarrier db 'NO CARRIER',13,10,0
ok db 'OK',13,10,0
error db 'ERROR',13,10,0
busy db 'BUSY',13,10,0
ring db 'RING',13,10,0
rring db 'RRING',13,10,0
voice db 'VOICE',13,10,0
; CONNECTS
connect db 'CONNECT',13,10,0
connect300 db 'CONNECT 300',13,10,0
connect1200 db 'CONNECT 1200',13,10,0
connect2400 db 'CONNECT 2400',13,10,0
connect24rel db 'CONNECT 2400/REL',13,10,0
connect9600 db 'CONNECT 9600',13,10,0
connectfast db 'CONNECT FAST',13,10,0
;
; This next section is a series of structures which allows a 'hotkey'
; combination to be tied to a given action. The structures contain the
; contents of the INT 14H variables used in the above intercept routines
; and pressing the hotkey combination simply copies in values for these
; variables setting of a reaction by the next intercepted INT 14H call.
;
notkey STRUC
scanc db ? ; Keyboard scan code (returned by KB ROM)
kshft db ? ; Keyboard shift state (BIOS)
cmask dw ? ; Status OR mask (force these bits on)
cbits dw ? ; Status AND mask (force these bits off)
itx dw ? ; Ignore transmited data flag (don't give to FOSSIL)
irx dw ? ; Don't call FOSSIL to receive data flag
srx dw ? ; Is there data to 'receive' flag
dofs dw ? ; Offset of string to 'receive'
notkey ENDS
SZ_ka equ <size notkey> ; Size of one hotkey structure
KEYS equ 20 ; Defines how many structures to scan
;
; Hot keys table
;
even
KeyCodes label word
notkey <29H, LSC, 0000H, not 0000H, 00H, 00H, 00H, 0 > ; cs` Turns all processing off
notkey <0bH, LSC, 0000H, not 0080H, 00H, 00H, 00H, 0 > ; cs0 Force no carrier
notkey <18H, LSC, 0100H, not 0080H, 00H, 01H, 01H, ok > ; csO 'OK'
notkey <12H, LSC, 0100H, not 0080H, 00H, 01H, 01H, error > ; csE 'ERROR'
notkey <31H, LSC, 0100H, not 0080H, 00H, 01H, 01H, nocarrier > ; csN 'NO CARRIER'
notkey <30H, LSC, 0100H, not 0080H, 00H, 01H, 01H, busy > ; csB 'BUSY'
notkey <21H, LSC, 0180H, not 0000H, 00H, 01H, 01H, connectfast > ; csF 'CONNECT FAST'
notkey <0aH, LSC, 0180H, not 0000H, 00H, 01H, 01H, connect9600 > ; cs9 'CONNECT 9600'
notkey <04H, LSC, 0180H, not 0000H, 00H, 01H, 01H, connect24rel> ; cs3 'CONNECT 2400/REL'
notkey <03H, LSC, 0180H, not 0000H, 00H, 01H, 01H, connect2400 > ; cs2 'CONNECT 2400'
notkey <02H, LSC, 0180H, not 0000H, 00H, 01H, 01H, connect1200 > ; cs1 'CONNECT 1200'
notkey <13H, LSC, 0100H, not 0080H, 00H, 01H, 01H, ring > ; csR 'RING'
notkey <2fH, LSC, 0100H, not 0080H, 00H, 01H, 01H, voice > ; csV 'VOICE'
notkey <17H, LSC, 0100H, not 0080H, 00H, 01H, 01H, rring > ; csI 'RRING'
notkey <00H, 00H, 0000H, not 0000H, 00H, 00H, 00H, 0 >
notkey <00H, 00H, 0000H, not 0000H, 00H, 00H, 00H, 0 >
notkey <00H, 00H, 0000H, not 0000H, 00H, 00H, 00H, 0 >
notkey <00H, 00H, 0000H, not 0000H, 00H, 00H, 00H, 0 >
notkey <00H, 00H, 0000H, not 0000H, 00H, 00H, 00H, 0 >
notkey <00H, 00H, 0000H, not 0000H, 00H, 00H, 00H, 0 >
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Keyboard (hardware) interrupt handler
;;
;; This routine is triggered on make or break (press or release)
;; of ANY key on the keyboard. The KB port is then inspected to
;; see which key was pressed, and the current shift status read.
;; The above hotkeys table is then scanned for a match; if found,
;; the rest of the structure is copied into the variable space,
;; otherwise the call passes to the previous INT 9H handler.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Int_9 PROC FAR
assume DS:nothing,ES:nothing ; Could (and will) be anywhere
push AX ; Must preserve EVERY register here
push CX
push DI
push ES
xor AX,AX
mov ES,AX
in AL,KBD_PORT ; Scan code of key pressed
mov AH,ES:[SH_STATE] ; Current shift state bits
and AH,KUSED ; Mask out unused bits
mov DI,offset KeyCodes ; Scan key codes table
mov CX,KEYS
@@:
cmp AX,CS:[DI]
je @F
add DI,SZ_ka
loop @B
; Key was not found
pop ES ; Restore saved registers
pop DI
pop CX
pop AX
jmp CS:[kbdvec] ; Pass though to original vector
;
; Key combo found; take action
;
@@:
in AL,KBD_CTRL ; Save value of kbd control lines
mov AH,AL
or AL,80H ; Set kbd enable bit
out KBD_CTRL,AL
mov AL,AH
out KBD_CTRL,AL
mov AL,20H ; Signal end of HW interrupt to 8259A
out 20H,AL
push BX
xor BX,BX
mov CX,SZ_ka/2
jmp SHORT @F
@Clp:
mov AX,CS:[DI+BX] ; Copy variables to intercept data area
mov CS:[BX+offset cstate-2],AX
@@:
inc BX
inc BX
loop @Clp
pop BX ; Restore registers
pop ES
pop DI
pop CX
pop AX
iret
Int_9 ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; End resident section
;;
;; The rest of this code is discarded on installation as a TSR, and
;; does not consume additional memory
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Installation messages
msg_nofos db 7,'No FOSSIL driver installed',13,10,'$'
msg_instald db 7,'FUTIL is already installed',13,10,'$'
msg_instnot db 7,'FUTIL is not installed',13,10,'$'
msg_instok db 'FUTIL is now active',13,10,'$'
msg_inval db 7,'Invalid command line option',13,10,'$'
msg_unloaded db 'FUTIL successfully unloaded',13,10,'$'
msg_start db 'FUTIL v1.10 FOSSIL Communications Companion Utility',13,10
db 'Copyright (C) 1989 David Nugent & Unique Computing Pty Ltd',13,10
db '$'
; ----------------------
; Installation procedure
; ----------------------
install PROC NEAR
assume ds:_code ; DS = CS by default
mov DX,offset msg_start ; Output our logo
mov AH,9
int DOS
cld ; Required for string opcodes
mov SI,81H ; Start of command line
@Top:
lodsb
cmp AL,13 ; Test for end of cmdline
je @Load
cmp AL,0
je @Load
cmp AL,32 ; Skip spaces,
je @Top
cmp AL,9 ; and tabs
je @Top
cmp AL,'/' ; Looking for a valid switch
je @F ; character (- or / will do)
cmp AL,'-'
je @F
@nogood:
mov AL,3 ; Something else is invalid
mov DX,offset msg_inval
jmp ExitMsg
;
; Read switch value
;
@@:
lodsb
cmp AL,'a' ; Convert to uppercase
jb @F
cmp AL,'z'
ja @F
sub AL,'a'-'A'
@@:
cmp AL,'U' ; /U = Uninstall
je @Unload
cmp AL,'P' ; /P = Port number
jne @nogood
lodsb
cmp AL,'0' ; Convert # to binary
jb @nogood
cmp AL,'9'
ja @nogood
sub AL,'0'
xor AH,AH
mov port,AX ; Save in our local variable
jmp SHORT @Top
;
; Unload from memory
;
@Unload:
call ChkLoad ; See if FUTIL is loaded
cmp ES:[BX+10],CDSIG ; Is this program installed?
mov DX,offset msg_instnot
mov AL,2
jne ExitMsg
push DS ; Preserve DS for later
push ES
push ES
pop DS
mov DX,word ptr [kbdvec]
mov DS,word ptr [kbdvec+2]
mov AX,2509H ; Release keyboard
int DOS
pop DS
mov DX,word ptr [oldvec]
mov DS,word ptr [oldvec+2]
mov AX,2514H ; Release INT 14H
int DOS
pop DS
mov AH,49H ; Deallocate memory (at ES)
int DOS
mov DX,offset msg_unloaded
xor AL,AL
jmp SHORT ExitMsg
;
; Load into memory
;
@Load:
call ChkLoad ; Check to see if we're loaded
cmp ES:[BX+10],CDSIG ; Is this program installed?
mov DX,offset msg_instald
mov AL,2
je ExitMsg
mov DX,offset Int_14 ; Install vector for INT 14H
mov AX,2514H
int DOS
mov AX,3509H ; Get keyboard vector
int DOS
mov word ptr [kbdvec],BX
mov word ptr [kbdvec+2],ES
mov DX,offset Int_9
mov AX,2509H ; Intercept keyboard
int DOS
mov AX,CS
mov ES,AX
mov ES,ES:[02cH] ; Free our environment
mov AH,049H
int DOS
mov DX,offset msg_instok
mov AH,09H ; Print message
int DOS
mov DX,offset msg_nofos ; Stay resident
int TSR
install ENDP
;
; Exit (abort) with a message
;
ExitMsg PROC NEAR
push AX ; Save exit code
mov AH,09H ; Print message
int DOS
pop AX
mov AH,4cH ; And exit
int DOS
ExitMsg ENDP
;
; Check to see if already loaded
;
ChkLoad PROC NEAR
mov AX,3514H ; Get int 14H vector
int DOS
mov word ptr [oldvec],BX ; And save it
mov word ptr [oldvec+2],ES
cmp ES:[BX+6],MAGIC ; Is a FOSSIL there?
mov DX,offset msg_nofos
mov AL,1
je @F
pop BX
mov BX,offset ExitMsg
push BX
@@:
ret
ChkLoad ENDP
_code ends
end start