Category : Files from Magazines
Archive   : VOL8N8.ZIP
Filename : MOUSECTL.ASM

 
Output of file : MOUSECTL.ASM contained in archive : VOL8N8.ZIP
;------------------------------------------------------------------------;
; MOUSE.CTL - Enhances mouse sensitivity control. ;
; PC Magazine - Michael J. Mefford ;
;------------------------------------------------------------------------;
_TEXT SEGMENT PUBLIC 'CODE'
ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT,SS:_TEXT
ORG 100H
START: JMP INITIALIZE

; DATA AREA
; ---------
SIGNATURE DB CR,SPACE,SPACE,SPACE,CR,LF
COPYRIGHT DB "MOUSECTL 1.0 (C) 1988 Ziff Communications Co.",CR,LF
PROGRAMMER DB "PC Magazine ",BOX," Michael J. Mefford",CR,LF,LF,"$"
DB CTRL_Z

CR EQU 13
LF EQU 10
CTRL_Z EQU 26
SPACE EQU 32
BELL EQU 7
BOX EQU 254
IRET_CODE EQU 0CFH

OLD_INT_33 DW ?,?
OLD_INT_10 DW ?,?

VIDEO_MODE DB ?
DISPLAY_MODE EQU 49H ;BIOS data.
TEXT_MODE EQU 0 ;Text video mode flag.
GRAPHICS EQU 1 ;Graphics video mode flag.
CHAR_WIDTH DW ? ;Adjustment for text cell size.
GRAPHICS_WIDTH DW ? ;Adjustment for graphics cell.

MOUSE_VARIABLES LABEL BYTE
HORZ_LAST DW 0 ;Mouse driver mickey count total.
VERT_LAST DW 0
HORZ_ADJUSTED DW 0 ;Mickey total application sees.
VERT_ADJUSTED DW 0
HORZ_REMAINDER DW 0 ;Mickey adjustment remainder.
VERT_REMAINDER DW 0
HORZ_RATIO_REMAIN DW 0 ;Mickey per pixel remainder.
VERT_RATIO_REMAIN DW 0
HORZ_CURS_REMAIN DW 0 ;Text cursor mickey remainder.
VERT_CURS_REMAIN DW 0
CALL_MASK DW 0 ;Subroutine call mask.
INTERRUPT_SUB DW 0,0 ;Subroutine address.
VARIABLES_LENGTH EQU ($ - MOUSE_VARIABLES) / 2

HORZ_RATIO DW 8 ;Mickeys / 8 pixel ratio.
VERT_RATIO DW 16

RANGE DW 3, 5, 7, 9, 12, 23, 32; and above
MULTIPLIER DW 5, 6, 10, 15, 22, 30, 50, 70
MULTIPLIER_END EQU $ - 2
MULTIPLIER_LENGTH EQU ($ - MULTIPLIER) / 2

; CODE AREA
;************* INTERRUPT HANDLERS *************;

NEW_INT_33 PROC FAR
OR AX,AX ;Is it Reset and Status?
JNZ READ_MOUSE
CALL MOUSE_DRIVER ;If yes, call the driver.
PUSH AX ;Save output.
PUSH BX
PUSH CX
PUSH DX

CALL RESET ;Zero out our variables.
MOV CS:HORZ_RATIO,8 ;Restore mickey/pixel ratio.
MOV CS:VERT_RATIO,16
MOV CX,32767 ;Disable mouse driver cursor
MOV DX,CX ; control by setting Mickey
MOV AX,15 ; to Pixel ratio very large.
CALL MOUSE_DRIVER
MOV DX,10000 ;Disable Double-speed by setting
MOV AX,19 ; threshold very large.
CALL MOUSE_DRIVER
MOV CX,1 ;Install our interrupt subroutine
CALL SET_INTERRUPT

POP DX ;Restore returned values.
POP CX
POP BX
POP AX
IRET ;Return to caller.

READ_MOUSE: CMP AX,11 ;Is it Read Mouse
JNZ SUBROUTINE ; Motion Counters?
CALL MOUSE_DRIVER ;If yes, call driver.
CLI ;No interrupts, especially mouse.
MOV CX,CS:HORZ_ADJUSTED ;Return adjusted mickey count.
MOV DX,CS:VERT_ADJUSTED
MOV CS:HORZ_LAST,0 ;Reset driver mickey count.
MOV CS:VERT_LAST,0
MOV CS:HORZ_ADJUSTED,0 ;Reset adjusted mickey count.
MOV CS:VERT_ADJUSTED,0
IRET

