File:  [RetroPC.NET] / xmil / io / fdc.c
Revision 1.1: download - view: text, annotated - select for diffs
Mon Aug 2 22:38:46 2004 JST (21 years, 3 months ago) by yui
Branches: MAIN
CVS tags: HEAD
fix...

#include	"compiler.h"
#include	"dosio.h"
#include	"z80core.h"
#include	"pccore.h"
#include	"iocore.h"
#include	"fddfile.h"
#include	"fdd_2d.h"
#include	"fdd_d88.h"
#include	"fdd_mtr.h"


		BYTE		FDC_c[4];
		BYTE		driveset = 0;
		BYTE		fdcdummyread = 0;
		WORD		readdiag = 0;

static const UINT8 fdctype[] = {1,1,1,1,1,1,1,1,2,2,2,2,3,4,3,3};


static BYTE fdd_stat(void) {

	FDDFILE fdd;

	fdd = fddfile + fdc.drv;
	switch(fdd->type) {
		case DISKTYPE_NOTREADY:
			return(0);

		case DISKTYPE_BETA:
			return(fdd_stat_2d());

		case DISKTYPE_D88:
		default:
			return(fdd_stat_d88());
	}
	return(0);
}


/***********************************************************************
	FDC (X1から見るI/Oに相当する関数)
***********************************************************************/

static int inc_off(void) {

	BYTE	ret;
	FDDFILE fdd;

	if (!fdc.motor) {
		return(0);
	}
	if (fdcdummyread) {
		fdcdummyread--;
		return(0);
	}
	else {
		fdd = fddfile + fdc.drv;
		switch(fdd->type) {
			case DISKTYPE_NOTREADY:
				return(0);

			case DISKTYPE_BETA:
				ret = fdd_incoff_2d();
				break;

			case DISKTYPE_D88:
			default:
				ret = fdd_incoff_d88();
				break;
		}
		if (ret) {
			dma.DMA_REDY = 8;	// <- DMA ノ レディシンゴウ ヲ クリア
		}
	}
	return(ret);
}

void IOOUTCALL fdc_o(UINT port, REG8 value) {

	REG8	cmd;

	port &= 0xf;
	if (port == 8) {						// コマンド
		driveset = 0;
		fdc.cmd = value;
		cmd = (REG8)(value >> 4);
		fdc.type = fdctype[cmd];
		fdc.skip = 2;
		switch(cmd) {
			case 0x00:								// リストア
				if (value & 8) {					// LAYDOCK
					fdc.skip = 0;
					fdc.busyclock = 20;				// ver0.25 (now testing)
					fdc.busystart = h_cntbase + h_cnt;
				}
				fdc.motor = 0x80;					// モーターOn?
				fdc.c = 0;
				fdc.treg = 0;
				FDDMTR_MOVE;
				fdc.step = 1;
#if 1												// ver0.25
				fdc.r = 0;							// デゼニワールド
				fdc.rreg = 0;
#endif
				break;

			case 0x01:								// シーク
				fdc.motor = 0x80;					// モーターOn
				fdc.step = (char)((fdc.c<=fdc.data)?1:-1);
#if 0												// スタクル		// ver0.50
				fdc.rreg = fdc.r = 0;
#endif
				fdc.c = fdc.data;
				fdc.treg = fdc.data;
				FDDMTR_MOVE;
				break;

			case 0x02:								// ステップ
			case 0x03:
				if (fdc.motor) {
					fdc.c += fdc.step;
					if (cmd & 1) {
						FDDMTR_MOVE;
						fdc.treg = fdc.c;
					}
				}
				break;

			case 0x04:								// ステップイン
			case 0x05:
				if (fdc.motor) {
					fdc.step = 1;
					fdc.c++;
					if (cmd & 1) {
						FDDMTR_MOVE;
						fdc.treg = fdc.c;
					}
				}
				break;

			case 0x06:								// ステップアウト
			case 0x07:
				if (fdc.motor) {
					fdc.step = -1;
					fdc.c--;
					if (cmd & 1) {
						FDDMTR_MOVE;
						fdc.treg = fdc.c;
					}
				}
				break;

			case 0x08:								// リードデータ
			case 0x09:
			case 0x0a:								// ライトデータ
			case 0x0b:
				fdc.off = 0;
				fdcdummyread = 2;
				if (fdc.motor) {
					if (dma.DMA_ENBL) {
						dma.DMA_REDY = 0;
//						fdc.skip = 0;			// DMAで割り込みを監視する事!
					}
				}
				break;

			case 0xc:								// リードアドレス
				fdc.crc_off = 0;
				fdcdummyread = 2;
				if (fdc.motor) {									// ver0.25
					if (dma.DMA_ENBL) {
						dma.DMA_REDY = 0;
					}
				}
				{
					FDDFILE fdd = fddfile + fdc.drv;
					switch(fdd->type) {
						case DISKTYPE_NOTREADY:
							break;

						case DISKTYPE_BETA:
							fdd_crc_2d();
							break;

						case DISKTYPE_D88:
						default:
							fdd_crc_d88();
							break;
					}
				}
				break;

			case 0x0d:								// フォースインタラプト
				fdcdummyread = 0;					// 必要ない?
				fdc.skip = 0;						// 000330
				dma.DMA_REDY = 8;					// ver0.25
				break;

			case 0x0e:								// リードトラック
				readdiag = 0;
				break;

			case 0x0f:								// ライトトラック
				{
					FDDFILE fdd = fddfile + fdc.drv;
					switch(fdd->type) {
						case DISKTYPE_NOTREADY:
						case DISKTYPE_BETA:
							break;

						case DISKTYPE_D88:
						default:
							if (fdc.motor) {						// ver0.25
								init_tao_d88();
								if (dma.DMA_ENBL) {
									dma.DMA_REDY = 0;
								}
							}
							break;
					}
				}
				break;
		}
	}
	else {
		cmd = (REG8)(fdc.cmd >> 4);
		switch(port) {
			case 0x09:								// トラック
				fdc.treg = value;
				break;

			case 0x0a:								// セクタ
				FDDMTR_WAITSEC(value);
				fdc.r = value;
				fdc.rreg = value;
				break;

			case 0x0b:								// データ
				fdc.data = value;
				if ((cmd == 0x0a) || (cmd == 0x0b)) {
					FDDFILE fdd = fddfile + fdc.drv;
					switch(fdd->type) {
						case DISKTYPE_NOTREADY:
							break;

						case DISKTYPE_BETA:
							fdd_write_2d();
							break;

						case DISKTYPE_D88:
						default:
							fdd_write_d88();
							break;
					}
					inc_off();
				}
				else if (cmd == 0x0f) {				// TRACK WRITE
					FDDFILE fdd = fddfile + fdc.drv;
					switch(fdd->type) {
						case DISKTYPE_NOTREADY:
						case DISKTYPE_BETA:
							break;

						case DISKTYPE_D88:
						default:
							fdd_wtao_d88(value);
							break;
					}
				}
				break;

			case 0x0c:								// ドライブ・サイド
				driveset = 1;
				FDC_c[fdc.drv] = fdc.c;
				fdc.c = FDC_c[value & 0x03];			// XTAL !!!
				fdc.motor = (UINT8)(value & 0x80);
				fdc.drv = (UINT8)(value & 0x03);
				fdc.h = (UINT8)((value >> 4) & 1);

				fdc.cmd = 0;							// T&E SORCERIAN
//				fdc.data = 0;							// 影の伝説
				fdc.type = 0;

				FDDMTR_DRVSET;
				if (!fdc.motor) {
					fdc.r = 0;							// SACOM TELENET
					fdc.rreg = 0;
#if 0													// XTAL
					fdc.c = 0;
					fdc.step = 1;
#endif
				}
				break;
		}
	}
}

