File:  [RetroPC.NET] / np2 / bios / bios1b.c
Revision 1.2: download - view: text, annotated - select for diffs
Fri Oct 17 12:52:24 2003 JST (22 years ago) by yui
Branches: MAIN
CVS tags: rel_036, HEAD
fix Project Builder (T.Yui)

#include	"compiler.h"
#include	"dosio.h"
#include	"i286.h"
#include	"memory.h"
#include	"pccore.h"
#include	"iocore.h"
#include	"bios.h"
#include	"biosmem.h"
#include	"fddfile.h"
#include	"fdd_mtr.h"
#include	"sxsi.h"


enum {
	CACHE_TABLES	= 4,
	CACHE_BUFFER	= 32768
};


		char	fdmode = 0;
static	BYTE	work[65536];
static	BYTE	mtr_c = 0;
static	UINT	mtr_r = 0;


// ---- FDD

static void init_fdd_equip(void) {

	UINT16	diskequip;

	diskequip = GETBIOSMEM16(MEMW_DISK_EQUIP);
	diskequip &= 0x0f00;
	diskequip |= (UINT16)(~fdmode) & 3;
	diskequip |= (UINT16)fdmode << 12;
	SETBIOSMEM16(MEMW_DISK_EQUIP, diskequip);
}

static void biosfd_setchrn(void) {

	fdc.C = I286_CL;
	fdc.H = I286_DH;
	fdc.R = I286_DL;
	fdc.N = I286_CH;
}

#if 0
static void biosfd_resultout(UINT32 result) {

	BYTE	*ptr;

	ptr = mem + 0x00564 + (fdc.us*8);
	ptr[0] = (BYTE)(result & 0xff) | (fdc.hd << 2) | fdc.us;
	ptr[1] = (BYTE)(result >> 8);
	ptr[2] = (BYTE)(result >> 16);
	ptr[3] = fdc.C;
	ptr[4] = fdc.H;
	ptr[5] = fdc.R;
	ptr[6] = fdc.N;
	ptr[7] = fdc.ncn;
}
#endif

static BOOL biosfd_seek(BYTE track, BOOL ndensity) {

	if (ndensity) {
		if (track < 42) {
			track <<= 1;
		}
		else {
			track = 42 * 2;
		}
	}
	fdc.ncn = track;
	mtr_c = track;
	if (fdd_seek()) {
		return(FAILURE);
	}
	return(SUCCESS);
}

static UINT16 fdfmt_biospara(BYTE fmt, BYTE rpm) {					// ver0.31

	UINT16	seg;
	UINT16	off;
	UINT16	n;

	n = fdc.N;
	if (n >= 4) {
		n = 3;
	}
	if (CTRL_FDMEDIA == DISKTYPE_2HD) {
		seg = GETBIOSMEM16(MEMW_F2HD_P_SEG);
		off = GETBIOSMEM16(MEMW_F2HD_P_OFF);
	}
	else {
		seg = GETBIOSMEM16(MEMW_F2DD_P_SEG);
		off = GETBIOSMEM16(MEMW_F2DD_P_OFF);
	}
	if (rpm) {
		off = 0x2361;									// see bios.cpp
	}
	off += fdc.us * 2;
	off = i286_memword_read(seg, off);
	off += n * 8;
	if (!(I286_AH & 0x40)) {
		off += 4;
	}
	if (fmt) {
		off += 2;
	}
	return(i286_memword_read(seg, off));
}

static void change_rpm(BYTE rpm) {									// ver0.31

	if (np2cfg.usefd144) {
		fdc.rpm = rpm;
	}
}



enum {
	FDCBIOS_NORESULT,
	FDCBIOS_SUCCESS,
	FDCBIOS_SEEKSUCCESS,
	FDCBIOS_ERROR,
	FDCBIOS_SEEKERROR,
	FDCBIOS_READERROR,
	FDCBIOS_WRITEERROR,
	FDCBIOS_NONREADY,
	FDCBIOS_WRITEPROTECT
};

