1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024 |
- //**************************************************************************
- //**
- //** i_cdmus.c
- //**
- //**************************************************************************
- // HEADER FILES ------------------------------------------------------------
- #include <stdio.h>
- #include <stdlib.h>
- #include <dos.h>
- #include <stddef.h>
- #include <string.h>
- #include "h2def.h"
- #include "i_sound.h"
- // MACROS ------------------------------------------------------------------
- #define MAX_AUDIO_TRACKS 25
- #define MULTIPLEX_INT 0x2f
- #define CDROM_GETDRIVECOUNT 0x1500
- #define CDROM_SENDDEVICEREQ 0x1510
- #define CDROM_GETVERSION 0x150c
- #define HSG_MODE 0
- #define RED_MODE 1
- #define DRC_IOCTLINPUT 0x03
- #define DRC_IOCTLOUTPUT 0x0c
- #define DRC_PLAYAUDIO 0x84
- #define DRC_STOPAUDIO 0x85
- #define DRC_RESUMEAUDIO 0x88
- #define DPMI_INT 0x31
- #define DPMI_ALLOCREALMEM 0x0100
- #define DPMI_FREEREALMEM 0x0101
- #define DPMI_SIMREALINT 0x0300
- // IOCTL input commands
- #define ADRDEVHEAD 0 // Return Address of Device Header
- #define HEADLOCATION 1 // Location of Head
- #define RESERVED 2 // Reserved
- #define ERRSTATISTICS 3 // Error Statistics
- #define AUDIOCHANINFO 4 // Audio Channel Info
- #define READDRVBYTES 5 // Read Drive Bytes
- #define DEVICESTATUS 6 // Device Status
- #define GETSECTORSIZE 7 // Return Sector Size
- #define GETVOLSIZE 8 // Return Volume Size
- #define MEDIACHANGED 9 // Media Changed
- #define AUDIODISKINFO 10 // Audio Disk Info
- #define AUDIOTRACKINFO 11 // Audio Track Info
- #define AUDIOQCHANINFO 12 // Audio Q-Channel Info
- #define AUDIOSUBINFO 13 // Audio Sub-Channel Info
- #define UPCCODE 14 // UPC Code
- #define AUDIOSTATUSINFO 15 // Audio Status Info
- // IOCTL output commands
- #define EJECTDISK 0 // Eject Disk
- #define DOORLOCK 1 // Lock/Unlock Door
- #define RESETDRIVE 2 // Reset Drive
- #define AUDIOCHANCONTROL 3 // Audio Channel Control
- #define WRITEDEVCONTROL 4 // Write Device Control String
- #define CLOSETRAY 5 // Close Tray
- // TYPES -------------------------------------------------------------------
- typedef signed char S_BYTE;
- typedef unsigned char U_BYTE;
- typedef signed short S_WORD;
- typedef unsigned short U_WORD;
- typedef signed int S_LONG;
- typedef unsigned int U_LONG;
- typedef struct {
- U_LONG size;
- void **address;
- U_WORD *segment;
- U_WORD *selector;
- } DOSChunk_t;
- typedef struct {
- U_LONG edi;
- U_LONG esi;
- U_LONG ebp;
- U_LONG reserved;
- U_LONG ebx;
- U_LONG edx;
- U_LONG ecx;
- U_LONG eax;
- U_WORD flags;
- U_WORD es;
- U_WORD ds;
- U_WORD fs;
- U_WORD gs;
- U_WORD ip;
- U_WORD cs;
- U_WORD sp;
- U_WORD ss;
- } RegBlock_t;
- typedef struct {
- short lengthMin;
- short lengthSec;
- int redStart;
- int sectorStart;
- int sectorLength;
- } AudioTrack_t;
- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
- static U_WORD InputIOCTL(S_WORD request, U_LONG pctrlblk);
- static U_WORD OutputIOCTL(S_WORD request, U_LONG pctrlblk);
- static U_LONG RedToSectors(U_LONG red);
- static int AllocIOCTLBuffers(void);
- static void DPMI_SimRealInt(U_LONG intr, RegBlock_t *rBlock);
- static void *DPMI_AllocRealMem(U_LONG size, U_WORD *segment,
- U_WORD *selector);
- static void DPMI_FreeRealMem(U_WORD selector);
- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
- // PUBLIC DATA DEFINITIONS -------------------------------------------------
- int cd_Error;
- // PRIVATE DATA DEFINITIONS ------------------------------------------------
- static int cd_DriveCount;
- static int cd_FirstDrive;
- static int cd_CurDrive;
- static U_WORD cd_Version;
- static int cd_FirstTrack;
- static int cd_LastTrack;
- static int cd_TrackCount;
- static U_WORD cd_LeadOutMin;
- static U_WORD cd_LeadOutSec;
- static U_LONG cd_LeadOutRed;
- static U_LONG cd_LeadOutSector;
- static U_LONG cd_IOCTLBufferTotal;
- static AudioTrack_t cd_AudioTracks[MAX_AUDIO_TRACKS];
- static int OkInit = 0;
- static RegBlock_t RegBlock;
- static struct PlayReq_s { // CD-ROM Play Audio Device Request Struct
- U_BYTE headerSize;
- U_BYTE subUnitCode;
- U_BYTE command; // = DRC_PLAYAUDIO
- U_WORD status;
- U_BYTE reserved[8];
- U_BYTE addressMode;
- U_LONG startSector;
- U_LONG numberToRead;
- } *cd_PlayReq;
- static U_WORD cd_PlayReqSeg;
- static U_WORD cd_PlayReqSel;
- static struct StopReq_s { // CD-ROM Stop Audio Device Request Struct
- U_BYTE headerSize;
- U_BYTE subUnitCode;
- U_BYTE command; // = DRC_STOPAUDIO
- U_WORD status;
- U_BYTE reserved[8];
- } *cd_StopReq;
- static U_WORD cd_StopReqSeg;
- static U_WORD cd_StopReqSel;
- static struct ResumeReq_s { // CD-ROM Resume Audio Device Request Struct
- U_BYTE headerSize;
- U_BYTE subUnitCode;
- U_BYTE command; // = DRC_RESUMEAUDIO
- U_WORD status;
- U_BYTE reserved[8];
- } *cd_ResumeReq;
- static U_WORD cd_ResumeReqSeg;
- static U_WORD cd_ResumeReqSel;
- // IOCTL Input command data buffer structures
- static struct IOCTLIn_s { // IOCTL Input Struct
- U_BYTE headerSize;
- U_BYTE subUnitCode;
- U_BYTE command; // = DRC_IOCTLINPUT
- U_WORD status;
- U_BYTE reserved[8];
- U_BYTE mediaDescriptor;
- U_LONG ctrlBlkAddr;
- U_WORD tranSize;
- U_WORD startSector;
- U_LONG volPtr;
- } *cd_IOCTLIn;
- static U_WORD cd_IOCTLInSeg;
- static U_WORD cd_IOCTLInSel;
- static struct RAddrDevHead_s {
- U_BYTE code; // ADRDEVHEAD
- U_LONG devHdrAddr; // Address of device header
- } *cd_RAddrDevHead;
- static U_WORD cd_RAddrDevHeadSeg;
- static U_WORD cd_RAddrDevHeadSel;
- static struct LocHead_s {
- U_BYTE code; // HEADLOCATION
- U_BYTE addrMode; // Addressing mode
- U_LONG headLocation; // Location of drive head
- } *cd_LocHead;
- static U_WORD cd_LocHeadSeg;
- static U_WORD cd_LocHeadSel;
- static struct ErrStat_s {
- U_BYTE code; // ERRSTATISTICS
- U_BYTE errVal; // Error statistics
- } *cd_ErrStat;
- static U_WORD cd_ErrStatSeg;
- static U_WORD cd_ErrStatSel;
- static struct AudChanInfo_s {
- U_BYTE code; // AUDIOCHANINFO
- U_BYTE inChanOut0; // Input chan(0,1,2,or 3) for output chan 0
- U_BYTE volumeOut0; // Volume control (0-0xff) for output chan 0
- U_BYTE inChanOut1; // Input chan(0,1,2,or 3) for output chan 1
- U_BYTE volumeOut1; // Volume control (0-0xff) for output chan 1
- U_BYTE inChanOut2; // Input chan(0,1,2,or 3) for output chan 2
- U_BYTE volumeOut2; // Volume control (0-0xff) for output chan 2
- U_BYTE inChanOut3; // Input chan(0,1,2,or 3) for output chan 3
- U_BYTE volumeOut3; // Volume control (0-0xff) for output chan 3
- } *cd_AudChanInfo;
- static U_WORD cd_AudChanInfoSeg;
- static U_WORD cd_AudChanInfoSel;
- static struct RDrvBytes_s {
- U_BYTE code; // READDRVBYTES
- U_BYTE numBytes; // Number of bytes to read
- U_BYTE rBuffer[128]; // Read buffer
- } *cd_RDrvBytes;
- static U_WORD cd_RDrvBytesSeg;
- static U_WORD cd_RDrvBytesSel;
- static struct DevStat_s {
- U_BYTE code; // DEVICESTATUS
- U_LONG devParams; // Device parameters
- } *cd_DevStat;
- static U_WORD cd_DevStatSeg;
- static U_WORD cd_DevStatSel;
- static struct SectSize_s {
- U_BYTE code; // GETSECTORSIZE
- U_BYTE readMode; // Read mode
- U_WORD sectorSize; // Sector size
- } *cd_SectSize;
- static U_WORD cd_SectSizeSeg;
- static U_WORD cd_SectSizeSel;
- static struct VolSize_s {
- U_BYTE code; // GETVOLSIZE
- U_LONG volumeSize; // Volume size
- } *cd_VolSize;
- static U_WORD cd_VolSizeSeg;
- static U_WORD cd_VolSizeSel;
- static struct MedChng_s {
- U_BYTE code; // MEDIACHANGED
- U_BYTE changed; // Media byte
- } *cd_MedChng;
- static U_WORD cd_MedChngSeg;
- static U_WORD cd_MedChngSel;
- static struct DiskInfo_s {
- U_BYTE code; // AUDIODISKINFO
- U_BYTE lowTrack; // Lowest track number
- U_BYTE highTrack; // Highest track number
- U_LONG startLeadOut; // Starting point of the lead-out track
- } *cd_DiskInfo;
- static U_WORD cd_DiskInfoSeg;
- static U_WORD cd_DiskInfoSel;
- static struct TrackInfo_s {
- U_BYTE code; // AUDIOTRACKINFO
- U_BYTE track; // Track number
- U_LONG start; // Starting point of the track
- U_BYTE ctrlInfo; // Track control information
- } *cd_TrackInfo;
- static U_WORD cd_TrackInfoSeg;
- static U_WORD cd_TrackInfoSel;
- static struct QInfo_s {
- U_BYTE code; // AUDIOQCHANINFO
- U_BYTE control; // CONTROL and ADR byte
- U_BYTE tno; // Track number (TNO)
- U_BYTE index; // (POINT) or Index(X)
- U_BYTE min; // (MIN) Running time within a track
- U_BYTE sec; // (SEC) " " " " "
- U_BYTE frame; // (FRAME) " " " " "
- U_BYTE zero; // (ZERO) " " " " "
- U_BYTE aMin; // (AMIN) or (PMIN) Running time on disk
- U_BYTE aSec; // (ASEC) or (PSEC) " " " "
- U_BYTE aFrame; // (AFRAME) or (PFRAME)" " " "
- } *cd_QInfo;
- static U_WORD cd_QInfoSeg;
- static U_WORD cd_QInfoSel;
- static struct SubChanInfo_s {
- U_BYTE code; // AUDIOSUBINFO
- U_LONG startSectAddr; // Starting sector address
- U_LONG transAddr; // Transfer address
- U_LONG numSects; // Number of sectors to read
- } *cd_SubChanInfo;
- static U_WORD cd_SubChanInfoSeg;
- static U_WORD cd_SubChanInfoSel;
- static struct UPCCode_s {
- U_BYTE code; // UPCCODE
- U_BYTE control; // CONTROL and ADR byte
- U_BYTE upc[7]; // UPC/EAN code
- U_BYTE zero; // Zero
- U_BYTE aFrame; // Aframe
- } *cd_UPCCode;
- static U_WORD cd_UPCCodeSeg;
- static U_WORD cd_UPCCodeSel;
- static struct AudStat_s {
- U_BYTE code; // AUDIOSTATUSINFO
- U_WORD status; // Audio status bits
- U_LONG startPlay; // Starting location of last Play/Resume
- U_LONG endPlay; // Ending location for last Play/Resume
- } *cd_AudStat;
- static U_WORD cd_AudStatSeg;
- static U_WORD cd_AudStatSel;
- // IOCTL Output command data buffer structures
- static struct IOCTLOut_s { // IOCTL Output struct
- U_BYTE headerSize;
- U_BYTE subUnitCode;
- U_BYTE command; // = DRC_IOCTLOUTPUT
- U_WORD status;
- U_BYTE reserved[8];
- U_BYTE mediaDescriptor;
- U_LONG ctrlBlkAddr;
- U_WORD tranSize;
- U_WORD startSector;
- U_LONG volPtr;
- } *cd_IOCTLOut;
- static U_WORD cd_IOCTLOutSeg;
- static U_WORD cd_IOCTLOutSel;
- static struct Eject_s {
- U_BYTE code; // EJECTDISK
- } *cd_Eject;
- static U_WORD cd_EjectSeg;
- static U_WORD cd_EjectSel;
- static struct LockDoor_s {
- U_BYTE code; // DOORLOCK
- U_BYTE lock; // Lock function : 0 = unlock, 1 = lock
- } *cd_LockDoor;
- static U_WORD cd_LockDoorSeg;
- static U_WORD cd_LockDoorSel;
- static struct ResetDrv_s {
- U_BYTE code; // RESETDRIVE
- } *cd_ResetDrv;
- static U_WORD cd_ResetDrvSeg;
- static U_WORD cd_ResetDrvSel;
- static struct AudInfo_s {
- U_BYTE code; // AUDIOCHANCONTROL
- U_BYTE inChanOut0; // Input chan(0,1,2,or 3) for output chan 0
- U_BYTE volumeOut0; // Volume control (0-0xff) for output chan 0
- U_BYTE inChanOut1; // Input chan(0,1,2,or 3) for output chan 1
- U_BYTE volumeOut1; // Volume control (0-0xff) for output chan 1
- U_BYTE inChanOut2; // Input chan(0,1,2,or 3) for output chan 2
- U_BYTE volumeOut2; // Volume control (0-0xff) for output chan 2
- U_BYTE inChanOut3; // Input chan(0,1,2,or 3) for output chan 3
- U_BYTE volumeOut3; // Volume control (0-0xff) for output chan 3
- } *cd_AudInfo;
- static U_WORD cd_AudInfoSeg;
- static U_WORD cd_AudInfoSel;
- static struct WDrvBytes_s {
- U_BYTE code; // WRITEDEVCONTROL
- U_BYTE buf[5]; // Write buffer - size ??
- } *cd_WDrvBytes;
- static U_WORD cd_WDrvBytesSeg;
- static U_WORD cd_WDrvBytesSel;
- static struct CloseTray_s {
- U_BYTE code; // CLOSETRAY
- } *cd_CloseTray;
- static U_WORD cd_CloseTraySeg;
- static U_WORD cd_CloseTraySel;
- static U_WORD InCtrlBlkSize[16] = {
- 0x05, 0x06, 0x00, 0x00,
- 0x09, 0x82, 0x05, 0x04,
- 0x05, 0x02, 0x07, 0x07,
- 0x0b, 0x0d, 0x0b, 0x0b
- };
- static U_WORD OutCtrlBlkSize[6] = {
- 0x01, 0x02,
- 0x01, 0x09,
- 0x06, 0x01
- };
- // Structures for allocating conventional memory
- static DOSChunk_t DOSChunks[] = {
- {
- sizeof(struct PlayReq_s),
- &cd_PlayReq, &cd_PlayReqSeg, &cd_PlayReqSel
- },
- {
- sizeof(struct StopReq_s),
- &cd_StopReq, &cd_StopReqSeg, &cd_StopReqSel
- },
- {
- sizeof(struct ResumeReq_s),
- &cd_ResumeReq, &cd_ResumeReqSeg, &cd_ResumeReqSel
- },
- {
- sizeof(struct IOCTLOut_s),
- &cd_IOCTLOut, &cd_IOCTLOutSeg, &cd_IOCTLOutSel
- },
- {
- sizeof(struct Eject_s),
- &cd_Eject, &cd_EjectSeg, &cd_EjectSel
- },
- {
- sizeof(struct LockDoor_s),
- &cd_LockDoor, &cd_LockDoorSeg, &cd_LockDoorSel
- },
- {
- sizeof(struct ResetDrv_s),
- &cd_ResetDrv, &cd_ResetDrvSeg, &cd_ResetDrvSel
- },
- {
- sizeof(struct AudInfo_s),
- &cd_AudInfo, &cd_AudInfoSeg, &cd_AudInfoSel
- },
- {
- sizeof(struct WDrvBytes_s),
- &cd_WDrvBytes, &cd_WDrvBytesSeg, &cd_WDrvBytesSel
- },
- {
- sizeof(struct CloseTray_s),
- &cd_CloseTray, &cd_CloseTraySeg, &cd_CloseTraySel
- },
- {
- sizeof(struct IOCTLIn_s),
- &cd_IOCTLIn, &cd_IOCTLInSeg, &cd_IOCTLInSel
- },
- {
- sizeof(struct RAddrDevHead_s),
- &cd_RAddrDevHead, &cd_RAddrDevHeadSeg, &cd_RAddrDevHeadSel
- },
- {
- sizeof(struct LocHead_s),
- &cd_LocHead, &cd_LocHeadSeg, &cd_LocHeadSel
- },
- {
- sizeof(struct ErrStat_s),
- &cd_ErrStat, &cd_ErrStatSeg, &cd_ErrStatSel
- },
- {
- sizeof(struct AudChanInfo_s),
- &cd_AudChanInfo, &cd_AudChanInfoSeg, &cd_AudChanInfoSel
- },
- {
- sizeof(struct RDrvBytes_s),
- &cd_RDrvBytes, &cd_RDrvBytesSeg, &cd_RDrvBytesSel
- },
- {
- sizeof(struct DevStat_s),
- &cd_DevStat, &cd_DevStatSeg, &cd_DevStatSel
- },
- {
- sizeof(struct SectSize_s),
- &cd_SectSize, &cd_SectSizeSeg, &cd_SectSizeSel
- },
- {
- sizeof(struct VolSize_s),
- &cd_VolSize, &cd_VolSizeSeg, &cd_VolSizeSel
- },
- {
- sizeof(struct MedChng_s),
- &cd_MedChng, &cd_MedChngSeg, &cd_MedChngSel
- },
- {
- sizeof(struct DiskInfo_s),
- &cd_DiskInfo, &cd_DiskInfoSeg, &cd_DiskInfoSel
- },
- {
- sizeof(struct TrackInfo_s),
- &cd_TrackInfo, &cd_TrackInfoSeg, &cd_TrackInfoSel
- },
- {
- sizeof(struct QInfo_s),
- &cd_QInfo, &cd_QInfoSeg, &cd_QInfoSel
- },
- {
- sizeof(struct SubChanInfo_s),
- &cd_SubChanInfo, &cd_SubChanInfoSeg, &cd_SubChanInfoSel
- },
- {
- sizeof(struct UPCCode_s),
- &cd_UPCCode, &cd_UPCCodeSeg, &cd_UPCCodeSel
- },
- {
- sizeof(struct AudStat_s),
- &cd_AudStat, &cd_AudStatSeg, &cd_AudStatSel
- },
- {
- 0, NULL, NULL, NULL
- }
- };
- // CODE --------------------------------------------------------------------
- //==========================================================================
- //
- // I_CDMusInit
- //
- // Initializes the CD audio system. Must be called before using any
- // other I_CDMus functions.
- //
- // Returns: 0 (ok) or -1 (error, in cd_Error).
- //
- //==========================================================================
- int I_CDMusInit(void)
- {
- int i;
- int sect;
- int maxTrack;
- S_BYTE startMin1 = 0;
- S_BYTE startSec1 = 0;
- S_BYTE startMin2 = 0;
- S_BYTE startSec2 = 0;
- S_BYTE lengthMin = 0;
- S_BYTE lengthSec = 0;
- if(OkInit != 1)
- { // Only execute if uninitialized
- // Get number of CD-ROM drives and first drive
- memset(&RegBlock, 0, sizeof(RegBlock));
- RegBlock.eax = CDROM_GETDRIVECOUNT;
- RegBlock.ebx = 0;
- DPMI_SimRealInt(MULTIPLEX_INT, &RegBlock);
- cd_DriveCount = RegBlock.ebx;
- // MSCDEX not installed if number of drives = 0
- if(cd_DriveCount == 0)
- {
- cd_Error = CDERR_NOTINSTALLED;
- return -1;
- }
- cd_FirstDrive = RegBlock.ecx;
- cd_CurDrive = cd_FirstDrive;
- // Allocate the IOCTL buffers
- if(AllocIOCTLBuffers() == -1)
- {
- cd_Error = CDERR_IOCTLBUFFMEM;
- return -1;
- }
- // Get MSCDEX version
- // Major version in upper byte, minor version in lower byte
- memset(&RegBlock, 0, sizeof(RegBlock));
- RegBlock.eax = CDROM_GETVERSION;
- DPMI_SimRealInt(MULTIPLEX_INT, &RegBlock);
- cd_Version = RegBlock.ebx;
- // Check device status to make sure we can read Audio CD's
- InputIOCTL(DEVICESTATUS, cd_DevStatSeg);
- if((cd_DevStat->devParams & 0x0010) == 0)
- {
- cd_Error = CDERR_NOAUDIOSUPPORT;
- return -1;
- }
- }
- // Force audio to stop playing
- I_CDMusStop();
- // Make sure we have the current TOC
- InputIOCTL(MEDIACHANGED, cd_MedChngSeg);
- // Set track variables
- InputIOCTL(AUDIODISKINFO, cd_DiskInfoSeg);
- cd_FirstTrack = cd_DiskInfo->lowTrack;
- cd_LastTrack = cd_DiskInfo->highTrack;
- if(cd_FirstTrack == 0 && cd_FirstTrack == cd_LastTrack)
- {
- cd_Error = CDERR_NOAUDIOTRACKS;
- return -1;
- }
- cd_TrackCount = cd_LastTrack-cd_FirstTrack+1;
- cd_LeadOutMin = cd_DiskInfo->startLeadOut>>16 & 0xFF;
- cd_LeadOutSec = cd_DiskInfo->startLeadOut>>8 & 0xFF;
- cd_LeadOutRed = cd_DiskInfo->startLeadOut;
- cd_LeadOutSector = RedToSectors(cd_DiskInfo->startLeadOut);
- // Create Red Book start, sector start, and sector length
- // for all tracks
- sect = cd_LeadOutSector;
- for(i = cd_LastTrack; i >= cd_FirstTrack; i--)
- {
- cd_TrackInfo->track = i;
- InputIOCTL(AUDIOTRACKINFO, cd_TrackInfoSeg);
- if(i < MAX_AUDIO_TRACKS)
- {
- cd_AudioTracks[i].redStart = cd_TrackInfo->start;
- cd_AudioTracks[i].sectorStart =
- RedToSectors(cd_TrackInfo->start);
- cd_AudioTracks[i].sectorLength =
- sect-RedToSectors(cd_TrackInfo->start);
- }
- sect = RedToSectors(cd_TrackInfo->start);
- }
- // Create track lengths in minutes and seconds
- if(cd_LastTrack >= MAX_AUDIO_TRACKS)
- {
- maxTrack = MAX_AUDIO_TRACKS-1;
- }
- else
- {
- maxTrack = cd_LastTrack;
- }
- cd_TrackInfo->track = cd_FirstTrack;
- InputIOCTL(AUDIOTRACKINFO, cd_TrackInfoSeg);
- startMin1 = (cd_TrackInfo->start >> 16);
- startSec1 = (cd_TrackInfo->start >> 8);
- for(i = cd_FirstTrack; i <= maxTrack; i++)
- {
- cd_TrackInfo->track = i+1;
- if(i < cd_LastTrack)
- {
- InputIOCTL(AUDIOTRACKINFO, cd_TrackInfoSeg);
- startMin2 = (cd_TrackInfo->start >> 16);
- startSec2 = (cd_TrackInfo->start >> 8);
- }
- else
- {
- startMin2 = cd_LeadOutRed>>16;
- startSec2 = cd_LeadOutRed>>8;
- }
- lengthSec = startSec2 - startSec1;
- lengthMin = startMin2 - startMin1;
- if(lengthSec < 0)
- {
- lengthSec += 60;
- lengthMin--;
- }
- cd_AudioTracks[i].lengthMin = lengthMin;
- cd_AudioTracks[i].lengthSec = lengthSec;
- startMin1 = startMin2;
- startSec1 = startSec2;
- }
- // Clip high tracks
- cd_LastTrack = maxTrack;
- OkInit = 1;
- return 0;
- }
- //==========================================================================
- //
- // I_CDMusPlay
- //
- // Play an audio CD track.
- //
- // Returns: 0 (ok) or -1 (error, in cd_Error).
- //
- //==========================================================================
- int I_CDMusPlay(int track)
- {
- int start;
- int len;
- if(track < cd_FirstTrack || track > cd_LastTrack)
- {
- cd_Error = CDERR_BADTRACK;
- return(-1);
- }
- I_CDMusStop();
- start = cd_AudioTracks[track].redStart;
- len = cd_AudioTracks[track].sectorLength;
- cd_PlayReq->addressMode = RED_MODE;
- cd_PlayReq->startSector = start;
- cd_PlayReq->numberToRead = len;
- memset(&RegBlock, 0, sizeof(RegBlock));
- RegBlock.eax = CDROM_SENDDEVICEREQ;
- RegBlock.ecx = cd_CurDrive;
- RegBlock.ebx = 0;
- RegBlock.es = cd_PlayReqSeg;
- DPMI_SimRealInt(MULTIPLEX_INT, &RegBlock);
- if(cd_PlayReq->status&0x8000)
- {
- cd_Error = CDERR_DEVREQBASE+(cd_PlayReq->status)&0x00ff;
- return(-1);
- }
- return(0);
- }
- //==========================================================================
- //
- // I_CDMusStop
- //
- // Stops the playing of an audio CD.
- //
- // Returns: 0 (ok) or -1 (error, in cd_Error).
- //
- //==========================================================================
- int I_CDMusStop(void)
- {
- memset(&RegBlock, 0, sizeof(RegBlock));
- RegBlock.eax = CDROM_SENDDEVICEREQ;
- RegBlock.ecx = cd_CurDrive;
- RegBlock.ebx = 0;
- RegBlock.es = cd_StopReqSeg;
- DPMI_SimRealInt(MULTIPLEX_INT, &RegBlock);
- if(cd_StopReq->status&0x8000)
- {
- cd_Error = CDERR_DEVREQBASE+(cd_StopReq->status)&0x00ff;
- return -1;
- }
- return 0;
- }
- //==========================================================================
- //
- // I_CDMusResume
- //
- // Resumes the playing of an audio CD.
- //
- // Returns: 0 (ok) or -1 (error, in cd_Error).
- //
- //==========================================================================
- int I_CDMusResume(void)
- {
- memset(&RegBlock, 0, sizeof(RegBlock));
- RegBlock.eax = CDROM_SENDDEVICEREQ;
- RegBlock.ecx = cd_CurDrive;
- RegBlock.ebx = 0;
- RegBlock.es = cd_ResumeReqSeg;
- DPMI_SimRealInt(MULTIPLEX_INT, &RegBlock);
- if(cd_ResumeReq->status&0x8000)
- {
- cd_Error = CDERR_DEVREQBASE+(cd_ResumeReq->status)&0x00ff;
- return -1;
- }
- return 0;
- }
- //==========================================================================
- //
- // I_CDMusSetVolume
- //
- // Sets the CD audio volume (0 - 255).
- //
- // Returns: 0 (ok) or -1 (error, in cd_Error).
- //
- //==========================================================================
- int I_CDMusSetVolume(int volume)
- {
- if(!OkInit)
- {
- cd_Error = CDERR_NOTINSTALLED;
- return -1;
- }
- // Read current channel info
- InputIOCTL(AUDIOCHANINFO, cd_AudChanInfoSeg);
- // Change the volumes
- cd_AudChanInfo->volumeOut0 =
- cd_AudChanInfo->volumeOut1 =
- cd_AudChanInfo->volumeOut2 =
- cd_AudChanInfo->volumeOut3 = volume;
- // Write modified channel info
- OutputIOCTL(AUDIOCHANCONTROL, cd_AudChanInfoSeg);
- return 0;
- }
- //==========================================================================
- //
- // I_CDMusFirstTrack
- //
- // Returns: the number of the first track.
- //
- //==========================================================================
- int I_CDMusFirstTrack(void)
- {
- return cd_FirstTrack;
- }
- //==========================================================================
- //
- // I_CDMusLastTrack
- //
- // Returns: the number of the last track.
- //
- //==========================================================================
- int I_CDMusLastTrack(void)
- {
- return cd_LastTrack;
- }
- //==========================================================================
- //
- // I_CDMusTrackLength
- //
- // Returns: Length of the given track in seconds, or -1 (error, in
- // cd_Error).
- //
- //==========================================================================
- int I_CDMusTrackLength(int track)
- {
- if(track < cd_FirstTrack || track > cd_LastTrack)
- {
- cd_Error = CDERR_BADTRACK;
- return -1;
- }
- return cd_AudioTracks[track].lengthMin*60
- +cd_AudioTracks[track].lengthSec;
- }
- //==========================================================================
- //
- // AllocIOCTLBuffers
- //
- // Allocates conventional memory for the IOCTL input and output buffers.
- // Sets cd_IOCTLBufferTotal to the total allocated.
- //
- // Returns: 0 (ok) or -1 (error, in cd_Error).
- //
- //==========================================================================
- static int AllocIOCTLBuffers(void)
- {
- int i;
- int size;
- DOSChunk_t *ck;
- cd_IOCTLBufferTotal = 0;
- for(i = 0; DOSChunks[i].size != 0; i++)
- {
- ck = &DOSChunks[i];
- size = ck->size;
- cd_IOCTLBufferTotal += (size+15)&0xfffffff0;
- *ck->address = DPMI_AllocRealMem(size, ck->segment, ck->selector);
- if(*ck->address == NULL)
- {
- return -1;
- }
- memset(*ck->address, 0, size);
- }
- cd_IOCTLIn->headerSize = sizeof(struct IOCTLIn_s);
- cd_IOCTLIn->command = DRC_IOCTLINPUT;
- cd_IOCTLOut->headerSize = sizeof(struct IOCTLOut_s);
- cd_IOCTLOut->command = DRC_IOCTLOUTPUT;
- cd_PlayReq->headerSize = sizeof(struct PlayReq_s);
- cd_PlayReq->command = DRC_PLAYAUDIO;
- cd_StopReq->headerSize = sizeof(struct StopReq_s);
- cd_StopReq->command = DRC_STOPAUDIO;
- cd_ResumeReq->headerSize = sizeof(struct ResumeReq_s);
- cd_ResumeReq->command = DRC_RESUMEAUDIO;
- return 0;
- }
- //==========================================================================
- //
- // InputIOCTL
- //
- // Sends an IOCTL input device request command.
- //
- // Returns: the status of the request.
- //
- //==========================================================================
- static U_WORD InputIOCTL(S_LONG request, U_WORD buffSeg)
- {
- U_BYTE *code;
- code = (U_BYTE *)(buffSeg<<4);
- *code = (U_BYTE)request;
- cd_IOCTLIn->ctrlBlkAddr = buffSeg<<16;
- cd_IOCTLIn->tranSize = InCtrlBlkSize[request];
- memset(&RegBlock, 0, sizeof(RegBlock));
- RegBlock.eax = CDROM_SENDDEVICEREQ;
- RegBlock.ecx = cd_CurDrive;
- RegBlock.ebx = 0;
- RegBlock.es = cd_IOCTLInSeg;
- DPMI_SimRealInt(MULTIPLEX_INT, &RegBlock);
- return cd_IOCTLIn->status;
- }
- //==========================================================================
- //
- // OutputIOCTL
- //
- // Sends an IOCTL output device request command.
- //
- // Returns: the status of the request.
- //
- //==========================================================================
- static U_WORD OutputIOCTL(S_LONG request, U_WORD buffSeg)
- {
- U_BYTE *code;
- code = (U_BYTE *)(buffSeg<<4);
- *code = (U_BYTE)request;
- cd_IOCTLOut->ctrlBlkAddr = buffSeg<<16;
- cd_IOCTLOut->tranSize = OutCtrlBlkSize[request];
- RegBlock.eax = CDROM_SENDDEVICEREQ;
- RegBlock.ecx = cd_CurDrive;
- RegBlock.ebx = 0;
- RegBlock.es = cd_IOCTLOutSeg;
- DPMI_SimRealInt(MULTIPLEX_INT, &RegBlock);
- return cd_IOCTLOut->status;
- }
- //==========================================================================
- //
- // RedToSectors
- //
- // Converts Red Book addresses to HSG sectors.
- // Sectors = Minutes * 60 * 75 + Seconds * 75 + Frame - 150
- //
- // Returns: HSG sectors.
- //
- //==========================================================================
- static U_LONG RedToSectors(U_LONG red)
- {
- U_LONG sector;
- sector = ((red&0x00ff0000) >> 16) * 60 * 75;
- sector += ((red&0x0000ff00) >> 8) * 75;
- sector += (red&0x000000ff);
- return sector-150;
- }
- //==========================================================================
- //
- // DPMI_SimRealInt
- //
- //==========================================================================
- static void DPMI_SimRealInt(U_LONG intr, RegBlock_t *rBlock)
- {
- union REGS regs;
- struct SREGS sRegs;
- regs.x.eax = DPMI_SIMREALINT;
- regs.x.ebx = intr;
- regs.x.ecx = 0;
- regs.x.edi = FP_OFF((void far *)rBlock);
- sRegs.es = FP_SEG((void far *)rBlock);
- sRegs.ds = FP_SEG((void far *)rBlock);
- int386x(DPMI_INT, ®s, ®s, &sRegs);
- }
- //==========================================================================
- //
- // DPMI_AllocRealMem
- //
- //==========================================================================
- static void *DPMI_AllocRealMem(U_LONG size, U_WORD *segment,
- U_WORD *selector)
- {
- union REGS inRegs;
- union REGS outRegs;
- inRegs.x.eax = DPMI_ALLOCREALMEM;
- inRegs.x.ebx = (size+15)/16;
- int386(DPMI_INT, &inRegs, &outRegs);
- if(outRegs.x.cflag)
- {
- return NULL;
- }
- *segment = outRegs.x.eax&0xffff;
- *selector = outRegs.x.edx&0xffff;
- return (void *)(outRegs.x.eax<<4);
- }
- //==========================================================================
- //
- // DPMI_FreeRealMem
- //
- //==========================================================================
- static void DPMI_FreeRealMem(U_WORD selector)
- {
- union REGS regs;
- regs.x.eax = DPMI_FREEREALMEM;
- regs.x.edx = selector;
- int386(DPMI_INT, ®s, ®s);
- }
|