REG8 IOINPCALL fdc_i(UINT port) {

static	BYTE	timeoutwait;
static	BYTE	last_r;
static	short	last_off;
		BYTE	ans;
		REG8	cmd;

	cmd = (REG8)(fdc.cmd >> 4);

	if ((port &= 0xf) != 8) {
		last_r = -1;
		last_off = -1;
		timeoutwait = 4;
	}
	switch(port) {
		case 0x8:	// ステータス
			ans = 0;
			fdcdummyread = 0;
			if (fdc.skip) {
				fdc.skip--;
				return(0x01);
			}
			if (fdc.busyclock) {					// ver0.25
				if (((h_cntbase + h_cnt) - fdc.busystart) < fdc.busyclock) {
					return(0x01);
				}
				fdc.busyclock = 0;
			}
		{
			FDDFILE fdd = fddfile + fdc.drv;
			if (fdd->type == DISKTYPE_NOTREADY) {
				if (fdc.type == 1 && fdc.c == 0) {	// ドライブチェック !!!
					return(0x84);					// ←接続されてる時だけ
				}
				return(0x80);
			}
		}
			if (fdc.type == 2) {
				if (last_r == fdc.r && last_off == fdc.off &&
						!(--timeoutwait)) {
					inc_off();
					timeoutwait = 4;
				}
				last_r = fdc.r;
				last_off = fdc.off;
			}							// Read Write時のみの変化でいい筈
			if (!((ans = fdd_stat()) & 2)) {
				dma.DMA_REDY = 8;				// <- DMA ノ レディシンゴウ ヲ クリア
			}
#if 1
			if (driveset) {					// 0xffcを叩いた直後だったら
				ans &= 0xc4;
			}
#endif
			return(ans);

		case 0x9:							// トラック
			return(fdc.treg);

		case 0xa:							// セクタ
			return(fdc.rreg);				// ver0.25

		case 0xb:							// データ
			if (fdc.motor) {
				if ((cmd == 0x08) || (cmd == 0x09)) {	// リード・データ
					FDDFILE fdd;
					fdd = fddfile + fdc.drv;
					switch(fdd->type) {
						case DISKTYPE_NOTREADY:
							break;

						case DISKTYPE_BETA:
							fdd_read_2d();
							break;

						case DISKTYPE_D88:
						default:
							fdd_read_d88();		// WOODY POCO !!!
							break;
					}
					inc_off();
				}
				else if (cmd == 0x0c) {			// リード・アドレス
					if (fdc.crc_off < 6) {		// ver0.25
						fdc.data = fdc.crc_dat[fdc.crc_off];
						if (fdcdummyread) {		// ver0.25
							fdcdummyread--;
						}
						else {
							fdc.crc_off++;
						}
					}
				}
				else if (cmd == 0x0e) {								// ver0.25
					fdc.data = 0;
					readdiag++;
				}
			}
			return(fdc.data);					// WOODY POCO !!!

//		case 0xc:								// FM
//		case 0xd:								// MFM
//			break;

		case 0xe:								// 1.6M
			fdc.media = 1;
			return(0xff);

		case 0xf:								// 500K/1M
			fdc.media = 0;
			return(0xff);
	}
	return(0);
}


// ----

void fdc_reset(void) {

	FDDMTR_INIT;
	ZeroMemory(&fdc, sizeof(fdc));
	fdc.step = 1;
	ZeroMemory(FDC_c, 4);
}


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