MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.scrn3.asm

251 lines
8.1 KiB
NASM
Raw Normal View History

2021-01-12 23:58:25 +00:00
TITLE scrn3.asm
; AUTHOR Tim Spencer - Compuserve [73657,1400]
; DATE March 17, 1987
_TEXT SEGMENT BYTE PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT WORD PUBLIC 'DATA'
SCRN STRUC ; screen data structure - defined in video.h
off dw 0 ; offset (cursor position)
seg dw 0 ; screen buffer address
port dw 0 ; status port address
attrib dw 0 ; attribute to use
cgacrd dw 0 ; enable retrace checking if not zero
SCRN ENDS
_DATA ENDS
DGROUP GROUP _DATA
ASSUME CS:_TEXT, DS:DGROUP, SS:DGROUP, ES:NOTHING
_TEXT SEGMENT BYTE PUBLIC 'CODE'
;-----------------------------------------------------------------------;
; scrn_restore - MSC callable function to restore a rectangular area ;
; of the screen buffer. Checks for vertical retrace ;
; only if the external structure member cga_card is ;
; non-zero. &scrn is the address of that structure. ;
; (see video.h). ;
; ; ;
; Note: This procedure uses stosb in retrace checking mode (instead of ;
; movsb) because it stuffs the char/attrib into the screen buffer ;
; slightly faster. ;
; ;
; Usage: scrn_restore(left, right, top, bottom, data_buff, &scrn) ;
; ;
;-----------------------------------------------------------------------;
_DATA SEGMENT
restore_args STRUC ; structure for easy argument reference
dw 0 ; saved BP value
dw 0 ; return address
rleft dw 0 ; rectangular boundries...
rright dw 0
rtop dw 0
rbottom dw 0
mdata dw 0 ; address of data buffer to write to screen
mstruct dw 0 ; pointer to SCRN structure(defined in video.h)
restore_args ENDS
cga db 0 ; variable to hold cga_card value
_DATA ENDS
PUBLIC _scrn_restore
_scrn_restore PROC NEAR
push bp ; set up frame pointer
mov bp,sp
push si
push di
mov bx,[bp].mstruct ; get pointer to SCRN structure
les di,dword ptr[bx].off ; get scrn seg in es, off in di
mov dx,[bx].port ; get status port address
mov ax,[bx].cgacrd ; hold cga status in variable cga
mov cga,al
mov si,[bp].mdata ; make si point to data buffer
mov bh,byte ptr[bp].rtop ; top will be incremented until it
mov bl,byte ptr[bp].rbottom ; is greater than bottom, then exit.
xor cx,cx ; set initial logical cursor position
mov cl,bh ; by getting top into cx,
mov al,80 ; multiplying by 80,
mul cl
mov cx,ax
add cx,[bp].rleft ; adding left.
shl cx,1 ; and multiplying by 2
mov di,cx ; put result into di
mov cx,[bp].rright ; get the length of one line into
sub cx,[bp].rleft ; cx by subtracting left from right
add cx,1 ; adding 1
push cx ; save it
mov ax,79 ; calculate offset from end of line to
sub ax,[bp].rright ; the start of the next line
add ax,[bp].rleft
shl ax,1
push ax ; and save it
write_line:
cmp cga,0 ; cga card in use?
jnz rwait1 ; yes, go wait
rep movsw ; no, warp speed.
jmp short rcheck_pos ; go check position
rwait1:
in al, dx ; wait for end of retrace
shr al, 1 ; test horizontal trace bit
jc rwait1 ; loop if still tracing
cli ; disable writus interuptus
rwait2:
in al, dx ; now wait until the very moment
shr al, 1 ; when the next retrace begins
jnc rwait2 ; still waiting...
mov al,[si] ; load the char into al for stosb
stosb ; write it and update pointer
sti ; enable interrupts again
inc si ; point si at attribute
rwait3:
in al, dx ; repeat these steps for the attribute
shr al, 1
jc rwait3
cli
rwait4:
in al, dx
shr al, 1
jnc rwait4
mov al,[si] ; load the attribute
stosb
sti
inc si ; point si at next char
loop rwait1
rcheck_pos:
pop ax ; restore offset to next line start
pop cx ; restore count
inc bh ; is top greater than bottom yet?
cmp bh,bl
ja rexit ; yes.
push cx ; no, save count again
push ax ; save line start offset again
add di,ax ; move di to start of next line
jmp short write_line ; write another line
rexit:
pop di
pop si
pop bp
ret
_scrn_restore ENDP
;-----------------------------------------------------------------------;
; scrn_save - MSC callable function to save a rectangular area of the ;
; screen to a user defined buffer. ;
; ;
; Usage: scrn_save(left, right, top, bottom, data_buff, &scrn) ;
;-----------------------------------------------------------------------;
_DATA SEGMENT
save_args STRUC ; structure for easy argument reference
dw 0 ; saved bp value
dw 0 ; return address
sleft dw 0 ; rectangular boundries
sright dw 0
stop dw 0
sbottom dw 0
sbuff dw 0 ; user defined buffer to hold screen contents
sstruct dw 0 ; pointer to SCRN structure (see video.h)
save_args ENDS
_DATA ENDS
scga db 0 ; store cga true/false value here - must be
; declared outside data segment because es and
; ds are swapped in this function.
PUBLIC _scrn_save
_scrn_save PROC NEAR
push bp ; set up frame pointer
mov bp,sp
push si
push di
push ds
mov bx,[bp].mstruct ; get pointer to SCRN structure
mov dx,[bx].port ; get status port address
mov ax,[bx].cgacrd ; hold cga status in variable scga
mov scga,al
mov ax,ds
mov es,ax ; get data segment into es
mov di,[bp].sbuff ; and offset of user buffer in di
mov ax,[bx].seg ; get the screen segment and
mov ds,ax ; put in ds
mov bh,byte ptr[bp].stop ; top will be incremented until it
mov bl,byte ptr[bp].sbottom ; is greater than bottom, then exit.
xor cx,cx ; set initial logical cursor position
mov cl,bh ; by getting top into cx,
mov al,80 ; multiplying by 80,
mul cl
mov cx,ax
add cx,[bp].sleft ; adding left.
shl cx,1 ; and multiplying by 2
mov si,cx ; put result into si
mov cx,[bp].sright ; get the length of one line into
sub cx,[bp].sleft ; cx by subtracting left from right
add cx,1 ; adding 1
push cx ; save it
mov ax,79 ; calculate offset from end of line to
sub ax,[bp].sright ; the start of the next line
add ax,[bp].sleft
shl ax,1
push ax ; and save it
read_line:
cmp cga,0 ; cga card in use?
jnz swait1 ; yes, go wait
rep movsw ; no, warp speed.
jmp short scheck_pos ; go check position
swait1:
in al, dx ; wait for end of retrace
shr al, 1 ; test horizontal trace bit
jc swait1 ; loop if still tracing
cli ; disable writus interuptus
swait2:
in al, dx ; now wait until the very moment
shr al, 1 ; when the next retrace begins
jnc swait2 ; still waiting...
mov al,[si] ; load the char into al for stosb
stosb ; write it and update pointer
sti ; enable interrupts again
inc si ; point si at attribute
swait3:
in al, dx ; repeat these steps for the attribute
shr al, 1
jc swait3
cli
swait4:
in al, dx
shr al, 1
jnc swait4
mov al,[si] ; load the attribute
stosb
sti
inc si ; point si at next char
loop swait1
scheck_pos:
pop ax ; restore offset to next line start
pop cx ; restore count
inc bh ; is top greater than bottom yet?
cmp bh,bl
ja sexit ; yes.
push cx ; no, save count again
push ax ; save line start offset again
add si,ax ; move di to start of next line
jmp short read_line ; write another line
sexit:
pop ds
pop di
pop si
pop bp
ret
_scrn_save ENDP
_TEXT ENDS
END