static void fdd_int(int result) {

	if (result == FDCBIOS_NORESULT) {						// ver0.29
		return;
	}
	switch(I286_AH & 0x0f) {
		case 0x00:								// シーク
		case 0x01:								// ベリファイ
		case 0x02:								// 診断の為の読み込み
		case 0x05:								// データの書き込み
		case 0x06:								// データの読み込み
//		case 0x07:								// シリンダ0へシーク
		case 0x0a:								// READ ID
		case 0x0d:								// フォーマット
			break;
		default:
			return;
	}
	fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us;
	switch(result) {
		case FDCBIOS_SUCCESS:
			fdcsend_success7();
			break;

		case FDCBIOS_SEEKSUCCESS:
		case FDCBIOS_SEEKERROR:
			fdc.stat[fdc.us] |= FDCRLT_SE;
			fdc_interrupt();
			fdc.event = FDCEVENT_NEUTRAL;
			fdc.status = FDCSTAT_RQM;
			break;

		case FDCBIOS_READERROR:
			fdc.stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_ND;
			fdcsend_error7();
			break;

		case FDCBIOS_WRITEERROR:
			fdc.stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_EN;
			fdcsend_error7();
			break;

		case FDCBIOS_NONREADY:
			fdc.stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_NR;
			fdcsend_error7();
			break;

		case FDCBIOS_WRITEPROTECT:
			fdc.stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_NW;
			fdcsend_error7();
			break;
	}
}

#if 1
static struct {
	BOOL	flg;
	UINT16	cx;
	UINT16	dx;
	UINT	pos;
//	UINT	cnt;
} b0p;

static void b0patch(void) {

	if ((!b0p.flg) || (b0p.cx != I286_CX) || (b0p.dx != I286_DX)) {
		b0p.flg = TRUE;
		b0p.pos = 0;
		b0p.cx = I286_CX;
		b0p.dx = I286_DX;
	}
	else {
		if (!b0p.pos) {
			UINT32	addr;
			UINT	size;
			UINT	cnt;
			BYTE	c;
			BYTE	cl;
			BYTE	last;
			addr = ES_BASE + I286_BP;
			size = I286_BX;
			cnt = 0;
			last = 0;
			while(size--) {
				c = i286_memoryread(addr++);
				cl = 0;
				do {
					BYTE now = c & 0x80;
					c <<= 1;
					b0p.pos++;
					if (now == last) {
						cnt++;
						if (cnt > 4) {
							break;
						}
					}
					else {
						cnt = 0;
						last = now;
					}
					cl++;
				} while(cl < 8);
				if (cnt > 4) {
					break;
				}
			}
		}
		if ((b0p.pos >> 3) < I286_BX) {
			UINT32 addr;
			BYTE c;
			addr = ES_BASE + I286_BP + (b0p.pos >> 3);
			c = i286_memoryread(addr);
			c ^= (1 << (b0p.pos & 7));
			b0p.pos++;
			i286_memorywrite(addr, c);
		}
	}
}

static void b0clr(void) {
	b0p.flg = 0;
}
#endif

