openMSX
YMF262.hh
Go to the documentation of this file.
1#ifndef YMF262_HH
2#define YMF262_HH
3
5#include "SimpleDebuggable.hh"
6#include "EmuTimer.hh"
7#include "EmuTime.hh"
8#include "FixedPoint.hh"
9#include "IRQHelper.hh"
10#include "serialize_meta.hh"
11#include <array>
12#include <cstdint>
13#include <memory>
14#include <span>
15#include <string>
16
17namespace openmsx {
18
19class DeviceConfig;
20
21class YMF262 final : private ResampledSoundDevice, private EmuTimerCallback
22{
23public:
24 // sin-wave entries
25 static constexpr int SIN_BITS = 10;
26 static constexpr int SIN_LEN = 1 << SIN_BITS;
27 static constexpr int SIN_MASK = SIN_LEN - 1;
28
29public:
30 YMF262(const std::string& name, const DeviceConfig& config,
31 bool isYMF278);
32 ~YMF262();
33
34 void reset(EmuTime::param time);
35 void writeReg (unsigned r, uint8_t v, EmuTime::param time);
36 void writeReg512(unsigned r, uint8_t v, EmuTime::param time);
37 [[nodiscard]] uint8_t readReg(unsigned reg);
38 [[nodiscard]] uint8_t peekReg(unsigned reg) const;
39 [[nodiscard]] uint8_t readStatus();
40 [[nodiscard]] uint8_t peekStatus() const;
41
42 void setMixLevel(uint8_t x, EmuTime::param time);
43
44 template<typename Archive>
45 void serialize(Archive& ar, unsigned version);
46
47public:
50
53 };
54
55private:
56 class Channel;
57
58 class Slot {
59 public:
60 Slot();
61 [[nodiscard]] inline int op_calc(unsigned phase, unsigned lfo_am) const;
62 inline void FM_KEYON(uint8_t key_set);
63 inline void FM_KEYOFF(uint8_t key_clr);
64 inline void advanceEnvelopeGenerator(unsigned egCnt);
65 inline void advancePhaseGenerator(Channel& ch, unsigned lfo_pm);
66 void update_ar_dr();
67 void update_rr();
68 void calc_fc(const Channel& ch);
69
72 void setFeedbackShift(uint8_t value) {
73 fb_shift = value ? 9 - value : 0;
74 }
75
76 template<typename Archive>
77 void serialize(Archive& ar, unsigned version);
78
79 // Phase Generator
80 FreqIndex Cnt{0}; // frequency counter
81 FreqIndex Incr{0}; // frequency counter step
82 int* connect{nullptr}; // slot output pointer
83 std::array<int, 2> op1_out{0, 0}; // slot1 output for feedback
84
85 // Envelope Generator
86 unsigned TL{0}; // total level: TL << 2
87 unsigned TLL{0}; // adjusted now TL
88 int volume{0}; // envelope counter
89 int sl{0}; // sustain level: sl_tab[SL]
90
91 std::span<const unsigned, SIN_LEN> waveTable; // waveform select
92
93 EnvelopeState state{EG_OFF}; // EG: phase type
94 unsigned eg_m_ar{0}; // (attack state)
95 unsigned eg_m_dr{0}; // (decay state)
96 unsigned eg_m_rr{0}; // (release state)
97 uint8_t eg_sh_ar{0}; // (attack state)
98 uint8_t eg_sel_ar{0}; // (attack state)
99 uint8_t eg_sh_dr{0}; // (decay state)
100 uint8_t eg_sel_dr{0}; // (decay state)
101 uint8_t eg_sh_rr{0}; // (release state)
102 uint8_t eg_sel_rr{0}; // (release state)
103
104 uint8_t key{0}; // 0 = KEY OFF, >0 = KEY ON
105
106 uint8_t fb_shift{0}; // PG: feedback shift value
107 bool CON{false}; // PG: connection (algorithm) type
108 bool eg_type{false}; // EG: percussive/non-percussive mode
109
110 // LFO
111 uint8_t AMmask{0}; // LFO Amplitude Modulation enable mask
112 bool vib{false}; // LFO Phase Modulation enable flag (active high)
113
114 uint8_t ar{0}; // attack rate: AR<<2
115 uint8_t dr{0}; // decay rate: DR<<2
116 uint8_t rr{0}; // release rate:RR<<2
117 uint8_t KSR{0}; // key scale rate
118 uint8_t ksl{0}; // key scale level
119 uint8_t ksr{0}; // key scale rate: kcode>>KSR
120 uint8_t mul{0}; // multiple: mul_tab[ML]
121 };
122
123 class Channel {
124 public:
125 void chan_calc(unsigned lfo_am);
126 void chan_calc_ext(unsigned lfo_am);
127
128 template<typename Archive>
129 void serialize(Archive& ar, unsigned version);
130
131 std::array<Slot, 2> slot;
132
133 int block_fnum{0}; // block+fnum
134 FreqIndex fc{0}; // Freq. Increment base
135 unsigned ksl_base{0}; // KeyScaleLevel Base step
136 uint8_t kcode{0}; // key code (for key scaling)
137
138 // there are 12 2-operator channels which can be combined in pairs
139 // to form six 4-operator channel, they are:
140 // 0 and 3,
141 // 1 and 4,
142 // 2 and 5,
143 // 9 and 12,
144 // 10 and 13,
145 // 11 and 14
146 bool extended{false}; // set if this channel forms up a 4op channel with
147 // another channel (only used by first of pair of
148 // channels, ie 0,1,2 and 9,10,11)
149 };
150
151 // SoundDevice
152 [[nodiscard]] float getAmplificationFactorImpl() const override;
153 void generateChannels(std::span<float*> bufs, unsigned num) override;
154
155 void callback(uint8_t flag) override;
156
157 void writeRegDirect(unsigned r, uint8_t v, EmuTime::param time);
158 void init_tables();
159 void setStatus(uint8_t flag);
160 void resetStatus(uint8_t flag);
161 void changeStatusMask(uint8_t flag);
162 void advance();
163
164 [[nodiscard]] inline unsigned genPhaseHighHat();
165 [[nodiscard]] inline unsigned genPhaseSnare();
166 [[nodiscard]] inline unsigned genPhaseCymbal();
167
168 void chan_calc_rhythm(unsigned lfo_am);
169 void set_mul(unsigned sl, uint8_t v);
170 void set_ksl_tl(unsigned sl, uint8_t v);
171 void set_ar_dr(unsigned sl, uint8_t v);
172 void set_sl_rr(unsigned sl, uint8_t v);
173 bool checkMuteHelper();
174
175 [[nodiscard]] inline bool isExtended(unsigned ch) const;
176 [[nodiscard]] inline Channel& getFirstOfPair(unsigned ch);
177 [[nodiscard]] inline Channel& getSecondOfPair(unsigned ch);
178
179 struct Debuggable final : SimpleDebuggable {
180 Debuggable(MSXMotherBoard& motherBoard, const std::string& name);
181 [[nodiscard]] uint8_t read(unsigned address) override;
182 void write(unsigned address, uint8_t value, EmuTime::param time) override;
183 } debuggable;
184
185 // Bitmask for register 0x04
186 static constexpr int R04_ST1 = 0x01; // Timer1 Start
187 static constexpr int R04_ST2 = 0x02; // Timer2 Start
188 static constexpr int R04_MASK_T2 = 0x20; // Mask Timer2 flag
189 static constexpr int R04_MASK_T1 = 0x40; // Mask Timer1 flag
190 static constexpr int R04_IRQ_RESET = 0x80; // IRQ RESET
191
192 // Bitmask for status register
193 static constexpr int STATUS_T2 = R04_MASK_T2;
194 static constexpr int STATUS_T1 = R04_MASK_T1;
195 // Timers (see EmuTimer class for details about timing)
196 const std::unique_ptr<EmuTimer> timer1; // 80.8us OPL4 ( 80.5us OPL3)
197 const std::unique_ptr<EmuTimer> timer2; // 323.1us OPL4 (321.8us OPL3)
198
199 IRQHelper irq;
200
201 std::array<int, 18> chanOut = {}; // 18 channels
202
203 std::array<uint8_t, 512> reg = {};
204 std::array<Channel, 18> channel; // OPL3 chips have 18 channels
205
206 std::array<int, 18 * 4> pan; // channels output masks 4 per channel
207 // 0xffffffff = enable
208 unsigned eg_cnt{0}; // global envelope generator counter
209 unsigned noise_rng{1}; // 23 bit noise shift register
210
211 // LFO
212 using LFOAMIndex = FixedPoint< 6>;
213 using LFOPMIndex = FixedPoint<10>;
214 LFOAMIndex lfo_am_cnt{0};
215 LFOPMIndex lfo_pm_cnt{0};
216 bool lfo_am_depth{false};
217 uint8_t lfo_pm_depth_range{0};
218
219 uint8_t rhythm{0}; // Rhythm mode
220 bool nts{false}; // NTS (note select)
221 bool OPL3_mode{false}; // OPL3 extension enable flag
222
223 uint8_t status{0}; // status flag
224 uint8_t status2{0};
225 uint8_t statusMask{0}; // status mask
226
227 bool alreadySignaledNEW2{false};
228 const bool isYMF278; // true iff this is actually a YMF278
229 // ATM only used for NEW2 bit
230};
232
233} // namespace openmsx
234
235#endif
Debuggable(const Debuggable &)=delete
virtual byte read(unsigned address, EmuTime::param time)
void write(unsigned address, byte value) override
static constexpr int SIN_LEN
Definition: YMF262.hh:26
void reset(EmuTime::param time)
Definition: YMF262.cc:1390
uint8_t peekStatus() const
Definition: YMF262.cc:1474
void setMixLevel(uint8_t x, EmuTime::param time)
Definition: YMF262.cc:1494
uint8_t readStatus()
Definition: YMF262.cc:1466
YMF262(const std::string &name, const DeviceConfig &config, bool isYMF278)
Definition: YMF262.cc:1431
static constexpr int SIN_BITS
Definition: YMF262.hh:25
static constexpr int SIN_MASK
Definition: YMF262.hh:27
FixedPoint< 16 > FreqIndex
16.16 fixed point type for frequency calculations
Definition: YMF262.hh:49
void serialize(Archive &ar, unsigned version)
Definition: YMF262.cc:1655
void writeReg(unsigned r, uint8_t v, EmuTime::param time)
Definition: YMF262.cc:1031
uint8_t peekReg(unsigned reg) const
Definition: YMF262.cc:1026
uint8_t readReg(unsigned reg)
Definition: YMF262.cc:1020
void writeReg512(unsigned r, uint8_t v, EmuTime::param time)
Definition: YMF262.cc:1039
This file implemented 3 utility functions:
Definition: Autofire.cc:9
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)
IntHelper< IRQSource > IRQHelper
Definition: IRQHelper.hh:122