Working on apu
This commit is contained in:
parent
4823aeae93
commit
020feb2a6f
@ -7,6 +7,7 @@ typedef struct {
|
||||
bool running;
|
||||
bool die;
|
||||
u64 ticks;
|
||||
const char *app_path;
|
||||
} emu_context;
|
||||
|
||||
int emu_run(int, char**);
|
||||
|
@ -80,6 +80,8 @@ typedef struct {
|
||||
|
||||
bool rendering_window;
|
||||
u32 target_frame_time;
|
||||
bool paused;
|
||||
bool frame;
|
||||
} ppu_context;
|
||||
|
||||
void ppu_init();
|
||||
|
97
lib/audio.c
97
lib/audio.c
@ -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)){
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ int emu_run(int argc, char **argv) {
|
||||
}
|
||||
|
||||
printf("Cart loaded..\n");
|
||||
ctx.app_path = argv[0];
|
||||
|
||||
ui_init();
|
||||
#ifdef _WIN32
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
20
lib/ui.c
20
lib/ui.c
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user