static BYTE fdd_operate(BYTE type, BOOL ndensity, BYTE rpm) {		// ver0.31

	BYTE	ret_ah = 0x60;
	UINT16	size;
	UINT16	pos;
	UINT16	accesssize;
	UINT16	secsize;
	UINT16	para;
	BYTE	s;
	BYTE	ID[4];
	BYTE	hd;
	int		result = FDCBIOS_NORESULT;
	UINT32	addr;

	mtr_c = 0xff;
	mtr_r = 0;


	// とりあえずBIOSの時は無視する
	fdc.mf = 0xff;						// ver0.29

//	TRACE_("int 1Bh", I286_AH);

	change_rpm(rpm);												// ver0.31
	if ((I286_AH & 0x0f) != 0x0a) {
		fdc.crcn = 0;
	}
	if ((I286_AH & 0x0f) != 0x03) {
		CTRL_FDMEDIA = type;
		switch(type) {
			case DISKTYPE_2HD:
				if (pic.pi[1].imr & PIC_INT42) {
					return(0xd0);
				}
				break;
			case DISKTYPE_2DD:
				if (pic.pi[1].imr & PIC_INT41) {
					return(0xd0);
				}
				break;
		}
		if (fdc.us != (I286_AL & 0x03)) {
			fdc.us = I286_AL & 0x03;
			fdc.crcn = 0;
		}
		hd = ((I286_DH) ^ (I286_AL >> 2)) & 1;
		if (fdc.hd != hd) {
			fdc.hd = hd;
			fdc.crcn = 0;
		}
		if (!fdd_diskready(fdc.us)) {
			fdd_int(FDCBIOS_NONREADY);
			if (I286_AH == 0x84) {								// ver0.28
				return(0x68);			// 新センスは 両用ドライブ情報も
			}
			if (I286_AH == 0xc4) {								// ver0.31
				if (np2cfg.usefd144) {
					return(0x6c);
				}
				return(0x68);
			}
			return(0x60);
		}
	}

	// 2DDのモード選択							// ver0.29
	if (type == DISKTYPE_2DD) {
		if (!(mem[MEMB_F2DD_MODE] & (0x10 << fdc.us))) {
			ndensity = 1;
		}
	}

	switch(I286_AH & 0x0f) {
		case 0x00:								// シーク
			if (I286_AH & 0x10) {
				if (!biosfd_seek(I286_CL, ndensity)) {
					result = FDCBIOS_SEEKSUCCESS;
				}
				else {
					result = FDCBIOS_SEEKERROR;
				}
			}
			ret_ah = 0x00;
			break;

		case 0x01:								// ベリファイ
			if (I286_AH & 0x10) {
				if (!biosfd_seek(I286_CL, ndensity)) {
					result = FDCBIOS_SEEKSUCCESS;
				}
				else {
					ret_ah = 0xe0;
					result = FDCBIOS_SEEKERROR;
					break;
				}
			}
			biosfd_setchrn();
			para = fdfmt_biospara(0, rpm);
			if (!para) {
				ret_ah = 0xd0;
				break;
			}
			if (fdc.N < 8) {
				secsize = 128 << fdc.N;
			}
			else {
				secsize = 128 << 8;
			}
			size = I286_BX;
			while(size) {
				if (size > secsize) {
					accesssize = secsize;
				}
				else {
					accesssize = size;
				}
				if (fdd_read()) {
					break;
				}
				size -= accesssize;
				mtr_r += accesssize;						// ver0.26
				if ((fdc.R++ == (BYTE)para) && (I286_AH & 0x80) && (!fdc.hd)) {
					fdc.hd = 1;
					fdc.H = 1;
					fdc.R = 1;
					if (biosfd_seek(fdc.treg[fdc.us], 0)) {
						break;
					}
				}
			}
			if (!size) {
				ret_ah = 0x00;
				result = FDCBIOS_SUCCESS;
			}
			else {
				ret_ah = 0xc0;
				result = FDCBIOS_READERROR;
			}
			break;

		case 0x03:								// 初期化
			init_fdd_equip();
			ret_ah = 0x00;
			break;

		case 0x04:								// センス
			ret_ah = 0x00;
			if (fdd_diskaccess()) {
				ret_ah = 0xc0;
			}
			else if (fdd_diskprotect(fdc.us)) {
				ret_ah = 0x10;
			}
			if (I286_AL & 0x80) {				// 2HD
				ret_ah |= 0x01;
			}
			else {								// 2DD
				if (mem[0x005ca] & (0x01 << fdc.us)) {
					ret_ah++;
				}
				if (mem[0x005ca] & (0x10 << fdc.us)) {				// ver0.30
					ret_ah |= 0x04;
				}
			}
			if (I286_AH & 0x80) {				// ver0.30
				ret_ah |= 8;					// 1MB/640KB両用ドライブ
				if ((I286_AH & 0x40) &&
					(np2cfg.usefd144)) {		// ver0.31
					ret_ah |= 4;				// 1.44対応ドライブ
				}
			}
			break;

		case 0x05:								// データの書き込み
			if (I286_AH & 0x10) {
				if (!biosfd_seek(I286_CL, ndensity)) {
					result = FDCBIOS_SEEKSUCCESS;
				}
				else {
					ret_ah = 0xe0;
					result = FDCBIOS_SEEKERROR;
					break;
				}
			}
			biosfd_setchrn();
			para = fdfmt_biospara(0, rpm);
			if (!para) {
				ret_ah = 0xd0;
				break;
			}
			if (fdd_diskprotect(fdc.us)) {
				ret_ah = 0x70;
				result = FDCBIOS_WRITEPROTECT;
				break;
			}
			if (fdc.N < 8) {
				secsize = 128 << fdc.N;
			}
			else {
				secsize = 128 << 8;
			}
			size = I286_BX;
			addr = ES_BASE + I286_BP;
			while(size) {
				if (size > secsize) {
					accesssize = secsize;
				}
				else {
					accesssize = size;
				}
				i286_memx_read(addr, fdc.buf, accesssize);
				if (fdd_write()) {
					break;
				}
				addr += accesssize;
				size -= accesssize;
				mtr_r += accesssize;						// ver0.26
				if ((fdc.R++ == (BYTE)para) && (I286_AH & 0x80) && (!fdc.hd)) {
					fdc.hd = 1;
					fdc.H = 1;
					fdc.R = 1;
					if (biosfd_seek(fdc.treg[fdc.us], 0)) {
						break;
					}
				}
			}
			if (!size) {
				ret_ah = 0x00;
				result = FDCBIOS_SUCCESS;
			}
			else {
				ret_ah = fddlasterror;			// 0xc0		// ver0.28
				result = FDCBIOS_WRITEERROR;
			}
			break;

		case 0x02:								// 診断の為の読み込み
		case 0x06:								// データの読み込み
			if (I286_AH & 0x10) {
				if (!biosfd_seek(I286_CL, ndensity)) {
					result = FDCBIOS_SEEKSUCCESS;
				}
				else {
					ret_ah = 0xe0;
					result = FDCBIOS_SEEKERROR;
					break;
				}
			}
			biosfd_setchrn();
			para = fdfmt_biospara(0, rpm);
			if (!para) {
				ret_ah = 0xd0;
				break;
			}
#if 0
			if (fdc.R >= 0xf4) {
				ret_ah = 0xb0;
				break;
			}
#endif
			if (fdc.N < 8) {
				secsize = 128 << fdc.N;
			}
			else {
				secsize = 128 << 8;
			}
			size = I286_BX;
			addr = ES_BASE + I286_BP;
			while(size) {
				if (size > secsize) {
					accesssize = secsize;
				}
				else {
					accesssize = size;
				}
				if (fdd_read()) {
					break;
				}
				i286_memx_write(addr, fdc.buf, accesssize);
				addr += accesssize;
				size -= accesssize;
				mtr_r += accesssize;						// ver0.26
				if (fdc.R++ == (BYTE)para) {
					if ((I286_AH & 0x80) && (!fdc.hd)) {
						fdc.hd = 1;
						fdc.H = 1;
						fdc.R = 1;
						if (biosfd_seek(fdc.treg[fdc.us], 0)) {
							break;
						}
					}
#if 1
					else {
						fdc.C++;
						fdc.R = 1;
						break;
					}
#endif
				}
			}
			if (!size) {
				ret_ah = fddlasterror;				// 0x00;
				result = FDCBIOS_SUCCESS;
#if 1
				if (ret_ah == 0xb0) {
					b0patch();
				}
				else {
					b0clr();
				}
#endif
			}
#if 1
			else if ((I286_AH & 0x0f) == 0x02) {	// ARS対策…
				ret_ah = 0x00;
				result = FDCBIOS_READERROR;
			}
#endif
			else {
				ret_ah = fddlasterror;				// 0xc0;	// ver0.28
				result = FDCBIOS_READERROR;
			}
			break;

		case 0x07:						// シリンダ0へシーク
			biosfd_seek(0, 0);
			ret_ah = 0x00;
			result = FDCBIOS_SEEKSUCCESS;
			break;

		case 0x0a:						// READ ID
			fdc.mf = I286_AH & 0x40;						// ver0.29
			if (I286_AH & 0x10) {							// ver0.28
				if (!biosfd_seek(I286_CL, ndensity)) {
					result = FDCBIOS_SEEKSUCCESS;
				}
				else {
					ret_ah = 0xe0;
					result = FDCBIOS_SEEKERROR;
					break;
				}
			}
			if (fdd_readid()) {
				ret_ah = fddlasterror;			// 0xa0;	// ver0.28
				break;
			}
			if (fdc.N < 8) {								// ver0.26
				mtr_r += 128 << fdc.N;
			}
			else {
				mtr_r += 128 << 8;
			}
			ret_ah = 0x00;
			I286_CL = fdc.C;
			I286_DH = fdc.H;
			I286_DL = fdc.R;
			I286_CH = fdc.N;
			result = FDCBIOS_SUCCESS;
			break;

		case 0x0d:						// フォーマット
			if (I286_AH & 0x10) {
				biosfd_seek(I286_CL, ndensity);
			}
			if (fdd_diskprotect(fdc.us)) {
				ret_ah = 0x70;
				break;
			}
			fdc.d = I286_DL;
			fdc.N = I286_CH;
			para = fdfmt_biospara(1, rpm);
			if (!para) {
				ret_ah = 0xd0;
				break;
			}
			fdc.sc = (BYTE)para;
			fdd_formatinit();
			pos = I286_BP;
			for (s=0; s<fdc.sc; s++) {
				i286_memstr_read(I286_ES, pos, ID, 4);
				fdd_formating(ID);
				pos += 4;
			}
			ret_ah = 0x00;
			break;
	}
	fdd_int(result);
	fddmtr_seek(fdc.us, mtr_c, mtr_r);
	I286_IP = BIOSOFST_WAIT;										// ver0.30
	return(ret_ah);
}


