T6W28: finish it up (mostly)
This commit is contained in:
parent
88444e6f59
commit
843d18290d
|
@ -25,8 +25,6 @@
|
||||||
//#define rWrite(a,v) pendingWrites[a]=v;
|
//#define rWrite(a,v) pendingWrites[a]=v;
|
||||||
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
|
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
|
||||||
|
|
||||||
#define CHIP_DIVIDER 16
|
|
||||||
|
|
||||||
const char* regCheatSheetT6W28[]={
|
const char* regCheatSheetT6W28[]={
|
||||||
"Data0", "0",
|
"Data0", "0",
|
||||||
"Data1", "1",
|
"Data1", "1",
|
||||||
|
@ -72,14 +70,21 @@ void DivPlatformT6W28::acquire(short* bufL, short* bufR, size_t start, size_t le
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformT6W28::writeOutVol(int ch) {
|
void DivPlatformT6W28::writeOutVol(int ch) {
|
||||||
int left=15-CLAMP(chan[ch].outVol+chan[ch].panL-15,0,15);
|
if (chan[ch].active) {
|
||||||
int right=15-CLAMP(chan[ch].outVol+chan[ch].panR-15,0,15);
|
int left=15-CLAMP(chan[ch].outVol+chan[ch].panL-15,0,15);
|
||||||
rWrite(0,0x90|(ch<<5)|(isMuted[ch]?15:left));
|
int right=15-CLAMP(chan[ch].outVol+chan[ch].panR-15,0,15);
|
||||||
rWrite(1,0x90|(ch<<5)|(isMuted[ch]?15:right));
|
rWrite(0,0x90|(ch<<5)|(isMuted[ch]?15:left));
|
||||||
|
rWrite(1,0x90|(ch<<5)|(isMuted[ch]?15:right));
|
||||||
|
} else {
|
||||||
|
rWrite(0,0x9f|(ch<<5));
|
||||||
|
rWrite(1,0x9f|(ch<<5));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformT6W28::tick(bool sysTick) {
|
void DivPlatformT6W28::tick(bool sysTick) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
|
double CHIP_DIVIDER=16;
|
||||||
|
if (i==3) CHIP_DIVIDER=15;
|
||||||
chan[i].std.next();
|
chan[i].std.next();
|
||||||
if (chan[i].std.vol.had) {
|
if (chan[i].std.vol.had) {
|
||||||
chan[i].outVol=VOL_SCALE_LOG(chan[i].vol&15,MIN(15,chan[i].std.vol.val),15);
|
chan[i].outVol=VOL_SCALE_LOG(chan[i].vol&15,MIN(15,chan[i].std.vol.val),15);
|
||||||
|
@ -91,6 +96,12 @@ void DivPlatformT6W28::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
}
|
}
|
||||||
|
if (i==3 && chan[i].std.duty.had) {
|
||||||
|
if (chan[i].duty!=chan[i].std.duty.val) {
|
||||||
|
chan[i].duty=chan[i].std.duty.val&7;
|
||||||
|
rWrite(1,0xe0+chan[i].duty);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (chan[i].std.panL.had) {
|
if (chan[i].std.panL.had) {
|
||||||
chan[i].panL=chan[i].std.panL.val&15;
|
chan[i].panL=chan[i].std.panL.val&15;
|
||||||
}
|
}
|
||||||
|
@ -109,12 +120,13 @@ void DivPlatformT6W28::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
}
|
}
|
||||||
|
if (chan[i].std.phaseReset.had) {
|
||||||
|
rWrite(1,0xe0+chan[i].duty);
|
||||||
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
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,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
|
||||||
if (chan[i].freq>1023) chan[i].freq=1023;
|
if (chan[i].freq>1023) chan[i].freq=1023;
|
||||||
if (i==3) {
|
if (i==3) {
|
||||||
rWrite(1,0xe7);
|
|
||||||
rWrite(1,0x80|(2<<5)|(chan[3].freq&15));
|
rWrite(1,0x80|(2<<5)|(chan[3].freq&15));
|
||||||
rWrite(1,chan[3].freq>>4);
|
rWrite(1,chan[3].freq>>4);
|
||||||
} else {
|
} else {
|
||||||
|
@ -129,6 +141,8 @@ void DivPlatformT6W28::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivPlatformT6W28::dispatch(DivCommand c) {
|
int DivPlatformT6W28::dispatch(DivCommand c) {
|
||||||
|
double CHIP_DIVIDER=16;
|
||||||
|
if (c.chan==3) CHIP_DIVIDER=15;
|
||||||
switch (c.cmd) {
|
switch (c.cmd) {
|
||||||
case DIV_CMD_NOTE_ON: {
|
case DIV_CMD_NOTE_ON: {
|
||||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_PCE);
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_PCE);
|
||||||
|
@ -142,6 +156,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) {
|
||||||
chan[c.chan].macroInit(ins);
|
chan[c.chan].macroInit(ins);
|
||||||
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
|
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
|
||||||
chan[c.chan].outVol=chan[c.chan].vol;
|
chan[c.chan].outVol=chan[c.chan].vol;
|
||||||
|
writeOutVol(c.chan);
|
||||||
}
|
}
|
||||||
chan[c.chan].insChanged=false;
|
chan[c.chan].insChanged=false;
|
||||||
break;
|
break;
|
||||||
|
@ -150,6 +165,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) {
|
||||||
chan[c.chan].active=false;
|
chan[c.chan].active=false;
|
||||||
chan[c.chan].keyOff=true;
|
chan[c.chan].keyOff=true;
|
||||||
chan[c.chan].macroInit(NULL);
|
chan[c.chan].macroInit(NULL);
|
||||||
|
writeOutVol(c.chan);
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_NOTE_OFF_ENV:
|
case DIV_CMD_NOTE_OFF_ENV:
|
||||||
case DIV_CMD_ENV_RELEASE:
|
case DIV_CMD_ENV_RELEASE:
|
||||||
|
@ -166,8 +182,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) {
|
||||||
chan[c.chan].vol=c.value;
|
chan[c.chan].vol=c.value;
|
||||||
if (!chan[c.chan].std.vol.has) {
|
if (!chan[c.chan].std.vol.has) {
|
||||||
chan[c.chan].outVol=c.value;
|
chan[c.chan].outVol=c.value;
|
||||||
if (chan[c.chan].active) {
|
writeOutVol(c.chan);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -205,7 +220,9 @@ int DivPlatformT6W28::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_STD_NOISE_MODE:
|
case DIV_CMD_STD_NOISE_MODE:
|
||||||
chan[c.chan].noise=c.value;
|
if (c.chan!=3) break;
|
||||||
|
chan[c.chan].duty=(((c.value&15)==1)?4:0)|((c.value>>4)&3);
|
||||||
|
rWrite(1,0xe0+chan[c.chan].duty);
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_PANNING: {
|
case DIV_CMD_PANNING: {
|
||||||
chan[c.chan].panL=c.value>>4;
|
chan[c.chan].panL=c.value>>4;
|
||||||
|
@ -226,7 +243,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) {
|
||||||
chan[c.chan].inPorta=c.value;
|
chan[c.chan].inPorta=c.value;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_GET_VOLMAX:
|
case DIV_CMD_GET_VOLMAX:
|
||||||
return 31;
|
return 15;
|
||||||
break;
|
break;
|
||||||
case DIV_ALWAYS_SET_VOLUME:
|
case DIV_ALWAYS_SET_VOLUME:
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -289,6 +306,8 @@ void DivPlatformT6W28::reset() {
|
||||||
cycles=0;
|
cycles=0;
|
||||||
curChan=-1;
|
curChan=-1;
|
||||||
delay=0;
|
delay=0;
|
||||||
|
// default noise mode
|
||||||
|
rWrite(1,0xe7);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivPlatformT6W28::isStereo() {
|
bool DivPlatformT6W28::isStereo() {
|
||||||
|
|
|
@ -29,8 +29,8 @@ class DivPlatformT6W28: public DivDispatch {
|
||||||
struct Channel {
|
struct Channel {
|
||||||
int freq, baseFreq, pitch, pitch2, note;
|
int freq, baseFreq, pitch, pitch2, note;
|
||||||
int ins;
|
int ins;
|
||||||
unsigned char panL, panR;
|
unsigned char panL, panR, duty;
|
||||||
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, noise;
|
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta;
|
||||||
signed char vol, outVol;
|
signed char vol, outVol;
|
||||||
DivMacroInt std;
|
DivMacroInt std;
|
||||||
void macroInit(DivInstrument* which) {
|
void macroInit(DivInstrument* which) {
|
||||||
|
@ -46,13 +46,13 @@ class DivPlatformT6W28: public DivDispatch {
|
||||||
ins(-1),
|
ins(-1),
|
||||||
panL(15),
|
panL(15),
|
||||||
panR(15),
|
panR(15),
|
||||||
|
duty(7),
|
||||||
active(false),
|
active(false),
|
||||||
insChanged(true),
|
insChanged(true),
|
||||||
freqChanged(false),
|
freqChanged(false),
|
||||||
keyOn(false),
|
keyOn(false),
|
||||||
keyOff(false),
|
keyOff(false),
|
||||||
inPorta(false),
|
inPorta(false),
|
||||||
noise(false),
|
|
||||||
vol(15),
|
vol(15),
|
||||||
outVol(15) {}
|
outVol(15) {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1664,7 +1664,7 @@ void DivEngine::registerSystems() {
|
||||||
{DIV_INS_T6W28, DIV_INS_T6W28, DIV_INS_T6W28, DIV_INS_T6W28},
|
{DIV_INS_T6W28, DIV_INS_T6W28, DIV_INS_T6W28, DIV_INS_T6W28},
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
{0x20, {DIV_CMD_STD_NOISE_MODE, "20xy: Set noise mode (x: preset/variable; y: thin pulse/noise)"}}
|
{0x20, {DIV_CMD_STD_NOISE_MODE, "20xy: Set noise mode (x: 0-2 for preset, 3 for tonal; y: thin pulse/noise)"}}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -4693,6 +4693,10 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
dutyLabel="Pulse Width";
|
dutyLabel="Pulse Width";
|
||||||
dutyMax=255;
|
dutyMax=255;
|
||||||
}
|
}
|
||||||
|
if (ins->type==DIV_INS_T6W28) {
|
||||||
|
dutyLabel="Noise Type/Freq";
|
||||||
|
dutyMax=7;
|
||||||
|
}
|
||||||
if (ins->type==DIV_INS_AY8930) {
|
if (ins->type==DIV_INS_AY8930) {
|
||||||
dutyMax=ins->amiga.useSample?0:255;
|
dutyMax=ins->amiga.useSample?0:255;
|
||||||
}
|
}
|
||||||
|
@ -4973,6 +4977,7 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
ins->type==DIV_INS_SU ||
|
ins->type==DIV_INS_SU ||
|
||||||
ins->type==DIV_INS_MIKEY ||
|
ins->type==DIV_INS_MIKEY ||
|
||||||
ins->type==DIV_INS_ES5506 ||
|
ins->type==DIV_INS_ES5506 ||
|
||||||
|
ins->type==DIV_INS_T6W28 ||
|
||||||
(ins->type==DIV_INS_X1_010 && ins->amiga.useSample)) {
|
(ins->type==DIV_INS_X1_010 && ins->amiga.useSample)) {
|
||||||
macroList.push_back(FurnaceGUIMacroDesc("Phase Reset",&ins->std.phaseResetMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true));
|
macroList.push_back(FurnaceGUIMacroDesc("Phase Reset",&ins->std.phaseResetMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true));
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,6 +270,12 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Toshiba T6W28", {
|
||||||
|
DIV_SYSTEM_T6W28, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"AY-3-8910", {
|
"AY-3-8910", {
|
||||||
DIV_SYSTEM_AY8910, 64, 0, 0,
|
DIV_SYSTEM_AY8910, 64, 0, 0,
|
||||||
|
|
Loading…
Reference in New Issue