diff --git a/include/emu.h b/include/emu.h index 10eddb7..fda3c47 100644 --- a/include/emu.h +++ b/include/emu.h @@ -7,6 +7,7 @@ typedef struct { bool running; bool die; u64 ticks; + const char *app_path; } emu_context; int emu_run(int, char**); diff --git a/include/ppu.h b/include/ppu.h index 2cec42a..b5bc0e8 100644 --- a/include/ppu.h +++ b/include/ppu.h @@ -80,6 +80,8 @@ typedef struct { bool rendering_window; u32 target_frame_time; + bool paused; + bool frame; } ppu_context; void ppu_init(); diff --git a/lib/audio.c b/lib/audio.c index dc3176d..1dac96c 100644 --- a/lib/audio.c +++ b/lib/audio.c @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -22,12 +23,14 @@ static float audio_time = 0; static float wave_time = 0; static float lfsr_timer = 0; static float lfsr_clock = LFSR_BASE_CLOCK; +static float lfsr_clock_buffer = LFSR_BASE_CLOCK; static float left_cap = 0.0f; static float right_cap = 0.0f; static int history_timer = 0; const int history_interval = 5; +static int lfsr_clocks = 0; const u8 square_sample_00[8] = { 0x0, @@ -87,6 +90,11 @@ static int audio_callback(const void* input_uffer, void *output_buffer, void *userData ) { float *out = (float *)output_buffer; for(int i = 0; i < framesPerBuffer; i++) { + if(ppu_get_context()->paused) { + *out++ = 0; + *out++ = 0; + continue; + } float left = 0; float right = 0; audio_time += TIME_PER_SAMPLE; @@ -118,17 +126,29 @@ static int audio_callback(const void* input_uffer, void *output_buffer, } lfsr_timer += TIME_PER_SAMPLE; for(;lfsr_timer >= lfsr_clock;lfsr_timer -= lfsr_clock) { - if(ctx.ch4_enable) { - lfsr_timer = 0; - u8 new = !((ctx.ch4_lfsr & 0b1) ^ ((ctx.ch4_lfsr >> 1) & 0b1)) & 0b1; - ctx.ch4_lfsr |= (new << 15); - if(ctx.ch4_lfsr_width) { - ctx.ch4_lfsr &= ~(1 << 7); - ctx.ch4_lfsr |= (new << 7); - } - ctx.ch4_lfsr = ctx.ch4_lfsr >> 1; + //if(ctx.ch4_enable) { + lfsr_clocks++; + lfsr_clock = lfsr_clock_buffer; + //lfsr_timer = 0; + //u16 new = ~((ctx.ch4_lfsr & 0b1) ^ ((ctx.ch4_lfsr & 0b10) >> 1)) & 0b1; + //ctx.ch4_lfsr &= ~(1 << 15); + //ctx.ch4_lfsr |= ((new << 15) & 0x8000); + //printf("new bit: %02X\n", (new << 15)); + //if(ctx.ch4_lfsr_width) { + // ctx.ch4_lfsr &= ~(1 << 7); + // ctx.ch4_lfsr |= (new << 7); + //} + //ctx.ch4_lfsr = ctx.ch4_lfsr >> 1; //printf("lfsr: %02X, bit: %d\n", ctx.ch4_lfsr, new); - } + unsigned bit_mask = ctx.ch4_lfsr_width ? 0x4040 : 0x4000; + bool new_bit = (ctx.ch4_lfsr ^ (ctx.ch4_lfsr >> 1) ^ 1) & 1; + ctx.ch4_lfsr >>= 1; + if(new_bit) { + ctx.ch4_lfsr |= bit_mask; + } else { + ctx.ch4_lfsr &= ~bit_mask; + } + //} } float sq1_val = 0; float sq2_val = 0; @@ -206,7 +226,7 @@ static int audio_callback(const void* input_uffer, void *output_buffer, if(ctx.ch4_dac){ ch4_val = -1; if(ctx.ch4_enable) { - ch4_val = (ctx.ch4_lfsr & 0b1) ? (((float)ctx.ch4_volume - 7.5f)/7.5f) : -1.0f; + ch4_val = ((ctx.ch4_lfsr & 0b1) == 0b1) ? (((float)ctx.ch4_volume - 7.5f)/7.5f) : -1.0f; if(ctx.ch4_left) { left += ch4_val; //printf("left: %d\n", ctx.ch3_volume); @@ -248,7 +268,16 @@ static int audio_callback(const void* input_uffer, void *output_buffer, right_out /= 4; if(left_out < -1.0f) { - printf("Uh Oh! %f\n", left_out); + left_out = -1; + } + if(left_out > 1.0f) { + left_out = 1; + } + if(right_out < -1.0f) { + right_out = -1; + } + if(right_out > 1.0f) { + right_out = 1; } history_timer++; if(history_timer >= history_interval){ @@ -382,6 +411,7 @@ void sq1_sweep() { static int change = 1; static u32 ticks = 0; +static u32 start, end = 0; void audio_tick(){ u32 prev_ticks = ticks; @@ -415,7 +445,7 @@ void audio_tick(){ if(ctx.ch4_len_enable && ctx.ch4_enable) { ctx.ch4_len++; - //printf("Ch4 env: %02X\n", ctx.ch4_len); + //printf("Ch4 len: %02X\n", ctx.ch4_len); if(ctx.ch4_len >= 64) { ctx.ch4_len = 0; ctx.ch4_enable = false; @@ -454,19 +484,20 @@ void audio_tick(){ } } - if(ctx.ch4_env_pace != 0){ - ctx.ch4_env_timer++; - if(ctx.ch4_env_timer >= ctx.ch4_env_pace) { - ctx.ch4_env_timer = 0; - if((ctx.ch4_env_direction && ctx.ch4_volume != 15) || (!ctx.ch4_env_direction && ctx.ch4_volume != 0)){ - ctx.ch4_volume += ctx.ch4_env_direction ? 1 : -1; - if(ctx.ch4_volume < 0) - ctx.ch4_volume = 0; - if(ctx.ch4_volume > 15) - ctx.ch4_volume = 15; - } + //if(ctx.ch4_env_pace != 0){ + ctx.ch4_env_timer--; + if(ctx.ch4_env_timer <= 0) { + ctx.ch4_env_timer = ctx.ch4_env_pace_buffer != 0 ? ctx.ch4_env_pace_buffer : 8; + if(ctx.ch4_env_pace != 0 && ((ctx.ch4_env_direction && ctx.ch4_volume != 15) || (!ctx.ch4_env_direction && ctx.ch4_volume != 0))){ + ctx.ch4_volume += ctx.ch4_env_direction ? 1 : -1; + //printf("Noise Vol: %02X\n", ctx.ch4_volume); + if(ctx.ch4_volume < 0) + ctx.ch4_volume = 0; + if(ctx.ch4_volume > 15) + ctx.ch4_volume = 15; } } + //} } @@ -528,12 +559,15 @@ void enable_noise() { if(!ctx.ch4_dac){ return; } + start = get_ticks(); ctx.ch4_enable = true; - ctx.ch4_env_timer = 0; + ctx.ch4_env_timer = ctx.ch4_env_pace_buffer != 0 ? ctx.ch4_env_pace_buffer : 8; ctx.ch4_env_direction = ctx.ch4_env_direction_buffer; ctx.ch4_env_pace = ctx.ch4_env_pace_buffer; ctx.ch4_volume = ctx.ch4_initial_volume; ctx.ch4_lfsr = 0; + lfsr_clock = lfsr_clock_buffer; + lfsr_timer = 0; } u8 audio_read(u16 address) { @@ -928,6 +962,7 @@ void audio_write(u16 address, u8 value){ ctx.ch4_len = ctx.ch4_initial_len; ctx.ch4_len_fz = false; //printf("ch4 len: %02X\n", ctx.ch4_len); + printf("Write Ch4 Len: %02X\n", value); } if(address == 0xFF21) { @@ -940,15 +975,18 @@ void audio_write(u16 address, u8 value){ } else { ctx.ch4_dac = true; } + printf("Write Ch4 env: %02X\n", value); } if(address == 0xFF22) { - ctx.ch4_clock_shift = (value >> 4); + ctx.ch4_clock_shift = (value >> 4) & 0xF; ctx.ch4_lfsr_width = (value & 0x08); ctx.ch4_clock_divider = value & 0b111; - float div = (ctx.ch4_clock_divider == 0 ? 0.5f : ctx.ch4_clock_divider); - float lfsr_rate = (LFSR_BASE_CLOCK) / (div * (1 << ctx.ch4_clock_shift)); - lfsr_clock = 1.0f / (lfsr_rate/1000.0f/1000.0f); + float div = (ctx.ch4_clock_divider == 0 ? 0.5f : (float)ctx.ch4_clock_divider); + float lfsr_rate = (LFSR_BASE_CLOCK) / (div * (float)(1 << ctx.ch4_clock_shift)); + lfsr_clock_buffer = 1.0f / (lfsr_rate/1000.0f/1000.0f); + //printf("Ch4 clock: Shift: %01X, Width: %d, Div: %f (%01X), Rate: %f, Clock %f\n", ctx.ch4_clock_shift, ctx.ch4_lfsr_width, div, ctx.ch4_clock_divider, lfsr_rate, lfsr_clock); + printf("Write Ch4 Clock: %02X\n", value); } if(address == 0xFF23) { @@ -975,5 +1013,6 @@ void audio_write(u16 address, u8 value){ if(value & 0x80) { enable_noise(); } + printf("Write Ch4 Trigger: %02X\n", value); } } diff --git a/lib/emu.c b/lib/emu.c index 1e5eb1a..2aec343 100644 --- a/lib/emu.c +++ b/lib/emu.c @@ -71,6 +71,7 @@ int emu_run(int argc, char **argv) { } printf("Cart loaded..\n"); + ctx.app_path = argv[0]; ui_init(); #ifdef _WIN32 diff --git a/lib/ppu_sm.c b/lib/ppu_sm.c index 81b4750..9bd4f55 100644 --- a/lib/ppu_sm.c +++ b/lib/ppu_sm.c @@ -158,6 +158,14 @@ void ppu_mode_hblank() { delay((ppu_get_context()->target_frame_time - frame_time)); } + while(ppu_get_context()->paused) { + delay(10); + if(ppu_get_context()->frame){ + ppu_get_context()->frame = false; + break; + } + } + if (end - start_timer >= 1000) { u32 fps = frame_count; start_timer = end; diff --git a/lib/timer.c b/lib/timer.c index 569ffb2..a45a675 100644 --- a/lib/timer.c +++ b/lib/timer.c @@ -39,7 +39,7 @@ void timer_tick() { } } - if((prev_div & (1 << 13)) && (!(ctx.div & (1 << 13)))){ + if((prev_div & (1 << 12)) && (!(ctx.div & (1 << 12)))){ audio_tick(); } diff --git a/lib/ui.c b/lib/ui.c index 8889637..92a3d9d 100644 --- a/lib/ui.c +++ b/lib/ui.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -131,7 +132,11 @@ void ui_update() { SDL_UpdateTexture(sdlTexture, NULL, screen->pixels, screen->pitch); SDL_RenderClear(sdlRenderer); SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL); - TTF_Font* sans = TTF_OpenFont("Sans.ttf", 24); + char buffer[1024]; + strcpy(buffer, emu_get_context()->app_path); + *strrchr(buffer, '\\') = 0; + strcat(buffer,"/Sans.ttf"); + TTF_Font* sans = TTF_OpenFont(buffer, 24); if ( !sans ) { printf("Failed to load font: %s\n", TTF_GetError()); } @@ -289,6 +294,19 @@ void ui_on_key(bool down, u32 key_code) { } printf("target frame time: %d\n", ppu_get_context()->target_frame_time); } + if(ppu_get_context()->paused) { + if(key_code == SDLK_PERIOD && down == true){ + ppu_get_context()->frame = true; + } + } + if(key_code == SDLK_p && down == true) { + ppu_get_context()->paused = !ppu_get_context()->paused; + if(ppu_get_context()->paused) { + printf("Paused Emulation\n"); + } else { + printf("Resumed Emulation\n"); + } + } switch(key_code){ case SDLK_z: gamepad_get_state()->b = down; break; case SDLK_x: gamepad_get_state()->a = down; break;