home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / devel5 / sgsppt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-23  |  16.7 KB  |  677 lines

  1. /* IMPORTANT NOTE: THIS MODULE MUST NOT BE COMPILED WITH
  2.    THE -3 OPTION IN BORLAND C++ 3.1 */
  3.  
  4. /* Sega and glove support routines; written by Dave Stampe, July 1992 */
  5.  
  6. /* Copyright 1992 by Dave Stampe and Bernie Roehl.
  7.    May be freely used to write software for release into the public domain;
  8.    all commercial endeavours MUST contact Bernie Roehl and Dave Stampe
  9.    for permission to incorporate any part of this software into their
  10.    products!
  11.  
  12.      ATTRIBUTION:  If you use any part of this source code or the libraries
  13.      in your projects, you must give attribution to REND386, Dave Stampe,
  14.      and Bernie Roehl in your documentation, source code, and at startup
  15.      of your program.  Let's keep the freeware ball rolling!
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <dos.h>
  21. #include <bios.h>
  22. #include <signal.h>
  23. #include <string.h>     /* stricmp() */
  24. #include "segasupp.h"
  25. #include "f3dkitd.h"    /* set_vpage() */
  26.  
  27. /************ INTERFACE SPECIFIC GLOVE STUFF ****************/
  28.  
  29. int port_image = 0;
  30. int sega_port_image = 0;
  31.  
  32. #define INPORT   0x379           /* i/o port addresses */
  33. #define OUTPORT  0x378
  34.  
  35. /* bits from parallel port: */
  36. #define GDATA    0x10    /* PG data in */
  37. #define GLATCH   0x02    /* PG latch out */
  38. #define GCLOCK   0x01    /* PG clock out */
  39. #define GCLOLAT  0x03    /* clock + latch */
  40.  
  41. #define GMASK    0x03     /* bits changable for glove access */
  42.  
  43. /************ GLOVE SPEED AND INTERFACE *****************/
  44.  
  45. #define FASTCOUNT 8       /* # of fast packet bytes */
  46.  
  47. #define D2BITS      12      /* BIT DELAY: microseconds */
  48. #define D2BYTES      140      /* BYTE DELAY: microseconds */
  49.  
  50. #define MAXRESET  200      /* failed reads before resetting glove */
  51.  
  52.  
  53. /***** declarations for assembly code in glovedel.asm *****/
  54.  
  55. int glove_none_mask = 0;
  56. int glove_latch_mask = GLATCH;
  57. int glove_clock_mask = GCLOCK;
  58. int glove_clock_latch = GCLOLAT;
  59.  
  60. int glove_in_port = INPORT;
  61. int glove_out_port = OUTPORT;
  62.  
  63. int glove_data_mask = GDATA;
  64. int glove_write_mask = GMASK;
  65.  
  66. int glove_bit_delay = D2BITS;
  67.  
  68. int glove_byte_delay = D2BYTES;
  69.  
  70. static int glove_892_delay = 892;
  71. static int glove_2260_delay = 2260;
  72. static int glove_7212_delay = 7212;
  73. static int glove_10000_delay = 10000;
  74.  
  75. extern unsigned int timed_glove_delay(int count);
  76.     /* returns time in 1.1925 MHZ ticks */
  77.     /* to perform <count> delay steps   */
  78.     /* call with timer at 18.2 Hz rate  */
  79.  
  80. extern int glove_delay(int count);  /* performs <count> delay steps   */
  81.  
  82. extern int get_glove_byte(void);  /* reads a byte from glove */
  83.  
  84. extern void set_glove_bits(int data);  /* sets glove clock, data lines */
  85.                                        /* and does a bit delay         */
  86.  
  87. /********* defines for output line pair control *******/
  88.  
  89. #define C0L0() set_glove_bits(glove_none_mask)    /* clock 0 latch 0 */
  90. #define C0L1() set_glove_bits(glove_latch_mask)   /* clock 0 latch 1 */
  91. #define C1L0() set_glove_bits(glove_clock_mask)   /* clock 1 latch 0 */
  92. #define C1L1() set_glove_bits(glove_clock_latch)  /* clock 1 latch 1 */
  93.  
  94. /************ status and read control **********/
  95.  
  96. static int glove_rx_try = 10; /* number of read tries: first will be rxflags */
  97. static int glove_rx_flags = 0; /* holds flags (read 10 mS after packet */
  98.  
  99.  
  100. /********************** HIRES MODE SETUP *****************/
  101.  
  102. /*  HIRES ENTRY CODES
  103.     byte:
  104.     1- any value between $05 and $31   (x,y res. divisor???)
  105.     2- only $C1 and $81 work OK (C1)(81 does garbage)
  106.     3- no effect    (08)
  107.     4- no effect    (00)
  108.     5- no effect    (02)
  109.     6- only $FF works   (FF)
  110.     7- seems to affect read rate slightly, 1 fastest (01)
  111.  */
  112.  
  113. static int glove_ignore = 0; /* # of interrupts to ignore glove so it */
  114.                              /* will recover from mode setup          */
  115.  
  116. static int hires_code[7] = { 0x05, 0xC1, 0x08, 0x00, 0x02, 0xFF, 0x01 };
  117.  
  118. static void Hires(void) /* enter HIRES mode */
  119. {
  120.     int i,j,k;
  121.     /* dummy read 4 bits from glove:  */
  122.     C1L0(); 
  123.     C1L1(); /* generate a reset (latch) pulse */
  124.     glove_delay(glove_bit_delay); /* delay for 6 us */
  125.     C1L0();
  126.     glove_delay(glove_bit_delay); /* delay for 6 us */
  127.  
  128.     C0L0(); 
  129.     C1L0(); /* pulse clock */
  130.     C0L0();
  131.     C1L0(); /* pulse clock */
  132.     C0L0(); 
  133.     C1L0(); /* pulse clock */
  134.     C0L0(); 
  135.     C1L0(); /* pulse clock */
  136.  
  137.     /* force glove to listen for setup */
  138.     C1L0();
  139.     glove_delay(glove_7212_delay); /* 7212 us delay */
  140.     C1L1();
  141.     glove_delay(glove_2260_delay); /* 2260 us delay */
  142.  
  143.     for (i = 0; i < 7; i++) /* send 7 bytes of mode data */
  144.     {
  145.         k = hires_code[i];
  146.         for (j = 0; j < 8; j++) /* 8 bits per byte, MSB first */
  147.         {
  148.             if (k & 0x80)
  149.             {
  150.                 C1L1();
  151.                 C0L1();
  152.                 C1L1();
  153.             }
  154.             else
  155.             {
  156.                 C1L0();
  157.                 C0L0();
  158.                 C1L0();
  159.             }
  160.             k <<= 1;
  161.         }
  162.         glove_delay(glove_byte_delay);
  163.     }
  164.  
  165.     glove_delay(glove_892_delay); /* 892 us delay (end of setup data) */
  166.  
  167.     C1L0(); /* drop the reset line */
  168.     glove_ignore = 10; /* some time for the glove controller to relax */
  169. }
  170.  
  171.  
  172. /**************** HYSTERISIS NOISE REMOVAL: x,y,z,rot *************/
  173.  
  174. #define XHYST 2            /* hysterisis for X, Y low noise reduction */
  175. #define YHYST 2            /* 2 eliminates +/-3 quanta of noise */
  176. #define ZHYST 1
  177. #define RHYST 0
  178.  
  179. static int ox = -1000; /* last x,y for hysterisis */
  180. static int oy = -1000;
  181. static int oz = -1000;
  182. static int or = -1000;
  183.  
  184. static void dehyst(glove_data *g) /* hysterisis deglitch (low noise removal) */
  185. {
  186.     int x = g->x;
  187.     int y = g->y;
  188.     int z = g->z;
  189.     int r = g->rot;
  190.     /* handle recentering ("0"key or "Center") */
  191.     if (g->keys == 0) ox = oy = oz = 0;
  192.  
  193.     if (x-ox > XHYST) ox = x-XHYST; /* X hysterisis */
  194.     else
  195.         if (ox-x > XHYST) ox = x+XHYST;
  196.  
  197.     if (y-oy > YHYST) oy = y-YHYST; /* Y hysterisis */
  198.     else
  199.         if (oy-y > YHYST) oy = y+YHYST;
  200.  
  201.     if (z-oz > ZHYST) oz = z-ZHYST; /* Z hysterisis */
  202.     else
  203.         if (oz-z > ZHYST) oz = z+ZHYST;
  204.  
  205.     if (RHYST)
  206.     {
  207.         if (or < 3 && r > 8) /* CCW around-end */
  208.             if (or > 0 || r < 11) or = r+RHYST; 
  209.         else;
  210.         else
  211.             if (or > 8 && r < 3) /* CW around-end */
  212.                 if (or < 11 || r > 0) or = r-RHYST; 
  213.         else;
  214.             else
  215.                 if (r-or > RHYST) or = r-RHYST; /* R hysterisis */
  216.                 else
  217.                     if (or-r > RHYST) or = r+RHYST;
  218.  
  219.         if (or > 11) or -= 11;
  220.         if (or < 0) or += 11;
  221.     }
  222.     else or = r;
  223.     g->x = ox; /* replace present X,Y data */
  224.     g->y = oy;
  225.     g->z = oz;
  226.     g->rot = or;
  227. }
  228.  
  229. /****************** DEGLITCHING ***************/
  230.  
  231. #define XACC 8          /* X, Y maximum accel/decel level. Should */
  232. #define YACC 8        /* be 6-10, but too high limits gesturing */
  233.  
  234. #define XXTEND 1    /* stretches deglitching time */
  235. #define YXTEND 1
  236. #define ROTTIME 1
  237.  
  238. static int x1 = 0; /* delayed 1 sample (for smoothed velocity test) */
  239. static int y1 = 0;
  240. static int x2 = 0; /* delayed 2 samples */
  241. static int y2 = 0;
  242. static int lx = 0; /* last good X,Y speed */
  243. static int ly = 0;
  244. static int lax = 0; /* bad data "stretch" counter */
  245. static int lay = 0;
  246. static int lsx = 0; /* X,Y "hold" values to replace bad data */
  247. static int lsy = 0;
  248. static int lcx = 0; /* last X,Y speed for accel. calc. */
  249. static int lcy = 0;
  250.  
  251. static int saverot = 0;
  252. static int lastrot = 0; /* last stable rotate */
  253. static int chrot = 0; /* time its been stable */
  254.  
  255. static void deglitch(glove_data *g)
  256. {
  257.     int vx, vy;
  258.  
  259.     int x = g->x;
  260.     int y = g->y;
  261.  
  262.     if (g->keys == 0) /* reset on recentering ("0" or "Center" key) */
  263.     {
  264.         x1 = x2 = y1 = y2 = 0;
  265.         lx = ly = lax = lay = 0;
  266.         lsx = lsy = lcx = lcy = 0;
  267.         lastrot = chrot = saverot = 0;
  268.     }
  269.  
  270.     if (lastrot != g->rot)
  271.     {
  272.         chrot = 0;
  273.         lastrot = g->rot;
  274.         g->rot = saverot;
  275.     }
  276.     else
  277.         {
  278.         if (chrot < ROTTIME)
  279.         {
  280.             chrot++;
  281.             g->rot = saverot;
  282.         }
  283.         else saverot = lastrot = g->rot;
  284.     }
  285.  
  286.     vx = x-((x1+x2) >> 1); /* smoothed velocity */
  287.     vy = y-((y1+y2) >> 1);
  288.  
  289.     x2 = x1; /* update last values */
  290.     x1 = g->x;
  291.  
  292.     y2 = y1;
  293.     y1 = g->y;
  294.  
  295.     if (abs(lcx-vx) > XACC) lax = XXTEND; /* check for extreme acceleration */
  296.     if (lax == 0) lx = vx; /* save only good velocity        */
  297.     lcx = vx; /* save velocity for next accel.  */
  298.  
  299.     if (abs(lcy-vy) > YACC) lay = YXTEND; /* same deal for Y accel. */
  300.     if (lay == 0) ly = vy;
  301.     lcy = vy;
  302.  
  303.     if (lax != 0) /* hold X pos'n if glitch */
  304.     {
  305.         g->x = lsx;
  306.         lax--;
  307.     }
  308.  
  309.     if (lay != 0) /* hold Y pos'n if glitch */
  310.     {
  311.         g->y = lsy;
  312.         lay--;
  313.     }
  314.  
  315.     lsx = g->x; /* save position for X,Y hold */
  316.     lsy = g->y;
  317. }
  318.  
  319. /**************** COMPUTE COUNTS FOR TIME CALIBRATION ***********/
  320.  
  321. static float factor;
  322.  
  323. static int uconvert(int t)
  324. {
  325.     float f;
  326.     f = factor*((float)t);
  327.     if (f < 1.0) return 1;
  328.     if (f > 60000.0) return 60000;
  329.     return f;
  330. }
  331.  
  332.  
  333. static void calibrate(void)
  334. {
  335.     factor = 11900.0/((float) timed_glove_delay(10000));
  336.  
  337.     glove_bit_delay = uconvert(glove_bit_delay);
  338.     glove_byte_delay = uconvert(glove_byte_delay);
  339.     glove_892_delay = uconvert(glove_892_delay);
  340.     glove_2260_delay = uconvert(glove_2260_delay);
  341.     glove_7212_delay = uconvert(glove_7212_delay);
  342.     glove_10000_delay = uconvert(glove_10000_delay);
  343. }
  344.  
  345. /******************* gesture recognition **************/
  346.  
  347. #define G_FLAT      0
  348. #define G_THUMB_IN  1
  349. #define G_INDEX_IN  2
  350. #define G_MIDDLE_IN 3
  351. #define G_RING_IN   4
  352. #define G_PINCH     5
  353. #define G_FIST      6
  354. #define G_THUMB_OUT 7
  355. #define G_POINT     8
  356. #define G_BADFINGER 9
  357. #define G_RING_OUT 10
  358. #define G_UNKNOWN  11      /* gesture classification */
  359.  
  360. long gesture_time = 0;
  361. unsigned char gesture_type = G_UNKNOWN;
  362. static unsigned char last_gesture = G_UNKNOWN;
  363.  
  364. /* more reliable mapped gestures */
  365.  
  366. static unsigned char gesture_map[12] = { 
  367.     G_FLAT, G_FLAT, G_PINCH, G_MIDDLE_IN,
  368.     G_RING_IN, G_PINCH, G_FIST, G_FIST, G_POINT,
  369.     G_BADFINGER, G_FIST, G_UNKNOWN };
  370.  
  371. /* unmapped gestures */
  372. /*
  373. char gesture_map[12] = { G_FLAT, G_THUMB_IN, G_INDEX_IN, G_MIDDLE_IN,
  374.              G_RING_IN, G_PINCH, G_FIST, G_THUMB_OUT,
  375.              G_POINT, G_BADFINGER, G_RING_OUT, G_UNKNOWN };
  376. */
  377.  
  378. static int g_lookup[256]; /* compiled lookup table for gestures */
  379.  
  380. static char gs[11][8] = { 
  381.     0,1, 0,0, 0,0, 0,0,
  382.     2,3, 0,0, 0,0, 0,1,
  383.     /* data is: for each gesture   */ 0,1, 2,3, 0,1, 0,1,
  384.     /* and for each finger, a max. */ 0,3, 0,1, 2,3, 0,1,
  385.     /* and min. bend value         */ 0,3, 0,1, 0,1, 2,3,
  386.     1,3, 2,3, 0,1, 0,1,
  387.     2,3, 2,3, 2,3, 1,3,
  388.     0,1, 2,3, 2,3, 1,3,
  389.     0,3, 0,1, 2,3, 1,3,
  390.     0,3, 2,3, 0,1, 1,3,
  391.     0,3, 2,3, 2,3, 0,1 };
  392.  
  393. static void init_gestures(void)
  394. {
  395.     int g,t,i,m,r,x;
  396.  
  397.     for (g = 0; g < 256; g++) g_lookup[g] = G_UNKNOWN;
  398.  
  399.     for (g = 11; g; )
  400.     {
  401.         g--;
  402.         for (t = 0; t < 4; t++)
  403.             for (i = 0; i < 4; i++)
  404.                 for (m = 0; m < 4; m++)
  405.                     for (r = 0; r < 4; r++)
  406.                     {
  407.                         x = (t<<6)+(i<<4)+(m<<2)+r;
  408.                         if (gs[g][0] <= t && gs[g][1] >= t)
  409.                             if (gs[g][2] <= i && gs[g][3] >= i)
  410.                                 if (gs[g][4] <= m && gs[g][5] >= m)
  411.                                     if (gs[g][6] <= r && gs[g][7] >= r)
  412.                                         g_lookup[x] = g;
  413.                     }
  414.     }
  415. }
  416.  
  417. static void gesture_process(glove_data *g)
  418. {
  419.     gesture_time++;
  420.     gesture_type = g_lookup[((int)g->fingers) & 255];
  421.     gesture_type = gesture_map[gesture_type];
  422.     if (gesture_type != last_gesture) gesture_time = 0;
  423.     last_gesture = gesture_type;
  424. }
  425.  
  426.  
  427. /******************* READ GLOVE DATA PACKET *************/
  428.  
  429. void getglove(glove_data *buf) /* read 6 byte data packet */
  430. {
  431.     unsigned char *bp = (char *) buf;
  432.     int i;
  433.  
  434.     for (i = 0; i < FASTCOUNT; ++i)
  435.     {
  436.         *bp++ = get_glove_byte(); /* read data */
  437.         glove_delay(glove_byte_delay);
  438.     }
  439.     glove_rx_try = 0;
  440.     buf->rxflags = 0x3f; /* default all rx fired, but will be read in */
  441. }   /* 8-10 mS when glove_ready returns 2        */
  442.     /* also stored in glove_rx_flags          */
  443.  
  444. /*************** GLOVE INTERRUPT HANDLER **************/
  445.  
  446. static glove_data glove_int_data; /* our copy of the most recent data */
  447.  
  448. static unsigned unready = 0; /* number of times glove has been not ready */
  449. static int glove_deglitch; /* switches deglitching on and off */
  450.  
  451. void glove_int_handler()
  452. {
  453.     int n;
  454.  
  455.     if (glove_ignore) /* wait out setup time if required */
  456.     {
  457.         glove_ignore--;
  458.         return;
  459.     }
  460.  
  461.     glove_rx_try++;
  462.  
  463.     if ((n = get_glove_byte()) != 0xA0)
  464.     {
  465.         if (glove_rx_try == 1) glove_rx_flags = glove_int_data.rxflags = n;
  466.         if (++unready > MAXRESET)
  467.         { /* glove not responding... reset it */
  468.             unready = 0;
  469.             Hires();
  470.         }
  471.     }
  472.     else
  473.         { /* data ready! */
  474.         glove_delay(glove_byte_delay);
  475.         unready = 0;
  476.         getglove(&glove_int_data);
  477.  
  478.         if (glove_deglitch)
  479.             deglitch(&glove_int_data); /* remove spikes and jumps */
  480.         dehyst(&glove_int_data); /* add hysteresis to remove LL noise */
  481.         gesture_process(&glove_int_data);
  482.         ++glove_int_data.nmissed; /* flag data as new */
  483.     }
  484. }
  485.  
  486. /******************* GLOVE INITIALIZATION ***************/
  487.  
  488. #define TIMER_CONTROL 0x43    /* timer control register */
  489. #define TIMER_0       0x40    /* timer zero data register */
  490. #define TIMER_MODE    0x36    /* byte to write to control register */
  491.  
  492. void glove_init(int gdeg) /* gdeg switches deglitching */
  493. {
  494.     outportb(TIMER_CONTROL, TIMER_MODE); /* reprogram timer to mod 65536 */
  495.     outportb(TIMER_0, 0); /* so calibration is correct    */
  496.     outportb(TIMER_0, 0);
  497.  
  498.     glove_deglitch = gdeg;
  499.     calibrate(); /* compute timing counts */
  500.     Hires(); /* enter hires mode */
  501.     init_gestures();
  502.     glove_int_data.nmissed = 0; /* mark no new data yet */
  503. }
  504.  
  505. /************** EXTERNAL DATA INTERFACE **************/
  506.  
  507. int glove_read(glove_data *glov) /* return copy of data packet */
  508. {
  509.     disable();
  510.     *glov = glove_int_data;
  511.     glove_int_data.nmissed = 0;
  512.     enable();
  513.     return glov->nmissed;
  514. }
  515.  
  516.                    /* data status:                   */
  517. int glove_ready()  /* returns 0 if no new data,      */
  518. {                  /*         1 if new data ready,   */
  519.     int lgin, lgrt;  /*         2 if rxflags valid too */
  520.  
  521.     disable();
  522.     lgin = glove_int_data.nmissed;
  523.     lgrt = glove_rx_try;
  524.     enable();
  525.  
  526.     if (lgin == 0) return 0;
  527.     if (lgrt > 0) return 2;
  528.     return 1;
  529. }
  530.  
  531.  
  532.  
  533. /****************** SWITCHER DRIVER INTERFACE *************/
  534.  
  535.  
  536. #define SW_INIT        0
  537. #define SW_QUIT        1
  538. #define SW_ADV_SWITCH  2
  539. #define SW_SYNC_SWITCH 3
  540.  
  541. static int (*switch_driver)() = NULL;
  542.  
  543. static void sdriver_quit()
  544. {
  545.     if (switch_driver) switch_driver(SW_QUIT);
  546. }
  547.  
  548. extern void *load_driver();
  549.  
  550. void init_switch_driver(char *sdname)
  551. {
  552.     if (!stricmp(sdname, "sega"))
  553.     {
  554.         atexit(sega_off);
  555.         return;
  556.     }
  557.  
  558.     switch_driver = load_driver(sdname);
  559.  
  560.     if (switch_driver == NULL)
  561.     {
  562.         fprintf(stderr,"Cannot read switcher driver %s\n", sdname);
  563.         exit(0);
  564.     }
  565.  
  566.     switch_driver = MK_FP(FP_SEG(switch_driver), 16+FP_OFF(switch_driver)); /* entry point */
  567.     switch_driver(SW_INIT);
  568.     atexit(sdriver_quit);
  569. }
  570.  
  571.  
  572. /********************* SEGA GLASSES CONTROL *****************/
  573.  
  574. int left_page = 0; /* left image */
  575. int right_page = 1; /* right image */
  576. int has_switched; /* = 3 once both switched in */
  577.  
  578. static int adv_has_switched = 0;
  579.  
  580. #define SEGA_LEFT  0x30
  581. #define SEGA_RIGHT 0x20
  582. #define SEGA_OFF   0x00
  583.  
  584. #define SEGA_MASK  0x30       /* bits writeable for Sega */
  585.  
  586. #define COMPORT 0x3fc       /* com1 = 0x3fc, com2 = 0x2fc */
  587.  
  588. int sega_left = SEGA_LEFT;
  589. int sega_right = SEGA_RIGHT;
  590. int sega_address = COMPORT;
  591. int sega_mask = SEGA_MASK;
  592. int sega_doff = SEGA_OFF;
  593.  
  594. static int phase = 1; /* current image */
  595.  
  596. void select_sega_port(int port)  /* sets up default Sega stuff */
  597. {
  598.  sega_address = port;
  599.  sega_left = SEGA_LEFT;
  600.  sega_right = SEGA_RIGHT;
  601.  sega_mask = SEGA_MASK;
  602.  sega_doff = SEGA_OFF;
  603. }
  604.  
  605. static void sega_write(int data)  /* write Sega data w/o disturbance */
  606. {                          /* can also handle glove, Sega on same port */
  607.     disable();
  608.     if (sega_address == glove_out_port)
  609.         sega_port_image = port_image =
  610.             (port_image & (~sega_mask)) | (data & sega_mask);
  611.     else
  612.         sega_port_image = (sega_port_image & (~sega_mask)) | (data & sega_mask);
  613.     outportb(sega_address, sega_port_image);
  614.     enable();
  615. }
  616.  
  617. void switch_sega(int to_go)  /* now gets arg, sync at 0, 1 = advanced signal */
  618. {                            /* 2-step switching ensures adr. load of VGA    */
  619.     if (switch_driver)
  620.     {
  621.         if (to_go == 1)
  622.         {
  623.             if (phase == sega_left)
  624.             {
  625.                 phase = sega_right;
  626.                 if (switch_driver(SW_ADV_SWITCH, 0) )
  627.                     set_vpage(right_page);
  628.                 adv_has_switched = 1;
  629.             }
  630.             else
  631.                 {
  632.                 phase = sega_left;
  633.                 if (switch_driver(SW_ADV_SWITCH, 1) )
  634.                     set_vpage(left_page);
  635.                 adv_has_switched = 2;
  636.             }
  637.         }
  638.         if (to_go == 0)
  639.         {
  640.             switch_driver(SW_SYNC_SWITCH, (phase == sega_left) ? 1 : 0);
  641.             has_switched |= adv_has_switched;
  642.             adv_has_switched = 0;
  643.         }
  644.     }
  645.     else
  646.         {
  647.         if (to_go == 1)
  648.         {
  649.             if (phase == sega_left)
  650.             {
  651.                 phase = sega_right;
  652.                 set_vpage(right_page);
  653.                 adv_has_switched = 1;
  654.             }
  655.             else
  656.                 {
  657.                 phase = sega_left;
  658.                 set_vpage(left_page);
  659.                 adv_has_switched = 2;
  660.             }
  661.         }
  662.         if (to_go == 0)
  663.         {
  664.             sega_write(phase);
  665.             has_switched |= adv_has_switched;
  666.             adv_has_switched = 0;
  667.         }
  668.     }
  669. }
  670.  
  671.  
  672. void sega_off()
  673. {
  674.     sega_write(sega_doff); /* turn glasses driver off to save lcds! */
  675. }
  676.  
  677.