home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Phoenix Heaven Sunny 2
/
APPARE2.BIN
/
oh_towns
/
dic
/
src
/
cdio.c
< prev
next >
Wrap
Text File
|
1995-06-20
|
11KB
|
499 lines
/********************************************
CD Access Func
*********************************************/
#include "defs.h"
#ifdef MSC
# define HAVE_STRERROR
#endif
#ifdef HAVE_STRERROR
#include <errno.h>
#endif
ulong vtoc_start_block = 0L;
ulong vtoc_end_block = 0L;
int vtoc_file_max = 0;
char file_name[48];
ulong file_start_block = 0L;
ulong file_end_block = 0xFFFFFFFFL;
uchar dic_buf[BLOCK_SIZE];
#ifdef MSCDEX
static int mscdex_unit_max = 0;
#endif
/* compess dic */
int comp_dic_mode = FALSE;
static ulong comp_tab[256];
static ulong comp_seek = 0xFFFFFFFFL;
static int decode(char *buf, int len, FILE *fp)
{
int i, n, c, d, bit;
n = 0;
while ( n < len && (bit = getc(fp)) != EOF ) {
for ( i = 1 ; i < 0x100 && n < len ; i <<= 1 ) {
if ( (bit & i) == 0 ) {
if ( (c = getc(fp)) == EOF || (d = getc(fp)) == EOF )
break;
d |= (c << 8);
c = ((d & 0x1F) + 3);
d >>= 5; d &= 0x7FF;
while ( c-- > 0 && n < len )
buf[n++] = buf[d++];
} else {
if ( (c = getc(fp)) == EOF )
break;
buf[n++] = c;
}
}
}
return n;
}
#ifdef FMRBIOS
int CD_mode_set(int mode)
{
union REGS regs;
regs.h.ah = 0x00;
regs.h.al = dev_unit_no;
regs.h.ch = 0x00;
regs.h.dl = mode;
int86(0x93, ®s, ®s);
return (regs.h.ah);
}
#endif /* FMRBIOS */
#ifdef MSCDEX
int CD_mscdex_init()
{
/*
** Get CD-ROM Drive Number
** INT 2Fh FUNCTION 00h
** return: cx = Drive Number (A=0, B=1...)
** bx = Drive Count
*/
union REGS inregs, outregs;
static char tmp[8];
inregs.h.ah = 0x15; /* MSCDEX Function Call */
inregs.h.al = 0x00; /* MSCDEX Sub-Function */
inregs.x.bx = 0;
int86(0x2f, &inregs, &outregs); /* MSCDEX Call */
if (outregs.x.bx == 0)
return ERR; /* Not Install MSCDEX.EXE */
mscdex_unit_max = outregs.x.bx; /* Return CD-ROM Drive Count */
dev_unit_no = outregs.x.cx; /* Return CD-ROM Drive Number */
sprintf(tmp, "%x", dev_unit_no);
dev_unit_name = tmp;
return 0;
}
#endif /* MSCDEX */
static int REAL_read_sect(ulong sect, int count, char *buff)
{
#ifdef FMRBIOS
union REGS regs;
struct SREGS segs;
char far *p;
if ( now_dic_mode == DIC_FILE_MODE )
goto FILEIO;
p = (char far *)buff;
regs.h.ah = 0x05;
regs.h.al = dev_unit_no;
regs.h.ch = 0x00;
regs.h.cl = (uchar)(sect >> 16);
regs.x.dx = (ushort)sect;
regs.x.bx = count;
segs.ds = FP_SEG(p);
regs.x.di = FP_OFF(p);
int86x(0x93, ®s, ®s, &segs);
return (regs.h.ah);
#else
#ifdef MSCDEX
union REGS regs;
struct SREGS segs;
char far *p;
if ( now_dic_mode == DIC_FILE_MODE )
goto FILEIO;
p = (char far *)buff;
regs.h.ah = 0x15; /* MSCDEX Function Call */
regs.h.al = 0x08; /* MSCDEX Sub-Function */
regs.x.cx = dev_unit_no;
regs.x.si = (uchar)(sect >> 16);
regs.x.di = (ushort)sect;
regs.x.dx = count;
regs.x.bx = FP_OFF(p);
segs.es = FP_SEG(p);
int86x(0x2f, ®s, ®s, &segs); /* MSCDEX Call */
if ((regs.x.ax & 0x00ff) != 0)
return ERR;
return 0;
#endif /* MSCDEX */
#endif /* FMRBIOS */
FILEIO:
if ( comp_dic_mode ) {
if ( comp_seek != (sect & 0xFFFFFF00L) ) {
comp_seek = (sect & 0xFFFFFF00L);
if ( fseek(dev_fp, comp_seek * sizeof(long) + 4L, 0) ||
fread(comp_tab, sizeof(long), 256, dev_fp) != 256 )
goto ERROR;
}
if ( comp_tab[sect & 0xFF] == 0L ||
fseek(dev_fp, comp_tab[sect & 0xFF], 0) )
goto ERROR;
while ( count-- > 0 ) {
if ( decode(buff, BLOCK_SIZE, dev_fp) != BLOCK_SIZE )
goto ERROR;
buff += BLOCK_SIZE;
}
} else if ( fseek(dev_fp, sect * BLOCK_SIZE, 0) ||
fread(buff, BLOCK_SIZE, count, dev_fp) != count )
goto ERROR;
return FALSE;
ERROR:
#ifdef HAVE_STRERROR
fprintf(stderr, "dic: %s\n", strerror(errno));
#else
fprintf(stderr, "dic: Dictionary Read Error\n");
#endif
return ERR;
}
/********************************************
Disk Cache Func
*********************************************/
#ifdef UNIX
# define CACHE_MAX 32
#else
# define CACHE_MAX 16
#endif
typedef struct _CAHPTR {
struct _CAHPTR *next;
int id;
ulong block;
char FAR *buff;
} CAHPTR;
static CAHPTR *cache_top = NULL;
static CAHPTR cache_tab[CACHE_MAX];
#ifdef MSDOS
static char far *FAR_MEMCPY(char far *buf, register char *s, int len)
{
register char far *p = buf;
while ( len-- > 0 )
*(p++) = *(s++);
return buf;
}
static char *NEAR_MEMCPY(char *buf, register char far *s, int len)
{
register char *p = buf;
while ( len-- > 0 )
*(p++) = *(s++);
return buf;
}
#endif /* MSDOS */
int Cache_init()
{
int n;
now_dev_id = (-1);
comp_seek = 0xFFFFFFFFL;
cache_top = NULL;
for ( n = 0 ; n < CACHE_MAX ; n++ ) {
if ( (cache_tab[n].buff = (char FAR *)MALLOC(BLOCK_SIZE)) == NULL )
break;
cache_tab[n].next = cache_top;
cache_top = &(cache_tab[n]);
cache_tab[n].id = (-1);
cache_tab[n].block = 0xFFFFFFFFL;
}
return FALSE;
}
int Cache_flush(int id)
{
if ( now_dev_id == id )
return TRUE;
now_dev_id = id;
comp_seek = 0xFFFFFFFFL;
return FALSE;
}
int CD_read_sect(ulong block, int count, char *buff)
{
register CAHPTR *bp;
CAHPTR *tp;
while ( count-- > 0 ) {
tp = bp = cache_top;
for ( ; ; ) {
if ( bp->block == block && bp->id == now_dev_id ) {
if ( tp != bp ) {
tp->next = bp->next;
bp->next = cache_top;
cache_top = bp;
}
NEAR_MEMCPY(buff, bp->buff, BLOCK_SIZE);
break;
}
if ( bp->next == NULL ) {
if ( REAL_read_sect(block, 1, buff) )
return ERR;
tp->next = bp->next;
bp->next = cache_top;
cache_top = bp;
bp->id = now_dev_id;
bp->block = block;
FAR_MEMCPY(bp->buff, buff, BLOCK_SIZE);
break;
}
tp = bp;
bp = bp->next;
}
block++;
buff += BLOCK_SIZE;
}
return FALSE;
}
/********************************************
VTOC File Access Func
*********************************************/
int CD_read_time(int min, int sec, int blk, int count, char *buff)
{
ulong sect;
sect = min * (60L * 75L);
sect += (sec * 75L);
sect += blk;
sect -= (2 * 75L); /* 0 is 0:2:0 */
return CD_read_sect(sect, count, buff);
}
static char *CD_form_name(uchar *ptn, int len)
{
static char buf[128];
static char ext[] = {
'\0', '?', '?', '?', '?', '?', '?', '?',
'?', '?', '?', '\\', '?', '?', '?', '?'
};
int n, ch;
for ( n = 0 ; n < len && n < 127 ; n++ ) {
switch(ptn[n] & 0xF0) {
case 0x40:
ch = ext[ptn[n] & 0x0F];
break;
case 0xC0:
ch = '@' + (ptn[n] & 0x0F);
break;
case 0xD0:
ch = 'I' + (ptn[n] & 0x0F);
break;
case 0xE0:
ch = 'Q' + (ptn[n] & 0x0F);
break;
case 0xF0:
ch = '0' + (ptn[n] & 0x0F);
break;
}
buf[n] = ch;
if ( ch == 0 )
break;
}
buf[n] = '\0';
return buf;
}
static ulong CD_time_to_sect(int min, int sec, int blk)
{
return ((ulong)min * 60L * 75L + sec * 75L + blk - (2 * 75L));
}
int CD_file_init()
{
int min, sec, blk;
#ifdef FMRBIOS
if ( towns_flg && CD_mode_set(0x04) )
return ERR;
#endif
if ( CD_read_time(0, 3, 38, 1, dic_buf) )
return ERR;
if ( strcmp(CD_form_name(dic_buf, 3), "VTC") != 0 )
return ERR;
min = (dic_buf[180] & 0x0F) * 10 + (dic_buf[181] & 0x0F);
sec = (dic_buf[182] & 0x0F) * 10 + (dic_buf[183] & 0x0F);
blk = (dic_buf[184] & 0x0F) * 10 + (dic_buf[185] & 0x0F);
vtoc_start_block = CD_time_to_sect(min, sec, blk);
min = (dic_buf[188] & 0x0F) * 10 + (dic_buf[189] & 0x0F);
sec = (dic_buf[190] & 0x0F) * 10 + (dic_buf[191] & 0x0F);
blk = (dic_buf[192] & 0x0F) * 10 + (dic_buf[193] & 0x0F);
vtoc_end_block = CD_time_to_sect(min, sec, blk);
vtoc_file_max = vtoc_end_block - vtoc_start_block + 1;
return FALSE;
}
int CD_file_open(int no)
{
int min, sec, blk;
ulong sect;
sect = vtoc_start_block + no - 1;
if ( sect < vtoc_start_block || sect > vtoc_end_block )
return ERR;
if ( CD_read_sect(sect, 1, dic_buf) )
return ERR;
if ( strcmp(CD_form_name(dic_buf, 3), "HDR") != 0 )
return ERR;
strcpy(file_name, CD_form_name(dic_buf + 4, 47));
min = (dic_buf[180] & 0x0F) * 10 + (dic_buf[181] & 0x0F);
sec = (dic_buf[182] & 0x0F) * 10 + (dic_buf[183] & 0x0F);
blk = (dic_buf[184] & 0x0F) * 10 + (dic_buf[185] & 0x0F);
file_start_block = CD_time_to_sect(min, sec, blk);
min = (dic_buf[188] & 0x0F) * 10 + (dic_buf[189] & 0x0F);
sec = (dic_buf[190] & 0x0F) * 10 + (dic_buf[191] & 0x0F);
blk = (dic_buf[192] & 0x0F) * 10 + (dic_buf[193] & 0x0F);
file_end_block = CD_time_to_sect(min, sec, blk);
return FALSE;
}
/********************************************
CD Low Block I/O Func
*********************************************/
static ulong io_block;
static ushort io_offset;
int IO_block_read(ulong block)
{
block = file_start_block + block - 1;
if ( block < file_start_block || block > file_end_block )
return ERR;
return CD_read_sect(block, 1, dic_buf);
}
int IO_seek(ulong block, ushort offset)
{
io_block = block;
io_offset = offset;
return IO_block_read(io_block++);
}
int IO_getc()
{
if ( io_offset >= BLOCK_SIZE ) {
if ( IO_block_read(io_block++) )
return EOF;
io_offset = 0;
}
return (dic_buf[io_offset++] & 0xFF);
}
int IO_read(char *buf, int size)
{
int ch, len;
for ( len = 0 ; len < size ; ) {
if ( (ch = IO_getc()) == EOF )
break;
buf[len++] = ch;
}
return len;
}
/********************************************
Device/File Name ID Make/Get
*********************************************/
typedef struct _IP {
struct _IP *next;
int id;
char name[1];
} NAMEID;
static int id_counter = 0;
static NAMEID *name_id_ptr = NULL;
char *id_to_name(int id)
{
NAMEID *np;
np = name_id_ptr;
while ( np != NULL ) {
if ( np->id == id )
return np->name;
np = np->next;
}
return NULL;
}
int name_to_id(char *name)
{
NAMEID *np;
np = name_id_ptr;
while ( np != NULL ) {
if ( strcmp(np->name, name) == 0 )
return np->id;
np = np->next;
}
if ( (np = (NAMEID *)malloc(sizeof(NAMEID) + strlen(name))) == NULL ) {
fprintf(stderr, "dic: Name ID struct memory alloc error\n");
exit(1);
}
np->next = name_id_ptr;
name_id_ptr = np;
np->id = id_counter++;
strcpy(np->name, name);
return np->id;
}