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 | |
parent | 45e73c2aa4868a602e8120e50812e1641af342e2 (diff) |
libopna: enable register read
-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; |