2 FUJITSU FMR-30 Emulator 'eFMR-30'
3 FUJITSU FMR-50 Emulator 'eFMR-50'
4 FUJITSU FMR-60 Emulator 'eFMR-60'
6 Author : Takeda.Toshiya
49 #define ERR_FDD_NOTREADY 1
50 #define ERR_FDD_PROTECTED 2
51 #define ERR_FDD_DELETED 4
52 #define ERR_FDD_NOTFOUND 8
53 #define ERR_FDD_CRCERROR 0x10
54 #define ERR_SCSI_NOTREADY 1
55 #define ERR_SCSI_PARAMERROR 2
56 #define ERR_SCSI_NOTCONNECTED 4
57 #define ERR_MEMCARD_NOTREADY 1
58 #define ERR_MEMCARD_PROTECTED 2
59 #define ERR_MEMCARD_PARAMERROR 0x200
63 #define CMOS_SIZE 0x2000
64 #define VRAM_SIZE 0x20000
65 #define IPL_SIZE 0x10000
69 #define CMOS_SIZE 0x800
70 #define VRAM_SIZE 0x40000
71 #define IPL_SIZE 0x4000
75 #define CMOS_SIZE 0x800
76 #define VRAM_SIZE 0x80000
77 #define IPL_SIZE 0x4000
81 #define BLOCK_SIZE 512
83 static const int iotable[][2] = {
85 {0x0100, 0x19}, // pic
95 {0x0042, 0x00}, // timer
99 {0x000b, 0x02}, // sio
105 {0x001d, 0x02}, // memory
107 {0x0040, 0x9f}, // psg
111 {0x0300, 0x01}, // lcdc
135 {0x0060, 0x00}, // timer
136 {0x0604, 0x00}, // keyboard
137 {0x0000, 0x19}, // pic
148 {0x0046, 0x36}, // pit
151 {0x0404, 0x00}, // memory
152 {0x0500, 0x00}, // crtc
192 {0xfd98, 0x00}, // palette
200 {0xfda0, 0x0f}, // video
206 static const uint8 cmos_t[] = {
208 0x01,0xff,0x42,0x4f,0x4f,0x54,0xa8,0x00,0x40,0x00,0x01,0xfe,0x53,0x45,0x54,0x55,
209 0xe8,0x00,0x00,0x01,0x01,0xfd,0x4c,0x4f,0x47,0x20,0xe8,0x01,0x10,0x03,0x01,0xfc,
210 0x4f,0x41,0x53,0x59,0xf8,0x04,0x20,0x00,0x01,0xfb,0x44,0x45,0x42,0x20,0x18,0x05,
211 0x00,0x01,0x01,0xfa,0x44,0x45,0x53,0x4b,0x18,0x06,0x32,0x00,0x00,0x00,0x00,0x00,
212 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
213 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
214 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
215 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
216 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
217 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
218 0x4a,0x06,0x7b,0x19,0x97,0x62,0x79,0x41
220 0x01,0xff,0x42,0x4f,0x4f,0x54,0xa8,0x00,0x40,0x00,0x01,0xfe,0x53,0x45,0x54,0x55,
221 0xe8,0x00,0x00,0x01,0x01,0xfd,0x4c,0x4f,0x47,0x20,0xe8,0x01,0x10,0x03,0x01,0xfc,
222 0x4f,0x41,0x53,0x59,0xf8,0x04,0x20,0x00,0x01,0xfb,0x58,0x45,0x4e,0x49,0x18,0x05,
223 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
224 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
225 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
226 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
227 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
228 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
229 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
230 // 0x28,0x05,0x99,0x02,0xe1,0xe1,0x79,0x41
231 0x28,0x05,0x99,0x02,0x00,0x00,0x79,0x41
234 // FMR-30: cmos $1fd0-
235 // FMR-50: cmos $7d0-
236 static const uint8 cmos_b[] = {
238 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0xff,0xff,0xff,0xff,0xff,
239 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
240 0x7f,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
242 0x00,0x00,0x01,0x02,0x03,0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
243 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
244 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
249 static const uint8 msg_c[] = {
250 0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,
251 0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,
252 0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,
253 0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07
256 // '
\83V
\83X
\83e
\83\80\82ð
\83Z
\83b
\83g
\82µ
\82Ä
\82Â
\82¾
\82³
\82¢'
257 static const uint8 msg_k[] = {
258 0x25,0x37,0x00,0x00,0x25,0x39,0x00,0x00,0x25,0x46,0x00,0x00,0x25,0x60,0x00,0x00,
259 0x24,0x72,0x00,0x00,0x25,0x3b,0x00,0x00,0x25,0x43,0x00,0x00,0x25,0x48,0x00,0x00,
260 0x24,0x37,0x00,0x00,0x24,0x46,0x00,0x00,0x24,0x2f,0x00,0x00,0x24,0x40,0x00,0x00,
261 0x24,0x35,0x00,0x00,0x24,0x24,0x00,0x00,0x21,0x21,0x00,0x00
264 void BIOS::initialize()
267 disk_pc1 = disk_pc2 = cmos_pc = wait_pc = -1;
270 FILEIO* fio = new FILEIO();
271 if(fio->Fopen(emu->bios_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
272 fio->Fread(buffer, sizeof(buffer), 1);
275 uint32 addr = 0xfffc4;
276 if(buffer[addr & (IPL_SIZE - 1)] == 0xea) {
277 int ofs = buffer[++addr & (IPL_SIZE - 1)];
278 ofs |= buffer[++addr & (IPL_SIZE - 1)] << 8;
279 int seg = buffer[++addr & (IPL_SIZE - 1)];
280 seg |= buffer[++addr & (IPL_SIZE - 1)] << 8;
281 disk_pc1 = addr = ofs + (seg << 4);
283 if(buffer[addr & (IPL_SIZE - 1)] == 0xea) {
284 int ofs = buffer[++addr & (IPL_SIZE - 1)];
285 ofs |= buffer[++addr & (IPL_SIZE - 1)] << 8;
286 int seg = buffer[++addr & (IPL_SIZE - 1)];
287 seg |= buffer[++addr & (IPL_SIZE - 1)] << 8;
288 disk_pc2 = ofs + (seg << 4);
297 register_frame_event(this);
301 memset(scsi_blocks, 0, sizeof(scsi_blocks));
302 for(int i = 0; i < MAX_SCSI; i++) {
303 _stprintf_s(scsi_path[i], _MAX_PATH, _T("%sSCSI%d.DAT"), emu->application_path(), i);
304 if(fio->Fopen(scsi_path[i], FILEIO_READ_BINARY)) {
305 fio->Fseek(0, FILEIO_SEEK_END);
306 scsi_blocks[i] = fio->Ftell() / BLOCK_SIZE;
312 memset(memcard_blocks, 0, sizeof(memcard_blocks));
313 for(int i = 0; i < MAX_MEMCARD; i++) {
314 _stprintf_s(memcard_path[i], _MAX_PATH, _T("%sMEMCARD%d.DAT"), emu->application_path(), i);
315 if(fio->Fopen(memcard_path[i], FILEIO_READ_BINARY)) {
316 fio->Fseek(0, FILEIO_SEEK_END);
317 memcard_blocks[i] = fio->Ftell() / BLOCK_SIZE;
318 memcard_protected[i] = FILEIO::IsFileProtected(memcard_path[i]);
327 for(int i = 0; i < MAX_DRIVE; i++) {
328 access_fdd[i] = false;
336 void BIOS::event_frame()
341 bool BIOS::bios_call_i86(uint32 PC, uint16 regs[], uint16 sregs[], int32* ZeroFlag, int32* CarryFlag)
343 uint8 *regs8 = (uint8 *)regs;
346 if(PC == 0xfffc4 || PC == disk_pc1 || PC == disk_pc2) {
349 emu->out_debug_log(_T("%6x\tDISK BIOS: AH=%2x,AL=%2x,CX=%4x,DX=%4x,BX=%4x,DS=%2x,DI=%2x\n"), get_cpu_pc(0), AH,AL,CX,DX,BX,DS,DI);
351 // if(ipl_loaded && (AL & 0xf0) == 0x20) {
352 // don't use pseudo bios for floppy drive
355 // if(!((AL & 0xf0) == 0x20 || (AL & 0xf0) == 0x50 || (AL & 0xf0) == 0xb0)) {
356 // target drive is not floppy, memcard and scsi hard drive
361 if((AL & 0xf0) == 0x20) {
363 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
365 CX = ERR_FDD_NOTREADY;
371 if(disk[drv]->write_protected) {
378 if((AL & 0xf0) == 0x50) {
380 if(!(drv < MAX_MEMCARD && memcard_blocks[drv])) {
382 CX = ERR_MEMCARD_NOTREADY;
388 DL = memcard_protected[drv] ? 2 : 0;
393 if((AL & 0xf0) == 0xb0) {
395 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
397 CX = ERR_SCSI_NOTCONNECTED;
402 AL = (BLOCK_SIZE == 128) ? 0 : (BLOCK_SIZE == 256) ? 1 : (BLOCK_SIZE == 512) ? 2 : 3;
403 BX = scsi_blocks[drv] >> 16;
404 DX = scsi_blocks[drv] & 0xffff;
412 } else if(AH == 3 || AH == 4) {
414 if((AL & 0xf0) == 0x20) {
416 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
418 CX = ERR_FDD_NOTREADY;
427 if((AL & 0xf0) == 0xb0) {
429 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
431 CX = ERR_SCSI_NOTCONNECTED;
445 if((AL & 0xf0) == 0x20) {
447 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
449 CX = ERR_FDD_NOTREADY;
454 int ofs = DS * 16 + DI;
460 disk[drv]->get_track(trk, hed);
461 access_fdd[drv] = true;
463 if(!disk[drv]->get_sector(trk, hed, sct - 1)) {
465 CX = ERR_FDD_NOTFOUND;
469 // check id crc error
470 if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
472 CX = ERR_FDD_NOTFOUND | ERR_FDD_CRCERROR;
476 // check deleted mark
477 if(disk[drv]->deleted) {
479 CX = ERR_FDD_DELETED;
484 for(int i = 0; i < disk[drv]->sector_size.sd; i++) {
485 d_mem->write_data8(ofs++, disk[drv]->sector[i]);
488 // check data crc error
489 if(disk[drv]->data_crc_error && !disk[drv]->ignore_crc()) {
491 CX = ERR_FDD_CRCERROR;
496 if(++sct > disk[drv]->sector_num.sd) {
509 if((AL & 0xf0) == 0x50) {
511 if(!(drv < MAX_MEMCARD && memcard_blocks[drv])) {
513 CX = ERR_MEMCARD_NOTREADY;
517 FILEIO* fio = new FILEIO();
518 if(!fio->Fopen(memcard_path[drv], FILEIO_READ_BINARY)) {
520 CX = ERR_MEMCARD_NOTREADY;
526 int ofs = DS * 16 + DI;
527 int block = (CL << 16) | DX;
528 fio->Fseek(block * BLOCK_SIZE, FILEIO_SEEK_SET);
531 if(!(block++ < memcard_blocks[drv])) {
533 CX = ERR_MEMCARD_PARAMERROR;
540 fio->Fread(buffer, BLOCK_SIZE, 1);
541 for(int i = 0; i < BLOCK_SIZE; i++) {
542 d_mem->write_data8(ofs++, buffer[i]);
553 if((AL & 0xf0) == 0xb0) {
555 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
557 CX = ERR_SCSI_NOTCONNECTED;
561 FILEIO* fio = new FILEIO();
562 if(!fio->Fopen(scsi_path[drv], FILEIO_READ_BINARY)) {
564 CX = ERR_SCSI_NOTREADY;
570 int ofs = DS * 16 + DI;
571 int block = (CL << 16) | DX;
572 fio->Fseek(block * BLOCK_SIZE, FILEIO_SEEK_SET);
576 if(!(block++ < scsi_blocks[drv])) {
578 CX = ERR_SCSI_PARAMERROR;
585 fio->Fread(buffer, BLOCK_SIZE, 1);
586 for(int i = 0; i < BLOCK_SIZE; i++) {
587 d_mem->write_data8(ofs++, buffer[i]);
603 if((AL & 0xf0) == 0x20) {
605 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
607 CX = ERR_FDD_NOTREADY;
611 if(disk[drv]->write_protected) {
613 CX = ERR_FDD_PROTECTED;
618 int ofs = DS * 16 + DI;
624 disk[drv]->get_track(trk, hed);
625 access_fdd[drv] = true;
627 if(!disk[drv]->get_sector(trk, hed, sct - 1)) {
629 CX = ERR_FDD_NOTFOUND;
633 // check id crc error
634 if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
636 CX = ERR_FDD_NOTFOUND | ERR_FDD_CRCERROR;
641 for(int i = 0; i < disk[drv]->sector_size.sd; i++) {
642 disk[drv]->sector[i] = d_mem->read_data8(ofs++);
645 // clear deleted mark and data crc error
646 disk[drv]->set_deleted(false);
647 disk[drv]->set_data_crc_error(false);
649 if(++sct > disk[drv]->sector_num.sd) {
662 if((AL & 0xf0) == 0x50) {
664 if(!(drv < MAX_MEMCARD && memcard_blocks[drv])) {
666 CX = ERR_MEMCARD_NOTREADY;
670 if(memcard_protected[drv]) {
672 CX = ERR_MEMCARD_PROTECTED;
676 FILEIO* fio = new FILEIO();
677 if(!fio->Fopen(memcard_path[drv], FILEIO_READ_WRITE_BINARY)) {
679 CX = ERR_MEMCARD_NOTREADY;
685 int ofs = DS * 16 + DI;
686 int block = (CL << 16) | DX;
687 fio->Fseek(block * BLOCK_SIZE, FILEIO_SEEK_SET);
691 if(!(block++ < scsi_blocks[drv])) {
693 CX = ERR_MEMCARD_PARAMERROR;
700 for(int i = 0; i < BLOCK_SIZE; i++) {
701 buffer[i] = d_mem->read_data8(ofs++);
703 fio->Fwrite(buffer, BLOCK_SIZE, 1);
713 if((AL & 0xf0) == 0xb0) {
715 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
717 CX = ERR_SCSI_NOTCONNECTED;
721 FILEIO* fio = new FILEIO();
722 if(!fio->Fopen(scsi_path[drv], FILEIO_READ_WRITE_BINARY)) {
724 CX = ERR_SCSI_NOTREADY;
730 int ofs = DS * 16 + DI;
731 int block = (CL << 16) | DX;
732 fio->Fseek(block * BLOCK_SIZE, FILEIO_SEEK_SET);
736 if(!(block++ < scsi_blocks[drv])) {
738 CX = ERR_SCSI_PARAMERROR;
745 for(int i = 0; i < BLOCK_SIZE; i++) {
746 buffer[i] = d_mem->read_data8(ofs++);
748 fio->Fwrite(buffer, BLOCK_SIZE, 1);
763 if((AL & 0xf0) == 0x20) {
765 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
767 CX = ERR_FDD_NOTREADY;
777 disk[drv]->get_track(trk, hed);
778 access_fdd[drv] = true;
780 if(!disk[drv]->get_sector(trk, hed, sct - 1)) {
782 CX = ERR_FDD_NOTFOUND;
786 // check id crc error
787 if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
789 CX = ERR_FDD_NOTFOUND | ERR_FDD_CRCERROR;
795 // check data crc error
796 if(disk[drv]->data_crc_error && !disk[drv]->ignore_crc()) {
798 CX = ERR_FDD_CRCERROR;
803 if(++sct > disk[drv]->sector_num.sd) {
816 if((AL & 0xf0) == 0xb0) {
818 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
820 CX = ERR_SCSI_NOTCONNECTED;
825 int block = (CL << 16) | DX;
829 if(!(block++ < scsi_blocks[drv])) {
831 CX = ERR_SCSI_PARAMERROR;
846 // reset hard drive controller
853 if((AL & 0xf0) == 0x20) {
855 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
857 CX = ERR_FDD_NOTREADY;
862 int ofs = DS * 16 + DI;
866 disk[drv]->get_track(trk, hed);
867 access_fdd[drv] = true;
868 if(++secnum > disk[drv]->sector_num.sd) {
871 if(!disk[drv]->get_sector(trk, hed, secnum - 1)) {
873 CX = ERR_FDD_NOTFOUND;
878 for(int i = 0; i < 6; i++) {
879 d_mem->write_data8(ofs++, disk[drv]->id[i]);
881 // check id crc error
882 if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
884 CX = ERR_FDD_CRCERROR;
896 } else if(AH == 0xa) {
898 if((AL & 0xf0) == 0x20) {
900 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
902 CX = ERR_FDD_NOTREADY;
907 int ofs = DS * 16 + DI;
911 disk[drv]->format_track(trk, hed);
912 access_fdd[drv] = true;
913 bool id_written = false;
914 bool sector_found = false;
915 int sector_length, sector_index;
916 for(int index = 0; index < disk[drv]->get_track_size(); index++) {
917 uint8 datareg = d_mem->read_data8(ofs++);
918 if(datareg == 0xf5) {
919 // write a1h in missing clock
920 } else if(datareg == 0xf6) {
921 // write c2h in missing clock
922 } else if(datareg == 0xf7) {
925 // insert new sector with data crc error
928 sector_found = false;
929 uint8 c = disk[drv]->track[index - 4];
930 uint8 h = disk[drv]->track[index - 3];
931 uint8 r = disk[drv]->track[index - 2];
932 uint8 n = disk[drv]->track[index - 1];
933 sector_length = 0x80 << (n & 3);
935 disk[drv]->insert_sector(c, h, r, n, false, true, 0xe5, sector_length);
936 } else if(sector_found) {
937 // clear data crc error if all sector data are written
938 disk[drv]->set_data_crc_error(false);
941 // data mark of current sector is not written
942 disk[drv]->set_data_mark_missing();
945 } else if(id_written) {
948 if(sector_index < sector_length) {
949 disk[drv]->sector[sector_index] = datareg;
952 } else if(datareg == 0xf8 || datareg == 0xfb) {
954 disk[drv]->set_deleted(datareg == 0xf8);
958 disk[drv]->track[index] = datareg;
968 } else if(AH == 0xd) {
974 } else if(AH == 0xe) {
976 if((AL & 0xf0) == 0x20) {
978 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
987 DL = disk[drv]->changed ? 1 : 0;
988 disk[drv]->changed = false;
992 if((AL & 0xf0) == 0xb0) {
994 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
1009 } else if(AH == 0xfa) {
1011 if((AL & 0xf0) == 0x20) {
1018 if((AL & 0xf0) == 0xb0) {
1020 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
1022 CX = ERR_SCSI_NOTCONNECTED;
1034 } else if(AH == 0xfd) {
1036 if((AL & 0xf0) == 0x20) {
1043 if((AL & 0xf0) == 0xb0) {
1045 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
1060 } else if(AH == 0x80) {
1061 // pseudo bios: init i/o
1062 for(int i = 0;; i++) {
1063 if(iotable[i][0] < 0) {
1066 d_io->write_io8(iotable[i][0], iotable[i][1]);
1069 memset(cmos, 0, CMOS_SIZE);
1070 memcpy(cmos, cmos_t, sizeof(cmos_t));
1071 memcpy(cmos + CMOS_SIZE - sizeof(cmos_b), cmos_b, sizeof(cmos_b));
1073 for(int i = 0, ofs = 0; i < 256; i++) {
1074 // int vector = ffff:0008
1075 d_mem->write_data16(ofs + 0, 0x0008);
1076 d_mem->write_data16(ofs + 2, 0xffff);
1080 memset(vram, 0, VRAM_SIZE);
1082 memset(cvram, 0, 0x2000);
1083 memset(avram, 0, 0x2000);
1085 memset(cvram, 0, 0x1000);
1086 memset(kvram, 0, 0x1000);
1087 memcpy(cvram + 0xf00, msg_c, sizeof(msg_c));
1088 memcpy(kvram + 0xf00, msg_k, sizeof(msg_k));
1092 } else if(AH == 0x81) {
1093 // pseudo bios: boot from fdd #0
1094 *ZeroFlag = (timeout > (int)(FRAMES_PER_SEC * 4));
1095 if(!disk[0]->inserted) {
1100 disk[0]->get_track(0, 0);
1101 access_fdd[0] = true;
1102 if(!disk[0]->get_sector(0, 0, 0)) {
1106 for(int i = 0; i < disk[0]->sector_size.sd; i++) {
1107 buffer[i] = disk[0]->sector[i];
1110 if(!(buffer[0] == 'I' && buffer[1] == 'P' && buffer[2] == 'L' && buffer[3] == IPL_ID)) {
1115 for(int i = 0; i < disk[0]->sector_size.sd; i++) {
1116 d_mem->write_data8(0xb0000 + i, buffer[i]);
1120 memset(cvram, 0, 0x2000);
1121 memset(avram, 0, 0x2000);
1123 memset(cvram, 0, 0x1000);
1124 memset(kvram, 0, 0x1000);
1133 } else if(AH == 0x82) {
1134 // pseudo bios: boot from scsi-hdd #0
1136 if(!scsi_blocks[0]) {
1140 FILEIO* fio = new FILEIO();
1141 if(!fio->Fopen(scsi_path[drv], FILEIO_READ_BINARY)) {
1148 fio->Fread(buffer, BLOCK_SIZE * 4, 1);
1152 if(!(buffer[0] == 'I' && buffer[1] == 'P' && buffer[2] == 'L' && buffer[3] == IPL_ID)) {
1157 for(int i = 0; i < BLOCK_SIZE * 4; i++) {
1158 d_mem->write_data8(0xb0000 + i, buffer[i]);
1162 memset(cvram, 0, 0x2000);
1163 memset(avram, 0, 0x2000);
1165 memset(cvram, 0, 0x1000);
1166 memset(kvram, 0, 0x1000);
1176 } else if(PC == cmos_pc) {
1179 emu->out_debug_log(_T("%6x\tCMOS BIOS: AH=%2x,AL=%2x,CX=%4x,DX=%4x,BX=%4x,DS=%2x,DI=%2x\n"), get_cpu_pc(0), AH,AL,CX,DX,BX,DS,DI);
1183 memcpy(cmos, cmos_t, sizeof(cmos_t));
1184 memcpy(cmos + CMOS_SIZE - sizeof(cmos_b), cmos_b, sizeof(cmos_b));
1185 } else if(AH == 5) {
1187 BX = cmos[0xa2] | (cmos[0xa3] << 8);
1188 } else if(AH == 10) {
1190 int block = AL * 10;
1191 int len = cmos[block + 6] | (cmos[block + 7] << 8);
1192 int dst = cmos[block + 8] | (cmos[block + 9] << 8);
1193 int src = DS * 16 + DI;
1194 for(int i = 0; i < len; i++) {
1195 cmos[dst++] = d_mem->read_data8(src++);
1197 } else if(AH == 11) {
1199 int block = AL * 10;
1200 int len = cmos[block + 6] | (cmos[block + 7] << 8);
1201 int src = cmos[block + 8] | (cmos[block + 9] << 8);
1202 int dst = DS * 16 + DI;
1203 for(int i = 0; i < len; i++) {
1204 d_mem->write_data8(dst++, cmos[src++]);
1206 } else if(AH == 20) {
1207 // check block header
1213 } else if(PC == wait_pc) {
1216 emu->out_debug_log(_T("%6x\tWAIT BIOS: AH=%2x,AL=%2x,CX=%4x,DX=%4x,BX=%4x,DS=%2x,DI=%2x\n"), get_cpu_pc(0), AH,AL,CX,DX,BX,DS,DI);
1224 bool BIOS::bios_int_i86(int intnum, uint16 regs[], uint16 sregs[], int32* ZeroFlag, int32* CarryFlag)
1226 uint8 *regs8 = (uint8 *)regs;
1228 if(intnum == 0x93) {
1230 return bios_call_i86(0xfffc4, regs, sregs, ZeroFlag, CarryFlag);
1231 } else if(intnum == 0xaa) {
1232 // power management bios
1243 } else if(AH == 1) {
1253 uint32 BIOS::read_signal(int ch)
1255 // get access status
1257 for(int i = 0; i < MAX_DRIVE; i++) {
1261 access_fdd[i] = false;
1266 access_scsi = false;
1270 #define STATE_VERSION 2
1272 void BIOS::save_state(FILEIO* state_fio)
1274 state_fio->FputUint32(STATE_VERSION);
1275 state_fio->FputInt32(this_device_id);
1277 for(int i = 0; i < MAX_DRIVE; i++) {
1278 disk[i]->save_state(state_fio);
1280 state_fio->FputInt32(secnum);
1281 state_fio->FputInt32(timeout);
1282 state_fio->Fwrite(buffer, sizeof(buffer), 1);
1283 state_fio->FputUint8(powmode);
1284 state_fio->FputUint32(disk_pc1);
1285 state_fio->FputUint32(disk_pc2);
1286 state_fio->FputUint32(cmos_pc);
1287 state_fio->FputUint32(wait_pc);
1288 state_fio->FputBool(ipl_loaded);
1291 bool BIOS::load_state(FILEIO* state_fio)
1293 if(state_fio->FgetUint32() != STATE_VERSION) {
1296 if(state_fio->FgetInt32() != this_device_id) {
1299 for(int i = 0; i < MAX_DRIVE; i++) {
1300 if(!disk[i]->load_state(state_fio)) {
1304 secnum = state_fio->FgetInt32();
1305 timeout = state_fio->FgetInt32();
1306 state_fio->Fread(buffer, sizeof(buffer), 1);
1307 powmode = state_fio->FgetUint8();
1308 disk_pc1 = state_fio->FgetUint32();
1309 disk_pc2 = state_fio->FgetUint32();
1310 cmos_pc = state_fio->FgetUint32();
1311 wait_pc = state_fio->FgetUint32();
1312 ipl_loaded = state_fio->FgetBool();