A new version arrived to me from Mark Andreas reducing the size to 122 bytes. If speed is not the issue and a very instable keycheck is used it can be reduced to 120 bytes (both these to version are included in the archive along with the previous two ones). All optimizations are described in the text below. Also note that it may run on a 386 based computer if source modified (still same size), read in the source.
This is the original gem text:
Now we have 128 bytes.
; ; ; - f l a m e - ; quality 122 byte fire ; copyright 1997 Gaffer/prometheus ; gaffer@zip.com.au ; ; optimization contribution: ; goblin,icepick,mf,patrik sundberg,pgeist ; mark andreas .MODEL TINY .486 ;# see note next to XADD instruction UDATASEG Buffer DB 320*203 dup(?) ;# You may wish to insert code to keep Buffer aligned on an ;# even address, regardless of the size of the program. CODESEG ORG 100h LOCALS ; INITIALIZATION: setup video mode & palette ; ------------------------------------------ .STARTUP ; SETUP VGA SEG push 0A000h pop es ; INIT VGA MODE 13h mov al,13h ;# doesn't look nice if using mode 93h int 10h ; GENERATE PALETTE dec di PaletteGen: ; alternate palette generation xor ax,ax ; (Patrick Sundberg) mov cl,63 @@L1: stosb inc ax cmpsw ; small way to advance si,di! ;# why are we advancing SI too ;# scasw works just as well (same size) loop @@L1 push di mov cl,192 @@L2: stosw inc di loop @@L2 pop di inc di jns PaletteGen ; cheesy! :) ; SET PALETTE mov ax,1012h cwd ; equivalent to 'xor dx,dx' mov cl,255 int 10h ; MAIN LOOP: Cycle through flame animation until keypress ; ------------------------------------------------------- MainLoop: push es push ds pop es ; set es=ds to use stosw ; FLAME ANIMATION inc cx mov di,OFFSET Buffer mov bl,99 @@L3: mov ax,[di+639] add al,ah setc ah mov dl,[di+641] add ax,dx mov dl,[di+1280] add ax,dx shr ax,2 jz @@ZERO ; cool a bit... dec ax @@ZERO: stosb add ax,dx ; double the height shr ax,1 mov [di+319],al loop @@L3 mov cx,320 add di,cx dec bx jnz @@L3 ; FLAME GENERATOR BAR ; assumes cx=320 ; assumes di=generator bar offset (bottom of flame buffer) @@L4: ;# in ax,40h ; read from timer ;# don't need to thump the clock 320 times per frame. That just ;# kills the display on slower video cards, even on Pentiums ;# In fact, the display looks just as nice without this instruction. ;# If you decide it's needed, try moving it to be just before the ;# loop, so you're only reading the port once per frame. ;# xadd [ds:100h],ax ; "seed" is first two bytes of code ;# Instead, use the BP register as a seed. xadd bp,ax ;# ;# another option for allowing the program to run on a 386 is to ;# replace XADD, since that's the only 486 instruction used. ;# an alternate of the same size is: ;# add ax,[di] ;# inc ax ;# mov ah,al ;# removing this instruction doesn't seem to affect the display. stosw stosw loop @@L4 pop es ; restore es=A000h ; OUTPUT FLAME TO SCREEN xor di,di mov si,OFFSET Buffer + 320 mov ch,60 ; assumes cl=0 rep movsd ; change to "mov ch,120" "rep movsw" ; saves one byte but is slower ; (patrik sundberg) ; CHECK FOR KEYPRESS mov ah,1 int 16h jz MainLoop ; alternative keypress check ; "in al,60h" "das" "jc MainLoop" ; saves one byte but is not as reliable ; (icepick) ; DOS EXIT CODE: Switch to textmode, return to DOS ; ------------------------------------------------ mov ax,03h int 10h ret END