#define EVENT_MULTI1 4
#define EVENT_MULTI2 5
#define EVENT_LOST 6
+#define EVENT_END_READ_SECTOR 7
+#define EVENT_CRC_ERROR 8
//#define DRIVE_MASK (MAX_DRIVE - 1)
-#define DELAY_TIME (disk[drvreg]->drive_type == DRIVE_TYPE_2HD ? 15000 : 30000)
+#define DELAY_AFTER_HLD (disk[drvreg]->drive_type == DRIVE_TYPE_2HD ? 15000 : 30000)
static const int seek_wait_hi[4] = {3000, 6000, 10000, 16000}; // 2MHz
static const int seek_wait_lo[4] = {6000, 12000, 20000, 30000}; // 1MHz
}
}
+bool MB8877::register_my_event_with_check(int event, double usec)
+{
+ if(register_id[event] >= 0) return false;
+ register_my_event(event, usec);
+ return true;
+}
+
void MB8877::register_my_event(int event, double usec)
{
cancel_my_event(event);
register_event(this, (event << 8) | (cmdtype & 0xff), usec, false, ®ister_id[event]);
}
-void MB8877::register_seek_event()
+void MB8877::register_seek_event(bool first)
{
cancel_my_event(EVENT_SEEK);
if(fdc[drvreg].track == seektrk) {
- register_event(this, (EVENT_SEEK << 8) | (cmdtype & 0xff), 1, false, ®ister_id[EVENT_SEEK]);
+ register_event(this, (EVENT_SEEK << 8) | (cmdtype & 0xff), 300, false, ®ister_id[EVENT_SEEK]); // From XM7 v3.4L77a Wait 300uS.
} else if(disk[drvreg]->drive_type == DRIVE_TYPE_2HD) {
- register_event(this, (EVENT_SEEK << 8) | (cmdtype & 0xff), seek_wait_hi[cmdreg & 3], false, ®ister_id[EVENT_SEEK]);
+ register_event(this, (EVENT_SEEK << 8) | (cmdtype & 0xff), seek_wait_hi[cmdreg & 3] - (first ? 250 : 0), false, ®ister_id[EVENT_SEEK]);
} else {
- register_event(this, (EVENT_SEEK << 8) | (cmdtype & 0xff), seek_wait_lo[cmdreg & 3], false, ®ister_id[EVENT_SEEK]);
+ register_event(this, (EVENT_SEEK << 8) | (cmdtype & 0xff), seek_wait_lo[cmdreg & 3] - (first ? 500 : 0), false, ®ister_id[EVENT_SEEK]);
}
now_seek = true;
}
} else {
_max_drive = 1;
}
+
_drive_mask = _max_drive - 1;
for(int i = 0; i < _max_drive; i++) {
disk[i] = new DISK(emu);
if(osd->check_feature(_T("MB8877_NO_BUSY_AFTER_SEEK"))) {
mb8877_no_busy_after_seek = true;
}
+ if(osd->check_feature(_T("MB8877_DELAY_AFTER_SEEK"))) {
+ mb8877_delay_after_seek = osd->get_feature_int_value(_T("MB8877_DELAY_AFTER_SEEK"));
+ }
//if(osd->check_feature(_T("_FDC_DEBUG_LOG"))) {
// fdc_debug_log = true;
//}
d_noise_head_up->set_mute(!config.sound_noise_fdd);
}
- // initialize timing
+ // initialize fdc
memset(fdc, 0, sizeof(fdc));
for(int i = 0; i < 16; i++) {
fdc[i].track = 40; // OK?
fdc[i].count_immediate = false;
}
- // initialize fdc
- seektrk = 0;
- seekvct = true;
- status = cmdreg = trkreg = secreg = datareg = sidereg = cmdtype = 0;
- drvreg = 0;
+// drvreg = sidereg = 0;
+ cmdtype = 0;
+// motor_on = drive_sel = false;
prev_drq_clock = seekend_clock = 0;
}
void MB8877::reset()
{
- for(int i = 0; i < _max_drive; i++) {
- //fdc[i].track = 0; // Hold to track
- fdc[i].index = 0;
- fdc[i].access = false;
- }
+ // finish previous command
+ if(cmdtype == FDC_CMD_WR_SEC || cmdtype == FDC_CMD_WR_MSEC) {
+ // abort write sector command
+ if(sector_changed) {
+ disk[drvreg]->set_data_crc_error(false);
+ }
+ } else if(cmdtype == FDC_CMD_WR_TRK) {
+ // abort write track command
+ if(!disk[drvreg]->write_protected) {
+ if(fdc[drvreg].id_written && !fdc[drvreg].sector_found) {
+ // data mark of last sector is not written
+ disk[drvreg]->set_data_mark_missing();
+ }
+ disk[drvreg]->sync_buffer();
+ }
+ }
+
+ // single events are automatically canceled in event manager
for(int i = 0; i < (int)array_length(register_id); i++) {
register_id[i] = -1;
}
- now_search = now_seek = drive_sel = false;
- no_command = 0;
+ // reset fdc
+ memset(fdc, 0, sizeof(fdc));
+ status = status_tmp = cmdreg = cmdreg_tmp = trkreg = secreg = datareg = cmdtype = 0;
+ now_search = now_seek = sector_changed = false;
+ no_command = seektrk = 0;
+ seekvct = false;
//#ifdef HAS_MB89311
if(type_mb89311) {
extended_mode = true;
}
//#endif
ready = ((status & FDC_ST_DRQ) && !now_search);
+
//#if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
if(type_fm7) {
if(disk[drvreg]->is_special_disk != SPECIAL_DISK_FM7_RIGLAS) {
if(!motor_on) ready = false;
}
+ if(!fdc[drvreg].head_load) ready = false;
} else
//#endif
{
if(!motor_on) ready = false;
+ if(!fdc[drvreg].head_load) ready = false;
}
// if(motor_on && (status & FDC_ST_DRQ) && !now_search) {
if(ready) {
uint32_t MB8877::read_io8(uint32_t addr)
{
uint32_t val;
- bool not_ready;
+ bool not_ready = false;
bool ready;
switch(addr & 3) {
//#endif
}
}
+
if(cmdtype == 0 && !(status & FDC_ST_NOTREADY)) {
// MZ-2000 HuBASIC invites NOT READY status
if(++no_command == 16) {
} else {
no_command = 0;
}
+
// reset irq/drq
if(!(status & FDC_ST_DRQ)) {
set_drq(false);
if(disk[drvreg]->is_special_disk != SPECIAL_DISK_FM7_RIGLAS) {
if(!motor_on) ready = false;
}
+ if(!fdc[drvreg].head_load) ready = false;
} else
//#endif
{
if(!motor_on) ready = false;
+ if(!fdc[drvreg].head_load) ready = false;
}
// if(motor_on && (status & FDC_ST_DRQ) && !now_search) {
if(ready) {
if(disk[drvreg]->data_crc_error && !disk[drvreg]->ignore_crc()) {
// data crc error
+#if 0
//#ifdef _FDC_DEBUG_LOG
if(fdc_debug_log) this->out_debug_log(_T("FDC\tEND OF SECTOR (DATA CRC ERROR)\n"));
//#endif
status &= ~FDC_ST_BUSY;
cmdtype = 0;
set_irq(true);
+#else
+ register_my_event_with_check(EVENT_CRC_ERROR, disk[drvreg]->get_usec_per_bytes(3));
+#endif
} else if(cmdtype == FDC_CMD_RD_SEC) {
// single sector
+#if 0
//#ifdef _FDC_DEBUG_LOG
if(fdc_debug_log) this->out_debug_log(_T("FDC\tEND OF SECTOR\n"));
//#endif
status &= ~FDC_ST_BUSY;
cmdtype = 0;
set_irq(true);
+#else
+ register_my_event_with_check(EVENT_END_READ_SECTOR, disk[drvreg]->get_usec_per_bytes(3));
+#endif
} else {
// multisector
//#ifdef _FDC_DEBUG_LOG
if(d_noise_seek != NULL) d_noise_seek->play();
//need_after_irq = true;
}
- if((cmdreg & 0x10) || ((cmdreg & 0xf0) == 0)) {
+ // Not update track register if "SEEK" command.Thanks to Haserin. 20180224 K.O.
+ if((((cmdreg & 0x10) != 0) && (cmdreg >= 0x20)) || ((cmdreg & 0xf0) == 0)) {
trkreg = fdc[drvreg].track;
}
- if(seektrk != fdc[drvreg].track) {
+ if((uint8_t)seektrk != (uint8_t)fdc[drvreg].track) {
//if(need_after_irq) {
//set_drq(false);
//set_irq(true); // 20180118 K.O Turn ON IRQ -> Turn OFF DRQ
//}
- register_seek_event();
+ register_seek_event(false);
break;
}
+#if 1
+ // Verify before execute command.
+ // Port from XM7.Thanks to Ryu Takegami.
+ if(cmdreg & 4) {
+ // verify
+ if(trkreg != fdc[drvreg].track) {
+ status |= FDC_ST_SEEKERR;
+ trkreg = fdc[drvreg].track; // Reload track register when verify: Really OK? 20180224 K.O
+ }
+ }
+#endif
seekend_clock = get_current_clock();
//#ifdef HAS_MB89311
if(type_mb89311) {
// verify
status_tmp |= search_track();
double time;
+#if 0
if(status_tmp & FDC_ST_SEEKERR) {
time = get_usec_to_detect_index_hole(5, true);
} else {
time = get_usec_to_next_trans_pos(true);
}
+#else
+ // Verify wait is shorter than above at least FM-7 series's MB8877. 20180223 K.O.
+ // Thanks to Ryu Takegami.
+ time = (disk[drvreg]->drive_type == DRIVE_TYPE_2HD) ? 10000.0 : 20000.0;
+#endif
// 20180128 K.O If seek completed, delay to make IRQ/DRQ at SEEKEND_VERIFY.
register_my_event(EVENT_SEEKEND_VERIFY, time);
break;
cmd_writedata(false);
}
break;
+ case EVENT_CRC_ERROR:
+ //#ifdef _FDC_DEBUG_LOG
+ if(fdc_debug_log) this->out_debug_log(_T("FDC\tEND OF SECTOR (DATA CRC ERROR)\n"));
+//#endif
+ status |= FDC_ST_CRCERR;
+ status &= ~FDC_ST_BUSY;
+ cmdtype = 0;
+ set_irq(true);
+ break;
+ case EVENT_END_READ_SECTOR:
+//#ifdef _FDC_DEBUG_LOG
+ if(fdc_debug_log) this->out_debug_log(_T("FDC\tEND OF SECTOR\n"));
+//#endif
+ status &= ~FDC_ST_BUSY;
+ cmdtype = 0;
+ set_irq(true);
+ break;
case EVENT_LOST:
if(status & FDC_ST_BUSY) {
//#ifdef _FDC_DEBUG_LOG
// command
// ----------------------------------------------------------------------------
+
void MB8877::process_cmd()
{
set_irq(false);
//#endif
// MB8877 mode commands
-//#ifdef _FDC_DEBUG_LOG
- static const _TCHAR *cmdstr[0x10] = {
- _T("RESTORE "), _T("SEEK "), _T("STEP "), _T("STEP "),
- _T("STEP IN "), _T("STEP IN "), _T("STEP OUT"), _T("STEP OUT"),
- _T("RD DATA "), _T("RD DATA "), _T("RD DATA "), _T("WR DATA "),
- _T("RD ADDR "), _T("FORCEINT"), _T("RD TRACK"), _T("WR TRACK")
- };
- if(fdc_debug_log) this->out_debug_log(_T("FDC\tCMD=%2xh (%s) DATA=%2xh DRV=%d TRK=%3d SIDE=%d SEC=%2d\n"), cmdreg, cmdstr[cmdreg >> 4], datareg, drvreg, trkreg, sidereg, secreg);
-//#endif
-
+ if(fdc_debug_log) {
+ _TCHAR tmps[512];
+ memset(tmps, 0x00, sizeof(tmps));
+ get_debug_regs_info(tmps, sizeof(tmps));
+ if(fdc_debug_log) this->out_debug_log(_T("%s"), tmps);
+ }
switch(cmdreg & 0xf8) {
// type-1
case 0x00: case 0x08:
seektrk = 0;
seekvct = true;
- register_seek_event();
+ register_seek_event(true);
}
void MB8877::cmd_seek()
} else {
status = FDC_ST_BUSY;
}
-
-// seektrk = (uint8_t)(fdc[drvreg].track + datareg - trkreg);
- seektrk = datareg;
+
+ // revert below 20180225 K.O
+ //seektrk = (uint8_t)(fdc[drvreg].track + datareg - trkreg); // Seek target is differ when drive's track != trkreg.Thanks to Haserin and Ryu Takegami.
+ seektrk = (int)((int8_t)datareg);
//#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV20) || defined(_FM77AV20EX)
- if(type_fm77av_2dd) {
- if(disk[drvreg]->drive_type != DRIVE_TYPE_2D) {
- seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
- } else {
- seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
- }
- } else if(disk[drvreg]->media_type != MEDIA_TYPE_2D){
- seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
- } else {
- seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
- }
+ if(seektrk >= disk[drvreg]->get_max_tracks()) {
+ seektrk = disk[drvreg]->get_max_tracks() - 1;
+ } else if(seektrk < 0) {
+ seektrk = 0;
+ }
+
seekvct = !(seektrk > fdc[drvreg].track);
-
- if(cmdreg & 4) {
- // verify
- if(trkreg != fdc[drvreg].track) {
- status |= FDC_ST_SEEKERR;
- trkreg = fdc[drvreg].track;
- }
- }
- register_seek_event();
+ // Update track register by data register.Thanks to Ryu Takegami. 20180224 K.O
+ trkreg = datareg;
+ set_irq(false);
+ set_drq(false);
+ register_seek_event(true);
}
void MB8877::cmd_step()
status = FDC_ST_HEADENG | FDC_ST_BUSY;
} else {
status = FDC_ST_BUSY;
- }
- seektrk = fdc[drvreg].track + 1;
- if(type_fm77av_2dd) {
- if(disk[drvreg]->drive_type != DRIVE_TYPE_2D) {
- seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
- } else {
- seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
- }
- } else if(disk[drvreg]->media_type != MEDIA_TYPE_2D){
- seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
- } else {
- seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
- }
- seekvct = false;
-
+ }
+
+ // Verify before execute command.
+ // Port from XM7.Thanks to Ryu Takegami.
+#if 1
if(cmdreg & 4) {
// verify
if(trkreg != fdc[drvreg].track) {
// trkreg = fdc[drvreg].track;
}
}
- register_seek_event();
+#endif
+ seektrk = fdc[drvreg].track + 1;
+ if(seektrk >= disk[drvreg]->get_max_tracks()) {
+ seektrk = disk[drvreg]->get_max_tracks() - 1;
+ } else if(seektrk < 0) {
+ seektrk = 0;
+ }
+ seekvct = false;
+ set_irq(false);
+ set_drq(false);
+ register_seek_event(true);
}
void MB8877::cmd_stepout()
status = FDC_ST_HEADENG | FDC_ST_BUSY;
} else {
status = FDC_ST_BUSY;
- }
-
- seektrk = fdc[drvreg].track - 1;
- if(type_fm77av_2dd) {
- if(disk[drvreg]->drive_type != DRIVE_TYPE_2D) {
- seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
- } else {
- seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
- }
- } else if(disk[drvreg]->media_type != MEDIA_TYPE_2D){
- seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
- } else {
- seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
- }
- seekvct = true;
-
+ }
+
+ // Verify before execute command.
+ // Port from XM7.Thanks to Ryu Takegami.
+#if 1
if(cmdreg & 4) {
// verify
if(trkreg != fdc[drvreg].track) {
// trkreg = fdc[drvreg].track;
}
}
- register_seek_event();
+#endif
+ seektrk = fdc[drvreg].track - 1;
+ if(seektrk >= disk[drvreg]->get_max_tracks()) {
+ seektrk = disk[drvreg]->get_max_tracks() - 1;
+ } else if(seektrk < 0) {
+ seektrk = 0;
+ }
+ seekvct = true;
+ register_seek_event(true);
}
void MB8877::cmd_readdata(bool first_sector)
if(status_tmp & FDC_ST_RECNFND) {
time = get_usec_to_detect_index_hole(5, first_sector && ((cmdreg & 4) != 0));
} else if(status & FDC_ST_WRITEFAULT) {
- time = (cmdreg & 4) ? DELAY_TIME : 1;
+ time = (cmdreg & 4) ? DELAY_AFTER_HLD : 1;
} else {
time = get_usec_to_start_trans(first_sector);
}
double time;
if(disk[drvreg]->write_protected) {
status_tmp = FDC_ST_WRITEFAULT;
- time = (cmdreg & 4) ? DELAY_TIME : 1;
+ time = (cmdreg & 4) ? DELAY_AFTER_HLD : 1;
} else {
if(cmdreg & 4) {
// wait 15msec before raise first drq
- fdc[drvreg].next_trans_position = (get_cur_position() + disk[drvreg]->get_bytes_per_usec(DELAY_TIME)) % disk[drvreg]->get_track_size();
- time = DELAY_TIME;
+ fdc[drvreg].next_trans_position = (get_cur_position() + disk[drvreg]->get_bytes_per_usec(DELAY_AFTER_HLD)) % disk[drvreg]->get_track_size();
+ time = DELAY_AFTER_HLD;
} else {
// raise first drq soon
fdc[drvreg].next_trans_position = (get_cur_position() + 1) % disk[drvreg]->get_track_size();
now_search = true;
status_tmp = FDC_ST_WRITEFAULT;
- double time = (cmdreg & 4) ? DELAY_TIME : 1;
+ double time = (cmdreg & 4) ? DELAY_AFTER_HLD : 1;
register_my_event(EVENT_SEARCH, time);
cancel_my_event(EVENT_LOST);
void MB8877::cmd_forceint()
{
// type-4 force interrupt
+ bool ready = (cmdtype == 0);
+ bool is_busy = ((status & FDC_ST_BUSY) != 0);
+ bool now_seek_bak = now_seek;
+ bool is_type1 = (cmdtype == FDC_CMD_TYPE1);
+ bool is_read = ((cmdtype == FDC_CMD_RD_SEC) || (cmdtype == FDC_CMD_RD_MSEC) || \
+ (cmdtype == FDC_CMD_RD_ADDR) || (cmdtype == FDC_CMD_RD_TRK));
+ bool is_trkwrite = (cmdtype == FDC_CMD_WR_TRK);
+
if(cmdtype == FDC_CMD_TYPE1) {
// abort restore/seek/step command
if(now_seek) {
if(seektrk > fdc[drvreg].track) {
- fdc[drvreg].track++;
+ if((fdc[drvreg].track < 0xff) && (fdc[drvreg].track >= 0)) fdc[drvreg].track++;
} else if(seektrk < fdc[drvreg].track) {
- fdc[drvreg].track--;
+ if((fdc[drvreg].track <= 0xff) && (fdc[drvreg].track > 0)) fdc[drvreg].track--;
}
- if((cmdreg_tmp & 0x10) || ((cmdreg_tmp & 0xf0) == 0)) {
+ // Not update track register if "SEEK" command.Thanks to Haserin. 20180224 K.O.
+ if((((cmdreg_tmp & 0x10) != 0) && (cmdreg_tmp >= 0x20)) || ((cmdreg_tmp & 0xf0) == 0)) {
trkreg = fdc[drvreg].track;
}
}
if(!type_fm7) status = FDC_ST_HEADENG; // Hack for FUKUALL.d77 .
}
status &= ~FDC_ST_BUSY;
-
+ if((now_seek_bak) || (ready)) {// Refer from XM7, is this write implement? 20180210 K.O
+ status = 0;
+ if(((ready) || !(is_busy)) && (!type_fm7)) status = FDC_ST_HEADENG;
+ // indexcount = 0;
+ if(check_drive2()) {
+ if(!(is_read) && (disk[drvreg]->write_protected)) status |= FDC_ST_WRITEP;
+ if((is_trkwrite) && (disk[drvreg]->write_protected)) status |= FDC_ST_WRITEFAULT;
+ if(is_type1) {
+ if(fdc[drvreg].track == 0) status |= FDC_ST_TRACK00;
+ if(get_cur_position() < disk[drvreg]->get_bytes_per_usec(5000)) {
+ status |= FDC_ST_INDEX;
+ }
+ }
+ }
+ }
// force interrupt if bit0-bit3 is high
if(cmdreg & 0x0f) {
set_irq(true);
{
// get track
int track = fdc[drvreg].track;
-//#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV20) || defined(_FM77AV20EX)
- if(type_fm77av_2dd) {
- if(disk[drvreg]->media_type == MEDIA_TYPE_2D) {
- if((disk[drvreg]->drive_type == DRIVE_TYPE_2DD) ||
- (disk[drvreg]->drive_type == DRIVE_TYPE_2HD) ||
- (disk[drvreg]->drive_type == DRIVE_TYPE_144)) {
- track >>= 1;
- }
- } else { // OS-9 2DD Access fix by Ryu Takegami
- if((disk[drvreg]->media_type != MEDIA_TYPE_2D) &&
- (disk[drvreg]->media_type != MEDIA_TYPE_UNK)) {
- if(disk[drvreg]->drive_type == DRIVE_TYPE_2D) {
- track <<= 1;
- }
- }
- }
- }
-//#endif
+
if(!disk[drvreg]->get_track(track, sidereg)){
return FDC_ST_SEEKERR;
}
// get track
int track = fdc[drvreg].track;
-//#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV20) || defined(_FM77AV20EX)
- if(type_fm77av_2dd) {
- if(disk[drvreg]->media_type == MEDIA_TYPE_2D) {
- if((disk[drvreg]->drive_type == DRIVE_TYPE_2DD) ||
- (disk[drvreg]->drive_type == DRIVE_TYPE_2HD) ||
- (disk[drvreg]->drive_type == DRIVE_TYPE_144)) {
- track >>= 1;
- }
- } else { // OS-9 2DD Access fix by Ryu Takegami
- if((disk[drvreg]->media_type != MEDIA_TYPE_2D) &&
- (disk[drvreg]->media_type != MEDIA_TYPE_UNK)) {
- if(disk[drvreg]->drive_type == DRIVE_TYPE_2D) {
- track <<= 1;
- }
- }
- }
- }
-//#endif
+
+
if(!disk[drvreg]->get_track(track, sidereg)) {
return FDC_ST_RECNFND;
}
{
// get track
int track = fdc[drvreg].track;
-//#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV20) || defined(_FM77AV20EX)
- if(type_fm77av_2dd) {
- if(disk[drvreg]->media_type == MEDIA_TYPE_2D) {
- if((disk[drvreg]->drive_type == DRIVE_TYPE_2DD) ||
- (disk[drvreg]->drive_type == DRIVE_TYPE_2HD) ||
- (disk[drvreg]->drive_type == DRIVE_TYPE_144)) {
- track >>= 1;
- }
- } else { // OS-9 2DD Access fix by Ryu Takegami
- if((disk[drvreg]->media_type != MEDIA_TYPE_2D) &&
- (disk[drvreg]->media_type != MEDIA_TYPE_UNK)) {
- if(disk[drvreg]->drive_type == DRIVE_TYPE_2D) {
- track <<= 1;
- }
- }
- }
- }
-//#endif
+
if(!disk[drvreg]->get_track(track, sidereg)) {
return FDC_ST_RECNFND;
}
{
// get time from current position
double time = get_usec_to_next_trans_pos(first_sector && ((cmdreg & 4) != 0));
- if(first_sector && time < 60000 - get_passed_usec(seekend_clock)) {
- time += disk[drvreg]->get_usec_per_track();
+
+ if(mb8877_delay_after_seek > 0) {
+ // wait 60ms to start read/write after seek is finished (FM-Techknow, p.180)
+ if(first_sector && time < mb8877_delay_after_seek - get_passed_usec(seekend_clock)) {
+ time += disk[drvreg]->get_usec_per_track();
+ }
}
return time;
}
return 50000;
}
if(delay) {
- position = (position + disk[drvreg]->get_bytes_per_usec(DELAY_TIME)) % disk[drvreg]->get_track_size();
+ position = (position + disk[drvreg]->get_bytes_per_usec(DELAY_AFTER_HLD)) % disk[drvreg]->get_track_size();
}
int bytes = fdc[drvreg].next_trans_position - position;
if(fdc[drvreg].next_am1_position < position || bytes < 0) {
}
double time = disk[drvreg]->get_usec_per_bytes(bytes);
if(delay) {
- time += DELAY_TIME;
+ time += DELAY_AFTER_HLD;
}
return time;
}
{
int position = get_cur_position();
if(delay) {
- position = (position + disk[drvreg]->get_bytes_per_usec(DELAY_TIME)) % disk[drvreg]->get_track_size();
+ position = (position + disk[drvreg]->get_bytes_per_usec(DELAY_AFTER_HLD)) % disk[drvreg]->get_track_size();
}
int bytes = disk[drvreg]->get_track_size() * count - position;
if(bytes < 0) {
}
double time = disk[drvreg]->get_usec_per_bytes(bytes);
if(delay) {
- time += DELAY_TIME;
+ time += DELAY_AFTER_HLD;
}
return time;
}
{
if(drv < _max_drive) {
disk[drv]->close();
- cmdtype = 0;
- update_head_flag(drvreg, false);
+ //cmdtype = 0;
+ if(drv == drvreg) {
+ cmdtype = 0;
+ }
+ update_head_flag(drv, false);
fdc[drv].count_immediate = false;
}
}
return false;
}
+uint8_t MB8877::get_media_type(int drv)
+{
+ if(drv < _max_drive) {
+ if(disk[drv]->inserted) {
+ return disk[drv]->media_type;
+ }
+ }
+ return MEDIA_TYPE_UNK;
+}
+
void MB8877::set_drive_type(int drv, uint8_t type)
{
if(drv < _max_drive) {
fdc_debug_log = config.special_debug_fdc;
}
-#define STATE_VERSION 6
+//#ifdef USE_DEBUGGER
+static const _TCHAR *cmdstr[0x10] = {
+ _T("RESTORE "), _T("SEEK "), _T("STEP "), _T("STEP "),
+ _T("STEP IN "), _T("STEP IN "), _T("STEP OUT"), _T("STEP OUT"),
+ _T("RD DATA "), _T("RD DATA "), _T("RD DATA "), _T("WR DATA "),
+ _T("RD ADDR "), _T("FORCEINT"), _T("RD TRACK"), _T("WR TRACK")
+};
-void MB8877::save_state(FILEIO* state_fio)
+bool MB8877::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
{
- state_fio->FputUint32(STATE_VERSION);
- state_fio->FputInt32(this_device_id);
+ int position = get_cur_position();
- state_fio->Fwrite(fdc, sizeof(fdc), 1);
- for(int i = 0; i < _max_drive; i++) {
- disk[i]->save_state(state_fio);
- }
- state_fio->FputUint8(status);
- state_fio->FputUint8(status_tmp);
- state_fio->FputUint8(cmdreg);
- state_fio->FputUint8(cmdreg_tmp);
- state_fio->FputUint8(trkreg);
- state_fio->FputUint8(secreg);
- state_fio->FputUint8(datareg);
- state_fio->FputUint8(drvreg);
- state_fio->FputUint8(sidereg);
- state_fio->FputUint8(cmdtype);
- state_fio->Fwrite(register_id, sizeof(register_id), 1);
- state_fio->FputBool(now_search);
- state_fio->FputBool(now_seek);
- state_fio->FputBool(sector_changed);
- state_fio->FputInt32(no_command);
- state_fio->FputInt32(seektrk);
- state_fio->FputBool(seekvct);
- state_fio->FputBool(motor_on);
- state_fio->FputBool(drive_sel);
- state_fio->FputUint32(prev_drq_clock);
- state_fio->FputUint32(seekend_clock);
+ my_stprintf_s(buffer, buffer_len,
+ _T("CMDREG=%02X (%s) DATAREG=%02X DRVREG=%02X TRKREG=%02X SIDEREG=%d SECREG=%02X\n")
+ _T("UNIT: DRIVE=%d TRACK=%2d SIDE=%d POSITION=%5d/%d"),
+ cmdreg, cmdstr[cmdreg >> 4], datareg, drvreg, trkreg, sidereg, secreg,
+ drvreg, fdc[drvreg].track, sidereg,
+ position, disk[drvreg]->get_track_size());
+
+ for(int i = 0; i < disk[drvreg]->sector_num.sd; i++) {
+ uint8_t c, h, r, n;
+ int length;
+ if(disk[drvreg]->get_sector_info(-1, -1, i, &c, &h, &r, &n, &length)) {
+ my_tcscat_s(buffer, buffer_len,
+ create_string(_T("\nSECTOR %2d: C=%02X H=%02X R=%02X N=%02X SIZE=%4d AM1=%5d DATA=%5d"), i + 1, c, h, r, n, length, disk[drvreg]->am1_position[i], disk[drvreg]->data_position[i]));
+ if(position >= disk[drvreg]->am1_position[i] && position < disk[drvreg]->data_position[i] + length) {
+ my_tcscat_s(buffer, buffer_len, _T(" <==="));
+ }
+ }
+ }
+ return true;
}
+//#endif
-bool MB8877::load_state(FILEIO* state_fio)
-{
- if(state_fio->FgetUint32() != STATE_VERSION) {
- return false;
- }
- if(state_fio->FgetInt32() != this_device_id) {
- return false;
- }
- state_fio->Fread(fdc, sizeof(fdc), 1);
- for(int i = 0; i < _max_drive; i++) {
- if(!disk[i]->load_state(state_fio)) {
- return false;
- }
- }
- status = state_fio->FgetUint8();
- status_tmp = state_fio->FgetUint8();
- cmdreg = state_fio->FgetUint8();
- cmdreg_tmp = state_fio->FgetUint8();
- trkreg = state_fio->FgetUint8();
- secreg = state_fio->FgetUint8();
- datareg = state_fio->FgetUint8();
- drvreg = state_fio->FgetUint8();
- sidereg = state_fio->FgetUint8();
- cmdtype = state_fio->FgetUint8();
- state_fio->Fread(register_id, sizeof(register_id), 1);
- now_search = state_fio->FgetBool();
- now_seek = state_fio->FgetBool();
- sector_changed = state_fio->FgetBool();
- no_command = state_fio->FgetInt32();
- seektrk = state_fio->FgetInt32();
- seekvct = state_fio->FgetBool();
- motor_on = state_fio->FgetBool();
- drive_sel = state_fio->FgetBool();
- prev_drq_clock = state_fio->FgetUint32();
- seekend_clock = state_fio->FgetUint32();
+#define STATE_VERSION 6
- fdc_debug_log = config.special_debug_fdc;
- return true;
+bool MB8877::process_state(FILEIO* state_fio, bool loading)
+{
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+//
+ for(int i = 0; i < array_length(fdc); i++) {
+ state_fio->StateValue(fdc[i].track);
+ state_fio->StateValue(fdc[i].index);
+ state_fio->StateValue(fdc[i].access);
+ state_fio->StateValue(fdc[i].head_load);
+ state_fio->StateValue(fdc[i].id_written);
+ state_fio->StateValue(fdc[i].sector_found);
+ state_fio->StateValue(fdc[i].sector_length);
+ state_fio->StateValue(fdc[i].sector_index);
+ state_fio->StateValue(fdc[i].side);
+ state_fio->StateValue(fdc[i].side_changed);
+ state_fio->StateValue(fdc[i].cur_position);
+ state_fio->StateValue(fdc[i].next_trans_position);
+ state_fio->StateValue(fdc[i].bytes_before_2nd_drq);
+ state_fio->StateValue(fdc[i].next_am1_position);
+ state_fio->StateValue(fdc[i].prev_clock);
+ }
+ for(int i = 0; i < array_length(disk); i++) {
+ if(disk[i] == NULL) continue;
+ if(!disk[i]->process_state(state_fio, loading)) {
+ return false;
+ }
+ }
+ state_fio->StateValue(status);
+ state_fio->StateValue(status_tmp);
+ state_fio->StateValue(cmdreg);
+ state_fio->StateValue(cmdreg_tmp);
+ state_fio->StateValue(trkreg);
+ state_fio->StateValue(secreg);
+ state_fio->StateValue(datareg);
+ state_fio->StateValue(drvreg);
+ state_fio->StateValue(sidereg);
+ state_fio->StateValue(cmdtype);
+ state_fio->StateArray(register_id, sizeof(register_id), 1);
+ state_fio->StateValue(now_search);
+ state_fio->StateValue(now_seek);
+ state_fio->StateValue(sector_changed);
+ state_fio->StateValue(no_command);
+ state_fio->StateValue(seektrk);
+ state_fio->StateValue(seekvct);
+ state_fio->StateValue(motor_on);
+ state_fio->StateValue(drive_sel);
+ state_fio->StateValue(prev_drq_clock);
+ state_fio->StateValue(seekend_clock);
+ if(loading) {
+ fdc_debug_log = config.special_debug_fdc;
+ }
+ return true;
}