summaryrefslogtreecommitdiff
path: root/sid/sidplay-libs-2.1.0/resid/sid.h
blob: 33754547f8c736d8519654ed88a1c55349c63006 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//  ---------------------------------------------------------------------------
//  This file is part of reSID, a MOS6581 SID emulator engine.
//  Copyright (C) 2002  Dag Lem <resid@nimrod.no>
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//  ---------------------------------------------------------------------------

#ifndef __SID_H__
#define __SID_H__

#include "siddefs.h"
#include "voice.h"
#include "filter.h"
#include "extfilt.h"
#include "pot.h"

enum
{   // VC <= 6 patch
    RESID_FIR_ORDER = 123,
    RESID_FIR_N     = RESID_FIR_ORDER/2 + 1,
    RESID_FIR_RES   = 512,
    RESID_FIR_SHIFT = 16
};

RESID_NAMESPACE_START

class SID
{
public:
  SID();

  void set_chip_model(chip_model model);
  void enable_filter(bool enable);
  void enable_external_filter(bool enable);
  bool set_sampling_parameters(double clock_freq, sampling_method method,
			       double sample_freq, double pass_freq = -1);
  void adjust_sampling_frequency(double sample_freq);

  void fc_default(const fc_point*& points, int& count);
  PointPlotter<sound_sample> fc_plotter();

  void clock();
  void clock(cycle_count delta_t);
  int clock(cycle_count& delta_t, short* buf, int n, int interleave = 1);
  void reset();
  
  // Read/write registers.
  reg8 read(reg8 offset);
  void write(reg8 offset, reg8 value);
  void mute(reg8 channel, bool enable);

  // Read/write state.
  class State
  {
  public:
    State();

    char sid_register[0x20];

    reg8 bus_value;
    cycle_count bus_value_ttl;

    reg24 accumulator[3];
    reg24 shift_register[3];
    reg16 rate_counter[3];
    reg16 exponential_counter[3];
    reg8 envelope_counter[3];
    bool hold_zero[3];
  };
    
  State read_state();
  void write_state(const State& state);

  // 16-bit output.
  int output();
  // n-bit output.
  int output(int bits);

protected:
  static double I0(double x);
  RESID_INLINE int clock_fast(cycle_count& delta_t, short* buf, int n,
			      int interleave);
  RESID_INLINE int clock_interpolate(cycle_count& delta_t, short* buf, int n,
				     int interleave);
  RESID_INLINE int clock_resample(cycle_count& delta_t, short* buf, int n,
				  int interleave);

  Voice voice[3];
  Filter filter;
  ExternalFilter extfilt;
  Potentiometer potx;
  Potentiometer poty;

  reg8 bus_value;
  cycle_count bus_value_ttl;

  double clock_frequency;

  // Sampling variables.
  cycle_count sample_offset;
  short sample_prev;
  unsigned int sample_index;
  short sample[16384];

  // Sampling constants.
  // VC <= 6 patch
  static const int FIR_ORDER;
  static const int FIR_N;
  static const int FIR_RES;
  static const int FIR_SHIFT;
  sampling_method sampling;
  cycle_count cycles_per_sample;
  cycle_count fstep_per_cycle;
  cycle_count sample_delay;
  int fir_N;
  int foffset_max;
  // VC <= 6 patch
  short fir[RESID_FIR_N*RESID_FIR_RES + 1];
  short fir_diff[RESID_FIR_N*RESID_FIR_RES + 1];
};

RESID_NAMESPACE_STOP

#endif // not __SID_H__