2
* resid-fp.cc - reSID-fp interface code.
5
* Teemu Rantanen <tvr@cs.hut.fi>
6
* Dag Lem <resid@nimrod.no>
7
* Andreas Boose <viceteam@t-online.de>
8
* Antti S. Lankila <alankila@bel.fi>
10
* This file is part of VICE, the Versatile Commodore Emulator.
11
* See README for copyright notice.
13
* This program is free software; you can redistribute it and/or modify
14
* it under the terms of the GNU General Public License as published by
15
* the Free Software Foundation; either version 2 of the License, or
16
* (at your option) any later version.
18
* This program is distributed in the hope that it will be useful,
19
* but WITHOUT ANY WARRANTY; without even the implied warranty of
20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
* GNU General Public License for more details.
23
* You should have received a copy of the GNU General Public License
24
* along with this program; if not, write to the Free Software
25
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
30
/* resid itself is always compiled with C64DTV support */
31
#include "resid-fp/sid.h"
35
/* QNX has problems with const and inline definitions
36
in its string.h file when using g++ */
42
#include "sid/sid.h" /* sid_engine_t */
46
#include "resources.h"
47
#include "sid-snapshot.h"
52
/* resid sid implementation */
56
typedef struct sound_s sound_t;
58
static sound_t *residfp_open(BYTE *sidstate)
64
psid->sid = new SIDFP;
66
for (i = 0x00; i <= 0x18; i++) {
67
psid->sid->write(i, sidstate[i]);
73
static int residfp_init(sound_t *psid, int speed, int cycles_per_sec)
75
sampling_method method;
77
char method_text[100];
79
int filters_enabled, model, sampling, passband_percentage;
81
if (resources_get_int("SidFilters", &filters_enabled) < 0)
84
if (resources_get_int("SidModel", &model) < 0)
87
if (resources_get_int("SidResidSampling", &sampling) < 0)
90
if (resources_get_int("SidResidPassband", &passband_percentage) < 0)
93
passband = speed * passband_percentage / 200.f;
95
/* Some mostly-common settings for all modes abstracted here. */
98
/* Model numbers 8-15 are reserved for distorted 6581s. */
99
if (model < 8 || model > 15) {
100
psid->sid->set_chip_model(MOS8580FP);
101
psid->sid->set_voice_nonlinearity(1.0f);
102
psid->sid->get_filter().set_distortion_properties(0.f, 0.f, 0.f);
104
psid->sid->set_chip_model(MOS6581FP);
105
psid->sid->set_voice_nonlinearity(0.96f);
106
psid->sid->get_filter().set_distortion_properties(3.7e-3f, 2048.f, 1.2e-4f);
111
case SID_MODEL_8580R5_3691:
112
psid->sid->get_filter().set_type4_properties(6.55f, 20.0f);
113
strcpy(model_text, "8580R5 3691");
115
case SID_MODEL_8580R5_3691D:
116
psid->sid->get_filter().set_type4_properties(6.55f, 20.0f);
117
psid->sid->input(-32768);
118
strcpy(model_text, "8580R5 3691 + digi boost");
121
case SID_MODEL_8580R5_1489:
122
psid->sid->get_filter().set_type4_properties(5.7f, 20.0f);
123
strcpy(model_text, "8580R5 1489");
125
case SID_MODEL_8580R5_1489D:
126
psid->sid->get_filter().set_type4_properties(5.7f, 20.0f);
127
psid->sid->input(-32768);
128
strcpy(model_text, "8580R5 1489 + digi boost");
131
case SID_MODEL_6581R3_4885:
132
psid->sid->get_filter().set_type3_properties(8.5e5f, 2.2e6f, 1.0075f, 1.8e4f);
133
strcpy(model_text, "6581R3 4885");
135
case SID_MODEL_6581R3_0486S:
136
psid->sid->get_filter().set_type3_properties(1.1e6f, 1.5e7f, 1.006f, 1e4f);
137
strcpy(model_text, "6581R3 0486S");
139
case SID_MODEL_6581R3_3984:
140
psid->sid->get_filter().set_type3_properties(1.8e6f, 3.5e7f, 1.0051f, 1.45e4f);
141
strcpy(model_text, "6581R3 3984");
144
case SID_MODEL_6581R4AR_3789:
145
psid->sid->get_filter().set_type3_properties(1.40e6f, 1.47e8f, 1.0059f, 1.55e4f);
146
strcpy(model_text, "6581R4AR 3789");
148
case SID_MODEL_6581R3_4485:
149
psid->sid->get_filter().set_type3_properties(1.3e6f, 5.2e8f, 1.0053f, 1.1e4f);
150
strcpy(model_text, "6581R3 4485");
152
case SID_MODEL_6581R4_1986S:
153
psid->sid->get_filter().set_type3_properties(1.33e6f, 2.2e9f, 1.0056f, 7e3f);
154
strcpy(model_text, "6581R4 1986S");
158
psid->sid->enable_filter(filters_enabled ? true : false);
159
psid->sid->enable_external_filter(filters_enabled ? true : false);
164
method = SAMPLE_INTERPOLATE;
165
strcpy(method_text, "interpolation");
169
method = SAMPLE_RESAMPLE_INTERPOLATE;
170
sprintf(method_text, "%sresampling, cutoff %d Hz",
171
(psid->sid->sse_enabled() ? "SSE " : ""),
172
(int) (passband > 20000.f ? 20000.f : passband));
176
//! \todo FIXME: These casts have to go away
177
if (!psid->sid->set_sampling_parameters((float)cycles_per_sec, method,
178
(float)speed, passband)) {
179
log_warning(LOG_DEFAULT,
180
"ReSID-FP: unable to set sampling mode; try increasing sampling frequency to 44.1-48 kHz and keep passband around 80-90 %%.");
184
log_message(LOG_DEFAULT,
185
"ReSID-FP: %s, filter %s, sampling rate %d Hz with %s",
187
filters_enabled ? "on" : "off",
193
static void residfp_close(sound_t *psid)
199
static BYTE residfp_read(sound_t *psid, WORD addr)
201
return psid->sid->read(addr);
204
static void residfp_store(sound_t *psid, WORD addr, BYTE byte)
206
psid->sid->write(addr, byte);
209
static void residfp_reset(sound_t *psid, CLOCK cpu_clk)
214
static int residfp_calculate_samples(sound_t *psid, SWORD *pbuf, int nr,
215
int interleave, int *delta_t)
217
return psid->sid->clock(*delta_t, pbuf, nr, interleave);
220
static void residfp_prevent_clk_overflow(sound_t *psid, CLOCK sub)
224
static char *residfp_dump_state(sound_t *psid)
226
return lib_stralloc("");
229
static void residfp_state_read(sound_t *psid, sid_snapshot_state_t *sid_state)
234
state = psid->sid->read_state();
236
for (i = 0; i < 0x20; i++) {
237
sid_state->sid_register[i] = (BYTE)state.sid_register[i];
240
sid_state->bus_value = (BYTE)state.bus_value;
241
sid_state->bus_value_ttl = (DWORD)state.bus_value_ttl;
242
for (i = 0; i < 3; i++) {
243
sid_state->accumulator[i] = (DWORD)state.accumulator[i];
244
sid_state->shift_register[i] = (DWORD)state.shift_register[i];
245
sid_state->rate_counter[i] = (WORD)state.rate_counter[i];
246
sid_state->rate_counter_period[i] = (WORD)state.rate_counter_period[i];
247
sid_state->exponential_counter[i] = (WORD)state.exponential_counter[i];
248
sid_state->exponential_counter_period[i] = (WORD)state.exponential_counter_period[i];
249
sid_state->envelope_counter[i] = (BYTE)state.envelope_counter[i];
250
sid_state->envelope_state[i] = (BYTE)state.envelope_state[i];
251
sid_state->hold_zero[i] = (BYTE)state.hold_zero[i];
255
static void residfp_state_write(sound_t *psid, sid_snapshot_state_t *sid_state)
260
for (i = 0; i < 0x20; i++) {
261
state.sid_register[i] = (char)sid_state->sid_register[i];
264
state.bus_value = (reg8)sid_state->bus_value;
265
state.bus_value_ttl = (cycle_count)sid_state->bus_value_ttl;
266
for (i = 0; i < 3; i++) {
267
state.accumulator[i] = (reg24)sid_state->accumulator[i];
268
state.shift_register[i] = (reg24)sid_state->shift_register[i];
269
state.rate_counter[i] = (reg16)sid_state->rate_counter[i];
270
if (sid_state->rate_counter_period[i])
271
state.rate_counter_period[i] = (reg16)sid_state->rate_counter_period[i];
272
state.exponential_counter[i] = (reg16)sid_state->exponential_counter[i];
273
if (sid_state->exponential_counter_period[i])
274
state.exponential_counter_period[i] = (reg16)sid_state->exponential_counter_period[i];
275
state.envelope_counter[i] = (reg8)sid_state->envelope_counter[i];
276
state.envelope_state[i] = (EnvelopeGeneratorFP::State)sid_state->envelope_state[i];
277
state.hold_zero[i] = (sid_state->hold_zero[i] != 0);
280
psid->sid->write_state((const SIDFP::State)state);
283
sid_engine_t residfp_hooks =
291
residfp_calculate_samples,
292
residfp_prevent_clk_overflow,