ORG 100h
numstars equ 100
; star:
; word x
; word y
; word z
; word unused
; total 8 bytes, shl 3
bigthreshold equ 70
; Z less than this makes a big star
SECTION .text
main:
; point es to vga memory
mov ax,0A000h
mov es,ax
; switch to graphics mode 13h
mov ax,0013h ; INT10h AH=00h BIOS Set video mode
int 10h ; mode 13h 320x200 8 bit single page
; don't clear screen, assume switching mode does that
call randseed
%macro for_all_stars 1
mov cx,numstars
mov bx,stardata
%%loop:
call %1
; assume function moves bx to next star
loop %%loop
%endmacro
; don't init stars, use whatever is already in memory
;for_all_stars resetstar
.mainloop:
; process all stars
for_all_stars updatestar
; check for keyboard input
mov ah,01h ; haha bios function leaves keystroke in buffer
int 16h ; so dos gets it too
jz .mainloop
; out of mainloop, reset mode
mov ax,0003h ; INT10h AH=00h BIOS Set video mode
int 10h ; text 80x25 colour
.exit:
; terminate to dos
int 20h
; Initialise a star to a new location
; Entry:
; ds:bs points to star to init
; Exit:
; ax destroyed
; ds:bx points to next star
resetstar:
; generate x
call .gencoord
; generate y
call .gencoord
; set z to 511-256
call rand
and ax,00FFh
add ax,256
mov [bx],ax
add bx,4 ; next star
ret
.gencoord:
call rand
sar ax,1
mov [bx],ax
add bx,2
ret
; Move and redraw a star
; Entry:
; ds:bx points to star to update
; Exit:
; no change
updatestar:
; save
pushad
; read star x and y, abuse si/di for temp storage
mov si,[bx]
add bx,2
mov di,[bx]
add bx,2
; read star z into cx which we'll be dividing by
mov cx,[bx]
cmp cx,0
jz .needreset
; get screen coordinates
call getscreenxy
; determine painting attributes from z
xor ax,ax
cmp cx,bigthreshold
setbe ah
; clear old star position (al=0 i.e. black, from xor)
call drawstar
; update star z
dec cx
jz .needreset ; hit zero, time to spawn a new star to avoid singularity
mov [bx],cx ; store back
; move back to start of star and re-read it
sub bx,2
mov di,[bx]
sub bx,2
mov si,[bx]
; cx has updated z coord, get screen new coordinates
call getscreenxy
; check coordinates are inside screen bounds
cmp si,0
jl .needreset
cmp si,318
jg .needreset
cmp di,0
jl .needreset
cmp di,198
jg .needreset
; if star is too distant, skip it
cmp cx,255
ja .skipdraw
; inside bounds, so draw
mov dx,cx ; get 4 upper bits of distance
shr dx,4
and dx,15
mov ax,15 ; distant stars (dx now large) must have small values (darker)
sub ax,dx
add ax,16 ; make 16-31 (grays in vga palette)
xor ah,ah
cmp cx,bigthreshold ; check size
setbe ah
call drawstar
.skipdraw
; restore
popad
add bx,8
ret
.needreset:
popad
jmp resetstar
; Calculate the screen x/y of a star
; Entry:
; cx has z coordinate
; si has x coordinate
; di has y coordinate
; Exit:
; ax destroyed
; dx destroyed
; cx unchanged
; si has screen x coordinate
; di has screen y coordinate
getscreenxy:
%macro work 2
mov ax,%1
mov dx,%1
sar dx,16
idiv cx
add ax,%2
mov %1,ax
%endmacro
work si,160 ; calculate star x screen coordinate
work di,100 ; calculate star y screen coordinate
%undef work
ret
; Draw a star
;
; Entry:
; ah is size (0 small, else large)
; al is colour to use for drawing
; si is X coordinate
; di is Y coordinate
; es has vga memory segment
; Exit:
; ah destroyed
; dx destroyed
; di destroyed
drawstar:
; set di = 320*di + si
; 320 = 101000000b
mov dx,di
shl di,2
add di,dx
shl di,6
add di,si
; fill first pixel
stosb
; check if big
cmp ah,0
jne .big
ret
.big:
stosb
add di,318
mov ah,al
stosw
ret
; Seed random number generator
;
; Entry:
; nothing
; Exit:
; nothing
randseed:
; save
push ax
push bx
push cx
push dx
; get system time for seeding
mov ah,2Ch ; INT21h AH=2Ch get system time
int 21h ; stores hour/min in cx and sec/csec in dx
; store seed
mov bx,.seed
mov [ds:bx],dx
; restore
pop dx
pop cx
pop bx
pop ax
ret
.seed:
dw 0
; Get random bits
;
; Entry:
; nothing
; Exit:
; ax contains random bits
rand:
; save
push bx
push cx
push dx
; load seed and multiplier
mov bx,randseed.seed
mov ax,[ds:bx]
mov cx,16807
; multiply
mul cx
; add
add ax,1
; store new seed
mov [ds:bx],ax
; restore
pop dx
pop cx
pop bx
ret
stardata:
; end of code, store star data here