SUBROUTINE: CMP AX,12 ;Is it Set Interrupt Subroutine
JNZ SET_RATIO ; Call Mask and Address?
MOV CS:CALL_MASK,CX ;If yes, store call mask.
MOV CS:INTERRUPT_SUB[0],DX ;Store address.
MOV CS:INTERRUPT_SUB[2],ES
PUSH CX ;Save call mask.
OR CX,1 ;Add Cursor position changes
CALL SET_INTERRUPT ; and install subroutine.
POP CX ;Restore CX.
IRET

SET_RATIO: CMP AX,15 ;Is it Set Mickey/Pixel Ratio?
JNZ SWAP_INT
MOV CS:HORZ_RATIO,CX ;If yes, store requested values.
MOV CS:VERT_RATIO,DX
IRET

SWAP_INT: CMP AX,20 ;Is it Swap Interrupt
JNZ DOUBLE_SPEED ; Subroutines?
PUSH CS:CALL_MASK ;If yes, save old call mask
PUSH CS:INTERRUPT_SUB[0] ; and subroutine address.
PUSH CS:INTERRUPT_SUB[2]
MOV CS:CALL_MASK,CX ;Store new call mask and
MOV CS:INTERRUPT_SUB[0],DX ; subroutine address.
MOV CS:INTERRUPT_SUB[2],BX
OR CX,1 ;Set our subroutine with
CALL SET_INTERRUPT ; new call mask.
POP BX ;Return old call mask and
POP DX ; subroutine address.
POP CX
IRET

DOUBLE_SPEED: CMP AX,19 ;Skip Double-Speed Threshold.
JZ INT_33_END
CMP AX,26 ;Skip Sensitivity.
JZ INT_33_END
JMP CS:DWORD PTR OLD_INT_33 ;Pass all other calls as is.
INT_33_END: IRET
NEW_INT_33 ENDP

;----------------------------------------------;
RESET: PUSH DI ;Preserve registers.
PUSH ES
PUSH CS
POP ES
XOR AX,AX ;Store zeros in appropriate
MOV DI,OFFSET MOUSE_VARIABLES ; mouse variables.
MOV CX,VARIABLES_LENGTH
CLD ;Forward direction.
CLI ;No interrupts.
REP STOSW
POP ES ;Restore registers.
POP DI
RET

;----------------------------------------------;
; INPUT: CX = Call Mask ;
;----------------------------------------------;
SET_INTERRUPT: PUSH AX ;Preserve registers.
PUSH DX
PUSH ES
PUSH CS
POP ES
MOV DX,OFFSET MOUSE_CONTROL ;Install our subroutine.
MOV AX,12
CALL MOUSE_DRIVER
POP ES ;Restore registers.
POP DX
POP AX
RET

;----------------------------------------------;
MOUSE_DRIVER: PUSHF
CLI
CALL CS:DWORD PTR OLD_INT_33
RET

;----------------------------------------------;
NEW_INT_10 PROC FAR
OR AH,AH ;Video mode change?
JZ INT_UPDATE ;If yes, update variables.
CMP AH,11H ;Is it User Alpha Load?
JAE INT_UPDATE ;If yes, update variables.
JMP CS:DWORD PTR OLD_INT_10 ;Else, no business.
INT_UPDATE: PUSHF ;Update by calling INT 10
CALL CS:DWORD PTR OLD_INT_10
CALL GET_BIOS_DATA ;Then retrieve video data.
IRET
NEW_INT_10 ENDP

;----------------------------------------------;
GET_BIOS_DATA: PUSH AX ;Preserve registers.
PUSH DS
MOV AX,40H ;Point to BIOS data.
MOV DS,AX
MOV AL,DS:DISPLAY_MODE ;Retrieve display mode.
PUSH CS
POP DS ;Point to our data.
MOV AH,TEXT_MODE ;Assume text mode.
MOV CHAR_WIDTH,16 ;Assume low resolution.
CMP AL,1 ;Is it 40 column?
JBE BIOS_END ;If yes, assumed right.
MOV CHAR_WIDTH,8 ;Else, assume high resolution.
CMP AL,3 ;Is it 80 column color or
JBE BIOS_END
CMP AL,7 ; MONO? If yes, assumed right.
JZ BIOS_END

