From dc6e126a719217b14de43c02eb34b11eea97fc6a Mon Sep 17 00:00:00 2001 From: Sjoerd van der Berg Date: Sun, 4 Jul 2004 21:07:45 +0000 Subject: [PATCH] Changes for 1 global capture directory Support for capturing raw midi Support for capturing raw opl Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1864 --- src/hardware/adlib.cpp | 156 ++++++++++++++++++++++++++++++++++++++--- src/hardware/mixer.cpp | 34 +-------- 2 files changed, 151 insertions(+), 39 deletions(-) diff --git a/src/hardware/adlib.cpp b/src/hardware/adlib.cpp index 5c276768..f5237aff 100644 --- a/src/hardware/adlib.cpp +++ b/src/hardware/adlib.cpp @@ -19,16 +19,23 @@ #include #include #include +#include +#include + #include "dosbox.h" #include "inout.h" #include "mixer.h" #include "pic.h" #include "hardware.h" #include "setup.h" +#include "mapper.h" +#include "mem.h" + /* Thanks to vdmsound for nice simple way to implement this */ -# define logerror + +#define logerror #ifdef _MSC_VER /* Disable recurring warnings */ @@ -75,12 +82,24 @@ namespace THEOPL3 { #define OPL2_INTERNAL_FREQ 3600000 // The OPL2 operates at 3.6MHz #define OPL3_INTERNAL_FREQ 14400000 // The OPL3 operates at 14.4MHz +#define RAW_SIZE 1024 static struct { bool active; OPL_Mode mode; MIXER_Channel * chan; Bit32u last_used; Bit16s mixbuf[2][128]; + struct { + FILE * handle; + Bit32u start; + Bit32u last; + Bit8u index; + Bit8u buffer[RAW_SIZE+8]; + Bit8u regs[2][256]; + Bit32u used; + Bit32u done; + Bit8u cmd[2]; + } raw; } opl; static void OPL_CallBack(Bit8u *stream, Bit32u len) { @@ -104,7 +123,6 @@ static void OPL_CallBack(Bit8u *stream, Bit32u len) { ((Bit16u *)stream)[i*2+1]=opl.mixbuf[1][i]; } break; - } if ((PIC_Ticks-opl.last_used)>5000) { MIXER_Enable(opl.chan,false); @@ -125,27 +143,147 @@ static Bitu OPL_Read(Bitu port,Bitu iolen) { return 0xff; } +static void OPL_RawAdd(Bitu index,Bitu val); void OPL_Write(Bitu port,Bitu val,Bitu iolen) { opl.last_used=PIC_Ticks; if (!opl.active) { opl.active=true; MIXER_Enable(opl.chan,true); } - Bitu addr=port & 3; - if (!addr) adlib_commandreg=val; + port&=3; + if (port&1) { + Bitu index=port>>1; + opl.raw.regs[index][opl.raw.cmd[index]]=val; + if (opl.raw.handle) OPL_RawAdd(index,val); + } else opl.raw.cmd[port>>1]=val; + if (!port) adlib_commandreg=val; switch (opl.mode) { case OPL_opl2: - OPL2::YM3812Write(0,addr,val); + OPL2::YM3812Write(0,port,val); break; case OPL_opl3: - THEOPL3::YMF262Write(0,addr,val); + THEOPL3::YMF262Write(0,port,val); break; case OPL_dualopl2: - OPL2::YM3812Write(addr>>1,addr,val); + OPL2::YM3812Write(port>>1,port,val); break; } } +static Bit8u dro_header[]={ + 'D','B','R','A', /* Bit32u ID */ + 'W','O','P','L', /* Bit32u ID */ + 0x0,0x0,0x0,0x0, /* Bit32u total milliseconds */ + 0x0,0x0,0x0,0x0, /* Bit32u total data */ + 0x0, /* Type 0=opl2,1=opl3,2=dual-opl2 */ +}; +/* Commands + 0x00 Bit8u, millisecond delay+1 + 0x01 Bit16u, millisecond delay+1 + 0x02 none, Use the low index/data pair + 0x03 none, Use the high index/data pair + 0xxx Bit8u, send command and data to current index/data pair +*/ + +static void OPL_RawEmptyBuffer(void) { + fwrite(opl.raw.buffer,1,opl.raw.used,opl.raw.handle); + opl.raw.done+=opl.raw.used; + opl.raw.used=0; +} + +#define ADDBUF(_VAL_) opl.raw.buffer[opl.raw.used++]=_VAL_; +static void OPL_RawAdd(Bitu index,Bitu val) { + /* Check if we have yet to start */ + if (!opl.raw.start) { + Bitu i; + opl.raw.last=PIC_Ticks; + opl.raw.start=PIC_Ticks; + /* Check the registers to add */ + for (i=4;i<256;i++) { + if (!opl.raw.regs[0][i]) continue; + if ((i &0xe0)==0xb0) continue; + ADDBUF((Bit8u)i); + ADDBUF(opl.raw.regs[0][i]); + } + bool donesecond=false; + for (i=4;i<256;i++) { + if (!opl.raw.regs[0][i]) continue; + if ((i&0xe0)==0xb0) continue; + if (!donesecond) { + donesecond=true; + ADDBUF(0x3); + } + ADDBUF((Bit8u)i); + ADDBUF(opl.raw.regs[0][i]); + } + if (donesecond) ADDBUF(0x2); + } + /* Check how much time has passed, Allow an extra 5 milliseconds? */ + if (PIC_Ticks>(opl.raw.last+5)) { + Bitu passed=PIC_Ticks-opl.raw.last; + opl.raw.last=PIC_Ticks; + while (passed) { + passed-=1; + if (passed<256) { + ADDBUF(0x00); //8bit delay + ADDBUF((Bit8u)passed); //8bit delay + passed=0; + } else if (passed<0x10000) { + ADDBUF(0x01); //16bit delay + ADDBUF((Bit8u)(passed & 0xff)); //lo-byte + ADDBUF((Bit8u)(passed >> 8)); //hi-byte + passed=0; + } else { + ADDBUF(0x01); //16bit delay + ADDBUF(0xff); //lo-byte + ADDBUF(0xff); //hi-byte + passed-=0xffff; + } + } + } + /* Check if we're still sending to the correct index */ + if (opl.raw.index != index) { + opl.raw.index=index; + ADDBUF(opl.raw.index ? 0x3 : 0x2); + } + ADDBUF(opl.raw.cmd[opl.raw.index]); + ADDBUF(val); + if (opl.raw.used>=RAW_SIZE) OPL_RawEmptyBuffer(); +} + +static void OPL_SaveRawEvent(void) { + /* Check for previously opened wave file */ + if (opl.raw.handle) { + LOG_MSG("Stopping Raw OPL capturing."); + OPL_RawEmptyBuffer(); + /* Fill in the header with useful information */ + host_writed(&dro_header[0x08],opl.raw.last-opl.raw.start); + host_writed(&dro_header[0x0c],opl.raw.done); + switch (opl.mode) { + case OPL_opl2:host_writeb(&dro_header[0x10],0x0);break; + case OPL_opl3:host_writeb(&dro_header[0x10],0x1);break; + case OPL_dualopl2:host_writeb(&dro_header[0x10],0x2);break; + } + fseek(opl.raw.handle,0,0); + fwrite(dro_header,1,sizeof(dro_header),opl.raw.handle); + fclose(opl.raw.handle); + opl.raw.handle=0; + return; + } + opl.raw.handle=OpenCaptureFile("Raw Opl",".dro"); + opl.raw.index=0; + opl.raw.used=0; + opl.raw.done=0; + opl.raw.start=0; + opl.raw.last=0; + memset(opl.raw.buffer,0,sizeof(opl.raw.buffer)); + fwrite(dro_header,1,sizeof(dro_header),opl.raw.handle); +} + +static void OPL_Stop(Section* sec) { + if (opl.raw.handle) OPL_SaveRawEvent(); +} + void OPL_Init(Section* sec,Bitu base,OPL_Mode oplmode,Bitu rate) { Section_prop * section=static_cast(sec); if (OPL2::YM3812Init(2,OPL2_INTERNAL_FREQ,rate)) { @@ -170,9 +308,11 @@ void OPL_Init(Section* sec,Bitu base,OPL_Mode oplmode,Bitu rate) { opl.active=false; opl.last_used=0; opl.mode=oplmode; - + memset(opl.raw.regs,0,sizeof(opl.raw.regs)); opl.chan=MIXER_AddChannel(OPL_CallBack,rate,"FM"); MIXER_SetMode(opl.chan,(opl.mode>OPL_opl2) ? MIXER_16STEREO : MIXER_16MONO); MIXER_Enable(opl.chan,false); + MAPPER_AddHandler(OPL_SaveRawEvent,MK_f7,MMOD1|MMOD2,"caprawopl","Cap OPL"); + sec->AddDestroyFunction(&OPL_Stop); }; diff --git a/src/hardware/mixer.cpp b/src/hardware/mixer.cpp index 421be8d7..d32852df 100644 --- a/src/hardware/mixer.cpp +++ b/src/hardware/mixer.cpp @@ -35,6 +35,7 @@ #include "cross.h" #include "support.h" #include "mapper.h" +#include "hardware.h" #include "programs.h" #define MIXER_MAXCHAN 8 @@ -108,7 +109,6 @@ static struct { Bitu tick_add,tick_remain; struct { FILE * handle; - const char * dir; Bit16s buf[MIXER_WAVESIZE][2]; Bitu used; Bit32u length; @@ -265,9 +265,6 @@ static void MIXER_CallBack(void * userdata, Uint8 *stream, int len) { } static void MIXER_WaveEvent(void) { - Bitu last=0;char file_name[CROSS_LEN]; - DIR * dir;struct dirent * dir_ent; - /* Check for previously opened wave file */ if (mixer.wave.handle) { LOG_MSG("Stopped recording"); @@ -285,34 +282,10 @@ static void MIXER_WaveEvent(void) { mixer.wave.handle=0; return; } - /* Find a filename to open */ - dir=opendir(mixer.wave.dir); - if (!dir) { - LOG_MSG("Can't open waveout dir %s",mixer.wave.dir); - return; - } - while ((dir_ent=readdir(dir))) { - char tempname[CROSS_LEN]; - strcpy(tempname,dir_ent->d_name); - char * test=strstr(tempname,".wav"); - if (!test) continue; - *test=0; - if (strlen(tempname)<5) continue; - if (strncmp(tempname,"wave",4)!=0) continue; - Bitu num=atoi(&tempname[4]); - if (num>=last) last=num+1; - } - closedir(dir); - sprintf(file_name,"%s%cwave%04d.wav",mixer.wave.dir,CROSS_FILESPLIT,last); - /* Open the actual file */ - mixer.wave.handle=fopen(file_name,"wb"); - if (!mixer.wave.handle) { - LOG_MSG("Can't open file %s for waveout",file_name); - return; - } + mixer.wave.handle=OpenCaptureFile("Wave Outut",".wav"); + if (!mixer.wave.handle) return; mixer.wave.length=0; mixer.wave.used=0; - LOG_MSG("Started recording to file %s",file_name); fwrite(wavheader,1,sizeof(wavheader),mixer.wave.handle); } @@ -384,7 +357,6 @@ void MIXER_Init(Section* sec) { mixer.freq=section->Get_int("rate"); mixer.nosound=section->Get_bool("nosound"); mixer.blocksize=section->Get_int("blocksize"); - mixer.wave.dir=section->Get_string("wavedir"); /* Initialize the internal stuff */ mixer.channels=0;