Subj : futil.asm To : BEN RITCHEY From : Paul Williams Date : Thu Sep 12 2002 12:50 am Hi BEN RITCHEY, hope you are having a nice day Here's the original code for futil.com from the bnu fossil archive. Next msg I'll post just the bits I modified for the additional response codes along w/ what I'd like to try to add. ---futil.asm--- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; FOSSIL/Modem Testing Utility ;; Copyright (c) June, 1992 ;; 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 1992 Original release ; V1.10 July 1992 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 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) 1992 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 ---------------- -=> Yours sincerely, Paul Williams <=- .... "Hey Jamie. Haul your butt over here and do what you do best!--Mandy --- Terminate 4.00/Pro * Origin: Reality crept in... I shot it for trespassing (1:387/710) .