// ---- SASI

static void init_sasi_equip(void) {

	UINT16	diskequip;
	UINT	i;
	UINT16	bit;

	diskequip = GETBIOSMEM16(MEMW_DISK_EQUIP);
	diskequip &= 0xf0ff;
	for (i=0, bit=0x0100; i<2; i++, bit<<=1) {
		if (sxsi_hd[i].fname[0]) {
			diskequip |= bit;
		}
	}
	SETBIOSMEM16(MEMW_DISK_EQUIP, diskequip);
}

static void init_scsi_equip(void) {

	UINT	i;
	BYTE	bit;
	UINT16	w;

	mem[MEMB_DISK_EQUIPS] = 0;
	ZeroMemory(&mem[0x00460], 0x20);
	for (i=0, bit=1; i<2; i++, bit<<=1) {
		if (sxsi_hd[i+2].fname[0]) {
			mem[MEMB_DISK_EQUIPS] |= bit;
			mem[0x00460+i*4] = sxsi_hd[i+2].sectors;
			mem[0x00461+i*4] = sxsi_hd[i+2].surfaces;
			switch(sxsi_hd[i+2].size) {
				case 256:
					w = 0 << 12;
					break;

				case 512:
					w = 1 << 12;
					break;

				default:
					w = 2 << 12;
					break;
			}
			w |= sxsi_hd[i+2].tracks;
			SETBIOSMEM16(0x00462+i*4, w);
		}
	}
}

