Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt

This commit is contained in:
cam900 2023-02-05 10:00:27 +09:00
commit dd79ae401b
52 changed files with 578 additions and 329 deletions

View file

@ -44,7 +44,7 @@ void DivPlatformBubSysWSG::acquire(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
signed int out=0;
// K005289 part
k005289.tick();
k005289.tick(8);
// Wavetable part
for (int i=0; i<2; i++) {
@ -60,7 +60,7 @@ void DivPlatformBubSysWSG::acquire(short** buf, size_t len) {
}
}
if (++writeOscBuf>=64) writeOscBuf=0;
if (++writeOscBuf>=8) writeOscBuf=0;
out<<=6; // scale output to 16 bit
@ -332,9 +332,9 @@ void DivPlatformBubSysWSG::notifyInsDeletion(void* ins) {
void DivPlatformBubSysWSG::setFlags(const DivConfig& flags) {
chipClock=COLOR_NTSC;
CHECK_CUSTOM_CLOCK;
rate=chipClock;
rate=chipClock/8;
for (int i=0; i<2; i++) {
oscBuf[i]->rate=rate/64;
oscBuf[i]->rate=rate/8;
}
}

View file

@ -41,8 +41,14 @@ class DivPlatformOPM: public DivPlatformFMBase {
0x00, 0x08, 0x10, 0x18
};
unsigned char lfoValue, lfoValue2, lfoShape, lfoShape2;
DivPlatformOPM():
DivPlatformFMBase() {}
DivPlatformFMBase(),
lfoValue(0),
lfoValue2(0),
lfoShape(0),
lfoShape2(0) {}
};
#endif

View file

@ -225,6 +225,9 @@ void DivPlatformGenesis::acquire_ymfm(short** buf, size_t len) {
//OPN2_Write(&fm,0,0);
for (int i=0; i<6; i++) {
int chOut=(fme->debug_channel(i)->debug_output(0)+fme->debug_channel(i)->debug_output(1))<<6;
if (chOut<-32768) chOut=-32768;
if (chOut>32767) chOut=32767;
if (i==5) {
if (fm_ymfm->debug_dac_enable()) {
if (softPCM) {
@ -234,10 +237,10 @@ void DivPlatformGenesis::acquire_ymfm(short** buf, size_t len) {
oscBuf[i]->data[oscBuf[i]->needle++]=fm_ymfm->debug_dac_data()<<7;
}
} else {
oscBuf[i]->data[oscBuf[i]->needle++]=(fme->debug_channel(i)->debug_output(0)+fme->debug_channel(i)->debug_output(1))<<6;
oscBuf[i]->data[oscBuf[i]->needle++]=chOut;
}
} else {
oscBuf[i]->data[oscBuf[i]->needle++]=(fme->debug_channel(i)->debug_output(0)+fme->debug_channel(i)->debug_output(1))<<6;
oscBuf[i]->data[oscBuf[i]->needle++]=chOut;
}
}

View file

@ -651,10 +651,10 @@ void DivPlatformGenesisExt::forceIns() {
unsigned short baseAddr=chanOffs[i]|opOffs[j];
DivInstrumentFM::Operator& op=chan[i].state.op[j];
if (i==2 && extMode) { // extended channel
if (isOpMuted[j]) {
if (isOpMuted[orderedOps[j]]) {
rWrite(baseAddr+0x40,127);
} else if (KVS(i,j)) {
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[j].outVol&0x7f,127));
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[orderedOps[j]].outVol&0x7f,127));
} else {
rWrite(baseAddr+0x40,op.tl);
}

View file

@ -1555,7 +1555,11 @@ DivMacroInt* DivPlatformOPL::getChanMacroInt(int ch) {
}
DivDispatchOscBuffer* DivPlatformOPL::getOscBuffer(int ch) {
if (ch>=totalChans) return NULL;
if (oplType==759) {
if (ch>=totalChans+1) return NULL;
} else {
if (ch>=totalChans) return NULL;
}
if (oplType==3 && ch<12) {
if (chan[ch&(~1)].fourOp) {
if (ch&1) {

View file

@ -82,9 +82,7 @@ const char** DivPlatformSCC::getRegisterSheet() {
void DivPlatformSCC::acquire(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
for (int i=0; i<16; i++) {
scc->tick();
}
scc->tick(16);
short out=(short)scc->out()<<5;
buf[0][h]=out;

View file

@ -22,7 +22,7 @@
#include "../../ta-log.h"
#include <math.h>
#define rWrite(a,v) {if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(0x200+a,v);}}}
#define rWrite(a,v) {if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);}}}
const char* regCheatSheetSN[]={
"DATA", "0",

View file

@ -811,7 +811,7 @@ const void* DivPlatformSNES::getSampleMem(int index) {
size_t DivPlatformSNES::getSampleMemCapacity(int index) {
// TODO change it based on current echo buffer size
return index == 0 ? 65536 : 0;
return index == 0 ? (65536-echoDelay*2048) : 0;
}
size_t DivPlatformSNES::getSampleMemUsage(int index) {
@ -825,7 +825,7 @@ bool DivPlatformSNES::isSampleLoaded(int index, int sample) {
}
void DivPlatformSNES::renderSamples(int sysID) {
memset(copyOfSampleMem,0,getSampleMemCapacity());
memset(copyOfSampleMem,0,65536);
memset(sampleOff,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*sizeof(bool));

View file

@ -1,3 +1,25 @@
/* su.cpp/su.h - Sound Unit emulator
* Copyright (C) 2015-2023 tildearrow
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define _USE_MATH_DEFINES
#include "su.h"
#include <string.h>
@ -391,7 +413,7 @@ void SoundUnit::Reset() {
#ifdef TA_BIG_ENDIAN
const unsigned char suBERemap[32]={
0x01, 0x00, 0x02, 0x03, 0x05, 0x04, 0x07, 0x06, 0x08, 0x09, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e,
0x01, 0x00, 0x02, 0x03, 0x04, 0x05, 0x07, 0x06, 0x08, 0x09, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e,
0x11, 0x10, 0x12, 0x13, 0x15, 0x14, 0x16, 0x17, 0x19, 0x18, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f, 0x1e
};
#endif

View file

@ -1,7 +1,27 @@
/* su.cpp/su.h - Sound Unit emulator
* Copyright (C) 2015-2023 tildearrow
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
class SoundUnit {
signed char SCsine[256];

View file

@ -497,6 +497,9 @@ void DivPlatformSoundUnit::reset() {
rWrite(0x9d,ilCtrl);
rWrite(0xbc,ilSize);
rWrite(0xbd,fil1);
// copy sample memory
memcpy(su->pcm,sampleMem,sampleMemSize?65536:8192);
}
int DivPlatformSoundUnit::getOutputCount() {
@ -545,7 +548,7 @@ void DivPlatformSoundUnit::poke(std::vector<DivRegWrite>& wlist) {
}
const void* DivPlatformSoundUnit::getSampleMem(int index) {
return (index==0)?su->pcm:NULL;
return (index==0)?sampleMem:NULL;
}
size_t DivPlatformSoundUnit::getSampleMemCapacity(int index) {
@ -563,7 +566,7 @@ bool DivPlatformSoundUnit::isSampleLoaded(int index, int sample) {
}
void DivPlatformSoundUnit::renderSamples(int sysID) {
memset(su->pcm,0,getSampleMemCapacity(0));
memset(sampleMem,0,sampleMemSize?65536:8192);
memset(sampleOffSU,0,256*sizeof(unsigned int));
memset(sampleLoaded,0,256*sizeof(bool));
@ -582,10 +585,10 @@ void DivPlatformSoundUnit::renderSamples(int sysID) {
break;
}
if (memPos+paddedLen>=getSampleMemCapacity(0)) {
memcpy(su->pcm+memPos,s->data8,getSampleMemCapacity(0)-memPos);
memcpy(sampleMem+memPos,s->data8,getSampleMemCapacity(0)-memPos);
logW("out of PCM memory for sample %d!",i);
} else {
memcpy(su->pcm+memPos,s->data8,paddedLen);
memcpy(sampleMem+memPos,s->data8,paddedLen);
sampleLoaded[i]=true;
}
sampleOffSU[i]=memPos;
@ -593,6 +596,8 @@ void DivPlatformSoundUnit::renderSamples(int sysID) {
}
sampleMemLen=memPos;
sysIDCache=sysID;
memcpy(su->pcm,sampleMem,sampleMemSize?65536:8192);
}
int DivPlatformSoundUnit::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
@ -604,6 +609,8 @@ int DivPlatformSoundUnit::init(DivEngine* p, int channels, int sugRate, const Di
oscBuf[i]=new DivDispatchOscBuffer;
}
su=new SoundUnit();
sampleMem=new unsigned char[65536];
memset(sampleMem,0,65536);
sysIDCache=0;
setFlags(flags);
reset();
@ -615,6 +622,7 @@ void DivPlatformSoundUnit::quit() {
delete oscBuf[i];
}
delete su;
delete sampleMem;
}
DivPlatformSoundUnit::~DivPlatformSoundUnit() {

View file

@ -89,6 +89,7 @@ class DivPlatformSoundUnit: public DivDispatch {
short tempR;
unsigned char sampleBank, lfoMode, lfoSpeed;
SoundUnit* su;
unsigned char* sampleMem;
size_t sampleMemLen;
unsigned char regPool[128];
double NOTE_SU(int ch, int note);

View file

@ -138,14 +138,14 @@ void DivPlatformTIA::tick(bool sysTick) {
bf+=chan[i].arpOff;
}
}
chan[i].freq=dealWithFreq(chan[i].shape,bf,chan[i].pitch)+chan[i].pitch2;
chan[i].freq=dealWithFreq(chan[i].shape,bf,chan[i].pitch+chan[i].pitch2);
if ((chan[i].shape==4 || chan[i].shape==5) && !(chan[i].baseFreq&0x80000000 && ((chan[i].baseFreq&0x7fffffff)<32))) {
if (bf<39*256) {
rWrite(0x15+i,6);
chan[i].freq=dealWithFreq(6,bf,chan[i].pitch)+chan[i].pitch2;
chan[i].freq=dealWithFreq(6,bf,chan[i].pitch+chan[i].pitch2);
} else if (bf<59*256) {
rWrite(0x15+i,12);
chan[i].freq=dealWithFreq(12,bf,chan[i].pitch)+chan[i].pitch2;
chan[i].freq=dealWithFreq(12,bf,chan[i].pitch+chan[i].pitch2);
} else {
rWrite(0x15+i,chan[i].shape);
}

View file

@ -26,6 +26,8 @@
#define ADDR_WS_FINE 0x100
// actually 0xc0 but bit 5 of data selects address
#define ADDR_EGS_REV 0x120
// actually 0x38 but bits 7 and 2 select address
#define ADDR_FMS2_AMS2 0x140
const char* regCheatSheetOPZ[]={
"Test", "00",
@ -139,7 +141,8 @@ void DivPlatformTX81Z::tick(bool sysTick) {
}
if (chan[i].std.wave.had) {
rWrite(0x1b,chan[i].std.wave.val&3);
lfoShape=chan[i].std.wave.val&3;
immWrite(0x1b,lfoShape|(lfoShape2<<2));
}
if (chan[i].std.pitch.had) {
@ -177,7 +180,28 @@ void DivPlatformTX81Z::tick(bool sysTick) {
}
if (chan[i].std.ex3.had) {
immWrite(0x18,chan[i].std.ex3.val);
lfoValue=chan[i].std.ex3.val;
immWrite(0x18,lfoValue);
}
if (chan[i].std.ex5.had) {
amDepth2=chan[i].std.ex5.val;
immWrite(0x17,amDepth2);
}
if (chan[i].std.ex6.had) {
pmDepth2=chan[i].std.ex6.val;
immWrite(0x17,0x80|pmDepth2);
}
if (chan[i].std.ex7.had) {
lfoValue2=chan[i].std.ex7.val;
immWrite(0x16,lfoValue2);
}
if (chan[i].std.ex8.had) {
lfoShape2=chan[i].std.ex8.val&3;
immWrite(0x1b,lfoShape|(lfoShape2<<2));
}
if (chan[i].std.alg.had) {
@ -286,6 +310,12 @@ void DivPlatformTX81Z::tick(bool sysTick) {
oldWrites[i]=pendingWrites[i];
}
}
for (int i=320; i<328; i++) {
if (pendingWrites[i]!=oldWrites[i]) {
immWrite(0x38+(i&7),(0x84|pendingWrites[i]));
oldWrites[i]=pendingWrites[i];
}
}
int hardResetElapsed=0;
bool mustHardReset=false;
@ -405,7 +435,7 @@ void DivPlatformTX81Z::commitState(int ch, DivInstrument* ins) {
rWrite(chanOffs[ch]+ADDR_LR_FB_ALG,(chan[ch].state.alg&7)|(chan[ch].state.fb<<3)|((chan[ch].chVolL&1)<<6)|((chan[ch].chVolR&1)<<7));
}*/
rWrite(chanOffs[ch]+ADDR_FMS_AMS,((chan[ch].state.fms&7)<<4)|(chan[ch].state.ams&3));
//rWrite(chanOffs[ch]+ADDR_FMS_AMS,0x84|((chan[ch].state.fms2&7)<<4)|(chan[ch].state.ams2&3));
rWrite(chanOffs[ch]+ADDR_FMS2_AMS2,((chan[ch].state.fms2&7)<<4)|(chan[ch].state.ams2&3));
}
}
@ -528,11 +558,23 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
break;
}
case DIV_CMD_FM_LFO: {
rWrite(0x18,c.value);
lfoValue=c.value;
immWrite(0x18,lfoValue);
break;
}
case DIV_CMD_FM_LFO_WAVE: {
rWrite(0x1b,c.value&3);
lfoShape=c.value&3;
immWrite(0x1b,lfoShape|(lfoShape2<<2));
break;
}
case DIV_CMD_FM_LFO2: {
lfoValue2=c.value;
immWrite(0x16,lfoValue2);
break;
}
case DIV_CMD_FM_LFO2_WAVE: {
lfoShape2=c.value&3;
immWrite(0x1b,lfoShape|(lfoShape2<<2));
break;
}
case DIV_CMD_FM_FB: {
@ -810,6 +852,16 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
immWrite(0x19,0x80|pmDepth);
break;
}
case DIV_CMD_FM_AM2_DEPTH: {
amDepth2=c.value;
immWrite(0x17,amDepth);
break;
}
case DIV_CMD_FM_PM2_DEPTH: {
pmDepth2=c.value;
immWrite(0x17,0x80|pmDepth);
break;
}
case DIV_CMD_FM_HARD_RESET:
chan[c.chan].hardReset=c.value;
break;
@ -880,7 +932,7 @@ void DivPlatformTX81Z::forceIns() {
rWrite(chanOffs[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)|((chan[i].chVolL&1)<<6)|((chan[i].chVolR&1)<<7));
}*/
rWrite(chanOffs[i]+ADDR_FMS_AMS,((chan[i].state.fms&7)<<4)|(chan[i].state.ams&3));
//rWrite(chanOffs[i]+ADDR_FMS_AMS,0x84|((chan[i].state.fms2&7)<<4)|(chan[i].state.ams2&3));
rWrite(chanOffs[i]+ADDR_FMS2_AMS2,((chan[i].state.fms2&7)<<4)|(chan[i].state.ams2&3));
if (chan[i].active) {
chan[i].keyOn=true;
chan[i].freqChanged=true;
@ -888,6 +940,11 @@ void DivPlatformTX81Z::forceIns() {
}
immWrite(0x19,amDepth);
immWrite(0x19,0x80|pmDepth);
immWrite(0x17,amDepth2);
immWrite(0x17,0x80|pmDepth2);
immWrite(0x18,lfoValue);
immWrite(0x16,lfoValue2);
immWrite(0x1b,lfoShape|(lfoShape2<<2));
}
void DivPlatformTX81Z::notifyInsChange(int ins) {
@ -958,12 +1015,19 @@ void DivPlatformTX81Z::reset() {
delay=0;
amDepth=0x7f;
pmDepth=0x7f;
amDepth2=0x7f;
pmDepth2=0x7f;
lfoValue=0;
lfoValue2=0;
lfoShape=0;
lfoShape2=0;
//rWrite(0x18,0x10);
immWrite(0x18,0x00); // LFO Freq Off
immWrite(0x16,0x00);
immWrite(0x19,amDepth);
immWrite(0x19,0x80|pmDepth);
//rWrite(0x1b,0x00);
immWrite(0x17,amDepth2);
immWrite(0x17,0x80|pmDepth2);
extMode=false;
}

View file

@ -45,7 +45,7 @@ class DivPlatformTX81Z: public DivPlatformOPM {
DivDispatchOscBuffer* oscBuf[8];
int baseFreqOff;
int pcmL, pcmR, pcmCycles;
unsigned char amDepth, pmDepth;
unsigned char amDepth, pmDepth, amDepth2, pmDepth2;
ymfm::ym2414* fm_ymfm;
ymfm::ym2414::output_data out_ymfm;

View file

@ -558,10 +558,10 @@ void DivPlatformYM2203Ext::forceIns() {
unsigned short baseAddr=chanOffs[i]|opOffs[j];
DivInstrumentFM::Operator& op=chan[i].state.op[j];
if (i==2 && extMode) { // extended channel
if (isOpMuted[j]) {
if (isOpMuted[orderedOps[j]]) {
rWrite(baseAddr+0x40,127);
} else if (KVS(i,j)) {
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[j].outVol&0x7f,127));
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[orderedOps[j]].outVol&0x7f,127));
} else {
rWrite(baseAddr+0x40,op.tl);
}

View file

@ -582,10 +582,10 @@ void DivPlatformYM2608Ext::forceIns() {
unsigned short baseAddr=chanOffs[i]|opOffs[j];
DivInstrumentFM::Operator& op=chan[i].state.op[j];
if (i==2 && extMode) { // extended channel
if (isOpMuted[j]) {
if (isOpMuted[orderedOps[j]]) {
rWrite(baseAddr+0x40,127);
} else if (KVS(i,j)) {
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[j].outVol&0x7f,127));
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[orderedOps[j]].outVol&0x7f,127));
} else {
rWrite(baseAddr+0x40,op.tl);
}

View file

@ -578,10 +578,10 @@ void DivPlatformYM2610BExt::forceIns() {
unsigned short baseAddr=chanOffs[i]|opOffs[j];
DivInstrumentFM::Operator& op=chan[i].state.op[j];
if (i==extChanOffs && extMode) { // extended channel
if (isOpMuted[j]) {
if (isOpMuted[orderedOps[j]]) {
rWrite(baseAddr+0x40,127);
} else if (KVS(i,j)) {
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[j].outVol&0x7f,127));
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[orderedOps[j]].outVol&0x7f,127));
} else {
rWrite(baseAddr+0x40,op.tl);
}

View file

@ -578,10 +578,10 @@ void DivPlatformYM2610Ext::forceIns() {
unsigned short baseAddr=chanOffs[i]|opOffs[j];
DivInstrumentFM::Operator& op=chan[i].state.op[j];
if (i==extChanOffs && extMode) { // extended channel
if (isOpMuted[j]) {
if (isOpMuted[orderedOps[j]]) {
rWrite(baseAddr+0x40,127);
} else if (KVS(i,j)) {
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[j].outVol&0x7f,127));
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[orderedOps[j]].outVol&0x7f,127));
} else {
rWrite(baseAddr+0x40,op.tl);
}