CnC_Red_Alert/WWFLAT32/PLAYCD/REDBOOK.CPP

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, &regs, & 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, &regs, &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, &regs , &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, &regs, &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, &regs, &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, &regs, &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, &regs, &sregs);
// ReadRealMem(&Stop, REALPTR(Stop_addrp) << 16, sizeof(StopType));
Mem_Copy ( (void *) ( Stop_addrp.seg << 4 ) , &Stop, sizeof(StopType));
}