Merge pull request #1063 from tildearrow/pv1000_xor
pv1000: Add ring modulation support
This commit is contained in:
		
						commit
						896941e4a8
					
				| 
						 | 
					@ -29,6 +29,7 @@ const char* regCheatSheetPV1000[]={
 | 
				
			||||||
  "CH1_Pitch", "00",
 | 
					  "CH1_Pitch", "00",
 | 
				
			||||||
  "CH2_Pitch", "01",
 | 
					  "CH2_Pitch", "01",
 | 
				
			||||||
  "CH3_Pitch", "02",
 | 
					  "CH3_Pitch", "02",
 | 
				
			||||||
 | 
					  "Control", "03",
 | 
				
			||||||
  NULL
 | 
					  NULL
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,11 +39,10 @@ const char** DivPlatformPV1000::getRegisterSheet() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DivPlatformPV1000::acquire(short** buf, size_t len) {
 | 
					void DivPlatformPV1000::acquire(short** buf, size_t len) {
 | 
				
			||||||
  for (size_t h=0; h<len; h++) {
 | 
					  for (size_t h=0; h<len; h++) {
 | 
				
			||||||
    short samp;
 | 
					    short samp=d65010g031_sound_tick(&d65010g031,1);
 | 
				
			||||||
    samp=d65010g031_sound_tick(&d65010g031,1);
 | 
					 | 
				
			||||||
    buf[0][h]=samp;
 | 
					    buf[0][h]=samp;
 | 
				
			||||||
    for (int i=0; i<3; i++) {
 | 
					    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,17 +73,17 @@ void DivPlatformPV1000::tick(bool sysTick) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
 | 
					    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);
 | 
					      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 (chan[i].freq>62) chan[i].freq=62;
 | 
				
			||||||
      if (isMuted[i]) chan[i].keyOn=false;
 | 
					      if (isMuted[i]) chan[i].keyOn=false;
 | 
				
			||||||
      if (chan[i].keyOn) {
 | 
					      if (chan[i].keyOn) {
 | 
				
			||||||
        rWrite(i,(isMuted[i] || (chan[i].outVol<=0)) ? 0 : chan[i].freq);
 | 
					        rWrite(i,(isMuted[i] || (chan[i].outVol<=0)) ? 0x3f : chan[i].freq);
 | 
				
			||||||
        chan[i].keyOn=false;
 | 
					        chan[i].keyOn=false;
 | 
				
			||||||
      } else if (chan[i].freqChanged && chan[i].active && !isMuted[i]) {
 | 
					      } else if (chan[i].freqChanged && chan[i].active && !isMuted[i]) {
 | 
				
			||||||
        rWrite(i,(isMuted[i] || (chan[i].outVol<=0)) ? 0 : chan[i].freq);
 | 
					        rWrite(i,(isMuted[i] || (chan[i].outVol<=0)) ? 0x3f : chan[i].freq);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (chan[i].keyOff) {
 | 
					      if (chan[i].keyOff) {
 | 
				
			||||||
        rWrite(i,0);
 | 
					        rWrite(i,0x3f);
 | 
				
			||||||
        chan[i].keyOff=false;
 | 
					        chan[i].keyOff=false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      chan[i].freqChanged=false;
 | 
					      chan[i].freqChanged=false;
 | 
				
			||||||
| 
						 | 
					@ -137,6 +137,13 @@ int DivPlatformPV1000::dispatch(DivCommand c) {
 | 
				
			||||||
      chan[c.chan].pitch=c.value;
 | 
					      chan[c.chan].pitch=c.value;
 | 
				
			||||||
      chan[c.chan].freqChanged=true;
 | 
					      chan[c.chan].freqChanged=true;
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
 | 
					    case DIV_CMD_STD_NOISE_MODE: // ring modulation
 | 
				
			||||||
 | 
					      if (c.value&1) {
 | 
				
			||||||
 | 
					        rWrite(3,3);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        rWrite(3,2);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
    case DIV_CMD_NOTE_PORTA: {
 | 
					    case DIV_CMD_NOTE_PORTA: {
 | 
				
			||||||
      int destFreq=NOTE_PERIODIC(c.value2);
 | 
					      int destFreq=NOTE_PERIODIC(c.value2);
 | 
				
			||||||
      bool return2=false;
 | 
					      bool return2=false;
 | 
				
			||||||
| 
						 | 
					@ -224,16 +231,21 @@ unsigned char* DivPlatformPV1000::getRegisterPool() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int DivPlatformPV1000::getRegisterPoolSize() {
 | 
					int DivPlatformPV1000::getRegisterPoolSize() {
 | 
				
			||||||
  return 3;
 | 
					  return 4;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DivPlatformPV1000::reset() {
 | 
					void DivPlatformPV1000::reset() {
 | 
				
			||||||
  memset(regPool,0,3);
 | 
					  memset(regPool,0,4);
 | 
				
			||||||
  for (int i=0; i<3; i++) {
 | 
					  for (int i=0; i<3; i++) {
 | 
				
			||||||
    chan[i]=Channel();
 | 
					    chan[i]=Channel();
 | 
				
			||||||
    chan[i].std.setEngine(parent);
 | 
					    chan[i].std.setEngine(parent);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  d65010g031_reset(&d65010g031);
 | 
					  d65010g031_reset(&d65010g031);
 | 
				
			||||||
 | 
					  // mute
 | 
				
			||||||
 | 
					  rWrite(0,0x3f);
 | 
				
			||||||
 | 
					  rWrite(1,0x3f);
 | 
				
			||||||
 | 
					  rWrite(2,0x3f);
 | 
				
			||||||
 | 
					  rWrite(3,2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int DivPlatformPV1000::getOutputCount() {
 | 
					int DivPlatformPV1000::getOutputCount() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@ class DivPlatformPV1000: public DivDispatch {
 | 
				
			||||||
  DivDispatchOscBuffer* oscBuf[3];
 | 
					  DivDispatchOscBuffer* oscBuf[3];
 | 
				
			||||||
  bool isMuted[3];
 | 
					  bool isMuted[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  unsigned char regPool[3];
 | 
					  unsigned char regPool[4];
 | 
				
			||||||
  d65010g031_t d65010g031;
 | 
					  d65010g031_t d65010g031;
 | 
				
			||||||
  friend void putDispatchChip(void*,int);
 | 
					  friend void putDispatchChip(void*,int);
 | 
				
			||||||
  friend void putDispatchChan(void*,int,int);
 | 
					  friend void putDispatchChan(void*,int,int);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,7 +67,7 @@ int d65010g031_square_tick(struct d65010g031_square_t *square, const int cycle)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (square->period > 0)
 | 
						if (square->period > 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int period = d65010g031_max(1, (0x3f - square->period));
 | 
							const int period = square->period;
 | 
				
			||||||
		square->counter += cycle;
 | 
							square->counter += cycle;
 | 
				
			||||||
		while (square->counter >= period)
 | 
							while (square->counter >= period)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
| 
						 | 
					@ -82,9 +82,9 @@ int d65010g031_square_tick(struct d65010g031_square_t *square, const int cycle)
 | 
				
			||||||
// this is the bit I altered
 | 
					// this is the bit I altered
 | 
				
			||||||
// THIS IS **NOT** THE ORIGINAL SOFTWARE! I am plainly marking it as such!
 | 
					// THIS IS **NOT** THE ORIGINAL SOFTWARE! I am plainly marking it as such!
 | 
				
			||||||
const int d65Volumes[3]={
 | 
					const int d65Volumes[3]={
 | 
				
			||||||
  3840,
 | 
					  3840, // -6dB
 | 
				
			||||||
  5120,
 | 
					  5120, // -3dB
 | 
				
			||||||
  8192
 | 
					  8192 // 0dB
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int d65010g031_sound_tick(struct d65010g031_t *d65010g031, const int cycle)
 | 
					int d65010g031_sound_tick(struct d65010g031_t *d65010g031, const int cycle)
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,29 @@ int d65010g031_sound_tick(struct d65010g031_t *d65010g031, const int cycle)
 | 
				
			||||||
	int out = 0;
 | 
						int out = 0;
 | 
				
			||||||
	for (int i = 0; i < 3; i++)
 | 
						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) // ring modulation
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								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;
 | 
						return out;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -105,12 +127,25 @@ void d65010g031_reset(struct d65010g031_t *d65010g031)
 | 
				
			||||||
		d65010g031->square[i].counter = 0;
 | 
							d65010g031->square[i].counter = 0;
 | 
				
			||||||
		d65010g031->square[i].out = 0;
 | 
							d65010g031->square[i].out = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						d65010g031->ctrl = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void d65010g031_write(struct d65010g031_t *d65010g031, const unsigned char a, const unsigned char d)
 | 
					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 per = (unsigned char)(~d) & 0x3f;
 | 
				
			||||||
 | 
								if ((per == 0) && (d65010g031->square[a].period != 0))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									d65010g031->square[a].out ^= 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								d65010g031->square[a].period = per;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,6 +54,8 @@ struct d65010g031_square_t
 | 
				
			||||||
struct d65010g031_t
 | 
					struct d65010g031_t
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct d65010g031_square_t square[3];
 | 
						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);
 | 
					int d65010g031_square_tick(struct d65010g031_square_t *square, const int cycle);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1839,7 +1839,11 @@ void DivEngine::registerSystems() {
 | 
				
			||||||
    {"Square 1", "Square 2", "Square 3"},
 | 
					    {"Square 1", "Square 2", "Square 3"},
 | 
				
			||||||
    {"S1", "S2", "S3"},
 | 
					    {"S1", "S2", "S3"},
 | 
				
			||||||
    {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE},
 | 
					    {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_STD_NOISE_MODE, "10xx: Set ring modulation (0: disable, 1: enable)"}}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  sysDefs[DIV_SYSTEM_SFX_BEEPER_QUADTONE]=new DivSysDef(
 | 
					  sysDefs[DIV_SYSTEM_SFX_BEEPER_QUADTONE]=new DivSysDef(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue