DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/adlib.cpp
00001 /*
00002  *  Copyright (C) 2002-2020  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <math.h>
00023 #include <sys/types.h>
00024 #include "adlib.h"
00025 
00026 #include "setup.h"
00027 #include "mapper.h"
00028 #include "mem.h"
00029 #include "dbopl.h"
00030 #include "nukedopl.h"
00031 
00032 #include "mame/emu.h"
00033 #include "mame/fmopl.h"
00034 #include "mame/ymf262.h"
00035 
00036 #define OPL2_INTERNAL_FREQ    3600000   // The OPL2 operates at 3.6MHz
00037 #define OPL3_INTERNAL_FREQ    14400000  // The OPL3 operates at 14.4MHz
00038 
00039 bool adlib_force_timer_overflow_on_polling = false;
00040 
00041 namespace OPL2 {
00042         #include "opl.cpp"
00043 
00044         struct Handler : public Adlib::Handler {
00045                 virtual void WriteReg( Bit32u reg, Bit8u val ) {
00046                         adlib_write(reg,val);
00047                 }
00048                 virtual Bit32u WriteAddr( Bit32u port, Bit8u val ) {
00049             (void)port;//UNUSED
00050                         return val;
00051                 }
00052 
00053                 virtual void Generate( MixerChannel* chan, Bitu samples ) {
00054                         Bit16s buf[1024];
00055                         while( samples > 0 ) {
00056                                 Bitu todo = samples > 1024 ? 1024 : samples;
00057                                 samples -= todo;
00058                                 adlib_getsample(buf, (Bits)todo);
00059                                 chan->AddSamples_m16( todo, buf );
00060                         }
00061                 }
00062 
00063                 virtual void Init( Bitu rate ) {
00064                         adlib_init((Bit32u)rate);
00065                 }
00066 
00067                 virtual void SaveState( std::ostream& stream ) {
00068                         const char pod_name[32] = "OPL2";
00069 
00070                         if( stream.fail() ) return;
00071 
00072 
00073                         WRITE_POD( &pod_name, pod_name );
00074 
00075                         //************************************************
00076                         //************************************************
00077                         //************************************************
00078 
00079                         adlib_savestate(stream);
00080                 }
00081 
00082                 virtual void LoadState( std::istream& stream ) {
00083                         char pod_name[32] = {0};
00084 
00085                         if( stream.fail() ) return;
00086 
00087 
00088                         // error checking
00089                         READ_POD( &pod_name, pod_name );
00090                         if( strcmp( pod_name, "OPL2" ) ) {
00091                                 stream.clear( std::istream::failbit | std::istream::badbit );
00092                                 return;
00093                         }
00094 
00095                         //************************************************
00096                         //************************************************
00097                         //************************************************
00098 
00099                         adlib_loadstate(stream);
00100                 }
00101 
00102                 ~Handler() {
00103                 }
00104         };
00105 }
00106 
00107 namespace OPL3 {
00108         #define OPLTYPE_IS_OPL3
00109         #include "opl.cpp"
00110 
00111         struct Handler : public Adlib::Handler {
00112                 virtual void WriteReg( Bit32u reg, Bit8u val ) {
00113                         adlib_write(reg,val);
00114                 }
00115                 virtual Bit32u WriteAddr( Bit32u port, Bit8u val ) {
00116                         adlib_write_index(port, val);
00117                         return opl_index;
00118                 }
00119                 virtual void Generate( MixerChannel* chan, Bitu samples ) {
00120                         Bit16s buf[1024*2];
00121                         while( samples > 0 ) {
00122                                 Bitu todo = samples > 1024 ? 1024 : samples;
00123                                 samples -= todo;
00124                                 adlib_getsample(buf, (Bits)todo);
00125                                 chan->AddSamples_s16( todo, buf );
00126                         }
00127                 }
00128 
00129                 virtual void Init( Bitu rate ) {
00130                         adlib_init((Bit32u)rate);
00131                 }
00132 
00133                 virtual void SaveState( std::ostream& stream ) {
00134                         const char pod_name[32] = "OPL3";
00135 
00136                         if( stream.fail() ) return;
00137 
00138 
00139                         WRITE_POD( &pod_name, pod_name );
00140 
00141                         //************************************************
00142                         //************************************************
00143                         //************************************************
00144 
00145                         adlib_savestate(stream);
00146                 }
00147 
00148                 virtual void LoadState( std::istream& stream ) {
00149                         char pod_name[32] = {0};
00150 
00151                         if( stream.fail() ) return;
00152 
00153 
00154                         // error checking
00155                         READ_POD( &pod_name, pod_name );
00156                         if( strcmp( pod_name, "OPL3" ) ) {
00157                                 stream.clear( std::istream::failbit | std::istream::badbit );
00158                                 return;
00159                         }
00160 
00161                         //************************************************
00162                         //************************************************
00163                         //************************************************
00164 
00165                         adlib_loadstate(stream);
00166                 }
00167 
00168                 ~Handler() {
00169                 }
00170         };
00171 }
00172 
00173 namespace NukedOPL {
00174 
00175 struct Handler : public Adlib::Handler {
00176         opl3_chip chip = {};
00177         Bit8u newm = 0;
00178 
00179         void WriteReg(Bit32u reg, Bit8u val) override {
00180                 OPL3_WriteRegBuffered(&chip, (Bit16u)reg, val);
00181                 if (reg == 0x105)
00182                         newm = reg & 0x01;
00183         }
00184 
00185         Bit32u WriteAddr(Bit32u port, Bit8u val) override {
00186                 Bit16u addr;
00187                 addr = val;
00188                 if ((port & 2) && (addr == 0x05 || newm)) {
00189                         addr |= 0x100;
00190                 }
00191                 return addr;
00192         }
00193 
00194         void Generate(MixerChannel *chan, Bitu samples) override {
00195                 int16_t buf[1024 * 2];
00196                 while (samples > 0) {
00197                         uint32_t todo = samples > 1024 ? 1024 : samples;
00198                         OPL3_GenerateStream(&chip, buf, todo);
00199                         chan->AddSamples_s16(todo, buf);
00200                         samples -= todo;
00201                 }
00202         }
00203 
00204         void Init(Bitu rate) override {
00205                 newm = 0;
00206                 OPL3_Reset(&chip, rate);
00207         }
00208 
00209         ~Handler() {
00210         }
00211 };
00212 
00213 }
00214 
00215 namespace MAMEOPL2 {
00216 
00217 struct Handler : public Adlib::Handler {
00218         void* chip = NULL;
00219 
00220         virtual void WriteReg(Bit32u reg, Bit8u val) {
00221                 ym3812_write(chip, 0, (int)reg);
00222                 ym3812_write(chip, 1, (int)val);
00223         }
00224         virtual Bit32u WriteAddr(Bit32u /*port*/, Bit8u val) {
00225                 return val;
00226         }
00227         virtual void Generate(MixerChannel* chan, Bitu samples) {
00228                 Bit16s buf[1024 * 2];
00229                 while (samples > 0) {
00230                         Bitu todo = samples > 1024 ? 1024 : samples;
00231                         samples -= todo;
00232                         ym3812_update_one(chip, buf, (int)todo);
00233                         chan->AddSamples_m16(todo, buf);
00234                 }
00235         }
00236         virtual void Init(Bitu rate) {
00237                 chip = ym3812_init(0, OPL2_INTERNAL_FREQ, (uint32_t)rate);
00238         }
00239         virtual void SaveState( std::ostream& stream ) {
00240         const char pod_name[32] = "MAMEOPL2";
00241 
00242         if( stream.fail() ) return;
00243 
00244 
00245         WRITE_POD( &pod_name, pod_name );
00246 
00247         //************************************************
00248         //************************************************
00249         //************************************************
00250 
00251         FMOPL_SaveState(chip, stream);
00252     }
00253 
00254     virtual void LoadState( std::istream& stream ) {
00255         char pod_name[32] = {0};
00256 
00257         if( stream.fail() ) return;
00258 
00259 
00260         // error checking
00261         READ_POD( &pod_name, pod_name );
00262         if( strcmp( pod_name, "MAMEOPL2" ) ) {
00263                 stream.clear( std::istream::failbit | std::istream::badbit );
00264                 return;
00265         }
00266 
00267         //************************************************
00268         //************************************************
00269         //************************************************
00270 
00271         FMOPL_LoadState(chip, stream);
00272     }
00273         ~Handler() {
00274                 ym3812_shutdown(chip);
00275         }
00276 };
00277 
00278 }
00279 
00280 
00281 namespace MAMEOPL3 {
00282 
00283 struct Handler : public Adlib::Handler {
00284         void* chip = NULL;
00285 
00286         virtual void WriteReg(Bit32u reg, Bit8u val) {
00287                 ymf262_write(chip, 0, (int)reg);
00288                 ymf262_write(chip, 1, (int)val);
00289         }
00290         virtual Bit32u WriteAddr(Bit32u /*port*/, Bit8u val) {
00291                 return val;
00292         }
00293         virtual void Generate(MixerChannel* chan, Bitu samples) {
00294                 //We generate data for 4 channels, but only the first 2 are connected on a pc
00295                 Bit16s buf[4][1024];
00296                 Bit16s result[1024][2];
00297                 Bit16s* buffers[4] = { buf[0], buf[1], buf[2], buf[3] };
00298 
00299                 while (samples > 0) {
00300                         Bitu todo = samples > 1024 ? 1024 : samples;
00301                         samples -= todo;
00302                         ymf262_update_one(chip, buffers, (int)todo);
00303                         //Interleave the samples before mixing
00304                         for (Bitu i = 0; i < todo; i++) {
00305                                 result[i][0] = buf[0][i];
00306                                 result[i][1] = buf[1][i];
00307                         }
00308                         chan->AddSamples_s16(todo, result[0]);
00309                 }
00310         }
00311         virtual void Init(Bitu rate) {
00312                 chip = ymf262_init(0, OPL3_INTERNAL_FREQ, (int)rate);
00313         }
00314         virtual void SaveState( std::ostream& stream ) {
00315         const char pod_name[32] = "MAMEOPL3";
00316 
00317         if( stream.fail() ) return;
00318 
00319 
00320         WRITE_POD( &pod_name, pod_name );
00321 
00322         //************************************************
00323         //************************************************
00324         //************************************************
00325 
00326         YMF_SaveState(chip, stream);
00327         }
00328     virtual void LoadState( std::istream& stream ) {
00329         char pod_name[32] = {0};
00330 
00331         if( stream.fail() ) return;
00332 
00333 
00334         // error checking
00335         READ_POD( &pod_name, pod_name );
00336         if( strcmp( pod_name, "MAMEOPL3" ) ) {
00337                 stream.clear( std::istream::failbit | std::istream::badbit );
00338                 return;
00339         }
00340 
00341         //************************************************
00342         //************************************************
00343         //************************************************
00344 
00345         YMF_LoadState(chip, stream);
00346         }
00347         ~Handler() {
00348                 ymf262_shutdown(chip);
00349         }
00350 };
00351 
00352 }
00353 
00354 #define RAW_SIZE 1024
00355 
00356 
00357 /*
00358         Main Adlib implementation
00359 
00360 */
00361 
00362 namespace Adlib {
00363 
00364 
00365 /* Raw DRO capture stuff */
00366 
00367 #ifdef _MSC_VER
00368 #pragma pack (1)
00369 #endif
00370 
00371 #define HW_OPL2 0
00372 #define HW_DUALOPL2 1
00373 #define HW_OPL3 2
00374 
00375 struct RawHeader {
00376         Bit8u id[8];                            /* 0x00, "DBRAWOPL" */
00377         Bit16u versionHigh;                     /* 0x08, size of the data following the m */
00378         Bit16u versionLow;                      /* 0x0a, size of the data following the m */
00379         Bit32u commands;                        /* 0x0c, Bit32u amount of command/data pairs */
00380         Bit32u milliseconds;            /* 0x10, Bit32u Total milliseconds of data in this chunk */
00381         Bit8u hardware;                         /* 0x14, Bit8u Hardware Type 0=opl2,1=dual-opl2,2=opl3 */
00382         Bit8u format;                           /* 0x15, Bit8u Format 0=cmd/data interleaved, 1 maybe all cdms, followed by all data */
00383         Bit8u compression;                      /* 0x16, Bit8u Compression Type, 0 = No Compression */
00384         Bit8u delay256;                         /* 0x17, Bit8u Delay 1-256 msec command */
00385         Bit8u delayShift8;                      /* 0x18, Bit8u (delay + 1)*256 */                       
00386         Bit8u conversionTableSize;      /* 0x191, Bit8u Raw Conversion Table size */
00387 } GCC_ATTRIBUTE(packed);
00388 #ifdef _MSC_VER
00389 #pragma pack()
00390 #endif
00391 /*
00392         The Raw Tables is < 128 and is used to convert raw commands into a full register index 
00393         When the high bit of a raw command is set it indicates the cmd/data pair is to be sent to the 2nd port
00394         After the conversion table the raw data follows immediatly till the end of the chunk
00395 */
00396 
00397 //Table to map the opl register to one <127 for dro saving
00398 class Capture {
00399         //127 entries to go from raw data to registers
00400         Bit8u ToReg[127];
00401         //How many entries in the ToPort are used
00402         Bit8u RawUsed;
00403         //256 entries to go from port index to raw data
00404         Bit8u ToRaw[256];
00405         Bit8u delay256;
00406         Bit8u delayShift8;
00407     RawHeader header = {};
00408 
00409         FILE*   handle;                         //File used for writing
00410         Bit32u  startTicks;                     //Start used to check total raw length on end
00411         Bit32u  lastTicks;                      //Last ticks when last last cmd was added
00412     Bit8u   buf[1024] = {};     //16 added for delay commands and what not
00413         Bit32u  bufUsed;
00414 #if 0//unused
00415     Bit8u       cmd[2];                         //Last cmd's sent to either ports
00416         bool    doneOpl3;
00417         bool    doneDualOpl2;
00418 #endif
00419         RegisterCache* cache;
00420 
00421         void MakeEntry( Bit8u reg, Bit8u& raw ) {
00422                 ToReg[ raw ] = reg;
00423                 ToRaw[ reg ] = raw;
00424                 raw++;
00425         }
00426         void MakeTables( void ) {
00427                 Bit8u index = 0;
00428                 memset( ToReg, 0xff, sizeof ( ToReg ) );
00429                 memset( ToRaw, 0xff, sizeof ( ToRaw ) );
00430                 //Select the entries that are valid and the index is the mapping to the index entry
00431                 MakeEntry( 0x01, index );                                       //0x01: Waveform select
00432                 MakeEntry( 0x04, index );                                       //104: Four-Operator Enable
00433                 MakeEntry( 0x05, index );                                       //105: OPL3 Mode Enable
00434                 MakeEntry( 0x08, index );                                       //08: CSW / NOTE-SEL
00435                 MakeEntry( 0xbd, index );                                       //BD: Tremolo Depth / Vibrato Depth / Percussion Mode / BD/SD/TT/CY/HH On
00436                 //Add the 32 byte range that hold the 18 operators
00437                 for ( int i = 0 ; i < 24; i++ ) {
00438                         if ( (i & 7) < 6 ) {
00439                                 MakeEntry(0x20 + i, index );            //20-35: Tremolo / Vibrato / Sustain / KSR / Frequency Multiplication Facto
00440                                 MakeEntry(0x40 + i, index );            //40-55: Key Scale Level / Output Level 
00441                                 MakeEntry(0x60 + i, index );            //60-75: Attack Rate / Decay Rate 
00442                                 MakeEntry(0x80 + i, index );            //80-95: Sustain Level / Release Rate
00443                                 MakeEntry(0xe0 + i, index );            //E0-F5: Waveform Select
00444                         }
00445                 }
00446                 //Add the 9 byte range that hold the 9 channels
00447                 for ( int i = 0 ; i < 9; i++ ) {
00448                         MakeEntry(0xa0 + i, index );                    //A0-A8: Frequency Number
00449                         MakeEntry(0xb0 + i, index );                    //B0-B8: Key On / Block Number / F-Number(hi bits) 
00450                         MakeEntry(0xc0 + i, index );                    //C0-C8: FeedBack Modulation Factor / Synthesis Type
00451                 }
00452                 //Store the amount of bytes the table contains
00453                 RawUsed = index;
00454 //              assert( RawUsed <= 127 );
00455                 delay256 = RawUsed;
00456                 delayShift8 = RawUsed+1; 
00457         }
00458 
00459         void ClearBuf( void ) {
00460                 fwrite( buf, 1, bufUsed, handle );
00461                 header.commands += bufUsed / 2;
00462                 bufUsed = 0;
00463         }
00464         void AddBuf( Bit8u raw, Bit8u val ) {
00465                 buf[bufUsed++] = raw;
00466                 buf[bufUsed++] = val;
00467                 if ( bufUsed >= sizeof( buf ) ) {
00468                         ClearBuf();
00469                 }
00470         }
00471         void AddWrite( Bit32u regFull, Bit8u val ) {
00472                 Bit8u regMask = regFull & 0xff;
00473                 /*
00474                         Do some special checks if we're doing opl3 or dualopl2 commands
00475                         Although you could pretty much just stick to always doing opl3 on the player side
00476                 */
00477                 //Enabling opl3 4op modes will make us go into opl3 mode
00478                 if ( header.hardware != HW_OPL3 && regFull == 0x104 && val && (*cache)[0x105] ) {
00479                         header.hardware = HW_OPL3;
00480                 } 
00481                 //Writing a keyon to a 2nd address enables dual opl2 otherwise
00482                 //Maybe also check for rhythm
00483                 if ( header.hardware == HW_OPL2 && regFull >= 0x1b0 && regFull <=0x1b8 && val ) {
00484                         header.hardware = HW_DUALOPL2;
00485                 }
00486                 Bit8u raw = ToRaw[ regMask ];
00487                 if ( raw == 0xff )
00488                         return;
00489                 if ( regFull & 0x100 )
00490                         raw |= 128;
00491                 AddBuf( raw, val );
00492         }
00493         void WriteCache( void  ) {
00494                 Bit16u i;
00495         Bit8u val;
00496                 /* Check the registers to add */
00497                 for (i=0;i<256;i++) {
00498                         //Skip the note on entries
00499                         if (i>=0xb0 && i<=0xb8) 
00500                                 continue;
00501                         val = (*cache)[ i ];
00502                         if (val) {
00503                                 AddWrite( i, val );
00504                         }
00505                         val = (*cache)[ 0x100u + i ];
00506                         if (val) {
00507                                 AddWrite( 0x100u + i, val );
00508                         }
00509                 }
00510         }
00511         void InitHeader( void ) {
00512                 memset( &header, 0, sizeof( header ) );
00513                 memcpy( header.id, "DBRAWOPL", 8 );
00514                 header.versionLow = 0;
00515                 header.versionHigh = 2;
00516                 header.delay256 = delay256;
00517                 header.delayShift8 = delayShift8;
00518                 header.conversionTableSize = RawUsed;
00519         }
00520         void CloseFile( void ) {
00521                 if ( handle ) {
00522                         ClearBuf();
00523                         /* Endianize the header and write it to beginning of the file */
00524                         var_write( &header.versionHigh, header.versionHigh );
00525                         var_write( &header.versionLow, header.versionLow );
00526                         var_write( &header.commands, header.commands );
00527                         var_write( &header.milliseconds, header.milliseconds );
00528                         fseek( handle, 0, SEEK_SET );
00529                         fwrite( &header, 1, sizeof( header ), handle );
00530                         fclose( handle );
00531                         handle = 0;
00532                 }
00533         }
00534 public:
00535         bool DoWrite( Bit32u regFull, Bit8u val ) {
00536                 Bit8u regMask = regFull & 0xff;
00537                 //Check the raw index for this register if we actually have to save it
00538                 if ( handle ) {
00539                         /*
00540                                 Check if we actually care for this to be logged, else just ignore it
00541                         */
00542                         Bit8u raw = ToRaw[ regMask ];
00543                         if ( raw == 0xff ) {
00544                                 return true;
00545                         }
00546                         /* Check if this command will not just replace the same value 
00547                            in a reg that doesn't do anything with it
00548                         */
00549                         if ( (*cache)[ regFull ] == val )
00550                                 return true;
00551                         /* Check how much time has passed */
00552                         Bitu passed = PIC_Ticks - lastTicks;
00553                         lastTicks = (Bit32u)PIC_Ticks;
00554                         header.milliseconds += (Bit32u)passed;
00555 
00556                         //if ( passed > 0 ) LOG_MSG( "Delay %d", passed ) ;
00557                         
00558                         // If we passed more than 30 seconds since the last command, we'll restart the the capture
00559                         if ( passed > 30000 ) {
00560                                 CloseFile();
00561                                 goto skipWrite; 
00562                         }
00563                         while (passed > 0) {
00564                                 if (passed < 257) {                     //1-256 millisecond delay
00565                                         AddBuf( delay256, (Bit8u)(passed - 1));
00566                                         passed = 0;
00567                                 } else {
00568                                         Bitu shift = (passed >> 8);
00569                                         passed -= shift << 8;
00570                                         AddBuf( delayShift8, (Bit8u)(shift - 1));
00571                                 }
00572                         }
00573                         AddWrite( regFull, val );
00574                         return true;
00575                 }
00576 skipWrite:
00577                 //Not yet capturing to a file here
00578                 //Check for commands that would start capturing, if it's not one of them return
00579                 if ( !(
00580                         //note on in any channel 
00581                         ( regMask>=0xb0 && regMask<=0xb8 && (val&0x020) ) ||
00582                         //Percussion mode enabled and a note on in any percussion instrument
00583                         ( regMask == 0xbd && ( (val&0x3f) > 0x20 ) )
00584                 )) {
00585                         return true;
00586                 }
00587                 handle = OpenCaptureFile("Raw Opl",".dro");
00588                 if (!handle)
00589                         return false;
00590                 InitHeader();
00591                 //Prepare space at start of the file for the header
00592                 fwrite( &header, 1, sizeof(header), handle );
00593                 /* write the Raw To Reg table */
00594                 fwrite( &ToReg, 1, RawUsed, handle );
00595                 /* Write the cache of last commands */
00596                 WriteCache( );
00597                 /* Write the command that triggered this */
00598                 AddWrite( regFull, val );
00599                 //Init the timing information for the next commands
00600                 lastTicks = (Bit32u)PIC_Ticks;  
00601                 startTicks = (Bit32u)PIC_Ticks;
00602                 return true;
00603         }
00604         Capture( RegisterCache* _cache ) {
00605                 cache = _cache;
00606                 handle = 0;
00607                 bufUsed = 0;
00608         startTicks = 0;
00609         lastTicks = 0;
00610                 MakeTables();
00611         }
00612         ~Capture() {
00613                 CloseFile();
00614         }
00615 
00616 };
00617 
00618 /*
00619 Chip
00620 */
00621 
00622 Chip::Chip() : timer0(80), timer1(320) {
00623 }
00624 
00625 bool Chip::Write( Bit32u reg, Bit8u val ) {
00626         if (adlib_force_timer_overflow_on_polling) {
00627                 /* detect end of polling loop by whether it writes */
00628                 last_poll = PIC_FullIndex();
00629                 poll_counter = 0;
00630         }
00631 
00632         switch ( reg ) {
00633         case 0x02:
00634                 timer0.SetCounter(val);
00635                 return true;
00636         case 0x03:
00637                 timer1.SetCounter(val);
00638                 return true;
00639         case 0x04:
00640                 double time;
00641                 time = PIC_FullIndex();
00642                 //Reset overflow in both timers
00643                 if ( val & 0x80 ) {
00644                         timer0.Reset( time );
00645                         timer1.Reset( time );
00646                 } else {
00647                         //timer 0 not masked
00648                         if (val&0x20) {
00649                                 if (val & 0x1) {
00650                                         timer0.Start(time);
00651                                 }
00652                                 else {
00653                                         timer0.Stop();
00654                                 }
00655                         }
00656                         //Timer 1 not masked
00657                         if (val&0x40) {
00658                                 if (val & 0x2) {
00659                                         timer1.Start(time);
00660                                 }
00661                                 else {
00662                                         timer1.Stop();
00663                                 }
00664                         }
00665                 }
00666                 return true;
00667         }
00668         return false;
00669 }
00670 
00671 
00672 Bit8u Chip::Read( ) {
00673         const double time( PIC_FullIndex() );
00674 
00675         if (adlib_force_timer_overflow_on_polling) {
00676                 static const double poll_timeout = 0.1; /* if polling more than 100us per second, do timeout */
00677 
00678                 if ((time-last_poll) > poll_timeout) {
00679                         poll_counter = 0;
00680                 }
00681                 else if (++poll_counter >= 50) {
00682 //                      LOG_MSG("Adlib polling hack triggered. Forcing timers to reset. Hope this helps your DOS game to detect Adlib.");
00683 
00684                         poll_counter = 0;
00685                         if (!timer0.overflow && timer0.enabled) {
00686                                 timer0.Stop();
00687                                 timer0.overflow = true;
00688                         }
00689                         if (!timer1.overflow && timer1.enabled) {
00690                                 timer1.Stop();
00691                                 timer1.overflow = true;
00692                         }
00693                 }
00694 
00695                 last_poll = time;
00696         }
00697 
00698         Bit8u ret = 0;
00699         //Overflow won't be set if a channel is masked
00700         if (timer0.Update(time)) {
00701                 ret |= 0x40;
00702                 ret |= 0x80;
00703         }
00704         if (timer1.Update(time)) {
00705                 ret |= 0x20;
00706                 ret |= 0x80;
00707         }
00708         return ret;
00709 }
00710 
00711 void Module::CacheWrite( Bit32u reg, Bit8u val ) {
00712         //capturing?
00713         if ( capture ) {
00714                 capture->DoWrite( reg, val );
00715         }
00716         //Store it into the cache
00717         cache[ reg ] = val;
00718 }
00719 
00720 void Module::DualWrite( Bit8u index, Bit8u reg, Bit8u val ) {
00721         //Make sure you don't use opl3 features
00722         //Don't allow write to disable opl3             
00723         if ( reg == 5 ) {
00724                 return;
00725         }
00726         //Only allow 4 waveforms
00727         if ( reg >= 0xE0 ) {
00728                 val &= 3;
00729         } 
00730         //Write to the timer?
00731         if ( chip[index].Write( reg, val ) ) 
00732                 return;
00733         //Enabling panning
00734         if ( reg >= 0xc0 && reg <=0xc8 ) {
00735                 val &= 0x0f;
00736                 val |= index ? 0xA0 : 0x50;
00737         }
00738         Bit32u fullReg = reg + (index ? 0x100u : 0u);
00739         handler->WriteReg( fullReg, val );
00740         CacheWrite( fullReg, val );
00741 }
00742 
00743 void Module::CtrlWrite( Bit8u val ) {
00744         switch ( ctrl.index ) {
00745         case 0x09: /* Left FM Volume */
00746                 ctrl.lvol = val;
00747                 goto setvol;
00748         case 0x0a: /* Right FM Volume */
00749                 ctrl.rvol = val;
00750 setvol:
00751                 if ( ctrl.mixer ) {
00752                         //Dune cdrom uses 32 volume steps in an apparent mistake, should be 128
00753                         mixerChan->SetVolume( (float)(ctrl.lvol&0x1f)/31.0f, (float)(ctrl.rvol&0x1f)/31.0f );
00754                 }
00755                 break;
00756         }
00757 }
00758 
00759 Bitu Module::CtrlRead( void ) {
00760         switch ( ctrl.index ) {
00761         case 0x00: /* Board Options */
00762                 return 0x70; //No options installed
00763         case 0x09: /* Left FM Volume */
00764                 return ctrl.lvol;
00765         case 0x0a: /* Right FM Volume */
00766                 return ctrl.rvol;
00767         case 0x15: /* Audio Relocation */
00768                 return 0x388 >> 3; //Cryo installer detection
00769         }
00770         return 0xff;
00771 }
00772 
00773 
00774 void Module::PortWrite( Bitu port, Bitu val, Bitu iolen ) {
00775     (void)iolen;//UNUSED
00776         //Keep track of last write time
00777         lastUsed = (Bit32u)PIC_Ticks;
00778         //Maybe only enable with a keyon?
00779         if ( !mixerChan->enabled ) {
00780                 mixerChan->Enable(true);
00781         }
00782         if ( port&1 ) {
00783                 switch ( mode ) {
00784                 case MODE_OPL3GOLD:
00785                         if ( port == 0x38b ) {
00786                                 if ( ctrl.active ) {
00787                                         CtrlWrite( (Bit8u)val );
00788                                         break;
00789                                 }
00790                         }
00791                         //Fall-through if not handled by control chip
00792                 case MODE_OPL2:
00793                 case MODE_OPL3:
00794                         if ( !chip[0].Write( reg.normal, (Bit8u)val ) ) {
00795                                 handler->WriteReg( reg.normal, (Bit8u)val );
00796                                 CacheWrite( reg.normal, (Bit8u)val );
00797                         }
00798                         break;
00799                 case MODE_DUALOPL2:
00800                         //Not a 0x??8 port, then write to a specific port
00801                         if ( !(port & 0x8) ) {
00802                                 Bit8u index = (Bit8u)(( port & 2 ) >> 1);
00803                                 DualWrite( index, reg.dual[index], (Bit8u)val );
00804                         } else {
00805                                 //Write to both ports
00806                                 DualWrite( 0, reg.dual[0], (Bit8u)val );
00807                                 DualWrite( 1, reg.dual[1], (Bit8u)val );
00808                         }
00809                         break;
00810                 }
00811         } else {
00812                 //Ask the handler to write the address
00813                 //Make sure to clip them in the right range
00814                 switch ( mode ) {
00815                 case MODE_OPL2:
00816                         reg.normal = handler->WriteAddr( (Bit32u)port, (Bit8u)val ) & 0xff;
00817                         break;
00818                 case MODE_OPL3GOLD:
00819                         if ( port == 0x38a ) {
00820                                 if ( val == 0xff ) {
00821                                         ctrl.active = true;
00822                                         break;
00823                                 } else if ( val == 0xfe ) {
00824                                         ctrl.active = false;
00825                                         break;
00826                                 } else if ( ctrl.active ) {
00827                                         ctrl.index = val & 0xff;
00828                                         break;
00829                                 }
00830                         }
00831                         //Fall-through if not handled by control chip
00832                 case MODE_OPL3:
00833                         reg.normal = handler->WriteAddr( (Bit32u)port, (Bit8u)val ) & 0x1ff;
00834                         break;
00835                 case MODE_DUALOPL2:
00836                         //Not a 0x?88 port, when write to a specific side
00837                         if ( !(port & 0x8) ) {
00838                                 Bit8u index = ( port & 2 ) >> 1;
00839                                 reg.dual[index] = val & 0xff;
00840                         } else {
00841                                 reg.dual[0] = val & 0xff;
00842                                 reg.dual[1] = val & 0xff;
00843                         }
00844                         break;
00845                 }
00846         }
00847 }
00848 
00849 
00850 Bitu Module::PortRead( Bitu port, Bitu iolen ) {
00851     (void)iolen;//UNUSED
00852         switch ( mode ) {
00853         case MODE_OPL2:
00854                 //We allocated 4 ports, so just return -1 for the higher ones
00855                 if ( !(port & 3 ) ) {
00856                         //Make sure the low bits are 6 on opl2
00857                         return chip[0].Read() | 0x6;
00858                 } else {
00859                         return 0xff;
00860                 }
00861         case MODE_OPL3GOLD:
00862                 if ( ctrl.active ) {
00863                         if ( port == 0x38a ) {
00864                                 return 0; //Control status, not busy
00865                         } else if ( port == 0x38b ) {
00866                                 return CtrlRead();
00867                         }
00868                 }
00869                 //Fall-through if not handled by control chip
00870         case MODE_OPL3:
00871                 //We allocated 4 ports, so just return -1 for the higher ones
00872                 if ( !(port & 3 ) ) {
00873                         return chip[0].Read();
00874                 } else {
00875                         return 0xff;
00876                 }
00877         case MODE_DUALOPL2:
00878                 //Only return for the lower ports
00879                 if ( port & 1 ) {
00880                         return 0xff;
00881                 }
00882                 //Make sure the low bits are 6 on opl2
00883                 return chip[ (port >> 1) & 1].Read() | 0x6;
00884         }
00885         return 0;
00886 }
00887 
00888 
00889 void Module::Init( Mode m ) {
00890         mode = m;
00891         switch ( mode ) {
00892         case MODE_OPL3:
00893         case MODE_OPL3GOLD:
00894         case MODE_OPL2:
00895                 break;
00896         case MODE_DUALOPL2:
00897                 //Setup opl3 mode in the hander
00898                 handler->WriteReg( 0x105, 1 );
00899                 //Also set it up in the cache so the capturing will start opl3
00900                 CacheWrite( 0x105, 1 );
00901                 break;
00902         }
00903 }
00904 
00905 } //namespace
00906 
00907 
00908 
00909 static Adlib::Module* module = 0;
00910 
00911 static void OPL_CallBack(Bitu len) {
00912         module->handler->Generate( module->mixerChan, len );
00913         //Disable the sound generation after 30 seconds of silence
00914         if ((PIC_Ticks - module->lastUsed) > 30000) {
00915                 Bitu i;
00916                 for (i=0xb0;i<0xb9;i++) if (module->cache[i]&0x20||module->cache[i+0x100]&0x20) break;
00917                 if (i==0xb9) module->mixerChan->Enable(false);
00918                 else module->lastUsed = (Bit32u)PIC_Ticks;
00919         }
00920 }
00921 
00922 static Bitu OPL_Read(Bitu port,Bitu iolen) {
00923     if (IS_PC98_ARCH) port >>= 8u; // C8D2h -> C8h, C9D2h -> C9h, OPL emulation looks only at bit 0.
00924 
00925         return module->PortRead( port, iolen );
00926 }
00927 
00928 void OPL_Write(Bitu port,Bitu val,Bitu iolen) {
00929     if (IS_PC98_ARCH) port >>= 8u; // C8D2h -> C8h, C9D2h -> C9h, OPL emulation looks only at bit 0.
00930 
00931         // if writing the data port, assume a change in OPL state that should be reflected immediately.
00932         // this is a way to render "sample accurate" without needing "sample accurate" mode in the mixer.
00933         // CHGOLF's Adlib digital audio hack works fine with this hack.
00934         if (port&1) module->mixerChan->FillUp();
00935 
00936         module->PortWrite( port, val, iolen );
00937 }
00938 
00939 /*
00940         Save the current state of the operators as instruments in an reality adlib tracker file
00941 */
00942 void SaveRad() {
00943         unsigned char b[16 * 1024];
00944         unsigned int w = 0;
00945 
00946         FILE* handle = OpenCaptureFile("RAD Capture",".rad");
00947         if ( !handle )
00948                 return;
00949         //Header
00950         fwrite( "RAD by REALiTY!!", 1, 16, handle );
00951         b[w++] = 0x10;          //version
00952         b[w++] = 0x06;          //default speed and no description
00953         //Write 18 instuments for all operators in the cache
00954         for ( unsigned int i = 0; i < 18; i++ ) {
00955                 Bit8u* set = module->cache + ( i / 9 ) * 256;
00956                 Bitu offset = ((i % 9) / 3) * 8 + (i % 3);
00957                 Bit8u* base = set + offset;
00958                 b[w++] = 1 + i;         //instrument number
00959                 b[w++] = base[0x23];
00960                 b[w++] = base[0x20];
00961                 b[w++] = base[0x43];
00962                 b[w++] = base[0x40];
00963                 b[w++] = base[0x63];
00964                 b[w++] = base[0x60];
00965                 b[w++] = base[0x83];
00966                 b[w++] = base[0x80];
00967                 b[w++] = set[0xc0 + (i % 9)];
00968                 b[w++] = base[0xe3];
00969                 b[w++] = base[0xe0];
00970         }
00971         b[w++] = 0;             //instrument 0, no more instruments following
00972         b[w++] = 1;             //1 pattern following
00973         //Zero out the remaing part of the file a bit to make rad happy
00974         for ( unsigned int i = 0; i < 64; i++ ) {
00975                 b[w++] = 0;
00976         }
00977         fwrite( b, 1, w, handle );
00978         fclose( handle );
00979 }
00980 
00981 
00982 void OPL_SaveRawEvent(bool pressed) {
00983         if (!pressed)
00984                 return;
00985     if (module == NULL)
00986         return;
00987 
00988 //      SaveRad();return;
00989         /* Check for previously opened wave file */
00990         if ( module->capture ) {
00991                 delete module->capture;
00992                 module->capture = 0;
00993                 LOG_MSG("Stopped Raw OPL capturing.");
00994         } else {
00995                 LOG_MSG("Preparing to capture Raw OPL, will start with first note played.");
00996                 module->capture = new Adlib::Capture( &module->cache );
00997         }
00998 
00999         mainMenu.get_item("mapper_caprawopl").check(module->capture != NULL).refresh_item(mainMenu);
01000 }
01001 
01002 namespace Adlib {
01003 
01004 Module::Module( Section* configuration ) : Module_base(configuration) {
01005     Bitu sb_addr=0,sb_irq=0,sb_dma=0;
01006         DOSBoxMenu::item *item;
01007     lastUsed = 0;
01008     mode = MODE_OPL2;
01009     capture = NULL;
01010     handler = NULL;
01011 
01012     SB_Get_Address(sb_addr,sb_irq,sb_dma);
01013 
01014     if (IS_PC98_ARCH && sb_addr == 0) {
01015         LOG_MSG("Adlib: Rejected configuration, OPL3 disabled in PC-98 mode");
01016         return; // OPL3 emulation must work alongside SB16 emulation
01017     }
01018 
01019         reg.dual[0] = 0;
01020         reg.dual[1] = 0;
01021         reg.normal = 0;
01022         ctrl.active = false;
01023         ctrl.index = 0;
01024         ctrl.lvol = 0xff;
01025         ctrl.rvol = 0xff;
01026         handler = 0;
01027         capture = 0;
01028 
01029         Section_prop * section=static_cast<Section_prop *>(configuration);
01030         Bitu base = (Bitu)section->Get_hex("sbbase");
01031         Bitu rate = (Bitu)section->Get_int("oplrate");
01032         //Make sure we can't select lower than 8000 to prevent fixed point issues
01033         if ( rate < 8000 )
01034                 rate = 8000;
01035         std::string oplemu( section->Get_string( "oplemu" ) );
01036         ctrl.mixer = section->Get_bool("sbmixer");
01037 
01038         adlib_force_timer_overflow_on_polling = section->Get_bool("adlib force timer overflow on detect");
01039 
01040         mixerChan = mixerObject.Install(OPL_CallBack,rate,"FM");
01041         //Used to be 2.0, which was measured to be too high. Exact value depends on card/clone.
01042         mixerChan->SetScale( 1.5f );  
01043 
01044         if (oplemu == "fast") {
01045                 handler = new DBOPL::Handler();
01046         }
01047         else if (oplemu == "compat") {
01048                 if (oplmode == OPL_opl2) {
01049                         handler = new OPL2::Handler();
01050                 }
01051                 else {
01052                         handler = new OPL3::Handler();
01053                 }
01054         } else if (oplemu == "nuked") {
01055                 handler = new NukedOPL::Handler();
01056         }
01057         else if (oplemu == "mame") {
01058                 if (oplmode == OPL_opl2) {
01059                         handler = new MAMEOPL2::Handler();
01060                 }
01061                 else {
01062                         handler = new MAMEOPL3::Handler();
01063                 }
01064         } else {
01065                 handler = new DBOPL::Handler();
01066         }
01067         handler->Init( rate );
01068         bool single = false;
01069         switch ( oplmode ) {
01070         case OPL_opl2:
01071                 single = true;
01072                 Init( Adlib::MODE_OPL2 );
01073                 break;
01074         case OPL_dualopl2:
01075                 Init( Adlib::MODE_DUALOPL2 );
01076                 break;
01077         case OPL_opl3:
01078                 Init( Adlib::MODE_OPL3 );
01079                 break;
01080         case OPL_opl3gold:
01081                 Init( Adlib::MODE_OPL3GOLD );
01082                 break;
01083         default:
01084                 break;
01085         }
01086 
01087     if (IS_PC98_ARCH) {
01088         /* needs to match the low 8 bits */
01089         assert(sb_addr != 0);
01090 
01091         //0xC8XX range (ex. C8D2)
01092         WriteHandler[0].Install(sb_addr+0xC800,OPL_Write,IO_MB, 1 );
01093         ReadHandler[0].Install(sb_addr+0xC800,OPL_Read,IO_MB, 1 );
01094         WriteHandler[1].Install(sb_addr+0xC900,OPL_Write,IO_MB, 1 );
01095         ReadHandler[1].Install(sb_addr+0xC900,OPL_Read,IO_MB, 1 );
01096         WriteHandler[2].Install(sb_addr+0xCA00,OPL_Write,IO_MB, 1 );
01097         ReadHandler[2].Install(sb_addr+0xCA00,OPL_Read,IO_MB, 1 );
01098         WriteHandler[3].Install(sb_addr+0xCB00,OPL_Write,IO_MB, 1 );
01099         ReadHandler[3].Install(sb_addr+0xCB00,OPL_Read,IO_MB, 1 );
01100         //0x20XX range (ex. 20D2)
01101         WriteHandler[4].Install(sb_addr+0x2000,OPL_Write,IO_MB, 1 );
01102         ReadHandler[4].Install(sb_addr+0x2000,OPL_Read,IO_MB, 1 );
01103         WriteHandler[5].Install(sb_addr+0x2100,OPL_Write,IO_MB, 1 );
01104         ReadHandler[5].Install(sb_addr+0x2100,OPL_Read,IO_MB, 1 );
01105         WriteHandler[6].Install(sb_addr+0x2200,OPL_Write,IO_MB, 1 );
01106         ReadHandler[6].Install(sb_addr+0x2200,OPL_Read,IO_MB, 1 );
01107         WriteHandler[7].Install(sb_addr+0x2300,OPL_Write,IO_MB, 1 );
01108         ReadHandler[7].Install(sb_addr+0x2300,OPL_Read,IO_MB, 1 );
01109         //0x28XX range (ex. 28D2)
01110         WriteHandler[8].Install(sb_addr+0x2800,OPL_Write,IO_MB, 1 );
01111         ReadHandler[8].Install(sb_addr+0x2800,OPL_Read,IO_MB, 1 );
01112         WriteHandler[9].Install(sb_addr+0x2900,OPL_Write,IO_MB, 1 );
01113 //      ReadHandler[9].Install(sb_addr+0x2900,OPL_Read,IO_MB, 1 );
01114     }
01115     else {
01116         //0x388 range
01117         WriteHandler[0].Install(0x388,OPL_Write,IO_MB, 4 );
01118         ReadHandler[0].Install(0x388,OPL_Read,IO_MB, 4 );
01119         //0x220 range
01120         if ( !single ) {
01121             WriteHandler[1].Install(base,OPL_Write,IO_MB, 4 );
01122             ReadHandler[1].Install(base,OPL_Read,IO_MB, 4 );
01123         }
01124         //0x228 range
01125         WriteHandler[2].Install(base+8,OPL_Write,IO_MB, 2);
01126         ReadHandler[2].Install(base+8,OPL_Read,IO_MB, 1);
01127     }
01128 
01129         MAPPER_AddHandler(OPL_SaveRawEvent,MK_nothing,0,"caprawopl","Cap OPL",&item);
01130         item->set_text("Record FM (OPL) output");
01131 }
01132 
01133 Module::~Module() {
01134         if ( capture ) {
01135                 delete capture;
01136         }
01137         if ( handler ) {
01138                 delete handler;
01139         }
01140 }
01141 
01142 //Initialize static members
01143 OPL_Mode Module::oplmode=OPL_none;
01144 
01145 }       //Adlib Namespace
01146 
01147 
01148 void OPL_Init(Section* sec,OPL_Mode oplmode) {
01149         Adlib::Module::oplmode = oplmode;
01150         module = new Adlib::Module( sec );
01151 }
01152 
01153 void OPL_ShutDown(Section* sec){
01154     (void)sec;//UNUSED
01155         delete module;
01156         module = 0;
01157 }
01158 
01159 // savestate support
01160 void Adlib::Module::SaveState( std::ostream& stream )
01161 {
01162         // - pure data
01163         WRITE_POD( &mode, mode );
01164         WRITE_POD( &reg, reg );
01165         WRITE_POD( &ctrl, ctrl );
01166         WRITE_POD( &oplmode, oplmode );
01167         WRITE_POD( &lastUsed, lastUsed );
01168 
01169         handler->SaveState(stream);
01170 
01171         WRITE_POD( &cache, cache );
01172         WRITE_POD( &chip, chip );
01173 }
01174 
01175 void Adlib::Module::LoadState( std::istream& stream )
01176 {
01177         // - pure data
01178         READ_POD( &mode, mode );
01179         READ_POD( &reg, reg );
01180         READ_POD( &ctrl, ctrl );
01181         READ_POD( &oplmode, oplmode );
01182         READ_POD( &lastUsed, lastUsed );
01183 
01184         handler->LoadState(stream);
01185 
01186         READ_POD( &cache, cache );
01187         READ_POD( &chip, chip );
01188 }
01189 
01190 void POD_Save_Adlib(std::ostream& stream)
01191 {
01192         const char pod_name[32] = "Adlib";
01193 
01194         if( stream.fail() ) return;
01195         if( !module ) return;
01196         if( !module->mixerChan ) return;
01197 
01198 
01199         WRITE_POD( &pod_name, pod_name );
01200 
01201         //************************************************
01202         //************************************************
01203         //************************************************
01204 
01205         module->SaveState(stream);
01206         module->mixerChan->SaveState(stream);
01207 }
01208 
01209 void POD_Load_Adlib(std::istream& stream)
01210 {
01211         char pod_name[32] = {0};
01212 
01213         if( stream.fail() ) return;
01214         if( !module ) return;
01215         if( !module->mixerChan ) return;
01216 
01217 
01218         // error checking
01219         READ_POD( &pod_name, pod_name );
01220         if( strcmp( pod_name, "Adlib" ) ) {
01221                 stream.clear( std::istream::failbit | std::istream::badbit );
01222                 return;
01223         }
01224 
01225         //************************************************
01226         //************************************************
01227         //************************************************
01228 
01229         module->LoadState(stream);
01230         module->mixerChan->LoadState(stream);
01231 }