pouët.net

256 Automata by Northern Dragons [web]

;===============================================================================
;
;	256 AUTOMATA      
;	a 
;	256byte demo
;	by                
;	Polaris & BarZoule
;	of the            
;	Northern Dragons  
;	
;	featuring:
;	 colors, music, sync, self-exit, exit on [esc]
;
;	Lastest version of the source is below, so you can try
;	to figure out what's going on and maybe learn from it.
;
;===============================================================================
bits 16					
org 100h                
                        
%define b byte          
%define w word          
                        
GD_WIDTH	equ 40      
GD_HEIGHT 	equ 25      
GD_SIZE 	equ (GD_WIDTH*GD_HEIGHT-8)  ;//paste it to screen+8, but logically it starts at 0,0
GD_STEP_X 	equ (3)
GD_STEP_Y 	equ (GD_WIDTH*3)
PART_MAX 	equ 6
COLORIZE	equ 0
COLORIZE2	equ 1

PENTIUMPRO	equ 0

	
SECTION .text ;_________________________________________________________________
;_______________________________________________________________________________

main:
;set screen mode
					;mov ax,0h
	int 10h
	;15 bytes of code. same as 5 particles.
	mov di,partD	;assume partD and partP are consecutive
	mov al,GD_STEP_X
	mov cl,PART_MAX
rep	stosb
	mov al,4*GD_STEP_X+2*GD_STEP_Y	;00FC
	mov cl,PART_MAX
rep	stosw	
	
	mov ch,02h		;mov cx,512, drives the length of the intro
mloop:	
	mov ax,242h		;mov ax,512+64+2, gotta be more than 64 more than CX
	sub ax,cx
	shr ax,6		;3	ax = (512-cntz)/64
	cmp al,PART_MAX	;2	compare low only.
	jl under5		;2	max of 5 particle at once
	mov al,PART_MAX	;2	if(PART_NUM>=5)PART_NUM=5;
under5:
	push cx
