aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakamichi Horikawa <takamichiho@gmail.com>2017-03-14 19:07:57 +0900
committerTakamichi Horikawa <takamichiho@gmail.com>2017-03-14 19:07:57 +0900
commit16be4100808e09a94e802adb58bc1c79e5eefd65 (patch)
tree002942b6503b7f706a6bfe9b05df538d1d97320e
parent45e73c2aa4868a602e8120e50812e1641af342e2 (diff)
libopna: enable register read
-rw-r--r--libopna/opna.c5
-rw-r--r--libopna/opna.h1
-rw-r--r--libopna/opnassg.c13
-rw-r--r--libopna/opnassg.h2
-rw-r--r--libopna/opnatimer.c36
-rw-r--r--libopna/opnatimer.h3
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;