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 #include <string.h> 00020 #include "dosbox.h" 00021 #include "inout.h" 00022 #include "mixer.h" 00023 #include "pic.h" 00024 #include "setup.h" 00025 #include "control.h" 00026 00027 #include "reSID/sid.h" 00028 00029 #define SID_FREQ 894886 00030 00031 static struct { 00032 SID2* sid; 00033 Bitu rate; 00034 Bitu basePort; 00035 Bitu last_used; 00036 MixerChannel * chan; 00037 } innova; 00038 00039 static void innova_write(Bitu port,Bitu val,Bitu iolen) { 00040 (void)iolen;//UNUSED 00041 if (!innova.last_used) { 00042 innova.chan->Enable(true); 00043 } 00044 innova.last_used=PIC_Ticks; 00045 00046 Bitu sidPort = port-innova.basePort; 00047 innova.sid->write((reg8)sidPort, (reg8)val); 00048 } 00049 00050 static Bitu innova_read(Bitu port,Bitu iolen) { 00051 (void)iolen;//UNUSED 00052 Bitu sidPort = port-innova.basePort; 00053 return innova.sid->read((reg8)sidPort); 00054 } 00055 00056 00057 static void INNOVA_CallBack(Bitu len) { 00058 if (!len) return; 00059 00060 cycle_count delta_t = (cycle_count)(SID_FREQ*len/innova.rate); 00061 short* buffer = (short*)MixTemp; 00062 Bitu bufindex = 0; 00063 00064 while(delta_t && bufindex != len) { 00065 bufindex += (Bitu)innova.sid->clock(delta_t, buffer+bufindex, (int)(len-bufindex)); 00066 } 00067 innova.chan->AddSamples_m16(len, buffer); 00068 00069 if (innova.last_used+5000<PIC_Ticks) { 00070 innova.last_used=0; 00071 innova.chan->Enable(false); 00072 } 00073 } 00074 00075 class INNOVA: public Module_base { 00076 private: 00077 IO_ReadHandleObject ReadHandler; 00078 IO_WriteHandleObject WriteHandler; 00079 MixerObject MixerChan; 00080 public: 00081 INNOVA(Section* configuration):Module_base(configuration) { 00082 Section_prop * section=static_cast<Section_prop *>(configuration); 00083 if(!section->Get_bool("innova")) return; 00084 innova.rate = (unsigned int)section->Get_int("samplerate"); 00085 innova.basePort = (unsigned int)section->Get_hex("sidbase"); 00086 sampling_method method = SAMPLE_FAST; 00087 int m = section->Get_int("quality"); 00088 switch(m) { 00089 case 1: method = SAMPLE_INTERPOLATE; break; 00090 case 2: method = SAMPLE_RESAMPLE_FAST; break; 00091 case 3: method = SAMPLE_RESAMPLE_INTERPOLATE; break; 00092 } 00093 00094 LOG_MSG("INNOVA:Initializing Innovation SSI-2001 (SID) emulation..."); 00095 00096 WriteHandler.Install(innova.basePort,innova_write,IO_MB,0x20); 00097 ReadHandler.Install(innova.basePort,innova_read,IO_MB,0x20); 00098 00099 innova.chan=MixerChan.Install(&INNOVA_CallBack,innova.rate,"INNOVA"); 00100 00101 innova.sid = new SID2; 00102 innova.sid->set_chip_model(MOS6581); 00103 innova.sid->enable_filter(true); 00104 innova.sid->enable_external_filter(true); 00105 innova.sid->set_sampling_parameters(SID_FREQ, method, (double)innova.rate, -1, 0.97); 00106 00107 innova.last_used=0; 00108 00109 LOG_MSG("INNOVA:... finished."); 00110 } 00111 ~INNOVA(){ 00112 delete innova.sid; 00113 } 00114 }; 00115 00116 static INNOVA* test = NULL; 00117 00118 static void INNOVA_ShutDown(Section* sec){ 00119 (void)sec;//UNUSED 00120 if (test != NULL) { 00121 delete test; 00122 test = NULL; 00123 } 00124 } 00125 00126 void INNOVA_OnReset(Section *sec) { 00127 (void)sec;//UNUSED 00128 if (test == NULL && !IS_PC98_ARCH) { 00129 LOG(LOG_MISC,LOG_DEBUG)("Allocating Innova emulation"); 00130 test = new INNOVA(control->GetSection("innova")); 00131 } 00132 } 00133 00134 void INNOVA_Init() { 00135 LOG(LOG_MISC,LOG_DEBUG)("Initializing INNOVA emulation"); 00136 00137 AddExitFunction(AddExitFunctionFuncPair(INNOVA_ShutDown),true); 00138 AddVMEventFunction(VM_EVENT_RESET,AddVMEventFunctionFuncPair(INNOVA_OnReset)); 00139 } 00140