;updateASM______________________________________________________________________
	push ax			;got PART_NUM through AX

	mov ch, 4h ;GD_SIZE	;undo last draw (GD_SIZE if 03e0, if we count over 400, it's plenty
%IF COLORIZE2
	mov di, grid-1	;grid-1 == col
	stosb			;al == particle count
%ELSE
	mov di, grid	;grid-1 == col
%ENDIF
	mov al,-1
rep	stosb

;//move + draw
	pop cx			;retrieve PART_NUM to cx
	stosb
update:
	mov si,cx		; cx at this point is 5..1, hence -1 and -2
	lea di,[partP-2+si]
	add di,si
	add si,partD-1
	
;//flip dir on borders
	mov ax,[di]		;partP+[di]
	mov dl,GD_WIDTH
	div dl			;ah = ax % W  ; al = ax / W
	mov dx,ax		;keep a copy
	or ax, 1818h	;	((24<<8)|24)	;ah|=24 ; al|=24
	cmp ah,18h
	je play
	mov dl,dh		;note to play in dl
	cmp al,18h
	jne noplay
play:
;//play note
	movzx ax,dl
	mov dl,3
	div dl			;al/=3
	push cx
	xchg cx,ax		;not really safe but.. dl should always be multiple of 3 right?
;playNote_______________________________________________________________________
	;; takes bx as input
	;; put mpu into uart mode
	;; dx = midiport
	mov dx,331h
	mov al,3Fh
	out dx,al

	;;play a test note
	dec dx
	mov al,90h
	out dx,al		; Note on - chanel 0
	mov ax,0A53Ah	; otherwise get it in CX
%IF COLORIZE2
	mov b [col],al	;colorize background, picking an ok col-scheme
%ENDIF
gnote:
	shl ah,1
	adc al,2
	loop gnote		; done computing the note
	out dx,al		; Note number
	out dx,al		; Velocity
;_______________________________________________________________________________
	pop cx

;//bounce
	neg b [si]		;partD+[si]
noplay:
;//move
	movsx ax, b [si];partD+[si]		;partD is byte   ;movsx as big as mov + cbw
	add [di],ax		;partP is word
	;di == partP[cx]
	;di = &grid[ partP[cx] ]
	;bx = grid[ partP[cx] ]
	mov di, [di]
	add di, grid
	movzx bx, b [di];bx used in full for storing AL
	mov ax,cx		;counter is 1..5
	dec ax
	cmp bl,bh		;grid+[di]  if <0, nothing plot yet on grid
	jl  keepdir		;signed compare
;//collide
	mov ax, ((-GD_STEP_Y) & 0FFh) | (GD_STEP_Y << 8)
	mov dl, [si]
	cmp dl, ah
	je xax
	cmp dl, al
	je xax
	jmp yax
midjump:	jmp mloop	;loop mloop toward the end can't jumps that far so we use this to bounce up
xax:
	mov ax, ((-GD_STEP_X) & 0FFh) | (GD_STEP_X << 8)
yax:
	mov [si],ah
	mov [partD+bx],al
	mov al,-2
keepdir:
	stosb			;mov BYTE PTR [di],al		;di is gonna be reset after loop, don't care.
	loop update
;_______________________________________________________________________________
;pwait______________;(15b)______________________________________________________
	xor ah,ah		;2	;seed initial value
	int 1ah			;2
	xchg bx,dx		;2
	inc bx			;add bl,02 takes 3 bytes. two inc takes 2
	inc bx
wloop:
	int 1ah			;2
	cmp dx,bx		;2
	jbe wloop		;2
;_______________________________________________________________________________
;drawASM________________________________________________________________________
	;mov cx, GD_SIZE
	mov ch, 4		;GD_SIZE is 03E0h, couple bytes short of 0400h
	mov si, grid	;grid is char
	xor di,di		;mov di,0	;screen offset
	push es
	push 0B801h		;+1 to center in screen :D
	pop es
fillit:
	lodsb			;al = *(grid++)
	cbw				;do we really have to clean it up? yes!
	cmp al,0		;-1:space  -2:diamond
	jl  ntbl
ndm:
	xchg ax,bx
	mov al,[partD+bx]
	shr al,6		;hack, because of the input numbers, gives 0..4
ntbl:
	add al,2		;from -2..3 to 0..5
	mov bx,glyph
	xlat
	
;	About coloring.
;	removing the coloring removes a whole 12 bytes.
;	recoloring with a constant color could also save an additional byte
;	now about coloring separately, in a deicated loop: while it looks
;	like a good idea, removing the need of division and test, it adds
;	no less than 26 bytes!!

%IF COLORIZE
ok:
	xchg bx,ax
	mov bh,0Eh		;white on black
	;this provides some coloring... (just a pale square in the middle)
	mov ax,di
	mov dl,GD_WIDTH*2
	div dl			;ah= ax % dl; al= ax / dl
	cmp ah,48
	ja ncol			;need just one compare, since it's shifted AFTER :)
;	mov bh,7Fh		;white on grey, if on the square
	mov bh,[col]
ncol:
	xchg ax,bx
	stosw			;mov al only (not ax), to omit coloring
%ELIF COLORIZE2
ok:
;	push ax
;	mov ax,di
;	mov dh,GD_WIDTH*2
;	div dh
;	sub ah,50
;	pop ax
;	lahf
;	and ah,080h
;	stosw

	stosb
	mov ax,di
;	mov dx,(GD_WIDTH*2)<<8|7Eh
	mov dl, GD_WIDTH*2
	div dl
	cmp ah,50
	mov al,[col]
%IF PENTIUMPRO
	cmovge ax,di	;crashes on DOSBOX
%ELSE
	jnge skip		;one byte too large :(
	mov ax,di
skip:
%ENDIF
	stosb
%ELSE
ok:
	stosb
	inc di
%ENDIF
	loop fillit
	pop es
;_______________________________________________________________________________
	pop cx
	in al,60h
	dec al
	loopnz midjump	;mloop is too far, gotta use a midjump
;restore screen mode
	mov ax,3h
	int 10h
	ret				;Terminate not so clean, but it's cheap
;===============================================================================
;keping data in the same section to prevent byte wasting alignment
;SECTION .data ;_________________________________________________________________

;super precise order. we shr 6 the input and it gives us the index.
;only posible with these number, otherwise we'd have to find other masks or something :)
	;03h -> 10h		00000011
	;78h -> 1Fh		01111000
	;88h -> 1Eh		10001000
	;FDh -> 11h		11111101
	glyph	db 04,32
			db 16,31,30,17
	;padding	dw 444Eh ;last word for ND ;)


SECTION .bss ;__________________________________________________________________
	partD	resb PART_MAX
	partP	resw PART_MAX
%IF COLORIZE || COLORIZE2
	col		resb 1
%ENDIF
	grid	resw GD_SIZE
;===============================================================================