aboutsummaryrefslogtreecommitdiff
path: root/common/fmplayer_work_opna.c
blob: 16bb85cc1d618fc21ca50e79515d098ffe94fc29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "fmplayer_common.h"
#include "fmplayer_drumrom.h"
#include "fmdriver/fmdriver.h"
#include "fmdriver/ppz8.h"
#include "libopna/opna.h"
#include "libopna/opnatimer.h"
#include <string.h>

enum {
  SRATE = 55467,
  PPZ8MIX = 0xa000,
};

static void opna_writereg_libopna(struct fmdriver_work *work, unsigned addr, unsigned data) {
  struct opna_timer *timer = (struct opna_timer *)work->opna;
  opna_timer_writereg(timer, addr, data);
}

static unsigned opna_readreg_libopna(struct fmdriver_work *work, unsigned addr) {
  struct opna_timer *timer = (struct opna_timer *)work->opna;
  return opna_readreg(timer->opna, addr);
}

static uint8_t opna_status_libopna(struct fmdriver_work *work, bool a1) {
  struct opna_timer *timer = (struct opna_timer *)work->opna;
  uint8_t status = opna_timer_status(timer);
  if (!a1) {
    status &= 0x83;
  }
  return status;
}

static void opna_int_cb(void *userptr) {
  struct fmdriver_work *work = (struct fmdriver_work *)userptr;
  work->driver_opna_interrupt(work);
}

static void opna_mix_cb(void *userptr, int16_t *buf, unsigned samples) {
  struct ppz8 *ppz8 = (struct ppz8 *)userptr;
  ppz8_mix(ppz8, buf, samples);
}

void fmplayer_init_work_opna(
  struct fmdriver_work *work,
  struct ppz8 *ppz8,
  struct opna *opna,
  struct opna_timer *timer,
  void *adpcm_ram
) {
  opna_reset(opna);
  fmplayer_drum_rom_load(&opna->drum);
  opna_adpcm_set_ram_256k(&opna->adpcm, adpcm_ram);
  opna_timer_reset(timer, opna);
  ppz8_init(ppz8, SRATE, PPZ8MIX);
  memset(work, 0, sizeof(*work));
  work->opna_writereg = opna_writereg_libopna;
  work->opna_readreg = opna_readreg_libopna;
  work->opna_status = opna_status_libopna;
  work->opna = timer;
  work->ppz8 = ppz8;
  work->ppz8_functbl = &ppz8_functbl;
  opna_timer_set_int_callback(timer, opna_int_cb, work);
  opna_timer_set_mix_callback(timer, opna_mix_cb, ppz8);
}