diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 000000000..3ece4a3e9 --- /dev/null +++ b/.github/issue_template.md @@ -0,0 +1 @@ + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 95b3229f1..980062769 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ defaults: shell: bash env: - BUILD_TYPE: Release + BUILD_TYPE: Debug jobs: build: @@ -20,13 +20,13 @@ jobs: config: - { name: 'Windows MSVC x86', os: windows-latest, compiler: msvc, arch: x86 } - { name: 'Windows MSVC x86_64', os: windows-latest, compiler: msvc, arch: x86_64 } - - { name: 'Windows MinGW x86', os: ubuntu-20.04, compiler: mingw, arch: x86 } - - { name: 'Windows MinGW x86_64', os: ubuntu-20.04, compiler: mingw, arch: x86_64 } + ##- { name: 'Windows MinGW x86', os: ubuntu-20.04, compiler: mingw, arch: x86 } + ##- { name: 'Windows MinGW x86_64', os: ubuntu-20.04, compiler: mingw, arch: x86_64 } - { name: 'macOS x86_64', os: macos-latest, arch: x86_64 } - { name: 'macOS ARM', os: macos-latest, arch: arm64 } - - { name: 'Linux x86_64', os: ubuntu-18.04, arch: x86_64 } + ##- { name: 'Linux x86_64', os: ubuntu-18.04, arch: x86_64 } #- { name: 'Linux ARM', os: ubuntu-18.04, arch: armhf } - fail-fast: true + fail-fast: false name: ${{ matrix.config.name }} runs-on: ${{ matrix.config.os }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 305ccacdb..9af0ba741 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -753,7 +753,7 @@ if (WARNINGS_ARE_ERRORS) ) endif() -if (MSVC) +if (WIN32) add_executable(furnace WIN32 ${USED_SOURCES}) elseif(ANDROID AND NOT TERMUX) add_library(furnace SHARED ${USED_SOURCES}) diff --git a/android/app/build.gradle b/android/app/build.gradle index 92a79e4d6..9f0cb2594 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -15,8 +15,8 @@ android { } minSdkVersion 21 targetSdkVersion 26 - versionCode 113 - versionName "dev113" + versionCode 136 + versionName "dev136" externalNativeBuild { cmake { arguments "-DANDROID_APP_PLATFORM=android-21", "-DANDROID_STL=c++_static" diff --git a/demos/arcade/ToHeart_QoH98_TPower_Asuka120Style.fur b/demos/arcade/ToHeart_QoH98_TPower_Asuka120Style.fur new file mode 100644 index 000000000..ce0c73bad Binary files /dev/null and b/demos/arcade/ToHeart_QoH98_TPower_Asuka120Style.fur differ diff --git a/demos/genesis/Puyopuyo~n_DopplegangerArle-TsuuStyle.fur b/demos/genesis/Puyopuyo~n_DopplegangerArle-TsuuStyle.fur new file mode 100644 index 000000000..53866b5b2 Binary files /dev/null and b/demos/genesis/Puyopuyo~n_DopplegangerArle-TsuuStyle.fur differ diff --git a/demos/misc/Inner Machinations YM2610B.fur b/demos/misc/Inner Machinations YM2610B.fur new file mode 100644 index 000000000..b6e72a593 Binary files /dev/null and b/demos/misc/Inner Machinations YM2610B.fur differ diff --git a/demos/misc/lagrange_point_2023_opm.fur b/demos/misc/lagrange_point_2023_opm.fur new file mode 100644 index 000000000..31832bc93 Binary files /dev/null and b/demos/misc/lagrange_point_2023_opm.fur differ diff --git a/demos/msx/Lagrange_Point.fur b/demos/msx/Lagrange_Point.fur deleted file mode 100644 index bff5248c3..000000000 Binary files a/demos/msx/Lagrange_Point.fur and /dev/null differ diff --git a/demos/multichip/Sky Chaze Zone 32X.fur b/demos/multichip/Sky Chaze Zone 32X.fur new file mode 100644 index 000000000..3a19b4166 Binary files /dev/null and b/demos/multichip/Sky Chaze Zone 32X.fur differ diff --git a/demos/multichip/colab.fur b/demos/multichip/colab.fur new file mode 100644 index 000000000..4d104da1a Binary files /dev/null and b/demos/multichip/colab.fur differ diff --git a/demos/opl/PhantomBreakerBattleGrounds_ShinjukuStage-OPL3.fur b/demos/opl/PhantomBreakerBattleGrounds_ShinjukuStage-OPL3.fur new file mode 100644 index 000000000..3ba0598e0 Binary files /dev/null and b/demos/opl/PhantomBreakerBattleGrounds_ShinjukuStage-OPL3.fur differ diff --git a/demos/opl/TeamInnocent-BGM4-OPL3Plus.fur b/demos/opl/TeamInnocent-BGM4-OPL3Plus.fur new file mode 100644 index 000000000..9043c2635 Binary files /dev/null and b/demos/opl/TeamInnocent-BGM4-OPL3Plus.fur differ diff --git a/demos/snes/tetristheme.fur b/demos/snes/tetristheme.fur new file mode 100644 index 000000000..e7ab8578c Binary files /dev/null and b/demos/snes/tetristheme.fur differ diff --git a/demos/x16/Melody of Certain Feelings.fur b/demos/x16/Melody of Certain Feelings.fur new file mode 100644 index 000000000..eacec7a9a Binary files /dev/null and b/demos/x16/Melody of Certain Feelings.fur differ diff --git a/demos/x16/dance with me.fur b/demos/x16/dance with me.fur new file mode 100644 index 000000000..7cb53305a Binary files /dev/null and b/demos/x16/dance with me.fur differ diff --git a/extern/opl/opl3.c b/extern/opl/opl3.c index b0a090c5f..3358f0335 100644 --- a/extern/opl/opl3.c +++ b/extern/opl/opl3.c @@ -946,10 +946,8 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel) } } -static void OPL3_ChannelWriteC0(opl3_channel *channel, uint8_t data) +static void OPL3_ChannelUpdateAlg(opl3_channel *channel) { - channel->fb = (data & 0x0e) >> 1; - channel->con = data & 0x01; channel->alg = channel->con; if (channel->chip->newm) { @@ -974,14 +972,25 @@ static void OPL3_ChannelWriteC0(opl3_channel *channel, uint8_t data) { OPL3_ChannelSetupAlg(channel); } +} + +static void OPL3_ChannelWriteC0(opl3_channel *channel, uint8_t data) +{ + channel->fb = (data & 0x0e) >> 1; + channel->con = data & 0x01; + OPL3_ChannelUpdateAlg(channel); if (channel->chip->newm) { channel->cha = ((data >> 4) & 0x01) ? ~0 : 0; channel->chb = ((data >> 5) & 0x01) ? ~0 : 0; + channel->chc = ((data >> 6) & 0x01) ? ~0 : 0; + channel->chd = ((data >> 7) & 0x01) ? ~0 : 0; } else { channel->cha = channel->chb = (uint16_t)~0; + // TODO: Verify on real chip if DAC2 output is disabled in compat mode + channel->chc = channel->chd = 0; } #if OPL_ENABLE_STEREOEXT if (!channel->chip->stereoext) @@ -1066,11 +1075,14 @@ static void OPL3_ChannelSet4Op(opl3_chip *chip, uint8_t data) { chip->channel[chnum].chtype = ch_4op; chip->channel[chnum + 3].chtype = ch_4op2; + OPL3_ChannelUpdateAlg(&chip->channel[chnum]); } else { chip->channel[chnum].chtype = ch_2op; chip->channel[chnum + 3].chtype = ch_2op; + OPL3_ChannelUpdateAlg(&chip->channel[chnum]); + OPL3_ChannelUpdateAlg(&chip->channel[chnum+3]); } } } @@ -1096,17 +1108,18 @@ static void OPL3_ProcessSlot(opl3_slot *slot) OPL3_SlotGenerate(slot); } -void OPL3_Generate(opl3_chip *chip, int16_t *buf) +inline void OPL3_Generate4Ch(opl3_chip *chip, int16_t *buf4) { opl3_channel *channel; opl3_writebuf *writebuf; int16_t **out; - int32_t mix; + int32_t mix[2]; uint8_t ii; int16_t accm; uint8_t shift = 0; - buf[1] = OPL3_ClipSample(chip->mixbuff[1]); + buf4[1] = OPL3_ClipSample(chip->mixbuff[1]); + buf4[3] = OPL3_ClipSample(chip->mixbuff[3]); #if OPL_QUIRK_CHANNELSAMPLEDELAY for (ii = 0; ii < 15; ii++) @@ -1117,7 +1130,7 @@ void OPL3_Generate(opl3_chip *chip, int16_t *buf) OPL3_ProcessSlot(&chip->slot[ii]); } - mix = 0; + mix[0] = mix[1] = 0; for (ii = 0; ii < 18; ii++) { channel = &chip->channel[ii]; @@ -1125,12 +1138,14 @@ void OPL3_Generate(opl3_chip *chip, int16_t *buf) out = channel->out; accm = *out[0] + *out[1] + *out[2] + *out[3]; #if OPL_ENABLE_STEREOEXT - mix += (int16_t)((accm * channel->leftpan) >> 16); + mix[0] += (int16_t)((accm * channel->leftpan) >> 16); #else - mix += (int16_t)(accm & channel->cha); -#endif + mix[0] += (int16_t)(accm & channel->cha); + #endif + mix[1] += (int16_t)(accm & channel->chc); } - chip->mixbuff[0] = mix; + chip->mixbuff[0] = mix[0]; + chip->mixbuff[2] = mix[1]; #if OPL_QUIRK_CHANNELSAMPLEDELAY for (ii = 15; ii < 18; ii++) @@ -1139,7 +1154,8 @@ void OPL3_Generate(opl3_chip *chip, int16_t *buf) } #endif - buf[0] = OPL3_ClipSample(chip->mixbuff[0]); + buf4[0] = OPL3_ClipSample(chip->mixbuff[0]); + buf4[2] = OPL3_ClipSample(chip->mixbuff[2]); #if OPL_QUIRK_CHANNELSAMPLEDELAY for (ii = 18; ii < 33; ii++) @@ -1148,7 +1164,7 @@ void OPL3_Generate(opl3_chip *chip, int16_t *buf) } #endif - mix = 0; + mix[0] = mix[1] = 0; for (ii = 0; ii < 18; ii++) { channel = &chip->channel[ii]; @@ -1156,12 +1172,14 @@ void OPL3_Generate(opl3_chip *chip, int16_t *buf) out = channel->out; accm = *out[0] + *out[1] + *out[2] + *out[3]; #if OPL_ENABLE_STEREOEXT - mix += (int16_t)((accm * channel->rightpan) >> 16); + mix[0] += (int16_t)((accm * channel->rightpan) >> 16); #else - mix += (int16_t)(accm & channel->chb); -#endif + mix[0] += (int16_t)(accm & channel->chb); + #endif + mix[1] += (int16_t)(accm & channel->chd); } - chip->mixbuff[1] = mix; + chip->mixbuff[1] = mix[0]; + chip->mixbuff[3] = mix[1]; #if OPL_QUIRK_CHANNELSAMPLEDELAY for (ii = 33; ii < 36; ii++) @@ -1236,22 +1254,44 @@ void OPL3_Generate(opl3_chip *chip, int16_t *buf) chip->writebuf_samplecnt++; } -void OPL3_GenerateResampled(opl3_chip *chip, int16_t *buf) +void OPL3_Generate(opl3_chip *chip, int16_t *buf) +{ + int16_t samples[4]; + OPL3_Generate4Ch(chip, samples); + buf[0] = samples[0]; + buf[1] = samples[1]; +} + +void OPL3_Generate4ChResampled(opl3_chip *chip, int16_t *buf4) { while (chip->samplecnt >= chip->rateratio) { chip->oldsamples[0] = chip->samples[0]; chip->oldsamples[1] = chip->samples[1]; - OPL3_Generate(chip, chip->samples); + chip->oldsamples[2] = chip->samples[2]; + chip->oldsamples[3] = chip->samples[3]; + OPL3_Generate4Ch(chip, chip->samples); chip->samplecnt -= chip->rateratio; } - buf[0] = (int16_t)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) - + chip->samples[0] * chip->samplecnt) / chip->rateratio); - buf[1] = (int16_t)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt) - + chip->samples[1] * chip->samplecnt) / chip->rateratio); + buf4[0] = (int16_t)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) + + chip->samples[0] * chip->samplecnt) / chip->rateratio); + buf4[1] = (int16_t)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt) + + chip->samples[1] * chip->samplecnt) / chip->rateratio); + buf4[2] = (int16_t)((chip->oldsamples[2] * (chip->rateratio - chip->samplecnt) + + chip->samples[2] * chip->samplecnt) / chip->rateratio); + buf4[3] = (int16_t)((chip->oldsamples[3] * (chip->rateratio - chip->samplecnt) + + chip->samples[3] * chip->samplecnt) / chip->rateratio); chip->samplecnt += 1 << RSM_FRAC; } +void OPL3_GenerateResampled(opl3_chip *chip, int16_t *buf) +{ + int16_t samples[4]; + OPL3_Generate4ChResampled(chip, samples); + buf[0] = samples[0]; + buf[1] = samples[1]; +} + void OPL3_Reset(opl3_chip *chip, uint32_t samplerate) { opl3_slot *slot; @@ -1464,9 +1504,26 @@ void OPL3_WriteRegBuffered(opl3_chip *chip, uint16_t reg, uint8_t v) chip->writebuf_last = (writebuf_last + 1) % OPL_WRITEBUF_SIZE; } +void OPL3_Generate4ChStream(opl3_chip *chip, int16_t *sndptr1, int16_t *sndptr2, uint32_t numsamples) +{ + uint_fast32_t i; + int16_t samples[4]; + + for(i = 0; i < numsamples; i++) + { + OPL3_Generate4ChResampled(chip, samples); + sndptr1[0] = samples[0]; + sndptr1[1] = samples[1]; + sndptr2[0] = samples[2]; + sndptr2[1] = samples[3]; + sndptr1 += 2; + sndptr2 += 2; + } +} + void OPL3_GenerateStream(opl3_chip *chip, int16_t *sndptr, uint32_t numsamples) { - uint32_t i; + uint_fast32_t i; for(i = 0; i < numsamples; i++) { diff --git a/extern/opl/opl3.h b/extern/opl/opl3.h index 6ad33f3e0..8d5153237 100644 --- a/extern/opl/opl3.h +++ b/extern/opl/opl3.h @@ -101,6 +101,7 @@ struct _opl3_channel { uint8_t alg; uint8_t ksv; uint16_t cha, chb; + uint16_t chc, chd; uint8_t ch_num; uint8_t muted; }; @@ -129,7 +130,7 @@ struct _opl3_chip { uint8_t tremoloshift; uint32_t noise; int16_t zeromod; - int32_t mixbuff[2]; + int32_t mixbuff[4]; uint8_t rm_hh_bit2; uint8_t rm_hh_bit3; uint8_t rm_hh_bit7; @@ -144,8 +145,8 @@ struct _opl3_chip { /* OPL3L */ int32_t rateratio; int32_t samplecnt; - int16_t oldsamples[2]; - int16_t samples[2]; + int16_t oldsamples[4]; + int16_t samples[4]; uint64_t writebuf_samplecnt; uint32_t writebuf_cur; @@ -161,6 +162,10 @@ void OPL3_WriteReg(opl3_chip *chip, uint16_t reg, uint8_t v); void OPL3_WriteRegBuffered(opl3_chip *chip, uint16_t reg, uint8_t v); void OPL3_GenerateStream(opl3_chip *chip, int16_t *sndptr, uint32_t numsamples); +void OPL3_Generate4Ch(opl3_chip *chip, int16_t *buf4); +void OPL3_Generate4ChResampled(opl3_chip *chip, int16_t *buf4); +void OPL3_Generate4ChStream(opl3_chip *chip, int16_t *sndptr1, int16_t *sndptr2, uint32_t numsamples); + #ifdef __cplusplus } #endif diff --git a/papers/format.md b/papers/format.md index ab8cacd64..6522760e8 100644 --- a/papers/format.md +++ b/papers/format.md @@ -32,6 +32,9 @@ these fields are 0 in format versions prior to 100 (0.6pre1). the format versions are: +- 136: Furnace dev136 +- 135: Furnace dev135 +- 134: Furnace dev134 - 133: Furnace 0.6pre3 - 132: Furnace 0.6pre2 - 131: Furnace dev131 @@ -386,8 +389,42 @@ size | description STR | song author (Japanese) STR | system name (Japanese) STR | album/category/game name (Japanese) + --- | **extra chip output settings (× chipCount)** (>=135) + 4f | chip volume + 4f | chip panning + 4f | chip front/rear balance + --- | **patchbay** (>=135) + 4 | patchbay connection count + 4?? | patchbay + | - see next section for more details. + 1 | automatic patchbay (>=136) ``` +# patchbay + +Furnace dev135 adds a "patchbay" which allows for arbitrary connection of chip outputs to system outputs. +it eventually will allow connecting outputs to effects and so on. + +a connection is represented as an unsigned int in the following format: + +- bit 16-31: source port +- bit 0-15: destination port + +a port is in the following format (hexadecimal): `xxxy` + +- `xxx` (bit 4 to 15) represents a portset. +- `y` (bit 0 to 3) is the port in that portset. + +reserved input portsets: +- `000`: system outputs +- `FFF`: "null" portset + +reserved output portsets: +- `000` through `01F`: chip outputs +- `FFD`: wave/sample preview +- `FFE`: metronome +- `FFF`: "null" portset + # subsong from version 95 onwards, Furnace supports storing multiple songs on a single file. diff --git a/src/engine/defines.h b/src/engine/defines.h index 2cd4b692f..3461a52db 100644 --- a/src/engine/defines.h +++ b/src/engine/defines.h @@ -33,4 +33,7 @@ // sample related #define DIV_MAX_SAMPLE_TYPE 4 +// dispatch +#define DIV_MAX_OUTPUTS 16 + #endif diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 46a49cb4a..1970afed6 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -213,6 +213,8 @@ enum DivDispatchCmds { DIV_CMD_MACRO_OFF, // (which) DIV_CMD_MACRO_ON, // (which) + DIV_CMD_SURROUND_PANNING, // (out, val) + DIV_ALWAYS_SET_VOLUME, // () -> alwaysSetVol DIV_CMD_MAX @@ -322,12 +324,10 @@ class DivDispatch { /** * fill a buffer with sound data. - * @param bufL the left or mono channel buffer. - * @param bufR the right channel buffer. - * @param start the start offset. + * @param buf pointers to output buffers. * @param len the amount of samples to fill. */ - virtual void acquire(short* bufL, short* bufR, size_t start, size_t len); + virtual void acquire(short** buf, size_t len); /** * fill a write stream with data (e.g. for software-mixed PCM). @@ -413,10 +413,10 @@ class DivDispatch { virtual void muteChannel(int ch, bool mute); /** - * test whether this dispatch outputs audio in two channels. - * @return whether it does. + * get the number of outputs this dispatch provides. + * @return number of outputs (usually 1 or 2 but may be more). SHALL NOT be less than one. */ - virtual bool isStereo(); + virtual int getOutputCount(); /** * test whether sending a key off command to a channel should reset arp too. diff --git a/src/engine/dispatchContainer.cpp b/src/engine/dispatchContainer.cpp index 5768bde38..4e4e5d96c 100644 --- a/src/engine/dispatchContainer.cpp +++ b/src/engine/dispatchContainer.cpp @@ -80,79 +80,131 @@ #include "song.h" void DivDispatchContainer::setRates(double gotRate) { - blip_set_rates(bb[0],dispatch->rate,gotRate); - blip_set_rates(bb[1],dispatch->rate,gotRate); + int outs=dispatch->getOutputCount(); + + for (int i=0; irate,gotRate); + } + rateMemory=gotRate; } void DivDispatchContainer::setQuality(bool lowQual) { lowQuality=lowQual; } +void DivDispatchContainer::grow(size_t size) { + bbInLen=size; + for (int i=0; igetOutputCount(); \ + \ + /* create missing buffers if any */ \ + bool mustClear=false; \ + for (int i=0; irate,rateMemory); \ + \ + if (bbIn[i]==NULL) bbIn[i]=new short[bbInLen]; \ + if (bbOut[i]==NULL) bbOut[i]=new short[bbInLen]; \ + memset(bbIn[i],0,bbInLen*sizeof(short)); \ + memset(bbOut[i],0,bbInLen*sizeof(short)); \ + mustClear=true; \ + } \ + } \ + if (mustClear) clear(); \ + void DivDispatchContainer::acquire(size_t offset, size_t count) { - dispatch->acquire(bbIn[0],bbIn[1],offset,count); + CHECK_MISSING_BUFS; + + for (int i=0; i=outs) { + bbInMapped[i]=NULL; + } else { + if (bbIn[i]==NULL) { + bbInMapped[i]=NULL; + } else { + bbInMapped[i]=&bbIn[i][offset]; + } + } + } + dispatch->acquire(bbInMapped,count); } void DivDispatchContainer::flush(size_t count) { - blip_read_samples(bb[0],bbOut[0],count,0); + int outs=dispatch->getOutputCount(); - if (dispatch->isStereo()) { - blip_read_samples(bb[1],bbOut[1],count,0); + for (int i=0; i0) { dcOffCompensation=false; - prevSample[0]=bbIn[0][0]; - if (dispatch->isStereo()) prevSample[1]=bbIn[1][0]; + for (int i=0; iisStereo()) for (size_t i=0; iisStereo()) for (size_t i=0; i0) { for (size_t i=totalRead; iisStereo()) { - blip_end_frame(bb[1],runtotal); - blip_read_samples(bb[1],bbOut[1]+offset,size,0); - } } void DivDispatchContainer::clear() { - blip_clear(bb[0]); - blip_clear(bb[1]); - temp[0]=0; - temp[1]=0; - prevSample[0]=0; - prevSample[1]=0; + for (int i=0; igetDCOffRequired()) { dcOffCompensation=true; } @@ -166,26 +218,10 @@ void DivDispatchContainer::clear() { } void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, double gotRate, const DivConfig& flags) { + // quit if we already initialized if (dispatch!=NULL) return; - bb[0]=blip_new(32768); - if (bb[0]==NULL) { - logE("not enough memory!"); - return; - } - - bb[1]=blip_new(32768); - if (bb[1]==NULL) { - logE("not enough memory!"); - return; - } - - bbOut[0]=new short[32768]; - bbOut[1]=new short[32768]; - bbIn[0]=new short[32768]; - bbIn[1]=new short[32768]; - bbInLen=32768; - + // initialize chip switch (sys) { case DIV_SYSTEM_YMU759: dispatch=new DivPlatformOPL; @@ -461,6 +497,23 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do break; } dispatch->init(eng,chanCount,gotRate,flags); + + // initialize output buffers + int outs=dispatch->getOutputCount(); + bbInLen=32768; + + for (int i=0; iwriteC(2); // length w->writeC(c.value); w->writeC(c.value2); @@ -897,11 +907,7 @@ void DivEngine::runExportThread() { for (int i=0; iisStereo()) { - si[i].channels=2; - } else { - si[i].channels=1; - } + si[i].channels=disCont[i].dispatch->getOutputCount(); si[i].format=SF_FORMAT_WAV|SF_FORMAT_PCM_16; } @@ -944,11 +950,12 @@ void DivEngine::runExportThread() { if (isFadingOut) { double mul=(1.0-((double)curFadeOutSample/(double)fadeOutSamples)); for (int i=0; iisStereo()) { - sysBuf[i][j]=(double)disCont[i].bbOut[0][j]*mul; - } else { - sysBuf[i][j<<1]=(double)disCont[i].bbOut[0][j]*mul; - sysBuf[i][1+(j<<1)]=(double)disCont[i].bbOut[1][j]*mul; + for (int k=0; k=fadeOutSamples) { @@ -957,11 +964,12 @@ void DivEngine::runExportThread() { } } else { for (int i=0; iisStereo()) { - sysBuf[i][j]=disCont[i].bbOut[0][j]; - } else { - sysBuf[i][j<<1]=disCont[i].bbOut[0][j]; - sysBuf[i][1+(j<<1)]=disCont[i].bbOut[1][j]; + for (int k=0; k-1 && j>=lastLoopPos && totalLoops>=exportLoopCount) { @@ -1333,8 +1341,8 @@ String DivEngine::decodeSysDesc(String desc) { int val=0; int curStage=0; int sysID=0; - int sysVol=0; - int sysPan=0; + float sysVol=0; + float sysPan=0; int sysFlags=0; int curSys=0; desc+=' '; // ha @@ -1349,24 +1357,25 @@ String DivEngine::decodeSysDesc(String desc) { curStage++; break; case 1: - sysVol=val; + sysVol=(float)val/64.0f; curStage++; break; case 2: - sysPan=val; + sysPan=(float)val/127.0f; curStage++; break; case 3: sysFlags=val; if (sysID!=0) { - if (sysVol<-128) sysVol=-128; - if (sysVol>127) sysVol=127; - if (sysPan<-128) sysPan=-128; - if (sysPan>127) sysPan=127; + if (sysVol<-1.0f) sysVol=-1.0f; + if (sysVol>1.0f) sysVol=1.0f; + if (sysPan<-1.0f) sysPan=-1.0f; + if (sysPan>1.0f) sysPan=1.0f; newDesc.set(fmt::sprintf("id%d",curSys),sysID); newDesc.set(fmt::sprintf("vol%d",curSys),sysVol); newDesc.set(fmt::sprintf("pan%d",curSys),sysPan); + newDesc.set(fmt::sprintf("fr%d",curSys),0.0f); DivConfig newFlagsC; newFlagsC.clear(); convertOldFlags((unsigned int)sysFlags,newFlagsC,systemFromFileFur(sysID)); @@ -1396,7 +1405,7 @@ String DivEngine::decodeSysDesc(String desc) { return newDesc.toBase64(); } -void DivEngine::initSongWithDesc(const char* description, bool inBase64) { +void DivEngine::initSongWithDesc(const char* description, bool inBase64, bool oldVol) { int chanCount=0; DivConfig c; if (inBase64) { @@ -1415,9 +1424,16 @@ void DivEngine::initSongWithDesc(const char* description, bool inBase64) { song.system[index]=DIV_SYSTEM_NULL; break; } - song.systemVol[index]=c.getInt(fmt::sprintf("vol%d",index),DIV_SYSTEM_NULL); - song.systemPan[index]=c.getInt(fmt::sprintf("pan%d",index),DIV_SYSTEM_NULL); + song.systemVol[index]=c.getFloat(fmt::sprintf("vol%d",index),1.0f); + song.systemPan[index]=c.getFloat(fmt::sprintf("pan%d",index),0.0f); + song.systemPanFR[index]=c.getFloat(fmt::sprintf("fr%d",index),0.0f); song.systemFlags[index].clear(); + + if (oldVol) { + song.systemVol[index]/=64.0f; + song.systemPan[index]/=127.0f; + } + String flags=c.getString(fmt::sprintf("flags%d",index),""); song.systemFlags[index].loadFromBase64(flags.c_str()); } @@ -1667,14 +1683,36 @@ bool DivEngine::addSystem(DivSystem which) { BUSY_BEGIN; saveLock.lock(); song.system[song.systemLen]=which; - song.systemVol[song.systemLen]=64; + song.systemVol[song.systemLen]=1.0; song.systemPan[song.systemLen]=0; + song.systemPanFR[song.systemLen]=0; song.systemFlags[song.systemLen++].clear(); recalcChans(); saveLock.unlock(); BUSY_END; initDispatch(); BUSY_BEGIN; + saveLock.lock(); + if (song.patchbayAuto) { + autoPatchbay(); + } else { + int i=song.systemLen-1; + if (disCont[i].dispatch!=NULL) { + unsigned int outs=disCont[i].dispatch->getOutputCount(); + if (outs>16) outs=16; + if (outs<2) { + for (unsigned int j=0; j>20)&0xfff)==(unsigned int)index) { + song.patchbay.erase(song.patchbay.begin()+i); + i--; + } + } + song.system[index]=DIV_SYSTEM_NULL; song.systemLen--; for (int i=index; i>20)&0xfff)==(unsigned int)src) { + i=(i&(~0xfff00000))|((unsigned int)dest<<20); + } else if (((i>>20)&0xfff)==(unsigned int)dest) { + i=(i&(~0xfff00000))|((unsigned int)src<<20); + } + } + recalcChans(); saveLock.unlock(); BUSY_END; @@ -1904,10 +1964,11 @@ String DivEngine::getPlaybackDebugInfo() { "speed1: %d\n" "speed2: %d\n" "tempoAccum: %d\n" - "totalProcessed: %d\n", + "totalProcessed: %d\n" + "bufferPos: %d\n", curOrder,prevOrder,curRow,prevRow,ticks,subticks,totalLoops,lastLoopPos,nextSpeed,divider,cycles,clockDrift, changeOrd,changePos,totalSeconds,totalTicks,totalTicksR,totalCmds,lastCmds,cmdsPerSecond,globalPitch, - (int)extValue,(int)speed1,(int)speed2,(int)tempoAccum,(int)totalProcessed + (int)extValue,(int)speed1,(int)speed2,(int)tempoAccum,(int)totalProcessed,(int)bufferPos ); } @@ -3750,6 +3811,102 @@ bool DivEngine::moveSampleDown(int which) { return true; } +void DivEngine::autoPatchbay() { + song.patchbay.clear(); + for (unsigned int i=0; igetOutputCount(); + if (outs>16) outs=16; + if (outs<2) { + for (unsigned int j=0; j=chans) return; BUSY_BEGIN; @@ -3889,6 +4046,14 @@ void DivEngine::updateSysFlags(int system, bool restart) { BUSY_BEGIN_SOFT; disCont[system].dispatch->setFlags(song.systemFlags[system]); disCont[system].setRates(got.rate); + + // patchbay + if (song.patchbayAuto) { + saveLock.lock(); + autoPatchbay(); + saveLock.unlock(); + } + if (restart && isPlaying()) { playSub(false); } @@ -4053,6 +4218,11 @@ void DivEngine::initDispatch() { disCont[i].setRates(got.rate); disCont[i].setQuality(lowQuality); } + if (song.patchbayAuto) { + saveLock.lock(); + autoPatchbay(); + saveLock.unlock(); + } recalcChans(); BUSY_END; } @@ -4151,10 +4321,13 @@ bool DivEngine::initAudioBackend() { want.rate=getConfInt("audioRate",44100); want.fragments=2; want.inChans=0; - want.outChans=2; + want.outChans=getConfInt("audioChans",2); want.outFormat=TA_AUDIO_FORMAT_F32; want.name="Furnace"; + if (want.outChans<1) want.outChans=1; + if (want.outChans>16) want.outChans=16; + output->setCallback(process,this); if (!output->init(want,got)) { @@ -4165,6 +4338,13 @@ bool DivEngine::initAudioBackend() { return false; } + for (int i=0; iinitMidi(false)) { midiIns=output->midiIn->listDevices(); midiOuts=output->midiOut->listDevices(); @@ -4246,13 +4426,15 @@ bool DivEngine::init() { if (!hasLoadedSomething) { logD("setting default preset"); String preset=getConfString("initialSys2",""); + bool oldVol=getConfInt("configVersion",DIV_ENGINE_VERSION)<135; if (preset.empty()) { // try loading old preset preset=decodeSysDesc(getConfString("initialSys","")); + oldVol=false; } logD("preset size %ld",preset.size()); if (preset.size()>0 && (preset.size()&3)==0) { - initSongWithDesc(preset.c_str()); + initSongWithDesc(preset.c_str(),true,oldVol); } String sysName=getConfString("initialSysName",""); if (sysName=="") { @@ -4281,6 +4463,9 @@ bool DivEngine::init() { samp_bbIn=new short[32768]; samp_bbInLen=32768; + + metroBuf=new float[8192]; + metroBufLen=8192; blip_set_rates(samp_bb,44100,got.rate); @@ -4297,12 +4482,6 @@ bool DivEngine::init() { keyHit[i]=false; } - oscBuf[0]=new float[32768]; - oscBuf[1]=new float[32768]; - - memset(oscBuf[0],0,32768*sizeof(float)); - memset(oscBuf[1],0,32768*sizeof(float)); - initDispatch(); renderSamples(); reset(); @@ -4311,6 +4490,10 @@ bool DivEngine::init() { if (!haveAudio) { return false; } else { + if (output==NULL) { + logE("output is NULL!"); + return false; + } if (!output->setRun(true)) { logE("error while activating!"); return false; @@ -4325,8 +4508,14 @@ bool DivEngine::quit() { logI("saving config."); saveConf(); active=false; - delete[] oscBuf[0]; - delete[] oscBuf[1]; + for (int i=0; i>3)|(ds.systemVol[i]&128); + ds.systemVol[i+1]=ds.systemVol[i]*0.375f; } } if (ds.system[i]==DIV_SYSTEM_GENESIS_EXT) { ds.system[i]=DIV_SYSTEM_YM2612_EXT; if (i<31) { ds.system[i+1]=DIV_SYSTEM_SMS; - ds.systemVol[i+1]=(((ds.systemVol[i]&127)*3)>>3)|(ds.systemVol[i]&128); + ds.systemVol[i+1]=ds.systemVol[i]*0.375f; } } if (ds.system[i]==DIV_SYSTEM_ARCADE) { @@ -2200,6 +2204,23 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { ds.autoSystem=true; } + // system output config + if (ds.version>=135) { + for (int i=0; i=136) song.patchbayAuto=reader.readC(); + // read system flags if (ds.version>=119) { logD("reading chip flags..."); @@ -2543,6 +2564,16 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { } } + // OPL3 pan compat + if (ds.version<134) { + for (int i=0; iwriteC(song.systemVol[i]); + w->writeC(song.systemVol[i]*64.0f); } for (int i=0; iwriteC(song.systemPan[i]); + w->writeC(song.systemPan[i]*127.0f); } // chip flags (we'll seek here later) @@ -4446,6 +4477,18 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { w->writeString(song.systemNameJ,false); w->writeString(song.categoryJ,false); + // system output config + for (int i=0; iwriteF(song.systemVol[i]); + w->writeF(song.systemPan[i]); + w->writeF(song.systemPanFR[i]); + } + w->writeI(song.patchbay.size()); + for (unsigned int i: song.patchbay) { + w->writeI(i); + } + w->writeC(song.patchbayAuto); + blockEndSeek=w->tell(); w->seek(blockStartSeek,SEEK_SET); w->writeI(blockEndSeek-blockStartSeek-4); diff --git a/src/engine/platform/abstract.cpp b/src/engine/platform/abstract.cpp index bd56efb8f..214157258 100644 --- a/src/engine/platform/abstract.cpp +++ b/src/engine/platform/abstract.cpp @@ -19,7 +19,7 @@ #include "../dispatch.h" -void DivDispatch::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivDispatch::acquire(short** buf, size_t len) { } void DivDispatch::fillStream(std::vector& stream, int sRate, size_t len) { @@ -69,8 +69,8 @@ int DivDispatch::dispatch(DivCommand c) { void DivDispatch::reset() { } -bool DivDispatch::isStereo() { - return false; +int DivDispatch::getOutputCount() { + return 1; } bool DivDispatch::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/amiga.cpp b/src/engine/platform/amiga.cpp index 0ecd6ba41..6f70a310e 100644 --- a/src/engine/platform/amiga.cpp +++ b/src/engine/platform/amiga.cpp @@ -75,9 +75,9 @@ const char** DivPlatformAmiga::getRegisterSheet() { if (chan[i+1].freq>12; filter[1][0]+=(filtConst*(outR-filter[1][0]))>>12; filter[1][1]+=(filtConst*(filter[1][0]-filter[1][1]))>>12; - bufL[h]=filter[0][1]; - bufR[h]=filter[1][1]; + buf[0][h]=filter[0][1]; + buf[1][h]=filter[1][1]; } } @@ -401,8 +401,8 @@ void DivPlatformAmiga::reset() { filtConst=filterOn?filtConstOn:filtConstOff; } -bool DivPlatformAmiga::isStereo() { - return true; +int DivPlatformAmiga::getOutputCount() { + return 2; } bool DivPlatformAmiga::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/amiga.h b/src/engine/platform/amiga.h index f28707440..494b5da7c 100644 --- a/src/engine/platform/amiga.h +++ b/src/engine/platform/amiga.h @@ -67,7 +67,7 @@ class DivPlatformAmiga: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivDispatchOscBuffer* getOscBuffer(int chan); @@ -75,7 +75,7 @@ class DivPlatformAmiga: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); DivMacroInt* getChanMacroInt(int ch); void setFlags(const DivConfig& flags); diff --git a/src/engine/platform/arcade.cpp b/src/engine/platform/arcade.cpp index e73249988..1984e5a18 100644 --- a/src/engine/platform/arcade.cpp +++ b/src/engine/platform/arcade.cpp @@ -19,6 +19,7 @@ #include "arcade.h" #include "../engine.h" +#include "../../ta-log.h" #include #include @@ -50,10 +51,10 @@ const char** DivPlatformArcade::getRegisterSheet() { return regCheatSheetOPM; } -void DivPlatformArcade::acquire_nuked(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformArcade::acquire_nuked(short** buf, size_t len) { static int o[2]; - for (size_t h=start; h32767) o[1]=32767; - bufL[h]=o[0]; - bufR[h]=o[1]; + buf[0][h]=o[0]; + buf[1][h]=o[1]; } } -void DivPlatformArcade::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformArcade::acquire_ymfm(short** buf, size_t len) { static int os[2]; ymfm::ym2151::fm_engine* fme=fm_ymfm->debug_engine(); - for (size_t h=start; h32767) os[1]=32767; - bufL[h]=os[0]; - bufR[h]=os[1]; + buf[0][h]=os[0]; + buf[1][h]=os[1]; } } -void DivPlatformArcade::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformArcade::acquire(short** buf, size_t len) { if (useYMFM) { - acquire_ymfm(bufL,bufR,start,len); + acquire_ymfm(buf,len); } else { - acquire_nuked(bufL,bufR,start,len); + acquire_nuked(buf,len); } } @@ -868,25 +869,26 @@ void DivPlatformArcade::setFlags(const DivConfig& flags) { switch (flags.getInt("clockSel",0)) { case 1: chipClock=COLOR_PAL*4.0/5.0; - baseFreqOff=12; break; case 2: chipClock=4000000.0; - baseFreqOff=-122; break; default: chipClock=COLOR_NTSC; - baseFreqOff=0; break; } + CHECK_CUSTOM_CLOCK; + + baseFreqOff=round(768.0*(log((COLOR_NTSC/(double)chipClock))/log(2.0))); + rate=chipClock/64; for (int i=0; i<8; i++) { oscBuf[i]->rate=rate; } } -bool DivPlatformArcade::isStereo() { - return true; +int DivPlatformArcade::getOutputCount() { + return 2; } void DivPlatformArcade::setYMFM(bool use) { diff --git a/src/engine/platform/arcade.h b/src/engine/platform/arcade.h index f8c66aca1..0bbd9b2cb 100644 --- a/src/engine/platform/arcade.h +++ b/src/engine/platform/arcade.h @@ -58,13 +58,13 @@ class DivPlatformArcade: public DivPlatformOPM { int octave(int freq); int toFreq(int freq); - void acquire_nuked(short* bufL, short* bufR, size_t start, size_t len); - void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len); + void acquire_nuked(short** buf, size_t len); + void acquire_ymfm(short** buf, size_t len); friend void putDispatchChan(void*,int,int); friend void putDispatchChip(void*,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivDispatchOscBuffer* getOscBuffer(int chan); @@ -77,7 +77,7 @@ class DivPlatformArcade: public DivPlatformOPM { DivMacroInt* getChanMacroInt(int ch); void notifyInsChange(int ins); void setFlags(const DivConfig& flags); - bool isStereo(); + int getOutputCount(); void setYMFM(bool use); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index bc3abc3c0..be2ac933c 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -169,7 +169,7 @@ void DivPlatformAY8910::checkWrites() { } } -void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformAY8910::acquire(short** buf, size_t len) { if (ayBufLensound_stream_update(ayBuf,1); - bufL[i+start]=ayBuf[0][0]; - bufR[i+start]=bufL[i+start]; + buf[0][i]=ayBuf[0][0]; + buf[1][i]=buf[0][i]; oscBuf[0]->data[oscBuf[0]->needle++]=sunsoftVolTable[31-(ay->lastIndx&31)]>>3; oscBuf[1]->data[oscBuf[1]->needle++]=sunsoftVolTable[31-((ay->lastIndx>>5)&31)]>>3; @@ -198,11 +198,11 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l ay->sound_stream_update(ayBuf,1); if (stereo) { - bufL[i+start]=ayBuf[0][0]+ayBuf[1][0]+((ayBuf[2][0]*stereoSep)>>8); - bufR[i+start]=((ayBuf[0][0]*stereoSep)>>8)+ayBuf[1][0]+ayBuf[2][0]; + buf[0][i]=ayBuf[0][0]+ayBuf[1][0]+((ayBuf[2][0]*stereoSep)>>8); + buf[1][i]=((ayBuf[0][0]*stereoSep)>>8)+ayBuf[1][0]+ayBuf[2][0]; } else { - bufL[i+start]=ayBuf[0][0]+ayBuf[1][0]+ayBuf[2][0]; - bufR[i+start]=bufL[i+start]; + buf[0][i]=ayBuf[0][0]+ayBuf[1][0]+ayBuf[2][0]; + buf[1][i]=buf[0][i]; } oscBuf[0]->data[oscBuf[0]->needle++]=ayBuf[0][0]<<2; @@ -337,6 +337,7 @@ void DivPlatformAY8910::tick(bool sysTick) { chan[i].dac.rate=((double)rate*((sunsoft||clockSel)?8.0:16.0))/(double)(MAX(1,off*chan[i].freq)); if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].dac.rate); } + if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq>4095) chan[i].freq=4095; if (chan[i].keyOn) { //rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(ins->gb.soundLen&63))); @@ -751,8 +752,8 @@ void DivPlatformAY8910::reset() { portBVal=0; } -bool DivPlatformAY8910::isStereo() { - return true; +int DivPlatformAY8910::getOutputCount() { + return 2; } bool DivPlatformAY8910::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/ay.h b/src/engine/platform/ay.h index e8d7efcec..ad8b46255 100644 --- a/src/engine/platform/ay.h +++ b/src/engine/platform/ay.h @@ -128,7 +128,7 @@ class DivPlatformAY8910: public DivDispatch { public: void setExtClockDiv(unsigned int eclk=COLOR_NTSC, unsigned char ediv=8); - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivDispatchOscBuffer* getOscBuffer(int chan); @@ -140,7 +140,7 @@ class DivPlatformAY8910: public DivDispatch { void tick(bool sysTick=true); void muteChannel(int ch, bool mute); void setFlags(const DivConfig& flags); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); DivMacroInt* getChanMacroInt(int ch); bool getDCOffRequired(); diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index 5d8cbc137..3dc8eedbc 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -164,7 +164,7 @@ void DivPlatformAY8930::checkWrites() { } } -void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformAY8930::acquire(short** buf, size_t len) { if (ayBufLensound_stream_update(ayBuf,1); if (stereo) { - bufL[i+start]=ayBuf[0][0]+ayBuf[1][0]+((ayBuf[2][0]*stereoSep)>>8); - bufR[i+start]=((ayBuf[0][0]*stereoSep)>>8)+ayBuf[1][0]+ayBuf[2][0]; + buf[0][i]=ayBuf[0][0]+ayBuf[1][0]+((ayBuf[2][0]*stereoSep)>>8); + buf[1][i]=((ayBuf[0][0]*stereoSep)>>8)+ayBuf[1][0]+ayBuf[2][0]; } else { - bufL[i+start]=ayBuf[0][0]+ayBuf[1][0]+ayBuf[2][0]; - bufR[i+start]=bufL[i+start]; + buf[0][i]=ayBuf[0][0]+ayBuf[1][0]+ayBuf[2][0]; + buf[1][i]=buf[0][i]; } oscBuf[0]->data[oscBuf[0]->needle++]=ayBuf[0][0]<<2; @@ -270,7 +270,7 @@ void DivPlatformAY8930::tick(bool sysTick) { if (chan[i].std.pitch.had) { if (chan[i].std.pitch.mode) { chan[i].pitch2+=chan[i].std.pitch.val; - CLAMP_VAR(chan[i].pitch2,-32768,32767); + CLAMP_VAR(chan[i].pitch2,-65535,65535); } else { chan[i].pitch2=chan[i].std.pitch.val; } @@ -297,7 +297,7 @@ void DivPlatformAY8930::tick(bool sysTick) { } } if (chan[i].std.ex1.had) { // duty - rWrite(0x16+i,chan[i].std.ex1.val); + immWrite(0x16+i,chan[i].std.ex1.val); } if (chan[i].std.ex2.had) { chan[i].envelope.mode=chan[i].std.ex2.val; @@ -336,6 +336,7 @@ void DivPlatformAY8930::tick(bool sysTick) { chan[i].dac.rate=((double)chipClock*4.0)/(double)(MAX(1,off*chan[i].freq)); if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].dac.rate); } + if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].keyOn) { if (!chan[i].nextPSGMode.dac) { @@ -747,8 +748,8 @@ void DivPlatformAY8930::reset() { immWrite(0x1a,0x00); // or mask } -bool DivPlatformAY8930::isStereo() { - return true; +int DivPlatformAY8930::getOutputCount() { + return 2; } bool DivPlatformAY8930::keyOffAffectsArp(int ch) { @@ -808,6 +809,12 @@ void DivPlatformAY8930::setFlags(const DivConfig& flags) { case 12: chipClock=3600000; break; + case 13: + chipClock=20000000/16; + break; + case 14: + chipClock=1536000; + break; default: chipClock=COLOR_NTSC/2.0; break; diff --git a/src/engine/platform/ay8930.h b/src/engine/platform/ay8930.h index 0bd2171a1..0e60c3508 100644 --- a/src/engine/platform/ay8930.h +++ b/src/engine/platform/ay8930.h @@ -131,7 +131,7 @@ class DivPlatformAY8930: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivDispatchOscBuffer* getOscBuffer(int chan); @@ -142,7 +142,7 @@ class DivPlatformAY8930: public DivDispatch { void tick(bool sysTick=true); void muteChannel(int ch, bool mute); void setFlags(const DivConfig& flags); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); DivMacroInt* getChanMacroInt(int ch); void notifyInsDeletion(void* ins); diff --git a/src/engine/platform/bubsyswsg.cpp b/src/engine/platform/bubsyswsg.cpp index 2d3f6ed00..d7b15d8ff 100644 --- a/src/engine/platform/bubsyswsg.cpp +++ b/src/engine/platform/bubsyswsg.cpp @@ -39,9 +39,9 @@ const char** DivPlatformBubSysWSG::getRegisterSheet() { return regCheatSheetBubSysWSG; } -void DivPlatformBubSysWSG::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformBubSysWSG::acquire(short** buf, size_t len) { int chanOut=0; - for (size_t h=start; h32767) out=32767; //printf("out: %d\n",out); - bufL[h]=bufR[h]=out; + buf[0][h]=out; } } @@ -306,8 +306,8 @@ void DivPlatformBubSysWSG::reset() { k005289.reset(); } -bool DivPlatformBubSysWSG::isStereo() { - return false; +int DivPlatformBubSysWSG::getOutputCount() { + return 1; } bool DivPlatformBubSysWSG::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/bubsyswsg.h b/src/engine/platform/bubsyswsg.h index 92c64d898..d544c2ecd 100644 --- a/src/engine/platform/bubsyswsg.h +++ b/src/engine/platform/bubsyswsg.h @@ -45,7 +45,7 @@ class DivPlatformBubSysWSG: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivDispatchOscBuffer* getOscBuffer(int chan); @@ -56,7 +56,7 @@ class DivPlatformBubSysWSG: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); DivMacroInt* getChanMacroInt(int ch); void setFlags(const DivConfig& flags); diff --git a/src/engine/platform/c64.cpp b/src/engine/platform/c64.cpp index 8091e179a..d52a5dd00 100644 --- a/src/engine/platform/c64.cpp +++ b/src/engine/platform/c64.cpp @@ -63,9 +63,9 @@ const char** DivPlatformC64::getRegisterSheet() { return regCheatSheetSID; } -void DivPlatformC64::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformC64::acquire(short** buf, size_t len) { int dcOff=isFP?0:sid.get_dc(0); - for (size_t i=start; i=4) { writeOscBuf=0; oscBuf[0]->data[oscBuf[0]->needle++]=(sid_fp.lastChanOut[0]-dcOff)>>5; @@ -86,7 +86,7 @@ void DivPlatformC64::acquire(short* bufL, short* bufR, size_t start, size_t len) } } else { sid.clock(); - bufL[i]=sid.output(); + buf[0][i]=sid.output(); if (++writeOscBuf>=16) { writeOscBuf=0; oscBuf[0]->data[oscBuf[0]->needle++]=(sid.last_chan_out[0]-dcOff)>>5; @@ -148,7 +148,7 @@ void DivPlatformC64::tick(bool sysTick) { if (chan[i].std.pitch.had) { if (chan[i].std.pitch.mode) { chan[i].pitch2+=chan[i].std.pitch.val; - CLAMP_VAR(chan[i].pitch2,-32768,32767); + CLAMP_VAR(chan[i].pitch2,-65535,65535); } else { chan[i].pitch2=chan[i].std.pitch.val; } @@ -188,6 +188,7 @@ void DivPlatformC64::tick(bool sysTick) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,8,chan[i].pitch2,chipClock,CHIP_FREQBASE); + if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq>0xffff) chan[i].freq=0xffff; if (chan[i].keyOn) { rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay)); diff --git a/src/engine/platform/c64.h b/src/engine/platform/c64.h index 9bdabbe45..28cf5b29d 100644 --- a/src/engine/platform/c64.h +++ b/src/engine/platform/c64.h @@ -79,7 +79,7 @@ class DivPlatformC64: public DivDispatch { void updateFilter(); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivDispatchOscBuffer* getOscBuffer(int chan); diff --git a/src/engine/platform/dummy.cpp b/src/engine/platform/dummy.cpp index 898809cc9..28cb5d40e 100644 --- a/src/engine/platform/dummy.cpp +++ b/src/engine/platform/dummy.cpp @@ -24,9 +24,9 @@ #define CHIP_FREQBASE 2048 -void DivPlatformDummy::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformDummy::acquire(short** buf, size_t len) { int chanOut; - for (size_t i=start; i32767) out=32767; - bufL[i]=out; + buf[0][i]=out; } } diff --git a/src/engine/platform/dummy.h b/src/engine/platform/dummy.h index d3a1b91e3..c12d494b7 100644 --- a/src/engine/platform/dummy.h +++ b/src/engine/platform/dummy.h @@ -37,7 +37,7 @@ class DivPlatformDummy: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); void muteChannel(int ch, bool mute); int dispatch(DivCommand c); void* getChanState(int chan); diff --git a/src/engine/platform/fds.cpp b/src/engine/platform/fds.cpp index e0047ace8..cdddbacab 100644 --- a/src/engine/platform/fds.cpp +++ b/src/engine/platform/fds.cpp @@ -55,13 +55,13 @@ const char** DivPlatformFDS::getRegisterSheet() { return regCheatSheetFDS; } -void DivPlatformFDS::acquire_puNES(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t i=start; isnd.main.output; if (sample>32767) sample=32767; if (sample<-32768) sample=-32768; - bufL[i]=sample; + buf[i]=sample; if (++writeOscBuf>=32) { writeOscBuf=0; oscBuf->data[oscBuf->needle++]=sample<<1; @@ -69,15 +69,15 @@ void DivPlatformFDS::acquire_puNES(short* bufL, short* bufR, size_t start, size_ } } -void DivPlatformFDS::acquire_NSFPlay(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformFDS::acquire_NSFPlay(short* buf, size_t len) { int out[2]; - for (size_t i=start; iTick(1); fds_NP->Render(out); int sample=isMuted[0]?0:(out[0]<<1); if (sample>32767) sample=32767; if (sample<-32768) sample=-32768; - bufL[i]=sample; + buf[i]=sample; if (++writeOscBuf>=32) { writeOscBuf=0; oscBuf->data[oscBuf->needle++]=sample<<1; @@ -93,11 +93,11 @@ void DivPlatformFDS::doWrite(unsigned short addr, unsigned char data) { } } -void DivPlatformFDS::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformFDS::acquire(short** buf, size_t len) { if (useNP) { - acquire_NSFPlay(bufL,bufR,start,len); + acquire_NSFPlay(buf[0],len); } else { - acquire_puNES(bufL,bufR,start,len); + acquire_puNES(buf[0],len); } } diff --git a/src/engine/platform/fds.h b/src/engine/platform/fds.h index beabb6417..7872319b1 100644 --- a/src/engine/platform/fds.h +++ b/src/engine/platform/fds.h @@ -62,11 +62,11 @@ class DivPlatformFDS: public DivDispatch { friend void putDispatchChan(void*,int,int); void doWrite(unsigned short addr, unsigned char data); - void acquire_puNES(short* bufL, short* bufR, size_t start, size_t len); - void acquire_NSFPlay(short* bufL, short* bufR, size_t start, size_t len); + void acquire_puNES(short* buf, size_t len); + void acquire_NSFPlay(short* buf, size_t len); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/platform/ga20.cpp b/src/engine/platform/ga20.cpp index bd3c79dfd..c5cbbb61e 100644 --- a/src/engine/platform/ga20.cpp +++ b/src/engine/platform/ga20.cpp @@ -51,7 +51,7 @@ inline void DivPlatformGA20::chWrite(unsigned char ch, unsigned int addr, unsign } } -void DivPlatformGA20::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformGA20::acquire(short** buf, size_t len) { if (ga20BufLen>2; + buf[0][h]=(signed int)(ga20Buf[0][h]+ga20Buf[1][h]+ga20Buf[2][h]+ga20Buf[3][h])>>2; for (int i=0; i<4; i++) { oscBuf[i]->data[oscBuf[i]->needle++]=ga20Buf[i][h]; } @@ -361,8 +361,8 @@ void DivPlatformGA20::reset() { } } -bool DivPlatformGA20::isStereo() { - return false; +int DivPlatformGA20::getOutputCount() { + return 1; } void DivPlatformGA20::notifyInsChange(int ins) { diff --git a/src/engine/platform/ga20.h b/src/engine/platform/ga20.h index 88b475472..9c67a9fd3 100644 --- a/src/engine/platform/ga20.h +++ b/src/engine/platform/ga20.h @@ -74,7 +74,7 @@ class DivPlatformGA20: public DivDispatch, public iremga20_intf { void chWrite(unsigned char ch, unsigned int addr, unsigned char val); public: virtual u8 read_byte(u32 address) override; - virtual void acquire(short* bufL, short* bufR, size_t start, size_t len) override; + virtual void acquire(short** buf, size_t len) override; virtual int dispatch(DivCommand c) override; virtual void* getChanState(int chan) override; virtual DivMacroInt* getChanMacroInt(int ch) override; @@ -85,7 +85,7 @@ class DivPlatformGA20: public DivDispatch, public iremga20_intf { virtual void forceIns() override; virtual void tick(bool sysTick=true) override; virtual void muteChannel(int ch, bool mute) override; - virtual bool isStereo() override; + virtual int getOutputCount() override; virtual void notifyInsChange(int ins) override; virtual void notifyWaveChange(int wave) override; virtual void notifyInsDeletion(void* ins) override; diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index e84d212b6..6e6c317c9 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -61,8 +61,8 @@ const char** DivPlatformGB::getRegisterSheet() { return regCheatSheetGB; } -void DivPlatformGB::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t i=start; iapu_output.final_sample.left; - bufR[i]=gb->apu_output.final_sample.right; + buf[0][i]=gb->apu_output.final_sample.left; + buf[1][i]=gb->apu_output.final_sample.right; for (int i=0; i<4; i++) { oscBuf[i]->data[oscBuf[i]->needle++]=(gb->apu_output.current_sample[i].left+gb->apu_output.current_sample[i].right)<<6; @@ -284,14 +284,14 @@ void DivPlatformGB::tick(bool sysTick) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (i==3) { // noise - int ntPos=chan[i].baseFreq; + int ntPos=chan[i].baseFreq+chan[i].pitch2; if (ntPos<0) ntPos=0; if (ntPos>255) ntPos=255; chan[i].freq=noiseTable[ntPos]; } else { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER); if (chan[i].freq>2047) chan[i].freq=2047; - if (chan[i].freq<0) chan[i].freq=0; + if (chan[i].freq<1) chan[i].freq=1; } if (chan[i].keyOn) { if (i==2) { // wave @@ -604,8 +604,8 @@ int DivPlatformGB::getPortaFloor(int ch) { return 24; } -bool DivPlatformGB::isStereo() { - return true; +int DivPlatformGB::getOutputCount() { + return 2; } bool DivPlatformGB::getDCOffRequired() { diff --git a/src/engine/platform/gb.h b/src/engine/platform/gb.h index 581962999..8f70fecb8 100644 --- a/src/engine/platform/gb.h +++ b/src/engine/platform/gb.h @@ -78,7 +78,7 @@ class DivPlatformGB: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -90,7 +90,7 @@ class DivPlatformGB: public DivDispatch { void tick(bool sysTick=true); void muteChannel(int ch, bool mute); int getPortaFloor(int ch); - bool isStereo(); + int getOutputCount(); bool getDCOffRequired(); void notifyInsChange(int ins); void notifyWaveChange(int wave); diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 166607207..b547181da 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -132,11 +132,11 @@ void DivPlatformGenesis::processDAC(int iRate) { } } -void DivPlatformGenesis::acquire_nuked(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformGenesis::acquire_nuked(short** buf, size_t len) { static short o[2]; static int os[2]; - for (size_t h=start; h32767) os[1]=32767; - bufL[h]=os[0]; - bufR[h]=os[1]; + buf[0][h]=os[0]; + buf[1][h]=os[1]; } } -void DivPlatformGenesis::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformGenesis::acquire_ymfm(short** buf, size_t len) { static int os[2]; ymfm::ym2612::fm_engine* fme=fm_ymfm->debug_engine(); - for (size_t h=start; h32767) os[1]=32767; - bufL[h]=os[0]; - bufR[h]=os[1]; + buf[0][h]=os[0]; + buf[1][h]=os[1]; } } -void DivPlatformGenesis::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformGenesis::acquire(short** buf, size_t len) { if (useYMFM) { - acquire_ymfm(bufL,bufR,start,len); + acquire_ymfm(buf,len); } else { - acquire_nuked(bufL,bufR,start,len); + acquire_nuked(buf,len); } } @@ -1193,8 +1193,8 @@ void DivPlatformGenesis::reset() { delay=0; } -bool DivPlatformGenesis::isStereo() { - return true; +int DivPlatformGenesis::getOutputCount() { + return 2; } bool DivPlatformGenesis::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index d66083826..f57c33a38 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -92,13 +92,13 @@ class DivPlatformGenesis: public DivPlatformOPN { friend void putDispatchChan(void*,int,int); inline void processDAC(int iRate); - void acquire_nuked(short* bufL, short* bufR, size_t start, size_t len); - void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len); + void acquire_nuked(short** buf, size_t len); + void acquire_ymfm(short** buf, size_t len); friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); void fillStream(std::vector& stream, int sRate, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); @@ -110,7 +110,7 @@ class DivPlatformGenesis: public DivPlatformOPN { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); void setYMFM(bool use); bool keyOffAffectsArp(int ch); bool keyOffAffectsPorta(int ch); diff --git a/src/engine/platform/k007232.cpp b/src/engine/platform/k007232.cpp index 58304553a..6a333c6c6 100644 --- a/src/engine/platform/k007232.cpp +++ b/src/engine/platform/k007232.cpp @@ -54,8 +54,8 @@ inline void DivPlatformK007232::chWrite(unsigned char ch, unsigned int addr, uns } } -void DivPlatformK007232::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t h=start; h>4)&0xf)),(k007232.output(1)*((vol2>>4)&0xf))}; - bufL[h]=(lout[0]+lout[1])<<4; - bufR[h]=(rout[0]+rout[1])<<4; + buf[0][h]=(lout[0]+lout[1])<<4; + buf[1][h]=(rout[0]+rout[1])<<4; for (int i=0; i<2; i++) { oscBuf[i]->data[oscBuf[i]->needle++]=(lout[i]+rout[i])<<4; } } else { const unsigned char vol=regPool[0xc]; const signed int out[2]={(k007232.output(0)*(vol&0xf)),(k007232.output(1)*((vol>>4)&0xf))}; - bufL[h]=bufR[h]=(out[0]+out[1])<<4; + buf[0][h]=(out[0]+out[1])<<4; for (int i=0; i<2; i++) { oscBuf[i]->data[oscBuf[i]->needle++]=out[i]<<5; } @@ -448,8 +448,8 @@ void DivPlatformK007232::reset() { } } -bool DivPlatformK007232::isStereo() { - return stereo; +int DivPlatformK007232::getOutputCount() { + return stereo?2:1; } void DivPlatformK007232::notifyInsChange(int ins) { diff --git a/src/engine/platform/k007232.h b/src/engine/platform/k007232.h index 04e6e73f0..8d9aeb28b 100644 --- a/src/engine/platform/k007232.h +++ b/src/engine/platform/k007232.h @@ -80,7 +80,7 @@ class DivPlatformK007232: public DivDispatch, public k007232_intf { void chWrite(unsigned char ch, unsigned int addr, unsigned char val); public: u8 read_sample(u8 ne, u32 address); - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -91,7 +91,7 @@ class DivPlatformK007232: public DivDispatch, public k007232_intf { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); void notifyInsChange(int ins); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); diff --git a/src/engine/platform/lynx.cpp b/src/engine/platform/lynx.cpp index 3af5dbd83..07be2d6f6 100644 --- a/src/engine/platform/lynx.cpp +++ b/src/engine/platform/lynx.cpp @@ -130,8 +130,8 @@ const char** DivPlatformLynx::getRegisterSheet() { return regCheatSheetLynx; } -void DivPlatformLynx::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t h=start; h=0 && chan[i].samplesong.sampleLen) { chan[i].sampleAccum-=chan[i].sampleFreq; @@ -156,7 +156,7 @@ void DivPlatformLynx::acquire(short* bufL, short* bufR, size_t start, size_t len } } - mikey->sampleAudio( bufL + h, bufR + h, 1, oscBuf ); + mikey->sampleAudio(buf[0]+h,buf[1]+h,1,oscBuf); } } @@ -393,8 +393,8 @@ void DivPlatformLynx::muteChannel(int ch, bool mute) { if (chan[ch].active) WRITE_VOLUME(ch,(isMuted[ch]?0:(chan[ch].outVol&127))); } -bool DivPlatformLynx::isStereo() { - return true; +int DivPlatformLynx::getOutputCount() { + return 2; } void DivPlatformLynx::forceIns() { @@ -509,12 +509,12 @@ DivPlatformLynx::MikeyFreqDiv::MikeyFreqDiv(int frequency) { if (top>7) { clockDivider=top-7; - backup=frequency>>(top-7); + backup=clamped>>(top-7); } else { clockDivider=0; - backup=frequency; + backup=clamped; } } diff --git a/src/engine/platform/lynx.h b/src/engine/platform/lynx.h index 463aad3d0..ec2208d38 100644 --- a/src/engine/platform/lynx.h +++ b/src/engine/platform/lynx.h @@ -68,7 +68,7 @@ class DivPlatformLynx: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -79,7 +79,7 @@ class DivPlatformLynx: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); bool keyOffAffectsPorta(int ch); //int getPortaFloor(int ch); diff --git a/src/engine/platform/mmc5.cpp b/src/engine/platform/mmc5.cpp index a00dd7718..6e44ea1cb 100644 --- a/src/engine/platform/mmc5.cpp +++ b/src/engine/platform/mmc5.cpp @@ -43,8 +43,8 @@ const char** DivPlatformMMC5::getRegisterSheet() { return regCheatSheetMMC5; } -void DivPlatformMMC5::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t i=start; i=rate) { @@ -81,7 +81,7 @@ void DivPlatformMMC5::acquire(short* bufL, short* bufR, size_t start, size_t len } if (sample>32767) sample=32767; if (sample<-32768) sample=-32768; - bufL[i]=sample; + buf[0][i]=sample; if (++writeOscBuf>=32) { writeOscBuf=0; diff --git a/src/engine/platform/mmc5.h b/src/engine/platform/mmc5.h index a3ab90538..3e83ff06d 100644 --- a/src/engine/platform/mmc5.h +++ b/src/engine/platform/mmc5.h @@ -50,7 +50,7 @@ class DivPlatformMMC5: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/platform/msm5232.cpp b/src/engine/platform/msm5232.cpp index 4781945f5..7405f8d36 100644 --- a/src/engine/platform/msm5232.cpp +++ b/src/engine/platform/msm5232.cpp @@ -45,8 +45,8 @@ const char** DivPlatformMSM5232::getRegisterSheet() { return regCheatSheetMSM5232; } -void DivPlatformMSM5232::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t h=start; hwrite(w.addr,w.val); @@ -75,9 +75,9 @@ void DivPlatformMSM5232::acquire(short* bufL, short* bufR, size_t start, size_t } //printf("tempL: %d tempR: %d\n",tempL,tempR); - bufL[h]=0; + buf[0][h]=0; for (int i=0; i<8; i++) { - bufL[h]+=(temp[i]*partVolume[i])>>8; + buf[0][h]+=(temp[i]*partVolume[i])>>8; } } } @@ -371,8 +371,8 @@ void DivPlatformMSM5232::reset() { } } -bool DivPlatformMSM5232::isStereo() { - return false; +int DivPlatformMSM5232::getOutputCount() { + return 1; } bool DivPlatformMSM5232::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/msm5232.h b/src/engine/platform/msm5232.h index 2d4b9705e..26d2a34b0 100644 --- a/src/engine/platform/msm5232.h +++ b/src/engine/platform/msm5232.h @@ -60,7 +60,7 @@ class DivPlatformMSM5232: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -71,7 +71,7 @@ class DivPlatformMSM5232: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); diff --git a/src/engine/platform/msm6258.cpp b/src/engine/platform/msm6258.cpp index 32fe24cc8..af1472af2 100644 --- a/src/engine/platform/msm6258.cpp +++ b/src/engine/platform/msm6258.cpp @@ -30,12 +30,12 @@ const char** DivPlatformMSM6258::getRegisterSheet() { return NULL; } -void DivPlatformMSM6258::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformMSM6258::acquire(short** buf, size_t len) { short* outs[2]={ &msmOut, NULL }; - for (size_t h=start; hdata[oscBuf[0]->needle++]=0; } else { - bufL[h]=(msmPan&2)?msmOut:0; - bufR[h]=(msmPan&1)?msmOut:0; + buf[0][h]=(msmPan&2)?msmOut:0; + buf[1][h]=(msmPan&1)?msmOut:0; oscBuf[0]->data[oscBuf[0]->needle++]=msmPan?msmOut:0; } } @@ -336,8 +336,8 @@ void DivPlatformMSM6258::reset() { delay=0; } -bool DivPlatformMSM6258::isStereo() { - return true; +int DivPlatformMSM6258::getOutputCount() { + return 2; } bool DivPlatformMSM6258::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/msm6258.h b/src/engine/platform/msm6258.h index d64d40b43..47d079cab 100644 --- a/src/engine/platform/msm6258.h +++ b/src/engine/platform/msm6258.h @@ -58,7 +58,7 @@ class DivPlatformMSM6258: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -69,7 +69,7 @@ class DivPlatformMSM6258: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void notifyInsChange(int ins); void notifyInsDeletion(void* ins); diff --git a/src/engine/platform/msm6295.cpp b/src/engine/platform/msm6295.cpp index 2423167f7..bc41091c0 100644 --- a/src/engine/platform/msm6295.cpp +++ b/src/engine/platform/msm6295.cpp @@ -37,8 +37,8 @@ u8 DivPlatformMSM6295::read_byte(u32 address) { return adpcmMem[address&0x3ffff]; } -void DivPlatformMSM6295::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t h=start; h=22) { updateOsc=0; diff --git a/src/engine/platform/msm6295.h b/src/engine/platform/msm6295.h index e3339df31..77a82f580 100644 --- a/src/engine/platform/msm6295.h +++ b/src/engine/platform/msm6295.h @@ -64,7 +64,7 @@ class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf { public: virtual u8 read_byte(u32 address) override; - virtual void acquire(short* bufL, short* bufR, size_t start, size_t len) override; + virtual void acquire(short** buf, size_t len) override; virtual int dispatch(DivCommand c) override; virtual void* getChanState(int chan) override; virtual DivMacroInt* getChanMacroInt(int ch) override; diff --git a/src/engine/platform/n163.cpp b/src/engine/platform/n163.cpp index c3efd5ac5..a65532793 100644 --- a/src/engine/platform/n163.cpp +++ b/src/engine/platform/n163.cpp @@ -108,13 +108,13 @@ const char** DivPlatformN163::getRegisterSheet() { return regCheatSheetN163; } -void DivPlatformN163::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t i=start; i32767) out=32767; if (out<-32768) out=-32768; - bufL[i]=bufR[i]=out; + buf[0][i]=out; if (n163.voice_cycle()==0x78) for (int i=0; i<8; i++) { oscBuf[i]->data[oscBuf[i]->needle++]=n163.voice_out(i)<<7; diff --git a/src/engine/platform/n163.h b/src/engine/platform/n163.h index 872c622bf..30eb222ce 100644 --- a/src/engine/platform/n163.h +++ b/src/engine/platform/n163.h @@ -74,7 +74,7 @@ class DivPlatformN163: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/platform/namcowsg.cpp b/src/engine/platform/namcowsg.cpp index 10b2aeb25..cb4540f5c 100644 --- a/src/engine/platform/namcowsg.cpp +++ b/src/engine/platform/namcowsg.cpp @@ -151,7 +151,7 @@ const char** DivPlatformNamcoWSG::getRegisterSheet() { return regCheatSheetNamcoWSG; } -void DivPlatformNamcoWSG::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformNamcoWSG::acquire(short** buf, size_t len) { while (!writes.empty()) { QueuedWrite w=writes.front(); switch (devType) { @@ -171,11 +171,11 @@ void DivPlatformNamcoWSG::acquire(short* bufL, short* bufR, size_t start, size_t regPool[w.addr&0x3f]=w.val; writes.pop(); } - for (size_t h=start; hsound_stream_update(buf,1); + namco->sound_stream_update(bufC,1); for (int i=0; idata[oscBuf[i]->needle++]=namco->m_channel_list[i].last_out*chans; } @@ -494,8 +494,8 @@ void DivPlatformNamcoWSG::reset() { namco->device_start(NULL); } -bool DivPlatformNamcoWSG::isStereo() { - return (devType==30); +int DivPlatformNamcoWSG::getOutputCount() { + return (devType==30)?2:1; } bool DivPlatformNamcoWSG::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/namcowsg.h b/src/engine/platform/namcowsg.h index 127f84aa4..87a2517ef 100644 --- a/src/engine/platform/namcowsg.h +++ b/src/engine/platform/namcowsg.h @@ -54,7 +54,7 @@ class DivPlatformNamcoWSG: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -65,7 +65,7 @@ class DivPlatformNamcoWSG: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void setDeviceType(int type); void setFlags(const DivConfig& flags); diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index d0cae5ec0..435384c46 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -100,8 +100,8 @@ void DivPlatformNES::doWrite(unsigned short addr, unsigned char data) { } \ } -void DivPlatformNES::acquire_puNES(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t i=start; i32767) sample=32767; if (sample<-32768) sample=-32768; - bufL[i]=sample; + buf[0][i]=sample; if (++writeOscBuf>=32) { writeOscBuf=0; oscBuf[0]->data[oscBuf[0]->needle++]=isMuted[0]?0:(nes->S1.output<<11); @@ -124,10 +124,10 @@ void DivPlatformNES::acquire_puNES(short* bufL, short* bufR, size_t start, size_ } } -void DivPlatformNES::acquire_NSFPlay(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformNES::acquire_NSFPlay(short** buf, size_t len) { int out1[2]; int out2[2]; - for (size_t i=start; iTick(1); @@ -139,7 +139,7 @@ void DivPlatformNES::acquire_NSFPlay(short* bufL, short* bufR, size_t start, siz int sample=(out1[0]+out1[1]+out2[0]+out2[1])<<1; if (sample>32767) sample=32767; if (sample<-32768) sample=-32768; - bufL[i]=sample; + buf[0][i]=sample; if (++writeOscBuf>=32) { writeOscBuf=0; oscBuf[0]->data[oscBuf[0]->needle++]=nes1_NP->out[0]<<11; @@ -151,11 +151,11 @@ void DivPlatformNES::acquire_NSFPlay(short* bufL, short* bufR, size_t start, siz } } -void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformNES::acquire(short** buf, size_t len) { if (useNP) { - acquire_NSFPlay(bufL,bufR,start,len); + acquire_NSFPlay(buf,len); } else { - acquire_puNES(bufL,bufR,start,len); + acquire_puNES(buf,len); } } @@ -278,6 +278,7 @@ void DivPlatformNES::tick(bool sysTick) { ntPos+=chan[i].arpOff; } } + ntPos+=chan[i].pitch2; if (parent->song.properNoiseLayout) { chan[i].freq=15-(ntPos&15); } else { diff --git a/src/engine/platform/nes.h b/src/engine/platform/nes.h index d9f43e915..22ccfd913 100644 --- a/src/engine/platform/nes.h +++ b/src/engine/platform/nes.h @@ -68,11 +68,11 @@ class DivPlatformNES: public DivDispatch { void doWrite(unsigned short addr, unsigned char data); unsigned char calcDPCMRate(int inRate); - void acquire_puNES(short* bufL, short* bufR, size_t start, size_t len); - void acquire_NSFPlay(short* bufL, short* bufR, size_t start, size_t len); + void acquire_puNES(short** buf, size_t len); + void acquire_NSFPlay(short** buf, size_t len); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index 8c5f6c759..bab5886be 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -159,13 +159,13 @@ const int orderedOpsL[4]={ #define ADDR_FREQH 0xb0 #define ADDR_LR_FB_ALG 0xc0 -void DivPlatformOPL::acquire_nuked(short* bufL, short* bufR, size_t start, size_t len) { - static short o[2]; - static int os[2]; +void DivPlatformOPL::acquire_nuked(short** buf, size_t len) { + static short o[4]; + static int os[4]; static ymfm::ymfm_output<2> aOut; - for (size_t h=start; h=0) { adpcmB->clock(); @@ -225,6 +228,12 @@ void DivPlatformOPL::acquire_nuked(short* bufL, short* bufR, size_t start, size_ if (fm.channel[i].out[1]!=NULL) { oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[1]; } + if (fm.channel[i].out[2]!=NULL) { + oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[2]; + } + if (fm.channel[i].out[3]!=NULL) { + oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[3]; + } oscBuf[i]->data[oscBuf[i]->needle]<<=1; oscBuf[i]->needle++; } @@ -244,6 +253,12 @@ void DivPlatformOPL::acquire_nuked(short* bufL, short* bufR, size_t start, size_ if (fm.channel[i].out[1]!=NULL) { oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[1]; } + if (fm.channel[i].out[2]!=NULL) { + oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[2]; + } + if (fm.channel[i].out[3]!=NULL) { + oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[3]; + } oscBuf[i]->data[oscBuf[i]->needle]<<=1; oscBuf[i]->needle++; } @@ -254,19 +269,36 @@ void DivPlatformOPL::acquire_nuked(short* bufL, short* bufR, size_t start, size_ if (os[1]<-32768) os[1]=-32768; if (os[1]>32767) os[1]=32767; + + if (os[2]<-32768) os[2]=-32768; + if (os[2]>32767) os[2]=32767; + + if (os[3]<-32768) os[3]=-32768; + if (os[3]>32767) os[3]=32767; - bufL[h]=os[0]; - if (oplType==3 || oplType==759) { - bufR[h]=os[1]; + buf[0][h]=os[0]; + if (totalOutputs>1) { + buf[1][h]=os[1]; + } + if (totalOutputs>2) { + buf[2][h]=os[2]; + } + if (totalOutputs>3) { + buf[3][h]=os[3]; + } + if (totalOutputs==6) { + // placeholder for OPL4 + buf[4][h]=0; + buf[5][h]=0; } } } -void DivPlatformOPL::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformOPL::acquire(short** buf, size_t len) { //if (useYMFM) { - // acquire_ymfm(bufL,bufR,start,len); + // acquire_ymfm(buf,len); //} else { - acquire_nuked(bufL,bufR,start,len); + acquire_nuked(buf,len); //} } @@ -314,13 +346,13 @@ void DivPlatformOPL::tick(bool sysTick) { } if (oplType==3 && chan[i].std.panL.had) { - chan[i].pan=((chan[i].std.panL.val&1)<<1)|((chan[i].std.panL.val&2)>>1); + chan[i].pan=((chan[i].std.panL.val&1)<<1)|((chan[i].std.panL.val&2)>>1)|((chan[i].std.panL.val&4)<<1)|((chan[i].std.panL.val&8)>>1); } if (chan[i].std.pitch.had) { if (chan[i].std.pitch.mode) { chan[i].pitch2+=chan[i].std.pitch.val; - CLAMP_VAR(chan[i].pitch2,-32768,32767); + CLAMP_VAR(chan[i].pitch2,-131071,131071); } else { chan[i].pitch2=chan[i].std.pitch.val; } @@ -347,9 +379,9 @@ void DivPlatformOPL::tick(bool sysTick) { rWrite(chanMap[i+1]+ADDR_LR_FB_ALG,((chan[i].state.alg>>1)&1)|(chan[i].state.fb<<1)); } } else { - rWrite(chanMap[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&1)|(chan[i].state.fb<<1)|((chan[i].pan&3)<<4)); + rWrite(chanMap[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&1)|(chan[i].state.fb<<1)|((chan[i].pan&15)<<4)); if (ops==4) { - rWrite(chanMap[i+1]+ADDR_LR_FB_ALG,((chan[i].state.alg>>1)&1)|(chan[i].state.fb<<1)|((chan[i].pan&3)<<4)); + rWrite(chanMap[i+1]+ADDR_LR_FB_ALG,((chan[i].state.alg>>1)&1)|(chan[i].state.fb<<1)|((chan[i].pan&15)<<4)); } } } @@ -659,9 +691,9 @@ void DivPlatformOPL::muteChannel(int ch, bool mute) { rWrite(chanMap[ch+1]+ADDR_LR_FB_ALG,((chan[ch].state.alg>>1)&1)|(chan[ch].state.fb<<1)); } } else { - rWrite(chanMap[ch]+ADDR_LR_FB_ALG,(chan[ch].state.alg&1)|(chan[ch].state.fb<<1)|((chan[ch].pan&3)<<4)); + rWrite(chanMap[ch]+ADDR_LR_FB_ALG,(chan[ch].state.alg&1)|(chan[ch].state.fb<<1)|((chan[ch].pan&15)<<4)); if (ops==4) { - rWrite(chanMap[ch+1]+ADDR_LR_FB_ALG,((chan[ch].state.alg>>1)&1)|(chan[ch].state.fb<<1)|((chan[ch].pan&3)<<4)); + rWrite(chanMap[ch+1]+ADDR_LR_FB_ALG,((chan[ch].state.alg>>1)&1)|(chan[ch].state.fb<<1)|((chan[ch].pan&15)<<4)); } } } @@ -797,7 +829,7 @@ int DivPlatformOPL::dispatch(DivCommand c) { rWrite(chanMap[ch]+ADDR_LR_FB_ALG,(chan[ch].state.alg&1)|(chan[ch].state.fb<<1)); } else { oldWrites[chanMap[ch]+ADDR_LR_FB_ALG]=-1; - rWrite(chanMap[ch]+ADDR_LR_FB_ALG,(chan[ch].state.alg&1)|(chan[ch].state.fb<<1)|((chan[ch].pan&3)<<4)); + rWrite(chanMap[ch]+ADDR_LR_FB_ALG,(chan[ch].state.alg&1)|(chan[ch].state.fb<<1)|((chan[ch].pan&15)<<4)); } } } else { @@ -847,10 +879,10 @@ int DivPlatformOPL::dispatch(DivCommand c) { } } else { oldWrites[chanMap[c.chan]+ADDR_LR_FB_ALG]=-1; - rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4)); + rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&15)<<4)); if (ops==4) { oldWrites[chanMap[c.chan+1]+ADDR_LR_FB_ALG]=-1; - rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4)); + rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&15)<<4)); } } } @@ -956,10 +988,11 @@ int DivPlatformOPL::dispatch(DivCommand c) { case DIV_CMD_PANNING: { if (oplType!=3) break; if (c.chan==adpcmChan) break; - if (c.value==0 && c.value2==0) { - chan[c.chan].pan=3; + chan[c.chan].pan&=~3; + if (c.value==0 && c.value2==0 && compatPan) { + chan[c.chan].pan|=3; } else { - chan[c.chan].pan=(c.value>0)|((c.value2>0)<<1); + chan[c.chan].pan|=(c.value>0)|((c.value2>0)<<1); } int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; if (isMuted[c.chan]) { @@ -968,9 +1001,36 @@ int DivPlatformOPL::dispatch(DivCommand c) { rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)); } } else { - rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4)); + rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&15)<<4)); if (ops==4) { - rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4)); + rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&15)<<4)); + } + } + break; + } + case DIV_CMD_SURROUND_PANNING: { + if (oplType!=3) break; + if (c.chan==adpcmChan) break; + + if (c.value==2) { + chan[c.chan].pan&=3; + if (c.value2>0) chan[c.chan].pan|=4; + } else if (c.value==3) { + if (c.value2>0) chan[c.chan].pan|=8; + } else { + break; + } + + int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; + if (isMuted[c.chan]) { + rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)); + if (ops==4) { + rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)); + } + } else { + rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&15)<<4)); + if (ops==4) { + rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&15)<<4)); } } break; @@ -1049,9 +1109,9 @@ int DivPlatformOPL::dispatch(DivCommand c) { rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)); } } else { - rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4)); + rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&15)<<4)); if (ops==4) { - rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4)); + rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&15)<<4)); } } break; @@ -1431,9 +1491,9 @@ void DivPlatformOPL::forceIns() { rWrite(chanMap[i+1]+ADDR_LR_FB_ALG,((chan[i].state.alg>>1)&1)|(chan[i].state.fb<<1)); } } else { - rWrite(chanMap[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&1)|(chan[i].state.fb<<1)|((chan[i].pan&3)<<4)); + rWrite(chanMap[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&1)|(chan[i].state.fb<<1)|((chan[i].pan&15)<<4)); if (ops==4) { - rWrite(chanMap[i+1]+ADDR_LR_FB_ALG,((chan[i].state.alg>>1)&1)|(chan[i].state.fb<<1)|((chan[i].pan&3)<<4)); + rWrite(chanMap[i+1]+ADDR_LR_FB_ALG,((chan[i].state.alg>>1)&1)|(chan[i].state.fb<<1)|((chan[i].pan&15)<<4)); } } */ @@ -1568,8 +1628,8 @@ void DivPlatformOPL::reset() { immWrite(0xbd,(dam<<7)|(dvb<<6)|(properDrums<<5)|drumState); } -bool DivPlatformOPL::isStereo() { - return (oplType==3 || oplType==759); +int DivPlatformOPL::getOutputCount() { + return totalOutputs; } bool DivPlatformOPL::keyOffAffectsArp(int ch) { @@ -1625,6 +1685,7 @@ void DivPlatformOPL::setOPLType(int type, bool drums) { if (type==8950) { adpcmChan=drums?11:9; } + totalOutputs=1; break; case 3: case 4: case 759: slotsNonDrums=slotsOPL3; @@ -1643,6 +1704,7 @@ void DivPlatformOPL::setOPLType(int type, bool drums) { chipFreqBase=32768*684; downsample=true; } + totalOutputs=(type==4)?6:4; break; } chipType=type; @@ -1681,6 +1743,8 @@ void DivPlatformOPL::setFlags(const DivConfig& flags) { rate=chipClock/36; }*/ + compatPan=false; + switch (chipType) { default: case 1: case 2: case 8950: @@ -1736,12 +1800,14 @@ void DivPlatformOPL::setFlags(const DivConfig& flags) { rate=chipClock/768; chipRateBase=chipClock/684; downsample=true; + totalOutputs=2; // Stereo output only break; default: // YMF262 chipFreqBase=32768*288; rate=chipClock/288; chipRateBase=rate; downsample=false; + totalOutputs=4; break; } reset(); @@ -1768,6 +1834,7 @@ void DivPlatformOPL::setFlags(const DivConfig& flags) { chipClock=rate*288; break; } + compatPan=flags.getBool("compatPan",false); for (int i=0; i<20; i++) { oscBuf[i]->rate=rate; diff --git a/src/engine/platform/opl.h b/src/engine/platform/opl.h index f4a6788cb..849ed0496 100644 --- a/src/engine/platform/opl.h +++ b/src/engine/platform/opl.h @@ -81,7 +81,7 @@ class DivPlatformOPL: public DivDispatch { const unsigned short* chanMap; const unsigned char* outChanMap; int chipFreqBase, chipRateBase; - int delay, chipType, oplType, chans, melodicChans, totalChans, adpcmChan, sampleBank; + int delay, chipType, oplType, chans, melodicChans, totalChans, adpcmChan, sampleBank, totalOutputs; unsigned char lastBusy; unsigned char drumState; unsigned char drumVol[5]; @@ -92,7 +92,7 @@ class DivPlatformOPL: public DivDispatch { unsigned char lfoValue; - bool useYMFM, update4OpMask, pretendYMU, downsample; + bool useYMFM, update4OpMask, pretendYMU, downsample, compatPan; short oldWrites[512]; short pendingWrites[512]; @@ -104,11 +104,11 @@ class DivPlatformOPL: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); - void acquire_nuked(short* bufL, short* bufR, size_t start, size_t len); - //void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len); + void acquire_nuked(short** buf, size_t len); + //void acquire_ymfm(short** buf, size_t len); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -119,7 +119,7 @@ class DivPlatformOPL: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); void setYMFM(bool use); void setOPLType(int type, bool drums); bool keyOffAffectsArp(int ch); diff --git a/src/engine/platform/opll.cpp b/src/engine/platform/opll.cpp index 8ffd65014..cba125c15 100644 --- a/src/engine/platform/opll.cpp +++ b/src/engine/platform/opll.cpp @@ -39,11 +39,11 @@ const unsigned char visMapOPLL[9]={ 6, 7, 8, 3, 4, 5, 0, 1, 2 }; -void DivPlatformOPLL::acquire_nuked(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformOPLL::acquire_nuked(short** buf, size_t len) { static int o[2]; static int os; - for (size_t h=start; h32767) os=32767; - bufL[h]=os; + buf[0][h]=os; } } -void DivPlatformOPLL::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformOPLL::acquire_ymfm(short** buf, size_t len) { } -void DivPlatformOPLL::acquire(short* bufL, short* bufR, size_t start, size_t len) { - acquire_nuked(bufL,bufR,start,len); +void DivPlatformOPLL::acquire(short** buf, size_t len) { + acquire_nuked(buf,len); } void DivPlatformOPLL::tick(bool sysTick) { @@ -124,7 +124,7 @@ void DivPlatformOPLL::tick(bool sysTick) { if (chan[i].std.pitch.had) { if (chan[i].std.pitch.mode) { chan[i].pitch2+=chan[i].std.pitch.val; - CLAMP_VAR(chan[i].pitch2,-32768,32767); + CLAMP_VAR(chan[i].pitch2,-65535,65535); } else { chan[i].pitch2=chan[i].std.pitch.val; } diff --git a/src/engine/platform/opll.h b/src/engine/platform/opll.h index a1eb70048..74d7b1bc3 100644 --- a/src/engine/platform/opll.h +++ b/src/engine/platform/opll.h @@ -77,11 +77,11 @@ class DivPlatformOPLL: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); - void acquire_nuked(short* bufL, short* bufR, size_t start, size_t len); - void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len); + void acquire_nuked(short** buf, size_t len); + void acquire_ymfm(short** buf, size_t len); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/platform/pce.cpp b/src/engine/platform/pce.cpp index 3d9c0aee9..3efbd7c8c 100644 --- a/src/engine/platform/pce.cpp +++ b/src/engine/platform/pce.cpp @@ -53,8 +53,8 @@ const char** DivPlatformPCE::getRegisterSheet() { return regCheatSheetPCE; } -void DivPlatformPCE::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t h=start; h32767) tempR[0]=32767; //printf("tempL: %d tempR: %d\n",tempL,tempR); - bufL[h]=tempL[0]; - bufR[h]=tempR[0]; + buf[0][h]=tempL[0]; + buf[1][h]=tempR[0]; } } @@ -242,6 +242,7 @@ void DivPlatformPCE::tick(bool sysTick) { chan[i].dacRate=((double)chipClock/2)/MAX(1,off*chan[i].freq); if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].dacRate); } + if (chan[i].freq<1) chan[i].freq=1; if (chan[i].freq>4095) chan[i].freq=4095; chWrite(i,0x02,chan[i].freq&0xff); chWrite(i,0x03,chan[i].freq>>8); @@ -547,8 +548,8 @@ void DivPlatformPCE::reset() { delay=500; } -bool DivPlatformPCE::isStereo() { - return true; +int DivPlatformPCE::getOutputCount() { + return 2; } bool DivPlatformPCE::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/pce.h b/src/engine/platform/pce.h index 7a417a2a2..6493840c1 100644 --- a/src/engine/platform/pce.h +++ b/src/engine/platform/pce.h @@ -76,7 +76,7 @@ class DivPlatformPCE: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -87,7 +87,7 @@ class DivPlatformPCE: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void setFlags(const DivConfig& flags); void notifyWaveChange(int wave); diff --git a/src/engine/platform/pcmdac.cpp b/src/engine/platform/pcmdac.cpp index abcdd39ff..2843f0797 100644 --- a/src/engine/platform/pcmdac.cpp +++ b/src/engine/platform/pcmdac.cpp @@ -26,13 +26,13 @@ // to ease the driver, freqency register is a 8.16 counter relative to output sample rate #define CHIP_FREQBASE 65536 -void DivPlatformPCMDAC::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformPCMDAC::acquire(short** buf, size_t len) { const int depthScale=(15-outDepth); int output=0; - for (size_t h=start; hdata[oscBuf->needle++]=0; continue; } @@ -157,12 +157,12 @@ void DivPlatformPCMDAC::acquire(short* bufL, short* bufR, size_t start, size_t l output=output*chan[0].vol*chan[0].envVol/16384; oscBuf->data[oscBuf->needle++]=output; if (outStereo) { - bufL[h]=((output*chan[0].panL)>>(depthScale+8))<>(depthScale+8))<>(depthScale+8))<>(depthScale+8))<>depthScale)<freq) pos=freq; @@ -207,17 +207,17 @@ void DivPlatformPCSpeaker::acquire_unfilt(short* bufL, short* bufR, size_t start } } out=(pos>(freq>>1) && !isMuted[0])?32767:0; - bufL[i]=out; + buf[0][i]=out; oscBuf->data[oscBuf->needle++]=out; } else { - bufL[i]=0; + buf[0][i]=0; oscBuf->data[oscBuf->needle++]=0; } } } -void DivPlatformPCSpeaker::acquire_cone(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t i=start; ifreq) pos=freq; @@ -234,17 +234,17 @@ void DivPlatformPCSpeaker::acquire_cone(short* bufL, short* bufR, size_t start, float out=(low+band)*0.75; if (out>1.0) out=1.0; if (out<-1.0) out=-1.0; - bufL[i]=out*32767; + buf[0][i]=out*32767; oscBuf->data[oscBuf->needle++]=out*32767; } else { - bufL[i]=0; + buf[0][i]=0; oscBuf->data[oscBuf->needle++]=0; } } } -void DivPlatformPCSpeaker::acquire_piezo(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t i=start; ifreq) pos=freq; @@ -261,10 +261,10 @@ void DivPlatformPCSpeaker::acquire_piezo(short* bufL, short* bufR, size_t start, float out=band*0.15-(next-low)*0.06; if (out>1.0) out=1.0; if (out<-1.0) out=-1.0; - bufL[i]=out*32767; + buf[0][i]=out*32767; oscBuf->data[oscBuf->needle++]=out*32767; } else { - bufL[i]=0; + buf[0][i]=0; oscBuf->data[oscBuf->needle++]=0; } } @@ -274,7 +274,7 @@ void DivPlatformPCSpeaker::beepFreq(int freq, int delay) { realQueueLock.lock(); #ifdef __linux__ struct timespec ts; - double addition=1000000000.0*(double)delay/(double)rate; + double addition=1000000000.0*(double)delay/parent->getAudioDescGot().rate; addition+=1500000000.0*((double)parent->getAudioDescGot().bufsize/parent->getAudioDescGot().rate); if (clock_gettime(CLOCK_MONOTONIC,&ts)<0) { ts.tv_sec=0; @@ -294,14 +294,14 @@ void DivPlatformPCSpeaker::beepFreq(int freq, int delay) { realOutCond.notify_one(); } -void DivPlatformPCSpeaker::acquire_real(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformPCSpeaker::acquire_real(short** buf, size_t len) { int out=0; if (lastOn!=on || lastFreq!=freq) { lastOn=on; lastFreq=freq; - beepFreq((on && !isMuted[0])?freq:0,start); + beepFreq((on && !isMuted[0])?freq:0,parent->getBufferPos()); } - for (size_t i=start; ifreq) pos=freq; @@ -317,23 +317,23 @@ void DivPlatformPCSpeaker::acquire_real(short* bufL, short* bufR, size_t start, } else { oscBuf->data[oscBuf->needle++]=0; } - bufL[i]=0; + buf[0][i]=0; } } -void DivPlatformPCSpeaker::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformPCSpeaker::acquire(short** buf, size_t len) { switch (speakerType) { case 0: - acquire_unfilt(bufL,bufR,start,len); + acquire_unfilt(buf,len); break; case 1: - acquire_cone(bufL,bufR,start,len); + acquire_cone(buf,len); break; case 2: - acquire_piezo(bufL,bufR,start,len); + acquire_piezo(buf,len); break; case 3: - acquire_real(bufL,bufR,start,len); + acquire_real(buf,len); break; } } diff --git a/src/engine/platform/pcspkr.h b/src/engine/platform/pcspkr.h index b3028d784..554c0d074 100644 --- a/src/engine/platform/pcspkr.h +++ b/src/engine/platform/pcspkr.h @@ -61,14 +61,14 @@ class DivPlatformPCSpeaker: public DivDispatch { void beepFreq(int freq, int delay=0); - void acquire_unfilt(short* bufL, short* bufR, size_t start, size_t len); - void acquire_cone(short* bufL, short* bufR, size_t start, size_t len); - void acquire_piezo(short* bufL, short* bufR, size_t start, size_t len); - void acquire_real(short* bufL, short* bufR, size_t start, size_t len); + void acquire_unfilt(short** buf, size_t len); + void acquire_cone(short** buf, size_t len); + void acquire_piezo(short** buf, size_t len); + void acquire_real(short** buf, size_t len); public: void pcSpeakerThread(); - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/platform/pet.cpp b/src/engine/platform/pet.cpp index b3279e8e1..b4399bcbc 100644 --- a/src/engine/platform/pet.cpp +++ b/src/engine/platform/pet.cpp @@ -55,14 +55,14 @@ void DivPlatformPET::rWrite(unsigned int addr, unsigned char val) { regPool[addr]=val; } -void DivPlatformPET::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformPET::acquire(short** buf, size_t len) { bool hwSROutput=((regPool[11]>>2)&7)==4; if (chan[0].enable) { int reload=regPool[8]*2+4; if (!hwSROutput) { reload+=regPool[9]*512; } - for (size_t h=start; hchan[0].cnt) { chan[0].out=(chan[0].sreg&1)*32767; chan[0].sreg=(chan[0].sreg>>1)|((chan[0].sreg&1)<<7); @@ -70,17 +70,15 @@ void DivPlatformPET::acquire(short* bufL, short* bufR, size_t start, size_t len) } else { chan[0].cnt-=SAMP_DIVIDER; } - bufL[h]=chan[0].out; - bufR[h]=chan[0].out; + buf[0][h]=chan[0].out; oscBuf->data[oscBuf->needle++]=chan[0].out; } // emulate driver writes to PCR if (!hwSROutput) regPool[12]=chan[0].out?0xe0:0xc0; } else { chan[0].out=0; - for (size_t h=start; hdata[oscBuf->needle++]=0; } } @@ -287,8 +285,8 @@ void DivPlatformPET::reset() { chan[0].std.setEngine(parent); } -bool DivPlatformPET::isStereo() { - return false; +int DivPlatformPET::getOutputCount() { + return 1; } void DivPlatformPET::notifyInsDeletion(void* ins) { diff --git a/src/engine/platform/pet.h b/src/engine/platform/pet.h index 0078e3f3f..5942817c2 100644 --- a/src/engine/platform/pet.h +++ b/src/engine/platform/pet.h @@ -45,7 +45,7 @@ class DivPlatformPET: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -57,7 +57,7 @@ class DivPlatformPET: public DivDispatch { void tick(bool sysTick=true); void muteChannel(int ch, bool mute); void notifyInsDeletion(void* ins); - bool isStereo(); + int getOutputCount(); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); diff --git a/src/engine/platform/pokemini.cpp b/src/engine/platform/pokemini.cpp index 7625f1ed7..9b543153c 100644 --- a/src/engine/platform/pokemini.cpp +++ b/src/engine/platform/pokemini.cpp @@ -86,9 +86,9 @@ void DivPlatformPokeMini::rWrite(unsigned char addr, unsigned char val) { } } -void DivPlatformPokeMini::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformPokeMini::acquire(short** buf, size_t len) { int out=0; - for (size_t i=start; i=pivot && !isMuted[0])?volTable[vol&3]:0; - bufL[i]=out; + buf[0][i]=out; oscBuf->data[oscBuf->needle++]=out; } else { - bufL[i]=0; + buf[0][i]=0; oscBuf->data[oscBuf->needle++]=0; } } diff --git a/src/engine/platform/pokemini.h b/src/engine/platform/pokemini.h index 7fc17ddf2..80233eb42 100644 --- a/src/engine/platform/pokemini.h +++ b/src/engine/platform/pokemini.h @@ -46,7 +46,7 @@ class DivPlatformPokeMini: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/platform/pokey.cpp b/src/engine/platform/pokey.cpp index a79ec4537..8294d9dcc 100644 --- a/src/engine/platform/pokey.cpp +++ b/src/engine/platform/pokey.cpp @@ -64,16 +64,16 @@ const char** DivPlatformPOKEY::getRegisterSheet() { return regCheatSheetPOKEY; } -void DivPlatformPOKEY::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformPOKEY::acquire(short** buf, size_t len) { if (useAltASAP) { - acquireASAP(bufL, start, len); + acquireASAP(buf[0],len); } else { - acquireMZ(bufL, start, len); + acquireMZ(buf[0],len); } } -void DivPlatformPOKEY::acquireMZ(short* buf, size_t start, size_t len) { - for (size_t h=start; h=2) { oscBufDelay=0; buf[h]=altASAP.sampleAudio(oscBuf); @@ -241,7 +241,7 @@ void DivPlatformPOKEY::tick(bool sysTick) { chan[i].ctlChanged=false; if ((i==1 && audctl&16) || (i==3 && audctl&8)) { // ignore - channel is paired - } else if ((i==0 && audctl&16) || (i==0 && audctl&8)) { + } else if ((i==0 && audctl&16) || (i==2 && audctl&8)) { rWrite(1+(i<<1),0); rWrite(3+(i<<1),val); } else { diff --git a/src/engine/platform/pokey.h b/src/engine/platform/pokey.h index e68178a2c..79206a745 100644 --- a/src/engine/platform/pokey.h +++ b/src/engine/platform/pokey.h @@ -58,9 +58,9 @@ class DivPlatformPOKEY: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); - void acquireMZ(short* buf, size_t start, size_t len); - void acquireASAP(short* buf, size_t start, size_t len); + void acquire(short** buf, size_t len); + void acquireMZ(short* buf, size_t len); + void acquireASAP(short* buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/platform/pong.cpp b/src/engine/platform/pong.cpp index 0c97391c4..27fd76b38 100644 --- a/src/engine/platform/pong.cpp +++ b/src/engine/platform/pong.cpp @@ -23,19 +23,19 @@ #define CHIP_DIVIDER 1024 -void DivPlatformPong::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformPong::acquire(short** buf, size_t len) { int out=0; - for (size_t i=start; idata[oscBuf->needle++]=out; } else { - bufL[i]=0; + buf[0][i]=0; oscBuf->data[oscBuf->needle++]=0; flip=false; } diff --git a/src/engine/platform/pong.h b/src/engine/platform/pong.h index 835809f5c..8259b14cf 100644 --- a/src/engine/platform/pong.h +++ b/src/engine/platform/pong.h @@ -39,7 +39,7 @@ class DivPlatformPong: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/platform/qsound.cpp b/src/engine/platform/qsound.cpp index bc9e0f2ab..57ab138c6 100644 --- a/src/engine/platform/qsound.cpp +++ b/src/engine/platform/qsound.cpp @@ -265,11 +265,11 @@ const char** DivPlatformQSound::getRegisterSheet() { return regCheatSheetQSound; } -void DivPlatformQSound::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t h=start; hsong.sampleLen; i++) { DivSample* s=parent->song.sample[i]; @@ -818,6 +819,7 @@ int DivPlatformQSound::init(DivEngine* p, int channels, int sugRate, const DivCo sampleMem=new unsigned char[getSampleMemCapacity()]; sampleMemLen=0; sampleMemLenBS=0; + sampleMemUsage=0; chip.rom_data=sampleMem; chip.rom_mask=0xffffff; reset(); diff --git a/src/engine/platform/qsound.h b/src/engine/platform/qsound.h index dbdffd051..c04514ed8 100644 --- a/src/engine/platform/qsound.h +++ b/src/engine/platform/qsound.h @@ -50,6 +50,7 @@ class DivPlatformQSound: public DivDispatch { unsigned char* sampleMem; size_t sampleMemLen; size_t sampleMemLenBS; + size_t sampleMemUsage; bool sampleLoaded[256]; bool sampleLoadedBS[256]; struct qsound_chip chip; @@ -62,7 +63,7 @@ class DivPlatformQSound: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -74,7 +75,7 @@ class DivPlatformQSound: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void setFlags(const DivConfig& flags); void notifyInsChange(int ins); diff --git a/src/engine/platform/rf5c68.cpp b/src/engine/platform/rf5c68.cpp index bf87ce761..e5484dc77 100644 --- a/src/engine/platform/rf5c68.cpp +++ b/src/engine/platform/rf5c68.cpp @@ -54,25 +54,27 @@ void DivPlatformRF5C68::chWrite(unsigned char ch, unsigned int addr, unsigned ch } } -void DivPlatformRF5C68::acquire(short* bufL, short* bufR, size_t start, size_t len) { - short buf[16][256]; +// TODO: this code is weird +// make sure newDispatch didn't break it up +void DivPlatformRF5C68::acquire(short** buf, size_t len) { + short bufC[16][256]; short* chBufPtrs[16]={ - buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7], - buf[8],buf[9],buf[10],buf[11],buf[12],buf[13],buf[14],buf[15] + bufC[0],bufC[1],bufC[2],bufC[3],bufC[4],bufC[5],bufC[6],bufC[7], + bufC[8],bufC[9],bufC[10],bufC[11],bufC[12],bufC[13],bufC[14],bufC[15] }; - size_t pos=start; + size_t pos=0; for (int i=0; i<16; i++) { - memset(buf[i],0,256*sizeof(short)); + memset(bufC[i],0,256*sizeof(short)); } while (len > 0) { size_t blockLen=MIN(len,256); - short* bufPtrs[2]={&bufL[pos],&bufR[pos]}; + short* bufPtrs[2]={&buf[0][pos],&buf[1][pos]}; rf5c68.sound_stream_update(bufPtrs,chBufPtrs,blockLen); for (int i=0; i<8; i++) { for (size_t j=0; jdata[oscBuf[i]->needle++]=buf[i*2][j]+buf[i*2+1][j]; + oscBuf[i]->data[oscBuf[i]->needle++]=bufC[i*2][j]+bufC[i*2+1][j]; } } pos+=blockLen; @@ -332,8 +334,8 @@ void DivPlatformRF5C68::reset() { } } -bool DivPlatformRF5C68::isStereo() { - return true; +int DivPlatformRF5C68::getOutputCount() { + return 2; } void DivPlatformRF5C68::notifyInsChange(int ins) { diff --git a/src/engine/platform/rf5c68.h b/src/engine/platform/rf5c68.h index 2703a2900..98fc1a759 100644 --- a/src/engine/platform/rf5c68.h +++ b/src/engine/platform/rf5c68.h @@ -56,7 +56,7 @@ class DivPlatformRF5C68: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -67,7 +67,7 @@ class DivPlatformRF5C68: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); void setChipModel(int type); void notifyInsChange(int ins); void notifyWaveChange(int wave); diff --git a/src/engine/platform/saa.cpp b/src/engine/platform/saa.cpp index 102b00216..924bc73ac 100644 --- a/src/engine/platform/saa.cpp +++ b/src/engine/platform/saa.cpp @@ -56,7 +56,7 @@ const char** DivPlatformSAA1099::getRegisterSheet() { return regCheatSheetSAA; } -void DivPlatformSAA1099::acquire_saaSound(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformSAA1099::acquire_saaSound(short** buf, size_t len) { if (saaBufLenGenerateMany((unsigned char*)saaBuf[0],len,oscBuf); #ifdef TA_BIG_ENDIAN for (size_t i=0; i>8)); - bufR[i+start]=(short)((((unsigned short)saaBuf[0][i<<1])<<8)|(((unsigned short)saaBuf[0][i<<1])>>8)); + buf[0][i]=(short)((((unsigned short)saaBuf[0][1+(i<<1)])<<8)|(((unsigned short)saaBuf[0][1+(i<<1)])>>8)); + buf[1][i]=(short)((((unsigned short)saaBuf[0][i<<1])<<8)|(((unsigned short)saaBuf[0][i<<1])>>8)); } #else for (size_t i=0; itick(); } short out=(short)scc->out()<<5; - bufL[h]=bufR[h]=out; + buf[0][h]=out; for (int i=0; i<5; i++) { oscBuf[i]->data[oscBuf[i]->needle++]=scc->voice_out(i)<<7; @@ -335,8 +335,8 @@ void DivPlatformSCC::reset() { lastUpdated34=0; } -bool DivPlatformSCC::isStereo() { - return false; +int DivPlatformSCC::getOutputCount() { + return 1; } void DivPlatformSCC::notifyWaveChange(int wave) { diff --git a/src/engine/platform/scc.h b/src/engine/platform/scc.h index 5c4db4e28..1c7364723 100644 --- a/src/engine/platform/scc.h +++ b/src/engine/platform/scc.h @@ -50,7 +50,7 @@ class DivPlatformSCC: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -61,7 +61,7 @@ class DivPlatformSCC: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); diff --git a/src/engine/platform/segapcm.cpp b/src/engine/platform/segapcm.cpp index a206de5c0..25af42113 100644 --- a/src/engine/platform/segapcm.cpp +++ b/src/engine/platform/segapcm.cpp @@ -26,10 +26,10 @@ //#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;} //#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} } -void DivPlatformSegaPCM::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformSegaPCM::acquire(short** buf, size_t len) { static int os[2]; - for (size_t h=start; h32767) os[1]=32767; - bufL[h]=os[0]; - bufR[h]=os[1]; + buf[0][h]=os[0]; + buf[1][h]=os[1]; } } @@ -502,8 +502,8 @@ void DivPlatformSegaPCM::setFlags(const DivConfig& flags) { } } -bool DivPlatformSegaPCM::isStereo() { - return true; +int DivPlatformSegaPCM::getOutputCount() { + return 2; } int DivPlatformSegaPCM::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { diff --git a/src/engine/platform/segapcm.h b/src/engine/platform/segapcm.h index 0c99a20ca..3164e1b98 100644 --- a/src/engine/platform/segapcm.h +++ b/src/engine/platform/segapcm.h @@ -77,7 +77,7 @@ class DivPlatformSegaPCM: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -91,7 +91,7 @@ class DivPlatformSegaPCM: public DivDispatch { void notifyInsChange(int ins); void renderSamples(int chipID); void setFlags(const DivConfig& flags); - bool isStereo(); + int getOutputCount(); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index dd639b64e..cfe04d183 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -39,10 +39,10 @@ const char** DivPlatformSMS::getRegisterSheet() { return stereo?regCheatSheetGG:regCheatSheetSN; } -void DivPlatformSMS::acquire_nuked(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformSMS::acquire_nuked(short** buf, size_t len) { int oL=0; int oR=0; - for (size_t h=start; h32767) oL=32767; if (oR<-32768) oR=-32768; if (oR>32767) oR=32767; - bufL[h]=oL; - bufR[h]=oR; + buf[0][h]=oL; + if (stereo) buf[1][h]=oR; for (int i=0; i<4; i++) { if (isMuted[i]) { oscBuf[i]->data[oscBuf[i]->needle++]=0; @@ -85,7 +85,7 @@ void DivPlatformSMS::acquire_nuked(short* bufL, short* bufR, size_t start, size_ } } -void DivPlatformSMS::acquire_mame(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformSMS::acquire_mame(short** buf, size_t len) { while (!writes.empty()) { QueuedWrite w=writes.front(); if (stereo && (w.addr==1)) @@ -95,10 +95,10 @@ void DivPlatformSMS::acquire_mame(short* bufL, short* bufR, size_t start, size_t } writes.pop(); } - for (size_t h=start; hsound_stream_update(outs,1); for (int i=0; i<4; i++) { @@ -111,11 +111,11 @@ void DivPlatformSMS::acquire_mame(short* bufL, short* bufR, size_t start, size_t } } -void DivPlatformSMS::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformSMS::acquire(short** buf, size_t len) { if (nuked) { - acquire_nuked(bufL,bufR,start,len); + acquire_nuked(buf,len); } else { - acquire_mame(bufL,bufR,start,len); + acquire_mame(buf,len); } } @@ -445,8 +445,8 @@ void DivPlatformSMS::reset() { } } -bool DivPlatformSMS::isStereo() { - return stereo; +int DivPlatformSMS::getOutputCount() { + return stereo?2:1; } bool DivPlatformSMS::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/sms.h b/src/engine/platform/sms.h index 7bb3b1b16..cd0a7a1f6 100644 --- a/src/engine/platform/sms.h +++ b/src/engine/platform/sms.h @@ -66,10 +66,10 @@ class DivPlatformSMS: public DivDispatch { double NOTE_SN(int ch, int note); int snCalcFreq(int ch); - void acquire_nuked(short* bufL, short* bufR, size_t start, size_t len); - void acquire_mame(short* bufL, short* bufR, size_t start, size_t len); + void acquire_nuked(short** buf, size_t len); + void acquire_mame(short** buf, size_t len); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -78,7 +78,7 @@ class DivPlatformSMS: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); bool keyOffAffectsPorta(int ch); int getPortaFloor(int ch); diff --git a/src/engine/platform/snes.cpp b/src/engine/platform/snes.cpp index 053ac9b76..6fb942d48 100644 --- a/src/engine/platform/snes.cpp +++ b/src/engine/platform/snes.cpp @@ -65,10 +65,10 @@ const char** DivPlatformSNES::getRegisterSheet() { return regCheatSheetSNESDSP; } -void DivPlatformSNES::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformSNES::acquire(short** buf, size_t len) { short out[2]; short chOut[16]; - for (size_t h=start; h>2; if (next<-32768) next=-32768; @@ -768,8 +768,8 @@ void DivPlatformSNES::reset() { initEcho(); } -bool DivPlatformSNES::isStereo() { - return true; +int DivPlatformSNES::getOutputCount() { + return 2; } void DivPlatformSNES::notifyInsChange(int ins) { diff --git a/src/engine/platform/snes.h b/src/engine/platform/snes.h index 8d5e25311..884c7d804 100644 --- a/src/engine/platform/snes.h +++ b/src/engine/platform/snes.h @@ -93,7 +93,7 @@ class DivPlatformSNES: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -104,7 +104,7 @@ class DivPlatformSNES: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); void notifyInsChange(int ins); void notifyWaveChange(int wave); void setFlags(const DivConfig& flags); diff --git a/src/engine/platform/sound/ay8910.cpp b/src/engine/platform/sound/ay8910.cpp index c7be503e7..530b03d0c 100644 --- a/src/engine/platform/sound/ay8910.cpp +++ b/src/engine/platform/sound/ay8910.cpp @@ -1064,12 +1064,11 @@ void ay8910_device::sound_stream_update(short** outputs, int outLen) tone = &m_tone[chan]; const int period = std::max(1, tone->period) * (m_step_mul << 1); tone->count += is_expanded_mode() ? 32 : ((m_feature & PSG_HAS_EXPANDED_MODE) ? 1 : 2); - while (tone->count >= period) - { - tone->duty_cycle = (tone->duty_cycle - 1) & 0x1f; - tone->output = is_expanded_mode() ? BIT(duty_cycle[tone_duty(tone)], tone->duty_cycle) : BIT(tone->duty_cycle, 0); - tone->count -= period; - } + if (tone->count>=period) { + tone->duty_cycle = (tone->duty_cycle - (tone->count/period)) & 0x1f; + tone->output = is_expanded_mode() ? BIT(duty_cycle[tone_duty(tone)], tone->duty_cycle) : BIT(tone->duty_cycle, 0); + tone->count = tone->count % period; + } } const int period_noise = (int)(noise_period()) * m_step_mul; diff --git a/src/engine/platform/sound/namco.cpp b/src/engine/platform/sound/namco.cpp index 473a80c6e..ee4c1b16a 100644 --- a/src/engine/platform/sound/namco.cpp +++ b/src/engine/platform/sound/namco.cpp @@ -659,11 +659,13 @@ void namco_audio_device::sound_stream_update(short** outputs, int len) { lmix[i]+=l_noise_data; rmix[i]+=r_noise_data; + voice->last_out=(l_noise_data+r_noise_data)>>1; } else { lmix[i]+=-l_noise_data; rmix[i]+=-r_noise_data; + voice->last_out=-((l_noise_data+r_noise_data)>>1); } if (hold) diff --git a/src/engine/platform/su.cpp b/src/engine/platform/su.cpp index 1508c6846..51b04e0e6 100644 --- a/src/engine/platform/su.cpp +++ b/src/engine/platform/su.cpp @@ -40,14 +40,14 @@ double DivPlatformSoundUnit::NOTE_SU(int ch, int note) { return NOTE_FREQUENCY(note); } -void DivPlatformSoundUnit::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t h=start; hWrite(w.addr,w.val); writes.pop(); } - su->NextSample(&bufL[h],&bufR[h]); + su->NextSample(&buf[0][h],&buf[1][h]); for (int i=0; i<8; i++) { oscBuf[i]->data[oscBuf[i]->needle++]=su->GetSample(i); } @@ -499,8 +499,8 @@ void DivPlatformSoundUnit::reset() { rWrite(0xbd,fil1); } -bool DivPlatformSoundUnit::isStereo() { - return true; +int DivPlatformSoundUnit::getOutputCount() { + return 2; } bool DivPlatformSoundUnit::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/su.h b/src/engine/platform/su.h index ebaa911b9..518edafa4 100644 --- a/src/engine/platform/su.h +++ b/src/engine/platform/su.h @@ -98,7 +98,7 @@ class DivPlatformSoundUnit: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -109,7 +109,7 @@ class DivPlatformSoundUnit: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); diff --git a/src/engine/platform/swan.cpp b/src/engine/platform/swan.cpp index f10a4e4e6..f5a2dfb9a 100644 --- a/src/engine/platform/swan.cpp +++ b/src/engine/platform/swan.cpp @@ -50,8 +50,8 @@ const char** DivPlatformSwan::getRegisterSheet() { return regCheatSheetWS; } -void DivPlatformSwan::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t h=start; hSoundUpdate(16); ws->SoundFlush(samp, 1); - bufL[h]=samp[0]; - bufR[h]=samp[1]; + buf[0][h]=samp[0]; + buf[1][h]=samp[1]; for (int i=0; i<4; i++) { oscBuf[i]->data[oscBuf[i]->needle++]=(ws->sample_cache[i][0]+ws->sample_cache[i][1])<<6; } @@ -490,8 +490,8 @@ void DivPlatformSwan::reset() { rWrite(0x11,0x09); // enable speakers } -bool DivPlatformSwan::isStereo() { - return true; +int DivPlatformSwan::getOutputCount() { + return 2; } void DivPlatformSwan::notifyWaveChange(int wave) { diff --git a/src/engine/platform/swan.h b/src/engine/platform/swan.h index b93f0859d..6f129e6dd 100644 --- a/src/engine/platform/swan.h +++ b/src/engine/platform/swan.h @@ -56,7 +56,7 @@ class DivPlatformSwan: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -69,7 +69,7 @@ class DivPlatformSwan: public DivDispatch { void muteChannel(int ch, bool mute); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); - bool isStereo(); + int getOutputCount(); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); diff --git a/src/engine/platform/t6w28.cpp b/src/engine/platform/t6w28.cpp index c1689977e..e81d156f1 100644 --- a/src/engine/platform/t6w28.cpp +++ b/src/engine/platform/t6w28.cpp @@ -35,8 +35,8 @@ const char** DivPlatformT6W28::getRegisterSheet() { return regCheatSheetT6W28; } -void DivPlatformT6W28::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t h=start; h32767) tempR=32767; - bufL[h]=tempL; - bufR[h]=tempR; + buf[0][h]=tempL; + buf[1][h]=tempR; } } @@ -289,6 +289,7 @@ void DivPlatformT6W28::forceIns() { chan[i].insChanged=true; chan[i].freqChanged=true; } + rWrite(1,0xe0+chan[3].duty); } void* DivPlatformT6W28::getChanState(int ch) { @@ -336,8 +337,8 @@ void DivPlatformT6W28::reset() { rWrite(1,0xe7); } -bool DivPlatformT6W28::isStereo() { - return true; +int DivPlatformT6W28::getOutputCount() { + return 2; } bool DivPlatformT6W28::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/t6w28.h b/src/engine/platform/t6w28.h index c526fd5d8..dd49d1b86 100644 --- a/src/engine/platform/t6w28.h +++ b/src/engine/platform/t6w28.h @@ -59,7 +59,7 @@ class DivPlatformT6W28: public DivDispatch { void writeOutVol(int ch); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -70,7 +70,7 @@ class DivPlatformT6W28: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); diff --git a/src/engine/platform/tia.cpp b/src/engine/platform/tia.cpp index 9517204e3..02f422011 100644 --- a/src/engine/platform/tia.cpp +++ b/src/engine/platform/tia.cpp @@ -38,16 +38,16 @@ const char** DivPlatformTIA::getRegisterSheet() { return regCheatSheetTIA; } -void DivPlatformTIA::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t h=start; h>1; + buf[0][h]=(tia.myCurrentSample[0]+tia.myCurrentSample[1])>>1; } else { - bufL[h]=tia.myCurrentSample[0]; + buf[0][h]=tia.myCurrentSample[0]; } if (++chanOscCounter>=114) { chanOscCounter=0; @@ -342,8 +342,8 @@ float DivPlatformTIA::getPostAmp() { return 0.5f; } -bool DivPlatformTIA::isStereo() { - return (mixingType==2); +int DivPlatformTIA::getOutputCount() { + return (mixingType==2)?2:1; } bool DivPlatformTIA::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/tia.h b/src/engine/platform/tia.h index d60d41656..b4b867dc4 100644 --- a/src/engine/platform/tia.h +++ b/src/engine/platform/tia.h @@ -45,7 +45,7 @@ class DivPlatformTIA: public DivDispatch { unsigned char dealWithFreq(unsigned char shape, int base, int pitch); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -58,7 +58,7 @@ class DivPlatformTIA: public DivDispatch { void muteChannel(int ch, bool mute); void setFlags(const DivConfig& flags); float getPostAmp(); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); diff --git a/src/engine/platform/tx81z.cpp b/src/engine/platform/tx81z.cpp index 88266114c..fa3d4d18a 100644 --- a/src/engine/platform/tx81z.cpp +++ b/src/engine/platform/tx81z.cpp @@ -55,12 +55,12 @@ const char** DivPlatformTX81Z::getRegisterSheet() { return regCheatSheetOPZ; } -void DivPlatformTX81Z::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformTX81Z::acquire(short** buf, size_t len) { static int os[2]; ymfm::ym2414::fm_engine* fme=fm_ymfm->debug_engine(); - for (size_t h=start; h32767) os[1]=32767; - bufL[h]=os[0]; - bufR[h]=os[1]; + buf[0][h]=os[0]; + buf[1][h]=os[1]; } } @@ -152,6 +152,14 @@ void DivPlatformTX81Z::tick(bool sysTick) { chan[i].freqChanged=true; } + if (chan[i].std.panL.had) { + chan[i].chVolL=(chan[i].std.panL.val&2)>>1; + chan[i].chVolR=chan[i].std.panL.val&1; + chan[i].freqChanged=true; + + immWrite(chanOffs[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)|(chan[i].active?0x40:0)|(chan[i].chVolR<<7)); + } + if (chan[i].std.phaseReset.had) { if (chan[i].std.phaseReset.val==1 && chan[i].active) { chan[i].keyOn=true; @@ -933,22 +941,23 @@ void DivPlatformTX81Z::setFlags(const DivConfig& flags) { int clockSel=flags.getInt("clockSel",0); if (clockSel==2) { chipClock=4000000.0; - baseFreqOff=-122; } else if (clockSel==1) { chipClock=COLOR_PAL*4.0/5.0; - baseFreqOff=12; } else { chipClock=COLOR_NTSC; - baseFreqOff=0; } + CHECK_CUSTOM_CLOCK; + + baseFreqOff=round(768.0*(log((COLOR_NTSC/(double)chipClock))/log(2.0))); + rate=chipClock/64; for (int i=0; i<8; i++) { oscBuf[i]->rate=rate; } } -bool DivPlatformTX81Z::isStereo() { - return true; +int DivPlatformTX81Z::getOutputCount() { + return 2; } int DivPlatformTX81Z::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { diff --git a/src/engine/platform/tx81z.h b/src/engine/platform/tx81z.h index b180f28c5..4dea61e70 100644 --- a/src/engine/platform/tx81z.h +++ b/src/engine/platform/tx81z.h @@ -60,7 +60,7 @@ class DivPlatformTX81Z: public DivPlatformOPM { friend void putDispatchChip(void*,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -73,7 +73,7 @@ class DivPlatformTX81Z: public DivPlatformOPM { void muteChannel(int ch, bool mute); void notifyInsChange(int ins); void setFlags(const DivConfig& flags); - bool isStereo(); + int getOutputCount(); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); diff --git a/src/engine/platform/vb.cpp b/src/engine/platform/vb.cpp index 5d79e5083..374aebaaf 100644 --- a/src/engine/platform/vb.cpp +++ b/src/engine/platform/vb.cpp @@ -93,8 +93,8 @@ const char** DivPlatformVB::getRegisterSheet() { return regCheatSheetVB; } -void DivPlatformVB::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t h=start; h32767) tempR=32767; - bufL[h]=tempL; - bufR[h]=tempR; + buf[0][h]=tempL; + buf[1][h]=tempR; } } @@ -465,8 +465,8 @@ void DivPlatformVB::reset() { delay=500; } -bool DivPlatformVB::isStereo() { - return true; +int DivPlatformVB::getOutputCount() { + return 2; } bool DivPlatformVB::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/vb.h b/src/engine/platform/vb.h index bcce42fee..7475c7453 100644 --- a/src/engine/platform/vb.h +++ b/src/engine/platform/vb.h @@ -64,7 +64,7 @@ class DivPlatformVB: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -76,7 +76,7 @@ class DivPlatformVB: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); float getPostAmp(); void setFlags(const DivConfig& flags); diff --git a/src/engine/platform/vera.cpp b/src/engine/platform/vera.cpp index 5021ac854..ba9f95fe0 100644 --- a/src/engine/platform/vera.cpp +++ b/src/engine/platform/vera.cpp @@ -53,11 +53,11 @@ const char** DivPlatformVERA::getRegisterSheet() { return regCheatSheetVERA; } -void DivPlatformVERA::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformVERA::acquire(short** buf, size_t len) { // both PSG part and PCM part output a full 16-bit range, putting bufL/R // argument right into both could cause an overflow - short buf[4][128]; - size_t pos=start; + short whyCallItBuf[4][128]; + size_t pos=0; DivSample* s=parent->getSample(chan[16].pcm.sample); while (len>0) { if (s->samples>0) { @@ -98,18 +98,18 @@ void DivPlatformVERA::acquire(short* bufL, short* bufR, size_t start, size_t len chan[16].pcm.sample=-1; } int curLen=MIN(len,128); - memset(buf,0,sizeof(buf)); - pcm_render(pcm,buf[2],buf[3],curLen); + memset(whyCallItBuf,0,sizeof(whyCallItBuf)); + pcm_render(pcm,whyCallItBuf[2],whyCallItBuf[3],curLen); for (int i=0; idata[oscBuf[i]->needle++]=psg->channels[i].lastOut<<4; } - int pcmOut=buf[2][i]+buf[3][i]; + int pcmOut=whyCallItBuf[2][i]+whyCallItBuf[3][i]; if (pcmOut<-32768) pcmOut=-32768; if (pcmOut>32767) pcmOut=32767; oscBuf[16]->data[oscBuf[16]->needle++]=pcmOut; @@ -406,8 +406,8 @@ float DivPlatformVERA::getPostAmp() { return 4.0f; } -bool DivPlatformVERA::isStereo() { - return true; +int DivPlatformVERA::getOutputCount() { + return 2; } void DivPlatformVERA::notifyInsDeletion(void* ins) { diff --git a/src/engine/platform/vera.h b/src/engine/platform/vera.h index 57be5dc9a..762a32c87 100644 --- a/src/engine/platform/vera.h +++ b/src/engine/platform/vera.h @@ -60,7 +60,7 @@ class DivPlatformVERA: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -72,7 +72,7 @@ class DivPlatformVERA: public DivDispatch { void muteChannel(int ch, bool mute); void notifyInsDeletion(void* ins); float getPostAmp(); - bool isStereo(); + int getOutputCount(); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); diff --git a/src/engine/platform/vic20.cpp b/src/engine/platform/vic20.cpp index 3e8046d28..3a4e25721 100644 --- a/src/engine/platform/vic20.cpp +++ b/src/engine/platform/vic20.cpp @@ -39,13 +39,13 @@ const char** DivPlatformVIC20::getRegisterSheet() { return regCheatSheetVIC; } -void DivPlatformVIC20::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformVIC20::acquire(short** buf, size_t len) { const unsigned char loadFreq[3] = {0x7e, 0x7d, 0x7b}; const unsigned char wavePatterns[16] = { 0b0, 0b10, 0b100, 0b110, 0b1000, 0b1010, 0b1011, 0b1110, 0b10010, 0b10100, 0b10110, 0b11000, 0b11010, 0b100100, 0b101010, 0b101100 }; - for (size_t h=start; hdata[oscBuf[i]->needle++]=vic->ch[i].out?(vic->volume<<11):0; } @@ -299,8 +298,8 @@ void DivPlatformVIC20::reset() { vic_sound_clock(vic,4); } -bool DivPlatformVIC20::isStereo() { - return false; +int DivPlatformVIC20::getOutputCount() { + return 1; } void DivPlatformVIC20::notifyInsDeletion(void* ins) { diff --git a/src/engine/platform/vic20.h b/src/engine/platform/vic20.h index a2628872e..3fc9fade5 100644 --- a/src/engine/platform/vic20.h +++ b/src/engine/platform/vic20.h @@ -43,7 +43,7 @@ class DivPlatformVIC20: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -56,7 +56,7 @@ class DivPlatformVIC20: public DivDispatch { void muteChannel(int ch, bool mute); void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); - bool isStereo(); + int getOutputCount(); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); diff --git a/src/engine/platform/vrc6.cpp b/src/engine/platform/vrc6.cpp index bb1a7a42a..f798d6e8d 100644 --- a/src/engine/platform/vrc6.cpp +++ b/src/engine/platform/vrc6.cpp @@ -46,8 +46,8 @@ const char** DivPlatformVRC6::getRegisterSheet() { return regCheatSheetVRC6; } -void DivPlatformVRC6::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t i=start; i32767) sample=32767; if (sample<-32768) sample=-32768; - bufL[i]=bufR[i]=sample; + buf[0][i]=sample; // Oscilloscope buffer part if (++writeOscBuf>=32) { diff --git a/src/engine/platform/vrc6.h b/src/engine/platform/vrc6.h index 3cb02c415..5facd13a6 100644 --- a/src/engine/platform/vrc6.h +++ b/src/engine/platform/vrc6.h @@ -61,7 +61,7 @@ class DivPlatformVRC6: public DivDispatch, public vrcvi_intf { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/platform/x1_010.cpp b/src/engine/platform/x1_010.cpp index 093b952c2..12e6280d9 100644 --- a/src/engine/platform/x1_010.cpp +++ b/src/engine/platform/x1_010.cpp @@ -205,8 +205,8 @@ const char** DivPlatformX1_010::getRegisterSheet() { return regCheatSheetX1_010; } -void DivPlatformX1_010::acquire(short* bufL, short* bufR, size_t start, size_t len) { - for (size_t h=start; h32767) tempR=32767; //printf("tempL: %d tempR: %d\n",tempL,tempR); - bufL[h]=stereo?tempL:((tempL+tempR)>>1); - bufR[h]=stereo?tempR:bufL[h]; + buf[0][h]=stereo?tempL:((tempL+tempR)>>1); + if (stereo) buf[1][h]=tempR; for (int i=0; i<16; i++) { oscBuf[i]->data[oscBuf[i]->needle++]=(x1_010.voice_out(i,0)+x1_010.voice_out(i,1))>>1; @@ -362,7 +362,7 @@ void DivPlatformX1_010::tick(bool sysTick) { if (chan[i].std.pitch.had) { if (chan[i].std.pitch.mode) { chan[i].pitch2+=chan[i].std.pitch.val; - CLAMP_VAR(chan[i].pitch2,-32768,32767); + CLAMP_VAR(chan[i].pitch2,-65535,65535); } else { chan[i].pitch2=chan[i].std.pitch.val; } @@ -484,6 +484,7 @@ void DivPlatformX1_010::tick(bool sysTick) { if (chan[i].freq>255) chan[i].freq=255; chWrite(i,2,chan[i].freq&0xff); } else { + if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq>65535) chan[i].freq=65535; chWrite(i,2,chan[i].freq&0xff); chWrite(i,3,(chan[i].freq>>8)&0xff); @@ -894,8 +895,8 @@ void DivPlatformX1_010::reset() { } } -bool DivPlatformX1_010::isStereo() { - return stereo; +int DivPlatformX1_010::getOutputCount() { + return stereo?2:1; } bool DivPlatformX1_010::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/x1_010.h b/src/engine/platform/x1_010.h index 28b180eb4..eaa4258af 100644 --- a/src/engine/platform/x1_010.h +++ b/src/engine/platform/x1_010.h @@ -127,7 +127,7 @@ class DivPlatformX1_010: public DivDispatch, public vgsound_emu_mem_intf { friend void putDispatchChan(void*,int,int); public: u8 read_byte(u32 address); - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -138,7 +138,7 @@ class DivPlatformX1_010: public DivDispatch, public vgsound_emu_mem_intf { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void setFlags(const DivConfig& flags); void notifyWaveChange(int wave); diff --git a/src/engine/platform/ym2203.cpp b/src/engine/platform/ym2203.cpp index 3419a1b6e..493adfc3a 100644 --- a/src/engine/platform/ym2203.cpp +++ b/src/engine/platform/ym2203.cpp @@ -156,19 +156,19 @@ const char** DivPlatformYM2203::getRegisterSheet() { return regCheatSheetYM2203; } -void DivPlatformYM2203::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformYM2203::acquire(short** buf, size_t len) { if (useCombo) { - acquire_combo(bufL,bufR,start,len); + acquire_combo(buf,len); } else { - acquire_ymfm(bufL,bufR,start,len); + acquire_ymfm(buf,len); } } -void DivPlatformYM2203::acquire_combo(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformYM2203::acquire_combo(short** buf, size_t len) { static int os; static short ignored[2]; - for (size_t h=start; h32767) os=32767; - bufL[h]=os; + buf[0][h]=os; for (int i=0; i<3; i++) { oscBuf[i]->data[oscBuf[i]->needle++]=fm_nuked.ch_out[i]; @@ -230,7 +230,7 @@ void DivPlatformYM2203::acquire_combo(short* bufL, short* bufR, size_t start, si } } -void DivPlatformYM2203::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformYM2203::acquire_ymfm(short** buf, size_t len) { static int os; ymfm::ym2203::fm_engine* fme=fm->debug_fm_engine(); @@ -240,7 +240,7 @@ void DivPlatformYM2203::acquire_ymfm(short* bufL, short* bufR, size_t start, siz fmChan[i]=fme->debug_channel(i); } - for (size_t h=start; h32767) os=32767; - bufL[h]=os; + buf[0][h]=os; for (int i=0; i<3; i++) { @@ -967,8 +967,8 @@ void DivPlatformYM2203::reset() { ay->flushWrites(); } -bool DivPlatformYM2203::isStereo() { - return false; +int DivPlatformYM2203::getOutputCount() { + return 1; } bool DivPlatformYM2203::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/ym2203.h b/src/engine/platform/ym2203.h index 3d4670f7b..2f4da5b49 100644 --- a/src/engine/platform/ym2203.h +++ b/src/engine/platform/ym2203.h @@ -55,11 +55,11 @@ class DivPlatformYM2203: public DivPlatformOPN { friend void putDispatchChip(void*,int); - void acquire_combo(short* bufL, short* bufR, size_t start, size_t len); - void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len); + void acquire_combo(short** buf, size_t len); + void acquire_ymfm(short** buf, size_t len); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -70,7 +70,7 @@ class DivPlatformYM2203: public DivPlatformOPN { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void notifyInsChange(int ins); void notifyInsDeletion(void* ins); diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index fc0b08de6..169537463 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -297,15 +297,15 @@ double DivPlatformYM2608::NOTE_ADPCMB(int note) { return 0; } -void DivPlatformYM2608::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformYM2608::acquire(short** buf, size_t len) { if (useCombo) { - acquire_combo(bufL,bufR,start,len); + acquire_combo(buf,len); } else { - acquire_ymfm(bufL,bufR,start,len); + acquire_ymfm(buf,len); } } -void DivPlatformYM2608::acquire_combo(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformYM2608::acquire_combo(short** buf, size_t len) { static int os[2]; static short ignored[2]; @@ -320,7 +320,7 @@ void DivPlatformYM2608::acquire_combo(short* bufL, short* bufR, size_t start, si adpcmAChan[i]=aae->debug_channel(i); } - for (size_t h=start; h32767) os[1]=32767; - bufL[h]=os[0]; - bufR[h]=os[1]; + buf[0][h]=os[0]; + buf[1][h]=os[1]; for (int i=0; idebug_fm_engine(); @@ -424,7 +424,7 @@ void DivPlatformYM2608::acquire_ymfm(short* bufL, short* bufR, size_t start, siz adpcmAChan[i]=aae->debug_channel(i); } - for (size_t h=start; h32767) os[1]=32767; - bufL[h]=os[0]; - bufR[h]=os[1]; + buf[0][h]=os[0]; + buf[1][h]=os[1]; for (int i=0; i<6; i++) { oscBuf[i]->data[oscBuf[i]->needle++]=(fmChan[i]->debug_output(0)+fmChan[i]->debug_output(1)); @@ -715,6 +715,17 @@ void DivPlatformYM2608::tick(bool sysTick) { } chan[15].freqChanged=true; } + + if (chan[15].std.pitch.had) { + if (chan[15].std.pitch.mode) { + chan[15].pitch2+=chan[15].std.pitch.val; + CLAMP_VAR(chan[15].pitch2,-65535,65535); + } else { + chan[15].pitch2=chan[15].std.pitch.val; + } + chan[15].freqChanged=true; + } + if (chan[15].std.panL.had) { if (chan[15].pan!=(chan[15].std.panL.val&3)) { chan[15].pan=chan[15].std.panL.val&3; @@ -1424,8 +1435,8 @@ void DivPlatformYM2608::reset() { ay->flushWrites(); } -bool DivPlatformYM2608::isStereo() { - return true; +int DivPlatformYM2608::getOutputCount() { + return 2; } bool DivPlatformYM2608::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/ym2608.h b/src/engine/platform/ym2608.h index 4e6c59b90..3953e6f68 100644 --- a/src/engine/platform/ym2608.h +++ b/src/engine/platform/ym2608.h @@ -70,11 +70,11 @@ class DivPlatformYM2608: public DivPlatformOPN { friend void putDispatchChip(void*,int); - void acquire_combo(short* bufL, short* bufR, size_t start, size_t len); - void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len); + void acquire_combo(short** buf, size_t len); + void acquire_ymfm(short** buf, size_t len); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -85,7 +85,7 @@ class DivPlatformYM2608: public DivPlatformOPN { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void notifyInsChange(int ins); void notifyInsDeletion(void* ins); diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index 9251a39f3..bec65c785 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -232,15 +232,15 @@ const char** DivPlatformYM2610::getRegisterSheet() { return regCheatSheetYM2610; } -void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformYM2610::acquire(short** buf, size_t len) { if (useCombo) { - acquire_combo(bufL,bufR,start,len); + acquire_combo(buf,len); } else { - acquire_ymfm(bufL,bufR,start,len); + acquire_ymfm(buf,len); } } -void DivPlatformYM2610::acquire_combo(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformYM2610::acquire_combo(short** buf, size_t len) { static int os[2]; static short ignored[2]; @@ -255,7 +255,7 @@ void DivPlatformYM2610::acquire_combo(short* bufL, short* bufR, size_t start, si adpcmAChan[i]=aae->debug_channel(i); } - for (size_t h=start; h32767) os[1]=32767; - bufL[h]=os[0]; - bufR[h]=os[1]; + buf[0][h]=os[0]; + buf[1][h]=os[1]; for (int i=0; idebug_fm_engine(); @@ -357,7 +357,7 @@ void DivPlatformYM2610::acquire_ymfm(short* bufL, short* bufR, size_t start, siz adpcmAChan[i]=aae->debug_channel(i); } - for (size_t h=start; hread(0)&0x80)) { @@ -380,8 +380,8 @@ void DivPlatformYM2610::acquire_ymfm(short* bufL, short* bufR, size_t start, siz if (os[1]<-32768) os[1]=-32768; if (os[1]>32767) os[1]=32767; - bufL[h]=os[0]; - bufR[h]=os[1]; + buf[0][h]=os[0]; + buf[1][h]=os[1]; for (int i=0; idata[oscBuf[i]->needle++]=(fmChan[i]->debug_output(0)+fmChan[i]->debug_output(1)); @@ -650,6 +650,17 @@ void DivPlatformYM2610::tick(bool sysTick) { } chan[adpcmBChanOffs].freqChanged=true; } + + if (chan[adpcmBChanOffs].std.pitch.had) { + if (chan[adpcmBChanOffs].std.pitch.mode) { + chan[adpcmBChanOffs].pitch2+=chan[adpcmBChanOffs].std.pitch.val; + CLAMP_VAR(chan[adpcmBChanOffs].pitch2,-65535,65535); + } else { + chan[adpcmBChanOffs].pitch2=chan[adpcmBChanOffs].std.pitch.val; + } + chan[adpcmBChanOffs].freqChanged=true; + } + if (chan[adpcmBChanOffs].std.panL.had) { if (chan[adpcmBChanOffs].pan!=(chan[adpcmBChanOffs].std.panL.val&3)) { chan[adpcmBChanOffs].pan=chan[adpcmBChanOffs].std.panL.val&3; @@ -1372,8 +1383,8 @@ void DivPlatformYM2610::reset() { immWrite(0x1b,0xff); // B } -bool DivPlatformYM2610::isStereo() { - return true; +int DivPlatformYM2610::getOutputCount() { + return 2; } bool DivPlatformYM2610::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/ym2610.h b/src/engine/platform/ym2610.h index f2ffb9c7d..a3bf53b46 100644 --- a/src/engine/platform/ym2610.h +++ b/src/engine/platform/ym2610.h @@ -38,11 +38,11 @@ class DivPlatformYM2610: public DivPlatformYM2610Base { friend void putDispatchChip(void*,int); - void acquire_combo(short* bufL, short* bufR, size_t start, size_t len); - void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len); + void acquire_combo(short** buf, size_t len); + void acquire_ymfm(short** buf, size_t len); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -53,7 +53,7 @@ class DivPlatformYM2610: public DivPlatformYM2610Base { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void notifyInsChange(int ins); void notifyInsDeletion(void* ins); diff --git a/src/engine/platform/ym2610b.cpp b/src/engine/platform/ym2610b.cpp index 593ecfa0b..4a58878ee 100644 --- a/src/engine/platform/ym2610b.cpp +++ b/src/engine/platform/ym2610b.cpp @@ -296,15 +296,15 @@ const char** DivPlatformYM2610B::getRegisterSheet() { return regCheatSheetYM2610B; } -void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformYM2610B::acquire(short** buf, size_t len) { if (useCombo) { - acquire_combo(bufL,bufR,start,len); + acquire_combo(buf,len); } else { - acquire_ymfm(bufL,bufR,start,len); + acquire_ymfm(buf,len); } } -void DivPlatformYM2610B::acquire_combo(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformYM2610B::acquire_combo(short** buf, size_t len) { static int os[2]; static short ignored[2]; @@ -319,7 +319,7 @@ void DivPlatformYM2610B::acquire_combo(short* bufL, short* bufR, size_t start, s adpcmAChan[i]=aae->debug_channel(i); } - for (size_t h=start; h32767) os[1]=32767; - bufL[h]=os[0]; - bufR[h]=os[1]; + buf[0][h]=os[0]; + buf[1][h]=os[1]; for (int i=0; idebug_fm_engine(); @@ -423,7 +423,7 @@ void DivPlatformYM2610B::acquire_ymfm(short* bufL, short* bufR, size_t start, si adpcmAChan[i]=aae->debug_channel(i); } - for (size_t h=start; hread(0)&0x80)) { @@ -446,8 +446,8 @@ void DivPlatformYM2610B::acquire_ymfm(short* bufL, short* bufR, size_t start, si if (os[1]<-32768) os[1]=-32768; if (os[1]>32767) os[1]=32767; - bufL[h]=os[0]; - bufR[h]=os[1]; + buf[0][h]=os[0]; + buf[1][h]=os[1]; for (int i=0; iflushWrites(); } -bool DivPlatformYM2610B::isStereo() { - return true; +int DivPlatformYM2610B::getOutputCount() { + return 2; } bool DivPlatformYM2610B::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/ym2610b.h b/src/engine/platform/ym2610b.h index 6052a535e..ca2cb3337 100644 --- a/src/engine/platform/ym2610b.h +++ b/src/engine/platform/ym2610b.h @@ -34,11 +34,11 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base { friend void putDispatchChip(void*,int); - void acquire_combo(short* bufL, short* bufR, size_t start, size_t len); - void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len); + void acquire_combo(short** buf, size_t len); + void acquire_ymfm(short** buf, size_t len); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -49,7 +49,7 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - bool isStereo(); + int getOutputCount(); bool keyOffAffectsArp(int ch); void notifyInsChange(int ins); void notifyInsDeletion(void* ins); diff --git a/src/engine/platform/ym2610shared.h b/src/engine/platform/ym2610shared.h index ab1bd0528..517186999 100644 --- a/src/engine/platform/ym2610shared.h +++ b/src/engine/platform/ym2610shared.h @@ -119,8 +119,8 @@ class DivPlatformYM2610Base: public DivPlatformOPN { } } - bool isStereo() { - return true; + int getOutputCount() { + return 2; } const void* getSampleMem(int index) { diff --git a/src/engine/platform/ymz280b.cpp b/src/engine/platform/ymz280b.cpp index 7c7c56861..a5fdf10bd 100644 --- a/src/engine/platform/ymz280b.cpp +++ b/src/engine/platform/ymz280b.cpp @@ -60,13 +60,13 @@ const char** DivPlatformYMZ280B::getRegisterSheet() { return regCheatSheetYMZ280B; } -void DivPlatformYMZ280B::acquire(short* bufL, short* bufR, size_t start, size_t len) { - short buf[16][256]; +void DivPlatformYMZ280B::acquire(short** buf, size_t len) { + short why[16][256]; short *bufPtrs[16]={ - buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7], - buf[8],buf[9],buf[10],buf[11],buf[12],buf[13],buf[14],buf[15] + why[0],why[1],why[2],why[3],why[4],why[5],why[6],why[7], + why[8],why[9],why[10],why[11],why[12],why[13],why[14],why[15] }; - size_t pos=start; + size_t pos=0; while (len > 0) { size_t blockLen = MIN(len, 256); ymz280b.sound_stream_update(bufPtrs, blockLen); @@ -74,12 +74,12 @@ void DivPlatformYMZ280B::acquire(short* bufL, short* bufR, size_t start, size_t int dataL=0; int dataR=0; for (int j=0; j<8; j++) { - dataL+=buf[j*2][i]; - dataR+=buf[j*2+1][i]; - oscBuf[j]->data[oscBuf[j]->needle++]=(short)(((int)buf[j*2][i]+buf[j*2+1][i])/2); + dataL+=why[j*2][i]; + dataR+=why[j*2+1][i]; + oscBuf[j]->data[oscBuf[j]->needle++]=(short)(((int)why[j*2][i]+why[j*2+1][i])/2); } - bufL[pos]=(short)(dataL/8); - bufR[pos]=(short)(dataR/8); + buf[0][pos]=(short)(dataL/8); + buf[1][pos]=(short)(dataR/8); pos++; } len-=blockLen; @@ -372,8 +372,8 @@ void DivPlatformYMZ280B::reset() { } } -bool DivPlatformYMZ280B::isStereo() { - return true; +int DivPlatformYMZ280B::getOutputCount() { + return 2; } void DivPlatformYMZ280B::notifyInsChange(int ins) { diff --git a/src/engine/platform/ymz280b.h b/src/engine/platform/ymz280b.h index 810d52230..78ea544ba 100644 --- a/src/engine/platform/ymz280b.h +++ b/src/engine/platform/ymz280b.h @@ -56,7 +56,7 @@ class DivPlatformYMZ280B: public DivDispatch { friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); @@ -68,7 +68,7 @@ class DivPlatformYMZ280B: public DivDispatch { void tick(bool sysTick=true); void muteChannel(int ch, bool mute); float getPostAmp(); - bool isStereo(); + int getOutputCount(); void setChipModel(int type); void notifyInsChange(int ins); void notifyWaveChange(int wave); diff --git a/src/engine/platform/zxbeeper.cpp b/src/engine/platform/zxbeeper.cpp index 90ddfe2c3..f8762c7f2 100644 --- a/src/engine/platform/zxbeeper.cpp +++ b/src/engine/platform/zxbeeper.cpp @@ -27,9 +27,9 @@ const char** DivPlatformZXBeeper::getRegisterSheet() { return NULL; } -void DivPlatformZXBeeper::acquire(short* bufL, short* bufR, size_t start, size_t len) { +void DivPlatformZXBeeper::acquire(short** buf, size_t len) { bool o=false; - for (size_t h=start; h=0 && curSamplesong.sampleLen) { if (--curSamplePeriod<0) { @@ -46,7 +46,7 @@ void DivPlatformZXBeeper::acquire(short* bufL, short* bufR, size_t start, size_t } } o=sampleOut; - bufL[h]=o?16384:0; + buf[0][h]=o?16384:0; oscBuf[0]->data[oscBuf[0]->needle++]=o?16384:-16384; continue; } @@ -64,7 +64,7 @@ void DivPlatformZXBeeper::acquire(short* bufL, short* bufR, size_t start, size_t } if (++curChan>=6) curChan=0; - bufL[h]=o?16384:0; + buf[0][h]=o?16384:0; oscBuf[0]->data[oscBuf[0]->needle++]=o?16384:-16384; } } @@ -90,7 +90,7 @@ void DivPlatformZXBeeper::tick(bool sysTick) { if (chan[i].std.pitch.had) { if (chan[i].std.pitch.mode) { chan[i].pitch2+=chan[i].std.pitch.val; - CLAMP_VAR(chan[i].pitch2,-32768,32767); + CLAMP_VAR(chan[i].pitch2,-65535,65535); } else { chan[i].pitch2=chan[i].std.pitch.val; } @@ -99,6 +99,7 @@ void DivPlatformZXBeeper::tick(bool sysTick) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].active) { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE); + if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq>65535) chan[i].freq=65535; } if (chan[i].keyOn) { diff --git a/src/engine/platform/zxbeeper.h b/src/engine/platform/zxbeeper.h index 19c3e6ed9..a9b3594c3 100644 --- a/src/engine/platform/zxbeeper.h +++ b/src/engine/platform/zxbeeper.h @@ -52,7 +52,7 @@ class DivPlatformZXBeeper: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); + void acquire(short** buf, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 335da02a9..33f2d66c7 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -213,6 +213,8 @@ const char* cmdName[]={ "MACRO_OFF", "MACRO_ON", + "SURROUND_PANNING", + "ALWAYS_SET_VOLUME" }; @@ -555,6 +557,7 @@ void DivEngine::processRow(int i, bool afterDelay) { short lastSlide=-1; bool calledPorta=false; bool panChanged=false; + bool surroundPanChanged=false; // effects for (int j=0; j>4)|(effectVal&0xf0); + chan[i].panRR=(effectVal&15)|((effectVal&15)<<4); + surroundPanChanged=true; + break; + case 0x89: // panning left (split 8-bit) + chan[i].panRL=effectVal; + surroundPanChanged=true; + break; + case 0x8a: // panning right (split 8-bit) + chan[i].panRR=effectVal; + surroundPanChanged=true; + break; case 0x01: // ramp up if (song.ignoreDuplicateSlides && (lastSlide==0x01 || lastSlide==0x1337)) break; lastSlide=0x01; @@ -866,6 +882,10 @@ void DivEngine::processRow(int i, bool afterDelay) { if (panChanged) { dispatchCmd(DivCommand(DIV_CMD_PANNING,i,chan[i].panL,chan[i].panR)); } + if (surroundPanChanged) { + dispatchCmd(DivCommand(DIV_CMD_SURROUND_PANNING,i,2,chan[i].panRL)); + dispatchCmd(DivCommand(DIV_CMD_SURROUND_PANNING,i,3,chan[i].panRR)); + } if (insChanged && (chan[i].inPorta || calledPorta) && song.newInsTriggersInPorta) { dispatchCmd(DivCommand(DIV_CMD_NOTE_ON,i,DIV_NOTE_NULL)); @@ -1359,12 +1379,17 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { return ret; } +int DivEngine::getBufferPos() { + return bufferPos>>MASTER_CLOCK_PREC; +} + void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size) { lastLoopPos=-1; if (out!=NULL) { - memset(out[0],0,size*sizeof(float)); - memset(out[1],0,size*sizeof(float)); + for (int i=0; i=0 && sPreview.sample<(int)song.sample.size()) || (sPreview.wave>=0 && sPreview.wave<(int)song.wave.size()))) { + if ((sPreview.sample>=0 && sPreview.sample<(int)song.sample.size()) || (sPreview.wave>=0 && sPreview.wave<(int)song.wave.size())) { unsigned int samp_bbOff=0; unsigned int prevAvail=blip_samples_avail(samp_bb); if (prevAvail>size) prevAvail=size; @@ -1565,191 +1590,232 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi blip_end_frame(samp_bb,prevtotal); blip_read_samples(samp_bb,samp_bbOut+samp_bbOff,size-samp_bbOff,0); - for (size_t i=0; i=32768) oscWritePos=0; + if (playing && !halted) { + // logic starts here + for (int i=0; i0) { + disCont[i].flush(disCont[i].lastAvail); } - oscSize=size; + if (sizedisCont[i].bbInLen) { + logD("growing dispatch %d bbIn to %d",i,disCont[i].runtotal+256); + disCont[i].grow(disCont[i].runtotal+256); + } + disCont[i].runLeft=disCont[i].runtotal; + disCont[i].runPos=0; } - isBusy.unlock(); - return; - } - // logic starts here - for (int i=0; i0) { - disCont[i].flush(disCont[i].lastAvail); + if (metroTickLendisCont[i].bbInLen) { - logV("growing dispatch %d bbIn to %d",i,disCont[i].runtotal+256); - delete[] disCont[i].bbIn[0]; - delete[] disCont[i].bbIn[1]; - disCont[i].bbIn[0]=new short[disCont[i].runtotal+256]; - disCont[i].bbIn[1]=new short[disCont[i].runtotal+256]; - disCont[i].bbInLen=disCont[i].runtotal+256; - } - disCont[i].runLeft=disCont[i].runtotal; - disCont[i].runPos=0; - } - if (metroTickLen>MASTER_CLOCK_PREC); - logD("last loop pos: %d for a size of %d and runLeftG of %d",lastLoopPos,size,runLeftG); - totalLoops++; - if (remainingLoops>0) { - remainingLoops--; - if (!remainingLoops) { - logI("end of song!"); - remainingLoops=-1; - playing=false; - freelance=false; - extValuePresent=false; - break; + // 2. check whether we gonna tick + if (cycles<=0) { + // we have to tick + if (nextTick()) { + lastLoopPos=size-(runLeftG>>MASTER_CLOCK_PREC); + logD("last loop pos: %d for a size of %d and runLeftG of %d",lastLoopPos,size,runLeftG); + totalLoops++; + if (remainingLoops>0) { + remainingLoops--; + if (!remainingLoops) { + logI("end of song!"); + remainingLoops=-1; + playing=false; + freelance=false; + extValuePresent=false; + break; + } + } + } + if (pendingMetroTick) { + unsigned int realPos=size-(runLeftG>>MASTER_CLOCK_PREC); + if (realPos>=size) realPos=size-1; + metroTick[realPos]=pendingMetroTick; + pendingMetroTick=0; + } + } else { + // 3. tick the clock and fill buffers as needed + if (cycles>MASTER_CLOCK_PREC); - if (realPos>=size) realPos=size-1; - metroTick[realPos]=pendingMetroTick; - pendingMetroTick=0; + } + + //logD("attempts: %d",attempts); + if (attempts>=(int)size) { + logE("hang detected! stopping! at %d seconds %d micro",totalSeconds,totalTicks); + freelance=false; + playing=false; + extValuePresent=false; + } + totalProcessed=size-(runLeftG>>MASTER_CLOCK_PREC); + + for (int i=0; i0.0f) { + for (int j=0; j=1) metroPos--; } } - if (out==NULL || halted) { - isBusy.unlock(); - return; - } + // resolve patchbay + for (unsigned int i: song.patchbay) { + const unsigned short srcPort=i>>16; + const unsigned short destPort=i&0xffff; - //logD("attempts: %d",attempts); - if (attempts>=(int)size) { - logE("hang detected! stopping! at %d seconds %d micro",totalSeconds,totalTicks); - freelance=false; - playing=false; - extValuePresent=false; - } - totalProcessed=size-(runLeftG>>MASTER_CLOCK_PREC); + const unsigned short srcPortSet=srcPort>>4; + const unsigned short destPortSet=destPort>>4; + const unsigned char srcSubPort=srcPort&15; + const unsigned char destSubPort=destPort&15; - for (int i=0; igetPostAmp(); - volR*=disCont[i].dispatch->getPostAmp(); - if (disCont[i].dispatch->isStereo()) { - for (size_t j=0; j=outChans) continue; + + // chip outputs + if (srcPortSetgetOutputCount()) { + float vol=song.systemVol[srcPortSet]*disCont[srcPortSet].dispatch->getPostAmp()*song.masterVol; + + switch (destSubPort&3) { + case 0: + vol*=MIN(1.0f,1.0f-song.systemPan[srcPortSet])*MIN(1.0f,1.0f+song.systemPanFR[srcPortSet]); + break; + case 1: + vol*=MIN(1.0f,1.0f+song.systemPan[srcPortSet])*MIN(1.0f,1.0f+song.systemPanFR[srcPortSet]); + break; + case 2: + vol*=MIN(1.0f,1.0f-song.systemPan[srcPortSet])*MIN(1.0f,1.0f-song.systemPanFR[srcPortSet]); + break; + case 3: + vol*=MIN(1.0f,1.0f+song.systemPan[srcPortSet])*MIN(1.0f,1.0f-song.systemPanFR[srcPortSet]); + break; + } + + for (size_t j=0; j0.0f) { - out[0][i]+=(sin(metroPos*2*M_PI))*metroAmp*metroVol; - out[1][i]+=(sin(metroPos*2*M_PI))*metroAmp*metroVol; - } - metroAmp-=0.0003f; - if (metroAmp<0.0f) metroAmp=0.0f; - metroPos+=metroFreq; - while (metroPos>=1) metroPos--; + + // nothing/invalid } for (unsigned int i=0; i=32768) oscWritePos=0; } oscSize=size; - if (forceMono) { + if (forceMono && outChans>1) { for (size_t i=0; i1.0) out[0][i]=1.0; - if (out[1][i]<-1.0) out[1][i]=-1.0; - if (out[1][i]>1.0) out[1][i]=1.0; + for (int j=0; j1.0) out[j][i]=1.0; + } } } isBusy.unlock(); diff --git a/src/engine/song.h b/src/engine/song.h index d7c287368..dfe579bbb 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -238,8 +238,9 @@ struct DivSong { // system DivSystem system[DIV_MAX_CHIPS]; unsigned char systemLen; - signed char systemVol[DIV_MAX_CHIPS]; - signed char systemPan[DIV_MAX_CHIPS]; + float systemVol[DIV_MAX_CHIPS]; + float systemPan[DIV_MAX_CHIPS]; + float systemPanFR[DIV_MAX_CHIPS]; DivConfig systemFlags[DIV_MAX_CHIPS]; // song information @@ -328,12 +329,14 @@ struct DivSong { bool disableSampleMacro; bool autoSystem; bool oldArpStrategy; + bool patchbayAuto; std::vector ins; std::vector wave; std::vector sample; std::vector subsong; + std::vector patchbay; DivInstrument nullIns, nullInsOPLL, nullInsOPL, nullInsOPLDrums, nullInsQSound; DivWavetable nullWave; @@ -435,11 +438,13 @@ struct DivSong { snNoLowPeriods(false), disableSampleMacro(false), autoSystem(true), - oldArpStrategy(false) { + oldArpStrategy(false), + patchbayAuto(true) { for (int i=0; igetAudioDescGot().outChans; j++) { + peakMix+=peak[j]; + } + peakMix/=e->getAudioDescGot().outChans; + } ImGui::ColorConvertHSVtoRGB(aboutHue,1.0,0.25+MIN(0.75f,peakMix*0.75f),r,g,b); dl->AddRectFilled(ImVec2(0,0),ImVec2(canvasW,canvasH),0xff000000); bool skip=false; diff --git a/src/gui/editControls.cpp b/src/gui/editControls.cpp index 912665f60..173b64de4 100644 --- a/src/gui/editControls.cpp +++ b/src/gui/editControls.cpp @@ -449,6 +449,10 @@ void FurnaceGUI::drawMobileControls() { mobScene=GUI_SCENE_CHIPS; } ImGui::TableNextColumn(); + if (ImGui::Button("Mixer",buttonSize)) { + mobScene=GUI_SCENE_MIXER; + } + ImGui::TableNextColumn(); if (ImGui::Button("Other",buttonSize)) { mobScene=GUI_SCENE_OTHER; } @@ -521,6 +525,9 @@ void FurnaceGUI::drawMobileControls() { case GUI_SCENE_CHIPS: ImGui::Text("Chips here..."); break; + case GUI_SCENE_MIXER: + ImGui::Text("What the hell..."); + break; case GUI_SCENE_OTHER: { if (ImGui::Button("Osc")) { oscOpen=!oscOpen; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 59d23f2e2..1ec735f1d 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -3863,6 +3863,11 @@ bool FurnaceGUI::loop() { curWindow=GUI_WINDOW_SYS_MANAGER; drawSysManager(); break; + case GUI_SCENE_MIXER: + mixerOpen=true; + curWindow=GUI_WINDOW_MIXER; + drawMixer(); + break; default: patternOpen=true; curWindow=GUI_WINDOW_PATTERN; @@ -6016,6 +6021,14 @@ FurnaceGUI::FurnaceGUI(): openSampleAmplifyOpt(false), openSampleSilenceOpt(false), openSampleFilterOpt(false), + selectedPortSet(0x1fff), + selectedSubPort(-1), + hoveredPortSet(0x1fff), + hoveredSubPort(-1), + portDragActive(false), + displayHiddenPorts(false), + displayInternalPorts(false), + subPortPos(0.0f,0.0f), oscTotal(0), oscZoom(0.5f), oscWindowSize(20.0f), @@ -6095,8 +6108,7 @@ FurnaceGUI::FurnaceGUI(): memset(willExport,1,DIV_MAX_CHIPS*sizeof(bool)); - peak[0]=0; - peak[1]=0; + memset(peak,0,DIV_MAX_OUTPUTS*sizeof(float)); opMaskTransposeNote.note=true; opMaskTransposeNote.ins=false; diff --git a/src/gui/gui.h b/src/gui/gui.h index 88c30651b..15319f747 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -270,6 +270,13 @@ enum FurnaceGUIColors { GUI_COLOR_CLOCK_BEAT_LOW, GUI_COLOR_CLOCK_BEAT_HIGH, + GUI_COLOR_PATCHBAY_PORTSET, + GUI_COLOR_PATCHBAY_PORT, + GUI_COLOR_PATCHBAY_PORT_HIDDEN, + GUI_COLOR_PATCHBAY_CONNECTION, + GUI_COLOR_PATCHBAY_CONNECTION_BG, + GUI_COLOR_PATCHBAY_CONNECTION_HI, + GUI_COLOR_LOGLEVEL_ERROR, GUI_COLOR_LOGLEVEL_WARNING, GUI_COLOR_LOGLEVEL_INFO, @@ -325,6 +332,7 @@ enum FurnaceGUIMobileScenes { GUI_SCENE_SONG, GUI_SCENE_CHANNELS, GUI_SCENE_CHIPS, + GUI_SCENE_MIXER, GUI_SCENE_OTHER, }; @@ -935,9 +943,9 @@ struct Gradient2D { struct FurnaceGUISysDefChip { DivSystem sys; - int vol, pan; + float vol, pan; const char* flags; - FurnaceGUISysDefChip(DivSystem s, int v, int p, const char* f): + FurnaceGUISysDefChip(DivSystem s, float v, float p, const char* f): sys(s), vol(v), pan(p), @@ -1172,6 +1180,7 @@ class FurnaceGUI { int mainFontSize, patFontSize, iconSize; int audioEngine; int audioQuality; + int audioChans; int arcadeCore; int ym2612Core; int snCore; @@ -1306,6 +1315,7 @@ class FurnaceGUI { iconSize(16), audioEngine(DIV_AUDIO_SDL), audioQuality(0), + audioChans(2), arcadeCore(0), ym2612Core(0), snCore(0), @@ -1458,7 +1468,7 @@ class FurnaceGUI { bool keepLoopAlive, orderScrollLocked, orderScrollTolerance, dragMobileMenu, dragMobileEditButton; FurnaceGUIWindows curWindow, nextWindow, curWindowLast; std::atomic curWindowThreadSafe; - float peak[2]; + float peak[DIV_MAX_OUTPUTS]; float patChanX[DIV_MAX_CHANS+1]; float patChanSlideY[DIV_MAX_CHANS+1]; float lastPatternWidth, longThreshold; @@ -1649,6 +1659,17 @@ class FurnaceGUI { size_t sampleClipboardLen; bool openSampleResizeOpt, openSampleResampleOpt, openSampleAmplifyOpt, openSampleSilenceOpt, openSampleFilterOpt; + // mixer + // 0xxx: output + // 1xxx: input + unsigned int selectedPortSet; + // any value not between 0 and 15 are "none" + int selectedSubPort; + unsigned int hoveredPortSet; + int hoveredSubPort; + bool portDragActive, displayHiddenPorts, displayInternalPorts; + ImVec2 subPortPos; + // oscilloscope int oscTotal; float oscValues[512]; @@ -1757,6 +1778,10 @@ class FurnaceGUI { // inverted checkbox bool InvCheckbox(const char* label, bool* value); + // mixer stuff + ImVec2 calcPortSetSize(String label, int ins, int outs); + bool portSet(String label, unsigned int portSetID, int ins, int outs, int activeIns, int activeOuts, int& clickedPort, std::map& portPos); + void updateWindowTitle(); void autoDetectSystem(); void prepareLayout(); diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index 0c8a6d029..d19070fdd 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -319,9 +319,9 @@ const FurnaceGUIColors fxColors[256]={ GUI_COLOR_PATTERN_EFFECT_INVALID, GUI_COLOR_PATTERN_EFFECT_INVALID, GUI_COLOR_PATTERN_EFFECT_INVALID, - GUI_COLOR_PATTERN_EFFECT_INVALID, - GUI_COLOR_PATTERN_EFFECT_INVALID, - GUI_COLOR_PATTERN_EFFECT_INVALID, + GUI_COLOR_PATTERN_EFFECT_PANNING, + GUI_COLOR_PATTERN_EFFECT_PANNING, + GUI_COLOR_PATTERN_EFFECT_PANNING, GUI_COLOR_PATTERN_EFFECT_INVALID, GUI_COLOR_PATTERN_EFFECT_INVALID, GUI_COLOR_PATTERN_EFFECT_INVALID, @@ -896,6 +896,13 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={ D(GUI_COLOR_CLOCK_BEAT_LOW,"",ImVec4(0.1f,0.13f,0.25f,1.0f)), D(GUI_COLOR_CLOCK_BEAT_HIGH,"",ImVec4(0.5f,0.8f,1.0f,1.0f)), + D(GUI_COLOR_PATCHBAY_PORTSET,"",ImVec4(0.25f,0.25f,0.25f,1.0f)), + D(GUI_COLOR_PATCHBAY_PORT,"",ImVec4(0.3f,0.4f,0.6f,1.0f)), + D(GUI_COLOR_PATCHBAY_PORT_HIDDEN,"",ImVec4(0.4f,0.4f,0.4f,1.0f)), + D(GUI_COLOR_PATCHBAY_CONNECTION,"",ImVec4(0.3f,0.55f,0.8f,1.0f)), + D(GUI_COLOR_PATCHBAY_CONNECTION_BG,"",ImVec4(0.1f,0.25f,0.3f,1.0f)), + D(GUI_COLOR_PATCHBAY_CONNECTION_HI,"",ImVec4(0.2f,1.0f,1.0f,1.0f)), + D(GUI_COLOR_LOGLEVEL_ERROR,"",ImVec4(1.0f,0.2f,0.2f,1.0f)), D(GUI_COLOR_LOGLEVEL_WARNING,"",ImVec4(1.0f,1.0f,0.2f,1.0f)), D(GUI_COLOR_LOGLEVEL_INFO,"",ImVec4(0.4f,1.0f,0.4f,1.0f)), diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 66fc5eec4..c72958ed9 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -283,8 +283,8 @@ const char* es5506FilterModes[4]={ "HP/K2, HP/K2", "HP/K2, LP/K1", "LP/K2, LP/K2", "LP/K2, LP/K1", }; -const char* panBits[3]={ - "right", "left", NULL +const char* panBits[5]={ + "right", "left", "rear right", "rear left", NULL }; const char* oneBit[2]={ @@ -1850,6 +1850,7 @@ void FurnaceGUI::drawMacros(std::vector& macros, FurnaceGUI case 2: { int columns=round(ImGui::GetContentRegionAvail().x/(400.0*dpiScale)); int curColumn=0; + if (columns<1) columns=1; if (ImGui::BeginTable("MacroGrid",columns,ImGuiTableFlags_BordersInner)) { for (FurnaceGUIMacroDesc& i: macros) { if (curColumn==0) ImGui::TableNextRow(); @@ -5195,15 +5196,18 @@ void FurnaceGUI::drawInsEdit() { if (ins->type==DIV_INS_STD ||//Game Gear ins->type==DIV_INS_FM || ins->type==DIV_INS_OPM || - ins->type==DIV_INS_OPL || - ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_GB || ins->type==DIV_INS_OPZ || ins->type==DIV_INS_MSM6258 || ins->type==DIV_INS_VERA || ins->type==DIV_INS_ADPCMA || ins->type==DIV_INS_ADPCMB) { - panMax=1; + panMax=2; + panSingle=true; + } + if (ins->type==DIV_INS_OPL || + ins->type==DIV_INS_OPL_DRUMS) { + panMax=4; panSingle=true; } if (ins->type==DIV_INS_X1_010 || ins->type==DIV_INS_PCE || ins->type==DIV_INS_MIKEY || @@ -5249,7 +5253,9 @@ void FurnaceGUI::drawInsEdit() { if (volMax>0) { macroList.push_back(FurnaceGUIMacroDesc(volumeLabel,&ins->std.volMacro,volMin,volMax,160,uiColors[GUI_COLOR_MACRO_VOLUME])); } - macroList.push_back(FurnaceGUIMacroDesc("Arpeggio",&ins->std.arpMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,0,true,ins->std.arpMacro.val)); + if (ins->type!=DIV_INS_MSM6258 && ins->type!=DIV_INS_MSM6295) { + macroList.push_back(FurnaceGUIMacroDesc("Arpeggio",&ins->std.arpMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,0,true,ins->std.arpMacro.val)); + } if (dutyMax>0) { if (ins->type==DIV_INS_MIKEY) { macroList.push_back(FurnaceGUIMacroDesc(dutyLabel,&ins->std.dutyMacro,0,dutyMax,160,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,mikeyFeedbackBits)); @@ -5268,7 +5274,7 @@ void FurnaceGUI::drawInsEdit() { } if (panMax>0) { if (panSingle) { - macroList.push_back(FurnaceGUIMacroDesc("Panning",&ins->std.panLMacro,0,2,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,panBits)); + macroList.push_back(FurnaceGUIMacroDesc("Panning",&ins->std.panLMacro,0,panMax,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,panBits)); } else if (ins->type==DIV_INS_QSOUND) { macroList.push_back(FurnaceGUIMacroDesc("Panning",&ins->std.panLMacro,panMin,panMax,CLAMP(31+panMax-panMin,32,160),uiColors[GUI_COLOR_MACRO_OTHER])); macroList.push_back(FurnaceGUIMacroDesc("Surround",&ins->std.panRMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true)); @@ -5287,7 +5293,7 @@ void FurnaceGUI::drawInsEdit() { } } } - if (ins->type!=DIV_INS_MSM5232) { + if (ins->type!=DIV_INS_MSM5232 && ins->type!=DIV_INS_MSM6258 && ins->type!=DIV_INS_MSM6295) { macroList.push_back(FurnaceGUIMacroDesc("Pitch",&ins->std.pitchMacro,-2048,2047,160,uiColors[GUI_COLOR_MACRO_PITCH],true,macroRelativeMode)); } if (ins->type==DIV_INS_FM || diff --git a/src/gui/mixer.cpp b/src/gui/mixer.cpp index 019336ae4..c9aa96b80 100644 --- a/src/gui/mixer.cpp +++ b/src/gui/mixer.cpp @@ -19,6 +19,193 @@ #include "gui.h" #include "intConst.h" +#include +#include "../ta-log.h" +#include "imgui_internal.h" + +const char* portNamesStereo[2]={ + "left", + "right" +}; + +ImVec2 FurnaceGUI::calcPortSetSize(String label, int ins, int outs) { + ImGuiStyle& style=ImGui::GetStyle(); + + ImVec2 labelSize=ImGui::CalcTextSize(label.c_str(),NULL,false,ImGui::GetWindowSize().x*0.6f); + + ImVec2 size=labelSize; + + // pad + size.x+=style.FramePadding.x*2.0f; + size.y+=style.FramePadding.y*2.0f; + + // space for ports + size.y+=MAX(ins,outs)*(labelSize.y+style.FramePadding.y+style.ItemSpacing.y); + + return size; +} + +bool FurnaceGUI::portSet(String label, unsigned int portSetID, int ins, int outs, int activeIns, int activeOuts, int& clickedPort, std::map& portPos) { + String portID=fmt::sprintf("portSet%.4x",portSetID); + + ImDrawList* dl=ImGui::GetWindowDrawList(); + ImGuiWindow* window=ImGui::GetCurrentWindow(); + ImGuiStyle& style=ImGui::GetStyle(); + + ImVec2 labelSize=ImGui::CalcTextSize(label.c_str(),NULL,false,ImGui::GetWindowSize().x*0.6f); + + ImVec2 size=labelSize; + + // pad + size.x+=style.FramePadding.x*2.0f; + size.y+=style.FramePadding.y*2.0f; + + // space for ports + size.y+=MAX(ins,outs)*(ImGui::GetFontSize()+style.FramePadding.y+style.ItemSpacing.y); + + ImVec4 portSetBorderColor=uiColors[GUI_COLOR_PATCHBAY_PORTSET]; + ImVec4 portSetColor=ImVec4( + portSetBorderColor.x*0.75f, + portSetBorderColor.y*0.75f, + portSetBorderColor.z*0.75f, + portSetBorderColor.w + ); + + ImVec4 portBorderColor=uiColors[GUI_COLOR_PATCHBAY_PORT]; + ImVec4 portColor=ImVec4( + portBorderColor.x*0.75f, + portBorderColor.y*0.75f, + portBorderColor.z*0.75f, + portBorderColor.w + ); + + ImVec4 portBorderColorH=uiColors[GUI_COLOR_PATCHBAY_PORT_HIDDEN]; + ImVec4 portColorH=ImVec4( + portBorderColorH.x*0.75f, + portBorderColorH.y*0.75f, + portBorderColorH.z*0.75f, + portBorderColorH.w + ); + + ImVec2 minArea=window->DC.CursorPos; + ImVec2 maxArea=ImVec2( + minArea.x+size.x, + minArea.y+size.y + ); + ImRect rect=ImRect(minArea,maxArea); + + ImVec2 textPos=ImVec2( + minArea.x+style.FramePadding.x, + minArea.y+style.FramePadding.y + ); + + ImGui::ItemSize(size,style.FramePadding.y); + bool visible=ImGui::ItemAdd(rect,ImGui::GetID(portID.c_str())); + bool hovered=false; + bool active=false; + if (visible) { + hovered=ImGui::ItemHoverable(rect,ImGui::GetID(portID.c_str())); + active=(hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left)); + + if (hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) { + ImGui::OpenPopup("SubPortOptions"); + selectedPortSet=portSetID; + clickedPort=-1; + } + + if (hovered) hoveredPortSet=portSetID; + if (active) clickedPort=-1; + + // label + dl->AddRectFilled(minArea,maxArea,ImGui::GetColorU32(portSetColor),0.0f); + dl->AddRect(minArea,maxArea,ImGui::GetColorU32((selectedPortSet==portSetID)?uiColors[GUI_COLOR_TEXT]:portSetBorderColor),0.0f,0,dpiScale); + dl->AddText(ImGui::GetFont(),ImGui::GetFontSize(),textPos,ImGui::GetColorU32(uiColors[GUI_COLOR_TEXT]),label.c_str(),NULL,ImGui::GetWindowSize().x*0.6f); + } + + // input ports + for (int i=0; i2) { + portLabel=fmt::sprintf("%d",i+1); + } + ImVec2 portLabelSize=ImGui::CalcTextSize(portLabel.c_str()); + + ImVec2 portMin=ImVec2( + minArea.x, + minArea.y+style.FramePadding.y+labelSize.y+style.ItemSpacing.y+(style.ItemSpacing.y+portLabelSize.y+style.FramePadding.y)*i + ); + ImVec2 portMax=ImVec2( + minArea.x+portLabelSize.x+style.FramePadding.x, + portMin.y+style.FramePadding.y+portLabelSize.y + ); + ImRect portRect=ImRect(portMin,portMax); + ImVec2 portLabelPos=portMin; + portLabelPos.x+=style.FramePadding.x*0.5; + portLabelPos.y+=style.FramePadding.y*0.5; + + portPos[(portSetID<<4)|i]=ImLerp(portMin,portMax,ImVec2(0.0f,0.5f)); + + if (visible) { + if (ImGui::ItemAdd(portRect,ImGui::GetID(subPortID.c_str()))) { + dl->AddRectFilled(portMin,portMax,ImGui::GetColorU32((iAddRect(portMin,portMax,ImGui::GetColorU32((iAddText(portLabelPos,ImGui::GetColorU32(uiColors[GUI_COLOR_TEXT]),portLabel.c_str()); + } + + if (ImGui::IsMouseHoveringRect(portMin,portMax)) { + hoveredSubPort=i; + if (active) clickedPort=i; + } + } + } + + // output ports + for (int i=0; i2) { + portLabel=fmt::sprintf("%d",i+1); + } + ImVec2 portLabelSize=ImGui::CalcTextSize(portLabel.c_str()); + + ImVec2 portMin=ImVec2( + maxArea.x-portLabelSize.x-style.FramePadding.x, + minArea.y+style.FramePadding.y+labelSize.y+style.ItemSpacing.y+(style.ItemSpacing.y+portLabelSize.y+style.FramePadding.y)*i + ); + ImVec2 portMax=ImVec2( + maxArea.x, + portMin.y+style.FramePadding.y+portLabelSize.y + ); + ImRect portRect=ImRect(portMin,portMax); + ImVec2 portLabelPos=portMin; + portLabelPos.x+=style.FramePadding.x*0.5; + portLabelPos.y+=style.FramePadding.y*0.5; + + portPos[(portSetID<<4)|i]=ImLerp(portMin,portMax,ImVec2(1.0f,0.5f)); + + if (visible) { + if (ImGui::ItemAdd(portRect,ImGui::GetID(subPortID.c_str()))) { + dl->AddRectFilled(portMin,portMax,ImGui::GetColorU32((iAddRect(portMin,portMax,ImGui::GetColorU32((iAddText(portLabelPos,ImGui::GetColorU32(uiColors[GUI_COLOR_TEXT]),portLabel.c_str()); + } + + if (ImGui::IsMouseHoveringRect(portMin,portMax)) { + if (active) clickedPort=i; + hoveredSubPort=i; + } + } + } + + if (visible && hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) return true; + + return false; +} void FurnaceGUI::drawMixer() { if (nextWindow==GUI_WINDOW_MIXER) { @@ -27,37 +214,217 @@ void FurnaceGUI::drawMixer() { nextWindow=GUI_WINDOW_NOTHING; } if (!mixerOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(canvasW,canvasH)); + if (mobileUI) { + patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*canvasH)):ImVec2((0.16*canvasH)+0.5*canvasW*mobileMenuPos,0.0f)); + patWindowSize=(portrait?ImVec2(canvasW,canvasH-(0.16*canvasW)):ImVec2(canvasW-(0.16*canvasH),canvasH)); + ImGui::SetNextWindowPos(patWindowPos); + ImGui::SetNextWindowSize(patWindowSize); + } else { + ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(canvasW,canvasH)); + } if (ImGui::Begin("Mixer",&mixerOpen,globalWinFlags|(settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking))) { - char id[32]; + std::map portPos; if (ImGui::SliderFloat("Master Volume",&e->song.masterVol,0,3,"%.2fx")) { if (e->song.masterVol<0) e->song.masterVol=0; if (e->song.masterVol>3) e->song.masterVol=3; MARK_MODIFIED; } rightClickable - for (int i=0; isong.systemLen; i++) { - snprintf(id,31,"MixS%d",i); - bool doInvert=e->song.systemVol[i]&128; - signed char vol=e->song.systemVol[i]&127; - ImGui::PushID(id); - ImGui::Text("%d. %s",i+1,getSystemName(e->song.system[i])); - ImGui::SameLine(ImGui::GetWindowWidth()-(82.0f*dpiScale)); - if (ImGui::Checkbox("Invert",&doInvert)) { - e->song.systemVol[i]^=128; + if (selectedPortSetsong.systemLen) { + if (ImGui::BeginTable("CurPortSet",2)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed); + + bool doInvert=e->song.systemVol[selectedPortSet]<0; + float vol=fabs(e->song.systemVol[selectedPortSet]); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("%d. %s",selectedPortSet+1,getSystemName(e->song.system[selectedPortSet])); + ImGui::TableNextColumn(); + if (ImGui::Checkbox("Invert",&doInvert)) { + e->song.systemVol[selectedPortSet]=-e->song.systemVol[selectedPortSet]; + MARK_MODIFIED; + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderFloat("##Volume",&vol,0,2)) { + if (doInvert) { + if (vol<0.0001) vol=0.0001; + } + if (vol<0) vol=0; + if (vol>10) vol=10; + e->song.systemVol[selectedPortSet]=(doInvert)?-vol:vol; + MARK_MODIFIED; + } rightClickable + ImGui::TableNextColumn(); + ImGui::Text("Volume"); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderFloat("##Panning",&e->song.systemPan[selectedPortSet],-1.0f,1.0f)) { + if (e->song.systemPan[selectedPortSet]<-1.0f) e->song.systemPan[selectedPortSet]=-1.0f; + if (e->song.systemPan[selectedPortSet]>1.0f) e->song.systemPan[selectedPortSet]=1.0f; + MARK_MODIFIED; + } rightClickable + ImGui::TableNextColumn(); + ImGui::Text("Panning"); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderFloat("##FrontRear",&e->song.systemPanFR[selectedPortSet],-1.0f,1.0f)) { + if (e->song.systemPanFR[selectedPortSet]<-1.0f) e->song.systemPanFR[selectedPortSet]=-1.0f; + if (e->song.systemPanFR[selectedPortSet]>1.0f) e->song.systemPanFR[selectedPortSet]=1.0f; + MARK_MODIFIED; + } rightClickable + ImGui::TableNextColumn(); + ImGui::Text("Front/Rear"); + + ImGui::EndTable(); + } + } else { + if (ImGui::Checkbox("Automatic patchbay",&e->song.patchbayAuto)) { + if (e->song.patchbayAuto) e->autoPatchbayP(); MARK_MODIFIED; } - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-(50.0f*dpiScale)); - if (CWSliderScalar("Volume",ImGuiDataType_S8,&vol,&_ZERO,&_ONE_HUNDRED_TWENTY_SEVEN)) { - e->song.systemVol[i]=(e->song.systemVol[i]&128)|vol; - MARK_MODIFIED; - } rightClickable - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-(50.0f*dpiScale)); - if (CWSliderScalar("Panning",ImGuiDataType_S8,&e->song.systemPan[i],&_MINUS_ONE_HUNDRED_TWENTY_SEVEN,&_ONE_HUNDRED_TWENTY_SEVEN)) { - MARK_MODIFIED; - } rightClickable - - ImGui::PopID(); + ImGui::Checkbox("Display hidden ports",&displayHiddenPorts); + ImGui::Checkbox("Display internal",&displayInternalPorts); + ImGui::Dummy(ImVec2(1.0f,ImGui::GetFrameHeightWithSpacing())); } + + hoveredPortSet=0x1fff; + hoveredSubPort=-1; + + if (ImGui::BeginChild("Patchbay",ImVec2(0,0),true)) { + ImDrawList* dl=ImGui::GetWindowDrawList(); + ImVec2 topPos=ImGui::GetCursorPos(); + ImVec2 sysSize=calcPortSetSize("System",displayHiddenPorts?DIV_MAX_OUTPUTS:e->getAudioDescGot().outChans,0); + topPos.x+=ImGui::GetContentRegionAvail().x-sysSize.x; + if (ImGui::GetContentRegionAvail().y>sysSize.y) topPos.y+=(ImGui::GetContentRegionAvail().y-sysSize.y)*0.5+ImGui::GetScrollY(); + + if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) selectedPortSet=0x1fff; + + if (portDragActive) { + dl->AddLine(subPortPos,ImGui::GetMousePos(),ImGui::GetColorU32(uiColors[GUI_COLOR_PATCHBAY_CONNECTION]),2.0f*dpiScale); + } + + for (int i=0; isong.systemLen; i++) { + DivDispatch* dispatch=e->getDispatch(i); + if (dispatch==NULL) continue; + int outputs=dispatch->getOutputCount(); + if (portSet(fmt::sprintf("%d. %s",i+1,getSystemName(e->song.system[i])),i,0,outputs,0,outputs,selectedSubPort,portPos)) { + selectedPortSet=i; + if (selectedSubPort>=0) { + portDragActive=true; + ImGui::InhibitInertialScroll(); + try { + subPortPos=portPos.at((selectedPortSet<<4)|selectedSubPort); + } catch (std::out_of_range& e) { + portDragActive=false; + } + } + } + } + + // metronome/sample preview + if (displayInternalPorts) { + if (portSet("Sample Preview",0xffd,0,1,0,1,selectedSubPort,portPos)) { + selectedPortSet=0xffd; + if (selectedSubPort>=0) { + portDragActive=true; + ImGui::InhibitInertialScroll(); + try { + subPortPos=portPos.at((selectedPortSet<<4)|selectedSubPort); + } catch (std::out_of_range& e) { + portDragActive=false; + } + } + } + if (portSet("Metronome",0xffe,0,1,0,1,selectedSubPort,portPos)) { + selectedPortSet=0xffe; + if (selectedSubPort>=0) { + portDragActive=true; + ImGui::InhibitInertialScroll(); + try { + subPortPos=portPos.at((selectedPortSet<<4)|selectedSubPort); + } catch (std::out_of_range& e) { + portDragActive=false; + } + } + } + } + + ImGui::SetCursorPos(topPos); + if (portSet("System",0x1000,displayHiddenPorts?DIV_MAX_OUTPUTS:e->getAudioDescGot().outChans,0,e->getAudioDescGot().outChans,0,selectedSubPort,portPos)) { + selectedPortSet=0x1000; + if (selectedSubPort>=0) { + portDragActive=true; + ImGui::InhibitInertialScroll(); + try { + subPortPos=portPos.at((selectedPortSet<<4)|selectedSubPort); + } catch (std::out_of_range& e) { + portDragActive=false; + } + } + } + + if (portDragActive) { + if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) { + portDragActive=false; + if (hoveredPortSet!=0x1fff && hoveredSubPort>=0 && selectedPortSet!=hoveredPortSet) { + unsigned int src=(selectedPortSet<<4)|selectedSubPort; + unsigned int dest=(hoveredPortSet<<4)|hoveredSubPort; + + if (src&0x10000) { + src^=dest; + dest^=src; + src^=dest; + } + + src&=0xffff; + dest&=0xffff; + + if (!e->patchConnect(src,dest)) { + e->patchDisconnect(src,dest); + } + MARK_MODIFIED; + } + } + } + + // draw connections + for (unsigned int i: e->song.patchbay) { + if ((i>>20)==selectedPortSet) continue; + try { + ImVec2 portSrc=portPos.at(i>>16); + ImVec2 portDest=portPos.at(0x10000|(i&0xffff)); + dl->AddLine(portSrc,portDest,ImGui::GetColorU32(uiColors[GUI_COLOR_PATCHBAY_CONNECTION_BG]),2.0f*dpiScale); + } catch (std::out_of_range& e) { + } + } + + // foreground + for (unsigned int i: e->song.patchbay) { + if ((i>>20)!=selectedPortSet) continue; + try { + ImVec2 portSrc=portPos.at(i>>16); + ImVec2 portDest=portPos.at(0x10000|(i&0xffff)); + dl->AddLine(portSrc,portDest,ImGui::GetColorU32(uiColors[GUI_COLOR_PATCHBAY_CONNECTION]),2.0f*dpiScale); + } catch (std::out_of_range& e) { + } + } + } + if (ImGui::BeginPopup("SubPortOptions",ImGuiWindowFlags_NoMove|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings)) { + if (ImGui::MenuItem("disconnect all")) { + e->patchDisconnectAll(selectedPortSet); + MARK_MODIFIED; + } + ImGui::EndPopup(); + } + ImGui::EndChild(); } if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_MIXER; ImGui::End(); diff --git a/src/gui/osc.cpp b/src/gui/osc.cpp index 7791e8e56..7f4142211 100644 --- a/src/gui/osc.cpp +++ b/src/gui/osc.cpp @@ -49,14 +49,19 @@ void FurnaceGUI::readOsc() { int oscReadPos=(writePos-winSize)&0x7fff; for (int i=0; i<512; i++) { int pos=(oscReadPos+(i*winSize/512))&0x7fff; - oscValues[i]=(e->oscBuf[0][pos]+e->oscBuf[1][pos])*0.5f; + oscValues[i]=0; + for (int j=0; jgetAudioDescGot().outChans; j++) { + oscValues[i]+=e->oscBuf[j][pos]; + } + oscValues[i]/=e->getAudioDescGot().outChans; + if (oscValues[i]>0.001f || oscValues[i]<-0.001f) { WAKE_UP; } } float peakDecay=0.05f*60.0f*ImGui::GetIO().DeltaTime; - for (int i=0; i<2; i++) { + for (int i=0; igetAudioDescGot().outChans; i++) { peak[i]*=1.0-peakDecay; if (peak[i]<0.0001) { peak[i]=0.0; diff --git a/src/gui/presets.cpp b/src/gui/presets.cpp index 375794668..75d1ffb0e 100644 --- a/src/gui/presets.cpp +++ b/src/gui/presets.cpp @@ -45,39 +45,39 @@ void FurnaceGUI::initSystemPresets() { CATEGORY_BEGIN("Game consoles","let's play some chiptune making games!"); ENTRY( "Sega Genesis", { - CH(DIV_SYSTEM_YM2612, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 32, 0, "") + CH(DIV_SYSTEM_YM2612, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 0.5f, 0, "") } ); ENTRY( "Sega Genesis (extended channel 3)", { - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 32, 0, "") + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 0.5f, 0, "") } ); ENTRY( "Sega Genesis (CSM)", { - CH(DIV_SYSTEM_YM2612_CSM, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 32, 0, "") + CH(DIV_SYSTEM_YM2612_CSM, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 0.5f, 0, "") } ); ENTRY( "Sega Genesis (DualPCM)", { - CH(DIV_SYSTEM_YM2612_DUALPCM, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 32, 0, "") + CH(DIV_SYSTEM_YM2612_DUALPCM, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 0.5f, 0, "") } ); ENTRY( "Sega Genesis (DualPCM, extended channel 3)", { - CH(DIV_SYSTEM_YM2612_DUALPCM_EXT, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 32, 0, "") + CH(DIV_SYSTEM_YM2612_DUALPCM_EXT, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 0.5f, 0, "") } ); ENTRY( "Sega Genesis (with Sega CD)", { - CH(DIV_SYSTEM_YM2612, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 32, 0, ""), - CH(DIV_SYSTEM_RF5C68, 64, 0, + CH(DIV_SYSTEM_YM2612, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 0.5f, 0, ""), + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=2\n" "chipType=1\n" ) @@ -85,9 +85,9 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Sega Genesis (extended channel 3 with Sega CD)", { - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 32, 0, ""), - CH(DIV_SYSTEM_RF5C68, 64, 0, + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 0.5f, 0, ""), + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=2\n" "chipType=1\n" ) @@ -95,9 +95,9 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Sega Genesis (CSM with Sega CD)", { - CH(DIV_SYSTEM_YM2612_CSM, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 32, 0, ""), - CH(DIV_SYSTEM_RF5C68, 64, 0, + CH(DIV_SYSTEM_YM2612_CSM, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 0.5f, 0, ""), + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=2\n" "chipType=1\n" ) @@ -105,39 +105,39 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Sega Master System", { - CH(DIV_SYSTEM_SMS, 64, 0, "") + CH(DIV_SYSTEM_SMS, 1.0f, 0, "") } ); ENTRY( "Sega Master System (with FM expansion)", { - CH(DIV_SYSTEM_SMS, 64, 0, ""), - CH(DIV_SYSTEM_OPLL, 64, 0, "") + CH(DIV_SYSTEM_SMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_OPLL, 1.0f, 0, "") } ); ENTRY( "Sega Master System (with FM expansion in drums mode)", { - CH(DIV_SYSTEM_SMS, 64, 0, ""), - CH(DIV_SYSTEM_OPLL_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_SMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_OPLL_DRUMS, 1.0f, 0, "") } ); ENTRY( "Sega Game Gear", { - CH(DIV_SYSTEM_SMS, 64, 0, "chipType=3") + CH(DIV_SYSTEM_SMS, 1.0f, 0, "chipType=3") } ); ENTRY( "Game Boy", { - CH(DIV_SYSTEM_GB, 64, 0, "") + CH(DIV_SYSTEM_GB, 1.0f, 0, "") } ); ENTRY( "Neo Geo Pocket", { - CH(DIV_SYSTEM_T6W28, 64, 0, ""), - CH(DIV_SYSTEM_PCM_DAC, 64, -127, + CH(DIV_SYSTEM_T6W28, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, -1.0f, "rate=11025\n" "outDepth=5\n" ), - CH(DIV_SYSTEM_PCM_DAC, 64, 127, + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 1.0f, "rate=11025\n" "outDepth=5\n" ) // don't know what the actual sample rate is @@ -145,106 +145,106 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "NEC PC Engine/TurboGrafx-16", { - CH(DIV_SYSTEM_PCE, 64, 0, "") + CH(DIV_SYSTEM_PCE, 1.0f, 0, "") } ); ENTRY( "NES", { - CH(DIV_SYSTEM_NES, 64, 0, "") + CH(DIV_SYSTEM_NES, 1.0f, 0, "") } ); ENTRY( "Famicom with Konami VRC6", { - CH(DIV_SYSTEM_NES, 64, 0, ""), - CH(DIV_SYSTEM_VRC6, 64, 0, "") + CH(DIV_SYSTEM_NES, 1.0f, 0, ""), + CH(DIV_SYSTEM_VRC6, 1.0f, 0, "") } ); ENTRY( "Famicom with Konami VRC7", { - CH(DIV_SYSTEM_NES, 64, 0, ""), - CH(DIV_SYSTEM_VRC7, 64, 0, "") + CH(DIV_SYSTEM_NES, 1.0f, 0, ""), + CH(DIV_SYSTEM_VRC7, 1.0f, 0, "") } ); ENTRY( "Famicom with MMC5", { - CH(DIV_SYSTEM_NES, 64, 0, ""), - CH(DIV_SYSTEM_MMC5, 64, 0, "") + CH(DIV_SYSTEM_NES, 1.0f, 0, ""), + CH(DIV_SYSTEM_MMC5, 1.0f, 0, "") } ); ENTRY( "Famicom with Sunsoft 5B", { - CH(DIV_SYSTEM_NES, 64, 0, ""), - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=2") + CH(DIV_SYSTEM_NES, 1.0f, 0, ""), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=2") } ); ENTRY( "Famicom with Namco 163", { - CH(DIV_SYSTEM_NES, 64, 0, ""), - CH(DIV_SYSTEM_N163, 64, 0, "channels=7") + CH(DIV_SYSTEM_NES, 1.0f, 0, ""), + CH(DIV_SYSTEM_N163, 1.0f, 0, "channels=7") } ); ENTRY( "Famicom Disk System", { - CH(DIV_SYSTEM_NES, 64, 0, ""), - CH(DIV_SYSTEM_FDS, 64, 0, "") + CH(DIV_SYSTEM_NES, 1.0f, 0, ""), + CH(DIV_SYSTEM_FDS, 1.0f, 0, "") } ); ENTRY( "SNES", { - CH(DIV_SYSTEM_SNES, 64, 0, "") + CH(DIV_SYSTEM_SNES, 1.0f, 0, "") } ); ENTRY( "Mattel Intellivision", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=3") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=3") } ); ENTRY( "Vectrex", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=4") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=4") } ); ENTRY( "Neo Geo AES", { - CH(DIV_SYSTEM_YM2610_FULL, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2610_FULL, 1.0f, 0, "clockSel=1") } ); ENTRY( "Neo Geo AES (extended channel 2)", { - CH(DIV_SYSTEM_YM2610_FULL_EXT, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2610_FULL_EXT, 1.0f, 0, "clockSel=1") } ); ENTRY( "Atari 2600/7800", { - CH(DIV_SYSTEM_TIA, 64, 0, "") + CH(DIV_SYSTEM_TIA, 1.0f, 0, "") } ); ENTRY( "Atari 7800 + Ballblazer/Commando", { - CH(DIV_SYSTEM_TIA, 64, 0, ""), - CH(DIV_SYSTEM_POKEY, 64, 0, "") + CH(DIV_SYSTEM_TIA, 1.0f, 0, ""), + CH(DIV_SYSTEM_POKEY, 1.0f, 0, "") } ); ENTRY( "Atari Lynx", { - CH(DIV_SYSTEM_LYNX, 64, 0, "") + CH(DIV_SYSTEM_LYNX, 1.0f, 0, "") } ); ENTRY( "WonderSwan", { - CH(DIV_SYSTEM_SWAN, 64, 0, "") + CH(DIV_SYSTEM_SWAN, 1.0f, 0, "") }, "tickRate=75.47169811320754716981" ); ENTRY( "Virtual Boy", { - CH(DIV_SYSTEM_VBOY, 64, 0, "") + CH(DIV_SYSTEM_VBOY, 1.0f, 0, "") }, "tickRate=50.2734877734878" ); ENTRY( "Gamate", { - CH(DIV_SYSTEM_AY8910, 64, 0, + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=9\n" "chipType=0\n" "stereo=true\n" @@ -253,7 +253,7 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Pokémon Mini", { - CH(DIV_SYSTEM_POKEMINI, 32, 0, "") + CH(DIV_SYSTEM_POKEMINI, 0.5f, 0, "") } ); CATEGORY_END; @@ -261,132 +261,132 @@ void FurnaceGUI::initSystemPresets() { CATEGORY_BEGIN("Computers","let's get to work on chiptune today."); ENTRY( "Commodore PET", { - CH(DIV_SYSTEM_PET, 64, 0, "") + CH(DIV_SYSTEM_PET, 1.0f, 0, "") }, "tickRate=50" ); ENTRY( "Commodore VIC-20", { - CH(DIV_SYSTEM_VIC20, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_VIC20, 1.0f, 0, "clockSel=1") } ); ENTRY( "Commodore 64 (6581 SID)", { - CH(DIV_SYSTEM_C64_6581, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_C64_6581, 1.0f, 0, "clockSel=1") }, "tickRate=50.1245421" ); ENTRY( "Commodore 64 (8580 SID)", { - CH(DIV_SYSTEM_C64_8580, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_C64_8580, 1.0f, 0, "clockSel=1") }, "tickRate=50.1245421" ); ENTRY( "Commodore 64 (6581 SID + Sound Expander)", { - CH(DIV_SYSTEM_C64_6581, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_OPL, 64, 0, "") + CH(DIV_SYSTEM_C64_6581, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_OPL, 1.0f, 0, "") }, "tickRate=50.1245421" ); ENTRY( "Commodore 64 (6581 SID + Sound Expander in drums mode)", { - CH(DIV_SYSTEM_C64_6581, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_C64_6581, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "") }, "tickRate=50.1245421" ); ENTRY( "Commodore 64 (8580 SID + Sound Expander)", { - CH(DIV_SYSTEM_C64_8580, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_OPL, 64, 0, "") + CH(DIV_SYSTEM_C64_8580, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_OPL, 1.0f, 0, "") }, "tickRate=50.1245421" ); ENTRY( "Commodore 64 (8580 SID + Sound Expander in drums mode)", { - CH(DIV_SYSTEM_C64_8580, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_C64_8580, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "") }, "tickRate=50.1245421" ); ENTRY( "Commodore 64 (6581 SID + FM-YAM)", { - CH(DIV_SYSTEM_C64_6581, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_OPL2, 64, 0, "") + CH(DIV_SYSTEM_C64_6581, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "") }, "tickRate=50.1245421" ); ENTRY( "Commodore 64 (6581 SID + FM-YAM in drums mode)", { - CH(DIV_SYSTEM_C64_6581, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_C64_6581, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "") }, "tickRate=50.1245421" ); ENTRY( "Commodore 64 (8580 SID + FM-YAM)", { - CH(DIV_SYSTEM_C64_8580, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_OPL2, 64, 0, "") + CH(DIV_SYSTEM_C64_8580, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "") }, "tickRate=50.1245421" ); ENTRY( "Commodore 64 (8580 SID + FM-YAM in drums mode)", { - CH(DIV_SYSTEM_C64_8580, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_C64_8580, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "") }, "tickRate=50.1245421" ); ENTRY( "Amiga", { - CH(DIV_SYSTEM_AMIGA, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_AMIGA, 1.0f, 0, "clockSel=1") }, "tickRate=50" ); ENTRY( "MSX", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=0\nchipType=1") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=0\nchipType=1") } ); ENTRY( "MSX + SFG-01", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_YM2151, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_YM2151, 1.0f, 0, "") } ); ENTRY( "MSX + MSX-AUDIO", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_Y8950, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_Y8950, 1.0f, 0, "") } ); ENTRY( "MSX + MSX-AUDIO (drums mode)", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_Y8950_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, 0, "") } ); ENTRY( "MSX + MSX-MUSIC", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_OPLL, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_OPLL, 1.0f, 0, "") } ); ENTRY( "MSX + MSX-MUSIC (drums mode)", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_OPLL_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_OPLL_DRUMS, 1.0f, 0, "") } ); ENTRY( "MSX + Darky", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_AY8930, 64, 0, + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_AY8930, 1.0f, 0, "clockSel=11\n" "halfClock=true\n" ), // 3.58MHz - CH(DIV_SYSTEM_AY8930, 64, 0, + CH(DIV_SYSTEM_AY8930, 1.0f, 0, "clockSel=11\n" "halfClock=true\n" ) // 3.58MHz or 3.6MHz selectable via register @@ -395,52 +395,52 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "MSX + Playsoniq", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_SMS, 64, 0, ""), // Sega VDP - CH(DIV_SYSTEM_C64_8580, 64, 0, ""), - CH(DIV_SYSTEM_SCC_PLUS, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_SMS, 1.0f, 0, ""), // Sega VDP + CH(DIV_SYSTEM_C64_8580, 1.0f, 0, ""), + CH(DIV_SYSTEM_SCC_PLUS, 1.0f, 0, "") } ); ENTRY( "MSX + SCC", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_SCC, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_SCC, 1.0f, 0, "") } ); ENTRY( "MSX + SCC+", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_SCC_PLUS, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_SCC_PLUS, 1.0f, 0, "") } ); ENTRY( "MSX + Neotron", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_YM2610_FULL, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_YM2610_FULL, 1.0f, 0, "") } ); ENTRY( "MSX + Neotron (extended channel 2)", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_YM2610_FULL_EXT, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_YM2610_FULL_EXT, 1.0f, 0, "") } ); ENTRY( "MSX + Neotron (with YM2610B)", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_YM2610B, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_YM2610B, 1.0f, 0, "") } ); ENTRY( "MSX + Neotron (with YM2610B; extended channel 3)", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_YM2610B_EXT, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_YM2610B_EXT, 1.0f, 0, "") } ); ENTRY( "MSX + SIMPL", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=55930\n" "outDepth=7\n" ) // variable rate, Mono DAC @@ -448,435 +448,435 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "NEC PC-88 (with PC-8801-10)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=15"), // external - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=15") // "" + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=15"), // external + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=15") // "" } ); ENTRY( "NEC PC-88 (with PC-8801-11)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4") // external } ); ENTRY( "NEC PC-88 (with PC-8801-11; extended channel 3)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4") // external } ); ENTRY( "NEC PC-88 (with PC-8801-23)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=1") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=1") // external } ); ENTRY( "NEC PC-88 (with PC-8801-23; extended channel 3)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=1") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=1") // external } ); ENTRY( "NEC PC-88 (with HMB-20 HIBIKI-8800)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2151, 64, 0, "clockSel=2") // external; 4.0000MHz + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2151, 1.0f, 0, "clockSel=2") // external; 4.0000MHz } ); ENTRY( "NEC PC-8801mk2SR (with PC-8801-10)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=15"), // external - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=15") // "" + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=15"), // external + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=15") // "" } ); ENTRY( "NEC PC-8801mk2SR (with PC-8801-10; extended channel 3)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=15"), // external - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=15") // "" + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=15"), // external + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=15") // "" } ); ENTRY( "NEC PC-8801mk2SR (with PC-8801-11)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4") // external } ); ENTRY( "NEC PC-8801mk2SR (with PC-8801-11; extended channel 3 on internal OPN)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4") // external } ); ENTRY( "NEC PC-8801mk2SR (with PC-8801-11; extended channel 3 on external OPN)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4") // external } ); ENTRY( "NEC PC-8801mk2SR (with PC-8801-11; extended channel 3 on both OPNs)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4") // external } ); ENTRY( "NEC PC-8801mk2SR (with PC-8801-23)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=1") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=1") // external } ); ENTRY( "NEC PC-8801mk2SR (with PC-8801-23; extended channel 3 on internal OPN)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=1") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=1") // external } ); ENTRY( "NEC PC-8801mk2SR (with PC-8801-23; extended channel 3 on external OPN)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=1") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=1") // external } ); ENTRY( "NEC PC-8801mk2SR (with PC-8801-23; extended channel 3 on both OPNs)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=1") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=1") // external } ); ENTRY( "NEC PC-8801mk2SR (with HMB-20 HIBIKI-8800)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_YM2151, 64, 0, "clockSel=2") // external; 4.0000MHz + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_YM2151, 1.0f, 0, "clockSel=2") // external; 4.0000MHz } ); ENTRY( "NEC PC-8801mk2SR (with HMB-20 HIBIKI-8800; extended channel 3)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_YM2151, 64, 0, "clockSel=2") // external; 4.0000MHz + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_YM2151, 1.0f, 0, "clockSel=2") // external; 4.0000MHz } ); ENTRY( "NEC PC-8801FA (with PC-8801-10)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=15"), // external - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=15") // "" + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=15"), // external + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=15") // "" } ); ENTRY( "NEC PC-8801FA (with PC-8801-10; extended channel 3)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=4"), // internal - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=15"), // external - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=15") // "" + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=4"), // internal + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=15"), // external + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=15") // "" } ); ENTRY( "NEC PC-8801FA (with PC-8801-11)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=1"), // internal - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=1"), // internal + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4") // external } ); ENTRY( "NEC PC-8801FA (with PC-8801-11; extended channel 3 on internal OPN)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=1"), // internal - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=1"), // internal + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4") // external } ); ENTRY( "NEC PC-8801FA (with PC-8801-11; extended channel 3 on external OPN)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=1"), // internal - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=1"), // internal + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4") // external } ); ENTRY( "NEC PC-8801FA (with PC-8801-11; extended channel 3 on both OPNs)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=1"), // internal - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=1"), // internal + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4") // external } ); ENTRY( "NEC PC-8801FA (with PC-8801-23)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=1"), // internal - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=1") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=1"), // internal + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=1") // external } ); ENTRY( "NEC PC-8801FA (with PC-8801-23; extended channel 3 on internal OPN)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=1"), // internal - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=1") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=1"), // internal + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=1") // external } ); ENTRY( "NEC PC-8801FA (with PC-8801-23; extended channel 3 on external OPN)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=1"), // internal - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=1") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=1"), // internal + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=1") // external } ); ENTRY( "NEC PC-8801FA (with PC-8801-23; extended channel 3 on both OPNs)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=1"), // internal - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=1") // external + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=1"), // internal + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=1") // external } ); ENTRY( "NEC PC-8801FA (with HMB-20 HIBIKI-8800)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=1"), // internal - CH(DIV_SYSTEM_YM2151, 64, 0, "clockSel=2") // external; 4.0000MHz + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=1"), // internal + CH(DIV_SYSTEM_YM2151, 1.0f, 0, "clockSel=2") // external; 4.0000MHz } ); ENTRY( "NEC PC-8801FA (with HMB-20 HIBIKI-8800; extended channel 3)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=1"), // internal - CH(DIV_SYSTEM_YM2151, 64, 0, "clockSel=2") // external; 4.0000MHz + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=1"), // internal + CH(DIV_SYSTEM_YM2151, 1.0f, 0, "clockSel=2") // external; 4.0000MHz } ); ENTRY( "NEC PC-98 (with PC-9801-26/K)", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4"), // 3.9936MHz but some compatible card has 4MHz - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4"), // 3.9936MHz but some compatible card has 4MHz + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with PC-9801-26/K; extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4"), // 3.9936MHz but some compatible card has 4MHz - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4"), // 3.9936MHz but some compatible card has 4MHz + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with Sound Orchestra)", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_OPL2, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with Sound Orchestra; extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_OPL2, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with Sound Orchestra in drums mode)", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with Sound Orchestra in drums mode; extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with Sound Orchestra V)", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_Y8950, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_Y8950, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with Sound Orchestra V; extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_Y8950, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_Y8950, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with Sound Orchestra V in drums mode)", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_Y8950_DRUMS, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with Sound Orchestra V in drums mode; extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_Y8950_DRUMS, 64, 0, "clockSel=4"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, 0, "clockSel=4"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with PC-9801-86)", { // -73 also has OPNA - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, // 2x 16-bit Burr Brown DAC + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, // 2x 16-bit Burr Brown DAC "rate=44100\n" "outDepth=15\n" ), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=44100\n" "outDepth=15\n" ), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with PC-9801-86; extended channel 3)", { // -73 also has OPNA - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=44100\n" "outDepth=15\n" ), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=44100\n" "outDepth=15\n" ), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with PC-9801-73)", { - CH(DIV_SYSTEM_YM2608, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with PC-9801-73; extended channel 3)", { - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible)", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=44100\n" "outDepth=15\n" "stereo=true\n" ), - CH(DIV_SYSTEM_OPL3, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_OPL3, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible; extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=44100\n" "outDepth=15\n" "stereo=true\n" ), - CH(DIV_SYSTEM_OPL3, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_OPL3, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible in drums mode)", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=44100\n" "outDepth=15\n" "stereo=true\n" ), - CH(DIV_SYSTEM_OPL3_DRUMS, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_OPL3_DRUMS, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible in drums mode; extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=44100\n" "outDepth=15\n" "stereo=true\n" ), - CH(DIV_SYSTEM_OPL3_DRUMS, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_OPL3_DRUMS, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "clockSel=1") } ); ENTRY( "ZX Spectrum (48K)", { - CH(DIV_SYSTEM_SFX_BEEPER, 64, 0, "") + CH(DIV_SYSTEM_SFX_BEEPER, 1.0f, 0, "") } ); ENTRY( "ZX Spectrum (128K)", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=1") //beeper was also included + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=1") //beeper was also included } ); ENTRY( "ZX Spectrum (128K) with TurboSound FM", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=1") } ); ENTRY( "ZX Spectrum (128K) with TurboSound FM (extended channel 3 on first OPN)", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=1") } ); ENTRY( "ZX Spectrum (128K) with TurboSound FM (extended channel 3 on second OPN)", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=1") } ); ENTRY( "ZX Spectrum (128K) with TurboSound FM (extended channel 3 on both OPNs)", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=1") } ); ENTRY( "ZX Spectrum (128K) with TurboSound", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=1"), // or YM2149 - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=1") // or YM2149 + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=1"), // or YM2149 + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=1") // or YM2149 } ); ENTRY( "Amstrad CPC", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=5") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=5") } ); ENTRY( "Atari 800", { - CH(DIV_SYSTEM_POKEY, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_POKEY, 1.0f, 0, "clockSel=1") }, "tickRate=50" ); ENTRY( "Atari 800 (stereo)", { - CH(DIV_SYSTEM_POKEY, 64, -127, "clockSel=1"), - CH(DIV_SYSTEM_POKEY, 64, 127, "clockSel=1"), + CH(DIV_SYSTEM_POKEY, 1.0f, -1.0f, "clockSel=1"), + CH(DIV_SYSTEM_POKEY, 1.0f, 1.0f, "clockSel=1"), }, "tickRate=50" ); ENTRY( "Atari ST", { - CH(DIV_SYSTEM_AY8910, 64, 0, + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3\n" "chipType=1\n" ) @@ -884,15 +884,15 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Atari STE", { - CH(DIV_SYSTEM_AY8910, 64, 0, + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3\n" "chipType=1\n" ), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=50668\n" "outDepth=7\n" ), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=50668\n" "outDepth=7\n" ) @@ -900,12 +900,12 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "SAM Coupé", { - CH(DIV_SYSTEM_SAA1099, 64, 0, "") + CH(DIV_SYSTEM_SAA1099, 1.0f, 0, "") } ); ENTRY( "BBC Micro", { - CH(DIV_SYSTEM_SMS, 64, 0, + CH(DIV_SYSTEM_SMS, 1.0f, 0, "clockSel=2\n" "chipType=4\n" // SN76489A 4MHz ) @@ -913,57 +913,57 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "PC (barebones)", { - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "IBM PCjr", { // it can be enable sound output at once - CH(DIV_SYSTEM_SMS, 64, 0, "chipType=5") // SN76496 + CH(DIV_SYSTEM_SMS, 1.0f, 0, "chipType=5") // SN76496 } ); ENTRY( "Tandy 1000", { - CH(DIV_SYSTEM_SMS, 64, 0, "chipType=5"), // NCR 8496 or SN76496 or Tandy PSSJ(with 8 bit DAC) - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_SMS, 1.0f, 0, "chipType=5"), // NCR 8496 or SN76496 or Tandy PSSJ(with 8 bit DAC) + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + Covox Sound Master", { - CH(DIV_SYSTEM_AY8930, 64, 0, "clockSel=3"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_AY8930, 1.0f, 0, "clockSel=3"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + SSI 2001", { - CH(DIV_SYSTEM_C64_6581, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_C64_6581, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + Game Blaster", { - CH(DIV_SYSTEM_SAA1099, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_SAA1099, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_SAA1099, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_SAA1099, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + AdLib", { - CH(DIV_SYSTEM_OPL2, 64, 0, ""), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_OPL2, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + AdLib (drums mode)", { - CH(DIV_SYSTEM_OPL2, 64, 0, ""), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_OPL2, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + Sound Blaster", { - CH(DIV_SYSTEM_OPL2, 64, 0, ""), - CH(DIV_SYSTEM_PCSPKR, 64, 0, ""), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_OPL2, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=22050\n" "outDepth=7\n" ) @@ -971,9 +971,9 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "PC + AdLib/Sound Blaster (drums mode)", { - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, ""), - CH(DIV_SYSTEM_PCSPKR, 64, 0, ""), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=22050\n" "outDepth=7\n" ) @@ -981,132 +981,132 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "PC + Sound Blaster w/Game Blaster Compatible", { - CH(DIV_SYSTEM_OPL2, 64, 0, ""), - CH(DIV_SYSTEM_SAA1099, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_SAA1099, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_OPL2, 1.0f, 0, ""), + CH(DIV_SYSTEM_SAA1099, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_SAA1099, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=22050\n" "outDepth=7\n" ), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + Sound Blaster w/Game Blaster Compatible (drums mode)", { - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, ""), - CH(DIV_SYSTEM_SAA1099, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_SAA1099, 64, 0, "clockSel=1"), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_SAA1099, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_SAA1099, 1.0f, 0, "clockSel=1"), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=22050\n" "outDepth=7\n" ), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + Sound Blaster Pro", { - CH(DIV_SYSTEM_OPL2, 64, -127, ""), - CH(DIV_SYSTEM_OPL2, 64, 127, ""), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_OPL2, 1.0f, -1.0f, ""), + CH(DIV_SYSTEM_OPL2, 1.0f, 1.0f, ""), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=22050\n" "outDepth=7\n" "stereo=true\n" ), //alternatively 44.1 khz mono - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + Sound Blaster Pro (drums mode)", { - CH(DIV_SYSTEM_OPL2_DRUMS, 64, -127, ""), - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 127, ""), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, -1.0f, ""), + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 1.0f, ""), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=22050\n" "outDepth=7\n" "stereo=true\n" ), //alternatively 44.1 khz mono - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + Sound Blaster Pro 2", { - CH(DIV_SYSTEM_OPL3, 64, 0, ""), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_OPL3, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=44100\n" "outDepth=15\n" "stereo=true\n" ), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + Sound Blaster Pro 2 (drums mode)", { - CH(DIV_SYSTEM_OPL3_DRUMS, 64, 0, ""), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_OPL3_DRUMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=44100\n" "outDepth=15\n" "stereo=true\n" ), - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + PC-FXGA", { - CH(DIV_SYSTEM_PCE, 64, 0, ""), // HuC6230 (WSG from HuC6280 but with built in 2 OKI ADPCM playback engines) - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_PCE, 1.0f, 0, ""), // HuC6230 (WSG from HuC6280 but with built in 2 OKI ADPCM playback engines) + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "PC + SAAYM", { - CH(DIV_SYSTEM_YM2151, 64, 0, ""), // 3.58MHz or 4MHz selectable via jumper - CH(DIV_SYSTEM_SAA1099, 64, 0, "clockSel=1"), // 7.16MHz or 8MHz selectable via jumper - CH(DIV_SYSTEM_SAA1099, 64, 0, "clockSel=1"), // "" - CH(DIV_SYSTEM_PCSPKR, 64, 0, "") + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), // 3.58MHz or 4MHz selectable via jumper + CH(DIV_SYSTEM_SAA1099, 1.0f, 0, "clockSel=1"), // 7.16MHz or 8MHz selectable via jumper + CH(DIV_SYSTEM_SAA1099, 1.0f, 0, "clockSel=1"), // "" + CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, "") } ); ENTRY( "Sharp X1", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=3") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3") } ); ENTRY( "Sharp X1 + FM Addon", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=3"), - CH(DIV_SYSTEM_YM2151, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3"), + CH(DIV_SYSTEM_YM2151, 1.0f, 0, "clockSel=2") } ); ENTRY( "Sharp X68000", { - CH(DIV_SYSTEM_YM2151, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_MSM6258, 64, 0, "") + CH(DIV_SYSTEM_YM2151, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_MSM6258, 1.0f, 0, "") } ); ENTRY( "FM Towns", { - CH(DIV_SYSTEM_YM2612, 64, 0, "clockSel=2"), // YM3438 - CH(DIV_SYSTEM_RF5C68, 64, 0, "") + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=2"), // YM3438 + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "") } ); ENTRY( "FM Towns (extended channel 3)", { - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "clockSel=2"), // YM3438 - CH(DIV_SYSTEM_RF5C68, 64, 0, "") + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=2"), // YM3438 + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "") } ); ENTRY( "FM Towns (CSM)", { - CH(DIV_SYSTEM_YM2612_CSM, 64, 0, "clockSel=2"), // YM3438 - CH(DIV_SYSTEM_RF5C68, 64, 0, "") + CH(DIV_SYSTEM_YM2612_CSM, 1.0f, 0, "clockSel=2"), // YM3438 + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "") } ); ENTRY( "Commander X16", { - CH(DIV_SYSTEM_VERA, 64, 0, ""), - CH(DIV_SYSTEM_YM2151, 32, 0, "") + CH(DIV_SYSTEM_VERA, 1.0f, 0, ""), + CH(DIV_SYSTEM_YM2151, 0.5f, 0, "") } ); ENTRY( "TI-99/4A", { - CH(DIV_SYSTEM_SMS, 64, 0, + CH(DIV_SYSTEM_SMS, 1.0f, 0, "clockSel=6\n" "chipType=8\n" // SN94624 447KHz ) @@ -1117,143 +1117,143 @@ void FurnaceGUI::initSystemPresets() { CATEGORY_BEGIN("Arcade systems","INSERT COIN"); ENTRY( "Pong", { - CH(DIV_SYSTEM_PONG, 64, 0, "") + CH(DIV_SYSTEM_PONG, 1.0f, 0, "") } ); ENTRY( "Bally Midway MCR", { // SSIO sound board - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=3"), // 2MHz - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=3") // 2MHz + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3"), // 2MHz + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3") // 2MHz // additional sound boards, mostly software controlled DAC } ); ENTRY( "Williams/Midway Y/T unit w/ADPCM sound board", { // ADPCM sound board - CH(DIV_SYSTEM_YM2151, 64, 0, ""), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=15625\n" "outDepth=7\n" ), // variable via OPM timer? - CH(DIV_SYSTEM_MSM6295, 64, 0, "") + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") } ); ENTRY( "Konami Gyruss", { - CH(DIV_SYSTEM_AY8910, 64, 0, ""), - CH(DIV_SYSTEM_AY8910, 64, 0, ""), - CH(DIV_SYSTEM_AY8910, 64, 0, ""), - CH(DIV_SYSTEM_AY8910, 64, 0, ""), - CH(DIV_SYSTEM_AY8910, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, ""), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, ""), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, ""), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, ""), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "") // additional discrete sound logics } ); ENTRY( "Konami Bubble System", { - CH(DIV_SYSTEM_AY8910, 64, 0, ""), - CH(DIV_SYSTEM_AY8910, 64, 0, ""), - CH(DIV_SYSTEM_BUBSYS_WSG, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, ""), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, ""), + CH(DIV_SYSTEM_BUBSYS_WSG, 1.0f, 0, "") // VLM5030 exists but not used for music at all } ); ENTRY( "Konami MX5000", { - CH(DIV_SYSTEM_YM2151, 64, 0, ""), // 3.58MHz - CH(DIV_SYSTEM_K007232, 64, 0, "") // "" + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), // 3.58MHz + CH(DIV_SYSTEM_K007232, 1.0f, 0, "") // "" } ); ENTRY( "Konami Battlantis", { - CH(DIV_SYSTEM_OPL2, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_OPL2, 64, 0, "clockSel=3") // "" + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "clockSel=3") // "" } ); ENTRY( "Konami Battlantis (drums mode on first OPL2)", { - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_OPL2, 64, 0, "clockSel=3") // "" + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "clockSel=3") // "" } ); ENTRY( "Konami Battlantis (drums mode on second OPL2)", { - CH(DIV_SYSTEM_OPL2, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "clockSel=3") // "" + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "clockSel=3") // "" } ); ENTRY( "Konami Battlantis (drums mode on both OPL2s)", { - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "clockSel=3") // "" + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "clockSel=3") // "" } ); ENTRY( "Konami Fast Lane", { - CH(DIV_SYSTEM_K007232, 64, 0, ""), // 3.58MHz - CH(DIV_SYSTEM_K007232, 64, 0, "") // "" + CH(DIV_SYSTEM_K007232, 1.0f, 0, ""), // 3.58MHz + CH(DIV_SYSTEM_K007232, 1.0f, 0, "") // "" } ); ENTRY( "Konami Chequered Flag", { - CH(DIV_SYSTEM_YM2151, 64, 0, ""), // 3.58MHz - CH(DIV_SYSTEM_K007232, 64, 0, "stereo=true"), // "" - CH(DIV_SYSTEM_K007232, 64, 0, "") // "" + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), // 3.58MHz + CH(DIV_SYSTEM_K007232, 1.0f, 0, "stereo=true"), // "" + CH(DIV_SYSTEM_K007232, 1.0f, 0, "") // "" } ); ENTRY( "Konami Haunted Castle", { - CH(DIV_SYSTEM_OPL2, 64, 0, ""), // 3.58MHz - CH(DIV_SYSTEM_SCC, 64, 0, ""), // "" - CH(DIV_SYSTEM_K007232, 64, 0, "") // "" + CH(DIV_SYSTEM_OPL2, 1.0f, 0, ""), // 3.58MHz + CH(DIV_SYSTEM_SCC, 1.0f, 0, ""), // "" + CH(DIV_SYSTEM_K007232, 1.0f, 0, "") // "" } ); ENTRY( "Konami Haunted Castle (drums mode)", { - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, ""), // 3.58MHz - CH(DIV_SYSTEM_SCC, 64, 0, ""), // "" - CH(DIV_SYSTEM_K007232, 64, 0, "") // "" + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, ""), // 3.58MHz + CH(DIV_SYSTEM_SCC, 1.0f, 0, ""), // "" + CH(DIV_SYSTEM_K007232, 1.0f, 0, "") // "" } ); ENTRY( "Konami Hot Chase", { - CH(DIV_SYSTEM_K007232, 64, 0, "stereo=true"), // 3.58MHz - CH(DIV_SYSTEM_K007232, 64, 0, "stereo=true"), // "" - CH(DIV_SYSTEM_K007232, 64, 0, "stereo=true") // "" + CH(DIV_SYSTEM_K007232, 1.0f, 0, "stereo=true"), // 3.58MHz + CH(DIV_SYSTEM_K007232, 1.0f, 0, "stereo=true"), // "" + CH(DIV_SYSTEM_K007232, 1.0f, 0, "stereo=true") // "" } ); ENTRY( "Konami S.P.Y.", { - CH(DIV_SYSTEM_OPL2, 64, 0, ""), // 3.58MHz - CH(DIV_SYSTEM_K007232, 64, 0, ""), // "" - CH(DIV_SYSTEM_K007232, 64, 0, "") // "" + CH(DIV_SYSTEM_OPL2, 1.0f, 0, ""), // 3.58MHz + CH(DIV_SYSTEM_K007232, 1.0f, 0, ""), // "" + CH(DIV_SYSTEM_K007232, 1.0f, 0, "") // "" } ); ENTRY( "Konami S.P.Y. (drums mode)", { - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, ""), // 3.58MHz - CH(DIV_SYSTEM_K007232, 64, 0, ""), // "" - CH(DIV_SYSTEM_K007232, 64, 0, "") // "" + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, ""), // 3.58MHz + CH(DIV_SYSTEM_K007232, 1.0f, 0, ""), // "" + CH(DIV_SYSTEM_K007232, 1.0f, 0, "") // "" } ); ENTRY( "Konami Hexion", { - CH(DIV_SYSTEM_SCC, 64, 0, "clockSel=2"), // 1.5MHz (3MHz input) - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_SCC, 1.0f, 0, "clockSel=2"), // 1.5MHz (3MHz input) + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=1") } ); ENTRY( "Sega Kyugo", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=14"), - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=14") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=14"), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=14") } ); ENTRY( "Sega System 1", { - CH(DIV_SYSTEM_SMS, 64, 0, + CH(DIV_SYSTEM_SMS, 1.0f, 0, "clockSel=2\n" "chipType=4\n" ), // SN76489A 4MHz - CH(DIV_SYSTEM_SMS, 64, 0, + CH(DIV_SYSTEM_SMS, 1.0f, 0, "clockSel=5\n" "chipType=4\n" ) // SN76489A 2MHz @@ -1261,46 +1261,46 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Sega System E", { - CH(DIV_SYSTEM_SMS, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 64, 0, "") + CH(DIV_SYSTEM_SMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 1.0f, 0, "") } ); ENTRY( "Sega System E (with FM expansion)", { - CH(DIV_SYSTEM_SMS, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 64, 0, ""), - CH(DIV_SYSTEM_OPLL, 64, 0, "") + CH(DIV_SYSTEM_SMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_OPLL, 1.0f, 0, "") } ); ENTRY( "Sega System E (with FM expansion in drums mode)", { - CH(DIV_SYSTEM_SMS, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 64, 0, ""), - CH(DIV_SYSTEM_OPLL_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_SMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_OPLL_DRUMS, 1.0f, 0, "") } ); ENTRY( "Sega Hang-On", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_SEGAPCM, 64, 0, "") // discrete logics, 62.5KHz output rate + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_SEGAPCM, 1.0f, 0, "") // discrete logics, 62.5KHz output rate } ); ENTRY( "Sega Hang-On (extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_SEGAPCM, 64, 0, "") // discrete logics, 62.5KHz output rate + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_SEGAPCM, 1.0f, 0, "") // discrete logics, 62.5KHz output rate } ); ENTRY( "Sega OutRun/X Board", { - CH(DIV_SYSTEM_YM2151, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_SEGAPCM, 64, 0, "") // ASIC, 31.25KHz output rate + CH(DIV_SYSTEM_YM2151, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_SEGAPCM, 1.0f, 0, "") // ASIC, 31.25KHz output rate } ); ENTRY( "Sega System 24", { - CH(DIV_SYSTEM_YM2151, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2151, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=61500\n" "outDepth=7\n" ) // software controlled, variable rate via configurable timers @@ -1308,68 +1308,68 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Sega System 18", { - CH(DIV_SYSTEM_YM2612, 64, 0, "clockSel=2"), // discrete 8MHz YM3438 - CH(DIV_SYSTEM_YM2612, 64, 0, "clockSel=2"), // ^^ - CH(DIV_SYSTEM_RF5C68, 64, 0, "clockSel=1") // 10MHz + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=2"), // discrete 8MHz YM3438 + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=2"), // ^^ + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=1") // 10MHz } ); ENTRY( "Sega System 18 (extended channel 3 on first OPN2C)", { - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "clockSel=2"), // discrete 8MHz YM3438 - CH(DIV_SYSTEM_YM2612, 64, 0, "clockSel=2"), // ^^ - CH(DIV_SYSTEM_RF5C68, 64, 0, "clockSel=1") // 10MHz + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=2"), // discrete 8MHz YM3438 + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=2"), // ^^ + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=1") // 10MHz } ); ENTRY( "Sega System 18 (extended channel 3 on second OPN2C)", { - CH(DIV_SYSTEM_YM2612, 64, 0, "clockSel=2"), // discrete 8MHz YM3438 - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "clockSel=2"), // ^^ - CH(DIV_SYSTEM_RF5C68, 64, 0, "clockSel=1") // 10MHz + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=2"), // discrete 8MHz YM3438 + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=2"), // ^^ + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=1") // 10MHz } ); ENTRY( "Sega System 18 (extended channel 3 on both OPN2Cs)", { - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "clockSel=2"), // discrete 8MHz YM3438 - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "clockSel=2"), // ^^ - CH(DIV_SYSTEM_RF5C68, 64, 0, "clockSel=1") // 10MHz + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=2"), // discrete 8MHz YM3438 + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=2"), // ^^ + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=1") // 10MHz } ); ENTRY( "Sega System 32", { - CH(DIV_SYSTEM_YM2612, 64, 0, "clockSel=4"), // discrete 8.05MHz YM3438 - CH(DIV_SYSTEM_YM2612, 64, 0, "clockSel=4"), // ^^ - CH(DIV_SYSTEM_RF5C68, 64, 0, "clockSel=2") // 12.5MHz + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=4"), // discrete 8.05MHz YM3438 + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=4"), // ^^ + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=2") // 12.5MHz } ); ENTRY( "Sega System 32 (extended channel 3 on first OPN2C)", { - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "clockSel=4"), // discrete 8.05MHz YM3438 - CH(DIV_SYSTEM_YM2612, 64, 0, "clockSel=4"), // ^^ - CH(DIV_SYSTEM_RF5C68, 64, 0, "clockSel=2") // 12.5MHz + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=4"), // discrete 8.05MHz YM3438 + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=4"), // ^^ + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=2") // 12.5MHz } ); ENTRY( "Sega System 32 (extended channel 3 on second OPN2C)", { - CH(DIV_SYSTEM_YM2612, 64, 0, "clockSel=4"), // discrete 8.05MHz YM3438 - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "clockSel=4"), // ^^ - CH(DIV_SYSTEM_RF5C68, 64, 0, "clockSel=2") // 12.5MHz + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=4"), // discrete 8.05MHz YM3438 + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=4"), // ^^ + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=2") // 12.5MHz } ); ENTRY( "Sega System 32 (extended channel 3 on both OPN2Cs)", { - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "clockSel=4"), // discrete 8.05MHz YM3438 - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "clockSel=4"), // ^^ - CH(DIV_SYSTEM_RF5C68, 64, 0, "clockSel=2") // 12.5MHz + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=4"), // discrete 8.05MHz YM3438 + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=4"), // ^^ + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=2") // 12.5MHz } ); ENTRY( "Capcom Exed Eyes", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=4"), // 1.5MHz - CH(DIV_SYSTEM_SMS, 64, 0, + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=4"), // 1.5MHz + CH(DIV_SYSTEM_SMS, 1.0f, 0, "clockSel=4\n" "chipType=1\n" ), // SN76489 3MHz - CH(DIV_SYSTEM_SMS, 64, 0, + CH(DIV_SYSTEM_SMS, 1.0f, 0, "clockSel=4\n" "chipType=1\n" ) // SN76489 3MHz @@ -1377,66 +1377,66 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Capcom Arcade", { // 1943, Side arms, etc - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=5"), // 4 or 1.5MHz; various per games - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=5") + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=5"), // 4 or 1.5MHz; various per games + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=5") } ); ENTRY( "Capcom Arcade (extended channel 3 on first OPN)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=5"), - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=5") + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=5"), + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=5") } ); ENTRY( "Capcom Arcade (extended channel 3 on second OPN)", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=5"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=5") + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=5"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=5") } ); ENTRY( "Capcom Arcade (extended channel 3 on both OPNs)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=5"), - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=5") + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=5"), + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=5") } ); ENTRY( "Capcom CPS-1", { - CH(DIV_SYSTEM_YM2151, 64, 0, ""), // 3.58MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "") + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), // 3.58MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") } ); ENTRY( "Capcom CPS-2 (QSound)", { - CH(DIV_SYSTEM_QSOUND, 64, 0, "") + CH(DIV_SYSTEM_QSOUND, 1.0f, 0, "") } ); ENTRY( "Jaleco Ginga NinkyouDen", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), // 1.79MHz - CH(DIV_SYSTEM_Y8950, 64, 0, "") // 3.58MHz + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), // 1.79MHz + CH(DIV_SYSTEM_Y8950, 1.0f, 0, "") // 3.58MHz } ); ENTRY( "Jaleco Ginga NinkyouDen (drums mode)", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1"), // 1.79MHz - CH(DIV_SYSTEM_Y8950_DRUMS, 64, 0, "") // 3.58MHz + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"), // 1.79MHz + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, 0, "") // 3.58MHz } ); ENTRY( "Jaleco Mega System 1", { - CH(DIV_SYSTEM_YM2151, 64, 0, "clockSel=1"), // 3.5MHz (7MHz / 2) - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=2") // 4MHz + CH(DIV_SYSTEM_YM2151, 1.0f, 0, "clockSel=1"), // 3.5MHz (7MHz / 2) + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=2") // 4MHz } ); ENTRY( "NMK 16-bit Arcade", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=5"), // 1.5MHz; optional - CH(DIV_SYSTEM_MSM6295, 64, 0, + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=5"), // 1.5MHz; optional + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=2\n" "rateSel=true\n" ), // 4MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=2\n" "rateSel=true\n" ) // ^^ @@ -1444,12 +1444,12 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "NMK 16-bit Arcade (extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=5"), // 1.5MHz; optional - CH(DIV_SYSTEM_MSM6295, 64, 0, + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=5"), // 1.5MHz; optional + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=2\n" "rateSel=true\n" ), // 4MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=2\n" "rateSel=true\n" ) // ^^ @@ -1457,22 +1457,22 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Kaneko DJ Boy", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_MSM6295, 64, -127, "clockSel=12"), // 1.5MHz, Left output - CH(DIV_SYSTEM_MSM6295, 64, 127, "clockSel=12"), // 1.5MHz, Right output + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, -1.0f, "clockSel=12"), // 1.5MHz, Left output + CH(DIV_SYSTEM_MSM6295, 1.0f, 1.0f, "clockSel=12"), // 1.5MHz, Right output } ); ENTRY( "Kaneko DJ Boy (extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_MSM6295, 64, -127, "clockSel=12"), // 1.5MHz, Left output - CH(DIV_SYSTEM_MSM6295, 64, 127, "clockSel=12") // 1.5MHz, Right output + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, -1.0f, "clockSel=12"), // 1.5MHz, Left output + CH(DIV_SYSTEM_MSM6295, 1.0f, 1.0f, "clockSel=12") // 1.5MHz, Right output } ); ENTRY( "Kaneko Air Buster", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=13\n" "rateSel=true\n" ) // 3MHz @@ -1480,8 +1480,8 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Kaneko Air Buster (extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=13\n" "rateSel=true\n" ) // 3MHz @@ -1489,349 +1489,349 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Kaneko Toybox System", { - CH(DIV_SYSTEM_AY8910, 64, 0, + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3\n" "chipType=1\n" ), // YM2149 2MHz - CH(DIV_SYSTEM_AY8910, 64, 0, + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3\n" "chipType=1\n" ), // ^^ - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=8") // 2MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=8") // 2MHz } ); ENTRY( "Kaneko Jackie Chan", { - CH(DIV_SYSTEM_YMZ280B, 64, 0, "clockSel=3") // 16MHz + CH(DIV_SYSTEM_YMZ280B, 1.0f, 0, "clockSel=3") // 16MHz } ); ENTRY( "Super Kaneko Nova System", { - CH(DIV_SYSTEM_YMZ280B, 64, 0, "clockSel=4") // 16.67MHz (33.33MHz / 2) + CH(DIV_SYSTEM_YMZ280B, 1.0f, 0, "clockSel=4") // 16.67MHz (33.33MHz / 2) } ); ENTRY( "Tecmo Ninja Gaiden", { // Ninja Gaiden, Raiga, etc - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "") // 1MHz + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") // 1MHz } ); ENTRY( "Tecmo Ninja Gaiden (extended channel 3 on first OPN)", { // Ninja Gaiden, Raiga, etc - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "") // 1MHz + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") // 1MHz } ); ENTRY( "Tecmo Ninja Gaiden (extended channel 3 on second OPN)", { // Ninja Gaiden, Raiga, etc - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "") // 1MHz + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") // 1MHz } ); ENTRY( "Tecmo Ninja Gaiden (extended channel 3 on both OPNs)", { // Ninja Gaiden, Raiga, etc - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=2"), // 4MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "") // 1MHz + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=2"), // 4MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") // 1MHz } ); ENTRY( "Tecmo System", { - CH(DIV_SYSTEM_OPL3, 64, 0, ""), - CH(DIV_SYSTEM_YMZ280B, 64, 0, ""), - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=8") // 2MHz + CH(DIV_SYSTEM_OPL3, 1.0f, 0, ""), + CH(DIV_SYSTEM_YMZ280B, 1.0f, 0, ""), + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=8") // 2MHz } ); ENTRY( "Tecmo System (drums mode)", { - CH(DIV_SYSTEM_OPL3_DRUMS, 64, 0, ""), - CH(DIV_SYSTEM_YMZ280B, 64, 0, ""), - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=8") // 2MHz + CH(DIV_SYSTEM_OPL3_DRUMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_YMZ280B, 1.0f, 0, ""), + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=8") // 2MHz } ); ENTRY( "Seibu Kaihatsu Raiden", { // Raiden, Seibu cup soccer, Zero team, etc - CH(DIV_SYSTEM_OPL2, 64, 0, ""), // YM3812 3.58MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "") // 1 or 1.023MHz (28.636363MHz / 28); various per games + CH(DIV_SYSTEM_OPL2, 1.0f, 0, ""), // YM3812 3.58MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") // 1 or 1.023MHz (28.636363MHz / 28); various per games } ); ENTRY( "Seibu Kaihatsu Raiden (drums mode)", { // Raiden, Seibu cup soccer, Zero team, etc - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, ""), // YM3812 3.58MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "") // 1 or 1.023MHz (28.636363MHz / 28); various per games + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, ""), // YM3812 3.58MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") // 1 or 1.023MHz (28.636363MHz / 28); various per games } ); ENTRY( "Sunsoft Shanghai 3", { - CH(DIV_SYSTEM_AY8910, 64, 0, + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=4\n" "chipType=1\n" ), // YM2149 1.5MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=1") // 1.056MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=1") // 1.056MHz } ); ENTRY( "Sunsoft Arcade", { - CH(DIV_SYSTEM_YM2612, 64, 0, "clockSel=2"), // discrete YM3438 8MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=1") // 1.056MHz + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=2"), // discrete YM3438 8MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=1") // 1.056MHz } ); ENTRY( "Sunsoft Arcade (extended channel 3)", { - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "clockSel=2"), // discrete YM3438 8MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=1") // 1.056MHz + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=2"), // discrete YM3438 8MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=1") // 1.056MHz } ); ENTRY( "Atari Klax", { - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=7") // 0.895MHz (3.579545MHz / 4) + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=7") // 0.895MHz (3.579545MHz / 4) } ); ENTRY( "Atari Rampart", { - CH(DIV_SYSTEM_OPLL, 64, 0, ""), // 3.579545MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=14") // 1.193MHz (3.579545MHz / 3) + CH(DIV_SYSTEM_OPLL, 1.0f, 0, ""), // 3.579545MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=14") // 1.193MHz (3.579545MHz / 3) } ); ENTRY( "Atari Rampart (drums mode)", { - CH(DIV_SYSTEM_OPLL_DRUMS, 64, 0, ""), // 3.579545MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=14") // 1.193MHz (3.579545MHz / 3) + CH(DIV_SYSTEM_OPLL_DRUMS, 1.0f, 0, ""), // 3.579545MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=14") // 1.193MHz (3.579545MHz / 3) } ); ENTRY( "Atari JSA IIIs", { - CH(DIV_SYSTEM_YM2151, 64, 0, ""), // 3.579545MHz - CH(DIV_SYSTEM_MSM6295, 64, -127, "clockSel=14"), // 1.193MHz (3.579545MHz / 3), Left output - CH(DIV_SYSTEM_MSM6295, 64, 127, "clockSel=14") // 1.193MHz (3.579545MHz / 3), Right output + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), // 3.579545MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, -1.0f, "clockSel=14"), // 1.193MHz (3.579545MHz / 3), Left output + CH(DIV_SYSTEM_MSM6295, 1.0f, 1.0f, "clockSel=14") // 1.193MHz (3.579545MHz / 3), Right output } ); ENTRY( "Atari Marble Madness", { - CH(DIV_SYSTEM_YM2151, 64, 0, ""), - CH(DIV_SYSTEM_POKEY, 64, 0, "") + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), + CH(DIV_SYSTEM_POKEY, 1.0f, 0, "") } ); ENTRY( "Atari Championship Sprint", { - CH(DIV_SYSTEM_YM2151, 64, 0, ""), - CH(DIV_SYSTEM_POKEY, 64, 0, ""), - CH(DIV_SYSTEM_POKEY, 64, 0, "") + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), + CH(DIV_SYSTEM_POKEY, 1.0f, 0, ""), + CH(DIV_SYSTEM_POKEY, 1.0f, 0, "") } ); ENTRY( "Atari Tetris", { - CH(DIV_SYSTEM_POKEY, 64, 0, ""), - CH(DIV_SYSTEM_POKEY, 64, 0, "") + CH(DIV_SYSTEM_POKEY, 1.0f, 0, ""), + CH(DIV_SYSTEM_POKEY, 1.0f, 0, "") } ); ENTRY( "Atari I, Robot", { - CH(DIV_SYSTEM_POKEY, 64, 0, "customClock=1512000"), - CH(DIV_SYSTEM_POKEY, 64, 0, "customClock=1512000"), - CH(DIV_SYSTEM_POKEY, 64, 0, "customClock=1512000"), - CH(DIV_SYSTEM_POKEY, 64, 0, "customClock=1512000") + CH(DIV_SYSTEM_POKEY, 1.0f, 0, "customClock=1512000"), + CH(DIV_SYSTEM_POKEY, 1.0f, 0, "customClock=1512000"), + CH(DIV_SYSTEM_POKEY, 1.0f, 0, "customClock=1512000"), + CH(DIV_SYSTEM_POKEY, 1.0f, 0, "customClock=1512000") } ); ENTRY( "Data East Karnov", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=5"), // 1.5MHz - CH(DIV_SYSTEM_OPL, 64, 0, "clockSel=3") // 3MHz + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=5"), // 1.5MHz + CH(DIV_SYSTEM_OPL, 1.0f, 0, "clockSel=3") // 3MHz } ); ENTRY( "Data East Karnov (extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=5"), // 1.5MHz - CH(DIV_SYSTEM_OPL, 64, 0, "clockSel=3") // 3MHz + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=5"), // 1.5MHz + CH(DIV_SYSTEM_OPL, 1.0f, 0, "clockSel=3") // 3MHz } ); ENTRY( "Data East Karnov (drums mode)", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=5"), // 1.5MHz - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "clockSel=3") // 3MHz + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=5"), // 1.5MHz + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "clockSel=3") // 3MHz } ); ENTRY( "Data East Karnov (extended channel 3; drums mode)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=5"), // 1.5MHz - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "clockSel=3") // 3MHz + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=5"), // 1.5MHz + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "clockSel=3") // 3MHz } ); ENTRY( "Data East Arcade", { // Bad dudes, Robocop, etc - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=5"), // 1.5MHz - CH(DIV_SYSTEM_OPL2, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "") // 1 to 1.056MHz; various per games or optional + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=5"), // 1.5MHz + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") // 1 to 1.056MHz; various per games or optional } ); ENTRY( "Data East Arcade (extended channel 3)", { // Bad dudes, Robocop, etc - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=5"), // 1.5MHz - CH(DIV_SYSTEM_OPL2, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "") // 1 to 1.056MHz; various per games or optional + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=5"), // 1.5MHz + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") // 1 to 1.056MHz; various per games or optional } ); ENTRY( "Data East Arcade (drums mode)", { // Bad dudes, Robocop, etc - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=5"), // 1.5MHz - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "") // 1 to 1.056MHz; various per games or optional + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=5"), // 1.5MHz + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") // 1 to 1.056MHz; various per games or optional } ); ENTRY( "Data East Arcade (extended channel 3; drums mode)", { // Bad dudes, Robocop, etc - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=5"), // 1.5MHz - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_MSM6295, 64, 0, "") // 1 to 1.056MHz; various per games or optional + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=5"), // 1.5MHz + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") // 1 to 1.056MHz; various per games or optional } ); ENTRY( "Data East PCX", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=5"), // 1.5MHz - CH(DIV_SYSTEM_PCE, 64, 0, "") + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=5"), // 1.5MHz + CH(DIV_SYSTEM_PCE, 1.0f, 0, "") // software controlled MSM5205 } ); ENTRY( "Data East PCX (extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=5"), // 1.5MHz - CH(DIV_SYSTEM_PCE, 64, 0, "") + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=5"), // 1.5MHz + CH(DIV_SYSTEM_PCE, 1.0f, 0, "") // software controlled MSM5205 } ); ENTRY( "Data East Dark Seal", { // Dark Seal, Crude Buster, Vapor Trail, etc - CH(DIV_SYSTEM_YM2151, 64, 0, ""), // 3.580MHz (32.22MHz / 9) - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=2"), // 4.0275MHz (32.22MHz / 8); optional - CH(DIV_SYSTEM_MSM6295, 64, 0, ""), // 1.007MHz (32.22MHz / 32) - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=8") // 2.014MHz (32.22MHz / 16); optional + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), // 3.580MHz (32.22MHz / 9) + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=2"), // 4.0275MHz (32.22MHz / 8); optional + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, ""), // 1.007MHz (32.22MHz / 32) + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=8") // 2.014MHz (32.22MHz / 16); optional // HuC6280 is for control them, internal sound isn't used } ); ENTRY( "Data East Dark Seal (extended channel 3)", { // Dark Seal, Crude Buster, Vapor Trail, etc - CH(DIV_SYSTEM_YM2151, 64, 0, ""), // 3.580MHz (32.22MHz / 9) - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=2"), // 4.0275MHz (32.22MHz / 8); optional - CH(DIV_SYSTEM_MSM6295, 64, 0, ""), // 1.007MHz (32.22MHz / 32) - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=8") // 2.014MHz (32.22MHz / 16); optional + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), // 3.580MHz (32.22MHz / 9) + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=2"), // 4.0275MHz (32.22MHz / 8); optional + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, ""), // 1.007MHz (32.22MHz / 32) + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=8") // 2.014MHz (32.22MHz / 16); optional // HuC6280 is for control them, internal sound isn't used } ); ENTRY( "Data East Deco 156", { - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=0"), // 1 or 1.007MHz (32.22MHz / 32); various per games - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=8") // 1 or 2 or 2.014MHz (32.22MHz / 16); various per games + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=0"), // 1 or 1.007MHz (32.22MHz / 32); various per games + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=8") // 1 or 2 or 2.014MHz (32.22MHz / 16); various per games } ); ENTRY( "Data East MLC", { - CH(DIV_SYSTEM_YMZ280B, 64, 0, "clockSel=5") // 14MHz + CH(DIV_SYSTEM_YMZ280B, 1.0f, 0, "clockSel=5") // 14MHz } ); ENTRY( "SNK Ikari Warriors", { - CH(DIV_SYSTEM_OPL, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_OPL, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_OPL, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_OPL, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Ikari Warriors (drums mode on first OPL)", { - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_OPL, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_OPL, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Ikari Warriors (drums mode on second OPL)", { - CH(DIV_SYSTEM_OPL, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_OPL, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Ikari Warriors (drums mode on both OPLs)", { - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Triple Z80", { - CH(DIV_SYSTEM_Y8950, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_OPL, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_Y8950, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_OPL, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Triple Z80 (drums mode on Y8950)", { - CH(DIV_SYSTEM_Y8950_DRUMS, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_OPL, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_OPL, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Triple Z80 (drums mode on OPL)", { - CH(DIV_SYSTEM_Y8950, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_Y8950, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Triple Z80 (drums mode on Y8950 and OPL)", { - CH(DIV_SYSTEM_Y8950_DRUMS, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Chopper I", { - CH(DIV_SYSTEM_Y8950, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_OPL2, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_Y8950, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Chopper I (drums mode on Y8950)", { - CH(DIV_SYSTEM_Y8950_DRUMS, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_OPL2, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Chopper I (drums mode on OPL2)", { - CH(DIV_SYSTEM_Y8950, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_Y8950, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Chopper I (drums mode on Y8950 and OPL2)", { - CH(DIV_SYSTEM_Y8950_DRUMS, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Touchdown Fever", { - CH(DIV_SYSTEM_OPL, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_Y8950, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_OPL, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_Y8950, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Touchdown Fever (drums mode on OPL)", { - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_Y8950, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_Y8950, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Touchdown Fever (drums mode on Y8950)", { - CH(DIV_SYSTEM_OPL, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_Y8950_DRUMS, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_OPL, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, 0, "clockSel=2") } ); ENTRY( "SNK Touchdown Fever (drums mode on OPL and Y8950)", { - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "clockSel=2"), - CH(DIV_SYSTEM_Y8950_DRUMS, 64, 0, "clockSel=2") + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "clockSel=2"), + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, 0, "clockSel=2") } ); ENTRY( "Alpha denshi Alpha-68K", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_OPLL, 64, 0, "clockSel=0"), // 3.58MHz - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_OPLL, 1.0f, 0, "clockSel=0"), // 3.58MHz + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=7614\n" "outDepth=7\n" ) // software controlled 8 bit DAC @@ -1839,9 +1839,9 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Alpha denshi Alpha-68K (extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_OPLL, 64, 0, "clockSel=0"), // 3.58MHz - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_OPLL, 1.0f, 0, "clockSel=0"), // 3.58MHz + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=7614\n" "outDepth=7\n" ) // software controlled 8 bit DAC @@ -1849,9 +1849,9 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Alpha denshi Alpha-68K (drums mode)", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_OPLL_DRUMS, 64, 0, "clockSel=0"), // 3.58MHz - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_OPLL_DRUMS, 1.0f, 0, "clockSel=0"), // 3.58MHz + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=7614\n" "outDepth=7\n" ) // software controlled 8 bit DAC @@ -1859,9 +1859,9 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Alpha denshi Alpha-68K (extended channel 3; drums mode)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=3"), // 3MHz - CH(DIV_SYSTEM_OPLL_DRUMS, 64, 0, "clockSel=0"), // 3.58MHz - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=3"), // 3MHz + CH(DIV_SYSTEM_OPLL_DRUMS, 1.0f, 0, "clockSel=0"), // 3.58MHz + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=7614\n" "outDepth=7\n" ) // software controlled 8 bit DAC @@ -1869,13 +1869,13 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Alpha denshi Equites", { - CH(DIV_SYSTEM_MSM5232, 64, 0, "customClock=6144000"), - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=14"), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_MSM5232, 1.0f, 0, "customClock=6144000"), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=14"), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=11025\n" "outDepth=5\n" ), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=11025\n" "outDepth=5\n" ) // don't know what the actual sample rate is @@ -1883,47 +1883,47 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Neo Geo MVS", { - CH(DIV_SYSTEM_YM2610_FULL, 64, 0, "") + CH(DIV_SYSTEM_YM2610_FULL, 1.0f, 0, "") } ); ENTRY( "Neo Geo MVS (extended channel 2)", { - CH(DIV_SYSTEM_YM2610_FULL_EXT, 64, 0, "") + CH(DIV_SYSTEM_YM2610_FULL_EXT, 1.0f, 0, "") } ); ENTRY( "Nichibutsu Mag Max", { - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=13"), - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=13"), - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=13") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=13"), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=13"), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=13") } ); ENTRY( "Namco (3-channel WSG)", { // Pac-Man, Galaga, Xevious, etc - CH(DIV_SYSTEM_NAMCO, 64, 0, "") + CH(DIV_SYSTEM_NAMCO, 1.0f, 0, "") } ); ENTRY( "Namco Mappy", { // Mappy, Super Pac-Man, Libble Rabble, etc - CH(DIV_SYSTEM_NAMCO_15XX, 64, 0, "") + CH(DIV_SYSTEM_NAMCO_15XX, 1.0f, 0, "") } ); ENTRY( "Namco Pac-Land", { // Pac-Land, Baraduke, Sky kid, etc - CH(DIV_SYSTEM_NAMCO_CUS30, 64, 0, "") + CH(DIV_SYSTEM_NAMCO_CUS30, 1.0f, 0, "") } ); ENTRY( "Namco System 86", { // without expansion board case; Hopping Mappy, etc - CH(DIV_SYSTEM_YM2151, 64, 0, ""), - CH(DIV_SYSTEM_NAMCO_CUS30, 64, 0, "") + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), + CH(DIV_SYSTEM_NAMCO_CUS30, 1.0f, 0, "") } ); ENTRY( "Namco Thunder Ceptor", { - CH(DIV_SYSTEM_YM2151, 64, 0, ""), - CH(DIV_SYSTEM_NAMCO_CUS30, 64, 0, ""), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), + CH(DIV_SYSTEM_NAMCO_CUS30, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=8000\n" "outDepth=7\n" ) // M65C02 software driven, correct sample rate? @@ -1931,13 +1931,13 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Namco System 1", { - CH(DIV_SYSTEM_YM2151, 64, 0, ""), - CH(DIV_SYSTEM_NAMCO_CUS30, 64, 0, ""), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), + CH(DIV_SYSTEM_NAMCO_CUS30, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=6000\n" "outDepth=7\n" ), // sample rate verified from https://github.com/mamedev/mame/blob/master/src/devices/sound/n63701x.cpp - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=6000\n" "outDepth=7\n" ) // "" @@ -1945,29 +1945,29 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Taito Arcade", { - CH(DIV_SYSTEM_YM2610B, 64, 0, "") + CH(DIV_SYSTEM_YM2610B, 1.0f, 0, "") } ); ENTRY( "Taito Arcade (extended channel 3)", { - CH(DIV_SYSTEM_YM2610B_EXT, 64, 0, "") + CH(DIV_SYSTEM_YM2610B_EXT, 1.0f, 0, "") } ); ENTRY( "Taito Metal Soldier Isaac II", { - CH(DIV_SYSTEM_MSM5232, 64, 0, ""), - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=3"), - CH(DIV_SYSTEM_AY8910, 64, 0, "clockSel=3") + CH(DIV_SYSTEM_MSM5232, 1.0f, 0, ""), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3"), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3") } ); ENTRY( "Taito The Fairyland Story", { - CH(DIV_SYSTEM_MSM5232, 64, 0, ""), - CH(DIV_SYSTEM_AY8910, 64, 0, + CH(DIV_SYSTEM_MSM5232, 1.0f, 0, ""), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3\n" "chipType=1\n" ), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=11025\n" "outDepth=7\n" ) // don't know what the actual sample rate is @@ -1975,16 +1975,16 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Taito Wyvern F-0", { - CH(DIV_SYSTEM_MSM5232, 64, 0, ""), - CH(DIV_SYSTEM_AY8910, 64, 0, + CH(DIV_SYSTEM_MSM5232, 1.0f, 0, ""), + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3\n" "chipType=1\n" ), - CH(DIV_SYSTEM_AY8910, 64, 0, + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "clockSel=3\n" "chipType=1\n" ), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=11025\n" "outDepth=7\n" ) // don't know what the actual sample rate is @@ -1992,97 +1992,97 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Seta 1", { - CH(DIV_SYSTEM_X1_010, 64, 0, "") + CH(DIV_SYSTEM_X1_010, 1.0f, 0, "") } ); ENTRY( "Seta 1 + FM addon", { - CH(DIV_SYSTEM_X1_010, 64, 0, ""), - CH(DIV_SYSTEM_YM2612, 64, 0, "clockSel=2") // Discrete YM3438 + CH(DIV_SYSTEM_X1_010, 1.0f, 0, ""), + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=2") // Discrete YM3438 } ); ENTRY( "Seta 1 + FM addon (extended channel 3)", { - CH(DIV_SYSTEM_X1_010, 64, 0, ""), - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "clockSel=2") // Discrete YM3438 + CH(DIV_SYSTEM_X1_010, 1.0f, 0, ""), + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=2") // Discrete YM3438 } ); ENTRY( "Seta 2", { - CH(DIV_SYSTEM_X1_010, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_X1_010, 1.0f, 0, "clockSel=1") } ); ENTRY( "Cave 68000", { - CH(DIV_SYSTEM_YMZ280B, 64, 0, "") + CH(DIV_SYSTEM_YMZ280B, 1.0f, 0, "") } ); ENTRY( "Coreland Cyber Tank", { - CH(DIV_SYSTEM_Y8950, 64, -127, ""), // 3.58MHz, Left output - CH(DIV_SYSTEM_Y8950, 64, 127, "") // 3.58MHz, Right output + CH(DIV_SYSTEM_Y8950, 1.0f, -1.0f, ""), // 3.58MHz, Left output + CH(DIV_SYSTEM_Y8950, 1.0f, 1.0f, "") // 3.58MHz, Right output } ); ENTRY( "Coreland Cyber Tank (drums mode)", { - CH(DIV_SYSTEM_Y8950_DRUMS, 64, -127, ""), // 3.58MHz, Left output - CH(DIV_SYSTEM_Y8950_DRUMS, 64, 127, "") // 3.58MHz, Right output + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, -1.0f, ""), // 3.58MHz, Left output + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, 1.0f, "") // 3.58MHz, Right output } ); ENTRY( "ICE Skimaxx", { - CH(DIV_SYSTEM_MSM6295, 64, -127, + CH(DIV_SYSTEM_MSM6295, 1.0f, -1.0f, "clockSel=2\n" "rateSel=true\n" ), // 4MHz, Left output - CH(DIV_SYSTEM_MSM6295, 64, 127, + CH(DIV_SYSTEM_MSM6295, 1.0f, 1.0f, "clockSel=2\n" "rateSel=true\n" ), // 4MHz, Right output - CH(DIV_SYSTEM_MSM6295, 64, -127, "clockSel=8"), // 2MHz, Left output - CH(DIV_SYSTEM_MSM6295, 64, 127, "clockSel=8") // 2MHz, Right output + CH(DIV_SYSTEM_MSM6295, 1.0f, -1.0f, "clockSel=8"), // 2MHz, Left output + CH(DIV_SYSTEM_MSM6295, 1.0f, 1.0f, "clockSel=8") // 2MHz, Right output } ); ENTRY( "Toaplan 1", { - CH(DIV_SYSTEM_OPL2, 64, 0, "clockSel=5") // 3.5MHz + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "clockSel=5") // 3.5MHz } ); ENTRY( "Toaplan 1 (drums mode)", { - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "clockSel=5") // 3.5MHz + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "clockSel=5") // 3.5MHz } ); ENTRY( "Dynax/Nakanihon 3rd generation hardware", { - CH(DIV_SYSTEM_AY8910, 64, 0, ""), // AY or YM, optional - 1.79MHz or 3.58MHz; various per game - CH(DIV_SYSTEM_OPLL, 64, 0, ""), - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=6") // 1.023MHz mostly + CH(DIV_SYSTEM_AY8910, 1.0f, 0, ""), // AY or YM, optional - 1.79MHz or 3.58MHz; various per game + CH(DIV_SYSTEM_OPLL, 1.0f, 0, ""), + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=6") // 1.023MHz mostly } ); ENTRY( "Dynax/Nakanihon 3rd generation hardware (drums mode)", { - CH(DIV_SYSTEM_AY8910, 64, 0, ""), // AY or YM, optional - 1.79MHz or 3.58MHz; various per game - CH(DIV_SYSTEM_OPLL_DRUMS, 64, 0, ""), - CH(DIV_SYSTEM_MSM6295, 64, 0, "clockSel=6") // 1.023MHz mostly + CH(DIV_SYSTEM_AY8910, 1.0f, 0, ""), // AY or YM, optional - 1.79MHz or 3.58MHz; various per game + CH(DIV_SYSTEM_OPLL_DRUMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "clockSel=6") // 1.023MHz mostly } ); ENTRY( "Dynax/Nakanihon Real Break", { - CH(DIV_SYSTEM_OPLL, 64, 0, ""), - CH(DIV_SYSTEM_YMZ280B, 64, 0, "") + CH(DIV_SYSTEM_OPLL, 1.0f, 0, ""), + CH(DIV_SYSTEM_YMZ280B, 1.0f, 0, "") } ); ENTRY( "Dynax/Nakanihon Real Break (drums mode)", { - CH(DIV_SYSTEM_OPLL_DRUMS, 64, 0, ""), - CH(DIV_SYSTEM_YMZ280B, 64, 0, "") + CH(DIV_SYSTEM_OPLL_DRUMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_YMZ280B, 1.0f, 0, "") } ); ENTRY( "Irem M72", { - CH(DIV_SYSTEM_YM2151, 64, 0, ""), - CH(DIV_SYSTEM_PCM_DAC, 64, 0, + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "rate=7812\n" "outDepth=7\n" ) @@ -2090,8 +2090,8 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Irem M92/M107", { - CH(DIV_SYSTEM_YM2151, 64, 0, ""), - CH(DIV_SYSTEM_GA20, 64, 0, "") + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), + CH(DIV_SYSTEM_GA20, 1.0f, 0, "") } ); CATEGORY_END; @@ -2100,152 +2100,152 @@ void FurnaceGUI::initSystemPresets() { CATEGORY_BEGIN("FM","chips which use frequency modulation (FM) to generate sound.\nsome of these also pack more (like square and sample channels)."); ENTRY( "Yamaha YM2151 (OPM)", { - CH(DIV_SYSTEM_YM2151, 64, 0, "") + CH(DIV_SYSTEM_YM2151, 1.0f, 0, "") } ); ENTRY( "Yamaha YM2203 (OPN)", { - CH(DIV_SYSTEM_YM2203, 64, 0, "clockSel=3") + CH(DIV_SYSTEM_YM2203, 1.0f, 0, "clockSel=3") } ); ENTRY( "Yamaha YM2203 (extended channel 3)", { - CH(DIV_SYSTEM_YM2203_EXT, 64, 0, "clockSel=3") + CH(DIV_SYSTEM_YM2203_EXT, 1.0f, 0, "clockSel=3") } ); ENTRY( "Yamaha YM2608 (OPNA)", { - CH(DIV_SYSTEM_YM2608, 64, 0, "") + CH(DIV_SYSTEM_YM2608, 1.0f, 0, "") } ); ENTRY( "Yamaha YM2608 (extended channel 3)", { - CH(DIV_SYSTEM_YM2608_EXT, 64, 0, "") + CH(DIV_SYSTEM_YM2608_EXT, 1.0f, 0, "") } ); ENTRY( "Yamaha YM2610 (OPNB)", { - CH(DIV_SYSTEM_YM2610_FULL, 64, 0, "") + CH(DIV_SYSTEM_YM2610_FULL, 1.0f, 0, "") } ); ENTRY( "Yamaha YM2610 (extended channel 2)", { - CH(DIV_SYSTEM_YM2610_FULL_EXT, 64, 0, "") + CH(DIV_SYSTEM_YM2610_FULL_EXT, 1.0f, 0, "") } ); ENTRY( "Yamaha YM2610B (OPNB2)", { - CH(DIV_SYSTEM_YM2610B, 64, 0, "") + CH(DIV_SYSTEM_YM2610B, 1.0f, 0, "") } ); ENTRY( "Yamaha YM2610B (extended channel 3)", { - CH(DIV_SYSTEM_YM2610B_EXT, 64, 0, "") + CH(DIV_SYSTEM_YM2610B_EXT, 1.0f, 0, "") } ); ENTRY( "Yamaha YM2612 (OPN2)", { - CH(DIV_SYSTEM_YM2612, 64, 0, "ladderEffect=true") + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "ladderEffect=true") } ); ENTRY( "Yamaha YM2612 (extended channel 3)", { - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "ladderEffect=true") + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "ladderEffect=true") } ); ENTRY( "Yamaha YM2612 (OPN2) CSM", { - CH(DIV_SYSTEM_YM2612_CSM, 64, 0, "ladderEffect=true") + CH(DIV_SYSTEM_YM2612_CSM, 1.0f, 0, "ladderEffect=true") } ); ENTRY( "Yamaha YM2612 (OPN2) with DualPCM", { - CH(DIV_SYSTEM_YM2612_DUALPCM, 64, 0, "ladderEffect=true") + CH(DIV_SYSTEM_YM2612_DUALPCM, 1.0f, 0, "ladderEffect=true") } ); ENTRY( "Yamaha YM2612 (extended channel 3) with DualPCM", { - CH(DIV_SYSTEM_YM2612_DUALPCM_EXT, 64, 0, "ladderEffect=true") + CH(DIV_SYSTEM_YM2612_DUALPCM_EXT, 1.0f, 0, "ladderEffect=true") } ); ENTRY( "Yamaha YM2413 (OPLL)", { - CH(DIV_SYSTEM_OPLL, 64, 0, "") + CH(DIV_SYSTEM_OPLL, 1.0f, 0, "") } ); ENTRY( "Yamaha YM2413 (drums mode)", { - CH(DIV_SYSTEM_OPLL_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_OPLL_DRUMS, 1.0f, 0, "") } ); ENTRY( "Yamaha YM2414 (OPZ)", { - CH(DIV_SYSTEM_OPZ, 64, 0, "") + CH(DIV_SYSTEM_OPZ, 1.0f, 0, "") } ); ENTRY( "Yamaha YM3438 (OPN2C)", { - CH(DIV_SYSTEM_YM2612, 64, 0, "") + CH(DIV_SYSTEM_YM2612, 1.0f, 0, "") } ); ENTRY( "Yamaha YM3438 (extended channel 3)", { - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, "") + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "") } ); ENTRY( "Yamaha YM3438 (OPN2C) CSM", { - CH(DIV_SYSTEM_YM2612_CSM, 64, 0, "") + CH(DIV_SYSTEM_YM2612_CSM, 1.0f, 0, "") } ); ENTRY( "Yamaha YM3438 (OPN2C) with DualPCM", { - CH(DIV_SYSTEM_YM2612_DUALPCM, 64, 0, "") + CH(DIV_SYSTEM_YM2612_DUALPCM, 1.0f, 0, "") } ); ENTRY( "Yamaha YM3438 (extended channel 3) with DualPCM", { - CH(DIV_SYSTEM_YM2612_DUALPCM_EXT, 64, 0, "") + CH(DIV_SYSTEM_YM2612_DUALPCM_EXT, 1.0f, 0, "") } ); ENTRY( "Yamaha YM3526 (OPL)", { - CH(DIV_SYSTEM_OPL, 64, 0, "") + CH(DIV_SYSTEM_OPL, 1.0f, 0, "") } ); ENTRY( "Yamaha YM3526 (drums mode)", { - CH(DIV_SYSTEM_OPL_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_OPL_DRUMS, 1.0f, 0, "") } ); ENTRY( "Yamaha Y8950", { - CH(DIV_SYSTEM_Y8950, 64, 0, "") + CH(DIV_SYSTEM_Y8950, 1.0f, 0, "") } ); ENTRY( "Yamaha Y8950 (drums mode)", { - CH(DIV_SYSTEM_Y8950_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_Y8950_DRUMS, 1.0f, 0, "") } ); ENTRY( "Yamaha YM3812 (OPL2)", { - CH(DIV_SYSTEM_OPL2, 64, 0, "") + CH(DIV_SYSTEM_OPL2, 1.0f, 0, "") } ); ENTRY( "Yamaha YM3812 (drums mode)", { - CH(DIV_SYSTEM_OPL2_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, "") } ); ENTRY( "Yamaha YMF262 (OPL3)", { - CH(DIV_SYSTEM_OPL3, 64, 0, "") + CH(DIV_SYSTEM_OPL3, 1.0f, 0, "") } ); ENTRY( "Yamaha YMF262 (drums mode)", { - CH(DIV_SYSTEM_OPL3_DRUMS, 64, 0, "") + CH(DIV_SYSTEM_OPL3_DRUMS, 1.0f, 0, "") } ); ENTRY( @@ -2267,7 +2267,7 @@ void FurnaceGUI::initSystemPresets() { if (settings.hiddenSystems) { ENTRY( "Yamaha YMU759 (MA-2)", { - CH(DIV_SYSTEM_YMU759, 64, 0, "") + CH(DIV_SYSTEM_YMU759, 1.0f, 0, "") } ); } @@ -2276,43 +2276,43 @@ void FurnaceGUI::initSystemPresets() { CATEGORY_BEGIN("Square","these chips generate square/pulse tones only (but may include noise)."); ENTRY( "TI SN76489", { - CH(DIV_SYSTEM_SMS, 64, 0, "chipType=1") + CH(DIV_SYSTEM_SMS, 1.0f, 0, "chipType=1") } ); ENTRY( "TI SN76489A", { - CH(DIV_SYSTEM_SMS, 64, 0, "chipType=4") + CH(DIV_SYSTEM_SMS, 1.0f, 0, "chipType=4") } ); ENTRY( "TI SN76496", { - CH(DIV_SYSTEM_SMS, 64, 0, "chipType=5") + CH(DIV_SYSTEM_SMS, 1.0f, 0, "chipType=5") } ); ENTRY( "NCR 8496", { - CH(DIV_SYSTEM_SMS, 64, 0, "chipType=6") + CH(DIV_SYSTEM_SMS, 1.0f, 0, "chipType=6") } ); ENTRY( "Tandy PSSJ 3-voice sound", { - CH(DIV_SYSTEM_SMS, 64, 0, "chipType=7") + CH(DIV_SYSTEM_SMS, 1.0f, 0, "chipType=7") // 8 bit DAC } ); ENTRY( "Sega PSG (SN76489-like)", { - CH(DIV_SYSTEM_SMS, 64, 0, ""), + CH(DIV_SYSTEM_SMS, 1.0f, 0, ""), } ); ENTRY( "Sega PSG (SN76489-like, Stereo)", { - CH(DIV_SYSTEM_SMS, 64, 0, "chipType=3") + CH(DIV_SYSTEM_SMS, 1.0f, 0, "chipType=3") } ); ENTRY( "TI SN94624", { - CH(DIV_SYSTEM_SMS, 64, 0, + CH(DIV_SYSTEM_SMS, 1.0f, 0, "clockSel=6\n" "chipType=8\n" ) @@ -2320,7 +2320,7 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "TI SN76494", { - CH(DIV_SYSTEM_SMS, 64, 0, + CH(DIV_SYSTEM_SMS, 1.0f, 0, "clockSel=6\n" "chipType=9\n" ) @@ -2328,52 +2328,52 @@ void FurnaceGUI::initSystemPresets() { ); ENTRY( "Toshiba T6W28", { - CH(DIV_SYSTEM_T6W28, 64, 0, "") + CH(DIV_SYSTEM_T6W28, 1.0f, 0, "") } ); ENTRY( "AY-3-8910", { - CH(DIV_SYSTEM_AY8910, 64, 0, "") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "") } ); ENTRY( "AY-3-8914", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=3") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=3") } ); ENTRY( "Yamaha YM2149(F)", { - CH(DIV_SYSTEM_AY8910, 64, 0, "chipType=1") + CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1") } ); ENTRY( "Philips SAA1099", { - CH(DIV_SYSTEM_SAA1099, 64, 0, "") + CH(DIV_SYSTEM_SAA1099, 1.0f, 0, "") } ); ENTRY( "PC Speaker", { - CH(DIV_SYSTEM_PCSPKR, 32, 0, "") + CH(DIV_SYSTEM_PCSPKR, 0.5f, 0, "") } ); ENTRY( "Pokémon Mini", { - CH(DIV_SYSTEM_POKEMINI, 32, 0, "") + CH(DIV_SYSTEM_POKEMINI, 0.5f, 0, "") } ); ENTRY( "Commodore VIC", { - CH(DIV_SYSTEM_VIC20, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_VIC20, 1.0f, 0, "clockSel=1") } ); ENTRY( "OKI MSM5232", { - CH(DIV_SYSTEM_MSM5232, 64, 0, "") + CH(DIV_SYSTEM_MSM5232, 1.0f, 0, "") } ); ENTRY( "Pong", { - CH(DIV_SYSTEM_PONG, 64, 0, "") + CH(DIV_SYSTEM_PONG, 1.0f, 0, "") } ); CATEGORY_END; @@ -2381,63 +2381,63 @@ void FurnaceGUI::initSystemPresets() { CATEGORY_BEGIN("Sample","chips/systems which use PCM or ADPCM samples for sound synthesis."); ENTRY( "Amiga", { - CH(DIV_SYSTEM_AMIGA, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_AMIGA, 1.0f, 0, "clockSel=1") }, "tickRate=50" ); ENTRY( "SegaPCM", { - CH(DIV_SYSTEM_SEGAPCM, 64, 0, "") + CH(DIV_SYSTEM_SEGAPCM, 1.0f, 0, "") } ); ENTRY( "Capcom QSound", { - CH(DIV_SYSTEM_QSOUND, 64, 0, "") + CH(DIV_SYSTEM_QSOUND, 1.0f, 0, "") } ); ENTRY( "Seta/Allumer X1-010", { - CH(DIV_SYSTEM_X1_010, 64, 0, "") + CH(DIV_SYSTEM_X1_010, 1.0f, 0, "") } ); ENTRY( "Yamaha YMZ280B (PCMD8)", { - CH(DIV_SYSTEM_YMZ280B, 64, 0, "") + CH(DIV_SYSTEM_YMZ280B, 1.0f, 0, "") } ); ENTRY( "Ricoh RF5C68", { - CH(DIV_SYSTEM_RF5C68, 64, 0, "") + CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "") } ); ENTRY( "OKI MSM6258", { - CH(DIV_SYSTEM_MSM6258, 64, 0, "") + CH(DIV_SYSTEM_MSM6258, 1.0f, 0, "") } ); ENTRY( "OKI MSM6295", { - CH(DIV_SYSTEM_MSM6295, 64, 0, "") + CH(DIV_SYSTEM_MSM6295, 1.0f, 0, "") } ); ENTRY( "SNES", { - CH(DIV_SYSTEM_SNES, 64, 0, "") + CH(DIV_SYSTEM_SNES, 1.0f, 0, "") } ); ENTRY( "Konami K007232", { - CH(DIV_SYSTEM_K007232, 64, 0, "") + CH(DIV_SYSTEM_K007232, 1.0f, 0, "") } ); ENTRY( "Irem GA20", { - CH(DIV_SYSTEM_GA20, 64, 0, "") + CH(DIV_SYSTEM_GA20, 1.0f, 0, "") } ); ENTRY( "Generic PCM DAC", { - CH(DIV_SYSTEM_PCM_DAC, 64, 0, "") + CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, "") } ); CATEGORY_END; @@ -2445,70 +2445,70 @@ void FurnaceGUI::initSystemPresets() { CATEGORY_BEGIN("Wavetable","chips which use user-specified waveforms to generate sound."); ENTRY( "PC Engine", { - CH(DIV_SYSTEM_PCE, 64, 0, "") + CH(DIV_SYSTEM_PCE, 1.0f, 0, "") } ); ENTRY( "Commodore PET (pseudo-wavetable)", { - CH(DIV_SYSTEM_PET, 64, 0, "") + CH(DIV_SYSTEM_PET, 1.0f, 0, "") }, "tickRate=50" ); ENTRY( "Konami Bubble System WSG", { - CH(DIV_SYSTEM_BUBSYS_WSG, 64, 0, "") + CH(DIV_SYSTEM_BUBSYS_WSG, 1.0f, 0, "") } ); ENTRY( "Konami SCC", { - CH(DIV_SYSTEM_SCC, 64, 0, "") + CH(DIV_SYSTEM_SCC, 1.0f, 0, "") } ); ENTRY( "Konami SCC+", { - CH(DIV_SYSTEM_SCC_PLUS, 64, 0, "") + CH(DIV_SYSTEM_SCC_PLUS, 1.0f, 0, "") } ); ENTRY( "Namco WSG", { - CH(DIV_SYSTEM_NAMCO, 64, 0, "") + CH(DIV_SYSTEM_NAMCO, 1.0f, 0, "") } ); ENTRY( "Namco C15 (8-channel mono)", { - CH(DIV_SYSTEM_NAMCO_15XX, 64, 0, "") + CH(DIV_SYSTEM_NAMCO_15XX, 1.0f, 0, "") } ); ENTRY( "Namco C30 (8-channel stereo)", { - CH(DIV_SYSTEM_NAMCO_CUS30, 64, 0, "") + CH(DIV_SYSTEM_NAMCO_CUS30, 1.0f, 0, "") } ); ENTRY( "Namco 163", { - CH(DIV_SYSTEM_N163, 64, 0, "") + CH(DIV_SYSTEM_N163, 1.0f, 0, "") } ); ENTRY( "Famicom Disk System (chip)", { - CH(DIV_SYSTEM_FDS, 64, 0, "") + CH(DIV_SYSTEM_FDS, 1.0f, 0, "") } ); ENTRY( "WonderSwan", { - CH(DIV_SYSTEM_SWAN, 64, 0, "") + CH(DIV_SYSTEM_SWAN, 1.0f, 0, "") }, "tickRate=75.47169811320754716981" ); ENTRY( "Virtual Boy", { - CH(DIV_SYSTEM_VBOY, 64, 0, "") + CH(DIV_SYSTEM_VBOY, 1.0f, 0, "") }, "tickRate=50.2734877734878" ); ENTRY( "Seta/Allumer X1-010", { - CH(DIV_SYSTEM_X1_010, 64, 0, "") + CH(DIV_SYSTEM_X1_010, 1.0f, 0, "") } ); CATEGORY_END; @@ -2516,67 +2516,67 @@ void FurnaceGUI::initSystemPresets() { CATEGORY_BEGIN("Specialized","chips/systems with unique sound synthesis methods."); ENTRY( "MOS Technology SID (6581)", { - CH(DIV_SYSTEM_C64_6581, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_C64_6581, 1.0f, 0, "clockSel=1") }, "tickRate=50.1245421" ); ENTRY( "MOS Technology SID (8580)", { - CH(DIV_SYSTEM_C64_8580, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_C64_8580, 1.0f, 0, "clockSel=1") }, "tickRate=50.1245421" ); ENTRY( "Microchip AY8930", { - CH(DIV_SYSTEM_AY8930, 64, 0, "") + CH(DIV_SYSTEM_AY8930, 1.0f, 0, "") } ); ENTRY( "Game Boy", { - CH(DIV_SYSTEM_GB, 64, 0, "") + CH(DIV_SYSTEM_GB, 1.0f, 0, "") } ); ENTRY( "Atari Lynx", { - CH(DIV_SYSTEM_LYNX, 64, 0, "") + CH(DIV_SYSTEM_LYNX, 1.0f, 0, "") } ); ENTRY( "POKEY", { - CH(DIV_SYSTEM_POKEY, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_POKEY, 1.0f, 0, "clockSel=1") }, "tickRate=50" ); ENTRY( "Atari TIA", { - CH(DIV_SYSTEM_TIA, 64, 0, "") + CH(DIV_SYSTEM_TIA, 1.0f, 0, "") } ); ENTRY( "NES (Ricoh 2A03)", { - CH(DIV_SYSTEM_NES, 64, 0, "") + CH(DIV_SYSTEM_NES, 1.0f, 0, "") } ); ENTRY( "Commander X16 (VERA only)", { - CH(DIV_SYSTEM_VERA, 64, 0, "") + CH(DIV_SYSTEM_VERA, 1.0f, 0, "") } ); ENTRY( "ZX Spectrum (beeper only)", { - CH(DIV_SYSTEM_SFX_BEEPER, 64, 0, "") + CH(DIV_SYSTEM_SFX_BEEPER, 1.0f, 0, "") } ); if (settings.hiddenSystems) { ENTRY( "Dummy System", { - CH(DIV_SYSTEM_DUMMY, 64, 0, "") + CH(DIV_SYSTEM_DUMMY, 1.0f, 0, "") } ); } ENTRY( "tildearrow Sound Unit", { - CH(DIV_SYSTEM_SOUND_UNIT, 64, 0, "") + CH(DIV_SYSTEM_SOUND_UNIT, 1.0f, 0, "") } ); CATEGORY_END; @@ -2584,80 +2584,80 @@ void FurnaceGUI::initSystemPresets() { CATEGORY_BEGIN("DefleMask-compatible","these configurations are compatible with DefleMask.\nselect this if you need to save as .dmf or work with that program."); ENTRY( "Sega Genesis", { - CH(DIV_SYSTEM_YM2612, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 32, 0, "") + CH(DIV_SYSTEM_YM2612, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 0.5f, 0, "") } ); ENTRY( "Sega Genesis (extended channel 3)", { - CH(DIV_SYSTEM_YM2612_EXT, 64, 0, ""), - CH(DIV_SYSTEM_SMS, 32, 0, "") + CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, ""), + CH(DIV_SYSTEM_SMS, 0.5f, 0, "") } ); ENTRY( "Sega Master System", { - CH(DIV_SYSTEM_SMS, 64, 0, "") + CH(DIV_SYSTEM_SMS, 1.0f, 0, "") } ); ENTRY( "Sega Master System (with FM expansion)", { - CH(DIV_SYSTEM_SMS, 64, 0, ""), - CH(DIV_SYSTEM_OPLL, 64, 0, "") + CH(DIV_SYSTEM_SMS, 1.0f, 0, ""), + CH(DIV_SYSTEM_OPLL, 1.0f, 0, "") } ); ENTRY( "Game Boy", { - CH(DIV_SYSTEM_GB, 64, 0, "") + CH(DIV_SYSTEM_GB, 1.0f, 0, "") } ); ENTRY( "NEC PC Engine/TurboGrafx-16", { - CH(DIV_SYSTEM_PCE, 64, 0, "") + CH(DIV_SYSTEM_PCE, 1.0f, 0, "") } ); ENTRY( "NES", { - CH(DIV_SYSTEM_NES, 64, 0, "") + CH(DIV_SYSTEM_NES, 1.0f, 0, "") } ); ENTRY( "Famicom with Konami VRC7", { - CH(DIV_SYSTEM_NES, 64, 0, ""), - CH(DIV_SYSTEM_VRC7, 64, 0, "") + CH(DIV_SYSTEM_NES, 1.0f, 0, ""), + CH(DIV_SYSTEM_VRC7, 1.0f, 0, "") } ); ENTRY( "Famicom Disk System", { - CH(DIV_SYSTEM_NES, 64, 0, ""), - CH(DIV_SYSTEM_FDS, 64, 0, "") + CH(DIV_SYSTEM_NES, 1.0f, 0, ""), + CH(DIV_SYSTEM_FDS, 1.0f, 0, "") } ); ENTRY( "Commodore 64 (6581 SID)", { - CH(DIV_SYSTEM_C64_6581, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_C64_6581, 1.0f, 0, "clockSel=1") }, "tickRate=50.1245421" ); ENTRY( "Commodore 64 (8580 SID)", { - CH(DIV_SYSTEM_C64_8580, 64, 0, "clockSel=1") + CH(DIV_SYSTEM_C64_8580, 1.0f, 0, "clockSel=1") }, "tickRate=50.1245421" ); ENTRY( "Arcade (YM2151 and SegaPCM)", { - CH(DIV_SYSTEM_YM2151, 64, 0, ""), - CH(DIV_SYSTEM_SEGAPCM_COMPAT, 64, 0, "") + CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), + CH(DIV_SYSTEM_SEGAPCM_COMPAT, 1.0f, 0, "") } ); ENTRY( "Neo Geo CD", { - CH(DIV_SYSTEM_YM2610, 64, 0, "") + CH(DIV_SYSTEM_YM2610, 1.0f, 0, "") } ); ENTRY( "Neo Geo CD (extended channel 2)", { - CH(DIV_SYSTEM_YM2610_EXT, 64, 0, "") + CH(DIV_SYSTEM_YM2610_EXT, 1.0f, 0, "") } ); CATEGORY_END; @@ -2670,7 +2670,7 @@ FurnaceGUISysDef::FurnaceGUISysDef(const char* n, std::initializer_listsong.systemLen; i++) { settings.initialSys.set(fmt::sprintf("id%d",i),e->systemToFileFur(e->song.system[i])); - settings.initialSys.set(fmt::sprintf("vol%d",i),(int)e->song.systemVol[i]); - settings.initialSys.set(fmt::sprintf("pan%d",i),(int)e->song.systemPan[i]); + settings.initialSys.set(fmt::sprintf("vol%d",i),(float)e->song.systemVol[i]); + settings.initialSys.set(fmt::sprintf("pan%d",i),(float)e->song.systemPan[i]); + settings.initialSys.set(fmt::sprintf("fr%d",i),(float)e->song.systemPanFR[i]); settings.initialSys.set(fmt::sprintf("flags%d",i),e->song.systemFlags[i].toBase64()); } settings.initialSysName=e->song.systemName; @@ -303,14 +325,16 @@ void FurnaceGUI::drawSettings() { if (totalAvailSys>0) { for (int i=0; isystemToFileFur((DivSystem)availableSystems[rand()%totalAvailSys])); - settings.initialSys.set(fmt::sprintf("vol%d",i),64); - settings.initialSys.set(fmt::sprintf("pan%d",i),0); + settings.initialSys.set(fmt::sprintf("vol%d",i),1.0f); + settings.initialSys.set(fmt::sprintf("pan%d",i),0.0f); + settings.initialSys.set(fmt::sprintf("fr%d",i),0.0f); settings.initialSys.set(fmt::sprintf("flags%d",i),""); } } else { settings.initialSys.set("id0",e->systemToFileFur(DIV_SYSTEM_DUMMY)); - settings.initialSys.set("vol0",64); - settings.initialSys.set("pan0",0); + settings.initialSys.set("vol0",1.0f); + settings.initialSys.set("pan0",0.0f); + settings.initialSys.set("fr0",0.0f); settings.initialSys.set("flags0",""); howMany=1; } @@ -345,12 +369,14 @@ void FurnaceGUI::drawSettings() { if (ImGui::Button("Reset to defaults")) { settings.initialSys.clear(); settings.initialSys.set("id0",e->systemToFileFur(DIV_SYSTEM_YM2612)); - settings.initialSys.set("vol0",64); - settings.initialSys.set("pan0",0); + settings.initialSys.set("vol0",1.0f); + settings.initialSys.set("pan0",0.0f); + settings.initialSys.set("fr0",0.0f); settings.initialSys.set("flags0",""); settings.initialSys.set("id1",e->systemToFileFur(DIV_SYSTEM_SMS)); - settings.initialSys.set("vol1",32); - settings.initialSys.set("pan1",0); + settings.initialSys.set("vol1",0.5f); + settings.initialSys.set("pan1",0.0f); + settings.initialSys.set("fr1",0.0f); settings.initialSys.set("flags1",""); settings.initialSysName="Sega Genesis/Mega Drive"; } @@ -364,14 +390,15 @@ void FurnaceGUI::drawSettings() { int doRemove=-1; for (size_t i=0; settings.initialSys.getInt(fmt::sprintf("id%d",i),0); i++) { DivSystem sysID=e->systemFromFileFur(settings.initialSys.getInt(fmt::sprintf("id%d",i),0)); - signed char sysVol=settings.initialSys.getInt(fmt::sprintf("vol%d",i),0); - signed char sysPan=settings.initialSys.getInt(fmt::sprintf("pan%d",i),0); + float sysVol=settings.initialSys.getFloat(fmt::sprintf("vol%d",i),0); + float sysPan=settings.initialSys.getFloat(fmt::sprintf("pan%d",i),0); + float sysPanFR=settings.initialSys.getFloat(fmt::sprintf("fr%d",i),0); sysCount=i+1; //bool doRemove=false; - bool doInvert=sysVol&128; - signed char vol=sysVol&127; + bool doInvert=(sysVol<0); + float vol=fabs(sysVol); ImGui::PushID(i); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-ImGui::CalcTextSize("Invert").x-ImGui::GetFrameHeightWithSpacing()*2.0-ImGui::GetStyle().ItemSpacing.x); @@ -388,8 +415,8 @@ void FurnaceGUI::drawSettings() { ImGui::SameLine(); if (ImGui::Checkbox("Invert",&doInvert)) { - sysVol^=128; - settings.initialSys.set(fmt::sprintf("vol%d",i),(int)sysVol); + sysVol=-sysVol; + settings.initialSys.set(fmt::sprintf("vol%d",i),sysVol); } ImGui::SameLine(); //ImGui::BeginDisabled(settings.initialSys.size()<=4); @@ -397,14 +424,27 @@ void FurnaceGUI::drawSettings() { doRemove=i; } //ImGui::EndDisabled(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-(50.0f*dpiScale)); - if (CWSliderScalar("Volume",ImGuiDataType_S8,&vol,&_ZERO,&_ONE_HUNDRED_TWENTY_SEVEN)) { - sysVol=(sysVol&128)|vol; - settings.initialSys.set(fmt::sprintf("vol%d",i),(int)sysVol); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderFloat("Volume",&vol,0.0f,3.0f)) { + if (doInvert) { + if (vol<0.0001) vol=0.0001; + } + if (vol<0) vol=0; + if (vol>10) vol=10; + sysVol=doInvert?-vol:vol; + settings.initialSys.set(fmt::sprintf("vol%d",i),(float)sysVol); } rightClickable - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-(50.0f*dpiScale)); - if (CWSliderScalar("Panning",ImGuiDataType_S8,&sysPan,&_MINUS_ONE_HUNDRED_TWENTY_SEVEN,&_ONE_HUNDRED_TWENTY_SEVEN)) { - settings.initialSys.set(fmt::sprintf("pan%d",i),(int)sysPan); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderFloat("Panning",&sysPan,-1.0f,1.0f)) { + if (sysPan<-1.0f) sysPan=-1.0f; + if (sysPan>1.0f) sysPan=1.0f; + settings.initialSys.set(fmt::sprintf("pan%d",i),(float)sysPan); + } rightClickable + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderFloat("Front/Rear",&sysPanFR,-1.0f,1.0f)) { + if (sysPanFR<-1.0f) sysPanFR=-1.0f; + if (sysPanFR>1.0f) sysPanFR=1.0f; + settings.initialSys.set(fmt::sprintf("fr%d",i),(float)sysPanFR); } rightClickable // oh please MSVC don't cry @@ -424,25 +464,29 @@ void FurnaceGUI::drawSettings() { if (doRemove>=0 && sysCount>1) { for (int i=doRemove; isystemToFileFur(DIV_SYSTEM_YM2612)); - settings.initialSys.set(fmt::sprintf("vol%d",sysCount),64); - settings.initialSys.set(fmt::sprintf("pan%d",sysCount),0); + settings.initialSys.set(fmt::sprintf("vol%d",sysCount),1.0f); + settings.initialSys.set(fmt::sprintf("pan%d",sysCount),0.0f); + settings.initialSys.set(fmt::sprintf("fr%d",sysCount),0.0f); settings.initialSys.set(fmt::sprintf("flags%d",sysCount),""); } @@ -676,9 +720,16 @@ void FurnaceGUI::drawSettings() { ImVec2 settingsViewSize=ImGui::GetContentRegionAvail(); settingsViewSize.y-=ImGui::GetFrameHeight()+ImGui::GetStyle().WindowPadding.y; if (ImGui::BeginChild("SettingsView",settingsViewSize)) { +#ifdef HAVE_JACK ImGui::Text("Backend"); ImGui::SameLine(); - ImGui::Combo("##Backend",&settings.audioEngine,audioBackends,2); + int prevAudioEngine=settings.audioEngine; + if (ImGui::Combo("##Backend",&settings.audioEngine,audioBackends,2)) { + if (settings.audioEngine!=prevAudioEngine) { + if (!isProAudio[settings.audioEngine]) settings.audioChans=2; + } + } +#endif ImGui::Text("Device"); ImGui::SameLine(); @@ -711,6 +762,27 @@ void FurnaceGUI::drawSettings() { ImGui::EndCombo(); } + if (isProAudio[settings.audioEngine]) { + ImGui::Text("Outputs"); + ImGui::SameLine(); + if (ImGui::InputInt("##AudioChansI",&settings.audioChans,1,1)) { + if (settings.audioChans<1) settings.audioChans=1; + if (settings.audioChans>16) settings.audioChans=16; + } + } else { + ImGui::Text("Channels"); + ImGui::SameLine(); + String chStr=(settings.audioChans<1 || settings.audioChans>8)?"What?":nonProAudioOuts[settings.audioChans-1]; + if (ImGui::BeginCombo("##AudioChans",chStr.c_str())) { + CHANS_SELECTABLE(1); + CHANS_SELECTABLE(2); + CHANS_SELECTABLE(4); + CHANS_SELECTABLE(6); + CHANS_SELECTABLE(8); + ImGui::EndCombo(); + } + } + ImGui::Text("Buffer size"); ImGui::SameLine(); String bs=fmt::sprintf("%d (latency: ~%.1fms)",settings.audioBufSize,2000.0*(double)settings.audioBufSize/(double)MAX(1,settings.audioRate)); @@ -757,8 +829,8 @@ void FurnaceGUI::drawSettings() { TAAudioDesc& audioWant=e->getAudioDescWant(); TAAudioDesc& audioGot=e->getAudioDescGot(); - ImGui::Text("want: %d samples @ %.0fHz",audioWant.bufsize,audioWant.rate); - ImGui::Text("got: %d samples @ %.0fHz",audioGot.bufsize,audioGot.rate); + ImGui::Text("want: %d samples @ %.0fHz (%d channels)",audioWant.bufsize,audioWant.rate,audioWant.outChans); + ImGui::Text("got: %d samples @ %.0fHz (%d channels)",audioGot.bufsize,audioGot.rate,audioWant.outChans); ImGui::Separator(); @@ -1900,6 +1972,22 @@ void FurnaceGUI::drawSettings() { UI_COLOR_CONFIG(GUI_COLOR_PIANO_KEY_BOTTOM_ACTIVE,"Lower key (pressed)"); ImGui::TreePop(); } + if (ImGui::TreeNode("Clock")) { + UI_COLOR_CONFIG(GUI_COLOR_CLOCK_TEXT,"Clock text"); + UI_COLOR_CONFIG(GUI_COLOR_CLOCK_BEAT_LOW,"Beat (off)"); + UI_COLOR_CONFIG(GUI_COLOR_CLOCK_BEAT_HIGH,"Beat (on)"); + + ImGui::TreePop(); + } + if (ImGui::TreeNode("Patchbay")) { + UI_COLOR_CONFIG(GUI_COLOR_PATCHBAY_PORTSET,"PortSet"); + UI_COLOR_CONFIG(GUI_COLOR_PATCHBAY_PORT,"Port"); + UI_COLOR_CONFIG(GUI_COLOR_PATCHBAY_PORT_HIDDEN,"Port (hidden/unavailable)"); + UI_COLOR_CONFIG(GUI_COLOR_PATCHBAY_CONNECTION,"Connection (selected)"); + UI_COLOR_CONFIG(GUI_COLOR_PATCHBAY_CONNECTION_BG,"Connection (other)"); + + ImGui::TreePop(); + } if (ImGui::TreeNode("Log Viewer")) { UI_COLOR_CONFIG(GUI_COLOR_LOGLEVEL_ERROR,"Log level: Error"); UI_COLOR_CONFIG(GUI_COLOR_LOGLEVEL_WARNING,"Log level: Warning"); @@ -2343,6 +2431,7 @@ void FurnaceGUI::syncSettings() { settings.iconSize=e->getConfInt("iconSize",16); settings.audioEngine=(e->getConfString("audioEngine","SDL")=="SDL")?1:0; settings.audioDevice=e->getConfString("audioDevice",""); + settings.audioChans=e->getConfInt("audioChans",2); settings.midiInDevice=e->getConfString("midiInDevice",""); settings.midiOutDevice=e->getConfString("midiOutDevice",""); settings.c163Name=e->getConfString("c163Name",DIV_C163_DEFAULT_NAME); @@ -2476,6 +2565,7 @@ void FurnaceGUI::syncSettings() { clampSetting(settings.audioQuality,0,1); clampSetting(settings.audioBufSize,32,4096); clampSetting(settings.audioRate,8000,384000); + clampSetting(settings.audioChans,1,16); clampSetting(settings.arcadeCore,0,1); clampSetting(settings.ym2612Core,0,1); clampSetting(settings.snCore,0,1); @@ -2582,21 +2672,37 @@ void FurnaceGUI::syncSettings() { if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0; String initialSys2=e->getConfString("initialSys2",""); + bool oldVol=e->getConfInt("configVersion",DIV_ENGINE_VERSION)<135; if (initialSys2.empty()) { initialSys2=e->decodeSysDesc(e->getConfString("initialSys","")); + oldVol=false; } settings.initialSys.clear(); settings.initialSys.loadFromBase64(initialSys2.c_str()); if (settings.initialSys.getInt("id0",0)==0) { settings.initialSys.clear(); settings.initialSys.set("id0",e->systemToFileFur(DIV_SYSTEM_YM2612)); - settings.initialSys.set("vol0",64); - settings.initialSys.set("pan0",0); + settings.initialSys.set("vol0",1.0f); + settings.initialSys.set("pan0",0.0f); + settings.initialSys.set("fr0",0.0f); settings.initialSys.set("flags0",""); settings.initialSys.set("id1",e->systemToFileFur(DIV_SYSTEM_SMS)); - settings.initialSys.set("vol1",64); + settings.initialSys.set("vol1",0.5f); settings.initialSys.set("pan1",0); + settings.initialSys.set("fr1",0); settings.initialSys.set("flags1",""); + } else { + if (oldVol) { + for (int i=0; settings.initialSys.getInt(fmt::sprintf("id%d",i),0); i++) { + float newVol=settings.initialSys.getInt(fmt::sprintf("vol%d",i),64); + float newPan=settings.initialSys.getInt(fmt::sprintf("pan%d",i),0); + newVol/=64.0f; + newPan/=127.0f; + settings.initialSys.set(fmt::sprintf("vol%d",i),newVol); + settings.initialSys.set(fmt::sprintf("pan%d",i),newPan); + } + e->setConf("initialSys2",settings.initialSys.toBase64()); + } } // keybinds @@ -2643,6 +2749,7 @@ void FurnaceGUI::commitSettings() { e->setConf("audioQuality",settings.audioQuality); e->setConf("audioBufSize",settings.audioBufSize); e->setConf("audioRate",settings.audioRate); + e->setConf("audioChans",settings.audioChans); e->setConf("arcadeCore",settings.arcadeCore); e->setConf("ym2612Core",settings.ym2612Core); e->setConf("snCore",settings.snCore); diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index ff60b3136..4612d90eb 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -1183,6 +1183,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo case DIV_SYSTEM_OPL3_DRUMS: { int clockSel=flags.getInt("clockSel",0); int chipType=flags.getInt("chipType",0); + bool compatPan=flags.getBool("compatPan",false); ImGui::Text("Clock rate:"); if (ImGui::RadioButton("14.32MHz (NTSC)",clockSel==0)) { @@ -1219,10 +1220,15 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo altered=true; } + if (ImGui::Checkbox("Compatible panning (0800)",&compatPan)) { + altered=true; + } + if (altered) { e->lockSave([&]() { flags.set("clockSel",clockSel); flags.set("chipType",chipType); + flags.set("compatPan",compatPan); }); } break; diff --git a/src/gui/volMeter.cpp b/src/gui/volMeter.cpp index d058e31f7..f050341dd 100644 --- a/src/gui/volMeter.cpp +++ b/src/gui/volMeter.cpp @@ -51,7 +51,8 @@ void FurnaceGUI::drawVolMeter() { ImU32 lowColor=ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_LOW]); if (ImGui::ItemAdd(rect,ImGui::GetID("volMeter"))) { ImGui::RenderFrame(rect.Min,rect.Max,ImGui::GetColorU32(ImGuiCol_FrameBg),true,style.FrameRounding); - for (int i=0; i<2; i++) { + int outChans=e->getAudioDescGot().outChans; + for (int i=0; iAddRectFilled(s.Min,s.Max,ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_PEAK])); } else { @@ -77,10 +78,10 @@ void FurnaceGUI::drawVolMeter() { } } else { s=ImRect( - ImLerp(rect.Min,rect.Max,ImVec2(float(i)*0.5,1.0-logPeak)), - ImLerp(rect.Min,rect.Max,ImVec2(float(i+1)*0.5,1.0)) + ImLerp(rect.Min,rect.Max,ImVec2(float(i)/outChans,1.0-logPeak)), + ImLerp(rect.Min,rect.Max,ImVec2(float(i+1)/outChans,1.0)) ); - if (i==0) s.Max.x-=dpiScale; + if (i!=(outChans-1)) s.Max.x-=dpiScale; if (isClipping) { dl->AddRectFilled(s.Min,s.Max,ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_PEAK])); } else { diff --git a/src/log.cpp b/src/log.cpp index 1611e688f..8fec13189 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -29,13 +29,14 @@ int logLevel=LOGLEVEL_INFO; FILE* logFile; char* logFileBuf; +char* logFileWriteBuf; unsigned int logFilePosI; unsigned int logFilePosO; std::thread* logFileThread; std::mutex logFileLock; std::mutex logFileLockI; std::condition_variable logFileNotify; -bool logFileAvail=false; +std::atomic logFileAvail(false); std::atomic logPosition; @@ -157,8 +158,8 @@ void _logFileThread() { } } else { // wait - if (!logFileAvail) break; fflush(logFile); + if (!logFileAvail) break; logFileNotify.wait(lock); } } @@ -177,6 +178,7 @@ bool startLogFile(const char* path) { } logFileBuf=new char[TA_LOGFILE_BUF_SIZE]; + logFileWriteBuf=new char[TA_LOGFILE_BUF_SIZE]; logFilePosI=0; logFilePosO=0; logFileAvail=true; diff --git a/src/winMain.cpp b/src/winMain.cpp index c904b996a..853b11530 100644 --- a/src/winMain.cpp +++ b/src/winMain.cpp @@ -22,10 +22,6 @@ typedef HRESULT (*SPDA)(int); int WINAPI WinMain(HINSTANCE inst, HINSTANCE prevInst, PSTR args, int state) { - if (AttachConsole(ATTACH_PARENT_PROCESS)==0) { - if (GetLastError()==ERROR_ACCESS_DENIED) FreeConsole(); - } - int argc=0; wchar_t** argw=CommandLineToArgvW(GetCommandLineW(),&argc); char** argv=new char*[argc+1];