openMSX
YM2151.hh
Go to the documentation of this file.
1/*
2 **
3 ** File: ym2151.h - header file for software implementation of YM2151
4 ** FM Operator Type-M(OPM)
5 **
6 ** (c) 1997-2002 Jarek Burczynski (s0246@poczta.onet.pl, bujar@mame.net)
7 ** Some of the optimizing ideas by Tatsuyuki Satoh
8 **
9 ** Version 2.150 final beta May, 11th 2002
10 **
11 **
12 ** I would like to thank following people for making this project possible:
13 **
14 ** Beauty Planets - for making a lot of real YM2151 samples and providing
15 ** additional informations about the chip. Also for the time spent making
16 ** the samples and the speed of replying to my endless requests.
17 **
18 ** Shigeharu Isoda - for general help, for taking time to scan his YM2151
19 ** Japanese Manual first of all, and answering MANY of my questions.
20 **
21 ** Nao - for giving me some info about YM2151 and pointing me to Shigeharu.
22 ** Also for creating fmemu (which I still use to test the emulator).
23 **
24 ** Aaron Giles and Chris Hardy - they made some samples of one of my favorite
25 ** arcade games so I could compare it to my emulator.
26 **
27 ** Bryan McPhail and Tim (powerjaw) - for making some samples.
28 **
29 ** Ishmair - for the datasheet and motivation.
30 */
31
32// YM2164/OPP specifics info from http://map.grauw.nl/resources/sound/yamaha_ym2164.php
33
34#ifndef YM2151_HH
35#define YM2151_HH
36
38#include "EmuTimer.hh"
39
40#include "EmuTime.hh"
41#include "IRQHelper.hh"
42
43#include <array>
44#include <cstdint>
45#include <string>
46#include <memory>
47
48namespace openmsx {
49
50class DeviceConfig;
51
52class YM2151 final : public ResampledSoundDevice, private EmuTimerCallback
53{
54public:
55 enum class Variant : char {
56 YM2151, // aka OPM
57 YM2164, // aka OPP
58 };
59
60 YM2151(const std::string& name, static_string_view desc,
61 const DeviceConfig& config, EmuTime::param time, Variant variant);
62 ~YM2151();
63
64 void reset(EmuTime::param time);
65 void writeReg(uint8_t r, uint8_t v, EmuTime::param time);
66 [[nodiscard]] uint8_t readStatus() const;
67
68 template<typename Archive>
69 void serialize(Archive& ar, unsigned version);
70
71private:
72 // a single operator
73 struct YM2151Operator {
74 template<typename Archive>
75 void serialize(Archive& ar, unsigned version);
76
77 int* connect; // operator output 'direction'
78 int* mem_connect; // where to put the delayed sample (MEM)
79
80 unsigned phase; // accumulated operator phase
81 unsigned freq; // operator frequency count
82 int dt1; // current DT1 (detune 1 phase inc/decrement) value
83 unsigned mul; // frequency count multiply
84 unsigned dt1_i; // DT1 index * 32
85 unsigned dt2; // current DT2 (detune 2) value
86
87 int mem_value; // delayed sample (MEM) value
88
89 // channel specific data
90 // note: each operator number 0 contains channel specific data
91 unsigned fb_shift; // feedback shift value for operators 0 in each channel
92 int fb_out_curr; // operator feedback value (used only by operators 0)
93 int fb_out_prev; // previous feedback value (used only by operators 0)
94 unsigned kc; // channel KC (copied to all operators)
95 unsigned kc_i; // just for speedup
96 int8_t pms; // channel PMS 0..7
97 unsigned ams; // channel AMS
98
99 unsigned AMmask; // LFO Amplitude Modulation enable mask
100 unsigned state; // Envelope state: 4-attack(AR)
101 // 3-decay(D1R)
102 // 2-sustain(D2R)
103 // 1-release(RR)
104 // 0-off
105 unsigned tl; // Total attenuation Level
106 int volume; // current envelope attenuation level
107 unsigned d1l; // envelope switches to sustain state after
108
109 unsigned key; // 0=last key was KEY OFF, 1=last key was KEY ON
110
111 unsigned ks; // key scale
112 unsigned ar; // attack rate
113 unsigned d1r; // decay rate
114 unsigned d2r; // sustain rate
115 unsigned rr; // release rate
116
117 uint8_t eg_sh_ar; // (attack state)
118 uint8_t eg_sel_ar; // (attack state)
119 uint8_t eg_sh_d1r; // (decay state)
120 uint8_t eg_sel_d1r; // (decay state)
121 // reaching this level
122 uint8_t eg_sh_d2r; // (sustain state)
123 uint8_t eg_sel_d2r; // (sustain state)
124 uint8_t eg_sh_rr; // (release state)
125 uint8_t eg_sel_rr; // (release state)
126 };
127
128 void setConnect(std::span<YM2151Operator, 4> o, int cha, int v);
129
130 // SoundDevice
131 void generateChannels(std::span<float*> bufs, unsigned num) override;
132
133 void callback(uint8_t flag) override;
134 void setStatus(uint8_t flags);
135 void resetStatus(uint8_t flags);
136
137 // operator methods
138 void envelopeKONKOFF(std::span<YM2151Operator, 4> op, int v) const;
139 static void refreshEG(std::span<YM2151Operator, 4> op);
140 [[nodiscard]] int opCalc(const YM2151Operator& op, unsigned env, int pm) const;
141 [[nodiscard]] int opCalc1(const YM2151Operator& op, unsigned env, int pm) const;
142 [[nodiscard]] inline unsigned volumeCalc(const YM2151Operator& op, unsigned AM) const;
143 inline void keyOn(YM2151Operator& op, unsigned keySet) const;
144 inline void keyOff(YM2151Operator& op, unsigned keyClear) const;
145
146 // general chip methods
147 void chanCalc(unsigned chan);
148 void chan7Calc();
149
150 void advanceEG();
151 void advance();
152
153 [[nodiscard]] bool checkMuteHelper();
154
155 IRQHelper irq;
156
157 // Timers (see EmuTimer class for details about timing)
158 const std::unique_ptr<EmuTimer> timer1;
159 const std::unique_ptr<EmuTimer> timer2;
160
161 std::array<YM2151Operator, 32> oper; // the 32 operators
162
163 std::array<unsigned, 16> pan; // channels output masks (0xffffffff = enable)
164
165 unsigned eg_cnt; // global envelope generator counter
166 unsigned eg_timer; // global envelope generator counter
167 // works at frequency = chip-clock / (64 * 3)
168 unsigned lfo_phase; // accumulated LFO phase (0 to 255)
169 unsigned lfo_timer; // LFO timer
170 unsigned lfo_overflow; // LFO generates new output when lfo_timer
171 // reaches this value
172 unsigned lfo_counter; // LFO phase increment counter
173 unsigned lfo_counter_add;// step of lfo_counter
174 unsigned lfa; // LFO current AM output
175 int lfp; // LFO current PM output
176
177 unsigned noise; // noise enable/period register
178 // bit 7 - noise enable, bits 4-0 - noise period
179 unsigned noise_rng; // 17 bit noise shift register
180 int noise_p; // current noise 'phase'
181 int noise_f; // current noise period
182
183 unsigned csm_req; // CSM KEY ON / KEY OFF sequence request
184
185 unsigned irq_enable; // IRQ enable for timer B (bit 3) and timer A
186 // (bit 2); bit 7 - CSM mode (keyon to all
187 // slots, every time timer A overflows)
188 uint8_t status; // chip status (BUSY, IRQ Flags)
189
190 std::array<int, 8> chanOut;
191 int m2, c1, c2; // Phase Modulation input for operators 2,3,4
192 int mem; // one sample delay memory
193
194 uint16_t timer_A_val{0};
195
196 uint8_t lfo_wsel; // LFO waveform (0-saw, 1-square, 2-triangle,
197 // 3-random noise)
198 uint8_t amd; // LFO Amplitude Modulation Depth
199 int8_t pmd; // LFO Phase Modulation Depth
200
201 uint8_t test; // TEST register
202 uint8_t ct; // output control pins (bit1-CT2, bit0-CT1)
203
204 std::array<uint8_t, 256> regs = {}; // only used for serialization ATM
205 const Variant variant; // Whether we're emulating YM2151 or YM2164
206};
207
208} // namespace openmsx
209
210#endif
uint8_t readStatus() const
Definition YM2151.cc:1535
void reset(EmuTime::param time)
Definition YM2151.cc:927
void serialize(Archive &ar, unsigned version)
Definition YM2151.cc:1600
void writeReg(uint8_t r, uint8_t v, EmuTime::param time)
Definition YM2151.cc:651
static_string_view
This file implemented 3 utility functions:
Definition Autofire.cc:11
void serialize(Archive &ar, T &t, unsigned version)
IntHelper< IRQSource > IRQHelper
Definition IRQHelper.hh:124