1 #include "Opl_Apu.h"
2
3 #include "blargg_source.h"
4
5 extern "C" {
6 #include "../vgmplay/VGMPlay/chips/mamedef.h"
7 #include "../vgmplay/VGMPlay/chips/emu2413.h"
8 #include "../vgmplay/VGMPlay/chips/fmopl.h"
9 }
10
11 static unsigned char vrc7_inst[(16 + 3) * 8] =
12 {
13 #include "../vgmplay/VGMPlay/chips/vrc7tone.h"
14 };
15
Opl_Apu()16 Opl_Apu::Opl_Apu() { opl = 0; opl_memory = 0; }
17
init(long clock,long rate,blip_time_t period,type_t type)18 blargg_err_t Opl_Apu::init( long clock, long rate, blip_time_t period, type_t type )
19 {
20 type_ = type;
21 clock_ = clock;
22 rate_ = rate;
23 period_ = period;
24 set_output( 0, 0 );
25 volume( 1.0 );
26 switch (type)
27 {
28 case type_opll:
29 case type_msxmusic:
30 case type_smsfmunit:
31 opl = OPLL_new( (uint32_t) clock, (uint32_t) rate );
32 OPLL_SetChipMode( (OPLL *) opl, 0);
33 break;
34
35 case type_vrc7:
36 opl = OPLL_new( (uint32_t) clock, (uint32_t) rate );
37 OPLL_SetChipMode((OPLL *) opl, 1 );
38 OPLL_setPatch((OPLL *) opl, vrc7_inst);
39 break;
40
41 case type_opl:
42 opl = ym3526_init( (uint32_t) clock, (uint32_t) rate );
43 break;
44
45 case type_msxaudio:
46 //logfile = fopen("c:\\temp\\msxaudio.log", "wb");
47 opl = y8950_init( (uint32_t) clock, (uint32_t) rate );
48 opl_memory = malloc( 32768 );
49 y8950_set_delta_t_memory( opl, opl_memory, 32768 );
50 break;
51
52 case type_opl2:
53 opl = ym3812_init( (uint32_t) clock, (uint32_t) rate );
54 break;
55 }
56 reset();
57 return 0;
58 }
59
~Opl_Apu()60 Opl_Apu::~Opl_Apu()
61 {
62 if (opl)
63 {
64 switch (type_)
65 {
66 case type_opll:
67 case type_msxmusic:
68 case type_smsfmunit:
69 case type_vrc7:
70 OPLL_delete( (OPLL *) opl );
71 break;
72
73 case type_opl:
74 ym3526_shutdown( opl );
75 break;
76
77 case type_msxaudio:
78 y8950_shutdown( opl );
79 free( opl_memory );
80 //fclose( logfile );
81 break;
82
83 case type_opl2:
84 ym3812_shutdown( opl );
85 break;
86 }
87 }
88 }
89
reset()90 void Opl_Apu::reset()
91 {
92 addr = 0;
93 next_time = 0;
94 last_amp = 0;
95
96 switch (type_)
97 {
98 case type_opll:
99 case type_msxmusic:
100 case type_smsfmunit:
101 case type_vrc7:
102 OPLL_reset( (OPLL *) opl );
103 break;
104
105 case type_opl:
106 ym3526_reset_chip( opl );
107 break;
108
109 case type_msxaudio:
110 y8950_reset_chip( opl );
111 break;
112
113 case type_opl2:
114 ym3812_reset_chip( opl );
115 break;
116 }
117 }
118
write_data(blip_time_t time,int data)119 void Opl_Apu::write_data( blip_time_t time, int data )
120 {
121 run_until( time );
122 switch (type_)
123 {
124 case type_opll:
125 case type_msxmusic:
126 case type_smsfmunit:
127 case type_vrc7:
128 OPLL_writeIO( (OPLL *) opl, 0, addr );
129 OPLL_writeIO( (OPLL *) opl, 1, data );
130 break;
131
132 case type_opl:
133 ym3526_write( opl, 0, addr );
134 ym3526_write( opl, 1, data );
135 break;
136
137 case type_msxaudio:
138 /*if ( addr >= 7 && addr <= 7 + 11 )
139 {
140 unsigned char temp [2] = { addr - 7, data };
141 fwrite( &temp, 1, 2, logfile );
142 }*/
143 y8950_write( opl, 0, addr );
144 y8950_write( opl, 1, data );
145 break;
146
147 case type_opl2:
148 ym3812_write( opl, 0, addr );
149 ym3812_write( opl, 1, data );
150 break;
151 }
152 }
153
read(blip_time_t time,int port)154 int Opl_Apu::read( blip_time_t time, int port )
155 {
156 run_until( time );
157 switch (type_)
158 {
159 case type_opll:
160 case type_msxmusic:
161 case type_smsfmunit:
162 case type_vrc7:
163 return port ? 0xFF : 0;
164
165 case type_opl:
166 return ym3526_read( opl, port );
167
168 case type_msxaudio:
169 {
170 int ret = y8950_read( opl, port );
171 /*unsigned char temp [2] = { port + 0x80, ret };
172 fwrite( &temp, 1, 2, logfile );*/
173 return ret;
174 }
175
176 case type_opl2:
177 return ym3812_read( opl, port );
178 }
179
180 return 0;
181 }
182
end_frame(blip_time_t time)183 void Opl_Apu::end_frame( blip_time_t time )
184 {
185 run_until( time );
186 next_time -= time;
187
188 if ( output_ )
189 output_->set_modified();
190 }
191
run_until(blip_time_t end_time)192 void Opl_Apu::run_until( blip_time_t end_time )
193 {
194 if ( end_time > next_time )
195 {
196 blip_time_t time_delta = end_time - next_time;
197 blip_time_t time = next_time;
198 unsigned count = time_delta / period_ + 1;
199 switch (type_)
200 {
201 case type_opll:
202 case type_msxmusic:
203 case type_smsfmunit:
204 case type_vrc7:
205 {
206 e_int32 bufMO[ 1024 ];
207 e_int32 bufRO[ 1024 ];
208 e_int32 * buffers[2] = { bufMO, bufRO };
209
210 while ( count > 0 )
211 {
212 unsigned todo = count;
213 if ( todo > 1024 ) todo = 1024;
214 OPLL_calc_stereo( (OPLL *) opl, buffers, todo, -1 );
215
216 if ( output_ )
217 {
218 int last_amp = this->last_amp;
219 for ( unsigned i = 0; i < todo; i++ )
220 {
221 int amp = bufMO [i] + bufRO [i];
222 int delta = amp - last_amp;
223 if ( delta )
224 {
225 last_amp = amp;
226 synth.offset_inline( time, delta, output_ );
227 }
228 time += period_;
229 }
230 this->last_amp = last_amp;
231 }
232 else time += period_ * todo;
233
234 count -= todo;
235 }
236 }
237 break;
238
239 case type_opl:
240 case type_msxaudio:
241 case type_opl2:
242 {
243 OPLSAMPLE bufL[ 1024 ];
244 OPLSAMPLE bufR[ 1024 ];
245 OPLSAMPLE* buffers[2] = {bufL, bufR};
246
247 while ( count > 0 )
248 {
249 unsigned todo = count;
250 if ( todo > 1024 ) todo = 1024;
251 switch (type_)
252 {
253 case type_opl: ym3526_update_one( opl, buffers, todo ); break;
254 case type_msxaudio: y8950_update_one( opl, buffers, todo ); break;
255 case type_opl2: ym3812_update_one( opl, buffers, todo ); break;
256 default: break;
257 }
258
259 if ( output_ )
260 {
261 int last_amp = this->last_amp;
262 for ( unsigned i = 0; i < todo; i++ )
263 {
264 int amp = bufL [i] + bufR [i];
265 int delta = amp - last_amp;
266 if ( delta )
267 {
268 last_amp = amp;
269 synth.offset_inline( time, delta, output_ );
270 }
271 time += period_;
272 }
273 this->last_amp = last_amp;
274 }
275 else time += period_ * todo;
276
277 count -= todo;
278 }
279 }
280 break;
281 }
282 next_time = time;
283 }
284 }