home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / cellsim / v2_5 / src / cm_cllsm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-04-04  |  16.2 KB  |  851 lines

  1. /*****
  2.  *
  3.  * File: cm_cellsim.c
  4.  *
  5.  * Cellsim, cellular automata simulator
  6.  *
  7.  * Routines to communicate with the Connection Machine Front End (CMFE),
  8.  * and maintain data-structures relevant to controlling the CM.
  9.  *
  10.  *****/
  11.  
  12.  
  13.  
  14. #include "cm_cellsim.h"
  15.  
  16.  
  17. /*
  18.  *
  19.  * Cellsim copyright 1989, 1990 by Chris Langton and Dave Hiebeler
  20.  * (cgl@lanl.gov, hiebeler@heretic.lanl.gov)
  21.  *
  22.  * This package may be freely distributed, as long as you don't:
  23.  * - remove this notice
  24.  * - try to make money by doing so
  25.  * - prevent others from copying it freely
  26.  * - distribute modified versions without clearly documenting your changes
  27.  *   and notifying us
  28.  *
  29.  * Please contact either of the authors listed above if you have questions
  30.  * or feel an exception to any of the above restrictions is in order.
  31.  *
  32.  * If you make changes to the code, or have suggestions for changes,
  33.  * let us know!  If we use your suggestion, you will receive full credit
  34.  * of course.
  35.  */
  36.  
  37. /*****
  38.  * Cellsim history:
  39.  *
  40.  * Cellsim was originally written on Apollo workstations by Chris Langton.
  41.  *
  42.  * Sun versions:
  43.  *
  44.  * - version 1.0
  45.  *   by C. Ferenbaugh and C. Langton
  46.  *   released 09/02/88
  47.  *
  48.  * - version 1.5
  49.  *   by Dave Hiebeler and C. Langton  May - June 1989
  50.  *   released 07/03/89
  51.  *
  52.  * - version 2.0
  53.  *   by Dave Hiebeler and C. Langton  July - August 1989
  54.  *   never officially released (unofficially released 09/08/89)
  55.  *
  56.  * - version 2.5
  57.  *   by Dave Hiebeler and C. Langton  September '89 - February 1990
  58.  *   released 02/26/90
  59.  *****/
  60.  
  61.  
  62. /*
  63.  * wait for acknowledgement from CMFE, and an error msg if something
  64.  * went wrong
  65.  */
  66. int
  67. CM_wait_for_ack()
  68. {
  69.     unsigned char buf[80];
  70.  
  71.     clear_msg();
  72.     show_msg("Waiting for CM...");
  73.     read_from_sock(server_fd, buf, 1, OFF, 0);
  74.     clear_msg();
  75.     if (buf[0] == 0) {
  76.     show_msg("CM program crashed...");
  77.     sleep(1);
  78.     fprintf(stderr, "CM program has crashed...\n");
  79.     CM_disconnect();
  80.     return 1;
  81.     }
  82.     if (buf[0] != DONE) {
  83.     read_from_sock(server_fd, buf, 80, OFF, 0);
  84.     show_msg("Error on CM");
  85.     show_msg(buf);
  86.     return 1;
  87.     }
  88.     else
  89.     show_msg("Done.");
  90.     return 0;
  91. }
  92.  
  93.  
  94. /*
  95.  * Send a byte to the CMFE
  96.  */
  97. void
  98. CM_send_byte(b)
  99. unsigned char b;
  100. {
  101.     unsigned char local_b;
  102.  
  103.     local_b = b;
  104.     write_to_sock(server_fd, &local_b, 1, OFF, 0);
  105. }
  106.  
  107.  
  108. /*
  109.  * Send integer to CMFE.  This has to be done this way, rather than
  110.  * just sending it directly, because a Vax holds its integers with bytes
  111.  * in reverse order relative to Suns.  So a portable method was needed.
  112.  */
  113. void
  114. CM_send_int(n)
  115. int n;
  116. {
  117.     unsigned char buf[4];
  118.  
  119.     /* buf[0] = n%256;
  120.     buf[1] = n/256;
  121.     buf[2] = n/(256*256);
  122.     buf[3] = n/(256*256*256);
  123.     */
  124.     buf[0] = n & 0xff;
  125.     buf[1] = (n>>8) & 0xff;
  126.     buf[2] = (n>>16) & 0xff;
  127.     buf[3] = (n>>24) & 0xff;
  128.     write_to_sock(server_fd, buf, 4, OFF, 0);
  129. }
  130.  
  131.  
  132. /*
  133.  * Read an int from CMFE.
  134.  */
  135. int
  136. CM_read_int()
  137. {
  138.     unsigned char buf[4];
  139.     int n;
  140.  
  141.     read_from_sock(server_fd, buf, 4, OFF, 0);
  142.     n = buf[0] + buf[1]*256;
  143.     n += buf[2]*256*256 + buf[3]*256*256*256;
  144.     return n;
  145. }
  146.  
  147.  
  148. /*
  149.  * Connect to a waiting socket on a CMFE
  150.  */
  151. void
  152. CM_connect()
  153. {
  154.     char buf[80], nh[80];
  155.     struct hostent *server_hostent;
  156.     int tmp, err, use_host_number;
  157.     long int CM_host;
  158.     struct in_addr tmp_addr;
  159.  
  160.     clear_msg();
  161.     if (invalid_set_pressed())
  162.     return;
  163.     if (setting_sequence)
  164.     add_sequence(CM_connect);
  165.     if (use_CM) {
  166.     show_msg("Already connected to CM");
  167.     return;
  168.     }
  169.     if (!valid_CM_state(NHOOD, S, R)) {
  170.     show_msg("Invalid nhood for use");
  171.     show_msg("with CM");
  172.     return;
  173.     }
  174.     if (!valid_CM_image(B)) {
  175.     show_msg("Image size must be 128 or");
  176.     show_msg("256 or 512 to connect to CM");
  177.     return;
  178.     }
  179.     def_CM_get_settings();
  180.     switch (B) {
  181.       case 128:
  182.     CM_zoom = 6;
  183.     break;
  184.       case 256:
  185.     CM_zoom = 3;
  186.     break;
  187.       case 512:
  188.     CM_zoom = 1;
  189.     break;
  190.     }
  191.     CM_panx = B/2;
  192.     CM_pany = B/2;
  193.     set_CM_sliders();
  194.     err = sscanf(CM_hostname, "%d", &tmp);
  195.     if ((err == 0) || (tmp == 0))
  196.     use_host_number = 0;
  197.     else
  198.     use_host_number = 1;
  199.     if (use_host_number)
  200.     CM_host = inet_addr(CM_hostname);
  201.     else
  202.     {
  203.         if ((server_hostent = gethostbyname(CM_hostname)) == NULL) {
  204.         sprintf(buf,"Host '%s' unknown",CM_hostname);
  205.         clear_msg();
  206.         show_msg(buf);
  207.         return;
  208.         }
  209.         CM_host = *((long int *) server_hostent->h_addr);
  210.     }
  211.     tmp_addr.s_addr = CM_host;
  212.     sprintf(buf, "Trying to connect");
  213.     show_msg(buf);
  214.     sprintf(buf, "to %s", inet_ntoa(tmp_addr));
  215.     show_msg(buf);
  216.     if ((server_fd = connect_to_waiting_socket(CM_host, CM_port, 0)) == -1) {
  217.     sprintf(buf, "Error trying to connect");
  218.     show_msg(buf);
  219.     return;
  220.     }
  221.     clear_msg();
  222.     show_msg("Successfully connected");
  223.     use_CM = 1;
  224.     read_from_sock(server_fd, buf, 1, OFF, 0);    /* read 1 byte to be sure
  225.                          * someone's really there */
  226.     /* Construct a string to tell CMFE what nhood and size to use */
  227.     switch (NHOOD) {
  228.       case NH_VONN:
  229.     nh[0] = 'v';
  230.     break;
  231.       case NH_MOORE:
  232.     nh[0] = 'm';
  233.     break;
  234.       case NH_MARG:
  235.     nh[0] = 'M';
  236.     break;
  237.       case NH_LIN:
  238.     nh[0] = 'l';
  239.     break;
  240.     }
  241.     sprintf(&nh[1], "%d ", S);
  242.     strcpy(buf, nh);
  243.     sprintf(&buf[strlen(buf)], "b%d", B);
  244.     if (NHOOD == NH_LIN)
  245.     sprintf(&buf[strlen(buf)], " r%d", R);
  246.     write_to_sock(server_fd, buf, 80, OFF, 0);
  247.     /* set up some intiial stuff on the CM */
  248.     if (SOCKET_INUSE)
  249.     CM_send_byte(USE_SOCK);
  250.     else
  251.     CM_send_byte(DONT_USE_SOCK);
  252.     CM_set_displays();
  253.     CM_set_disp_interval();
  254.     CM_send_cmap();
  255.     CM_send_delay();
  256.     CM_send_zoom();
  257.     CM_send_pan();
  258.     CM_get_dirs();
  259.     /* It's possible something bombed on the CMFE while we were doing this,
  260.      * so let's make a final check */
  261.     if (use_CM)
  262.     show_msg("Connected to CM");
  263.     else
  264.     show_msg("Not connected!");
  265. }
  266.  
  267.  
  268. /*
  269.  * See if we're connected to CMFE.  If err is non-zero, print a message
  270.  * complaining if we're not connected.  Otherwise, silently return 1 if
  271.  * we are NOT connected, 0 if we are connected.
  272.  */
  273. int
  274. CM_check_connection(err)
  275. int err;
  276. {
  277.     if (!use_CM) {
  278.     if (err) {
  279.         clear_msg();
  280.         show_msg("Not connected to CM");
  281.     }
  282.     return 1;
  283.     }
  284.     return 0;
  285. }
  286.     
  287.     
  288.  
  289. /*
  290.  * Run for specified # of steps on CM
  291.  */
  292. void
  293. CM_auto_step(step)
  294. int step;
  295. {
  296.     CM_auto_screen(step);
  297. }
  298.  
  299.  
  300.  
  301. void
  302. CM_auto_screen(step)
  303. int step;
  304. {
  305.     char buf[80];
  306.     int i,j;
  307.  
  308.     if (CM_check_connection(1))
  309.     return;
  310.     CM_send_delay();
  311.     CM_send_byte(RUN);        /* tell CMFE we want to run */
  312.     CM_send_int(step);        /* and how long to run */
  313.     CM_send_int(CM_disp_interval);    /* and how often to display */
  314.     if (function) {    /* send parms if necessary */
  315.     CM_send_int(parm1);
  316.     CM_send_int(parm2);
  317.     }
  318.     if (NHOOD == NH_MARG) {    /* and stime for margolus phase */
  319.     CM_send_int(stime);
  320.     }
  321.     /* read back state-counts, if that is being done */
  322.     if (SOCKET_INUSE) {
  323.     for (i=0; i<step; i++) {
  324.         read_from_sock(server_fd, buf, S*4, OFF, 0);
  325.         for (j=0; j<S; j++)
  326.         statecount[j] = buf[j*4] + buf[j*4 + 1]*256 +
  327.             buf[j*4 + 2]*256*256 + buf[j*4 + 3]*256*256*256;
  328.         send_sock();
  329.     }
  330.     }
  331.     CM_wait_for_ack();    /* get acknowledgement from CMFE */
  332.     clear_msg();
  333.     show_msg("Done");
  334. }
  335.  
  336.  
  337. /*
  338.  * This routine is used to "run forever", that is run with no bound.
  339.  * It's different than above, because the CM will have to check the
  340.  * socket every now & then to see if the Sun has told it to stop.
  341.  */
  342. void
  343. CM_auto_run()
  344. {
  345.     if (CM_check_connection(1))
  346.     return;
  347.     CM_send_delay();
  348.     CM_send_byte(RUN_FOREVER);    /* tell CMFE we want to run forever */
  349.     if (function) {
  350.     CM_send_int(parm1);
  351.     CM_send_int(parm2);
  352.     }
  353.     if (NHOOD == NH_MARG) {
  354.     CM_send_int(stime);
  355.     }
  356.     CM_send_int(CM_disp_interval);
  357.     /* Now that we've sent all the necessary parms, just return.
  358.      * The routine that called this one will tell the CM when to stop.
  359.      */
  360.     clear_msg();
  361.     show_msg("Done.");
  362. }
  363.  
  364.  
  365. /*
  366.  * This routine sends a byte to the CM to terminate a "forever run".
  367. */
  368. void
  369. CM_stop_run()
  370. {
  371.     CM_send_byte(STOP_RUN);
  372.     /* Find out how long CM ran, and increment time-variable */
  373.     stime += CM_read_int();
  374. }
  375.  
  376.  
  377. /*
  378.  * Send lookup table to CM
  379.  */
  380. void
  381. CM_send_LT()
  382. {
  383.     clear_msg();
  384.     if (invalid_set_pressed())
  385.     return;
  386.     if (function) {
  387.     show_msg("Can't send LT when");
  388.     show_msg("using 256 states");
  389.     }
  390.     if (setting_sequence)
  391.     add_sequence(CM_send_LT);
  392.     if (CM_check_connection(1))
  393.     return;
  394.     CM_send_byte(SEND_LT);
  395.     CM_send_byte(UNCOMPRESSED);    /* future versions may be able to send
  396.                  * things in compressed form... */
  397.     show_msg("Sending LT...");
  398.     write_to_sock(server_fd, ta, TSIZE, OFF, 0);
  399.     CM_wait_for_ack();
  400. }
  401.  
  402.  
  403.  
  404. /*
  405.  * Send colormap to CM, for use on the CM Frame Buffer (CMFB)
  406.  */
  407. void
  408. CM_send_cmap()
  409. {
  410.     unsigned char red[256], green[256], blue[256];
  411.  
  412.     clear_msg();
  413.     if (invalid_set_pressed())
  414.     return;
  415.     if (setting_sequence)
  416.     add_sequence(CM_send_cmap);
  417.     if (CM_check_connection(1))
  418.     return;
  419.     CM_send_byte(SEND_CMAP);
  420.     set_rgb_arrays(red,green,blue);    /* get cmap into rgb arrays */
  421.     /* Now send arrays */
  422.     write_to_sock(server_fd, red, 256, OFF, 0);
  423.     write_to_sock(server_fd, green, 256, OFF, 0);
  424.     write_to_sock(server_fd, blue, 256, OFF, 0);
  425.     CM_wait_for_ack();
  426. }
  427.  
  428.  
  429. /*
  430.  * Send current image over to CM
  431.  */
  432. void
  433. CM_send_image()
  434. {
  435.     clear_msg();
  436.     if (invalid_set_pressed())
  437.     return;
  438.     if (setting_sequence)
  439.     add_sequence(CM_send_image);
  440.     if (CM_check_connection(1))
  441.     return;
  442.     CM_send_byte(SEND_IMAGE);
  443.     CM_send_byte(UNCOMPRESSED);
  444.     show_msg("Sending image...");
  445.     /* Note that we send the whole 2-D array, even when using 1-D nhood */
  446.     write_to_sock(server_fd, ca + B, B*B, OFF, 0);
  447.     CM_wait_for_ack();
  448. }
  449.  
  450.  
  451. /*
  452.  * Probe on CM.  Right now, this really uses the CM to probe a local
  453.  * neighborhood, rather than probing the neighborhood at the selected
  454.  * coordinates on the CM
  455.  */
  456. int
  457. CM_probe(x,y,a)
  458. int x,y,a;    /* table address */
  459. {
  460.     char buf[128];
  461.  
  462.     clear_msg();
  463.     if (CM_check_connection(1))
  464.     return;
  465.     if (function) {
  466.     show_msg("Can't probe on CM in");
  467.     show_msg("256-state mode yet");
  468.     return;
  469.     }
  470.     CM_send_byte(PROBE);
  471.     CM_send_int(x);
  472.     CM_send_int(y);
  473.     bcopy(&a, buf, 4);
  474.     write_to_sock(server_fd, buf, 4, OFF, 0);
  475.     if (NHOOD == NH_MARG) {
  476.     CM_send_int(stime);
  477.     }
  478.     /* read back results */
  479.     read_from_sock(server_fd, buf, 1, OFF, 0);
  480.     return (int)buf[0];
  481. }
  482.  
  483.  
  484. /*
  485.  * Display the image currently in memory on the CM.
  486.  * This involves either or both of:
  487.  *  - displaying the image on the CM frame-buffer, if it exists and has
  488.  *    been enabled
  489.  *  - reading the image back to the Sun through the socket, and
  490.  *    displaying it in the Cellsim canvas.
  491.  */
  492. void
  493. CM_display_image()
  494. {
  495.     if (CM_check_connection(1))
  496.     return;
  497.     CM_send_byte(DISPLAY);
  498.     if (use_Sun_disp) {
  499.     swap_data();
  500.     clear_msg();
  501.     show_msg("Reading image from CM..");
  502.     CM_send_byte(UNCOMPRESSED);
  503.     read_from_sock(server_fd, ca + B, B*B, OFF, 0);
  504.     show_msg("Done.");
  505.     display_image();
  506.     }
  507. }
  508.  
  509.  
  510. /*
  511.  * Disconnect from the CMFE
  512.  */
  513. void
  514. CM_disconnect()
  515. {
  516.     clear_msg();
  517.     if (invalid_set_pressed())
  518.     return;
  519.     if (setting_sequence)
  520.     add_sequence(CM_disconnect);
  521.     if (CM_check_connection(1))
  522.     return;
  523.     CM_send_byte(QUIT);
  524.     close(server_fd);
  525.     use_CM = 0;
  526.     show_msg("Disconnected from CM.");
  527. }
  528.  
  529.  
  530. void
  531. CM_change_stuff(str)
  532. char *str;
  533. {
  534.     char buf[80];
  535.  
  536.     CM_send_byte(CHANGE_STUFF);
  537.     /* "str" might not be 80 chars long, so make a local copy to send */
  538.     strcpy(buf, str);
  539.     write_to_sock(server_fd, buf, 80, OFF, 0);
  540.     CM_wait_for_ack();
  541. }
  542.  
  543.  
  544.  
  545. /*
  546.  * Send run-delay to CMFE
  547.  */
  548. void
  549. CM_send_delay()
  550. {
  551.     if (CM_check_connection(0))
  552.     return;
  553.     CM_send_byte(CHANGE_DELAY);
  554.     CM_send_int(CM_delay);
  555.     CM_wait_for_ack();
  556. }
  557.  
  558.  
  559. /*
  560.  * Tell CMFE which displays (CMFB and/or Sun display) we want to use
  561.  */
  562. void
  563. CM_set_displays()
  564. {
  565.     byte setting;
  566.  
  567.     setting = use_FB + use_Sun_disp * 2;
  568.     if (CM_check_connection(0))
  569.     return;
  570.     CM_send_byte(SET_DISPLAYS);
  571.     CM_send_byte(setting);
  572.     CM_wait_for_ack();
  573. }
  574.  
  575.  
  576. /*
  577.  * Set display-interval for displaying images when running
  578.  */
  579. void
  580. CM_set_disp_interval()
  581. {
  582.     if (CM_check_connection(0))
  583.     return;
  584.     CM_send_byte(SET_DISP_INTERVAL);
  585.     CM_send_int(CM_disp_interval);
  586.     CM_wait_for_ack();
  587. }
  588.  
  589.  
  590. /*
  591.  * Load an image into CM array, from the CMFE filesystem
  592.  */
  593. void
  594. CM_load_image(fname)
  595. char fname[128];
  596. {
  597.     if (CM_check_connection(1))
  598.     return;
  599.     CM_send_byte(LOAD_IMAGE);
  600.     write_to_sock(server_fd, fname, 128, OFF, 0);
  601.     CM_wait_for_ack();
  602. }
  603.  
  604.  
  605. /*
  606.  * Generate a quick random image on CM
  607.  */
  608. CM_quick_random()
  609. {
  610.     if (CM_check_connection(1))
  611.     return;
  612.     CM_send_byte(QUICK_RANDOM);
  613.     CM_wait_for_ack();
  614. }
  615.  
  616.  
  617. /*
  618.  * Generate general random image on CM
  619.  */
  620. CM_general_random()
  621. {
  622.     if (CM_check_connection(1))
  623.     return;
  624.     CM_send_byte(GENERAL_RANDOM);
  625.     CM_send_int(saved_ox);
  626.     CM_send_int(saved_oy);
  627.     CM_send_int(saved_sx);
  628.     CM_send_int(saved_sy);
  629.     CM_send_int(saved_density);
  630.     CM_send_int(saved_min_val);
  631.     CM_send_int(saved_max_val);
  632.     CM_wait_for_ack();
  633. }
  634.  
  635.  
  636. /*
  637.  * Clear array on CM
  638.  */
  639. CM_clear()
  640. {
  641.     if (CM_check_connection(1))
  642.     return;
  643.     CM_send_byte(CLEAR);
  644.     CM_wait_for_ack();
  645. }
  646.  
  647.  
  648. /*
  649.  * Get image from CM to local array
  650.  */
  651. CM_get_image_proc()
  652. {
  653.     if (CM_check_connection(1))
  654.     return;
  655.     clear_msg();
  656.     show_msg("Reading image from CM..");
  657.     CM_send_byte(GET_IMAGE);
  658.     read_from_sock(server_fd, ca + B, B*B, OFF, 0);
  659.     display_image();
  660.     show_msg("Done.");
  661. }
  662.  
  663.  
  664.  
  665. /*
  666.  * Get image-dir from CMFE
  667.  */
  668. CM_get_image_dir()
  669. {
  670.     char buf[128];
  671.  
  672.     CM_send_byte(GET_CM_IMAGE_DIR);
  673.     read_from_sock(server_fd, buf, 128, OFF, 0);
  674.     strcpy(CM_image_dir, buf);
  675. }
  676.  
  677.  
  678. /*
  679.  * Send image-dir to CMFE
  680.  */
  681. CM_send_image_dir()
  682. {
  683.     if (CM_check_connection(1))
  684.     return;
  685.     clear_msg();
  686.     CM_send_byte(SET_CM_IMAGE_DIR);
  687.     write_to_sock(server_fd, CM_image_dir, 128, OFF, 0);
  688. }
  689.  
  690.  
  691.  
  692.  
  693. /*
  694.  * Get fcn-dir from CMFE
  695.  */
  696. CM_get_fcn_dir()
  697. {
  698.     char buf[128];
  699.  
  700.     CM_send_byte(GET_CM_FCN_DIR);
  701.     read_from_sock(server_fd, buf, 128, OFF, 0);
  702.     strcpy(CM_fcn_dir, buf);
  703. }
  704.  
  705.  
  706. /*
  707.  * Send fcn-dir to CMFE
  708.  */
  709. CM_send_fcn_dir()
  710. {
  711.     if (CM_check_connection(1))
  712.     return;
  713.     clear_msg();
  714.     CM_send_byte(SET_CM_FCN_DIR);
  715.     write_to_sock(server_fd, CM_fcn_dir, 128, OFF, 0);
  716. }
  717.  
  718.  
  719.  
  720. /*
  721.  * Get LT-dir from CMFE
  722.  */
  723. CM_get_LT_dir()
  724. {
  725.     char buf[128];
  726.  
  727.     CM_send_byte(GET_CM_LT_DIR);
  728.     read_from_sock(server_fd, buf, 128, OFF, 0);
  729.     strcpy(CM_LT_dir, buf);
  730. }
  731.  
  732.  
  733. /*
  734.  * Send LT-dir to CMFE
  735.  */
  736. CM_send_LT_dir()
  737. {
  738.     if (CM_check_connection(1))
  739.     return;
  740.     clear_msg();
  741.     CM_send_byte(SET_CM_LT_DIR);
  742.     write_to_sock(server_fd, CM_LT_dir, 128, OFF, 0);
  743. }
  744.  
  745.  
  746.  
  747. /*
  748.  * Load a rule (either LT or fcn) from CMFE filesystem
  749.  */
  750. CM_load_rule_proc()
  751. {
  752.     char fname[128], buf[128];
  753.  
  754.     if (CM_check_connection(1))
  755.     return;
  756.     clear_msg();
  757.     if (invalid_set_pressed())
  758.     return;
  759.     if (setting_sequence)
  760.     add_sequence(CM_load_rule_proc);
  761.     def_CM_get_settings();
  762.     get_msg("Load CM rule:", buf, BUFLEN, saved_CM_rule_file);
  763.     if (buf[0] == NULL)
  764.     return;
  765.     strcpy(saved_CM_rule_file, buf);
  766.     strcpy(fname, buf);
  767.     if (auto_nhood_change)
  768.     change_stuff_file(buf);
  769.     strcpy(buf, fname);
  770.     CM_send_byte(LOAD_RULE);
  771.     write_to_sock(server_fd, fname, 128, OFF, 0);
  772.     if (CM_wait_for_ack())
  773.     return;
  774.     if (function) {
  775.     parm1 = CM_read_int();
  776.     parm2 = CM_read_int();
  777.     }
  778. }
  779.  
  780.  
  781. /*
  782.  * Set the zoom-factor (magnification) of CM Frame Buffer (CMFB)
  783.  */
  784. CM_set_zoom()
  785. {
  786.     int new_zoom;
  787.     
  788.     clear_msg();
  789.     if (get_num("New zoom factor: ", &new_zoom, 0, 1000000, CM_zoom))
  790.     return;
  791.     CM_zoom = new_zoom;
  792.     CM_send_zoom();
  793. }
  794.  
  795.  
  796. /*
  797.  * Send the new zoom-factor to CMFE
  798.  */
  799. CM_send_zoom()
  800. {
  801.     CM_send_byte(SET_ZOOM);
  802.     CM_send_int(CM_zoom);
  803.     /* CM_wait_for_ack(); */
  804. }
  805.  
  806.  
  807.  
  808. /*
  809.  * Send pan (translational offsets) for CMFB image
  810.  */
  811. CM_send_pan()
  812. {
  813.     CM_panx = CM_panx - CM_panx%8;
  814.     CM_pany = CM_pany - CM_pany%4;
  815.     CM_send_byte(SET_PAN);
  816.     CM_send_int(CM_panx);
  817.     CM_send_int(CM_pany);
  818.     /* CM_wait_for_ack(); */
  819. }
  820.  
  821.  
  822. /*
  823.  * Tell CMFE we've changed image-size
  824.  */
  825. CM_change_image_size()
  826. {
  827.     CM_send_byte(CHANGE_IMAGE_SIZE);
  828.     CM_send_int(B);
  829.     CM_wait_for_ack();
  830.     /* Reset the zoom factor to be something good again */
  831.     if (B == 128)
  832.     CM_zoom = 6;
  833.     else if (B == 256)
  834.     CM_zoom = 3;
  835.     else if (B == 512)
  836.     CM_zoom = 1;
  837.     CM_panx = B/2;
  838.     CM_pany = B/2;
  839.     set_CM_sliders();
  840.     CM_send_zoom();
  841. }
  842.  
  843.  
  844. void
  845. CM_send_dirs()
  846. {
  847.     CM_send_LT_dir();
  848.     CM_send_fcn_dir();
  849.     CM_send_image_dir();
  850. }
  851.