File:  [RetroPC.NET] / xmil / io / subcpu.c
Revision 1.9: download - view: text, annotated - select for diffs
Fri Feb 4 15:42:11 2005 JST (20 years, 8 months ago) by yui
Branches: MAIN
CVS tags: HEAD
RetroPC CVS restarting 2005/02/04 (T.Yui)

#include	"compiler.h"
#include	"timemng.h"
#include	"z80core.h"
#include	"pccore.h"
#include	"iocore.h"
#include	"nevent.h"
#include	"ievent.h"
#include	"keystat.h"
#include	"calendar.h"


// 							     e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef
//static const UINT8 cmdtbl[] = { 0, 1, 0, 0, 1, 0, 1, 0, 0, 3, 0, 3, 0};
//static const UINT8 dattbl[] = { 3, 0, 0, 2, 0, 1, 0, 1, 1, 0, 3, 0, 3};

typedef struct {
	UINT8	pos;
	UINT8	flag;
} SCPUTBL;

enum {
	SCPU_CNTMASK	= 0x07,
	SCPU_INPUT		= 0x08
};

static const SCPUTBL scputbl[0x20] = {
		{offsetof(SUBCPU, s.timer[0]),	6},					// d0: timer0 set
		{offsetof(SUBCPU, s.timer[1]),	6},					// d1: timer1 set
		{offsetof(SUBCPU, s.timer[2]),	6},					// d2: timer2 set
		{offsetof(SUBCPU, s.timer[3]),	6},					// d3: timer3 set
		{offsetof(SUBCPU, s.timer[4]),	6},					// d4: timer4 set
		{offsetof(SUBCPU, s.timer[5]),	6},					// d5: timer5 set
		{offsetof(SUBCPU, s.timer[6]),	6},					// d6: timer6 set
		{offsetof(SUBCPU, s.timer[7]),	6},					// d7: timer7 set
		{offsetof(SUBCPU, s.timer[0]),	6 + SCPU_INPUT},	// d8: timer0 get
		{offsetof(SUBCPU, s.timer[1]),	6 + SCPU_INPUT},	// d9: timer1 get
		{offsetof(SUBCPU, s.timer[2]),	6 + SCPU_INPUT},	// da: timer2 get
		{offsetof(SUBCPU, s.timer[3]),	6 + SCPU_INPUT},	// db: timer3 get
		{offsetof(SUBCPU, s.timer[4]),	6 + SCPU_INPUT},	// dc: timer4 get
		{offsetof(SUBCPU, s.timer[5]),	6 + SCPU_INPUT},	// dd: timer5 get
		{offsetof(SUBCPU, s.timer[6]),	6 + SCPU_INPUT},	// de: timer6 get
		{offsetof(SUBCPU, s.timer[7]),	6 + SCPU_INPUT},	// df: timer7 get
		{offsetof(SUBCPU, s.zero),		0},					// e0:
		{offsetof(SUBCPU, s.zero),		0},					// e1:
		{offsetof(SUBCPU, s.zero),		0},					// e2:
		{offsetof(SUBCPU, s.work),		3 + SCPU_INPUT},	// e3: game keys
		{offsetof(SUBCPU, s.vect),		1},					// e4: intr vector
		{offsetof(SUBCPU, s.zero),		0},					// e5:
		{offsetof(SUBCPU, s.work),		2 + SCPU_INPUT},	// e6: game keys
		{offsetof(SUBCPU, s.tvctrl),	1},					// e7: set TV ctrl
		{offsetof(SUBCPU, s.tvctrl),	1 + SCPU_INPUT},	// e8: get TV ctrl
		{offsetof(SUBCPU, s.work),		1},					// e9: cmt ctrl
		{offsetof(SUBCPU, s.work),		1 + SCPU_INPUT},	// ea: cmtctrlstat
		{offsetof(SUBCPU, s.work),		1 + SCPU_INPUT},	// eb: cmttypestat
		{offsetof(SUBCPU, s.work),		3},					// ec: date set
		{offsetof(SUBCPU, s.work),		3 + SCPU_INPUT},	// ed: date set
		{offsetof(SUBCPU, s.work),		3},					// ee: time set
		{offsetof(SUBCPU, s.work),		3 + SCPU_INPUT}};	// ef: time set


// ----

void neitem_scpu(UINT id) {

	BRESULT	intr;

	intr = FALSE;
	// こうすると同時押しが判定できないのでキーバッファを持つべし
	if (keystat.req_int) {
		keystat.req_int = 0;
		intr = TRUE;
	}
	else if (subcpu.s.keydata) {
		subcpu.s.keycount++;
		if (subcpu.s.keycount >= subcpu.s.keycountrep) {
			subcpu.s.keycount = 0;
			intr = TRUE;
		}
		nevent_set(NEVENT_SUBCPU, subcpu.e.intrclock,
											neitem_scpu, NEVENT_RELATIVE);
	}
	if (intr) {
		ievent_set(IEVENT_SUBCPU);
	}
}