MOV AH,GRAPHICS ;Else, gotta be graphics mode.
MOV GRAPHICS_WIDTH,1 ;Assume low resolution.
CMP AL,5 ;Is it mode 4, 5, D, or 13?
JBE BIOS_END ;If yes, assumed right?
CMP AL,0DH
JZ BIOS_END
CMP AL,13H
JZ BIOS_END
MOV GRAPHICS_WIDTH,0 ;Else gotta be high resolution.

BIOS_END: MOV DS:VIDEO_MODE,AH ;Store video mode.
POP DS ;Restore registers.
POP AX
RET

;----------------------------------------------;
MOUSE_CONTROL PROC FAR
PUSH AX ;Condition mask.
PUSH BX ;Button state.
PUSH DX ;Vertical cursor coordinate.
PUSH DI ;Vertical Mickeys.
MOV BP,CX ;Horizontal cursor coordinate.

PUSH CS ;Point to our data
POP DS
PUSH CS ; and extra segment.
POP ES
CLD ;All strings forward.

MOV AX,HORZ_LAST ;Retrieve last mickey count.
MOV HORZ_LAST,SI ;Last gets new count.
SUB SI,AX ;SI gets difference since last.
JZ VERTICAL ;If no change, done here.
MOV AX,HORZ_REMAINDER ;Else, retrieve remainder.
CALL LOOKUP ;Calculate adjusted mickeys.
ADD HORZ_ADJUSTED,AX ;Add to our mickey count.
MOV HORZ_REMAINDER,DX ;Store remainder for next time.

MOV CX,8 ;Multiply count by 8.
IMUL CX
MOV SI,HORZ_RATIO_REMAIN ;Last ratio remainder.
MOV CX,HORZ_RATIO ;Mickeys per 8 pixels.
CALL SIGN_ADD_DIV ;Calculate Mickey/pixels.
MOV HORZ_RATIO_REMAIN,DX ;Store remainder for next time.

CMP VIDEO_MODE,GRAPHICS ;Graphics video mode?
JNZ HORZ_TEXT ;If no, do text cursor.
CMP AX,0 ;Else, are there any mickeys?
JZ VERTICAL ;If no, done here.
MOV CX,GRAPHICS_WIDTH ;Retrieve resolution adjustment.
JG ADD_WIDTH ;Is it positive mickeys?
NEG CX ;If no, negate adjustment.
ADD_WIDTH: ADD AX,CX ;Add adjustment value.
ADD BP,AX ;Add result to cursor position.
JMP SHORT VERTICAL ;Done here.

HORZ_TEXT: ADD AX,HORZ_CURS_REMAIN ;Add last remainder.
CWD ;Convert to double word.
MOV SI,AX ;Store in SI.
MOV CX,CHAR_WIDTH ;Divide by mouse
IDIV CX ; pixels/character (8 or 16).
MOV HORZ_CURS_REMAIN,DX ;Store remainder for next time.
SUB SI,DX ;Subtract remainder to get pixels
ADD BP,SI ;Add result to cursor position.

;----------------------------------------------;
VERTICAL: POP SI ;Retrieve vertical Mickeys.
POP BX ;Retrieve vertical coordinate.
MOV AX,VERT_LAST
MOV VERT_LAST,SI ;Calculate vertical same as
SUB SI,AX ; horizontal.
JZ MOVE_CURSOR
MOV AX,VERT_REMAINDER
CALL LOOKUP
ADD VERT_ADJUSTED,AX
MOV VERT_REMAINDER,DX

MOV CX,8
IMUL CX
MOV SI,VERT_RATIO_REMAIN
MOV CX,VERT_RATIO
CALL SIGN_ADD_DIV
MOV VERT_RATIO_REMAIN,DX

CMP VIDEO_MODE,GRAPHICS
JNZ VERT_TEXT
ADD BX,AX
JMP SHORT MOVE_CURSOR

VERT_TEXT: ADD AX,VERT_CURS_REMAIN
CWD
MOV SI,AX
MOV CX,8
IDIV CX
MOV VERT_CURS_REMAIN,DX
SUB SI,DX
ADD BX,SI

