home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
mouse
/
pointer
/
pointer.asm
next >
Wrap
Assembly Source File
|
1991-08-19
|
38KB
|
871 lines
.model small
.stack 200h
.data
NO_MSG DB 0Ah,0Dh,'Staben Technologies "DOS_MOUSE" v0.95 ',0Ah,0Dh
DB '================================',0Ah,0Dh
DB 'You must have a MICROSOFT mouse ',0Ah,0Dh
DB 'driver installed in your machine',0Ah,0Dh
DB 'to use this program. $'
BAD_ENV DB 0Ah,0Dh,'Staben Technologies "DOS_MOUSE" v0.95 ',0Ah,0Dh
DB '================================',0Ah,0Dh
DB 'You must have a "BMOUSE" string ',0Ah,0Dh
DB 'in your environment. To correct',0Ah,0Dh
DB 'this situation, type: ',0Ah,0Dh
DB 'SET BMOUSE=00000 ',0Ah,0Dh,'$'
BAD_DOS DB 0Ah,0Dh,'Staben Technologies "DOS_MOUSE" v0.95 ',0Ah,0Dh
DB '================================',0Ah,0Dh
DB 'Incorrect DOS version. DOS 3.0 ',0Ah,0Dh
DB 'or better required. ',0Ah,0Dh,'$'
.code
INIT_MOUSE:
xor ax, ax
int 33h
;==================================:
; return values are: :
; AX = FFFF if mouse installed :
; AX = 0 if no mouse :
; BX = # of buttions :
;==================================:
cmp ax, 0FFFFh
je mouse_avail
jmp no_mouse
MOUSE_AVAIL:
;===============================:
; first, test for MS-DOS or 4DOS:
;===============================:
mov ax, 0D44Dh ; 4DOS swap area
mov bx, 0
int 2Fh ; and interrupt it
;===============================:
;IF ax = 44DD, 4DOS is used. :
;===============================:
cmp ax, 44DDh ; compare the deal
je IS_4DOS ; and if equal, its 4DOS
mov ax, 352Eh ; find the master env
int 21h
mov es, [es:2Ch] ; es = environment segment
jmp short dos_checked ; jump past 4dos stuff
is_4dos:
mov es, cx ; es = 4dos environment segment
mov es, [es:2Ch]
dos_checked:
mov [cs:envseg1], es
xor di, di ; point to start of env in es:di
cld ; scan in forward
FIND_STRING: ; - loop thru 1 by 1
test [byte ptr es:[di]], -1 ; end of env?
jnz check_string ; nope... continue
jmp short no_environment ; error...
CHECK_STRING:
push cs
pop ds
mov si, offset ENVSTR ; point to BMOUSE
mov bx, di ; save ptr to start
mov cx, envlen ; length of envstr
repe cmpsb ; compare
je ALL_PASSED ; found it!
mov di, bx ; restore ptr to start
xor al, al ; scan for end of string
mov cx, -1 ; FFFF <- cx
repne scasb
jmp short find_string ; go back for next string
ALL_PASSED:
mov [cs:envoff1], di
CHECK_DOS:
mov ah, 30h
int 21h
cmp al, 03h
jnz wrongversion
dec bx
cmp ah, 1eh
jnz v3xx
mov ax, 5d06h
int 21h
v3xx:
clc
jmp BEGIN
wrongversion:
stc
jmp BADDOS
NO_ENVIRONMENT:
;===========================:
; This procedure is called :
; if the environment string :
; does not exist. :
;===========================:
mov ax, @data
mov ds, ax
mov dx, offset BAD_ENV ; point to bad env.
jmp show_message
NO_MOUSE:
;===========================:
; This procedure is called :
; if there is NO MOUSE :
; installed. :
;===========================:
mov ax, @data
mov ds, ax
mov dx, offset NO_MSG ; point to NO MOUSE MSG.
jmp show_message
BADDOS:
;===========================:
; This procedure is called :
; if the DOS version is bad :
;===========================:
mov ax, @data
mov ds, ax
mov dx, offset BAD_DOS
SHOW_MESSAGE:
mov ah, 09h
int 21h
EXIT_OUT:
jmp bye_bye
BEGIN:
mov [cs:videooffs], 08888h
mov [cs:vid_shift], 3
mov [cs:vid_count], 16
mov [cs:vid_cursr], offset curs_bmp
jmp GET_CHARS
GET_POSITION:
mov ax, 000Bh ; get mickeys since last call
; into CX, DX
int 33h
;
; If CX or DX is greater than 08888h, then the value in CX/DX happens to be
; FFFF-CX/DX = # of mickeys moved LEFT/UP.
;
@check_newx:
cmp CX, 08888h ; see if its a LEFT for CX
ja @cx_left
cmp CX, 00000h ; see if never moved
je @check_newy
add [cs:actual_x], cx ; just add it if positive
jmp short @check_newy
@cx_left:
mov ax, 0FFFFh ; load high
xor ax, cx ; get change in positive
sub [cs:actual_x], ax ; and subtract change
@check_newy:
cmp DX, 08888h ; see if its an up for DX
ja @dx_up
cmp dx, 00000h ; see if never moved
je check_range
add [cs:actual_y], dx ; just add if positive
jmp short CHECK_RANGE
@dx_up:
mov ax, 0FFFFh ; load high
xor ax, dx ; get change in positive
sub [cs:actual_y], ax ; and subtract change
CHECK_RANGE:
@compare_xsmall:
mov ax, [cs:min_actual_x]
cmp [cs:actual_x], ax
jb @xtoolow
cmp [cs:actual_x], 08888h
ja @xtoolow
@compare_ysmall:
mov ax, [cs:min_actual_y]
cmp [cs:actual_y], ax
jb @ytoolow
cmp [cs:actual_y], 08888h
ja @ytoolow
@compare_xbig:
mov ax, [cs:max_actual_x]
cmp [cs:actual_x], ax
ja @xtoohigh
@compare_ybig:
mov ax, [cs:max_actual_y]
cmp [cs:actual_y], ax
ja @ytoohigh
jmp CONVERT_TO_BLOCK
@xtoolow:
mov [cs:actual_x], ax
jmp @compare_ysmall
@ytoolow:
mov [cs:actual_y], ax
jmp @compare_xbig
@xtoohigh:
mov [cs:actual_x], ax
jmp @compare_ybig
@ytoohigh:
mov [cs:actual_y], ax
CONVERT_TO_BLOCK:
;===============================:
; The actual values need to be :
; converted to block values :
; based on # of pixels per char :
; and then these values are used:
; to determine BMOUSE=xxxxx :
;===============================:
mov dx, [cs:actual_y]
mov cl, [cs:vid_shift]
shr dx, cl
mov cl, 3
mov ax, [cs:actual_x]
shr ax, cl
;=============================:
; ax = actual_x/8 :
; dx = actual_y/8/16 :
;=============================:
mov [cs:vx_position], ax
mov [cs:vy_position], dx
mov ax, 3 ; call get mouse position
int 33h ; and do the interrupt
mov [cs:vb_position], bx ; and save button status
MODIFY_ENV:
; [slave] = cycle 1 or 2
;==================================================:
; A button was apparently pushed. We need to :
; fix a SETting to the environment to reflect the :
; current positions of the mouse, etc. :
; BMOUSE=xxyyb :
;==================================================:
mov [cs:slave], 65 ; cycle 1
@mod_loop:
cmp [cs:slave], 66
je @SECOND_CYCLE
mov ah, 62h ; get PSP
int 21h
mov es, bx ; and es=bx
mov es, es:[2Ch] ; get env segment
mov [cs:envseg2], es
jmp @SECOND_PAST
@second_cycle:
mov ax, 0D44Dh
mov bx, 0
int 2Fh
cmp ax, 44DDh
je @IS_4DOS
mov ax, 352Eh
int 21h
mov es, [es:2Ch]
jmp short @dos_checked
@is_4dos:
mov es, cx
mov es, [es:2Ch]
@dos_checked:
mov [cs:envseg1], es
@second_past:
xor di, di ; point to start of env in es:di
cld ; scan in forward
@find_string: ; - loop thru 1 by 1
test [byte ptr es:[di]], -1 ; end of env?
jnz @scan_string ; nope... continue
jmp bye_bye ; error... so quit
@scan_string:
push cs
pop ds
mov si, offset ENVSTR ; point to BMOUSE
mov bx, di ; save ptr to start
mov cx, envlen ; length of envstr
repe cmpsb ; compare
je @found_string ; found it!
mov di, bx ; restore ptr to start
xor al, al ; scan for end of string
mov cx, -1 ; FFFF <- cx
repne scasb
jmp short @find_string ; go back for next string
@found_string:
cmp [cs:slave], 66
je @SECOND_STORE
mov [cs:envoff2], di
mov [cs:slave], 66
jmp @MOD_LOOP
@second_store:
mov [cs:envoff1], di
;================================:
; Notes of interest. We've got :
; a possible two digits, or just :
; one. :
;================================:
mov es, [cs:envseg1] ; prepare the env. segment
mov di, [cs:envoff1] ; prepare the offset to env.
mov ds, [cs:envseg2]
mov si, [cs:envoff2]
;===============================:
; When making DECIMAL from BIN :
; need to simply divide by 10 :
; and convert the al, ah to the :
; correct memory locations. :
;===============================:
WRITE_BMOUSE:
mov ax, [cs:vy_position] ; ready the row coord
mov dl, 10 ; to divide by 10
div dl ; get first digit >> AL = first
; AH = remainder
add al, 30h ; and convert to ASCII
add ah, 30h
mov [byte ptr es:[di]], al
mov [byte ptr ds:[si]], al
inc di
inc si
mov [byte ptr es:[di]], ah
mov [byte ptr ds:[si]], ah
inc di
inc si
mov ax, [cs:vx_position] ; ready the column coord
mov dl, 10 ; to divide by 10
div dl ; get first digit >> AL - first
; ah = remainder
add al, 30h ; and convert to ASCII
add ah, 30h
mov [byte ptr es:[di]], al
mov [byte ptr ds:[si]], al
inc di
inc si
mov [byte ptr es:[di]], ah
mov [byte ptr ds:[si]], ah
inc di
inc si
mov ax, [cs:vb_position] ; and then the button...
mov dl, 1 ; to divide by 1
div dl ; get first digit >> al - first
; ah = remainder
add al, 30h ; and convert to ASCII
mov [byte ptr es:[di]], al
mov [byte ptr ds:[si]], al
PLACE_CURSOR:
; The actual character pointed to by the "hotspot" is the
; character pointed to by BMOUSE. The cursor MUST be on the
; character. So, save the position, the one below, the one
; over, and one down and over.
;======================:
; get hot character :
;======================:
mov ax, [cs:vy_position] ; get Y-position
mov dl, 5 ; multiply by 5
mul dl ; and then shift for *32
mov cl, 5 ; to get ax * 160
shl ax, cl ; ax = the row
mov bx, [cs:vx_position] ; get X-position
mov cl, 1 ; multiply by 2 (miss attrib)
shl bx, cl ; to get column.
add ax, bx
mov [cs:videooffs], ax ; save the offset to block of 4
;==========================:
; restore screen so that :
; the cursor isn't being :
; read in! on > 1st time :
;==========================:
mov ax, [cs:vb_position]
cmp ax, 0
jne REST_SCREEN
mov ax, [cs:videooffs]
cmp ax, [cs:ovideooffs]
je OFFSET_CALC
REST_SCREEN:
mov ds, [cs:videopage]
mov di, [cs:ovideooffs]
mov ah, [cs:char_1] ; and re-write it out
mov byte ptr [ds:di], ah
;=====================:
; put char over one :
;=====================:
inc di ; set pointer to next one
inc di ; but skip attribute byte
mov ah, [cs:char_2]
mov byte ptr [ds:di], ah
;=====================:
; put char down one :
; and over. :
;=====================:
mov ax, di ; add 160 for next row
add ax, 160
mov di, ax
mov ah, [cs:char_4]
mov byte ptr [ds:di], ah
;=====================
; put char down :
;====================:
dec di ; character under hot
dec di ; and skip attribute byte
mov ah, [cs:char_3]
mov byte ptr [ds:di], ah
;=============================:
; if a button is pressed, :
; exit out :
;=============================:
cmp [cs:vb_position], 0
je GET_CHARS
jmp bye_bye
GET_CHARS:
mov di, [cs:videooffs]
mov ah, byte ptr [ds:di] ; and save the character there
mov [cs:char_1], ah
;=====================:
; get char over one :
;=====================:
inc di ; set pointer to next one
inc di ; but skip attribute byte
mov ah, byte ptr [ds:di]
mov [cs:char_2], ah
;=====================:
; get char down one :
; and over. :
;=====================:
mov ax, di ; add 160 for next row
add ax, 160
mov di, ax
mov ah, byte ptr [ds:di]
mov [cs:char_4], ah
;=====================
; get char down :
;====================:
dec di ; character under hot
dec di ; and skip attribute byte
mov ah, byte ptr [ds:di]
mov [cs:char_3], ah
;==========================================:
; now the characters at these locations :
; have been saved. Find the offset to :
; these characters where the cursor is to :
; be. :
;==========================================:
OFFSET_CALC:
mov dx, [cs:vx_position]
mov cl, 3
shl dx, cl ; get rounded column
mov bx, [cs:vy_position]
mov cl, [cs:vid_shift]
shl bx, cl ; get rounded row
;========================================:
; Now, the rounded row/column XOR'd with :
; the non-rounded should give the offset :
; for the cursor. :
;========================================:
xor bx, [cs:actual_y] ; get vertical offset
xor dx, [cs:actual_x] ; get horizontal offset
mov ax, bx
mov cl, 1
shl ax, cl
cmp ax, 0
je save_offs
dec ax
save_offs:
mov [cs:horizont_offs], dl
mov [cs:vertical_offs], al
;=======================================:
; Get the bitmaps of the characters in :
; char_1,2,3 & 4. These are to be OR'd :
; with the cursor bitmaps. :
;=======================================:
SET_MAP:
;=====================:
; Set char map 2 to :
; readable form :
;=====================:
mov dx, 3C4h
mov ax, 0402h
out dx, ax
mov ax, 0704h
out dx, ax
mov dl, 0CEh
mov ax, 0204h
out dx, ax
mov ax, 0005h
out dx, ax
mov ax, 0006h
out dx, ax
;============================:
; In this section, each loop :
; will read, modify, and :
; write modified char sets :
;============================:
READ_WRITE_MAPS:
RP01:
mov ds, [cs:videochar] ; get videochar offset
xor ax, ax
mov di, 219*32 ; new location pointer
mov es, [cs:videochar]
cld
mov al, [cs:char_1] ; char_1's position
mov cl, 5 ; shift it 5 to get *32
shl ax, cl
mov si, ax ; and put it in si
mov cx, [cs:vid_count] ; do it 16 times
xor dx, dx
push di
mov di, [cs:vid_cursr]
RL01:
lodsb ; load byte at DS:SI -> al
;============:
; Vertical :
;============:
cmp dl, [cs:vertical_offs]
jb copyPL01
;============:
; Horizontal :
;============:
mov bh, byte ptr [cs:di] ; load cursor bitmap at line si
inc di
push cx
mov cl, [cs:horizont_offs] ; and cl the shift amount
shr bx, cl ; and move it over
pop cx
xor al, bh
COPYPL01:
mov bx, di
pop di
mov byte ptr [es:di], al ; and save it on table
inc di
push di
mov di, bx
inc dx
loop RL01
pop di
RP02:
xor ax, ax
mov di, 220*32
cld
mov al, [cs:char_2] ; char_2's position
mov cl, 5 ; shift it 5 to get *32
shl ax, cl
mov si, ax ; and put it in si
mov cx, [cs:vid_count]
xor dx, dx
push di
mov di, [cs:vid_cursr]
RL02:
lodsb ; load byte at DS:SI -> al
xor bx, bx
;==========:
; vertical :
;==========:
cmp dl, [cs:vertical_offs]
jb copyPL02
;============:
; Horizontal :
;============:
mov bh, byte ptr [cs:di] ; load cursor bitmap
inc di
push cx
mov cl, [cs:horizont_offs]
mov ch, 8
sub ch, cl
mov cl, ch
shl bx, cl
pop cx
xor al, bh
copyPL02:
mov bx, di
pop di
mov byte ptr [es:di], al
inc di
push di
mov di, bx
inc dx
loop RL02
pop di
RP03:
xor ax, ax
mov di, 221*32
cld
mov al, [cs:char_3] ; char_2's position
mov cl, 5 ; shift it 5 to get *32
shl ax, cl
mov si, ax ; and put it in si
xor dx, dx
push di
mov di, [cs:vid_cursr]
inc di
mov cx, [cs:vid_count]
mov ch, [cs:vertical_offs]
sub cl, ch
mov ch, 0
add di, cx
mov [cs:vslave1], cl
mov cx, [cs:vid_count]
xor dx, dx
RL03:
lodsb ; load byte at DS:SI -> al
xor bx, bx
;==========:
; vertical :
;==========:
push cx
mov cx, [cs:vid_count]
cmp [cs:vslave1], cl
pop cx
ja copyPL03
;============:
; Horizontal :
;============:
mov bh, byte ptr [cs:di] ; load cursor bitmap
inc di
inc [cs:vslave1]
push cx
mov cl, [cs:horizont_offs]
shr bx, cl
pop cx
xor al, bh
copyPL03:
mov bx, di
pop di
mov byte ptr [es:di], al
inc di
push di
mov di, bx
inc dx
loop RL03
pop di
RP04:
xor ax, ax
mov di, 222*32
cld
mov al, [cs:char_4] ; char_2's position
mov cl, 5 ; shift it 5 to get *32
shl ax, cl
mov si, ax ; and put it in si
xor dx, dx
push di
mov di, [cs:vid_cursr]
inc di
mov cx, [cs:vid_count]
mov ch, [cs:vertical_offs]
sub cl, ch
mov ch, 0
add di, cx
mov [cs:vslave1], cl
mov cx, [cs:vid_count]
xor dx, dx
RL04:
lodsb ; load byte at DS:SI -> al
xor bx, bx
;==========:
; vertical :
;==========:
push cx
mov cx, [cs:vid_count]
cmp [cs:vslave1], cl
pop cx
ja copyPL04
;============:
; Horizontal :
;============:
mov bh, byte ptr [cs:di] ; load cursor bitmap
inc di
inc [cs:vslave1]
push cx
mov cl, [cs:horizont_offs]
mov ch, 8
sub ch, cl
mov cl, ch
shl bx, cl
pop cx
xor al, bh
copyPL04:
mov bx, di
pop di
mov byte ptr [es:di], al
inc di
push di
mov di, bx
inc dx
loop RL04
pop di
;========================================:
; Now the bitmaps are loaded up in to :
; the memory. :
;========================================:
;=====================:
; turn on sequencer :
;=====================:
mov dx, 3C4h
mov ax, 0302h
out dx, ax
mov ax, 0304h
out dx, ax
mov dl, 0CEh
mov ax, 0004h
out dx, ax
mov ax, 1005h
out dx, ax
mov ax, 0E06h
out dx, ax
;===========================:
; now, check for position :
; changes, if the position :
; has changed, the old ones :
; need to be written back :
; out and then the new ones :
; are then the old ones. :
;===========================:
mov ax, [cs:videooffs]
cmp ax, [cs:ovideooffs]
jne changed
jmp PUT_SCREEN
changed:
;======================:
; the new ones are now :
; the old ones. :
;======================:
mov ah, [cs:char_1]
mov [cs:old_char_1], ah
mov ah, [cs:char_2]
mov [cs:old_char_2], ah
mov ah, [cs:char_3]
mov [cs:old_char_3], ah
mov ah, [cs:char_4]
mov [cs:old_char_4], ah
mov ax, [cs:videooffs]
mov [cs:ovideooffs], ax
PUT_SCREEN:
;=======================================:
; and put those 4 characters at the :
; cursor's current location :
;=======================================:
mov ds, [cs:videopage]
mov di, [cs:videooffs] ; get screen offset
mov byte ptr [ds:di], 219 ; put remap #1
inc di
inc di ; go one over
cmp [cs:vx_position], 79
je skip1
mov byte ptr [ds:di], 220 ; put remap #2
skip1:
mov ax, di
add ax, 160 ; add 160 for next row
mov di, ax
cmp [cs:vx_position], 79
je skip2
mov byte ptr [ds:di], 222 ; put remap #3
skip2:
dec di
dec di ; go back one over
mov byte ptr [ds:di], 221 ; put remap #4
jmp get_position
bye_bye:
mov ah, 4Ch
int 21h
;============================================:
; Variables which are internally used by the :
; program. :
;============================================:
EMPTYSPOT DB 'D'
ENVSTR DB 'BMOUSE=' ; Env. variable to find
ENVLEN EQU 7 ; length of env variable
envseg1 DW 0 ; PSP environment seg
envseg2 DW 0 ; PSP environment offset
envoff1 DW 0 ; MASTER environment seg
envoff2 DW 0 ; MASTER environment offset
slave DB 0 ; Slave spot
;===========================================:
; Video & Pixel Location Information :
;===========================================:
videopage DW 0B800h ; Videopage starting location
videochar DW 0A000h ; Videochar map location
videooffs DW 00000h ; Offset to block of 4
actual_x DW 0 ; actual x position
actual_y DW 0 ; actual y position
old_actual_x DW 0 ; old actual x position
old_actual_y DW 0 ; old actual y position
min_actual_x DW 1 ; minimum actual x position
max_actual_x DW 638 ; maximum actual x position
min_actual_y DW 1 ; minimum actual y position
max_actual_y DW 199 ; maximum actual y position
vx_position DW 0 ; current alpha x position
vy_position DW 0 ; current alpha y position
vb_position DW 0 ; current button position
ovideooffs DW 0 ; old position of block of 4
vid_count DW 0 ; video count 16 or 8
vid_shift DB 0 ; shift count, 3 or 4
vid_cursr DW 0 ; cursor offset
char_1 DB 0 ; character hot'spotted
char_2 DB 0 ; character over one
char_3 DB 0 ; character under hot'spotted
char_4 DB 0 ; character down and over
old_char_1 DB 0 ; old character hot'spotted
old_char_2 DB 0 ; old character over one
old_char_3 DB 0 ; old character under hot'spotted
old_char_4 DB 0 ; old character down and over
vertical_offs DB 0 ; vertical offset
horizont_offs DB 0 ; horizontal offset
char_map DB 64 DUP (255)
vslave1 DB 0
vslave2 DW 0
; 8x16
curs_bmp DB 00000000b
DB 00000000b
DB 10000000b
DB 11000000b
DB 11100000b
DB 11110000b
DB 11111000b
DB 11111100b
DB 11111110b
DB 11111111b
DB 00011100b
DB 00001100b
DB 00000110b
DB 00000011b
DB 00000000b
DB 00000000b
DB 00000000b
DB 00000000b
END