extern int PicoCDBuffers;\r
\r
// Pico/Pico.c\r
+#define XPCM_BUFFER_SIZE (320+32)\r
typedef struct\r
{\r
int pen_pos[2];\r
int page;\r
// internal\r
- int fifo_bytes;\r
+ int fifo_bytes; // free bytes in FIFO\r
+ int fifo_line_bytes; // float part, << 16\r
int line_counter;\r
- unsigned int r1, r12;\r
+ unsigned short r1, r12;\r
+ unsigned char xpcm_buffer[XPCM_BUFFER_SIZE+4];\r
+ unsigned char *xpcm_ptr;\r
} picohw_state;\r
extern picohw_state PicoPicohw;\r
\r
if ((a&0xfffff0)==0xc00000) { PicoVideoWrite(a,(u16)d); return; } // VDP
// if (a == 0x800010) dump(d);
- if (a == 0x800010) PicoPicohw.fifo_bytes += 2;
- if (a == 0x800012) PicoPicohw.r12 = d;
+ if (a == 0x800010)
+ {
+ PicoPicohw.fifo_bytes += 2;
+
+ if (PicoPicohw.xpcm_ptr < PicoPicohw.xpcm_buffer + XPCM_BUFFER_SIZE) {
+ *PicoPicohw.xpcm_ptr++ = d >> 8;
+ *PicoPicohw.xpcm_ptr++ = d;
+ }
+ else if (PicoPicohw.xpcm_ptr == PicoPicohw.xpcm_buffer + XPCM_BUFFER_SIZE) {
+ elprintf(EL_ANOMALY, "xpcm_buffer overflow!");
+ PicoPicohw.xpcm_ptr++;
+ }
+ }
+ else if (a == 0x800012) PicoPicohw.r12 = d;
elprintf(EL_UIO, "w16: %06x, %04x", a&0xffffff, d);
}
picohw_state PicoPicohw;
static int prev_line_cnt_irq3 = 0, prev_line_cnt_irq5 = 0;
+static int fifo_bytes_line = (16000<<16)/60/262/2; // fifo bytes/line. FIXME: other rates, modes
-static void PicoLineHookPico(int count)
+static void PicoLinePico(int count)
{
PicoPicohw.line_counter += count;
}
#endif
- if ((PicoPicohw.line_counter & 3) == 0 || count > 10)
+ if (PicoPicohw.fifo_bytes > 0)
{
- if (PicoPicohw.fifo_bytes > 0)
- PicoPicohw.fifo_bytes--;
+ PicoPicohw.fifo_line_bytes += fifo_bytes_line * count;
+ if (PicoPicohw.fifo_line_bytes >= (1<<16)) {
+ PicoPicohw.fifo_bytes -= PicoPicohw.fifo_line_bytes >> 16;
+ PicoPicohw.fifo_line_bytes &= 0xffff;
+ if (PicoPicohw.fifo_bytes < 0)
+ PicoPicohw.fifo_bytes = 0;
+ }
}
+ else
+ PicoPicohw.fifo_line_bytes = 0;
#if 0
if (PicoPicohw.line_counter - prev_line_cnt_irq5 > 512) {
#endif
}
+static void PicoResetPico(void)
+{
+ PicoPicoPCMReset();
+ PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer;
+}
+
PICO_INTERNAL int PicoInitPico(void)
{
elprintf(EL_STATUS, "Pico detected");
- PicoLineHook = PicoLineHookPico;
+ PicoLineHook = PicoLinePico;
+ PicoResetHook = PicoResetPico;
PicoAHW = PAHW_PICO;
memset(&PicoPicohw, 0, sizeof(PicoPicohw));
PicoPicohw.pen_pos[0] = 0x03c + 352/2;
PicoPicohw.pen_pos[1] = 0x200 + 252/2;
- prev_line_cnt_irq3 = 0, prev_line_cnt_irq5 = 0;
+ prev_line_cnt_irq3 = prev_line_cnt_irq5 = 0;
// map version register
PicoDetectRegion();
- elprintf(EL_STATUS, "a %x", Pico.m.hardware);
switch (Pico.m.hardware >> 6) {
case 0: PicoPicohw.r1 = 0x00; break;
case 1: PicoPicohw.r1 = 0x00; break;
--- /dev/null
+/*
+ * The following ADPCM algorithm was stolen from MAME aica driver.
+ * I'm quite sure it's not the right one, but it's the
+ * best sounding of the ones that I tried.
+ */
+
+#include "../PicoInt.h"
+
+#define ADPCMSHIFT 8
+#define ADFIX(f) (int) ((double)f * (double)(1<<ADPCMSHIFT))
+
+/* limitter */
+#define Limit(val, max, min) { \
+ if ( val > max ) val = max; \
+ else if ( val < min ) val = min; \
+}
+
+const int TableQuant[8] =
+{
+ ADFIX(0.8984375),
+ ADFIX(0.8984375),
+ ADFIX(0.8984375),
+ ADFIX(0.8984375),
+ ADFIX(1.19921875),
+ ADFIX(1.59765625),
+ ADFIX(2.0),
+ ADFIX(2.3984375)
+};
+
+// changed using trial and error..
+//const int quant_mul[16] = { 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15 };
+const int quant_mul[16] = { 1, 3, 5, 7, 9, 11, 13, -1, -1, -3, -5, -7, -9, -11, -13, -15 };
+
+static int sample = 0, quant = 0;
+
+PICO_INTERNAL void PicoPicoPCMReset(void)
+{
+ sample = 0;
+ quant = 0x7f;
+ memset(PicoPicohw.xpcm_buffer, 0, sizeof(PicoPicohw.xpcm_buffer));
+}
+
+#define XSHIFT 7
+
+#define do_sample() \
+{ \
+ sample += quant * quant_mul[srcval] >> XSHIFT; \
+ quant = (quant * TableQuant[srcval&7]) >> ADPCMSHIFT; \
+ Limit(quant, 0x6000, 0x7f); \
+ Limit(sample, 32767, -32768); \
+}
+
+PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo)
+{
+ unsigned char *src = PicoPicohw.xpcm_buffer;
+ unsigned char *lim = PicoPicohw.xpcm_ptr;
+ int srcval, stepsamples = (44100<<10)/16000, needsamples = 0; // TODO: stepsamples
+
+ if (src == lim)
+ {
+ if (stereo)
+ // still must expand SN76496 to stereo
+ for (; length > 0; buffer+=2, length--)
+ buffer[1] = buffer[0];
+ sample = quant = 0;
+ return;
+ }
+
+ for (; length > 0 && src < lim; src++)
+ {
+ srcval = *src >> 4;
+ do_sample();
+
+ for (needsamples += stepsamples; needsamples > (1<<10) && length > 0; needsamples -= (1<<10), length--) {
+ *buffer++ = sample;
+ if (stereo) { buffer[0] = buffer[-1]; buffer++; }
+ }
+
+ srcval = *src & 0xf;
+ do_sample();
+
+ for (needsamples += stepsamples; needsamples > (1<<10) && length > 0; needsamples -= (1<<10), length--) {
+ *buffer++ = sample;
+ if (stereo) { buffer[0] = buffer[-1]; buffer++; }
+ }
+ }
+
+ if (src < lim) {
+ int di = lim - src;
+ memmove(PicoPicohw.xpcm_buffer, src, di);
+ PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer + di;
+ elprintf(EL_STATUS, "xpcm update: over %i", di);
+ }
+ else
+ {
+ elprintf(EL_STATUS, "xpcm update: under %i", length);
+ PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer;
+ }
+}
+
// Pico/Pico.c\r
PICO_INTERNAL int PicoInitPico(void);\r
\r
+// Pico/xpcm.c\r
+PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo);\r
+PICO_INTERNAL void PicoPicoPCMReset(void);\r
+\r
// Sek.c\r
PICO_INTERNAL int SekInit(void);\r
PICO_INTERNAL int SekReset(void);\r
if (PicoOpt & POPT_EN_PSG)\r
SN76496Update(PsndOut+offset, length, stereo);\r
\r
+ if (PicoAHW & PAHW_PICO) {\r
+ PicoPicoPCMUpdate(PsndOut+offset, length, stereo);\r
+ return length;\r
+ }\r
+\r
// Add in the stereo FM buffer\r
if (PicoOpt & POPT_EN_FM) {\r
buf32_updated = YM2612UpdateOne(buf32, length, stereo, 1);\r
Pico/cd/cd_sys.o Pico/cd/cd_file.o Pico/cd/cue.o Pico/cd/gfx_cd.o \
Pico/cd/Area.o Pico/cd/Misc.o Pico/cd/pcm.o Pico/cd/buffering.o
# Pico - Pico
-OBJS += Pico/Pico/Pico.o Pico/Pico/Memory.o
+OBJS += Pico/Pico/Pico.o Pico/Pico/Memory.o Pico/Pico/xpcm.o
# Pico - sound
OBJS += Pico/sound/sound.o Pico/sound/sn76496.o Pico/sound/ym2612.o Pico/sound/mix.o
# Pico - carthw