;----------------------------------------------;
MOVE_CURSOR: MOV CX,BP ;New horizontal cursor coordinate
MOV DX,BX ;New vertical cursor coordinate.
MOV AX,4 ;Set Mouse Cursor.
CALL MOUSE_DRIVER
POP BX ;Retrieve Button state
POP AX ;Retrieve Condition mask.
TEST AX,CALL_MASK ;Is there a subroutine installed?
JZ MOUSE_END ;If no, done here.
MOV SI,HORZ_ADJUSTED ;Else, pass on vertical mouse
MOV DI,VERT_ADJUSTED ; counts and horizontal mouse
CALL DWORD PTR INTERRUPT_SUB ; counts to the subroutine.
MOUSE_END: RET
MOUSE_CONTROL ENDP

;--------------------------------------------------------------------;
;INPUT: SI = MICKEYS; AX = Last remainder; Flags = sign of MICKEYS. ;
;OUTPUT: AX = Adjusted MICKEYS, DX = New remainder. ;
;--------------------------------------------------------------------;
LOOKUP: PUSHF ;Save sign.
JNS EXCHANGE
NEG SI ;Absolute value of Mickeys.
EXCHANGE: XCHG AX,SI ;Store in AX for scan.
MOV CX,MULTIPLIER_LENGTH - 1 ;Length of table.
MOV DI,OFFSET RANGE ;Point to table.
NEXT_ACCEL: SCASW ;Scan until Mickeys exceeds
JB GOT_ACCEL ; range.
LOOP NEXT_ACCEL
GOT_ACCEL: POPF ;Retrieve sign.
JNS MULTIPLY
NEG AX ;Return sign to Adjusted Mickeys.
MULTIPLY: MOV DI,OFFSET MULTIPLIER_END ;Point to multipliers.
SHL CX,1 ;Retrieve multiplier for
SUB DI,CX ; appropriate range.
MOV CX,[DI]
IMUL CX ;Multiply.
MOV CX,10 ;Divide to achieve implied
CALL SIGN_ADD_DIV ; decimal point.
RET

;----------------------------------------------------------------------;
; Calculates: signed double word DX:AX + SI / CX; OUTPUT: DX:AX=Result ;
;----------------------------------------------------------------------;
SIGN_ADD_DIV: XCHG AX,SI ;Place SI in AX to sign extend.
MOV DI,DX ;DX:AX now in DI:SI.
CWD ;Sign extend AX to DX:AX.
ADD AX,SI ;Add to DX:DX, DI:SI.
ADC DX,DI
IDIV CX ;Divide DX:AX result by CX.
RET ; and return.

; DISPOSABLE DATA
; ---------------
SYNTAX LABEL BYTE
DB "Syntax: MOUSECTL [n ... n | filename | /U]",CR,LF
DB "n = up to 8 mouse multipliers with values between 0-32767"
DB CR,LF,"defaults = 5,6,10,15,22,30,50,70",CR,LF
DB "Implied decimal in values; ie. 5 = 0.5, 18 = 1.8",CR,LF
DB "filename = file with multiplier values",CR,LF
DB "/U = Uninstall"
CR_LF DB CR,LF,LF,"$"

NOT_ENOUGH DB "Not enough memory",CR,LF,"$"
NOT_FOUND DB "File not found",CR,LF,"$"
NO_MOUSE DB "Mouse driver not installed so "
NOT_INSTALLED DB "MOUSECTL not installed",CR,LF,"$"
UNLOAD_MSG DB "MOUSECTL can't be uninstalled",CR,LF
DB "Uninstall resident programs in reverse order",CR,LF,"$"
ALLOCATE_MSG DB "Memory allocation error",CR,LF,BELL,"$"
INSTALL_MSG DB "Installed",CR,LF,"$"
UNINSTALL_MSG DB "Uninstalled",CR,LF,"$"

;--------------------------------------------------------------------;
; Search memory for a copy of our code, to see if already installed. ;
;--------------------------------------------------------------------;
INITIALIZE PROC NEAR
CLD ;All string operations forward.
MOV BX,OFFSET START ;Point to start of code.
NOT BYTE PTR [BX] ;Change a byte so no false match.
XOR DX,DX ;Start at segment zero.
MOV AX,CS ;Store our segment in AX.
NEXT_PARAG: INC DX ;Next paragraph.
MOV ES,DX
CMP DX,AX ;Is it our segment?
JZ ANNOUNCE ;If yes, search is done.
MOV SI,BX ;Else, point to our signature
MOV DI,BX ; and offset of possible match.
MOV CX,16 ;Check 16 bytes for match.
REP CMPSB
JNZ NEXT_PARAG ;If no match, keep looking.

