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

#include	"compiler.h"
#include	"cpucore.h"
#include	"pccore.h"
#include	"iocore.h"
#include	"pcm86io.h"
#include	"sound.h"
#include	"fmboard.h"


extern	PCM86CFG	pcm86cfg;


static const UINT8 pcm86bits[] = {1, 1, 1, 2, 0, 0, 0, 1};
static const SINT32 pcm86rescue[] = {PCM86_RESCUE * 32, PCM86_RESCUE * 24,
									 PCM86_RESCUE * 16, PCM86_RESCUE * 12,
									 PCM86_RESCUE *  8, PCM86_RESCUE *  6,
									 PCM86_RESCUE *  4, PCM86_RESCUE *  3};


static void IOOUTCALL pcm86_oa460(UINT port, REG8 val) {

	pcm86.extfunc = val;
	fmboard_extenable((REG8)(val & 1));
	(void)port;
}

static void IOOUTCALL pcm86_oa466(UINT port, REG8 val) {

	if ((val & 0xe0) == 0xa0) {
		sound_sync();
		pcm86.vol5 = (~val) & 15;
		pcm86.volume = pcm86cfg.vol * pcm86.vol5;
	}
	(void)port;
}

static void IOOUTCALL pcm86_oa468(UINT port, REG8 val) {

	REG8	xchgbit;

	sound_sync();
	xchgbit = pcm86.fifo ^ val;
	// バッファリセット判定
	if ((xchgbit & 8) && (val & 8)) {
		pcm86.readpos = 0;				// バッファリセット
		pcm86.wrtpos = 0;
		pcm86.realbuf = 0;
		pcm86.virbuf = 0;
		pcm86.write = 0;
		pcm86.reqirq = 0;
		pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
		pcm86.lastclock <<= 6;
	}
	// サンプリングレート変更
	if (xchgbit & 7) {
		pcm86.rescue = pcm86rescue[val & 7] << pcm86.stepbit;
		pcm86_setpcmrate(val);
	}
	pcm86.fifo = val & (~0x10);
	if ((xchgbit & 0x80) && (val & 0x80)) {
		pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
		pcm86.lastclock <<= 6;
	}
	pcm86.write = 1;
	pcm86_setnextintr();
	(void)port;
}

static void IOOUTCALL pcm86_oa46a(UINT port, REG8 val) {

	sound_sync();
	if (pcm86.fifo & 0x20) {
#if 1
		if (val != 0xff) {
			pcm86.fifosize = (UINT16)((val + 1) << 7);
		}
		else {
			pcm86.fifosize = 0x7ffc;
		}
#else
		if (!val) {
			val++;
		}
		pcm86.fifosize = (WORD)(val) << 7;
#endif
	}
	else {
		pcm86.dactrl = val;
		pcm86.stepbit = pcm86bits[(val >> 4) & 7];
		pcm86.stepmask = (1 << pcm86.stepbit) - 1;
		pcm86.rescue = pcm86rescue[pcm86.fifo & 7] << pcm86.stepbit;
	}
	pcm86_setnextintr();
	(void)port;
}

static void IOOUTCALL pcm86_oa46c(UINT port, REG8 val) {

	if (pcm86.virbuf < PCM86_LOGICALBUF) {
		pcm86.virbuf++;
		pcm86.buffer[pcm86.wrtpos] = val;
		pcm86.wrtpos = (pcm86.wrtpos + 1) & PCM86_BUFMSK;
		pcm86.realbuf++;
		// バッファオーバーフローの監視
		if (pcm86.realbuf >= PCM86_REALBUFSIZE) {
			pcm86.realbuf &= 3;				// align4決めウチ
			pcm86.realbuf += PCM86_REALBUFSIZE - 4;
		}
		pcm86.write = 1;
		pcm86.reqirq = 1;
	}
	(void)port;
}

static REG8 IOINPCALL pcm86_ia460(UINT port) {

	(void)port;
	return(0x40 | (pcm86.extfunc & 1));
}

static REG8 IOINPCALL pcm86_ia466(UINT port) {

	UINT32	nowclk;
	UINT32	past;
	REG8	ret;

	sound_sync();
	nowclk = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
	nowclk <<= 6;
	past = nowclk - pcm86.lastclock;
	if (past >= pcm86.stepclock) {
		RECALC_NOWCLKWAIT;
		past = nowclk - pcm86.lastclock;
	}
	ret = ((past << 1) >= pcm86.stepclock)?1:0;
	if (pcm86.virbuf >= PCM86_LOGICALBUF) {			// バッファフル
		ret |= 0x80;
	}
	else if (!pcm86.virbuf) {						// バッファ0
		ret |= 0x40;								// ちと変…
	}
	(void)port;
	return(ret);
}

static REG8 IOINPCALL pcm86_ia468(UINT port) {

	REG8	ret;

	ret = pcm86.fifo & (~0x10);
	if ((pcm86.write) && (pcm86.fifo & 0x20)) {
//		pcm86.write = 0;
		sound_sync();
		if (pcm86.virbuf <= pcm86.fifosize) {
			pcm86.write = 0;
			ret |= 0x10;
		}
	}
	(void)port;
	return(ret);
}

static REG8 IOINPCALL pcm86_ia46a(UINT port) {

	(void)port;
	return(pcm86.dactrl);
}

static REG8 IOINPCALL pcm86_inpdummy(UINT port) {

	(void)port;
	return(0);
}


// ----

void pcm86io_bind(void) {

	sound_streamregist(&pcm86, (SOUNDCB)pcm86gen_getpcm);

	iocore_attachout(0xa460, pcm86_oa460);
	iocore_attachout(0xa466, pcm86_oa466);
	iocore_attachout(0xa468, pcm86_oa468);
	iocore_attachout(0xa46a, pcm86_oa46a);
	iocore_attachout(0xa46c, pcm86_oa46c);

	iocore_attachinp(0xa460, pcm86_ia460);
	iocore_attachinp(0xa462, pcm86_inpdummy);
	iocore_attachinp(0xa464, pcm86_inpdummy);
	iocore_attachinp(0xa466, pcm86_ia466);
	iocore_attachinp(0xa468, pcm86_ia468);
	iocore_attachinp(0xa46a, pcm86_ia46a);
	iocore_attachinp(0xa46c, pcm86_inpdummy);
	iocore_attachinp(0xa46e, pcm86_inpdummy);
}


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