also enable backward on Windows XP

This commit is contained in:
tildearrow 2024-02-04 02:05:00 -05:00
parent b3b84d41b6
commit 4df1c59698
6 changed files with 201 additions and 53 deletions

View file

@ -15,7 +15,7 @@ fi
cd xpbuild
# TODO: potential Arch-ism?
i686-w64-mingw32-cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_FLAGS="-O2" -DCMAKE_CXX_FLAGS="-O2 -Wall -Wextra -Wno-unused-parameter -Wno-cast-function-type" -DBUILD_SHARED_LIBS=OFF -DSUPPORT_XP=ON -DWITH_RENDER_DX11=OFF -DSDL_SSE2=OFF -DSDL_SSE3=OFF -DENABLE_SSE=OFF -DENABLE_SSE2=OFF -DENABLE_AVX=OFF -DENABLE_AVX2=OFF .. || exit 1
i686-w64-mingw32-cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_FLAGS="-O2" -DCMAKE_CXX_FLAGS="-O2 -Wall -Wextra -Wno-unused-parameter -Wno-cast-function-type" -DBUILD_SHARED_LIBS=OFF -DSUPPORT_XP=ON -DWITH_RENDER_DX11=OFF -DSDL_SSE2=OFF -DSDL_SSE3=OFF -DENABLE_SSE=OFF -DENABLE_SSE2=OFF -DENABLE_AVX=OFF -DENABLE_AVX2=OFF -DUSE_BACKWARD=ON .. || exit 1
make -j8 || exit 1
cd ..

View file

