File:  [RetroPC.NET] / xmil / nds / patch / subcpu.c
Revision 1.1: download - view: text, annotated - select for diffs
Tue Mar 24 22:52:52 2009 JST (16 years, 7 months ago) by yui
Branches: MAIN
CVS tags: HEAD
add nds-win32 simulation project

#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"


void neitem_scpu(UINT uId)
{
	BRESULT	bIntr;

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

BRESULT ieitem_scpu(UINT uId)
{
	UINT	uKey;
	REG8	cKeyData;

	if ((subcpu.s.cmdcnt) || (subcpu.s.datcnt))
	{
		keystat.req_int = 1;		/* 再送しる */
		subcpu_sendkey();
		return FALSE;
	}
	if (subcpu.s.vect == 0)			/* 割り込み不要だったら捨てる */
	{
		return FALSE;
	}
	uKey = keystat_getflag();
	cKeyData = (UINT8)(uKey >> 8);
	if (subcpu.s.keydata != cKeyData)
	{
		subcpu.s.keydata = cKeyData;
		subcpu.s.keycount = 0;
		subcpu.s.keycountrep = 480;
	}
	else
	{
		if (cKeyData == 0)
		{
			return FALSE;
		}
		uKey = uKey & (~0x20);			// rep
		subcpu.s.keycountrep = 48;		// 0.1sec
	}
	subcpu.s.work[1] = (UINT8)uKey;
	subcpu.s.work[0] = cKeyData;
	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)uId;
	return TRUE;
}


// ----

void subcpusetbuffer(SUBCPU *s, REG8 cMode)
{
	UINT32	uKey;

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

		case 0xe6:
			uKey = keystat_getflag();
			s->s.work[1] = (UINT8)(uKey >> 0);
			s->s.work[0] = (UINT8)(uKey >> 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 subcpusendctrl(SUBCPU *s)
{
	switch(s->s.mode)
	{
		case 0xe9:
			cmt_ctrl(s->s.work[0]);
			break;

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

		case 0xee:
			calendar_settime(s->s.work);
			break;
	}
}


typedef struct
{
	UINT8	cFlag;
	UINT8	cPos;
} SCPUTBL;

enum
{
	SCPU_CNTMASK	= 0x07,

	SCPU_OUTPUT		= 0x08,
	SCPU_INPUT		= 0x00,
	SCPU_IODIR		= 0x08
};

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

#if !defined(USE_ARMROUTINE)
void IOOUTCALL subcpu_o(UINT uPort, REG8 cValue)
{
	UINT		uTblPos;
const SCPUTBL	*p;

	if (iocore.s.ppib & 0x40)
	{
		return;
	}
	if (!subcpu.s.cmdcnt)
	{
		subcpu.s.mode = (UINT8)cValue;
		uTblPos = cValue - 0xd0;
		if (uTblPos >= 0x20)
		{
			uTblPos = 0x10;
		}
		p = s_scputbl + uTblPos;
		iocore.s.ppib = (UINT8)(iocore.s.ppib & (~0x60));
		if ((p->cFlag & SCPU_IODIR) == SCPU_INPUT)
		{
			subcpu.s.cmdptr = offsetof(SUBCPU, s.zero);
			subcpu.s.datptr = p->cPos;
		//	subcpu.s.cmdcnt = 0;
			subcpu.s.datcnt = p->cFlag & SCPU_CNTMASK;
			iocore.s.ppib |= 0x40;
			subcpusetbuffer(&subcpu, cValue);
		}
		else
		{
			subcpu.s.cmdptr = p->cPos;
			subcpu.s.datptr = offsetof(SUBCPU, s.zero);
			subcpu.s.cmdcnt = p->cFlag & SCPU_CNTMASK;
			subcpu.s.datcnt = 0;
			iocore.s.ppib |= 0x20;
		}
	}
	else
	{
		subcpu.s.cmdcnt--;
		((UINT8 *)(&subcpu))[subcpu.s.cmdptr + subcpu.s.cmdcnt] = cValue;
		if (subcpu.s.cmdcnt == 0)
		{
			subcpusendctrl(&subcpu);
		}
	}
	(void)uPort;
}

REG8 IOINPCALL subcpu_i(UINT uPort)
{
	if (subcpu.s.datcnt)
	{
		subcpu.s.datcnt--;
	}
	else								/* D-SIDE で通るように… */
	{
		subcpusetbuffer(&subcpu, subcpu.s.mode);
	}

	iocore.s.ppib = (UINT8)(iocore.s.ppib & (~0x60));
	if (subcpu.s.datcnt)
	{
		 iocore.s.ppib |= 0x40;
	}
	else
	{
		 iocore.s.ppib |= 0x20;
	}

	(void)uPort;
	return (((UINT8 *)(&subcpu))[subcpu.s.datptr + subcpu.s.datcnt]);
}
#endif	/* !defined(USE_ARMROUTINE) */


/* reset */

void subcpu_reset(void)
{
	ZeroMemory(&subcpu, sizeof(subcpu));

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

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

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>