home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Hack-Phreak Scene Programs
/
cleanhpvac.zip
/
cleanhpvac
/
FAQSYS18.ZIP
/
FAQS.DAT
/
READCDA.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-05
|
13KB
|
588 lines
/*
GOAL:
This program is intended to read CD audio data into a disk file.
Author:
Yeng-Chee Su (yenchee@csie.nctu.edu.tw)
Department of Computer Science and Information Engineering
National Chiao Tung University
&
Klaas Hemstra (hst@mh.nl)
Gouda, the Netherlands
Notice:
Most CD-ROM drive doesn't have the capability to read raw
data on compact disk, but some drives can work. These includes
Panasonic CR-562B/563B and Toshiba XM-3401B. This program
is designed on CR-562B and should work well on it. If it
can't work for you, find a better driver around.
Yeng-Chee Su wrote the first attempt, but the program depended on
the speed of the file-system for clean 'recordings'.
The buffered read + synchronisation is added later by me.
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include <dir.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <io.h>
#define RAW_MODE 1
#define COOKED_MODE 0
#define READ_MODE RAW_MODE
#if READ_MODE == COOKED_MODE
#define FRAME_SIZE 2048
#else
#define FRAME_SIZE 2352
#endif
#define NBLOCK 16
#define NBUF 10
#define SYNCH_SIZE 128 /* Bytes synch pattern */
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long int DWORD;
struct ReqHdr {
BYTE len;
BYTE unit;
BYTE command;
WORD status;
BYTE reserved[8];
};
struct IOCTLI {
struct ReqHdr req;
BYTE descriptor;
void far *address;
WORD len;
WORD secnum;
void far *ptr;
};
struct DeviceStatus {
BYTE control;
DWORD param;
};
struct DiskInfo {
BYTE control;
BYTE lowest;
BYTE highest;
DWORD total;
};
struct TrackInfo {
BYTE control;
BYTE track;
DWORD loc;
BYTE info;
};
struct SEEK {
struct ReqHdr req;
BYTE mode;
DWORD address;
WORD secnum;
DWORD loc;
};
struct PlayReq {
struct ReqHdr req;
BYTE mode;
DWORD loc;
DWORD secnum;
};
int CDROM;
int lowest, highest;
DWORD total_time;
char image[MAXPATH];
void CallDevice(void *ptr)
{
static union REGS reg;
static struct SREGS seg;
segread(&seg);
seg.es=FP_SEG(ptr);
reg.x.ax=0x1510;
reg.x.bx=FP_OFF(ptr);
reg.x.cx=CDROM;
int86x(0x2f, ®, ®, &seg);
}
int check_mscdex(void)
{
union REGS reg;
reg.x.ax=0x1500;
reg.x.bx=0;
int86(0x2f, ®, ®);
if (!reg.x.bx)
return 0;
else {
CDROM=reg.x.cx;
return 1;
}
}
int GetDeviceStatus(void)
{
struct IOCTLI cmd;
struct DeviceStatus buf;
cmd.req.len=26;
cmd.req.unit=0;
cmd.req.command=3;
cmd.descriptor=0;
cmd.address=&buf;
cmd.len=5;
cmd.secnum=0;
cmd.ptr=NULL;
buf.control=6;
CallDevice(&cmd);
return cmd.req.status;
}
int GetDiskInfo(void)
{
struct IOCTLI cmd;
struct DiskInfo buf;
cmd.req.len=26;
cmd.req.unit=0;
cmd.req.command=3;
cmd.descriptor=0;
cmd.address=&buf;
cmd.len=7;
cmd.secnum=0;
cmd.ptr=NULL;
buf.control=10;
CallDevice(&cmd);
lowest=buf.lowest;
highest=buf.highest;
total_time=buf.total;
return cmd.req.status;
}
int GetTrackInfo(int track, DWORD *loc, BYTE *info)
{
struct IOCTLI cmd;
struct TrackInfo buf;
cmd.req.len=26;
cmd.req.unit=0;
cmd.req.command=3;
cmd.descriptor=0;
cmd.address=&buf;
cmd.len=7;
cmd.secnum=0;
cmd.ptr=NULL;
buf.control=11;
buf.track=track;
CallDevice(&cmd);
*loc=buf.loc;
*info=buf.info;
return cmd.req.status;
}
int SeekTrack(DWORD loc)
{
struct SEEK cmd;
cmd.req.len=24;
cmd.req.unit=0;
cmd.req.command=131;
cmd.mode=1;
cmd.address=NULL;
cmd.secnum=0;
cmd.loc=loc;
CallDevice(&cmd);
return cmd.req.status;
}
int PlayAudio(DWORD loc, DWORD num)
{
struct PlayReq cmd;
cmd.req.len=22;
cmd.req.unit=0;
cmd.req.command=132;
cmd.mode=1;
cmd.loc=loc;
cmd.secnum=num;
CallDevice(&cmd);
return cmd.req.status;
}
int StopAudio(void)
{
struct ReqHdr cmd;
cmd.len=13;
cmd.unit=0;
cmd.command=133;
CallDevice(&cmd);
return cmd.status;
}
DWORD Red2Sierra(DWORD loc)
{
BYTE min, sec, frame;
min = (loc >> 16) & 0xff;
sec = (loc >> 8) & 0xff;
frame = loc & 0xff;
return (DWORD)min * 75 * 60 + (DWORD)sec * 75 + (DWORD)frame - 150;
}
int ReadLong(DWORD loc, WORD secnum, char far *buf)
{
struct ReadL {
struct ReqHdr req;
BYTE mode;
void far *address;
WORD secnum;
DWORD loc;
BYTE readmode;
BYTE skip[2];
} cmd;
cmd.req.len=sizeof(cmd);
cmd.req.unit=0;
cmd.req.command=128;
cmd.mode=0;
cmd.address=buf;
cmd.secnum=secnum;
cmd.loc=loc;
cmd.readmode=READ_MODE;
cmd.skip[0]=cmd.skip[1]=0;
CallDevice(&cmd);
return cmd.req.status;
}
int GetVolSize(DWORD *size)
{
struct IOCTLI cmd;
struct {
BYTE control;
DWORD size;
} buf;
cmd.req.len=sizeof(cmd);
cmd.req.unit=0;
cmd.req.command=3;
cmd.descriptor=0;
cmd.address=&buf;
cmd.len=sizeof(buf);
cmd.secnum=0;
cmd.ptr=NULL;
buf.control=8;
CallDevice(&cmd);
*size=buf.size;
return cmd.req.status;
}
char *
location_str( DWORD loc)
{
static char ret_buf[256];
long min,sec,frames;
frames = loc % 75;
sec = (loc+150) / 75;
min = sec / 60;
sec = sec % 60;
sprintf(ret_buf,"High sierra %ld ; %02ld:%02ld.%02ld",loc,min,sec,frames);
return ret_buf;
}
void
read_location(char *question,DWORD *loc)
{
#define MAX_LOC 256
char buf[MAX_LOC],*p;
buf[0] = '\0';
while (buf[0] == '\0') {
printf("%s",question);
fgets(buf,MAX_LOC,stdin);
}
for (p=buf;*p && (*p != ':'); p++)
;
if (*p == ':') {
*loc = atol(buf)*75L*60L+atol(p+1)*75L;
} else {
*loc = atol(buf);
}
}
void main()
{
WORD status;
char *buf[NBUF],*previous_end;
DWORD *track_loc, loc, end_pos, size;
DWORD i, j, offset,synch_size;
BYTE info;
int fd, key, n,first_time;
int retry, waveform;
struct RIFF {
char rID[4];
DWORD rLen;
} riff;
struct FORMAT {
char fID[4];
DWORD fLen;
WORD wTag;
WORD wChannel;
DWORD nSample;
DWORD nByte;
WORD align;
WORD sample;
};
struct DATA {
char dID[4];
DWORD dLen;
};
struct WAVE {
char wID[4];
struct FORMAT fmt;
struct DATA data;
} wave;
printf("CD-ROM digital audio data extractor, Ver 1.1\n");
printf(" written by Yeng-Chee Su, CSIE, NCTU & Klaas Hemstra (hst@mh.nl)\n");
printf("\n");
/*
* Allocate memory buffers
*/
for (i=0; i< NBUF; i++)
buf[i] = (char*)malloc((long)FRAME_SIZE * NBLOCK);
if (buf[i] == NULL) {
printf("Out of memory!\n");
exit(1);
}
previous_end = (char*)malloc((long)FRAME_SIZE * NBLOCK);
if (previous_end == (char *) NULL) {
printf("Out of memory!\n");
exit(1);
}
/*
* Get Disc info
*/
if (!check_mscdex()) {
printf("No CD-ROM extension available!\n");
exit(1);
}
retry=0;
status=GetDiskInfo();
while (status != 0x0100) {
printf("Can't get CD-ROM information, status=%x\n", status);
delay(1000);
retry++;
if (retry == 3) {
printf("Get CD-ROM information failed\n");
exit(1);
}
status=GetDiskInfo();
}
track_loc=(DWORD*)malloc(sizeof(DWORD)*(highest-lowest+2));
if (track_loc==NULL) {
printf("Out of memory!\n");
exit(1);
}
track_loc = &track_loc[-lowest];
track_loc[highest+1]=total_time;
for (i=lowest; i<=highest; i++) {
status=GetTrackInfo(i, &loc, &info);
track_loc[i]=loc;
}
for (i=lowest; i<=highest; i++)
printf("Track %2ld : %02ld:%02ld.%02ld %6ld Len = %ld\n", i, (track_loc[i] >> 16) & 0xff,
(track_loc[i] >> 8) & 0xff, track_loc[i] & 0xff, Red2Sierra(track_loc[i]),
Red2Sierra(track_loc[i+1]) - Red2Sierra(track_loc[i]));
printf("Total time : %02ld:%02ld.%02ld\n", (total_time >> 16) & 0xff,
(total_time >> 8) & 0xff, total_time & 0xff);
/*
* User interface
*/
printf("Image filename:");
gets(image);
printf("(0) CDDA format, (1) WAV format :");
key = getch();
while (key != '0' && key != '1')
key = getch();
printf("%c\n", key);
if (key == '1') waveform = 1; else waveform = 0;
printf("(0) Read Track, (1) Read A to B :");
key = getch();
while (key != '0' && key != '1')
key = getch();
printf("%c\n", key);
if (key == '1') {
read_location("Start location (High sierra or min:sec) : ",&loc);
read_location("Frame length (Sectors or min:sec) : ",&size);
} else {
track_again:
printf("Which track :");
scanf("%d", &n);
if (n < lowest || n > highest) {
printf("illega track!\n");
goto track_again;
}
loc = Red2Sierra(track_loc[n]);
size = Red2Sierra(track_loc[n+1]) - Red2Sierra(track_loc[n]);
}
printf("Start location %s\n", location_str(loc));
printf("Stop location %s\n", location_str(loc+size));
/*
* Create the file
*/
_fmode = O_BINARY;
fd = creat(image, S_IREAD|S_IWRITE);
if (fd == -1) {
perror("open");
exit(1);
}
if (waveform) {
strcpy(riff.rID, "RIFF");
riff.rLen = FRAME_SIZE * (DWORD)size + sizeof(struct WAVE);
strcpy(wave.wID, "WAVE");
strcpy(wave.fmt.fID, "fmt ");
wave.fmt.fLen = sizeof(struct FORMAT) - 8;
wave.fmt.wTag = 1;
wave.fmt.wChannel = 2;
wave.fmt.nSample = 44100L;
wave.fmt.nByte = 44100L * 4;
wave.fmt.align = 4;
wave.fmt.sample = 16;
strcpy(wave.data.dID, "data");
wave.data.dLen = FRAME_SIZE * (DWORD)size;
if (write(fd, &riff, sizeof(struct RIFF)) != sizeof(struct RIFF)) {
perror("write");
exit(1);
}
if (write(fd, &wave, sizeof(struct WAVE)) != sizeof(struct WAVE)) {
perror("write");
exit(1);
}
}
/*
* Read the date in blocks, first in memory
*/
wave.data.dLen = 0L;
first_time = 1;
end_pos = loc+size;
while (loc < end_pos) {
for (i=0;(i < NBUF);i++) {
printf("\rReading frame %ld to %ld in memory \r",
loc, loc+NBLOCK-1);
status = ReadLong(loc, NBLOCK, buf[i]);
if (status != 0x0100) {
printf("CDROM read with status %x\n", status);
exit(1);
}
loc += NBLOCK;
}
if (first_time == 0) {
/*
* Synchronize data to previous block
*/
offset = 0;
synch_size = SYNCH_SIZE;
while (offset == 0) {
for (i=(NBLOCK/4)*FRAME_SIZE;
i < (((unsigned int)NBLOCK*FRAME_SIZE)-synch_size);
i+=4) {
if (memcmp(previous_end+(NBLOCK/2)*FRAME_SIZE,buf[0]+i,synch_size) == 0) {
if (offset == 0)
offset = i;
else {
synch_size *= 2;
if (synch_size > 4096) {
fprintf(stderr,"Synchronisation failed, synch size to big !!\n");
exit(1);
}
break;
}
}
}
if (offset == 0) {
fprintf(stderr,"Synchronisation failed, no matching block found !!\n");
exit(1);
}
}
}
else
offset = 0;
first_time = 0;
memcpy(previous_end,buf[NBUF-1],(long)FRAME_SIZE*NBLOCK);
printf("\rSynchronized write frame %ld to %ld to disk, offset = %ld ",
loc-(NBUF*NBLOCK),loc-(NBLOCK/2),offset-(NBLOCK/2*FRAME_SIZE));
for (i=0;(i < NBUF-1);i++) {
if (write(fd, buf[i]+offset, ((long) FRAME_SIZE * NBLOCK)-offset) == -1) {
perror("write");
exit(1);
}
wave.data.dLen += (((long) FRAME_SIZE * NBLOCK)-offset);
offset = 0;
}
/*
* Write only half of last buffer,
* The next loop, after synchronisation the rest will be written
*/
if (write(fd, buf[NBUF-1], ((long) FRAME_SIZE * (NBLOCK/2))) == -1) {
perror("write");
exit(1);
}
wave.data.dLen += ((long) FRAME_SIZE * (NBLOCK/2));
loc -= NBLOCK;
/* sleep(1); */
}
if (waveform) {
lseek(fd,0L,SEEK_SET);
printf("\nCompleting header information of WAV file\n");
riff.rLen = wave.data.dLen + sizeof(struct WAVE);
if (write(fd, &riff, sizeof(struct RIFF)) != sizeof(struct RIFF)) {
perror("write");
exit(1);
}
if (write(fd, &wave, sizeof(struct WAVE)) != sizeof(struct WAVE)) {
perror("write");
exit(1);
}
}
close(fd);
free(&track_loc[lowest]);
free(buf);
}