BRESULT ieitem_scpu(UINT id) {

	UINT	key;
	UINT8	keydata;

	if ((subcpu.s.cmdcnt) || (subcpu.s.datcnt)) {
		keystat.req_int = 1;			// 再送しる
		subcpu_sendkey();
		return(FALSE);
	}
	if (subcpu.s.vect == 0) {			// 割り込み不要だったら捨てる
		return(FALSE);
	}
	key = keystat_getflag();
	keydata = (UINT8)(key >> 8);
	if (subcpu.s.keydata != keydata) {
		subcpu.s.keydata = keydata;
		subcpu.s.keycount = 0;
		subcpu.s.keycountrep = 480;
	}
	else {
		if (keydata == 0) {
			return(FALSE);
		}
		key = key & (~0x20);			// rep
		subcpu.s.keycountrep = 48;		// 0.1sec
	}
	subcpu.s.work[1] = (UINT8)key;
	subcpu.s.work[0] = keydata;
	subcpu.s.cmdptr = offsetof(SUBCPU, s.zero);
	subcpu.s.datptr = offsetof(SUBCPU, s.work);
	subcpu.s.mode = 0xe6;
	subcpu.s.cmdcnt = 0;
	subcpu.s.datcnt = 2;

//	subcpu.s.OBF = 0;
//	subcpu.s.IBF = 1;
	iocore.s.ppib = (UINT8)((iocore.s.ppib & (~0x20)) | 0x40);

	Z80_INTERRUPT(subcpu.s.vect);
	(void)id;
	return(TRUE);
}


// ----

static void subcpusetbuffer(SUBCPU *s) {

	UINT32	key;

	switch(s->s.mode) {
		case 0xe3:
			key = keystat_gete3();
			s->s.work[2] = (UINT8)(key >> 16);
			s->s.work[1] = (UINT8)(key >> 8);
			s->s.work[0] = (UINT8)(key >> 0);
			break;

		case 0xe6:
			key = keystat_getflag();
			s->s.work[1] = (UINT8)(key >> 0);
			s->s.work[0] = (UINT8)(key >> 8);
			break;

		case 0xea:
			s->s.work[0] = cmt_ctrl_stat();
			break;

		case 0xeb:
			s->s.work[0] = cmt_tape_stat();
			break;

		case 0xed:
			calendar_getdate(s->s.work);
			break;

		case 0xef:
			calendar_gettime(s->s.work);
			break;
	}
}

void IOOUTCALL subcpu_o(UINT port, REG8 value) {

	UINT		tblpos;
const SCPUTBL	*p;

	if (iocore.s.ppib & 0x40) {		// subcpu.IBF
		return;
	}
	if (!subcpu.s.cmdcnt) {
		subcpu.s.mode = (UINT8)value;
		tblpos = value - 0xd0;
		if (tblpos >= 0x20) {
			tblpos = 0x10;
		}
		p = scputbl + tblpos;
		iocore.s.ppib = (UINT8)(iocore.s.ppib & (~0x60));
		if (p->flag & SCPU_INPUT) {
			subcpu.s.cmdptr = offsetof(SUBCPU, s.zero);
			subcpu.s.datptr = p->pos;
		//	subcpu.s.cmdcnt = 0;
			subcpu.s.datcnt = p->flag & SCPU_CNTMASK;
		//	subcpu.s.OBF = (UINT8)(subcpu.s.datacnt?0:1);	// = 0
		//	subcpu.s.IBF = (UINT8)(subcpu.s.datacnt?1:0);	// = 1
			iocore.s.ppib |= 0x40;
			subcpusetbuffer(&subcpu);
		}
		else {
			subcpu.s.cmdptr = p->pos;
			subcpu.s.datptr = offsetof(SUBCPU, s.zero);
			subcpu.s.cmdcnt = p->flag & SCPU_CNTMASK;
			subcpu.s.datcnt = 0;
		//	subcpu.s.OBF = (UINT8)(subcpu.s.datacnt?0:1);	// = 1
		//	subcpu.s.IBF = (UINT8)(subcpu.s.datacnt?1:0);	// = 0
			iocore.s.ppib |= 0x20;
		}
	}
	else {
		subcpu.s.cmdcnt--;
		((UINT8 *)(&subcpu))[subcpu.s.cmdptr + subcpu.s.cmdcnt] = value;
		if (subcpu.s.cmdcnt == 0) {
			switch(subcpu.s.mode) {
				case 0xe9:
					cmt_ctrl(subcpu.s.work[0]);
					break;

				case 0xec:
					calendar_setdate(subcpu.s.work);
					break;

				case 0xee:
					calendar_settime(subcpu.s.work);
					break;
			}
		}
	}
	(void)port;
}

REG8 IOINPCALL subcpu_i(UINT port) {

	if (subcpu.s.datcnt) {
		subcpu.s.datcnt--;
	}
	else {									// D-SIDE で通るように…
		subcpusetbuffer(&subcpu);
	}

//	subcpu.s.OBF = (UINT8)(subcpu.s.datacnt?0:1);
//	subcpu.s.IBF = (UINT8)(subcpu.s.datacnt?1:0);
	iocore.s.ppib = (UINT8)(iocore.s.ppib & (~0x60));
	if (subcpu.s.datcnt) {
		 iocore.s.ppib |= 0x40;
	}
	else {
		 iocore.s.ppib |= 0x20;
	}

	(void)port;
	return(((UINT8 *)(&subcpu))[subcpu.s.datptr + subcpu.s.datcnt]);
}


// ----

void subcpu_reset(void) {

	ZeroMemory(&subcpu, sizeof(subcpu));

//	subcpu.s.OBF = 1;
	iocore.s.ppib = (UINT8)(iocore.s.ppib | 0x20);

#if defined(FIX_Z80A)
	subcpu.e.intrclock = 2000000 * 2 / 480;
#else
	subcpu.e.intrclock = pccore.realclock / 480;
#endif
}

void subcpu_sendkey(void) {

	if (!nevent_iswork(NEVENT_SUBCPU)) {
		nevent_set(NEVENT_SUBCPU, subcpu.e.intrclock,
											neitem_scpu, NEVENT_ABSOLUTE);
	}
}


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