mirror of
https://github.com/libretro/xmil-libretro.git
synced 2024-11-23 16:19:43 +00:00
4ec8db659d
refs #90 svn merge -r 175:176 https://amethyst.yui.ne.jp/svn-dev/x1/xmil/branches/yui/WORK_01 svn merge -r 218:219 https://amethyst.yui.ne.jp/svn-dev/x1/xmil/branches/yui/WORK_01
852 lines
16 KiB
C
852 lines
16 KiB
C
#include "compiler.h"
|
||
#include "z80core.h"
|
||
#include "pccore.h"
|
||
#include "iocore.h"
|
||
#include "nevent.h"
|
||
#include "fddfile.h"
|
||
#include "fdd_mtr.h"
|
||
|
||
enum {
|
||
FDCCTYPE_CMD1 = 0x01,
|
||
FDCCTYPE_CMD2 = 0x02,
|
||
FDCCTYPE_CMD3 = 0x04,
|
||
FDCCTYPE_CMD4 = 0x08,
|
||
|
||
FDCCTYPE_RO = 0x10,
|
||
FDCCTYPE_DATA = 0x80
|
||
};
|
||
|
||
|
||
static const UINT8 fdctype[] = {
|
||
FDCCTYPE_CMD1,
|
||
FDCCTYPE_CMD1,
|
||
FDCCTYPE_CMD1,
|
||
FDCCTYPE_CMD1,
|
||
FDCCTYPE_CMD1,
|
||
FDCCTYPE_CMD1,
|
||
FDCCTYPE_CMD1,
|
||
FDCCTYPE_CMD1,
|
||
FDCCTYPE_CMD2 + FDCCTYPE_RO,
|
||
FDCCTYPE_CMD2 + FDCCTYPE_RO,
|
||
FDCCTYPE_CMD2,
|
||
FDCCTYPE_CMD2,
|
||
FDCCTYPE_CMD3 + FDCCTYPE_RO,
|
||
FDCCTYPE_CMD4,
|
||
FDCCTYPE_CMD3 + FDCCTYPE_RO,
|
||
FDCCTYPE_CMD3};
|
||
|
||
|
||
/* write track */
|
||
|
||
#if !defined(CONST_DISKIMAGE)
|
||
enum {
|
||
TAO_MODE_GAP = 0x4e,
|
||
TAO_MODE_SYNC = 0x00,
|
||
TAO_MODE_AM = 0xf5,
|
||
TAO_MODE_IM = 0xf6,
|
||
TAO_MODE_ID = 0xfe,
|
||
TAO_MODE_DATA = 0xfb,
|
||
TAO_ENDOFDATA = 0xf7,
|
||
|
||
TAO_CMD_GAP = 0x4e,
|
||
TAO_CMD_SYNC = 0x00,
|
||
TAO_CMD_IM_IN = 0xf6,
|
||
TAO_CMD_IM = 0xfc,
|
||
TAO_CMD_AM_IN = 0xf5,
|
||
TAO_CMD_IAM = 0xfe,
|
||
TAO_CMD_DAM = 0xfb,
|
||
TAO_CMD_DDAM = 0xf8,
|
||
TAO_CMD_CRC = 0xf7
|
||
};
|
||
|
||
|
||
static REG8 wrtrkstart(FDC *f) {
|
||
|
||
FDDFILE fdd;
|
||
|
||
fdd = fddfile + f->s.drv;
|
||
if ((fdd->type == DISKTYPE_NOTREADY) || (fdd->protect)) {
|
||
return(0);
|
||
}
|
||
f->s.bufdir = FDCDIR_TAO;
|
||
f->s.bufpos = 0;
|
||
f->s.bufmedia = f->s.media;
|
||
f->s.bufunit = f->s.drv;
|
||
f->s.buftrack = (f->s.c << 1) + f->s.h;
|
||
|
||
f->s.wt_mode = TAO_ENDOFDATA;
|
||
f->s.wt_sectors = 0;
|
||
f->s.wt_ptr = 0;
|
||
f->s.wt_datpos = 0;
|
||
f->s.wt_datsize = 0;
|
||
ZeroMemory(f->s.buffer, sizeof(f->s.buffer));
|
||
|
||
return(0);
|
||
}
|
||
|
||
static void wrtrkdata(FDC *f, REG8 data) {
|
||
|
||
TAOSEC *t;
|
||
REG8 n;
|
||
UINT datsize;
|
||
FDDFILE fdd;
|
||
|
||
switch(f->s.wt_mode) {
|
||
case TAO_ENDOFDATA:
|
||
if (data == TAO_MODE_GAP) {
|
||
f->s.wt_mode = TAO_MODE_GAP;
|
||
f->s.wt_ptr = 0;
|
||
}
|
||
break;
|
||
|
||
case TAO_MODE_GAP:
|
||
if (data == TAO_MODE_GAP) {
|
||
f->s.wt_ptr++;
|
||
if (f->s.wt_ptr >= 256) {
|
||
goto wtd_done;
|
||
}
|
||
}
|
||
else if (data == TAO_CMD_SYNC) {
|
||
f->s.wt_mode = TAO_MODE_SYNC;
|
||
}
|
||
else if (data == 0xf4) {
|
||
goto wtd_done;
|
||
}
|
||
else {
|
||
goto wtd_err;
|
||
}
|
||
break;
|
||
|
||
case TAO_MODE_SYNC:
|
||
if (data == TAO_CMD_AM_IN) {
|
||
f->s.wt_mode = TAO_MODE_AM;
|
||
}
|
||
else if (data == TAO_CMD_IM_IN) {
|
||
f->s.wt_mode = TAO_MODE_IM;
|
||
}
|
||
else if (data) {
|
||
goto wtd_err;
|
||
}
|
||
break;
|
||
|
||
case TAO_MODE_IM:
|
||
if (data == TAO_CMD_IM) {
|
||
f->s.wt_mode = TAO_ENDOFDATA;
|
||
}
|
||
else if (data != TAO_CMD_IM_IN) {
|
||
goto wtd_err;
|
||
}
|
||
break;
|
||
|
||
case TAO_MODE_AM:
|
||
if (data == TAO_CMD_IAM) {
|
||
f->s.wt_mode = TAO_MODE_ID;
|
||
f->s.wt_ptr = 0;
|
||
}
|
||
else if ((data == TAO_CMD_DAM) || (data == TAO_CMD_DDAM)) {
|
||
f->s.wt_mode = TAO_MODE_DATA;
|
||
f->s.wt_ptr = 0;
|
||
if (f->s.wt_datsize) {
|
||
t = (TAOSEC *)(f->s.buffer + f->s.wt_datpos);
|
||
t[-1].flag = (UINT8)(data == TAO_CMD_DDAM);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case TAO_MODE_ID:
|
||
if ((f->s.wt_ptr == 0) && (data == TAO_CMD_IAM)) {
|
||
break;
|
||
}
|
||
else if (f->s.wt_ptr < 4) {
|
||
f->s.buffer[f->s.bufpos + f->s.wt_ptr] = data;
|
||
f->s.wt_ptr++;
|
||
}
|
||
else if (data == TAO_CMD_CRC) {
|
||
f->s.wt_mode = TAO_ENDOFDATA;
|
||
n = f->s.buffer[f->s.bufpos + 3];
|
||
if (n > 3) {
|
||
n = 3;
|
||
}
|
||
datsize = 128 << n;
|
||
if ((f->s.bufpos + (sizeof(TAOSEC) * 2) + datsize)
|
||
<= sizeof(f->s.buffer)) {
|
||
t = (TAOSEC *)(f->s.buffer + f->s.bufpos);
|
||
STOREINTELWORD(t->size, datsize);
|
||
f->s.wt_datpos = f->s.bufpos + sizeof(TAOSEC);
|
||
f->s.wt_datsize = datsize;
|
||
f->s.bufpos = f->s.wt_datpos + datsize;
|
||
f->s.wt_sectors += 1;
|
||
}
|
||
else {
|
||
goto wtd_err;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case TAO_MODE_DATA: /* DATA WRITE */
|
||
if ((f->s.wt_ptr == 0) &&
|
||
((data == TAO_CMD_DAM) || (data == TAO_CMD_DDAM))) {
|
||
break;
|
||
}
|
||
else if (f->s.wt_ptr < f->s.wt_datsize) {
|
||
f->s.buffer[f->s.wt_datpos + f->s.wt_ptr] = data;
|
||
f->s.wt_ptr++;
|
||
}
|
||
else if (data == TAO_CMD_CRC) {
|
||
f->s.wt_mode = TAO_ENDOFDATA;
|
||
f->s.wt_datsize = 0;
|
||
}
|
||
break;
|
||
}
|
||
return;
|
||
|
||
wtd_done:
|
||
fdd = fddfile + f->s.bufunit;
|
||
TRACEOUT(("write! %d %dbytes", f->s.wt_sectors, f->s.bufpos));
|
||
f->s.stat = (*fdd->wrtrk)(fdd, f->s.bufmedia, f->s.buftrack,
|
||
f->s.wt_sectors, f->s.buffer, f->s.bufpos);
|
||
f->s.bufdir = FDCDIR_NONE;
|
||
dmac_sendready(FALSE);
|
||
return;
|
||
|
||
wtd_err:
|
||
f->s.stat = FDDSTAT_LOSTDATA;
|
||
f->s.bufdir = FDCDIR_NONE;
|
||
dmac_sendready(FALSE);
|
||
}
|
||
#endif
|
||
|
||
|
||
/* ---- */
|
||
|
||
void neitem_fdcbusy(NEVENTID id) {
|
||
|
||
fdc.s.busy = 0;
|
||
if (fdc.s.bufdir) {
|
||
/* TRACEOUT(("dma ready!")); */
|
||
dmac_sendready(TRUE);
|
||
}
|
||
(void)id;
|
||
}
|
||
|
||
static void setbusy(FDC *f, SINT32 clock) {
|
||
|
||
if (clock > 0) {
|
||
f->s.busy = FDDSTAT_BUSY;
|
||
nevent_set(NEVENT_FDC, clock, neitem_fdcbusy, NEVENT_ABSOLUTE);
|
||
}
|
||
else {
|
||
f->s.busy = 0;
|
||
nevent_reset(NEVENT_FDC);
|
||
}
|
||
}
|
||
|
||
#if defined(SUPPORT_MOTORRISEUP)
|
||
static void setmotor(FDC *f, REG8 drvcmd) {
|
||
|
||
UINT drv;
|
||
SINT32 clock;
|
||
|
||
drv = drvcmd & 3;
|
||
clock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||
if (drvcmd & 0x80) {
|
||
if (f->s.motorevent[drv] == FDCMOTOR_STOP) {
|
||
f->s.motorevent[drv] = FDCMOTOR_STARTING;
|
||
f->s.motorclock[drv] = clock;
|
||
}
|
||
else if (f->s.motorevent[drv] == FDCMOTOR_STOPING) {
|
||
f->s.motorevent[drv] = FDCMOTOR_READY;
|
||
}
|
||
}
|
||
else {
|
||
if ((f->s.motorevent[drv] == FDCMOTOR_STARTING) ||
|
||
(f->s.motorevent[drv] == FDCMOTOR_READY)) {
|
||
f->s.motorevent[drv] = FDCMOTOR_STOPING;
|
||
f->s.motorclock[drv] = clock;
|
||
}
|
||
}
|
||
}
|
||
|
||
void fdc_callback(void) {
|
||
|
||
SINT32 clock;
|
||
UINT i;
|
||
|
||
clock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||
for (i=0; i<4; i++) {
|
||
if (fdc.s.motorevent[i] == FDCMOTOR_STARTING) {
|
||
if ((clock - fdc.s.motorclock[i]) >= (SINT32)pccore.realclock) {
|
||
fdc.s.motorevent[i] = FDCMOTOR_READY;
|
||
}
|
||
}
|
||
else if (fdc.s.motorevent[i] == FDCMOTOR_STOPING) {
|
||
if ((clock - fdc.s.motorclock[i]) >= (SINT32)pccore.realclock) {
|
||
fdc.s.motorevent[i] = FDCMOTOR_STOP;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
static SINT32 motorwait(const FDC *f) {
|
||
|
||
SINT32 curclock;
|
||
SINT32 nextclock;
|
||
|
||
if (f->s.motorevent[f->s.drv] == FDCMOTOR_STARTING) {
|
||
curclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
|
||
curclock -= f->s.motorclock[f->s.drv];
|
||
if (curclock < (SINT32)pccore.realclock) {
|
||
nextclock = pccore.realclock - curclock;
|
||
/* TRACEOUT(("motor starting busy %d", nextclock)); */
|
||
return(nextclock);
|
||
}
|
||
}
|
||
return(0);
|
||
}
|
||
#endif
|
||
|
||
|
||
static REG8 getstat(FDC *f) {
|
||
|
||
FDDFILE fdd;
|
||
REG8 ctype;
|
||
REG8 ret;
|
||
|
||
fdd = fddfile + f->s.drv;
|
||
ctype = f->s.ctype;
|
||
if (fdd->type == DISKTYPE_NOTREADY) {
|
||
ret = FDDSTAT_NOTREADY;
|
||
}
|
||
else {
|
||
ret = f->s.stat;
|
||
}
|
||
if ((ctype & FDCCTYPE_CMD1) && (f->s.c == 0)) {
|
||
ret |= FDDSTAT_TRACK00;
|
||
}
|
||
if (!(ctype & FDCCTYPE_RO)) {
|
||
if (fdd->protect) {
|
||
ret |= FDDSTAT_WRITEP;
|
||
}
|
||
}
|
||
if (ctype & (FDCCTYPE_CMD1 | FDCCTYPE_CMD4)) {
|
||
f->s.hole++;
|
||
if (f->s.hole < 8) {
|
||
ret |= FDDSTAT_INDEX;
|
||
}
|
||
}
|
||
else if (!(ret & 0xf0)) {
|
||
if (fddmtr_isbusy()) {
|
||
ret |= FDDSTAT_BUSY;
|
||
}
|
||
if (f->s.bufdir) {
|
||
ret |= FDDSTAT_DRQ | FDDSTAT_BUSY;
|
||
}
|
||
}
|
||
return(ret);
|
||
}
|
||
|
||
static void seekcmd(FDC *f) {
|
||
|
||
FDDFILE fdd;
|
||
UINT track;
|
||
|
||
f->s.crcnum = 0;
|
||
f->s.creg = f->s.c;
|
||
fdd = fddfile + f->s.drv;
|
||
track = (f->s.c << 1) + f->s.h;
|
||
f->s.stat = fdd->seek(fdd, f->s.media, track) | FDDSTAT_HEADENG;
|
||
fddmtr_motormove();
|
||
}
|
||
|
||
static REG8 type2cmd(FDC *f, REG8 sc) {
|
||
|
||
REG8 dir;
|
||
UINT track;
|
||
UINT8 *p;
|
||
FDDFILE fdd;
|
||
UINT size;
|
||
REG8 stat;
|
||
SINT32 clock;
|
||
#if defined(SUPPORT_DISKEXT)
|
||
SINT32 curclock;
|
||
SINT32 nextclock;
|
||
UINT32 secinfo;
|
||
#endif
|
||
|
||
track = (f->s.c << 1) + f->s.h;
|
||
fdd = fddfile + f->s.drv;
|
||
#if !defined(CONST_DISKIMAGE)
|
||
if (!(f->s.cmd & 0x20)) {
|
||
p = f->s.buffer;
|
||
dir = FDCDIR_IN;
|
||
}
|
||
else {
|
||
p = NULL;
|
||
dir = FDCDIR_OUT;
|
||
}
|
||
size = sizeof(f->s.buffer);
|
||
stat = fdd->read(fdd, f->s.media, track, sc, p, &size);
|
||
if (stat & FDDSTAT_RECNFND) {
|
||
size = 0;
|
||
dir = FDCDIR_NONE;
|
||
}
|
||
else if (dir == FDCDIR_OUT) {
|
||
if (size) {
|
||
ZeroMemory(f->s.buffer, size);
|
||
}
|
||
stat = stat & (~FDDSTAT_RECTYPE);
|
||
}
|
||
#else
|
||
size = 0;
|
||
dir = FDCDIR_NONE;
|
||
if (!(f->s.cmd & 0x20)) {
|
||
stat = fdd->readp(fdd, f->s.media, track, sc, (void **)&p, &size);
|
||
if (!(stat & FDDSTAT_RECNFND)) {
|
||
f->e.buffer = p;
|
||
dir = FDCDIR_IN;
|
||
}
|
||
}
|
||
else {
|
||
stat = FDDSTAT_RECNFND | FDDSTAT_WRITEFAULT;
|
||
}
|
||
#endif
|
||
f->s.bufmedia = f->s.media;
|
||
f->s.bufunit = f->s.drv;
|
||
f->s.buftrack = track;
|
||
f->s.bufsc = sc;
|
||
f->s.bufwrite = FALSE;
|
||
f->s.bufdir = dir;
|
||
f->s.bufmark = f->s.cmd & 1;
|
||
f->s.bufpos = 0;
|
||
f->s.bufsize = size;
|
||
f->s.curtime = 0;
|
||
|
||
clock = 0;
|
||
#if defined(SUPPORT_MOTORRISEUP)
|
||
clock += motorwait(f);
|
||
#endif
|
||
#if defined(SUPPORT_DISKEXT)
|
||
secinfo = fdd->sec(fdd, f->s.media, track, sc);
|
||
if (secinfo) {
|
||
nextclock = LOW16(secinfo);
|
||
nextclock *= f->s.loopclock;
|
||
nextclock /= LOW16(secinfo >> 16);
|
||
curclock = nevent_getwork(NEVENT_RTC);
|
||
nextclock -= curclock;
|
||
if (nextclock < 0) {
|
||
nextclock += f->s.loopclock;
|
||
}
|
||
/* TRACEOUT(("wait clock -> %d [%d/%d]", nextclock,
|
||
LOW16(secinfo), LOW16(secinfo >> 16))); */
|
||
clock += nextclock;
|
||
}
|
||
#endif
|
||
setbusy(f, max(clock, 500));
|
||
return(stat);
|
||
}
|
||
|
||
static REG8 type2flash(FDC *f) {
|
||
|
||
#if !defined(CONST_DISKIMAGE)
|
||
FDDFILE fdd;
|
||
|
||
f->s.bufwrite = FALSE;
|
||
fdd = fddfile + f->s.bufunit;
|
||
if (fdd->protect) {
|
||
return(FDDSTAT_WRITEFAULT);
|
||
}
|
||
return(fdd->write(fdd, f->s.bufmedia, f->s.buftrack,
|
||
f->s.bufsc, f->s.buffer, f->s.bufpos));
|
||
#else
|
||
(void)f;
|
||
return(FDDSTAT_RECNFND | FDDSTAT_WRITEFAULT);
|
||
#endif
|
||
}
|
||
|
||
static REG8 crccmd(FDC *f) {
|
||
|
||
UINT8 *crcbuf;
|
||
UINT track;
|
||
FDDFILE fdd;
|
||
REG8 stat;
|
||
|
||
#if !defined(CONST_DISKIMAGE)
|
||
crcbuf = f->s.buffer;
|
||
#else
|
||
crcbuf = f->s.crcbuf;
|
||
f->e.buffer = crcbuf;
|
||
#endif
|
||
|
||
track = (f->s.c << 1) + f->s.h;
|
||
fdd = fddfile + f->s.drv;
|
||
/* TRACEOUT(("fdd->crc %d %d %d", f->s.drv, track, f->s.crcnum)); */
|
||
stat = fdd->crc(fdd, f->s.media, track, f->s.crcnum, crcbuf);
|
||
if (stat & FDDSTAT_RECNFND) {
|
||
f->s.crcnum = 0;
|
||
stat = fdd->crc(fdd, f->s.media, track, 0, crcbuf);
|
||
}
|
||
if (!(stat & FDDSTAT_RECNFND)) {
|
||
f->s.bufdir = FDCDIR_IN;
|
||
f->s.bufsize = 6;
|
||
f->s.rreg = crcbuf[0];
|
||
f->s.crcnum++;
|
||
}
|
||
else {
|
||
f->s.bufdir = FDCDIR_NONE;
|
||
f->s.bufsize = 0;
|
||
}
|
||
f->s.bufwrite = FALSE;
|
||
f->s.curtime = 0;
|
||
return(stat);
|
||
}
|
||
|
||
static void fdcenddata(FDC *f) {
|
||
|
||
BOOL r;
|
||
REG8 stat;
|
||
|
||
r = FALSE;
|
||
if (f->s.ctype & FDCCTYPE_CMD2) {
|
||
stat = 0;
|
||
if (f->s.cmd & 0x10) {
|
||
r = TRUE;
|
||
}
|
||
if ((f->s.cmd & 0x20) && (f->s.bufwrite)) {
|
||
stat = type2flash(f);
|
||
if (stat & (FDDSTAT_RECNFND | FDDSTAT_WRITEFAULT)) {
|
||
r = FALSE;
|
||
}
|
||
f->s.stat = stat;
|
||
}
|
||
}
|
||
f->s.bufdir = FDCDIR_NONE;
|
||
dmac_sendready(FALSE);
|
||
if (r) {
|
||
f->s.rreg = f->s.r + 1;
|
||
stat = type2cmd(f, f->s.rreg);
|
||
if (!(stat & FDDSTAT_RECNFND)) {
|
||
f->s.r = f->s.r + 1;
|
||
f->s.stat = stat;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/* IO-Sub */
|
||
|
||
static void IOOUTCALL fdc_o0ff8(FDC *f, REG8 value) {
|
||
|
||
REG8 cmd;
|
||
|
||
/* <20>R<EFBFBD>}<7D><><EFBFBD>h */
|
||
if (f->s.bufwrite) {
|
||
f->s.stat = type2flash(f);
|
||
}
|
||
if (f->s.bufdir != FDCDIR_NONE) {
|
||
f->s.bufdir = FDCDIR_NONE;
|
||
dmac_sendready(FALSE);
|
||
}
|
||
|
||
f->s.cmd = value;
|
||
cmd = (REG8)(value >> 4);
|
||
f->s.ctype = fdctype[cmd];
|
||
/* TRACEOUT(("fdc cmd: %.2x", value)); */
|
||
/* <20><><EFBFBD>X<EFBFBD>g<EFBFBD>A<EFBFBD>R<EFBFBD>}<7D><><EFBFBD>h<EFBFBD>ɂ<EFBFBD><C982><EFBFBD><EFBFBD><EFBFBD>
|
||
* <20>@<40>}<7D><><EFBFBD>I<EFBFBD><49> <20>R<EFBFBD>}<7D><><EFBFBD>h<EFBFBD><68><EFBFBD>s<EFBFBD><73><EFBFBD><EFBFBD>busy<73><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
* <20>@<40>t<EFBFBD>Ƀ\<5C>[<5B>T<EFBFBD><54><EFBFBD>A<EFBFBD><41><EFBFBD>Ƃ<EFBFBD><C682><EFBFBD> busy<73><79><EFBFBD>ƃG<C683><47><EFBFBD>[<5B>ɂȂ<C982><C882>c
|
||
* <20><><EFBFBD><EFBFBD><EFBFBD>͉<EFBFBD><CD89>H
|
||
*/
|
||
setbusy(f, 20);
|
||
switch(cmd) {
|
||
case 0x00: /* <20><><EFBFBD>X<EFBFBD>g<EFBFBD>A */
|
||
f->s.motor = 0x80; /* <20><><EFBFBD>[<5B>^<5E>[On? */
|
||
f->s.c = 0;
|
||
f->s.step = 1;
|
||
f->s.r = 0; /* <20>f<EFBFBD>[<5B>j<EFBFBD><6A><EFBFBD>[<5B><><EFBFBD>h */
|
||
seekcmd(f);
|
||
f->s.rreg = 0;
|
||
break;
|
||
|
||
case 0x01: /* <20>V<EFBFBD>[<5B>N */
|
||
f->s.motor = 0x80; /* <20><><EFBFBD>[<5B>^<5E>[On */
|
||
f->s.step = (SINT8)((f->s.c<=f->s.data)?1:-1);
|
||
f->s.c = f->s.data;
|
||
seekcmd(f);
|
||
break;
|
||
|
||
case 0x02: /* <20>X<EFBFBD>e<EFBFBD>b<EFBFBD>v */
|
||
case 0x03:
|
||
case 0x04: /* <20>X<EFBFBD>e<EFBFBD>b<EFBFBD>v<EFBFBD>C<EFBFBD><43> */
|
||
case 0x05:
|
||
case 0x06: /* <20>X<EFBFBD>e<EFBFBD>b<EFBFBD>v<EFBFBD>A<EFBFBD>E<EFBFBD>g */
|
||
case 0x07:
|
||
f->s.stat = FDDSTAT_HEADENG;
|
||
if (f->s.motor) {
|
||
if (cmd & 0x04) {
|
||
f->s.step = (cmd & 0x02)?-1:1;
|
||
}
|
||
f->s.c += f->s.step;
|
||
if (cmd & 1) {
|
||
seekcmd(f);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 0x08: /* <20><><EFBFBD>[<5B>h<EFBFBD>f<EFBFBD>[<5B>^ */
|
||
case 0x09:
|
||
case 0x0a: /* <20><><EFBFBD>C<EFBFBD>g<EFBFBD>f<EFBFBD>[<5B>^ */
|
||
case 0x0b:
|
||
f->s.stat = type2cmd(f, f->s.r);
|
||
break;
|
||
|
||
case 0xc: /* <20><><EFBFBD>[<5B>h<EFBFBD>A<EFBFBD>h<EFBFBD><68><EFBFBD>X */
|
||
setbusy(f, 200);
|
||
f->s.stat = crccmd(f);
|
||
break;
|
||
|
||
case 0x0d: /* <20>t<EFBFBD>H<EFBFBD>[<5B>X<EFBFBD>C<EFBFBD><43><EFBFBD>^<5E><><EFBFBD>v<EFBFBD>g */
|
||
setbusy(f, 0); /* <20>K<EFBFBD>v<EFBFBD>Ȃ<EFBFBD><C882>H */
|
||
/* f->s.skip = 0; */ /* 000330 */
|
||
f->s.stat = 0;
|
||
dmac_sendready(FALSE);
|
||
break;
|
||
|
||
case 0x0e: /* <20><><EFBFBD>[<5B>h<EFBFBD>g<EFBFBD><67><EFBFBD>b<EFBFBD>N */
|
||
#if !defined(CONST_DISKIMAGE)
|
||
setbusy(f, 200);
|
||
ZeroMemory(f->s.buffer, 0x1a00);
|
||
f->s.bufpos = 0;
|
||
f->s.bufsize = 0x1a00;
|
||
f->s.bufdir = FDCDIR_IN;
|
||
f->s.stat = 0;
|
||
#else
|
||
f->s.stat = FDDSTAT_SEEKERR;
|
||
#endif
|
||
break;
|
||
|
||
case 0x0f: /* <20><><EFBFBD>C<EFBFBD>g<EFBFBD>g<EFBFBD><67><EFBFBD>b<EFBFBD>N */
|
||
#if !defined(CONST_DISKIMAGE)
|
||
setbusy(f, 200);
|
||
f->s.stat = wrtrkstart(f);
|
||
#else
|
||
f->s.stat = FDDSTAT_LOSTDATA;
|
||
#endif
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void IOOUTCALL fdc_o0ff9(FDC *f, REG8 value) {
|
||
|
||
/* <20>g<EFBFBD><67><EFBFBD>b<EFBFBD>N */
|
||
f->s.creg = value;
|
||
}
|
||
|
||
static void IOOUTCALL fdc_o0ffa(FDC *f, REG8 value) {
|
||
|
||
/* <20>Z<EFBFBD>N<EFBFBD>^ */
|
||
fddmtr_waitsec(value);
|
||
f->s.r = value;
|
||
f->s.rreg = value;
|
||
}
|
||
|
||
static void IOOUTCALL fdc_o0ffb(FDC *f, REG8 value) {
|
||
|
||
/* <20>f<EFBFBD>[<5B>^ */
|
||
f->s.data = value;
|
||
#if !defined(CONST_DISKIMAGE)
|
||
if (f->s.motor) {
|
||
if (f->s.bufdir == FDCDIR_OUT) {
|
||
f->s.bufwrite = TRUE;
|
||
f->s.curtime = 0;
|
||
f->s.buffer[f->s.bufpos] = value;
|
||
if (!f->s.busy) {
|
||
f->s.bufpos++;
|
||
if (f->s.bufpos >= f->s.bufsize) {
|
||
fdcenddata(f);
|
||
}
|
||
}
|
||
}
|
||
else if (f->s.bufdir == FDCDIR_TAO) {
|
||
wrtrkdata(f, value);
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
static void IOOUTCALL fdc_o0ffc(FDC *f, REG8 value) {
|
||
|
||
/* <20>h<EFBFBD><68><EFBFBD>C<EFBFBD>u<EFBFBD>E<EFBFBD>T<EFBFBD>C<EFBFBD>h */
|
||
f->s.ctbl[f->s.drv] = f->s.c;
|
||
f->s.c = f->s.ctbl[value & 0x03];
|
||
f->s.motor = (UINT8)(value & 0x80);
|
||
f->s.drv = (UINT8)(value & 0x03);
|
||
f->s.h = (UINT8)((value >> 4) & 1);
|
||
f->s.cmd = 0; /* T&E SORCERIAN */
|
||
f->s.ctype = 0;
|
||
f->s.stat = 0;
|
||
|
||
fddmtr_drvset();
|
||
if (!f->s.motor) {
|
||
f->s.r = 0; /* SACOM TELENET */
|
||
f->s.rreg = 0;
|
||
}
|
||
#if defined(SUPPORT_MOTORRISEUP)
|
||
setmotor(f, value);
|
||
#endif
|
||
}
|
||
|
||
static void IOOUTCALL fdc_o0(FDC *f, REG8 value) {
|
||
}
|
||
|
||
static REG8 IOINPCALL fdc_i0ff8(FDC *f) {
|
||
|
||
REG8 ret;
|
||
|
||
/* <20>X<EFBFBD>e<EFBFBD>[<5B>^<5E>X */
|
||
ret = f->s.busy;
|
||
if (ret) {
|
||
return(ret);
|
||
}
|
||
#if 1
|
||
if (f->s.bufdir >= FDCDIR_IN) { /* YsII */
|
||
f->s.curtime++;
|
||
if (f->s.curtime >= 8) {
|
||
f->s.curtime = 0;
|
||
f->s.stat |= FDDSTAT_LOSTDATA;
|
||
f->s.bufpos++;
|
||
if (f->s.bufpos >= f->s.bufsize) {
|
||
fdcenddata(f);
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
ret = getstat(f);
|
||
#if 1
|
||
if (!(ret & 0x02)) {
|
||
dmac_sendready(FALSE);
|
||
}
|
||
#endif
|
||
/* TRACEOUT(("ret->%.2x", ret)); */
|
||
return(ret);
|
||
}
|
||
|
||
static REG8 IOINPCALL fdc_i0ff9(FDC *f) {
|
||
|
||
/* <20>g<EFBFBD><67><EFBFBD>b<EFBFBD>N */
|
||
TRACEOUT(("fdc inp %.4x,%.2x", 0x0ff9, f->s.creg));
|
||
return(f->s.creg);
|
||
}
|
||
|
||
static REG8 IOINPCALL fdc_i0ffa(FDC *f) {
|
||
|
||
/* <20>Z<EFBFBD>N<EFBFBD>^ */
|
||
TRACEOUT(("fdc inp %.4x,%.2x", 0x0ffa, f->s.rreg));
|
||
return(f->s.rreg);
|
||
}
|
||
|
||
static REG8 IOINPCALL fdc_i0ffb(FDC *f) {
|
||
|
||
/* <20>f<EFBFBD>[<5B>^ */
|
||
if (f->s.motor) {
|
||
if (f->s.bufdir == FDCDIR_IN) {
|
||
f->s.curtime = 0;
|
||
#if !defined(CONST_DISKIMAGE)
|
||
f->s.data = f->s.buffer[f->s.bufpos];
|
||
#else
|
||
f->s.data = f->e.buffer[f->s.bufpos];
|
||
#endif
|
||
if (!f->s.busy) {
|
||
f->s.bufpos++;
|
||
if (f->s.bufpos >= f->s.bufsize) {
|
||
fdcenddata(f);
|
||
}
|
||
}
|
||
/* TRACEOUT(("read %.2x - %.2x [%.4x]", f->s.bufpos, f->s.data, Z80_PC)); */
|
||
}
|
||
}
|
||
return(f->s.data);
|
||
}
|
||
|
||
static REG8 IOINPCALL fdc_i0ffc(FDC *f) {
|
||
|
||
/* FM */
|
||
return(0x00);
|
||
}
|
||
|
||
static REG8 IOINPCALL fdc_i0ffd(FDC *f) {
|
||
|
||
/* MFM */
|
||
return(0x00);
|
||
}
|
||
|
||
static REG8 IOINPCALL fdc_i0ffe(FDC *f) {
|
||
|
||
/* 1.6M */
|
||
f->s.media = DISKTYPE_2HD;
|
||
return(0xff);
|
||
}
|
||
|
||
static REG8 IOINPCALL fdc_i0fff(FDC *f) {
|
||
|
||
/* 500K/1M */
|
||
f->s.media = DISKTYPE_2D;
|
||
return(0xff);
|
||
}
|
||
|
||
|
||
/* IO */
|
||
|
||
typedef void (IOINPCALL * FNFDCOUT)(FDC *f, REG8 value);
|
||
static const FNFDCOUT s_fnOut[] =
|
||
{
|
||
fdc_o0ff8, fdc_o0ff9, fdc_o0ffa, fdc_o0ffb,
|
||
fdc_o0ffc, fdc_o0, fdc_o0, fdc_o0,
|
||
};
|
||
|
||
typedef REG8 (IOINPCALL * FNFDCINP)(FDC *f);
|
||
static const FNFDCINP s_fnInp[] =
|
||
{
|
||
fdc_i0ff8, fdc_i0ff9, fdc_i0ffa, fdc_i0ffb,
|
||
fdc_i0ffc, fdc_i0ffd, fdc_i0ffe, fdc_i0fff,
|
||
};
|
||
|
||
void IOINPCALL fdc_o(UINT port, REG8 value)
|
||
{
|
||
if ((port & (~7)) != 0x0ff8)
|
||
{
|
||
return;
|
||
}
|
||
|
||
/* TRACEOUT(("fdc out %.4x,%.2x", port, value)); */
|
||
(s_fnOut[port & 7])(&fdc, value);
|
||
}
|
||
|
||
REG8 IOINPCALL fdc_i(UINT uPort)
|
||
{
|
||
if ((uPort & (~7)) != 0x0ff8)
|
||
{
|
||
return 0xff;
|
||
}
|
||
|
||
/* TRACEOUT(("fdc inp %.4x", port)); */
|
||
return (s_fnInp[uPort & 7])(&fdc);
|
||
}
|
||
|
||
|
||
/* reset */
|
||
|
||
void fdc_reset(void) {
|
||
|
||
fddmtr_initialize();
|
||
ZeroMemory(&fdc, sizeof(fdc));
|
||
fdc.s.step = 1;
|
||
fdc.s.equip = xmilcfg.fddequip;
|
||
#if defined(FIX_Z80A)
|
||
fdc.s.loopclock = 2000000 * 2 / 5;
|
||
#else
|
||
fdc.s.loopclock = pccore.realclock / 5;
|
||
#endif
|
||
}
|
||
|