this does not compile
This commit is contained in:
parent
f47543ab98
commit
7080434ed4
|
@ -98,6 +98,7 @@ src/engine/platform/ym2610Interface.cpp
|
||||||
src/engine/blip_buf.c
|
src/engine/blip_buf.c
|
||||||
src/engine/safeReader.cpp
|
src/engine/safeReader.cpp
|
||||||
src/engine/safeWriter.cpp
|
src/engine/safeWriter.cpp
|
||||||
|
src/engine/dispatchContainer.cpp
|
||||||
src/engine/engine.cpp
|
src/engine/engine.cpp
|
||||||
src/engine/macroInt.cpp
|
src/engine/macroInt.cpp
|
||||||
src/engine/pattern.cpp
|
src/engine/pattern.cpp
|
||||||
|
|
|
@ -66,21 +66,24 @@ enum DivDispatchCmds {
|
||||||
|
|
||||||
struct DivCommand {
|
struct DivCommand {
|
||||||
DivDispatchCmds cmd;
|
DivDispatchCmds cmd;
|
||||||
unsigned char chan;
|
unsigned char chan, dis;
|
||||||
int value, value2;
|
int value, value2;
|
||||||
DivCommand(DivDispatchCmds c, unsigned char ch, int val, int val2):
|
DivCommand(DivDispatchCmds c, unsigned char ch, int val, int val2):
|
||||||
cmd(c),
|
cmd(c),
|
||||||
chan(ch),
|
chan(ch),
|
||||||
|
dis(ch),
|
||||||
value(val),
|
value(val),
|
||||||
value2(val2) {}
|
value2(val2) {}
|
||||||
DivCommand(DivDispatchCmds c, unsigned char ch, int val):
|
DivCommand(DivDispatchCmds c, unsigned char ch, int val):
|
||||||
cmd(c),
|
cmd(c),
|
||||||
chan(ch),
|
chan(ch),
|
||||||
|
dis(ch),
|
||||||
value(val),
|
value(val),
|
||||||
value2(0) {}
|
value2(0) {}
|
||||||
DivCommand(DivDispatchCmds c, unsigned char ch):
|
DivCommand(DivDispatchCmds c, unsigned char ch):
|
||||||
cmd(c),
|
cmd(c),
|
||||||
chan(ch),
|
chan(ch),
|
||||||
|
dis(ch),
|
||||||
value(0),
|
value(0),
|
||||||
value2(0) {}
|
value2(0) {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include "engine.h"
|
||||||
|
#include "platform/genesis.h"
|
||||||
|
#include "platform/genesisext.h"
|
||||||
|
#include "platform/sms.h"
|
||||||
|
#include "platform/gb.h"
|
||||||
|
#include "platform/pce.h"
|
||||||
|
#include "platform/nes.h"
|
||||||
|
#include "platform/c64.h"
|
||||||
|
#include "platform/arcade.h"
|
||||||
|
#include "platform/ym2610.h"
|
||||||
|
#include "platform/ym2610ext.h"
|
||||||
|
#include "platform/dummy.h"
|
||||||
|
#include "../ta-log.h"
|
||||||
|
|
||||||
|
void DivDispatchContainer::setRates(double gotRate) {
|
||||||
|
blip_set_rates(bb[0],dispatch->rate,gotRate);
|
||||||
|
blip_set_rates(bb[1],dispatch->rate,gotRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivDispatchContainer::clear() {
|
||||||
|
blip_clear(bb[0]);
|
||||||
|
blip_clear(bb[1]);
|
||||||
|
temp[0]=0;
|
||||||
|
temp[1]=0;
|
||||||
|
prevSample[0]=0;
|
||||||
|
prevSample[1]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, double gotRate, bool pal) {
|
||||||
|
if (dispatch!=NULL) return;
|
||||||
|
|
||||||
|
bb[0]=blip_new(32768);
|
||||||
|
if (bb[0]==NULL) {
|
||||||
|
logE("not enough memory!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb[1]=blip_new(32768);
|
||||||
|
if (bb[1]==NULL) {
|
||||||
|
logE("not enough memory!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bbOut[0]=new short[32768];
|
||||||
|
bbOut[1]=new short[32768];
|
||||||
|
bbIn[0]=new short[32768];
|
||||||
|
bbIn[1]=new short[32768];
|
||||||
|
bbInLen=32768;
|
||||||
|
|
||||||
|
switch (sys) {
|
||||||
|
case DIV_SYSTEM_GENESIS:
|
||||||
|
dispatch=new DivPlatformGenesis;
|
||||||
|
break;
|
||||||
|
case DIV_SYSTEM_GENESIS_EXT:
|
||||||
|
dispatch=new DivPlatformGenesisExt;
|
||||||
|
break;
|
||||||
|
case DIV_SYSTEM_SMS:
|
||||||
|
dispatch=new DivPlatformSMS;
|
||||||
|
break;
|
||||||
|
case DIV_SYSTEM_GB:
|
||||||
|
dispatch=new DivPlatformGB;
|
||||||
|
break;
|
||||||
|
case DIV_SYSTEM_PCE:
|
||||||
|
dispatch=new DivPlatformPCE;
|
||||||
|
break;
|
||||||
|
case DIV_SYSTEM_NES:
|
||||||
|
dispatch=new DivPlatformNES;
|
||||||
|
break;
|
||||||
|
case DIV_SYSTEM_C64_6581:
|
||||||
|
dispatch=new DivPlatformC64;
|
||||||
|
((DivPlatformC64*)dispatch)->setChipModel(true);
|
||||||
|
break;
|
||||||
|
case DIV_SYSTEM_C64_8580:
|
||||||
|
dispatch=new DivPlatformC64;
|
||||||
|
((DivPlatformC64*)dispatch)->setChipModel(false);
|
||||||
|
break;
|
||||||
|
case DIV_SYSTEM_ARCADE:
|
||||||
|
dispatch=new DivPlatformArcade;
|
||||||
|
((DivPlatformArcade*)dispatch)->setYMFM(true);
|
||||||
|
break;
|
||||||
|
case DIV_SYSTEM_YM2610:
|
||||||
|
dispatch=new DivPlatformYM2610;
|
||||||
|
break;
|
||||||
|
case DIV_SYSTEM_YM2610_EXT:
|
||||||
|
dispatch=new DivPlatformYM2610Ext;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logW("this system is not supported yet! using dummy platform.\n");
|
||||||
|
dispatch=new DivPlatformDummy;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dispatch->init(eng,chanCount,gotRate,pal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivDispatchContainer::quit() {
|
||||||
|
if (dispatch==NULL) return;
|
||||||
|
dispatch->quit();
|
||||||
|
delete dispatch;
|
||||||
|
dispatch=NULL;
|
||||||
|
|
||||||
|
delete[] bbOut[0];
|
||||||
|
delete[] bbOut[1];
|
||||||
|
delete[] bbIn[0];
|
||||||
|
delete[] bbIn[1];
|
||||||
|
bbInLen=0;
|
||||||
|
blip_delete(bb[0]);
|
||||||
|
blip_delete(bb[1]);
|
||||||
|
}
|
|
@ -13,17 +13,6 @@
|
||||||
#ifdef HAVE_JACK
|
#ifdef HAVE_JACK
|
||||||
#include "../audio/jack.h"
|
#include "../audio/jack.h"
|
||||||
#endif
|
#endif
|
||||||
#include "platform/genesis.h"
|
|
||||||
#include "platform/genesisext.h"
|
|
||||||
#include "platform/sms.h"
|
|
||||||
#include "platform/gb.h"
|
|
||||||
#include "platform/pce.h"
|
|
||||||
#include "platform/nes.h"
|
|
||||||
#include "platform/c64.h"
|
|
||||||
#include "platform/arcade.h"
|
|
||||||
#include "platform/ym2610.h"
|
|
||||||
#include "platform/ym2610ext.h"
|
|
||||||
#include "platform/dummy.h"
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include <sndfile.h>
|
#include <sndfile.h>
|
||||||
|
@ -246,117 +235,119 @@ const int chanTypes[11][17]={
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* DivEngine::getChannelName(int chan) {
|
const char* DivEngine::getChannelName(int chan) {
|
||||||
switch (song.system[0]) {
|
if (chan<0 || chan>chans) return "??";
|
||||||
|
switch (sysOfChan[chan]) {
|
||||||
case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759:
|
case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759:
|
||||||
return chanNames[0][chan];
|
return chanNames[0][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_GENESIS:
|
case DIV_SYSTEM_GENESIS:
|
||||||
return chanNames[1][chan];
|
return chanNames[1][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_GENESIS_EXT:
|
case DIV_SYSTEM_GENESIS_EXT:
|
||||||
return chanNames[2][chan];
|
return chanNames[2][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_SMS:
|
case DIV_SYSTEM_SMS:
|
||||||
return chanNames[3][chan];
|
return chanNames[3][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_GB:
|
case DIV_SYSTEM_GB:
|
||||||
return chanNames[4][chan];
|
return chanNames[4][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_PCE:
|
case DIV_SYSTEM_PCE:
|
||||||
return chanNames[5][chan];
|
return chanNames[5][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_NES:
|
case DIV_SYSTEM_NES:
|
||||||
return chanNames[6][chan];
|
return chanNames[6][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580:
|
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580:
|
||||||
return chanNames[7][chan];
|
return chanNames[7][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_ARCADE:
|
case DIV_SYSTEM_ARCADE:
|
||||||
return chanNames[8][chan];
|
return chanNames[8][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_YM2610:
|
case DIV_SYSTEM_YM2610:
|
||||||
return chanNames[9][chan];
|
return chanNames[9][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_YM2610_EXT:
|
case DIV_SYSTEM_YM2610_EXT:
|
||||||
return chanNames[10][chan];
|
return chanNames[10][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return "??";
|
return "??";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* DivEngine::getChannelShortName(int chan) {
|
const char* DivEngine::getChannelShortName(int chan) {
|
||||||
switch (song.system[0]) {
|
if (chan<0 || chan>chans) return "??";
|
||||||
|
switch (sysOfChan[chan]) {
|
||||||
case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759:
|
case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759:
|
||||||
return chanShortNames[0][chan];
|
return chanShortNames[0][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_GENESIS:
|
case DIV_SYSTEM_GENESIS:
|
||||||
return chanShortNames[1][chan];
|
return chanShortNames[1][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_GENESIS_EXT:
|
case DIV_SYSTEM_GENESIS_EXT:
|
||||||
return chanShortNames[2][chan];
|
return chanShortNames[2][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_SMS:
|
case DIV_SYSTEM_SMS:
|
||||||
return chanShortNames[3][chan];
|
return chanShortNames[3][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_GB:
|
case DIV_SYSTEM_GB:
|
||||||
return chanShortNames[4][chan];
|
return chanShortNames[4][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_PCE:
|
case DIV_SYSTEM_PCE:
|
||||||
return chanShortNames[5][chan];
|
return chanShortNames[5][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_NES:
|
case DIV_SYSTEM_NES:
|
||||||
return chanShortNames[6][chan];
|
return chanShortNames[6][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580:
|
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580:
|
||||||
return chanShortNames[7][chan];
|
return chanShortNames[7][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_ARCADE:
|
case DIV_SYSTEM_ARCADE:
|
||||||
return chanShortNames[8][chan];
|
return chanShortNames[8][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_YM2610:
|
case DIV_SYSTEM_YM2610:
|
||||||
return chanShortNames[9][chan];
|
return chanShortNames[9][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_YM2610_EXT:
|
case DIV_SYSTEM_YM2610_EXT:
|
||||||
return chanShortNames[10][chan];
|
return chanShortNames[10][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return "??";
|
return "??";
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivEngine::getChannelType(int chan) {
|
int DivEngine::getChannelType(int chan) {
|
||||||
switch (song.system[0]) {
|
switch (sysOfChan[chan]) {
|
||||||
case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759:
|
case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759:
|
||||||
return chanTypes[0][chan];
|
return chanTypes[0][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_GENESIS:
|
case DIV_SYSTEM_GENESIS:
|
||||||
return chanTypes[1][chan];
|
return chanTypes[1][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_GENESIS_EXT:
|
case DIV_SYSTEM_GENESIS_EXT:
|
||||||
return chanTypes[2][chan];
|
return chanTypes[2][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_SMS:
|
case DIV_SYSTEM_SMS:
|
||||||
return chanTypes[3][chan];
|
return chanTypes[3][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_GB:
|
case DIV_SYSTEM_GB:
|
||||||
return chanTypes[4][chan];
|
return chanTypes[4][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_PCE:
|
case DIV_SYSTEM_PCE:
|
||||||
return chanTypes[5][chan];
|
return chanTypes[5][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_NES:
|
case DIV_SYSTEM_NES:
|
||||||
return chanTypes[6][chan];
|
return chanTypes[6][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580:
|
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580:
|
||||||
return chanTypes[7][chan];
|
return chanTypes[7][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_ARCADE:
|
case DIV_SYSTEM_ARCADE:
|
||||||
return chanTypes[8][chan];
|
return chanTypes[8][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_YM2610:
|
case DIV_SYSTEM_YM2610:
|
||||||
return chanTypes[9][chan];
|
return chanTypes[9][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_YM2610_EXT:
|
case DIV_SYSTEM_YM2610_EXT:
|
||||||
return chanTypes[10][chan];
|
return chanTypes[10][dispatchChanOfChan[chan]];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -882,7 +873,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
||||||
isBusy.lock();
|
isBusy.lock();
|
||||||
song.unload();
|
song.unload();
|
||||||
song=ds;
|
song=ds;
|
||||||
chans=getChannelCount(song.system[0]);
|
recalcChans();
|
||||||
renderSamples();
|
renderSamples();
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
if (active) {
|
if (active) {
|
||||||
|
@ -1494,7 +1485,7 @@ void DivEngine::createNew() {
|
||||||
song.unload();
|
song.unload();
|
||||||
song=DivSong();
|
song=DivSong();
|
||||||
song.system[0]=sys;
|
song.system[0]=sys;
|
||||||
chans=getChannelCount(song.system[0]);
|
recalcChans();
|
||||||
renderSamples();
|
renderSamples();
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
initDispatch();
|
initDispatch();
|
||||||
|
@ -1503,17 +1494,17 @@ void DivEngine::createNew() {
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivEngine::changeSystem(DivSystem which) {
|
void DivEngine::changeSystem(int index, DivSystem which) {
|
||||||
quitDispatch();
|
quitDispatch();
|
||||||
isBusy.lock();
|
isBusy.lock();
|
||||||
song.system[0]=which;
|
song.system[index]=which;
|
||||||
chans=getChannelCount(song.system[0]);
|
recalcChans();
|
||||||
// instrument safety check
|
// instrument safety check (TODO: rewrite for multi-system)
|
||||||
for (DivInstrument* i: song.ins) {
|
for (DivInstrument* i: song.ins) {
|
||||||
if (!isFMSystem(song.system[0]) && i->mode) {
|
if (!isFMSystem(song.system[index]) && i->mode) {
|
||||||
i->mode=false;
|
i->mode=false;
|
||||||
}
|
}
|
||||||
if (!isSTDSystem(song.system[0]) && !i->mode) {
|
if (!isSTDSystem(song.system[index]) && !i->mode) {
|
||||||
i->mode=true;
|
i->mode=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1557,9 +1548,12 @@ void DivEngine::playSub(bool preserveDrift) {
|
||||||
int goal=curOrder;
|
int goal=curOrder;
|
||||||
curOrder=0;
|
curOrder=0;
|
||||||
curRow=0;
|
curRow=0;
|
||||||
int prevDrift=clockDrift;
|
int prevDrift[32];
|
||||||
clockDrift=0;
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
cycles=0;
|
prevDrift[i]=disCont[i].clockDrift;
|
||||||
|
disCont[i].clockDrift=0;
|
||||||
|
disCont[i].cycles=0;
|
||||||
|
}
|
||||||
if (preserveDrift) {
|
if (preserveDrift) {
|
||||||
endOfSong=false;
|
endOfSong=false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1568,22 +1562,24 @@ void DivEngine::playSub(bool preserveDrift) {
|
||||||
}
|
}
|
||||||
speedAB=false;
|
speedAB=false;
|
||||||
playing=true;
|
playing=true;
|
||||||
dispatch->setSkipRegisterWrites(true);
|
for (int i=0; i<song.systemLen; i++) disCont[i].dispatch->setSkipRegisterWrites(true);
|
||||||
while (curOrder<goal) {
|
while (curOrder<goal) {
|
||||||
if (nextTick(preserveDrift)) break;
|
if (nextTick(preserveDrift)) break;
|
||||||
}
|
}
|
||||||
dispatch->setSkipRegisterWrites(false);
|
for (int i=0; i<song.systemLen; i++) disCont[i].dispatch->setSkipRegisterWrites(false);
|
||||||
if (goal>0) {
|
if (goal>0) {
|
||||||
dispatch->forceIns();
|
for (int i=0; i<song.systemLen; i++) disCont[i].dispatch->forceIns();
|
||||||
}
|
}
|
||||||
repeatPattern=oldRepeatPattern;
|
repeatPattern=oldRepeatPattern;
|
||||||
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
if (preserveDrift) {
|
if (preserveDrift) {
|
||||||
clockDrift=prevDrift;
|
disCont[i].clockDrift=prevDrift[i];
|
||||||
} else {
|
} else {
|
||||||
clockDrift=0;
|
disCont[i].clockDrift=0;
|
||||||
|
disCont[i].cycles=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!preserveDrift) {
|
if (!preserveDrift) {
|
||||||
cycles=0;
|
|
||||||
ticks=1;
|
ticks=1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1609,10 +1605,25 @@ void DivEngine::stop() {
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivEngine::recalcChans() {
|
||||||
|
chans=0;
|
||||||
|
int chanIndex=0;
|
||||||
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
|
int chanCount=getChannelCount(song.system[i]);
|
||||||
|
chans+=chanCount;
|
||||||
|
for (int j=0; j<chanCount; j++) {
|
||||||
|
sysOfChan[chanIndex]=song.system[i];
|
||||||
|
dispatchOfChan[chanIndex]=i;
|
||||||
|
dispatchChanOfChan[chanIndex]=j;
|
||||||
|
chanIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DivEngine::reset() {
|
void DivEngine::reset() {
|
||||||
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
chan[i]=DivChannelState();
|
chan[i]=DivChannelState();
|
||||||
chan[i].volMax=(dispatch->dispatch(DivCommand(DIV_CMD_GET_VOLMAX,i))<<8)|0xff;
|
if (i<chans) chan[i].volMax=(disCont[dispatchOfChan[i]].dispatch->dispatch(DivCommand(DIV_CMD_GET_VOLMAX,dispatchChanOfChan[i]))<<8)|0xff;
|
||||||
chan[i].volume=chan[i].volMax;
|
chan[i].volume=chan[i].volMax;
|
||||||
}
|
}
|
||||||
extValue=0;
|
extValue=0;
|
||||||
|
@ -1621,13 +1632,10 @@ void DivEngine::reset() {
|
||||||
speed2=song.speed2;
|
speed2=song.speed2;
|
||||||
nextSpeed=speed1;
|
nextSpeed=speed1;
|
||||||
globalPitch=0;
|
globalPitch=0;
|
||||||
blip_clear(bb[0]);
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
blip_clear(bb[1]);
|
disCont[i].clear();
|
||||||
temp[0]=0;
|
disCont[i].dispatch->reset();
|
||||||
temp[1]=0;
|
}
|
||||||
prevSample[0]=0;
|
|
||||||
prevSample[1]=0;
|
|
||||||
dispatch->reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivEngine::syncReset() {
|
void DivEngine::syncReset() {
|
||||||
|
@ -1690,9 +1698,9 @@ void DivEngine::previewSample(int sample) {
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
blip_clear(bb[2]);
|
blip_clear(samp_bb);
|
||||||
blip_set_rates(bb[2],song.sample[sample]->rate,got.rate);
|
blip_set_rates(samp_bb,song.sample[sample]->rate,got.rate);
|
||||||
prevSample[2]=0;
|
samp_prevSample=0;
|
||||||
sPreview.pos=0;
|
sPreview.pos=0;
|
||||||
sPreview.sample=sample;
|
sPreview.sample=sample;
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
|
@ -1784,15 +1792,15 @@ void DivEngine::toggleSolo(int chan) {
|
||||||
if (!solo) {
|
if (!solo) {
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
isMuted[i]=(i!=chan);
|
isMuted[i]=(i!=chan);
|
||||||
if (dispatch!=NULL) {
|
if (disCont[dispatchOfChan[i]].dispatch!=NULL) {
|
||||||
dispatch->muteChannel(i,isMuted[i]);
|
disCont[dispatchOfChan[i]].dispatch->muteChannel(dispatchChanOfChan[i],isMuted[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
isMuted[i]=false;
|
isMuted[i]=false;
|
||||||
if (dispatch!=NULL) {
|
if (disCont[dispatchOfChan[i]].dispatch!=NULL) {
|
||||||
dispatch->muteChannel(i,isMuted[i]);
|
disCont[dispatchOfChan[i]].dispatch->muteChannel(dispatchChanOfChan[i],isMuted[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1802,8 +1810,8 @@ void DivEngine::toggleSolo(int chan) {
|
||||||
void DivEngine::muteChannel(int chan, bool mute) {
|
void DivEngine::muteChannel(int chan, bool mute) {
|
||||||
isBusy.lock();
|
isBusy.lock();
|
||||||
isMuted[chan]=mute;
|
isMuted[chan]=mute;
|
||||||
if (dispatch!=NULL) {
|
if (disCont[dispatchOfChan[chan]].dispatch!=NULL) {
|
||||||
dispatch->muteChannel(chan,isMuted[chan]);
|
disCont[dispatchOfChan[chan]].dispatch->muteChannel(dispatchChanOfChan[chan],isMuted[chan]);
|
||||||
}
|
}
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
}
|
}
|
||||||
|
@ -2061,9 +2069,10 @@ void DivEngine::setSongRate(int hz, bool pal) {
|
||||||
song.pal=!pal;
|
song.pal=!pal;
|
||||||
song.hz=hz;
|
song.hz=hz;
|
||||||
song.customTempo=(song.hz!=50 && song.hz!=60);
|
song.customTempo=(song.hz!=50 && song.hz!=60);
|
||||||
dispatch->setPAL((!song.pal) || (song.customTempo!=0 && song.hz<53));
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
blip_set_rates(bb[0],dispatch->rate,got.rate);
|
disCont[i].dispatch->setPAL((!song.pal) || (song.customTempo!=0 && song.hz<53));
|
||||||
blip_set_rates(bb[1],dispatch->rate,got.rate);
|
disCont[i].setRates(got.rate);
|
||||||
|
}
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2089,74 +2098,30 @@ void DivEngine::setConsoleMode(bool enable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivEngine::initDispatch() {
|
void DivEngine::initDispatch() {
|
||||||
if (dispatch!=NULL) return;
|
|
||||||
isBusy.lock();
|
isBusy.lock();
|
||||||
switch (song.system[0]) {
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
case DIV_SYSTEM_GENESIS:
|
disCont[i].init(song.system[i],this,getChannelCount(song.system[i]),got.rate,(!song.pal) || (song.customTempo!=0 && song.hz<53));
|
||||||
dispatch=new DivPlatformGenesis;
|
disCont[i].setRates(got.rate);
|
||||||
break;
|
|
||||||
case DIV_SYSTEM_GENESIS_EXT:
|
|
||||||
dispatch=new DivPlatformGenesisExt;
|
|
||||||
break;
|
|
||||||
case DIV_SYSTEM_SMS:
|
|
||||||
dispatch=new DivPlatformSMS;
|
|
||||||
break;
|
|
||||||
case DIV_SYSTEM_GB:
|
|
||||||
dispatch=new DivPlatformGB;
|
|
||||||
break;
|
|
||||||
case DIV_SYSTEM_PCE:
|
|
||||||
dispatch=new DivPlatformPCE;
|
|
||||||
break;
|
|
||||||
case DIV_SYSTEM_NES:
|
|
||||||
dispatch=new DivPlatformNES;
|
|
||||||
break;
|
|
||||||
case DIV_SYSTEM_C64_6581:
|
|
||||||
dispatch=new DivPlatformC64;
|
|
||||||
((DivPlatformC64*)dispatch)->setChipModel(true);
|
|
||||||
break;
|
|
||||||
case DIV_SYSTEM_C64_8580:
|
|
||||||
dispatch=new DivPlatformC64;
|
|
||||||
((DivPlatformC64*)dispatch)->setChipModel(false);
|
|
||||||
break;
|
|
||||||
case DIV_SYSTEM_ARCADE:
|
|
||||||
dispatch=new DivPlatformArcade;
|
|
||||||
((DivPlatformArcade*)dispatch)->setYMFM(true);
|
|
||||||
break;
|
|
||||||
case DIV_SYSTEM_YM2610:
|
|
||||||
dispatch=new DivPlatformYM2610;
|
|
||||||
break;
|
|
||||||
case DIV_SYSTEM_YM2610_EXT:
|
|
||||||
dispatch=new DivPlatformYM2610Ext;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
logW("this system is not supported yet! using dummy platform.\n");
|
|
||||||
dispatch=new DivPlatformDummy;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
dispatch->init(this,getChannelCount(song.system[0]),got.rate,(!song.pal) || (song.customTempo!=0 && song.hz<53));
|
recalcChans();
|
||||||
chans=getChannelCount(song.system[0]);
|
|
||||||
|
|
||||||
blip_set_rates(bb[0],dispatch->rate,got.rate);
|
|
||||||
blip_set_rates(bb[1],dispatch->rate,got.rate);
|
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivEngine::quitDispatch() {
|
void DivEngine::quitDispatch() {
|
||||||
if (dispatch==NULL) return;
|
|
||||||
isBusy.lock();
|
isBusy.lock();
|
||||||
dispatch->quit();
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
delete dispatch;
|
disCont[i].quit();
|
||||||
dispatch=NULL;
|
disCont[i].cycles=0;
|
||||||
|
disCont[i].clockDrift=0;
|
||||||
|
}
|
||||||
chans=0;
|
chans=0;
|
||||||
playing=false;
|
playing=false;
|
||||||
speedAB=false;
|
speedAB=false;
|
||||||
endOfSong=false;
|
endOfSong=false;
|
||||||
ticks=0;
|
ticks=0;
|
||||||
cycles=0;
|
|
||||||
curRow=0;
|
curRow=0;
|
||||||
curOrder=0;
|
curOrder=0;
|
||||||
nextSpeed=3;
|
nextSpeed=3;
|
||||||
clockDrift=0;
|
|
||||||
changeOrd=-1;
|
changeOrd=-1;
|
||||||
changePos=0;
|
changePos=0;
|
||||||
totalTicks=0;
|
totalTicks=0;
|
||||||
|
@ -2193,6 +2158,7 @@ void DivEngine::quitDispatch() {
|
||||||
#include "winStuff.h"
|
#include "winStuff.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// TODO: all of this!
|
||||||
bool DivEngine::init(String outName) {
|
bool DivEngine::init(String outName) {
|
||||||
// init config
|
// init config
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -2279,34 +2245,18 @@ bool DivEngine::init(String outName) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bb[0]=blip_new(32768);
|
samp_bb=blip_new(32768);
|
||||||
if (bb[0]==NULL) {
|
if (samp_bb==NULL) {
|
||||||
logE("not enough memory!\n");
|
logE("not enough memory!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb[1]=blip_new(32768);
|
samp_bbOut=new short[got.bufsize];
|
||||||
if (bb[1]==NULL) {
|
|
||||||
logE("not enough memory!\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb[2]=blip_new(32768);
|
samp_bbIn=new short[32768];
|
||||||
if (bb[2]==NULL) {
|
samp_bbInLen=32768;
|
||||||
logE("not enough memory!\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bbOut[0]=new short[got.bufsize];
|
blip_set_rates(samp_bb,44100,got.rate);
|
||||||
bbOut[1]=new short[got.bufsize];
|
|
||||||
bbOut[2]=new short[got.bufsize];
|
|
||||||
|
|
||||||
bbIn[0]=new short[32768];
|
|
||||||
bbIn[1]=new short[32768];
|
|
||||||
bbIn[2]=new short[32768];
|
|
||||||
bbInLen=32768;
|
|
||||||
|
|
||||||
blip_set_rates(bb[2],44100,got.rate);
|
|
||||||
|
|
||||||
for (int i=0; i<64; i++) {
|
for (int i=0; i<64; i++) {
|
||||||
vibTable[i]=127*sin(((double)i/64.0)*(2*M_PI));
|
vibTable[i]=127*sin(((double)i/64.0)*(2*M_PI));
|
||||||
|
|
|
@ -90,10 +90,27 @@ struct DivDispatchContainer {
|
||||||
int temp[2], prevSample[2];
|
int temp[2], prevSample[2];
|
||||||
short* bbIn[2];
|
short* bbIn[2];
|
||||||
short* bbOut[2];
|
short* bbOut[2];
|
||||||
|
|
||||||
|
int cycles, clockDrift;
|
||||||
|
|
||||||
|
void setRates(double gotRate);
|
||||||
|
void clear();
|
||||||
|
void init(DivSystem sys, DivEngine* eng, int chanCount, double gotRate, bool pal);
|
||||||
|
void quit();
|
||||||
|
DivDispatchContainer():
|
||||||
|
dispatch(NULL),
|
||||||
|
bb{NULL,NULL},
|
||||||
|
bbInLen(0),
|
||||||
|
temp{0,0},
|
||||||
|
prevSample{0,0},
|
||||||
|
bbIn{NULL,NULL},
|
||||||
|
bbOut{NULL,NULL},
|
||||||
|
cycles(0),
|
||||||
|
clockDrift(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DivEngine {
|
class DivEngine {
|
||||||
DivDispatch* dispatch;
|
DivDispatchContainer disCont[32];
|
||||||
TAAudio* output;
|
TAAudio* output;
|
||||||
TAAudioDesc want, got;
|
TAAudioDesc want, got;
|
||||||
int chans;
|
int chans;
|
||||||
|
@ -106,7 +123,7 @@ class DivEngine {
|
||||||
bool extValuePresent;
|
bool extValuePresent;
|
||||||
bool repeatPattern;
|
bool repeatPattern;
|
||||||
bool metronome;
|
bool metronome;
|
||||||
int ticks, cycles, curRow, curOrder, remainingLoops, nextSpeed, clockDrift;
|
int ticks, curRow, curOrder, remainingLoops, nextSpeed;
|
||||||
int changeOrd, changePos, totalTicks, totalCmds, lastCmds, cmdsPerSecond, globalPitch;
|
int changeOrd, changePos, totalTicks, totalCmds, lastCmds, cmdsPerSecond, globalPitch;
|
||||||
unsigned char extValue;
|
unsigned char extValue;
|
||||||
unsigned char speed1, speed2;
|
unsigned char speed1, speed2;
|
||||||
|
@ -116,6 +133,9 @@ class DivEngine {
|
||||||
std::map<String,String> conf;
|
std::map<String,String> conf;
|
||||||
std::queue<DivNoteEvent> pendingNotes;
|
std::queue<DivNoteEvent> pendingNotes;
|
||||||
bool isMuted[DIV_MAX_CHANS];
|
bool isMuted[DIV_MAX_CHANS];
|
||||||
|
DivSystem sysOfChan[DIV_MAX_CHANS];
|
||||||
|
int dispatchOfChan[DIV_MAX_CHANS];
|
||||||
|
int dispatchChanOfChan[DIV_MAX_CHANS];
|
||||||
std::mutex isBusy;
|
std::mutex isBusy;
|
||||||
String configPath;
|
String configPath;
|
||||||
String configFile;
|
String configFile;
|
||||||
|
@ -131,11 +151,11 @@ class DivEngine {
|
||||||
|
|
||||||
short vibTable[64];
|
short vibTable[64];
|
||||||
|
|
||||||
blip_buffer_t* bb[3];
|
blip_buffer_t* samp_bb;
|
||||||
size_t bbInLen;
|
size_t samp_bbInLen;
|
||||||
int temp[3], prevSample[3];
|
int samp_temp, samp_prevSample;
|
||||||
short* bbIn[3];
|
short* samp_bbIn;
|
||||||
short* bbOut[3];
|
short* samp_bbOut;
|
||||||
unsigned char* metroTick;
|
unsigned char* metroTick;
|
||||||
size_t metroTickLen;
|
size_t metroTickLen;
|
||||||
float metroFreq, metroPos;
|
float metroFreq, metroPos;
|
||||||
|
@ -153,6 +173,7 @@ class DivEngine {
|
||||||
bool nextTick(bool noAccum=false);
|
bool nextTick(bool noAccum=false);
|
||||||
bool perSystemEffect(int ch, unsigned char effect, unsigned char effectVal);
|
bool perSystemEffect(int ch, unsigned char effect, unsigned char effectVal);
|
||||||
bool perSystemPostEffect(int ch, unsigned char effect, unsigned char effectVal);
|
bool perSystemPostEffect(int ch, unsigned char effect, unsigned char effectVal);
|
||||||
|
void recalcChans();
|
||||||
void renderSamples();
|
void renderSamples();
|
||||||
void reset();
|
void reset();
|
||||||
void playSub(bool preserveDrift);
|
void playSub(bool preserveDrift);
|
||||||
|
@ -376,7 +397,13 @@ class DivEngine {
|
||||||
void renderSamplesP();
|
void renderSamplesP();
|
||||||
|
|
||||||
// change system
|
// change system
|
||||||
void changeSystem(DivSystem which);
|
void changeSystem(int index, DivSystem which);
|
||||||
|
|
||||||
|
// add system
|
||||||
|
void addSystem(DivSystem which);
|
||||||
|
|
||||||
|
// remove system
|
||||||
|
void removeSystem(int index);
|
||||||
|
|
||||||
// get last error
|
// get last error
|
||||||
String getLastError();
|
String getLastError();
|
||||||
|
@ -407,12 +434,10 @@ class DivEngine {
|
||||||
repeatPattern(false),
|
repeatPattern(false),
|
||||||
metronome(false),
|
metronome(false),
|
||||||
ticks(0),
|
ticks(0),
|
||||||
cycles(0),
|
|
||||||
curRow(0),
|
curRow(0),
|
||||||
curOrder(0),
|
curOrder(0),
|
||||||
remainingLoops(-1),
|
remainingLoops(-1),
|
||||||
nextSpeed(3),
|
nextSpeed(3),
|
||||||
clockDrift(0),
|
|
||||||
changeOrd(-1),
|
changeOrd(-1),
|
||||||
changePos(0),
|
changePos(0),
|
||||||
totalTicks(0),
|
totalTicks(0),
|
||||||
|
@ -424,9 +449,9 @@ class DivEngine {
|
||||||
speed2(3),
|
speed2(3),
|
||||||
view(DIV_STATUS_NOTHING),
|
view(DIV_STATUS_NOTHING),
|
||||||
audioEngine(DIV_AUDIO_SDL),
|
audioEngine(DIV_AUDIO_SDL),
|
||||||
bbInLen(0),
|
samp_bbInLen(0),
|
||||||
temp{0,0},
|
samp_temp(0),
|
||||||
prevSample{0,0},
|
samp_prevSample(0),
|
||||||
metroTick(NULL),
|
metroTick(NULL),
|
||||||
metroTickLen(0),
|
metroTickLen(0),
|
||||||
metroFreq(0),
|
metroFreq(0),
|
||||||
|
|
|
@ -90,11 +90,12 @@ int DivEngine::dispatchCmd(DivCommand c) {
|
||||||
printf("%8d | %d: %s(%d, %d)\n",totalTicks,c.chan,cmdName[c.cmd],c.value,c.value2);
|
printf("%8d | %d: %s(%d, %d)\n",totalTicks,c.chan,cmdName[c.cmd],c.value,c.value2);
|
||||||
}
|
}
|
||||||
totalCmds++;
|
totalCmds++;
|
||||||
return dispatch->dispatch(c);
|
c.chan=dispatchChanOfChan[c.dis];
|
||||||
|
return disCont[dispatchOfChan[c.dis]].dispatch->dispatch(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effectVal) {
|
bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effectVal) {
|
||||||
switch (song.system[0]) {
|
switch (sysOfChan[ch]) {
|
||||||
case DIV_SYSTEM_GENESIS:
|
case DIV_SYSTEM_GENESIS:
|
||||||
case DIV_SYSTEM_GENESIS_EXT:
|
case DIV_SYSTEM_GENESIS_EXT:
|
||||||
switch (effect) {
|
switch (effect) {
|
||||||
|
@ -172,7 +173,7 @@ bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effe
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char effectVal) {
|
bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char effectVal) {
|
||||||
switch (song.system[0]) {
|
switch (sysOfChan[ch]) {
|
||||||
case DIV_SYSTEM_GENESIS:
|
case DIV_SYSTEM_GENESIS:
|
||||||
case DIV_SYSTEM_GENESIS_EXT:
|
case DIV_SYSTEM_GENESIS_EXT:
|
||||||
case DIV_SYSTEM_ARCADE:
|
case DIV_SYSTEM_ARCADE:
|
||||||
|
@ -180,7 +181,7 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char
|
||||||
case DIV_SYSTEM_YM2610_EXT:
|
case DIV_SYSTEM_YM2610_EXT:
|
||||||
switch (effect) {
|
switch (effect) {
|
||||||
case 0x10: // LFO or noise mode
|
case 0x10: // LFO or noise mode
|
||||||
if (song.system[0]==DIV_SYSTEM_ARCADE) {
|
if (sysOfChan[ch]==DIV_SYSTEM_ARCADE) {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_FREQ,ch,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_FREQ,ch,effectVal));
|
||||||
} else {
|
} else {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_FM_LFO,ch,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_FM_LFO,ch,effectVal));
|
||||||
|
@ -207,12 +208,12 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x17: // arcade LFO
|
case 0x17: // arcade LFO
|
||||||
if (song.system[0]==DIV_SYSTEM_ARCADE) {
|
if (sysOfChan[ch]==DIV_SYSTEM_ARCADE) {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_FM_LFO,ch,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_FM_LFO,ch,effectVal));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x18: // EXT or LFO waveform
|
case 0x18: // EXT or LFO waveform
|
||||||
if (song.system[0]==DIV_SYSTEM_ARCADE) {
|
if (sysOfChan[ch]==DIV_SYSTEM_ARCADE) {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_FM_LFO_WAVE,ch,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_FM_LFO_WAVE,ch,effectVal));
|
||||||
} else {
|
} else {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_FM_EXTCH,ch,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_FM_EXTCH,ch,effectVal));
|
||||||
|
@ -234,29 +235,29 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char
|
||||||
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,3,effectVal&31));
|
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,3,effectVal&31));
|
||||||
break;
|
break;
|
||||||
case 0x20: // PCM frequency or Neo Geo PSG mode
|
case 0x20: // PCM frequency or Neo Geo PSG mode
|
||||||
if (song.system[0]==DIV_SYSTEM_ARCADE) {
|
if (sysOfChan[ch]==DIV_SYSTEM_ARCADE) {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_SAMPLE_FREQ,ch,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_SAMPLE_FREQ,ch,effectVal));
|
||||||
} else if (song.system[0]==DIV_SYSTEM_YM2610 || song.system[0]==DIV_SYSTEM_YM2610_EXT) {
|
} else if (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT) {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_MODE,ch,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_MODE,ch,effectVal));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x21: // Neo Geo PSG noise freq
|
case 0x21: // Neo Geo PSG noise freq
|
||||||
if (song.system[0]==DIV_SYSTEM_YM2610 || song.system[0]==DIV_SYSTEM_YM2610_EXT) {
|
if (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT) {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_FREQ,ch,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_FREQ,ch,effectVal));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x22: // UNOFFICIAL: Neo Geo PSG envelope enable
|
case 0x22: // UNOFFICIAL: Neo Geo PSG envelope enable
|
||||||
if (song.system[0]==DIV_SYSTEM_YM2610 || song.system[0]==DIV_SYSTEM_YM2610_EXT) {
|
if (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT) {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_SET,ch,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_SET,ch,effectVal));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x23: // UNOFFICIAL: Neo Geo PSG envelope period low
|
case 0x23: // UNOFFICIAL: Neo Geo PSG envelope period low
|
||||||
if (song.system[0]==DIV_SYSTEM_YM2610 || song.system[0]==DIV_SYSTEM_YM2610_EXT) {
|
if (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT) {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_LOW,ch,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_LOW,ch,effectVal));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x24: // UNOFFICIAL: Neo Geo PSG envelope period high
|
case 0x24: // UNOFFICIAL: Neo Geo PSG envelope period high
|
||||||
if (song.system[0]==DIV_SYSTEM_YM2610 || song.system[0]==DIV_SYSTEM_YM2610_EXT) {
|
if (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT) {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_HIGH,ch,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_HIGH,ch,effectVal));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -322,7 +323,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
chan[i].delayOrder=whatOrder;
|
chan[i].delayOrder=whatOrder;
|
||||||
chan[i].delayRow=whatRow;
|
chan[i].delayRow=whatRow;
|
||||||
if (effectVal==nextSpeed) {
|
if (effectVal==nextSpeed) {
|
||||||
if (song.system[0]!=DIV_SYSTEM_YM2610 && song.system[0]!=DIV_SYSTEM_YM2610_EXT) chan[i].delayLocked=true;
|
if (sysOfChan[i]!=DIV_SYSTEM_YM2610 && sysOfChan[i]!=DIV_SYSTEM_YM2610_EXT) chan[i].delayLocked=true;
|
||||||
} else {
|
} else {
|
||||||
chan[i].delayLocked=false;
|
chan[i].delayLocked=false;
|
||||||
}
|
}
|
||||||
|
@ -348,10 +349,10 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
chan[i].portaSpeed=-1;
|
chan[i].portaSpeed=-1;
|
||||||
chan[i].stopOnOff=false;
|
chan[i].stopOnOff=false;
|
||||||
}
|
}
|
||||||
if (dispatch->keyOffAffectsPorta(i)) {
|
if (disCont[dispatchOfChan[i]].dispatch->keyOffAffectsPorta(dispatchChanOfChan[i])) {
|
||||||
chan[i].portaNote=-1;
|
chan[i].portaNote=-1;
|
||||||
chan[i].portaSpeed=-1;
|
chan[i].portaSpeed=-1;
|
||||||
if (i==2 && song.system[0]==DIV_SYSTEM_SMS) {
|
if (i==2 && sysOfChan[i]==DIV_SYSTEM_SMS) {
|
||||||
chan[i+1].portaNote=-1;
|
chan[i+1].portaNote=-1;
|
||||||
chan[i+1].portaSpeed=-1;
|
chan[i+1].portaSpeed=-1;
|
||||||
}
|
}
|
||||||
|
@ -361,7 +362,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
chan[i].oldNote=chan[i].note;
|
chan[i].oldNote=chan[i].note;
|
||||||
chan[i].note=pat->data[whatRow][0]+pat->data[whatRow][1]*12;
|
chan[i].note=pat->data[whatRow][0]+pat->data[whatRow][1]*12;
|
||||||
if (!chan[i].keyOn) {
|
if (!chan[i].keyOn) {
|
||||||
if (dispatch->keyOffAffectsArp(i)) {
|
if (disCont[dispatchOfChan[i]].dispatch->keyOffAffectsArp(dispatchChanOfChan[i])) {
|
||||||
chan[i].arp=0;
|
chan[i].arp=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,7 +429,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
chan[i].portaSpeed=-1;
|
chan[i].portaSpeed=-1;
|
||||||
chan[i].inPorta=false;
|
chan[i].inPorta=false;
|
||||||
} else {
|
} else {
|
||||||
chan[i].portaNote=dispatch->getPortaFloor(i);
|
chan[i].portaNote=disCont[dispatchOfChan[i]].dispatch->getPortaFloor(dispatchChanOfChan[i]);
|
||||||
chan[i].portaSpeed=effectVal;
|
chan[i].portaSpeed=effectVal;
|
||||||
chan[i].portaStop=true;
|
chan[i].portaStop=true;
|
||||||
chan[i].nowYouCanStop=false;
|
chan[i].nowYouCanStop=false;
|
||||||
|
@ -507,7 +508,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
break;
|
break;
|
||||||
case 0xe5: // pitch
|
case 0xe5: // pitch
|
||||||
chan[i].pitch=effectVal-0x80;
|
chan[i].pitch=effectVal-0x80;
|
||||||
if (song.system[0]==DIV_SYSTEM_ARCADE) { // arcade pitch oddity
|
if (sysOfChan[i]==DIV_SYSTEM_ARCADE) { // arcade pitch oddity
|
||||||
chan[i].pitch*=2;
|
chan[i].pitch*=2;
|
||||||
if (chan[i].pitch<-128) chan[i].pitch=-128;
|
if (chan[i].pitch<-128) chan[i].pitch=-128;
|
||||||
if (chan[i].pitch>127) chan[i].pitch=127;
|
if (chan[i].pitch>127) chan[i].pitch=127;
|
||||||
|
@ -708,11 +709,15 @@ bool DivEngine::nextTick(bool noAccum) {
|
||||||
divider=50;
|
divider=50;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cycles=dispatch->rate/divider;
|
|
||||||
clockDrift+=dispatch->rate%divider;
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
if (clockDrift>=divider) {
|
DivDispatchContainer& dc=dispatch[i];
|
||||||
clockDrift-=divider;
|
dc.cycles=dc.dispatch->rate/divider;
|
||||||
cycles++;
|
dc.clockDrift+=dc.dispatch->rate%divider;
|
||||||
|
if (dc.clockDrift>=divider) {
|
||||||
|
dc.clockDrift-=divider;
|
||||||
|
dc.cycles++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!pendingNotes.empty()) {
|
while (!pendingNotes.empty()) {
|
||||||
|
@ -813,7 +818,7 @@ bool DivEngine::nextTick(bool noAccum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// system tick
|
// system tick
|
||||||
dispatch->tick();
|
for (int i=0; i<song.systemLen; i++) disCont[i].dispatch->tick();
|
||||||
|
|
||||||
if (!freelance) {
|
if (!freelance) {
|
||||||
if (!noAccum) totalTicks++;
|
if (!noAccum) totalTicks++;
|
||||||
|
@ -837,6 +842,13 @@ bool DivEngine::nextTick(bool noAccum) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: all of this!
|
||||||
|
// PLAYBACK LOGIC:
|
||||||
|
// 1. end of buffer for all chips? if so quit
|
||||||
|
// 2. are all chips clocked yet?
|
||||||
|
// if not clock them until possible and try again
|
||||||
|
// 3. engine tick
|
||||||
|
|
||||||
void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size) {
|
void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size) {
|
||||||
if (out!=NULL) {
|
if (out!=NULL) {
|
||||||
memset(out[0],0,size*sizeof(float));
|
memset(out[0],0,size*sizeof(float));
|
||||||
|
@ -869,10 +881,12 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!playing || dispatch==NULL) {
|
if (!playing) {
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// logic starts here
|
||||||
size_t runtotal=blip_clocks_needed(bb[0],size);
|
size_t runtotal=blip_clocks_needed(bb[0],size);
|
||||||
|
|
||||||
if (runtotal>bbInLen) {
|
if (runtotal>bbInLen) {
|
||||||
|
|
|
@ -1713,9 +1713,6 @@ void FurnaceGUI::editAdvance() {
|
||||||
void FurnaceGUI::prepareUndo(ActionType action) {
|
void FurnaceGUI::prepareUndo(ActionType action) {
|
||||||
int order=e->getOrder();
|
int order=e->getOrder();
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case GUI_ACTION_CHANGE_SYSTEM:
|
|
||||||
oldSystem=e->song.system[0];
|
|
||||||
break;
|
|
||||||
case GUI_ACTION_CHANGE_ORDER:
|
case GUI_ACTION_CHANGE_ORDER:
|
||||||
oldOrders=e->song.orders;
|
oldOrders=e->song.orders;
|
||||||
oldOrdersLen=e->song.ordersLen;
|
oldOrdersLen=e->song.ordersLen;
|
||||||
|
@ -1744,13 +1741,6 @@ void FurnaceGUI::makeUndo(ActionType action) {
|
||||||
s.order=order;
|
s.order=order;
|
||||||
s.nibble=curNibble;
|
s.nibble=curNibble;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case GUI_ACTION_CHANGE_SYSTEM:
|
|
||||||
if (oldSystem!=e->song.system[0]) {
|
|
||||||
s.oldSystem=oldSystem;
|
|
||||||
s.newSystem=e->song.system[0];
|
|
||||||
doPush=true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GUI_ACTION_CHANGE_ORDER:
|
case GUI_ACTION_CHANGE_ORDER:
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<32; i++) {
|
||||||
for (int j=0; j<128; j++) {
|
for (int j=0; j<128; j++) {
|
||||||
|
@ -2085,10 +2075,6 @@ void FurnaceGUI::doUndo() {
|
||||||
modified=true;
|
modified=true;
|
||||||
|
|
||||||
switch (us.type) {
|
switch (us.type) {
|
||||||
case GUI_ACTION_CHANGE_SYSTEM:
|
|
||||||
e->changeSystem(us.oldSystem);
|
|
||||||
updateWindowTitle();
|
|
||||||
break;
|
|
||||||
case GUI_ACTION_CHANGE_ORDER:
|
case GUI_ACTION_CHANGE_ORDER:
|
||||||
e->song.ordersLen=us.oldOrdersLen;
|
e->song.ordersLen=us.oldOrdersLen;
|
||||||
for (UndoOrderData& i: us.ord) {
|
for (UndoOrderData& i: us.ord) {
|
||||||
|
@ -2126,10 +2112,6 @@ void FurnaceGUI::doRedo() {
|
||||||
modified=true;
|
modified=true;
|
||||||
|
|
||||||
switch (us.type) {
|
switch (us.type) {
|
||||||
case GUI_ACTION_CHANGE_SYSTEM:
|
|
||||||
e->changeSystem(us.newSystem);
|
|
||||||
updateWindowTitle();
|
|
||||||
break;
|
|
||||||
case GUI_ACTION_CHANGE_ORDER:
|
case GUI_ACTION_CHANGE_ORDER:
|
||||||
e->song.ordersLen=us.newOrdersLen;
|
e->song.ordersLen=us.newOrdersLen;
|
||||||
for (UndoOrderData& i: us.ord) {
|
for (UndoOrderData& i: us.ord) {
|
||||||
|
@ -2575,10 +2557,8 @@ void FurnaceGUI::processDrags(int dragX, int dragY) {
|
||||||
|
|
||||||
#define sysChangeOption(x) \
|
#define sysChangeOption(x) \
|
||||||
if (ImGui::MenuItem(e->getSystemName(x),NULL,e->song.system[0]==x)) { \
|
if (ImGui::MenuItem(e->getSystemName(x),NULL,e->song.system[0]==x)) { \
|
||||||
prepareUndo(GUI_ACTION_CHANGE_SYSTEM); \
|
e->changeSystem(0,x); \
|
||||||
e->changeSystem(x); \
|
|
||||||
updateWindowTitle(); \
|
updateWindowTitle(); \
|
||||||
makeUndo(GUI_ACTION_CHANGE_SYSTEM); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FurnaceGUI::loop() {
|
bool FurnaceGUI::loop() {
|
||||||
|
|
|
@ -87,7 +87,6 @@ struct SelectionPoint {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ActionType {
|
enum ActionType {
|
||||||
GUI_ACTION_CHANGE_SYSTEM,
|
|
||||||
GUI_ACTION_CHANGE_ORDER,
|
GUI_ACTION_CHANGE_ORDER,
|
||||||
GUI_ACTION_PATTERN_EDIT,
|
GUI_ACTION_PATTERN_EDIT,
|
||||||
GUI_ACTION_PATTERN_DELETE,
|
GUI_ACTION_PATTERN_DELETE,
|
||||||
|
|
Loading…
Reference in New Issue