ScummVM API documentation
nuked.h
1/* Nuked OPL3 emulator.
2 *
3 * Copyright (C) 2013-2020 Nuke.YKT
4 * Copyright (C) 2026 Tony Gies (Nuked-OPL3-fast modifications)
5 *
6 * This file is part of Nuked OPL3.
7 *
8 * Nuked OPL3 is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as
10 * published by the Free Software Foundation, either version 2.1
11 * of the License, or (at your option) any later version.
12 *
13 * Nuked OPL3 is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with Nuked OPL3. If not, see <https://www.gnu.org/licenses/>.
20 *
21 * Thanks:
22 * MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh):
23 * Feedback and Rhythm part calculation information.
24 * forums.submarine.org.uk(carbon14, opl3):
25 * Tremolo and phase generator calculation information.
26 * OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
27 * OPL2 ROMs.
28 * siliconpr0n.org(John McMaster, digshadow):
29 * YMF262 and VRC VII decaps and die shots.
30 *
31 * Upstream version: 1.8 (commit cfedb09)
32 * Fork version: 1.8-fast.2
33 * Fork home: https://github.com/tgies/Nuked-OPL3-fast
34 *
35 * Nuked-OPL3-fast is a bit-exact performance-optimized fork of Nuked-OPL3.
36 * Audio output is identical to upstream for the same register stream.
37 */
38
39#ifndef AUDIO_SOFTSYNTH_OPL_NUKED_H
40#define AUDIO_SOFTSYNTH_OPL_NUKED_H
41
42#include "common/scummsys.h"
43#include "audio/fmopl.h"
44
45#ifndef DISABLE_NUKED_OPL
46
47#ifndef OPL_ENABLE_STEREOEXT
48#define OPL_ENABLE_STEREOEXT 0
49#endif
50
51#ifndef OPL_QUIRK_CHANNELSAMPLEDELAY
52#define OPL_QUIRK_CHANNELSAMPLEDELAY (!OPL_ENABLE_STEREOEXT)
53#endif
54
55#define OPL_WRITEBUF_SIZE 1024
56#define OPL_WRITEBUF_DELAY 2
57
58namespace OPL {
59namespace NUKED {
60
61typedef struct _opl3_slot opl3_slot;
62typedef struct _opl3_channel opl3_channel;
63typedef struct _opl3_chip opl3_chip;
64
65struct _opl3_slot {
66 opl3_channel *channel;
67 opl3_chip *chip;
68 int16_t *mod;
69 uint8_t *trem;
70 uint32_t pg_reset;
71 uint32_t pg_phase;
72 uint32_t pg_inc;
73 int16_t out;
74 int16_t fbmod;
75 int16_t prout;
76 uint16_t eg_rout;
77 uint16_t eg_out;
78 /* Cached (reg_tl << 2) + (eg_ksl >> kslshift[reg_ksl]); maintained by
79 * OPL3_EnvelopeUpdateKSL whenever any of those inputs change. Hoists
80 * a load + lookup + shift out of the per-sample envelope hot path. */
81 uint16_t eg_tl_ksl;
82 uint16_t pg_phase_out;
83 uint8_t key;
84 uint8_t eg_gen;
85 uint8_t reg_vib;
86 uint8_t reg_mult;
87 uint8_t reg_wf;
88 uint8_t slot_num;
89 uint8_t eg_ksl;
90 uint8_t eg_ks;
91 uint8_t reg_type;
92 uint8_t reg_ksr;
93 uint8_t reg_ksl;
94 uint8_t reg_tl;
95 uint8_t reg_ar;
96 uint8_t reg_dr;
97 uint8_t reg_sl;
98 uint8_t reg_rr;
99 uint8_t eg_rates[4];
100 uint8_t eg_rate_hi[4];
101 uint8_t eg_rate_lo[4];
102 /* Phase increment per vibrato position, maintained by
103 * OPL3_PhaseUpdateInc (and rebuilt on vibshift changes); pg_inc_vib[pos]
104 * equals the upstream per-sample vibrato f_num adjustment for that pos. */
105 uint32_t pg_inc_vib[8];
106};
107
109 opl3_slot *slotz[2];/*Don't use "slots" keyword to avoid conflict with Qt applications*/
110 opl3_channel *pair;
111 opl3_chip *chip;
112 int16_t *out[4];
113#if OPL_QUIRK_CHANNELSAMPLEDELAY
114 /* Mix-pass pointer lists: identical to out[] except entries pointing at
115 * a delayed slot's out are redirected to its prout, which holds the
116 * previous sample's out once all 36 slots are processed. out_left delays
117 * slots 15-35 and out_right delays 33-35, reproducing the
118 * CHANNELSAMPLEDELAY snapshots without staging slot processing around
119 * the mixes. */
120 int16_t *out_left[4];
121 int16_t *out_right[4];
122#endif
123 uint8_t out_cnt;
124
125#if OPL_ENABLE_STEREOEXT
126 int32_t leftpan;
127 int32_t rightpan;
128#endif
129
130 uint8_t chtype;
131 uint16_t f_num;
132 uint8_t block;
133 uint8_t fb;
134 uint8_t con;
135 uint8_t alg;
136 uint8_t ksv;
137 uint16_t cha, chb;
138 uint16_t chc, chd;
139 uint8_t ch_num;
140};
141
142typedef struct _opl3_writebuf {
143 uint64_t time;
144 uint16_t reg;
145 uint8_t data;
147
149 opl3_channel channel[18];
150 opl3_slot slot[36];
151 uint16_t timer;
152 uint64_t eg_timer;
153 uint8_t eg_timerrem;
154 uint8_t eg_state;
155 uint8_t eg_add;
156 uint8_t eg_timer_lo;
157 uint8_t newm;
158 uint8_t nts;
159 uint8_t rhy;
160 uint8_t vibpos;
161 uint8_t vibshift;
162 uint8_t tremolo;
163 uint8_t tremolopos;
164 uint8_t tremoloshift;
165 uint8_t tremolo_dirty;
166 uint32_t noise;
167 /* Bit 0 of the noise LFSR state as seen by the hh (slot 13) and sd
168 * (slot 16) rhythm operators, precomputed per sample */
169 uint32_t noise_hh;
170 uint32_t noise_sd;
171 int16_t zeromod;
172 int32_t mixbuff[4];
173 uint8_t rm_hh_bit2;
174 uint8_t rm_hh_bit3;
175 uint8_t rm_hh_bit7;
176 uint8_t rm_hh_bit8;
177 uint8_t rm_tc_bit3;
178 uint8_t rm_tc_bit5;
179
180#if OPL_ENABLE_STEREOEXT
181 uint8_t stereoext;
182#endif
183
184 /* OPL3L */
185 int32_t rateratio;
186 int32_t samplecnt;
187 int16_t oldsamples[4];
188 int16_t samples[4];
189
190 uint64_t writebuf_samplecnt;
191 uint32_t writebuf_cur;
192 uint32_t writebuf_last;
193 uint64_t writebuf_lasttime;
194 opl3_writebuf writebuf[OPL_WRITEBUF_SIZE];
195};
196
197void OPL3_Generate(opl3_chip *chip, int16_t *buf);
198void OPL3_GenerateResampled(opl3_chip *chip, int16_t *buf);
199void OPL3_Reset(opl3_chip *chip, uint32_t samplerate);
200void OPL3_WriteReg(opl3_chip *chip, uint16_t reg, uint8_t v);
201void OPL3_WriteRegBuffered(opl3_chip *chip, uint16_t reg, uint8_t v);
202void OPL3_GenerateStream(opl3_chip *chip, int16_t *sndptr, uint32_t numsamples);
203
204void OPL3_Generate4Ch(opl3_chip *chip, int16_t *buf4);
205void OPL3_Generate4ChResampled(opl3_chip *chip, int16_t *buf4);
206void OPL3_Generate4ChStream(opl3_chip *chip, int16_t *sndptr1, int16_t *sndptr2, uint32_t numsamples);
207
208class OPL : public ::OPL::OPL, public Audio::EmulatedChip {
209private:
210 Config::OplType _type;
211 uint _rate;
212 opl3_chip chip;
213 uint address[2];
214 void dualWrite(uint8 index, uint8 reg, uint8 val);
215
216public:
217 OPL(Config::OplType type);
218 ~OPL();
219
220 bool init() override;
221 void reset() override;
222
223 void write(int a, int v) override;
224
225 void writeReg(int r, int v) override;
226
227 bool isStereo() const override { return true; }
228
229protected:
230 void generateSamples(int16 *buffer, int length) override;
231};
232
233}
234}
235
236#endif // !DISABLE_NUKED_OPL
237
238#endif
Definition: chip.h:112
OplType
Definition: fmopl.h:58
Definition: nuked.h:208
void writeReg(int r, int v) override
bool init() override
void reset() override
bool isStereo() const override
Definition: nuked.h:227
void write(int a, int v) override
void generateSamples(int16 *buffer, int length) override
Definition: fmopl.h:116
Definition: nuked.h:108
Definition: nuked.h:148
Definition: nuked.h:65
Definition: nuked.h:142