From: ljsebald <ljs...@us...> - 2023-11-05 03:48:28
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 3065978c74fe2e03df1eda3464d35a1115d8f830 (commit) via a8b0bc3d72a2fe0b86dd63a95b35d3442b15620f (commit) via 17633dc9bd128356050292c885c9cebd8c21b7a0 (commit) via 8a0f03efb8d469c780804d6f65bbe7f1c2055565 (commit) via a2c13f5b879dee33ead90488e94fcfed30d2bb7d (commit) from a113876777c99e0ed3edded98f226a6c902af97e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 3065978c74fe2e03df1eda3464d35a1115d8f830 Author: Ruslan Rostovtsev <sw...@21...> Date: Sun Nov 5 10:47:47 2023 +0700 Improvements for sound FX and added ADPCM long stream support. (#334) * Added spu_memload_sq(). * Added ADPCM long stream AICA sample format. * Changed API for snd_pcm16_split_sq(). * Improved sound FX samples loading. * 4-byte align support for spu_memload_sq() * Added support for ADPCM streams. * Added G2 Bus locking for SQ's with SPU memory. * Cleanup for SFX loading * Workaround for sound stream memory allocation bug. * Apply suggestions from code review commit a8b0bc3d72a2fe0b86dd63a95b35d3442b15620f Merge: 17633dc a2c13f5 Author: Lawrence Sebald <ljs...@us...> Date: Sat Nov 4 23:46:16 2023 -0400 Merge pull request #338 from KallistiOS/timerfix Fix race condition while getting timer info commit 17633dc9bd128356050292c885c9cebd8c21b7a0 Merge: a113876 8a0f03e Author: Lawrence Sebald <ljs...@us...> Date: Sat Nov 4 23:44:25 2023 -0400 Merge pull request #339 from KallistiOS/abortused Add __attribute__((used)) to abort to fix linking issues when using LTO commit 8a0f03efb8d469c780804d6f65bbe7f1c2055565 Author: darc <da...@pr...> Date: Sat Nov 4 19:00:46 2023 -0500 Add __attribute__((used)) to abort to fix linking issues when using LTO commit a2c13f5b879dee33ead90488e94fcfed30d2bb7d Author: darc <da...@pr...> Date: Sat Nov 4 18:29:03 2023 -0500 Fix race condition while getting timer info ----------------------------------------------------------------------- Summary of changes: kernel/arch/dreamcast/exports-naomi.txt | 1 + kernel/arch/dreamcast/exports-pristine.txt | 1 + kernel/arch/dreamcast/hardware/spu.c | 38 ++++++- kernel/arch/dreamcast/include/dc/sound/aica_comm.h | 8 +- kernel/arch/dreamcast/include/dc/sound/sound.h | 22 +++- kernel/arch/dreamcast/include/dc/sound/stream.h | 13 ++- kernel/arch/dreamcast/include/dc/spu.h | 18 ++- kernel/arch/dreamcast/kernel/timer.c | 22 +++- kernel/arch/dreamcast/sound/snd_pcm_split.s | 53 ++++++++- kernel/arch/dreamcast/sound/snd_sfxmgr.c | 126 ++++++++------------- kernel/arch/dreamcast/sound/snd_stream.c | 93 +++++++++------ kernel/libc/koslib/abort.c | 2 +- 12 files changed, 263 insertions(+), 134 deletions(-) diff --git a/kernel/arch/dreamcast/exports-naomi.txt b/kernel/arch/dreamcast/exports-naomi.txt index 1744f16..3a5587d 100644 --- a/kernel/arch/dreamcast/exports-naomi.txt +++ b/kernel/arch/dreamcast/exports-naomi.txt @@ -130,6 +130,7 @@ snd_stream_reinit snd_stream_prefill snd_pcm16_split snd_pcm16_split_sq +snd_adpcm_split # Video vid_check_cable diff --git a/kernel/arch/dreamcast/exports-pristine.txt b/kernel/arch/dreamcast/exports-pristine.txt index 361b525..93e0c14 100644 --- a/kernel/arch/dreamcast/exports-pristine.txt +++ b/kernel/arch/dreamcast/exports-pristine.txt @@ -173,6 +173,7 @@ snd_stream_reinit snd_stream_prefill snd_pcm16_split snd_pcm16_split_sq +snd_adpcm_split # Video vid_check_cable diff --git a/kernel/arch/dreamcast/hardware/spu.c b/kernel/arch/dreamcast/hardware/spu.c index f4d393f..9f500ac 100644 --- a/kernel/arch/dreamcast/hardware/spu.c +++ b/kernel/arch/dreamcast/hardware/spu.c @@ -1,11 +1,14 @@ /* KallistiOS ##version## spu.c - (c)2000-2001 Megan Potter + Copyright (C) 2000, 2001 Megan Potter + Copyright (C) 2023 Ruslan Rostovtsev */ #include <dc/spu.h> #include <dc/g2bus.h> +#include <dc/sq.h> +#include <arch/memory.h> #include <arch/timer.h> /* @@ -62,6 +65,39 @@ void spu_memload(uint32 dst, void *src_void, int length) { } } +void spu_memload_sq(uint32 dst, void *src_void, int length) { + uint8 *src = (uint8 *)src_void; + int aligned_len, old; + + /* Make sure it's an even number of 32-bit words and convert the + count to a 32-bit word count */ + if(length & 3) { + length = (length + 4) & ~3; + } + + /* Add in the SPU RAM base (cached area) */ + dst += 0x00800000; + + /* Using SQs for all that is divisible by 32 */ + aligned_len = length & ~31; + length &= 31; + + old = irq_disable(); + do { } while(*(vuint32 *)0xa05f688c & (1 << 5)); /* FIFO_SH4 */ + do { } while(*(vuint32 *)0xa05f688c & (1 << 4)); /* FIFO_G2 */ + sq_cpy((void *)dst, src, aligned_len); + irq_restore(old); + + if(length > 0) { + /* Make sure the destination is in a non-cached area */ + dst |= MEM_AREA_P2_BASE; + dst += aligned_len; + src += aligned_len; + g2_fifo_wait(); + g2_write_block_32((uint32 *)src, dst, length >> 2); + } +} + void spu_memread(void *dst_void, uint32 src, int length) { uint8 *dst = (uint8*)dst_void; diff --git a/kernel/arch/dreamcast/include/dc/sound/aica_comm.h b/kernel/arch/dreamcast/include/dc/sound/aica_comm.h index f51b70d..3e280a2 100644 --- a/kernel/arch/dreamcast/include/dc/sound/aica_comm.h +++ b/kernel/arch/dreamcast/include/dc/sound/aica_comm.h @@ -2,6 +2,7 @@ aica_comm.h Copyright (C) 2000-2002 Megan Potter + Copyright (C) 2023 Ruslan Rostovtsev Structure and constant definitions for the SH-4/AICA interface. This file is included from both the ARM and SH-4 sides of the fence. @@ -100,8 +101,9 @@ typedef struct aica_channel { #define AICA_CH_UPDATE_SET_PAN 0x00004000 /* panning */ /* Sample types */ -#define AICA_SM_8BIT 1 -#define AICA_SM_16BIT 0 -#define AICA_SM_ADPCM 2 +#define AICA_SM_16BIT 0 /* Linear PCM 16-bit */ +#define AICA_SM_8BIT 1 /* Linear PCM 8-bit */ +#define AICA_SM_ADPCM 2 /* Yamaha ADPCM 4-bit */ +#define AICA_SM_ADPCM_LS 3 /* Long stream ADPCM 4-bit */ #endif /* !__DC_SOUND_AICA_COMM_H */ diff --git a/kernel/arch/dreamcast/include/dc/sound/sound.h b/kernel/arch/dreamcast/include/dc/sound/sound.h index 86ed253..02bcdbe 100644 --- a/kernel/arch/dreamcast/include/dc/sound/sound.h +++ b/kernel/arch/dreamcast/include/dc/sound/sound.h @@ -166,13 +166,9 @@ void snd_pcm16_split(uint32_t *data, uint32_t *left, uint32_t *right, size_t siz \warning All arguments must be 32-byte aligned. - \warning - The store queues must be configured for transferring to the left and right - destination buffers beforehand (QACRO <= left, QACRO1 <= right). - \param data Source buffer of interleaved stereo samples - \param left SQ-masked left destination buffer address - \param right SQ-masked right destination buffer address + \param left Destination buffer address for left mono samples + \param right Destination buffer address for right mono samples \param size Size of the source buffer in bytes (must be divisible by 32) \sa snd_pcm16_split() @@ -180,6 +176,20 @@ void snd_pcm16_split(uint32_t *data, uint32_t *left, uint32_t *right, size_t siz */ void snd_pcm16_split_sq(uint32_t *data, uintptr_t left, uintptr_t right, size_t size); +/** \brief Separates stereo ADPCM samples into 2 mono channels. + + Splits a buffer containing 2 interleaved channels of 4-bit ADPCM samples + into 2 separate buffers of 4-bit ADPCM samples. + + \param data Source buffer of interleaved stereo samples + \param left Destination buffer for left mono samples + \param right Destination buffer for right mono samples + \param size Size of the source buffer in bytes + + \sa snd_pcm16_split() +*/ +void snd_adpcm_split(uint32_t *data, uint32_t *left, uint32_t *right, size_t size); + __END_DECLS #endif /* __DC_SOUND_SOUND_H */ diff --git a/kernel/arch/dreamcast/include/dc/sound/stream.h b/kernel/arch/dreamcast/include/dc/sound/stream.h index 80c8204..97825ff 100644 --- a/kernel/arch/dreamcast/include/dc/sound/stream.h +++ b/kernel/arch/dreamcast/include/dc/sound/stream.h @@ -238,7 +238,7 @@ void snd_stream_queue_disable(snd_stream_hnd_t hnd); */ void snd_stream_queue_go(snd_stream_hnd_t hnd); -/** \brief Start a stream. +/** \brief Start a 16-bit PCM stream. This function starts processing the given stream, prefilling the buffers as necessary. In queueing mode, this will not start playback. @@ -249,6 +249,17 @@ void snd_stream_queue_go(snd_stream_hnd_t hnd); */ void snd_stream_start(snd_stream_hnd_t hnd, uint32 freq, int st); +/** \brief Start a 4-bit ADPCM stream. + + This function starts processing the given stream, prefilling the buffers as + necessary. In queueing mode, this will not start playback. + + \param hnd The stream to start. + \param freq The frequency of the sound. + \param st 1 if the sound is stereo, 0 if mono. +*/ +void snd_stream_start_adpcm(snd_stream_hnd_t hnd, uint32 freq, int st); + /** \brief Stop a stream. This function stops a stream, stopping any sound playing from it. This will diff --git a/kernel/arch/dreamcast/include/dc/spu.h b/kernel/arch/dreamcast/include/dc/spu.h index a425d33..3ea8e73 100644 --- a/kernel/arch/dreamcast/include/dc/spu.h +++ b/kernel/arch/dreamcast/include/dc/spu.h @@ -1,7 +1,8 @@ /* KallistiOS ##version## dc/spu.h - Copyright (C) 2000-2001 Megan Potter + Copyright (C) 2000, 2001 Megan Potter + Copyright (C) 2023 Ruslan Rostovtsev */ @@ -11,6 +12,7 @@ This file deals with memory transfers and the like for the sound hardware. \author Megan Potter + \author Ruslan Rostovtsev */ #ifndef __DC_SPU_H @@ -37,6 +39,20 @@ void spu_write_wait(void); */ void spu_memload(uint32 to, void *from, int length); + +/** \brief Copy a block of data to sound RAM. + + This function acts much like memcpy() but copies to the sound RAM area + by using the store queues. + + \param to The offset in sound RAM to copy to. Do not include + the 0xA0800000 part, it is implied. + \param from A pointer to copy from. + \param length The number of bytes to copy. Automatically rounded + up to be a multiple of 4. +*/ +void spu_memload_sq(uint32 to, void *from, int length); + /** \brief Copy a block of data from sound RAM. This function acts much like memcpy() but copies from the sound RAM area. diff --git a/kernel/arch/dreamcast/kernel/timer.c b/kernel/arch/dreamcast/kernel/timer.c index b9276d8..39bf2d4 100644 --- a/kernel/arch/dreamcast/kernel/timer.c +++ b/kernel/arch/dreamcast/kernel/timer.c @@ -146,6 +146,9 @@ static void timer_ms_handler(irq_t source, irq_context_t *context) { (void)source; (void)context; timer_ms_counter++; + + /* Clear overflow bit so we can check it when returning time */ + TIMER16(tcrs[TMU2]) &= ~0x100; } void timer_ms_enable(void) { @@ -165,6 +168,8 @@ void timer_ms_disable(void) { void timer_ms_gettime(uint32 *secs, uint32 *msecs) { uint32 used; + int irq_status = irq_disable(); + /* Seconds part comes from ms_counter */ if(secs) *secs = timer_ms_counter; @@ -172,9 +177,14 @@ void timer_ms_gettime(uint32 *secs, uint32 *msecs) { /* Milliseconds, we check how much of the timer has elapsed */ if(msecs) { assert(timer_ms_countdown > 0); - used = timer_ms_countdown - timer_count(TMU2); - *msecs = used * 1000 / timer_ms_countdown; + /* Overflow is only notable if we have seconds we can + overflow into, so avoid read of TCR if secs is null */ + if (secs && TIMER16(tcrs[TMU2]) & 0x100) + *secs += 1; + used = timer_count(TMU2); + *msecs = (timer_ms_countdown - used) * 1000 / timer_ms_countdown; } + irq_restore(irq_status); } uint64 timer_ms_gettime64(void) { @@ -192,8 +202,15 @@ uint64 timer_us_gettime64(void) { uint64 usec; uint64 used; + int irq_status = irq_disable(); scnt = timer_ms_counter; cnt = timer_count(TMU2); + if (TIMER16(tcrs[TMU2]) & 0x100) { + /* If we underflowed, add an extra second and reload microseconds */ + scnt++; + cnt = timer_count(TMU2); + } + irq_restore(irq_status); assert(timer_ms_countdown > 0); used = timer_ms_countdown - cnt; @@ -389,4 +406,3 @@ inline uint64 timer_ns_gettime64(void) { return micro_secs * 1000; } } - diff --git a/kernel/arch/dreamcast/sound/snd_pcm_split.s b/kernel/arch/dreamcast/sound/snd_pcm_split.s index 276507a..1752b41 100644 --- a/kernel/arch/dreamcast/sound/snd_pcm_split.s +++ b/kernel/arch/dreamcast/sound/snd_pcm_split.s @@ -8,12 +8,13 @@ .section .text .globl _snd_pcm16_split -.globl _snd_pcm16_split_sq +.globl _snd_pcm16_split_sq_start +.globl _snd_adpcm_split .align 2 ! -! void snd_pcm16_split(uint32_t *data, uint32_t *left, uint32_t *right, uint32_t size); +! void snd_pcm16_split(uint32_t *data, uint32_t *left, uint32_t *right, size_t size); ! _snd_pcm16_split: mov #-5, r3 @@ -64,9 +65,9 @@ _snd_pcm16_split: mov #0, r0 ! -! void snd_pcm16_split_sq(uint32_t *data, uint32_t left, uint32_t right, uint32_t size); +! void snd_pcm16_split_sq_start(uint32_t *data, uintptr_t left, uintptr_t right, size_t size); ! -_snd_pcm16_split_sq: +_snd_pcm16_split_sq_start: mov #-5, r3 shld r3, r7 mov.l r8, @-r15 @@ -112,3 +113,47 @@ _snd_pcm16_split_sq: mov.l @r15+, r8 rts nop + +! +! void snd_adpcm_split(uint32_t *data, uint32_t *left, uint32_t *right, size_t size); +! +_snd_adpcm_split: + mov #-5, r1 + shld r1, r7 + mov.l r10, @-r15 + mov #16, r1 +.adpcm_pref: + add #32, r4 + pref @r4 + add #-32, r4 +.adpcm_copy: + dt r1 + mov.w @r4+, r10 + mov r10, r0 + and #0xf0, r0 + mov r0, r2 + shlr2 r2 + mov r10, r0 + shlr2 r2 + and #0x0f, r0 + mov r0, r3 + shlr8 r10 + mov r10, r0 + and #0xf0, r0 + or r0, r2 + mov.b r2, @r5 + add #1, r5 + mov r10, r0 + and #0x0f, r0 + shll2 r0 + shll2 r0 + or r0, r3 + mov.b r3, @r6 + bf/s .adpcm_copy + add #1, r6 + dt r7 + bf/s .adpcm_pref + mov #16, r1 + mov.l @r15+, r10 + rts + nop diff --git a/kernel/arch/dreamcast/sound/snd_sfxmgr.c b/kernel/arch/dreamcast/sound/snd_sfxmgr.c index 9d0fade..d0eb44a 100644 --- a/kernel/arch/dreamcast/sound/snd_sfxmgr.c +++ b/kernel/arch/dreamcast/sound/snd_sfxmgr.c @@ -2,6 +2,7 @@ snd_sfxmgr.c Copyright (C) 2000, 2001, 2002, 2003, 2004 Megan Potter + Copyright (C) 2023 Ruslan Rostovtsev Sound effects management system; this thing loads and plays sound effects during game operation. @@ -11,6 +12,7 @@ #include <stdlib.h> #include <assert.h> #include <string.h> +#include <malloc.h> #include <sys/queue.h> #include <kos/fs.h> @@ -96,11 +98,11 @@ void snd_sfx_unload(sfxhnd_t idx) { /* Load a sound effect from a WAV file and return a handle to it */ sfxhnd_t snd_sfx_load(const char *fn) { - file_t fd; - uint32 len, hz; - uint16 *tmp, stereo, bitsize, fmt; + file_t fd; + uint32_t len, hz; + uint8_t *tmp; + uint16_t channels, bitsize, fmt; snd_effect_t *t; - int ownmem; dbglog(DBG_DEBUG, "snd_sfx: loading effect %s\n", fn); @@ -116,7 +118,7 @@ sfxhnd_t snd_sfx_load(const char *fn) { fs_seek(fd, 0x08, SEEK_SET); fs_read(fd, &hz, 4); - if(strncmp((char*)&hz, "WAVE", 4)) { + if(strncmp((char *)&hz, "WAVE", 4)) { dbglog(DBG_WARNING, "snd_sfx: file is not RIFF WAVE\n"); fs_close(fd); return SFXHND_INVALID; @@ -125,7 +127,7 @@ sfxhnd_t snd_sfx_load(const char *fn) { /* Read WAV header info */ fs_seek(fd, 0x14, SEEK_SET); fs_read(fd, &fmt, 2); - fs_read(fd, &stereo, 2); + fs_read(fd, &channels, 2); fs_read(fd, &hz, 4); fs_seek(fd, 0x22, SEEK_SET); fs_read(fd, &bitsize, 2); @@ -135,35 +137,26 @@ sfxhnd_t snd_sfx_load(const char *fn) { fs_read(fd, &len, 4); dbglog(DBG_DEBUG, "WAVE file is %s, %luHZ, %d bits/sample, %lu bytes total," - " format %d\n", stereo == 1 ? "mono" : "stereo", hz, bitsize, len, fmt); + " format %d\n", channels == 1 ? "mono" : "stereo", hz, bitsize, len, fmt); - /* Try to mmap it and if that works, no need to copy it again */ - ownmem = 0; - tmp = (uint16 *)fs_mmap(fd); + tmp = (uint8_t *)memalign(32, len); - if(!tmp) { - tmp = malloc(len); - - if(tmp == NULL) { - fs_close(fd); - return SFXHND_INVALID; - } - - fs_read(fd, tmp, len); - ownmem = 1; - } - else { - tmp = (uint16 *)(((uint8 *)tmp) + fs_tell(fd)); + if(tmp == NULL) { + fs_close(fd); + return SFXHND_INVALID; } + uint32_t rd = fs_read(fd, tmp, len); fs_close(fd); + if (rd != len) { + dbglog(DBG_WARNING, "snd_sfx: file has not been fully read.\n"); + } + t = malloc(sizeof(snd_effect_t)); if(t == NULL) { - if(ownmem) - free(tmp); - + free(tmp); return SFXHND_INVALID; } @@ -171,19 +164,17 @@ sfxhnd_t snd_sfx_load(const char *fn) { /* Common characteristics not impacted by stream type */ t->rate = hz; - t->stereo = stereo - 1; + t->stereo = channels - 1; - if(stereo == 1) { + if(channels == 1) { /* Mono PCM/ADPCM */ t->len = len / 2; /* 16-bit samples */ - t->rate = hz; t->locl = snd_mem_malloc(len); if(t->locl) - spu_memload(t->locl, tmp, len); + spu_memload_sq(t->locl, tmp, len); t->locr = 0; - t->stereo = 0; if(fmt == 20) { t->fmt = AICA_SM_ADPCM; @@ -192,77 +183,54 @@ sfxhnd_t snd_sfx_load(const char *fn) { else t->fmt = AICA_SM_16BIT; } - else if(stereo == 2 && fmt == 1) { + else if(channels == 2 && fmt == 1) { /* Stereo PCM */ - uint32 i; - uint16 * sepbuf; ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |