diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 72f4b0899..ea48355ad 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -632,6 +632,11 @@ void DivEngine::renderSamples() { } } +DivInstrument* DivEngine::getIns(int index) { + if (index<0 || index>=song.insLen) return &song.nullIns; + return song.ins[index]; +} + void DivEngine::play() { } diff --git a/src/engine/engine.h b/src/engine/engine.h index d31653603..595b26d34 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -62,6 +62,7 @@ class DivEngine { public: DivSong song; void nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size); + DivInstrument* getIns(int index); // load a .dmf. bool load(void* f, size_t length); // save as .dmf. diff --git a/src/engine/instrument.h b/src/engine/instrument.h index fd0c1b403..6372a5d06 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -49,5 +49,14 @@ struct DivInstrument { DivInstrumentSTD std; DivInstrumentGB gb; DivInstrumentC64 c64; + DivInstrument(): + name(""), + mode(false), + type(DIV_INS_FM) { + memset(&fm,0,sizeof(DivInstrumentFM)); + memset(&std,0,sizeof(DivInstrumentSTD)); + memset(&gb,0,sizeof(DivInstrumentGB)); + memset(&c64,0,sizeof(DivInstrumentC64)); + } }; #endif diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index d959cd707..bb14755e0 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -10,7 +10,7 @@ void DivPlatformGenesis::acquire(int& l, int& r) { if (--dacPeriod<1) { DivSample* s=parent->song.sample[dacSample]; writes.emplace(0x2a,((unsigned short)s->rendData[dacPos++]+0x8000)>>8); - if (dacPos>s->rendLength) { + if (dacPos>=s->rendLength) { dacSample=-1; } dacPeriod=dacRate; @@ -95,6 +95,7 @@ void DivPlatformGenesis::tick() { for (int i=0; i<6; i++) { if (chan[i].freqChanged) { + chan[i].freq=(chan[i].baseFreq*(ONE_SEMITONE+chan[i].pitch))/ONE_SEMITONE; if (chan[i].freq>=82432) { chan[i].freqH=((chan[i].freq>>15)&7)|0x38; chan[i].freqL=(chan[i].freq>>7)&0xff; @@ -152,7 +153,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) { dacRate=dacRates[parent->song.sample[dacSample]->rate]; break; } - DivInstrument* ins=parent->song.ins[chan[c.chan].ins]; + DivInstrument* ins=parent->getIns(chan[c.chan].ins); for (int i=0; i<4; i++) { unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; @@ -172,7 +173,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) { rWrite(chanOffs[c.chan]+0xb0,(ins->fm.alg&7)|(ins->fm.fb<<3)); rWrite(chanOffs[c.chan]+0xb4,(chan[c.chan].pan<<6)|(ins->fm.fms&7)|((ins->fm.ams&3)<<4)); chan[c.chan].baseFreq=644.0f*pow(2.0f,((float)c.value/12.0f)); - chan[c.chan].freq=(chan[c.chan].baseFreq*(ONE_SEMITONE+chan[c.chan].pitch))/ONE_SEMITONE; + chan[c.chan].freqChanged=true; chan[c.chan].keyOn=true; chan[c.chan].active=true; @@ -184,7 +185,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) { break; case DIV_CMD_VOLUME: { chan[c.chan].vol=c.value; - DivInstrument* ins=parent->song.ins[chan[c.chan].ins]; + DivInstrument* ins=parent->getIns(chan[c.chan].ins); for (int i=0; i<4; i++) { unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; DivInstrumentFM::Operator op=ins->fm.op[i]; @@ -214,7 +215,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) { chan[c.chan].pan=3; break; } - DivInstrument* ins=parent->song.ins[chan[c.chan].ins]; + DivInstrument* ins=parent->getIns(chan[c.chan].ins); rWrite(chanOffs[c.chan]+0xb4,(chan[c.chan].pan<<6)|(ins->fm.fms&7)|((ins->fm.ams&3)<<4)); break; } @@ -260,14 +261,14 @@ int DivPlatformGenesis::dispatch(DivCommand c) { } case DIV_CMD_FM_MULT: { unsigned short baseAddr=chanOffs[c.chan]|opOffs[c.value]; - DivInstrument* ins=parent->song.ins[chan[c.chan].ins]; + DivInstrument* ins=parent->getIns(chan[c.chan].ins); DivInstrumentFM::Operator op=ins->fm.op[c.value]; rWrite(baseAddr+0x30,(c.value2&15)|(dtTable[op.dt&7]<<4)); break; } case DIV_CMD_FM_TL: { unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]]; - DivInstrument* ins=parent->song.ins[chan[c.chan].ins]; + DivInstrument* ins=parent->getIns(chan[c.chan].ins); if (isOutput[ins->fm.alg][c.value]) { rWrite(baseAddr+0x40,127-(((127-c.value2)*chan[c.chan].vol)/127)); } else { @@ -276,7 +277,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) { break; } case DIV_CMD_FM_AR: { - DivInstrument* ins=parent->song.ins[chan[c.chan].ins]; + DivInstrument* ins=parent->getIns(chan[c.chan].ins); if (c.value<0) { for (int i=0; i<4; i++) { DivInstrumentFM::Operator op=ins->fm.op[i]; @@ -318,6 +319,8 @@ int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate) { dacRate=0; dacSample=-1; + extMode=false; + // LFO writes.emplace(0x22,0x08); diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index 22fd66f5d..e0d5a9f79 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -16,7 +16,7 @@ class DivPlatformGenesis: public DivDispatch { bool active, insChanged, freqChanged, keyOn, keyOff; signed char vol; unsigned char pan; - Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), ins(0), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), vol(0), pan(3) {} + Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), ins(-1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), vol(0), pan(3) {} }; Channel chan[10]; struct QueuedWrite { @@ -38,6 +38,8 @@ class DivPlatformGenesis: public DivDispatch { int dacRate; int dacPos; int dacSample; + + bool extMode; short oldWrites[512]; short pendingWrites[512]; diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index 321267666..88478b35e 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -9,7 +9,6 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { c.chan-=3; return DivPlatformGenesis::dispatch(c); } - printf("HANDLE: %d %d %d %d\n",c.cmd,c.chan,c.value,c.value2); switch (c.cmd) { case DIV_CMD_NOTE_ON: chan[c.chan].freq=16.4f*pow(2.0f,((float)c.value/12.0f)); @@ -30,3 +29,10 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { void DivPlatformGenesisExt::tick() { DivPlatformGenesis::tick(); } + +int DivPlatformGenesisExt::init(DivEngine* parent, int channels, int sugRate) { + DivPlatformGenesis::init(parent,channels,sugRate); + + extMode=true; + return 13; +} \ No newline at end of file diff --git a/src/engine/platform/genesisext.h b/src/engine/platform/genesisext.h index 330fb1ddd..1c67f42eb 100644 --- a/src/engine/platform/genesisext.h +++ b/src/engine/platform/genesisext.h @@ -3,7 +3,19 @@ #include "genesis.h" class DivPlatformGenesisExt: public DivPlatformGenesis { + struct Channel { + unsigned char freqH, freqL; + int freq, baseFreq, pitch; + unsigned char ins; + signed char konCycles; + bool active, insChanged, freqChanged, keyOn, keyOff; + signed char vol; + unsigned char pan; + Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), ins(-1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), vol(0), pan(3) {} + }; + Channel opChan[4]; public: int dispatch(DivCommand c); void tick(); + int init(DivEngine* parent, int channels, int sugRate); }; diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 5e54c6644..f72729873 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -62,7 +62,7 @@ int DivPlatformSMS::dispatch(DivCommand c) { chan[c.chan].note=c.value; chan[c.chan].active=true; sn->write(0x90|c.chan<<5|(15-chan[c.chan].vol)); - chan[c.chan].std.init(parent->song.ins[chan[c.chan].ins]); + chan[c.chan].std.init(parent->getIns(chan[c.chan].ins)); break; case DIV_CMD_NOTE_OFF: chan[c.chan].active=false; @@ -71,7 +71,7 @@ int DivPlatformSMS::dispatch(DivCommand c) { break; case DIV_CMD_INSTRUMENT: chan[c.chan].ins=c.value; - //chan[c.chan].std.init(parent->song.ins[chan[c.chan].ins]); + //chan[c.chan].std.init(parent->getIns(chan[c.chan].ins)); break; case DIV_CMD_VOLUME: chan[c.chan].vol=c.value; diff --git a/src/engine/platform/sms.h b/src/engine/platform/sms.h index 132e4b59b..5a1a6fff6 100644 --- a/src/engine/platform/sms.h +++ b/src/engine/platform/sms.h @@ -12,7 +12,7 @@ class DivPlatformSMS: public DivDispatch { bool active, insChanged, freqChanged, keyOn, keyOff; signed char vol; DivMacroInt std; - Channel(): freq(0), baseFreq(0), pitch(0), ins(0), note(0), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), vol(15) {} + Channel(): freq(0), baseFreq(0), pitch(0), ins(-1), note(0), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), vol(15) {} }; Channel chan[4]; unsigned char snNoiseMode; diff --git a/src/engine/platform/sound/sn76496.cpp b/src/engine/platform/sound/sn76496.cpp index 5e876c38b..2bce97b1b 100644 --- a/src/engine/platform/sound/sn76496.cpp +++ b/src/engine/platform/sound/sn76496.cpp @@ -158,6 +158,7 @@ sn76496_base_device::sn76496_base_device( : m_feedback_mask(feedbackmask) , m_whitenoise_tap1(noisetap1) , m_whitenoise_tap2(noisetap2) + , m_negate(negate) , m_clock_divider(clockdivider) , m_ncr_style_psg(ncr) , m_sega_style_psg(sega) @@ -165,7 +166,7 @@ sn76496_base_device::sn76496_base_device( } sn76496_device::sn76496_device(const char *tag, uint32_t clock) - : sn76496_base_device(tag, 0x8000, 0x01, 0x08, true, 1, false, false, clock) + : sn76496_base_device(tag, 0x8000, 0x01, 0x08, false, 1, false, false, clock) { } diff --git a/src/engine/song.h b/src/engine/song.h index a45f700f7..b779a09f2 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -94,4 +94,6 @@ struct DivSong { std::vector pat; std::vector wave; std::vector sample; + + DivInstrument nullIns; };