519 lines
19 KiB
C++
519 lines
19 KiB
C++
![]() |
/*
|
||
|
** 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 <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
/***************************************************************************
|
||
|
** 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 <stddef.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <dos.h>
|
||
|
|
||
|
#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));
|
||
|
|
||
|
}
|
||
|
|