comparison psg.c @ 483:3e1573fa22cf

Implement turbo/slow motion feature that overclocks or underclocks the entire system at the push of a button
author Mike Pavone <pavone@retrodev.com>
date Tue, 01 Oct 2013 23:51:16 -0700
parents 140af5509ce7
children b7b7a1cab44a
comparison
equal deleted inserted replaced
482:4b24260125f3 483:3e1573fa22cf
1 /* 1 /*
2 Copyright 2013 Michael Pavone 2 Copyright 2013 Michael Pavone
3 This file is part of BlastEm. 3 This file is part of BlastEm.
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
5 */ 5 */
6 #include "psg.h" 6 #include "psg.h"
7 #include "render.h" 7 #include "render.h"
8 #include <string.h> 8 #include <string.h>
11 void psg_init(psg_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t samples_frame) 11 void psg_init(psg_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t samples_frame)
12 { 12 {
13 memset(context, 0, sizeof(*context)); 13 memset(context, 0, sizeof(*context));
14 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame); 14 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame);
15 context->back_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame); 15 context->back_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame);
16 double clock_rate = (double)master_clock / (double)clock_div;
17 context->buffer_inc = ((double)sample_rate / (double)master_clock) * clock_div;
18 context->clock_inc = clock_div; 16 context->clock_inc = clock_div;
17 context->sample_rate = sample_rate;
19 context->samples_frame = samples_frame; 18 context->samples_frame = samples_frame;
19 psg_adjust_master_clock(context, master_clock);
20 for (int i = 0; i < 4; i++) { 20 for (int i = 0; i < 4; i++) {
21 context->volume[i] = 0xF; 21 context->volume[i] = 0xF;
22 } 22 }
23 }
24
25 #define BUFFER_INC_RES 1000000000UL
26
27 void psg_adjust_master_clock(psg_context * context, uint32_t master_clock)
28 {
29 uint64_t old_inc = context->buffer_inc;
30 context->buffer_inc = ((BUFFER_INC_RES * (uint64_t)context->sample_rate) / (uint64_t)master_clock) * (uint64_t)context->clock_inc;
23 } 31 }
24 32
25 void psg_write(psg_context * context, uint8_t value) 33 void psg_write(psg_context * context, uint8_t value)
26 { 34 {
27 if (value & 0x80) { 35 if (value & 0x80) {
68 #define PSG_VOL_DIV 6 76 #define PSG_VOL_DIV 6
69 77
70 //table shamelessly swiped from PSG doc from smspower.org 78 //table shamelessly swiped from PSG doc from smspower.org
71 int16_t volume_table[16] = { 79 int16_t volume_table[16] = {
72 32767/PSG_VOL_DIV, 26028/PSG_VOL_DIV, 20675/PSG_VOL_DIV, 16422/PSG_VOL_DIV, 13045/PSG_VOL_DIV, 10362/PSG_VOL_DIV, 80 32767/PSG_VOL_DIV, 26028/PSG_VOL_DIV, 20675/PSG_VOL_DIV, 16422/PSG_VOL_DIV, 13045/PSG_VOL_DIV, 10362/PSG_VOL_DIV,
73 8231/PSG_VOL_DIV, 6568/PSG_VOL_DIV, 5193/PSG_VOL_DIV, 4125/PSG_VOL_DIV, 3277/PSG_VOL_DIV, 2603/PSG_VOL_DIV, 81 8231/PSG_VOL_DIV, 6568/PSG_VOL_DIV, 5193/PSG_VOL_DIV, 4125/PSG_VOL_DIV, 3277/PSG_VOL_DIV, 2603/PSG_VOL_DIV,
74 2067/PSG_VOL_DIV, 1642/PSG_VOL_DIV, 1304/PSG_VOL_DIV, 0 82 2067/PSG_VOL_DIV, 1642/PSG_VOL_DIV, 1304/PSG_VOL_DIV, 0
75 }; 83 };
76 84
77 void psg_run(psg_context * context, uint32_t cycles) 85 void psg_run(psg_context * context, uint32_t cycles)
78 { 86 {
95 } 103 }
96 } 104 }
97 } 105 }
98 } 106 }
99 context->buffer_fraction += context->buffer_inc; 107 context->buffer_fraction += context->buffer_inc;
100 if (context->buffer_fraction >= 1.0) { 108 if (context->buffer_fraction >= BUFFER_INC_RES) {
101 context->buffer_fraction -= 1.0; 109 context->buffer_fraction -= BUFFER_INC_RES;
102 int16_t acc = 0; 110 int16_t acc = 0;
103 for (int i = 0; i < 3; i++) { 111 for (int i = 0; i < 3; i++) {
104 if (context->output_state[i]) { 112 if (context->output_state[i]) {
105 acc += volume_table[context->volume[i]]; 113 acc += volume_table[context->volume[i]];
106 } 114 }