;----------------------------------------------;
ANNOUNCE: MOV DX,OFFSET SIGNATURE ;Display our signature.
CALL PRINT_STRING
MOV DX,OFFSET SYNTAX ;And syntax.
CALL PRINT_STRING

;----------------------------------------------;
PARSE: MOV SI,81H ;Point to command line again.
NEXT_PARSE: LODSB ;Get a byte.
CMP AL,CR ;Is it carriage return?
JZ INSTALL ;If yes, done here.
CMP AL,"/" ;Is it switch character?
JNZ CK_NUMBER ;If no, check if number.
LODSB ;Else, get the switch.
DEC SI ;Adjust pointer.
AND AL,5FH ;Capitalize.
CMP AL,"U" ;Is it "U"?
JNZ NEXT_PARSE ;If no, continue parsing.
CALL CK_INSTALLED ;Else, are we installed?
MOV DX,OFFSET NOT_INSTALLED ;If no, exit with error message.
JZ MSG_EXIT
JMP SHORT UNINSTALL ;Else, attempt to uninstall.

CK_NUMBER: CMP AL,"9" ;Is it a number?
JA CK_FILENAME ;If no, must be a filename.
CMP AL,"0"
JB CK_FILENAME
DEC SI ;Else, adjust pointer.
JMP SHORT LOAD_TABLE ;Load the table with multipliers.

CK_FILENAME: CMP AL,SPACE ;Is it a delimiting character?
JBE NEXT_PARSE ;If yes, continue parsing.
PUSH SI ;Else, save start.
FIND_END: LODSB ;Find the end and convert
CMP AL,SPACE ; to ASCIIZ.
JA FIND_END
MOV BYTE PTR [SI-1],0
POP DX ;Retrieve start.
DEC DX ;Adjust.
MOV AX,3D00H ;Open file for reading.
INT 21H
MOV DX,OFFSET NOT_FOUND ;Exit with error message if
JC MSG_EXIT ; not found.
MOV BX,AX ;Else, save handle.
MOV DX,OFFSET BUFFER ;Point to buffer and
MOV CX,100 ; read up to 100 characters.
MOV AH,3FH
INT 21H
MOV AH,3EH ;Close the file.
INT 21H
MOV SI,DX ;Point to buffer.
MOV BYTE PTR [SI+100],CR ;Add ending carriage return.

LOAD_TABLE: MOV DI,OFFSET MULTIPLIER ;Point to multiplier table.
MOV CX,MULTIPLIER_LENGTH ;Number of entries.
NEXT_MULT: LODSB ;Read a byte.
CMP AL,CR ;Ending carriage return?
JZ INSTALL ;If yes, done here.
CMP AL,"0" ;Is it delimiter?
JB NEXT_MULT ;If yes, next byte.
DEC SI ;Else, adjust pointer.
CALL DECIMAL_HEX ;Convert decimal to hex.
STOSW ;Store the value.
LOOP NEXT_MULT ;Retrieve all values.

;----------------------------------------------;
INSTALL: CALL CK_INSTALLED ;Check if already installed.
JZ CK_MOUSE ;If no, see if mouse installed.
OR AL,AL ;Else, done.
JMP SHORT EXIT ;Exit with ERRORLEVEL = 0.

;-------------------------------------------------------------------;
; Exit. Return ERRORLEVEL code 0 if successful, 1 if unsuccessful. ;
;-------------------------------------------------------------------;
MSG_EXIT: CALL PRINT_STRING
ERROR_EXIT: MOV AL,1 ;ERRORLEVEL = 1.
EXIT: MOV AH,4CH ;Terminate.
INT 21H

;-------------------------------------------------------;
; This subroutine uninstalls the resident MOUSECTL.COM. ;
;-------------------------------------------------------;
UNINSTALL: MOV CX,ES ;Save segment in CX.
MOV AX,3533H ;Get interrupt 33.
INT 21H
CMP BX,OFFSET NEW_INT_33 ;Has it been hooked by another?
JNZ UNINSTALL_ERR ;If yes, exit with error message.
MOV BX,ES
CMP BX,CX ;Is the segment vector same?
JNZ UNINSTALL_ERR ;If no, exit with error message.