@ -25,7 +25,7 @@
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER 32
#define CHIP_DIVIDER 8
const char* regCheatSheetDave[]={
"Freq0", "00",
@ -48,36 +48,54 @@ const char* regCheatSheetDave[]={
NULL
};
const unsigned char snapPeriodLong[15]={
0, 1, 3, 3, 3, 6, 6, 7, 7, 10, 10, 12, 12, 13, 13
};
const unsigned char snapPeriodShort[15]={
2, 2, 2, 2, 5, 5, 5, 8, 8, 8, 11, 11, 11, 11, 11
};
const unsigned char waveMap[8]={
0, 1, 1, 2, 3, 0, 0, 0
};
const char** DivPlatformDave::getRegisterSheet() {
return regCheatSheetDave;
}
void DivPlatformDave::acquire(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
// PCM part
for (int i=4; i<6; i++) {
if (chan[i].dacSample!=-1) {
chan[i].dacPeriod+=chan[i].dacRate;
chan[i].dacPeriod+=chan[i].freq;
if (chan[i].dacPeriod>rate) {
DivSample* s=parent->getSample(chan[i].dacSample);
if (s->samples<=0) {
chan[i].dacSample=-1;
writeControl=true;
chan[0].writeVol=true;
continue;
}
signed char dacData=((signed char)((unsigned char)s->data8[chan[i].dacPos]^0x80))>>3;
chan[i].dacOut=CLAMP(dacData,-16,15);
signed char dacData=(s->data8[chan[i].dacPos]*chan[i].outVol)>>8;
chan[i].dacOut=dacData+32;
chan[i].dacPos++;
if (!isMuted[i]) {
rWrite(8+((i-4)<<2),chan[i].dacOut&0x3f);
}
if (s->isLoopable() && chan[i].dacPos>=(unsigned int)s->loopEnd) {
chan[i].dacPos=s->loopStart;
} else if (chan[i].dacPos>=s->samples) {
chan[i].dacSample=-1;
writeControl=true;
chan[0].writeVol=true;
}
chan[i].dacPeriod-=rate;
}
}
}
while (!writes.empty()) {
if (!writes.empty()) {
QueuedWrite w=writes.front();
dave->writePort(w.addr,w.val);
regPool[w.addr&0x1f]=w.val;
@ -101,18 +119,24 @@ void DivPlatformDave::tick(bool sysTick) {
chan[i].writeVol=true;
}
if (chan[i].std.duty.had) {
chan[i].noiseFreq=chan[i].std.duty.val&3;
chan[i].freqChanged=true;
}
if (NEW_ARP_STRAT) {
chan[i].handleArp();
} else if (chan[i].std.arp.had) {
if (!chan[i].inPorta) {
chan[i].baseFreq=parent->calcArp(chan[i].note,chan[i].std.arp.val);
if (i>=4) {
chan[i].baseFreq=parent->calcBaseFreq(1,1,parent->calcArp(chan[i].note,chan[i].std.arp.val),false);
} else {
chan[i].baseFreq=NOTE_PERIODIC(parent->calcArp(chan[i].note,chan[i].std.arp.val));
}
}
chan[i].freqChanged=true;
}
if (chan[i].std.wave.had) {
chan[i].wave=chan[i].std.wave.val;
chan[i].wave=chan[i].std.wave.val&7;
if (i==3 && chan[i].wave>3) chan[i].wave=3;
chan[i].freqChanged=true;
}
if (chan[i].std.panL.had) {
@ -124,6 +148,13 @@ void DivPlatformDave::tick(bool sysTick) {
if (chan[i].std.panL.had || chan[i].std.panR.had) {
chan[i].writeVol=true;
}
if (chan[i].std.ex1.had) {
chan[i].highPass=chan[i].std.ex1.val&1;
chan[i].ringMod=chan[i].std.ex1.val&2;
chan[i].swapCounters=chan[i].std.ex1.val&4;
chan[i].lowPass=chan[i].std.ex1.val&8;
chan[i].freqChanged=true;
}
if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val;
@ -140,53 +171,135 @@ void DivPlatformDave::tick(bool sysTick) {
chan[i].dacPeriod=0;
chan[i].keyOn=true;
}
} else {
chan[i].resetPhase=true;
writeControl=true;
}
}
if (chan[i].writeVol) {
if (chan[i].active) {
rWrite(8+i,(63+chan[i].outVol*chan[i].panL)>>6);
rWrite(12+i,(63+chan[i].outVol*chan[i].panR)>>6);
} else {
rWrite(8+i,0);
rWrite(12+i,0);
if (i<4) {
if (chan[i].active && !isMuted[i]) {
if (i!=0 || chan[4].dacSample<0) {
rWrite(8+i,(63+chan[i].outVol*chan[i].panL)>>6);
}
if (i!=0 || chan[5].dacSample<0) {
rWrite(12+i,(63+chan[i].outVol*chan[i].panR)>>6);
}
} else {
if (i!=0 || chan[4].dacSample<0) {
rWrite(8+i,0);
}
if (i!=0 || chan[5].dacSample<0) {
rWrite(12+i,0);
}
}
}
chan[i].writeVol=false;
}
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_PCE);
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<1) chan[i].freq=1;
if (chan[i].freq>4095) chan[i].freq=4095;
if (i>=4) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,0,chan[i].pitch2,1,1);
} 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 (i<3) {
rWrite((i<<1),chan[i].freq&0xff);
rWrite(1+(i<<1),(chan[i].freq>>8)|((chan[i].wave&3)<<4));
switch (chan[i].wave) {
case 0:
chan[i].freq>>=2;
break;
case 1:
chan[i].freq/=5;
chan[i].freq>>=1;
break;
case 2:
chan[i].freq/=15;
chan[i].freq>>=1;
break;
case 3:
chan[i].freq/=63;
break;
case 4:
chan[i].freq>>=5;
break;
}
}
if (chan[i].keyOn) {
if (i<4) {
if (chan[i].freq<1) chan[i].freq=1;
if (chan[i].freq>4095) chan[i].freq=4095;
}
if (chan[i].keyOff) {
if (i<3) {
if (chan[i].wave==1) { // short 1
chan[i].freq=15*(chan[i].freq/15)+snapPeriodShort[(chan[i].freq%15)];
} else if (chan[i].wave==2) { // long 1
chan[i].freq=15*(chan[i].freq/15)+snapPeriodLong[(chan[i].freq%15)];
} else if (chan[i].wave==3) { // long 2 (30, 61, 92, 123... result in silence)
if ((chan[i].freq%30)==(chan[i].freq/30)-1) chan[i].freq++;
}
rWrite((i<<1),chan[i].freq&0xff);
rWrite(1+(i<<1),(chan[i].freq>>8)|((waveMap[chan[i].wave])<<4)|(chan[i].highPass?0x40:0)|(chan[i].ringMod?0x80:0));
} else if (i==3) {
rWrite(6,(chan[i].noiseFreq&3)|((chan[i].wave&3)<<2)|(chan[i].swapCounters?0x10:0)|(chan[i].lowPass?0x20:0)|(chan[i].highPass?0x40:0)|(chan[i].ringMod?0x80:0));
}
if (chan[i].keyOn) chan[i].keyOn=false;
if (chan[i].keyOff) chan[i].keyOff=false;
chan[i].freqChanged=false;
}
}
if (writeControl) {
rWrite(7,(chan[0].resetPhase?1:0)|(chan[1].resetPhase?2:0)|(chan[2].resetPhase?4:0)|((chan[4].dacSample>=0)?8:0)|((chan[5].dacSample>=0)?16:0));
rWrite(7,((chan[4].dacSample>=0)?8:0)|((chan[5].dacSample>=0)?16:0));
chan[0].resetPhase=false;
chan[1].resetPhase=false;
chan[2].resetPhase=false;
chan[3].resetPhase=false;
writeControl=false;
}
}
int DivPlatformDave::dispatch(DivCommand c) {
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_PCE);
// TODO: handle DAC
if (c.chan>=4) break;
chan[c.chan].sampleNote=DIV_NOTE_NULL;
chan[c.chan].sampleNoteDelta=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
DivInstrument* ins=NULL;
// DAC
if (c.chan>=4) {
ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].dacSample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
chan[c.chan].dacSample=ins->amiga.getSample(chan[c.chan].sampleNote);
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
if (chan[c.chan].dacSample<0 || chan[c.chan].dacSample>=parent->song.sampleLen) {
chan[c.chan].dacSample=-1;
chan[0].writeVol=true;
}
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
chan[c.chan].dacPos=0;
chan[c.chan].dacPeriod=0;
writeControl=true;
} else {
ins=parent->getIns(chan[c.chan].ins,DIV_INS_DAVE);
chan[c.chan].sampleNote=DIV_NOTE_NULL;
chan[c.chan].sampleNoteDelta=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
@ -202,6 +315,11 @@ int DivPlatformDave::dispatch(DivCommand c) {
chan[c.chan].active=false;
chan[c.chan].keyOff=true;
chan[c.chan].writeVol=true;
if (c.chan>=4) {
chan[c.chan].dacSample=-1;
chan[0].writeVol=true;
writeControl=true;
}
chan[c.chan].macroInit(NULL);
break;
case DIV_CMD_NOTE_OFF_ENV:
@ -220,6 +338,7 @@ int DivPlatformDave::dispatch(DivCommand c) {
if (!chan[c.chan].std.vol.has) {
chan[c.chan].outVol=c.value;
if (chan[c.chan].active) {
chan[c.chan].writeVol=true;
}
}
}
@ -236,7 +355,7 @@ int DivPlatformDave::dispatch(DivCommand c) {
break;
case DIV_CMD_WAVE:
chan[c.chan].wave=c.value;
chan[c.chan].keyOn=true;
chan[c.chan].freqChanged=true;
break;
case DIV_CMD_NOTE_PORTA: {
int destFreq=NOTE_PERIODIC(c.value2+chan[c.chan].sampleNoteDelta);
@ -267,13 +386,13 @@ int DivPlatformDave::dispatch(DivCommand c) {
break;
}
case DIV_CMD_LEGATO:
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)));
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+chan[c.chan].sampleNoteDelta);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
break;
case DIV_CMD_PRE_PORTA:
if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_PCE));
if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_DAVE));
}
if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note);
chan[c.chan].inPorta=c.value;
@ -298,14 +417,16 @@ int DivPlatformDave::dispatch(DivCommand c) {
void DivPlatformDave::muteChannel(int ch, bool mute) {
isMuted[ch]=mute;
// TODO
chan[ch].writeVol=true;
}
void DivPlatformDave::forceIns() {
for (int i=0; i<6; i++) {
chan[i].insChanged=true;
chan[i].freqChanged=true;
chan[i].writeVol=true;
}
writeControl=true;
}
void* DivPlatformDave::getChanState(int ch) {
@ -364,16 +485,8 @@ void DivPlatformDave::reset() {
if (dumpWrites) {
addWrite(0xffffffff,0);
}
writeControl=false;
dave->reset(true);
lastPan=0xff;
cycles=0;
curChan=-1;
// set global volume
rWrite(0,0);
rWrite(0x01,0xff);
// set per-channel initial panning
for (int i=0; i<6; i++) {
}
}
int DivPlatformDave::getOutputCount() {

View file

@ -29,10 +29,11 @@ class DivPlatformDave: public DivDispatch {
int dacPeriod, dacRate, dacOut;
unsigned int dacPos;
int dacSample;
unsigned char noiseFreq;
unsigned char panL;
unsigned char panR;
unsigned char wave;
bool writeVol;
bool writeVol, highPass, ringMod, swapCounters, lowPass, resetPhase;
Channel():
SharedChannel<signed char>(63),
dacPeriod(0),
@ -40,10 +41,16 @@ class DivPlatformDave: public DivDispatch {
dacOut(0),
dacPos(0),
dacSample(-1),
noiseFreq(0),
panL(63),
panR(63),
wave(0),
writeVol(false) {}
writeVol(false),
highPass(false),
ringMod(false),
swapCounters(false),
lowPass(false),
resetPhase(false) {}
};
Channel chan[6];
DivDispatchOscBuffer* oscBuf[6];
@ -55,9 +62,8 @@ class DivPlatformDave: public DivDispatch {
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
FixedQueue<QueuedWrite,512> writes;
unsigned char lastPan;
bool writeControl;
int cycles, curChan;
Ep128::Dave* dave;
unsigned char regPool[32];
friend void putDispatchChip(void*,int);

View file

@ -2003,7 +2003,7 @@ void DivEngine::registerSystems() {
);
sysDefs[DIV_SYSTEM_DAVE]=new DivSysDef(
"Dave", NULL, 0xd5, 0, 6, false, true, 0, false, 0, 0, 0,
"Dave", NULL, 0xd5, 0, 6, false, true, 0, false, 1U<<DIV_SAMPLE_DEPTH_8BIT, 0, 0,
"this chip was featured in the Enterprise 128 computer. it is similar to POKEY, but with stereo output.",
{"Channel 1", "Channel 2", "Channel 3", "Noise", "DAC Left", "DAC Right"},
{"CH1", "CH2", "CH3", "NO", "L", "R"},

View file

@ -336,6 +336,10 @@ const char* powerNoiseSlopeControlBits[7]={
"invert B", "invert A", "reset B", "reset A", "clip B", "clip A", NULL
};
const char* daveControlBits[5]={
"high pass", "ring mod", "swap counters (noise)", "low pass (noise)", NULL
};
const char* panBits[5]={
"right", "left", "rear right", "rear left", NULL
};
@ -6916,6 +6920,10 @@ void FurnaceGUI::drawInsEdit() {
if (ins->type==DIV_INS_POWERNOISE_SLOPE) {
dutyMax=0;
}
if (ins->type==DIV_INS_DAVE) {
dutyLabel="Noise Freq";
dutyMax=3;
}
const char* waveLabel="Waveform";
int waveMax=(ins->type==DIV_INS_VERA)?3:(MAX(1,e->song.waveLen-1));
@ -6953,7 +6961,7 @@ void FurnaceGUI::drawInsEdit() {
if (ins->type==DIV_INS_POWERNOISE) waveMax=0;
if (ins->type==DIV_INS_POWERNOISE_SLOPE) waveMax=0;
if (ins->type==DIV_INS_SU || ins->type==DIV_INS_POKEY) waveMax=7;
if (ins->type==DIV_INS_DAVE) waveMax=3;
if (ins->type==DIV_INS_DAVE) waveMax=4;
if (ins->type==DIV_INS_PET) {
waveMax=8;
waveBitMode=true;
@ -7020,12 +7028,15 @@ void FurnaceGUI::drawInsEdit() {
ex1Max=5;
ex2Max=11;
}
if (ins->type==DIV_INS_DAVE) {
ex1Max=4;
}
int panMin=0;
int panMax=0;
bool panSingle=false;
bool panSingleNoBit=false;
if (ins->type==DIV_INS_STD ||//Game Gear
if (ins->type==DIV_INS_STD || // Game Gear
ins->type==DIV_INS_FM ||
ins->type==DIV_INS_OPM ||
ins->type==DIV_INS_GB ||
@ -7097,6 +7108,9 @@ void FurnaceGUI::drawInsEdit() {
if (ins->type==DIV_INS_POWERNOISE_SLOPE) {
panMax=15;
}
if (ins->type==DIV_INS_DAVE) {
panMax=63;
}
if (volMax>0) {
macroList.push_back(FurnaceGUIMacroDesc(volumeLabel,&ins->std.volMacro,volMin,volMax,160,uiColors[GUI_COLOR_MACRO_VOLUME]));
@ -7186,7 +7200,8 @@ void FurnaceGUI::drawInsEdit() {
ins->type==DIV_INS_TED ||
ins->type==DIV_INS_ESFM ||
ins->type==DIV_INS_POWERNOISE ||
ins->type==DIV_INS_POWERNOISE_SLOPE) {
ins->type==DIV_INS_POWERNOISE_SLOPE ||
ins->type==DIV_INS_DAVE) {
macroList.push_back(FurnaceGUIMacroDesc("Phase Reset",&ins->std.phaseResetMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true));
}
if (ex1Max>0) {
@ -7220,6 +7235,8 @@ void FurnaceGUI::drawInsEdit() {
macroList.push_back(FurnaceGUIMacroDesc("Special",&ins->std.ex1Macro,0,ex1Max,96,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,snesModeBits));
} else if (ins->type==DIV_INS_MSM5232) {
macroList.push_back(FurnaceGUIMacroDesc("Group Attack",&ins->std.ex1Macro,0,ex1Max,96,uiColors[GUI_COLOR_MACRO_OTHER]));
} else if (ins->type==DIV_INS_DAVE) {
macroList.push_back(FurnaceGUIMacroDesc("Control",&ins->std.ex1Macro,0,ex1Max,64,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true,daveControlBits));
} else {
macroList.push_back(FurnaceGUIMacroDesc("Duty",&ins->std.ex1Macro,0,ex1Max,160,uiColors[GUI_COLOR_MACRO_OTHER]));
}

View file

@ -952,6 +952,12 @@ void FurnaceGUI::initSystemPresets() {
CH(DIV_SYSTEM_SAA1099, 1.0f, 0, "")
}
);
ENTRY(
"Enterprise 128", {
CH(DIV_SYSTEM_DAVE, 1.0f, 0, "")
},
"tickRate=50"
);
ENTRY(
"BBC Micro", {
CH(DIV_SYSTEM_SMS, 1.0f, 0,
@ -2778,6 +2784,12 @@ void FurnaceGUI::initSystemPresets() {
CH(DIV_SYSTEM_POWERNOISE, 1.0f, 0, "")
}
);
ENTRY(
"Dave", {
CH(DIV_SYSTEM_DAVE, 1.0f, 0, "")
},
"tickRate=50"
);
CATEGORY_END;
CATEGORY_BEGIN("DefleMask-compatible","these configurations are compatible with DefleMask.\nselect this if you need to save as .dmf or work with that program.");