home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / util / bugs.sit / Simulate.c.bin / Simulate.c
Encoding:
C/C++ Source or Header  |  1989-05-30  |  14.2 KB  |  598 lines  |  [TEXT/KAHL]

  1. /*    Bacteria simulation program. Scientific American, may 1989 */
  2. /* Written by Jurjen N.E. Bos */
  3. /* Compile this file with THINK C 3.0, MacHeaders on */
  4. /* Link it with TransSkel.c, MacTraps and add the resources of Bugs Project.rsrc */
  5. /* Of course, portions ⌐THINK technologies, inc. */
  6.  
  7. #define nil (void *)0
  8. #define FrontMost -1L
  9.  
  10. #define FieldWidth 507        /* width of window */
  11. #define FieldHeight 299        /* height of window */
  12. #define MaxBugs 150        /* maximum number of bugs allowed */
  13. #define HealthPerBact 40        /* number of moves to live from an eaten bacteria */
  14. #define MaxHealth 1500        /* maximum health */
  15. #define StrongHealth 1000    /* health to be strong enough for children */
  16. #define SplitAge 800/2        /* age to be old enough for children */
  17. #define MaxAge 1200/2        /* maximum displayable age.  Value makes nice picture */
  18. #define InitBugs 10            /* initial number of bugs */
  19. #define InitHealth 500        /* initial health of first bugs */
  20. #define DieTime 50            /* die delay */
  21. #define InitBact 1000        /* initial number of bacteria */
  22. #define InitMinDist 50*50    /* square of minimal distance for clicking */
  23.  
  24. typedef struct {
  25.     Point loc;
  26.     int gene[6],sum;
  27.     int dir;
  28.     int health,age;
  29.     } Bug;
  30.  
  31. void MenuClobber(MenuHandle theMenu);
  32. void About(void);
  33. void EditMenu(int item);
  34. void FileMenu(void);
  35. void BactMenu(int item);
  36. void WindowClobber(void);
  37. void WindowUpdate(void);
  38. void WindowActivate(Boolean active);
  39. void MakePort(GrafPtr port);
  40. void Init(void);
  41. void DoGeneration(void);
  42. void WindowMouse(Point thePoint);
  43. void PutBacteria(void);
  44. void MoveBug(Bug *theBug);
  45. void KillBug(Bug *theBug);
  46. void SplitBug(Bug *theBug);
  47.  
  48. unsigned int RandomRange(/* unsigned int top */);
  49. long int SQDist(/* Point a,b */);
  50. int Scale(int a,int b,int c);
  51. int CountPixels(int h,int v);
  52.  
  53. WindowPtr myWindow;
  54. enum {
  55.     F=0,R,HR,RV,HL,L
  56.     };
  57. enum {
  58.     growUniform=4,growNone,growPattern,growGarden,growCentered
  59.     };
  60. int hmove[]={2,1,-1,-2,-1,1};
  61. int vmove[]={0,2,2,0,-2,-2};
  62. Bug bug[MaxBugs];
  63. int numBugs=InitBugs;         /* number of bugs */
  64. GrafPort bactPort;
  65. GrafPtr windowMap;
  66. int growMode=growUniform;    /* bacteria grow mode */
  67. Point bactLoc={10,10};        /* location for pattern grow mode */
  68.  
  69.  
  70. main()
  71. {
  72. Rect R;
  73.     SkelInit(1,nil);
  74.     SkelApple("\pAbout Bugs╔",About);
  75.     SkelMenu(GetMenu(129),FileMenu,MenuClobber,false);
  76.     SkelMenu(GetMenu(130),EditMenu,MenuClobber,false);
  77.     SkelMenu(GetMenu(131),BactMenu,MenuClobber,true);
  78.         /* make our window */
  79.     R=screenBits.bounds;
  80.         /* Watch this: centering the right way! */
  81.     R.bottom=( R.top=(R.top+R.bottom+38-FieldHeight)/2 )+FieldHeight;
  82.     R.right=( R.left=(R.left+R.right-FieldWidth)/2 )+FieldWidth;
  83.     myWindow=NewWindow(nil,&R,"\pJurjen╒s Bugs",true,4,FrontMost,false,0);
  84.     SkelWindow(myWindow,
  85.         WindowMouse,nil,WindowUpdate,WindowActivate,nil,WindowClobber,DoGeneration,false);
  86.     Init();
  87.     SkelMain();
  88.     SkelClobber();
  89. }
  90.  
  91. void MenuClobber(theMenu)
  92. MenuHandle theMenu;
  93. {
  94.     ReleaseResource(theMenu);
  95. }
  96.  
  97. void About()
  98. {
  99.     Alert(1002,nil);
  100. }
  101.  
  102. void EditMenu(item)
  103. int item;
  104. {
  105.     SystemEdit(item-1);
  106. }
  107.  
  108. void FileMenu()
  109. {
  110.     SkelWhoa();
  111. }
  112.  
  113. void BactMenu(item)
  114. int item;
  115. {
  116. register DialogPtr myDialog;
  117. int type;
  118. Handle itemHandle;
  119. Rect box;
  120.     if(item==1){
  121.         /* change bacteria population */
  122.     register int population=5, add=0;
  123.     register int value;
  124.         myDialog=GetNewDialog(1000,nil,FrontMost);
  125.         SetPort(myDialog);
  126.         GetDItem(myDialog,1,&type,&itemHandle,&box);
  127.         PenSize(3,3);
  128.         InsetRect(&box,-4,-4);
  129.         FrameRoundRect(&box,16,16);
  130.         item=5;value=1;
  131.         do {
  132.             GetDItem(myDialog,item,&type,&itemHandle,&box);
  133.             SetCtlValue(itemHandle,value);
  134.             ModalDialog(nil,&item);
  135.             /* 1: OK, 2: cancel, 4: Add to current population,
  136.                 5: Random, 6: None, 7: Pattern */
  137.             if(item==4)
  138.                 value=add=1-add;
  139.             else if(item>4) {
  140.                 GetDItem(myDialog,population,&type,&itemHandle,&box);
  141.                 SetCtlValue(itemHandle,0);
  142.                 value=population=item;
  143.             }
  144.         } while (item>2);
  145.         DisposDialog(myDialog);
  146.         if(item==1) {
  147.             SetPort(&bactPort);
  148.             if(!add) EraseRect(&bactPort.portRect);
  149.             if(population==7) {
  150.                 PenMode(patOr);
  151.                 PenPat(ltGray);
  152.                 PaintRect(&bactPort.portRect);
  153.                 PenMode(patCopy);
  154.                 PenPat(black);
  155.             }
  156.             SetPort(windowMap);
  157.             WindowUpdate();
  158.             if(population==5) for(value=0;value<InitBact;value++) PutBacteria();
  159.         }
  160.     }else{
  161.         /* change bacteria growth */
  162.     register int growth=growUniform;
  163.         myDialog=GetNewDialog(1001,nil,FrontMost);
  164.         SetPort(myDialog);
  165.         GetDItem(myDialog,1,&type,&itemHandle,&box);
  166.         PenSize(3,3);
  167.         InsetRect(&box,-4,-4);
  168.         FrameRoundRect(&box,16,16);
  169.         do {
  170.             GetDItem(myDialog,growth,&type,&itemHandle,&box);
  171.             SetCtlValue(itemHandle,1);
  172.             ModalDialog(nil,&item);
  173.             /* 1: OK, 2: cancel, 4: q,
  174.                 5: q, 6: q, 7: q, 8:q */
  175.             if(item>3) {
  176.                 GetDItem(myDialog,growth,&type,&itemHandle,&box);
  177.                 SetCtlValue(itemHandle,0);
  178.                 growth=item;
  179.             }
  180.         } while (item>2);
  181.         DisposDialog(myDialog);
  182.         if(item==1) growMode=growth;
  183. }    }
  184.  
  185. void WindowClobber()
  186. {
  187.     DisposeWindow(myWindow);
  188. }
  189.  
  190. void WindowUpdate(){
  191. register int i;
  192.     CopyBits(&bactPort.portBits,&thePort->portBits,
  193.         &bactPort.portRect,&thePort->portRect,
  194.         srcCopy,nil);
  195.     PenSize(3,3);
  196.     for(i=0;i<numBugs;i++){
  197.         MoveTo(bug[i].loc.h,bug[i].loc.v);
  198.         Line(0,0);
  199.     }
  200.     PenSize(1,1);
  201. }
  202.  
  203. void WindowActivate(active)
  204. Boolean active;
  205. {
  206.     if(active){
  207.         DisableItem(Get1Resource('MENU',130),0);
  208.         EnableItem(Get1Resource('MENU',131),0);
  209.         DrawMenuBar();
  210.     }else{
  211.         EnableItem(Get1Resource('MENU',130),0);
  212.         DisableItem(Get1Resource('MENU',131),0);
  213.         DrawMenuBar();
  214.     }
  215. }
  216.  
  217. void MakePort(port)
  218. register GrafPtr port; /* port must be a GrafPtr to a valid port */
  219. {
  220. Rect r;
  221. register int rowBytes;
  222.     r=thePort->portRect;
  223.     rowBytes=(r.right-r.left+15)/16*2;
  224.     OpenPort(port);
  225.     port->portBits.baseAddr=NewPtr((long)rowBytes*(r.bottom-r.top));
  226.     port->portBits.rowBytes=rowBytes;
  227.     port->portBits.bounds=port->portRect=r;
  228.     RectRgn(port->visRgn,&r);
  229. }
  230.  
  231. /* interesting part */
  232.  
  233. void Init()
  234. {
  235. register int i;
  236.     GetDateTime(&randSeed);
  237.     PenSize(3,3);
  238.     for (i=0;i<numBugs;++i) {
  239.     register int gene;
  240.     int sum;
  241.         bug[i].loc.h=RandomRange(FieldWidth-3);
  242.         bug[i].loc.v=RandomRange(FieldHeight-3);
  243.         bug[i].dir=RandomRange(6);
  244.         sum=0;
  245.         for(gene=0;gene<6;gene++) sum+= bug[i].gene[gene]=1<<RandomRange(10);
  246.         bug[i].sum=sum;
  247.         bug[i].health=InitHealth;
  248.     }
  249.     PenSize(1,1);
  250.     GetPort(&windowMap);
  251.     MakePort(&bactPort);
  252.     EraseRect(&thePort->portRect);
  253.     SetPort(windowMap);
  254.     for(i=0;i<InitBact;i++) PutBacteria();
  255. }
  256.  
  257. void DoGeneration()
  258. {
  259. register Bug *curBug;
  260.     ObscureCursor();
  261.     PutBacteria();
  262.     /* Move everybody and adapt other values */
  263.     PenSize(3,3);
  264.     curBug=&bug[numBugs];
  265.     do {
  266.         MoveBug(--curBug);
  267.         if(curBug->health < -DieTime)KillBug(curBug);
  268.         else if(curBug->age++>SplitAge && curBug->health>StrongHealth)SplitBug(curBug);
  269.     } while (curBug!=&bug[0]);
  270.     PenPat(black);
  271.     PenSize(1,1);
  272. }
  273.  
  274. void WindowMouse(thePoint)
  275. Point thePoint;
  276. {
  277. register int i;
  278. register Bug *theBug;
  279. long minDist=InitMinDist;
  280.     for(i=numBugs;i--;){
  281.         register long d;
  282.         if(minDist> (d=SQDist(bug[i].loc,thePoint))){
  283.             minDist=d;
  284.             theBug=&bug[i];
  285.     }    }
  286.     if(minDist<InitMinDist){
  287.         WindowRecord showWindow;
  288.         Rect R;
  289.         register int x;
  290.         R.left=50;R.top=70;R.right=225;R.bottom=160;
  291.         if(theBug->loc.h<FieldWidth/2)OffsetRect(&R,FieldWidth/2,0);
  292.         NewWindow(&showWindow,&R,"\p",true,2,FrontMost,false,0);
  293.         SetPort(&showWindow);
  294.         TextFont(systemFont);
  295.         MoveTo(10,20);
  296.         DrawString("\pBug ");
  297.         x=theBug-&bug[0]+1;
  298. #define DrawDigit(d) DrawChar('0'+(d))
  299.         if(x>=100)DrawDigit(x/100);
  300.         if(x>=10)DrawDigit(x/10%10);
  301.         DrawDigit(x%10);
  302.         DrawString("\p of ");
  303.         x=numBugs;
  304.         if(x>=100)DrawDigit(x/100);
  305.         if(x>=10)DrawDigit(x/10%10);
  306.         DrawDigit(x%10);
  307. #undef DrawDigit
  308.         TextFont(geneva);
  309.         MoveTo(10,36);
  310.         DrawString("\pAge");
  311.         R.left=60;R.top=28;R.right=160;R.bottom=36;
  312.         FrameRect(&R);
  313.         InsetRect(&R,1,1);
  314.         R.right=R.left+Scale(80,MaxAge,theBug->age);
  315.         if(R.right>=160){
  316.             R.right=160;
  317.             MoveTo(162,32);
  318.             Line(5,0);
  319.             Line(-2,-2);
  320.             Move(2,2);
  321.             Line(-2,2);
  322.         }
  323.         FillRect(&R,gray);
  324.         MoveTo(60,28);
  325.         Line(0,10);
  326.         MoveTo(60+Scale(100,MaxAge,SplitAge),28);
  327.         Line(0,10);
  328.         MoveTo(10,52);
  329.         DrawString("\pHealth");
  330.         R.left=60;R.top=44;R.right=160;R.bottom=52;
  331.         FrameRect(&R);
  332.         InsetRect(&R,1,1);
  333.         R.right=R.left+Scale(98,MaxHealth,theBug->health);
  334.         FillRect(&R,gray);
  335.         MoveTo(60,44);
  336.         Line(0,10);
  337.         MoveTo(60+Scale(100,MaxHealth,StrongHealth),44);
  338.         Line(0,10);
  339.         MoveTo(159,44);
  340.         Line(0,10);
  341.         MoveTo(10,69);
  342.         DrawString("\pGenes");
  343.         PenSize(2,1);
  344.         for(x=0;x<6;x++){
  345.             MoveTo(72+15*x,68);
  346.             switch(theBug->gene[(x+HL)%6]){
  347.             case 1<<0:Line(0,-1); break;
  348.             case 1<<1:Line(0,-2); break;
  349.             case 1<<2:Line(0,-3); break;
  350.             case 1<<3:Line(0,-4); break;
  351.             case 1<<4:Line(0,-5); break;
  352.             case 1<<5:Line(0,-6); break;
  353.             case 1<<6:Line(0,-7); break;
  354.             case 1<<7:Line(0,-8); break;
  355.             case 1<<8:Line(0,-9); break;
  356.             case 1<<9:Line(0,-10); break;
  357.             case 1<<10:Line(0,-11); break;
  358.             }
  359.         }
  360.         PenSize(1,1);
  361.         TextSize(9);
  362.         MoveTo(68,77);DrawString("\pHL");
  363.         MoveTo(86,77);DrawString("\pL");
  364.         MoveTo(101,77);DrawString("\pF");
  365.         MoveTo(116,77);DrawString("\pR");
  366.         MoveTo(128,77);DrawString("\pHR");
  367.         MoveTo(143,77);DrawString("\pRV");
  368.         SetPort(windowMap);
  369.         PenSize(3,3);
  370.         MoveTo(theBug->loc.h,theBug->loc.v);
  371.         while(StillDown()){
  372.             long *junk;
  373.             PenPat(white);
  374.             Line(0,0);
  375.             Delay(10,&junk);
  376.             PenPat(black);
  377.             Line(0,0);
  378.             Delay(10,&junk);
  379.             }
  380.         CloseWindow(&showWindow);
  381.         PenSize(1,1);
  382.     } else SysBeep(5);    /* no bug is close enough */
  383. }
  384.  
  385. void PutBacteria(){
  386. register int h,v;
  387.     /* Make a bacteria for food */
  388.     switch(growMode){
  389.     case growGarden:
  390.         if(RandomRange(2)){
  391.             h=RandomRange(50)+(FieldWidth-50)/2;
  392.             v=RandomRange(50)+(FieldHeight-50)/2;
  393.             break;
  394.         }
  395.     case growUniform:
  396.         h=RandomRange(FieldWidth-10)+5;
  397.         v=RandomRange(FieldHeight-10)+5;
  398.         break;
  399.     case growNone:
  400.         return;
  401.     case growPattern:
  402.         h=bactLoc.h;
  403.         if( (h+=307) >FieldWidth-5) h-=FieldWidth-10;
  404.         bactLoc.h=h;
  405.         v=bactLoc.v;
  406.         if( (v+=113) >FieldHeight-5) v-=FieldHeight-10;
  407.         bactLoc.v=v;
  408.         break;
  409.     case     growCentered:
  410.         h=RandomRange((FieldWidth-10)/2)+RandomRange((FieldWidth-10)/2)+10;
  411.         v=RandomRange((FieldHeight-10)/2)+RandomRange((FieldHeight-10)/2)+10;
  412.         break;
  413.     }
  414.     asm{        /* set the bit in our bitmap, the quick and dirty way */
  415.         move.w    v,D0
  416.     ;    sub.w    bactPort.portBits.bounds.top,D0    ;this number is zero here
  417.         mulu        bactPort.portBits.rowBytes,D0
  418.         movea.l    bactPort.portBits.baseAddr,A0
  419.         adda.l    D0,A0
  420.         move.w    h,D1
  421.     ;    sub.w    bactPort.portBits.bounds.left,D1    ;this number is zero here
  422.         move.w    D1,D0
  423.         not.w    D0
  424.         lsr.w    #3,D1
  425.         bset        D0,0(A0,D1.w)
  426.     }
  427.     /* draw the bit on screen */
  428.     MoveTo(h,v);
  429.     Line(0,0);
  430. }
  431.  
  432. void MoveBug(theBug) /* assume window active, PenSize = 3,3 */
  433. register Bug *theBug;
  434. {
  435. register int r,dir;
  436. register int h,v;
  437.     /* remove bug from old location */
  438.     PenPat(white);
  439.     MoveTo( h=theBug->loc.h , v=theBug->loc.v );
  440.     Line(0,0);
  441.     /* compute new location */
  442.     if(theBug->health>=0) {
  443.         {    /* compute direction */
  444.         register int *gene;
  445.             dir=theBug->dir;
  446.             r=RandomRange(theBug->sum);
  447.             for(gene=&theBug->gene[6];--gene!=&theBug->gene[0];)
  448.                 if( (r-=*gene) <0)dir++;
  449.             if(dir>=6)dir-=6;
  450.         }
  451.         theBug->dir=dir;
  452.         /* move in new direction */
  453.         if( (h+=hmove[dir]) <0)h+=FieldWidth-2;
  454.         else if(h>FieldWidth-3)h-=FieldWidth-2;
  455.         if( (v+=vmove[dir]) <0)v+=FieldHeight-2;
  456.         else if(v>FieldHeight-3)v-=FieldHeight-2;
  457.     }
  458.     SetPort(&bactPort);
  459.     /* eat bacteria, adapt health */
  460. /*    if(CountPixels(h,v)!=GetPixel(h,v)+GetPixel(h+1,v)+GetPixel(h+2,v)+
  461.         GetPixel(h,v+1)+GetPixel(h+1,v+1)+GetPixel(h+2,v+1)+
  462.         GetPixel(h,v+2)+GetPixel(h+1,v+2)+GetPixel(h+2,v+2)){
  463.         SysBeep(1);SysBeep(1);SysBeep(1);Debugger();}*/
  464.     r=CountPixels(h,v)*HealthPerBact+theBug->health-1;
  465.     if(r>MaxHealth)r=MaxHealth;
  466.     SetPort(windowMap);
  467.     if(r>0 || (r>=-DieTime && r%2==0) ){
  468.         /* draw bug at new location */
  469.         PenPat(black);
  470.         MoveTo( theBug->loc.h=h , theBug->loc.v=v );
  471.         Line(0,0);
  472.     }
  473.     theBug->health=r;
  474. }
  475.  
  476. void KillBug(theBug)
  477. Bug *theBug;
  478. {
  479.     *theBug=bug[--numBugs];
  480. }
  481.  
  482. void SplitBug(theBug)
  483. Bug *theBug;
  484. {
  485. register int i,r,g,sum;
  486.     if(numBugs<MaxBugs){
  487.         bug[numBugs++]=*theBug;
  488.         r=RandomRange(6);
  489.         g=theBug->gene[r];
  490.         g*=2;
  491.         theBug->gene[r]=g;
  492.         if(g>1024)
  493.             for(i=F;i<=L;i++)
  494.                 theBug->gene[i]/=2;
  495.         theBug->health/=2;
  496.         theBug->age=0;
  497.         sum=0;
  498.         for(i=F;i<=L;i++)
  499.             sum+=theBug->gene[i];
  500.         theBug->sum=sum;
  501.         r=RandomRange(6);
  502.         g=(theBug=&bug[numBugs-1])->gene[r];
  503.         g/=2;
  504.         theBug->gene[r]=g;
  505.         theBug->health/=2;
  506.         theBug->age=0;
  507.         sum=0;
  508.         for(i=F;i<=L;i++)sum+=theBug->gene[i];
  509.         theBug->sum=sum;
  510.     } else SysBeep(20);
  511. }
  512.  
  513. unsigned int RandomRange(/* unsigned int top */)
  514. /* Produces random number 0..top-1 */
  515. {    asm{
  516.         clr.w    -(SP)
  517.         _Random
  518.         move.w    (SP)+,D0
  519.         mulu        4(SP),D0
  520.         swap        D0
  521. }        }
  522.  
  523. long int SQDist(/* Point a,b */)
  524. /* square of distance.  Is awful to write in C (takes 67 instead of 8 instructions!) */
  525. {    asm{
  526.         move.w    4(SP),D0        ;b.v
  527.         sub.w    8(SP),D0        ;a.v
  528.         muls        D0,D0
  529.         move.w    6(SP),D1        ;b.h
  530.         sub.w    10(SP),D1    ;a.h
  531.         muls        D1,D1
  532.         add.l        D1,D0
  533. }    }
  534.  
  535. int Scale(a, b, c)
  536. int a, b, c;
  537. {    /* this routine computes the rounded value of (c*(a/b)).
  538.     This is done as (c*a+b/2)/b, where intermediate results are long. */
  539.     asm{
  540.         move.w    a,D0        ;get a
  541.         muls        c,D0        ;a*c
  542.         move.w    b,D1        ;get b
  543.         ext.l        D1
  544.         divs        #2,D1    ;b/2
  545.         ext.l        D1
  546.         add.l        D1,D0    ;c*a+b/2
  547.         divs        b,D0        ;result
  548. }    }
  549.  
  550. int CountPixels(h,v)
  551. register int h;
  552. int v;
  553. {    register bit;
  554.     /* count the number of pixels that would fall under a 3*3 pen at location h,v */
  555.     /* also clear the pixels */
  556.     asm{
  557.         movea.l    thePort,A0
  558.         move.w    v,D0
  559. ;    compensation for origin is not neccesary here
  560. ;        sub.w    OFFSET(GrafPort,portBits.bounds.top) (A0),D0
  561. ;        sub.w    OFFSET(GrafPort,portBits.bounds.left),bit
  562.         mulu        OFFSET(GrafPort,portBits.rowBytes) (A0),D0
  563.         movea.l    OFFSET(GrafPort,portBits.baseAddr) (A0),A1
  564.         adda.l    D0,A1    ;address of the top row
  565.         clr.w    D0        ;for summing up the result
  566.         move.w    #3-1,D2    ;three rows, you know?
  567.  
  568.     @0    move.w    h,bit
  569.         not.w    bit        ;lower three bits are bit #
  570.         move.w    h,D1
  571.         lsr.w    #3,D1    ;offset for byte in row
  572.         btst        bit,0(A1,D1.w)        ;test h,v
  573.         beq.s        @1
  574.         add.w    #1,D0
  575.         bclr        bit,0(A1,D1.w)        ;reset the bit
  576.     @1    sub.w    #1,bit    ;h+1
  577.         move.w    h,D1
  578.         add.w    #1,D1
  579.         lsr.w    #3,D1    ;offset for byte in row
  580.         btst        bit,0(A1,D1.w)        ;test h+1,v
  581.         beq.s        @2
  582.         add.w    #1,D0
  583.         bclr        bit,0(A1,D1.w)        ;reset the bit
  584.     @2    sub.w    #1,bit    ;h+2
  585.         move.w    h,D1
  586.         add.w    #2,D1
  587.         lsr.w    #3,D1    ;offset for byte in row
  588.         btst        bit,0(A1,D1.w)        ;test h+2,v
  589.         beq.s        @3
  590.         add.w    #1,D0
  591.         bclr        bit,0(A1,D1.w)        ;reset the bit
  592.     @3    move.w    OFFSET(GrafPort,portBits.rowBytes) (A0),bit
  593.         ext.l        bit
  594.         adda.l    bit,A1    ;bit=thePort->portBits.rowBytes here
  595.  
  596.         dbra        d2,@0
  597.         ;ready!
  598. }    }