2016-08-14 22:07:17 -04:00
|
|
|
/* Copyright holders: Sarah Walker, SA1988
|
|
|
|
|
see COPYING for more details
|
|
|
|
|
*/
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <stdio.h>
|
2016-06-26 00:34:39 +02:00
|
|
|
#include <stdint.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <string.h>
|
2016-06-26 00:34:39 +02:00
|
|
|
#include <stdlib.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <wchar.h>
|
2020-02-29 19:12:23 +01:00
|
|
|
#include "86box.h"
|
|
|
|
|
#include "cpu.h"
|
|
|
|
|
#include "86box_io.h"
|
|
|
|
|
#include "timer.h"
|
2016-06-26 00:34:39 +02:00
|
|
|
#include "sound.h"
|
2017-05-06 17:48:33 +02:00
|
|
|
#include "snd_opl.h"
|
2019-12-21 20:06:34 +01:00
|
|
|
#include "snd_opl_backend.h"
|
2017-05-06 17:48:33 +02:00
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-09-25 04:31:20 -04:00
|
|
|
/*Interfaces between 86Box and the actual OPL emulator*/
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
uint8_t
|
|
|
|
|
opl2_read(uint16_t a, void *priv)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_t *opl = (opl_t *)priv;
|
|
|
|
|
|
|
|
|
|
sub_cycles((int) (isa_timing * 8));
|
|
|
|
|
opl2_update2(opl);
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
return opl_read(0, a);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
opl2_write(uint16_t a, uint8_t v, void *priv)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_t *opl = (opl_t *)priv;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
opl2_update2(opl);
|
|
|
|
|
opl_write(0, a, v);
|
|
|
|
|
opl_write(1, a, v);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
uint8_t
|
|
|
|
|
opl2_l_read(uint16_t a, void *priv)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_t *opl = (opl_t *)priv;
|
|
|
|
|
|
|
|
|
|
sub_cycles((int)(isa_timing * 8));
|
|
|
|
|
opl2_update2(opl);
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
return opl_read(0, a);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
opl2_l_write(uint16_t a, uint8_t v, void *priv)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_t *opl = (opl_t *)priv;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
opl2_update2(opl);
|
|
|
|
|
opl_write(0, a, v);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
uint8_t
|
|
|
|
|
opl2_r_read(uint16_t a, void *priv)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_t *opl = (opl_t *)priv;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
sub_cycles((int)(isa_timing * 8));
|
|
|
|
|
opl2_update2(opl);
|
|
|
|
|
|
|
|
|
|
return opl_read(1, a);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
opl2_r_write(uint16_t a, uint8_t v, void *priv)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_t *opl = (opl_t *)priv;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
opl2_update2(opl);
|
|
|
|
|
opl_write(1, a, v);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
uint8_t
|
|
|
|
|
opl3_read(uint16_t a, void *priv)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_t *opl = (opl_t *)priv;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
sub_cycles((int)(isa_timing * 8));
|
|
|
|
|
opl3_update2(opl);
|
|
|
|
|
|
|
|
|
|
return opl_read(0, a);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
opl3_write(uint16_t a, uint8_t v, void *priv)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
|
|
|
|
opl_t *opl = (opl_t *)priv;
|
|
|
|
|
|
|
|
|
|
opl3_update2(opl);
|
|
|
|
|
opl_write(0, a, v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
void
|
|
|
|
|
opl2_update2(opl_t *opl)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
if (opl->pos < sound_pos_global) {
|
|
|
|
|
opl2_update(0, &opl->buffer[opl->pos << 1], sound_pos_global - opl->pos);
|
|
|
|
|
opl2_update(1, &opl->buffer2[opl->pos << 1], sound_pos_global - opl->pos);
|
|
|
|
|
for (; opl->pos < sound_pos_global; opl->pos++) {
|
|
|
|
|
opl->buffer[(opl->pos << 1) + 1] = opl->buffer2[(opl->pos << 1) + 1];
|
|
|
|
|
opl->filtbuf[0] = opl->buffer[opl->pos << 1] = (opl->buffer[opl->pos << 1] / 2);
|
|
|
|
|
opl->filtbuf[1] = opl->buffer[(opl->pos << 1) + 1] = (opl->buffer[(opl->pos << 1) + 1] / 2);
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
opl3_update2(opl_t *opl)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
if (opl->pos < sound_pos_global) {
|
|
|
|
|
opl3_update(0, &opl->buffer[(opl->pos << 1)], sound_pos_global - opl->pos);
|
|
|
|
|
for (; opl->pos < sound_pos_global; opl->pos++) {
|
|
|
|
|
opl->filtbuf[0] = opl->buffer[opl->pos << 1] = (opl->buffer[opl->pos << 1] / 2);
|
|
|
|
|
opl->filtbuf[1] = opl->buffer[(opl->pos << 1) + 1] = (opl->buffer[(opl->pos << 1) + 1] / 2);
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ym3812_timer_set_0(void *param, int timer, uint64_t period)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_t *opl = (opl_t *)param;
|
|
|
|
|
|
|
|
|
|
if (period)
|
|
|
|
|
timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20);
|
|
|
|
|
else
|
|
|
|
|
timer_disable(&opl->timers[0][timer]);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ym3812_timer_set_1(void *param, int timer, uint64_t period)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_t *opl = (opl_t *)param;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
if (period)
|
|
|
|
|
timer_set_delay_u64(&opl->timers[1][timer], period * TIMER_USEC * 20);
|
|
|
|
|
else
|
|
|
|
|
timer_disable(&opl->timers[1][timer]);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ymf262_timer_set(void *param, int timer, uint64_t period)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_t *opl = (opl_t *)param;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
if (period)
|
|
|
|
|
timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20);
|
|
|
|
|
else
|
|
|
|
|
timer_disable(&opl->timers[0][timer]);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
opl_timer_callback00(void *p)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_timer_over(0, 0);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
opl_timer_callback01(void *p)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_timer_over(0, 1);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
opl_timer_callback10(void *p)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_timer_over(1, 0);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
opl_timer_callback11(void *p)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_timer_over(1, 1);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
opl2_init(opl_t *opl)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_init(ym3812_timer_set_0, opl, 0, 0);
|
|
|
|
|
opl_init(ym3812_timer_set_1, opl, 1, 0);
|
|
|
|
|
|
|
|
|
|
timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0);
|
|
|
|
|
timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0);
|
|
|
|
|
timer_add(&opl->timers[1][0], opl_timer_callback10, (void *)opl, 0);
|
|
|
|
|
timer_add(&opl->timers[1][1], opl_timer_callback11, (void *)opl, 0);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
opl3_init(opl_t *opl)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2019-12-21 20:06:34 +01:00
|
|
|
opl_init(ymf262_timer_set, opl, 0, 1);
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2019-12-21 20:06:34 +01:00
|
|
|
timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0);
|
|
|
|
|
timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0);
|
|
|
|
|
}
|