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