mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-25 18:30:21 +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:
parent
c6e046253e
commit
3e65450a54
@ -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++)
|
||||
{
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user