DOSBox-X
|
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 ); 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 ); 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 }