/* Fractal zoom prog by David Hedley... Compile with GCC !!! */ #include #include #include #include #include typedef unsigned char byte; #define MAXX 256 #define MAXY 160 #define XPOS ((320-MAXX)/2) #define YPOS 4 #define xSAVE #define plot(x,y,c) (screen_data[(x)+(y)*MAXX] = (byte)(c)) #define peek(x,y) (screen_data[(x)+(y)*MAXX]) #define F_BITS 22 typedef long fixed; #define Float2Fixed(a) (fixed)((a) * (float)(1 << F_BITS)) #define Int2Fixed(a) (fixed)((a) << F_BITS) #define Fixed2Int(a) (int)((a) >> F_BITS) #define Fixed2Float(a) (float)((a) / (float)(1 << F_BITS)) #define S_BITS 16 #define Float2SF(a) (fixed)((a) * (float)(1 << S_BITS)) #define Int2SF(a) (fixed)((a) << S_BITS) #define SF2Int(a) (int)((a) >> S_BITS) #ifdef SAVE byte array1[MAXX*MAXY*4]; #else extern byte array1[MAXX*MAXY*4]; #endif byte array2[MAXX*MAXY*4]; byte screen_data[MAXX*MAXY]; byte *mand_data = array1; byte *other_data = array2; fixed m_x1 = Float2Fixed(-3.17559521); fixed m_y1 = Float2Fixed(2.53588476); fixed m_x2 = Float2Fixed(1.97954465); fixed m_y2 = Float2Fixed(-1.21328414); extern byte bits_graphic[]; extern byte lefttext[]; extern byte righttext[]; int ysrc,xsrc; fixed ysz,xsz; int frame = 0; extern byte palette[]; fixed FixedMul(fixed a, fixed b) { asm (" movl 8(%ebp),%eax imull 12(%ebp) "); asm ("shrd %0,%%edx,%%eax" : : "i" (F_BITS)); } fixed FixedDiv(fixed a, fixed b) { asm (" movl 8(%ebp),%eax movl %eax,%edx "); asm ("sar %0,%%edx" : : "i" (32-F_BITS)); asm ("shl %0,%%eax" : : "i" (F_BITS)); asm ("idivl 12(%ebp)"); } /* byte getch(void) { union REGS regs; regs.h.ah = 0x06; regs.h.dl = 0xff; int86(0x21,®s,®s); return regs.h.al; } */ void zoom(void *src, void *dest, int n_width, int n_height, int o_width, int o_height, int d_width, int s_width) { if (n_width == 0 || n_height == 0) return; asm(" pushl %esi pushl %edi pushl %ebx pushl %ebp movl 8(%ebp),%esi movl 12(%ebp),%edi movl 16(%ebp),%eax movl 20(%ebp),%ebx movl 24(%ebp),%ecx movl 28(%ebp),%edx movl 32(%ebp),%ebp shll $16,%ebp movw 52(%esp),%ebp call do_zoom popl %ebp popl %ebx popl %edi popl %esi "); } byte scrn_buff[320*200]; void Sync(void) { while (inportb(0x3da) & 8); while (!(inportb(0x3da) & 8)); } void ZoomScreen(void) { int height; fixed denom,width; denom = Int2Fixed(80); width = Int2Fixed(0); while (width < Int2Fixed(320)) { width = FixedDiv(Int2Fixed(320),denom); height = (200*Fixed2Int(width)) / 320; Sync(); zoom(scrn_buff,(void *)(0xd0000000+(320-Fixed2Int(width))/2+ ((200-height)/2)*320),Fixed2Int(width),height,320,200,320,320); denom -= Float2Fixed(0.25); } } void EndZoom(void) { int height; int width; bcopy((void *)0xd0000000,scrn_buff,320*200); width = 320; while (width > 1) { height = (200*width) / 320; Sync(); zoom(scrn_buff+(320-width)/2+((200-height)/2)*320, (void *)0xd0000000,320,200,width,height,320,320); width -= 4; } } #define MAXITER 256 byte Mandel(fixed x, fixed y) { int volatile iter = MAXITER-1; asm (" pushl %esi pushl %edi pushl %ebx movl 8(%ebp),%esi movl 12(%ebp),%edi LOOP: movl %esi,%eax imul %eax "); asm ("shrd %0,%%edx,%%eax" : : "i" (F_BITS) ); asm (" movl %eax,%ebx movl %edi,%eax imul %eax "); asm ("shrd %0,%%edx,%%eax" : : "i" (F_BITS) ); asm (" movl %eax,%ecx addl %ebx,%eax "); asm ("cmpl %0,%%eax" : : "i" (4*(1 << F_BITS)) ); asm (" jg EXIT movl %edi,%eax imul %esi "); asm ("shrd %0,%%edx,%%eax" : : "i" (F_BITS) ); asm (" movl %ebx,%esi subl %ecx,%esi addl 8(%ebp),%esi leal (%eax,%eax),%edi addl 12(%ebp),%edi decl -4(%ebp) jnz LOOP EXIT: popl %ebx popl %edi popl %esi "); return (byte)(MAXITER - iter); } void ResetAll(void) { register byte *dest; fixed tmp = FixedDiv(m_x2-m_x1,Float2Fixed(4.0)); m_x1 += tmp; m_x2 -= tmp; tmp = FixedDiv(m_y2-m_y1,Float2Fixed(4.0)); m_y1 += tmp; m_y2 -= tmp; dest = mand_data; mand_data = other_data; other_data = dest; ysz = Int2SF(2*MAXY); xsz = Int2SF(2*MAXX); ysrc = 0; xsrc = 0; frame = 0; } void UpdateScreen(void *destination) { asm(" pushl %esi pushl %edi pushl %ebx cld "); asm("movl %0,%%edx" : : "i" (MAXY-9)); asm("movl %0,%%esi" : : "i" (screen_data)); asm(" movl 8(%ebp),%edi update_back: "); asm("movl %0,%%ecx" : : "i" (MAXX/4)); asm(" rep movsl "); asm("addl %0,%%edi" : : "i" (320-MAXX)); asm(" decl %edx jnz update_back "); asm("movl %0,%%ebx" : : "i" (bits_graphic+XPOS)); asm(" movl $9,%edx update_under: "); asm("movl %0,%%ecx" : : "i" (MAXX)); asm(" update_under_next: testb $-1,(%ebx) jnz update_skip movb (%esi),%al movb %al,(%edi) update_skip: inc %esi inc %edi inc %ebx dec %ecx jnz update_under_next "); asm("addl %0,%%edi" : : "i" (320-MAXX)); asm("addl %0,%%ebx" : : "i" (320-MAXX)); asm(" decl %edx jnz update_under popl %ebx popl %edi popl %esi "); } /* #define GetMandel(a,b,xp,yp) Mandel(xp,yp) */ #define GetMandel(Mx,My,Mxpos,Mypos) \ ((Mx) < MAXX-1 \ ? \ ((peek((Mx)+1,(My)+1) == peek((Mx)-1,(My)-1) && \ peek((Mx)+1,(My)+1) == peek((Mx)+1,(My)-1) && \ peek((Mx)+1,(My)+1) == peek((Mx)-1,(My)+1)) \ ? \ peek((Mx)+1,(My)+1) \ : \ Mandel(Mxpos,Mypos)) \ : \ ((peek((Mx),(My)) == peek((Mx),(My)-1) && \ peek((Mx),(My)) == peek((Mx),(My)+1)) \ ? \ peek((Mx),(My)) \ : \ Mandel(Mxpos,Mypos))) void CalcColumn() { #define YS_BITS 30 fixed n_x1,n_y1,n_x2,n_y2; fixed xdiff,ydiff,s_x1,s_y1; register int y; register fixed ypos; fixed xp,ystep,sstep; register byte *m,*mand; int sx; fixed sy; n_x1 = m_x1+FixedDiv(m_x2-m_x1,Int2Fixed(4)); n_x2 = m_x2-FixedDiv(m_x2-m_x1,Int2Fixed(4)); n_y1 = m_y1+FixedDiv(m_y2-m_y1,Int2Fixed(4)); n_y2 = m_y2-FixedDiv(m_y2-m_y1,Int2Fixed(4)); xdiff = FixedMul(m_x2 - m_x1, Int2Fixed(1)- FixedDiv(Int2Fixed(xsrc),Int2Fixed(MAXX))); ydiff = FixedMul(m_y2 - m_y1, Int2Fixed(1)- FixedDiv(Int2Fixed(ysrc),Int2Fixed(MAXY))); s_x1 = FixedMul(m_x2-m_x1,FixedDiv(Int2Fixed(xsrc) >> 1,Int2Fixed(MAXX))) + m_x1; s_y1 = FixedMul(m_y2-m_y1,FixedDiv(Int2Fixed(ysrc) >> 1,Int2Fixed(MAXY))) + m_y1; ystep = ((n_y2-n_y1) << (YS_BITS-F_BITS)) / (2*MAXY); sstep = FixedMul(FixedDiv(ystep >> (YS_BITS-F_BITS), ydiff),Int2Fixed(MAXY)); m = &other_data[frame << 1]; mand = &mand_data[(frame + MAXX/2)+(MAXY/2)*2*MAXX]; for (y = 0; y < MAXY; y++, m += 2*2*MAXX, mand += 2*MAXX) *m = *mand; xp = FixedMul(FixedDiv(Int2Fixed(frame << 1) >> 1, Int2Fixed(MAXX)), n_x2-n_x1) + n_x1; sx = Fixed2Int(FixedMul(FixedDiv(xp - s_x1, xdiff),Int2Fixed(MAXX))); m = &other_data[(frame << 1)+2*MAXX]; ypos = (n_y1 << (YS_BITS-F_BITS))+ystep; sy = FixedMul(FixedDiv((ypos >> (YS_BITS-F_BITS))-s_y1,ydiff), Int2Fixed(MAXY)); for (y = 0; y < MAXY-3; y++,m+=2*2*MAXX,ypos+=ystep << 1,sy+=(sstep<<1)) *m = GetMandel(sx+1,Fixed2Int(sy)+1,xp, ypos >> (YS_BITS-F_BITS)); xp = FixedMul(FixedDiv(Int2Fixed((frame << 1)+1) >> 1, Int2Fixed(MAXX)), n_x2-n_x1) + n_x1; sx = Fixed2Int(FixedMul(FixedDiv(xp - s_x1, xdiff),Int2Fixed(MAXX))); m = &other_data[(frame << 1)+1]; ypos = n_y1 << (YS_BITS - F_BITS); sy = FixedMul(FixedDiv((ypos >> (YS_BITS-F_BITS))-s_y1,ydiff), Int2Fixed(MAXY)); for (y = 0; y < 2*MAXY-2; y++,m += 2*MAXX, ypos += ystep, sy += sstep) *m = GetMandel(sx+1,Fixed2Int(sy)+1,xp, ypos >> (YS_BITS-F_BITS)); m = &other_data[(frame+128) << 1]; mand = &mand_data[(frame+MAXX)+(MAXY/2)*2*MAXX]; for (y = 0; y < MAXY; y++, m += 2*2*MAXX, mand += 2*MAXX) *m = *mand; xp = FixedMul(FixedDiv(Int2Fixed((frame+128) << 1) >> 1, Int2Fixed(MAXX)), n_x2-n_x1) + n_x1; sx = Fixed2Int(FixedMul(FixedDiv(xp - s_x1, xdiff),Int2Fixed(MAXX))); m = &other_data[((frame+128) << 1)+2*MAXX]; ypos = (n_y1 << (YS_BITS-F_BITS)) + ystep; sy = FixedMul(FixedDiv((ypos >> (YS_BITS-F_BITS))-s_y1,ydiff), Int2Fixed(MAXY)); for (y = 0; y < MAXY-3;y++,m+=2*2*MAXX,ypos+=ystep << 1,sy+=(sstep<<1)) *m = GetMandel(sx+1,Fixed2Int(sy)+1,xp, ypos >> (YS_BITS-F_BITS)); xp = FixedMul(FixedDiv(Int2Fixed(((frame+128) << 1)+1) >> 1, Int2Fixed(MAXX)), n_x2-n_x1) + n_x1; sx = Fixed2Int(FixedMul(FixedDiv(xp - s_x1, xdiff),Int2Fixed(MAXX))); m = &other_data[((frame+128) << 1)+1]; ypos = n_y1 << (YS_BITS-F_BITS); sy = FixedMul(FixedDiv((ypos >> (YS_BITS-F_BITS))-s_y1,ydiff), Int2Fixed(MAXY)); for (y = 0; y < 2*MAXY-2; y++,m += 2*MAXX,ypos+=ystep, sy += sstep) *m = GetMandel(sx+1,Fixed2Int(sy)+1,xp, ypos >> (YS_BITS-F_BITS)); } void SetCols(void) { int c; outportb(0x3c8,0); for (c = 0; c < 256*3; c++) outportb(0x3c9,palette[c]); } void PutText(byte *text, int height, void *dest) { asm(" pushl %esi pushl %edi cld movl 12(%ebp),%edx movl 8(%ebp),%esi movl 16(%ebp),%edi next_row_left: movl $8,%ecx rep movsl addl $288,%edi decl %edx jnz next_row_left popl %edi popl %esi "); } void PutGraphic(void) { asm(" pushl %esi pushl %edi "); asm("movl %0,%%esi" : : "i" (bits_graphic)); asm("movl %0,%%edi" : : "i" (scrn_buff+155*320)); asm("movl %0,%%ecx" : : "i" (45*320)); asm(" put_graphic_next: testb $-1,(%esi) jz put_graphic_skip movb (%esi),%al movb %al,(%edi) put_graphic_skip: incl %esi incl %edi decl %ecx jnz put_graphic_next popl %edi popl %esi "); } int main(void) { union REGS regs; int count; byte pic; #ifdef SAVE int j; byte *m; FILE *f1; #endif regs.x.ax = 0x13; int86(0x10,®s,®s); pic = inportb(0x21); outportb(0x21,0xfe); SetCols(); PutText(lefttext,161,scrn_buff); PutText(righttext,161,scrn_buff+288); PutGraphic(); ysrc = 0; ysz = Int2SF(MAXY*2); xsz = Int2SF(MAXX*2); #ifdef SAVE f1 = fopen("data.tbl","wb"); for (j = 0,m = mand_data; j < 2*MAXY; j++) for (i = 0; i < 2*MAXX; i++,m++) { *m = Mandel(FixedMul(FixedDiv(Int2Fixed(i) >> 1, Int2Fixed(MAXX)),m_x2-m_x1)+m_x1, FixedMul(FixedDiv(Int2Fixed(j) >> 1, Int2Fixed(MAXY)), m_y2-m_y1) + m_y1); plot(i >> 1, j >> 1, *m); } fwrite(mand_data,1,sizeof array1,f1); fclose(f1); return 0; #endif zoom(mand_data,screen_data,MAXX,MAXY,2*MAXX,2*MAXY,MAXX,2*MAXX); UpdateScreen((void *)(scrn_buff+XPOS+(YPOS)*320)); ZoomScreen(); for(count = 1450; count > 0; count--) { if (inportb(0x60) == 1) break; xsz -= Float2SF(2.0); ysz -= Float2SF(1.25); xsrc = SF2Int((Int2SF(2*MAXX)-xsz)/2); ysrc = SF2Int((Int2SF(2*MAXY)-ysz)/2); zoom(mand_data+xsrc+ysrc*2*MAXX,screen_data,MAXX,MAXY,SF2Int(xsz), SF2Int(ysz),MAXX,2*MAXX); CalcColumn(); UpdateScreen((void *)(0xd0000000+XPOS+(YPOS)*320)); frame++; if (xsz == Int2SF(MAXX)) ResetAll(); } EndZoom(); regs.x.ax = 0x3; int86(0x10,®s,®s); outportb(0x21,pic); return 0; }