diff --git a/.vscode/settings.json b/.vscode/settings.json index e351eb9..34ac8c4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,6 +5,8 @@ "string.h": "c", "common.h": "c", "ppu.h": "c", - "profileapi.h": "c" + "profileapi.h": "c", + "type_traits": "c", + "xtr1common": "c" } } \ No newline at end of file diff --git a/include/audio.h b/include/audio.h index 016cf5d..43137da 100644 --- a/include/audio.h +++ b/include/audio.h @@ -17,6 +17,8 @@ typedef struct { u8 volume_left; u8 volume_right; + bool vin_left; + bool vin_right; u8 sq1_duty; u8 sq1_volume; @@ -59,6 +61,7 @@ typedef struct { u8 sq2_env_timer; bool ch3_enable; + bool ch3_dac; u8 ch3_initial_len; u8 ch3_len; u8 ch3_volume; diff --git a/lib/audio.c b/lib/audio.c index 1e79b1c..65300ac 100644 --- a/lib/audio.c +++ b/lib/audio.c @@ -161,9 +161,10 @@ static int audio_callback(const void* input_uffer, void *output_buffer, } } } - - left *= (float)ctx.volume_left/7.0f; - right *= (float)ctx.volume_right/7.0f; + u8 left_vol = ctx.volume_left == 0 ? 1 : ctx.volume_left; + u8 right_vol = ctx.volume_right == 0 ? 1 : ctx.volume_right; + left *= (float)left_vol/7.0f; + right *= (float)right_vol/7.0f; left /= 4; right /= 4; @@ -280,6 +281,7 @@ void audio_tick(){ if(ctx.sq1_len >= 64) { ctx.sq1_enable = false; } + printf("Len: %02X\n", ctx.sq1_len); } if(ctx.sq2_len_enable) { @@ -291,7 +293,7 @@ void audio_tick(){ if(ctx.ch3_len_enable) { ctx.ch3_len++; - if(ctx.ch3_len >= 64) { + if(ctx.ch3_len >= 256) { ctx.ch3_enable = false; } } @@ -399,7 +401,7 @@ void enable_square2() { void enable_wave() { ctx.ch3_enable = true; - if(ctx.ch3_len >= 64) { + if(ctx.ch3_len >= 256) { ctx.ch3_len = ctx.ch3_initial_len; } ctx.ch3_sample = 0; @@ -420,13 +422,216 @@ void enable_noise() { } u8 audio_read(u16 address) { - return 0x00; + printf("read at %02X\n", address); + if(address == 0xFF26) { + u8 value = (ctx.audio_enabled << 7) | (ctx.ch4_enable << 3) | (ctx.ch3_enable << 2) | (ctx.sq2_enable << 1) | (ctx.sq1_enable); + return value | 0b01110000; + } + if(address == 0xFF25) { + u8 value; + value |= ctx.ch4_left << 7; + value |= ctx.ch3_left << 6; + value |= ctx.ch2_left << 5; + value |= ctx.ch1_left << 4; + + value |= ctx.ch4_right << 3; + value |= ctx.ch3_right << 2; + value |= ctx.ch2_right << 1; + value |= ctx.ch1_right; + return value; + } + + if(address == 0xFF24) { + u8 value = (ctx.volume_left & 0b111) << 4; + value |= (ctx.volume_right & 0b111); + value |= (ctx.vin_left << 7); + value |= (ctx.vin_right << 3); + return value; + } + + if(address == 0xFF10) { + u8 value = (ctx.sq1_sweep_pace & 0b111) << 4; + value |= (ctx.sq1_sweep_direction) << 3; + value |= ctx.sq1_sweep_step & 0b111; + return value | 0x80; + } + if(address == 0xFF11) { + u8 value = (ctx.sq1_duty & 0b11) << 6; + return value | 0b00111111; + } + if(address == 0xFF12) { + u8 value = (ctx.sq1_initial_volume & 0b1111) << 4; + value |= ctx.sq1_env_direction_buffer << 3; + value |= (ctx.sq1_env_pace_buffer & 0b111); + return value; + } + if(address == 0xFF13) { + return 0xFF; + } + if(address == 0xFF14) { + return (ctx.sq1_len_enable << 6) | 0b10111111; + } + + + if(address == 0xFF16) { + u8 value = (ctx.sq2_duty & 0b11) << 6; + return value | 0b00111111; + } + if(address == 0xFF17) { + u8 value = (ctx.sq2_initial_volume & 0b1111) << 4; + value |= ctx.sq2_env_direction_buffer << 3; + value |= (ctx.sq2_env_pace_buffer & 0b111); + return value; + } + if(address == 0xFF18) { + return 0xFF; + } + if(address == 0xFF19) { + return (ctx.sq2_len_enable << 6) | 0b10111111; + } + + if(address == 0xFF1A) { + return (ctx.ch3_dac << 7) | 0b01111111; + } + + if(address == 0xFF1B) { + return 0xFF; + } + + if(address == 0xFF1C) { + return ((ctx.ch3_initial_volume & 0b11) << 5) | 0b10011111; + } + + if(address == 0xFF1D) { + return 0xFF; + } + + if(address == 0xFF1E) { + return (ctx.ch3_len_enable << 6) | 0b10111111; + } + + if(address == 0xFF20) { + return 0xFF; + } + + if(address == 0xFF21) { + u8 value = (ctx.ch4_initial_volume & 0b1111) << 4; + value |= ctx.ch4_env_direction_buffer << 3; + value |= (ctx.ch4_env_pace_buffer & 0b111); + return value; + } + + if(address == 0xFF22) { + u8 value = (ctx.ch4_clock_shift & 0xF) << 4; + value |= ctx.ch4_lfsr_width << 3; + value |= (ctx.ch4_clock_divider & 0b111); + return value; + } + + if(address == 0xFF23) { + return (ctx.ch4_len_enable << 6) | 0b10111111; + } + + if(BETWEEN(address, 0xFF30, 0xFF3F)) { + return ctx.wave_ram[address - 0xFF30]; + } + return 0xFF; +} + +void reset_buffers(){ + ctx.ch1_left = 0; + ctx.ch1_right = 0; + ctx.ch2_left = 0; + ctx.ch2_right = 0; + ctx.ch3_left = 0; + ctx.ch3_right = 0; + ctx.ch4_left = 0; + ctx.ch4_right = 0; + ctx.volume_left = 0; + ctx.volume_right = 0; + ctx.vin_left = 0; + ctx.vin_right = 0; + ctx.sq1_duty = 0; + ctx.sq1_volume = 0; + ctx.sq1_sample = 0; + ctx.sq1_period_reset = 0; + ctx.sq1_period_timer = 0; + ctx.sq1_enable = 0; + ctx.sq1_len_enable = 0; + ctx.sq1_sweep_pace = 0; + ctx.sq1_sweep_direction = 0; + ctx.sq1_initial_len = 0; + ctx.sq1_len = 0; + ctx.sq1_initial_volume = 0; + ctx.sq1_env_direction = 0; + ctx.sq1_env_direction_buffer = 0; + ctx.sq1_env_pace = 0; + ctx.sq1_env_pace_buffer = 0; + ctx.sq1_env_timer = 0; + ctx.sq1_sweep_step = 0; + ctx.sq1_sweep_timer = 0; + ctx.sq1_sweep_enabled = 0; + ctx.sq1_sweep_period = 0; + ctx.sq1_calc_period = 0; + ctx.sq2_duty = 0; + ctx.sq2_volume = 0; + ctx.sq2_sample = 0; + ctx.sq2_period_reset = 0; + ctx.sq2_period_timer = 0; + ctx.sq2_enable = 0; + ctx.sq2_len_enable = 0; + ctx.sq2_initial_len = 0; + ctx.sq2_len = 0; + ctx.sq2_initial_volume = 0; + ctx.sq2_env_direction = 0; + ctx.sq2_env_direction_buffer = 0; + ctx.sq2_env_pace = 0; + ctx.sq2_env_pace_buffer = 0; + ctx.sq2_env_timer = 0; + ctx.ch3_enable = 0; + ctx.ch3_dac = 0; + ctx.ch3_initial_len = 0; + ctx.ch3_len = 0; + ctx.ch3_volume = 0; + ctx.ch3_initial_volume = 0; + ctx.ch3_period_timer = 0; + ctx.ch3_period_reset = 0; + ctx.ch3_len_enable = 0; + ctx.ch3_last_sample = 0; + ctx.ch3_sample = 0; + ctx.ch4_enable = 0; + ctx.ch4_initial_len = 0; + ctx.ch4_len = 0; + ctx.ch4_initial_volume = 0; + ctx.ch4_volume = 0; + ctx.ch4_env_pace = 0; + ctx.ch4_env_pace_buffer = 0; + ctx.ch4_env_timer = 0; + ctx.ch4_env_direction = 0; + ctx.ch4_env_direction_buffer = 0; + ctx.ch4_clock_shift = 0; + ctx.ch4_lfsr_width = 0; + ctx.ch4_clock_divider = 0; + ctx.ch4_len_enable = 0; + ctx.ch4_lfsr = 0; } void audio_write(u16 address, u8 value){ + if(BETWEEN(address, 0xFF30, 0xFF3F)) { + ctx.wave_ram[address - 0xFF30] = value; + } + if(address == 0xFF26) { ctx.audio_enabled = value & 0x80; + if(!ctx.audio_enabled) { + reset_buffers(); + } } + + if(!ctx.audio_enabled){ + return; + } + if(address == 0xFF25) { ctx.ch4_left = value & 0b10000000; ctx.ch3_left = value & 0b01000000; @@ -441,9 +646,11 @@ void audio_write(u16 address, u8 value){ if(address == 0xFF24) { ctx.volume_left = (value >> 4) & 0b111; - if(ctx.volume_left == 0) ctx.volume_left = 1; + //if(ctx.volume_left == 0) ctx.volume_left = 1; ctx.volume_right = value & 0b111; - if(ctx.volume_right == 0) ctx.volume_right = 1; + //if(ctx.volume_right == 0) ctx.volume_right = 1; + ctx.vin_left = value & 0x80; + ctx.vin_right = value & 0x8; } if(address == 0xFF10) { @@ -454,10 +661,12 @@ void audio_write(u16 address, u8 value){ if(address == 0xFF11) { ctx.sq1_duty = value >> 6; ctx.sq1_initial_len = value & 0x3F; + ctx.sq1_len = ctx.sq1_initial_len; + printf("initial len: %02X\n", ctx.sq1_initial_len); } if(address == 0xFF12) { ctx.sq1_initial_volume = (value >> 4) & 0x0F; - ctx.sq1_env_direction_buffer = (value & 0x8) == 0x80; + ctx.sq1_env_direction_buffer = (value & 0x8) == 0x8; ctx.sq1_env_pace_buffer = value & 0b111; } if(address == 0xFF13) { @@ -475,10 +684,11 @@ void audio_write(u16 address, u8 value){ if(address == 0xFF16) { ctx.sq2_duty = value >> 6; ctx.sq2_initial_len = value & 0x3F; + ctx.sq2_len = ctx.sq2_initial_len; } if(address == 0xFF17) { ctx.sq2_initial_volume = (value >> 4) & 0x0F; - ctx.sq2_env_direction_buffer = (value & 0x8) == 0x80; + ctx.sq2_env_direction_buffer = (value & 0x8) == 0x8; ctx.sq2_env_pace_buffer = value & 0b111; if(ctx.sq2_env_direction == 0 && ctx.sq2_initial_volume == 0) { ctx.sq2_enable = false; @@ -498,11 +708,15 @@ void audio_write(u16 address, u8 value){ } if(address == 0xFF1A) { - //ctx.ch3_enable = (value & 0x80) == 0x80; + ctx.ch3_dac = value & 0x80; + if(!ctx.ch3_dac){ + ctx.ch3_enable = false; + } } if(address == 0xFF1B) { ctx.ch3_initial_len = value; + ctx.ch3_len = ctx.ch3_initial_len; } if(address == 0xFF1C) { @@ -523,11 +737,12 @@ void audio_write(u16 address, u8 value){ if(address == 0xFF20) { ctx.ch4_initial_len = value & 0b111111; + ctx.ch4_len = ctx.ch4_initial_len; } if(address == 0xFF21) { ctx.ch4_initial_volume = (value >> 4) & 0x0F; - ctx.ch4_env_direction_buffer = (value & 0x8) == 0x80; + ctx.ch4_env_direction_buffer = (value & 0x8) == 0x8; ctx.ch4_env_pace_buffer = value & 0b111; } @@ -546,8 +761,4 @@ void audio_write(u16 address, u8 value){ enable_noise(); } } - - if(BETWEEN(address, 0xFF30, 0xFF3F)) { - ctx.wave_ram[address - 0xFF30] = value; - } } \ No newline at end of file