mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +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:
parent
90bf6565d0
commit
40339a12e1
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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_;
|
||||
|
Loading…
Reference in New Issue
Block a user