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
14 #include "../harddisk.h"
50 #define ERR_FDD_NOTREADY 1
51 #define ERR_FDD_PROTECTED 2
52 #define ERR_FDD_DELETED 4
53 #define ERR_FDD_NOTFOUND 8
54 #define ERR_FDD_CRCERROR 0x10
55 #define ERR_SCSI_NOTREADY 1
56 #define ERR_SCSI_PARAMERROR 2
57 #define ERR_SCSI_NOTCONNECTED 4
61 #define CMOS_SIZE 0x2000
62 #define VRAM_SIZE 0x20000
63 #define IPL_SIZE 0x10000
67 #define CMOS_SIZE 0x800
68 #define VRAM_SIZE 0x40000
69 #define IPL_SIZE 0x4000
73 #define CMOS_SIZE 0x800
74 #define VRAM_SIZE 0x80000
75 #define IPL_SIZE 0x4000
79 #define BLOCK_SIZE 512
81 static const int iotable[][2] = {
83 {0x0100, 0x19}, // pic
93 {0x0042, 0x00}, // timer
97 {0x000b, 0x02}, // sio
103 {0x001d, 0x02}, // memory
105 {0x0040, 0x9f}, // psg
109 {0x0300, 0x01}, // lcdc
133 {0x0060, 0x00}, // timer
134 {0x0604, 0x00}, // keyboard
135 {0x0000, 0x19}, // pic
146 {0x0046, 0x36}, // pit
149 {0x0404, 0x00}, // memory
150 {0x0500, 0x00}, // crtc
190 {0xfd98, 0x00}, // palette
198 {0xfda0, 0x0f}, // video
204 static const uint8_t cmos_t[] = {
206 0x01,0xff,0x42,0x4f,0x4f,0x54,0xa8,0x00,0x40,0x00,0x01,0xfe,0x53,0x45,0x54,0x55,
207 0xe8,0x00,0x00,0x01,0x01,0xfd,0x4c,0x4f,0x47,0x20,0xe8,0x01,0x10,0x03,0x01,0xfc,
208 0x4f,0x41,0x53,0x59,0xf8,0x04,0x20,0x00,0x01,0xfb,0x44,0x45,0x42,0x20,0x18,0x05,
209 0x00,0x01,0x01,0xfa,0x44,0x45,0x53,0x4b,0x18,0x06,0x32,0x00,0x00,0x00,0x00,0x00,
210 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
211 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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 0x4a,0x06,0x7b,0x19,0x97,0x62,0x79,0x41
218 0x01,0xff,0x42,0x4f,0x4f,0x54,0xa8,0x00,0x40,0x00,0x01,0xfe,0x53,0x45,0x54,0x55,
219 0xe8,0x00,0x00,0x01,0x01,0xfd,0x4c,0x4f,0x47,0x20,0xe8,0x01,0x10,0x03,0x01,0xfc,
220 0x4f,0x41,0x53,0x59,0xf8,0x04,0x20,0x00,0x01,0xfb,0x58,0x45,0x4e,0x49,0x18,0x05,
221 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
222 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
223 0x00,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 // 0x28,0x05,0x99,0x02,0xe1,0xe1,0x79,0x41
229 0x28,0x05,0x99,0x02,0x00,0x00,0x79,0x41
232 // FMR-30: cmos $1fd0-
233 // FMR-50: cmos $7d0-
234 static const uint8_t cmos_b[] = {
236 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0xff,0xff,0xff,0xff,0xff,
237 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
238 0x7f,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
240 0x00,0x00,0x01,0x02,0x03,0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
241 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
242 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
247 static const uint8_t msg_c[] = {
248 0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,
249 0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,
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
254 // '
\83V
\83X
\83e
\83\80\82ð
\83Z
\83b
\83g
\82µ
\82Ä
\82Â
\82¾
\82³
\82¢'
255 static const uint8_t msg_k[] = {
256 0x25,0x37,0x00,0x00,0x25,0x39,0x00,0x00,0x25,0x46,0x00,0x00,0x25,0x60,0x00,0x00,
257 0x24,0x72,0x00,0x00,0x25,0x3b,0x00,0x00,0x25,0x43,0x00,0x00,0x25,0x48,0x00,0x00,
258 0x24,0x37,0x00,0x00,0x24,0x46,0x00,0x00,0x24,0x2f,0x00,0x00,0x24,0x40,0x00,0x00,
259 0x24,0x35,0x00,0x00,0x24,0x24,0x00,0x00,0x21,0x21,0x00,0x00
262 void BIOS::initialize()
264 // to increment timeout counter
265 register_frame_event(this);
270 for(int i = 0; i < MAX_DRIVE; i++) {
271 access_fdd[i] = false;
272 drive_mode1[i] = 0x03; // MFM, 2HD, 1024B
273 drive_mode2[i] = 0x208; // 2 Heads, 8 sectors
275 for(int i = 0; i < USE_HARD_DISK; i++) {
276 if(harddisk[i] != NULL && harddisk[i]->mounted()) {
277 scsi_blocks[i] = harddisk[i]->sector_size * harddisk[i]->sector_num / BLOCK_SIZE;
286 void BIOS::event_frame()
291 bool BIOS::bios_call_far_i86(uint32_t PC, uint16_t regs[], uint16_t sregs[], int32_t* ZeroFlag, int32_t* CarryFlag)
293 uint8_t *regs8 = (uint8_t *)regs;
295 uint8_t buffer[BLOCK_SIZE * 4];
300 this->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);
304 if(!(drv < MAX_DRIVE)) {
310 drive_mode1[drv] = DL;
311 drive_mode2[drv] = BX;
312 // ToDo: Trap when not resiztered disk[drv].
314 case 0x00: disk[drv]->drive_type = DRIVE_TYPE_2HD; break;
315 case 0x10: disk[drv]->drive_type = DRIVE_TYPE_2DD; break;
316 case 0x20: disk[drv]->drive_type = DRIVE_TYPE_2D ; break;
322 if(!(drv < MAX_DRIVE)) {
328 DL = drive_mode1[drv];
329 BX = drive_mode2[drv];
334 if((AL & 0xf0) == 0x20) {
336 // ToDo: Trap when not resiztered disk[drv].
337 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
339 CX = ERR_FDD_NOTREADY;
344 if(disk[drv]->get_track(0, 0) && disk[drv]->get_sector(0, 0, 0)) {
345 switch(disk[drv]->sector_size.sd) {
346 case 128: AH = 0; break;
347 case 256: AH = 1; break;
348 case 512: AH = 2; break;
349 default : AH = 3; break; // 1024
353 if(disk[drv]->write_protected) {
356 if(disk[drv]->two_side) {
359 // if(disk[drv]->drive_type == DRIVE_TYPE_2D || disk[drv]->drive_type == DRIVE_TYPE_2DD) {
360 if(disk[drv]->media_type == MEDIA_TYPE_2D || disk[drv]->media_type == MEDIA_TYPE_2DD) {
367 if((AL & 0xf0) == 0xb0) {
369 if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
371 CX = ERR_SCSI_NOTCONNECTED;
376 AL = (BLOCK_SIZE == 128) ? 0 : (BLOCK_SIZE == 256) ? 1 : (BLOCK_SIZE == 512) ? 2 : 3;
377 BX = scsi_blocks[drv] >> 16;
378 DX = scsi_blocks[drv] & 0xffff;
386 } else if(AH == 3 || AH == 4) {
388 if((AL & 0xf0) == 0x20) {
390 // ToDo: Trap when not resiztered disk[drv].
391 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
393 CX = ERR_FDD_NOTREADY;
402 if((AL & 0xf0) == 0xb0) {
404 if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
406 CX = ERR_SCSI_NOTCONNECTED;
420 if((AL & 0xf0) == 0x20) {
422 // ToDo: Trap when not resiztered disk[drv].
423 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
425 CX = ERR_FDD_NOTREADY;
430 int ofs = DS * 16 + DI;
436 // ToDo: Trap when not resiztered disk[drv].
437 if(!disk[drv]->get_track(trk, hed)) {
439 CX = ERR_FDD_NOTFOUND;
443 access_fdd[drv] = true;
445 if(!disk[drv]->get_sector(trk, hed, sct - 1)) {
447 CX = ERR_FDD_NOTFOUND;
451 // check id crc error
452 if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
454 CX = ERR_FDD_NOTFOUND | ERR_FDD_CRCERROR;
458 // check deleted mark
459 if(disk[drv]->deleted) {
461 CX = ERR_FDD_DELETED;
466 for(int i = 0; i < disk[drv]->sector_size.sd; i++) {
467 d_mem->write_data8(ofs++, disk[drv]->sector[i]);
470 // check data crc error
471 if(disk[drv]->data_crc_error && !disk[drv]->ignore_crc()) {
473 CX = ERR_FDD_CRCERROR;
478 if(++sct > disk[drv]->sector_num.sd) {
491 if((AL & 0xf0) == 0xb0) {
493 if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
495 CX = ERR_SCSI_NOTCONNECTED;
499 if(!(harddisk[drv] != NULL && harddisk[drv]->mounted())) {
501 CX = ERR_SCSI_NOTREADY;
506 int ofs = DS * 16 + DI;
507 int block = (CL << 16) | DX;
508 long position = block * BLOCK_SIZE;
511 if(!(block++ < scsi_blocks[drv])) {
513 CX = ERR_SCSI_PARAMERROR;
518 harddisk[drv]->read_buffer(position, BLOCK_SIZE, buffer);
519 position += BLOCK_SIZE;
520 for(int i = 0; i < BLOCK_SIZE; i++) {
521 d_mem->write_data8(ofs++, buffer[i]);
535 if((AL & 0xf0) == 0x20) {
537 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
539 CX = ERR_FDD_NOTREADY;
543 if(disk[drv]->write_protected) {
545 CX = ERR_FDD_PROTECTED;
550 int ofs = DS * 16 + DI;
555 // ToDo: Trap when not resiztered disk[drv].
557 if(!disk[drv]->get_track(trk, hed)) {
559 CX = ERR_FDD_NOTFOUND;
563 access_fdd[drv] = true;
565 if(!disk[drv]->get_sector(trk, hed, sct - 1)) {
567 CX = ERR_FDD_NOTFOUND;
571 // check id crc error
572 if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
574 CX = ERR_FDD_NOTFOUND | ERR_FDD_CRCERROR;
579 for(int i = 0; i < disk[drv]->sector_size.sd; i++) {
580 disk[drv]->sector[i] = d_mem->read_data8(ofs++);
583 // clear deleted mark and data crc error
584 disk[drv]->set_deleted(false);
585 disk[drv]->set_data_crc_error(false);
587 if(++sct > disk[drv]->sector_num.sd) {
600 if((AL & 0xf0) == 0xb0) {
602 if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
604 CX = ERR_SCSI_NOTCONNECTED;
608 if(!(harddisk[drv] != NULL && harddisk[drv]->mounted())) {
610 CX = ERR_SCSI_NOTREADY;
615 int ofs = DS * 16 + DI;
616 int block = (CL << 16) | DX;
617 long position = block * BLOCK_SIZE;
620 if(!(block++ < scsi_blocks[drv])) {
622 CX = ERR_SCSI_PARAMERROR;
627 for(int i = 0; i < BLOCK_SIZE; i++) {
628 buffer[i] = d_mem->read_data8(ofs++);
630 harddisk[drv]->write_buffer(position, BLOCK_SIZE, buffer);
631 position += BLOCK_SIZE;
644 if((AL & 0xf0) == 0x20) {
646 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
648 CX = ERR_FDD_NOTREADY;
658 // ToDo: Trap when not resiztered disk[drv].
659 if(!disk[drv]->get_track(trk, hed)) {
661 CX = ERR_FDD_NOTFOUND;
665 access_fdd[drv] = true;
667 if(!disk[drv]->get_sector(trk, hed, sct - 1)) {
669 CX = ERR_FDD_NOTFOUND;
673 // check id crc error
674 if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
676 CX = ERR_FDD_NOTFOUND | ERR_FDD_CRCERROR;
682 // check data crc error
683 if(disk[drv]->data_crc_error && !disk[drv]->ignore_crc()) {
685 CX = ERR_FDD_CRCERROR;
690 if(++sct > disk[drv]->sector_num.sd) {
703 if((AL & 0xf0) == 0xb0) {
705 if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
707 CX = ERR_SCSI_NOTCONNECTED;
712 int block = (CL << 16) | DX;
715 if(!(block++ < scsi_blocks[drv])) {
717 CX = ERR_SCSI_PARAMERROR;
732 // reset hard drive controller
739 if((AL & 0xf0) == 0x20) {
741 // ToDo: Trap when not resiztered disk[drv].
742 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
744 CX = ERR_FDD_NOTREADY;
749 int ofs = DS * 16 + DI;
753 if(!disk[drv]->get_track(trk, hed)) {
755 CX = ERR_FDD_NOTFOUND;
759 access_fdd[drv] = true;
760 if(++secnum > disk[drv]->sector_num.sd) {
763 if(!disk[drv]->get_sector(trk, hed, secnum - 1)) {
765 CX = ERR_FDD_NOTFOUND;
770 for(int i = 0; i < 6; i++) {
771 d_mem->write_data8(ofs++, disk[drv]->id[i]);
773 // check id crc error
774 if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
776 CX = ERR_FDD_CRCERROR;
788 } else if(AH == 0xa) {
790 if((AL & 0xf0) == 0x20) {
792 // ToDo: Trap when not resiztered disk[drv].
793 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
795 CX = ERR_FDD_NOTREADY;
800 int ofs = DS * 16 + DI;
804 // ToDo: Trap when not resiztered disk[drv].
805 disk[drv]->format_track(trk, hed);
806 access_fdd[drv] = true;
807 bool id_written = false;
808 bool sector_found = false;
809 int sector_length, sector_index;
810 for(int index = 0; index < disk[drv]->get_track_size(); index++) {
811 uint8_t datareg = d_mem->read_data8(ofs++);
812 if(datareg == 0xf5) {
813 // write a1h in missing clock
814 } else if(datareg == 0xf6) {
815 // write c2h in missing clock
816 } else if(datareg == 0xf7) {
819 // insert new sector with data crc error
821 // ToDo: Trap when not resiztered disk[drv].
823 sector_found = false;
824 uint8_t c = disk[drv]->track[index - 4];
825 uint8_t h = disk[drv]->track[index - 3];
826 uint8_t r = disk[drv]->track[index - 2];
827 uint8_t n = disk[drv]->track[index - 1];
828 sector_length = 0x80 << (n & 3);
830 disk[drv]->insert_sector(c, h, r, n, false, true, 0xe5, sector_length);
831 } else if(sector_found) {
832 // clear data crc error if all sector data are written
833 disk[drv]->set_data_crc_error(false);
836 // data mark of current sector is not written
837 disk[drv]->set_data_mark_missing();
840 } else if(id_written) {
843 // ToDo: Trap when not resiztered disk[drv].
844 if(sector_index < sector_length) {
845 disk[drv]->sector[sector_index] = datareg;
848 } else if(datareg == 0xf8 || datareg == 0xfb) {
850 // ToDo: Trap when not resiztered disk[drv].
851 disk[drv]->set_deleted(datareg == 0xf8);
855 disk[drv]->track[index] = datareg;
865 } else if(AH == 0xd) {
871 } else if(AH == 0xe) {
873 if((AL & 0xf0) == 0x20) {
875 // ToDo: Trap when not resiztered disk[drv].
876 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
885 DL = disk[drv]->changed ? 1 : 0;
886 disk[drv]->changed = false;
890 if((AL & 0xf0) == 0xb0) {
892 if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
907 } else if(AH == 0xfa) {
909 if((AL & 0xf0) == 0x20) {
916 if((AL & 0xf0) == 0xb0) {
918 if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
920 CX = ERR_SCSI_NOTCONNECTED;
932 } else if(AH == 0xfd) {
934 if((AL & 0xf0) == 0x20) {
941 if((AL & 0xf0) == 0xb0) {
943 if(!(drv < USE_HARD_DISK && scsi_blocks[drv])) {
958 } else if(AH == 0x80) {
959 // pseudo bios: init i/o
960 for(int i = 0;; i++) {
961 if(iotable[i][0] < 0) {
964 d_io->write_io8(iotable[i][0], iotable[i][1]);
967 memset(cmos, 0, CMOS_SIZE);
968 memcpy(cmos, cmos_t, sizeof(cmos_t));
969 memcpy(cmos + CMOS_SIZE - sizeof(cmos_b), cmos_b, sizeof(cmos_b));
971 for(int i = 0, ofs = 0; i < 256; i++) {
972 // int vector = ffff:0008
973 d_mem->write_data16(ofs + 0, 0x0008);
974 d_mem->write_data16(ofs + 2, 0xffff);
978 memset(vram, 0, VRAM_SIZE);
980 memset(cvram, 0, 0x2000);
981 memset(avram, 0, 0x2000);
983 memset(cvram, 0, 0x1000);
984 memset(kvram, 0, 0x1000);
985 memcpy(cvram + 0xf00, msg_c, sizeof(msg_c));
986 memcpy(kvram + 0xf00, msg_k, sizeof(msg_k));
990 } else if(AH == 0x81) {
991 // pseudo bios: boot from fdd #0
992 // ToDo: Trap when not resiztered disk[drv].
993 *ZeroFlag = (timeout > (int)(FRAMES_PER_SEC * 4));
994 if(!disk[0]->inserted) {
999 if(!disk[0]->get_track(0, 0)) {
1003 access_fdd[0] = true;
1004 if(!disk[0]->get_sector(0, 0, 0)) {
1008 for(int i = 0; i < disk[0]->sector_size.sd; i++) {
1009 buffer[i] = disk[0]->sector[i];
1012 if(!(buffer[0] == 'I' && buffer[1] == 'P' && buffer[2] == 'L' && buffer[3] == IPL_ID)) {
1017 for(int i = 0; i < disk[0]->sector_size.sd; i++) {
1018 d_mem->write_data8(0xb0000 + i, buffer[i]);
1022 memset(cvram, 0, 0x2000);
1023 memset(avram, 0, 0x2000);
1025 memset(cvram, 0, 0x1000);
1026 memset(kvram, 0, 0x1000);
1035 } else if(AH == 0x82) {
1036 // pseudo bios: boot from scsi-hdd #0
1038 if(!scsi_blocks[0]) {
1042 if(!(harddisk[drv] != NULL && harddisk[drv]->mounted())) {
1047 harddisk[drv]->read_buffer(0, BLOCK_SIZE * 4, buffer);
1049 if(!(buffer[0] == 'I' && buffer[1] == 'P' && buffer[2] == 'L' && buffer[3] == IPL_ID)) {
1054 for(int i = 0; i < BLOCK_SIZE * 4; i++) {
1055 d_mem->write_data8(0xb0000 + i, buffer[i]);
1059 memset(cvram, 0, 0x2000);
1060 memset(avram, 0, 0x2000);
1062 memset(cvram, 0, 0x1000);
1063 memset(kvram, 0, 0x1000);
1073 } else if(PC == 0xfffc9) {
1076 this->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);
1080 memcpy(cmos, cmos_t, sizeof(cmos_t));
1081 memcpy(cmos + CMOS_SIZE - sizeof(cmos_b), cmos_b, sizeof(cmos_b));
1082 } else if(AH == 5) {
1084 BX = cmos[0xa2] | (cmos[0xa3] << 8);
1085 } else if(AH == 10) {
1087 int block = AL * 10;
1088 int len = cmos[block + 6] | (cmos[block + 7] << 8);
1089 int dst = cmos[block + 8] | (cmos[block + 9] << 8);
1090 int src = DS * 16 + DI;
1091 for(int i = 0; i < len; i++) {
1092 cmos[dst++] = d_mem->read_data8(src++);
1094 } else if(AH == 11) {
1096 int block = AL * 10;
1097 int len = cmos[block + 6] | (cmos[block + 7] << 8);
1098 int src = cmos[block + 8] | (cmos[block + 9] << 8);
1099 int dst = DS * 16 + DI;
1100 for(int i = 0; i < len; i++) {
1101 d_mem->write_data8(dst++, cmos[src++]);
1103 } else if(AH == 20) {
1104 // check block header
1110 } else if(PC == 0xfffd3) {
1113 this->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);
1121 bool BIOS::bios_int_i86(int intnum, uint16_t regs[], uint16_t sregs[], int32_t* ZeroFlag, int32_t* CarryFlag)
1123 uint8_t *regs8 = (uint8_t *)regs;
1125 if(intnum == 0x93) {
1127 return bios_call_far_i86(0xfffc4, regs, sregs, ZeroFlag, CarryFlag);
1132 uint32_t BIOS::read_signal(int ch)
1134 // get access status
1137 for(int i = 0; i < MAX_DRIVE; i++) {
1141 access_fdd[i] = false;
1147 #define STATE_VERSION 5
1149 bool BIOS::process_state(FILEIO* state_fio, bool loading)
1151 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1154 if(!state_fio->StateCheckInt32(this_device_id)) {
1157 for(int i = 0; i < MAX_DRIVE; i++) {
1158 if(!disk[i]->process_state(state_fio, loading)) {
1162 state_fio->StateInt32(secnum);
1163 state_fio->StateInt32(timeout);
1164 state_fio->StateBuffer(drive_mode1, sizeof(drive_mode1), 1);
1165 //state_fio->StateBuffer(drive_mode2, sizeof(drive_mode2), 1);
1166 for(int i = 0; i < (sizeof(drive_mode2) / sizeof(uint16_t)); i++) {
1167 state_fio->StateUint16(drive_mode2[i]);
1169 //state_fio->StateBuffer(scsi_blocks, sizeof(scsi_blocks), 1);
1170 for(int i = 0; i < (sizeof(scsi_blocks) / sizeof(int)); i++) {
1171 state_fio->StateInt32(scsi_blocks[i]);