Mercurial > audlegacy
changeset 428:15ca2ea93a30 trunk
[svn] Sync with upstream CVS. This implements RIX playback.
line wrap: on
line diff
--- a/Plugins/Input/adplug/core/Makefile.am Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/Makefile.am Sat Jan 14 07:27:13 2006 -0800 @@ -5,7 +5,8 @@ players.cpp protrack.cpp a2m.cpp adtrack.cpp amd.cpp bam.cpp d00.cpp dfm.cpp dmo.cpp \ hsp.cpp ksm.cpp mad.cpp mid.cpp mkj.cpp cff.cpp dtm.cpp fmc.cpp mtk.cpp rad.cpp raw.cpp \ sa2.cpp s3m.cpp xad.cpp flash.cpp bmf.cpp hybrid.cpp hyp.cpp psi.cpp rat.cpp u6m.cpp \ -rol.cpp xsm.cpp adlibemu.c dro.cpp lds.cpp middata.h +rol.cpp xsm.cpp adlibemu.c dro.cpp lds.cpp mididata.h realopl.cpp analopl.cpp \ +temuopl.cpp msc.cpp rix.cpp # This is a hack. Throughout AdPlug, stricmp() is used to do caseless string # comparations. UNIX libc's don't support stricmp(), but do support the BSD @@ -17,6 +18,7 @@ a2m.h amd.h bam.h d00.h dfm.h hsc.h hsp.h imf.h ksm.h lds.h mid.h mkj.h mtk.h \ protrack.h rad.h raw.h sa2.h sng.h u6m.h player.h fmc.h mad.h xad.h bmf.h \ flash.h hyp.h psi.h rat.h hybrid.h rol.h adtrack.h cff.h dtm.h fprovide.h \ -database.h players.h xsm.h adlibemu.h kemuopl.h dro.h dmo.h s3m.h +database.h players.h xsm.h adlibemu.h kemuopl.h dro.h dmo.h s3m.h realopl.h \ +analopl.h temuopl.h msc.h rix.h INCLUDES = $(BINIO_CFLAGS) -I$(top_builddir)/intl -I$(top_srcdir)
--- a/Plugins/Input/adplug/core/adplug.cpp Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/adplug.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -42,7 +42,7 @@ #include "mid.h" #include "mkj.h" #include "cff.h" -#include "dmo.h" +#include "dmo.h" #include "s3m.h" #include "dtm.h" #include "fmc.h" @@ -61,10 +61,12 @@ #include "rol.h" #include "xsm.h" #include "dro.h" +#include "msc.h" +#include "rix.h" /***** Defines *****/ -#define VERSION "1.5.1" // AdPlug library version string +#define VERSION "1.6" // AdPlug library version string /***** CAdPlug *****/ @@ -104,6 +106,8 @@ CPlayerDesc(CrolPlayer::factory, "Adlib Visual Composer", ".rol\0"), CPlayerDesc(CxsmPlayer::factory, "eXtra Simple Music", ".xsm\0"), CPlayerDesc(CdroPlayer::factory, "DOSBox Raw OPL", ".dro\0"), + CPlayerDesc(CmscPlayer::factory, "Adlib MSC Player", ".msc\0"), + CPlayerDesc(CrixPlayer::factory, "Softstar RIX OPL Music", ".rix\0"), CPlayerDesc() };
--- a/Plugins/Input/adplug/core/analopl.cpp Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/analopl.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,152 +16,52 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * - * analopl.cpp - Spectrum analyzing hardware OPL, by Simon Peter (dn.tlp@gmx.net) + * analopl.cpp - Spectrum analyzing hardware OPL, by Simon Peter <dn.tlp@gmx.net> */ -#include <conio.h> #include "analopl.h" -#ifdef _MSC_VER - #define INP _inp - #define OUTP _outp -#elif defined(__WATCOMC__) - #define INP inp - #define OUTP outp -#endif - -#define SHORTDELAY 6 // short delay in I/O port-reads after OPL hardware output -#define LONGDELAY 35 // long delay in I/O port-reads after OPL hardware output - -// the 9 operators as expected by the OPL2 -static const unsigned char op_table[9] = {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12}; - -CAnalopl::CAnalopl(unsigned short initport): adlport(initport), hardvol(0), bequiet(false), nowrite(false) -{ - int i; - - for(i=0;i<22;i++) { - hardvols[i][0] = 0; - hardvols[i][1] = 0; - } - for(i=0;i<9;i++) { - keyregs[i][0] = 0; - keyregs[i][1] = 0; - } -} - -bool CAnalopl::detect() +CAnalopl::CAnalopl(unsigned short initport) + : CRealopl(initport) { - unsigned char stat1,stat2,i; - - hardwrite(4,0x60); hardwrite(4,0x80); - stat1 = INP(adlport); - hardwrite(2,0xff); hardwrite(4,0x21); - for(i=0;i<80;i++) // wait for adlib - INP(adlport); - stat2 = INP(adlport); - hardwrite(4,0x60); hardwrite(4,0x80); - - if(((stat1 & 0xe0) == 0) && ((stat2 & 0xe0) == 0xc0)) - return true; - else - return false; -} - -void CAnalopl::setvolume(int volume) -{ - int i; - - hardvol = volume; - for(i=0;i<9;i++) { - hardwrite(0x43+op_table[i],((hardvols[op_table[i]+3][0] & 63) + volume) > 63 ? 63 : hardvols[op_table[i]+3][0] + volume); - if(hardvols[i][1] & 1) // modulator too? - hardwrite(0x40+op_table[i],((hardvols[op_table[i]][0] & 63) + volume) > 63 ? 63 : hardvols[op_table[i]][0] + volume); - } -} - -void CAnalopl::setquiet(bool quiet) -{ - bequiet = quiet; - - if(quiet) { - oldvol = hardvol; - setvolume(63); - } else - setvolume(oldvol); -} - -void CAnalopl::hardwrite(int reg, int val) -{ - int i; - - OUTP(adlport,reg); // set register - for(i=0;i<SHORTDELAY;i++) // wait for adlib - INP(adlport); - OUTP(adlport+1,val); // set value - for(i=0;i<LONGDELAY;i++) // wait for adlib - INP(adlport); + for(int i = 0; i < 9; i++) { + keyregs[0][i][0] = 0; + keyregs[0][i][1] = 0; + keyregs[1][i][0] = 0; + keyregs[1][i][1] = 0; + } } void CAnalopl::write(int reg, int val) { - int i; - - if(nowrite) - return; + if(nowrite) return; - if(reg >= 0xb0 && reg <= 0xb8) { - if(!keyregs[reg - 0xb0][0] && (val & 32)) - keyregs[reg - 0xb0][1] = 1; - else - keyregs[reg - 0xb0][1] = 0; - keyregs[reg - 0xb0][0] = val & 32; - if(bequiet) // filter all key-on commands - val &= ~32; - } - if(reg >= 0x40 && reg <= 0x55) // cache volumes - hardvols[reg-0x40][0] = val; - if(reg >= 0xc0 && reg <= 0xc8) - hardvols[reg-0xc0][1] = val; - if(hardvol) // reduce volume - for(i=0;i<9;i++) { - if(reg == 0x43 + op_table[i]) - val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol; - else - if((reg == 0x40 + op_table[i]) && (hardvols[i][1] & 1)) - val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol; - } + if(reg >= 0xb0 && reg <= 0xb8) { + if(!keyregs[currChip][reg - 0xb0][0] && (val & 32)) + keyregs[currChip][reg - 0xb0][1] = 1; + else + keyregs[currChip][reg - 0xb0][1] = 0; + keyregs[currChip][reg - 0xb0][0] = val & 32; + } - hardwrite(reg,val); + CRealopl::write(reg, val); } -void CAnalopl::init() +int CAnalopl::getcarriervol(unsigned int v, unsigned int c) { - int i; - - for (i=0;i<9;i++) { // stop instruments - hardwrite(0xb0 + i,0); // key off - hardwrite(0x80 + op_table[i],0xff); // fastest release - } - hardwrite(0xbd,0); // clear misc. register + return (hardvols[c][op_table[v]+3][0] & 63); } -int CAnalopl::getcarriervol(unsigned int v) +int CAnalopl::getmodulatorvol(unsigned int v, unsigned int c) { - return (hardvols[op_table[v]+3][0] & 63); + return (hardvols[c][op_table[v]][0] & 63); } -int CAnalopl::getmodulatorvol(unsigned int v) -{ - return (hardvols[op_table[v]][0] & 63); -} - -bool CAnalopl::getkeyon(unsigned int v) +bool CAnalopl::getkeyon(unsigned int v, unsigned int c) { - if(keyregs[v][1]) { - keyregs[v][1] = 0; - return true; - } else - return false; + if(keyregs[c][v][1]) { + keyregs[c][v][1] = 0; + return true; + } else + return false; }
--- a/Plugins/Input/adplug/core/analopl.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/analopl.h Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,49 +16,29 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * - * analopl.h - Spectrum analyzing hardware OPL, by Simon Peter (dn.tlp@gmx.net) + * analopl.h - Spectrum analyzing hardware OPL, by Simon Peter <dn.tlp@gmx.net> */ -#ifndef H_ANALOPL_DEFINED -#define H_ANALOPL_DEFINED +#ifndef H_ADPLUG_ANALOPL +#define H_ADPLUG_ANALOPL -#include "opl.h" +#include "realopl.h" -#define DFL_ADLIBPORT 0x388 // default adlib baseport - -class CAnalopl: public Copl +class CAnalopl: public CRealopl { -public: - CAnalopl(unsigned short initport = DFL_ADLIBPORT); // initport = OPL2 hardware baseport - - bool detect(); // returns true if adlib compatible board is found, else false - void setvolume(int volume); // set adlib master volume (0 - 63) 0 = loudest, 63 = softest - void setquiet(bool quiet = true); // sets the OPL2 quiet, while still writing to the registers - void setport(unsigned short port) // set new OPL2 hardware baseport - { adlport = port; }; - void setnowrite(bool nw = true) // set hardware write status - { nowrite = nw; }; + public: + CAnalopl(unsigned short initport = DFL_ADLIBPORT); // initport = OPL2 hardware baseport - int getvolume() // get adlib master volume - { return hardvol; }; - int getcarriervol(unsigned int v); // get carrier volume of adlib voice v - int getmodulatorvol(unsigned int v); // get modulator volume of adlib voice v - bool getkeyon(unsigned int v); - - // template methods - void write(int reg, int val); - void init(); + // get carrier volume of adlib voice v on chip c + int getcarriervol(unsigned int v, unsigned int c = 0); + // get modulator volume of adlib voice v on chip c + int getmodulatorvol(unsigned int v, unsigned int c = 0); + bool getkeyon(unsigned int v, unsigned int c = 0); -private: - void hardwrite(int reg, int val); // write to OPL2 hardware registers + void write(int reg, int val); - unsigned short adlport; // adlib hardware baseport - int hardvol,oldvol; // hardware master volume - bool bequiet; // quiet status cache - char hardvols[22][2]; // volume cache - unsigned char keyregs[9][2]; // shadow key register - bool nowrite; // don't write to hardware, if true + protected: + unsigned char keyregs[2][9][2]; // shadow key register }; #endif
--- a/Plugins/Input/adplug/core/diskopl.cpp Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/diskopl.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,63 +16,75 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * * diskopl.cpp - Disk Writer OPL, by Simon Peter <dn.tlp@gmx.net> */ #include "diskopl.h" -static const unsigned short note_table[12] = {363,385,408,432,458,485,514,544,577,611,647,686}; -static const unsigned char op_table[9] = {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12}; +//static const unsigned short note_table[12] = {363,385,408,432,458,485,514,544,577,611,647,686}; +const unsigned char CDiskopl::op_table[9] = {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12}; -CDiskopl::CDiskopl(std::string filename): old_freq(0.0f), del(1), nowrite(false) +CDiskopl::CDiskopl(std::string filename) + : old_freq(0.0f), del(1), nowrite(false) { - unsigned short clock = 0xffff; - f = fopen(filename.c_str(),"wb"); - fwrite("RAWADATA",8,1,f); - fwrite(&clock,sizeof(clock),1,f); + unsigned short clock = 0xffff; + + currType = TYPE_OPL3; + f = fopen(filename.c_str(),"wb"); + fwrite("RAWADATA",8,1,f); + fwrite(&clock,sizeof(clock),1,f); } CDiskopl::~CDiskopl() { - fclose(f); + fclose(f); } void CDiskopl::update(CPlayer *p) { - unsigned short clock; - unsigned int wait; + unsigned short clock; + unsigned int wait; - if(p->getrefresh() != old_freq) { - old_freq = p->getrefresh(); - del = wait = (unsigned int)(18.2f / old_freq); - clock = (unsigned short)(1192737/(old_freq*(wait+1))); - fputc(0,f); fputc(2,f); - fwrite(&clock,2,1,f); - } - if(!nowrite) { - fputc(del+1,f); - fputc(0,f); - } + if(p->getrefresh() != old_freq) { + old_freq = p->getrefresh(); + del = wait = (unsigned int)(18.2f / old_freq); + clock = (unsigned short)(1192737/(old_freq*(wait+1))); + fputc(0,f); fputc(2,f); + fwrite(&clock,2,1,f); + } + if(!nowrite) { + fputc(del+1,f); + fputc(0,f); + } +} + +void CDiskopl::setchip(int n) +{ + Copl::setchip(n); + + if(!nowrite) { + fputc(currChip + 1, f); + fputc(2, f); + } } void CDiskopl::write(int reg, int val) { - if(!nowrite) - diskwrite(reg,val); + if(!nowrite) + diskwrite(reg,val); } void CDiskopl::init() { - for (int i=0;i<9;i++) { // stop instruments - diskwrite(0xb0 + i,0); // key off - diskwrite(0x80 + op_table[i],0xff); // fastest release - } - diskwrite(0xbd,0); // clear misc. register + for (int i=0;i<9;i++) { // stop instruments + diskwrite(0xb0 + i,0); // key off + diskwrite(0x80 + op_table[i],0xff); // fastest release + } + diskwrite(0xbd,0); // clear misc. register } void CDiskopl::diskwrite(int reg, int val) { - fputc(val,f); - fputc(reg,f); + fputc(val,f); + fputc(reg,f); }
--- a/Plugins/Input/adplug/core/diskopl.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/diskopl.h Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,7 +16,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * * diskopl.h - Disk Writer OPL, by Simon Peter <dn.tlp@gmx.net> */ @@ -27,23 +26,27 @@ class CDiskopl: public Copl { -public: - CDiskopl(std::string filename); - virtual ~CDiskopl(); + public: + CDiskopl(std::string filename); + virtual ~CDiskopl(); - void update(CPlayer *p); // write to file - void setnowrite(bool nw = true) // set file write status - { nowrite = nw; }; + void update(CPlayer *p); // write to file + void setnowrite(bool nw = true) // set file write status + { nowrite = nw; }; + + void setchip(int n); - // template methods - void write(int reg, int val); - void init(); + // template methods + void write(int reg, int val); + void init(); + + private: + static const unsigned char op_table[9]; -private: - void diskwrite(int reg, int val); + FILE *f; + float old_freq; + unsigned char del; + bool nowrite; // don't write to file, if true - FILE *f; - float old_freq; - unsigned char del; - bool nowrite; // don't write to file, if true + void diskwrite(int reg, int val); };
--- a/Plugins/Input/adplug/core/dro.cpp Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/dro.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,9 +18,12 @@ * * dro.c - DOSBox Raw OPL Player by Sjoerd van der Berg <harekiet@zophar.net> * - * NOTES: - * OPL3 and second opl2 writes are ignored - */ + * upgraded by matthew gambrell <zeromus@zeromus.org> + * + * NOTES: 3-oct-04: the DRO format is not yet finalized. beware. + */ + +#include <stdio.h> #include "dro.h" @@ -31,69 +34,96 @@ return new CdroPlayer(newopl); } +CdroPlayer::CdroPlayer(Copl *newopl) + : CPlayer(newopl), data(0) +{ + if(opl->gettype() == Copl::TYPE_OPL2) + opl3_mode = 0; + else + opl3_mode = 1; +} + bool CdroPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open(filename); if(!f) return false; - char id[8];unsigned long i; + binistream *f = fp.open(filename); if(!f) return false; + char id[8]; + unsigned long i; - // file validation section - f->readString(id, 8); - if(strncmp(id,"DBRAWOPL",8)) { fp.close (f); return false; } + // file validation section + f->readString(id, 8); + if(strncmp(id,"DBRAWOPL",8)) { fp.close (f); return false; } + int version = f->readInt(4); // not very useful just yet + if(version != 0x10000) { fp.close(f); return false; } - // load section - mstotal = f->readInt(4); // Total milliseconds in file - length = f->readInt(4); // Total data bytes in file - mode = (OplMode)f->readInt(1); // Type of opl data this can contain - data = new unsigned char [length]; - for (i=0;i<length;i++) - data[i]=f->readInt(1); - fp.close(f); - rewind(0); - return true; + // load section + mstotal = f->readInt(4); // Total milliseconds in file + length = f->readInt(4); // Total data bytes in file + f->ignore(1); // Type of opl data this can contain - ignored + data = new unsigned char [length]; + for (i=0;i<length;i++) + data[i]=f->readInt(1); + fp.close(f); + rewind(0); + return true; } bool CdroPlayer::update() { - if (delay>500) { - delay-=500; - return true; - } else delay=0; - while (pos < length) - { - unsigned char cmd = data[pos++]; - switch(cmd) { - case 0: - delay = 1 + data[pos++]; - return true; - case 1: - delay = 1 + data[pos] + (data[pos+1]<<8); - pos+=2; - return true; - case 2: - index = 0; - break; - case 3: - index = 0; - break; - default: - if(!index) - opl->write(cmd,data[pos++]); - break; - } - } - return pos<length; + if (delay>500) { + delay-=500; + return true; + } else + delay=0; + + while (pos < length) { + unsigned char cmd = data[pos++]; + switch(cmd) { + case 0: + delay = 1 + data[pos++]; + return true; + case 1: + delay = 1 + data[pos] + (data[pos+1]<<8); + pos+=2; + return true; + case 2: + index = 0; + opl->setchip(0); + break; + case 3: + index = 1; + opl->setchip(1); + break; + default: + if(cmd==4) cmd = data[pos++]; //data override + if(index == 0 || opl3_mode) + opl->write(cmd,data[pos++]); + break; + } + } + + return pos<length; } void CdroPlayer::rewind(int subsong) { - delay=1; - pos = index = 0; - opl->init(); - opl->write(1,32); // go to OPL2 mode + delay=1; + pos = index = 0; + opl->init(); + + //dro assumes all registers are initialized to 0 + //registers not initialized to 0 will be corrected + //in the data stream + for(int i=0;i<256;i++) + opl->write(i,0); + + opl->setchip(1); + for(int i=0;i<256;i++) + opl->write(i,0); + opl->setchip(0); } float CdroPlayer::getrefresh() { - if (delay > 500) return 1000 / 500; - else return 1000 / (double)delay; + if (delay > 500) return 1000 / 500; + else return 1000 / (double)delay; }
--- a/Plugins/Input/adplug/core/dro.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/dro.h Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,30 +23,30 @@ class CdroPlayer: public CPlayer { -public: + public: static CPlayer *factory(Copl *newopl); - CdroPlayer(Copl *newopl) - : CPlayer(newopl), data(0) - { }; - ~CdroPlayer() - { if(data) delete [] data; }; + CdroPlayer(Copl *newopl); + ~CdroPlayer() + { + if(data) + delete [] data; + } - bool load(const std::string &filename, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh(); - std::string gettype() - { return std::string("DOSBox Raw OPL"); }; + std::string gettype() + { + return std::string("DOSBox Raw OPL"); + } -protected: - unsigned char *data; - unsigned long pos,length; - unsigned long msdone,mstotal; - unsigned short delay; - unsigned char index; - enum OplMode { - ModeOPL2,ModeOPL3,ModeDUALOPL2 - } mode; + protected: + unsigned char *data; + unsigned long pos,length; + unsigned long msdone,mstotal; + unsigned short delay; + unsigned char index, opl3_mode; };
--- a/Plugins/Input/adplug/core/emuopl.cpp Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/emuopl.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * AdPlug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2002 Simon Peter <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,54 +22,126 @@ #include "emuopl.h" CEmuopl::CEmuopl(int rate, bool bit16, bool usestereo) - : use16bit(bit16), stereo(usestereo) + : use16bit(bit16), stereo(usestereo), mixbufSamples(0) { - opl = OPLCreate(OPL_TYPE_YM3812, 3579545, rate); + opl[0] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate); + opl[1] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate); + + currType = TYPE_DUAL_OPL2; + + init(); } CEmuopl::~CEmuopl() { - OPLDestroy(opl); + OPLDestroy(opl[0]); OPLDestroy(opl[1]); + + if(mixbufSamples) { + delete [] mixbuf0; + delete [] mixbuf1; + } } void CEmuopl::update(short *buf, int samples) { - int i; + int i; - if(use16bit) { - YM3812UpdateOne(opl,buf,samples); + //ensure that our mix buffers are adequately sized + if(mixbufSamples < samples) { + if(mixbufSamples) { delete[] mixbuf0; delete[] mixbuf1; } + mixbufSamples = samples; + + //*2 = make room for stereo, if we need it + mixbuf0 = new short[samples*2]; + mixbuf1 = new short[samples*2]; + } - if(stereo) - for(i=samples-1;i>=0;i--) { - buf[i*2] = buf[i]; - buf[i*2+1] = buf[i]; - } - } else { - short *tempbuf = new short[stereo ? samples*2 : samples]; - int i; + //data should be rendered to outbuf + //tempbuf should be used as a temporary buffer + //if we are supposed to generate 16bit output, + //then outbuf may point directly to the actual waveform output "buf" + //if we are supposed to generate 8bit output, + //then outbuf cannot point to "buf" (because there will not be enough room) + //and so it must point to a mixbuf instead-- + //it will be reduced to 8bit and put in "buf" later + short *outbuf; + short *tempbuf=mixbuf0; + short *tempbuf2=mixbuf1; + if(use16bit) outbuf = buf; + else outbuf = mixbuf1; + //...there is a potentially confusing situation where mixbuf1 can be aliased. + //beware. it is a little loony. + + //all of the following rendering code produces 16bit output + + switch(currType) { + case TYPE_OPL2: + //for opl2 mode: + //render chip0 to the output buffer + YM3812UpdateOne(opl[0],outbuf,samples); - YM3812UpdateOne(opl,tempbuf,samples); + //if we are supposed to output stereo, + //then we need to dup the mono channel + if(stereo) + for(i=samples-1;i>=0;i--) { + outbuf[i*2] = outbuf[i]; + outbuf[i*2+1] = outbuf[i]; + } + break; + + case TYPE_OPL3: // unsupported + break; + + case TYPE_DUAL_OPL2: + //for dual opl2 mode: + //render each chip to a different tempbuffer + YM3812UpdateOne(opl[0],tempbuf2,samples); + YM3812UpdateOne(opl[1],tempbuf,samples); - if(stereo) - for(i=samples-1;i>=0;i--) { - tempbuf[i*2] = tempbuf[i]; - tempbuf[i*2+1] = tempbuf[i]; - } + //output stereo: + //then we need to interleave the two buffers + if(stereo){ + //first, spread tempbuf's samples across left channel + //left channel + for(i=0;i<samples;i++) + outbuf[i*2] = tempbuf2[i]; + //next, insert the samples from tempbuf2 into right channel + for(i=0;i<samples;i++) + outbuf[i*2+1] = tempbuf[i]; + } else + //output mono: + //then we need to mix the two buffers into buf + for(i=0;i<samples;i++) + outbuf[i] = (tempbuf[i]>>1) + (tempbuf2[i]>>1); + break; + } - for(i=0;i<(stereo ? samples*2 : samples);i++) - ((char *)buf)[i] = (tempbuf[i] >> 8) ^ 0x80; - - delete [] tempbuf; - } + //now reduce to 8bit if we need to + if(!use16bit) + for(i=0;i<(stereo ? samples*2 : samples);i++) + ((char *)buf)[i] = (outbuf[i] >> 8) ^ 0x80; } void CEmuopl::write(int reg, int val) { - OPLWrite(opl,0,reg); - OPLWrite(opl,1,val); + switch(currType){ + case TYPE_OPL2: + case TYPE_DUAL_OPL2: + OPLWrite(opl[currChip], 0, reg); + OPLWrite(opl[currChip], 1, val); + break; + case TYPE_OPL3: // unsupported + break; + } } void CEmuopl::init() { - OPLResetChip(opl); + OPLResetChip(opl[0]); OPLResetChip(opl[1]); + currChip = 0; } + +void CEmuopl::settype(ChipType type) +{ + currType = type; +}
--- a/Plugins/Input/adplug/core/emuopl.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/emuopl.h Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,19 +29,21 @@ class CEmuopl: public Copl { -public: - CEmuopl(int rate, bool bit16, bool usestereo); // rate = sample rate - virtual ~CEmuopl(); + public: + CEmuopl(int rate, bool bit16, bool usestereo); // rate = sample rate + virtual ~CEmuopl(); - void update(short *buf, int samples); // fill buffer + void update(short *buf, int samples); // fill buffer + void write(int reg, int val); - // template methods - void write(int reg, int val); - void init(); + void init(); + void settype(ChipType type); -private: - bool use16bit,stereo; - FM_OPL *opl; // holds emulator data + private: + bool use16bit, stereo; + FM_OPL *opl[2]; // OPL2 emulator data + short *mixbuf0, *mixbuf1; + int mixbufSamples; }; #endif
--- a/Plugins/Input/adplug/core/hybrid.cpp Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/hybrid.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -132,8 +132,9 @@ // process channels for(i=0;i<9;i++) { + unsigned char *pos = &tune[0xADE + (hyb.order[hyb.order_pos*9 + i] * 64 * 2) + (patpos * 2)]; // read event - unsigned short event = *(unsigned short *)&tune[0xADE + (hyb.order[hyb.order_pos*9 + i] * 64 * 2) + (patpos * 2)]; + unsigned short event = (pos[1] << 8) + pos[0]; #ifdef DEBUG AdPlug_LogWrite("track %02X, channel %02X, event %04X:\n", hyb.order[hyb.order_pos*9 + i], i, event );
--- a/Plugins/Input/adplug/core/imf.cpp Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/imf.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -90,7 +90,7 @@ f->seek(-4, binio::Add); else f->seek(-2, binio::Add); - size = flsize / 4; + size = (flsize - mfsize) / 4; } else // file has got a footer size = fsize / 4; @@ -101,13 +101,20 @@ } // read footer, if any - if(fsize && (fsize < flsize - 2 - mfsize)) { - unsigned long footerlen = flsize - fsize - 2 - mfsize; + if(fsize && (fsize < flsize - 2 - mfsize)) + if(f->readInt(1) == 0x1a) { + // Adam Nielsen's footer format + track_name = f->readString(); + author_name = f->readString(); + remarks = f->readString(); + } else { + // Generic footer + unsigned long footerlen = flsize - fsize - 2 - mfsize; - footer = new char[footerlen + 1]; - f->readString(footer, footerlen); - footer[footerlen] = '\0'; // Make ASCIIZ string - } + footer = new char[footerlen + 1]; + f->readString(footer, footerlen); + footer[footerlen] = '\0'; // Make ASCIIZ string + } rate = getrate(f); fp.close(f); @@ -152,6 +159,21 @@ return title; } +std::string CimfPlayer::getdesc() +{ + std::string desc; + + if(footer) + desc = std::string(footer); + + if(!remarks.empty() && footer) + desc += "\n\n"; + + desc += remarks; + + return desc; +} + /*** private methods *************************************/ float CimfPlayer::getrate(binistream *f)
--- a/Plugins/Input/adplug/core/imf.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/imf.h Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,29 +31,30 @@ CimfPlayer(Copl *newopl) : CPlayer(newopl), footer(0), data(0) - { } + { } ~CimfPlayer() - { if(data) delete [] data; if(footer) delete [] footer; }; + { if(data) delete [] data; if(footer) delete [] footer; }; bool load(const std::string &filename, const CFileProvider &fp); bool update(); void rewind(int subsong); float getrefresh() - { return timer; }; + { return timer; }; std::string gettype() - { return std::string("IMF File Format"); } + { return std::string("IMF File Format"); } std::string gettitle(); - std::string getdesc() - { if(footer) return std::string(footer); else return std::string(); } + std::string getauthor() + { return author_name; } + std::string getdesc(); protected: - unsigned long pos,size; + unsigned long pos, size; unsigned short del; bool songend; - float rate,timer; + float rate, timer; char *footer; - std::string track_name, game_name; + std::string track_name, game_name, author_name, remarks; struct Sdata { unsigned char reg, val;
--- a/Plugins/Input/adplug/core/kemuopl.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/kemuopl.h Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,6 +35,7 @@ : use16bit(bit16), stereo(usestereo) { adlibinit(rate, usestereo ? 2 : 1, bit16 ? 2 : 1); + currType = TYPE_OPL2; }; void update(short *buf, int samples) @@ -47,7 +48,8 @@ // template methods void write(int reg, int val) { - adlib0(reg, val); + if(currChip == 0) + adlib0(reg, val); }; void init() {};
--- a/Plugins/Input/adplug/core/mid.cpp Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/mid.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * - * MIDI & MIDI-like file player - Last Update: 8/16/2000 + * MIDI & MIDI-like file player - Last Update: 10/15/2005 * by Phil Hassey - www.imitationpickles.org * philhassey@hotmail.com * @@ -57,9 +57,12 @@ * I think some of them are supposed to be * played at the same time, but I'm not sure * when. - * 8/16/200: + * 8/16/2000: * Status: LAA: now EGA and VGA lucas games work pretty well * + * 10/15/2005: Changes by Simon Peter + * Added rhythm mode support for CMF format. + * * Other acknowledgements: * Allegro - for the midi instruments and the midi volume table * SCUMM Revisited - for getting the .LAA / .MIDs out of those @@ -75,15 +78,59 @@ #include "mid.h" #include "mididata.h" +/*#define TESTING*/ +#ifdef TESTING +#define midiprintf printf +#else void CmidPlayer::midiprintf(char *format, ...) { } +#endif + +#define LUCAS_STYLE 1 +#define CMF_STYLE 2 +#define MIDI_STYLE 4 +#define SIERRA_STYLE 8 + +// AdLib melodic and rhythm mode defines +#define ADLIB_MELODIC 0 +#define ADLIB_RYTHM 1 + +// File types +#define FILE_LUCAS 1 +#define FILE_MIDI 2 +#define FILE_CMF 3 +#define FILE_SIERRA 4 +#define FILE_ADVSIERRA 5 +#define FILE_OLDLUCAS 6 + +// AdLib standard operator table +const unsigned char CmidPlayer::adlib_opadd[] = {0x00 ,0x01 ,0x02 ,0x08 ,0x09 ,0x0A ,0x10 ,0x11 ,0x12}; + +// dunno +const int CmidPlayer::ops[] = {0x20,0x20,0x40,0x40,0x60,0x60,0x80,0x80,0xe0,0xe0,0xc0}; + +// map CMF drum channels 12 - 15 to corresponding AdLib drum operators +// bass drum (channel 11) not mapped, cause it's handled like a normal instrument +const int CmidPlayer::map_chan[] = { 0x14, 0x12, 0x15, 0x11 }; + +// Standard AdLib frequency table +const int CmidPlayer::fnums[] = { 0x16b,0x181,0x198,0x1b0,0x1ca,0x1e5,0x202,0x220,0x241,0x263,0x287,0x2ae }; + +// Map CMF drum channels 11 - 15 to corresponding AdLib drum channels +const int CmidPlayer::percussion_map[] = { 6, 7, 8, 8, 7 }; CPlayer *CmidPlayer::factory(Copl *newopl) { return new CmidPlayer(newopl); } +CmidPlayer::CmidPlayer(Copl *newopl) + : CPlayer(newopl), author(&emptystr), title(&emptystr), remarks(&emptystr), + emptystr('\0'), flen(0), data(0) +{ +} + unsigned char CmidPlayer::datalook(long pos) { if (pos<0 || pos >= flen) return(0); @@ -130,14 +177,6 @@ return(v); } -#define LUCAS_STYLE 1 -#define CMF_STYLE 2 -#define MIDI_STYLE 4 -#define SIERRA_STYLE 8 - -#define ADLIB_MELODIC 0 -#define ADLIB_RYTHM 1 - bool CmidPlayer::load_sierra_ins(const std::string &fname, const CFileProvider &fp) { long i,j,k,l; @@ -241,13 +280,6 @@ doing=1; } -#define FILE_LUCAS 1 -#define FILE_MIDI 2 -#define FILE_CMF 3 -#define FILE_SIERRA 4 -#define FILE_ADVSIERRA 5 -#define FILE_OLDLUCAS 6 - bool CmidPlayer::load(const std::string &filename, const CFileProvider &fp) { binistream *f = fp.open(filename); if(!f) return false; @@ -297,13 +329,10 @@ void CmidPlayer::midi_write_adlib(unsigned int r, unsigned char v) { - opl->write(r,v); - adlib_data[r]=v; + opl->write(r,v); + adlib_data[r]=v; } -unsigned char adlib_opadd[] = {0x00 ,0x01 ,0x02 ,0x08 ,0x09 ,0x0A ,0x10 ,0x11 ,0x12}; -int ops[] = {0x20,0x20,0x40,0x40,0x60,0x60,0x80,0x80,0xe0,0xe0,0xc0}; - void CmidPlayer::midi_fm_instrument(int voice, unsigned char *inst) { if ((adlib_style&SIERRA_STYLE)!=0) @@ -350,6 +379,18 @@ midi_write_adlib(0xc0+voice,inst[10]); } +void CmidPlayer::midi_fm_percussion(int ch, unsigned char *inst) +{ + int opadd = map_chan[ch - 12]; + + midi_write_adlib(0x20 + opadd, inst[0]); + midi_write_adlib(0x40 + opadd, inst[2]); + midi_write_adlib(0x60 + opadd, inst[4]); + midi_write_adlib(0x80 + opadd, inst[6]); + midi_write_adlib(0xe0 + opadd, inst[8]); + midi_write_adlib(0xc0 + opadd, inst[10]); +} + void CmidPlayer::midi_fm_volume(int voice, int volume) { int vol; @@ -361,8 +402,7 @@ if ((adlib_style&LUCAS_STYLE)!=0) { if ((adlib_data[0xc0+voice]&1)==1) - midi_write_adlib(0x40+adlib_opadd[voice], (unsigned -char)((63-vol) | + midi_write_adlib(0x40+adlib_opadd[voice], (unsigned char)((63-vol) | (adlib_data[0x40+adlib_opadd[voice]]&0xc0))); midi_write_adlib(0x43+adlib_opadd[voice], (unsigned char)((63-vol) | (adlib_data[0x43+adlib_opadd[voice]]&0xc0))); @@ -370,8 +410,7 @@ else { if ((adlib_data[0xc0+voice]&1)==1) - midi_write_adlib(0x40+adlib_opadd[voice], (unsigned -char)((63-vol) | + midi_write_adlib(0x40+adlib_opadd[voice], (unsigned char)((63-vol) | (adlib_data[0x40+adlib_opadd[voice]]&0xc0))); midi_write_adlib(0x43+adlib_opadd[voice], (unsigned char)((63-vol) | (adlib_data[0x43+adlib_opadd[voice]]&0xc0))); @@ -379,11 +418,6 @@ } } - -int fnums[] = { -0x16b,0x181,0x198,0x1b0,0x1ca,0x1e5,0x202,0x220,0x241,0x263,0x287,0x2ae - }; - void CmidPlayer::midi_fm_playnote(int voice, int note, int volume) { int freq=fnums[note%12]; @@ -393,7 +427,7 @@ midi_fm_volume(voice,volume); midi_write_adlib(0xa0+voice,(unsigned char)(freq&0xff)); - c=((freq&0x300) >> 8)+(oct<<2) + (1<<5); + c=((freq&0x300) >> 8)+(oct<<2) + (adlib_mode == ADLIB_MELODIC || voice < 6 ? (1<<5) : 0); midi_write_adlib(0xb0+voice,(unsigned char)c); } @@ -408,6 +442,9 @@ void CmidPlayer::midi_fm_reset() { int i; + + opl->init(); + for (i=0; i<256; i++) midi_write_adlib(i,0); @@ -419,7 +456,7 @@ { long w,v,note,vel,ctrl,nv,x,l,lnum; int i=0,j,c; - int on,onl; + int on,onl,numchan; unsigned char ins[11]; int ret; @@ -473,44 +510,42 @@ // doing=0; note=getnext(1); vel=getnext(1); + if(adlib_mode == ADLIB_RYTHM) + numchan = 6; + else + numchan = 9; + if (ch[c].on!=0) { - for (i=0; i<9; i++) + for (i=0; i<18; i++) chp[i][2]++; - j=0; - on=-1;onl=0; - for (i=0; i<9; i++) - if (chp[i][0]==-1 && chp[i][2]>onl) - { onl=chp[i][2]; on=i; j=1; } + if(c < 11 || adlib_mode == ADLIB_MELODIC) { + j=0; + on=-1;onl=0; + for (i=0; i<numchan; i++) + if (chp[i][0]==-1 && chp[i][2]>onl) + { onl=chp[i][2]; on=i; j=1; } - if (on==-1) - { - onl=0; - for (i=0; i<9; i++) - if (chp[i][2]>onl) - { onl=chp[i][2]; on=i; } - } + if (on==-1) + { + onl=0; + for (i=0; i<numchan; i++) + if (chp[i][2]>onl) + { onl=chp[i][2]; on=i; } + } - if (j==0) - midi_fm_endnote(on); + if (j==0) + midi_fm_endnote(on); + } else + on = percussion_map[c - 11]; if (vel!=0 && ch[c].inum>=0 && ch[c].inum<128) { if (adlib_mode == ADLIB_MELODIC || c < 12) - midi_fm_instrument(on,ch[c].ins); - else - { - //the following fails to be effective - //at doing rythm sounds .. (cmf blah) - ins[0]=ins[1]=ch[c].ins[0]; - ins[2]=ins[3]=ch[c].ins[2]; - ins[4]=ins[5]=ch[c].ins[4]; - ins[6]=ins[7]=ch[c].ins[6]; - ins[8]=ins[9]=ch[c].ins[8]; - ins[10]=ch[c].ins[10]|1; - midi_fm_instrument(on,ins); - } + midi_fm_instrument(on,ch[c].ins); + else + midi_fm_percussion(c, ch[c].ins); if ((adlib_style&MIDI_STYLE)!=0) { @@ -527,10 +562,16 @@ nv=vel; } - midi_fm_playnote(on,note+ch[c].nshift,nv*2); + midi_fm_playnote(on,note+ch[c].nshift,nv*2); chp[on][0]=c; chp[on][1]=note; chp[on][2]=0; + + if(adlib_mode == ADLIB_RYTHM && c >= 11) { + midi_write_adlib(0xbd, adlib_data[0xbd] & ~(0x10 >> (c - 11))); + midi_write_adlib(0xbd, adlib_data[0xbd] | (0x10 >> (c - 11))); + } + } else { @@ -576,17 +617,22 @@ break; case 0x67: midiprintf ("\n\nhere:%d\n\n",vel); - if ((adlib_style&CMF_STYLE)!=0) - adlib_mode=vel; // this gets faked - no mode change + if ((adlib_style&CMF_STYLE)!=0) { + adlib_mode=vel; + if(adlib_mode == ADLIB_RYTHM) + midi_write_adlib(0xbd, adlib_data[0xbd] | (1 << 5)); + else + midi_write_adlib(0xbd, adlib_data[0xbd] & ~(1 << 5)); + } break; } break; case 0xc0: /*patch change*/ - x=getnext(1); - ch[c].inum=x; - for (j=0; j<11; j++) - ch[c].ins[j]=myinsbank[ch[c].inum][j]; - break; + x=getnext(1); + ch[c].inum=x; + for (j=0; j<11; j++) + ch[c].ins[j]=myinsbank[ch[c].inum][j]; + break; case 0xd0: /*chanel touch*/ x=getnext(1); break; @@ -599,11 +645,11 @@ { case 0xf0: case 0xf7: /*sysex*/ - l=getval(); - if (datalook(pos+l)==0xf7) - i=1; - midiprintf("{%d}",l); - midiprintf("\n"); + l=getval(); + if (datalook(pos+l)==0xf7) + i=1; + midiprintf("{%d}",l); + midiprintf("\n"); if (datalook(pos)==0x7d && datalook(pos+1)==0x10 && @@ -1019,7 +1065,7 @@ } doing=1; - opl->init(); + midi_fm_reset(); } std::string CmidPlayer::gettype()
--- a/Plugins/Input/adplug/core/mid.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/mid.h Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,86 +26,87 @@ public: static CPlayer *factory(Copl *newopl); - CmidPlayer(Copl *newopl) - : CPlayer(newopl), author(&emptystr), title(&emptystr), - remarks(&emptystr), emptystr('\0'), flen(0), data(0) - { }; - ~CmidPlayer() - { if(data) delete [] data; }; + CmidPlayer(Copl *newopl); + ~CmidPlayer() + { if(data) delete [] data; } + + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh(); - bool load(const std::string &filename, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh(); + std::string gettype(); + std::string gettitle() + { return std::string(title); } + std::string getauthor() + { return std::string(author); } + std::string getdesc() + { return std::string(remarks); } + unsigned int getinstruments() + { return tins; } + unsigned int getsubsongs() + { return subsongs; } - std::string gettype(); - std::string gettitle() - { return std::string(title); }; - std::string getauthor() - { return std::string(author); }; - std::string getdesc() - { return std::string(remarks); }; - unsigned int getinstruments() - { return tins; }; - unsigned int getsubsongs() - { return subsongs; }; + protected: + static const unsigned char adlib_opadd[]; + static const int ops[], map_chan[], fnums[], percussion_map[]; -protected: - struct midi_channel { - int inum; - unsigned char ins[11]; - int vol; - int nshift; - int on; - }; + struct midi_channel { + int inum; + unsigned char ins[11]; + int vol; + int nshift; + int on; + }; - struct midi_track { - unsigned long tend; - unsigned long spos; - unsigned long pos; - unsigned long iwait; - int on; - unsigned char pv; - }; + struct midi_track { + unsigned long tend; + unsigned long spos; + unsigned long pos; + unsigned long iwait; + int on; + unsigned char pv; + }; - char *author,*title,*remarks,emptystr; - long flen; - unsigned long pos; - unsigned long sierra_pos; //sierras gotta be special.. :> - int subsongs; - unsigned char *data; + char *author,*title,*remarks,emptystr; + long flen; + unsigned long pos; + unsigned long sierra_pos; //sierras gotta be special.. :> + int subsongs; + unsigned char *data; - unsigned char adlib_data[256]; - int adlib_style; - int adlib_mode; - unsigned char myinsbank[128][16], smyinsbank[128][16]; - midi_channel ch[16]; - int chp[9][3]; + unsigned char adlib_data[256]; + int adlib_style; + int adlib_mode; + unsigned char myinsbank[128][16], smyinsbank[128][16]; + midi_channel ch[16]; + int chp[18][3]; - long deltas; - long msqtr; + long deltas; + long msqtr; - midi_track track[16]; - unsigned int curtrack; + midi_track track[16]; + unsigned int curtrack; - float fwait; - unsigned long iwait; - int doing; + float fwait; + unsigned long iwait; + int doing; - int type,tins,stins; + int type,tins,stins; -private: - bool load_sierra_ins(const std::string &fname, const CFileProvider &fp); - void midiprintf(char *format, ...); - unsigned char datalook(long pos); - unsigned long getnexti(unsigned long num); - unsigned long getnext(unsigned long num); - unsigned long getval(); - void sierra_next_section(); - void midi_write_adlib(unsigned int r, unsigned char v); - void midi_fm_instrument(int voice, unsigned char *inst); - void midi_fm_volume(int voice, int volume); - void midi_fm_playnote(int voice, int note, int volume); - void midi_fm_endnote(int voice); - void midi_fm_reset(); + private: + bool load_sierra_ins(const std::string &fname, const CFileProvider &fp); + void midiprintf(char *format, ...); + unsigned char datalook(long pos); + unsigned long getnexti(unsigned long num); + unsigned long getnext(unsigned long num); + unsigned long getval(); + void sierra_next_section(); + void midi_write_adlib(unsigned int r, unsigned char v); + void midi_fm_instrument(int voice, unsigned char *inst); + void midi_fm_percussion(int ch, unsigned char *inst); + void midi_fm_volume(int voice, int volume); + void midi_fm_playnote(int voice, int note, int volume); + void midi_fm_endnote(int voice); + void midi_fm_reset(); };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/adplug/core/msc.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -0,0 +1,322 @@ +/* + * Adplug - Replayer for many OPL2/OPL3 audio file formats. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * msc.c - MSC Player by Lubomir Bulej (pallas@kadan.cz) + */ + +#include <stdio.h> + +#include "msc.h" + +const unsigned char CmscPlayer::msc_signature [MSC_SIGN_LEN] = { + 'C', 'e', 'r', 'e', 's', ' ', '\x13', ' ', + 'M', 'S', 'C', 'p', 'l', 'a', 'y', ' ' }; + + +/*** public methods *************************************/ + +CPlayer * +CmscPlayer::factory (Copl * newopl) +{ + return new CmscPlayer (newopl); +} + + +CmscPlayer::CmscPlayer (Copl * newopl) : CPlayer (newopl) { + desc = NULL; + msc_data = NULL; + raw_data = NULL; + nr_blocks = 0; +} + + +CmscPlayer::~CmscPlayer () +{ + if (raw_data != NULL) + delete [] raw_data; + + if (msc_data != NULL) { + // free compressed blocks + for (int blk_num = 0; blk_num < nr_blocks; blk_num++) { + if (msc_data [blk_num].mb_data != NULL) + delete [] msc_data [blk_num].mb_data; + } + + delete [] msc_data; + } + + if (desc != NULL) + delete [] desc; +} + + +bool +CmscPlayer::load (const std::string & filename, const CFileProvider & fp) +{ + binistream * bf; + msc_header hdr; + + // open and validate the file + bf = fp.open (filename); + if (! bf) + return false; + + if (! load_header (bf, & hdr)) { + fp.close (bf); + return false; + } + + // get stuff from the header + version = hdr.mh_ver; + timer_div = hdr.mh_timer; + nr_blocks = hdr.mh_nr_blocks; + block_len = hdr.mh_block_len; + + if (! nr_blocks) { + fp.close (bf); + return false; + } + + // load compressed data blocks + msc_data = new msc_block [nr_blocks]; + raw_data = new u8 [block_len]; + + for (int blk_num = 0; blk_num < nr_blocks; blk_num++) { + msc_block blk; + + blk.mb_length = bf->readInt (2); + blk.mb_data = new u8 [blk.mb_length]; + for (int oct_num = 0; oct_num < blk.mb_length; oct_num++) { + blk.mb_data [oct_num] = bf->readInt (1); + } + + msc_data [blk_num] = blk; + } + + // clean up & initialize + fp.close (bf); + rewind (0); + + return true; +} + + +bool +CmscPlayer::update () +{ + // output data + while (! delay) { + u8 cmnd; + u8 data; + + // decode data + if (! decode_octet (& cmnd)) + return false; + + if (! decode_octet (& data)) + return false; + + // check for special commands + switch (cmnd) { + + // delay + case 0xff: + delay = 1 + (u8) (data - 1); + break; + + // play command & data + default: + opl->write (cmnd, data); + + } // command switch + } // play pass + + + // count delays + if (delay) + delay--; + + // advance player position + play_pos++; + return true; +} + + +void +CmscPlayer::rewind (int subsong) +{ + // reset state + dec_prefix = 0; + block_num = 0; + block_pos = 0; + play_pos = 0; + raw_pos = 0; + delay = 0; + + // init the OPL chip and go to OPL2 mode + opl->init (); + opl->write (1, 32); +} + + +float +CmscPlayer::getrefresh () +{ + // PC timer oscillator frequency / wait register + return 1193180 / (float) (timer_div ? timer_div : 0xffff); +} + +std::string +CmscPlayer::gettype () +{ + char vstr [40]; + + snprintf (vstr, sizeof (vstr), "AdLib MSCplay (version %d)", version); + return std::string (vstr); +} + + +/*** private methods *************************************/ + +bool +CmscPlayer::load_header (binistream * bf, msc_header * hdr) +{ + // check signature + bf->readString ((char *) hdr->mh_sign, sizeof (hdr->mh_sign)); + if (memcmp (msc_signature, hdr->mh_sign, MSC_SIGN_LEN) != 0) + return false; + + // check version + hdr->mh_ver = bf->readInt (2); + if (hdr->mh_ver != 0) + return false; + + bf->readString ((char *) hdr->mh_desc, sizeof (hdr->mh_desc)); + hdr->mh_timer = bf->readInt (2); + hdr->mh_nr_blocks = bf->readInt (2); + hdr->mh_block_len = bf->readInt (2); + return true; +} + + +bool +CmscPlayer::decode_octet (u8 * output) +{ + msc_block blk; // compressed data block + + if (block_num >= nr_blocks) + return false; + + blk = msc_data [block_num]; + while (1) { + u8 octet; // decoded octet + u8 len_corr; // length correction + + // advance to next block if necessary + if (block_pos >= blk.mb_length && dec_len == 0) { + block_num++; + if (block_num >= nr_blocks) + return false; + + blk = msc_data [block_num]; + block_pos = 0; + raw_pos = 0; + } + + // decode the compressed music data + switch (dec_prefix) { + + // decode prefix + case 155: + case 175: + octet = blk.mb_data [block_pos++]; + if (octet == 0) { + // invalid prefix, output original + octet = dec_prefix; + dec_prefix = 0; + break; + } + + // isolate length and distance + dec_len = (octet & 0x0F); + len_corr = 2; + + dec_dist = (octet & 0xF0) >> 4; + if (dec_prefix == 155) + dec_dist++; + + // next decode step for respective prefix type + dec_prefix++; + continue; + + + // check for extended length + case 156: + if (dec_len == 15) + dec_len += blk.mb_data [block_pos++]; + + // add length correction and go for copy mode + dec_len += len_corr; + dec_prefix = 255; + continue; + + + // get extended distance + case 176: + dec_dist += 17 + 16 * blk.mb_data [block_pos++]; + len_corr = 3; + + // check for extended length + dec_prefix = 156; + continue; + + + // prefix copy mode + case 255: + octet = raw_data [raw_pos - dec_dist]; + + dec_len--; + if (dec_len == 0) { + // back to normal mode + dec_prefix = 0; + } + + break; + + + // normal mode + default: + octet = blk.mb_data [block_pos++]; + if (octet == 155 || octet == 175) { + // it's a prefix, restart + dec_prefix = octet; + continue; + } + } // prefix switch + + + // output the octet + if (output != NULL) + *output = octet; + + raw_data [raw_pos++] = octet; + break; + }; // decode pass + + return true; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/adplug/core/msc.h Sat Jan 14 07:27:13 2006 -0800 @@ -0,0 +1,90 @@ +/* + * Adplug - Replayer for many OPL2/OPL3 audio file formats. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * msc.h - MSC Player by Lubomir Bulej (pallas@kadan.cz) + */ + +#include "player.h" + +#define MSC_SIGN_LEN 16 +#define MSC_DESC_LEN 64 + +class CmscPlayer: public CPlayer +{ +public: + static CPlayer * factory (Copl * newopl); + + CmscPlayer (Copl * newopl); + ~CmscPlayer (); + + bool load (const std::string &filename, const CFileProvider &fp); + bool update (); + void rewind (int subsong); + float getrefresh (); + + std::string gettype (); + + +protected: + typedef unsigned char u8; + typedef unsigned short u16; + + struct msc_header { + u8 mh_sign [MSC_SIGN_LEN]; + u16 mh_ver; + u8 mh_desc [MSC_DESC_LEN]; + u16 mh_timer; + u16 mh_nr_blocks; + u16 mh_block_len; + }; + + struct msc_block { + u16 mb_length; + u8 * mb_data; + }; + + + // file data + char * desc; // song desctiption + unsigned short version; // file version + unsigned short nr_blocks; // number of music blocks + unsigned short block_len; // maximal block length + unsigned short timer_div; // timer divisor + msc_block * msc_data; // compressed music data + + // decoder state + unsigned long block_num; // active block + unsigned long block_pos; // position in block + unsigned long raw_pos; // position in data buffer + u8 * raw_data; // decompression buffer + + u8 dec_prefix; // prefix / state + int dec_dist; // prefix distance + unsigned int dec_len; // prefix length + + // player state + unsigned char delay; // active delay + unsigned long play_pos; // player position + + +private: + static const u8 msc_signature [MSC_SIGN_LEN]; + + bool load_header (binistream * bf, msc_header * hdr); + bool decode_octet (u8 * output); +};
--- a/Plugins/Input/adplug/core/opl.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/opl.h Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,7 +16,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * opl.h - OPL base class declaration, by Simon Peter <dn.tlp@gmx.net> + * opl.h - OPL base class, by Simon Peter <dn.tlp@gmx.net> */ #ifndef H_ADPLUG_OPL @@ -24,11 +24,37 @@ class Copl { -public: - virtual void write(int reg, int val) = 0; // combined register select + data write - virtual void init(void) = 0; // reinitialize OPL chip + public: + typedef enum { + TYPE_OPL2, TYPE_OPL3, TYPE_DUAL_OPL2 + } ChipType; + + Copl() + : currChip(0), currType(TYPE_OPL2) + { + } - virtual void update(short *buf, int samples) {}; // Emulation only: fill buffer + virtual void write(int reg, int val) = 0; // combined register select + data write + virtual void setchip(int n) // select OPL chip + { + if(n < 2) + currChip = n; + } + + virtual void init(void) = 0; // reinitialize OPL chip(s) + + // return this OPL chip's type + ChipType gettype() + { + return currType; + } + + // Emulation only: fill buffer + virtual void update(short *buf, int samples) {} + + protected: + int currChip; // currently selected OPL chip number + ChipType currType; // this OPL chip's type }; #endif
--- a/Plugins/Input/adplug/core/psi.cpp Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/psi.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -69,13 +69,20 @@ opl_write(0x08, 0x00); opl_write(0xBD, 0x00); + // get header + header.instr_ptr = (tune[1] << 8) + tune[0]; + header.seq_ptr = (tune[3] << 8) + tune[2]; + // define instruments - psi.instr_table = (unsigned short *)&tune[((psi_header *)&tune[0])->instr_ptr]; + psi.instr_table = &tune[header.instr_ptr]; for(int i=0; i<8; i++) { - for(int j=0; j<11; j++) - opl_write(psi_adlib_registers[i*11 + j],tune[psi.instr_table[i] + j]); + for(int j=0; j<11; j++) { + unsigned short inspos = (psi.instr_table[i * 2 + 1] << 8) + psi.instr_table[i * 2]; + + opl_write(psi_adlib_registers[i*11 + j],tune[inspos + j]); + } opl_write(0xA0+i, 0x00); opl_write(0xB0+i, 0x00); @@ -86,7 +93,7 @@ } // calculate sequence pointer - psi.seq_table = (unsigned short *)&tune[((psi_header *)&tune[0])->seq_ptr]; + psi.seq_table = &tune[header.seq_ptr]; } void CxadpsiPlayer::xadplayer_update() @@ -95,7 +102,7 @@ for(int i=0; i<8; i++) { - ptr = psi.seq_table[i<<1]; + ptr = (psi.seq_table[(i<<1) * 2 + 1] << 8) + psi.seq_table[(i<<1) * 2]; psi.note_curdelay[i]--; @@ -112,7 +119,7 @@ // end of sequence ? if (!event) { - ptr = psi.seq_table[(i<<1) + 1]; + ptr = (psi.seq_table[(i<<1) * 2 + 3] << 8) + psi.seq_table[(i<<1) * 2 + 2]; event = tune[ptr++]; #ifdef DEBUG @@ -148,7 +155,8 @@ opl_write(0xB0+i, (note >> 8) + ((event >> 2) & 0xFC)); // save position - psi.seq_table[i<<1] = ptr; + psi.seq_table[(i<<1) * 2] = ptr & 0xff; + psi.seq_table[(i<<1) * 2 + 1] = ptr >> 8; } } }
--- a/Plugins/Input/adplug/core/psi.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/psi.h Sat Jan 14 07:27:13 2006 -0800 @@ -34,12 +34,12 @@ { unsigned short instr_ptr; unsigned short seq_ptr; - }; + } header; struct { - unsigned short *instr_table; - unsigned short *seq_table; + unsigned char *instr_table; + unsigned char *seq_table; unsigned char note_delay[9]; unsigned char note_curdelay[9]; unsigned char looping[9];
--- a/Plugins/Input/adplug/core/rat.cpp Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/rat.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -72,7 +72,8 @@ rat.inst = (rat_instrument *)&tune[0x140]; // load pattern data - unsigned char *event_ptr = &tune[rat.hdr.patseg << 4]; + unsigned short patseg = (rat.hdr.patseg[1] << 8) + rat.hdr.patseg[0]; + unsigned char *event_ptr = &tune[patseg << 4]; for(int i=0;i<rat.hdr.numpat;i++) for(int j=0;j<64;j++) @@ -181,7 +182,8 @@ opl_write(0xE0+rat_adlib_bases[i+9], rat.inst[ins].car_wave); // octave/frequency - unsigned short freq = rat.inst[ins].freq * rat_notes[event.note & 0x0F] / 0x20AB; + unsigned short insfreq = (rat.inst[ins].freq[1] << 8) + rat.inst[ins].freq[0]; + unsigned short freq = insfreq * rat_notes[event.note & 0x0F] / 0x20AB; opl_write(0xA0+i, freq & 0xFF); opl_write(0xB0+i, (freq >> 8) | ((event.note & 0xF0) >> 2) | 0x20);
--- a/Plugins/Input/adplug/core/rat.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/rat.h Sat Jan 14 07:27:13 2006 -0800 @@ -50,7 +50,7 @@ unsigned char volume; unsigned char speed; unsigned char reserved_32[12]; - unsigned short patseg; + unsigned char patseg[2]; }; struct rat_event @@ -64,7 +64,7 @@ struct rat_instrument { - unsigned short freq; + unsigned char freq[2]; unsigned char reserved_2[2]; unsigned char mod_ctrl; unsigned char car_ctrl;
--- a/Plugins/Input/adplug/core/raw.cpp Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/raw.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,9 +17,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * raw.c - RAW Player by Simon Peter <dn.tlp@gmx.net> - * - * NOTES: - * OPL3 register writes are ignored (not possible with AdLib). */ #include "raw.h" @@ -76,7 +73,7 @@ speed = data[pos].param + (data[pos].command << 8); setspeed = true; } else - opl3 = data[pos].param - 1; + opl->setchip(data[pos].param - 1); break; case 0xff: if(data[pos].param == 0xff) { @@ -86,8 +83,7 @@ } break; default: - if(!opl3) - opl->write(data[pos].command,data[pos].param); + opl->write(data[pos].command,data[pos].param); break; } } while(data[pos++].command || setspeed); @@ -97,8 +93,8 @@ void CrawPlayer::rewind(int subsong) { - pos = del = opl3 = 0; speed = clock; songend = false; - opl->init(); opl->write(1,32); // go to OPL2 mode + pos = del = 0; speed = clock; songend = false; + opl->init(); opl->write(1, 32); // go to 9 channel mode } float CrawPlayer::getrefresh()
--- a/Plugins/Input/adplug/core/raw.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/raw.h Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -42,11 +42,11 @@ protected: struct Tdata { - unsigned char param,command; + unsigned char param, command; } *data; - unsigned long pos,length; - unsigned short clock,speed; - unsigned char del,opl3; + unsigned long pos, length; + unsigned short clock, speed; + unsigned char del; bool songend; };
--- a/Plugins/Input/adplug/core/realopl.cpp Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/realopl.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,143 +16,189 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * - * realopl.cpp - Real hardware OPL, by Simon Peter (dn.tlp@gmx.net) + * realopl.cpp - Real hardware OPL, by Simon Peter <dn.tlp@gmx.net> */ -#include <conio.h> -#include "realopl.h" - -#ifdef _MSC_VER - #define INP _inp - #define OUTP _outp -#elif defined(__WATCOMC__) - #define INP inp - #define OUTP outp +#ifdef _MSC_VER // Microsoft Visual C++ +# include <conio.h> +# define INP _inp +# define OUTP _outp +#elif defined(__WATCOMC__) // Watcom C/C++ and OpenWatcom +# include <conio.h> +# define INP inp +# define OUTP outp +#elif defined(WIN32) && defined(__MSVCRT__) && defined(__MINGW32__) +/* +int __cdecl _inp(unsigned short); +int __cdecl _outp(unsigned short, int); +# define INP _inp +# define OUTP _outp +*/ +# define INP inb +# define OUTP(reg, val) outb(val, reg) +#else // no support on other platforms +# define INP(reg) 0 +# define OUTP(reg, val) #endif -/* - * chris: TODO: This isn't quite right. According to Jeff Lee's doc: - * - * "After writing to the register port, you must wait twelve cycles before - * sending the data; after writing the data, eighty-four cycles must elapse - * before any other sound card operation may be performed. - * - * | The AdLib manual gives the wait times in microseconds: three point three - * | (3.3) microseconds for the address, and twenty-three (23) microseconds - * | for the data. - * | - * | The most accurate method of producing the delay is to read the register - * | port six times after writing to the register port, and read the register - * | port thirty-five times after writing to the data port." - * - * - * In other words, the delay constants represented by {SHORT|LONG}DELAY below - * aren't given in microseconds, but rather direct reads (INB) from the Adlib - * I/O ports. - * - * Translation: SHORTDELAY should be 6, and LONGDELAY is just fine. :-) - */ +#include "realopl.h" + +#define SHORTDELAY 6 // short delay in I/O port-reads after OPL hardware output +#define LONGDELAY 35 // long delay in I/O port-reads after OPL hardware output + +const unsigned char CRealopl::op_table[9] = + {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12}; + +#if defined(WIN32) && defined(__MINGW32__) +static __inline unsigned char +inb (unsigned short int port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline void +outb (unsigned char value, unsigned short int port) +{ + __asm__ __volatile__ ("outb %b0,%w1": :"a" (value), "Nd" (port)); +} +#endif -#define SHORTDELAY 6 // short delay in I/O port-reads after OPL hardware output -#define LONGDELAY 35 // long delay in I/O port-reads after OPL hardware output +CRealopl::CRealopl(unsigned short initport) + : adlport(initport), hardvol(0), bequiet(false), nowrite(false) +{ + for(int i=0;i<22;i++) { + hardvols[0][i][0] = 0; + hardvols[0][i][1] = 0; + hardvols[1][i][0] = 0; + hardvols[1][i][1] = 0; + } -// the 9 operators as expected by the OPL2 -static const unsigned char op_table[9] = {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12}; + currType = TYPE_OPL3; +} -CRealopl::CRealopl(unsigned short initport): adlport(initport), hardvol(0), bequiet(false), nowrite(false) +bool CRealopl::harddetect() { - for(int i=0;i<22;i++) { - hardvols[i][0] = 0; - hardvols[i][1] = 0; - } + unsigned char stat1, stat2, i; + unsigned short adp = (currChip == 0 ? adlport : adlport + 2); + + hardwrite(4,0x60); hardwrite(4,0x80); + stat1 = INP(adp); + hardwrite(2,0xff); hardwrite(4,0x21); + for(i=0;i<80;i++) // wait for adlib + INP(adp); + stat2 = INP(adp); + hardwrite(4,0x60); hardwrite(4,0x80); + + if(((stat1 & 0xe0) == 0) && ((stat2 & 0xe0) == 0xc0)) + return true; + else + return false; } bool CRealopl::detect() { - unsigned char stat1,stat2,i; + unsigned char stat; + + setchip(0); + if(harddetect()) { + // is at least OPL2, check for OPL3 + currType = TYPE_OPL2; - hardwrite(4,0x60); hardwrite(4,0x80); - stat1 = INP(adlport); - hardwrite(2,0xff); hardwrite(4,0x21); - for(i=0;i<80;i++) // wait for adlib - INP(adlport); - stat2 = INP(adlport); - hardwrite(4,0x60); hardwrite(4,0x80); + stat = INP(adlport); + if(stat & 6) { + // not OPL3, try dual-OPL2 + setchip(1); + if(harddetect()) + currType = TYPE_DUAL_OPL2; + } else + currType = TYPE_OPL3; - if(((stat1 & 0xe0) == 0) && ((stat2 & 0xe0) == 0xc0)) - return true; - else - return false; + setchip(0); + return true; + } else + return false; } void CRealopl::setvolume(int volume) { - int i; + int i, j; - hardvol = volume; - for(i=0;i<9;i++) { - hardwrite(0x43+op_table[i],((hardvols[op_table[i]+3][0] & 63) + volume) > 63 ? 63 : hardvols[op_table[i]+3][0] + volume); - if(hardvols[i][1] & 1) // modulator too? - hardwrite(0x40+op_table[i],((hardvols[op_table[i]][0] & 63) + volume) > 63 ? 63 : hardvols[op_table[i]][0] + volume); - } + hardvol = volume; + for(j = 0; j < 2; j++) + for(i = 0; i < 9; i++) { + hardwrite(0x43+op_table[i],((hardvols[j][op_table[i]+3][0] & 63) + volume) > 63 ? 63 : hardvols[j][op_table[i]+3][0] + volume); + if(hardvols[j][i][1] & 1) // modulator too? + hardwrite(0x40+op_table[i],((hardvols[j][op_table[i]][0] & 63) + volume) > 63 ? 63 : hardvols[j][op_table[i]][0] + volume); + } } void CRealopl::setquiet(bool quiet) { - bequiet = quiet; + bequiet = quiet; - if(quiet) { - oldvol = hardvol; - setvolume(63); - } else - setvolume(oldvol); + if(quiet) { + oldvol = hardvol; + setvolume(63); + } else + setvolume(oldvol); } void CRealopl::hardwrite(int reg, int val) { - int i; + int i; + unsigned short adp = (currChip == 0 ? adlport : adlport + 2); - OUTP(adlport,reg); // set register - for(i=0;i<SHORTDELAY;i++) // wait for adlib - INP(adlport); - OUTP(adlport+1,val); // set value - for(i=0;i<LONGDELAY;i++) // wait for adlib - INP(adlport); + OUTP(adp,reg); // set register + for(i=0;i<SHORTDELAY;i++) // wait for adlib + INP(adp); + OUTP(adp+1,val); // set value + for(i=0;i<LONGDELAY;i++) // wait for adlib + INP(adp); } void CRealopl::write(int reg, int val) { - int i; + int i; - if(nowrite) - return; + if(nowrite) + return; + + if(currType == TYPE_OPL2 && currChip > 0) + return; - if(bequiet && (reg >= 0xb0 && reg <= 0xb8)) // filter all key-on commands - val &= ~32; - if(reg >= 0x40 && reg <= 0x55) // cache volumes - hardvols[reg-0x40][0] = val; - if(reg >= 0xc0 && reg <= 0xc8) - hardvols[reg-0xc0][1] = val; - if(hardvol) // reduce volume - for(i=0;i<9;i++) { - if(reg == 0x43 + op_table[i]) - val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol; - else - if((reg == 0x40 + op_table[i]) && (hardvols[i][1] & 1)) - val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol; - } + if(bequiet && (reg >= 0xb0 && reg <= 0xb8)) // filter all key-on commands + val &= ~32; + if(reg >= 0x40 && reg <= 0x55) // cache volumes + hardvols[currChip][reg-0x40][0] = val; + if(reg >= 0xc0 && reg <= 0xc8) + hardvols[currChip][reg-0xc0][1] = val; + if(hardvol) // reduce volume + for(i=0;i<9;i++) { + if(reg == 0x43 + op_table[i]) + val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol; + else + if((reg == 0x40 + op_table[i]) && (hardvols[currChip][i][1] & 1)) + val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol; + } - hardwrite(reg,val); + hardwrite(reg,val); } void CRealopl::init() { - int i; + int i, j; + + for(j = 0; j < 2; j++) { + setchip(j); - for (i=0;i<9;i++) { // stop instruments - hardwrite(0xb0 + i,0); // key off - hardwrite(0x80 + op_table[i],0xff); // fastest release - } - hardwrite(0xbd,0); // clear misc. register + for(i=0;i<9;i++) { // stop instruments + hardwrite(0xb0 + i,0); // key off + hardwrite(0x80 + op_table[i],0xff); // fastest release + } + + hardwrite(0xbd,0); // clear misc. register + } }
--- a/Plugins/Input/adplug/core/realopl.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/realopl.h Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * AdPlug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2002 Simon Peter <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,36 +19,54 @@ * realopl.h - Real hardware OPL, by Simon Peter <dn.tlp@gmx.net> */ +#ifndef H_ADPLUG_REALOPL +#define H_ADPLUG_REALOPL + #include "opl.h" #define DFL_ADLIBPORT 0x388 // default adlib baseport class CRealopl: public Copl { -public: - CRealopl(unsigned short initport = DFL_ADLIBPORT); // initport = OPL2 hardware baseport + public: + CRealopl(unsigned short initport = DFL_ADLIBPORT); // initport = OPL2 hardware baseport - bool detect(); // returns true if adlib compatible board is found, else false - void setvolume(int volume); // set adlib master volume (0 - 63) 0 = loudest, 63 = softest - void setquiet(bool quiet = true); // sets the OPL2 quiet, while still writing to the registers - void setport(unsigned short port) // set new OPL2 hardware baseport - { adlport = port; }; - void setnowrite(bool nw = true) // set hardware write status - { nowrite = nw; }; + bool detect(); // returns true if adlib compatible board is found, else false + void setvolume(int volume); // set adlib master volume (0 - 63) 0 = loudest, 63 = softest + void setquiet(bool quiet = true); // sets the OPL2 quiet, while still writing to the registers + void setport(unsigned short port) // set new OPL2 hardware baseport + { + adlport = port; + } + void setnowrite(bool nw = true) // set hardware write status + { + nowrite = nw; + } - int getvolume() // get adlib master volume - { return hardvol; }; + int getvolume() // get adlib master volume + { + return hardvol; + } - // template methods - void write(int reg, int val); - void init(); - -private: - void hardwrite(int reg, int val); // write to OPL2 hardware registers + // template methods + void write(int reg, int val); + void init(); + void settype(ChipType type) + { + currType = type; + } - unsigned short adlport; // adlib hardware baseport - int hardvol,oldvol; // hardware master volume - bool bequiet; // quiet status cache - char hardvols[22][2]; // volume cache - bool nowrite; // don't write to hardware, if true + protected: + void hardwrite(int reg, int val); // write to OPL2 hardware registers + bool harddetect(); // do real hardware detection + + static const unsigned char op_table[9]; // the 9 operators as expected by the OPL2 + + unsigned short adlport; // adlib hardware baseport + int hardvol, oldvol; // hardware master volume + bool bequiet; // quiet status cache + char hardvols[2][22][2]; // volume cache + bool nowrite; // don't write to hardware, if true }; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/adplug/core/rix.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -0,0 +1,509 @@ +/* + * Adplug - Replayer for many OPL2/OPL3 audio file formats. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * rix.c - Dayu OPL Format Player by palxex <palxex@163.com/palxex.ys168.com> + */ + +#include "rix.h" +#include <binfile.h> + +const unsigned char CrixPlayer::adflag[] = {0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1}; +const unsigned char CrixPlayer::reg_data[] = {0,1,2,3,4,5,8,9,10,11,12,13,16,17,18,19,20,21}; +const unsigned char CrixPlayer::ad_C0_offs[] = {0,1,2,0,1,2,3,4,5,3,4,5,6,7,8,6,7,8}; +const unsigned char CrixPlayer::modify[] = {0,3,1,4,2,5,6,9,7,10,8,11,12,15,13,16,14,17,12,\ + 15,16,0,14,0,17,0,13,0}; +const unsigned char CrixPlayer::bd_reg_data[] = {\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x08,0x04,0x02,0x01,\ + 0x00,0x01,0x01,0x03,0x0F,0x05,0x00,0x01,0x03,0x0F,0x00,\ + 0x00,0x00,0x01,0x00,0x00,0x01,0x01,0x0F,0x07,0x00,0x02,\ + 0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x0A,\ + 0x04,0x00,0x08,0x0C,0x0B,0x00,0x00,0x00,0x01,0x00,0x00,\ + 0x00,0x00,0x0D,0x04,0x00,0x06,0x0F,0x00,0x00,0x00,0x00,\ + 0x01,0x00,0x00,0x0C,0x00,0x0F,0x0B,0x00,0x08,0x05,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x0F,0x0B,0x00,\ + 0x07,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,\ + 0x0F,0x0B,0x00,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x00,0x01,0x00,0x0F,0x0B,0x00,0x07,0x05,0x00,0x00,0x00,\ + 0x00,0x00,0x00}; +unsigned char CrixPlayer::for40reg[] = {0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,\ + 0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F}; +unsigned short CrixPlayer::mus_time = 0x4268; +/*** public methods *************************************/ +CPlayer *CrixPlayer::factory(Copl *newopl) +{ + return new CrixPlayer(newopl); +} + +bool CrixPlayer::load(const std::string &filename, const CFileProvider &fp) +{ + binistream *f = fp.open(filename); if(!f) return false; + unsigned long i=0; + + if(f->readInt(2)!=0x55aa) {fp.close(f);return false; } + buf_addr[i++]=0xaa;buf_addr[i++]=0x55; + while(!f->eof()) + buf_addr[i++]=f->readInt(1); + length=i; + fp.close(f); + set_new_int(); + data_initial(); + while(!dro_end) + int_08h_entry(); + + length=T; + mode = (OplMode)1; // Type of opl data this can contain + +// binofstream *g=new binofstream(filename+string(".dro")); +// g->writeString("DBRAWOPL",8); +// g->writeInt(mstotal,4); +// g->writeInt(length+1,4); +// g->writeInt(1,1); +// for(int t=0;t<length;t++) +// g->writeInt(dro[t],1); +// g->close(); +// delete g; + + rewind(0); + return true; +} + +bool CrixPlayer::update() +{ + if (delay>500) { + delay-=500; + return true; + } else delay=1; + while (pos < length) + { + unsigned char cmd = dro[pos++]; + switch(cmd) { + case 0: + delay = 1 + dro[pos++]; + return true; + case 1: + delay = 1 + dro[pos] + (dro[pos+1]<<8); + pos+=2; + return true; + case 2: + index = 0; + opl->setchip(0); + break; + case 3: + index = 1; + opl->setchip(1); + break; + default: + if(index == 0 || opl3_mode) + opl->write(cmd,dro[pos++]); + break; + } + } + return pos<length; +} + +void CrixPlayer::rewind(int subsong) +{ + delay=1; + pos = index = 0; + opl->init(); + opl->write(1,32); // go to OPL2 mode +} + +float CrixPlayer::getrefresh() +{ + if (delay > 500) return 1000 / 500; + else return 1000 / (double)delay; +} + +/*------------------Implemention----------------------------*/ +inline void CrixPlayer::set_new_int() +{ + if(!ad_initial()) exit(1); + prep_int(); +} +/*----------------------------------------------------------*/ +inline void CrixPlayer::Pause() +{ + register unsigned short i; + pause_flag = 1; + for(i=0;i<11;i++) + switch_ad_bd(i); +} +/*----------------------------------------------------------*/ +inline void CrixPlayer::ad_a0b0l_reg_(unsigned short index,unsigned short p2,unsigned short p3) +{ + unsigned short i = p2+a0b0_data2[index]; + a0b0_data4[index] = p3; + a0b0_data3[index] = p2; +} +inline void CrixPlayer::data_initial() +{ + rhythm = buf_addr[2]; + mus_block = (buf_addr[0x0D]<<8)+buf_addr[0x0C]; + ins_block = (buf_addr[0x09]<<8)+buf_addr[0x08]; + I = mus_block+1; + if(rhythm != 0) + { +// ad_a0b0_reg(6); +// ad_a0b0_reg(7); +// ad_a0b0_reg(8); + ad_a0b0l_reg_(8,0x18,0); + ad_a0b0l_reg_(7,0x1F,0); + } + bd_modify = 0; +// ad_bd_reg(); + band = 0; music_on = 1; +} +/*----------------------------------------------------------*/ +inline unsigned short CrixPlayer::ad_initial() +{ + register unsigned short i,j,k = 0; + for(i=0;i<25;i++) crc_trans(i,i*4); + for(i=0;i<8;i++) + for(j=0;j<12;j++) + { + a0b0_data5[k] = i; + addrs_head[k] = j; + k++; + } + //ad_bd_reg(); + //ad_08_reg(); + //for(i=0;i<9;i++) ad_a0b0_reg(i); + e0_reg_flag = 0x20; + //for(i=0;i<18;i++) ad_bop(0xE0+reg_data[i],0); + //ad_bop(1,e0_reg_flag); + return 1;//ad_test(); +} +/*----------------------------------------------------------*/ +inline void CrixPlayer::crc_trans(unsigned short index,unsigned short v) +{ + register unsigned short i; + unsigned int res; unsigned short low; + res = strm_and_fr(v); + low = res; + buffer[index*12] = (low+4)>>3; + for(i=1;i<=11;i++) + { + res *= 1.06; + buffer[index*12+i] = res>>3; + } +} + +/*----------------------------------------------------------*/ +inline void CrixPlayer::prep_int() +{ + mutex = 0; +} +/*----------------------------------------------------------*/ +inline void CrixPlayer::ad_bop(unsigned short reg,unsigned short value) +{ + dro[T++]=reg;dro[T++]=value; +} +/*------------------------------------------------------*/ +inline unsigned short CrixPlayer::ad_test() /* Test the SoundCard */ +{ + ad_bop(0x04,0x60); + ad_bop(0x04,0x80); + ad_bop(0x02,0xFF); + ad_bop(0x04,0x21); + ad_bop(0x04,0x60); + ad_bop(0x04,0x80); + return 1; +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::int_08h_entry() +{ + unsigned short band_sus = 1; + while(band_sus) + { + if(sustain <= 0 && mutex == 0) + { + mutex++; + band_sus = rix_proc(); + if(band_sus) sustain += band_sus * 1.06; + mstotal+=sustain; + dro[T++]=(sustain>=0x100?1:0); + dro[T++]=sustain&0xff; + if(sustain>=0x100) + dro[T++]=(sustain>>8)&0xff; + mutex--; + if(band_sus == 0) + { + dro_end=1; + break; + } + } + else + { + if(band_sus) sustain -= 14; /* aging */ + break; + } + } +} +/*--------------------------------------------------------------*/ +inline unsigned short CrixPlayer::rix_proc() +{ + unsigned char ctrl = 0; + if(music_on == 0||pause_flag == 1) return 0; + band = 0; + while(buf_addr[I] != 0x80 && I<length-1) + { + band_low = buf_addr[I-1]; + ctrl = buf_addr[I]; I+=2; + switch(ctrl&0xF0) + { + case 0x90: rix_get_ins(); rix_90_pro(ctrl&0x0F); break; + case 0xA0: rix_A0_pro(ctrl&0x0F,((unsigned short)band_low)<<6); break; + case 0xB0: rix_B0_pro(ctrl&0x0F,band_low); break; + case 0xC0: switch_ad_bd(ctrl&0x0F); + if(band_low != 0) rix_C0_pro(ctrl&0x0F,band_low); + break; + default: band = (ctrl<<8)+band_low; break; + } + if(band != 0) return band; + } + music_ctrl(); + I = mus_block+1; + band = 0; music_on = 1; + return 0; +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::rix_get_ins() +{ + memcpy(insbuf,(&buf_addr[ins_block])+(band_low<<6),56); +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::rix_90_pro(unsigned short ctrl_l) +{ + if(rhythm == 0 || ctrl_l < 6) + { + ins_to_reg(modify[ctrl_l*2],insbuf,insbuf[26]); + ins_to_reg(modify[ctrl_l*2+1],insbuf+13,insbuf[27]); + return; + } + else + { + if(ctrl_l > 6) + { + ins_to_reg(modify[ctrl_l*2+6],insbuf,insbuf[26]); + return; + } + else + { + ins_to_reg(12,insbuf,insbuf[26]); + ins_to_reg(15,insbuf+13,insbuf[27]); + return; + } + } +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::rix_A0_pro(unsigned short ctrl_l,unsigned short index) +{ + if(rhythm == 0 || ctrl_l <= 6) + { + prepare_a0b0(ctrl_l,index>0x3FFF?0x3FFF:index); + ad_a0b0l_reg(ctrl_l,a0b0_data3[ctrl_l],a0b0_data4[ctrl_l]); + } + else return; +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::prepare_a0b0(unsigned short index,unsigned short v) /* important !*/ +{ + short high = 0,low = 0; unsigned int res; + low = ((unsigned short)(v-0x2000))*0x19; + high = ((short)v)<0x2000?0xFFFF:0; + if(low == 0xFF && high == 0) return; + res = ((((unsigned int)high)<<16)|low)/0x2000; + low = res&0xFFFF; + if(low < 0) + { + low = 0x18-low; high = (signed short)low<0?0xFFFF:0; + res = high; res<<=16; res+=low; + low = ((signed short)res)/(signed short)0xFFE7; + a0b0_data2[index] = low; + low = res; + res = low - 0x18; + high = (signed short)res%0x19; + low = (signed short)res/0x19; + if(high != 0) {low = 0x19; low = low-high;} + } + else + { + res = high = low; + low = (signed short)res/(signed short)0x19; + a0b0_data2[index] = low; + res = high; + low = (signed short)res%(signed short)0x19; + } + low = (signed short)low*(signed short)0x18; + displace[index] = low; +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::ad_a0b0l_reg(unsigned short index,unsigned short p2,unsigned short p3) +{ + unsigned short data; unsigned short i = p2+a0b0_data2[index]; + a0b0_data4[index] = p3; + a0b0_data3[index] = p2; + i = ((signed short)i<=0x5F?i:0x5F); + i = ((signed short)i>=0?i:0); + data = buffer[addrs_head[i]+displace[index]/2]; + ad_bop(0xA0+index,data); + data = a0b0_data5[i]*4+(p3<1?0:0x20)+((data>>8)&3); + ad_bop(0xB0+index,data); +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::rix_B0_pro(unsigned short ctrl_l,unsigned short index) +{ + register int temp = 0; + if(rhythm == 0 || ctrl_l < 6) temp = modify[ctrl_l*2+1]; + else + { + temp = ctrl_l > 6?ctrl_l*2:ctrl_l*2+1; + temp = modify[temp+6]; + } + for40reg[temp] = index>0x7F?0x7F:index; + ad_40_reg(temp); +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::rix_C0_pro(unsigned short ctrl_l,unsigned short index) +{ + register unsigned short i = index>=12?index-12:0; + if(ctrl_l < 6 || rhythm == 0) + { + ad_a0b0l_reg(ctrl_l,i,1); + return; + } + else + { + if(ctrl_l != 6) + { + if(ctrl_l == 8) + { + ad_a0b0l_reg(ctrl_l,i,0); + ad_a0b0l_reg(7,i+7,0); + } + } + else ad_a0b0l_reg(ctrl_l,i,0); + bd_modify |= bd_reg_data[ctrl_l]; + ad_bd_reg(); + return; + } +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::switch_ad_bd(unsigned short index) +{ + + if(rhythm == 0 || index < 6) ad_a0b0l_reg(index,a0b0_data3[index],0); + else + { + bd_modify &= (~bd_reg_data[index]), + ad_bd_reg(); + } +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::ins_to_reg(unsigned short index,unsigned short* insb,unsigned short value) +{ + register unsigned short i; + for(i=0;i<13;i++) reg_bufs[index].v[i] = insb[i]; + reg_bufs[index].v[13] = value&3; + ad_bd_reg(),ad_08_reg(), + ad_40_reg(index),ad_C0_reg(index),ad_60_reg(index), + ad_80_reg(index),ad_20_reg(index),ad_E0_reg(index); +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::ad_E0_reg(unsigned short index) +{ + unsigned short data = e0_reg_flag == 0?0:(reg_bufs[index].v[13]&3); + ad_bop(0xE0+reg_data[index],data); +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::ad_20_reg(unsigned short index) +{ + unsigned short data = (reg_bufs[index].v[9] < 1?0:0x80); + data += (reg_bufs[index].v[10] < 1?0:0x40); + data += (reg_bufs[index].v[5] < 1?0:0x20); + data += (reg_bufs[index].v[11] < 1?0:0x10); + data += (reg_bufs[index].v[1]&0x0F); + ad_bop(0x20+reg_data[index],data); +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::ad_80_reg(unsigned short index) +{ + unsigned short data = (reg_bufs[index].v[7]&0x0F),temp = reg_bufs[index].v[4]; + data |= (temp << 4); + ad_bop(0x80+reg_data[index],data); +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::ad_60_reg(unsigned short index) +{ + unsigned short data = reg_bufs[index].v[6]&0x0F,temp = reg_bufs[index].v[3]; + data |= (temp << 4); + ad_bop(0x60+reg_data[index],data); +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::ad_C0_reg(unsigned short index) +{ + unsigned short data = reg_bufs[index].v[2]; + if(adflag[index] == 1) return; + data *= 2, + data |= (reg_bufs[index].v[12] < 1?1:0); + ad_bop(0xC0+ad_C0_offs[index],data); +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::ad_40_reg(unsigned short index) +{ + unsigned int res = 0; + unsigned short data = 0,temp = reg_bufs[index].v[0]; + data = 0x3F - (0x3F & reg_bufs[index].v[8]), + data *= for40reg[index], + data *= 2, + data += 0x7F, + res = data; + data = res/0xFE, + data -= 0x3F, + data = -data, + data |= temp<<6; + ad_bop(0x40+reg_data[index],data); +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::ad_bd_reg() +{ + unsigned short data = rhythm < 1? 0:0x20; + data |= bd_modify; + ad_bop(0xBD,data); +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::ad_a0b0_reg(unsigned short index) +{ + ad_bop(0xA0+index,0); + ad_bop(0xB0+index,0); +} +/*--------------------------------------------------------------*/ +inline void CrixPlayer::music_ctrl() +{ + register int i; + music_on = 0; + for(i=0;i<11;i++) + switch_ad_bd(i); +} +/*----------------------------------------------------------------------*/ +inline unsigned int CrixPlayer::strm_and_fr(unsigned short parm) +{ + return ((unsigned int)parm*6+10000)*0.27461678223; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/adplug/core/rix.h Sat Jan 14 07:27:13 2006 -0800 @@ -0,0 +1,130 @@ +/* + * Adplug - Replayer for many OPL2/OPL3 audio file formats. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * rix.h - Dayu OPL Format Player by palxex <palxex@163.com/palxex.ys168.com> + */ + +#include "player.h" + +class CrixPlayer: public CPlayer +{ +public: + static CPlayer *factory(Copl *newopl); + + CrixPlayer(Copl *newopl) + : CPlayer(newopl),I(0),T(0),mus_block(0),ins_block(0),rhythm(0),mutex(0),music_on(0), + pause_flag(0),band(0),band_low(0),e0_reg_flag(0),bd_modify(0),sustain(0),dro_end(0) + { + // memset(buffer,0,97948); + int i=0,j=i*3; + unsigned long t=9; + + if(opl->gettype() == Copl::TYPE_OPL2) + opl3_mode = 0; + else + opl3_mode = 1; + }; + ~CrixPlayer() + {}; + + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh(); + + std::string gettype() + { return std::string("Softstar RIX OPL Music Format"); }; + + typedef struct {unsigned char v[14];}ADDT; + +protected: + unsigned char dro[64000]; + unsigned char buf_addr[655360]; /* rix files' buffer */ + unsigned short buffer[300]; + unsigned short a0b0_data2[11]; + unsigned char a0b0_data3[18]; + unsigned char a0b0_data4[18]; + unsigned char a0b0_data5[96]; + unsigned char addrs_head[96]; + unsigned short insbuf[28]; + unsigned short displace[11]; + ADDT reg_bufs[18]; + unsigned long pos,length; + unsigned long msdone,mstotal; + unsigned short delay; + unsigned char index, opl3_mode; + enum OplMode { + ModeOPL2,ModeOPL3,ModeDUALOPL2 + } mode; + + static const unsigned char adflag[18]; + static const unsigned char reg_data[18]; + static const unsigned char ad_C0_offs[18]; + static const unsigned char modify[28]; + static const unsigned char bd_reg_data[124]; + static unsigned char for40reg[18]; + static unsigned short mus_time; + unsigned int I,T; + unsigned short mus_block; + unsigned short ins_block; + unsigned char rhythm; + unsigned char mutex; + unsigned char music_on; + unsigned char pause_flag; + unsigned short band; + unsigned char band_low; + unsigned short e0_reg_flag; + unsigned char bd_modify; + int sustain; + int dro_end; + + #define ad_08_reg() ad_bop(8,0) /**/ + inline void ad_20_reg(unsigned short); /**/ + inline void ad_40_reg(unsigned short); /**/ + inline void ad_60_reg(unsigned short); /**/ + inline void ad_80_reg(unsigned short); /**/ + inline void ad_a0b0_reg(unsigned short); /**/ + inline void ad_a0b0l_reg(unsigned short,unsigned short,unsigned short); /**/ + inline void ad_a0b0l_reg_(unsigned short,unsigned short,unsigned short); /**/ + inline void ad_bd_reg(); /**/ + inline void ad_bop(unsigned short,unsigned short); /**/ + inline void ad_C0_reg(unsigned short); /**/ + inline void ad_E0_reg(unsigned short); /**/ + inline unsigned short ad_initial(); /**/ + inline unsigned short ad_test(); /**/ + inline void crc_trans(unsigned short,unsigned short); /**/ + inline void data_initial(); /* done */ + inline void init(); /**/ + inline void ins_to_reg(unsigned short,unsigned short*,unsigned short); /**/ + inline void int_08h_entry(); /**/ + inline void music_ctrl(); /**/ + inline void Pause(); /**/ + inline void prep_int(); /**/ + inline void prepare_a0b0(unsigned short,unsigned short); /**/ + inline void rix_90_pro(unsigned short); /**/ + inline void rix_A0_pro(unsigned short,unsigned short); /**/ + inline void rix_B0_pro(unsigned short,unsigned short); /**/ + inline void rix_C0_pro(unsigned short,unsigned short); /**/ + inline void rix_get_ins(); /**/ + inline unsigned short rix_proc(); /**/ + inline void set_new_int(); + inline void set_speed(unsigned short); /**/ + inline void set_time(unsigned short); /**/ + inline void switch_ad_bd(unsigned short); /**/ + inline unsigned int strm_and_fr(unsigned short); /* done */ +};
--- a/Plugins/Input/adplug/core/silentopl.h Sat Jan 14 05:40:19 2006 -0800 +++ b/Plugins/Input/adplug/core/silentopl.h Sat Jan 14 07:27:13 2006 -0800 @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,7 +16,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * * silentopl.h - Silent OPL device, by Simon Peter (dn.tlp@gmx.net) */ @@ -25,6 +24,6 @@ class CSilentopl: public Copl { public: - void write(int reg, int val) { }; - void init() { }; + void write(int reg, int val) {} + void init() {} };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/adplug/core/temuopl.cpp Sat Jan 14 07:27:13 2006 -0800 @@ -0,0 +1,75 @@ +/* + * AdPlug - Replayer for many OPL2/OPL3 audio file formats. + * Copyright (C) 1999 - 2004 Simon Peter <dn.tlp@gmx.net>, et al. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * temuopl.cpp - Tatsuyuki Satoh's OPL2 emulator, by Simon Peter <dn.tlp@gmx.net> + */ + +#include "temuopl.h" + +CTemuopl::CTemuopl(int rate, bool bit16, bool usestereo) + : use16bit(bit16), stereo(usestereo) +{ + opl = OPLCreate(OPL_TYPE_YM3812, 3579545, rate); +} + +CTemuopl::~CTemuopl() +{ + OPLDestroy(opl); +} + +void CTemuopl::update(short *buf, int samples) +{ + int i; + + if(use16bit) { + YM3812UpdateOne(opl,buf,samples); + + if(stereo) + for(i=samples-1;i>=0;i--) { + buf[i*2] = buf[i]; + buf[i*2+1] = buf[i]; + } + } else { + short *tempbuf = new short[stereo ? samples*2 : samples]; + int i; + + YM3812UpdateOne(opl,tempbuf,samples); + + if(stereo) + for(i=samples-1;i>=0;i--) { + tempbuf[i*2] = tempbuf[i]; + tempbuf[i*2+1] = tempbuf[i]; + } + + for(i=0;i<(stereo ? samples*2 : samples);i++) + ((char *)buf)[i] = (tempbuf[i] >> 8) ^ 0x80; + + delete [] tempbuf; + } +} + +void CTemuopl::write(int reg, int val) +{ + OPLWrite(opl,0,reg); + OPLWrite(opl,1,val); +} + +void CTemuopl::init() +{ + OPLResetChip(opl); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Input/adplug/core/temuopl.h Sat Jan 14 07:27:13 2006 -0800 @@ -0,0 +1,47 @@ +/* + * Adplug - Replayer for many OPL2/OPL3 audio file formats. + * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * temuopl.h - Tatsuyuki Satoh's OPL2 emulator, by Simon Peter <dn.tlp@gmx.net> + */ + +#ifndef H_ADPLUG_TEMUOPL +#define H_ADPLUG_TEMUOPL + +#include "opl.h" +extern "C" { +#include "fmopl.h" +} + +class CTemuopl: public Copl +{ + public: + CTemuopl(int rate, bool bit16, bool usestereo); // rate = sample rate + virtual ~CTemuopl(); + + void update(short *buf, int samples); // fill buffer + + // template methods + void write(int reg, int val); + void init(); + + private: + bool use16bit,stereo; + FM_OPL *opl; // holds emulator data +}; + +#endif