/* ** Command & Conquer Red Alert(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*************************************************************************** ** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S ** *************************************************************************** * * * Project Name : WWLIB * * * * File Name : REDBOOK.CPP * * * * Programmer : STEVE WETHERILL (FROM SCOTT BOWEN CODE) * * * * Start Date : 5/13/94 * * * * Last Update : June 4, 1994 [SW] * * * *-------------------------------------------------------------------------* *-------------------------------------------------------------------------* * Functions: * * RedBookClass::~RedBookClass(VOID) * * RedBookClass::RedToHS(ULONG i) * * RedBookClass::MSFtoRed(UBYTE m, UBYTE s, UBYTE f) * * RedBookClass::FullCDVolume(UBYTE chan) * * RedBookClass::PlayTrack(UWORD track) * * RedBookClass::Play_CD_MSL(UWORD min_sec, UWORD len) * * RedBookClass::PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF, * * UBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan) * * RedBookClass::CheckCDMusic(VOID) * * RedBookClass::StopCDMusic(VOID) * *= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/ #include #include #include #include #include #include "wwstd.h" #include "playcd.h" #include "wwmem.h" /*************************************************************************** * RedBookClass -- default constructor * * * * * * * * INPUT: * * none * * OUTPUT: * * none * * WARNINGS: * * calls GetCDDrive() * * HISTORY: * * 05/25/1994 SW : Created. * *=========================================================================*/ RedBookClass::RedBookClass(VOID) : GetCDClass() // call the base constructor { SEGSEL tmpadr ; tmpadr = cdDrive_addrp; memset ( this , 0 , sizeof ( RedBookClass ) ) ; cdDrive_addrp = tmpadr ; Stop.Length = 13; Stop.Command = 133; Tinfo.Length = 26; Tinfo.Command = 3; Tinfo.CntTrns = 7; Tinfo.TrInfo = 11; Play.Length = 22; Play.Command = 132; Play.AddrMd = 1; Volm.Length = 26; Volm.Command = 12; Volm.CntTrns = 9; Volm.TrInfo = 3; Volm.In1 = 1; Volm.In2 = 2; Volm.In3 = 3; Stat.Length = 26; Stat.Command = 3; Stat.CntTrns = 11; Stat.StatInfo = 15; if (DPMI_real_alloc(sizeof(TinfoType)/16+1, &Tinfo_addrp, &largestp)) exit(1); if (DPMI_real_alloc(sizeof(StatType)/16+1, &Stat_addrp, &largestp)) exit(1); if (DPMI_real_alloc(sizeof(VolmType)/16+1, &Volm_addrp, &largestp)) exit(1); if (DPMI_real_alloc(sizeof(PlayType)/16+1, &Play_addrp, &largestp)) exit(1); if (DPMI_real_alloc(sizeof(StopType)/16+1, &Stop_addrp, &largestp)) exit(1); GetCDDrive(); } /*************************************************************************** * REDBOOKCLASS -- destructor * * * * * * * * INPUT: * * none * * OUTPUT: * * none * * WARNINGS: * * * * HISTORY: * * 05/26/1994 SW : Created. * *=========================================================================*/ RedBookClass::~RedBookClass(VOID) { if(Tinfo_addrp.seg) DPMI_real_free(Tinfo_addrp); // free up those conventional buffers if(Stat_addrp.seg) DPMI_real_free(Stat_addrp); if(Volm_addrp.seg) DPMI_real_free(Volm_addrp); if(Play_addrp.seg) DPMI_real_free(Play_addrp); if(Stop_addrp.seg) DPMI_real_free(Stop_addrp); } /*************************************************************************** * REDTOHS -- RedBook to High-Sierra conversion * * * * * * * * INPUT: * * ULONG * * OUTPUT: * * ULONG * * WARNINGS: * * * * HISTORY: * * 05/26/1994 SW : Created. * *=========================================================================*/ ULONG RedBookClass::RedToHS(ULONG i) { return( ((i>>16) & 0xFF) * 60 * 75) + ( ((i>>8) & 0xFF) * 75) + (i & 0xFF); } /*************************************************************************** * MSFTORED -- Minute, Second, Frame to RedBook conversion * * * * * * * * INPUT: * * UBYTE minute * * UBYTE second * * UBYTE frame * * OUTPUT: * * ULONG RedBook * * WARNINGS: * * * * HISTORY: * * 05/26/1994 SW : Created. * *=========================================================================*/ ULONG RedBookClass::MSFtoRed(UBYTE m, UBYTE s, UBYTE f) { return( ((ULONG)m << 16) + ((ULONG)s << 8) + (ULONG)f ); } /*************************************************************************** * FULLCDVOLUME -- set full volume * * * * * * * * INPUT: * * UBYTE channel * * * * CHLEFT * * CHRIGHT * * CHBOTH * * * * OUTPUT: * * none * * WARNINGS: * * * * HISTORY: * * 05/26/1994 SW : Created. * *=========================================================================*/ VOID RedBookClass::FullCDVolume(UBYTE chan) { Volm.Vol0 = Volm.Vol1 = Volm.Vol2 = Volm.Vol3 = 255; Volm.TrnsAdOff = offsetof (VolmType, TrInfo); Volm.TrnsAdSeg = Volm_addrp.seg; if(chan == CHLEFT) { // Volm.In0 = 0; // Volm.In1 = 3; // Volm.In2 = 3; // Volm.In3 = 3; Volm.Vol1 = 0; } else if(chan == CHRIGHT) { // Volm.In0 = 3; // Volm.In1 = 1; // Volm.In2 = 3; // Volm.In3 = 3; Volm.Vol0 = 0; } else /* both channels */ { Volm.In0 = 0; Volm.In1 = 1; Volm.In2 = 2; Volm.In3 = 3; } // WriteRealMem(REALPTR(Volm_addrp) << 16, &Volm, sizeof(VolmType)); Mem_Copy ( &Volm , (void *) ( Volm_addrp.seg << 4 ) , sizeof(VolmType)); regs.x.eax = 0x1510; regs.x.ecx = cdDrive[0]; regs.x.ebx = 0x0000; sregs.es = Volm_addrp.seg; DPMI_real_intr(0x2F, ®s, & sregs); // ReadRealMem(&Volm, REALPTR(Volm_addrp) << 16, sizeof(VolmType)); Mem_Copy ( (void *) ( Volm_addrp . seg << 4 ), &Volm ,sizeof(VolmType)); } /*************************************************************************** * PLAYTRACK -- play a track * * * * * * * * INPUT: * * UWORD track * * OUTPUT: * * none * * WARNINGS: * * * * HISTORY: * * 05/26/1994 SW : Created. * *=========================================================================*/ VOID RedBookClass::PlayTrack(UWORD track) { StopCDMusic(); Tinfo.Track = track; Tinfo.TrnsAdOff = offsetof (TinfoType, TrInfo); Tinfo.TrnsAdSeg = Tinfo_addrp.seg; // WriteRealMem(REALPTR(Tinfo_addrp) << 16, &Tinfo, sizeof(TinfoType)); Mem_Copy ( &Tinfo , (void *) ( Tinfo_addrp.seg << 4 ) , sizeof(TinfoType)); regs.x.eax = 0x1510; regs.x.ecx = cdDrive[0]; regs.x.ebx = 0x0000; sregs.es = Tinfo_addrp.seg; DPMI_real_intr(0x2F, ®s, &sregs); // gets start time of track in Tinfo.Start // ReadRealMem(&Tinfo, REALPTR(Tinfo_addrp) << 16, sizeof(TinfoType)); Mem_Copy ( (void *) ( Tinfo_addrp.seg << 4 ) , &Tinfo, sizeof(TinfoType)); Play.Start = Tinfo.Start; Tinfo.Track++; Tinfo.TrnsAdOff = offsetof (TinfoType, TrInfo); Tinfo.TrnsAdSeg = Tinfo_addrp.seg; // WriteRealMem(REALPTR(Tinfo_addrp) << 16, &Tinfo, sizeof(TinfoType)); Mem_Copy ( &Tinfo , (void *) ( Tinfo_addrp.seg << 4 ) , sizeof(TinfoType)); regs.x.eax = 0x1510; regs.x.ecx = cdDrive[0]; regs.x.ebx = 0x0000; sregs.es = Tinfo_addrp.seg; DPMI_real_intr(0x2F, ®s , &sregs); // gets start time of following track in Tinfo.Start // ReadRealMem(&Tinfo, REALPTR(Tinfo_addrp) << 16, sizeof(TinfoType)); Mem_Copy ( (void *) ( Tinfo_addrp.seg << 4 ) , &Tinfo, sizeof(TinfoType)); Play.CntSect = RedToHS(Tinfo.Start) - RedToHS(Play.Start) - 1; // WriteRealMem(REALPTR(Play_addrp) << 16, &Play, sizeof(PlayType)); Mem_Copy ( &Play , (void *) ( Play_addrp.seg << 4 ) , sizeof(PlayType)); regs.x.eax = 0x1510; regs.x.ecx = cdDrive[0]; regs.x.ebx = 0x0000; sregs.es = Play_addrp.seg; DPMI_real_intr(0x2F, ®s, &sregs); // ReadRealMem(&Play, REALPTR(Play_addrp) << 16, sizeof(PlayType)); Mem_Copy ( (void *) ( Play_addrp.seg << 4 ) , &Play, sizeof(PlayType)); FullCDVolume(CHBOTH); } /*************************************************************************** * PLAY_CD_MSL -- play cd from start min_sec for len * * * * * * * * INPUT: * * UWORD min_sec * * UWORD Len * * OUTPUT: * * none * * WARNINGS: * * * * HISTORY: * * 05/26/1994 SW : Created. * *=========================================================================*/ VOID RedBookClass::Play_CD_MSL(UWORD min_sec, UWORD len) { UWORD startM, startS, startF; UWORD endM, endS, endF; if (!len) return; endM = startM = (min_sec >> 8) + AUDIO_START_MIN; endS = startS = (min_sec & 0xFF) + AUDIO_START_SEC; startF = endF = 0; while (len > 59) { endM++; len -= 60; } endS += len; if (endS > 59) { endM++; endS -= 60; } PlayMSF((UBYTE) startM, (UBYTE)startS, (UBYTE)startF, (UBYTE)endM, (UBYTE)endS, (UBYTE)endF, 2 /* chan */); } /*************************************************************************** * PlayMSF -- Play Minute, Second, Frame to Minute, Second, Frame * * * * * * * * INPUT: * * UBYTE startM * * UBYTE startS * * UBYTE startF * * UBYTE endM * * UBYTE endS * * UBYTE endF * * UBYTE chan * * OUTPUT: * * none * * WARNINGS: * * * * HISTORY: * * 05/27/1994 SW : Created. * *=========================================================================*/ VOID RedBookClass::PlayMSF(UBYTE startM, UBYTE startS, UBYTE startF, UBYTE endM, UBYTE endS, UBYTE endF, UBYTE chan) { Play.Start = MSFtoRed(startM, startS, startF); Play.CntSect = RedToHS(MSFtoRed(endM, endS, endF)) - RedToHS(Play.Start) - 1; // WriteRealMem(REALPTR(Play_addrp) << 16, &Play, sizeof(PlayType)); Mem_Copy ( &Play , (void *) ( Play_addrp.seg << 4 ) , sizeof(PlayType)); regs.x.eax = 0x1510; regs.x.ecx = cdDrive[0]; regs.x.ebx = offsetof (PlayType, Length); sregs.es = Play_addrp.seg; DPMI_real_intr(0x2F, ®s, &sregs); // ReadRealMem(&Play, REALPTR(Play_addrp) << 16, sizeof(PlayType)); Mem_Copy ( (void *) ( Play_addrp.seg << 4 ) , &Play, sizeof(PlayType)); FullCDVolume(chan); } /*************************************************************************** * CheckCDMusic -- Check for CD playing * * * * * * * * INPUT: * * UBYTE startM * * UBYTE startS * * UBYTE startF * * UBYTE endM * * UBYTE endS * * UBYTE endF * * UBYTE chan * * OUTPUT: * * UWORD TRUE if playing else FALSE * * WARNINGS: * * * * HISTORY: * * 05/27/1994 SW : Created. * *=========================================================================*/ UWORD RedBookClass::CheckCDMusic(VOID) { Stat.TrnsAdOff = offsetof (StatType, StatInfo); Stat.TrnsAdSeg = Stat_addrp.seg; // WriteRealMem(REALPTR(Stat_addrp) << 16, &Stat, sizeof(StatType)); Mem_Copy ( &Stat , (void *) ( Stat_addrp.seg << 4 ) , sizeof(StatType)); regs.x.ecx = cdDrive[0]; regs.x.ebx = offsetof (StatType, Length); regs.x.eax = 0x1510; sregs.es = Stat_addrp.seg; DPMI_real_intr(0x2F, ®s, &sregs); // ReadRealMem(&Stat, REALPTR(Stat_addrp) << 16, sizeof(StatType)); Mem_Copy ( (void *) ( Stat_addrp.seg << 4 ) , &Stat, sizeof(StatType)); return (Stat.Status&0x200); } /*************************************************************************** * STOPCDMUSIC -- stop CD playing * * * * * * * * INPUT: * * none * * OUTPUT: * * none * * WARNINGS: * * * * HISTORY: * * 05/27/1994 SW : Created. * *=========================================================================*/ VOID RedBookClass::StopCDMusic(VOID) { // WriteRealMem(REALPTR(Stop_addrp) << 16, &Stop, sizeof(StopType)); Mem_Copy ( &Stop , (void *) ( Stop_addrp.seg << 4 ) , sizeof(StopType)); regs.x.eax = 0x1510; regs.x.ecx = cdDrive[0]; regs.x.ebx = offsetof (StopType, Length); sregs.es = Stop_addrp.seg; DPMI_real_intr(0x2F, ®s, &sregs); // ReadRealMem(&Stop, REALPTR(Stop_addrp) << 16, sizeof(StopType)); Mem_Copy ( (void *) ( Stop_addrp.seg << 4 ) , &Stop, sizeof(StopType)); }