13
1
mirror of https://github.com/vxunderground/MalwareSourceCode synced 2024-06-28 09:52:32 +00:00
vxug-MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.monograf.asm
2021-01-12 17:49:21 -06:00

312 lines
8.6 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; MONOGRAF.DRV -- Lotus Driver for Graphics on Monochrome Display
; ============
;
; (For use with Lotus 1-2-3 Version 1A)
;
; (C) Copyright Charles Petzold, 1985
CSEG Segment
Assume CS:CSEG
Org 0
Beginning dw Offset EndDriver,1,1,Offset Initialize
Org 18h
db "Monochrome Graphics (C) Charles Petzold, 1985",0
Org 40h
dw 40 * 8 - 1 ; Maximum Dot Column
dw 25 * 8 - 1 ; Maximum Dot Row
dw 10, 7, 6, 10, 7, 6, 256
db -1 ; For one monitor
Org 53h
Jmp Near Ptr ClearScreen ; Call 0 -- Clear Screen
Jmp Near Ptr ColorSet ; Call 1 -- Set Color
Jmp Near Ptr SetAddress ; Call 2 -- Set Row/Col Addr
Jmp Near Ptr DrawLine ; Call 3 -- Draw a Line
Jmp Near Ptr Initialize ; Call 4 -- Write Dot (nothing)
Jmp Near Ptr WriteChar ; Call 5 -- Write a Character
Jmp Near Ptr DrawBlock ; Call 6 -- Draw a Block
Jmp Near Ptr Initialize ; Call 7 -- Read Dot (nothing)
Jmp Near Ptr Initialize ; Call 8 -- Video Reset
; Initialization Routine
; ----------------------
Initialize Proc Far
Mov AX,0 ; This is standard
Or AX,AX ; for all drivers
Ret
Initialize EndP
; Common Data Used in Routines
; -----------------------------------
CharacterRow dw ? ; from 0 to 24
CharacterCol dw ? ; from 0 to 79
ScreenAddress dw ?,0B000h ; Offset & Segment
CurrentColor db ?,7 ; For Screen Output
Colors db 219,219,178,177,176,219,178 ; Actually blocks
; Row and Column Conversion of AX from graphics to character
; ----------------------------------------------------------
Rounder dw 0 ; Value to add before division
Divisor db ? ; Value to divide by
MaxDots dw ? ; Number of dots
RowConvertRnd: Mov [Rounder],4 ; Row rounding -- add 4
RowConvert: Mov [Divisor],8 ; Row normal -- divide by 8
Mov [MaxDots],200 ; 25 lines times 8 dots
Jmp Short Convert ; And do generalized conversion
ColConvertRnd: Mov [Rounder],2 ; Column rounding -- add 2
ColConvert: Mov [Divisor],4 ; Will divide by 4
Mov [MaxDots],320 ; 40 columns times 4 dots
Convert: Cmp AX,[MaxDots] ; See if graphics value OK
Jb OKToConvert ; It is if under maximum
Jl Negative ; But could be negative
Sub AX,[MaxDots] ; Otherwise wrap down
Jmp Convert ; And check again
Negative: Add AX,[MaxDots] ; Negatives wrap up
Jmp Convert ; And check again
OkToConvert: Add AX,[Rounder] ; Add rounding value
Div [Divisor] ; Divide
Cbw ; And convert to word
Mov [Rounder],0 ; For next time through
Ret
; Calc Offset -- DX, CX character positions in
; -----------
CalcOffset: Push AX
Push DX
Mov AX,80 ; Columns Per Line
Mul DX ; AX now at beginning of row
Add AX,CX ; Add column value
Add AX,AX ; Double for attributes
Mov [ScreenAddress],AX ; Save as the current address
Pop DX
Pop AX
Ret
; Address Convert -- DX, CX row and column converted to character
; ---------------
AddrConvert: Push AX
Mov AX,DX ; This is graphics row
Call RowConvert ; Convert to character row
Mov DX,AX ; Save back in DX
Mov [CharacterRow],AX ; And save value in memory
Mov AX,CX ; This is graphics column
Call ColConvert ; Convert to character column
Mov CX,AX ; Back in CX
Mov [CharacterCol],AX ; And value also saved
Call CalcOffset ; Find the screen destination
Pop AX
Ret
; Call 0 -- Clear Screen -- AL = 0 for B&W
; ====================== -1 for Color
ClearScreen Proc Far
Mov AX,0B000h ; Monochrome Segment
Mov ES,AX ; Set EX to it
Sub DI,DI ; Start at zero
Mov CX,25 * 80 ; Number of characters
Mov AX,0720h ; Blanks only
Cld ; Forward direction
Rep Stosw ; Do it
Ret
ClearScreen EndP
; Call 1 -- Color Set -- AL = Color (0, 1-6)
; -------------------
ColorSet Proc Far
Mov BX,Offset Colors ; Blocks for 7 colors
Xlat Colors ; Translate the bytes
Mov [CurrentColor],AL ; And save it
Ret
ColorSet EndP
; Call 2 -- Set Address -- DX = Graphics Row
; --------------------- CX = Graphics Columns
SetAddress Proc Far
Call AddrConvert ; One routine does it all
Ret
SetAddress EndP
; Call 3 -- Draw Line -- DX = End Row
; ------------------- CX = End Column
DrawLine Proc Far
Les DI,DWord Ptr [ScreenAddress] ; Beginning address
Mov AX,[CharacterCol] ; AX now beginning column
Mov BX,[CharacterRow] ; BX now beginning row
Call AddrConvert ; CX,DX now ending col, row
Cmp AX,CX ; See if cols are the same
Je VertLine ; If so, it's vertical line
Cmp BX,DX ; See if rows are the same
Jne DrawLineEnd ; If not, don't draw anything
HorizLine: Sub CX,AX ; Find the number of bytes
Mov BX,2 ; Increment for next byte
Mov AL,196 ; The horizontal line
Mov AH,179 ; The vertical line
Jae DrawTheLine ; If CX > AX, left to right
Jmp Short ReverseLine ; Otherwise right to left
VertLine: Mov CX,DX ; This is the ending column
Sub CX,BX ; Subtract beginning from it
Mov BX,80 * 2 ; Increment for next line
Mov AL,179 ; The vertical line
Mov AH,196 ; The horizontal line
Jae DrawTheLine ; If CX > BX, up to down
ReverseLine: Neg BX ; Reverse Increment
Neg CX ; Make a positive value
DrawTheLine: Inc CX ; One more byte than calced
DrawLineLoop: Cmp Byte Ptr ES:[DI],197 ; See if criss-cross there
Je DrawLineCont ; If so, branch around
Cmp ES:[DI],AH ; See if opposite line
Jne NoOverLap ; If not, skip next code
Mov Byte Ptr ES:[DI],197 ; Write out criss-cross
Jmp Short DrawLineCont ; And continue
NoOverLap: Mov ES:[DI],AL ; Display line chararacter
DrawLineCont: Add DI,BX ; Next destination
Loop DrawLineLoop ; For CX repetitions
DrawLineEnd: Ret
DrawLine EndP
; Call 5 -- Write Character -- DX, CX = row, col; BX = count,
; ------------------------- AH = direction, AL = type
Direction db ?
WriteChar Proc Far
Push BX ; Save count
Add BX,BX ; Initialize adjustment
Mov [Direction],AH ; Save direction
Or AL,AL ; Branch according to type
Jz WriteType0
Dec AL
Jz WriteType1
Dec AL
Jz WriteType2
Dec AL
Jz WriteType3
WriteType4: Mov AX,4 ; Adjustment to row
Jmp Short WriteCharCont
WriteType3: Add BX,BX ; Center on column
WriteType2: Sub AX,AX ; No adjustment to row
Jmp Short WriteCharCont
WriteType1: Sub BX,BX ; No adjustment on column
WriteType0: Mov AX,2 ; Adjustment to row
WriteCharCont: Cmp [Direction],0 ; Check the direction
Jz HorizChars
Sub DX,BX ; Vertical -- adjust row
Sub DX,BX
Sub CX,AX ; Adjust column
Mov AX,80 * 2 - 1 ; Increment for writes
Jmp Short DoWriteChar
HorizChars: Sub DX,AX ; Horizontal -- adjust row
Sub DX,AX
Sub CX,BX ; Adjust column
Mov AX,1 ; Increment for writes
DoWriteChar: Call AddrConvert ; Convert the address
Les DI,DWord Ptr [ScreenAddress] ; Get video address
Cld
Pop CX ; Get back character count
Jcxz WriteCharEnd ; Do nothing if no characters
CharacterLoop: Movsb ; Write character to display
Add DI,AX ; Increment address
Loop CharacterLoop ; Do it CX times
WriteCharEnd: Ret
WriteChar EndP
; Call 6 -- Draw Block -- BX,DX = Rows; AX,CX = Columns
; --------------------
DrawBlock Proc Far
Call ColConvertRnd ; AX now first char col
Xchg AX,CX ; Switch with 2nd graph col
Call ColConvertRnd ; AX now 2nd char col
Cmp AX,CX ; Compare two char cols
Je DrawBlockEnd ; End routine if the same
Ja NowDoRow ; If CX lowest, just continue
Xchg AX,CX ; Otherwise switch them
NowDoRow: Xchg AX,BX ; AX now 1st graph row
Call RowConvertRnd ; AX now 1st char row
Xchg AX,DX ; AX now 2nd graph row
Call RowConvertRnd ; AX now 2nd char row
Cmp AX,DX ; Compare two character columns
Je DrawBlockEnd ; End routine if the same
Ja BlockRowLoop ; If DX lowest, just continue
Xchg AX,DX ; Otherwise switch them
BlockRowLoop: Push CX ; Beginning Column
Push BX ; Ending Column
BlockColLoop: Call CalcOffset ; Calculate screen address
Les DI,DWord Ptr [ScreenAddress] ; And set ES:DI
Push Word Ptr [CurrentColor] ; Push the current color
Pop ES:[DI] ; And Pop it on the screen
Inc CX ; Next Column
Cmp CX,BX ; Are we an end?
Jb BlockColLoop ; Nope -- loop again
Pop BX ; Get back beginning col
Pop CX ; And the end
Inc DX ; Prepare for next row
Cmp DX,AX ; Are we at the end?
Jb BlockRowLoop ; If not, loop
DrawBlockEnd: Ret
DrawBlock EndP
Org $ + 16 - (($ - Beginning) Mod 16)
EndDriver Label Byte
CSEG EndS
End