aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Input/in_cdda/windac
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Plugins/Input/in_cdda/windac')
-rw-r--r--Src/Plugins/Input/in_cdda/windac/Aspi.h410
-rw-r--r--Src/Plugins/Input/in_cdda/windac/Aspifunc.cpp378
-rw-r--r--Src/Plugins/Input/in_cdda/windac/Aspifunc.h101
-rw-r--r--Src/Plugins/Input/in_cdda/windac/Dac32.cpp2667
-rw-r--r--Src/Plugins/Input/in_cdda/windac/Dac32.dsp127
-rw-r--r--Src/Plugins/Input/in_cdda/windac/Dac32.h775
-rw-r--r--Src/Plugins/Input/in_cdda/windac/Dac32.mak285
-rw-r--r--Src/Plugins/Input/in_cdda/windac/Dac32.rc121
-rw-r--r--Src/Plugins/Input/in_cdda/windac/NTScsi.cpp501
-rw-r--r--Src/Plugins/Input/in_cdda/windac/NTScsi.h147
-rw-r--r--Src/Plugins/Input/in_cdda/windac/RESOURCE.H17
-rw-r--r--Src/Plugins/Input/in_cdda/windac/SCSIDEFS.H252
-rw-r--r--Src/Plugins/Input/in_cdda/windac/Winaspi.h229
13 files changed, 6010 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_cdda/windac/Aspi.h b/Src/Plugins/Input/in_cdda/windac/Aspi.h
new file mode 100644
index 00000000..cc55c36e
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/Aspi.h
@@ -0,0 +1,410 @@
+#ifndef ASPI_INCLUDED
+#define ASPI_INCLUDED
+
+#include <Windows.h>
+#include <Stdio.h>
+#include <Stdlib.h>
+
+// Handle to the ASPI libaray
+extern HINSTANCE hAspiLib;
+void GetAspiError(int nErrorCode,LPSTR lpszError);
+
+// 1 byte alignment or SCSI structures
+#pragma pack(push,1)
+
+#define MAX_SCSIDEVICES 16
+
+
+#define TIMEOUT 10000
+
+
+typedef void (*POSTPROCFUNC)();
+
+typedef struct TOC_TAG
+{
+ BYTE _reserved1;
+ BYTE bFlags;
+ BYTE bTrack;
+ BYTE _reserved2;
+ DWORD dwStartSector;
+} TOC;
+
+
+// The SRB_Flags are defined below. These flags may be OR'd together to form
+// the final value for SRB_Flags in the SRB. Note that SRB_POSTING and
+// SRB_EVENT_NOTIFY are mutually exclusive, as are SRB_DIR_IN and SRB_DIR_OUT. In
+// addition, the directioin bits (SRB_DIR_IN and SRB_DIR_OUT) MUST be set
+// correctly on commands which transfer data. Using SRB_DIR_SCSI is no longer
+// an option as in ASPI for DOS and ASPI for Win16.
+
+#define SRB_POSTING 0x01 // Enable ASPI command completion posting. See section on posting below.
+#define SRB_ENABLE_RESIDUAL_COUNT 0x04 // Enables reporting of residual byte count.This flag is only significant if the host adapter reports support for residual byte count in the SC_HA_INQUIRY command. When data underrun occurs, the SRB_BufLen field is updated to reflect the remaining bytes to transfer.
+#define SRB_DIR_IN 0x08 // Data transfer from SCSI target to host.
+#define SRB_DIR_OUT 0x10 // Data transfer from host to SCSI target.
+#define SRB_EVENT_NOTIFY 0x40 // Enable ASPI command event notification. See section on event notification below.
+
+
+// Inquiry DeviceTypeCodes
+#define DTC_DISK 0x00 // Direct-access device
+#define DTC_TAPE 0x01 // Sequential-access device
+#define DTC_PRINTER 0x02 // Printer device
+#define DTC_PROCESSOR 0x03 // Processor device
+#define DTC_WORM 0x04 // Write-once device
+#define DTC_CDROM 0x05 // CD-ROM device
+#define DTC_SCANNER 0x06 // Scanner device
+#define DTC_OPTICAL 0x07 // Optical memory device
+#define DTC_JUKEBOX 0x08 // Medium changer device
+#define DTC_COMM 0x09 // Communications device
+#define DTC_PREPRESS1 0x0A // Pre-press device 1
+#define DTC_PREPRESS2 0x0B // Pre-press device 2
+#define DTC_UNKNOWN 0x1F // Unknown or no device type
+
+
+/***************************************************************************
+ ** SRB Status
+ ***************************************************************************/
+#define SS_PENDING 0x00 /* SRB being processed */
+#define SS_COMP 0x01 /* SRB completed without error */
+#define SS_ABORTED 0x02 /* SRB aborted */
+#define SS_ABORT_FAIL 0x03 /* Unable to abort SRB */
+#define SS_ERR 0x04 /* SRB completed with error */
+#define SS_INVALID_CMD 0x80 /* Invalid ASPI command */
+#define SS_INVALID_HA 0x81 /* Invalid host adapter number */
+#define SS_NO_DEVICE 0x82 /* SCSI device not installed */
+#define SS_INVALID_SRB 0xE0 /* Invalid parameter set in SRB */
+#define SS_OLD_MANAGER 0xE1 /* ASPI manager doesn't support */
+ /* windows */
+#define SS_BUFFER_ALIGN 0xE1 /* Buffer not aligned (replaces */
+ /* SS_OLD_MANAGER in Win32) */
+#define SS_ILLEGAL_MODE 0xE2 /* Unsupported Windows mode */
+#define SS_NO_ASPI 0xE3 /* No ASPI managers */
+#define SS_FAILED_INIT 0xE4 /* ASPI for windows failed init */
+#define SS_ASPI_IS_BUSY 0xE5 /* No resources available to */
+ /* execute command */
+#define SS_BUFFER_TO_BIG 0xE6 /* Buffer size too big to handle */
+#define SS_BUFFER_TOO_BIG 0xE6 /* Correct spelling of 'too' */
+#define SS_MISMATCHED_COMPONENTS 0xE7 /* The DLLs/EXEs of ASPI don't */
+ /* version check */
+#define SS_NO_ADAPTERS 0xE8 /* No host adapters to manager */
+#define SS_INSUFFICIENT_RESOURCES 0xE9 /* Couldn't allocate resources */
+ /* needed to init */
+#define SS_ASPI_IS_SHUTDOWN 0xEA /* Call came to ASPI after */
+ /* PROCESS_DETACH */
+#define SS_BAD_INSTALL 0xEB /* The DLL or other components */
+ /* are installed wrong */
+
+
+// SRB defines
+#define SC_HA_INQUIRY 0x00 // Get information about installed host adapters,including the number of installed adapters.
+#define SC_GET_DEV_TYPE 0x01 // Get information about installed SCSI devices.
+#define SC_EXEC_SCSI_CMD 0x02 // Execute SCSI I/O.
+#define SC_ABORT_SRB 0x03 // Abort an outstanding I/O request.
+#define SC_RESET_DEV 0x04 // Reset an individual SCSI target.
+#define SC_GET_DISK_INFO 0x06 // Get information on disk type SCSI devices (not available under Windows NT).
+#define SC_GETSET_TIMEOUTS 0x08
+
+// MISC defines
+#define CDSAMPLEFREQ 44100
+#define TRACKSPERSEC 75
+
+#define CB_CDDASECTOR 2352
+#define CB_QSUBCHANNEL 0
+#define CB_CDROMSECTOR 2048
+#define CB_AUDIO (CB_CDDASECTOR-CB_QSUBCHANNEL)
+
+
+
+typedef struct
+{
+ BYTE SRB_Cmd; // ASPI command code
+ BYTE SRB_Status; // ASPI command status byte
+ BYTE SRB_HaId; // ASPI host adapter number
+ BYTE SRB_Flags; // ASPI request flags
+ DWORD SRB_Hdr_Rsvd; // Reserved, MUST = 0
+} SRB_HEADER, *LPSRB;
+
+
+typedef struct
+{
+ BYTE SRB_Cmd; // ASPI command code = SC_HA_INQUIRY
+ BYTE SRB_Status; // ASPI command status byte
+ BYTE SRB_HaId; // ASPI host adapter number
+ BYTE SRB_Flags; // ASPI request flags
+ DWORD SRB_Hdr_Rsvd; // Reserved, MUST = 0
+ BYTE HA_Count; // Number of host adapters present
+ BYTE HA_SCSI_ID; // SCSI ID of host adapter
+ BYTE HA_ManagerId[16]; // String describing the manager
+ BYTE HA_Identifier[16]; // String describing the host adapter
+ BYTE HA_Unique[16]; // Host Adapter Unique parameters
+ WORD HA_Rsvd1;
+} SRB_HAINQUIRY, *LPSRB_HAINQUIRY;
+
+
+typedef struct
+{
+ BYTE SRB_Cmd; // ASPI command code = SC_GET_DEV_TYPE
+ BYTE SRB_Status; // ASPI command status byte
+ BYTE SRB_HaId; // ASPI host adapter number
+ BYTE SRB_Flags; // Reserved
+ DWORD SRB_Hdr_Rsvd; // Reserved
+ BYTE SRB_Target; // Target's SCSI ID
+ BYTE SRB_Lun; // Target's LUN number
+ BYTE SRB_DeviceType; // Target's peripheral device type
+ BYTE SRB_Rsvd1; // Reserved for alignment
+} SRB_GDEVBLOCK, *LPSRB_GDEVBLOCK;
+
+
+#define SENSE_LEN 14 // Maximum sense length
+
+
+typedef struct
+{
+ BYTE SRB_Cmd; // ASPI command code = SC_EXEC_SCSI_CMD
+ BYTE SRB_Status; // ASPI command status byte
+ BYTE SRB_HaId; // ASPI host adapter number
+ BYTE SRB_Flags; // ASPI request flags
+ DWORD SRB_Hdr_Rsvd; // Reserved
+ BYTE SRB_Target; // Target's SCSI ID
+ BYTE SRB_Lun; // Target's LUN number
+ WORD SRB_Rsvd1; // Reserved for Alignment
+ DWORD SRB_BufLen; // Data Allocation Length
+ BYTE *SRB_BufPointer; // Data Buffer Point
+ BYTE SRB_SenseLen; // Sense Allocation Length
+ BYTE SRB_CDBLen; // CDB Length
+ BYTE SRB_HaStat; // Host Adapter Status
+ BYTE SRB_TargStat; // Target Status
+ void (*SRB_PostProc)(); // Post routine
+ void *SRB_Rsvd2; // Reserved
+ BYTE SRB_Rsvd3[16]; // Reserved for expansion
+ BYTE CDBByte[16]; // SCSI CDB
+ BYTE SenseArea[SENSE_LEN+2]; // Request Sense buffer
+} SRB_EXECSCSICMD, *LPSRB_EXECSCSICMD;
+
+
+typedef struct
+{
+ BYTE SRB_Cmd; // ASPI command code = SC_EXEC_SCSI_CMD
+ BYTE SRB_Status; // ASPI command status byte
+ BYTE SRB_HaId; // ASPI host adapter number
+ BYTE SRB_Flags; // Reserved
+ DWORD SRB_Hdr_Rsvd; // Reserved
+ BYTE SRB_Target; // Target's SCSI ID
+ BYTE SRB_Lun; // Target's LUN number
+ BYTE SRB_DriveFlags; // Driver flags
+ BYTE SRB_Int13HDriveInfo;// Host Adapter Status
+ BYTE SRB_Heads; // Preferred number of heads translation
+ BYTE SRB_Sectors; // Preferred number of sectors translation
+ BYTE SRB_Rsvd1[10]; // Reserved
+} SRB_GETDISKINFO, *LPSRB_GETDISKINFO;
+
+
+
+typedef struct
+{
+ BYTE SRB_Cmd; // ASPI command code = SC_RESET_DEV
+ BYTE SRB_Status; // ASPI command status byte
+ BYTE SRB_HaId; // ASPI host adapter number
+ BYTE SRB_Flags; // Reserved
+ DWORD SRB_Hdr_Rsvd; // Reserved
+ BYTE SRB_Target; // Target's SCSI ID
+ BYTE SRB_Lun; // Target's LUN number
+ BYTE SRB_Rsvd1[12]; // Reserved for Alignment
+ BYTE SRB_HaStat; // Host Adapter Status
+ BYTE SRB_TargStat; // Target Status
+ void *SRB_PostProc; // Post routine
+ void *SRB_Rsvd2; // Reserved
+ BYTE SRB_Rsvd3[32]; // Reserved
+} SRB_BUSDEVICERESET, *LPSRB_BUSDEVICERESET;
+
+
+typedef struct
+{
+ BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_ABORT_SRB */
+ BYTE SRB_Status; /* 01/001 ASPI command status byte */
+ BYTE SRB_HaID; /* 02/002 ASPI host adapter number */
+ BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */
+ DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */
+ void *SRB_ToAbort; /* 08/008 Pointer to SRB to abort */
+} SRB_Abort, *PSRB_Abort, FAR *LPSRB_Abort;
+
+
+typedef unsigned char Ucbit;
+typedef unsigned char u_char;
+
+#define MP_P_CODE \
+ Ucbit p_code : 6; \
+ Ucbit p_res : 1; \
+ Ucbit parsave : 1
+
+
+// CD Cap / mech status
+typedef struct SCSICDMODEPAGE2A_TAG
+{
+ MP_P_CODE; // parsave & pagecode (0)
+ u_char p_len; // 0x14 = 20 Bytes (1)
+
+ Ucbit cd_r_read : 1; // Reads CD-R media (2)
+ Ucbit cd_rw_read : 1; // Reads CD-RW media
+ Ucbit method2 : 1; // Reads fixed packet method2 media
+ Ucbit dvd_rom_read: 1; // Reads DVD ROM media
+ Ucbit dvd_r_read : 1; // Reads DVD-R media
+ Ucbit dvd_ram_read: 1; // Reads DVD-RAM media
+ Ucbit res_2_67 : 2; // Reserved
+
+ Ucbit cd_r_write : 1; // Supports writing CD-R media (3)
+ Ucbit cd_rw_write : 1; // Supports writing CD-RW media
+ Ucbit test_write : 1; // Supports emulation write
+ Ucbit res_3_3 : 1; // Reserved
+ Ucbit dvd_r_write : 1; // Supports writing DVD-R media
+ Ucbit dvd_ram_write: 1; // Supports writing DVD-RAM media
+ Ucbit res_3_67 : 2; // Reserved
+
+ Ucbit audio_play : 1; // Supports Audio play operation (4)
+ Ucbit composite : 1; // Deliveres composite A/V stream
+ Ucbit digital_port_2: 1; // Supports digital output on port 2
+ Ucbit digital_port_1: 1; // Supports digital output on port 1
+ Ucbit mode_2_form_1: 1; // Reads Mode-2 form 1 media (XA)
+ Ucbit mode_2_form_2: 1; // Reads Mode-2 form 2 media
+ Ucbit multi_session: 1; // Reads multi-session media
+ Ucbit res_4 : 1; // Reserved
+
+ Ucbit cd_da_supported: 1; // Reads audio data with READ CD cmd
+ Ucbit cd_da_accurate: 1; // READ CD data stream is accurate
+ Ucbit rw_supported: 1; // Reads R-W sub channel information
+ Ucbit rw_deint_cor: 1; // Reads de-interleved R-W sub chan
+ Ucbit c2_pointers : 1; // Supports C2 error pointers
+ Ucbit ISRC : 1; // Reads ISRC information
+ Ucbit UPC : 1; // Reads media catalog number (UPC)
+ Ucbit read_bar_code: 1; // Supports reading bar codes
+
+ Ucbit lock : 1; // PREVENT/ALLOW may lock media (5)
+ Ucbit lock_state : 1; // Lock state 0=unlocked 1=locked
+ Ucbit prevent_jumper: 1; // State of prev/allow jumper 0=pres
+ Ucbit eject : 1; // Ejects disc/cartr with STOP LoEj
+ Ucbit res_6_4 : 1; // Reserved
+ Ucbit loading_type: 3; // Loading mechanism type
+
+ Ucbit sep_chan_vol: 1; // Vol controls each channel separat (6)
+ Ucbit sep_chan_mute: 1; // Mute controls each channel separat
+ Ucbit disk_present_rep:1; // Changer supports disk present rep
+ Ucbit sw_slot_sel:1; // Load empty slot in changer
+ Ucbit res_7 : 4; // Reserved
+
+ BYTE ReadSpeedH; // Max. read speed in KB/s (7)
+ BYTE ReadSpeedL; // Max. read speed in KB/s (7)
+
+ u_char num_vol_levels[2]; // # of supported volume levels (9)
+
+ u_char buffer_size[2]; // Buffer size for the data in KB (11)
+ u_char cur_read_speed[2]; // Current read speed in KB/s (13)
+ u_char res_16; // Reserved (14)
+
+ Ucbit res_17_0: 1; // Reserved (15)
+ Ucbit BCK : 1; // Data valid on falling edge of BCK
+ Ucbit RCK : 1; // Set: HIGH high LRCK=left channel
+ Ucbit LSBF : 1; // Set: LSB first Clear: MSB first
+ Ucbit length : 2; // 0=32BCKs 1=16BCKs 2=24BCKs 3=24I2c
+ Ucbit res_17 : 2; // Reserved
+
+ u_char max_write_speed[2]; // Max. write speed supported in KB/s (17)
+
+ u_char cur_write_speed[2]; // Current write speed in KB/s (19)
+
+} SCSICDMODEPAGE2A;
+
+char *fillbytes(void *tov, int cnt, char val);
+
+
+typedef struct SCISMODEHEADER_TAG {
+ Ucbit sense_data_len : 8;
+ u_char medium_type;
+ Ucbit res2 : 4;
+ Ucbit cache : 1;
+ Ucbit res : 2;
+ Ucbit write_prot : 1;
+ BYTE nBlockLen;
+} SCISMODEHEADER;
+
+typedef struct SCSIMODEHDR_6_TAG {
+ BYTE btModeDataLen; // 0
+ BYTE btMediumType; // 1
+ BYTE btDevSpecificParam; // 2
+ BYTE btBlkDescrLen; // 3
+} SCSIMODEHDR_6;
+
+
+typedef struct SCSIMODEHDR_10_TAG {
+ BYTE btModeDataLenH; // 0
+ BYTE btModeDataLenL; // 1
+ BYTE btMediumType; // 2
+ BYTE btDevSpecificParam; // 3
+ BYTE btReserved1; // 4
+ BYTE btReserved2; // 5
+ BYTE btBlkDescrLenH; // 6
+ BYTE btBlkDescrLenL; // 7
+} SCSIMODEHDR_10;
+
+typedef struct SCSIBLOCKDESCRIPTOR_TAG {
+ BYTE btDensity; // 0
+ BYTE btNumberOfBlocksH; // 1
+ BYTE btNumberOfBlocksM; // 2
+ BYTE btNumberOfBlocksL; // 3
+ BYTE btReserved; // 4
+ BYTE btBlockLenH; // 5
+ BYTE btBlockLenM; // 6
+ BYTE btBlockLenL; // 7
+} SCSIBLOCKDESCRIPTOR;
+
+
+
+
+// Error recovery Parameters
+typedef struct SCSICDMODEPAGE1A_TAG{
+ MP_P_CODE; // 0 parsave & pagecode
+ u_char p_len; // 1 0x0A = 12 Bytes
+ Ucbit disa_correction : 1; // 2 Byte 2
+ Ucbit term_on_rec_err : 1;
+ Ucbit report_rec_err : 1;
+ Ucbit en_early_corr : 1;
+ Ucbit read_continuous : 1;
+ Ucbit tranfer_block : 1;
+ Ucbit en_auto_reall_r : 1;
+ Ucbit en_auto_reall_w : 1;
+ u_char rd_retry_count; // 3 Byte 3
+ u_char correction_span; // 4
+ char head_offset_count; // 5
+ char data_strobe_offset; // 6
+ u_char res; // 7
+ u_char wr_retry_count; // 8
+ u_char res_tape[2]; // 9
+ u_char recov_timelim[2]; // 11
+} SCSICDMODEPAGE1A;
+
+
+
+
+typedef struct
+{
+ BYTE SRB_Cmd; // ASPI command code = SC_GETSET_TIMEOUTS
+ BYTE SRB_Status; // ASPI command status byte
+ BYTE SRB_HaId; // ASPI host adapter number
+ BYTE SRB_Flags; // ASPI request flags
+ DWORD SRB_Hdr_Rsvd; // Reserved
+ BYTE SRB_Target; // Target's SCSI ID
+ BYTE SRB_Lun; // Target's LUN number
+ DWORD SRB_Timeout; // Timeout in half seconds
+}
+SRB_GetSetTimeouts, *PSRB_GetSetTimeouts;
+
+typedef struct
+{
+ LPBYTE AB_BufPointer; // Pointer to the ASPI allocated buffer
+ DWORD AB_BufLen; // Length in bytes of the buffer
+ DWORD AB_ZeroFill; // Flag set to 1 if buffer should be zeroed
+ DWORD AB_Reserved; // Reserved, MUST = 0
+}
+ASPI32BUFF, *PASPI32BUFF;
+
+#pragma pack(pop)
+
+#endif \ No newline at end of file
diff --git a/Src/Plugins/Input/in_cdda/windac/Aspifunc.cpp b/Src/Plugins/Input/in_cdda/windac/Aspifunc.cpp
new file mode 100644
index 00000000..ee8f3544
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/Aspifunc.cpp
@@ -0,0 +1,378 @@
+// ----------------------------------------------
+// - ASPIFUNC implementation file -
+// - Written 1996-1998 by Christoph Schmelnik -
+// ----------------------------------------------
+
+// Version 1.40 : 24.02.1998
+// Changes:
+// Set correct direction flags, to work with NT device IO interface and ATAPI drives
+// Added Immediate paremeter for WaitSCSIRequest to allow detection of buffer underruns
+
+#include <stddef.h>
+#include "aspifunc.h"
+
+HMODULE hDLL=0;
+VOIDPROC GetASPI32SupportInfo;
+SRBPROC SendASPI32Command;
+int ASPIInstalled;
+int RunningNT;
+int NumberOfHostAdapters;
+
+//Implementation of base ASPI Functions
+BOOL HAInquiry(int HostAdapterNumber,char *ManagerID, char *HAID,THAUnique &HAUnique)
+{
+ SRB_HAInquiry MySRB;
+ DWORD ASPI_Status;
+ memset(&MySRB,0,sizeof(SRB_HAInquiry));
+ MySRB.SRB_Cmd = SC_HA_INQUIRY;
+ MySRB.SRB_HaId = HostAdapterNumber;
+ MySRB.SRB_Flags = 0;
+ MySRB.SRB_Hdr_Rsvd = 0;
+ ASPI_Status = SendASPI32Command ( (LPSRB) &MySRB );
+ if (ASPI_Status!=SS_COMP)
+ return FALSE;
+ HAUnique=MySRB.HA_Unique;
+ for (int i=0; i<16; i++)
+ {
+ ManagerID[i]=MySRB.HA_ManagerId[i];
+ HAID[i]=MySRB.HA_Identifier[i];
+ }
+ ManagerID[16]=0;
+ HAID[16]=0;
+ return TRUE;
+}
+
+int GetDeviceType(int HostAdapterNumber,int TargetId,int LUN)
+{
+ SRB_GDEVBlock MySRB;
+ DWORD ASPI_Status;
+ memset(&MySRB,0,sizeof(SRB_GDEVBlock));
+ MySRB.SRB_Cmd = SC_GET_DEV_TYPE;
+ MySRB.SRB_HaId = HostAdapterNumber;
+ MySRB.SRB_Flags = 0;
+ MySRB.SRB_Hdr_Rsvd = 0;
+ MySRB.SRB_Target = TargetId;
+ MySRB.SRB_Lun = LUN;
+ ASPI_Status = SendASPI32Command ((LPSRB)&MySRB);
+ /***************************************************/
+ /* If ASPI_Status == SS_COMP, MySRB.SRB_DeviceType */
+ /* will contain the peripheral device type. */
+ /***************************************************/
+ if (ASPI_Status==SS_COMP)
+ return MySRB.SRB_DeviceType;
+ return DTYPE_UNKNOWN;
+}
+
+BOOL ExecuteSCSIRequest(int HostAdapterNumber,int TargetId,int LUN,int RequestFlags,
+ TOpcode OpC, BYTE OpCLen,void *DataPtr, int DataLen, HANDLE hDriveEvent)
+{
+ if ((HostAdapterNumber>=NumberOfHostAdapters) &&
+ RunningNT)
+ {
+ DWORD il, ol;
+ SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sb;
+ ZeroMemory(&sb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
+ sb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
+ sb.sptd.CdbLength = OpCLen;
+ sb.sptd.DataIn = ((SRB_DIR_IN & RequestFlags) ? 1/*SCSI_IOCTL_DATA_IN*/ : 0/*SCSI_IOCTL_DATA_OUT*/);
+ sb.sptd.SenseInfoLength = 32;
+ sb.sptd.DataTransferLength = DataLen;
+ sb.sptd.TimeOutValue = 2;
+ sb.sptd.DataBuffer = (unsigned char*) DataPtr;
+ sb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
+ for (int i=0; i<OpCLen; i++) sb.sptd.Cdb[i]=OpC[i];
+ il = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
+ if (DeviceIoControl(hDriveEvent, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sb, il, &sb, il, &ol, FALSE))
+ {
+ if (sb.sptd.ScsiStatus==0)
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+
+ SRB_ExecSCSICmd MySRB;
+ DWORD ASPI_Status;
+ DWORD ASPIEventStatus;
+ memset(&MySRB,0,sizeof(SRB_ExecSCSICmd));
+ MySRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
+ MySRB.SRB_HaId = HostAdapterNumber;
+ MySRB.SRB_Flags = RequestFlags|SRB_EVENT_NOTIFY;
+ MySRB.SRB_Hdr_Rsvd = 0;
+ MySRB.SRB_Target = TargetId;
+ MySRB.SRB_Lun = LUN;
+ MySRB.SRB_BufPointer = (unsigned char*) DataPtr;
+ MySRB.SRB_BufLen = DataLen;
+ MySRB.SRB_CDBLen = OpCLen;
+ MySRB.SRB_SenseLen = SENSE_LEN;
+ MySRB.SRB_PostProc = (void(__cdecl *)(void))hDriveEvent;
+ for (int i=0; i<OpCLen; i++) MySRB.CDBByte[i]=OpC[i];
+
+ ResetEvent(hDriveEvent);
+ ASPI_Status = SendASPI32Command ((LPSRB)&MySRB);
+
+ /**************************************************/
+ /* Block on event till signaled */
+ /**************************************************/
+
+ if ( MySRB.SRB_Status == SS_PENDING )
+ {
+ ASPIEventStatus = WaitForSingleObject(hDriveEvent, TIMEOUT);
+
+ /**************************************************/
+ /* Reset event to non-signaled state. */
+ /**************************************************/
+ if (ASPIEventStatus == WAIT_OBJECT_0)
+ ResetEvent(hDriveEvent);
+ else
+ {
+ OutputDebugString(L"Execute Timed out\n");
+ AbortSCSIRequest(MySRB);
+ }
+ }
+
+ if (MySRB.SRB_Status==SS_COMP)
+ return TRUE;
+
+ return FALSE;
+}
+
+void FillSCSIRequest(int HostAdapterNumber,int TargetId,int LUN,int RequestFlags,
+ TOpcode OpC, BYTE OpCLen,void *DataPtr, int DataLen,SRB_ExecSCSICmd &MySRB, HANDLE hDriveEvent)
+{
+ memset(&MySRB,0,sizeof(SRB_ExecSCSICmd));
+ MySRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
+ MySRB.SRB_HaId = HostAdapterNumber;
+ if ((HostAdapterNumber>=NumberOfHostAdapters) &&
+ RunningNT)
+ {
+ MySRB.SRB_Flags = RequestFlags;
+ }
+ else
+ {
+ MySRB.SRB_Flags = RequestFlags|SRB_EVENT_NOTIFY;
+ MySRB.SRB_Hdr_Rsvd = 0;
+ MySRB.SRB_PostProc = (void(__cdecl *)(void))hDriveEvent;
+ }
+ MySRB.SRB_Target = TargetId;
+ MySRB.SRB_Lun = LUN;
+ MySRB.SRB_BufPointer = (unsigned char*) DataPtr;
+ MySRB.SRB_BufLen = DataLen;
+ MySRB.SRB_CDBLen = OpCLen;
+ MySRB.SRB_SenseLen = SENSE_LEN;
+ for (int i=0; i<OpCLen; i++) MySRB.CDBByte[i]=OpC[i];
+}
+
+void ExecuteSCSIRequest(SRB_ExecSCSICmd &MySRB,HANDLE hDriveEvent)
+{
+ if ((MySRB.SRB_HaId>=NumberOfHostAdapters) &&
+ RunningNT)
+ {
+ DWORD il, ol;
+ SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sb;
+ ZeroMemory(&sb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
+ sb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
+ sb.sptd.PathId = 0;
+ sb.sptd.TargetId = 1;
+ sb.sptd.Lun = 0;
+ sb.sptd.CdbLength = MySRB.SRB_CDBLen;
+ sb.sptd.DataIn = MySRB.SRB_Flags;
+ sb.sptd.SenseInfoLength = 32;
+ sb.sptd.DataTransferLength = MySRB.SRB_BufLen;
+ sb.sptd.TimeOutValue = TIMEOUT;
+ sb.sptd.DataBuffer = MySRB.SRB_BufPointer;
+ sb.sptd.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
+ for (int i=0; i<MySRB.SRB_CDBLen; i++) sb.sptd.Cdb[i]=MySRB.CDBByte[i];
+ il = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
+ if (DeviceIoControl(hDriveEvent, IOCTL_SCSI_PASS_THROUGH_DIRECT,
+ &sb, il, &sb, il, &ol, NULL))
+ if (sb.sptd.ScsiStatus==0)
+ {
+ MySRB.SRB_Status=SS_COMP;
+ return;
+ }
+ MySRB.SRB_Status=SS_ERR;
+ return;
+ }
+ DWORD ASPI_Status;
+ ResetEvent(hDriveEvent);
+ ASPI_Status = SendASPI32Command ((LPSRB)&MySRB);
+}
+
+BYTE WaitSCSIRequest(SRB_ExecSCSICmd &MySRB,HANDLE hDriveEvent,BOOL bImmediate)
+{
+ if ((MySRB.SRB_HaId>=NumberOfHostAdapters) &&
+ RunningNT)
+ return MySRB.SRB_Status;
+ if ((MySRB.SRB_Status == SS_PENDING) &&
+ !bImmediate)
+ {
+ DWORD ASPIEventStatus = WaitForSingleObject(hDriveEvent, 100);
+
+ if (ASPIEventStatus == WAIT_OBJECT_0)
+ {
+ ResetEvent(hDriveEvent);
+ }
+ }
+
+ return MySRB.SRB_Status;
+}
+
+BOOL AbortSCSIRequest(SRB_ExecSCSICmd &StuckSRB)
+{
+ SRB_Abort AbortSRB;
+ DWORD ASPIStatus;
+ AbortSRB.SRB_Cmd = SC_ABORT_SRB;
+ AbortSRB.SRB_HaId = StuckSRB.SRB_HaId;
+ AbortSRB.SRB_Flags = 0;
+ AbortSRB.SRB_Hdr_Rsvd = 0;
+ AbortSRB.SRB_ToAbort = (LPSRB)&StuckSRB;
+ ASPIStatus = SendASPI32Command ( (LPSRB)&AbortSRB );
+ return (ASPIStatus==SS_COMP);
+}
+
+
+int GetDeviceInfo(int HostAdapterNumber,int TargetId,int LUN,BYTE &SCSIType,char *VendorID,
+ char *ProductID,char *ProductRevision,HANDLE hDriveEvent)
+{
+ struct InquireFormat
+ {
+ BYTE ConfigPara[8];
+ char VendorID[8];
+ char ProductID[16];
+ char ProductRevision[4];
+ } DeviceInfo;
+ TOpcode OpC;
+ OpC[0]=0x12;
+ OpC[1]=0;
+ OpC[2]=0;
+ OpC[3]=0;
+ OpC[4]=sizeof(DeviceInfo);
+ OpC[5]=0;
+ memset(&DeviceInfo,0,sizeof(DeviceInfo));
+ BOOL r=ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,6,(void*)&DeviceInfo,sizeof(DeviceInfo),hDriveEvent);
+ if (r)
+ {
+ for (int i=0; i<16; i++)
+ {
+ if (i<8) VendorID[i]=DeviceInfo.VendorID[i];
+ ProductID[i]=DeviceInfo.ProductID[i];
+ if (i<4) ProductRevision[i]=DeviceInfo.ProductRevision[i];
+ }
+ VendorID[8]=0;
+ ProductID[16]=0;
+ ProductRevision[4]=0;
+ SCSIType=DeviceInfo.ConfigPara[2] & 0x0f;
+ return DeviceInfo.ConfigPara[0];
+ }
+ return DTYPE_UNKNOWN;
+}
+
+BOOL TestUnitReady(int HostAdapterNumber,int TargetId,int LUN,HANDLE hDriveEvent)
+{
+ TOpcode OpC;
+ OpC[0]=0;
+ OpC[1]=0;
+ OpC[2]=0;
+ OpC[3]=0;
+ OpC[4]=0;
+ OpC[5]=0;
+ return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,6,NULL,0,hDriveEvent);
+}
+
+BOOL ModeSense(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,int PageCode,HANDLE hDriveEvent)
+{
+// while (!TestUnitReady(HostAdapterNumber,TargetId,LUN));
+ TOpcode OpC;
+ OpC[0]=0x1a;
+ OpC[1]=0x00;
+ OpC[2]=PageCode;
+ OpC[3]=0x00;
+ OpC[4]=Size;
+ OpC[5]=0x00;
+ return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,6,(void *)&ModeData,Size,hDriveEvent);
+}
+
+BOOL ATAPIModeSense(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,int PageCode,HANDLE hDriveEvent)
+{
+// while (!TestUnitReady(HostAdapterNumber,TargetId,LUN));
+ TOpcode OpC;
+ OpC[0]=0x5a;
+ OpC[1]=0x00;
+ OpC[2]=PageCode;
+ OpC[3]=0x00;
+ OpC[4]=0x00;
+ OpC[5]=0x00;
+ OpC[6]=0x00;
+ OpC[7]=0x00;
+ OpC[8]=Size;
+ OpC[9]=0x00;
+ OpC[10]=0x00;
+ OpC[11]=0x00;
+ return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,12,(void *)&ModeData,Size,hDriveEvent);
+}
+
+BOOL addModeSense(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,HANDLE hDriveEvent)
+{
+// while (!TestUnitReady(HostAdapterNumber,TargetId,LUN));
+ TOpcode OpC;
+ OpC[0]=0xca;
+ OpC[1]=0x08;
+ OpC[2]=0x0f;
+ OpC[3]=0x00;
+ OpC[4]=0x00;
+ OpC[5]=0x00;
+ OpC[6]=0x00;
+ OpC[7]=0x00;
+ OpC[8]=Size;
+ OpC[9]=0x00;
+ return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,10,(void *)&ModeData,Size,hDriveEvent);
+}
+
+BOOL ModeSelect(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,HANDLE hDriveEvent)
+{
+// while (!TestUnitReady(HostAdapterNumber,TargetId,LUN));
+ TOpcode OpC;
+ OpC[0]=0x15;
+ if (Size==12)
+ OpC[1]=0x00;
+ else
+ OpC[1]=0x10;
+ OpC[2]=0x00;
+ OpC[3]=0x00;
+ OpC[4]=Size;
+ OpC[5]=0x00;
+ return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_OUT,OpC,6,(void *)&ModeData,Size,hDriveEvent);
+}
+
+BOOL addModeSelect(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,HANDLE hDriveEvent)
+{
+// while (!TestUnitReady(HostAdapterNumber,TargetId,LUN));
+ TOpcode OpC;
+ OpC[0]=0xc5;
+ OpC[1]=0x10;
+ OpC[2]=0x00;
+ OpC[3]=0x00;
+ OpC[4]=0x00;
+ OpC[5]=0x00;
+ OpC[6]=0x00;
+ OpC[7]=0x00;
+ OpC[8]=Size;
+ OpC[9]=0x00;
+ return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_OUT,OpC,10,(void *)&ModeData,Size,hDriveEvent);
+}
+
+BOOL SCSIMaxBlocks(HANDLE fh, int *mb)
+{
+ DWORD ol;
+ IO_SCSI_CAPABILITIES ca;
+
+ if (DeviceIoControl(fh,IOCTL_SCSI_GET_CAPABILITIES,NULL,0,
+ &ca,sizeof(IO_SCSI_CAPABILITIES),&ol,NULL))
+ {
+ *mb=(int)ca.MaximumTransferLength;
+ return TRUE;
+ }
+ return FALSE;
+} \ No newline at end of file
diff --git a/Src/Plugins/Input/in_cdda/windac/Aspifunc.h b/Src/Plugins/Input/in_cdda/windac/Aspifunc.h
new file mode 100644
index 00000000..c63c2f81
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/Aspifunc.h
@@ -0,0 +1,101 @@
+// ----------------------------------------------
+// - ASPIFUNC header file -
+// - Written 1996-1998 by Christoph Schmelnik -
+// ----------------------------------------------
+
+// Version 1.40 : 24.02.1998
+// Changes:
+// function prototype for WaitSCSIRequest extended by immediate parameter
+
+#ifndef _ASPIFUNC_H
+#define _ASPIFUNC_H
+
+#ifndef STRICT
+#define STRICT // Enable strict tape checking
+#define WIN32_LEAN_AND_MEAN // Include only needed header files
+#endif
+#include <windows.h>
+#include <stdio.h>
+#include <winioctl.h>
+
+#include "winaspi.h"
+#include "scsidefs.h"
+
+/*#ifdef DLL
+#define DACDLL __declspec(dllexport)
+#else
+#define DACDLL __declspec(dllimport)
+#endif*/
+#define DACDLL
+
+typedef DWORD (__cdecl *VOIDPROC)();
+typedef DWORD (__cdecl *SRBPROC)(LPSRB);
+typedef BYTE TOpcode[30];
+
+// NT DeviceIO Structures
+#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER
+#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+typedef struct _IO_SCSI_CAPABILITIES {
+ ULONG Length;
+ ULONG MaximumTransferLength;
+ ULONG MaximumPhysicalPages;
+ ULONG SupportedAsynchronousEvents;
+ ULONG AlignmentMask;
+ BOOLEAN TaggedQueuing;
+ BOOLEAN AdapterScansDown;
+ BOOLEAN AdapterUsesPio;
+} IO_SCSI_CAPABILITIES, *PIO_SCSI_CAPABILITIES;
+
+typedef struct _SCSI_PASS_THROUGH_DIRECT {
+ USHORT Length;
+ UCHAR ScsiStatus;
+ UCHAR PathId;
+ UCHAR TargetId;
+ UCHAR Lun;
+ UCHAR CdbLength;
+ UCHAR SenseInfoLength;
+ UCHAR DataIn;
+ ULONG DataTransferLength;
+ ULONG TimeOutValue;
+ PVOID DataBuffer;
+ ULONG SenseInfoOffset;
+ UCHAR Cdb[16];
+} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
+
+typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER {
+ SCSI_PASS_THROUGH_DIRECT sptd;
+ ULONG Filler; // realign buffer to double word boundary
+ UCHAR ucSenseBuf[32];
+} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
+
+
+extern HMODULE hDLL;
+extern VOIDPROC GetASPI32SupportInfo;
+extern SRBPROC SendASPI32Command;
+extern int ASPIInstalled;
+extern int RunningNT;
+extern int NumberOfHostAdapters;
+
+// base ASPI functions
+int DACDLL GetDeviceType(int HostAdapterNumber,int TargetId,int LUN);
+BOOL ExecuteSCSIRequest(int HostAdapterNumber,int TargetId,int LUN,int RequestFlags,
+ TOpcode OpC, BYTE OpCLen,void *DataPtr, int DataLen,HANDLE hDriveEvent);
+void ExecuteSCSIRequest(SRB_ExecSCSICmd &MySRB,HANDLE hDriveEvent);
+void FillSCSIRequest(int HostAdapterNumber,int TargetId,int LUN,int RequestFlags,
+ TOpcode OpC, BYTE OpCLen,void *DataPtr, int DataLen,SRB_ExecSCSICmd &MySRB,HANDLE hDriveEvent);
+BYTE WaitSCSIRequest(SRB_ExecSCSICmd &MySRB,HANDLE hDriveEvent,BOOL bImmediate=FALSE);
+BOOL AbortSCSIRequest(SRB_ExecSCSICmd &StuckSRB);
+int GetDeviceInfo(int HostAdapterNumber,int TargetId,int LUN,BYTE &SCSIType,char *VendorID,
+ char *ProductID,char *ProductRevision,HANDLE hDriveEvent);
+BOOL HAInquiry(int HostAdapterNumber,char *ManagerID, char *HAID,THAUnique &HAUnique);
+BOOL TestUnitReady(int HostAdapterNumber,int TargetId,int LUN,HANDLE hDriveEvent);
+BOOL ModeSense(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,int PageCode,HANDLE hDriveEvent);
+BOOL ATAPIModeSense(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,int PageCode,HANDLE hDriveEvent);
+BOOL addModeSense(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,HANDLE hDriveEvent);
+BOOL ModeSelect(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,HANDLE hDriveEvent);
+BOOL addModeSelect(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,HANDLE hDriveEvent);
+BOOL SCSIMaxBlocks(HANDLE fh, int *mb);
+
+#endif //_ASPIFUNC_H \ No newline at end of file
diff --git a/Src/Plugins/Input/in_cdda/windac/Dac32.cpp b/Src/Plugins/Input/in_cdda/windac/Dac32.cpp
new file mode 100644
index 00000000..9172a1dd
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/Dac32.cpp
@@ -0,0 +1,2667 @@
+// ----------------------------------------------
+// - DAC32.DLL Implementations Datei -
+// - Written 1996-1998 by Christoph Schmelnik -
+// ----------------------------------------------
+
+// Version 1.33 : 18.01.1998
+// Changes:
+// Added speed selection support for all current Plextor drives
+//
+// Version 1.40 : 24.02.1998
+// Changes:
+// Set correct direction flags, to work with NT device IO interface and ATAPI drives
+// Changed main CD detection to TestUnitReady
+// Removed CD detection from Audio Status Info
+// Added hopefully correct read command for Matsushita/Panasonic drives
+// Added Parameters to CDAC class to allow the disabling of the audio test and to spin up the drive for a specified time
+// in seconds to avoid spin up problems on some drives. Both parameters have default values so it behaves like the old version
+// without the additional parameters
+// Added Parameter to the constructor of CWaveSave to disable writing any Headers. Also this parameter has a default to work like
+// before.
+// Added virtual function in CDAC to report buffer underruns in Burst Copy Mode
+// For the last feature an immediate parameter in WaitCDDA is added
+// GetLastSense function added to return the sense information for the last read audio command
+// Configuration in CMapDrive extended by new features
+// Added function to CD Class to read Media Cataloge Number
+//
+// Version 1.41 : 02.05.1998
+// Changes:
+// New GetInfoEx() function in CMapDrive, to allow a better result checking.
+// Bugfixed error handling in CWaveSave and CDAC regarding write errors
+//
+// Version 1.42 : 02.08.1998
+// Changes:
+// Added GetLastReadableAddress function to get the last readable Sektor of a session.
+// Added a flag in the drive properties for the function.
+// Added this function to the CDAC object.
+//
+// Version 1.43 : 23.12.1998
+// Changes:
+// Added Wave and DAC classes are now available in a MT version, the old versions will not longer be updated.
+//
+// Version 1.44 : 10.03.1999
+// Changes:
+// Added Support for current Plextor CDROM drives and CD-Writers.
+// Added Support for Jukeboxes
+// Changed Handling of the Ringbuffer
+//
+// Version 1.45 : 15.08.1999
+// Changes:
+// Added Enhanced error detection for Plextor drives.
+// Several Bugfixes (initialising under NT and Ringbuffer specific)
+//
+// Version 1.45-Build 11 : 11.11.1999
+// Changes:
+// Added a check for the MaxSektor parameter in CBaseWaveMT to avoid Program failures even if the applications provides an invalid value.
+// Changed source to comile with Borland compiler
+// Added MMC-2 Type which will be default for Sony CD-Writers 140 and 928
+// Skip Virtual CD devices in Bus scan
+// Fixed Array out of bound bug in drive detection.
+
+//limit the read to 64k, because of a bug in the Adaptec drivers
+#define Bug64
+
+//limit the number of retries at error to 5
+#define MAXTRIES 5
+#include "dac32.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <process.h>
+
+#ifdef __BORLANDC__ // pgo (to make it compatible with Bormand compiler)
+#define _stricmp _stricmp
+#define _strlwr strlwr
+#endif
+
+// ----------------------------------------------------------------------------------------
+// - Implementation of the private copy operators -
+// - -
+// - Author: Christoph Schmelnik -
+// - Purpose: Check the syntax of program -
+// ----------------------------------------------------------------------------------------
+
+CBaseCD& CBaseCD::operator = (const CBaseCD &other)
+{
+ assert(!&other);
+ return (*this);
+}
+
+CSCSICD& CSCSICD::operator = (const CSCSICD &other)
+{
+ assert(!&other);
+ return (*this);
+}
+
+// ----------------------------------------------------------------------------------------
+// - Implementation of the class members of CCDAdress -
+// - -
+// - Author: Christoph Schmelnik -
+// - Purpose: Eliminate the errors at compile time -
+// ----------------------------------------------------------------------------------------
+void CCDAdress::SetRedbook(long Value)
+{
+ Adresse=Value >> 24;
+ Adresse+=((Value >> 16) & 255)*75;
+ Adresse+=((Value >> 8) & 255)*4500;
+};
+
+// ----------------------------------------------------------------------------------------
+// - Implementation of the class members of CMapInfo -
+// - -
+// - Author: Christoph Schmelnik -
+// - Purpose: Implement the information of the TypeMappings -
+// ----------------------------------------------------------------------------------------
+CMapInfo::CMapInfo()
+{
+ strncpy(TypNamen[0],"TOSHIBA ", 9);
+ strncpy(TypNamen[1],"SONY ", 9);
+ strncpy(TypNamen[2],"NEC ", 9);
+ strncpy(TypNamen[3],"HITACHI ", 9);
+ strncpy(TypNamen[4],"YAMAHA ", 9);
+ strncpy(TypNamen[5],"PIONEER ", 9);
+ strncpy(TypNamen[6],"IBM ", 9);
+ strncpy(TypNamen[7],"PLEXTOR ", 9);
+ strncpy(TypNamen[8],"PHILIPS ", 9);
+ strncpy(TypNamen[9],"GRUNDIG ", 9);
+ strncpy(TypNamen[10],"HP ", 9);
+ strncpy(TypNamen[11],"IMS ", 9);
+ strncpy(TypNamen[12],"MITSUMI ", 9);
+ strncpy(TypNamen[13],"ATAPI ", 9);
+ strncpy(TypNamen[14],"TOSHNEW ", 9);
+ strncpy(TypNamen[15],"RICOH ", 9);
+ strncpy(TypNamen[16],"MATSHITA", 9);
+ strncpy(TypNamen[17],"PLASMON ", 9);
+ strncpy(TypNamen[18],"KODAK ", 9);
+ strncpy(TypNamen[19],"TEAC ", 9);
+ strncpy(TypNamen[20],"CyberDrv", 9);
+ strncpy(TypNamen[21],"MMC-2 ", 9); // pgo
+ int const t[]={CDTYPE_TOSHIBA,CDTYPE_SONY,CDTYPE_NEC,CDTYPE_SONY,CDTYPE_SONY,CDTYPE_SONY,
+ CDTYPE_SONY,CDTYPE_PLEXTOR,CDTYPE_PHILIPS,CDTYPE_PHILIPS,CDTYPE_PHILIPS,CDTYPE_PHILIPS,
+ CDTYPE_PHILIPS,CDTYPE_ATAPI,CDTYPE_TOSHNEW,CDTYPE_RICOH,CDTYPE_MATSHITA,CDTYPE_PHILIPS,
+ CDTYPE_PHILIPS,CDTYPE_SONY,CDTYPE_CYBERDRV,
+ CDTYPE_CYBERDRV}; // pgo
+ for (int i=0; i<MaxMappings; i++)
+ TypMapping[i]=t[i];
+}
+
+char *CMapInfo::GetTypName(int Index)
+{
+ return TypNamen[Index];
+};
+
+int CMapInfo::GetTypMapping(int Index)
+{
+ return TypMapping[Index];
+};
+
+int CMapInfo::GetTypMappingRev(int CDType)
+{
+ int Index=0;
+ while ((Index<MaxMappings) &&
+ (TypMapping[Index]!=CDType))
+ Index++;
+ return Index;
+};
+
+// ----------------------------------------------------------------------------------------
+// - Implementation of the class members of CMapDrive -
+// - -
+// - Author: Christoph Schmelnik -
+// - Purpose: Administration of the drive configuration -
+// ----------------------------------------------------------------------------------------
+CMapDrive::CMapDrive(BOOL bDoReset)
+{
+ First=0;
+
+ m_hDriveEvent=INVALID_HANDLE_VALUE;
+ wchar_t szEventName[32] = {0};
+ wsprintf(szEventName,L"%X",this);
+ m_hDriveEvent=CreateEvent(NULL,TRUE,FALSE,szEventName);
+ if (bDoReset)
+ Reset();
+};
+
+CMapDrive::~CMapDrive()
+{
+ DeleteAll();
+ if (m_hDriveEvent!=INVALID_HANDLE_VALUE)
+ CloseHandle(m_hDriveEvent);
+};
+
+void CMapDrive::DeleteAll()
+{
+ TDriveInfoMem *Akt;
+ Akt=First;
+ while (First)
+ {
+ Akt=First;
+ First=Akt->Next;
+ delete Akt;
+ }
+};
+
+void CMapDrive::Reset()
+{
+ TDriveInfoMem *Akt,*Last;
+ DeleteAll();
+ BYTE SCSIType;
+ TDriveInfo Info = {0};
+ int DType = DTYPE_UNKNOWN;
+ char Revision[5] = {0};
+ char ManagerID[17] = {0};
+ char HAID[17] = {0};
+
+ THAUnique HAUnique;
+ MEMORYSTATUS MemStat;
+ MemStat.dwLength=sizeof(MEMORYSTATUS);
+ GlobalMemoryStatus((LPMEMORYSTATUS)&MemStat);
+ CMapInfo MapInfo;
+ int HostNum;
+ for (HostNum=0; HostNum<NumberOfHostAdapters; HostNum++)
+ {
+ memset(Revision,0,sizeof(Revision));
+ memset(ManagerID,0,sizeof(ManagerID));
+ memset(HAID,0,sizeof(HAID));
+ memset(&HAUnique,0,sizeof(HAUnique));
+ if (HAInquiry(HostNum,ManagerID,HAID,HAUnique))
+ {
+ if (_stricmp(HAID, "fastcdmp") == 0) //pgo: Skip Virtual CD Adapter in Bus Scan
+ continue;
+ HostAdapterMemory[HostNum]=HAUnique.MaximumTransferLen;
+ for (int IDNum=0; IDNum<8; IDNum++)
+ for (int LUNNum=0; LUNNum<=MAXLUN; LUNNum++)
+ {
+ DType=GetDeviceInfo(HostNum,IDNum,LUNNum,SCSIType,Info.VendorID,Info.ProductID,Revision,m_hDriveEvent);
+ if ((DType==DTYPE_CROM)||
+ (DType==DTYPE_WORM))
+ {
+ if (SCSIType)
+ {
+ int i;
+ for (i=0; (i<MaxMappings) && _stricmp(Info.VendorID,MapInfo.GetTypName(i)); i++);
+ if (i>=MaxMappings) i=1; //pgo: avoid array out of bound
+ Info.Type=i;
+ }
+ else
+ Info.Type=MapInfo.GetTypMappingRev(CDTYPE_ATAPI);
+
+ if (MapInfo.GetTypMapping(Info.Type)==CDTYPE_TOSHIBA)
+ {
+ char szNumbers[17] = {0};
+ for (size_t i=0; i<strlen(Info.ProductID); i++)
+ if (isdigit(Info.ProductID[i]))
+ strncat(szNumbers,&Info.ProductID[i],1);
+ int nProductID=atoi(szNumbers);
+ if (((nProductID>3800) &&
+ (nProductID<4000)) ||
+ ((nProductID>5700) &&
+ (nProductID<10000)))
+ Info.Type=MapInfo.GetTypMappingRev(CDTYPE_TOSHNEW);
+ }
+ // pgo
+ else if (MapInfo.GetTypMapping(Info.Type)==CDTYPE_SONY)
+ {
+ if (SCSIType)
+ {
+ char szNumbers[17] = {0};
+ for (size_t i=0; i<strlen(Info.ProductID); i++)
+ if (isdigit(Info.ProductID[i]))
+ strncat(szNumbers,&Info.ProductID[i],1);
+ int nProductID=atoi(szNumbers);
+ if ((nProductID == 140) || (nProductID == 928))
+ Info.Type=MapInfo.GetTypMappingRev(CDTYPE_CYBERDRV);
+ }
+ }
+ Info.ID=IDNum;
+ Info.LUN=LUNNum;
+ Info.HostAdapterNumber=HostNum;
+ Info.Mode=ModeBurst;
+ Info.MaxSektors=MemStat.dwTotalPhys/16/2352;
+ if (Info.MaxSektors>(HostAdapterMemory[HostNum]/2352))
+ Info.MaxSektors=HostAdapterMemory[HostNum]/2352;
+#ifdef Bug64
+ if (Info.MaxSektors>27) Info.MaxSektors=27;
+#else
+ if (Info.MaxSektors>446) Info.MaxSektors=446;
+#endif
+ if (!Info.MaxSektors) Info.MaxSektors=26;
+
+ Info.SynchSektors=3;
+ Info.Speed=0;
+ Info.PerformDATest=DATEST_FIRSTTRACK;
+ Info.SpinUpMode=SPINUP_NEVER;
+ Info.dwSpinUpTime=5;
+ Info.bUseLastReadableAddress=FALSE;
+ Info.bUseC2ErrorInfo=FALSE;
+ Info.bSpinDown=FALSE;
+ Akt=new TDriveInfoMem;
+ Akt->Info=Info;
+ Akt->Next=0;
+ if (!First) First=Akt;
+ else Last->Next=Akt;
+ //Last must be set to Akt
+ Last=Akt;
+ }
+ }
+ }
+ }
+ if (RunningNT)
+ {
+ //check all drives for direct access
+ int Index, Length;
+ wchar_t DriveList[128] = {0}, *pDrives = 0;
+
+ Length=GetLogicalDriveStrings(128,DriveList);
+ if (Length)
+ {
+ pDrives=DriveList;
+ Index=0;
+ while (pDrives && *pDrives && (Index<Length))
+ {
+ if (GetDriveType(pDrives)==DRIVE_CDROM)
+ {
+ wchar_t CDDevice[10]=L"\\\\.\\x:";
+ HANDLE hDrive;
+ CharLower(pDrives);
+ //_strlwr(pDrives);
+ CDDevice[4]=pDrives[0];
+ int IDNum=pDrives[0]-'a';
+
+ //For Windows NT 5 use other file flags
+ OSVERSIONINFO osver;
+ memset( &osver, 0x00, sizeof(osver) );
+ osver.dwOSVersionInfoSize = sizeof(osver);
+ GetVersionEx( &osver );
+
+ DWORD dwOpenFlags = GENERIC_READ;
+ if ( (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osver.dwMajorVersion > 4) ) dwOpenFlags |= GENERIC_WRITE;
+
+ hDrive=CreateFile(CDDevice,dwOpenFlags,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
+ if (hDrive!=INVALID_HANDLE_VALUE)
+ {
+ //CT> added correct host/id/lun guessing
+ extern int getSCSIIDFromDrive(char driveletter, int *host, int *id, int *lun);
+ int m_lun;
+ getSCSIIDFromDrive((char)pDrives[0],&HostNum,&IDNum,&m_lun);
+
+ DType=GetDeviceInfo(HostNum,IDNum,m_lun,SCSIType,Info.VendorID,Info.ProductID,Revision,hDrive);
+ if ((DType==DTYPE_CROM)||
+ (DType==DTYPE_WORM))
+ {
+ SCSIMaxBlocks(hDrive,&HostAdapterMemory[HostNum]);
+ if (SCSIType)
+ {
+ int i;
+ for (i=0; (i<MaxMappings) && _stricmp(Info.VendorID,MapInfo.GetTypName(i)); i++);
+ if (i>=MaxMappings) i=1; //pgo: avoid array out of bound
+ Info.Type=i;
+ }
+ else
+ Info.Type=MapInfo.GetTypMappingRev(CDTYPE_ATAPI);
+ if (MapInfo.GetTypMapping(Info.Type)==CDTYPE_TOSHIBA)
+ {
+ char szNumbers[17];
+ szNumbers[0]=0;
+ for (size_t i=0; i<strlen(Info.ProductID); i++)
+ if (isdigit(Info.ProductID[i]))
+ strncat(szNumbers,&Info.ProductID[i],1);
+ int nProductID=atoi(szNumbers);
+ if (((nProductID>3800) &&
+ (nProductID<4000)) ||
+ ((nProductID>5700) &&
+ (nProductID<10000)))
+ Info.Type=MapInfo.GetTypMappingRev(CDTYPE_TOSHNEW);
+ }
+ // pgo
+ else if (MapInfo.GetTypMapping(Info.Type)==CDTYPE_SONY)
+ {
+ if (SCSIType)
+ {
+ char szNumbers[17] = {0};
+ for (size_t i=0; i<strlen(Info.ProductID); i++)
+ if (isdigit(Info.ProductID[i]))
+ strncat(szNumbers,&Info.ProductID[i],1);
+ int nProductID=atoi(szNumbers);
+ if ((nProductID == 140) || (nProductID == 928))
+ Info.Type=MapInfo.GetTypMappingRev(CDTYPE_CYBERDRV);
+ }
+ }
+ Info.ID=IDNum;
+ Info.LUN=0;
+ Info.HostAdapterNumber=HostNum;
+ Info.Mode=ModeNormal;
+ Info.MaxSektors=MemStat.dwTotalPhys/16/2352;
+ if (Info.MaxSektors>(HostAdapterMemory[HostNum]/2352))
+ Info.MaxSektors=HostAdapterMemory[HostNum]/2352;
+#ifdef Bug64
+ if (Info.MaxSektors>27) Info.MaxSektors=27;
+#else
+ if (Info.MaxSektors>446) Info.MaxSektors=446;
+#endif
+ if (!Info.MaxSektors ||
+ (MapInfo.GetTypMapping(Info.Type)==CDTYPE_ATAPI))
+ Info.MaxSektors=26;
+ Info.SynchSektors=3;
+ Info.Speed=0;
+ Info.PerformDATest=DATEST_FIRSTTRACK;
+ Info.SpinUpMode=SPINUP_NEVER;
+ Info.dwSpinUpTime=5;
+ Info.bUseLastReadableAddress=FALSE;
+ Info.bUseC2ErrorInfo=FALSE;
+ Info.bSpinDown=FALSE;
+ Akt=new TDriveInfoMem;
+ Akt->Info=Info;
+ Akt->Next=0;
+ if (!First) First=Akt;
+ else Last->Next=Akt;
+ //Last must be set to Akt
+ Last=Akt;
+ HostNum++;
+ }
+ CloseHandle(hDrive);
+ }
+ }
+ pDrives+=4;
+ Index+=4;
+ }
+ }
+ }
+};
+
+int CMapDrive::GetMaxDrives()
+{
+ int i=0;
+ TDriveInfoMem *Akt;
+ Akt=First;
+ while (Akt)
+ {
+ i++;
+ Akt=Akt->Next;
+ }
+ return i;
+};
+
+TDriveInfo &CMapDrive::GetInfo(int index)
+{
+ int i=0;
+ TDriveInfoMem *Akt;
+ Akt=First;
+ while ((Akt) && (i<index))
+ {
+ i++;
+ Akt=Akt->Next;
+ }
+ return Akt->Info;
+};
+
+BOOL CMapDrive::GetInfoEx(int index, TDriveInfo *&pInfo)
+{
+ int i=0;
+ TDriveInfoMem *Akt;
+ Akt=First;
+ while ((Akt) && (i<index))
+ {
+ i++;
+ Akt=Akt->Next;
+ }
+ if (!Akt)
+ return FALSE;
+ pInfo=&Akt->Info;
+ return TRUE;
+};
+
+void CMapDrive::DeleteInfo(int index)
+{
+ int i=0;
+ TDriveInfoMem *Akt,*Prev;
+ Akt=First;
+ Prev=0;
+ while ((Akt) && (i<index))
+ {
+ i++;
+ Prev=Akt;
+ Akt=Akt->Next;
+ }
+ if (!Akt) return;
+ if (Prev) Prev->Next=Akt->Next;
+ else First=Akt->Next;
+ delete Akt;
+};
+
+int CMapDrive::GetMaxHostAdapters()
+{
+ return NumberOfHostAdapters;
+};
+
+int CMapDrive::GetSupportedHostAdapterMemory(int index)
+{
+ if ((index<NumberOfHostAdapters) &&
+ (index>=0))
+ return HostAdapterMemory[index];
+ else
+ return -1;
+};
+
+void CMapDrive::SetSupportedHostAdapterMemory(int index,int Memory)
+{
+ if ((index<NumberOfHostAdapters) &&
+ (index>=0))
+ HostAdapterMemory[index]=Memory;
+}
+
+int CMapDrive::GetMaxSektors(int HostAdapterNumber)
+{
+#ifdef Bug64
+ int Result=HostAdapterMemory[HostAdapterNumber]/2352;
+ if (Result>27)
+ Result=27;
+ return Result;
+#else
+ return HostAdapterMemory[HostAdapterNumber]/2352;
+#endif
+};
+
+// ----------------------------------------------------------------------------------------
+// - Implementation of the class members of CMapInfoJuke -
+// - -
+// - Author: Christoph Schmelnik -
+// - Purpose: Implement the information of the TypeMappings -
+// ----------------------------------------------------------------------------------------
+CMapInfoJuke::CMapInfoJuke()
+{
+ strncpy(TypNamen[0],"SONY ", 9);
+ strncpy(TypNamen[1],"PIONEER ", 9);
+ int const t[]={JUKETYPE_SONY,JUKETYPE_PIONEER};
+ for (int i=0; i<MaxMappingsJuke; i++)
+ TypMapping[i]=t[i];
+}
+
+char *CMapInfoJuke::GetTypName(int Index)
+{
+ return TypNamen[Index];
+};
+
+int CMapInfoJuke::GetTypMapping(int Index)
+{
+ return TypMapping[Index];
+};
+
+int CMapInfoJuke::GetTypMappingRev(int JukeType)
+{
+ int Index=0;
+ while ((Index<MaxMappingsJuke) &&
+ (TypMapping[Index]!=JukeType))
+ Index++;
+ return Index;
+};
+
+// ----------------------------------------------------------------------------------------
+// - Implementation of the class members of CMapJuke -
+// - -
+// - Author: Christoph Schmelnik -
+// - Purpose: Administration of the jukebox configuration -
+// ----------------------------------------------------------------------------------------
+CMapJuke::CMapJuke(BOOL bDoReset)
+{
+ First=0;
+
+ m_hJukeEvent=INVALID_HANDLE_VALUE;
+ wchar_t szEventName[32] = {0};
+ wsprintf(szEventName,L"%X",this);
+ m_hJukeEvent=CreateEvent(NULL,TRUE,FALSE,szEventName);
+ if (bDoReset)
+ Reset();
+};
+
+CMapJuke::~CMapJuke()
+{
+ DeleteAll();
+ if (m_hJukeEvent!=INVALID_HANDLE_VALUE)
+ CloseHandle(m_hJukeEvent);
+};
+
+void CMapJuke::DeleteAll()
+{
+ TJukeInfoMem *Akt;
+ Akt=First;
+ while (First)
+ {
+ Akt=First;
+ First=Akt->Next;
+ if (Akt->Info.pConnectedDrives)
+ delete Akt->Info.pConnectedDrives;
+ delete Akt;
+ }
+};
+
+void CMapJuke::Reset()
+{
+ TJukeInfoMem *Akt,*Last;
+ DeleteAll();
+ BYTE SCSIType = 0;
+ TJukeInfo Info = {0};
+ int DType = DTYPE_UNKNOWN;
+ char Revision[5] = {0};
+ char ManagerID[17] = {0};
+ char HAID[17] = {0};
+
+ THAUnique HAUnique;
+ CMapInfoJuke MapInfo;
+ for (int HostNum=0; HostNum<NumberOfHostAdapters; HostNum++)
+ {
+ memset(Revision,0,sizeof(Revision));
+ memset(ManagerID,0,sizeof(ManagerID));
+ memset(HAID,0,sizeof(HAID));
+ memset(&HAUnique,0,sizeof(HAUnique));
+ if (HAInquiry(HostNum,ManagerID,HAID,HAUnique))
+ {
+ for (int IDNum=0; IDNum<8; IDNum++)
+ {
+ for (int LUNNum=0; LUNNum<=MAXLUN; LUNNum++)
+ {
+ memset(&Info,0,sizeof(Info));
+ DType=GetDeviceInfo(HostNum,IDNum,LUNNum,SCSIType,Info.VendorID,Info.ProductID,Revision,m_hJukeEvent);
+ if (DType==DTYPE_JUKE)
+ {
+ int i;
+ for (i=0; (i<MaxMappingsJuke) && _stricmp(Info.VendorID,MapInfo.GetTypName(i)); i++);
+ if (_stricmp(Info.VendorID,MapInfo.GetTypName(i))) i=JUKETYPE_SONY;
+ Info.Type=i;
+ switch (Info.Type)
+ {
+ case JUKETYPE_PIONEER :
+ Info.MaxDrives=4; //currently only data for the 500x changer implemeneted
+ Info.MaxDiscs=500;
+ break;
+ case JUKETYPE_SONY :
+ default:
+ Info.MaxDrives=2;
+ Info.MaxDiscs=100;
+ break;
+ }
+ Info.pConnectedDrives=new int[Info.MaxDrives];
+ for (int nDriveNum=0; nDriveNum<Info.MaxDrives; nDriveNum++)
+ Info.pConnectedDrives[nDriveNum]=-1;
+ Info.ID=IDNum;
+ Info.LUN=LUNNum;
+ Info.HostAdapterNumber=HostNum;
+
+ Akt=new TJukeInfoMem;
+ Akt->Info=Info;
+ Akt->bIsWorking=FALSE;
+ Akt->Next=0;
+ if (!First) First=Akt;
+ else Last->Next=Akt;
+ //Last must be set to Akt
+ Last=Akt;
+ }
+ }
+ }
+ }
+ }
+};
+
+int CMapJuke::GetMaxJukes()
+{
+ int i=0;
+ TJukeInfoMem *Akt;
+ Akt=First;
+ while (Akt)
+ {
+ i++;
+ Akt=Akt->Next;
+ }
+ return i;
+};
+
+TJukeInfo &CMapJuke::GetInfo(int index)
+{
+ int i=0;
+ TJukeInfoMem *Akt;
+ Akt=First;
+ while ((Akt) && (i<index))
+ {
+ i++;
+ Akt=Akt->Next;
+ }
+ return Akt->Info;
+};
+
+BOOL CMapJuke::IsWorking(int index)
+{
+ int i=0;
+ TJukeInfoMem *Akt;
+ Akt=First;
+ while ((Akt) && (i<index))
+ {
+ i++;
+ Akt=Akt->Next;
+ }
+ return Akt->bIsWorking;
+};
+
+void CMapJuke::SetWorking(int index,BOOL bIsWorking)
+{
+ int i=0;
+ TJukeInfoMem *Akt;
+ Akt=First;
+ while ((Akt) && (i<index))
+ {
+ i++;
+ Akt=Akt->Next;
+ }
+ Akt->bIsWorking=bIsWorking;
+};
+
+void CMapJuke::DeleteInfo(int index)
+{
+ int i=0;
+ TJukeInfoMem *Akt,*Prev;
+ Akt=First;
+ Prev=0;
+ while ((Akt) && (i<index))
+ {
+ i++;
+ Prev=Akt;
+ Akt=Akt->Next;
+ }
+ if (!Akt) return;
+ if (Prev) Prev->Next=Akt->Next;
+ else First=Akt->Next;
+ if (Akt->Info.pConnectedDrives)
+ delete Akt->Info.pConnectedDrives;
+ delete Akt;
+};
+
+// ----------------------------------------------------------------------------------------
+// - Implementation of the class members of CJukeBox -
+// - -
+// - Author: Christoph Schmelnik -
+// - Purpose: Control the basic JukeBox functions over ASPI -
+// ----------------------------------------------------------------------------------------
+CJukeBox::CJukeBox (TJukeInfo &xInfo):Config(xInfo)
+{
+ m_hJukeEvent=INVALID_HANDLE_VALUE;
+ wchar_t szEventName[32] = {0};
+ wsprintf(szEventName,L"%X",this);
+ m_hJukeEvent=CreateEvent(NULL,TRUE,FALSE,szEventName);
+ assert(m_hJukeEvent);
+}
+
+CJukeBox::~CJukeBox()
+{
+ if (m_hJukeEvent!=INVALID_HANDLE_VALUE)
+ CloseHandle(m_hJukeEvent);
+}
+
+BOOL CJukeBox::MoveMedium(int Source,int Destination)
+{
+ switch (MapInfo.GetTypMapping(Config.Type))
+ {
+ case JUKETYPE_PIONEER :
+ if ((Source<1) || (Source>Config.MaxDiscs))
+ if ((Source<0x4000) || (Source>=(0x4000+Config.MaxDrives)))
+ return FALSE;
+ if ((Destination<1) || (Destination>Config.MaxDiscs))
+ if ((Destination<0x4000) || (Destination>=(0x4000+Config.MaxDrives)))
+ return FALSE;
+ break;
+ case JUKETYPE_SONY :
+ default:
+ if ((Source<1) || (Source>Config.MaxDiscs))
+ {
+ if ((Source<0x4000) || (Source>=(0x4000+Config.MaxDrives)))
+ return FALSE;
+ else
+ Source-=0x3fff;
+ }
+ else
+ Source+=10;
+ if ((Destination<1) || (Destination>Config.MaxDiscs))
+ {
+ if ((Destination<0x4000) || (Destination>=(0x4000+Config.MaxDrives)))
+ return FALSE;
+ else
+ Destination-=0x3fff;
+ }
+ else
+ Destination+=10;
+ break;
+ }
+
+ while (!TestUnitReady(Config.HostAdapterNumber,Config.ID,Config.LUN,m_hJukeEvent));
+ TOpcode OpC;
+ OpC[0]=0xa5;
+ OpC[1]=Config.LUN>>5;
+ OpC[2]=0x00;
+ OpC[3]=0x00;
+ OpC[4]=Source/256;
+ OpC[5]=Source%256;
+ OpC[6]=Destination/256;
+ OpC[7]=Destination%256;
+ OpC[8]=0x00;
+ OpC[9]=0x00;
+ OpC[10]=0x00;
+ OpC[11]=0x00;
+ return ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,12,NULL,0,m_hJukeEvent);
+}
+
+// ----------------------------------------------------------------------------------------
+// - Implementation of the class members of CBaseCD -
+// - -
+// - Author: Christoph Schmelnik -
+// - Purpose: The drive independent functions to access the CD-ROM drives -
+// ----------------------------------------------------------------------------------------
+int CBaseCD::Lasterror()
+{
+ int h;
+ h=Error;
+ Error=CDOK;
+ return h;
+}
+
+int CBaseCD::ReadFirstTrackInfo(TTrackList &Infos)
+{
+ if (!FirstTrack) return 0;
+ AktTrack=FirstTrack;
+ Infos=AktTrack->Info;
+ return 1;
+}
+
+int CBaseCD::ReadNextTrackInfo(TTrackList &Infos)
+{
+ if ((!FirstTrack) ||
+ (!AktTrack->Next)) return 0;
+ AktTrack=AktTrack->Next;
+ Infos=AktTrack->Info;
+ return 1;
+}
+
+int CBaseCD::ReadPrevTrackInfo(TTrackList &Infos)
+{
+ if ((!FirstTrack) ||
+ (!AktTrack->Prev)) return 0;
+ AktTrack=AktTrack->Prev;
+ Infos=AktTrack->Info;
+ return 1;
+}
+
+int CBaseCD::ReadTrackInfo(TTrackList &Infos)
+{
+ if ((!FirstTrack) ||
+ (Infos.TrackNummer<1)) return 0;
+ if (!AktTrack)
+ AktTrack=FirstTrack;
+ if (AktTrack->Info.TrackNummer==Infos.TrackNummer)
+ {
+ Infos=AktTrack->Info;
+ return 1;
+ }
+ while ((AktTrack->Info.TrackNummer>Infos.TrackNummer) &&
+ (AktTrack->Prev))
+ AktTrack=AktTrack->Prev;
+ while ((AktTrack->Info.TrackNummer<Infos.TrackNummer) &&
+ (AktTrack->Next))
+ AktTrack=AktTrack->Next;
+ if (AktTrack->Info.TrackNummer!=Infos.TrackNummer) return 0;
+ Infos=AktTrack->Info;
+ return 1;
+}
+
+int CBaseCD::ReadMaxTracks()
+{
+ TTrackListeMem *Laeufer;
+ if (!FirstTrack) return 0;
+ Laeufer=AktTrack;
+ while (Laeufer->Next)
+ Laeufer=Laeufer->Next;
+ return Laeufer->Info.TrackNummer;
+}
+
+void CBaseCD::DeleteTrackList()
+{
+ while (FirstTrack)
+ {
+ AktTrack=FirstTrack->Next;
+ delete FirstTrack;
+ FirstTrack=AktTrack;
+ }
+}
+
+
+// ----------------------------------------------------------------------------------------
+// - Implementation of the class members of CSCSICD -
+// - -
+// - Author: Christoph Schmelnik -
+// - Purpose: Control the basic CDROM functions over ASPI -
+// ----------------------------------------------------------------------------------------
+CSCSICD::CSCSICD (char drive, TDriveInfo &xInfo):Config(xInfo)
+{
+ m_bSpeedTableInitialized=FALSE;
+ FirstTrack=0;
+ NECRotationSpeed = 0; // pgo
+ Changed=FALSE;
+ CDPresentLast=TRUE;
+ Error=CDOK;
+ m_hDriveEvent=INVALID_HANDLE_VALUE;
+ memset(&m_SenseInfo,0,sizeof(TSenseInfo));
+ if ((Config.HostAdapterNumber>=NumberOfHostAdapters) &&
+ RunningNT)
+ {
+ DWORD dwFlags;
+ OSVERSIONINFO osver;
+ wchar_t CDDevice[10]=L"\\\\.\\x:";
+ CDDevice[4]=(wchar_t)drive;//(Config.HostAdapterNumber + 'A'/* + 1*/);
+ //For Windows NT 5 use other file flags
+ memset( &osver, 0x00, sizeof(osver) );
+ osver.dwOSVersionInfoSize = sizeof(osver);
+ GetVersionEx( &osver );
+
+ // if Win2K or greater, add GENERIC_WRITE
+ dwFlags = GENERIC_READ;
+ if ( (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osver.dwMajorVersion > 4) ) dwFlags |= GENERIC_WRITE;
+
+ m_hDriveEvent = CreateFile( CDDevice, dwFlags, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+ }
+ else
+ {
+ wchar_t szEventName[32] = {0};
+ wsprintf(szEventName,L"%X",this);
+ m_hDriveEvent=CreateEvent(NULL,TRUE,FALSE,szEventName);
+ assert(m_hDriveEvent);
+ }
+ TDriveStatus DInfo=Get_DriveStatus();
+ if (DInfo.CDPresent) ReRead();
+}
+
+CSCSICD::~CSCSICD()
+{
+ DeleteTrackList();
+ if (m_hDriveEvent!=INVALID_HANDLE_VALUE)
+ CloseHandle(m_hDriveEvent);
+}
+
+void CSCSICD::PrepareCDDA()
+{
+ switch (MapInfo.GetTypMapping(Config.Type))
+ {
+ case CDTYPE_TOSHIBA :
+ {
+ memset(&ModeData,0,sizeof(ModeData));
+ if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,0,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ ModeData[0]=0;
+ TDriveMode ModeSelectData;
+ ModeSelectData[0]=0x00;
+ ModeSelectData[1]=0x00;
+ ModeSelectData[2]=0x00;
+ ModeSelectData[3]=0x08;
+ ModeSelectData[4]=0x82;
+ ModeSelectData[5]=0x00;
+ ModeSelectData[6]=0x00;
+ ModeSelectData[7]=0x00;
+ ModeSelectData[8]=0x00;
+ ModeSelectData[9]=0x00;
+ ModeSelectData[10]=0x09;
+ ModeSelectData[11]=0x30;
+ if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSelectData,12,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ break;
+ }
+ case CDTYPE_TOSHNEW :
+ {
+ memset(&ModeData,0,sizeof(ModeData));
+ if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,15,0x20,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ ModeData[0]=0;
+ TDriveMode ModeSelectData;
+ ModeSelectData[0]=0x00;
+ ModeSelectData[1]=0x00;
+ ModeSelectData[2]=0x00;
+ ModeSelectData[3]=0x08;
+ ModeSelectData[4]=0x82;
+ ModeSelectData[5]=0x00;
+ ModeSelectData[6]=0x00;
+ ModeSelectData[7]=0x00;
+ ModeSelectData[8]=0x00;
+ ModeSelectData[9]=0x00;
+ ModeSelectData[10]=0x09;
+ ModeSelectData[11]=0x30;
+
+ ModeSelectData[12]=0x20;
+ ModeSelectData[13]=0x01;
+ ModeSelectData[14]=(ModeData[14] & 0xcf)|0x10;
+ if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSelectData,15,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ break;
+ }
+ case CDTYPE_NEC :
+ {
+ memset(&ModeData,0,sizeof(ModeData));
+ if (!addModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ NECRotationSpeed=ModeData[6] & 0x20;
+ ModeData[6]=ModeData[6]|0x20;
+ if (!addModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ break;
+ }
+ case CDTYPE_PHILIPS :
+ case CDTYPE_MATSHITA :
+ {
+ memset(&ModeData,0,sizeof(ModeData));
+ if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,0,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ ModeData[0]=0;
+ TDriveMode ModeSelectData;
+ ModeSelectData[0]=0x00;
+ ModeSelectData[1]=0x00;
+ ModeSelectData[2]=0x00;
+ ModeSelectData[3]=0x08;
+ ModeSelectData[4]=0x00;
+ ModeSelectData[5]=0x00;
+ ModeSelectData[6]=0x00;
+ ModeSelectData[7]=0x00;
+ ModeSelectData[8]=0x00;
+ ModeSelectData[9]=0x00;
+ ModeSelectData[10]=0x09;
+ ModeSelectData[11]=0x30;
+ if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSelectData,12,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ break;
+ }
+ }
+}
+
+void CSCSICD::ReadCDDA(CCDAdress StartSektor,long Sektoranzahl,void *Buffer,BOOL bUseC2ErrorInfo)
+{
+ TOpcode OpC;
+ OpC[1]=0x00;
+ OpC[2]=0x00;
+ OpC[3]=LOBYTE(HIWORD(StartSektor.GetHSG()));
+ OpC[4]=HIBYTE(LOWORD(StartSektor.GetHSG()));
+ OpC[5]=LOBYTE(LOWORD(StartSektor.GetHSG()));
+ OpC[6]=0x00;
+ switch (MapInfo.GetTypMapping(Config.Type))
+ {
+ case CDTYPE_TOSHIBA :
+ case CDTYPE_TOSHNEW :
+ {
+ OpC[0]=0x28;
+ OpC[7]=HIBYTE(LOWORD(Sektoranzahl));
+ OpC[8]=LOBYTE(LOWORD(Sektoranzahl));
+ OpC[9]=0x00;
+ FillSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,Buffer,Sektoranzahl*2352,ReadSRB,m_hDriveEvent);
+ break;
+ }
+ case CDTYPE_SONY :
+ case CDTYPE_RICOH :
+ case CDTYPE_PLEXTOR :
+ {
+ OpC[0]=0xD8;
+ OpC[7]=0x00;
+ OpC[8]=HIBYTE(LOWORD(Sektoranzahl));
+ OpC[9]=LOBYTE(LOWORD(Sektoranzahl));
+ // benski
+ if (bUseC2ErrorInfo)
+ OpC[10]=0x04;
+ else
+ OpC[10]=0x00;
+ OpC[11]=0x00;
+ FillSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,12,Buffer,(bUseC2ErrorInfo)?(Sektoranzahl*2646):(Sektoranzahl*2352),ReadSRB,m_hDriveEvent);
+ break;
+ }
+ case CDTYPE_NEC :
+ {
+ OpC[0]=0xD4;
+ OpC[7]=HIBYTE(LOWORD(Sektoranzahl));
+ OpC[8]=LOBYTE(LOWORD(Sektoranzahl));
+ OpC[9]=0x00;
+ FillSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,Buffer,Sektoranzahl*2352,ReadSRB,m_hDriveEvent);
+ break;
+ }
+ case CDTYPE_MATSHITA :
+ {
+ OpC[0]=0xD4;
+ OpC[7]=0x00;
+ OpC[8]=HIBYTE(LOWORD(Sektoranzahl));
+ OpC[9]=LOBYTE(LOWORD(Sektoranzahl));
+ OpC[10]=0x00;
+ OpC[11]=0x00;
+ FillSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,12,Buffer,Sektoranzahl*2352,ReadSRB,m_hDriveEvent);
+ break;
+ }
+ case CDTYPE_PHILIPS :
+ {
+ OpC[0]=0x28;
+ OpC[7]=HIBYTE(LOWORD(Sektoranzahl));
+ OpC[8]=LOBYTE(LOWORD(Sektoranzahl));
+ OpC[9]=0x00;
+ FillSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,Buffer,Sektoranzahl*2352,ReadSRB,m_hDriveEvent);
+ break;
+ }
+ case CDTYPE_ATAPI :
+ case CDTYPE_CYBERDRV :
+ {
+ OpC[0]=0xBE;
+ OpC[1]=0x04;
+ OpC[7]=HIBYTE(LOWORD(Sektoranzahl));
+ OpC[8]=LOBYTE(LOWORD(Sektoranzahl));
+ OpC[9]=0xF0;
+ // benski
+ if (bUseC2ErrorInfo)
+ OpC[9]|=2; // flag 2 is supposed to mean check for C2 error info
+ OpC[10]=0x00;
+ OpC[11]=0x00;
+ // with C2 error info, our sector size is now 2646 bytes
+ FillSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,12,Buffer,bUseC2ErrorInfo?(Sektoranzahl*2646):(Sektoranzahl*2352),ReadSRB,m_hDriveEvent);
+ break;
+ }
+ }
+ ExecuteSCSIRequest(ReadSRB,m_hDriveEvent);
+ StartReadTime=GetTickCount();
+}
+
+BOOL CSCSICD::WaitCDDA(BOOL bImmediate)
+{
+ BYTE Status=WaitSCSIRequest(ReadSRB,m_hDriveEvent,bImmediate);
+ if ((Status!=SS_PENDING) &&
+ (Status!=SS_COMP))
+ {
+ memcpy(&m_SenseInfo,&ReadSRB.SenseArea,SENSE_LEN);
+ Error=CDASPIError;
+ }
+ if ((Status==SS_PENDING) &&
+ !bImmediate)
+ {
+ DWORD AktReadTime=GetTickCount();
+ if (abs((long long)AktReadTime-StartReadTime)>12000)
+ {
+ AbortSCSIRequest(ReadSRB);
+ Error=CDTimeOut;
+ Status=SS_COMP;
+ }
+ }
+ return (Status!=SS_PENDING);
+}
+
+void CSCSICD::FinishCDDA()
+{
+ switch (MapInfo.GetTypMapping(Config.Type))
+ {
+ case CDTYPE_TOSHIBA :
+ {
+ if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ break;
+ }
+ case CDTYPE_TOSHNEW :
+ {
+ if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,15,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ break;
+ }
+ case CDTYPE_NEC :
+ {
+ ModeData[6]=ModeData[6]|NECRotationSpeed;
+ if (!addModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ break;
+ }
+ case CDTYPE_PHILIPS :
+ case CDTYPE_MATSHITA :
+ {
+ if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ break;
+ }
+ }
+}
+
+void CSCSICD::SortWaveData(DWORD *Data,int Samples)
+{
+ switch (MapInfo.GetTypMapping(Config.Type))
+ {
+ case CDTYPE_PHILIPS :
+// RICOH Drives doesn't seem to swap the bytes
+// This has been evaluated with the CD-RW drives
+// So they are even just handled like SONY drives, but i don't remove this type
+// case CDTYPE_RICOH :
+ {
+ for (int i=0; i<Samples; i++)
+ Data[i]=((Data[i]&0xff00ff00)>>8)|
+ ((Data[i]&0x00ff00ff)<<8);
+ break;
+ }
+ }
+}
+
+CCDAdress CSCSICD::GetErrorAdress()
+{
+ CCDAdress h;
+ h.SetHSG(0);
+ if ((Error!=CDOK)&&
+ (ReadSRB.SRB_TargStat==STATUS_CHKCOND))
+ h.SetHSG((ReadSRB.SenseArea[3]<<24)+
+ (ReadSRB.SenseArea[4]<<16)+
+ (ReadSRB.SenseArea[5]<<8)+
+ ReadSRB.SenseArea[6]);
+ return h;
+}
+
+void CSCSICD::Play_Audio(CCDAdress StartSektor,long Sektoranzahl)
+{
+ while (!TestUnitReady(Config.HostAdapterNumber,Config.ID,Config.LUN,m_hDriveEvent));
+ TOpcode OpC;
+ OpC[0]=0x45;
+ OpC[1]=0x00;
+ OpC[2]=HIBYTE(HIWORD(StartSektor.GetHSG()));
+ OpC[3]=LOBYTE(HIWORD(StartSektor.GetHSG()));
+ OpC[4]=HIBYTE(LOWORD(StartSektor.GetHSG()));
+ OpC[5]=LOBYTE(LOWORD(StartSektor.GetHSG()));
+ OpC[6]=0x00;
+ OpC[7]=HIBYTE(LOWORD(Sektoranzahl));
+ OpC[8]=LOBYTE(LOWORD(Sektoranzahl));
+ OpC[9]=0x00;
+ if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,10,NULL,0,m_hDriveEvent))
+ Error=CDDriveNotReady;
+}
+
+void CSCSICD::Stop_Audio()
+{
+ while (!TestUnitReady(Config.HostAdapterNumber,Config.ID,Config.LUN,m_hDriveEvent));
+ TOpcode OpC;
+/* OpC[0]=0x1b;
+ OpC[1]=0x00;
+ OpC[2]=0x00;
+ OpC[3]=0x00;
+ OpC[4]=0x00;
+ OpC[5]=0x00;
+*/
+ OpC[0]=0x2b;
+ OpC[1]=0x00;
+ OpC[2]=0x00;
+ OpC[3]=0x00;
+ OpC[4]=0x00;
+ OpC[5]=0x00;
+ OpC[6]=0x00;
+ OpC[7]=0x00;
+ OpC[8]=0x00;
+ OpC[9]=0x00;
+ if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,10,NULL,0,m_hDriveEvent))
+ Error=CDDriveNotReady;
+}
+
+void CSCSICD::Pause_Audio()
+{
+ while (!TestUnitReady(Config.HostAdapterNumber,Config.ID,Config.LUN,m_hDriveEvent));
+ TOpcode OpC;
+ OpC[0]=0x4b;
+ OpC[1]=0x00;
+ OpC[2]=0x00;
+ OpC[3]=0x00;
+ OpC[4]=0x00;
+ OpC[5]=0x00;
+ OpC[6]=0x00;
+ OpC[7]=0x00;
+ OpC[8]=0x00;
+ OpC[9]=0x00;
+ if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,10,NULL,0,m_hDriveEvent))
+ Error=CDDriveNotReady;
+}
+
+void CSCSICD::Resume_Audio()
+{
+ while (!TestUnitReady(Config.HostAdapterNumber,Config.ID,Config.LUN,m_hDriveEvent));
+ TOpcode OpC;
+ OpC[0]=0x4b;
+ OpC[1]=0x00;
+ OpC[2]=0x00;
+ OpC[3]=0x00;
+ OpC[4]=0x00;
+ OpC[5]=0x00;
+ OpC[6]=0x00;
+ OpC[7]=0x00;
+ OpC[8]=0x01;
+ OpC[9]=0x00;
+ if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,10,NULL,0,m_hDriveEvent))
+ Error=CDDriveNotReady;
+}
+
+TDriveStatus CSCSICD::Get_DriveStatus()
+{
+ TDriveStatus h = {0};
+/* TOpcode OpC;
+ TQChannelInfo ChannelInfo;
+ BOOL b;
+ memset(&ChannelInfo,0,sizeof(ChannelInfo));
+ OpC[0]=0x42;
+ OpC[1]=0x02;
+ OpC[2]=0x40;
+ OpC[3]=0x01;
+ OpC[4]=0x00;
+ OpC[5]=0x00;
+ OpC[6]=0x00;
+ OpC[7]=0x00;
+ OpC[8]=sizeof(ChannelInfo);
+ OpC[9]=0x00;
+ if (MapInfo.GetTypMapping(Config.Type)==CDTYPE_ATAPI)
+ {
+ OpC[10]=0;
+ OpC[11]=0;
+ b=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,12,(void *)&ChannelInfo,sizeof(ChannelInfo),m_hDriveEvent);
+ }
+ else
+ b=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,10,(void *)&ChannelInfo,sizeof(ChannelInfo),m_hDriveEvent);
+ if (b && ChannelInfo.DataLen)
+*/
+ if (TestUnitReady(Config.HostAdapterNumber,Config.ID,Config.LUN,m_hDriveEvent))
+ h.CDPresent=TRUE;
+ else
+ h.CDPresent=FALSE;
+ if (h.CDPresent!=CDPresentLast) Changed=TRUE;
+ CDPresentLast=h.CDPresent;
+ return h;
+}
+
+BOOL CSCSICD::MediaChanged()
+{
+ BOOL h;
+ h=Changed;
+ //if (CDPresentLast)
+ Changed=FALSE;
+ return h;
+}
+
+TAudioStatus CSCSICD::Get_AudioStatus_Info()
+{
+ TAudioStatus h;
+ TOpcode OpC;
+ TQChannelInfo ChannelInfo;
+ BOOL b;
+ memset(&ChannelInfo,0,sizeof(ChannelInfo));
+ OpC[0]=0x42;
+ OpC[1]=0x02;
+ OpC[2]=0x40;
+ OpC[3]=0x01;
+ OpC[4]=0x00;
+ OpC[5]=0x00;
+ OpC[6]=0x00;
+ OpC[7]=0x00;
+ OpC[8]=0x10;
+ OpC[9]=0x00;
+ h.Pause=FALSE;
+ h.IsPlaying=FALSE;
+ h.IsDone=FALSE;
+ h.PlayError=FALSE;
+ if (MapInfo.GetTypMapping(Config.Type)==CDTYPE_ATAPI)
+ {
+ OpC[10]=0;
+ OpC[11]=0;
+ b=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,12,(void *)&ChannelInfo,16,m_hDriveEvent);
+ }
+ else
+ b=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,(void *)&ChannelInfo,16,m_hDriveEvent);
+ if (b && ChannelInfo.DataLen)
+ {
+// if (!CDPresentLast) Changed=TRUE;
+// CDPresentLast=TRUE;
+ switch (ChannelInfo.AudioStatus)
+ {
+ case 0x11 : h.IsPlaying=TRUE; break;
+ case 0x12 : h.Pause=TRUE; break;
+ case 0x13 : h.IsDone=TRUE; break;
+ case 0x14 : h.PlayError=TRUE; break;
+ }
+ h.AbsSektor.SetRedbook(ChannelInfo.AbsCDAdress);
+ h.RelSektor.SetRedbook(ChannelInfo.RelTrackAdress);
+ h.TrackNummer=ChannelInfo.TrackNumber;
+ }
+ else
+ {
+// if (CDPresentLast) Changed=TRUE;
+// CDPresentLast=FALSE;
+ h.PlayError=TRUE;
+ Error=CDNoCD;
+ }
+ return h;
+}
+
+void CSCSICD::Get_MediaCatalogNumber(char szUPC[16])
+{
+ TOpcode OpC;
+ BYTE Info[24] = {0};
+ BOOL b;
+ szUPC[0]=0;
+ OpC[0]=0x42;
+ OpC[1]=0x02;
+ OpC[2]=0x40;
+ OpC[3]=0x02;
+ OpC[4]=0x00;
+ OpC[5]=0x00;
+ OpC[6]=0x00;
+ OpC[7]=0x00;
+ OpC[8]=sizeof(Info);
+ OpC[9]=0x00;
+ if (MapInfo.GetTypMapping(Config.Type)==CDTYPE_ATAPI)
+ {
+ OpC[10]=0;
+ OpC[11]=0;
+ b=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,12,(void *)&Info,sizeof(Info),m_hDriveEvent);
+ }
+ else
+ b=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,(void *)&Info,sizeof(Info),m_hDriveEvent);
+ if (b && (Info[8]&0x80))
+ {
+ BOOL bIsEmpty=TRUE;
+ for (int i=0; i<15; i++)
+ {
+ BYTE Value=Info[i+9];
+ if (Value)
+ bIsEmpty=FALSE;
+ if (Value<10)
+ Value+=0x30;
+ szUPC[i]=Value;
+ }
+ szUPC[15]=0;
+ if (bIsEmpty)
+ szUPC[0]=0;
+ }
+}
+
+void CSCSICD::EjectDisk()
+{
+ TOpcode OpC;
+ OpC[0]=0x1b;
+ OpC[1]=0x00;
+ OpC[2]=0x00;
+ OpC[3]=0x00;
+ OpC[4]=0x02;
+ OpC[5]=0x00;
+ if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,6,NULL,0,m_hDriveEvent))
+ Error=CDDriveNotReady;
+}
+
+void CSCSICD::LockDoor(int Lock)
+{
+ TOpcode OpC;
+ OpC[0]=0x1e;
+ OpC[1]=0x00;
+ OpC[2]=0x00;
+ OpC[3]=0x00;
+ OpC[4]=((BYTE) Lock) & 1;
+ OpC[5]=0x00;
+ if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,6,NULL,0,m_hDriveEvent))
+ Error=CDDriveNotReady;
+}
+
+void CSCSICD::CloseTray()
+{
+ TOpcode OpC;
+ OpC[0]=0x1b;
+ OpC[1]=0x00;
+ OpC[2]=0x00;
+ OpC[3]=0x00;
+ OpC[4]=0x03;
+ OpC[5]=0x00;
+ if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,6,NULL,0,m_hDriveEvent))
+ Error=CDDriveNotReady;
+}
+
+int Swap(int value)
+{
+ int result=(value & 0xff000000)>>24;
+ result|=(value & 0x00ff0000)>>8;
+ result|=(value & 0x0000ff00)<<8;
+ result|=(value & 0x000000ff)<<24;
+ return result;
+}
+
+void CSCSICD::ReRead()
+{
+ DeleteTrackList();
+ m_bSpeedTableInitialized=FALSE;
+ TTOCHeader TOCHeader;
+ memset(&TOCHeader,0,sizeof(TOCHeader));
+ TOpcode OpC;
+ OpC[0]=0x43;
+ OpC[1]=0;
+ OpC[2]=0;
+ OpC[3]=0;
+ OpC[4]=0;
+ OpC[5]=0;
+ OpC[6]=0;
+ OpC[7]=HIBYTE(sizeof(TTOCHeader));
+ OpC[8]=LOBYTE(sizeof(TTOCHeader));
+ OpC[9]=0;
+
+ BOOL r=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,(void*)&TOCHeader,sizeof(TOCHeader),m_hDriveEvent);
+ if (r && TOCHeader.FirstTrack && TOCHeader.LastTrack)
+ {
+ TTrackListeMem *Last;
+ CCDAdress Ende;
+ Last=FirstTrack;
+ for (int i=TOCHeader.FirstTrack; i<=TOCHeader.LastTrack; i++)
+ {
+ AktTrack=new TTrackListeMem;
+ //AbsCDAdress
+ //AdrCtrl
+ AktTrack->Info.TrackNummer=TOCHeader.Info[i-1].TrackNummer;
+ AktTrack->Info.StartSektor.SetHSG(Swap(TOCHeader.Info[i-1].AbsCDAdress)+150);
+ Ende.SetHSG(Swap(TOCHeader.Info[i].AbsCDAdress)+150);
+ AktTrack->Info.Laenge=Ende.GetHSG()-AktTrack->Info.StartSektor.GetHSG();
+ AktTrack->Info.StartSektor.SetHSG(AktTrack->Info.StartSektor.GetHSG()-150);
+ if (TOCHeader.Info[i-1].AdrCtrl & 8)
+ AktTrack->Info.Flags.AudioChannels=4;
+ else
+ AktTrack->Info.Flags.AudioChannels=2;
+ AktTrack->Info.Flags.PreEmphasis=(TOCHeader.Info[i-1].AdrCtrl & 1);
+ AktTrack->Info.Flags.DataTrack=(TOCHeader.Info[i-1].AdrCtrl & 4);
+ AktTrack->Info.Flags.CopyProhibeted=!(TOCHeader.Info[i-1].AdrCtrl & 2);
+ AktTrack->Prev=Last;
+ AktTrack->Next=0;
+ if (FirstTrack)
+ Last->Next=AktTrack;
+ else
+ FirstTrack=AktTrack;
+ Last=AktTrack;
+ }
+ // check for CD-Extra
+ if (AktTrack)
+ {
+ if (AktTrack->Info.Flags.DataTrack)
+ {
+ Last=AktTrack->Prev;
+ if (Last && !Last->Info.Flags.DataTrack)
+ {
+ if (Last->Info.Laenge>11400)
+ Last->Info.Laenge-=11400;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (CDPresentLast) Changed=TRUE;
+ CDPresentLast=FALSE;
+ Error=CDDriveNotReady;
+ }
+}
+
+CCDAdress CSCSICD::GetLastReadableAddress(CCDAdress StartSektor)
+{
+ CCDAdress LastSektor;
+ BYTE RetVal[8] = {0};
+ TOpcode OpC;
+ OpC[0]=0x25;
+ OpC[1]=0;
+ OpC[2]=HIBYTE(HIWORD(StartSektor.GetHSG()));
+ OpC[3]=LOBYTE(HIWORD(StartSektor.GetHSG()));
+ OpC[4]=HIBYTE(LOWORD(StartSektor.GetHSG()));
+ OpC[5]=LOBYTE(LOWORD(StartSektor.GetHSG()));
+ OpC[6]=0;
+ OpC[7]=0;
+ OpC[8]=1; //Set PMI Bit
+ OpC[9]=0;
+
+ BOOL r=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,(void*)&RetVal,sizeof(RetVal),m_hDriveEvent);
+ if (!r)
+ return StartSektor;
+ LastSektor.SetHSG((RetVal[0]<<24)+(RetVal[1]<<16)+(RetVal[2]<<8)+RetVal[3]);
+ return LastSektor;
+}
+
+int CSCSICD::GetMaxSektors()
+{
+ return Config.MaxSektors;
+};
+
+int CSCSICD::GetSynchSektors()
+{
+ return Config.SynchSektors;
+};
+
+int CSCSICD::GetMode()
+{
+ return Config.Mode;
+};
+
+int CSCSICD::GetSpeed()
+{
+ return Config.Speed;
+};
+
+TSenseInfo CSCSICD::GetSense()
+{
+ TSenseInfo SenseInfo;
+ memset(&SenseInfo,0,sizeof(SenseInfo));
+ TOpcode OpC;
+ OpC[0]=0x03;
+ OpC[1]=0;
+ OpC[2]=0;
+ OpC[3]=0;
+ OpC[4]=sizeof(SenseInfo);
+ OpC[5]=0;
+
+ BOOL r=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,6,(void*)&SenseInfo,sizeof(SenseInfo),m_hDriveEvent);
+ if (!r)
+ memset(&SenseInfo,0,sizeof(SenseInfo));
+ return SenseInfo;
+}
+
+TSenseInfo CSCSICD::GetLastSenseInfo()
+{
+ TSenseInfo Info=m_SenseInfo;
+ memset(&m_SenseInfo,0,sizeof(TSenseInfo));
+ return Info;
+}
+
+void CSCSICD::InitSpeedTable()
+{
+ if (m_bSpeedTableInitialized)
+ return;
+ SupportedSpeeds=0;
+ switch (MapInfo.GetTypMapping(Config.Type))
+ {
+ case CDTYPE_TOSHIBA :
+ break;
+ case CDTYPE_TOSHNEW :
+ {
+ SpeedTable[0]=2352*75;
+ SpeedTable[1]=2352*75*4;
+ SpeedTable[2]=2352*75*4;
+ SpeedTable[3]=-2;
+ SupportedSpeeds=4;
+ break;
+ }
+ case CDTYPE_SONY :
+ case CDTYPE_RICOH :
+ case CDTYPE_ATAPI :
+ case CDTYPE_CYBERDRV :
+ {
+ int LastSpeed=GetCurrentSpeed();
+ int Speed=65532000;
+ BOOL bFound=FALSE;
+ while (!bFound && (Speed>0))
+ {
+ SetCurrentSpeed(Speed);
+ if (Lasterror()==CDOK)
+ {
+ int ResultingSpeed=GetCurrentSpeed();
+ if (Lasterror()==CDOK)
+ {
+ bFound=FALSE;
+ for (int i=0; i<SupportedSpeeds; i++)
+ {
+ if (SpeedTable[i]==ResultingSpeed)
+ bFound=TRUE;
+ }
+ if (!bFound)
+ {
+ SpeedTable[SupportedSpeeds]=ResultingSpeed;
+ SupportedSpeeds++;
+ Speed=ResultingSpeed-2352*75;
+ }
+ else
+ {
+ Speed-=(2352*75);
+ bFound=FALSE;
+ }
+ }
+ }
+ else
+ Speed=0;
+ }
+ if (SupportedSpeeds>1)
+ {
+ //Swap entries
+ for (int i=0; i<(SupportedSpeeds/2); i++)
+ {
+ int Help=SpeedTable[i];
+ SpeedTable[i]=SpeedTable[SupportedSpeeds-1-i];
+ SpeedTable[SupportedSpeeds-1-i]=Help;
+ }
+ }
+ SetCurrentSpeed(LastSpeed);
+ break;
+ }
+ case CDTYPE_PLEXTOR :
+ {
+ int LastSpeed=GetCurrentSpeed();
+ for (int index=1; index<=20; index++)
+ {
+ SetCurrentSpeed(index*2352*75);
+ if (Lasterror()==CDOK)
+ {
+ int Speed=GetCurrentSpeed();
+ if (Lasterror()==CDOK)
+ {
+ BOOL found=FALSE;
+ for (int i=0; i<SupportedSpeeds; i++)
+ {
+ if (SpeedTable[i]==Speed)
+ found=TRUE;
+ }
+ if (!found)
+ {
+ SpeedTable[SupportedSpeeds]=Speed;
+ SupportedSpeeds++;
+ }
+ }
+ }
+ }
+ SetCurrentSpeed(LastSpeed);
+ break;
+ }
+ case CDTYPE_NEC :
+ {
+ break;
+ }
+ case CDTYPE_PHILIPS :
+ case CDTYPE_MATSHITA :
+ {
+ int LastSpeed=GetCurrentSpeed();
+ SpeedTable[0]=-1;
+ SupportedSpeeds++;
+ for (int index=1; index<8; index++)
+ {
+ SetCurrentSpeed(2352*75*index);
+ if (Lasterror()==CDOK)
+ {
+ int Speed=GetCurrentSpeed();
+ if ((Lasterror()==CDOK) &&
+ (Speed==2352*75*index))
+ {
+ SpeedTable[SupportedSpeeds]=2352*75*index;
+ SupportedSpeeds++;
+ }
+ }
+ }
+ SetCurrentSpeed(LastSpeed);
+ break;
+ }
+ }
+ m_bSpeedTableInitialized=TRUE;
+}
+
+BYTE CSCSICD::GetSupportedSpeeds()
+{
+ return SupportedSpeeds;
+}
+
+BOOL IsOldPhilips(TDriveInfo *pConfig)
+{
+ BOOL bResult=FALSE;
+ if (strstr(pConfig->ProductID,"2000"))
+ bResult=TRUE;
+ if (strstr(pConfig->ProductID,"4020"))
+ bResult=TRUE;
+ return bResult;
+}
+
+//return the identifictaion number for the plextor models
+//defined values:
+#define PX4X 0
+#define PX6X 1
+#define PX8X 2
+#define PX12X 3
+#define PX20X 4
+#define PX32X 5
+#define PXR412 6
+#define PX40X 7
+
+DWORD GetPlextorModel(TDriveInfo *pConfig)
+{
+ DWORD dwResult=PX40X;
+ char szId[7] = {0};
+ strncpy(szId,&pConfig->ProductID[10],6);
+ szId[6]=0;
+ if (!_stricmp(szId,"W4220T"))
+ {
+ dwResult=PXR412;
+ }
+ else
+ {
+ if (!_stricmp(szId,"W8220T"))
+ {
+ dwResult=PXR412;
+ }
+ else
+ {
+ szId[5]=0;
+ if (!_stricmp(szId,"R412C"))
+ {
+ dwResult=PXR412;
+ }
+ else
+ {
+ if (!_stricmp(szId,"R820T"))
+ {
+ dwResult=PXR412;
+ }
+ else
+ {
+ szId[2]=0;
+ if (!strcmp(szId,"40"))
+ dwResult=PX40X;
+ else
+ {
+ if (!strcmp(szId,"32"))
+ dwResult=PX32X;
+ else
+ {
+ if (!strcmp(szId,"20"))
+ dwResult=PX20X;
+ else
+ {
+ if (!strcmp(szId,"12"))
+ dwResult=PX12X;
+ else
+ {
+ if (!isdigit(szId[1]))
+ szId[1]=0;
+ if (!strcmp(szId,"8"))
+ dwResult=PX8X;
+ else
+ {
+ if (!strcmp(szId,"6"))
+ dwResult=PX6X;
+ else
+ {
+ if (!strcmp(szId,"4"))
+ dwResult=PX4X;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return dwResult;
+}
+
+int CSCSICD::GetCurrentSpeed()
+{
+ TDriveMode ModeSenseData;
+ int Speed=0;
+ switch (MapInfo.GetTypMapping(Config.Type))
+ {
+ case CDTYPE_TOSHIBA :
+ {
+ Speed=0;
+ break;
+ }
+ case CDTYPE_TOSHNEW :
+ {
+ if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,15,0x20,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return 0;
+ }
+ int Index=(ModeSenseData[14] & 0x30)>>4;
+ switch (Index)
+ {
+ case 0 :
+ Speed=2352*75;
+ break;
+ case 1 :
+ Speed=2352*75*4;
+ break;
+ case 2 :
+ Speed=2352*75*4;
+ break;
+ case 3 :
+ Speed=-2;
+ break;
+ }
+ break;
+ }
+ case CDTYPE_SONY :
+ case CDTYPE_RICOH :
+ case CDTYPE_CYBERDRV :
+ {
+ if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,34,0x2A,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return 0;
+ }
+ Speed=(ModeSenseData[26]*256+ModeSenseData[27])*1000;
+ break;
+ }
+ case CDTYPE_ATAPI :
+ {
+ if (!ATAPIModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,34,0x2A,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return 0;
+ }
+ if ((ModeSenseData[8]&0x3F)==0x2A)
+ Speed=(ModeSenseData[22]*256+ModeSenseData[23])*1000;
+ else if ((ModeSenseData[4]&0x3F)==0x2A)
+ Speed=(ModeSenseData[18]*256+ModeSenseData[19])*1000;
+ else Speed=-1;
+ break;
+ }
+ case CDTYPE_PLEXTOR :
+ {
+ DWORD dwModel=GetPlextorModel(&Config);
+ if (dwModel!=PXR412)
+ {
+ if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,16,0x31,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return 0;
+ }
+ int Index=ModeSenseData[14];
+ switch (dwModel)
+ {
+ case PX4X :
+ {
+ switch (Index)
+ {
+ case 0 :
+ Speed=2352*75;
+ break;
+ case 1 :
+ Speed=2352*75*2;
+ break;
+ case 2 :
+ Speed=2352*75*4;
+ break;
+ default :
+ Speed=-1;
+ break;
+ }
+ break;
+ }
+ case PX6X :
+ {
+ switch (Index)
+ {
+ case 0 :
+ Speed=2352*75;
+ break;
+ case 1 :
+ Speed=2352*75*4;
+ break;
+ case 2 :
+ Speed=2352*75*6;
+ break;
+ default :
+ Speed=-1;
+ break;
+ }
+ break;
+ }
+ case PX8X :
+ {
+ switch (Index)
+ {
+ case 0 :
+ Speed=2352*75;
+ break;
+ case 1 :
+ Speed=2352*75*2;
+ break;
+ case 2 :
+ Speed=2352*75*4;
+ break;
+ case 3 :
+ Speed=2352*75*8;
+ break;
+ default :
+ Speed=-1;
+ break;
+ }
+ break;
+ }
+ case PX12X :
+ {
+ switch (Index)
+ {
+ case 0 :
+ Speed=2352*75;
+ break;
+ case 1 :
+ Speed=2352*75*2;
+ break;
+ case 2 :
+ Speed=2352*75*4;
+ break;
+ case 3 :
+ Speed=2352*75*8;
+ break;
+ case 4 :
+ Speed=2352*75*8;
+ break;
+ case 5 :
+ Speed=2352*75*12;
+ break;
+ default :
+ Speed=-1;
+ break;
+ }
+ break;
+ }
+ case PX20X :
+ {
+ switch (Index)
+ {
+ case 0 :
+ Speed=2352*75;
+ break;
+ case 1 :
+ Speed=2352*75*2;
+ break;
+ case 2 :
+ Speed=2352*75*4;
+ break;
+ case 3 :
+ Speed=2352*75*8;
+ break;
+ case 4 :
+ Speed=2352*75*8;
+ break;
+ case 5 :
+ Speed=-2;
+ break;
+ case 6 :
+ Speed=2352*75*12;
+ break;
+ default :
+ Speed=-1;
+ break;
+ }
+ break;
+ }
+ case PX32X :
+ {
+ switch (Index)
+ {
+ case 0 :
+ Speed=2352*75;
+ break;
+ case 1 :
+ Speed=2352*75*2;
+ break;
+ case 2 :
+ Speed=2352*75*4;
+ break;
+ case 3 :
+ Speed=2352*75*8;
+ break;
+ case 4 :
+ Speed=2352*75*8;
+ break;
+ case 5 :
+ Speed=2352*75*8;
+ break;
+ case 6 :
+ Speed=2352*75*14;
+ break;
+ default :
+ Speed=-1;
+ break;
+ }
+ break;
+ }
+ case PX40X :
+ {
+ switch (Index)
+ {
+ case 0 :
+ Speed=2352*75;
+ break;
+ case 1 :
+ Speed=2352*75*2;
+ break;
+ case 2 :
+ Speed=2352*75*4;
+ break;
+ case 3 :
+ Speed=2352*75*8;
+ break;
+ case 4 :
+ Speed=2352*75*8;
+ break;
+ case 5 :
+ Speed=2352*75*10;
+ break;
+ case 6 :
+ Speed=2352*75*17;
+ break;
+ default :
+ Speed=-1;
+ break;
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,32,0x2A,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return 0;
+ }
+ Speed=(ModeSenseData[26]*256+ModeSenseData[27])*1000;
+ }
+ break;
+ }
+ case CDTYPE_NEC :
+ {
+ if (!addModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,12,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return 0;
+ }
+// Speed=ModeSenseData[6] & 0x20;
+ break;
+ }
+ case CDTYPE_PHILIPS :
+ case CDTYPE_MATSHITA :
+ {
+ if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,20,0x23,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return 0;
+ }
+ int Index;
+ if (IsOldPhilips(&Config))
+ Index=ModeSenseData[14];
+ else
+ Index=ModeSenseData[16];
+ switch (Index)
+ {
+ case 0 :
+ Speed=-1;
+ break;
+ case 1 :
+ Speed=2352*75;
+ break;
+ case 2 :
+ Speed=2352*75*2;
+ break;
+ case 4 :
+ Speed=2352*75*4;
+ break;
+ case 6 :
+ Speed=2352*75*6;
+ break;
+ case 8 :
+ Speed=2352*75*8;
+ break;
+ default :
+ Speed=-2;
+ }
+ break;
+ }
+ default :
+ Speed=0;
+ }
+ return Speed;
+}
+
+void CSCSICD::SetCurrentSpeed(int Speed)
+{
+ TDriveMode ModeSenseData;
+ if (Speed==0)
+ return;
+ switch (MapInfo.GetTypMapping(Config.Type))
+ {
+ case CDTYPE_TOSHIBA :
+ break;
+ case CDTYPE_TOSHNEW :
+ {
+ if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,15,0x20,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ ModeSenseData[0]=0;
+ int Index;
+ switch (Speed)
+ {
+ case -2 :
+ Index=3;
+ break;
+ case 2352*75 :
+ Index=0;
+ break;
+ case 2352*75*4 :
+ Index=1;
+ break;
+ default :
+ Index=2;
+ }
+ ModeSenseData[14]=(ModeSenseData[14] & 0xcf)|(Index<<4);
+ if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,15,m_hDriveEvent))
+ Error=CDASPIError;
+ break;
+ }
+ case CDTYPE_SONY :
+ case CDTYPE_RICOH :
+ case CDTYPE_CYBERDRV :
+ case CDTYPE_ATAPI :
+ {
+ TOpcode OpC;
+ OpC[0]=0xbb;
+ OpC[1]=0x00;
+ OpC[4]=0x00;
+ OpC[5]=0x00;
+ OpC[6]=0x00;
+ OpC[7]=0x00;
+ OpC[8]=0x00;
+ OpC[9]=0x00;
+ OpC[10]=0x00;
+ OpC[11]=0x00;
+ int NewSpeed=Speed/1000;
+ int ModSpeed=NewSpeed*1000;
+ int Direction=0;
+ int AktSpeed=0;
+ int Counter=0;
+ do
+ {
+ Error=CDOK;
+ Counter++;
+ NewSpeed+=Direction;
+ OpC[2]=NewSpeed/256;
+ OpC[3]=NewSpeed%256;
+ if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_OUT,OpC,12,NULL,0,m_hDriveEvent))
+ Error=CDASPIError;
+ // Is the speed really the one we have selected?
+ AktSpeed=GetCurrentSpeed();
+ if (!Direction)
+ {
+ if (AktSpeed<Speed)
+ Direction=1;
+ else if (AktSpeed>Speed)
+ Direction=-1;
+ }
+ }
+ while ((AktSpeed!=ModSpeed) && NewSpeed && (Counter<3));
+ break;
+ }
+ case CDTYPE_PLEXTOR :
+ {
+ DWORD dwModel=GetPlextorModel(&Config);
+ if (dwModel!=PXR412)
+ {
+ if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,16,0x31,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ int Index;
+ switch (dwModel)
+ {
+ case PX4X :
+ {
+ switch (Speed)
+ {
+ case 2352*75 :
+ Index=0;
+ break;
+ case 2352*75*2 :
+ Index=1;
+ break;
+ case -1 :
+ case 2352*75*4 :
+ Index=2;
+ break;
+ default :
+ Index=-1;
+ break;
+ }
+ break;
+ }
+ case PX6X :
+ {
+ switch (Speed)
+ {
+ case 2352*75 :
+ Index=0;
+ break;
+ case 2352*75*4 :
+ Index=1;
+ break;
+ case -1 :
+ case 2352*75*6 :
+ Index=2;
+ break;
+ default :
+ Index=-1;
+ break;
+ }
+ break;
+ }
+ case PX8X :
+ {
+ switch (Speed)
+ {
+ case 2352*75 :
+ Index=0;
+ break;
+ case 2352*75*2 :
+ Index=1;
+ break;
+ case 2352*75*4 :
+ Index=2;
+ break;
+ case -1 :
+ case 2352*75*8 :
+ Index=3;
+ break;
+ default :
+ Index=-1;
+ break;
+ }
+ break;
+ }
+ case PX12X :
+ {
+ switch (Speed)
+ {
+ case 2352*75 :
+ Index=0;
+ break;
+ case 2352*75*2 :
+ Index=1;
+ break;
+ case 2352*75*4 :
+ Index=2;
+ break;
+ case 2352*75*8 :
+ Index=3;
+ break;
+ case -1 :
+ case 2352*75*12 :
+ Index=5;
+ break;
+ default :
+ Index=-1;
+ break;
+ }
+ break;
+ }
+ case PX20X :
+ {
+ switch (Speed)
+ {
+ case 2352*75 :
+ Index=0;
+ break;
+ case 2352*75*2 :
+ Index=1;
+ break;
+ case 2352*75*4 :
+ Index=2;
+ break;
+ case 2352*75*8 :
+ Index=3;
+ break;
+ case -1 :
+ case 2352*75*12 :
+ Index=6;
+ break;
+ default :
+ Index=-1;
+ break;
+ }
+ break;
+ }
+ case PX32X :
+ {
+ switch (Speed)
+ {
+ case 2352*75 :
+ Index=0;
+ break;
+ case 2352*75*2 :
+ Index=1;
+ break;
+ case 2352*75*4 :
+ Index=2;
+ break;
+ case 2352*75*8 :
+ Index=3;
+ break;
+ case -1 :
+ case 2352*75*14 :
+ Index=6;
+ break;
+ default :
+ Index=-1;
+ break;
+ }
+ break;
+ }
+ case PX40X :
+ {
+ switch (Speed)
+ {
+ case 2352*75 :
+ Index=0;
+ break;
+ case 2352*75*2 :
+ Index=1;
+ break;
+ case 2352*75*4 :
+ Index=2;
+ break;
+ case 2352*75*8 :
+ Index=3;
+ break;
+ case 2352*75*10 :
+ Index=5;
+ break;
+ case -1 :
+ case 2352*75*17 :
+ Index=6;
+ break;
+ default :
+ Index=-1;
+ break;
+ }
+ break;
+ }
+ }
+ if (Index>=0)
+ {
+ ModeSenseData[14]=Index;
+ if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,16,m_hDriveEvent))
+ Error=CDASPIError;
+ }
+ else
+ Error=CDASPIError;
+ }
+ else
+ {
+ TOpcode OpC;
+ OpC[0]=0xbb;
+ OpC[1]=0x00;
+ OpC[4]=0xff;
+ OpC[5]=0xff;
+ OpC[6]=0x00;
+ OpC[7]=0x00;
+ OpC[8]=0x00;
+ OpC[9]=0x00;
+ OpC[10]=0x00;
+ OpC[11]=0x00;
+ int NewSpeed=Speed/1000;
+ int ModSpeed=NewSpeed*1000;
+ int Direction=0;
+ int AktSpeed=0;
+ int Counter=0;
+ do
+ {
+ Error=CDOK;
+ Counter++;
+ NewSpeed+=Direction;
+ OpC[2]=NewSpeed/256;
+ OpC[3]=NewSpeed%256;
+ if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_OUT,OpC,12,NULL,0,m_hDriveEvent))
+ Error=CDASPIError;
+ // Is the speed really the one we have selected?
+ AktSpeed=GetCurrentSpeed();
+ if (!Direction)
+ {
+ if (AktSpeed<Speed)
+ Direction=1;
+ else if (AktSpeed>Speed)
+ Direction=-1;
+ }
+ }
+ while ((AktSpeed!=ModSpeed) && NewSpeed && (Counter<3));
+ }
+ break;
+ }
+ case CDTYPE_NEC :
+ {
+ if (!addModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,12,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+// Speed=ModeSenseData[6] & 0x20;
+ if (!addModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,12,m_hDriveEvent))
+ Error=CDASPIError;
+ break;
+ }
+ case CDTYPE_PHILIPS :
+ case CDTYPE_MATSHITA :
+ {
+ if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,20,0x23,m_hDriveEvent))
+ {
+ Error=CDASPIError;
+ return;
+ }
+ ModeSenseData[0]=0;
+ int Index;
+ switch (Speed)
+ {
+ case -2 :
+ case -1 :
+ Index=0;
+ break;
+ case 2352*75 :
+ Index=1;
+ break;
+ case 2352*75*2 :
+ Index=2;
+ break;
+ case 2352*75*4 :
+ Index=4;
+ break;
+ case 2352*75*6 :
+ Index=6;
+ break;
+ case 2352*75*8 :
+ Index=8;
+ break;
+ default :
+ Index=0;
+ }
+ if (IsOldPhilips(&Config))
+ ModeSenseData[14]=Index;
+ else
+ ModeSenseData[16]=Index;
+ if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,20,m_hDriveEvent))
+ Error=CDASPIError;
+ break;
+ }
+ }
+}
+
+int CSCSICD::GetSpeed(BYTE Index)
+{
+ if (Index<SupportedSpeeds)
+ return SpeedTable[Index];
+ return 0;
+}
+
+
+// ----------------------------------------------------------------------------------------
+// - Implementation of general functions -
+// - -
+// - Author: Christoph Schmelnik -
+// - Purposee: variour initialisations -
+// ----------------------------------------------------------------------------------------
+
+extern "C" DWORD NtScsiSendASPI32Command( LPSRB lpsrb );
+int LoadASPI2()
+{
+ OSVERSIONINFO VersionInfo;
+ VersionInfo.dwOSVersionInfoSize=sizeof(VersionInfo);
+ GetVersionEx(&VersionInfo);
+ if (VersionInfo.dwPlatformId==VER_PLATFORM_WIN32_NT)
+ RunningNT=TRUE;
+ else
+ RunningNT=FALSE;
+ ASPIInstalled=TRUE;
+
+ hDLL=LoadLibrary(L"WNASPI32.DLL"); // load DLL
+
+ if (hDLL==0)
+ {
+ if(RunningNT) {
+ // ok, let's try to see if we can use NT's internal SCSI manager
+ extern int NtScsiInit( void );
+ int nb;
+ if(nb=NtScsiInit()) {
+ NumberOfHostAdapters=nb;
+ SendASPI32Command=(SRBPROC)&NtScsiSendASPI32Command;
+ return TRUE;
+ }
+ }
+ ASPIInstalled=FALSE;
+ return FALSE;
+ }
+ GetASPI32SupportInfo=(VOIDPROC)GetProcAddress(hDLL,"GetASPI32SupportInfo"); // get Address
+ SendASPI32Command=(SRBPROC)GetProcAddress(hDLL,"SendASPI32Command"); // get Address
+ if (GetASPI32SupportInfo==NULL)
+ {
+ ASPIInstalled=FALSE;
+ return FALSE;
+ }
+ if (SendASPI32Command==NULL)
+ {
+ ASPIInstalled=FALSE;
+ return FALSE;
+ }
+ int r=GetASPI32SupportInfo();
+ if (HIBYTE(r)!=SS_COMP)
+ {
+ ASPIInstalled=FALSE;
+ return FALSE;
+ }
+ NumberOfHostAdapters=LOBYTE(r);
+ return TRUE;
+}
+
+int LoadASPI() {
+ int ret=0;
+ __try {
+ ret=LoadASPI2();
+ } __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ret=0;
+ }
+ return ret;
+}
+
+
+int FreeASPI()
+{
+ extern int NtScsiDeInit( void );
+ NtScsiDeInit();
+ if (hDLL) FreeLibrary(hDLL);
+ hDLL=NULL;
+ return TRUE;
+}
+
+
+int CheckASPI()
+{
+ return ASPIInstalled;
+} \ No newline at end of file
diff --git a/Src/Plugins/Input/in_cdda/windac/Dac32.dsp b/Src/Plugins/Input/in_cdda/windac/Dac32.dsp
new file mode 100644
index 00000000..714b0166
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/Dac32.dsp
@@ -0,0 +1,127 @@
+# Microsoft Developer Studio Project File - Name="Dac32" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Dac32 - Win32 Release
+!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE
+!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl
+!MESSAGE
+!MESSAGE NMAKE /f "Dac32.mak".
+!MESSAGE
+!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben
+!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
+!MESSAGE
+!MESSAGE NMAKE /f "Dac32.mak" CFG="Dac32 - Win32 Release"
+!MESSAGE
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE
+!MESSAGE "Dac32 - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Dac32 - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/Win32/Digital Audio Copy/DAC32 DLL", FAAAAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Dac32 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\WinRel"
+# PROP BASE Intermediate_Dir ".\WinRel"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release"
+# PROP Intermediate_Dir ".\Release"
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "DLL" /Fr /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# SUBTRACT LINK32 /map /nodefaultlib
+
+!ELSEIF "$(CFG)" == "Dac32 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\WinDebug"
+# PROP BASE Intermediate_Dir ".\WinDebug"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug"
+# PROP Intermediate_Dir ".\Debug"
+# ADD BASE CPP /nologo /MT /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "DLL" /Fr /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# SUBTRACT LINK32 /nodefaultlib
+
+!ENDIF
+
+# Begin Target
+
+# Name "Dac32 - Win32 Release"
+# Name "Dac32 - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\aspifunc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\dac32.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\dac32.rc
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=.\Aspifunc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Dac32.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Scsidefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Winaspi.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Src/Plugins/Input/in_cdda/windac/Dac32.h b/Src/Plugins/Input/in_cdda/windac/Dac32.h
new file mode 100644
index 00000000..4e4ab624
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/Dac32.h
@@ -0,0 +1,775 @@
+// ----------------------------------------------
+// - DAC32.DLL Header Datei -
+// - Written 1996-1998 by Christoph Schmelnik -
+// ----------------------------------------------
+
+// Changes
+// ===========
+// Version 1.2 :
+// -CMapDrive supports now up to 34 Host Adapters, because now it could access the drives under
+// NT with the DeviceControl Interface
+// The required information for this is coded as:
+// Drives accessed over the new Interface have a HostAdapterNumber above or equal to the
+// NumberOfHostAdapters (global Information).
+// The ID consists of the good old drive number, like in DOS.
+// The LUN is not used for the configuration, but it is used to hold the open handle to the device
+// The Burstmodus couldn't be used with the new access mode, so the default setting for those
+// drives is the Normal-mode. (For those drives is no difference between Burst- and Normal-mode)
+// -LoadASPI checks now the Windows Version and hold this result global in the DLL
+// -The Constructor of CSCSCD opens the handles to the new devices
+// -The destructor closes those handles
+// Interface changes are not required but some values must be handled differnt to avoid
+// misconfiguring, e.g. it is not allowed to configure the new drives ID, LUN, and HostAdapterNumber
+// -A bug in CWaveSave regarding conversion to mixed mono has been fixed.
+//
+// Version 1.33 : 18.01.1998
+// Changes:
+// Added speed selection support for all current Plextor drives
+//
+// Version 1.40 : 24.02.1998
+// Changes:
+// Set correct direction flags, to work with NT device IO interface and ATAPI drives
+// Changed main CD detection to TestUnitReady
+// Removed CD detection from Audio Status Info
+// Added hopefully correct read command for Matsushita/Panasonic drives
+// Added Parameters to CDAC class to allow the disabling of the audio test and to spin up the drive for a specified time
+// in seconds to avoid spin up problems on some drives. Both parameters have default values so it behaves like the old version
+// without the additional parameters
+// Added Parameter to the constructor of CWaveSave to disable writing any Headers. Also this parameter has a default to work like
+// before.
+// Added virtual function in CDAC to report buffer underruns in Burst Copy Mode
+// For the last feature an immediate parameter in WaitCDDA is added
+// GetLastSense function added to return the sense information for the last read audio command
+// Configuration in CMapDrive extended by new features
+// Fixed GetRedBook operator in CCDAdress
+// Added function to CD Class to read Media Cataloge Number
+//
+// Version 1.41 : 28.04.1998
+// Changes:
+// New GetInfoEx() function in CMapDrive, to allow a better result checking.
+//
+// Version 1.42 : 02.08.1998
+// Changes:
+// Added GetLastReadableAddress function to get the last readable Sektor of a session.
+// Added a flag in the drive properties for the function.
+// Added this function to the CDAC object.
+//
+// Version 1.43 : 23.12.1998
+// Changes:
+// Added Wave and DAC classes are now available in a MT version, the old versions will not longer be updated.
+//
+// Version 1.44 : 10.03.1999
+// Changes:
+// Added Support for current Plextor CDROM drives and CD-Writers.
+// Added Support for Jukeboxes
+// Changed Handling of the Ringbuffer
+//
+// Version 1.45 : 15.08.1999
+// Changes:
+// Added Enhanced error detection for Plextor drives.
+// Several Bugfixes (initialising under NT and Ringbuffer specific)
+//
+// Version 1.45-Build 11 : 11.11.1999
+// Changes:
+// Added a check for the MaxSektor parameter in CBaseWaveMT to avoid Program failures even if the applications provides an invalid value.
+// Changed source to comile with Borland compiler
+// Added MMC-2 Type which will be default for Sony CD-Writers 140 and 928
+// Skip Virtual CD devices in Bus scan
+// Fixed Array out of bound bug in drive detection.
+
+
+#ifndef _DAC32_H
+#define _DAC32_H
+
+#ifndef STRICT
+#define STRICT // Use strct typechecking
+#define WIN32_LEAN_AND_MEAN // compile only important Headerfiles
+#endif
+
+#include <windows.h>
+#include <stdio.h>
+#include "aspifunc.h"
+
+/*#ifdef DLL
+#define DACDLL __declspec(dllexport)
+#else
+#define DACDLL __declspec(dllimport)
+#endif*/
+#define DACDLL
+
+#ifdef _DEBUG
+#define DBGOUT(sz) OutputDebugString(sz)
+#else
+#define DBGOUT(sz)
+#endif
+
+//The Errormessages for the CD and DAC Classes
+#define CDOK 0x000
+#define CDUnknownDrive 0x001
+#define CDDriveNotReady 0x002
+#define CDUnknownCommand 0x003
+#define CDSeekError 0x006
+#define CDSectorNotFound 0x008
+#define CDReadError 0x00B
+#define CDGeneralError 0x00C
+#define CDNoCD 0x00E
+#define CDIllegalCDChange 0x00F
+#define CDDriveNotFound 0x100
+#define CDNoMemory 0x101
+#define CDDACUnable 0x102
+#define CDASPIError 0x103
+#define CDUserBreak 0x104
+#define CDTimeOut 0x105
+
+//The Errormessage for the wave classes
+#define WAVEFileOpenError 0x200
+#define WAVEFileWriteError 0x201
+#define WAVEChannelError 0x202
+#define WAVEBitsError 0x203
+#define WAVEFreqError 0x204
+#define WAVENameError 0x205
+#define WAVEMemoryError 0x206
+
+//The supported base drive types
+#define CDTYPE_TOSHIBA 0
+#define CDTYPE_SONY 1
+#define CDTYPE_NEC 2
+#define CDTYPE_PHILIPS 3
+#define CDTYPE_ATAPI 4
+#define CDTYPE_TOSHNEW 5
+#define CDTYPE_RICOH 6
+#define CDTYPE_MATSHITA 7
+#define CDTYPE_PLEXTOR 8
+#define CDTYPE_CYBERDRV 9
+
+#define JUKETYPE_SONY 0
+#define JUKETYPE_PIONEER 1
+
+//Amount of predefined drive mappings (relationship between real drives and base drive types)
+#define MaxMappings 22 // pgo
+
+//Amount of predefined jukebox mappings (relationship between real jukeboxes and base jukebox types)
+#define MaxMappingsJuke 2
+
+//The possible Copy modes
+#define ModeNormal 0
+#define ModeSynch 1
+#define ModeBurst 2
+
+//The possible Values for the DA Test
+#define DATEST_ALLWAYS 0
+#define DATEST_FIRSTTRACK 1
+#define DATEST_NEVER 2
+
+//The possible SpinUp modes
+#define SPINUP_ALLWAYS 0
+#define SPINUP_FIRSTTRACK 1
+#define SPINUP_NEVER 2
+
+// Amount of DWORD for the synchronisation
+#define SynLen 512
+
+// The Class for the Addressformats
+class DACDLL CCDAdress
+{
+public:
+ void SetRedbook(long Value);
+ void SetHSG(long Value)
+ {
+ Adresse=Value;
+ };
+ long GetHSG()
+ {
+ return Adresse;
+ };
+ long GetRedbook()
+ {
+ long t;
+ t=(Adresse % 75)<<24;
+ t+=((Adresse / 75) % 60)<<16;
+ t+=((Adresse / 75) / 60)<<8;
+ return t;
+ };
+ CCDAdress &operator = (const CCDAdress &other)
+ {
+ Adresse=other.Adresse;
+ return (*this);
+ };
+ CCDAdress &operator + (const long Value)
+ {
+ Adresse+=Value;
+ return (*this);
+ };
+ CCDAdress &operator - (const long Value)
+ {
+ Adresse-=Value;
+ return (*this);
+ };
+ CCDAdress &operator += (const long Value)
+ {
+ Adresse+=Value;
+ return (*this);
+ };
+ CCDAdress &operator -= (const long Value)
+ {
+ Adresse-=Value;
+ return (*this);
+ };
+private:
+ long Adresse;
+};
+
+// Typendeclarations
+struct TDriveStatus
+{
+ int DoorOpen; //Door open/closed
+ int DoorLocked; //Door locked/unlocked
+ int Cooked_RAW; //supports Cooked and RAW or Cooked
+ int Read_Write; //supports read and write
+ int Data_Audio_Video; //supports Data/Audio/Video or only Data
+ int Interleave; //supports Interleave regarding ISO
+ int CommandPrefetch; //supports Command Prefetching
+ int AudioChannelManipulation; //supports Audio-Channel Manipulation
+ int HSG_Redbook; //supports HSG and Redbook Addressing or only HSG
+ int CDPresent; //CD inserted or not
+ int RWSupport; //supports R-W-Sub Channels
+};
+
+struct TAudioStatus
+{
+ BOOL Pause; //Play is paused
+ BOOL IsPlaying; //CD is playing
+ BOOL IsDone; //Play is stopped
+ BOOL PlayError; //Play completed with error
+ int TrackNummer; //Number of actual track
+ CCDAdress AbsSektor,RelSektor; //Startsector and Endsector of last/next Play
+};
+
+struct TTrackFlag
+{
+ BYTE AudioChannels; //Amount of Audio Channels (2/4)
+ BOOL PreEmphasis; //Audio Channel with or without...
+ BOOL DataTrack; //Data track or Audio track
+ BOOL CopyProhibeted; //Digital copy prohibited
+};
+
+struct TTrackList
+{
+ BYTE TrackNummer; //Number of Track
+ CCDAdress StartSektor; //First sector in HSG Format
+ long Laenge; //Amount of Sectors
+ TTrackFlag Flags;
+};
+
+struct TTrackListeMem
+{
+ TTrackList Info;
+ TTrackListeMem *Prev,*Next;
+};
+
+struct TDriveInfo
+{
+ int ID;
+ int LUN;
+ int HostAdapterNumber;
+ int Type;
+ int MaxSektors;
+ int SynchSektors;
+ int Mode;
+ char VendorID[9];
+ char ProductID[17];
+ int Speed;
+ int PerformDATest;
+ int SpinUpMode;
+ DWORD dwSpinUpTime;
+ BOOL bUseLastReadableAddress;
+ BOOL bUseC2ErrorInfo;
+ BOOL bSpinDown;
+};
+
+struct TJukeInfo
+{
+ int ID;
+ int LUN;
+ int HostAdapterNumber;
+ int Type;
+ int MaxDrives;
+ int *pConnectedDrives;
+ int MaxDiscs;
+ char VendorID[9];
+ char ProductID[17];
+};
+
+// The class with the infos for the type mapping
+class DACDLL CMapInfo
+{
+public:
+ CMapInfo();
+ char *GetTypName(int Index);
+ int GetTypMapping(int Index);
+ int GetTypMappingRev(int CDType);
+private:
+ char TypNamen[MaxMappings][9];
+ int TypMapping[MaxMappings];
+};
+
+// The class with the infos for the type mapping
+class DACDLL CMapInfoJuke
+{
+public:
+ CMapInfoJuke();
+ char *GetTypName(int Index);
+ int GetTypMapping(int Index);
+ int GetTypMappingRev(int JukeType);
+private:
+ char TypNamen[MaxMappingsJuke][9];
+ int TypMapping[MaxMappingsJuke];
+};
+
+// The base class (pure virtual) for the CD access
+class DACDLL CBaseCD
+{
+public:
+ int Lasterror();
+ virtual void PrepareCDDA()=0;
+ virtual void ReadCDDA(CCDAdress StartSektor,long Sektoranzahl,void *Buffer,BOOL bUseC2ErrorInfo=FALSE)=0;
+ virtual BOOL WaitCDDA(BOOL bImmediate=FALSE)=0;
+ virtual void FinishCDDA()=0;
+ virtual void SortWaveData(DWORD *Data,int Samples)=0;
+ virtual CCDAdress GetErrorAdress()=0;
+ virtual void Play_Audio(CCDAdress StartSektor,long Sektoranzahl)=0;
+ virtual void Stop_Audio()=0;
+ virtual void Pause_Audio()=0;
+ virtual void Resume_Audio()=0;
+ virtual TDriveStatus Get_DriveStatus()=0;
+ virtual BOOL MediaChanged()=0;
+ virtual void Get_MediaCatalogNumber(char szUPC[16])=0;
+ virtual void EjectDisk()=0;
+ virtual void LockDoor(int Lock)=0;
+ virtual void CloseTray()=0;
+ virtual void ReRead()=0;
+ virtual CCDAdress GetLastReadableAddress(CCDAdress StartSektor)=0;
+ virtual int GetMaxSektors()=0;
+ virtual int GetSynchSektors()=0;
+ virtual int GetMode()=0;
+ virtual int GetSpeed()=0;
+ virtual void InitSpeedTable()=0;
+ virtual BYTE GetSupportedSpeeds()=0;
+ virtual int GetCurrentSpeed()=0;
+ virtual void SetCurrentSpeed(int Speed)=0;
+ virtual int GetSpeed(BYTE Index)=0;
+ int ReadFirstTrackInfo(TTrackList &Infos);
+ int ReadNextTrackInfo(TTrackList &Infos);
+ int ReadPrevTrackInfo(TTrackList &Infos);
+ int ReadTrackInfo(TTrackList &Infos);
+ int ReadMaxTracks();
+protected:
+ int Error,BusyFlag,DoneFlag;
+ TTrackListeMem *FirstTrack,*AktTrack;
+ void DeleteTrackList();
+private:
+ CBaseCD& operator = (const CBaseCD &other);
+};
+
+// The class for the access to SCSI drives
+class DACDLL CSCSICD:public CBaseCD
+{
+public:
+ CSCSICD (char drive, TDriveInfo &xInfo);
+ ~CSCSICD();
+ virtual void PrepareCDDA();
+ virtual void ReadCDDA(CCDAdress StartSektor,long Sektoranzahl,void *Buffer,BOOL bUseC2ErrorInfo=FALSE);
+ virtual BOOL WaitCDDA(BOOL bImmediate=FALSE);
+ virtual void FinishCDDA();
+ virtual void SortWaveData(DWORD *Data,int Samples);
+ virtual CCDAdress GetErrorAdress();
+ virtual void Play_Audio(CCDAdress StartSektor,long Sektoranzahl);
+ virtual void Stop_Audio();
+ virtual void Pause_Audio();
+ virtual void Resume_Audio();
+ virtual TDriveStatus Get_DriveStatus();
+ virtual BOOL MediaChanged();
+ virtual TAudioStatus Get_AudioStatus_Info();
+ virtual void Get_MediaCatalogNumber(char szUPC[16]);
+ virtual void EjectDisk();
+ virtual void LockDoor(int Lock);
+ virtual void CloseTray();
+ virtual void ReRead();
+ virtual CCDAdress GetLastReadableAddress(CCDAdress StartSektor);
+ virtual int GetMaxSektors();
+ virtual int GetSynchSektors();
+ virtual int GetMode();
+ virtual int GetSpeed();
+ virtual void InitSpeedTable();
+ virtual BYTE GetSupportedSpeeds();
+ virtual int GetCurrentSpeed();
+ virtual void SetCurrentSpeed(int Speed);
+ virtual int GetSpeed(BYTE Index);
+ TDriveInfo &GetInfo()
+ {
+ return Config;
+ };
+ TSenseInfo GetSense();
+ TSenseInfo GetLastSenseInfo();
+
+private:
+ CSCSICD& operator = (const CSCSICD &other);
+
+ TDriveInfo &Config; // Drive Configuration
+ BOOL CDPresentLast,Changed; // Helpvariables for the MediaChanged function
+ SRB_ExecSCSICmd ReadSRB; // SCSI Commando Block
+ TDriveMode ModeData;
+ BYTE NECRotationSpeed;
+ CMapInfo MapInfo;
+ DWORD StartReadTime;
+ int SpeedTable[256];
+ BYTE SupportedSpeeds;
+ HANDLE m_hDriveEvent;
+ TSenseInfo m_SenseInfo;
+ BOOL m_bSpeedTableInitialized;
+};
+
+// The base class for saving/converting the audio data
+class DACDLL CBaseWave
+{
+public:
+ int Lasterror();
+ virtual void WritePuffer(long Samples,DWORD *Buffer)=0;
+protected:
+ int Error; //last occured error
+private:
+ CBaseWave& operator = (const CBaseWave &other);
+};
+
+typedef struct
+{
+ BOOL bIsUsed; //Is Buffer used?
+ BOOL bReady; //Is Nuffer ready to write?
+ int nSamples; //Number of Samples in Buffer.
+ int nZeroSamples; //Number of Silence Samples to insert before the buffer
+ DWORD *dwBuffer; //Buffer for Audio Data
+} WAVEBUFFER, *PWAVEBUFFER;
+
+typedef struct _WAVEBUFFERLIST
+{
+ PWAVEBUFFER pWaveBuffer;
+ _WAVEBUFFERLIST *pNext;
+} WAVEBUFFERLIST, *PWAVEBUFFERLIST;
+
+
+typedef struct
+{
+ HANDLE hEvent;
+ LPVOID pData;
+} TWAVEMTSTRUCT;
+
+// The base class for saving/converting the audio data as its own thread
+class DACDLL CBaseWaveMT
+{
+public:
+ CBaseWaveMT(DWORD dwBufferSize,BOOL bUseHighPriority=FALSE,int MaxSektors=27,DWORD dwExtraBytes=0);
+ ~CBaseWaveMT();
+
+ void SetFadeInOut(int dwTotalSamples,int dwFadeSamples);
+
+ PWAVEBUFFER GetBuffer(); //returns NULL if no Buffer is available
+ void SignalBuffer(); //signal if a buffer is filled;
+ int Lasterror();
+ double GetBufferFullRatio();
+ DWORD GetBytesInBuffer();
+
+ virtual void WritePuffer(long Samples,DWORD *Buffer)=0;
+
+ friend unsigned _stdcall WaveThreadProc(LPVOID pUserData);
+
+protected:
+ int Error; //last occured error
+
+ void StartThread(); //call this from your own initialisation function
+ BOOL WriteData();
+ void StopThread(BOOL bImmediate=FALSE); //call this from your own cleanup function
+
+private:
+ CBaseWaveMT& operator = (const CBaseWaveMT &other);
+
+ DWORD m_Nullen[256];
+ PWAVEBUFFERLIST m_pFirstBuffer, m_pReadBuffer, m_pWriteBuffer;
+ TWAVEMTSTRUCT m_WaveInfo;
+ BOOL m_bStopThread,m_bAbortThread,m_bIsWorking;
+ HANDLE m_hWaveThread;
+ BOOL m_bUseHighPriority;
+ int m_dwTotalSamples,m_dwFadeSamples,m_dwCurrentSample;
+ int m_nBufferNum,m_nReadBufferNum,m_nWriteBufferNum;
+ int m_nMaxSektors;
+};
+
+// The class for saving audio data in a wave file
+class DACDLL CWaveSave:public CBaseWave
+{
+public:
+ CWaveSave(const char *DateiName,BYTE Freq,BYTE Channels,BYTE Bits,BOOL bWriteHeaders=TRUE);
+ ~CWaveSave();
+ virtual void WritePuffer(long Samples,DWORD *Buffer);
+private:
+ void WMono8(long Samples,DWORD *Buffer);
+ void WStereo8(long Samples,DWORD *Buffer);
+ void WMono16(long Samples,DWORD *Buffer);
+ void WStereo16(long Samples,DWORD *Buffer);
+ void WLR8(long Samples,int Mode,DWORD *Buffer);
+ void WLR16(long Samples,int Mode,DWORD *Buffer);
+
+ CWaveSave& operator = (const CWaveSave &other);
+
+ BYTE ConvertType; //CodeNumber of the conversion type
+ FILE *Datei; //file variable to access the wave file
+ WORD *DPM16; //Pointer to the file data buffer
+ BYTE *DPM8; //Pointer to the file data buffer
+ DWORD *DPS16; //Pointer to the file data buffer
+ BYTE *DPS8; //Pointer to the file data buffer
+ int DatenCount; //Counter of data in buffer
+ long WaveBytes; //Counts all written bytes
+ BYTE SAdd; //Value to increment the source counter
+ BOOL m_bWriteHeaders; //Write Headers of Wave file
+};
+
+// The class for saving audio data in a wave file in its own thread
+class DACDLL CWaveSaveMT:public CBaseWaveMT
+{
+public:
+ CWaveSaveMT(DWORD dwBufferSize,BOOL bUseHighPriority=FALSE,int MaxSektors=27,DWORD dwExtraBytes=0):CBaseWaveMT(dwBufferSize,bUseHighPriority,MaxSektors,dwExtraBytes)
+ {
+ };
+ void Init(const char *DateiName,BYTE Freq,BYTE Channels,BYTE Bits,BOOL bWriteHeaders=TRUE);
+ void Done(BOOL bImmediate=FALSE);
+ virtual void WritePuffer(long Samples,DWORD *Buffer);
+private:
+ void WMono8(long Samples,DWORD *Buffer);
+ void WStereo8(long Samples,DWORD *Buffer);
+ void WMono16(long Samples,DWORD *Buffer);
+ void WStereo16(long Samples,DWORD *Buffer);
+ void WLR8(long Samples,int Mode,DWORD *Buffer);
+ void WLR16(long Samples,int Mode,DWORD *Buffer);
+
+ CWaveSave& operator = (const CWaveSave &other);
+
+ BYTE ConvertType; //CodeNumber of the conversion type
+ FILE *Datei; //file variable to access the wave file
+ WORD *DPM16; //Pointer to the file data buffer
+ BYTE *DPM8; //Pointer to the file data buffer
+ DWORD *DPS16; //Pointer to the file data buffer
+ BYTE *DPS8; //Pointer to the file data buffer
+ int DatenCount; //Counter of data in buffer
+ long WaveBytes; //Counts all written bytes
+ BYTE SAdd; //Value to increment the source counter
+ BOOL m_bWriteHeaders; //Write Headers of Wave file
+};
+
+// The class for copying the audio data from CD.
+class DACDLL CDAC
+{
+public:
+ CDAC(CBaseCD *pDrive,CBaseWave *pWave,
+ CCDAdress Start,long Laenge,BOOL xKillZeros,BOOL bPerformDATest=TRUE,DWORD dwSpinUpTime=0,BOOL bUseLastReadableAddress=FALSE);
+ ~CDAC();
+ int Lasterror();
+ void Copy();
+ int Errors();
+ void StopCopy();
+
+ // The following member functions are declared as virtual. They could be used to display
+ // information to the user. They do nothing by default.
+ virtual void WriteInit();
+ virtual void WritePercent(float Percent);
+ virtual void WriteReading();
+ virtual void WriteReadingEnd();
+ virtual void WriteSynch();
+ virtual void WriteSynchEnd();
+ virtual void WriteFlushing();
+ virtual void WriteFlushingEnd();
+ virtual void WriteSynchError();
+ virtual void WriteBufferUnderrun(CCDAdress Start);
+ virtual void WriteReRead(CCDAdress Start,long Laenge);
+ virtual void WriteSektorsSkipped(CCDAdress Start,long Laenge);
+ virtual void WriteDone();
+ virtual void OnIdle();
+
+protected:
+ CCDAdress StartSektor,StartOld;
+ int SynchErrors,Error;
+ long Anzahl,AnzahlOld,Remain;
+
+private:
+ CBaseCD *m_pCD;
+ BOOL RunCopy,KillFirst,KillLast,KillZero,Found;
+ DWORD m_dwSpinUpTime;
+ CBaseWave *m_pWaveSave;
+ long SektorAnzahl,Retries,SynchDiff,ZeroCount;
+ DWORD *MemBlocks[2];
+ int BlockCount,S_Offset;
+ int SpeedSave;
+ DWORD m_Nullen[256];
+
+ void ReadCDDA(CCDAdress Start,long Sektoranzahl,void *Buffer);
+ void FlushWave();
+ void FlushSynch(int Samples,DWORD *Data);
+ void MakeTable(DWORD *Werte,DWORD *Table);
+ int SynchSearch(DWORD *String1,DWORD *String2,DWORD *Table);
+ void SynchWave();
+
+ CDAC& operator = (const CDAC &other);
+};
+
+// The class for copying the audio data from CD.
+class DACDLL CDACMT
+{
+public:
+ CDACMT(CBaseCD *pDrive,CBaseWaveMT *pWave,
+ CCDAdress Start,long Laenge,BOOL xKillZeros,BOOL bPerformDATest=TRUE,DWORD dwSpinUpTime=0,BOOL bUseHighPriority=FALSE,BOOL bUseC2ErrorInfo=FALSE,BOOL bSpinDown=FALSE,BOOL bUseLastReadableAddress=FALSE);
+ ~CDACMT();
+ int Lasterror();
+ void Copy();
+ int Errors();
+ void StopCopy();
+
+ // The following member functions are declared as virtual. They could be used to display
+ // information to the user. They do nothing by default.
+ virtual void WriteInit();
+ virtual void WritePercent(float Percent);
+ virtual void WriteReading();
+ virtual void WriteReadingEnd();
+ virtual void WriteSynch();
+ virtual void WriteSynchEnd();
+ virtual void WriteFlushing();
+ virtual void WriteFlushingEnd();
+ virtual void WriteSynchError();
+ virtual void WriteBufferUnderrun(CCDAdress Start);
+ virtual void WriteReRead(CCDAdress Start,long Laenge);
+ virtual void WriteSektorsSkipped(CCDAdress Start,long Laenge);
+ virtual void WriteDone();
+ virtual void OnIdle(BOOL bReturnFast=TRUE);
+
+ friend unsigned _stdcall DACThreadProc(LPVOID pUserData);
+protected:
+ CCDAdress StartSektor,StartOld;
+ int SynchErrors,Error;
+ long Anzahl,AnzahlOld,Remain;
+
+ void CopyMT();
+private:
+ CBaseCD *m_pCD;
+ BOOL RunCopy,KillFirst,KillLast,KillZero,Found;
+ DWORD m_dwSpinUpTime;
+ CBaseWaveMT *m_pWaveSave;
+ BOOL m_bUseC2ErrorInfo;
+ BOOL m_bSpinDown;
+ long SektorAnzahl,Retries,SynchDiff,ZeroCount;
+ PWAVEBUFFER MemBlocks[2];
+ int BlockCount,S_Offset;
+ int SpeedSave;
+ int m_MaxSektors;
+ int m_SynchSektors;
+
+ void ReadCDDA(CCDAdress Start,long Sektoranzahl,void *Buffer);
+ void FlushWave(int nMax=2);
+ void FlushSynch(int Samples,PWAVEBUFFER Data);
+ void MakeTable(DWORD *Werte,DWORD *Table);
+ int SynchSearch(DWORD *String1,DWORD *String2,DWORD *Table);
+ void SynchWave();
+
+ CDACMT& operator = (const CDACMT &other);
+
+ HANDLE m_hDACThread;
+ BOOL m_bUseHighPriority;
+};
+
+// The class for configuring the SCSI CDROM drives
+class DACDLL CMapDrive
+{
+public:
+ CMapDrive(BOOL bDoReset=TRUE);
+ ~CMapDrive();
+ void Reset();
+ int GetMaxDrives();
+ TDriveInfo &GetInfo(int index);
+ BOOL GetInfoEx(int index, TDriveInfo *&pInfo);
+ void DeleteInfo(int index);
+ int GetMaxHostAdapters();
+ int GetSupportedHostAdapterMemory(int index);
+ void SetSupportedHostAdapterMemory(int index,int Memory);
+ int GetMaxSektors(int HostAdapterNumber);
+protected:
+ void DeleteAll();
+
+private:
+ struct TDriveInfoMem
+ {
+ TDriveInfo Info;
+ TDriveInfoMem *Next;
+ };
+ TDriveInfoMem *First;
+ int HostAdapterMemory[34];
+ HANDLE m_hDriveEvent;
+};
+
+
+// The class for configuring the SCSI Jukeboxes
+class DACDLL CMapJuke
+{
+public:
+ CMapJuke(BOOL bDoReset=TRUE);
+ ~CMapJuke();
+ void Reset();
+ int GetMaxJukes();
+ TJukeInfo &GetInfo(int index);
+ BOOL IsWorking(int index);
+ void SetWorking(int index,BOOL bIsWorking);
+ void DeleteInfo(int index);
+protected:
+ void DeleteAll();
+
+private:
+ struct TJukeInfoMem
+ {
+ TJukeInfo Info;
+ BOOL bIsWorking;
+ TJukeInfoMem *Next;
+ };
+ TJukeInfoMem *First;
+ HANDLE m_hJukeEvent;
+};
+
+//The class to access Jukeboxes
+class DACDLL CJukeBox
+{
+public:
+ CJukeBox (TJukeInfo &xInfo);
+ ~CJukeBox();
+ //use following defines to address an item in the jukebox:
+ //drive0..x : 0x4000...0x400x
+ //storage1..xxx : 0x0001...0x0xxx
+ BOOL MoveMedium(int Source,int Destination);
+ TJukeInfo &GetInfo()
+ {
+ return Config;
+ };
+
+private:
+ TJukeInfo &Config; // Drive Configuration
+ CMapInfoJuke MapInfo;
+ HANDLE m_hJukeEvent;
+};
+
+
+// ----------------------
+// function declarations
+// ----------------------
+
+// initialize and deinatialize the WNASPI32.DLL and some internal flags
+int DACDLL LoadASPI();
+int DACDLL FreeASPI();
+
+int DACDLL CheckASPI();
+
+
+
+#endif //_DAC32_H \ No newline at end of file
diff --git a/Src/Plugins/Input/in_cdda/windac/Dac32.mak b/Src/Plugins/Input/in_cdda/windac/Dac32.mak
new file mode 100644
index 00000000..46b175f7
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/Dac32.mak
@@ -0,0 +1,285 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+!IF "$(CFG)" == ""
+CFG=Dac32 - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to Dac32 - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "Dac32 - Win32 Release" && "$(CFG)" != "Dac32 - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Dac32.mak" CFG="Dac32 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Dac32 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Dac32 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "Dac32 - Win32 Debug"
+CPP=cl.exe
+RSC=rc.exe
+MTL=mktyplib.exe
+
+!IF "$(CFG)" == "Dac32 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "WinRel"
+# PROP BASE Intermediate_Dir "WinRel"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "$(OUTDIR)\Dac32.dll" "$(OUTDIR)\Dac32.bsc"
+
+CLEAN :
+ -@erase "$(INTDIR)\aspifunc.obj"
+ -@erase "$(INTDIR)\aspifunc.sbr"
+ -@erase "$(INTDIR)\dac32.obj"
+ -@erase "$(INTDIR)\dac32.res"
+ -@erase "$(INTDIR)\dac32.sbr"
+ -@erase "$(OUTDIR)\Dac32.bsc"
+ -@erase "$(OUTDIR)\Dac32.dll"
+ -@erase "$(OUTDIR)\Dac32.exp"
+ -@erase "$(OUTDIR)\Dac32.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "DLL" /Fr /YX /c
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "DLL"\
+ /Fr"$(INTDIR)/" /Fp"$(INTDIR)/Dac32.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\Release/
+CPP_SBRS=.\Release/
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+RSC_PROJ=/l 0x407 /fo"$(INTDIR)/dac32.res" /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/Dac32.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\aspifunc.sbr" \
+ "$(INTDIR)\dac32.sbr"
+
+"$(OUTDIR)\Dac32.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# SUBTRACT LINK32 /map /nodefaultlib
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\
+ /pdb:"$(OUTDIR)/Dac32.pdb" /machine:I386 /out:"$(OUTDIR)/Dac32.dll"\
+ /implib:"$(OUTDIR)/Dac32.lib"
+LINK32_OBJS= \
+ "$(INTDIR)\aspifunc.obj" \
+ "$(INTDIR)\dac32.obj" \
+ "$(INTDIR)\dac32.res"
+
+"$(OUTDIR)\Dac32.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "Dac32 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "WinDebug"
+# PROP BASE Intermediate_Dir "WinDebug"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+OUTDIR=.\Debug
+INTDIR=.\Debug
+
+ALL : "$(OUTDIR)\Dac32.dll" "$(OUTDIR)\Dac32.bsc"
+
+CLEAN :
+ -@erase "$(INTDIR)\aspifunc.obj"
+ -@erase "$(INTDIR)\aspifunc.sbr"
+ -@erase "$(INTDIR)\dac32.obj"
+ -@erase "$(INTDIR)\dac32.res"
+ -@erase "$(INTDIR)\dac32.sbr"
+ -@erase "$(INTDIR)\vc40.idb"
+ -@erase "$(INTDIR)\vc40.pdb"
+ -@erase "$(OUTDIR)\Dac32.bsc"
+ -@erase "$(OUTDIR)\Dac32.dll"
+ -@erase "$(OUTDIR)\Dac32.exp"
+ -@erase "$(OUTDIR)\Dac32.ilk"
+ -@erase "$(OUTDIR)\Dac32.lib"
+ -@erase "$(OUTDIR)\Dac32.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+# ADD BASE CPP /nologo /MT /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "DLL" /Fr /YX /c
+CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\
+ /D "DLL" /Fr"$(INTDIR)/" /Fp"$(INTDIR)/Dac32.pch" /YX /Fo"$(INTDIR)/"\
+ /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=.\Debug/
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+RSC_PROJ=/l 0x407 /fo"$(INTDIR)/dac32.res" /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/Dac32.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\aspifunc.sbr" \
+ "$(INTDIR)\dac32.sbr"
+
+"$(OUTDIR)\Dac32.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# SUBTRACT LINK32 /nodefaultlib
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /dll /incremental:yes\
+ /pdb:"$(OUTDIR)/Dac32.pdb" /debug /machine:I386 /out:"$(OUTDIR)/Dac32.dll"\
+ /implib:"$(OUTDIR)/Dac32.lib"
+LINK32_OBJS= \
+ "$(INTDIR)\aspifunc.obj" \
+ "$(INTDIR)\dac32.obj" \
+ "$(INTDIR)\dac32.res"
+
+"$(OUTDIR)\Dac32.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+################################################################################
+# Begin Target
+
+# Name "Dac32 - Win32 Release"
+# Name "Dac32 - Win32 Debug"
+
+!IF "$(CFG)" == "Dac32 - Win32 Release"
+
+!ELSEIF "$(CFG)" == "Dac32 - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\dac32.cpp
+
+!IF "$(CFG)" == "Dac32 - Win32 Release"
+
+DEP_CPP_DAC32=\
+ ".\Aspifunc.h"\
+ ".\Dac32.h"\
+ ".\Scsidefs.h"\
+ ".\Winaspi.h"\
+
+
+"$(INTDIR)\dac32.obj" : $(SOURCE) $(DEP_CPP_DAC32) "$(INTDIR)"
+
+"$(INTDIR)\dac32.sbr" : $(SOURCE) $(DEP_CPP_DAC32) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "Dac32 - Win32 Debug"
+
+DEP_CPP_DAC32=\
+ ".\Aspifunc.h"\
+ ".\Dac32.h"\
+ ".\Scsidefs.h"\
+ ".\Winaspi.h"\
+
+
+"$(INTDIR)\dac32.obj" : $(SOURCE) $(DEP_CPP_DAC32) "$(INTDIR)"
+
+"$(INTDIR)\dac32.sbr" : $(SOURCE) $(DEP_CPP_DAC32) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\aspifunc.cpp
+DEP_CPP_ASPIF=\
+ ".\Aspifunc.h"\
+ ".\Scsidefs.h"\
+ ".\Winaspi.h"\
+
+
+"$(INTDIR)\aspifunc.obj" : $(SOURCE) $(DEP_CPP_ASPIF) "$(INTDIR)"
+
+"$(INTDIR)\aspifunc.sbr" : $(SOURCE) $(DEP_CPP_ASPIF) "$(INTDIR)"
+
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\dac32.rc
+
+"$(INTDIR)\dac32.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+# End Source File
+# End Target
+# End Project
+################################################################################
diff --git a/Src/Plugins/Input/in_cdda/windac/Dac32.rc b/Src/Plugins/Input/in_cdda/windac/Dac32.rc
new file mode 100644
index 00000000..1e81aeee
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/Dac32.rc
@@ -0,0 +1,121 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,4,5,11
+ PRODUCTVERSION 1,4,5,11
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "\0"
+ VALUE "CompanyName", "CASH\0"
+ VALUE "FileDescription", "Christoph Schmelnik's Digital Audio Copy 32 Bit Copy Engine\0"
+ VALUE "FileVersion", "1, 4, 5, 11\0"
+ VALUE "InternalName", "DAC32 DLL\0"
+ VALUE "LegalCopyright", "Copyright © 1996-1999 by Christoph Schmelnik\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "Dac32.dll\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "Christoph Schmelnik's Digital Audio Copy for Win32\0"
+ VALUE "ProductVersion", "Version 1.45\0"
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+#endif // !_MAC
+
+#endif // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Deutsch (Deutschland) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
+#ifdef _WIN32
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Deutsch (Deutschland) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Src/Plugins/Input/in_cdda/windac/NTScsi.cpp b/Src/Plugins/Input/in_cdda/windac/NTScsi.cpp
new file mode 100644
index 00000000..8112b100
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/NTScsi.cpp
@@ -0,0 +1,501 @@
+#include <stdio.h>
+#include <stddef.h>
+#include "NTScsi.h"
+
+typedef struct {
+ BYTE ha;
+ BYTE tgt;
+ BYTE lun;
+ BYTE driveLetter;
+ BOOL bUsed;
+ HANDLE hDevice;
+ BYTE inqData[36];
+} NTSCSIDRIVE;
+
+typedef struct
+{
+ BYTE numAdapters;
+ NTSCSIDRIVE drive[26];
+} NTSCSIDRIVES;
+
+void GetDriveInformation( BYTE i, NTSCSIDRIVE *pDrive );
+
+static HANDLE GetFileHandle( BYTE i );
+
+static BOOL bNtScsiAvailable = FALSE;
+static NTSCSIDRIVES NtScsiDrives;
+static BOOL bUseNtScsi = FALSE;
+
+/*
+ * Initialization of SCSI Pass Through Interface code. Responsible for
+ * setting up the array of SCSI devices. This code will be a little
+ * different from the normal code -- it will query each drive letter from
+ * C: through Z: to see if it is a CD. When we identify a CD, we then
+ * send CDB with the INQUIRY command to it -- NT will automagically fill in
+ * the PathId, TargetId, and Lun for us.
+ */
+
+int NtScsiInit( void )
+{
+ BYTE i;
+ wchar_t buf[4] = {0};
+ UINT uDriveType;
+ int retVal = 0;
+
+ if ( bNtScsiAvailable )
+ {
+ for( i = 2; i < 26; i++ ) if ( NtScsiDrives.drive[i].bUsed ) retVal++;
+ bUseNtScsi = (retVal > 0 );
+ return retVal;
+ }
+
+ memset( &NtScsiDrives, 0x00, sizeof(NtScsiDrives) );
+
+ for( i = 0; i < 26; i++ )
+ {
+ NtScsiDrives.drive[i].hDevice = INVALID_HANDLE_VALUE;
+ }
+
+ for( i = 2; i < 26; i++ )
+ {
+ wsprintf( buf, L"%c:\\", (wchar_t)('A'+i) );
+ uDriveType = GetDriveType( buf );
+
+ /* check if this is a CDROM drive */
+ if ( uDriveType == DRIVE_CDROM )
+ {
+ GetDriveInformation( i, &NtScsiDrives.drive[i] );
+
+ if ( NtScsiDrives.drive[i].bUsed )
+ retVal++;
+ }
+ }
+
+ NtScsiDrives.numAdapters = NtScsiGetNumAdapters( );
+
+ bNtScsiAvailable = TRUE;
+
+ if ( retVal > 0 )
+ {
+ bUseNtScsi = TRUE;
+ }
+
+ return retVal;
+}
+
+
+int NtScsiDeInit( void )
+{
+ BYTE i;
+
+ if ( !bNtScsiAvailable )
+ return 0;
+
+ for( i = 2; i < 26; i++ )
+ {
+ if ( NtScsiDrives.drive[i].bUsed )
+ {
+ CloseHandle( NtScsiDrives.drive[i].hDevice );
+ }
+ }
+
+ NtScsiDrives.numAdapters = NtScsiGetNumAdapters( );
+
+ ZeroMemory( &NtScsiDrives, sizeof(NtScsiDrives) );
+ bNtScsiAvailable = FALSE;
+ return -1;
+}
+
+
+/*
+ * Returns the number of "adapters" present.
+ */
+BYTE NtScsiGetNumAdapters( void )
+{
+ BYTE buf[256] = {0};
+ WORD i;
+ BYTE numAdapters = 0;
+
+ // PortNumber 0 should exist, so pre-mark it. This avoids problems
+ // when the primary IDE drives are on PortNumber 0, but can't be opened
+ // because of insufficient privelege (ie. non-admin).
+ buf[0] = 1;
+
+ for( i = 0; i < 26; i++ )
+ {
+ if ( NtScsiDrives.drive[i].bUsed )
+ buf[NtScsiDrives.drive[i].ha] = 1;
+ }
+
+ for( i = 0; i <= 255; i++ )
+ {
+ if ( buf[i] )
+ numAdapters++;
+ }
+
+ return numAdapters;
+}
+
+
+/*
+ * Replacement for GetASPI32SupportInfo from wnaspi32.dll
+ */
+DWORD NtScsiGetASPI32SupportInfo( void )
+{
+ DWORD retVal;
+
+
+ if ( !NtScsiDrives.numAdapters )
+ retVal = (DWORD)(MAKEWORD(0,SS_NO_ADAPTERS));
+ else
+ retVal = (DWORD)(MAKEWORD(NtScsiDrives.numAdapters,SS_COMP));
+
+ return retVal;
+}
+
+/*
+ * Needs to call the appropriate function for the lpsrb->SRB_Cmd specified.
+ * Valid types are SC_HA_INQUIRY, SC_GET_DEV_TYPE, SC_EXEC_SCSI_CMD,
+ * and SC_RESET_DEV.
+ */
+DWORD NtScsiSendASPI32Command( LPSRB lpsrb )
+{
+ if ( !lpsrb )
+ return SS_ERR;
+
+ switch( lpsrb->SRB_Cmd )
+ {
+ case SC_HA_INQUIRY:
+ return NtScsiHandleHaInquiry( (LPSRB_HAINQUIRY)lpsrb );
+ break;
+
+ case SC_GET_DEV_TYPE:
+ return NtScsiGetDeviceType( (LPSRB_GDEVBLOCK)lpsrb );
+ break;
+
+ case SC_EXEC_SCSI_CMD:
+ return NtScsiExecSCSICommand( (LPSRB_EXECSCSICMD)lpsrb, FALSE );
+ break;
+
+ case SC_RESET_DEV:
+ default:
+ lpsrb->SRB_Status = SS_ERR;
+ return SS_ERR;
+ break;
+ }
+
+ return SS_ERR; // should never get to here...
+}
+
+
+/*
+ * Universal function to get a file handle to the CD device. Since
+ * NT 4.0 wants just the GENERIC_READ flag, and Win2K wants both
+ * GENERIC_READ and GENERIC_WRITE (why a read-only CD device needs
+ * GENERIC_WRITE access is beyond me...), the easist workaround is to just
+ * try them both.
+ */
+static HANDLE GetFileHandle( BYTE i )
+{
+ wchar_t buf[12] = {0};
+ HANDLE fh = NULL;
+ OSVERSIONINFO osver;
+ DWORD dwFlags;
+
+ memset( &osver, 0x00, sizeof(osver) );
+ osver.dwOSVersionInfoSize = sizeof(osver);
+ GetVersionEx( &osver );
+
+ // if Win2K or greater, add GENERIC_WRITE
+ dwFlags = GENERIC_READ;
+
+ if ( (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osver.dwMajorVersion > 4) )
+ {
+ dwFlags |= GENERIC_WRITE;
+ }
+
+ wsprintf( buf, L"\\\\.\\%c:", (wchar_t)('A'+i) );
+ fh = CreateFile( buf, dwFlags, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,OPEN_EXISTING, 0, NULL );
+
+ if ( fh == INVALID_HANDLE_VALUE )
+ {
+ // it went foobar somewhere, so try it with the GENERIC_WRITE bit flipped
+ dwFlags ^= GENERIC_WRITE;
+ fh = CreateFile( buf, dwFlags, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
+ }
+
+ if ( fh == INVALID_HANDLE_VALUE )
+ {
+ }
+ else
+ {
+ }
+
+ return fh;
+}
+
+
+
+/*
+ * fills in a pDrive structure with information from a SCSI_INQUIRY
+ * and obtains the ha:tgt:lun values via IOCTL_SCSI_GET_ADDRESS
+ */
+void GetDriveInformation( BYTE i, NTSCSIDRIVE *pDrive )
+{
+ HANDLE fh;
+ char buf[2048] = {0};
+ BOOL status;
+ PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER pswb;
+ PSCSI_ADDRESS pscsiAddr;
+ ULONG length, returned;
+ BYTE inqData[100] = {0};
+
+ fh = GetFileHandle( i );
+
+ if ( fh == INVALID_HANDLE_VALUE )
+ {
+ return;
+ }
+
+ /*
+ * Get the drive inquiry data
+ */
+ ZeroMemory( &buf, 2048 );
+ ZeroMemory( inqData, 100 );
+ pswb = (PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)buf;
+ pswb->spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
+ pswb->spt.CdbLength = 6;
+ pswb->spt.SenseInfoLength = 24;
+ pswb->spt.DataIn = SCSI_IOCTL_DATA_IN;
+ pswb->spt.DataTransferLength = 100;
+ pswb->spt.TimeOutValue = 2;
+ pswb->spt.DataBuffer = inqData;
+ pswb->spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf );
+ pswb->spt.Cdb[0] = 0x12;
+ pswb->spt.Cdb[4] = 100;
+
+ length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
+ status = DeviceIoControl( fh,
+ IOCTL_SCSI_PASS_THROUGH_DIRECT,
+ pswb,
+ length,
+ pswb,
+ length,
+ &returned,
+ NULL );
+
+ if ( !status )
+ {
+ CloseHandle( fh );
+ return;
+ }
+
+ memcpy( pDrive->inqData, inqData, 36 );
+
+ /*
+ * get the address (path/tgt/lun) of the drive via IOCTL_SCSI_GET_ADDRESS
+ */
+ ZeroMemory( &buf, 2048 );
+ pscsiAddr = (PSCSI_ADDRESS)buf;
+ pscsiAddr->Length = sizeof(SCSI_ADDRESS);
+ if ( DeviceIoControl( fh, IOCTL_SCSI_GET_ADDRESS, NULL, 0,
+ pscsiAddr, sizeof(buf), &returned,
+ NULL ) )
+ {
+ pDrive->bUsed = TRUE;
+ pDrive->ha = pscsiAddr->PortNumber;
+ pDrive->tgt = pscsiAddr->TargetId;
+ pDrive->lun = pscsiAddr->Lun;
+ pDrive->driveLetter = i;
+ pDrive->hDevice = INVALID_HANDLE_VALUE;
+ }
+ else if (50 == GetLastError()) // usb/firewire
+ {
+ pDrive->bUsed = TRUE;
+ pDrive->ha = i;
+ pDrive->tgt = 0;
+ pDrive->lun = 0;
+ pDrive->driveLetter = i;
+ pDrive->hDevice = INVALID_HANDLE_VALUE;
+ }
+ else
+ {
+ pDrive->bUsed = FALSE;
+ }
+
+ CloseHandle( fh );
+}
+
+
+
+DWORD NtScsiHandleHaInquiry( LPSRB_HAINQUIRY lpsrb )
+{
+ DWORD *pMTL;
+
+ lpsrb->HA_Count = NtScsiDrives.numAdapters;
+
+ if ( lpsrb->SRB_HaId >= NtScsiDrives.numAdapters )
+ {
+ lpsrb->SRB_Status = SS_INVALID_HA;
+ return SS_INVALID_HA;
+ }
+ lpsrb->HA_SCSI_ID = 7; // who cares... we're not really an ASPI manager
+ memcpy( lpsrb->HA_ManagerId, "blahblahblahblah", 16 );
+ memcpy( lpsrb->HA_Identifier, "blahblahblahblah", 16 );
+ lpsrb->HA_Identifier[13] = (char)('0'+lpsrb->SRB_HaId);
+ ZeroMemory( lpsrb->HA_Unique, 16 );
+ lpsrb->HA_Unique[3] = 8;
+ pMTL = (LPDWORD)&lpsrb->HA_Unique[4];
+ *pMTL = 64 * 1024;
+
+ lpsrb->SRB_Status = SS_COMP;
+ return SS_COMP;
+}
+
+
+/*
+ * Scans through the drive array and returns DTYPE_CDROM type for all items
+ * found, and DTYPE_UNKNOWN for all others.
+ */
+DWORD NtScsiGetDeviceType( LPSRB_GDEVBLOCK lpsrb )
+{
+ lpsrb->SRB_Status = SS_NO_DEVICE;
+ if ( NtScsiGetDeviceIndex( lpsrb->SRB_HaId, lpsrb->SRB_Target, lpsrb->SRB_Lun ) )
+ lpsrb->SRB_Status = SS_COMP;
+
+ if ( lpsrb->SRB_Status == SS_COMP )
+ lpsrb->SRB_DeviceType = DTC_CDROM;
+ else
+ lpsrb->SRB_DeviceType = DTC_UNKNOWN;
+
+ return lpsrb->SRB_Status;
+}
+
+
+/*
+ * Looks up the index in the drive array for a given ha:tgt:lun triple
+ */
+BYTE NtScsiGetDeviceIndex( BYTE ha, BYTE tgt, BYTE lun )
+{
+ BYTE i;
+
+ for( i = 2; i < 26; i++ )
+ {
+ if ( NtScsiDrives.drive[i].bUsed )
+ {
+ NTSCSIDRIVE *lpd;
+ lpd = &NtScsiDrives.drive[i];
+ if ( (lpd->ha == ha) && (lpd->tgt == tgt) && (lpd->lun == lun) )
+ return i;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Converts ASPI-style SRB to SCSI Pass Through IOCTL
+ */
+DWORD NtScsiExecSCSICommand( LPSRB_EXECSCSICMD lpsrb, BOOL bBeenHereBefore )
+{
+ BOOL status;
+ SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
+ ULONG length, returned;
+ BYTE idx;
+
+ idx = NtScsiGetDeviceIndex( lpsrb->SRB_HaId, lpsrb->SRB_Target, lpsrb->SRB_Lun );
+
+ if ( idx == 0 )
+ {
+ lpsrb->SRB_Status = SS_ERR;
+ return SS_ERR;
+ }
+
+ if ( lpsrb->CDBByte[0] == 0x12 ) // is it an INQUIRY?
+ {
+ lpsrb->SRB_Status = SS_COMP;
+ memcpy( lpsrb->SRB_BufPointer, NtScsiDrives.drive[idx].inqData, 36 );
+ return SS_COMP;
+ }
+
+ if ( NtScsiDrives.drive[idx].hDevice == INVALID_HANDLE_VALUE )
+ NtScsiDrives.drive[idx].hDevice = GetFileHandle( NtScsiDrives.drive[idx].driveLetter );
+
+ ZeroMemory( &swb, sizeof(swb) );
+ swb.spt.Length = sizeof(SCSI_PASS_THROUGH);
+ swb.spt.CdbLength = lpsrb->SRB_CDBLen;
+ if ( lpsrb->SRB_Flags & SRB_DIR_IN )
+ swb.spt.DataIn = SCSI_IOCTL_DATA_IN;
+ else if ( lpsrb->SRB_Flags & SRB_DIR_OUT )
+ swb.spt.DataIn = SCSI_IOCTL_DATA_OUT;
+ else
+ swb.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;
+ swb.spt.DataTransferLength = lpsrb->SRB_BufLen;
+ swb.spt.TimeOutValue = 5;
+ swb.spt.DataBuffer = lpsrb->SRB_BufPointer;
+ swb.spt.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf );
+ memcpy( swb.spt.Cdb, lpsrb->CDBByte, lpsrb->SRB_CDBLen );
+ length = sizeof(swb);
+
+ status = DeviceIoControl( NtScsiDrives.drive[idx].hDevice,
+ IOCTL_SCSI_PASS_THROUGH_DIRECT,
+ &swb,
+ length,
+ &swb,
+ length,
+ &returned,
+ NULL );
+
+ if ( status )
+ {
+ lpsrb->SRB_Status = SS_COMP;
+ }
+ else
+ {
+ DWORD dwErrCode;
+
+ lpsrb->SRB_Status = SS_ERR;
+ lpsrb->SRB_TargStat = 0x0004;
+ dwErrCode = GetLastError();
+ /*
+ * KLUDGE ALERT! KLUDGE ALERT! KLUDGE ALERT!
+ * Whenever a disk changer switches disks, it may render the device
+ * handle invalid. We try to catch these errors here and recover
+ * from them.
+ */
+ if ( !bBeenHereBefore &&
+ ((dwErrCode == ERROR_MEDIA_CHANGED) || (dwErrCode == ERROR_INVALID_HANDLE)) )
+ {
+ if ( dwErrCode != ERROR_INVALID_HANDLE )
+ CloseHandle( NtScsiDrives.drive[idx].hDevice );
+ GetDriveInformation( idx, &NtScsiDrives.drive[idx] );
+
+ return NtScsiExecSCSICommand( lpsrb, TRUE );
+ }
+ }
+
+ return lpsrb->SRB_Status;
+}
+
+
+
+BOOL UsingSCSIPT( void )
+{
+ return bUseNtScsi;
+}
+
+
+
+/*
+ * Calls GetFileHandle for the CD refered to by ha:tgt:lun to open it for
+ * use
+ */
+void NtScsiOpenCDHandle( BYTE ha, BYTE tgt, BYTE lun )
+{
+ BYTE idx;
+
+ idx = NtScsiGetDeviceIndex( ha, tgt, lun );
+
+ if ( idx && NtScsiDrives.drive[idx].hDevice == INVALID_HANDLE_VALUE )
+ NtScsiDrives.drive[idx].hDevice = GetFileHandle( NtScsiDrives.drive[idx].driveLetter );
+} \ No newline at end of file
diff --git a/Src/Plugins/Input/in_cdda/windac/NTScsi.h b/Src/Plugins/Input/in_cdda/windac/NTScsi.h
new file mode 100644
index 00000000..895c787d
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/NTScsi.h
@@ -0,0 +1,147 @@
+/*
+ * distilled information from various header files from Microsoft's
+ * DDK for Windows NT 4.0
+ */
+#ifndef NTSCSI_H_INCLUDED
+#define NTSCSI_H_INCLUDED
+
+#include <windows.h>
+#include "Aspi.h"
+
+typedef struct {
+ USHORT Length;
+ UCHAR ScsiStatus;
+ UCHAR PathId;
+ UCHAR TargetId;
+ UCHAR Lun;
+ UCHAR CdbLength;
+ UCHAR SenseInfoLength;
+ UCHAR DataIn;
+ ULONG DataTransferLength;
+ ULONG TimeOutValue;
+ ULONG DataBufferOffset;
+ ULONG SenseInfoOffset;
+ UCHAR Cdb[16];
+} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;
+
+
+typedef struct {
+ USHORT Length;
+ UCHAR ScsiStatus;
+ UCHAR PathId;
+ UCHAR TargetId;
+ UCHAR Lun;
+ UCHAR CdbLength;
+ UCHAR SenseInfoLength;
+ UCHAR DataIn;
+ ULONG DataTransferLength;
+ ULONG TimeOutValue;
+ PVOID DataBuffer;
+ ULONG SenseInfoOffset;
+ UCHAR Cdb[16];
+} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
+
+
+typedef struct {
+ SCSI_PASS_THROUGH spt;
+ ULONG Filler;
+ UCHAR ucSenseBuf[32];
+ UCHAR ucDataBuf[512];
+} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS;
+
+
+typedef struct {
+ SCSI_PASS_THROUGH_DIRECT spt;
+ ULONG Filler;
+ UCHAR ucSenseBuf[32];
+} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
+
+
+
+typedef struct {
+ UCHAR NumberOfLogicalUnits;
+ UCHAR InitiatorBusId;
+ ULONG InquiryDataOffset;
+} SCSI_BUS_DATA, *PSCSI_BUS_DATA;
+
+
+typedef struct {
+ UCHAR NumberOfBusses;
+ SCSI_BUS_DATA BusData[1];
+} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO;
+
+
+typedef struct {
+ UCHAR PathId;
+ UCHAR TargetId;
+ UCHAR Lun;
+ BOOLEAN DeviceClaimed;
+ ULONG InquiryDataLength;
+ ULONG NextInquiryDataOffset;
+ UCHAR InquiryData[1];
+} SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA;
+
+
+typedef struct {
+ ULONG Length;
+ UCHAR PortNumber;
+ UCHAR PathId;
+ UCHAR TargetId;
+ UCHAR Lun;
+} SCSI_ADDRESS, *PSCSI_ADDRESS;
+
+
+/*
+ * method codes
+ */
+#define METHOD_BUFFERED 0
+#define METHOD_IN_DIRECT 1
+#define METHOD_OUT_DIRECT 2
+#define METHOD_NEITHER 3
+
+/*
+ * file access values
+ */
+#define FILE_ANY_ACCESS 0
+#ifndef FILE_READ_ACCESS
+#define FILE_READ_ACCESS (0x0001)
+#define FILE_WRITE_ACCESS (0x0002)
+#endif
+
+
+#define IOCTL_SCSI_BASE 0x00000004
+
+/*
+ * constants for DataIn member of SCSI_PASS_THROUGH* structures
+ */
+#define SCSI_IOCTL_DATA_OUT 0
+#define SCSI_IOCTL_DATA_IN 1
+#define SCSI_IOCTL_DATA_UNSPECIFIED 2
+
+/*
+ * Standard IOCTL define
+ */
+#define CTL_CODE( DevType, Function, Method, Access ) ( \
+ ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+
+#define IOCTL_SCSI_PASS_THROUGH CTL_CODE( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
+#define IOCTL_SCSI_MINIPORT CTL_CODE( IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
+#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE( IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
+#define IOCTL_SCSI_GET_ADDRESS CTL_CODE( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS )
+
+int NtScsiInit( void );
+int NtScsiDeInit( void );
+
+BYTE NtScsiGetNumAdapters( void );
+DWORD NtScsiGetASPI32SupportInfo( void );
+DWORD NtScsiGetDeviceType( LPSRB_GDEVBLOCK lpsrb );
+BYTE NtScsiGetDeviceIndex( BYTE ha, BYTE tgt, BYTE lun );
+
+DWORD NtScsiHandleHaInquiry( LPSRB_HAINQUIRY lpsrb );
+extern "C" DWORD NtScsiSendASPI32Command( LPSRB lpsrb );
+DWORD NtScsiExecSCSICommand( LPSRB_EXECSCSICMD lpsrb, BOOL bBeenHereBefore );
+
+#endif \ No newline at end of file
diff --git a/Src/Plugins/Input/in_cdda/windac/RESOURCE.H b/Src/Plugins/Input/in_cdda/windac/RESOURCE.H
new file mode 100644
index 00000000..3a24dff9
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/RESOURCE.H
@@ -0,0 +1,17 @@
+#if USE_WINDAC
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by dac32.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
+#endif \ No newline at end of file
diff --git a/Src/Plugins/Input/in_cdda/windac/SCSIDEFS.H b/Src/Plugins/Input/in_cdda/windac/SCSIDEFS.H
new file mode 100644
index 00000000..5012429f
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/SCSIDEFS.H
@@ -0,0 +1,252 @@
+//**********************************************************************
+//
+// Name: SCSIDEFS.H
+//
+// Description: SCSI definitions ('C' Language)
+//
+//**********************************************************************
+//**********************************************************************
+// %%% TARGET STATUS VALUES %%%
+//**********************************************************************
+#define STATUS_GOOD 0x00 // Status Good
+#define STATUS_CHKCOND 0x02 // Check Condition
+#define STATUS_CONDMET 0x04 // Condition Met
+#define STATUS_BUSY 0x08 // Busy
+#define STATUS_INTERM 0x10 // Intermediate
+#define STATUS_INTCDMET 0x14 // Intermediate-condition met
+#define STATUS_RESCONF 0x18 // Reservation conflict
+#define STATUS_COMTERM 0x22 // Command Terminated
+#define STATUS_QFULL 0x28 // Queue full
+//**********************************************************************
+// %%% SCSI MISCELLANEOUS EQUATES %%%
+//**********************************************************************
+#define MAXLUN 7 // Maximum Logical Unit Id
+#define MAXTARG 7 // Maximum Target Id
+#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs
+#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's
+///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+//
+// %%% SCSI COMMAND OPCODES %%%
+//
+///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+//**********************************************************************
+// %%% Commands for all Device Types %%%
+//**********************************************************************
+#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional)
+#define SCSI_COMPARE 0x39 // Compare (O)
+#define SCSI_COPY 0x18 // Copy (O)
+#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O)
+#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY)
+#define SCSI_LOG_SELECT 0x4C // Log Select (O)
+#define SCSI_LOG_SENSE 0x4D // Log Sense (O)
+#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific)
+#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific)
+#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific)
+#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific)
+#define SCSI_READ_BUFF 0x3C // Read Buffer (O)
+#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY)
+#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O)
+#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O)
+#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY)
+#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O)
+//**********************************************************************
+// %%% Commands Unique to Direct Access Devices %%%
+//**********************************************************************
+#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY)
+#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O)
+#define SCSI_PREFETCH 0x34 // Prefetch (O)
+#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O)
+#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY)
+#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY)
+#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY)
+#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O)
+#define SCSI_READ_LONG 0x3E // Read Long (O)
+#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O)
+#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY)
+#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY)
+#define SCSI_REZERO 0x01 // Rezero Unit (O)
+#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O)
+#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O)
+#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O)
+#define SCSI_SEEK6 0x0B // Seek 6-Byte (O)
+#define SCSI_SEEK10 0x2B // Seek 10-Byte (O)
+#define SCSI_SET_LIMIT 0x33 // Set Limits (O)
+#define SCSI_START_STP 0x1B // Start/Stop Unit (O)
+#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O)
+#define SCSI_VERIFY 0x2F // Verify (O)
+#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY)
+#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY)
+#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O)
+#define SCSI_WRITE_LONG 0x3F // Write Long (O)
+#define SCSI_WRITE_SAME 0x41 // Write Same (O)
+//**********************************************************************
+// %%% Commands Unique to Sequential Access Devices %%%
+//**********************************************************************
+#define SCSI_ERASE 0x19 // Erase (MANDATORY)
+#define SCSI_LOAD_UN 0x1B // Load/Unload (O)
+#define SCSI_LOCATE 0x2B // Locate (O)
+#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY)
+#define SCSI_READ_POS 0x34 // Read Position (O)
+#define SCSI_READ_REV 0x0F // Read Reverse (O)
+#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O)
+#define SCSI_REWIND 0x01 // Rewind (MANDATORY)
+#define SCSI_SPACE 0x11 // Space (MANDATORY)
+#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O)
+#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY)
+#define SCSI_PARTITION 0x0D // DAT/QFA Partition Select
+#define SCSI_READWRITE 0x06 // Set Read/Write Parameters
+//**********************************************************************
+// %%% Commands Unique to Printer Devices %%%
+//**********************************************************************
+#define SCSI_PRINT 0x0A // Print (MANDATORY)
+#define SCSI_SLEW_PNT 0x0B // Slew and Print (O)
+#define SCSI_STOP_PNT 0x1B // Stop Print (O)
+#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O)
+//**********************************************************************
+// %%% Commands Unique to Processor Devices %%%
+//**********************************************************************
+#define SCSI_RECEIVE 0x08 // Receive (O)
+#define SCSI_SEND 0x0A // Send (O)
+//**********************************************************************
+// %%% Commands Unique to Write-Once Devices %%%
+//**********************************************************************
+#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O)
+#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O)
+#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O)
+#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O)
+#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O)
+#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O)
+#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O)
+#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O)
+#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O)
+#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O)
+#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O)
+#define SCSI_WRITE12 0xAA // Write 12-Byte (O)
+#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O)
+#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O)
+//**********************************************************************
+// %%% Commands Unique to CD-ROM Devices %%%
+//**********************************************************************
+#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O)
+#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O)
+#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O)
+#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O)
+#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O)
+#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O)
+#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY)
+#define SCSI_READHEADER 0x44 // Read Header (O)
+#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O)
+#define SCSI_READ_TOC 0x43 // Read TOC (O)
+//**********************************************************************
+// %%% Commands Unique to Scanner Devices %%%
+//**********************************************************************
+#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O)
+#define SCSI_GETWINDOW 0x25 // Get Window (O)
+#define SCSI_OBJECTPOS 0x31 // Object Position (O)
+#define SCSI_SCAN 0x1B // Scan (O)
+#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY)
+//**********************************************************************
+// %%% Commands Unique to Optical Memory Devices %%%
+//**********************************************************************
+#define SCSI_UpdateBlk 0x3D // Update Block (O)
+//**********************************************************************
+// %%% Commands Unique to Medium Changer Devices %%%
+//**********************************************************************
+#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O)
+#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O)
+#define SCSI_POSTOELEM 0x2B // Position to Element (O)
+#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O)
+#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O)
+//**********************************************************************
+// %%% Commands Unique to Communication Devices %%%
+//**********************************************************************
+#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY)
+#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O)
+#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O)
+#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY)
+#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O)
+#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O)
+///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+//
+// %%% END OF SCSI COMMAND OPCODES %%%
+//
+///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+//**********************************************************************
+// %%% Request Sense Data Format %%%
+//**********************************************************************
+typedef struct {
+ BYTE ErrorCode; // Error Code (70H or 71H)
+ BYTE SegmentNum; // Number of current segment descriptor
+ BYTE SenseKey; // Sense Key(See bit definitions too)
+ BYTE InfoByte0; // Information MSB
+ BYTE InfoByte1; // Information MID
+ BYTE InfoByte2; // Information MID
+ BYTE InfoByte3; // Information LSB
+ BYTE AddSenLen; // Additional Sense Length
+ BYTE ComSpecInf0; // Command Specific Information MSB
+ BYTE ComSpecInf1; // Command Specific Information MID
+ BYTE ComSpecInf2; // Command Specific Information MID
+ BYTE ComSpecInf3; // Command Specific Information LSB
+ BYTE AddSenseCode; // Additional Sense Code
+ BYTE AddSenQual; // Additional Sense Code Qualifier
+// BYTE FieldRepUCode; // Field Replaceable Unit Code
+// BYTE SenKeySpec15; // Sense Key Specific 15th byte
+// BYTE SenKeySpec16; // Sense Key Specific 16th byte
+// BYTE SenKeySpec17; // Sense Key Specific 17th byte
+// BYTE AddSenseBytes; // Additional Sense Bytes
+} SENSE_DATA_FMT;
+//**********************************************************************
+// %%% REQUEST SENSE ERROR CODE %%%
+//**********************************************************************
+#define SERROR_CURRENT 0x70 // Current Errors
+#define SERROR_DEFERED 0x71 // Deferred Errors
+//**********************************************************************
+// %%% REQUEST SENSE BIT DEFINITIONS %%%
+//**********************************************************************
+#define SENSE_VALID 0x80 // Byte 0 Bit 7
+#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7
+#define SENSE_EOM 0x40 // Byte 2 Bit 6
+#define SENSE_ILI 0x20 // Byte 2 Bit 5
+//**********************************************************************
+// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%%
+//**********************************************************************
+#define KEY_NOSENSE 0x00 // No Sense
+#define KEY_RECERROR 0x01 // Recovered Error
+#define KEY_NOTREADY 0x02 // Not Ready
+#define KEY_MEDIUMERR 0x03 // Medium Error
+#define KEY_HARDERROR 0x04 // Hardware Error
+#define KEY_ILLGLREQ 0x05 // Illegal Request
+#define KEY_UNITATT 0x06 // Unit Attention
+#define KEY_DATAPROT 0x07 // Data Protect
+#define KEY_BLANKCHK 0x08 // Blank Check
+#define KEY_VENDSPEC 0x09 // Vendor Specific
+#define KEY_COPYABORT 0x0A // Copy Abort
+#define KEY_ABORT 0x0B // Abort
+#define KEY_EQUAL 0x0C // Equal (Search)
+#define KEY_VOLOVRFLW 0x0D // Volume Overflow
+#define KEY_MISCOMP 0x0E // Miscompare (Search)
+#define KEY_RESERVED 0x0F // Reserved
+//**********************************************************************
+// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%%
+//**********************************************************************
+#define DTYPE_DASD 0x00 // Disk Device
+#define DTYPE_SEQD 0x01 // Tape Device
+#define DTYPE_PRNT 0x02 // Printer
+#define DTYPE_PROC 0x03 // Processor
+#define DTYPE_WORM 0x04 // Write-once read-multiple
+#define DTYPE_CROM 0x05 // CD-ROM device
+#define DTYPE_SCAN 0x06 // Scanner device
+#define DTYPE_OPTI 0x07 // Optical memory device
+#define DTYPE_JUKE 0x08 // Medium Changer device
+#define DTYPE_COMM 0x09 // Communications device
+#define DTYPE_RESL 0x0A // Reserved (low)
+#define DTYPE_RESH 0x1E // Reserved (high)
+#define DTYPE_UNKNOWN 0x1F // Unknown or no device type
+//**********************************************************************
+// %%% ANSI APPROVED VERSION DEFINITIONS %%%
+//**********************************************************************
+#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand
+#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1)
+#define ANSI_SCSI2 0x2 // Device complies to SCSI-2
+#define ANSI_RESLO 0x3 // Reserved (low)
+#define ANSI_RESHI 0x7 // Reserved (high) \ No newline at end of file
diff --git a/Src/Plugins/Input/in_cdda/windac/Winaspi.h b/Src/Plugins/Input/in_cdda/windac/Winaspi.h
new file mode 100644
index 00000000..5fc78fe5
--- /dev/null
+++ b/Src/Plugins/Input/in_cdda/windac/Winaspi.h
@@ -0,0 +1,229 @@
+//**********************************************************************
+//
+// Name: WINASPI.H
+//
+// Description: ASPI for Windows definitions ('C' Language)
+//
+//**********************************************************************
+
+#ifndef _WINASPI_H
+#define _WINASPI_H
+
+typedef BYTE *LPSRB;
+#define SENSE_LEN 14 // Default sense buffer length
+#define SRB_DIR_SCSI 0x00 // Direction determined by SCSI command
+#define SRB_DIR_IN 0x08 // Transfer from SCSI target to host
+#define SRB_DIR_OUT 0x10 // Transfer from host to SCSI targetw
+#define SRB_POSTING 0x01 // Enable ASPI posting
+#define SRB_EVENT_NOTIFY 0x40 // Enable ASPI command notification
+#define SRB_ENABLE_RESIDUAL_COUNT 0x04 //Enable reporting of residual byte count
+#define WM_ASPIPOST 0x4D42 // ASPI Post message
+#define TIMEOUT 30000 // Wait 30 seconds
+
+//**********************************************************************
+// %%% ASPI Command Definitions %%%
+//**********************************************************************
+#define SC_HA_INQUIRY 0x00 // Host adapter inquiry
+#define SC_GET_DEV_TYPE 0x01 // Get device type
+#define SC_EXEC_SCSI_CMD 0x02 // Execute SCSI command
+#define SC_ABORT_SRB 0x03 // Abort an SRB
+#define SC_RESET_DEV 0x04 // SCSI bus device reset
+//**********************************************************************
+// %%% SRB Status %%%
+//**********************************************************************
+#define SS_PENDING 0x00 // SRB being processed
+#define SS_COMP 0x01 // SRB completed without error
+#define SS_ABORTED 0x02 // SRB aborted
+#define SS_ABORT_FAIL 0x03 // Unable to abort SRB
+#define SS_ERR 0x04 // SRB completed with error
+#define SS_INVALID_CMD 0x80 // Invalid ASPI command
+#define SS_INVALID_HA 0x81 // Invalid host adapter number
+#define SS_NO_DEVICE 0x82 // SCSI device not installed
+#define SS_INVALID_SRB 0xE0 // Invalid parameter set in SRB
+#define SS_OLD_MANAGER 0xE1 // ASPI manager doesn't support Window
+#define SS_ILLEGAL_MODE 0xE2 // Unsupported Windows mode
+#define SS_NO_ASPI 0xE3 // No ASPI managers resident
+#define SS_FAILED_INIT 0xE4 // ASPI for windows failed init
+#define SS_ASPI_IS_BUSY 0xE5 // No resources available to execute cmd
+#define SS_BUFFER_TO_BIG 0xE6 // Buffer size to big to handle!
+//**********************************************************************
+// %%% Host Adapter Status %%%
+//**********************************************************************
+#define HASTAT_OK 0x00 // Host adapter did not detect an error
+#define HASTAT_SEL_TO 0x11 // Selection Timeout
+#define HASTAT_DO_DU 0x12 // Data overrun data underrun
+#define HASTAT_BUS_FREE 0x13 // Unexpected bus free
+#define HASTAT_PHASE_ERR 0x14 // Target bus phase sequence failure
+
+
+
+
+
+//**********************************************************************
+// %%% SRB - HOST ADAPTER INQUIRY - SC_HA_INQUIRY %%%
+//**********************************************************************
+#pragma pack(push,ASPI_Structures,1)
+
+typedef BYTE TDriveMode[64];
+
+struct THAUnique
+{
+ WORD BufferAlignmentMask;
+ BYTE AdapterUniqueFlags;
+ BYTE MaximumSCSITargets;
+ DWORD MaximumTransferLen;
+ BYTE Reserved[8];
+};
+
+typedef struct
+{
+ BYTE SRB_Cmd; // ASPI command code = SC_HA_INQUIRY
+ BYTE SRB_Status; // ASPI command status byte
+ BYTE SRB_HaId; // ASPI host adapter number
+ BYTE SRB_Flags; // ASPI request flags
+ DWORD SRB_Hdr_Rsvd; // Reserved, MUST = 0
+ BYTE HA_Count; // Number of host adapters present
+ BYTE HA_SCSI_ID; // SCSI ID of host adapter
+ BYTE HA_ManagerId[16]; // String describing the manager
+ BYTE HA_Identifier[16]; // String describing the host adapter
+ THAUnique HA_Unique; // Host Adapter Unique parameters
+ WORD HA_Rsvd1;
+} SRB_HAInquiry, *PSRB_HAInquiry;
+//**********************************************************************
+// %%% SRB - GET DEVICE TYPE - SC_GET_DEV_TYPE %%%
+//**********************************************************************
+typedef struct
+{
+ BYTE SRB_Cmd; // ASPI command code = SC_GET_DEV_TYPE
+ BYTE SRB_Status; // ASPI command status byte
+ BYTE SRB_HaId; // ASPI host adapter number
+ BYTE SRB_Flags; // Reserved
+ DWORD SRB_Hdr_Rsvd; // Reserved
+ BYTE SRB_Target; // Target's SCSI ID
+ BYTE SRB_Lun; // Target's LUN number
+ BYTE SRB_DeviceType; // Target's peripheral device type
+ BYTE SRB_Rsvd1; // Reserved for alignment
+} SRB_GDEVBlock, *PSRB_GDEVBlock;
+//**********************************************************************
+// %%% SRB - EXECUTE SCSI COMMAND - SC_EXEC_SCSI_CMD %%%
+//**********************************************************************
+typedef struct
+{
+ BYTE SRB_Cmd; // ASPI command code = SC_EXEC_SCSI_CMD
+ BYTE SRB_Status; // ASPI command status byte
+ BYTE SRB_HaId; // ASPI host adapter number
+ BYTE SRB_Flags; // ASPI request flags
+ DWORD SRB_Hdr_Rsvd; // Reserved
+ BYTE SRB_Target; // Target's SCSI ID
+ BYTE SRB_Lun; // Target's LUN number
+ WORD SRB_Rsvd1; // Reserved for Alignment
+ DWORD SRB_BufLen; // Data Allocation Length
+ BYTE *SRB_BufPointer; // Data Buffer Point
+ BYTE SRB_SenseLen; // Sense Allocation Length
+ BYTE SRB_CDBLen; // CDB Length
+ BYTE SRB_HaStat; // Host Adapter Status
+ BYTE SRB_TargStat; // Target Status
+ void (*SRB_PostProc)(); // Post routine
+ void *SRB_Rsvd2; // Reserved
+ BYTE SRB_Rsvd3[16]; // Reserved for expansion
+ BYTE CDBByte[16]; // SCSI CDB
+ BYTE SenseArea[SENSE_LEN+2]; // Request Sense buffer
+} SRB_ExecSCSICmd, *PSRB_ExecSCSICmd;
+//**********************************************************************
+// %%% SRB - ABORT AN SRB - SC_ABORT_SRB %%%
+//**********************************************************************
+typedef struct
+{
+ BYTE SRB_Cmd; // ASPI command code = SC_ABORT_SRB
+ BYTE SRB_Status; // ASPI command status byte
+ BYTE SRB_HaId; // ASPI host adapter number
+ BYTE SRB_Flags; // ASPI request flags
+ DWORD SRB_Hdr_Rsvd; // Reserved, MUST = 0
+ LPSRB SRB_ToAbort; // Pointer to SRB to abort
+} SRB_Abort;
+//**********************************************************************
+// %%% SRB - BUS DEVICE RESET - SC_RESET_DEV %%%
+//**********************************************************************
+typedef struct
+{
+ BYTE SRB_Cmd; // ASPI command code = SC_RESET_DEV
+ BYTE SRB_Status; // ASPI command status byte
+ BYTE SRB_HaId; // ASPI host adapter number
+ BYTE SRB_Flags; // Reserved
+ DWORD SRB_Hdr_Rsvd; // Reserved
+ BYTE SRB_Target; // Target's SCSI ID
+ BYTE SRB_Lun; // Target's LUN number
+ BYTE SRB_Rsvd1[12]; // Reserved for Alignment
+ BYTE SRB_HaStat; // Host Adapter Status
+ BYTE SRB_TargStat; // Target Status
+ void *SRB_PostProc; // Post routine
+ void *SRB_Rsvd2; // Reserved
+ BYTE SRB_Rsvd3[32]; // Reserved
+} SRB_BusDeviceReset, *PSRB_BusDeviceReset;
+
+
+//**********************************************************************
+// %%% Header for TOC Reading %%%
+//**********************************************************************
+struct TTrackInfo
+{
+ BYTE Reserved1;
+ BYTE AdrCtrl;
+ BYTE TrackNummer;
+ BYTE Reserved2;
+ DWORD AbsCDAdress;
+};
+
+struct TTOCHeader
+{
+ WORD TOCDataLength;
+ BYTE FirstTrack;
+ BYTE LastTrack;
+ TTrackInfo Info[100];
+};
+
+//**********************************************************************
+// %%% Structure for Read Sub-Channel %%%
+//**********************************************************************
+struct TQChannelInfo
+{
+ BYTE Reserved1;
+ BYTE AudioStatus;
+ WORD DataLen;
+ BYTE FormatCode;
+ BYTE ADRCtrl;
+ BYTE TrackNumber;
+ BYTE IndexNumber;
+ long AbsCDAdress;
+ long RelTrackAdress;
+};
+
+//**********************************************************************
+// %%% Request Sense Data Format %%%
+//**********************************************************************
+typedef struct {
+ BYTE ErrorCode; // Error Code (70H or 71H)
+ BYTE SegmentNum; // Number of current segment descriptor
+ BYTE SenseKey; // Sense Key(See bit definitions too)
+ BYTE InfoByte0; // Information MSB
+ BYTE InfoByte1; // Information MID
+ BYTE InfoByte2; // Information MID
+ BYTE InfoByte3; // Information LSB
+ BYTE AddSenLen; // Additional Sense Length
+ BYTE ComSpecInf0; // Command Specific Information MSB
+ BYTE ComSpecInf1; // Command Specific Information MID
+ BYTE ComSpecInf2; // Command Specific Information MID
+ BYTE ComSpecInf3; // Command Specific Information LSB
+ BYTE AddSenseCode; // Additional Sense Code
+ BYTE AddSenQual; // Additional Sense Code Qualifier
+ BYTE FieldRepUCode; // Field Replaceable Unit Code
+ BYTE SenKeySpec15; // Sense Key Specific 15th byte
+ BYTE SenKeySpec16; // Sense Key Specific 16th byte
+ BYTE SenKeySpec17; // Sense Key Specific 17th byte
+ BYTE AddSenseBytes; // Additional Sense Bytes
+} TSenseInfo;
+
+#pragma pack(pop,ASPI_Structures)
+
+
+#endif //_WINASPI_H \ No newline at end of file