#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
* cmd: 0, 1, 0, 0, 1, 0, 1, 0, 0, 3, 0, 3, 0
* dat: 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;
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) {
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;
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;
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);
}
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]);
}
/* reset */
void subcpu_reset(void) {
ZeroMemory(&subcpu, sizeof(subcpu));
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>