File:  [RetroPC.NET] / np2 / sound / cs4231g.c
Revision 1.4: download - view: text, annotated - select for diffs
Mon Dec 8 09:55:33 2003 JST (21 years, 10 months ago) by yui
Branches: MAIN
CVS tags: HEAD
add IA32 etc... (T.Yui)

#include	"compiler.h"
#include	"memory.h"
#include	"pccore.h"
#include	"iocore.h"
#include	"sound.h"
#include	"fmboard.h"


extern	CS4231CFG	cs4231cfg;


// ---- 補完くらいしようよ…

REG8 cs4231_nodecode(void) {

	return(0);
}

static REG8 cs4231_pcm8s(void) {

	SINT32	leng;
	UINT	indatas;
	UINT32	addr;
	UINT32	ctime;
	UINT	wpos;

	leng = dmac.dmach[0].leng.w;
	if ((leng >= 2) && (cs4231.bufsize < CS4231_BUFFERS)) {
		indatas = cs4231.bufsize;
		ctime = cs4231.curtime;
		wpos = cs4231.writepos;
		addr = dmac.dmach[0].adrs.d;
		do {
			while(ctime < cs4231.step) {
				ctime += cs4231cfg.rate;
				leng -= 2;
				if (leng < 0) {
					leng = 0;
					goto p8s_stop;
				}
				cs4231.pcmdata[0] = (i286_memoryread(addr + 0) ^ 0x80) << 8;
				cs4231.pcmdata[1] = (i286_memoryread(addr + 1) ^ 0x80) << 8;
				addr += 2;
			}
			ctime -= cs4231.step;
			*(UINT32 *)(cs4231.buffer + wpos) = *(UINT32 *)cs4231.pcmdata,
			wpos = (wpos + 4) & (CS4231_BUFBYTES - 1);
			indatas++;
		} while(indatas < CS4231_BUFFERS);

p8s_stop:
		dmac.dmach[0].leng.w = leng;
		dmac.dmach[0].adrs.d = addr;
		cs4231.bufsize = indatas;
		cs4231.curtime = ctime;
		cs4231.writepos = wpos;
	}
	return((leng < 2)?1:0);
}

static REG8 cs4231_pcm8m(void) {

	SINT32	leng;
	UINT	indatas;
	UINT32	addr;
	UINT32	ctime;
	UINT	wpos;
	SINT16	pcmdata;

	leng = dmac.dmach[0].leng.w;
	if ((leng > 0) && (cs4231.bufsize < CS4231_BUFFERS)) {
		indatas = cs4231.bufsize;
		ctime = cs4231.curtime;
		wpos = cs4231.writepos;
		addr = dmac.dmach[0].adrs.d;
		do {
			while(ctime < cs4231.step) {
				ctime += cs4231cfg.rate;
				leng -= 1;
				if (leng < 0) {
					leng = 0;
					goto p8m_stop;
				}
				pcmdata = (i286_memoryread(addr) ^ 0x80) << 8;
				cs4231.pcmdata[0] = pcmdata;
				cs4231.pcmdata[1] = pcmdata;
				addr += 1;
			}
			ctime -= cs4231.step;
			*(UINT32 *)(cs4231.buffer + wpos) = *(UINT32 *)cs4231.pcmdata,
			wpos = (wpos + 4) & (CS4231_BUFBYTES - 1);
			indatas++;
		} while(indatas < CS4231_BUFFERS);

p8m_stop:
		dmac.dmach[0].leng.w = leng;
		dmac.dmach[0].adrs.d = addr;
		cs4231.bufsize = indatas;
		cs4231.curtime = ctime;
		cs4231.writepos = wpos;
	}
	return((leng == 0)?1:0);
}

