home *** CD-ROM | disk | FTP | other *** search
/ Current Shareware 1994 January / SHAR194.ISO / pictures / mandzoom.zip / FRAC.C < prev    next >
C/C++ Source or Header  |  1993-09-02  |  14KB  |  654 lines

  1.  
  2. /* Fractal zoom prog by David Hedley...
  3.     Compile with GCC !!!
  4.  
  5. */
  6.  
  7.  
  8. #include <stdio.h>
  9. #include <pc.h>
  10. #include <dos.h>
  11. #include <math.h>
  12. #include <stdlib.h>
  13.  
  14. typedef unsigned char byte;
  15.  
  16. #define MAXX 256
  17. #define MAXY 160
  18.  
  19. #define XPOS ((320-MAXX)/2)
  20. #define YPOS 4
  21.  
  22. #define xSAVE
  23.  
  24. #define plot(x,y,c) (screen_data[(x)+(y)*MAXX] = (byte)(c))
  25. #define peek(x,y) (screen_data[(x)+(y)*MAXX])
  26.  
  27. #define F_BITS 22
  28.  
  29. typedef long fixed;
  30.  
  31. #define Float2Fixed(a) (fixed)((a) * (float)(1 << F_BITS))
  32. #define Int2Fixed(a) (fixed)((a) << F_BITS)
  33. #define Fixed2Int(a) (int)((a) >> F_BITS)
  34. #define Fixed2Float(a) (float)((a) / (float)(1 << F_BITS))
  35.  
  36.  
  37. #define S_BITS 16
  38.  
  39. #define Float2SF(a) (fixed)((a) * (float)(1 << S_BITS))
  40. #define Int2SF(a) (fixed)((a) << S_BITS)
  41. #define SF2Int(a) (int)((a) >> S_BITS)
  42.  
  43.  
  44. #ifdef SAVE
  45.     byte array1[MAXX*MAXY*4];
  46. #else
  47.     extern byte array1[MAXX*MAXY*4];
  48. #endif
  49.  
  50. byte array2[MAXX*MAXY*4];
  51.  
  52. byte screen_data[MAXX*MAXY];
  53.  
  54. byte *mand_data = array1;
  55. byte *other_data = array2;
  56.  
  57.  
  58. fixed m_x1 = Float2Fixed(-3.17559521);
  59. fixed m_y1 = Float2Fixed(2.53588476);
  60. fixed m_x2 = Float2Fixed(1.97954465);
  61. fixed m_y2 = Float2Fixed(-1.21328414);
  62.  
  63.  
  64. extern byte bits_graphic[];
  65. extern byte lefttext[];
  66. extern byte righttext[];
  67.  
  68. int ysrc,xsrc;
  69. fixed ysz,xsz;
  70. int frame = 0;
  71.  
  72.  
  73. extern byte palette[];
  74.  
  75.  
  76. fixed FixedMul(fixed a, fixed b)
  77. {
  78.     asm ("
  79.         movl 8(%ebp),%eax
  80.         imull 12(%ebp)
  81.         ");
  82.     asm ("shrd %0,%%edx,%%eax" : : "i" (F_BITS));
  83. }
  84.  
  85.  
  86. fixed FixedDiv(fixed a, fixed b)
  87. {
  88.     asm ("
  89.         movl 8(%ebp),%eax
  90.         movl %eax,%edx
  91.         ");
  92.     asm ("sar %0,%%edx" : : "i" (32-F_BITS));
  93.     asm ("shl %0,%%eax" : : "i" (F_BITS));
  94.     asm ("idivl 12(%ebp)");
  95. }
  96.  
  97.  
  98. /*
  99. byte getch(void)
  100. {
  101.     union REGS regs;
  102.  
  103.     regs.h.ah = 0x06;
  104.     regs.h.dl = 0xff;
  105.     int86(0x21,®s,®s);
  106.  
  107.     return regs.h.al;
  108. }
  109. */
  110.  
  111.  
  112. void zoom(void *src, void *dest, int n_width, int n_height, int o_width,
  113.                     int o_height, int d_width, int s_width)
  114. {
  115.     if (n_width == 0 || n_height == 0) return;
  116.  
  117.     asm("
  118.         pushl %esi
  119.         pushl %edi
  120.         pushl %ebx
  121.         pushl %ebp
  122.  
  123.         movl  8(%ebp),%esi
  124.         movl 12(%ebp),%edi
  125.         movl 16(%ebp),%eax
  126.         movl 20(%ebp),%ebx
  127.         movl 24(%ebp),%ecx
  128.         movl 28(%ebp),%edx
  129.         movl 32(%ebp),%ebp
  130.         shll $16,%ebp
  131.         movw 52(%esp),%ebp
  132.  
  133.         call do_zoom
  134.  
  135.         popl %ebp
  136.         popl %ebx
  137.         popl %edi
  138.         popl %esi
  139.         ");
  140. }
  141.  
  142.  
  143. byte scrn_buff[320*200];
  144.  
  145.  
  146. void Sync(void)
  147. {
  148.     while (inportb(0x3da) & 8);
  149.     while (!(inportb(0x3da) & 8));
  150. }
  151.  
  152.  
  153. void ZoomScreen(void)
  154. {
  155.     int height;
  156.     fixed denom,width;
  157.  
  158.     denom = Int2Fixed(80);
  159.     width = Int2Fixed(0);
  160.  
  161.     while (width < Int2Fixed(320))
  162.     {
  163.         width = FixedDiv(Int2Fixed(320),denom);
  164.         height = (200*Fixed2Int(width)) / 320;
  165.  
  166.         Sync();
  167.  
  168.         zoom(scrn_buff,(void *)(0xd0000000+(320-Fixed2Int(width))/2+
  169.                 ((200-height)/2)*320),Fixed2Int(width),height,320,200,320,320);
  170.  
  171.         denom -= Float2Fixed(0.25);
  172.     }
  173. }
  174.  
  175.  
  176.  
  177. void EndZoom(void)
  178. {
  179.     int height;
  180.     int width;
  181.  
  182.     bcopy((void *)0xd0000000,scrn_buff,320*200);
  183.  
  184.     width = 320;
  185.  
  186.     while (width > 1)
  187.     {
  188.         height = (200*width) / 320;
  189.  
  190.         Sync();
  191.  
  192.         zoom(scrn_buff+(320-width)/2+((200-height)/2)*320,
  193.                 (void *)0xd0000000,320,200,width,height,320,320);
  194.  
  195.         width -= 4;
  196.     }
  197. }
  198.  
  199.  
  200.  
  201. #define MAXITER 256
  202.  
  203.  
  204. byte Mandel(fixed x, fixed y)
  205. {
  206.     int volatile iter = MAXITER-1;
  207.  
  208.     asm ("
  209.         pushl %esi
  210.         pushl %edi
  211.         pushl %ebx
  212.  
  213.         movl 8(%ebp),%esi
  214.         movl 12(%ebp),%edi
  215. LOOP:
  216.         movl %esi,%eax
  217.         imul %eax
  218.         ");
  219.     asm ("shrd %0,%%edx,%%eax" : : "i" (F_BITS) );
  220.     asm ("
  221.         movl %eax,%ebx
  222.  
  223.         movl %edi,%eax
  224.         imul %eax
  225.         ");
  226.     asm ("shrd %0,%%edx,%%eax" : : "i" (F_BITS) );
  227.     asm ("
  228.         movl %eax,%ecx
  229.  
  230.         addl %ebx,%eax
  231.         ");
  232.  
  233.     asm ("cmpl %0,%%eax" : : "i" (4*(1 << F_BITS)) );
  234.     asm ("
  235.         jg EXIT
  236.  
  237.         movl %edi,%eax
  238.         imul %esi
  239.         ");
  240.     asm ("shrd %0,%%edx,%%eax" : : "i" (F_BITS) );
  241.     asm ("
  242.         movl %ebx,%esi
  243.         subl %ecx,%esi
  244.         addl 8(%ebp),%esi
  245.  
  246.         leal (%eax,%eax),%edi
  247.         addl 12(%ebp),%edi
  248.  
  249.         decl -4(%ebp)
  250.         jnz LOOP
  251.  
  252. EXIT:
  253.         popl %ebx
  254.         popl %edi
  255.         popl %esi
  256.         ");
  257.  
  258.     return (byte)(MAXITER - iter);
  259.  
  260. }
  261.  
  262.  
  263.  
  264. void ResetAll(void)
  265. {
  266.     register byte *dest;
  267.     fixed tmp = FixedDiv(m_x2-m_x1,Float2Fixed(4.0));
  268.  
  269.     m_x1 += tmp;
  270.     m_x2 -= tmp;
  271.  
  272.     tmp = FixedDiv(m_y2-m_y1,Float2Fixed(4.0));
  273.  
  274.     m_y1 += tmp;
  275.     m_y2 -= tmp;
  276.  
  277.     dest = mand_data;
  278.     mand_data = other_data;
  279.     other_data = dest;
  280.  
  281.     ysz = Int2SF(2*MAXY);
  282.     xsz = Int2SF(2*MAXX);
  283.  
  284.     ysrc = 0;
  285.     xsrc = 0;
  286.     frame = 0;
  287. }
  288.  
  289.  
  290. void UpdateScreen(void *destination)
  291. {
  292.     asm("
  293.         pushl %esi
  294.         pushl %edi
  295.         pushl %ebx
  296.         cld
  297.         ");
  298.     asm("movl %0,%%edx" : : "i" (MAXY-9));
  299.     asm("movl %0,%%esi" : : "i" (screen_data));
  300.     asm("
  301.         movl 8(%ebp),%edi
  302.  
  303. update_back:
  304.         ");
  305.     asm("movl %0,%%ecx" : : "i" (MAXX/4));
  306.     asm("
  307.         rep
  308.         movsl
  309.         ");
  310.     asm("addl %0,%%edi" : : "i" (320-MAXX));
  311.     asm("
  312.         decl %edx
  313.         jnz update_back
  314.         ");
  315.  
  316.     asm("movl %0,%%ebx" : : "i" (bits_graphic+XPOS));
  317.     asm("
  318.         movl $9,%edx
  319.  
  320. update_under:
  321.  
  322.         ");
  323.     asm("movl %0,%%ecx" : : "i" (MAXX));
  324.     asm("
  325.  
  326. update_under_next:
  327.  
  328.         testb $-1,(%ebx)
  329.         jnz update_skip
  330.  
  331.         movb (%esi),%al
  332.         movb %al,(%edi)
  333.  
  334. update_skip:
  335.  
  336.         inc %esi
  337.         inc %edi
  338.         inc %ebx
  339.  
  340.         dec %ecx
  341.         jnz update_under_next
  342.  
  343.         ");
  344.     asm("addl %0,%%edi" : : "i" (320-MAXX));
  345.     asm("addl %0,%%ebx" : : "i" (320-MAXX));
  346.     asm("
  347.  
  348.         decl %edx
  349.         jnz update_under
  350.  
  351.         popl %ebx
  352.         popl %edi
  353.         popl %esi
  354.         ");
  355. }
  356.  
  357. /*
  358. #define GetMandel(a,b,xp,yp) Mandel(xp,yp)
  359. */
  360.  
  361. #define GetMandel(Mx,My,Mxpos,Mypos) \
  362.     ((Mx) < MAXX-1 \
  363.     ? \
  364.         ((peek((Mx)+1,(My)+1) == peek((Mx)-1,(My)-1) && \
  365.         peek((Mx)+1,(My)+1) == peek((Mx)+1,(My)-1) && \
  366.         peek((Mx)+1,(My)+1) == peek((Mx)-1,(My)+1)) \
  367.             ? \
  368.                 peek((Mx)+1,(My)+1) \
  369.             : \
  370.                 Mandel(Mxpos,Mypos)) \
  371.     : \
  372.         ((peek((Mx),(My)) == peek((Mx),(My)-1) && \
  373.         peek((Mx),(My)) == peek((Mx),(My)+1)) \
  374.             ? \
  375.                 peek((Mx),(My)) \
  376.             : \
  377.                 Mandel(Mxpos,Mypos)))
  378.  
  379.  
  380. void CalcColumn()
  381. {
  382.     #define YS_BITS 30
  383.  
  384.     fixed n_x1,n_y1,n_x2,n_y2;
  385.     fixed xdiff,ydiff,s_x1,s_y1;
  386.     register int y;
  387.     register fixed ypos;
  388.     fixed xp,ystep,sstep;
  389.     register byte *m,*mand;
  390.     int sx;
  391.     fixed sy;
  392.  
  393.     n_x1 = m_x1+FixedDiv(m_x2-m_x1,Int2Fixed(4));
  394.     n_x2 = m_x2-FixedDiv(m_x2-m_x1,Int2Fixed(4));
  395.  
  396.     n_y1 = m_y1+FixedDiv(m_y2-m_y1,Int2Fixed(4));
  397.     n_y2 = m_y2-FixedDiv(m_y2-m_y1,Int2Fixed(4));
  398.  
  399.     xdiff = FixedMul(m_x2 - m_x1, Int2Fixed(1)-
  400.                     FixedDiv(Int2Fixed(xsrc),Int2Fixed(MAXX)));
  401.  
  402.     ydiff = FixedMul(m_y2 - m_y1, Int2Fixed(1)-
  403.                     FixedDiv(Int2Fixed(ysrc),Int2Fixed(MAXY)));
  404.  
  405.     s_x1 = FixedMul(m_x2-m_x1,FixedDiv(Int2Fixed(xsrc) >> 1,Int2Fixed(MAXX)))
  406.                 + m_x1;
  407.  
  408.     s_y1 = FixedMul(m_y2-m_y1,FixedDiv(Int2Fixed(ysrc) >> 1,Int2Fixed(MAXY)))
  409.                 + m_y1;
  410.  
  411.     ystep = ((n_y2-n_y1) << (YS_BITS-F_BITS)) / (2*MAXY);
  412.  
  413.     sstep = FixedMul(FixedDiv(ystep >> (YS_BITS-F_BITS), ydiff),Int2Fixed(MAXY));
  414.  
  415.     m = &other_data[frame << 1];
  416.     mand = &mand_data[(frame + MAXX/2)+(MAXY/2)*2*MAXX];
  417.  
  418.     for (y = 0; y < MAXY; y++, m += 2*2*MAXX, mand += 2*MAXX)
  419.         *m = *mand;
  420.  
  421.     xp = FixedMul(FixedDiv(Int2Fixed(frame << 1) >> 1, Int2Fixed(MAXX)),
  422.                 n_x2-n_x1) + n_x1;
  423.     sx = Fixed2Int(FixedMul(FixedDiv(xp - s_x1, xdiff),Int2Fixed(MAXX)));
  424.     m = &other_data[(frame << 1)+2*MAXX];
  425.     ypos = (n_y1 << (YS_BITS-F_BITS))+ystep;
  426.  
  427.     sy = FixedMul(FixedDiv((ypos >> (YS_BITS-F_BITS))-s_y1,ydiff),
  428.                                         Int2Fixed(MAXY));
  429.  
  430.  
  431.     for (y = 0; y < MAXY-3; y++,m+=2*2*MAXX,ypos+=ystep << 1,sy+=(sstep<<1))
  432.         *m = GetMandel(sx+1,Fixed2Int(sy)+1,xp, ypos >> (YS_BITS-F_BITS));
  433.  
  434.  
  435.     xp = FixedMul(FixedDiv(Int2Fixed((frame << 1)+1) >> 1, Int2Fixed(MAXX)),
  436.                 n_x2-n_x1) + n_x1;
  437.     sx = Fixed2Int(FixedMul(FixedDiv(xp - s_x1, xdiff),Int2Fixed(MAXX)));
  438.     m = &other_data[(frame << 1)+1];
  439.     ypos = n_y1 << (YS_BITS - F_BITS);
  440.  
  441.     sy = FixedMul(FixedDiv((ypos >> (YS_BITS-F_BITS))-s_y1,ydiff),
  442.                                         Int2Fixed(MAXY));
  443.  
  444.  
  445.     for (y = 0; y < 2*MAXY-2; y++,m += 2*MAXX, ypos += ystep, sy += sstep)
  446.         *m = GetMandel(sx+1,Fixed2Int(sy)+1,xp, ypos >> (YS_BITS-F_BITS));
  447.  
  448.  
  449.     m = &other_data[(frame+128) << 1];
  450.     mand = &mand_data[(frame+MAXX)+(MAXY/2)*2*MAXX];
  451.  
  452.     for (y = 0; y < MAXY; y++, m += 2*2*MAXX, mand += 2*MAXX)
  453.         *m = *mand;
  454.  
  455.     xp = FixedMul(FixedDiv(Int2Fixed((frame+128) << 1) >> 1, Int2Fixed(MAXX)),
  456.                 n_x2-n_x1) + n_x1;
  457.     sx = Fixed2Int(FixedMul(FixedDiv(xp - s_x1, xdiff),Int2Fixed(MAXX)));
  458.     m = &other_data[((frame+128) << 1)+2*MAXX];
  459.     ypos = (n_y1 << (YS_BITS-F_BITS)) + ystep;
  460.  
  461.     sy = FixedMul(FixedDiv((ypos >> (YS_BITS-F_BITS))-s_y1,ydiff),
  462.                                         Int2Fixed(MAXY));
  463.  
  464.  
  465.     for (y = 0; y < MAXY-3;y++,m+=2*2*MAXX,ypos+=ystep << 1,sy+=(sstep<<1))
  466.         *m = GetMandel(sx+1,Fixed2Int(sy)+1,xp, ypos >> (YS_BITS-F_BITS));
  467.  
  468.  
  469.     xp = FixedMul(FixedDiv(Int2Fixed(((frame+128) << 1)+1) >> 1, Int2Fixed(MAXX)),
  470.                 n_x2-n_x1) + n_x1;
  471.     sx = Fixed2Int(FixedMul(FixedDiv(xp - s_x1, xdiff),Int2Fixed(MAXX)));
  472.     m = &other_data[((frame+128) << 1)+1];
  473.     ypos = n_y1 << (YS_BITS-F_BITS);
  474.  
  475.     sy = FixedMul(FixedDiv((ypos >> (YS_BITS-F_BITS))-s_y1,ydiff),
  476.                                                         Int2Fixed(MAXY));
  477.  
  478.  
  479.     for (y = 0; y < 2*MAXY-2; y++,m += 2*MAXX,ypos+=ystep, sy += sstep)
  480.         *m = GetMandel(sx+1,Fixed2Int(sy)+1,xp, ypos >> (YS_BITS-F_BITS));
  481.  
  482. }
  483.  
  484.  
  485. void SetCols(void)
  486. {
  487.     int c;
  488.  
  489.     outportb(0x3c8,0);
  490.  
  491.     for (c = 0; c < 256*3; c++)
  492.         outportb(0x3c9,palette[c]);
  493.  
  494. }
  495.  
  496.  
  497. void PutText(byte *text, int height, void *dest)
  498. {
  499.     asm("
  500.         pushl %esi
  501.         pushl %edi
  502.         cld
  503.  
  504.         movl 12(%ebp),%edx
  505.         movl 8(%ebp),%esi
  506.         movl 16(%ebp),%edi
  507.  
  508. next_row_left:
  509.  
  510.         movl $8,%ecx
  511.         rep
  512.         movsl
  513.  
  514.         addl $288,%edi
  515.         decl %edx
  516.         jnz next_row_left
  517.  
  518.         popl %edi
  519.         popl %esi
  520.         ");
  521. }
  522.  
  523.  
  524. void PutGraphic(void)
  525. {
  526.     asm("
  527.         pushl %esi
  528.         pushl %edi
  529.         ");
  530.     asm("movl %0,%%esi" : : "i" (bits_graphic));
  531.     asm("movl %0,%%edi" : : "i" (scrn_buff+155*320));
  532.     asm("movl %0,%%ecx" : : "i" (45*320));
  533.     asm("
  534.  
  535. put_graphic_next:
  536.  
  537.         testb $-1,(%esi)
  538.         jz put_graphic_skip
  539.  
  540.         movb (%esi),%al
  541.         movb %al,(%edi)
  542.  
  543. put_graphic_skip:
  544.  
  545.         incl %esi
  546.         incl %edi
  547.         decl %ecx
  548.         jnz put_graphic_next
  549.  
  550.         popl %edi
  551.         popl %esi
  552.         ");
  553. }
  554.  
  555.  
  556.  
  557. int main(void)
  558. {
  559.     union REGS regs;
  560.     int count;
  561.  
  562.     byte pic;
  563.  
  564.  
  565. #ifdef SAVE
  566.     int j;
  567.     byte *m;
  568.     FILE *f1;
  569. #endif
  570.  
  571.     regs.x.ax = 0x13;
  572.     int86(0x10,®s,®s);
  573.  
  574.     pic = inportb(0x21);
  575.     outportb(0x21,0xfe);
  576.  
  577.     SetCols();
  578.  
  579.     PutText(lefttext,161,scrn_buff);
  580.     PutText(righttext,161,scrn_buff+288);
  581.     PutGraphic();
  582.  
  583.     ysrc = 0;
  584.     ysz = Int2SF(MAXY*2);
  585.     xsz = Int2SF(MAXX*2);
  586.  
  587. #ifdef SAVE
  588.     f1 = fopen("data.tbl","wb");
  589.  
  590.     for (j = 0,m = mand_data; j < 2*MAXY; j++)
  591.         for (i = 0; i < 2*MAXX; i++,m++)
  592.         {
  593.            *m = Mandel(FixedMul(FixedDiv(Int2Fixed(i) >> 1,
  594.                            Int2Fixed(MAXX)),m_x2-m_x1)+m_x1,
  595.                            FixedMul(FixedDiv(Int2Fixed(j) >> 1,
  596.                            Int2Fixed(MAXY)), m_y2-m_y1) + m_y1);
  597.            plot(i >> 1, j >> 1, *m);
  598.         }
  599.  
  600.     fwrite(mand_data,1,sizeof array1,f1);
  601.     fclose(f1);
  602.     return 0;
  603. #endif
  604.  
  605.     zoom(mand_data,screen_data,MAXX,MAXY,2*MAXX,2*MAXY,MAXX,2*MAXX);
  606.  
  607.     UpdateScreen((void *)(scrn_buff+XPOS+(YPOS)*320));
  608.     ZoomScreen();
  609.  
  610.     for(count = 1450; count > 0; count--)
  611.     {
  612.         if (inportb(0x60) == 1)
  613.             break;
  614.  
  615.         xsz -= Float2SF(2.0);
  616.         ysz -= Float2SF(1.25);
  617.  
  618.         xsrc = SF2Int((Int2SF(2*MAXX)-xsz)/2);
  619.         ysrc = SF2Int((Int2SF(2*MAXY)-ysz)/2);
  620.  
  621.         zoom(mand_data+xsrc+ysrc*2*MAXX,screen_data,MAXX,MAXY,SF2Int(xsz),
  622.                     SF2Int(ysz),MAXX,2*MAXX);
  623.  
  624.         CalcColumn();
  625.  
  626.         UpdateScreen((void *)(0xd0000000+XPOS+(YPOS)*320));
  627.  
  628.         frame++;
  629.  
  630.         if (xsz == Int2SF(MAXX))
  631.             ResetAll();
  632.     }
  633.  
  634.     EndZoom();
  635.  
  636.     regs.x.ax = 0x3;
  637.     int86(0x10,®s,®s);
  638.  
  639.     outportb(0x21,pic);
  640.  
  641.     return 0;
  642. }
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.