static BYTE sxsi_pos(long *pos) {

	SXSIHDD	sxsi;
	int		np2drv;

	*pos = 0;
	np2drv = (I286_AL & 0x20) >> 4;
	if ((I286_AL & 0x0f) >= 2) {
		return(0x60);
	}
	np2drv |= (I286_AL & 1);
	sxsi = &sxsi_hd[np2drv];
	if (I286_AL & 0x80) {
		if ((I286_DL >= sxsi->sectors) ||
			(I286_DH >= sxsi->surfaces) ||
			(I286_CX >= sxsi->tracks)) {
			return(0xd0);
		}
		(*pos) = ((I286_CX * sxsi->surfaces) + I286_DH) * sxsi->sectors
															+ I286_DL;
	}
	else {
		*pos = (I286_DL << 16) | I286_CX;
		if (!(I286_AL & 0x20)) {
			(*pos) &= 0x1fffff;
		}
		if ((*pos) >= sxsi->totals) {
			return(0xd0);
		}
	}
	return(0x00);
}


static BYTE sxsi_operate(BYTE type) {

	BYTE	ret_ah = 0x00;
	BYTE	drv;
	long	pos;
//	int		i;

	drv = (I286_AL & 0x20) >> 4;
	if ((I286_AL & 0x0f) >= 2) {
		return(0x60);
	}
	drv |= (I286_AL & 1);

	switch(I286_AH & 0x0f) {
		case 0x01:						// ベリファイ
		case 0x07:						// リトラクト
		case 0x0f:						// リトラクト
			break;

   		case 0x03:						// イニシャライズ
			if (type == HDDTYPE_SASI) {
				init_sasi_equip();
			}
			else if (type == HDDTYPE_SCSI) {
				init_scsi_equip();
			}
			break;

   		case 0x04:						// センス
			ret_ah = 0x00;
			if ((I286_AH == 0x04) && (type == HDDTYPE_SASI)) {
				ret_ah = 0x04;
			}
			else if ((I286_AH == 0x44) && (type == HDDTYPE_SCSI)) {
				I286_BX = 1;
			}
			else if (I286_AH == 0x84) {
				I286_BX = sxsi_hd[drv].size;
				I286_CX = sxsi_hd[drv].tracks;
				I286_DH = sxsi_hd[drv].surfaces;
				I286_DL = sxsi_hd[drv].sectors;
			}
			break;

		case 0x05:						// データの書き込み
			i286_memx_read(ES_BASE + I286_BP, work, I286_BX);
			ret_ah = sxsi_pos(&pos);
			if (!ret_ah) {
				ret_ah = sxsi_write(I286_AL, pos, work, I286_BX);
			}
			break;

		case 0x06:						// データの読み込み
			ret_ah = sxsi_pos(&pos);
			if (!ret_ah) {
				ret_ah = sxsi_read(I286_AL, pos, work, I286_BX);
				if (ret_ah < 0x20) {
					i286_memx_write(ES_BASE + I286_BP, work, I286_BX);
				}
			}
			break;

		case 0x0d:						// フォーマット
			if (I286_DL) {
				ret_ah = 0x30;
				break;
			}
			i286_memstr_read(I286_ES, I286_BP, work, I286_BX);
			ret_ah = sxsi_pos(&pos);
			if (!ret_ah) {
				ret_ah = sxsi_format(I286_AL, pos);
			}
			break;

		default:
			ret_ah = 0x40;
			break;
	}
	return(ret_ah);
}


