src/apu/apu.cc
/*
 * Updates the DMC channel, filling the buffer and updating the level as
 * necessary. May optionally generate an IRQ when a sample finishes.
 */
Updates the DMC channel, filling the buffer and updating the level as
necessary. May optionally generate an IRQ when a sample finishes.
Updates the DMC channel filling the buffer and updating the level as necessary . May optionally generate an IRQ when a sample finishes .
void Apu::UpdateDmc(void) {
  if (dmc_->clock >= dmc_rates[dmc_->rate]) {
    dmc_->clock = 0;
  } else {
    dmc_->clock++;
    return;
  }
  if ((dmc_->bits_remaining == 0) && (dmc_->bytes_remaining > 0)) {
    dmc_->sample_buffer = memory_->Read(dmc_->current_addr);
    dmc_->current_addr = (dmc_->current_addr + 1) | DMC_CURRENT_ADDR_BASE;
    dmc_->bytes_remaining--;
    dmc_->silent = false;
    if ((dmc_->bytes_remaining == 0) && (dmc_->control & FLAG_DMC_LOOP)) {
      dmc_->current_addr = dmc_->addr;
      dmc_->bytes_remaining = dmc_->length;
    } else if ((dmc_->bytes_remaining == 0) && (dmc_->control & FLAG_DMC_IRQ)
                                            && !dmc_irq_) {
      dmc_irq_ = true;
      (*irq_line_)++;
    }
  } else if ((dmc_->bits_remaining == 0) && (dmc_->bytes_remaining == 0)) {
    dmc_->silent = true;
  }
  dmc_->bits_remaining = (dmc_->bits_remaining > 0)
                       ? dmc_->bits_remaining - 1 : 7;
  if (!(dmc_->silent)) {
    if ((dmc_->sample_buffer & 1) && (dmc_->level <= (DMC_LEVEL_MAX - 2))) {
      dmc_->level += 2;
    } else if (!(dmc_->sample_buffer & 1) && (dmc_->level >= 2)) {
      dmc_->level -= 2;
    }
  }
  dmc_->sample_buffer >>= 1;
  return;
}
void Apu :: UpdateDmc ( void ) { if ( dmc_ -> clock >= dmc_rates [ dmc_ -> rate ] ) { dmc_ -> clock = 0 ; } else { dmc_ -> clock ++ ; return ; } if ( ( dmc_ -> bits_remaining == 0 ) && ( dmc_ -> bytes_remaining > 0 ) ) { dmc_ -> sample_buffer = memory_ -> Read ( dmc_ -> current_addr ) ; dmc_ -> current_addr = ( dmc_ -> current_addr + 1 ) | DMC_CURRENT_ADDR_BASE ; dmc_ -> bytes_remaining -- ; dmc_ -> silent = false ; if ( ( dmc_ -> bytes_remaining == 0 ) && ( dmc_ -> control & FLAG_DMC_LOOP ) ) { dmc_ -> current_addr = dmc_ -> addr ; dmc_ -> bytes_remaining = dmc_ -> length ; } else if ( ( dmc_ -> bytes_remaining == 0 ) && ( dmc_ -> control & FLAG_DMC_IRQ ) && ! dmc_irq_ ) { dmc_irq_ = true ; ( * irq_line_ ) ++ ; } } else if ( ( dmc_ -> bits_remaining == 0 ) && ( dmc_ -> bytes_remaining == 0 ) ) { dmc_ -> silent = true ; } dmc_ -> bits_remaining = ( dmc_ -> bits_remaining > 0 ) ? dmc_ -> bits_remaining - 1 : 7 ; if ( ! ( dmc_ -> silent ) ) { if ( ( dmc_ -> sample_buffer & 1 ) && ( dmc_ -> level <= ( DMC_LEVEL_MAX - 2 ) ) ) { dmc_ -> level += 2 ; } else if ( ! ( dmc_ -> sample_buffer & 1 ) && ( dmc_ -> level >= 2 ) ) { dmc_ -> level -= 2 ; } } dmc_ -> sample_buffer >>= 1 ; return ; }
Updates the DMC channel, filling the buffer and updating the level as
 necessary.
Updates the DMC channel filling the buffer and updating the level as necessary .
// Check if it is time for the DMC channel to update. // Refill the sample buffer if it is empty. // TODO: Stall CPU. // Load the next word into the sample buffer. // Send an IRQ if dmc IRQ's are eneabled and the sample has ended. // Use the sample buffer to update the dmc level.