static REG8 cs4231_pcm16s(void) {

	SINT32	leng;
	UINT	indatas;
	UINT32	addr;
	UINT32	ctime;
	UINT	wpos;
	UINT16	samp;

	leng = dmac.dmach[0].leng.w;
	if ((leng >= 4) && (cs4231.bufsize < CS4231_BUFFERS)) {
		indatas = cs4231.bufsize;
		ctime = cs4231.curtime;
		wpos = cs4231.writepos;
		addr = dmac.dmach[0].adrs.d;
// TRACEOUT(("addr: %x", addr));
		do {
			while(ctime < cs4231.step) {
				ctime += cs4231cfg.rate;
				leng -= 4;
				if (leng < 0) {
					leng = 0;
					goto p16s_stop;
				}
				samp = i286_memoryread_w(addr+0);
				cs4231.pcmdata[0] = (SINT16)((samp << 8) + (samp >> 8));
				samp = i286_memoryread_w(addr+2);
				cs4231.pcmdata[1] = (SINT16)((samp << 8) + (samp >> 8));
				addr += 4;
			}
			ctime -= cs4231.step;
			*(UINT32 *)(cs4231.buffer + wpos) = *(UINT32 *)cs4231.pcmdata,
			wpos = (wpos + 4) & (CS4231_BUFBYTES - 1);
			indatas++;
		} while(indatas < CS4231_BUFFERS);

p16s_stop:
		dmac.dmach[0].leng.w = leng;
		dmac.dmach[0].adrs.d = addr;
		cs4231.bufsize = indatas;
		cs4231.curtime = ctime;
		cs4231.writepos = wpos;
	}
	return((leng < 4)?1:0);
}

static REG8 cs4231_pcm16m(void) {

	SINT32	leng;
	UINT	indatas;
	UINT32	addr;
	UINT32	ctime;
	UINT	wpos;
	UINT16	samp;

	leng = dmac.dmach[0].leng.w;
	if ((leng >= 2) && (cs4231.bufsize < CS4231_BUFFERS)) {
		indatas = cs4231.bufsize;
		ctime = cs4231.curtime;
		wpos = cs4231.writepos;
		addr = dmac.dmach[0].adrs.d;
		do {
			while(ctime < cs4231.step) {
				ctime += cs4231cfg.rate;
				leng -= 2;
				if (leng < 0) {
					leng = 0;
					goto p16m_stop;
				}
				samp = i286_memoryread_w(addr);
				samp = (UINT16)((samp << 8) + (samp >> 8));
				cs4231.pcmdata[0] = (SINT16)samp;
				cs4231.pcmdata[1] = (SINT16)samp;
				addr += 2;
			}
			ctime -= cs4231.step;
			*(UINT32 *)(cs4231.buffer + wpos) = *(UINT32 *)cs4231.pcmdata,
			wpos = (wpos + 4) & (CS4231_BUFBYTES - 1);
			indatas++;
		} while(indatas < CS4231_BUFFERS);

p16m_stop:
		dmac.dmach[0].leng.w = leng;
		dmac.dmach[0].adrs.d = addr;
		cs4231.bufsize = indatas;
		cs4231.curtime = ctime;
		cs4231.writepos = wpos;
	}
	return((leng < 2)?1:0);
}

const CS4231DMA cs4231dec[16] = {
			cs4231_pcm8m,		// 0: 8bit PCM
			cs4231_pcm8s,
			cs4231_nodecode,	// 1: u-Law
			cs4231_nodecode,
			cs4231_nodecode,	// 2:
			cs4231_nodecode,
			cs4231_nodecode,	// 3: A-law
			cs4231_nodecode,
			cs4231_nodecode,	// 4:
			cs4231_nodecode,
			cs4231_nodecode,	// 5: ADPCM
			cs4231_nodecode,
			cs4231_pcm16m,		// 6: 16bit PCM
			cs4231_pcm16s,
			cs4231_nodecode,	// 7: ADPCM
			cs4231_nodecode};


// ----

void SOUNDCALL cs4231_getpcm(CS4231 cs, SINT32 *pcm, UINT count) {

	UINT	pos;

	count = min(count, cs->bufsize);
	if (count) {
		cs->bufsize -= count;
		pos = cs->readpos;
		do {
			pcm[0] += (*(SINT16 *)(cs->buffer + pos + 0)) >> 1;
			pcm[1] += (*(SINT16 *)(cs->buffer + pos + 2)) >> 1;
			pcm += 2;
			pos = (pos + 4) & (CS4231_BUFBYTES - 1);
		} while(--count);
		cs->readpos = pos;
	}
}


RetroPC.NET-CVS <cvs@retropc.net>