// -------------------------------------------------------------------- BIOS

static UINT16 boot_fd1(BYTE rpm) {									// ver0.31

	UINT	remain;
	UINT	size;
	UINT32	pos;
	UINT16	bootseg;

	change_rpm(rpm);												// ver0.31
	if (biosfd_seek(0, 0)) {
		return(0);
	}
	fdc.hd = 0;
	fdc.mf = 0x40;			// とりあえず MFMモードでリード
	if (fdd_readid()) {
		fdc.mf = 0x00;		// FMモードでリトライ
		if (fdd_readid()) {
			return(0);
		}
	}
	remain = 0x400;
	pos = 0x1fc00;
	if ((!fdc.N) || (!fdc.mf) || (rpm)) {
		pos = 0x1fe00;
		remain = 0x200;
	}
	fdc.R = 1;
	bootseg = (UINT16)(pos >> 4);
	while(remain) {
		if (fdd_read()) {
			return(0);
		}
		if (fdc.N < 3) {
			size = 128 << fdc.N;
		}
		else {
			size = 128 << 3;
		}
		if (remain < size) {
			CopyMemory(mem + pos, fdc.buf, remain);
			break;
		}
		else {
			CopyMemory(mem + pos, fdc.buf, size);
			pos += size;
			remain -= size;
			fdc.R++;
		}
	}
	return(bootseg);
}

static UINT16 boot_fd(BYTE drv, BYTE type) {						// ver0.27

	UINT16	bootseg;

	if (drv >= 4) {
		return(0);
	}
	fdc.us = drv & 3;
	if (!fdd_diskready(fdc.us)) {
		return(0);
	}

	// 2HD
	if (type & 1) {
		CTRL_FDMEDIA = DISKTYPE_2HD;
		// 1.25MB
		bootseg = boot_fd1(0);
		if (bootseg) {
			mem[MEMB_DISK_BOOT] = (BYTE)(0x90+drv);
			return(bootseg);
		}
		// 1.44MB
		bootseg = boot_fd1(1);
		if (bootseg) {
			mem[MEMB_DISK_BOOT] = (BYTE)(0x30+drv);
			return(bootseg);
		}
	}
	if (type & 2) {										// ver0.29
		// 2DD
		CTRL_FDMEDIA = DISKTYPE_2DD;
		bootseg = boot_fd1(0);
		if (bootseg) {
			mem[MEMB_DISK_BOOT] = (BYTE)(0x70+drv);
			fdmode = 3;
			return(bootseg);
		}
	}
	return(0);
}

static UINT16 boot_hd(BYTE drv) {									// ver0.27

	BYTE	ret;

	ret = sxsi_read(drv, 0, mem + 0x1fc00, 0x400);
	if (ret < 0x20) {
		mem[MEMB_DISK_BOOT] = drv;
		return(0x1fc0);
	}
	return(0);
}

