home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume6 / glib / part06 / pc-mach.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-14  |  11.2 KB  |  626 lines

  1. /* $Id: pc-mach.c,v 1.6 89/05/06 17:13:39 lee Exp $
  2.  *
  3.  * Glib - Generic LIBrarian and editor
  4.  *
  5.  * Machine dependent stuff for MIDI programs.
  6.  * Time Thompson
  7.  *
  8.  * This is for MS-DOS machines.  The screen operations should
  9.  * work okay, but the MIDI I/O needs to be worked on.  It may
  10.  * or may not be fast enough on some machines. 
  11.  * $Log:    pc-mach.c,v $
  12.  * Revision 1.6  89/05/06  17:13:39  lee
  13.  * rel. to comp.sources.misc
  14.  * 
  15.  */
  16.  
  17. #include "glib.h"
  18.  
  19. int Rows = 24;
  20. int Cols = 80;
  21.  
  22. char *
  23. alloc(n)
  24. {
  25.     char *p;
  26.  
  27.     if ( (p=malloc((unsigned)n)) == (char *)NULL ) {
  28.         printf("*** Whoops *** alloc has failed?!?  No more memory!\n");
  29.         fflush(stdout);
  30.         bye();
  31.     }
  32.     return(p);
  33. }
  34.  
  35. flushmidi()
  36. {
  37.     while ( STATMIDI )
  38.         getmidi();
  39. }
  40.  
  41. /* getmouse - get currect row and column of mouse */
  42. getmouse(amr,amc)
  43. int *amr;
  44. int *amc;
  45. {
  46.     *amr = -1;
  47.     *amc = -1;
  48. }
  49.  
  50. /* statmouse - return mouse button state (0=nothing pressed,1=left,2=right) */
  51. statmouse()
  52. {
  53.     return(-1);
  54. }
  55.  
  56. /* Return when either a console key or mouse button is pressed. */
  57. mouseorkey()
  58. {
  59.     return(getconsole());
  60. }
  61.  
  62. #ifdef C86
  63. getch()
  64. {
  65.     struct regval sreg, rreg;
  66.     sreg.ax = 0x0000;
  67.     sysint(0x16, &sreg, &rreg);
  68.     return(rreg.ax & 0x7f);
  69. }
  70. #endif
  71.  
  72. windinit()
  73. {
  74. }
  75.  
  76. windgoto(r,c)
  77. int r,c;
  78. {
  79. #ifdef C86
  80.     struct regval sreg, rreg;
  81.     sreg.ax = 0x200;
  82.     sreg.bx = 0;
  83.     sreg.dx = (r<<8) | c ;
  84.     sysint(0x10, &sreg, &rreg);
  85. #endif
  86. #ifdef TURBOC
  87.     gotoxy(1+c,1+r);
  88. #endif
  89. }
  90.  
  91. winderaserow(r)
  92. {
  93. #ifdef C86
  94.     struct regval sreg, rreg;
  95.     sreg.ax = 0x0600;
  96.     sreg.bx = 0;
  97.     sreg.cx = (r<<8);    /* urow, lcol */
  98.     sreg.dx = (r<<8) | 79;
  99.     sysint(0x10, &sreg, &rreg);
  100. #endif
  101. #ifdef TURBOC
  102.     gotoxy(1,r+1);
  103.     clreol();
  104. #endif
  105. }
  106.  
  107. windexit()
  108. {
  109.     /* windgoto(23,0);
  110.     windrefresh();
  111.     nocbreak();
  112.     nl();
  113.     echo();
  114.     endwin(); */
  115. }
  116.  
  117. windclear()
  118. {
  119. #ifdef C86
  120.     struct regval sreg, rreg;
  121.     sreg.ax = 0x0600;
  122.     sreg.bx = 0;
  123.     sreg.cx = 0;    /* urow, lcol */
  124.     sreg.dx = (24<<8) | 79;
  125.     sysint(0x10, &sreg, &rreg);
  126. #endif
  127. #ifdef TURBOC
  128.     clrscr();
  129. #endif
  130. }
  131.  
  132. /* windgets - get a line of input from the console, handling backspaces */
  133. windgets(s)
  134. char *s;
  135. {
  136.     char *origs = s;
  137.     int c;
  138.  
  139.     while ( (c=getconsole()) != '\n' && c!='\r' && c!= EOF ) {
  140.         if ( c == '\b' ) {
  141.             if ( s > origs ) {
  142.                 windstr("\b \b");
  143.                 s--;
  144.             }
  145.         }
  146.         else {
  147.             windputc(c);
  148.             *s++ = c;
  149.         }
  150.         windrefresh();
  151.     }
  152.     *s = '\0';
  153. }
  154.  
  155. windstr(s)
  156. char *s;
  157. {
  158.     int c;
  159.  
  160.     while ( (c=(*s++)) != '\0' )
  161.         windputc(c);
  162. }
  163.  
  164. windputc(c)
  165. int c;
  166. {
  167.     putchar(c);
  168. }
  169.  
  170. windrefresh()
  171. {
  172. }
  173.  
  174. beep()
  175. {
  176.     putchar('\007');
  177. }
  178.  
  179. windhigh()
  180. {
  181. }
  182.  
  183. windnorm()
  184. {
  185. }
  186.  
  187. /****************
  188.  * openls(), nextls(), and closels() are used to scan the current directory.
  189.  ***************/
  190.  
  191. int first = 1;
  192. openls()
  193. {
  194.     first = 1;
  195. }
  196. char *
  197. nextls()
  198. {
  199.     static struct ffblk ffblk;
  200.     int n;
  201.  
  202.     if ( first ) {
  203.         n = findfirst("*.*",&ffblk,0);
  204.         first = 0;
  205.     }
  206.     else
  207.         n = findnext(&ffblk);
  208.  
  209.     if ( n == 0 )
  210.         return(ffblk.ff_name);
  211.     else
  212.         return((char *)NULL);
  213. }
  214. closels()
  215. {
  216. }
  217.  
  218. #ifdef OLDSTUFF
  219. /*
  220.  * The following MPU code has been provided by Steve Frysinger (moss!spf).
  221.  */
  222.  
  223. #define    STATUS_PORT    0x0331
  224. #define    COMMAND_PORT    0x0331
  225. #define    DATA_PORT    0x0330
  226. #define    DATA_READY_MASK    0x40
  227. #define    DATA_AVAIL_MASK    0x80
  228.  
  229. int send_command_4001(val)    /* Patterned after Voyetra's reset_4001() */
  230. unsigned val;
  231. {
  232.     unsigned x = 0;
  233.     int flag;
  234.     int ack_count,time_count;
  235.     int retval=1; /* Assume success */
  236.     inportb(DATA_PORT);
  237.     for (time_count=5000,flag=1;time_count&&flag;time_count--)
  238.     {
  239.         if (!(inportb(STATUS_PORT)&DATA_READY_MASK)) flag=0;
  240.     }
  241.     if (flag)
  242.     {
  243.         fprintf(stderr,"Command timeout waiting for port!\n");
  244.         retval = -1;
  245.     }
  246.     else
  247.     {
  248.         outportb(COMMAND_PORT,val);
  249.         for (time_count=10000,ack_count=5,flag=0;!flag;)
  250.         {
  251.             if ((inportb(STATUS_PORT)&DATA_AVAIL_MASK))
  252.             {
  253.                 time_count--;
  254.                 if (!time_count)
  255.                 {
  256.                     flag++;
  257.                     fprintf(stderr,"Command timeout waiting for ACK.\n");
  258.                     retval = -1;
  259.                 }
  260.             }
  261.             else
  262.             {
  263.                 x = (unsigned)inportb(DATA_PORT);
  264.                 if (x == 0xfe)
  265.                 {
  266.                     flag++;
  267.                     fprintf(stderr,"Got command acknowledgement\n");
  268.                 }
  269.                 else
  270.                 {
  271.                     ack_count--;
  272.                     if (!ack_count)
  273.                     {
  274.                         printf("Too many data bytes without ACK\n");
  275.                         retval = -1;
  276.                     }
  277.                 }
  278.             }
  279.         }
  280.     }
  281.     return(retval);
  282. } /* send_command_4001 */
  283. #endif
  284.  
  285. /*
  286.  * Acknowledgements to John Helton for additions to support ATT PC6300 w/
  287.  * MPU401 and OP4000 MIDI Interface Controllers.
  288.  * PC6300 support uses Borland TurboC 'C' compiler, large model
  289.  *
  290.  */
  291. #define QUIT 1
  292. #define NOQUIT 0
  293.  
  294. void interrupt (*oldint0)();
  295. void interrupt (*oldint2)();
  296. void interrupt (*oldint1b)();
  297. void interrupt (*oldint23)();
  298. void interrupt (*oldint24)();
  299. void interrupt ctr_brk_handler();
  300. void interrupt fatal_err_hndlr();
  301.  
  302. void interrupt far tick_isr();
  303. void interrupt far midi_isr();
  304. extern unsigned long hzcount;
  305. extern char midi_buffer[];
  306. extern int wrt_index, rd_index;
  307.  
  308. extern unsigned _stklen;    /* Turbo C specific */ 
  309.  
  310. int Nextpcchar = EOF;
  311. int Fakemidi = 0;
  312. int (*Intfunc)() = NULL;
  313.  
  314. hello()
  315. {
  316.     _stklen = 50000;
  317.     hzcount = 0L;            /* init timer & buffer globals */
  318.     wrt_index = rd_index = 0;
  319.     if (!setup_MIC())            /* Set up the Midi Interface Ctrl */
  320.     {
  321.     if ( fisatty(stdout) )
  322.         printf("Can't initialize midi interface\n");
  323.     Fakemidi = 1;
  324.     reset_ints(NOQUIT);        /* restore interrupts to a suitable
  325.                        condition to keep running without
  326.                        the Midi Interface (for testing) */
  327.     return;
  328.     }
  329.     send_msg(UART, COMMAND_MSG);    /* run the MIC in dumb mode */
  330.     return;
  331. }
  332.  
  333. rtend()
  334. {
  335.     reset_MIC();
  336. }
  337.  
  338. bye()
  339. {
  340.     system_exit();
  341. }
  342.  
  343. flushconsole()
  344. { return; }
  345.  
  346. getconsole()
  347. {
  348.     int c;
  349.  
  350.     if ( Nextpcchar != EOF ) {
  351.         c = Nextpcchar;
  352.         Nextpcchar = EOF;
  353.     }
  354.     else {
  355.         c = getch();
  356.     }
  357.     return(c);
  358. }
  359.  
  360. putconsole(c)
  361. {
  362.     putch(c);
  363. }
  364.  
  365. /* getmidi reads data out of the circular midi buffer */
  366. getmidi()
  367. {
  368.     static char mbuff[1];
  369.     unsigned char *p;
  370.  
  371.     while ( wrt_index == rd_index)
  372.         ;
  373.     rd_index++;
  374.     if (rd_index > 511) rd_index = 0;
  375.     mbuff[0] = midi_buffer[rd_index];
  376.     return (mbuff[0] & 0xff);
  377. }
  378.  
  379. sendmidi(val)
  380. int val;
  381. {
  382.     unsigned char p[1];
  383.     p[0] = val;
  384.     putnmidi(1,p);
  385. }
  386.  
  387. putnmidi(n,p)
  388. char *p;
  389. {
  390.     while ( n-- > 0 ) {
  391.         int c = (*p++) & 0xff;
  392.         if ( Fakemidi )
  393.         printf("putmidi(d=%d x=%x o=%o)\n",c,c,c);
  394.         else
  395.         write_data_MPU(c);
  396.     }
  397. }
  398.  
  399. resetclock()
  400. {
  401.     hzcount = 0L;
  402. }
  403.  
  404. long
  405. milliclock()
  406. {
  407.     return (hzcount*5L);
  408. }
  409.  
  410. /* filetime - Return the modification time of a file in seconds. */
  411. long
  412. filetime(fn)
  413. char *fn;    /* file name */
  414. {
  415.     struct stat s;
  416.  
  417.     if ( stat(fn,&s) == -1 )
  418.         return(-1);
  419.     return(s.st_mtime);
  420. }
  421.  
  422. /* currtime - Return current time in seconds (consistent with filetime()) */
  423. long
  424. currtime()
  425. {
  426.     long time();
  427.     return ( time((long *)0) );
  428. }
  429.  
  430. fisatty(f)
  431. FILE* f;
  432. {
  433.     return(isatty(fileno(f)));
  434. }
  435.  
  436. /*
  437.  * send_msg(COM, TYPE, PTR, LENGTH)
  438.  * will send command to Midi Interface Controller (MIC) Command port, 
  439.  * then either return, wait for data or send data
  440.  */
  441.  
  442. send_msg(com, type, ptr, length)
  443. int com, type, length;
  444. char *ptr;
  445. {
  446.     int acked;
  447.     int x;
  448.  
  449.     while ( NOT_READY_FOR_DATA_MIC());
  450.     disable_ints();
  451.     COMMAND_OUT_MIC((char) com);    /* send the command to the MIC */
  452.     for(acked=0; !acked; ) {        /* wait until our command is acked */
  453.         x = read_MPU();            /* get a byte back from the MIC */
  454.         if (x == ACK) acked++;        /* done if ACK received */
  455.         else write_rcv_buff(x);        /* deal with this input stream first */
  456.     }
  457.     if (type == WRITE_MSG)        /* if write request... */
  458.         for (; length; ptr++, length--) write_data_MPU(*ptr);
  459.                     /* write all the bytes to the MIC */
  460.     enable_ints();            /* ints restored to where they were
  461.                        before we shut them off */
  462. }
  463.  
  464.  
  465. /* WRITE_RCV_BUFF(INPUT)
  466.  * part of the command handshake sequence.  Input read from the
  467.  * midi data port is saved in wraparound FIFO
  468. */
  469.  
  470. write_rcv_buff(val)
  471. int val;
  472. {
  473.     wrt_index++;
  474.     if (wrt_index > 511) wrt_index = 0;
  475.     midi_buffer[wrt_index] = (char) val;
  476. }
  477.  
  478. /*
  479.  * SETUP_MIC()
  480.  * resets MIC, sets up int vectors and enables int system
  481.  * Returns - true if MIC set ok
  482.  */
  483.  
  484. static setup_MIC()
  485. {
  486.     int retval;
  487.  
  488.     set_ints();            /* set the new interrupt vectors */
  489.     init_enable_MPU();         /* turn on interrupt system for first time */
  490.     retval = reset_MIC();        /* try to reset MIC */
  491.     if (!retval) retval = reset_MIC(); /* if no good, try again */
  492.     init_enable_TIMER();    /* turn on timer interrupt if reset ok*/
  493.     return(retval);
  494. }
  495.  
  496. /*
  497.  * RESET_MIC()
  498.  * attempts to do a low level software reset on the MIC
  499.  * returns - true if success
  500.  */
  501.  
  502. reset_MIC()
  503. {
  504.     unsigned x = 0;
  505.     int flag;
  506.     int ack_count, time_count;
  507.     int retval=1;        /* assume success */
  508.     
  509.     disable_ints();        /* disable interrupts */
  510.     READ_DATA_MIC();        /* Clear out any data in receiver */
  511.     /* Here we will loop until ready for data, or we give up     */
  512.     for (time_count=5000, flag=1; time_count && flag; time_count--) {
  513.     /* if MIC ready for data, we can quit loop */
  514.         if (!(NOT_READY_FOR_DATA_MIC())) flag=0;
  515.     }
  516.     /* if timed out before we got ready for data, return flag couldn't reset */
  517.     if (flag){    
  518.     retval = 0;
  519.     }
  520.     else {
  521.         COMMAND_OUT_MIC(RESET); /* Send the reset command */
  522.     /* loop here till time out, or ack recvd */
  523.         for (time_count=10000, ack_count=5, flag=0; !flag;) {
  524.         if ((NOT_DATA_AVAILABLE_MIC())) { /* if no data from MIC */
  525.             time_count--;        /* count one more wait */
  526.             if (!time_count) {
  527. BAD_RESET:
  528.             flag++;        /* if time out, note it */
  529.             retval=0;        /* and note failure */
  530.         }
  531.         }
  532.         else {        /* If there is data coming back form MIC */
  533.             x = (unsigned) READ_DATA_MIC(); /* ...read it */
  534.             if (x == ACK) { /* If data is the ACK message */
  535.             flag++;        /* note we are done, and no failure */
  536.         }
  537.             else {        /* if data back from MIC wasn't ack */
  538.             ack_count--;/* note that we got something that isn't ack */
  539.             if (!ack_count) goto BAD_RESET;
  540.                 /* If we get too many data bytes back from
  541.                    MIC with no ack, give up */
  542.         }
  543.         }
  544.     }
  545.     }
  546.     enable_ints();             /* turn ints back on */
  547.     return(retval);
  548. }
  549.  
  550. /*
  551.  * SYSTEM_EXIT()
  552.  * called to leave program.  resets ints and exits
  553.  */
  554. system_exit()
  555. {
  556.     reset_MIC();
  557.     disable_ints();
  558.     reset_ints(QUIT);    /* put all the int vectors back where they were */
  559.     reset_TIMER();
  560.     enable_ints();
  561.     windexit(0);
  562.     exit();
  563. }
  564.  
  565. /*
  566.  * hi level interrupt routines
  567.  */
  568.  
  569. void interrupt
  570. ctr_brk_handler()
  571. {
  572.     if ( Intfunc != NULL )
  573.     (*Intfunc)();
  574.     printf("interrupts reset; BYE!\n");
  575.     system_exit();
  576. }
  577.  
  578. void interrupt
  579. fatal_err_hndlr()
  580. {
  581.     fatal_dos_handler();
  582. }
  583.  
  584. fatal_dos_handler()    /* called by fatal error handler ISR */
  585. {
  586.     printf("got fatal error; BYE!\n");
  587.     system_exit();
  588. }
  589.  
  590. set_ints()
  591. {
  592.     oldint0 = getvect(0x08);    /* timer interrupt on irq0 */
  593.     setvect(0x08, tick_isr);
  594.     oldint2 = getvect(0x0a);    /* midi interrupt on irq2 */
  595.     setvect(0x0a, midi_isr);
  596.     oldint1b = getvect(0x1b);    /* the rest of these are dos & bios ints */
  597.     setvect(0x1b, ctr_brk_handler);
  598.     oldint23 = getvect(0x23);
  599.     setvect(0x23, ctr_brk_handler);
  600.     oldint24 = getvect(0x24);
  601.     setvect(0x24, fatal_err_hndlr);
  602. }
  603.  
  604. reset_ints(reset_type)
  605. {
  606.     if (reset_type == QUIT) {
  607.         setvect(0x08, oldint0);
  608.         setvect(0x1b, oldint1b);
  609.         setvect(0x23, oldint23);
  610.         setvect(0x24, oldint24);
  611.     }
  612.     setvect(0x0a, oldint2);    /* only need to reset one hardware interrupt
  613.                    if we're not going to quit */
  614. }
  615.  
  616. signal(type,func)
  617. int (*func)();
  618. {
  619.     if ( type == SIGINT ) {
  620.         if ( func == SIG_IGN )
  621.             Intfunc = NULL;
  622.         else
  623.             Intfunc = func;
  624.     }
  625. }
  626.