1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-04 18:29:40 +00:00

Converted the 6560 fully into a template; worked on allowing the typer to run at a much faster rate where hardware has some trigger by which it can request the next key.

This commit is contained in:
Thomas Harte 2016-08-06 14:33:24 -04:00
parent c6e046253e
commit 3e65450a54
6 changed files with 54 additions and 43 deletions

View File

@ -10,19 +10,19 @@
using namespace MOS;
MOS6560::Speaker::Speaker() :
Speaker::Speaker() :
_volume(0),
_control_registers{0, 0, 0, 0},
_shift_registers{0, 0, 0, 0},
_counters{2, 1, 0, 0} // create a slight phase offset for the three channels
{}
void MOS6560::Speaker::set_volume(uint8_t volume)
void Speaker::set_volume(uint8_t volume)
{
_volume = volume;
}
void MOS6560::Speaker::set_control(int channel, uint8_t value)
void Speaker::set_control(int channel, uint8_t value)
{
_control_registers[channel] = value;
}
@ -99,7 +99,7 @@ static uint8_t noise_pattern[] = {
#define increment(r) _shift_registers[r] = (_shift_registers[r]+1)%8191;
#define update(r, m, up) _counters[r]++; if((_counters[r] >> m) == 0x7f) { up(r); _counters[r] = _control_registers[r]&0x7f; }
void MOS6560::Speaker::get_samples(unsigned int number_of_samples, int16_t *target)
void Speaker::get_samples(unsigned int number_of_samples, int16_t *target)
{
for(unsigned int c = 0; c < number_of_samples; c++)
{
@ -119,7 +119,7 @@ void MOS6560::Speaker::get_samples(unsigned int number_of_samples, int16_t *targ
}
}
void MOS6560::Speaker::skip_samples(unsigned int number_of_samples)
void Speaker::skip_samples(unsigned int number_of_samples)
{
for(unsigned int c = 0; c < number_of_samples; c++)
{

View File

@ -14,6 +14,24 @@
namespace MOS {
// audio state
class Speaker: public ::Outputs::Filter<Speaker> {
public:
Speaker();
void set_volume(uint8_t volume);
void set_control(int channel, uint8_t value);
void get_samples(unsigned int number_of_samples, int16_t *target);
void skip_samples(unsigned int number_of_samples);
private:
unsigned int _counters[4];
unsigned int _shift_registers[4];
uint8_t _control_registers[4];
uint8_t _volume;
};
/*!
The 6560 Video Interface Chip ('VIC') is a video and audio output chip; it therefore vends both a @c CRT and a @c Speaker.
@ -22,7 +40,7 @@ namespace MOS {
@c set_register and @c get_register provide register access.
*/
class MOS6560 {
template <class T> class MOS6560 {
public:
MOS6560() :
_crt(new Outputs::CRT::CRT(65*4, 4, Outputs::CRT::NTSC60, 1)),
@ -395,23 +413,6 @@ class MOS6560 {
private:
std::shared_ptr<Outputs::CRT::CRT> _crt;
// audio state
class Speaker: public ::Outputs::Filter<Speaker> {
public:
Speaker();
void set_volume(uint8_t volume);
void set_control(int channel, uint8_t value);
void get_samples(unsigned int number_of_samples, int16_t *target);
void skip_samples(unsigned int number_of_samples);
private:
unsigned int _counters[4];
unsigned int _shift_registers[4];
uint8_t _control_registers[4];
uint8_t _volume;
};
std::shared_ptr<Speaker> _speaker;
unsigned int _cycles_since_speaker_update;
void update_audio()

View File

@ -128,7 +128,11 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
_userPortVIA->run_for_half_cycles(2);
_keyboardVIA->run_for_half_cycles(2);
if(_typer) _typer->update(1);
if(_typer && operation == CPU6502::BusOperation::ReadOpcode && address == 0xEB1E)
{
if(!_typer->type_next_character())
_typer.reset();
}
_tape.run_for_cycles(1);
if(_c1540) _c1540->run_for_cycles(1);
return 1;
@ -146,7 +150,7 @@ void Machine::mos6522_did_change_interrupt_status(void *mos6522)
void Machine::setup_output(float aspect_ratio)
{
_mos6560.reset(new MOS::MOS6560());
_mos6560.reset(new Vic6560());
}
void Machine::close_output()
@ -164,14 +168,9 @@ void Machine::set_rom(ROMSlot slot, size_t length, const uint8_t *data)
case Characters: target = _characterROM; max_length = 0x1000; break;
case BASIC: target = _basicROM; break;
case Drive:
if(_c1540)
_c1540->set_rom(data);
else
{
// if there's no 1540 now, hold onto the ROM in case one is added later
_driveROM.reset(new uint8_t[length]);
memcpy(_driveROM.get(), data, length);
}
_driveROM.reset(new uint8_t[length]);
memcpy(_driveROM.get(), data, length);
install_disk_rom();
return;
}
@ -204,7 +203,7 @@ void Machine::add_prg(size_t length, const uint8_t *data)
void Machine::set_tape(std::shared_ptr<Storage::Tape> tape)
{
_tape.set_tape(tape);
set_typer_for_string("LOAD\n");
set_typer_for_string("LOAD\nRUN\n");
}
void Machine::tape_did_change_input(Tape *tape)
@ -226,13 +225,19 @@ void Machine::set_disk(std::shared_ptr<Storage::Disk> disk)
_c1540->set_disk(disk);
// install the ROM if it was previously set
if(_driveROM)
install_disk_rom();
set_typer_for_string("LOAD\"*\",8,1\nRUN\n");
}
void Machine::install_disk_rom()
{
if(_driveROM && _c1540)
{
_c1540->set_rom(_driveROM.get());
_c1540->run_for_cycles(2000000);
_driveROM.reset();
}
set_typer_for_string("LOAD\"*\",8,1\n");
}
#pragma mark - Typer

View File

@ -225,6 +225,7 @@ class Tape: public Storage::TapePlayer {
bool _input_level;
};
class Vic6560: public MOS::MOS6560<Vic6560> {};
class Machine:
public CPU6502::Processor<Machine>,
@ -294,7 +295,7 @@ class Machine:
uint8_t *_processorWriteMemoryMap[64];
void write_to_map(uint8_t **map, uint8_t *area, uint16_t address, uint16_t length);
std::unique_ptr<MOS::MOS6560> _mos6560;
std::unique_ptr<Vic6560> _mos6560;
std::shared_ptr<UserPortVIA> _userPortVIA;
std::shared_ptr<KeyboardVIA> _keyboardVIA;
std::shared_ptr<SerialPort> _serialPort;
@ -305,8 +306,9 @@ class Machine:
Tape _tape;
bool _use_fast_tape_hack;
// Disc
// Disk
std::shared_ptr<::Commodore::C1540::Machine> _c1540;
void install_disk_rom();
};
}

View File

@ -32,8 +32,10 @@ void Typer::update(int duration)
}
}
void Typer::type_next_character()
bool Typer::type_next_character()
{
if(_string == nullptr) return false;
if(_delegate->typer_set_next_character(this, _string[_string_pointer], _phase))
{
_phase = 0;
@ -41,7 +43,7 @@ void Typer::type_next_character()
{
free(_string);
_string = nullptr;
return;
return false;
}
_string_pointer++;
@ -50,6 +52,8 @@ void Typer::type_next_character()
{
_phase++;
}
return true;
}
Typer::~Typer()

View File

@ -23,6 +23,7 @@ class Typer {
Typer(const char *string, int delay, int frequency, Delegate *delegate);
~Typer();
void update(int duration);
bool type_next_character();
private:
char *_string;
@ -31,8 +32,6 @@ class Typer {
int _phase;
Delegate *_delegate;
size_t _string_pointer;
void type_next_character();
};
class TypeRecipient: public Typer::Delegate {