C64: use full cutoff/duty range

this means .dmf becomes a second-class citizen since it only supports a
range of 0-100 (yeah) for arbitrary reasons...

the last bit to do is add effect that allows you to use the full range
This commit is contained in:
tildearrow 2022-01-09 17:00:52 -05:00
parent 4bbfc22c2a
commit 9b6db75d4f
4 changed files with 19 additions and 15 deletions

View file

@ -691,7 +691,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
ins->c64.s=reader.readC();
ins->c64.r=reader.readC();
ins->c64.duty=reader.readC();
ins->c64.duty=(reader.readC()*4095)/100;
ins->c64.ringMod=reader.readC();
ins->c64.oscSync=reader.readC();
@ -704,7 +704,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
ins->c64.initFilter=reader.readC();
ins->c64.res=reader.readC();
ins->c64.cut=reader.readC();
ins->c64.cut=(reader.readC()*2047)/100;
ins->c64.hp=reader.readC();
ins->c64.bp=reader.readC();
ins->c64.lp=reader.readC();
@ -1534,7 +1534,7 @@ SafeWriter* DivEngine::saveFur() {
w->writeC(ins->c64.d);
w->writeC(ins->c64.s);
w->writeC(ins->c64.r);
w->writeS((ins->c64.duty*4096)/100);
w->writeS(ins->c64.duty);
w->writeC(ins->c64.ringMod);
w->writeC(ins->c64.oscSync);
w->writeC(ins->c64.toFilter);
@ -1545,7 +1545,7 @@ SafeWriter* DivEngine::saveFur() {
w->writeC(ins->c64.bp);
w->writeC(ins->c64.hp);
w->writeC(ins->c64.ch3off);
w->writeS((ins->c64.cut*2047)/100);
w->writeS(ins->c64.cut);
w->writeC(ins->c64.dutyIsAbs);
w->writeC(ins->c64.filterIsAbs);
@ -1783,7 +1783,8 @@ SafeWriter* DivEngine::saveDMF() {
w->writeC(i->c64.s);
w->writeC(i->c64.r);
w->writeC(i->c64.duty);
logW("duty and cutoff precision will be lost!\n");
w->writeC((i->c64.duty*100)/4095);
w->writeC(i->c64.ringMod);
w->writeC(i->c64.oscSync);
@ -1793,7 +1794,7 @@ SafeWriter* DivEngine::saveDMF() {
w->writeC(i->c64.initFilter);
w->writeC(i->c64.res);
w->writeC(i->c64.cut);
w->writeC((i->c64.cut*100)/2047);
w->writeC(i->c64.hp);
w->writeC(i->c64.bp);
w->writeC(i->c64.lp);

View file

@ -116,10 +116,11 @@ struct DivInstrumentGB {
struct DivInstrumentC64 {
bool triOn, sawOn, pulseOn, noiseOn;
unsigned char a, d, s, r;
unsigned char duty;
unsigned short duty;
unsigned char ringMod, oscSync;
bool toFilter, volIsCutoff, initFilter, dutyIsAbs, filterIsAbs;
unsigned char res, cut;
unsigned char res;
unsigned short cut;
bool hp, lp, bp, ch3off;
DivInstrumentC64():
@ -131,7 +132,7 @@ struct DivInstrumentC64 {
d(8),
s(0),
r(0),
duty(50),
duty(2048),
ringMod(0),
oscSync(0),
toFilter(false),

View file

@ -100,7 +100,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
if (chan[c.chan].insChanged || chan[c.chan].resetDuty || ins->std.waveMacroLen>0) {
chan[c.chan].duty=(ins->c64.duty*4095)/100;
chan[c.chan].duty=ins->c64.duty;
rWrite(c.chan*7+2,chan[c.chan].duty&0xff);
rWrite(c.chan*7+3,chan[c.chan].duty>>8);
}
@ -116,7 +116,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
if (chan[c.chan].insChanged || chan[c.chan].resetFilter) {
chan[c.chan].filter=ins->c64.toFilter;
if (ins->c64.initFilter) {
filtCut=ins->c64.cut*2047/100;
filtCut=ins->c64.cut;
filtRes=ins->c64.res;
filtControl=ins->c64.lp|(ins->c64.bp<<1)|(ins->c64.hp<<2)|(ins->c64.ch3off<<3);
updateFilter();
@ -229,7 +229,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
case DIV_CMD_C64_FILTER_RESET:
if (c.value&15) {
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
filtCut=ins->c64.cut*2047/100;
filtCut=ins->c64.cut;
updateFilter();
}
chan[c.chan].resetFilter=c.value>>4;
@ -237,7 +237,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
case DIV_CMD_C64_DUTY_RESET:
if (c.value&15) {
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
chan[c.chan].duty=(ins->c64.duty*4095)/100;
chan[c.chan].duty=ins->c64.duty;
rWrite(c.chan*7+2,chan[c.chan].duty&0xff);
rWrite(c.chan*7+3,chan[c.chan].duty>>8);
}

View file

@ -38,6 +38,8 @@ const int _THIRTY_ONE=31;
const int _SIXTY_FOUR=64;
const int _ONE_HUNDRED=100;
const int _ONE_HUNDRED_TWENTY_SEVEN=127;
const int _TWO_THOUSAND_FORTY_SEVEN=2047;
const int _FOUR_THOUSAND_NINETY_FIVE=4095;
const FurnaceGUIColors fxColors[16]={
GUI_COLOR_PATTERN_EFFECT_MISC, // 00
@ -666,7 +668,7 @@ void FurnaceGUI::drawInsEdit() {
ImGui::SliderScalar("Decay",ImGuiDataType_U8,&ins->c64.d,&_ZERO,&_FIFTEEN);
ImGui::SliderScalar("Sustain",ImGuiDataType_U8,&ins->c64.s,&_ZERO,&_FIFTEEN);
ImGui::SliderScalar("Release",ImGuiDataType_U8,&ins->c64.r,&_ZERO,&_FIFTEEN);
ImGui::SliderScalar("Duty",ImGuiDataType_U8,&ins->c64.duty,&_ZERO,&_ONE_HUNDRED);
ImGui::SliderScalar("Duty",ImGuiDataType_U16,&ins->c64.duty,&_ZERO,&_FOUR_THOUSAND_NINETY_FIVE);
bool ringMod=ins->c64.ringMod;
if (ImGui::Checkbox("Ring Modulation",&ringMod)) ins->c64.ringMod=ringMod;
@ -676,7 +678,7 @@ void FurnaceGUI::drawInsEdit() {
ImGui::Checkbox("Enable filter",&ins->c64.toFilter);
ImGui::Checkbox("Initialize filter",&ins->c64.initFilter);
ImGui::SliderScalar("Cutoff",ImGuiDataType_U8,&ins->c64.cut,&_ZERO,&_ONE_HUNDRED);
ImGui::SliderScalar("Cutoff",ImGuiDataType_U16,&ins->c64.cut,&_ZERO,&_TWO_THOUSAND_FORTY_SEVEN);
ImGui::SliderScalar("Resonance",ImGuiDataType_U8,&ins->c64.res,&_ZERO,&_FIFTEEN);
ImGui::Text("Filter Mode");