home *** CD-ROM | disk | FTP | other *** search
- /* play.c: */
-
- #include "includes.h"
-
- #define VERSION "1.1 (04.01.1994)"
-
- #define HRDBLBF
-
- #define CDDA_BUFSIZE 2368
- #define SUBCHANNEL_SIZE 16
- #define STD_BUFSIZE 2048
- #define SENSE_LENGTH 32
- #define AUDIO_BUFSIZE ((CDDA_BUFSIZE-SUBCHANNEL_SIZE)/g_compression_factor/4)
- #define TOTAL_CDDA_BUFSIZE (g_buffers*2*CDDA_BUFSIZE)
- #define TOTAL_AUDIO_BUFSIZE (g_buffers*2*AUDIO_BUFSIZE)
- #define CDDA_STD_BUFSIZE (STD_BUFSIZE+SENSE_LENGTH)
-
- typedef short t_bool;
-
- typedef struct toc {
- char reserved1;
- unsigned char flags;
- unsigned char track_number;
- char reserved2;
- long address;
- } t_toc;
-
- typedef enum dtype {UNKNOWNDRIVE = 0, TOSHIBA, APPLECD300} t_drivetype;
-
- static char *TheVersion = "$VER: PlayCDDA " VERSION;
-
- t_bool g_called_from_cli;
- char g_scsi_device[80];
- t_drivetype g_whatdrive = UNKNOWNDRIVE;
- int g_scsi_id;
- LONG g_memory_type = MEMF_CHIP;
- UBYTE *g_cdda_base = NULL;
- UBYTE *g_audio_base = NULL;
- UBYTE *g_std_buf_base = NULL;
- UBYTE *g_cdda_buf[2];
- UBYTE *g_cdda_std_buf;
- UBYTE *g_audio_buf[2];
- struct MsgPort *g_cdda_port = NULL;
- struct MsgPort *g_audio_port[2] = { NULL, NULL };
- ULONG g_cdda_sigmask;
- ULONG g_audio_sigmask[2];
- #ifndef HRDBLBF
- struct IOStdReq *g_scsireq = NULL;
- t_bool g_outstanding_cdda_request = FALSE;
- struct SCSICmd *g_scsicmd = NULL;
- UBYTE *g_sense_data;
- #else
- struct IOStdReq *g_scsireq[2] = {NULL, NULL};
- t_bool g_outstanding_cdda_request[2] = {FALSE, FALSE};
- struct SCSICmd *g_scsicmd[2] = {NULL, NULL};
- UBYTE *g_sense_data[2];
- #endif
- struct IOAudio *g_audioreq[2] = { NULL, NULL };
- t_bool g_audio_device_open = FALSE;
- long g_period;
- int g_toc_length;
- t_toc g_toc[100];
- short g_volume = 1;
- /* possible values for g_compression_factor: 2, 3, 4, 6, 7, 12, 14, 28, 49 */
- unsigned short g_compression_factor = 2;
- unsigned short g_buffers = 4;
-
- /* user interface variables: */
-
- #ifdef __SASC
- extern struct Library *DOSBase;
- #endif
- struct Library *IconBase = NULL;
- struct Library *IntuitionBase = NULL;
- struct Library *GadToolsBase = NULL;
- struct GfxBase *GfxBase = NULL;
- struct Screen *g_screen = NULL;
- void *g_visual_info = NULL;
- struct Window *g_window = NULL;
- struct Gadget *g_glist = NULL;
- t_bool g_bye = FALSE;
- char g_track_str[3] = { 0, 0, 0 };
- char g_index_str[3] = { 0, 0, 0 };
- char g_time_str[6] = { 0, 0, ':', 0, 0, 0 };
- unsigned char g_track, g_index;
- unsigned char g_minute, g_seconds;
-
- enum gadget_ids {
- GID_SAMPLING_RATE = 21,
- GID_BUFFERS,
- GID_VOLUME,
- GID_PREV,
- GID_NEXT,
- GID_START,
- GID_STOP,
- GID_TRACK,
- GID_INDEX,
- GID_TIME,
-
- /* always last: */
- GID_MAX
- };
-
- struct Gadget *g_gadgets[GID_MAX];
-
- #ifdef __SASC
- void __regargs __chkabort(void)
- {
- }
- #endif
-
- void Cleanup_User_Interface (void)
- {
- if (g_window)
- CloseWindow (g_window);
- if (g_glist)
- FreeGadgets (g_glist);
- if (g_visual_info)
- FreeVisualInfo (g_visual_info);
- if (g_screen)
- UnlockPubScreen (NULL, g_screen);
- if (GfxBase)
- CloseLibrary ((struct Library *) GfxBase);
- if (GadToolsBase)
- CloseLibrary (GadToolsBase);
- if (IntuitionBase)
- CloseLibrary (IntuitionBase);
- }
-
- void Cleanup_Audio (void)
- {
- if (g_cdda_base) {
- FreeMem (g_cdda_base, TOTAL_CDDA_BUFSIZE + 15);
- g_cdda_base = NULL;
- }
- if (g_audio_base) {
- FreeMem (g_audio_base, TOTAL_AUDIO_BUFSIZE + 15);
- g_audio_base = NULL;
- }
- if (g_audio_device_open) {
- CloseDevice ((struct IORequest *) g_audioreq[0]);
- g_audio_device_open = FALSE;
- }
- if (g_audio_port[0]) {
- DeleteMsgPort (g_audio_port[0]);
- g_audio_port[0] = NULL;
- }
- if (g_audio_port[1]) {
- DeleteMsgPort (g_audio_port[1]);
- g_audio_port[1] = NULL;
- }
- if (g_audioreq[0]) {
- FreeMem (g_audioreq[0], sizeof (struct IOAudio));
- g_audioreq[0] = NULL;
- }
- if (g_audioreq[1]) {
- FreeMem (g_audioreq[1], sizeof (struct IOAudio));
- g_audioreq[1] = NULL;
- }
- }
-
- void Cleanup (void)
- {
- #ifdef HRDBLBF
- int i;
- #endif
-
- Cleanup_Audio ();
-
- if (g_std_buf_base)
- FreeMem (g_std_buf_base, CDDA_STD_BUFSIZE + 15);
- #ifndef HRDBLBF
- if (g_scsicmd)
- FreeMem (g_scsicmd, sizeof (struct SCSICmd));
- if (g_scsireq) {
- if (g_scsireq->io_Device) {
- if (g_outstanding_cdda_request) {
- AbortIO ((struct IORequest *) g_scsireq);
- WaitIO ((struct IORequest *) g_scsireq);
- }
- CloseDevice ((struct IORequest *) g_scsireq);
- }
- DeleteIORequest ((struct IORequest *) g_scsireq);
- }
- #else
- for (i = 0; i < 2; i++) {
- if (g_scsicmd[i])
- FreeMem (g_scsicmd[i], sizeof (struct SCSICmd));
- if (g_scsireq[i]) {
- if (g_scsireq[i]->io_Device) {
- if (g_outstanding_cdda_request[i]) {
- AbortIO ((struct IORequest *) g_scsireq[i]);
- WaitIO ((struct IORequest *) g_scsireq[i]);
- }
- CloseDevice ((struct IORequest *) g_scsireq[i]);
- }
- DeleteIORequest ((struct IORequest *) g_scsireq[i]);
- }
- }
- #endif
- if (g_cdda_port)
- DeleteMsgPort (g_cdda_port);
-
- Cleanup_User_Interface ();
-
- if (IconBase)
- CloseLibrary (IconBase);
- }
-
- void Fatal_Error (char *p_message, ...)
- {
- va_list arg;
-
- static struct EasyStruct req = {
- sizeof (struct EasyStruct),
- 0,
- (UBYTE *) "PlayCDDA Error",
- NULL,
- (UBYTE *) "Abort"
- };
-
- va_start (arg, p_message);
- if (IntuitionBase) {
- req.es_TextFormat = (UBYTE *) p_message;
- EasyRequestArgs (NULL, &req, NULL, arg);
- } else if (g_called_from_cli) {
- VPrintf ((UBYTE *) p_message, (LONG *) arg);
- WriteChars ((UBYTE *) "\n", 1);
- } else
- Alert (0x0000CDDA);
-
- va_end (p_message);
-
- exit (1);
- }
-
- char *Open_User_Interface (void)
- {
- static struct TextAttr Topaz8 = { (UBYTE *) "topaz.font", 8, 0, 0, };
- struct TextFont *font;
- int i, j;
- static char *labels[20] = {
- "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11",
- "12", "13", "14", "15", "16", "17", "18", "19", "20"
- };
- static char *sampling_rate_labels[] = {
- "22050 bps", /* 2 */
- "14700 bps", /* 3 */
- "11025 bps", /* 4 */
- "7350 bps", /* 6 */
- "6300 bps", /* 7 */
- NULL
- };
- static char *buffers_labels[] = {
- "2",
- "4",
- "8",
- "16",
- "32",
- "64",
- NULL
- };
- static char *volume_labels[] = {
- "Low",
- "Medium",
- "High",
- NULL
- };
- struct NewGadget ng;
- struct Gadget *gad;
- int topborder;
-
- if (!(IntuitionBase = OpenLibrary ((UBYTE *) "intuition.library", 37)))
- return "cannot open intuition.library";
- if (!(GadToolsBase = OpenLibrary ((UBYTE *) "gadtools.library", 37)))
- return "cannot open gadtools.library";
- if (!(GfxBase = (struct GfxBase *)
- OpenLibrary ((UBYTE *) "graphics.library", 37)))
- return "cannot open graphics.library";
-
- /* does the font exist? */
- if (!(font = OpenFont (&Topaz8)))
- return "cannot open topaz 8 font";
- CloseFont (font);
-
- if (!(g_screen = LockPubScreen (NULL)))
- return "cannot lock default public screen";
-
- if (!(g_visual_info = GetVisualInfo (g_screen, TAG_END)))
- return "GetVisualInfo() failed";
-
- gad = CreateContext (&g_glist);
-
- topborder = g_screen->WBorTop + (g_screen->Font->ta_YSize + 1);
-
- ng.ng_Width = 20;
- ng.ng_Height = 12;
- ng.ng_TextAttr = &Topaz8;
- ng.ng_VisualInfo = g_visual_info;
- ng.ng_Flags = 0;
-
- for (i=0; i<5; i++)
- for (j=0; j<4; j++) {
- ng.ng_GadgetText = (UBYTE *) labels[i*4+j];
- ng.ng_GadgetID = i*4 + j + 1;
- ng.ng_LeftEdge = 10 + j * 24;
- ng.ng_TopEdge = topborder + 2 + i * 16;
- g_gadgets[ng.ng_GadgetID] = gad =
- CreateGadget (BUTTON_KIND, gad, &ng,
- GA_Disabled, TRUE,
- TAG_END);
- }
-
- ng.ng_GadgetID = GID_PREV;
- ng.ng_GadgetText = (UBYTE *) "Prev";
- ng.ng_Width = 44;
- ng.ng_LeftEdge = 10;
- ng.ng_TopEdge = topborder + 2 + 5 * 16;
- g_gadgets[ng.ng_GadgetID] =
- gad = CreateGadget (BUTTON_KIND, gad, &ng, TAG_END);
-
- ng.ng_GadgetID = GID_NEXT;
- ng.ng_GadgetText = (UBYTE *) "Next";
- ng.ng_LeftEdge = 58;
- g_gadgets[ng.ng_GadgetID] =
- gad = CreateGadget (BUTTON_KIND, gad, &ng, TAG_END);
-
- ng.ng_GadgetID = GID_START;
- ng.ng_GadgetText = (UBYTE *) "Start";
- ng.ng_LeftEdge = 120;
- ng.ng_TopEdge = topborder + 2 + 4 * 16;
- ng.ng_Width = 120;
- ng.ng_Height = 28;
- g_gadgets[ng.ng_GadgetID] =
- gad = CreateGadget (BUTTON_KIND, gad, &ng, TAG_END);
-
- ng.ng_GadgetID = GID_STOP;
- ng.ng_GadgetText = (UBYTE *) "Stop";
- ng.ng_LeftEdge = 250;
- g_gadgets[ng.ng_GadgetID] =
- gad = CreateGadget (BUTTON_KIND, gad, &ng, TAG_END);
-
- ng.ng_GadgetText = (UBYTE *) "Sampling rate:";
- ng.ng_GadgetID = GID_SAMPLING_RATE;
- ng.ng_Width = 120;
- ng.ng_Height = 12;
- ng.ng_LeftEdge = 250;
- ng.ng_TopEdge = topborder + 2;
- g_gadgets[ng.ng_GadgetID] =
- gad = CreateGadget (CYCLE_KIND, gad, &ng,
- GTCY_Labels, sampling_rate_labels,
- TAG_END);
-
- ng.ng_GadgetText = (UBYTE *) "Buffers: ";
- ng.ng_TopEdge += 16;
- ng.ng_GadgetID = GID_BUFFERS;
- g_gadgets[ng.ng_GadgetID] =
- gad = CreateGadget (CYCLE_KIND, gad, &ng,
- GTCY_Labels, buffers_labels,
- GTCY_Active, 1,
- TAG_END);
-
- ng.ng_GadgetText = (UBYTE *) "Volume: ";
- ng.ng_TopEdge += 16;
- ng.ng_GadgetID = GID_VOLUME;
- g_gadgets[ng.ng_GadgetID] =
- gad = CreateGadget (CYCLE_KIND, gad, &ng,
- GTCY_Labels, volume_labels,
- GTCY_Active, (int) g_volume-1,
- TAG_END);
-
- ng.ng_GadgetID = GID_TRACK;
- ng.ng_GadgetText = (UBYTE *) "Track";
- ng.ng_Width = 25;
- ng.ng_Height = 12;
- ng.ng_LeftEdge = 170;
- ng.ng_TopEdge = topborder + 2 + 3 * 16;
- g_gadgets[ng.ng_GadgetID] =
- gad = CreateGadget (TEXT_KIND, gad, &ng,
- GTTX_Border, TRUE,
- TAG_END);
-
- ng.ng_GadgetID = GID_INDEX;
- ng.ng_GadgetText = (UBYTE *) "Index";
- ng.ng_LeftEdge = 250;
- g_gadgets[ng.ng_GadgetID] =
- gad = CreateGadget (TEXT_KIND, gad, &ng,
- GTTX_Border, TRUE,
- TAG_END);
-
- ng.ng_GadgetID = GID_TIME;
- ng.ng_GadgetText = (UBYTE *) "Time";
- ng.ng_Width = 50;
- ng.ng_LeftEdge = 320;
- g_gadgets[ng.ng_GadgetID] =
- gad = CreateGadget (TEXT_KIND, gad, &ng,
- GTTX_Border, TRUE,
- TAG_END);
-
-
- if (!gad)
- return "cannot create gadgets";
-
- g_window = OpenWindowTags (NULL,
- WA_Title, TheVersion + 6,
- WA_Gadgets, g_glist,
- WA_Left, 20,
- WA_Top, 20,
- WA_Width, 385,
- WA_Height, topborder + 98,
- WA_IDCMP, IDCMP_CLOSEWINDOW | BUTTONIDCMP | CYCLEIDCMP,
- WA_PubScreen, g_screen,
- WA_DragBar, TRUE,
- WA_DepthGadget, TRUE,
- WA_CloseGadget, TRUE,
- WA_Activate, TRUE,
- WA_SmartRefresh, TRUE,
- TAG_END);
- if (!g_window)
- return "cannot open window";
-
- return NULL;
- }
-
- void Alloc_Audio (void)
- {
- static UBYTE whichannel[] = { 1, 2, 4, 8 };
- int i;
-
- /* allocate buffers: */
-
- g_audio_base = AllocMem (TOTAL_AUDIO_BUFSIZE + 15, MEMF_PUBLIC | MEMF_CHIP);
- if (!g_audio_base)
- Fatal_Error ("cannot allocate memory");
-
- g_cdda_base = AllocMem (TOTAL_CDDA_BUFSIZE + 15, MEMF_PUBLIC | g_memory_type);
- if (!g_cdda_base)
- Fatal_Error ("cannot allocate memory");
-
- /* make the buffers quad-word aligned. This greatly helps
- * performance on '040-powered systems with DMA SCSI
- * controllers.
- */
- g_cdda_buf[0] = (UBYTE *)(((long) g_cdda_base + 15) & ~15);
- g_audio_buf[0] = (UBYTE *)(((long) g_audio_base + 15) & ~15);
-
- g_cdda_buf[1] = g_cdda_buf[0] + g_buffers * CDDA_BUFSIZE;
- g_audio_buf[1] = g_audio_buf[0] + g_buffers * AUDIO_BUFSIZE;
-
- /* allocate message ports and IO requests: */
-
- if (!(g_audio_port[0] = CreateMsgPort ()) ||
- !(g_audio_port[1] = CreateMsgPort ()))
- Fatal_Error ("cannot allocate message ports");
-
- g_audio_sigmask[0] = (1 << g_audio_port[0]->mp_SigBit);
- g_audio_sigmask[1] = (1 << g_audio_port[1]->mp_SigBit);
-
- if (!(g_audioreq[0] = AllocMem (sizeof (struct IOAudio),
- MEMF_PUBLIC | MEMF_CLEAR)) ||
- !(g_audioreq[1] = AllocMem (sizeof (struct IOAudio),
- MEMF_PUBLIC | MEMF_CLEAR)))
- Fatal_Error ("cannot allocate memory");
-
- /* open audio device: */
-
- g_audioreq[0]->ioa_Request.io_Message.mn_ReplyPort = g_audio_port[0];
- g_audioreq[0]->ioa_Request.io_Message.mn_Node.ln_Pri = 0;
- g_audioreq[0]->ioa_Request.io_Command = ADCMD_ALLOCATE;
- g_audioreq[0]->ioa_Request.io_Flags = ADIOF_NOWAIT;
- g_audioreq[0]->ioa_AllocKey = 0;
- g_audioreq[0]->ioa_Data = whichannel;
- g_audioreq[0]->ioa_Length = sizeof (whichannel);
-
- if (OpenDevice ((UBYTE *) AUDIONAME, 0,
- (struct IORequest *) g_audioreq[0], 0))
- Fatal_Error ("cannot open audio.device\n");
-
- g_audio_device_open = TRUE;
-
- *(g_audioreq[1]) = *(g_audioreq[0]);
- g_audioreq[0]->ioa_Request.io_Message.mn_ReplyPort = g_audio_port[0];
- g_audioreq[1]->ioa_Request.io_Message.mn_ReplyPort = g_audio_port[1];
- g_audioreq[0]->ioa_Data = (UBYTE *) g_audio_buf[0];
- g_audioreq[1]->ioa_Data = (UBYTE *) g_audio_buf[1];
-
- for (i=0; i<2; i++) {
- struct IOAudio *req = g_audioreq[i];
-
- req->ioa_Request.io_Command = CMD_WRITE;
- req->ioa_Request.io_Flags = ADIOF_PERVOL;
- req->ioa_Length = g_buffers * AUDIO_BUFSIZE;
- req->ioa_Period = g_period;
- req->ioa_Volume = 64;
- req->ioa_Cycles = 1;
- }
- }
-
- void Alloc_CDROM (void)
- {
- #ifdef HRDBLBF
- int i;
- #endif
-
- g_std_buf_base = AllocMem (CDDA_STD_BUFSIZE + 15, MEMF_PUBLIC | MEMF_CHIP);
- if (!g_std_buf_base)
- Fatal_Error ("cannot allocate memory");
-
- #ifndef HRDBLBF
- g_scsicmd = AllocMem (sizeof (struct SCSICmd), MEMF_PUBLIC | MEMF_CHIP);
- if (!g_scsicmd)
- Fatal_Error ("cannot allocate memory");
- #else
- for (i = 0; i < 2; i++) {
- g_scsicmd[i] = AllocMem (sizeof (struct SCSICmd), MEMF_PUBLIC | MEMF_CHIP);
- if (!g_scsicmd[i])
- Fatal_Error ("cannot allocate memory");
- }
- #endif
-
- /* make the buffer quad-word aligned. This greatly helps
- * performance on '040-powered systems with DMA SCSI
- * controllers.
- */
-
- g_cdda_std_buf = (UBYTE *)(((long) g_std_buf_base + 15) & ~15);
- #ifndef HRDBLBF
- g_sense_data = g_cdda_std_buf + STD_BUFSIZE;
- #else
- for (i = 0; i < 2; i++)
- g_sense_data[i] = g_cdda_std_buf + STD_BUFSIZE;
- #endif
-
- /* allocate message ports and IO requests: */
-
- if (!(g_cdda_port = CreateMsgPort ()))
- Fatal_Error ("cannot allocate message port");
-
- g_cdda_sigmask = (1 << g_cdda_port->mp_SigBit);
-
- #ifndef HRDBLBF
- if (!(g_scsireq = CreateIORequest (g_cdda_port,
- sizeof (struct IOStdReq))))
- Fatal_Error ("cannot create IO request\n");
-
- /* open SCSI device: */
-
- g_scsireq->io_Device = NULL;
-
- if (OpenDevice ((UBYTE *) g_scsi_device, g_scsi_id,
- (struct IORequest *) g_scsireq, 0)) {
- if (g_called_from_cli)
- Fatal_Error ("Cannot open \"%s\", unit %ld",
- g_scsi_device, g_scsi_id);
- else
- Fatal_Error ("Cannot open \"%s\", unit %ld\n"
- "Please edit the tooltype entries\n"
- "in the PlayCDDA icon!",
- g_scsi_device, g_scsi_id);
- }
- #else
- for (i = 0; i < 2; i++) {
- if (!(g_scsireq[i] = CreateIORequest (g_cdda_port,
- sizeof (struct IOStdReq))))
- Fatal_Error ("cannot create IO request\n");
-
- /* open SCSI device: */
-
- g_scsireq[i]->io_Device = NULL;
-
- if (OpenDevice ((UBYTE *) g_scsi_device, g_scsi_id,
- (struct IORequest *) g_scsireq[i], 0)) {
- if (g_called_from_cli)
- Fatal_Error ("Cannot open \"%s\", unit %ld",
- g_scsi_device, g_scsi_id);
- else
- Fatal_Error ("Cannot open \"%s\", unit %ld\n"
- "Please edit the tooltype entries\n"
- "in the PlayCDDA icon!",
- g_scsi_device, g_scsi_id);
- }
- }
- #endif
-
- }
-
- void Do_SCSI_Command (UBYTE *p_command, int p_length,
- short p_phase, int p_sync, int p_direction)
- {
- #ifndef HRDBLBF
- g_scsireq->io_Length = sizeof (struct SCSICmd);
- g_scsireq->io_Data = (APTR) g_scsicmd;
- g_scsireq->io_Command = HD_SCSICMD;
-
- if (p_phase == -1) {
- g_scsicmd->scsi_Data = (UWORD *) g_cdda_std_buf;
- g_scsicmd->scsi_Length = STD_BUFSIZE;
- } else {
- g_scsicmd->scsi_Data = (UWORD *) g_cdda_buf[p_phase];
- g_scsicmd->scsi_Length = g_buffers * CDDA_BUFSIZE;
- }
-
- g_scsicmd->scsi_Flags = SCSIF_AUTOSENSE | p_direction;
- g_scsicmd->scsi_SenseData = (UBYTE *) g_sense_data;
- g_scsicmd->scsi_SenseLength = SENSE_LENGTH;
- g_scsicmd->scsi_SenseActual = 0;
- g_scsicmd->scsi_Command = (UBYTE *) p_command;
- g_scsicmd->scsi_CmdLength = p_length;
-
- if (p_sync) {
- int i = 0;
-
- do {
- DoIO ((struct IORequest *) g_scsireq);
- if (g_scsicmd->scsi_Status == 0)
- return;
- i++;
- } while (i < 2);
- Fatal_Error ("sync SCSI command failed");
- } else {
- SendIO ((struct IORequest *) g_scsireq);
- g_outstanding_cdda_request = TRUE;
- }
- #else
- if (p_phase == -1) {
- p_phase = 0;
- g_scsicmd[p_phase]->scsi_Data = (UWORD *) g_cdda_std_buf;
- g_scsicmd[p_phase]->scsi_Length = STD_BUFSIZE;
- } else {
- g_scsicmd[p_phase]->scsi_Data = (UWORD *) g_cdda_buf[p_phase];
- g_scsicmd[p_phase]->scsi_Length = g_buffers * CDDA_BUFSIZE;
- }
- g_scsireq[p_phase]->io_Length = sizeof (struct SCSICmd);
- g_scsireq[p_phase]->io_Data = (APTR) g_scsicmd[p_phase];
- g_scsireq[p_phase]->io_Command = HD_SCSICMD;
-
- g_scsicmd[p_phase]->scsi_Flags = SCSIF_AUTOSENSE | p_direction;
- g_scsicmd[p_phase]->scsi_SenseData = (UBYTE *) g_sense_data[p_phase];
- g_scsicmd[p_phase]->scsi_SenseLength = SENSE_LENGTH;
- g_scsicmd[p_phase]->scsi_SenseActual = 0;
- g_scsicmd[p_phase]->scsi_Command = (UBYTE *) p_command;
- g_scsicmd[p_phase]->scsi_CmdLength = p_length;
-
- if (p_sync) {
- int i = 0;
-
- do {
- DoIO ((struct IORequest *) g_scsireq[p_phase]);
- if (g_scsicmd[p_phase]->scsi_Status == 0)
- return;
- i++;
- } while (i < 2);
- Fatal_Error ("sync SCSI command failed");
- } else {
- SendIO ((struct IORequest *) g_scsireq[p_phase]);
- g_outstanding_cdda_request[p_phase] = TRUE;
- }
- #endif
- }
-
- #ifndef HRDBLBF
- void Wait_CDROM_Command (void)
- #else
- void Wait_CDROM_Command (short p_phase)
- #endif
- {
- ULONG sig;
-
- #ifndef HRDBLBF
- sig = Wait (SIGBREAKF_CTRL_C | g_cdda_sigmask);
- if (sig & g_cdda_sigmask) {
- if (CheckIO ((struct IORequest *) g_scsireq)) {
- WaitIO ((struct IORequest *) g_scsireq);
- g_outstanding_cdda_request = FALSE;
- if (g_scsicmd->scsi_Status)
- Fatal_Error ("async SCSI command failed");
- }
- }
- if (sig & SIGBREAKF_CTRL_C)
- exit (1);
- #else
- /* HR */
-
- if (p_phase < 0 || p_phase > 1)
- Fatal_Error ("wrong p_phase argument for Wait_CDROM_Command");
-
- if (g_outstanding_cdda_request[p_phase] != FALSE) {
- for (;;) {
- sig = Wait (SIGBREAKF_CTRL_C | g_cdda_sigmask);
- if (sig & g_cdda_sigmask) {
- if (CheckIO ((struct IORequest *) g_scsireq[p_phase])) {
- WaitIO ((struct IORequest *) g_scsireq[p_phase]);
- g_outstanding_cdda_request[p_phase] = FALSE;
- if (g_scsicmd[p_phase]->scsi_Status)
- Do_SCSI_Command (g_scsicmd[p_phase]->scsi_Command,
- g_scsicmd[p_phase]->scsi_CmdLength,
- p_phase, FALSE, SCSIF_READ);
- else
- break;
- }
- }
- if (sig & SIGBREAKF_CTRL_C)
- exit (1);
- }
- }
- #endif
- }
-
- void Start_CDROM_Read (short p_phase, long p_sector)
- {
- static UBYTE cmd[2][12] =
- {
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}
- };
-
- if (p_phase < 0 || p_phase > 1)
- Fatal_Error ("Invalid p_phase argument for Start_CDROM_Read()");
-
- cmd[p_phase][2] = (p_sector >> 24);
- cmd[p_phase][3] = ((p_sector >> 16) & 0xFF);
- cmd[p_phase][4] = ((p_sector >> 8) & 0xFF);
- cmd[p_phase][5] = (p_sector & 0xFF);
-
- if (g_whatdrive == APPLECD300) {
- cmd[p_phase][0] = 0xD8;
- cmd[p_phase][9] = g_buffers;
- Do_SCSI_Command (cmd[p_phase], 12, p_phase, FALSE, SCSIF_READ);
- }
- else if (g_whatdrive == TOSHIBA) {
- cmd[p_phase][0] = 0x28;
- cmd[p_phase][8] = g_buffers;
- Do_SCSI_Command (cmd[p_phase], 10, p_phase, FALSE, SCSIF_READ);
- }
- }
-
- #ifndef HRDBLBF
- void Wait_CDROM_Read (void)
- {
- Wait_CDROM_Command ();
- }
- #else
- void Wait_CDROM_Read (short p_phase)
- {
- Wait_CDROM_Command (p_phase);
- }
- #endif
-
- void Update_Track_Data (short p_num)
- {
- g_track_str[0] = '0' + (p_num >> 4);
- g_track_str[1] = '0' + (p_num & 15);
- GT_SetGadgetAttrs (g_gadgets[GID_TRACK], g_window, NULL,
- GTTX_Text, g_track_str, TAG_END);
- g_track = p_num;
- }
-
- void Update_Index_Data (short p_num)
- {
- g_index_str[0] = '0' + (p_num >> 4);
- g_index_str[1] = '0' + (p_num & 15);
- GT_SetGadgetAttrs (g_gadgets[GID_INDEX], g_window, NULL,
- GTTX_Text, g_index_str, TAG_END);
- g_index = p_num;
- }
-
- void Update_Time_Data (short p_min, short p_sec)
- {
- g_time_str[0] = '0' + (p_min >> 4);
- g_time_str[1] = '0' + (p_min & 15);
- g_time_str[3] = '0' + (p_sec >> 4);
- g_time_str[4] = '0' + (p_sec & 15);
- GT_SetGadgetAttrs (g_gadgets[GID_TIME], g_window, NULL,
- GTTX_Text, g_time_str, TAG_END);
- g_minute = p_min;
- g_seconds = p_sec;
- }
-
- void Convert_Buffer (short p_phase)
- {
- short i;
- short sum;
- BYTE *src = (BYTE *) g_cdda_buf[p_phase];
- BYTE *dst = (BYTE *) g_audio_buf[p_phase];
- BYTE *stop = src + (g_buffers * CDDA_BUFSIZE);
- short skip = ((CDDA_BUFSIZE-SUBCHANNEL_SIZE)/4);
-
- while (src < stop) {
- sum = 0;
- for (i=0; i<g_compression_factor; i++) {
- sum += src[1] + src[3];
- src += 4;
- }
- for (i=g_volume-1; i--;) /* this is faster than multiplication */
- sum += sum;
- sum /= (g_compression_factor << 1);
- if (sum < -127)
- sum = -127;
- else if (sum > 127)
- sum = 127;
- *dst++ = sum;
- skip -= g_compression_factor;
- if (!skip) {
- /* analyze Q-sub channel data: */
- if (g_whatdrive == TOSHIBA) {
- if (src[1] == 1) {
- if (((UBYTE *) src)[2] != g_track)
- Update_Track_Data (((UBYTE *) src)[2]);
- if (((UBYTE *) src)[3] != g_index)
- Update_Index_Data (((UBYTE *) src)[3]);
- if (((UBYTE *) src)[5] != g_seconds ||
- ((UBYTE *) src)[4] != g_minute)
- Update_Time_Data (((UBYTE *) src)[4], ((UBYTE *) src)[5]);
- }
- }
- else if (g_whatdrive == APPLECD300) {
- if (src[0] == 1) {
- if (((UBYTE *) src)[1] != g_track)
- Update_Track_Data (((UBYTE *) src)[1]);
- if (((UBYTE *) src)[2] != g_index)
- Update_Index_Data (((UBYTE *) src)[2]);
- if (((UBYTE *) src)[8] != g_seconds ||
- ((UBYTE *) src)[7] != g_minute)
- Update_Time_Data (((UBYTE *) src)[7], ((UBYTE *) src)[8]);
- }
- }
- /* skip Q-sub channel data: */
- src += SUBCHANNEL_SIZE;
- skip = ((CDDA_BUFSIZE-SUBCHANNEL_SIZE)/4);
- }
- }
- }
-
- void Start_Play_Audio (short p_phase)
- {
- BeginIO ((struct IORequest *) (g_audioreq[p_phase]));
- }
-
- void Wait_Play_Audio (short p_phase)
- {
- ULONG sig;
-
- sig = Wait (SIGBREAKF_CTRL_C | g_audio_sigmask[p_phase]);
- if (sig & g_audio_sigmask[p_phase]) {
- while (GetMsg (g_audio_port[p_phase]) == 0) ;
- }
- if (sig & SIGBREAKF_CTRL_C)
- exit (1);
- }
-
- #define FORMAT_CDDA 0x82
- #define FORMAT_STD 0x00
-
- void Select_Block_Format (int p_format)
- {
- static UBYTE cmd[6] = { 0x15, 0x10, 0, 0, 12, 0 };
- static UBYTE mode[12] = { 0, 0, 0, 8,
- 0, 0, 0, 0, 0, 0, 0, 0 };
-
- mode[4] = p_format;
- switch (p_format) {
- case FORMAT_CDDA:
- mode[10] = (CDDA_BUFSIZE >> 8);
- mode[11] = (CDDA_BUFSIZE & 0xFF);
- break;
- case FORMAT_STD:
- mode[10] = (STD_BUFSIZE >> 8);
- mode[11] = (STD_BUFSIZE & 0xFF);
- break;
- }
-
- memcpy (g_cdda_std_buf, mode, sizeof (mode));
- Do_SCSI_Command (cmd, 6, -1, TRUE, SCSIF_WRITE);
- }
-
- void Read_Drive_Type (void)
- {
- static UBYTE cmd[6] = { 0x12, 0, 0, 0, 0, 0};
- static char *applecd300string = "SONY CD-ROM CDU-8003";
- static char *toshibastring = "TOSHIBA";
- UBYTE *buf = g_cdda_std_buf;
-
- #if STD_BUFSIZE > 255
- cmd[4] = 0xff;
- #else
- cmd[4] = STD_BUFSIZE & 0xff;
- #endif
-
- Do_SCSI_Command (cmd, 6, -1, TRUE, SCSIF_READ);
-
- if ((buf[0] & 0x1f) != 5)
- Fatal_Error ("not a CD-ROM device\n");
-
- if (!memcmp(applecd300string,
- &buf[8],
- strlen(applecd300string))) {
- g_whatdrive = APPLECD300;
- }
- else if (!memcmp(toshibastring,
- &buf[8],
- strlen(toshibastring))) {
- g_whatdrive = TOSHIBA;
- }
- else
- Fatal_Error ("unsupported CD-ROM drive\n");
- }
-
- void Read_TOC (void)
- {
- static UBYTE cmd[10] = { 0x43, 0, 0, 0, 0, 0, 1,
- STD_BUFSIZE >> 8, STD_BUFSIZE & 0xFF,
- 0, };
- UBYTE *buf = g_cdda_std_buf;
-
- Do_SCSI_Command (cmd, 10, -1, TRUE, SCSIF_READ);
- g_toc_length = ((buf[0] << 8) + buf[1] - 2) / 8;
- memcpy (g_toc, buf + 4, 8 * g_toc_length);
- }
-
- void Enable_Track_Buttons (void)
- {
- int i, foo;
-
- for (i=0; i<g_toc_length; i++) {
- /* ENFORCER HIT, because if () {statement} is executed, even
- * though expression evalutes to 0 with SAS/C 6.50.
- * (added foo to avoid problem <HR>)
- */
- foo = g_toc[i].track_number;
- if (foo <= 20 &&
- !(g_toc[i].flags & 4)) {
- GT_SetGadgetAttrs (g_gadgets[g_toc[i].track_number],
- g_window, NULL,
- GA_Disabled, FALSE,
- TAG_END);
- }
- }
- }
-
- long Track_Address (int p_track)
- {
- int i;
-
- for (i=0; i<g_toc_length; i++) {
- if (g_toc[i].track_number == p_track) {
- if (g_toc[i].flags & 4)
- return -1;
- return g_toc[i].address;
- }
- }
- return -1;
- }
-
- int First_Track (void)
- {
- int i;
-
- for (i=0; i<g_toc_length; i++) {
- if (g_toc[i].track_number != 0xAA &&
- !(g_toc[i].flags & 4))
- return g_toc[i].track_number;
- }
- return 0;
- }
-
- long Next_Track (int p_offset)
- {
- int track = (g_track >> 4) * 10 + (g_track & 15);
- long res;
-
- track += p_offset;
- res = Track_Address (track);
- return res == -1 ? Track_Address (track - p_offset) : res;
- }
-
- void NTSC_or_PAL (void)
- {
- if (GfxBase->DisplayFlags & PAL)
- g_period = 3546895 / (44100 / g_compression_factor);
- else
- g_period = 3579545 / (44100 / g_compression_factor);
- }
-
- void Init_Idle_Mode (void)
- {
- GT_SetGadgetAttrs (g_gadgets[GID_STOP], g_window, NULL,
- GA_Disabled, TRUE, TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_START], g_window, NULL,
- GA_Disabled, FALSE, TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_SAMPLING_RATE], g_window, NULL,
- GA_Disabled, FALSE, TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_BUFFERS], g_window, NULL,
- GA_Disabled, FALSE, TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_PREV], g_window, NULL,
- GA_Disabled, TRUE, TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_NEXT], g_window, NULL,
- GA_Disabled, TRUE, TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_TRACK], g_window, NULL,
- GTTX_Text, "", TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_INDEX], g_window, NULL,
- GTTX_Text, "", TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_TIME], g_window, NULL,
- GTTX_Text, "", TAG_END);
- }
-
- void Init_Play_Mode (void)
- {
- GT_SetGadgetAttrs (g_gadgets[GID_STOP], g_window, NULL,
- GA_Disabled, FALSE, TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_START], g_window, NULL,
- GA_Disabled, TRUE, TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_SAMPLING_RATE], g_window, NULL,
- GA_Disabled, TRUE, TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_BUFFERS], g_window, NULL,
- GA_Disabled, TRUE, TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_PREV], g_window, NULL,
- GA_Disabled, FALSE, TAG_END);
- GT_SetGadgetAttrs (g_gadgets[GID_NEXT], g_window, NULL,
- GA_Disabled, FALSE, TAG_END);
- g_track = g_index = g_minute = g_seconds = 0xFF;
- }
-
- int Get_Intui_Message (long *p_sec_no)
- {
- struct IntuiMessage *imsg;
- struct Gadget *gad;
- ULONG class;
- UWORD code;
-
- if (imsg = GT_GetIMsg (g_window->UserPort)) {
- class = imsg->Class;
- code = imsg->Code;
- gad = (struct Gadget *) imsg->IAddress;
- GT_ReplyIMsg (imsg);
- switch (class) {
- case IDCMP_CLOSEWINDOW: {
- g_bye = TRUE;
- return TRUE;
- }
- case IDCMP_GADGETUP:
- if (gad->GadgetID <= 20)
- *p_sec_no = Track_Address (gad->GadgetID);
- else if (gad->GadgetID == GID_STOP)
- return TRUE;
- else if (gad->GadgetID == GID_VOLUME)
- g_volume = code + 1;
- else if (gad->GadgetID == GID_PREV)
- *p_sec_no = Next_Track (-1);
- else if (gad->GadgetID == GID_NEXT)
- *p_sec_no = Next_Track (+1);
- break;
- default:
- break;
- }
- }
- return FALSE;
- }
-
- #define INC_SEC(ptr,inc) *(ptr) += (inc)
-
- void main (int argc, char *argv[])
- {
- short i=0;
- long sec_no;
- char *err;
- struct IntuiMessage *imsg;
- t_bool done;
- struct Gadget *gad;
- ULONG class;
- UWORD code;
- char *error_msg = NULL;
-
- atexit (Cleanup);
-
- g_called_from_cli = (argc > 0);
-
- if (g_called_from_cli) {
- static UBYTE* template = (UBYTE *)
- "DEVICE/A,UNIT/A/N,CHIP/S,FAST/S,DMA/S,ANY/S,"
- "LOW/S,MEDIUM/S,HIGH/S";
- enum Arg {
- ARG_DEVICE,
- ARG_UNIT,
- ARG_CHIP,
- ARG_FAST,
- ARG_DMA,
- ARG_ANY,
- ARG_LOW,
- ARG_MEDIUM,
- ARG_HIGH,
- ARGCOUNT
- };
- static LONG args[ARGCOUNT];
- struct RDArgs* rd;
- if (rd = ReadArgs (template, args, NULL)) {
- int cnt_mem = 0;
- int cnt_vol = 0;
- strcpy (g_scsi_device, (char*) (args[ARG_DEVICE]));
- g_scsi_id = args[ARG_UNIT];
- if (args[ARG_CHIP])
- g_memory_type = MEMF_CHIP, cnt_mem++;
- if (args[ARG_FAST])
- g_memory_type = MEMF_FAST, cnt_mem++;
- if (args[ARG_DMA])
- g_memory_type = MEMF_24BITDMA, cnt_mem++;
- if (args[ARG_ANY])
- g_memory_type = MEMF_ANY, cnt_mem++;
- if (args[ARG_LOW])
- g_volume = 1, cnt_vol++;
- if (args[ARG_MEDIUM])
- g_volume = 2, cnt_vol++;
- if (args[ARG_HIGH])
- g_volume = 3, cnt_vol++;
-
- FreeArgs (rd);
-
- if (cnt_mem > 1)
- Fatal_Error ("Only ONE memory option may be used!");
- if (cnt_vol > 1)
- Fatal_Error ("Only ONE volume option may be used!");
- } else
- Fatal_Error ("Args do not match template %s\n", template);
-
- strcpy (g_scsi_device, argv[1]);
- g_scsi_id = atoi (argv[2]);
- } else {
- char *str;
- UBYTE **toolarray;
- struct WBStartup *wbench_msg;
- struct DiskObject *dobj;
-
- if (!(IconBase = OpenLibrary ((UBYTE *) "icon.library", 37)))
- exit (1);
- wbench_msg = (struct WBStartup *) argv;
- dobj = GetDiskObject ((UBYTE *) wbench_msg->sm_ArgList->wa_Name);
- if (!dobj)
- exit (1);
- toolarray = (UBYTE **) dobj->do_ToolTypes;
- str = (char *) FindToolType (toolarray, (UBYTE *) "DEVICE");
- if (!str)
- error_msg = "Tool type DEVICE is missing";
- strcpy (g_scsi_device, str);
- str = (char *) FindToolType (toolarray, (UBYTE *) "UNIT");
- if (!str)
- error_msg = "Tool type UNIT is missing";
- g_scsi_id = atoi (str);
- str = (char *) FindToolType (toolarray, (UBYTE *) "MEMORY");
- if (str) {
- if (strcmp (str, "CHIP") == 0)
- g_memory_type = MEMF_CHIP;
- else if (strcmp (str, "FAST") == 0)
- g_memory_type = MEMF_FAST;
- else if (strcmp (str, "DMA") == 0)
- g_memory_type = MEMF_24BITDMA;
- else if (strcmp (str, "ANY") == 0)
- g_memory_type = MEMF_ANY;
- else
- error_msg = "Invalid MEMORY tool type";
- }
- str = (char *) FindToolType (toolarray, (UBYTE *) "VOLUME");
- if (str) {
- if (strcmp (str, "LOW") == 0)
- g_volume = 1;
- else if (strcmp (str, "MEDIUM") == 0)
- g_volume = 2;
- else if (strcmp (str, "HIGH") == 0)
- g_volume = 3;
- else
- error_msg = "Invalid VOLUME tool type";
- };
- FreeDiskObject (dobj);
- }
-
- err = Open_User_Interface ();
- if (err)
- Fatal_Error ("ERROR: %s", err);
-
- if (error_msg)
- Fatal_Error ("%s", error_msg);
-
- Alloc_CDROM ();
-
- Read_Drive_Type ();
-
- if (g_whatdrive == TOSHIBA)
- Select_Block_Format (FORMAT_CDDA);
-
- Read_TOC ();
-
- Enable_Track_Buttons ();
-
- if (!First_Track ())
- Fatal_Error ("This is no audio disk");
-
- while (!g_bye) {
-
- Init_Idle_Mode ();
-
- done = FALSE;
- while (!done) {
- Wait (1 << g_window->UserPort->mp_SigBit);
- while (imsg = GT_GetIMsg (g_window->UserPort)) {
- class = imsg->Class;
- code = imsg->Code;
- gad = (struct Gadget *) imsg->IAddress;
- GT_ReplyIMsg (imsg);
- switch (class) {
- case IDCMP_CLOSEWINDOW:
- Select_Block_Format (FORMAT_STD);
- exit (0);
- case IDCMP_GADGETUP:
- if (gad->GadgetID <= 20) {
- sec_no = Track_Address (gad->GadgetID);
- done = TRUE;
- } else if (gad->GadgetID == GID_START) {
- sec_no = Track_Address (First_Track ());
- done = TRUE;
- } else if (gad->GadgetID == GID_VOLUME)
- g_volume = code + 1;
- else if (gad->GadgetID == GID_SAMPLING_RATE) {
- static short factors[] = { 2, 3, 4, 6, 7 };
- g_compression_factor = factors[code];
- } else if (gad->GadgetID == GID_BUFFERS) {
- static short buffers[] = { 2, 4, 8, 16, 32, 64 };
- g_buffers = buffers[code];
- }
- break;
- default:
- break;
- }
- }
- }
-
- Init_Play_Mode ();
-
- NTSC_or_PAL ();
- Alloc_Audio ();
-
- Start_CDROM_Read (0, sec_no);
- #ifndef HRDBLBF
- Wait_CDROM_Read ();
- #else
- Wait_CDROM_Read (0);
- #endif
-
- INC_SEC (&sec_no, g_buffers);
- Start_CDROM_Read (1, sec_no);
- Convert_Buffer (0);
- #ifndef HRDBLBF
- Wait_CDROM_Read ();
- #else
- Wait_CDROM_Read (1);
- #endif
- Convert_Buffer (1);
- Start_Play_Audio (0);
- Start_Play_Audio (1);
- INC_SEC (&sec_no, g_buffers);
- Start_CDROM_Read (0, sec_no);
-
- for (;;) {
- /* HERE: scsi-request i is active,
- play-audio i is active and
- play-audio 1-i is queued */
-
- if (Get_Intui_Message (&sec_no))
- break;
- #ifndef HRDBLBF
- Wait_CDROM_Read ();
- #else
- Wait_CDROM_Read (i);
- #endif
- INC_SEC (&sec_no, g_buffers);
- Start_CDROM_Read (1-i, sec_no);
- Wait_Play_Audio (i);
- Convert_Buffer (i);
- Start_Play_Audio (i);
- i = 1-i;
- }
-
- #ifndef HRDBLBF
- Wait_CDROM_Read ();
- #else
- Wait_CDROM_Read (0);
- Wait_CDROM_Read (1);
- #endif
- Wait_Play_Audio (i);
- Wait_Play_Audio (1-i);
-
- Cleanup_Audio ();
- }
-
- if (g_whatdrive == TOSHIBA)
- Select_Block_Format (FORMAT_STD);
-
- exit (0);
- }
-
-