home *** CD-ROM | disk | FTP | other *** search
/ Phoenix Heaven Sunny 2 / APPARE2.BIN / oh_towns / dic / src / cdio.c < prev    next >
Text File  |  1995-06-20  |  11KB  |  499 lines

  1. /********************************************
  2.  
  3.     CD Access Func
  4.  
  5. *********************************************/
  6. #include    "defs.h"
  7.  
  8. #ifdef    MSC
  9. #  define    HAVE_STRERROR
  10. #endif
  11.  
  12. #ifdef    HAVE_STRERROR
  13. #include    <errno.h>
  14. #endif
  15.  
  16.     ulong    vtoc_start_block = 0L;
  17.     ulong    vtoc_end_block = 0L;
  18.     int    vtoc_file_max = 0;
  19.  
  20.     char    file_name[48];
  21.     ulong    file_start_block = 0L;
  22.     ulong    file_end_block = 0xFFFFFFFFL;
  23.  
  24.     uchar    dic_buf[BLOCK_SIZE];
  25.  
  26. #ifdef    MSCDEX
  27. static    int    mscdex_unit_max = 0;
  28. #endif
  29.  
  30. /*    compess dic    */
  31.  
  32.     int    comp_dic_mode = FALSE;
  33. static    ulong    comp_tab[256];
  34. static    ulong    comp_seek = 0xFFFFFFFFL;
  35.  
  36. static    int    decode(char *buf, int len, FILE *fp)
  37. {
  38.     int     i, n, c, d, bit;
  39.  
  40.     n = 0;
  41.     while ( n < len && (bit = getc(fp)) != EOF ) {
  42.     for ( i = 1 ; i < 0x100 && n < len ; i <<= 1 ) {
  43.         if ( (bit & i) == 0 ) {
  44.         if ( (c = getc(fp)) == EOF || (d = getc(fp)) == EOF )
  45.             break;
  46.         d |= (c << 8);
  47.         c = ((d & 0x1F) + 3);
  48.         d >>= 5; d &= 0x7FF;
  49.         while ( c-- > 0 && n < len )
  50.             buf[n++] = buf[d++];
  51.         } else {
  52.         if ( (c = getc(fp)) == EOF )
  53.             break;
  54.         buf[n++] = c;
  55.         }
  56.     }
  57.     }
  58.  
  59.     return n;
  60. }
  61. #ifdef    FMRBIOS
  62. int    CD_mode_set(int mode)
  63. {
  64.     union REGS     regs;
  65.  
  66.     regs.h.ah = 0x00;
  67.     regs.h.al = dev_unit_no;
  68.     regs.h.ch = 0x00;
  69.     regs.h.dl = mode;
  70.     int86(0x93, ®s, ®s);
  71.     return (regs.h.ah);
  72. }
  73. #endif    /* FMRBIOS */
  74.  
  75. #ifdef    MSCDEX
  76. int    CD_mscdex_init()
  77. {
  78. /*
  79. ** Get CD-ROM Drive Number
  80. **  INT 2Fh FUNCTION 00h
  81. **  return: cx = Drive Number (A=0, B=1...)
  82. **          bx = Drive Count
  83. */
  84.     union REGS inregs, outregs;
  85.     static char tmp[8];
  86.  
  87.     inregs.h.ah = 0x15;            /* MSCDEX Function Call */
  88.     inregs.h.al = 0x00;            /* MSCDEX Sub-Function */
  89.     inregs.x.bx = 0;
  90.     int86(0x2f, &inregs, &outregs);    /* MSCDEX Call */
  91.     if (outregs.x.bx == 0)
  92.     return ERR;            /* Not Install MSCDEX.EXE */
  93.  
  94.     mscdex_unit_max = outregs.x.bx;    /* Return CD-ROM Drive Count  */
  95.     dev_unit_no     = outregs.x.cx;    /* Return CD-ROM Drive Number */
  96.  
  97.     sprintf(tmp, "%x", dev_unit_no);
  98.     dev_unit_name   = tmp;
  99.  
  100.     return 0;
  101. }
  102. #endif    /* MSCDEX */
  103.  
  104. static    int    REAL_read_sect(ulong sect, int count, char *buff)
  105. {
  106. #ifdef    FMRBIOS
  107.     union REGS     regs;
  108.     struct SREGS segs;
  109.     char far     *p;
  110.  
  111.     if ( now_dic_mode == DIC_FILE_MODE )
  112.     goto FILEIO;
  113.  
  114.     p = (char far *)buff;
  115.     regs.h.ah = 0x05;
  116.     regs.h.al = dev_unit_no;
  117.     regs.h.ch = 0x00;
  118.     regs.h.cl = (uchar)(sect >> 16);
  119.     regs.x.dx = (ushort)sect;
  120.     regs.x.bx = count;
  121.     segs.ds   = FP_SEG(p);
  122.     regs.x.di = FP_OFF(p);
  123.     int86x(0x93, ®s, ®s, &segs);
  124.     return (regs.h.ah);
  125.  
  126. #else
  127. #ifdef    MSCDEX
  128.  
  129.     union REGS regs;
  130.     struct SREGS segs;
  131.     char far     *p;
  132.  
  133.     if ( now_dic_mode == DIC_FILE_MODE )
  134.     goto FILEIO;
  135.  
  136.     p = (char far *)buff;
  137.     regs.h.ah = 0x15;            /* MSCDEX Function Call */
  138.     regs.h.al = 0x08;            /* MSCDEX Sub-Function */
  139.     regs.x.cx = dev_unit_no;
  140.     regs.x.si = (uchar)(sect >> 16);
  141.     regs.x.di = (ushort)sect;
  142.     regs.x.dx = count;
  143.     regs.x.bx = FP_OFF(p);
  144.     segs.es = FP_SEG(p);
  145.     int86x(0x2f, ®s, ®s, &segs);    /* MSCDEX Call */
  146.     if ((regs.x.ax & 0x00ff) != 0)
  147.     return ERR;
  148.     return 0;
  149.  
  150. #endif    /* MSCDEX */
  151. #endif    /* FMRBIOS */
  152.  
  153. FILEIO:
  154.  
  155.     if ( comp_dic_mode ) {
  156.     if ( comp_seek != (sect & 0xFFFFFF00L) ) {
  157.         comp_seek = (sect & 0xFFFFFF00L);
  158.         if ( fseek(dev_fp, comp_seek * sizeof(long) + 4L, 0) ||
  159.          fread(comp_tab, sizeof(long), 256, dev_fp) != 256 )
  160.         goto ERROR;
  161.     }
  162.  
  163.     if ( comp_tab[sect & 0xFF] == 0L ||
  164.          fseek(dev_fp, comp_tab[sect & 0xFF], 0) )
  165.         goto ERROR;
  166.  
  167.     while ( count-- > 0 ) {
  168.         if ( decode(buff, BLOCK_SIZE, dev_fp) != BLOCK_SIZE )
  169.         goto ERROR;
  170.         buff += BLOCK_SIZE;
  171.     }
  172.  
  173.     } else if ( fseek(dev_fp, sect * BLOCK_SIZE, 0) ||
  174.          fread(buff, BLOCK_SIZE, count, dev_fp) != count )
  175.     goto ERROR;
  176.  
  177.     return FALSE;
  178.  
  179. ERROR:
  180.  
  181. #ifdef    HAVE_STRERROR
  182.     fprintf(stderr, "dic: %s\n", strerror(errno));
  183. #else
  184.     fprintf(stderr, "dic: Dictionary Read Error\n");
  185. #endif
  186.     return ERR;
  187. }
  188. /********************************************
  189.  
  190.     Disk Cache Func
  191.  
  192. *********************************************/
  193. #ifdef    UNIX
  194. #  define    CACHE_MAX    32
  195. #else
  196. #  define    CACHE_MAX    16
  197. #endif
  198.  
  199. typedef    struct _CAHPTR {
  200.     struct _CAHPTR    *next;
  201.     int        id;
  202.     ulong        block;
  203.     char FAR    *buff;
  204. } CAHPTR;
  205.  
  206. static    CAHPTR    *cache_top = NULL;
  207. static    CAHPTR    cache_tab[CACHE_MAX];
  208.  
  209. #ifdef    MSDOS
  210. static    char far *FAR_MEMCPY(char far *buf, register char *s, int len)
  211. {
  212.     register char far *p = buf;
  213.  
  214.     while ( len-- > 0 )
  215.     *(p++) = *(s++);
  216.     return buf;
  217. }
  218. static    char *NEAR_MEMCPY(char *buf, register char far *s, int len)
  219. {
  220.     register char *p = buf;
  221.  
  222.     while ( len-- > 0 )
  223.     *(p++) = *(s++);
  224.     return buf;
  225. }
  226. #endif    /* MSDOS */
  227.  
  228. int    Cache_init()
  229. {
  230.     int     n;
  231.  
  232.     now_dev_id = (-1);
  233.     comp_seek = 0xFFFFFFFFL;
  234.     cache_top = NULL;
  235.     for ( n = 0 ; n < CACHE_MAX ; n++ ) {
  236.     if ( (cache_tab[n].buff = (char FAR *)MALLOC(BLOCK_SIZE)) == NULL )
  237.         break;
  238.     cache_tab[n].next = cache_top;
  239.     cache_top = &(cache_tab[n]);
  240.     cache_tab[n].id    = (-1);
  241.     cache_tab[n].block = 0xFFFFFFFFL;
  242.     }
  243.     return FALSE;
  244. }
  245. int    Cache_flush(int id)
  246. {
  247.     if ( now_dev_id == id )
  248.     return TRUE;
  249.  
  250.     now_dev_id = id;
  251.     comp_seek = 0xFFFFFFFFL;
  252.  
  253.     return FALSE;
  254. }
  255. int    CD_read_sect(ulong block, int count, char *buff)
  256. {
  257.     register CAHPTR *bp;
  258.     CAHPTR *tp;
  259.  
  260.     while ( count-- > 0 ) {
  261.     tp = bp = cache_top;
  262.     for ( ; ; ) {
  263.         if ( bp->block == block && bp->id == now_dev_id ) {
  264.         if ( tp != bp ) {
  265.             tp->next = bp->next;
  266.             bp->next = cache_top;
  267.             cache_top = bp;
  268.         }
  269.         NEAR_MEMCPY(buff, bp->buff, BLOCK_SIZE);
  270.         break;
  271.         }
  272.         if ( bp->next == NULL ) {
  273.         if ( REAL_read_sect(block, 1, buff) )
  274.             return ERR;
  275.         tp->next = bp->next;
  276.         bp->next = cache_top;
  277.         cache_top = bp;
  278.         bp->id    = now_dev_id;
  279.         bp->block = block;
  280.         FAR_MEMCPY(bp->buff, buff, BLOCK_SIZE);
  281.         break;
  282.         }
  283.         tp = bp;
  284.         bp = bp->next;
  285.     }
  286.  
  287.     block++;
  288.     buff += BLOCK_SIZE;
  289.     }
  290.     return FALSE;
  291. }
  292. /********************************************
  293.  
  294.     VTOC File Access Func
  295.  
  296. *********************************************/
  297. int    CD_read_time(int min, int sec, int blk, int count, char *buff)
  298. {
  299.     ulong sect;
  300.  
  301.     sect = min * (60L * 75L);
  302.     sect += (sec * 75L);
  303.     sect += blk;
  304.     sect -= (2 * 75L);        /* 0 is 0:2:0 */
  305.  
  306.     return CD_read_sect(sect, count, buff);
  307. }
  308. static    char    *CD_form_name(uchar *ptn, int len)
  309. {
  310.     static char buf[128];
  311.     static char ext[] = { 
  312.     '\0', '?', '?', '?', '?', '?', '?', '?',
  313.     '?', '?', '?', '\\', '?', '?', '?', '?'
  314.     };
  315.     int     n, ch;
  316.  
  317.     for ( n = 0 ; n < len && n < 127 ; n++ ) {
  318.     switch(ptn[n] & 0xF0) {
  319.     case 0x40:
  320.         ch = ext[ptn[n] & 0x0F];
  321.         break;
  322.     case 0xC0:
  323.         ch = '@' + (ptn[n] & 0x0F);
  324.         break;
  325.     case 0xD0:
  326.         ch = 'I' + (ptn[n] & 0x0F);
  327.         break;
  328.     case 0xE0:
  329.         ch = 'Q' + (ptn[n] & 0x0F);
  330.         break;
  331.     case 0xF0:
  332.         ch = '0' + (ptn[n] & 0x0F);
  333.         break;
  334.     }
  335.     buf[n] = ch;
  336.     if ( ch == 0 )
  337.         break;
  338.     }
  339.  
  340.     buf[n] = '\0';
  341.     return buf;
  342. }
  343. static    ulong    CD_time_to_sect(int min, int sec, int blk)
  344. {
  345.     return ((ulong)min * 60L * 75L + sec * 75L + blk - (2 * 75L));
  346. }
  347. int    CD_file_init()
  348. {
  349.     int    min, sec, blk;
  350.  
  351. #ifdef    FMRBIOS
  352.     if ( towns_flg && CD_mode_set(0x04) )
  353.     return ERR;
  354. #endif
  355.  
  356.     if ( CD_read_time(0, 3, 38, 1, dic_buf) )
  357.         return ERR;
  358.  
  359.     if ( strcmp(CD_form_name(dic_buf, 3), "VTC") != 0 )
  360.         return ERR;
  361.  
  362.     min = (dic_buf[180] & 0x0F) * 10 + (dic_buf[181] & 0x0F);
  363.     sec = (dic_buf[182] & 0x0F) * 10 + (dic_buf[183] & 0x0F);
  364.     blk = (dic_buf[184] & 0x0F) * 10 + (dic_buf[185] & 0x0F);
  365.     vtoc_start_block = CD_time_to_sect(min, sec, blk);
  366.  
  367.     min = (dic_buf[188] & 0x0F) * 10 + (dic_buf[189] & 0x0F);
  368.     sec = (dic_buf[190] & 0x0F) * 10 + (dic_buf[191] & 0x0F);
  369.     blk = (dic_buf[192] & 0x0F) * 10 + (dic_buf[193] & 0x0F);
  370.     vtoc_end_block = CD_time_to_sect(min, sec, blk);
  371.  
  372.     vtoc_file_max = vtoc_end_block - vtoc_start_block + 1;
  373.  
  374.     return FALSE;
  375. }
  376. int    CD_file_open(int no)
  377. {
  378.     int    min, sec, blk;
  379.     ulong  sect;
  380.  
  381.     sect = vtoc_start_block + no - 1;
  382.  
  383.     if ( sect < vtoc_start_block || sect > vtoc_end_block )
  384.     return ERR;
  385.  
  386.     if ( CD_read_sect(sect, 1, dic_buf) )
  387.         return ERR;
  388.  
  389.     if ( strcmp(CD_form_name(dic_buf, 3), "HDR") != 0 )
  390.         return ERR;
  391.  
  392.     strcpy(file_name, CD_form_name(dic_buf + 4, 47));
  393.  
  394.     min = (dic_buf[180] & 0x0F) * 10 + (dic_buf[181] & 0x0F);
  395.     sec = (dic_buf[182] & 0x0F) * 10 + (dic_buf[183] & 0x0F);
  396.     blk = (dic_buf[184] & 0x0F) * 10 + (dic_buf[185] & 0x0F);
  397.     file_start_block = CD_time_to_sect(min, sec, blk);
  398.  
  399.     min = (dic_buf[188] & 0x0F) * 10 + (dic_buf[189] & 0x0F);
  400.     sec = (dic_buf[190] & 0x0F) * 10 + (dic_buf[191] & 0x0F);
  401.     blk = (dic_buf[192] & 0x0F) * 10 + (dic_buf[193] & 0x0F);
  402.     file_end_block = CD_time_to_sect(min, sec, blk);
  403.  
  404.     return FALSE;
  405. }
  406. /********************************************
  407.  
  408.     CD Low Block I/O Func
  409.  
  410. *********************************************/
  411.  
  412. static    ulong    io_block;
  413. static    ushort    io_offset;
  414.  
  415. int    IO_block_read(ulong block)
  416. {
  417.     block = file_start_block + block - 1;
  418.  
  419.     if ( block < file_start_block || block > file_end_block )
  420.     return ERR;
  421.  
  422.     return CD_read_sect(block, 1, dic_buf);
  423. }
  424. int    IO_seek(ulong block, ushort offset)
  425. {
  426.     io_block  = block;
  427.     io_offset = offset;
  428.     return IO_block_read(io_block++);
  429. }
  430. int    IO_getc()
  431. {
  432.     if ( io_offset >= BLOCK_SIZE ) {
  433.     if ( IO_block_read(io_block++) )
  434.         return EOF;
  435.     io_offset = 0;
  436.     }
  437.     return (dic_buf[io_offset++] & 0xFF);
  438. }
  439. int    IO_read(char *buf, int size)
  440. {
  441.     int     ch, len;
  442.  
  443.     for ( len = 0 ; len < size ; ) {
  444.     if ( (ch = IO_getc()) == EOF )
  445.         break;
  446.     buf[len++] = ch;
  447.     }
  448.     return len;
  449. }
  450. /********************************************
  451.  
  452.     Device/File Name ID Make/Get
  453.  
  454. *********************************************/
  455. typedef    struct _IP {
  456.     struct _IP    *next;
  457.     int        id;
  458.     char        name[1];
  459. } NAMEID;
  460.  
  461. static    int    id_counter = 0;
  462. static    NAMEID    *name_id_ptr = NULL;
  463.  
  464. char    *id_to_name(int id)
  465. {
  466.     NAMEID *np;
  467.  
  468.     np = name_id_ptr;
  469.     while ( np != NULL ) {
  470.     if ( np->id == id )
  471.         return np->name;
  472.     np = np->next;
  473.     }
  474.     return NULL;
  475. }
  476. int    name_to_id(char *name)
  477. {
  478.     NAMEID *np;
  479.  
  480.     np = name_id_ptr;
  481.     while ( np != NULL ) {
  482.     if ( strcmp(np->name, name) == 0 )
  483.         return np->id;
  484.     np = np->next;
  485.     }
  486.  
  487.     if ( (np = (NAMEID *)malloc(sizeof(NAMEID) + strlen(name))) == NULL ) {
  488.     fprintf(stderr, "dic: Name ID struct memory alloc error\n");
  489.     exit(1);
  490.     }
  491.  
  492.     np->next = name_id_ptr;
  493.     name_id_ptr = np;
  494.     np->id = id_counter++;
  495.     strcpy(np->name, name);
  496.  
  497.     return np->id;
  498. }
  499.