home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 9
/
MEDIASHARE_09.ISO
/
progmisc
/
fakesrc.zip
/
PART4
/
LENZ.ASM
next >
Wrap
Assembly Source File
|
1993-11-16
|
27KB
|
768 lines
;=============================================================================
; lenz.asm - Lenz or Crystal Ball Demostration.
; File created: 10/18/93
; Copyright (c) 1993, Carlos Hasan Last modified: 11/16/93
;
; Description:
; This file implements a Lenz-like Crystall Ball effect using the
; VGA 320x200x256 graphics mode and a 320x200x256 picture.
;
; Portability:
; Requires Turbo Assembler 3.2 or better to be assembled.
; Dependent on the IBM PC 286 and the VGA graphics card.
;
; Modifications:
; 10/22/93 - Startup Code and Picture/Palette in .OBJ files.
; 11/01/93 - Fixed Vertical Strengh Amplification.
; 11/16/93 - Added EmBoss and Slide Effect.
;=============================================================================
jumps
.model small,pascal
.286
dosseg ; used to link like
.stack 1024 ; an standalone program.
global LenzDemo:proc
global LenzPal:byte ; in LENZPAL.OBJ file.
global LenzPic:byte ; in LENZRAW.OBJ file.
;========================= Demo equates ======================================
;
; Note: 1. Lenz strengh is computed like: Strengh = 256/Factor
; where Factor is the real amplification of the lenz.
;
; 2. I have used a picture with a gray scale palette at
; entries from 128 to 255. Emboss Bright, Depth, MinGray
; and MaxGray must be adjusted for others pictures.
;
RADIUS equ 52 ; Lenz Radius in pixels.
RADIUSI equ (15*RADIUS)/20 ; Internal Lenz Radius.
STRENGH equ 155 ; Lenz Amplify (fixed 8.8).
MAXWIDTH equ 320 ; VGA 320x200x256 dimensions.
MAXHEIGHT equ 200
SEED equ 286Ah ; Random seed for movement.
BRIGHT equ 150 ; Emboss Bright Factor.
DEPTH equ 12*256 ; Emboss Depth Factor (8.8).
MINGRAY equ 128 ; Emboss Min/Max Gray
MAXGRAY equ 255 ; Scale Range Values.
TIMEOUT equ 70 * 6 ; at least 6 secs.
;======================== Demo data ==========================================
.data
LenzTable dw 4*RADIUS*RADIUS dup(?) ; Holds the transformation.
LenzWidth dw 2*RADIUS dup(?) ; Scanline widths.
RandSeed dw ? ; Random Seed.
Timer dw ? ; Timer counter.
;======================== Demo Routines ======================================
.code
;-----------------------------------------------------------------------------
; Random - Returns a random number of 16 bits, modified version of the
; ripped System unit random routine of the Borland Pascal 7.0.
; Out:
; AX - random value.
; Modified:
; AX, DX, Flags.
;-----------------------------------------------------------------------------
Random proc near
mov ax,[RandSeed]
mov dx,8405h
mul dx
inc ax
mov [RandSeed],ax
ret
Random endp
;-----------------------------------------------------------------------------
; WaitVRT - Waits the next VGA Vertical Retrace Period.
;-----------------------------------------------------------------------------
WaitVRT proc near
mov dx,3DAh
WaitVR1: in al,dx
test al,8
jne WaitVR1
WaitVR2: in al,dx
test al,8
je WaitVR2
ret
WaitVRT endp
;-----------------------------------------------------------------------------
; Delay - Sleeps during any amount of time. Uses the VGA Vertical retrace.
; In:
; CX - Number of ticks to speed (ticks at 70Hz).
;-----------------------------------------------------------------------------
Delay proc near
DelayLoop: call WaitVRT
loop DelayLoop
ret
Delay endp
;-----------------------------------------------------------------------------
; SetPalette - Sets the VGA color palette.
; In:
; ES:SI - Palette segment address.
;-----------------------------------------------------------------------------
SetPalette proc near
push ds
mov ax,es
mov ds,ax
mov dx,3C8h
xor al,al
out dx,al
inc dx
mov cx,768
cld
rep outsb
pop ds
ret
SetPalette endp
;-----------------------------------------------------------------------------
; ShowSpray - Writes a picture on the scren using a Spray-like effect.
; In:
; DX - Picture source segment.
;-----------------------------------------------------------------------------
ShowSpray proc near
push ds
push es
mov ds,dx
xor si,si
mov ax,0A000h
mov es,ax
xor cx,cx
SprayLoop: push cx
xor bx,bx
SprayLine: push bx
mov ah,cs:[RandTable+bx]
mov bx,cx
mov al,cs:[RandTable+bx]
mov bx,ax
mov di,ax
mov al,ds:[si+bx]
mov es:[di],al
pop bx
inc cl
inc bl
jne SprayLine
pop cx
inc cl
jne SprayLoop
pop es
pop ds
ret
RandTable label byte
db 83, 8, 18, 177, 13, 241, 149, 157
db 75, 248, 254, 23, 16, 66, 207, 31
db 211, 183, 80, 242, 218, 27, 15, 128
db 94, 98, 4, 36, 139, 110, 85, 230
db 212, 26, 12, 249, 169, 233, 200, 150
db 95, 114, 130, 167, 202, 187, 76, 145
db 62, 117, 115, 190, 209, 42, 185, 224
db 129, 104, 108, 192, 174, 137, 44, 41
db 141, 53, 179, 81, 181, 57, 147, 210
db 50, 134, 156, 125, 133, 126, 106, 162
db 20, 59, 84, 0, 151, 143, 101, 215
db 68, 246, 189, 197, 99, 213, 112, 144
db 28, 235, 240, 90, 154, 56, 138, 165
db 19, 166, 159, 92, 127, 208, 105, 118
db 119, 153, 191, 184, 87, 70, 9, 164
db 60, 252, 96, 3, 171, 38, 136, 14
db 7, 160, 71, 146, 102, 229, 227, 43
db 221, 182, 217, 30, 131, 219, 61, 180
db 195, 245, 109, 203, 24, 49, 170, 247
db 46, 148, 122, 250, 173, 107, 255, 194
db 6, 37, 93, 22, 168, 97, 193, 5
db 51, 223, 116, 86, 1, 89, 121, 243
db 140, 220, 39, 222, 65, 55, 17, 54
db 175, 206, 214, 155, 142, 163, 25, 188
db 178, 11, 204, 135, 201, 238, 79, 132
db 198, 40, 21, 45, 237, 253, 152, 74
db 32, 111, 52, 47, 236, 2, 176, 239
db 234, 58, 100, 91, 172, 73, 82, 205
db 34, 88, 78, 231, 232, 225, 48, 251
db 67, 123, 244, 29, 216, 64, 196, 69
db 199, 33, 72, 35, 10, 63, 161, 228
db 113, 158, 120, 103, 124, 186, 226, 77
ShowSpray endp
;-----------------------------------------------------------------------------
; DoEmBoss - Do the EmBoss effect into a 320x200x256 picture.
; In:
; DX - Picture Source Segment.
;-----------------------------------------------------------------------------
DoEmboss proc
pusha
push ds
mov ds,dx ; DS:SI = source image.
xor si,si
xor cx,cx
EmBossLine: push cx ; Y= 0..198
xor bx,bx
EmBossLoop: push bx ; X= 0..318
add bx,cx
xor dh,dh
mov dl,[si+bx]
mov ax,dx
mov dl,[si+bx+MAXWIDTH+1]
sub ax,dx
mov dx,DEPTH ; EmBoss Depth Factor.
imul dx
mov al,ah
mov ah,dl
add ax,BRIGHT
cmp ax,MINGRAY ; Check Color Range.
jge EmbossHigh
mov ax,MINGRAY
EmbossHigh: cmp ax,MAXGRAY
jle EmbossLow
mov ax,MAXGRAY
EmbossLow: mov [si+bx],al
pop bx
inc bx
cmp bx,MAXWIDTH-2
jbe EmbossLoop
pop cx
add cx,MAXWIDTH
cmp cx,MAXWIDTH*(MAXHEIGHT-2)
jbe EmbossLine
pop ds
popa
ret
DoEmboss endp
;-----------------------------------------------------------------------------
; ShowSlide - Shows a 320x200x256 picture using a Slide Effect.
; In:
; DX - Piccy Source Segment.
;-----------------------------------------------------------------------------
ShowSlide proc
local Level:word:MAXWIDTH,Weight:word:MAXWIDTH,\
LevelPtr:word,WeightPtr:word
pusha
push ds
push es
mov ds,dx ; DS:SI = Source Picture.
xor si,si
mov ax,ss
mov es,ax
lea di,[Level] ; Clear Slide Row Levels.
mov cx,MAXWIDTH
cld
xor ax,ax
rep stosw
lea di,[Weight] ; Clear Slide Row Weights.
mov cx,MAXWIDTH
cld
xor ax,ax
rep stosw
mov ax,0A000h
mov es,ax
SlideLoop: call WaitVRT
lea bx,[Level] ; Loads Level Pointer.
mov [LevelPtr],bx
lea bx,[Weight] ; Loads Weight Pointer.
mov [WeightPtr],bx
xor cx,cx ; For Each Column:
xor dx,dx
SlideInner: mov bx,[LevelPtr] ; Level[Col] < 320*200? Skip.
mov ax,ss:[bx]
cmp ax,MAXWIDTH*MAXHEIGHT
jae SlideContinue
inc dx ; Sets Flag.
mov bx,[WeightPtr] ; Weight[Col] <> 0?
mov ax,ss:[bx] ; Yes, Decrease.
test ax,ax ; No, Slide Down Row.
jz SlideDown
dec ax
mov ss:[bx],ax
jmp SlideContinue
SlideDown: mov bx,[LevelPtr] ; Level[Col] += 320
mov ax,ss:[bx]
add ax,MAXWIDTH
mov ss:[bx],ax
add ax,cx ; DI = Col + Level[Col]
mov di,ax
mov bx,di ; Sets New Row Weight:
mov al,es:[di+MAXWIDTH] ; W=ABS(VMEM[DI+320]-VMEM[DI])
sub al,es:[di]
jge SlidePos
neg al
SlidePos: xor ah,ah
mov bx,[WeightPtr]
mov ss:[bx],ax
mov bx,di ; Put Pixel at (Col,Level[Col])
mov al,ds:[si+bx]
mov es:[di],al
SlideContinue: add [LevelPtr],2 ; Next Column.
add [WeightPtr],2
inc cx
cmp cx,MAXWIDTH
jb SlideInner
test dx,dx ; Screen 100% filled?
jnz SlideLoop ; No, Repeat.
pop es
pop ds
popa
ret
ShowSlide endp
;-----------------------------------------------------------------------------
; GenLenz - Renders the Transformation matrix used during animation.
;
; Note: The square root is calculated using the Newton iteration
; aproximation algorithm:
; y² + (r² - x²)
; y² ≡ r² - x² ══ y ≈ ────────────────
; 2y
;
; We performs only one iteration using a initial «y» value
; near to the real square root wanted.
;-----------------------------------------------------------------------------
GenLenz proc near
local X:word,Y:word,R:word,Dist:Word,AddX:word,AddY:word
mov ax,ds
mov es,ax
cld
xor ax,ax ; Fills the whole rectangle
lea di,[LenzTable] ; matrix with a linear
mov cx,2*RADIUS ; transformation.
MakLinLoop: push ax
push cx
mov cx,2*RADIUS
MakLinRow: stosw
inc ax
loop MakLinRow
pop cx
pop ax
add ax,MAXWIDTH
loop MakLinLoop
mov [X],RADIUS ; makes the scanlines
mov [Y],0 ; widths of the lenz
MakWidth: cmp [Y],RADIUS ; with radius RADIUS.
jge MakXWidth
mov ax,[X]
mov bx,RADIUS ; LenzWidth[Radius+Y] = X
add bx,[Y]
shl bx,1
mov [LenzWidth+bx],ax
mov bx,RADIUS ; LenzWidth[Radius-Y-1] = X
sub bx,[Y]
dec bx
shl bx,1
mov [LenzWidth+bx],ax
mov ax,[Y] ; X² = Radius² - Y²
imul ax
mov bx,ax
mov ax,[X]
imul ax
sub ax,bx
add ax,RADIUS*RADIUS
sar ax,1
cwd
mov bx,[X]
idiv bx
mov [X],ax
inc [Y] ; Y = Y+1
jmp MakWidth
MakXWidth:
mov [X],RADIUSI ; Makes the transformation
mov [Y],0 ; for the Lenz of radius
MakLoop: cmp [Y],RADIUSI ; RADIUSY. Notice that
jge MakExit ; this lets a border
; used for restoring the
; background while moving
; the lenz into the screen.
mov ax,[X] ; compute the scanline
mov dx,6 ; width adjusting with
imul dx ; an aspect ratio of 6/5.
mov bx,5
idiv bx
mov [R],ax
mov [Dist],0
mov [AddX],0
mov [AddY],ax
MakLine: mov ax,[R]
cmp [AddX],ax
jge MakLineBreak
; si = @LenzTable[0,RADIUS-Y-1]
lea si,[LenzTable]
mov ax,RADIUS
sub ax,[Y]
dec ax
imul ax,2*RADIUS
add si,ax
shl si,1
; di = @LenzTable[0,RADIUS+Y]
lea di,[LenzTable]
mov ax,RADIUS
add ax,[Y]
imul ax,2*RADIUS
add di,ax
shl di,1
; Lenz[RADIUS+AddX,RADIUS-Y-1] = RADIUS+Hi(Dist) +
; MAXWIDTH * (RADIUS-1-STRENGH*Y)
mov bx,RADIUS
add bx,[AddX]
shl bx,1
mov ax,[Y]
imul ax,STRENGH
sar ax,8
imul ax,MAXWIDTH
neg ax
add ax,RADIUS+MAXWIDTH*(RADIUS-1)
mov dx,[Dist]
shr dx,8
add ax,dx
mov [si+bx],ax
; Lenz[RADIUS-AddX-1,RADIUS-Y-1] = RADIUS-Hi(Dist)-1+
; MAXWIDTH * (RADIUS-1-STRENGH*Y)
mov bx,RADIUS
sub bx,[AddX]
dec bx
shl bx,1
mov ax,[Y]
imul ax,STRENGH
sar ax,8
imul ax,MAXWIDTH
neg ax
add ax,RADIUS+MAXWIDTH*(RADIUS-1)
mov dx,[Dist]
shr dx,8
sub ax,dx
dec ax
mov [si+bx],ax
; LenzTable[RADIUS+AddX,RADIUS+Y] = RADIUS+Hi(Dist)+
; MAXWIDTH * (RADIUS + STRENGH*Y)
mov bx,RADIUS
add bx,[AddX]
shl bx,1
mov ax,[Y]
imul ax,STRENGH
sar ax,8
imul ax,MAXWIDTH
add ax,RADIUS+MAXWIDTH*RADIUS
mov dx,[Dist]
shr dx,8
add ax,dx
mov [di+bx],ax
; LenzTable[RADIUS-AddX-1,RADIUS+Y] = RADIUS-Hi(Dist)-1+
; MAXWIDTH * (RADIUS+STRENGH*Y)
mov bx,RADIUS
sub bx,[AddX]
dec bx
shl bx,1
mov ax,[Y]
imul ax,STRENGH
sar ax,8
imul ax,MAXWIDTH
add ax,RADIUS+MAXWIDTH*RADIUS
mov dx,[Dist]
shr dx,8
sub ax,dx
dec ax
mov [di+bx],ax
; Dist = Dist + (Strengh*Radius)/dY
mov ax,STRENGH*RADIUS
cwd
mov bx,[AddY]
idiv bx
add [Dist],ax
mov ax,[AddY] ; dY² = R² - dX²
imul ax
mov bx,ax
mov ax,[AddX]
imul ax
sub bx,ax
mov ax,[R]
imul ax
add ax,bx
sar ax,1
cwd
mov bx,[AddY]
idiv bx
mov [AddY],ax
inc [AddX] ; dX = dX+1
jmp MakLine
MakLineBreak: mov ax,[X] ; X² = Radius'² - Y²
imul ax
mov bx,ax
mov ax,[Y]
imul ax
sub bx,ax
mov ax,RADIUSI*RADIUSI
add ax,bx
sar ax,1
cwd
mov bx,[X]
idiv bx
mov [X],ax
inc [Y] ; Y = Y+1
jmp MakLoop
MakExit: ret
GenLenz endp
;-----------------------------------------------------------------------------
; WriteLenz - Writes the Lenz using the transformation matrix.
; In:
; DI - Starting offset location of the lenz.
; DX - Virtual picture used like background.
;-----------------------------------------------------------------------------
WriteLenz proc near
push bp
mov ax,0A000h
mov es,ax
lea bx,[LenzTable]
lea si,[LenzWidth]
mov bp,di
mov cx,2*RADIUS
cld
WriteLoop: push bx
push cx
push si
push di
cmp di,MAXWIDTH*MAXHEIGHT
jae WriteBreak
mov cx,[si] ; gets the scanline width.
mov ax,RADIUS
sub ax,cx
add di,ax
add bx,ax
add bx,ax
WriteLine: push es
mov es,dx
mov si,[bx]
mov al,es:[bp+si]
mov si,[bx+2]
mov ah,es:[bp+si]
add bx,4
pop es
stosw
loop WriteLine
WriteBreak: pop di
pop si
pop cx
pop bx
add bx,4*RADIUS
add si,2
add di,MAXWIDTH
loop WriteLoop
pop bp
ret
WriteLenz endp
;-----------------------------------------------------------------------------
; LenzDemo - Performs the demostration.
; In:
; DS - Data Segment.
; PicSeg - VGA 320x200x256 Picture used for Background.
; PalSeg - Color Palette of the Picture.
;-----------------------------------------------------------------------------
LenzDemo proc PicSeg:word,PalSeg:dword
local X:word,Y:word,AddX:word,AddY:word
mov ax,13h ; sets 320x200x256 mode.
int 10h
call GenLenz ; creates the lenz matrix.
mov cx,35 ; waits 0.5 seconds.
call Delay
les si,[PalSeg] ; sets the palette.
call SetPalette
mov dx,[PicSeg] ; writes the picture
call ShowSpray ; to the screen.
mov [RandSeed],SEED ; Randomize.
mov [Timer],0
mov [X],RADIUS
mov [Y],RADIUS
mov [AddX],3
mov [AddY],2
DemoLoop: call WaitVRT ; Waits VR period.
mov ax,[Y] ; outputs the lenz
sub ax,RADIUS ; crystall ball at
mov dx,MAXWIDTH ; center coordinates (X,Y).
mul dx
add ax,[X]
sub ax,RADIUS
mov di,ax
mov dx,[PicSeg]
call WriteLenz
AdjustX: mov ax,[X] ; adjust the X coord.
add ax,[AddX]
cmp ax,RADIUS
jb ChangeX
cmp ax,MAXWIDTH-RADIUS
ja ChangeX
mov [X],ax
jmp AdjustY
ChangeX: call Random
shr ax,15
inc ax
cmp [AddX],0
jl SetAddX
neg ax
SetAddX: mov [AddX],ax
AdjustY: mov ax,[Y] ; adjust the Y coord.
add ax,[AddY]
cmp ax,RADIUSI
jb ChangeY
cmp ax,MAXHEIGHT-RADIUSI
ja ChangeY
mov [Y],ax
jmp Continue
ChangeY: call Random
and ax,1
inc ax
cmp [AddY],0
jl SetAddY
neg ax
SetAddY: mov [AddY],ax
Continue: inc [Timer] ; timeout?
cmp [Timer],TIMEOUT
jae DemoExit
mov ah,1 ; any key pressed?
int 16h
je DemoLoop
mov ah,0 ; flush keyboard.
int 16h
DemoExit: mov dx,[PicSeg] ; EmBoss the Piccy.
call DoEmboss
mov dx,[PicSeg] ; SlideDown the Piccy.
call ShowSlide
mov cx,70 ; Sleep a while..
call Delay
mov es,[PicSeg] ; Blanks the picture.
xor di,di
mov cx,MAXWIDTH*MAXHEIGHT
xor ax,ax
cld
rep stosb
mov dx,[PicSeg] ; Clears the Screen.
call ShowSpray
mov cx,35 ; waits 0.5 seconds.
call Delay
mov ax,03h ; restores 80x25x16 mode.
int 10h
ret
LenzDemo endp
;-----------------------------------------------------------------------------
; Start - Startup Code called from DOS.
; In:
; ES - Program Segment Prefix.
;-----------------------------------------------------------------------------
Start proc
mov ax,@Data
mov ds,ax
call LenzDemo,SEG LenzPic,SEG LenzPal,OFFSET LenzPal
mov ax,4C00h
int 21h
Start endp
end Start