File:  [RetroPC.NET] / xmil / io / sio.c
Revision 1.4: download - view: text, annotated - select for diffs
Tue Jun 3 05:07:31 2008 JST (17 years, 4 months ago) by yui
Branches: MAIN
CVS tags: HEAD
change to c style comment

#include	"compiler.h"
#include	"mousemng.h"
#include	"z80core.h"
#include	"pccore.h"
#include	"iocore.h"


/* sw ... 割り込み 1=かける 0=かけない */
static void fifo_w(SIOFIFO *sf, REG8 data, REG8 sw) {

	UINT	off;

	off = sf->top + sf->cnt;
	if (off >= SIOFIFO_BUFMAX) {
		off -= SIOFIFO_BUFMAX;
	}
	sf->cnt++;
	if (sf->cnt >= SIOFIFO_BUFMAX) {
		sf->cnt = 0;
	}
	sf->buf[off] = (UINT8)data;
	sf->flg[off] = (UINT8)sw;
}

static REG8 fifo_r(SIOFIFO *sf) {

	REG8	data;

	if (!sf->cnt) {
		return(0);
	}
	sf->cnt--;
	data = sf->buf[sf->top++];
	if (sf->top >= SIOFIFO_BUFMAX) {
		sf->top = 0;
	}
	return(data);
}

#if 0
static REG8 fifo_chk(SIOFIFO *sf) {

	REG8	ret;

	if (sf->top != sf->fno) {
		return(0);
	}
	ret = sf->flg[sf->fno++];
	if (sf->fno >= SIOFIFO_BUFMAX) {
		sf->fno = 0;
	}
	return(ret);
}

static void x1_sio0(SIOCH *ch) {

	if ((!(ch->wr[1] & 0x18)) || (!(ch->wr[3] & 0x01)) || (!ch->RxD.cnt)) {
		return;
	}
	if (fifo_chk(&ch->RxD)) {
		ch->rx_int = 1;
	}
}

static BRESULT x1_sio1(SIOCH *ch) {

	REG8	vct;

	vct = (REG8)(ch->wr[2] & 0xf1);
	if ((ch->tx_int) && (!Z80_ABLEINTERRUPT())) {
		ch->tx_int = 0;
		Z80_INT(vct);
		return(TRUE);
	}
	if ((ch->rx_int) && (!Z80_ABLEINTERRUPT())) {
		ch->rx_int = 0;
		Z80_INT((REG8)(vct + 0x04));
		return(TRUE);
	}
	return(FALSE);
}

void sio_int(void) {

	x1_sio0(sio.ch + SIOCH_A);
	x1_sio0(sio.ch + SIOCH_B);
	if (x1_sio1(sio.ch + SIOCH_A)) return;
	if (x1_sio1(sio.ch + SIOCH_B)) return;
}
#endif

static void mouse_read(SIOCH *ch) {

	SINT16	mx;
	SINT16	my;
	UINT8	dat0, dat1, dat2;

	dat0 = mousemng_getstat(&mx, &my, TRUE) & 3;

	if (mx > 127) {
		dat1 = 0x7f;
		dat0 |= 0x10;
	}
	else if (mx < -127) {
		dat1 = 0x80;
		dat0 |= 0x20;
	}
	else {
		dat1 = (UINT8)mx;
	}
	if (my > 127) {
		dat2 = 0x7f;
		dat0 |= 0x40;
	}
	else if (my < -127) {
		dat2 = 0x80;
		dat0 |= 0x80;
	}
	else {
		dat2 = (UINT8)my;
	}
	if ((ch->wr[1] & 0x18) == 0x08) {
		fifo_w(&ch->RxD, dat0, 1);		/* 最初の1バイトだけ受信割り込み */
		fifo_w(&ch->RxD, dat1, 0);
		fifo_w(&ch->RxD, dat2, 0);
	}
	else {
		fifo_w(&ch->RxD, dat0, 1);		/* 1バイト毎に割り込み */
		fifo_w(&ch->RxD, dat1, 1);
		fifo_w(&ch->RxD, dat2, 1);
	}
}


/* ---- */

void IOOUTCALL sio_o(UINT port, REG8 value) {

	switch(port) {
		case 0x1f90:				/* CH-A データ */
			if (sio.ch[SIOCH_A].wr[3] & 0x08) {
				fifo_w(&sio.ch[SIOCH_A].TxD, value, 0);
			}
			break;

		case 0x1f91:				/* CH-A コントロール */
			sio.ch[SIOCH_A].wr[sio.ch[SIOCH_A].num] = value;
			if (sio.ch[SIOCH_A].num) {
				sio.ch[SIOCH_A].num = 0;
			}
			else if (value & 0xf1) {
				sio.ch[SIOCH_A].num = (value & 7);
			}
			break;
#if 0
		case 0x1f92:				/* CH-B データ   (Mouse) */
			if (CH_B.wr[3] & 0x08) {
				fifo_w(&CH_B.T_D, value, 0);
			}
			break;
#endif
		case 0x1f93:				/* CH-B コントロール (Mouse) */
			if (sio.ch[SIOCH_B].num == 5) {
				/* RTS(WR5:BIT1)を0から1へ変化させると */
				/* マウスから3バイトのデータが送られてくる */
				if (!(sio.ch[SIOCH_B].wr[5] & 2) && (value & 2)) {
					mouse_read(sio.ch + SIOCH_B);
				}
			}
			sio.ch[SIOCH_B].wr[sio.ch[SIOCH_B].num] = value;
			if (sio.ch[SIOCH_B].num) {
				sio.ch[SIOCH_B].num = 0;
			}
			else {
				sio.ch[SIOCH_B].num = value & 7;
			}
			break;
	}
}

REG8 IOINPCALL sio_i(UINT port) {

	REG8	ret;

	ret = 0;
	switch(port) {
		case 0x1f90:				/* CH-A データ */
			if (sio.ch[SIOCH_A].RxD.cnt) {
				return(fifo_r(&sio.ch[SIOCH_A].RxD));
			}
			break;

		case 0x1f91:				/* CH-A コントロール */
			if (sio.ch[SIOCH_A].num == 0) {
				if (sio.ch[SIOCH_A].RxD.cnt != 0) {
					ret |= 1;
				}
				if (sio.ch[SIOCH_A].TxD.cnt == 0) {
					ret |= 4;
				}
			}
			break;

		case 0x1f92:				/* CH-B データ   (Mouse) */
			if (sio.ch[SIOCH_B].RxD.cnt) {
				return(fifo_r(&sio.ch[SIOCH_B].RxD));
			}
			break;

		case 0x1f93:				/* CH-B コントロール (Mouse) */
			if (sio.ch[SIOCH_B].num == 0) {		/* ?? */
				if (sio.ch[SIOCH_B].RxD.cnt != 0) {
					ret |= 1;
				}
				if (sio.ch[SIOCH_B].TxD.cnt == 0) {
					ret |= 4;
				}
			}
			break;
	}
	return(ret);
}


/* reset */

void sio_reset(void) {

	ZeroMemory(&sio, sizeof(sio));
}


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