* The frequency is how many CPU cycles between DMC "ticks"
* Every time the DMC "ticks", if there are "bytes remaining" in the sample, then a DMA read might happen
* A DMA read happens if there are bytes remaining and the sample buffer is empty (AKA, every 8 ticks)
* After a read, bytes remaining is decremented, if it hits 0, we either STOP, IRQ, or LOOP.
Based on this, here's my current attempt at implementing the rules above, this function is called every CPU cycle:
Code: Select all
void DMC::tick() {
if(enabled()) {
if(frequency_ != 0) {
if(--frequency_ == 0) {
frequency_ = reload_frequency_;
if(bytes_remaining_ != 0) {
// read the 8-bit sample
if(bit_ == 0) {
// TODO: hijack the CPU for appropriate number of cycles
sample_buffer_ = nes::cpu.read(current_address_);
if(current_address_ == 0xffff) {
current_address_ = 0x8000;
} else {
++current_address_;
}
}
// TODO: grab appropriate bit from sample_buffer and update
bit_ = (bit_ + 1) % 8;
if(--bytes_remaining_ == 0) {
if(loop_) {
bytes_remaining_ = sample_length_;
current_address_ = sample_address_;
} else if(irq_enabled_) {
nes::cpu.irq(CPU::APU_IRQ);
nes::apu.status_ |= APU::STATUS_DMC_IRQ;
}
}
}
}
}
}
}