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 ;===============================================================================
[ back to the prod ]