MOV AX,3510H ;Get interrupt 10.
INT 21H
CMP BX,OFFSET NEW_INT_10 ;Has it been hooked by another?
JNZ UNINSTALL_ERR ;If yes, exit with error message.
MOV BX,ES
CMP BX,CX ;Is the segment vector same?
JNZ UNINSTALL_ERR ;If no, exit with error message.

MOV AH,49H ;Return memory to system pool.
INT 21H
MOV DX,OFFSET ALLOCATE_MSG
JC MSG_EXIT ;Display message if problem.

MOV DX,ES:OLD_INT_33[0] ;Restore old INT 33.
MOV DS,ES:OLD_INT_33[2]
MOV AX,2533H
INT 21H
MOV DX,ES:OLD_INT_10[0] ;Restore old INT 10.
MOV DS,ES:OLD_INT_10[2]
MOV AX,2510H
INT 21H

XOR AX,AX ;Mouse Reset.
INT 33H

PUSH CS
POP DS ;Point to our data.
MOV DX,OFFSET UNINSTALL_MSG ;Display uninstall message.
CALL PRINT_STRING
XOR AL,AL ;Exit with ERRORLEVEL = 0.
JMP EXIT


UNINSTALL_ERR: MOV ES,CX ;If error, exit
MOV DX,OFFSET UNLOAD_MSG ; with error message.
JMP MSG_EXIT

;--------------------------------;
; This is the install procedure. ;
;--------------------------------;
CK_MOUSE: MOV AX,3533H ;Else, get INT 33 vector.
INT 21H
MOV AX,ES
OR AX,AX ;If vector zero, no mouse driver.
MOV DX,OFFSET NO_MOUSE
JZ MSG_EXIT
MOV AL,ES:[BX]
CMP AL,IRET_CODE
JZ MSG_EXIT
MOV OLD_INT_33[0],BX ;Save old interrupt.
MOV OLD_INT_33[2],ES
MOV DX,OFFSET NEW_INT_33 ;Install new interrupt.
MOV AX,2533H
INT 21H

XOR AX,AX
INT 33H ;Initialize driver.
CALL GET_BIOS_DATA ;Get video mode.

MOV AX,3510H ;Get INT 10 vector.
INT 21H
MOV OLD_INT_10[0],BX ;Save old interrupt.
MOV OLD_INT_10[2],ES
MOV DX,OFFSET NEW_INT_10 ;Install new interrupt.
MOV AX,2510H
INT 21H

MOV AX,DS:[2CH] ;Get environment segment.
MOV ES,AX
MOV AH,49H ;Free up environment.
INT 21H

MOV DX,OFFSET INSTALL_MSG ;Display install message.
CALL PRINT_STRING
MOV DX,OFFSET SYNTAX ;End of resident portion.
ADD DX,15 ;Round up.
MOV CL,4
SHR DX,CL ;Convert to paragraphs.
MOV AX,3100H ;Return error code of zero.
INT 21H ;Terminate but stay resident.
INITIALIZE ENDP

;-------------------------------------------------------;
; OUTPUT: ZR = 1 if not installed; ZR = 0 if installed. ;
;-------------------------------------------------------;
CK_INSTALLED: MOV AX,ES
MOV BX,CS
CMP AX,BX ;Compare segments.
RET

;-------------------------------------------------------------;
; INPUT: SI points to decimal number; OUTPUT: AX = hex number ;
;-------------------------------------------------------------;
DECIMAL_HEX: XOR BX,BX
NEXT_DECIMAL: LODSB ;Get a character.
SUB AL,"0" ;ASCII to binary.
JC DECIMAL_END ;If not between 0 and 9, skip.
CMP AL,9
JA DECIMAL_END
CBW ;Convert to word.
XCHG AX,BX ;Swap old and new number.
MOV DX,10 ;Shift to left by multiplying
MUL DX ; last entry by ten.
ADD BX,AX ;Add new number and store in BX.
JMP NEXT_DECIMAL
DECIMAL_END: MOV AX,BX ;Return in AX.
DEC SI ;Adjust pointer.
RET

;----------------------------------------------;
PRINT_STRING: MOV AH,9
DOS_INT: INT 21H ;Print string via DOS.
RET

BUFFER EQU $

_TEXT ENDS
END START


  3 Responses to “Category : Files from Magazines
Archive   : VOL8N8.ZIP
Filename : MOUSECTL.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/