1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 01:31:42 +00:00

With no regard to performance whatsoever, endeavoured to bring sound to the 2600. It's very scratchy, so something is wrong.

This commit is contained in:
Thomas Harte 2016-06-02 19:50:16 -04:00
parent 1e0fcbbee8
commit 253e5a4203
4 changed files with 116 additions and 19 deletions

View File

@ -73,7 +73,7 @@ void Machine::setup_output(float aspect_ratio)
"}");
_crt->set_output_device(Outputs::CRT::Television);
_speaker.set_input_rate(2 * 263 * 60);
_speaker.set_input_rate(1194720 / 38);
}
void Machine::switch_region()
@ -93,7 +93,7 @@ void Machine::switch_region()
"}");
_crt->set_new_timing(228, 312, Outputs::CRT::ColourSpace::YUV, 228, 1);
_speaker.set_input_rate(2 * 312 * 50);
// _speaker.set_input_rate(2 * 312 * 50);
}
void Machine::close_output()
@ -692,6 +692,7 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
printf("!!!DDR!!!");
break;
case 0x04:
case 0x06:
returnValue &= _piaTimerValue >> _piaTimerShift;
if(_writtenPiaTimerShift != _piaTimerShift) {
@ -700,8 +701,9 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
}
break;
case 0x05:
case 0x07:
returnValue &= _piaTimerStatus;
_piaTimerStatus &= ~0x40;
_piaTimerStatus &= ~0x80;
break;
}
} else {
@ -711,9 +713,9 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
case 0x05:
case 0x06:
case 0x07:
_writtenPiaTimerShift = _piaTimerShift = (decodedAddress - 0x04) * 3 + (decodedAddress / 0x07);
_piaTimerValue = (unsigned int)(*value << _piaTimerShift);
_piaTimerStatus &= ~0xc0;
_writtenPiaTimerShift = _piaTimerShift = (decodedAddress - 0x04) * 3 + (decodedAddress / 0x07); // i.e. 0, 3, 6, 10
_piaTimerValue = (unsigned int)(*value) << _piaTimerShift;
_piaTimerStatus &= ~0x40;
break;
}
}
@ -727,7 +729,7 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
if(_piaTimerValue >= cycles_run_for / 3) {
_piaTimerValue -= cycles_run_for / 3;
} else {
_piaTimerValue += 0xff - cycles_run_for / 3;
_piaTimerValue = 0x100 + ((_piaTimerValue - (cycles_run_for / 3)) >> _piaTimerShift);
_piaTimerShift = 0;
_piaTimerStatus |= 0xc0;
}
@ -794,6 +796,17 @@ void Machine::synchronise()
update_audio();
}
Atari2600::Speaker::Speaker()
{
_poly4_counter[0] = _poly4_counter[1] =
_poly5_counter[0] = _poly5_counter[1] =
_poly9_counter[0] = _poly9_counter[1] = ~0;
}
Atari2600::Speaker::~Speaker()
{
}
void Atari2600::Speaker::set_volume(int channel, uint8_t volume)
{
_volume[channel] = volume & 0xf;
@ -808,8 +821,15 @@ void Atari2600::Speaker::set_divider(int channel, uint8_t divider)
void Atari2600::Speaker::set_control(int channel, uint8_t control)
{
_control[channel] = control & 0xf;
// _shift_counter[channel] = ~0;
// printf("%d\n", _control[channel]);
}
#define advance_poly4(c) _poly4_counter[channel] = (_poly4_counter[channel] >> 1) | (((_poly4_counter[channel] << 3) ^ (_poly4_counter[channel] << 2))&0x008)
#define advance_poly5(c) _poly5_counter[channel] = (_poly5_counter[channel] >> 1) | (((_poly5_counter[channel] << 4) ^ (_poly5_counter[channel] << 2))&0x010)
#define advance_poly9(c) _poly9_counter[channel] = (_poly9_counter[channel] >> 1) | (((_poly9_counter[channel] << 4) ^ (_poly9_counter[channel] << 8))&0x200)
void Atari2600::Speaker::get_samples(unsigned int number_of_samples, int16_t *target)
{
for(unsigned int c = 0; c < number_of_samples; c++)
@ -817,22 +837,89 @@ void Atari2600::Speaker::get_samples(unsigned int number_of_samples, int16_t *ta
target[c] = 0;
for(int channel = 0; channel < 2; channel++)
{
_divider_counter[channel] ++;
int level = 0;
switch(_control[channel])
{
case 0x0: case 0xb:
target[c] += _volume[channel] * 1024;
case 0x0: case 0xb: // constant 1
level = 1;
break;
case 0x4: case 0x5:
_divider_counter[channel] ++;
target[c] += _volume[channel] * 1024 * ((_divider_counter[channel] / (_divider[channel]+1))&1);
case 0x4: case 0x5: // div2 tone
level = (_divider_counter[channel] / (_divider[channel]+1))&1;
break;
case 0xc: case 0xd:
_divider_counter[channel] ++;
target[c] += _volume[channel] * 1024 * ((_divider_counter[channel] / ((_divider[channel]+1)*3))&1);
case 0xc: case 0xd: // div6 tone
level = (_divider_counter[channel] / ((_divider[channel]+1)*3))&1;
break;
case 0x6: case 0xa: // div31 tone
level = (_divider_counter[channel] / (_divider[channel]+1))%30 <= 18;
break;
case 0xe: // div93 tone
level = (_divider_counter[channel] / ((_divider[channel]+1)*3))%30 <= 18;
break;
case 0x1: // 4-bit poly
level = _poly4_counter[channel]&1;
if(_divider_counter[channel] == _divider[channel]+1)
{
_divider_counter[channel] = 0;
advance_poly4(channel);
}
break;
case 0x2: // 4-bit poly div31
level = _poly4_counter[channel]&1;
if(_divider_counter[channel]%(30*(_divider[channel]+1)) == 18)
{
advance_poly4(channel);
}
break;
case 0x3: // 5/4-bit poly
level = _output_state[channel];
if(_divider_counter[channel] == _divider[channel]+1)
{
if(_poly5_counter[channel]&1)
{
_output_state[channel] = _poly4_counter[channel]&1;
advance_poly4(channel);
}
advance_poly5(channel);
}
break;
case 0x7: case 0x9: // 5-bit poly
level = _poly5_counter[channel]&1;
if(_divider_counter[channel] == _divider[channel]+1)
{
_divider_counter[channel] = 0;
advance_poly5(channel);
}
break;
case 0xf: // 5-bit poly div6
level = _poly5_counter[channel]&1;
if(_divider_counter[channel] == (_divider[channel]+1)*3)
{
_divider_counter[channel] = 0;
advance_poly5(channel);
}
break;
case 0x8: // 9-bit poly
level = _poly9_counter[channel]&1;
if(_divider_counter[channel] == _divider[channel]+1)
{
_divider_counter[channel] = 0;
advance_poly9(channel);
}
break;
}
target[c] += _volume[channel] * 1024 * level;
}
}
}

View File

@ -21,6 +21,9 @@ const unsigned int number_of_recorded_counters = 7;
class Speaker: public ::Outputs::Filter<Speaker> {
public:
Speaker();
~Speaker();
void set_volume(int channel, uint8_t volume);
void set_divider(int channel, uint8_t divider);
void set_control(int channel, uint8_t control);
@ -32,9 +35,16 @@ class Speaker: public ::Outputs::Filter<Speaker> {
uint8_t _volume[2];
uint8_t _divider[2];
uint8_t _control[2];
int _shift_counter[2];
int _divider_counter[2];
int _poly4_counter[2];
int _poly5_counter[2];
int _poly9_counter[2];
int _output_state[2];
int _divider_counter[2];
int _pattern_periods[16];
int _patterns[16][512];
};
class Machine: public CPU6502::Processor<Machine>, public CRTMachine::Machine {

View File

@ -11,7 +11,7 @@
#define AudioQueueNumAudioBuffers 4
#define AudioQueueStreamLength 1024
#define AudioQueueBufferLength 256
#define AudioQueueBufferLength 512
enum {
AudioQueueCanProceed,

View File

@ -70,7 +70,7 @@ struct SpeakerDelegate: public Outputs::Speaker::Delegate {
Outputs::Speaker *speaker = self.machine->get_speaker();
if(speaker)
{
speaker->set_output_rate(sampleRate, 256);
speaker->set_output_rate(sampleRate, 512);
speaker->set_delegate(delegate);
return YES;
}