All pastes #1850881 Raw Edit

stars3.asm

public text v1 · immutable
#1850881 ·published 2010-03-23 22:52 UTC
rendered paste body
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
	push 0A000h
	pop es
	
	; 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
	pusha
	; 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
	popa
	add bx,8
	ret
.needreset:
	popa
	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
	pusha
	; 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 [.seed],dx
	; restore
	popa
	ret
.seed:
	dw 0

; Get random bits
;
; Entry:
;  nothing
; Exit:
;  ax contains random bits
rand:
	; save (can't use pusha/popa since ax needs to be returned)
	push cx
	push dx
	; load seed and multiplier
	mov ax,[randseed.seed]
	mov cx,16807
	; multiply
	mul cx
	; add
	add ax,1
	; store new seed
	mov [randseed.seed],ax
	; restore
	pop dx
	pop cx
	ret



stardata:
	; end of code, store star data here