repeats equ 1 offset equ 256 unity equ 16777216 two equ unity+unity colors equ 256 height equ 512 width equ 512 height2 equ height*8 width2 equ width*8 startx equ -2 starty equ -2 endx equ 2 endy equ 2 quantity equ height*width beginx equ startx*unity ;;;; -12713984 beginy equ starty*unity ;;;;4194304 stepx equ 131072 stepy equ 131072 stepx2 equ stepx/8 stepy2 equ stepy/8 jmp start words: db 13,"*************************" db 13,10,"* WEHNER`s *" db 13,10,"* OWLBROT FRACTAL MAKER *" db 13,10,"* COPYRIGHT 2006 *" db 13,10,"* WIDTH 512 PIXELS *" db 13,10,"* HEIGHT 512 PIXELS *" db 13,10,"* START -2 *" db 13,10,"* -2 *" db 13,10,"* STEP 131072 *" db 13,10,"* 131072 *" db 13,10,"* FINISH +2 *" db 13,10,"* +2 *" db 13,10,"*************************",13,10,"$",26 header: db 066,077,054,004,004,000,000,000,000,000,054,004,000,000,040,000 ;;;BM6.......6...(. db 000,000 dd width ; 000,002,000,000 for 512 dd height ; 000,002,000,000 for 512 db 001,000,008,000,000,000 db 000,000,000,000,004,000,000,000,000,000,000,000,000,000,000,001 db 000,000,000,001,000,000 palette: db 255,255,255,000,249,255,249,000,243,255 db 243,000,237,255,237,000,231,255,231,000,225,255,225,000,219,255 db 219,000,213,255,213,000,207,255,207,000,201,255,201,000,195,255 db 195,000,189,255,189,000,183,255,183,000,177,255,177,000,171,255 db 171,000,165,255,165,000,159,255,159,000,153,255,153,000,147,255 db 147,000,141,255,141,000,135,255,135,000,128,255,128,000,122,255 db 131,000,116,255,134,000,110,255,137,000,104,255,140,000,098,255 db 143,000,092,255,146,000,086,255,149,000,080,255,152,000,074,255 db 155,000,068,255,158,000,062,255,161,000,056,255,164,000,050,255 db 167,000,044,255,170,000,038,255,173,000,032,255,176,000,026,255 db 179,000,020,255,182,000,014,255,185,000,008,255,189,000,000,255 db 189,000,000,252,205,000,000,249,211,000,000,246,217,000,000,243 db 223,000,000,240,229,000,000,237,235,000,000,231,238,000,000,225 db 243,000,000,219,246,000,000,213,249,000,000,207,252,000,000,201 db 255,000,000,195,255,000,000,189,255,000,000,183,255,000,000,177 db 255,000,000,171,255,000,000,165,255,000,000,159,255,000,000,153 db 255,000,000,147,255,000,000,141,255,000,000,135,255,000,000,128 db 255,000,000,122,255,000,000,116,255,000,000,110,255,000,000,104 db 255,000,000,098,255,000,000,092,255,000,000,086,255,000,000,082 db 255,000,000,076,255,000,000,070,255,000,000,064,255,000,000,058 db 255,000,000,052,255,000,000,046,255,000,000,040,255,000,000,034 db 255,000,000,028,255,000,000,022,255,000,000,016,255,000,000,010 db 255,000,000,004,255,000,000,000,255,000,006,000,255,000,012,000 db 255,000,018,000,255,000,024,000,255,000,030,000,255,000,036,000 db 255,000,042,000,255,000,048,000,255,000,054,000,255,000,060,000 db 255,000,066,000,255,000,072,000,255,000,078,000,255,000,084,000 db 255,000,090,000,255,000,096,000,255,000,102,000,255,000,108,000 db 255,000,114,000,255,000,120,000,255,000,128,000,255,000,134,000 db 255,000,140,000,255,000,146,000,255,000,152,000,255,000,158,000 db 255,000,164,000,255,000,170,000,255,000,176,000,255,000,182,000 db 255,000,188,000,255,000,194,000,255,000,200,000,255,000,206,000 db 255,000,212,000,255,000,218,000,255,000,224,000,255,000,230,000 db 255,000,236,000,255,000,242,000,255,000,248,000,255,000,255,000 db 255,000,255,000,252,000,255,000,246,000,255,000,240,000,255,000 db 234,000,255,000,228,000,255,000,222,000,255,000,216,000,255,000 db 210,000,255,000,204,000,255,000,198,000,255,000,192,000,255,000 db 186,000,255,000,180,000,255,000,174,000,255,000,168,000,255,000 db 162,000,255,000,156,000,255,000,150,000,255,000,146,000,255,000 db 140,000,255,000,134,000,255,000,128,000,255,000,122,000,255,000 db 116,000,255,000,110,000,255,000,104,000,255,000,098,000,255,000 db 092,000,255,000,086,000,255,000,080,000,255,000,074,000,255,000 db 068,000,255,000,062,000,255,000,056,000,255,000,050,000,255,000 db 044,000,255,000,038,000,255,000,032,000,255,000,026,000,255,000 db 020,000,255,000,014,000,255,000,008,000,255,000,000,000,255,006 db 000,000,255,012,000,000,255,018,000,000,255,024,000,000,255,030 db 000,000,255,036,000,000,255,042,000,000,255,048,000,000,255,054 db 000,000,255,060,000,000,255,066,000,000,255,072,000,000,255,078 db 000,000,255,084,000,000,255,090,000,000,255,096,000,000,255,102 db 000,000,255,108,000,000,255,114,000,000,255,120,000,000,255,128 db 000,000,249,128,000,000,243,128,000,000,237,128,000,000,231,128 db 000,000,225,128,000,000,219,128,000,000,213,128,000,000,207,128 db 000,000,201,128,000,000,195,128,000,000,189,128,000,000,183,128 db 000,000,177,128,000,000,171,128,000,000,165,128,000,000,159,128 db 000,000,153,128,000,000,147,128,000,000,141,128,000,000,135,128 db 000,000,128,128,000,000,122,128,000,000,116,128,000,000,110,128 db 000,000,104,128,000,000,098,128,000,000,092,128,000,000,086,128 db 000,000,080,128,000,000,076,128,000,000,070,128,000,000,064,128 db 000,000,058,128,000,000,052,128,000,000,046,128,000,000,040,128 db 000,000,034,128,000,000,028,128,000,000,022,128,000,000,016,128 db 000,000,010,128,000,000,004,128,000,000,000,128,000,000,006,122 db 006,000,012,116,012,000,018,110,018,000,024,104,024,000,030,098 db 030,000,036,092,036,000,042,086,042,000,048,080,048,000,054,074 db 064,000,060,068,060,000,064,064,064,000,056,056,056,000,048,048 db 048,000,040,040,040,000,032,032,032,000,024,024,024,000,012,012 db 012,000,000,000,000,000 dest: ; File handle of destination file dw 0 dump: ; When dumping to disk, how many bytes dw 0 ; TOGETHER dumpseg: ; When dumping to disk, how many 32Ks dw 0 linepos: ; When printing "LINE NUMBER", last char dw linenoend+offset-2 mandelx: ; The real part of Zo times 16777216 dd beginx mandely: ; The unreal part of Zo times 16777216 dd beginy juliax: ; The real part of Z times 16777216 dd 0 juliay: ; The unreal part of Z times 16777216 dd 0 juliax2: ; The real part of the PREVIOUS iteration dd 0 juliay2: ; The unreal part of the PREVIOUS iteration dd 0 xsquared: ; Real-squared of Z dd 0,0 ysquared: ; Unreal-squared of Z dd 0,0 twicexy: ; Real times unreal of Z times 2 dd 0,0 mandpix: ; The pixel (byte) being evaluated dw 0 mandseg: ; The segment in which "mandpix" is dw 0 julidump: ; When working out the Julia byte dd 0,0 picseg: ; When working out the segment dw 0 fling: db 255 filename: db "owl.bmp",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 destprob: db "OUTPUT FILE PROBLEM",13,10,"$" nocreate: db "CANNOT CREATE THE OWL.BMP FILE",13,10,"$" completed: db 13,10,"DONE. FILE OWL.BMP COMPLETED",13,10,"$" lineno: db 13,"LINE NUMBER $" db "00000$" linenoend: abort: mov ax,cs mov ds,ax mov es,ax mov ax,900h int 33 mov ah,76 int 33 writeline: mov dx,lineno+offset ; Display CR,"LINE NUMBER" mov ax,900h int 33 std mov si,linenoend+offset-2 mov di,linenoend+offset-2 linenoloop: lodsb inc al ; Increment the last number cmp al,"9"+1 jnc repeatno stosb mov dx,si inc dx cmp dx,[linepos+offset] ; If linepos is lower than before, jnc sayline mov [linepos+offset],dx ; put it into the variable. sayline: mov dx,[linepos+offset] ; Get the start of the number mov ax,900h ; and display. int 33 ret repeatno: ; If a number went beyond 9 mov al,"0" ; set it to 0 stosb jmp linenoloop ; and increment the previous. start: mov dx,words+offset ; Display the title mov ax,900h int 33 mov dx,filename+offset xor cx,cx mov ax,3c00h ; Create the output file int 33 mov dx,nocreate+offset jc abort mov [dest+offset],ax mov ax,4000h ; Put in the header and palette mov bx,[dest+offset] mov cx,1078 mov dx,header+offset int 33 mov dx,destprob+offset jc abort mov eax,(height*width) ; Height*width in BYTES mov bx,ax and bx,32767 add eax,eax ; Upper is groups of 32k mov [dump+offset],eax ; DUMPSEG gets upper part. mov [dump+offset],bx ; DUMP gets modulus cld mov eax,0h ; Lowest palette value, 4 pixels mov cx,[dumpseg+offset] mov dx,cs add dx,(65536/16) ; Prepare for segment 64k above and cx,cx ; is CX nil? jz lastones blankloop: mov es,dx push cx mov cx,8192 ; Fill the buffer with 0s mov di,0 repz stosd ; Four at a time (d for DOUBLE) add dx,(32768/16) ; shift segment pointer pop cx loop blankloop lastones: mov cx,bx ; Fill the buffer with 255s and cx,cx jz nolast mov es,dx mov di,0 repz stosb ; One at a time (b for BYTE) nolast: mov dx,cs mov es,dx mov cx,repeats sevenflings: push cx mov eax,beginx mov [mandelx+offset],eax mov eax,beginy mov [mandely+offset],eax mov ax,0 ; Start off pixel address mov [mandpix+offset],ax mov ax,cs ; Start off pixel segment add ax,(65536/16) mov [mandseg+offset],ax ;************************ MAIN ROUTINE HERE ******************** mov cx,height2 ; Prepare for a loop of HEIGHT*8 lines. lineloop: push cx mov cx,width2 ; Prepare for a loop of WIDTH*8 pixels. dotloop: push cx ; Save the pixels-per-row counter mov cx,colors ; For each dot, COLORS iterations. mov eax,[mandelx+offset] ; Mandel X (Xo) mov [juliax+offset],eax ; is the first X mov eax,[mandely+offset] ; Mandel Y (Yo) mov [juliay+offset],eax ; is the first Y chaosloop: push cx ; Save the COLORS count mov eax,[juliax+offset] ; Working on X mov ecx,eax add ecx,ecx ; Signum into carry sbb ecx,ecx ; Signum is FFFFFFFF or 0 xor eax,ecx ; (Cancel the signum) mov ebx,eax ; Store absolute X mul ebx ; Multiply absolute X by absolute X mov [xsquared+offset],eax ; Put Xsq away mov [xsquared+offset+4],edx mov eax,[juliay+offset] ; Working on Y mov edx,eax add edx,edx ; Signum into carry sbb edx,edx ; Signum is FFFFFFFF or 0 xor eax,edx ; (Cancel the signum) push eax ; Save absolute Y xor ecx,edx ; Get combined signum to ECX mov edx,eax mul edx ; Multiply absolute Y by absolute Y mov [ysquared+offset],eax ; Put Ysq away mov [ysquared+offset+4],edx pop eax ; Rescue absolute Y mul ebx ; EBX contained absolute X add eax,eax ; Get 2 * XY adc edx,edx xor eax,ecx ; Correct the signum xor edx,ecx ; of both parts. mov [twicexy+offset],eax ; Store them. mov [twicexy+offset+4],edx pop cx ; Rescue the COLORS count dec cx jz bailout ; If count expired, jump out. mov edx,[ysquared+offset+3] mov eax,[xsquared+offset+3] add eax,edx cmp eax,4*unity jnc bailout ; If xsq + ysq >= 4, jump out. sub eax,edx ; EDX contained Y2, so subtract. sub eax,edx ; TWICE. add eax,[mandelx+offset] ;;cmp cl,[fling+offset] ;;jc nochange mov ebx,[juliax+offset] mov [juliax2+offset],ebx mov ebx,[juliay+offset] mov [juliay2+offset],ebx ;;nochange: mov [juliax+offset],eax ; New Julia Set X position mov eax,[twicexy+offset+3] ; Divide by 256 add eax,[mandely+offset] mov [juliay+offset],eax ; New Julia Set Y position jmp chaosloop bailout: not cl ;******** RANDOM ACCESS PLOTTING 512*512 *************** xor eax,eax mov [julidump+offset],eax mov ax,[juliax2+offset+2] ; Upper 2 bytes describe pixel X add ax,two/65536 ; when no longer negative rcr eax,1 ; and halved (128 represents 1) and ax,001ffh ; and masked. mov [julidump+offset],ax mov ax,[juliay2+offset+2] ; Upper 2 bytes describe pixel Y add ax,two/65536 ; when no longer negative and ax,003feh ; halved and doubled, then masked. or [julidump+offset+1],ax ; 256 bytes higher. mov eax,[julidump+offset] ; Top 3 bytes have the total cmp eax,quantity jnc plotdun mov di,ax ; Julia pixel 0 to 65535 xor ax,ax ; Clear the bottom part add eax,eax ; Upper part times 16 add eax,eax add eax,eax add eax,eax mov [julidump+offset],eax ; Dump mov ax,cs add ax,(65536/16) add ax,[julidump+offset+1] ; and fetch 256 times higher. mov es,ax ; ES:DI for destination mov ds,ax ; and DS:SI for source mov si,di ; are the same. lodsb ; Fetch inc al ; increment jz norise ; Bypass if as high as pos stosb ; Restore the byte. norise: mov ax,cs ; Return ES to the code segment mov es,ax mov ds,ax ; Also DS. plotdun: ;******** PLOTTING FINISHED ****************** mov eax,stepx2 ; Move the X position by the step add [mandelx+offset],eax mov ax,1 ; Increment the pixel count add [mandpix+offset],ax jnz nomoreseg mov ax,(65536/16) ; If above 65535, new segment add [mandseg+offset],ax nomoreseg: pop cx ; Rescue the column counter dec cx ; Count down jz writealine ; until finished. jmp dotloop writealine: call writeline ; Say "LINE NUMBER" mov eax,stepy2 ; Move the Y position by the step add [mandely+offset],eax mov eax,beginx ; Start a new row mov [mandelx+offset],eax pop cx ; Rescue the row counter dec cx ; Count down jz leavemand ; until finished. jmp lineloop leavemand: ;************************ MAIN ROUTINE ENDS ******************** mov al,1 sub [fling+offset],al pop cx dec cx jz dumpem jmp sevenflings dumpem: mov cx,[dumpseg+offset] mov bx,ds add bx,(65536/16) ; Prepare for source 64k up mov ds,bx loop32k: and cx,cx jz modulus push cx mov ax,4000h ; Put the picture onto disk (groups of 32k) mov bx,[cs:dest+offset] mov cx,32768 mov dx,0 int 33 mov dx,destprob+offset jc abort mov ax,ds add ax,(32768/16) mov ds,ax pop cx dec cx jmp loop32k modulus: mov cx,[cs:dump+offset] and cx,cx jz finished mov ax,4000h ; Put the picture onto disk (remainder) mov bx,[cs:dest+offset] mov dx,0 int 33 mov dx,destprob+offset jc abort finished: mov ax,cs mov ds,ax mov ax,3e00h ; Close the file mov bx,[dest+offset] int 33 mov dx,completed+offset ; Say that it is done. mov ah,9 int 33 mov ah,76 int 33 int 32 END