From 85ddf8b6b742e3fdb4f70990b30c7130b3ecc3f7 Mon Sep 17 00:00:00 2001 From: viciious Date: Wed, 12 Jun 2024 13:43:36 +0300 Subject: [PATCH] Use PWM on the 32X for YM2612 DAC samples playback --- src-md/crt0.s | 42 ++++++++++++++++++++++++++++++++++++++++++ src-md/vgm.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src-md/crt0.s b/src-md/crt0.s index 331d771d1..37b6530b4 100644 --- a/src-md/crt0.s +++ b/src-md/crt0.s @@ -67,6 +67,9 @@ .equ STRM_LENLL, 0xFFFF .equ MARS_FRAMEBUFFER, 0x840200 /* 32X frame buffer */ + .equ MARS_PWM_CTRL, 0xA15130 + .equ MARS_PWM_CYCLE, 0xA15132 + .equ MARS_PWM_MONO, 0xA15138 .equ COL_STORE, 0x600800 /* WORD RAM + 2K */ @@ -403,6 +406,32 @@ main_loop_start: move.l #0,0xA15120 /* let Master SH2 run */ main_loop: + tst.w dac_len + beq.b main_loop_chk_ctrl /* done/none, silence */ + + move.l dac_samples,a0 + move.w dac_center,d1 + move.w dac_len,d2 +0: + tst.w MARS_PWM_MONO /* check mono reg status */ + bmi.b 01f /* full */ + + move.b (a0)+,d0 /* fetch dac sample */ + eori.b #0x80,d0 /* unsigned to signed */ + ext.w d0 /* sign extend to word */ + add.w d0,d0 /* *2 */ +| add.w d0,d0 /* *4 */ + add.w d1,d0 + move.w d0,MARS_PWM_MONO + + subq.w #1,d2 + bne.b 0b /* not done */ + move.w dac_center,MARS_PWM_MONO /* silence */ +01: + move.w d2,dac_len + move.l a0,dac_samples + +main_loop_chk_ctrl: tst.b need_ctrl_int beq.b main_loop_bump_fm move.b #0,need_ctrl_int @@ -3082,6 +3111,9 @@ vgm_ptr: vgm_size: dc.l 0 .global fm_rep +dac_samples: + .global dac_samples + dc.l 0 fm_rep: dc.w 0 .global fm_idx @@ -3092,6 +3124,16 @@ fm_stream: fm_stream_freq: dc.w 0 +dac_freq: + .global dac_freq + dc.w 0 +dac_len: + .global dac_len + dc.w 0 +dac_center: + .global dac_center + dc.w 0 + rf5c68_start: dc.w 0 rf5c68_freq_incr: diff --git a/src-md/vgm.c b/src-md/vgm.c index 6ab959caa..5ce370b10 100644 --- a/src-md/vgm.c +++ b/src-md/vgm.c @@ -11,12 +11,18 @@ #define VGM_LZSS_BUF_SIZE 0x8000 #define VGM_MAX_SIZE 0x18000 +#define VGM_USE_PWM_FOR_DAC + #define MD_WORDRAM (void*)0x600000 #define MCD_WORDRAM (void*)0x0C0000 #define MD_WORDRAM_VGM_PTR (MD_WORDRAM+VGM_WORDRAM_OFS) #define MCD_WORDRAM_VGM_PTR (MCD_WORDRAM+VGM_WORDRAM_OFS) +#define MARS_PWM_CTRL (*(volatile unsigned short *)0xA15130) +#define MARS_PWM_CYCLE (*(volatile unsigned short *)0xA15132) +#define MARS_PWM_MONO (*(volatile unsigned short *)0xA15138) + static lzss_state_t vgm_lzss = { 0 }; static int rf5c68_dataofs; static int rf5c68_datalen; @@ -90,9 +96,9 @@ int vgm_setup(void* fm_ptr) if ((fm_ptr >= MD_WORDRAM_VGM_PTR && fm_ptr < MD_WORDRAM+0x20000) && pcm_baseoffs) { pcm_baseoffs += (fm_ptr - MD_WORDRAM_VGM_PTR); } - if (rf5c68_dataofs) + if (rf5c68_dataofs) { rf5c68_dataofs += pcm_baseoffs; - + } // convert RF5C68's signed PCM samples to uchar because that's what the driver expects if ((fm_ptr >= MD_WORDRAM_VGM_PTR && fm_ptr < MD_WORDRAM+0x20000) && rf5c68_dataofs) { @@ -170,6 +176,7 @@ void *vgm_cache_scd(const char *name, int offset, int length) return ptr; } +#ifndef VGM_USE_PWM_FOR_DAC void vgm_play_scd_samples(int offset, int length, int freq) { void *ptr = (char *)MCD_WORDRAM_VGM_PTR + pcm_baseoffs + offset; @@ -177,17 +184,57 @@ void vgm_play_scd_samples(int offset, int length, int freq) scd_queue_setptr_buf(VGM_MCD_BUFFER_ID, ptr, length); scd_queue_play_src(VGM_MCD_SOURCE_ID, VGM_MCD_BUFFER_ID, freq, 128, 255, 0); } +#endif void vgm_play_samples(int offset, int length, int freq) { +#ifdef VGM_USE_PWM_FOR_DAC + extern uint16_t dac_freq, dac_len, dac_center; + extern void *dac_samples; + + if (!cd_ok) + return; + + if (dac_freq != freq) + { + int cycle; + int ntsc = 1; + + dac_freq = freq; + if (ntsc) + cycle = (((23011361 << 1)/dac_freq + 1) >> 1) + 1; // for NTSC clock + else + cycle = (((22801467 << 1)/dac_freq + 1) >> 1) + 1; // for PAL clock + dac_center = cycle >> 1; + + MARS_PWM_CTRL = 0x05; // left and right + MARS_PWM_CYCLE = cycle; + MARS_PWM_MONO = dac_center; + MARS_PWM_MONO = dac_center; + MARS_PWM_MONO = dac_center; + } + + dac_samples = (char *)MD_WORDRAM_VGM_PTR + pcm_baseoffs + offset; + dac_len = length; +#else if (cd_ok) vgm_play_scd_samples(offset, length, freq); +#endif } void vgm_stop_samples(void) { +#ifdef VGM_USE_PWM_FOR_DAC + extern uint16_t dac_len, dac_center; + + dac_len = 0; + MARS_PWM_MONO = dac_center; + MARS_PWM_MONO = dac_center; + MARS_PWM_MONO = dac_center; +#else if (cd_ok) scd_queue_stop_src(VGM_MCD_SOURCE_ID); +#endif } void vgm_play_rf5c68_samples(int offset, int loopstart, int incr, int vol)