1 /* 2 * QEMU Proxy for OPL2/3 emulation by MAME team 3 * 4 * Copyright (c) 2004-2005 Vassili Karpov (malc) 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include "qapi/error.h" 27 #include "hw/hw.h" 28 #include "hw/audio/audio.h" 29 #include "audio/audio.h" 30 #include "hw/isa/isa.h" 31 32 //#define DEBUG 33 34 #define ADLIB_KILL_TIMERS 1 35 36 #ifdef HAS_YMF262 37 #define ADLIB_DESC "Yamaha YMF262 (OPL3)" 38 #else 39 #define ADLIB_DESC "Yamaha YM3812 (OPL2)" 40 #endif 41 42 #ifdef DEBUG 43 #include "qemu/timer.h" 44 #endif 45 46 #define dolog(...) AUD_log ("adlib", __VA_ARGS__) 47 #ifdef DEBUG 48 #define ldebug(...) dolog (__VA_ARGS__) 49 #else 50 #define ldebug(...) 51 #endif 52 53 #ifdef HAS_YMF262 54 #include "ymf262.h" 55 void YMF262UpdateOneQEMU (int which, INT16 *dst, int length); 56 #define SHIFT 2 57 #else 58 #include "fmopl.h" 59 #define SHIFT 1 60 #endif 61 62 #define TYPE_ADLIB "adlib" 63 #define ADLIB(obj) OBJECT_CHECK(AdlibState, (obj), TYPE_ADLIB) 64 65 typedef struct { 66 ISADevice parent_obj; 67 68 QEMUSoundCard card; 69 uint32_t freq; 70 uint32_t port; 71 int ticking[2]; 72 int enabled; 73 int active; 74 int bufpos; 75 #ifdef DEBUG 76 int64_t exp[2]; 77 #endif 78 int16_t *mixbuf; 79 uint64_t dexp[2]; 80 SWVoiceOut *voice; 81 int left, pos, samples; 82 QEMUAudioTimeStamp ats; 83 #ifndef HAS_YMF262 84 FM_OPL *opl; 85 #endif 86 PortioList port_list; 87 } AdlibState; 88 89 static AdlibState *glob_adlib; 90 91 static void adlib_stop_opl_timer (AdlibState *s, size_t n) 92 { 93 #ifdef HAS_YMF262 94 YMF262TimerOver (0, n); 95 #else 96 OPLTimerOver (s->opl, n); 97 #endif 98 s->ticking[n] = 0; 99 } 100 101 static void adlib_kill_timers (AdlibState *s) 102 { 103 size_t i; 104 105 for (i = 0; i < 2; ++i) { 106 if (s->ticking[i]) { 107 uint64_t delta; 108 109 delta = AUD_get_elapsed_usec_out (s->voice, &s->ats); 110 ldebug ( 111 "delta = %f dexp = %f expired => %d\n", 112 delta / 1000000.0, 113 s->dexp[i] / 1000000.0, 114 delta >= s->dexp[i] 115 ); 116 if (ADLIB_KILL_TIMERS || delta >= s->dexp[i]) { 117 adlib_stop_opl_timer (s, i); 118 AUD_init_time_stamp_out (s->voice, &s->ats); 119 } 120 } 121 } 122 } 123 124 static void adlib_write(void *opaque, uint32_t nport, uint32_t val) 125 { 126 AdlibState *s = opaque; 127 int a = nport & 3; 128 129 s->active = 1; 130 AUD_set_active_out (s->voice, 1); 131 132 adlib_kill_timers (s); 133 134 #ifdef HAS_YMF262 135 YMF262Write (0, a, val); 136 #else 137 OPLWrite (s->opl, a, val); 138 #endif 139 } 140 141 static uint32_t adlib_read(void *opaque, uint32_t nport) 142 { 143 AdlibState *s = opaque; 144 uint8_t data; 145 int a = nport & 3; 146 147 adlib_kill_timers (s); 148 149 #ifdef HAS_YMF262 150 data = YMF262Read (0, a); 151 #else 152 data = OPLRead (s->opl, a); 153 #endif 154 return data; 155 } 156 157 static void timer_handler (int c, double interval_Sec) 158 { 159 AdlibState *s = glob_adlib; 160 unsigned n = c & 1; 161 #ifdef DEBUG 162 double interval; 163 int64_t exp; 164 #endif 165 166 if (interval_Sec == 0.0) { 167 s->ticking[n] = 0; 168 return; 169 } 170 171 s->ticking[n] = 1; 172 #ifdef DEBUG 173 interval = NANOSECONDS_PER_SECOND * interval_Sec; 174 exp = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + interval; 175 s->exp[n] = exp; 176 #endif 177 178 s->dexp[n] = interval_Sec * 1000000.0; 179 AUD_init_time_stamp_out (s->voice, &s->ats); 180 } 181 182 static int write_audio (AdlibState *s, int samples) 183 { 184 int net = 0; 185 int pos = s->pos; 186 187 while (samples) { 188 int nbytes, wbytes, wsampl; 189 190 nbytes = samples << SHIFT; 191 wbytes = AUD_write ( 192 s->voice, 193 s->mixbuf + (pos << (SHIFT - 1)), 194 nbytes 195 ); 196 197 if (wbytes) { 198 wsampl = wbytes >> SHIFT; 199 200 samples -= wsampl; 201 pos = (pos + wsampl) % s->samples; 202 203 net += wsampl; 204 } 205 else { 206 break; 207 } 208 } 209 210 return net; 211 } 212 213 static void adlib_callback (void *opaque, int free) 214 { 215 AdlibState *s = opaque; 216 int samples, net = 0, to_play, written; 217 218 samples = free >> SHIFT; 219 if (!(s->active && s->enabled) || !samples) { 220 return; 221 } 222 223 to_play = audio_MIN (s->left, samples); 224 while (to_play) { 225 written = write_audio (s, to_play); 226 227 if (written) { 228 s->left -= written; 229 samples -= written; 230 to_play -= written; 231 s->pos = (s->pos + written) % s->samples; 232 } 233 else { 234 return; 235 } 236 } 237 238 samples = audio_MIN (samples, s->samples - s->pos); 239 if (!samples) { 240 return; 241 } 242 243 #ifdef HAS_YMF262 244 YMF262UpdateOneQEMU (0, s->mixbuf + s->pos * 2, samples); 245 #else 246 YM3812UpdateOne (s->opl, s->mixbuf + s->pos, samples); 247 #endif 248 249 while (samples) { 250 written = write_audio (s, samples); 251 252 if (written) { 253 net += written; 254 samples -= written; 255 s->pos = (s->pos + written) % s->samples; 256 } 257 else { 258 s->left = samples; 259 return; 260 } 261 } 262 } 263 264 static void Adlib_fini (AdlibState *s) 265 { 266 #ifdef HAS_YMF262 267 YMF262Shutdown (); 268 #else 269 if (s->opl) { 270 OPLDestroy (s->opl); 271 s->opl = NULL; 272 } 273 #endif 274 275 g_free(s->mixbuf); 276 277 s->active = 0; 278 s->enabled = 0; 279 AUD_remove_card (&s->card); 280 } 281 282 static MemoryRegionPortio adlib_portio_list[] = { 283 { 0, 4, 1, .read = adlib_read, .write = adlib_write, }, 284 { 0, 2, 1, .read = adlib_read, .write = adlib_write, }, 285 { 0x388, 4, 1, .read = adlib_read, .write = adlib_write, }, 286 PORTIO_END_OF_LIST(), 287 }; 288 289 static void adlib_realizefn (DeviceState *dev, Error **errp) 290 { 291 AdlibState *s = ADLIB(dev); 292 struct audsettings as; 293 294 if (glob_adlib) { 295 error_setg (errp, "Cannot create more than 1 adlib device"); 296 return; 297 } 298 glob_adlib = s; 299 300 #ifdef HAS_YMF262 301 if (YMF262Init (1, 14318180, s->freq)) { 302 error_setg (errp, "YMF262Init %d failed", s->freq); 303 return; 304 } 305 else { 306 YMF262SetTimerHandler (0, timer_handler, 0); 307 s->enabled = 1; 308 } 309 #else 310 s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, s->freq); 311 if (!s->opl) { 312 error_setg (errp, "OPLCreate %d failed", s->freq); 313 return; 314 } 315 else { 316 OPLSetTimerHandler (s->opl, timer_handler, 0); 317 s->enabled = 1; 318 } 319 #endif 320 321 as.freq = s->freq; 322 as.nchannels = SHIFT; 323 as.fmt = AUD_FMT_S16; 324 as.endianness = AUDIO_HOST_ENDIANNESS; 325 326 AUD_register_card ("adlib", &s->card); 327 328 s->voice = AUD_open_out ( 329 &s->card, 330 s->voice, 331 "adlib", 332 s, 333 adlib_callback, 334 &as 335 ); 336 if (!s->voice) { 337 Adlib_fini (s); 338 error_setg (errp, "Initializing audio voice failed"); 339 return; 340 } 341 342 s->samples = AUD_get_buffer_size_out (s->voice) >> SHIFT; 343 s->mixbuf = g_malloc0 (s->samples << SHIFT); 344 345 adlib_portio_list[0].offset = s->port; 346 adlib_portio_list[1].offset = s->port + 8; 347 portio_list_init (&s->port_list, OBJECT(s), adlib_portio_list, s, "adlib"); 348 portio_list_add (&s->port_list, isa_address_space_io(&s->parent_obj), 0); 349 } 350 351 static Property adlib_properties[] = { 352 DEFINE_PROP_UINT32 ("iobase", AdlibState, port, 0x220), 353 DEFINE_PROP_UINT32 ("freq", AdlibState, freq, 44100), 354 DEFINE_PROP_END_OF_LIST (), 355 }; 356 357 static void adlib_class_initfn (ObjectClass *klass, void *data) 358 { 359 DeviceClass *dc = DEVICE_CLASS (klass); 360 361 dc->realize = adlib_realizefn; 362 set_bit(DEVICE_CATEGORY_SOUND, dc->categories); 363 dc->desc = ADLIB_DESC; 364 dc->props = adlib_properties; 365 } 366 367 static const TypeInfo adlib_info = { 368 .name = TYPE_ADLIB, 369 .parent = TYPE_ISA_DEVICE, 370 .instance_size = sizeof (AdlibState), 371 .class_init = adlib_class_initfn, 372 }; 373 374 static int Adlib_init (ISABus *bus) 375 { 376 isa_create_simple (bus, TYPE_ADLIB); 377 return 0; 378 } 379 380 static void adlib_register_types (void) 381 { 382 type_register_static (&adlib_info); 383 isa_register_soundhw("adlib", ADLIB_DESC, Adlib_init); 384 } 385 386 type_init (adlib_register_types) 387