diff --git a/src/engine/platform/pv1000.cpp b/src/engine/platform/pv1000.cpp index d5f54e6a6..af4cae0c7 100644 --- a/src/engine/platform/pv1000.cpp +++ b/src/engine/platform/pv1000.cpp @@ -29,6 +29,7 @@ const char* regCheatSheetPV1000[]={ "CH1_Pitch", "00", "CH2_Pitch", "01", "CH3_Pitch", "02", + "Control", "03", NULL }; @@ -42,7 +43,7 @@ void DivPlatformPV1000::acquire(short** buf, size_t len) { samp=d65010g031_sound_tick(&d65010g031,1); buf[0][h]=samp; for (int i=0; i<3; i++) { - oscBuf[i]->data[oscBuf[i]->needle++]=(d65010g031.square[i].out<<12); + oscBuf[i]->data[oscBuf[i]->needle++]=(d65010g031.out[i]); } } } @@ -73,7 +74,7 @@ void DivPlatformPV1000::tick(bool sysTick) { } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { chan[i].freq=0x3f-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<0) chan[i].freq=0; if (chan[i].freq>62) chan[i].freq=62; if (isMuted[i]) chan[i].keyOn=false; if (chan[i].keyOn) { @@ -83,7 +84,7 @@ void DivPlatformPV1000::tick(bool sysTick) { rWrite(i,(isMuted[i] || (chan[i].outVol<=0)) ? 0 : chan[i].freq); } if (chan[i].keyOff) { - rWrite(i,0); + rWrite(i,0x3f); chan[i].keyOff=false; } chan[i].freqChanged=false; @@ -137,6 +138,13 @@ int DivPlatformPV1000::dispatch(DivCommand c) { chan[c.chan].pitch=c.value; chan[c.chan].freqChanged=true; break; + case DIV_CMD_WAVE: + if (c.value&1) { + rWrite(3,3); + } else { + rWrite(3,2); + } + break; case DIV_CMD_NOTE_PORTA: { int destFreq=NOTE_PERIODIC(c.value2); bool return2=false; @@ -224,16 +232,21 @@ unsigned char* DivPlatformPV1000::getRegisterPool() { } int DivPlatformPV1000::getRegisterPoolSize() { - return 3; + return 4; } void DivPlatformPV1000::reset() { - memset(regPool,0,3); + memset(regPool,0,4); for (int i=0; i<3; i++) { chan[i]=Channel(); chan[i].std.setEngine(parent); } d65010g031_reset(&d65010g031); + // mute + rWrite(0,0x3f); + rWrite(1,0x3f); + rWrite(2,0x3f); + rWrite(3,2); } int DivPlatformPV1000::getOutputCount() { diff --git a/src/engine/platform/pv1000.h b/src/engine/platform/pv1000.h index c32540763..852bf1204 100644 --- a/src/engine/platform/pv1000.h +++ b/src/engine/platform/pv1000.h @@ -33,7 +33,7 @@ class DivPlatformPV1000: public DivDispatch { DivDispatchOscBuffer* oscBuf[3]; bool isMuted[3]; - unsigned char regPool[3]; + unsigned char regPool[4]; d65010g031_t d65010g031; friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); diff --git a/src/engine/platform/sound/d65modified.c b/src/engine/platform/sound/d65modified.c index 8f53b34c8..5cd49f2fc 100644 --- a/src/engine/platform/sound/d65modified.c +++ b/src/engine/platform/sound/d65modified.c @@ -67,7 +67,7 @@ int d65010g031_square_tick(struct d65010g031_square_t *square, const int cycle) { if (square->period > 0) { - int period = d65010g031_max(1, (0x3f - square->period)); + const int period = square->period; square->counter += cycle; while (square->counter >= period) { @@ -92,7 +92,29 @@ int d65010g031_sound_tick(struct d65010g031_t *d65010g031, const int cycle) int out = 0; for (int i = 0; i < 3; i++) { - out += d65010g031_square_tick(&d65010g031->square[i], cycle)?d65Volumes[i]:-d65Volumes[i]; + d65010g031->out[i] = 0; + } + if (d65010g031->ctrl & 2) + { + if (d65010g031->ctrl & 1) + { + int sout[3] = { + d65010g031_square_tick(&d65010g031->square[0], cycle), + d65010g031_square_tick(&d65010g031->square[1], cycle), + d65010g031_square_tick(&d65010g031->square[2], cycle), + }; + d65010g031->out[0] = (sout[0] ^ sout[1]) ? d65Volumes[0] : -d65Volumes[0]; + d65010g031->out[1] = (sout[1] ^ sout[2]) ? d65Volumes[1] : -d65Volumes[1]; + d65010g031->out[2] = (sout[2] ? d65Volumes[2] : -d65Volumes[2]); + } + else + { + for (int i = 0; i < 3; i++) + { + d65010g031->out[i] = d65010g031_square_tick(&d65010g031->square[i], cycle)?d65Volumes[i]:-d65Volumes[i]; + } + } + out = d65010g031->out[0] + d65010g031->out[1] + d65010g031->out[2]; } return out; } @@ -105,12 +127,23 @@ void d65010g031_reset(struct d65010g031_t *d65010g031) d65010g031->square[i].counter = 0; d65010g031->square[i].out = 0; } + d65010g031->ctrl = 0; } void d65010g031_write(struct d65010g031_t *d65010g031, const unsigned char a, const unsigned char d) { - if (a < 3) + switch (a) { - d65010g031->square[a].period = d & 0x3f; + case 3: + d65010g031->ctrl = d; + break; + default: + const unsigned char period = ~d & 0x3f; + if ((period == 0) && (d65010g031->square[a].period != 0)) + { + d65010g031->square[a].out ^= 1; + } + d65010g031->square[a].period = period; + break; } } diff --git a/src/engine/platform/sound/d65modified.h b/src/engine/platform/sound/d65modified.h index 49dc13a15..eae0f8988 100644 --- a/src/engine/platform/sound/d65modified.h +++ b/src/engine/platform/sound/d65modified.h @@ -54,6 +54,8 @@ struct d65010g031_square_t struct d65010g031_t { struct d65010g031_square_t square[3]; + signed short out[3]; + unsigned char ctrl; }; int d65010g031_square_tick(struct d65010g031_square_t *square, const int cycle); diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index fbb718cb5..c9aef95ef 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -1839,7 +1839,11 @@ void DivEngine::registerSystems() { {"Square 1", "Square 2", "Square 3"}, {"S1", "S2", "S3"}, {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE}, - {DIV_INS_PV1000, DIV_INS_PV1000, DIV_INS_PV1000} + {DIV_INS_PV1000, DIV_INS_PV1000, DIV_INS_PV1000}, + {}, + { + {0x10, {DIV_CMD_WAVE, "10xx: Set waveform"}} + } ); sysDefs[DIV_SYSTEM_SFX_BEEPER_QUADTONE]=new DivSysDef(