mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-21 10:56:10 +00:00
312 lines
8.6 KiB
NASM
312 lines
8.6 KiB
NASM
|
; 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
|
|||
|
|