Working on apu

This commit is contained in:
Samuel Walker 2025-02-17 21:22:13 -07:00
parent 4823aeae93
commit 020feb2a6f
Signed by: piwalker
GPG Key ID: 616B1928705EA4C9
7 changed files with 100 additions and 31 deletions

View File

@ -7,6 +7,7 @@ typedef struct {
bool running;
bool die;
u64 ticks;
const char *app_path;
} emu_context;
int emu_run(int, char**);

View File

@ -80,6 +80,8 @@ typedef struct {
bool rendering_window;
u32 target_frame_time;
bool paused;
bool frame;
} ppu_context;
void ppu_init();

View File

@ -1,6 +1,7 @@
#include <audio.h>
#include <emu.h>
#include <ppu.h>
#include <portaudio.h>
#include <pa_ringbuffer.h>
@ -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)){
//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);
}
}

View File

@ -71,6 +71,7 @@ int emu_run(int argc, char **argv) {
}
printf("Cart loaded..\n");
ctx.app_path = argv[0];
ui_init();
#ifdef _WIN32

View File

@ -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;

View File

@ -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();
}

View File

@ -4,6 +4,7 @@
#include <gamepad.h>
#include <bus.h>
#include <audio.h>
#include <string.h>
#include <SDL.h>
#include <SDL_ttf.h>
@ -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;