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

Formalised the use of a cycles count with a divider, bringing a few additional plain-int users into the fold.

This commit is contained in:
Thomas Harte 2017-07-25 07:15:31 -04:00
parent 90bf6565d0
commit 40339a12e1
6 changed files with 22 additions and 23 deletions

View File

@ -151,11 +151,10 @@ template <class T> class MOS6560: public ClockReceiver<MOS6560<T>> {
Runs for cycles. Derr.
*/
inline void run_for(const Cycles &cycles) {
int number_of_cycles = cycles.as_int();
// keep track of the amount of time since the speaker was updated; lazy updates are applied
cycles_since_speaker_update_ += (unsigned int)number_of_cycles;
cycles_since_speaker_update_ += cycles;
int number_of_cycles = cycles.as_int();
while(number_of_cycles--) {
// keep an old copy of the vertical count because that test is a cycle later than the actual changes
int previous_vertical_counter = vertical_counter_;
@ -409,10 +408,9 @@ template <class T> class MOS6560: public ClockReceiver<MOS6560<T>> {
std::shared_ptr<Outputs::CRT::CRT> crt_;
std::shared_ptr<Speaker> speaker_;
unsigned int cycles_since_speaker_update_;
Cycles cycles_since_speaker_update_;
void update_audio() {
speaker_->run_for(Cycles((int)cycles_since_speaker_update_ >> 2));
cycles_since_speaker_update_ &= 3;
speaker_->run_for(Cycles(cycles_since_speaker_update_.divide(Cycles(4))));
}
// register state

View File

@ -68,6 +68,11 @@ template <class T> class WrappedInt {
inline operator bool() const { return !!length_; }
inline int as_int() const { return length_; }
inline T divide(const T &divisor) {
T result(length_ / divisor);
length_ %= divisor;
return result;
}
// operator int() is deliberately not provided, to avoid accidental subtitution of
// classes that use this template.

View File

@ -36,11 +36,9 @@ class Bus {
protected:
// speaker backlog accumlation counter
unsigned int cycles_since_speaker_update_;
Cycles cycles_since_speaker_update_;
inline void update_audio() {
unsigned int audio_cycles = cycles_since_speaker_update_ / (CPUTicksPerAudioTick * 3);
cycles_since_speaker_update_ %= (CPUTicksPerAudioTick * 3);
speaker_->run_for(Cycles((int)audio_cycles));
speaker_->run_for(cycles_since_speaker_update_.divide(Cycles(CPUTicksPerAudioTick * 3)));
}
// video backlog accumulation counter

View File

@ -29,19 +29,19 @@ template<class T> class Cartridge:
// to satisfy CPU::MOS6502::Processor
unsigned int perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
uint8_t returnValue = 0xff;
unsigned int cycles_run_for = 3;
int cycles_run_for = 3;
// this occurs as a feedback loop — the 2600 requests ready, then performs the cycles_run_for
// leap to the end of ready only once ready is signalled — because on a 6502 ready doesn't take
// effect until the next read; therefore it isn't safe to assume that signalling ready immediately
// skips to the end of the line.
if(operation == CPU::MOS6502::BusOperation::Ready)
cycles_run_for = (unsigned int)tia_->get_cycles_until_horizontal_blank(cycles_since_video_update_);
cycles_run_for = tia_->get_cycles_until_horizontal_blank(cycles_since_video_update_);
cycles_since_speaker_update_ += cycles_run_for;
cycles_since_video_update_ += (int)cycles_run_for;
cycles_since_6532_update_ += (int)(cycles_run_for / 3);
static_cast<T *>(this)->advance_cycles(cycles_run_for / 3);
cycles_since_speaker_update_ += Cycles(cycles_run_for);
cycles_since_video_update_ += Cycles(cycles_run_for);
cycles_since_6532_update_ += Cycles(cycles_run_for / 3);
static_cast<T *>(this)->advance_cycles((unsigned int)cycles_run_for / 3);
if(operation != CPU::MOS6502::BusOperation::Ready) {
// give the cartridge a chance to respond to the bus access
@ -158,7 +158,7 @@ template<class T> class Cartridge:
if(!tia_->get_cycles_until_horizontal_blank(cycles_since_video_update_)) CPU::MOS6502::Processor<Cartridge<T>>::set_ready_line(false);
return cycles_run_for / 3;
return (unsigned int)(cycles_run_for / 3);
}
void flush() {

View File

@ -316,8 +316,8 @@ unsigned int Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation
}
cycles_since_display_update_ += Cycles((int)cycles);
cycles_since_audio_update_ += cycles;
if(cycles_since_audio_update_ > 16384) update_audio();
cycles_since_audio_update_ += Cycles((int)cycles);
if(cycles_since_audio_update_ > Cycles(16384)) update_audio();
tape_.run_for(Cycles((int)cycles));
cycles_until_display_interrupt_ -= cycles;
@ -365,9 +365,7 @@ inline void Machine::queue_next_display_interrupt() {
inline void Machine::update_audio() {
if(cycles_since_audio_update_) {
unsigned int difference = cycles_since_audio_update_ / Speaker::clock_rate_divider;
cycles_since_audio_update_ %= Speaker::clock_rate_divider;
speaker_->run_for(Cycles((int)difference));
speaker_->run_for(cycles_since_audio_update_.divide(Cycles(Speaker::clock_rate_divider)));
}
}

View File

@ -129,7 +129,7 @@ class Machine:
// Counters related to simultaneous subsystems
Cycles cycles_since_display_update_;
unsigned int cycles_since_audio_update_;
Cycles cycles_since_audio_update_;
int cycles_until_display_interrupt_;
Interrupt next_display_interrupt_;
VideoOutput::Range video_access_range_;