Skip to content

Commit

Permalink
Use PWM on the 32X for YM2612 DAC samples playback
Browse files Browse the repository at this point in the history
  • Loading branch information
viciious committed Jun 12, 2024
1 parent 749cd7c commit 85ddf8b
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 2 deletions.
42 changes: 42 additions & 0 deletions src-md/crt0.s
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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:
Expand Down
51 changes: 49 additions & 2 deletions src-md/vgm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -170,24 +176,65 @@ 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;

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)
Expand Down

0 comments on commit 85ddf8b

Please sign in to comment.