Hey guys, sorry if this has been covered, but I'm a little stumped on my DMC implementation and wanted to see if any of you guys have any insight. I'm trying to get the APU "just right", and seem unable to get my DMC to pass even the "basic operations" test, so obviously I'm misunderstanding something. Here's what I believe happens:
* 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:
Any thoughts on where I am going wrong?
* 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:
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;
}
}
}
}
}
}
}
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;
}
}
}
}
}
}
}
Any thoughts on where I am going wrong?