#ifndef apu_h #define apu_h #include #include #include "gb_struct_def.h" #ifdef GB_INTERNAL /* Divides nicely and never overflows with 4 channels */ #define MAX_CH_AMP 0x1E00 #define CH_STEP (MAX_CH_AMP/0xF) #endif /* Lengths are in either DIV ticks (256Hz, triggered by the DIV register) or APU ticks (2MHz, triggered by an internal APU clock)*/ typedef struct { int16_t left; int16_t right; } GB_sample_t; typedef struct { double left; double right; } GB_double_sample_t; enum GB_CHANNELS { GB_SQUARE_1, GB_SQUARE_2, GB_WAVE, GB_NOISE, GB_N_CHANNELS }; typedef struct { bool global_enable; uint8_t left_volume; uint8_t right_volume; uint8_t samples[GB_N_CHANNELS]; bool left_enabled[GB_N_CHANNELS]; bool right_enabled[GB_N_CHANNELS]; bool is_active[GB_N_CHANNELS]; struct { bool enable; // NR30 uint8_t pulse_length; // Reloaded from NR31 (xorred), in DIV ticks uint8_t shift; // NR32 uint16_t sample_length; // NR33, NR34, in APU ticks bool length_enabled; // NR34 uint16_t sample_countdown; // in APU ticks uint8_t current_sample_index; uint8_t current_sample; // Current sample before shifting. int8_t wave_form[32]; bool wave_form_just_read; } wave_channel; } GB_apu_t; void GB_set_sample_rate(GB_gameboy_t *gb, unsigned int sample_rate); void GB_apu_copy_buffer(GB_gameboy_t *gb, GB_sample_t *dest, unsigned int count); unsigned GB_apu_get_current_buffer_length(GB_gameboy_t *gb); #ifdef GB_INTERNAL void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value); uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg); void GB_apu_div_event(GB_gameboy_t *gb); void GB_apu_init(GB_gameboy_t *gb); void GB_apu_run(GB_gameboy_t *gb, uint8_t cycles); #endif #endif /* apu_h */