diff --git a/apps/plugins/varvara/SOURCES b/apps/plugins/varvara/SOURCES index 8793ca4916..1920ad5344 100644 --- a/apps/plugins/varvara/SOURCES +++ b/apps/plugins/varvara/SOURCES @@ -4,4 +4,6 @@ devices/ppu.h devices/ppu.c devices/file.h devices/file.c +devices/apu.h +devices/apu.c varvara.c diff --git a/apps/plugins/varvara/varvara.c b/apps/plugins/varvara/varvara.c index aabde9313e..b735140f11 100644 --- a/apps/plugins/varvara/varvara.c +++ b/apps/plugins/varvara/varvara.c @@ -15,9 +15,13 @@ TODO audio device TODO clean up */ +#define POLYPHONY 4 +#define AUDIO_BUF_SIZE 1024 + #include "uxn.h" #include "devices/ppu.h" #include "devices/file.h" +#include "devices/apu.h" #include "plugin.h" #include "keymaps.h" #include @@ -26,11 +30,12 @@ TODO clean up static Uxn u; static Ppu ppu; -static Device *devctrl, *devsystem, *devconsole, *devscreen; +static Apu apu[POLYPHONY]; +static Device *devctrl, *devsystem, *devconsole, *devscreen, *devaudio0; unsigned int palette[3]; static Uint8 framebuffer[LCD_HEIGHT * LCD_WIDTH * 4]; static fb_data *lcd_fb = NULL; - +int audio_buf[AUDIO_BUF_SIZE]; static unsigned long starttick; static long sleeptime; @@ -208,6 +213,53 @@ datetime_dei(Device *d, Uint8 port) } } +void +apu_finished_handler(Apu *c) +{ + DEBUGF("APU done\n"); +} + +void audio_callback(const void** start, size_t *size) { + int high = 32000; + int low = 0; + for (size_t i = 0; i < AUDIO_BUF_SIZE; i++) { + if (i & 1) { + audio_buf[i] = high; + } else { + audio_buf[i] = low; + } + } + + *start = &audio_buf; + *size = AUDIO_BUF_SIZE; +} + +static Uint8 +audio_dei(Device *d, Uint8 port) +{ + Apu *c = &apu[d - devaudio0]; + switch(port) { + case 0x4: return apu_get_vu(c); + case 0x2: poke16(d->dat, 0x2, c->i); /* fall through */ + default: return d->dat[port]; + } +} + +static void +audio_deo(Device *d, Uint8 port) +{ + Apu *c = &apu[d - devaudio0]; + if(port == 0xf) { + c->len = peek16(d->dat, 0xa); + c->addr = &d->mem[peek16(d->dat, 0xc)]; + c->volume[0] = d->dat[0xe] >> 4; + c->volume[1] = d->dat[0xe] & 0xf; + c->repeat = !(d->dat[0xf] & 0x80); + apu_start(c, peek16(d->dat, 0x8), d->dat[0xf] & 0x7f); + } +} + + // TODO mono and greyscale that don't suck static void redraw(void) { @@ -313,7 +365,19 @@ enum plugin_status plugin_start(const void* parameter) rb->splash(HZ, "Please open a .rom file using this plugin!"); return PLUGIN_ERROR; } - + + /* audio init */ + #if INPUT_SRC_CAPS != 0 + /* Select playback */ + rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); + rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); + #endif + + rb->pcm_play_stop(); + rb->mixer_set_frequency(44100); + rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, audio_callback, NULL, 0); + + /* uxn init */ DEBUGF("zeroing\n"); memzero8(&u, sizeof(Uxn)); @@ -338,7 +402,7 @@ enum plugin_status plugin_start(const void* parameter) /* system */ devsystem = uxn_port(&u, 0x0, system_dei, system_deo); /* console */ devconsole = uxn_port(&u, 0x1, nil_dei, console_deo); /* screen */ devscreen = uxn_port(&u, 0x2, screen_dei, screen_deo); - /* audio0 */ uxn_port(&u, 0x3, nil_dei, nil_deo); + /* audio0 */ devaudio0 = uxn_port(&u, 0x3, audio_dei, audio_deo); /* audio1 */ uxn_port(&u, 0x4, nil_dei, nil_deo); /* audio2 */ uxn_port(&u, 0x5, nil_dei, nil_deo); /* audio3 */ uxn_port(&u, 0x6, nil_dei, nil_deo);