UINT16 bootstrapload(void) {										// ver0.27

	BYTE	i;
	UINT16	bootseg;

	fdmode = 0;
	bootseg = 0;
	switch(mem[MEMB_MSW5] & 0xf0) {		// うぐぅ…本当はALレジスタの値から
		case 0x00:					// ノーマル
			break;
		case 0x20:					// 640KB FDD
			for (i=0; (i<4) && (!bootseg); i++) {
				if (fdd_diskready(i)) {
					bootseg = boot_fd(i, 2);
				}
			}
			break;
		case 0x40:					// 1.2MB FDD
			for (i=0; (i<4) && (!bootseg); i++) {
				if (fdd_diskready(i)) {
					bootseg = boot_fd(i, 1);
				}
			}
			break;
		case 0x60:					// MO
			break;
		case 0xa0:					// SASI 1
			if (sxsi_hd[0].fname[0]) {
				bootseg = boot_hd(0x80);
			}
			break;
		case 0xb0:					// SASI 2
			if (sxsi_hd[1].fname[0]) {
				bootseg = boot_hd(0x81);
			}
			break;
		case 0xc0:					// SCSI
			for (i=0; (i<2) && (!bootseg); i++) {
				if (sxsi_hd[i+2].fname[0]) {
					bootseg = boot_hd((BYTE)(0xa0 | i));
				}
			}
			break;
		default:					// ROM
			return(0);
	}
	for (i=0; (i<4) && (!bootseg); i++) {
		if (fdd_diskready(i)) {
			bootseg = boot_fd(i, 3);
		}
	}
	for (i=0; (i<2) && (!bootseg); i++) {
		if (sxsi_hd[i].fname[0]) {
			bootseg = boot_hd((BYTE)(0x80 | i));
		}
	}
	for (i=0; (i<2) && (!bootseg); i++) {
		if (sxsi_hd[i+2].fname[0]) {
			bootseg = boot_hd((BYTE)(0xa0 | i));
		}
	}

	init_fdd_equip();
	init_sasi_equip();
	init_scsi_equip();
	return(bootseg);
}

// --------------------------------------------------------------------------

void bios0x1b(void) {

	BYTE	ret_ah;
	BYTE	flag;

	switch(I286_AL & 0xf0) {
		case 0x90:
			ret_ah = fdd_operate(DISKTYPE_2HD, 0, 0);
			break;

		case 0x30:
		case 0xb0:
			ret_ah = fdd_operate(DISKTYPE_2HD, 0, 1);
			break;

		case 0x10:
		case 0x70:
		case 0xf0:
			ret_ah = fdd_operate(DISKTYPE_2DD, 0, 0);
			break;

		case 0x50:
			ret_ah = fdd_operate(DISKTYPE_2DD, 1, 0);
			break;

		case 0x00:
		case 0x80:
			ret_ah = sxsi_operate(HDDTYPE_SASI);
			break;
#if 0
		case 0x20:
		case 0xa0:
			ret_ah = sxsi_operate(HDDTYPE_SCSI);
			break;
#endif

		default:
			ret_ah = 0x40;
			break;
	}
#if 0
	{
		static BYTE p = 0;
		if ((I286_CL == 0x4d) && (ret_ah == 0xe0)) {
			if (!p) {
				trace_sw = 1;
				p++;
				debug_status();
				memorydump();
			}
		}
	}
#endif
#if 0 // def TRACE
	{
		char	buf[256];
		wsprintf(buf, "%04x:%04x AX=%04x BX=%04x %02x:%02x:%02x:%02x\n"	\
						"ES=%04x BP=%04x \nret=%02x",
			i286_memword_read(I286_SS, I286_SP+2),
			i286_memword_read(I286_SS, I286_SP),
			I286_AX, I286_BX, I286_CL, I286_DH, I286_DL, I286_CH, 
			I286_ES, I286_BP, ret_ah);
			TRACE_(buf, 0);
	}
#endif
	I286_AH = ret_ah;
	flag = i286_membyte_read(I286_SS, I286_SP+4) & 0xfe;
	if (ret_ah >= 0x20) {
		flag |= 1;
	}
	i286_membyte_write(I286_SS, I286_SP+4, flag);
}


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