diff options
| author | Takamichi Horikawa <takamichiho@gmail.com> | 2017-03-14 19:07:57 +0900 | 
|---|---|---|
| committer | Takamichi Horikawa <takamichiho@gmail.com> | 2017-03-14 19:07:57 +0900 | 
| commit | 16be4100808e09a94e802adb58bc1c79e5eefd65 (patch) | |
| tree | 002942b6503b7f706a6bfe9b05df538d1d97320e /libopna | |
| parent | 45e73c2aa4868a602e8120e50812e1641af342e2 (diff) | |
libopna: enable register read
Diffstat (limited to 'libopna')
| -rw-r--r-- | libopna/opna.c | 5 | ||||
| -rw-r--r-- | libopna/opna.h | 1 | ||||
| -rw-r--r-- | libopna/opnassg.c | 13 | ||||
| -rw-r--r-- | libopna/opnassg.h | 2 | ||||
| -rw-r--r-- | libopna/opnatimer.c | 36 | ||||
| -rw-r--r-- | libopna/opnatimer.h | 3 | 
6 files changed, 54 insertions, 6 deletions
| diff --git a/libopna/opna.c b/libopna/opna.c index fb9e24a..10155d0 100644 --- a/libopna/opna.c +++ b/libopna/opna.c @@ -17,6 +17,11 @@ void opna_writereg(struct opna *opna, unsigned reg, unsigned val) {    opna_adpcm_writereg(&opna->adpcm, reg, val);  } +unsigned opna_readreg(const struct opna *opna, unsigned reg) { +  if (reg > 0xfu) return 0xff; +  return opna_ssg_readreg(&opna->ssg, reg); +} +  void opna_mix(struct opna *opna, int16_t *buf, unsigned samples) {    opna_fm_mix(&opna->fm, buf, samples);    opna_ssg_mix_55466(&opna->ssg, &opna->resampler, buf, samples); diff --git a/libopna/opna.h b/libopna/opna.h index b5e9d87..7d7d722 100644 --- a/libopna/opna.h +++ b/libopna/opna.h @@ -41,6 +41,7 @@ struct opna {  void opna_reset(struct opna *opna);  void opna_writereg(struct opna *opna, unsigned reg, unsigned val); +unsigned opna_readreg(const struct opna *opna, unsigned reg);  void opna_mix(struct opna *opna, int16_t *buf, unsigned samples);  unsigned opna_get_mask(const struct opna *opna);  void opna_set_mask(struct opna *opna, unsigned mask); diff --git a/libopna/opnassg.c b/libopna/opnassg.c index 1345502..3c5b108 100644 --- a/libopna/opnassg.c +++ b/libopna/opnassg.c @@ -103,6 +103,11 @@ void opna_ssg_writereg(struct opna_ssg *ssg, unsigned reg, unsigned val) {    }  } +unsigned opna_ssg_readreg(const struct opna_ssg *ssg, unsigned reg) { +  if (reg > 0xfu) return 0xff; +  return ssg->regs[reg]; +} +  static int opna_ssg_tone_period(const struct opna_ssg *ssg, int chan) {    return ssg->regs[0+chan*2] | ((ssg->regs[1+chan*2] & 0xf) << 8);  } @@ -173,7 +178,9 @@ void opna_ssg_generate_raw(struct opna_ssg *ssg, int16_t *buf, int samples) {          ssg->ch[ch].out = !ssg->ch[ch].out;        }        if (ssg->mask & (1<<ch)) continue; -#if 0 +#if 1 +      // may output DC offset +      // YMF288 seems to disable output when 0 <= Tp < 8        if (opna_ssg_tone_out(ssg, ch)) {          int level = opna_ssg_chan_env(ssg, ch)            ? opna_ssg_env_level(ssg) @@ -183,12 +190,12 @@ void opna_ssg_generate_raw(struct opna_ssg *ssg, int16_t *buf, int samples) {  #else        if (!opna_ssg_tone_silent(ssg, ch)) {          int level = opna_ssg_channel_level(ssg, ch); -        out += opna_ssg_tone_out(ssg, ch) ? voltable[level] : -voltable[level]; +        out += (opna_ssg_tone_out(ssg, ch) ? voltable[level] : -voltable[level]) / 2;        }  #endif      } -    buf[i] = out / 4; +    buf[i] = out / 2;    }  } diff --git a/libopna/opnassg.h b/libopna/opnassg.h index adcd231..1bd607a 100644 --- a/libopna/opnassg.h +++ b/libopna/opnassg.h @@ -50,7 +50,7 @@ void opna_ssg_mix_55466(    struct opna_ssg *ssg, struct opna_ssg_resampler *resampler,    int16_t *buf, int samples);  void opna_ssg_writereg(struct opna_ssg *ssg, unsigned reg, unsigned val); - +unsigned opna_ssg_readreg(const struct opna_ssg *ssg, unsigned reg);  // channel level (0 - 31)  int opna_ssg_channel_level(const struct opna_ssg *ssg, int ch); diff --git a/libopna/opnatimer.c b/libopna/opnatimer.c index 195e426..789c28e 100644 --- a/libopna/opnatimer.c +++ b/libopna/opnatimer.c @@ -2,6 +2,7 @@  #include "opna.h"  enum { +  TIMERA_BITS = 10,    TIMERB_SHIFT = 4,    TIMERB_BITS = 8 + TIMERB_SHIFT,  }; @@ -37,35 +38,66 @@ void opna_timer_writereg(struct opna_timer *timer, unsigned reg, unsigned val) {    val &= 0xff;    opna_writereg(timer->opna, reg, val);    switch (reg) { +  case 0x24: +    timer->timera &= ~0xff; +    timer->timera |= val; +    break; +  case 0x25: +    timer->timera &= 0xff; +    timer->timera |= ((val & 3) << 8); +    break;    case 0x26:      timer->timerb = val;      timer->timerb_cnt = timer->timerb << TIMERB_SHIFT;      break;    case 0x27: +    timer->timera_load = val & (1<<0); +    timer->timera_enable = val & (1<<2);      timer->timerb_load = val & (1<<1);      timer->timerb_enable = val & (1<<3); +     +    if (val & (1<<4)) { +      timer->status &= ~(1<<0); +    }      if (val & (1<<5)) {        //timer->timerb_cnt = timer->timerb << TIMERB_SHIFT;        timer->status &= ~(1<<1);      }    }  } - +#include <stdio.h> +#include <stdlib.h>  void opna_timer_mix(struct opna_timer *timer, int16_t *buf, unsigned samples) {    do {      unsigned generate_samples = samples; -    if (timer->timerb_enable) { +    if (timer->timerb_enable && timer->timerb_load) {        unsigned timerb_samples = (1<<TIMERB_BITS) - timer->timerb_cnt;        if (timerb_samples < generate_samples) {          generate_samples = timerb_samples;        }      } +    if (timer->timera_enable && timer->timera_load) { +      unsigned timera_samples = (1<<TIMERA_BITS) - timer->timera; +      if (timera_samples < generate_samples) { +        generate_samples = timera_samples; +      } +    }      opna_mix(timer->opna, buf, generate_samples);      if (timer->mix_cb) {        timer->mix_cb(timer->mix_userptr, buf, generate_samples);      }      buf += generate_samples*2;      samples -= generate_samples; +    if (timer->timera_load) { +      timer->timera = (timer->timera + generate_samples) & ((1<<TIMERA_BITS)-1); +      if (!timer->timera && timer->timera_enable) { +        if (!(timer->status & (1<<0))) { +          timer->status |= (1<<0); +          timer->interrupt_cb(timer->interrupt_userptr); +        } +      } +      timer->timera &= (1<<TIMERA_BITS)-1; +    }      if (timer->timerb_load) {        timer->timerb_cnt = (timer->timerb_cnt + generate_samples) & ((1<<TIMERB_BITS)-1);        if (!timer->timerb_cnt && timer->timerb_enable) { diff --git a/libopna/opnatimer.h b/libopna/opnatimer.h index f3094ba..ad0fe0b 100644 --- a/libopna/opnatimer.h +++ b/libopna/opnatimer.h @@ -20,7 +20,10 @@ struct opna_timer {    void *interrupt_userptr;    opna_timer_mix_cb_t mix_cb;    void *mix_userptr; +  uint16_t timera;    uint8_t timerb; +  bool timera_load; +  bool timera_enable;    bool timerb_load;    bool timerb_enable;    uint16_t timerb_cnt; | 
