mirror of
https://github.com/polpo/picogus.git
synced 2026-10-25 21:40:16 +00:00
Fix slow/missing note OPL2 playback on complex songs
This commit is contained in:
1 parent
771f8f8948
commit
88f52d6d96
4 files changed
+52
-85
No files matched your search
+1
-1
@@ -25,7 +25,7 @@ extern "C" {
|
||||
#include <stdbool.h>
|
||||
|
||||
#define SETTINGS_MAGIC 0x70677573 // "pgus" in ascii
|
||||
#define SETTINGS_VERSION 2
|
||||
#define SETTINGS_VERSION 3
|
||||
|
||||
// Settings struct has generous padding for future settings by aligning to 4 bytes
|
||||
typedef struct Settings {
|
||||
|
||||
+2
-2
@@ -383,7 +383,7 @@ static void OPLTimer_CalculateEndTime(opl_timer_t *timer)
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteRegister(unsigned int reg_num, unsigned int value)
|
||||
void OPL_Pico_WriteRegister(unsigned int reg_num, unsigned int value)
|
||||
{
|
||||
switch (reg_num)
|
||||
{
|
||||
@@ -450,7 +450,7 @@ void OPL_Pico_PortWrite(opl_port_t port, unsigned int value)
|
||||
}
|
||||
else if (port == OPL_DATA_PORT)
|
||||
{
|
||||
WriteRegister(register_num, value);
|
||||
OPL_Pico_WriteRegister(register_num, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-45
@@ -69,10 +69,9 @@ extern void sbdsp_process();
|
||||
#include "opl.h"
|
||||
void play_adlib(void);
|
||||
extern "C" int OPL_Pico_Init(unsigned int);
|
||||
extern "C" void OPL_Pico_PortWrite(opl_port_t, unsigned int);
|
||||
extern "C" unsigned int OPL_Pico_PortRead(opl_port_t);
|
||||
// #include "cmd_buffers.h"
|
||||
// cms_buffer_t opl_buffer = { {0}, 0, 0 };
|
||||
#include "cmd_buffers.h"
|
||||
cms_buffer_t opl_buffer = { {0}, 0, 0 };
|
||||
#endif
|
||||
|
||||
#ifdef CDROM
|
||||
@@ -648,29 +647,18 @@ __force_inline void handle_iow(void) {
|
||||
if ((port >> 4) == sb_port_test) {
|
||||
switch (port - settings.SB.basePort) {
|
||||
// OPL ports
|
||||
case 0x8 ... 0x9:
|
||||
case 0x8:
|
||||
// Fast write
|
||||
// pio_sm_put(pio0, IOW_PIO_SM, IO_END);
|
||||
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
|
||||
/*
|
||||
opl_buffer.cmds[opl_buffer.head++] = {
|
||||
OPL_REGISTER_PORT,
|
||||
(uint8_t)(iow_read & 0xFF)
|
||||
};
|
||||
pio_sm_put(pio0, IOW_PIO_SM, IO_END);
|
||||
// pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
|
||||
opl_buffer.cmds[opl_buffer.head].addr = (uint16_t)(iow_read & 0xFF);
|
||||
// Fast write - return early as we've already written 0x0u to the PIO
|
||||
return;
|
||||
*/
|
||||
OPL_Pico_PortWrite((opl_port_t)(port & 1), (uint8_t)(iow_read & 0xFF));
|
||||
break;
|
||||
/*
|
||||
case 0x9:
|
||||
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
|
||||
opl_buffer.cmds[opl_buffer.head++] = {
|
||||
OPL_DATA_PORT,
|
||||
(uint8_t)(iow_read & 0xFF)
|
||||
};
|
||||
opl_buffer.cmds[opl_buffer.head++].data = (uint8_t)(iow_read & 0xFF);
|
||||
break;
|
||||
*/
|
||||
// DSP ports
|
||||
default:
|
||||
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
|
||||
@@ -690,29 +678,19 @@ __force_inline void handle_iow(void) {
|
||||
#endif
|
||||
#if defined(SOUND_OPL)
|
||||
if ((port & 0x3fe) == settings.SB.oplBasePort) {
|
||||
/*
|
||||
// Fast write
|
||||
pio_sm_put(pio0, IOW_PIO_SM, IO_END);
|
||||
opl_buffer.cmds[opl_buffer.head++] = {
|
||||
OPL_REGISTER_PORT,
|
||||
(uint8_t)(iow_read & 0xFF)
|
||||
};
|
||||
// Fast write - return early as we've already written 0x0u to the PIO
|
||||
return;
|
||||
*/
|
||||
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
|
||||
OPL_Pico_PortWrite((opl_port_t)(port & 1), (uint8_t)(iow_read & 0xFF));
|
||||
/*
|
||||
} else if (port == settings.SB.oplBasePort + 1) {
|
||||
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
|
||||
if (settings.SB.oplSpeedSensitive) {
|
||||
busy_wait_us(1); // busy wait for speed sensitive games
|
||||
if ((port & 1) == 0) {
|
||||
// Fast write
|
||||
pio_sm_put(pio0, IOW_PIO_SM, IO_END);
|
||||
opl_buffer.cmds[opl_buffer.head].addr = (uint16_t)(iow_read & 0xFF);
|
||||
// Fast write - return early as we've already written 0x0u to the PIO
|
||||
return;
|
||||
} else {
|
||||
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
|
||||
if (settings.SB.oplSpeedSensitive) {
|
||||
busy_wait_us(1); // busy wait for speed sensitive games
|
||||
}
|
||||
opl_buffer.cmds[opl_buffer.head++].data = (uint8_t)(iow_read & 0xFF);
|
||||
}
|
||||
opl_buffer.cmds[opl_buffer.head++] = {
|
||||
OPL_DATA_PORT,
|
||||
(uint8_t)(iow_read & 0xFF)
|
||||
};
|
||||
*/
|
||||
} else // if follows down below
|
||||
#endif // SOUND_OPL
|
||||
#ifdef SOUND_TANDY
|
||||
@@ -848,12 +826,10 @@ __force_inline void handle_ior(void) {
|
||||
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
|
||||
switch (port - settings.SB.basePort) {
|
||||
case 0x8:
|
||||
/*
|
||||
// wait for OPL buffer to process
|
||||
while (opl_buffer.tail != opl_buffer.head) {
|
||||
tight_loop_contents();
|
||||
}
|
||||
*/
|
||||
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | OPL_Pico_PortRead(OPL_REGISTER_PORT));
|
||||
break;
|
||||
default:
|
||||
@@ -876,12 +852,10 @@ __force_inline void handle_ior(void) {
|
||||
if (port == settings.SB.oplBasePort) {
|
||||
// Tell PIO to wait for data
|
||||
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
|
||||
/*
|
||||
// wait for OPL buffer to process
|
||||
while (opl_buffer.tail != opl_buffer.head) {
|
||||
tight_loop_contents();
|
||||
}
|
||||
*/
|
||||
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | OPL_Pico_PortRead(OPL_REGISTER_PORT));
|
||||
} else // if follows down below
|
||||
#endif
|
||||
|
||||
+30
-37
@@ -31,7 +31,7 @@
|
||||
|
||||
#include "opl.h"
|
||||
extern "C" void OPL_Pico_simple(int16_t *buffer, uint32_t nsamples);
|
||||
extern "C" void OPL_Pico_PortWrite(opl_port_t, unsigned int);
|
||||
extern "C" void OPL_Pico_WriteRegister(unsigned int reg_num, unsigned int value);
|
||||
|
||||
#include "audio_fifo.h"
|
||||
#if SOUND_SB
|
||||
@@ -192,7 +192,9 @@ void play_adlib() {
|
||||
uint32_t cd_left = 0;
|
||||
uint32_t cd_index = 0;
|
||||
|
||||
int16_t opl_samples[SAMPLES_PER_BUFFER * 2] = {0};
|
||||
constexpr uint32_t OPL_SAMPLE_COUNT = 8;
|
||||
constexpr uint32_t OPL_BUFFER_BITS = (OPL_SAMPLE_COUNT << 1) - 1;
|
||||
int16_t opl_samples[OPL_SAMPLE_COUNT << 1] = {0};
|
||||
uint32_t opl_ratio = fixed_ratio(49716, 44100);
|
||||
printf("opl_ratio: %x ", opl_ratio);
|
||||
uint32_t opl_pos = 0;
|
||||
@@ -203,7 +205,6 @@ void play_adlib() {
|
||||
|
||||
int32_t accum[2] = {0};
|
||||
for (;;) {
|
||||
|
||||
#if CDROM
|
||||
has_cd_samples = cdrom_audio_callback_simple(&cdrom, cd_samples, SAMPLES_PER_BUFFER << 1, true);
|
||||
#endif
|
||||
@@ -221,44 +222,36 @@ void play_adlib() {
|
||||
accum[1] += cd_samples[(i << 1) + 1];
|
||||
}
|
||||
#endif // CDROM
|
||||
uint32_t opl_index = (opl_pos >> FRAC_BITS);
|
||||
// uint32_t opl_index = i;
|
||||
uint32_t opl_frac = opl_pos & FRAC_MASK;
|
||||
opl_pos += opl_ratio;
|
||||
|
||||
// printf("%x %x\n", opl_index, opl_frac);
|
||||
|
||||
uint32_t opl_index = (opl_pos >> FRAC_BITS);
|
||||
// uint32_t opl_index = i;
|
||||
uint32_t opl_frac = opl_pos & FRAC_MASK;
|
||||
opl_pos += opl_ratio;
|
||||
#if !SB_BUFFERLESS // don't support OPL in bufferless for now
|
||||
if (
|
||||
((opl_index & SAMPLES_PER_BUFFER) && opl_sample_idx != 0x0) ||
|
||||
(!(opl_index & SAMPLES_PER_BUFFER) && opl_sample_idx != SAMPLES_PER_BUFFER)
|
||||
) {
|
||||
opl_sample_idx = (opl_index + SAMPLES_PER_BUFFER) & SAMPLES_PER_BUFFER;
|
||||
/*
|
||||
bool notfirst = false;
|
||||
while (opl_buffer.tail != opl_buffer.head) {
|
||||
if (!notfirst) {
|
||||
if (
|
||||
((opl_index & OPL_SAMPLE_COUNT) && opl_sample_idx != 0x0) ||
|
||||
(!(opl_index & OPL_SAMPLE_COUNT) && opl_sample_idx != OPL_SAMPLE_COUNT)
|
||||
) {
|
||||
opl_sample_idx = (opl_index + OPL_SAMPLE_COUNT) & OPL_SAMPLE_COUNT;
|
||||
// bool notfirst = false;
|
||||
while (opl_buffer.tail != opl_buffer.head) {
|
||||
// if (!notfirst) {
|
||||
#ifndef PICOW
|
||||
gpio_xor_mask(LED_PIN);
|
||||
// gpio_xor_mask(LED_PIN);
|
||||
#endif
|
||||
notfirst = true;
|
||||
}
|
||||
auto cmd = opl_buffer.cmds[opl_buffer.tail];
|
||||
OPL_Pico_PortWrite((opl_port_t)cmd.addr, cmd.data);
|
||||
++opl_buffer.tail;
|
||||
}
|
||||
*/
|
||||
OPL_Pico_simple(opl_samples + opl_sample_idx, SAMPLES_PER_BUFFER);
|
||||
// notfirst = true;
|
||||
// }
|
||||
auto cmd = opl_buffer.cmds[opl_buffer.tail];
|
||||
OPL_Pico_WriteRegister(cmd.addr, cmd.data);
|
||||
++opl_buffer.tail;
|
||||
}
|
||||
int32_t opl_sample = lerp_fixed(
|
||||
opl_samples[opl_index & 0x1ff],
|
||||
opl_samples[(opl_index + 1) & 0x1ff],
|
||||
opl_frac);
|
||||
accum[0] += opl_samples[opl_index & 0x1ff];
|
||||
accum[1] += opl_samples[opl_index & 0x1ff];
|
||||
#if CDROM
|
||||
//}
|
||||
#endif
|
||||
OPL_Pico_simple(opl_samples + opl_sample_idx, OPL_SAMPLE_COUNT);
|
||||
}
|
||||
int32_t opl_sample = lerp_fixed(
|
||||
opl_samples[opl_index & OPL_BUFFER_BITS],
|
||||
opl_samples[(opl_index + 1) & OPL_BUFFER_BITS],
|
||||
opl_frac);
|
||||
accum[0] += opl_sample;
|
||||
accum[1] += opl_sample;
|
||||
#if SOUND_SB
|
||||
if (!sb_left) {
|
||||
// putchar('t');
|
||||
|
||||
Reference in new issue
Block a user