#define FDC_CMD_RD_TRK 7
#define FDC_CMD_WR_TRK 8
-#define EVENT_SEEK 0
-#define EVENT_SEEKEND 1
-#define EVENT_SEARCH 2
-#define EVENT_DRQ 3
-#define EVENT_MULTI1 4
-#define EVENT_MULTI2 5
-#define EVENT_LOST 6
+#define EVENT_SEEK 0
+#define EVENT_SEEKEND_VERIFY 1
+#define EVENT_SEARCH 2
+#define EVENT_DRQ 3
+#define EVENT_MULTI1 4
+#define EVENT_MULTI2 5
+#define EVENT_LOST 6
//#define DRIVE_MASK (MAX_DRIVE - 1)
void MB8877::register_drq_event(int bytes)
{
- double usec = disk[drvreg]->get_usec_per_bytes(bytes) - get_passed_usec(prev_drq_clock);
+ double nusec = disk[drvreg]->get_usec_per_bytes(bytes); // For debug
+ double usec = nusec - get_passed_usec(prev_drq_clock);
+
if(usec < 4) {
usec = 4;
}
-//#if defined(_FM7) || defined(_FM8) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
if(type_fm7) {
if((disk[drvreg]->is_special_disk == SPECIAL_DISK_FM7_GAMBLER) ||
- (disk[drvreg]->is_special_disk == SPECIAL_DISK_FM77AV_PSYOBLADE)) {
- usec = 4;
+ /* (disk[drvreg]->is_special_disk == SPECIAL_DISK_FM77AV_PSYOBLADE) || */
+ (config.correct_disk_timing[drvreg])) {
+ usec = 7;
}
}
-//#endif
+ this->out_debug_log("DRQ REG: %dbytes %d:%d -> %f\n", bytes, get_current_clock(), prev_drq_clock, usec);
cancel_my_event(EVENT_DRQ);
register_event(this, (EVENT_DRQ << 8) | (cmdtype & 0xff), usec, false, ®ister_id[EVENT_DRQ]);
}
register_event(this, (EVENT_LOST << 8) | (cmdtype & 0xff), disk[drvreg]->get_usec_per_bytes(bytes), false, ®ister_id[EVENT_LOST]);
}
+bool MB8877::check_drive(void)
+{
+ if(drvreg >= _max_drive) {
+ status = FDC_ST_NOTREADY;
+ //set_drq(false);
+ set_irq(true);
+ return false;
+ }
+ return true;
+}
+
+bool MB8877::check_drive2(void)
+{
+ if(!check_drive()) {
+ return false;
+ }
+ if(!is_disk_inserted(drvreg & 0x7f)) {
+ status = FDC_ST_NOTREADY;
+ set_irq(true);
+ //set_drq(false);
+ return false;
+ }
+ return true;
+}
+
void MB8877::initialize()
{
DEVICE::initialize();
// initialize d88 handler
- _max_drive = osd->get_feature_int_value(_T("MAX_DRIVE"));
+ if(osd->check_feature(_T("MAX_DRIVE"))) {
+ _max_drive = osd->get_feature_int_value(_T("MAX_DRIVE"));
+ } else if(osd->check_feature(_T("MAX_FD"))) {
+ _max_drive = osd->get_feature_int_value(_T("MAX_FD"));
+ } else {
+ _max_drive = 1;
+ }
_drive_mask = _max_drive - 1;
for(int i = 0; i < _max_drive; i++) {
disk[i] = new DISK(emu);
// initialize timing
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;
void MB8877::reset()
{
for(int i = 0; i < _max_drive; i++) {
- fdc[i].track = 0;
+ //fdc[i].track = 0; // Hold to track
fdc[i].index = 0;
fdc[i].access = false;
}
} else {
register_drq_event(1);
}
+ if(fdc[drvreg].count_immediate) fdc[drvreg].index++;
}
status &= ~FDC_ST_DRQ;
} else if(cmdtype == FDC_CMD_WR_TRK) {
} else {
register_drq_event(1);
}
+ if(fdc[drvreg].count_immediate) fdc[drvreg].index++;
}
status &= ~FDC_ST_DRQ;
}
// read or multisector read
if(fdc[drvreg].index < disk[drvreg]->sector_size.sd) {
datareg = disk[drvreg]->sector[fdc[drvreg].index];
- //fdc[drvreg].index++;
}
- if((fdc[drvreg].index + 1) >= disk[drvreg]->sector_size.sd) {
+ if((fdc[drvreg].index + 1) >= disk[drvreg]->sector_size.sd) { // Reading complete this sector.
if(disk[drvreg]->data_crc_error && !disk[drvreg]->ignore_crc()) {
// data crc error
register_my_event(EVENT_MULTI1, 30);
register_my_event(EVENT_MULTI2, 60);
}
- } else {
+ } else { // Still data remain.
register_drq_event(1);
+ if(fdc[drvreg].count_immediate) fdc[drvreg].index++;
}
status &= ~FDC_ST_DRQ;
} else if(cmdtype == FDC_CMD_RD_ADDR) {
//#endif
} else {
register_drq_event(1);
+ if(fdc[drvreg].count_immediate) fdc[drvreg].index++;
}
status &= ~FDC_ST_DRQ;
} else if(cmdtype == FDC_CMD_RD_TRK) {
set_irq(true);
} else {
register_drq_event(1);
+ if(fdc[drvreg].count_immediate) fdc[drvreg].index++;
}
status &= ~FDC_ST_DRQ;
}
}
}
//#ifdef _FDC_DEBUG_LOG
- if(fdc_debug_log) this->out_debug_log(_T("FDC\tDATA=%2x\n"), datareg);
+ if(fdc_debug_log) this->force_out_debug_log(_T("FDC\tDATA=%2x\n"), datareg); // emu->force_out_debug_log()
//#endif
//#if defined(HAS_MB8866) || defined(HAS_MB8876)
if(invert_registers) {
sidereg = (data & mask) ? 1 : 0;
} else if(id == SIG_MB8877_MOTOR) {
motor_on = ((data & mask) != 0);
- }
+ }
}
uint32_t MB8877::read_signal(int ch)
{
int event = event_id >> 8;
int cmd = event_id & 0xff;
+ //bool need_after_irq = false;
register_id[event] = -1;
// cancel event if the command is finished or other command is executed
if(cmd != cmdtype) {
- if(event == EVENT_SEEK || event == EVENT_SEEKEND) {
+ if(event == EVENT_SEEK || event == EVENT_SEEKEND_VERIFY) {
now_seek = false;
} else if(event == EVENT_SEARCH) {
now_search = false;
if(seektrk > fdc[drvreg].track) {
fdc[drvreg].track++;
if(d_noise_seek != NULL) d_noise_seek->play();
+ //need_after_irq = true;
} else if(seektrk < fdc[drvreg].track) {
fdc[drvreg].track--;
if(d_noise_seek != NULL) d_noise_seek->play();
+ //need_after_irq = true;
}
if((cmdreg & 0x10) || ((cmdreg & 0xf0) == 0)) {
trkreg = fdc[drvreg].track;
}
if(seektrk != 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();
break;
}
} else {
time = get_usec_to_next_trans_pos(true);
}
- register_my_event(EVENT_SEEKEND, time);
+ // 20180128 K.O If seek completed, delay to make IRQ/DRQ at SEEKEND_VERIFY.
+ register_my_event(EVENT_SEEKEND_VERIFY, time);
break;
}
- case EVENT_SEEKEND:
+// case EVENT_SEEKEND: // Separate SEEK and SEEKEND when verifying. 20180128 K.O
now_seek = false;
status = status_tmp;
- set_irq(true);
+ status &= (uint8_t)(~FDC_ST_BUSY); // 20180118 K.O Turn off BUSY flag.
+ set_drq(false);
+ set_irq(true); // 20180118 K.O Turn ON IRQ -> Turn OFF DRQ
+ break;
+ case EVENT_SEEKEND_VERIFY: // Separate SEEK and SEEKEND when verifying. 20180128 K.O
+ now_seek = false;
+ status &= (uint8_t)(~FDC_ST_BUSY); // 20180118 K.O Turn off BUSY flag.
+ set_drq(false);
+ set_irq(true); // 20180118 K.O Turn ON IRQ -> Turn OFF DRQ
//#ifdef _FDC_DEBUG_LOG
//this->out_debug_log(_T("FDC\tSEEK END\n"));
//#endif
if(type_x1) {
// for SHARP X1 Batten Tanuki
if(disk[drvreg]->is_special_disk == SPECIAL_DISK_X1_BATTEN && drive_sel) {
- status_tmp &= ~FDC_ST_RECNFND;
- }
+ status_tmp &= ~FDC_ST_RECNFND;
+ }
}
//#endif
//#ifdef _FDC_DEBUG_LOG
- if(fdc_debug_log) this->out_debug_log(_T("FDC\tSEARCH NG\n"));
+ if(fdc_debug_log) this->out_debug_log(_T("FDC\tSEARCH NG\n"));
//#endif
status = status_tmp & ~(FDC_ST_BUSY | FDC_ST_DRQ);
cmdtype = 0;
+ set_drq(false);
set_irq(true);
} else if(status_tmp & FDC_ST_WRITEFAULT) {
//#ifdef _FDC_DEBUG_LOG
//#endif
status = status_tmp & ~(FDC_ST_BUSY | FDC_ST_DRQ);
cmdtype = 0;
+ set_drq(false);
set_irq(true);
} else {
status = status_tmp | (FDC_ST_BUSY | FDC_ST_DRQ);
fdc[drvreg].prev_clock = prev_drq_clock = get_current_clock();
set_drq(true);
drive_sel = false;
+ this->out_debug_log("DRQ ON@SEARCH: %d\n", prev_drq_clock);
//#ifdef _FDC_DEBUG_LOG
if(fdc_debug_log) this->out_debug_log(_T("FDC\tSEARCH OK\n"));
//#endif
cmdtype == FDC_CMD_WR_SEC || cmdtype == FDC_CMD_WR_MSEC ||
cmdtype == FDC_CMD_RD_TRK || cmdtype == FDC_CMD_WR_TRK ||
cmdtype == FDC_CMD_RD_ADDR) {
- fdc[drvreg].index++;
+ if(!(fdc[drvreg].count_immediate)) fdc[drvreg].index++;
}
fdc[drvreg].prev_clock = prev_drq_clock = get_current_clock();
+
set_drq(true);
+ this->out_debug_log("DRQ ON@DRQ: %d\n", prev_drq_clock);
//#ifdef _FDC_DEBUG_LOG
//this->out_debug_log(_T("FDC\tDRQ!\n"));
//#endif
case EVENT_LOST:
if(status & FDC_ST_BUSY) {
//#ifdef _FDC_DEBUG_LOG
- if(fdc_debug_log) this->out_debug_log(_T("FDC\tDATA LOST\n"));
+ if(fdc_debug_log) this->out_debug_log(_T("FDC\tDATA LOST\n"));
//#endif
if(cmdtype == FDC_CMD_WR_SEC || cmdtype == FDC_CMD_WR_MSEC || cmdtype == FDC_CMD_WR_TRK) {
- if(fdc[drvreg].index == 0) {
- status &= ~FDC_ST_BUSY;
- //status &= ~FDC_ST_DRQ;
+ if(fdc[drvreg].index == 0) { // HEAD of REGION
cmdtype = 0;
+ //if((status & FDC_ST_DRQ) != 0) { // 20180130 FORCE DOWN DRQ ON LOST-DATA.
+ status |= FDC_ST_LOSTDATA;
+ status &= (uint8_t)(~(FDC_ST_DRQ | FDC_ST_BUSY));
+ set_drq(false);
+ //}
set_irq(true);
- //set_drq(false);
- } else {
+ } else { // STILL WRITING
write_io8(3, 0x00);
+ //if((status & FDC_ST_DRQ) != 0) {
+ status |= FDC_ST_LOSTDATA;
+ status &= (uint8_t)(~(FDC_ST_DRQ | FDC_ST_BUSY));
+ set_irq(true);
+ set_drq(false);
+ //cmdtype = 0;
+ //}
}
- } else {
+ } else { // READ
+ //if((status & FDC_ST_DRQ) != 0) {
+ status |= FDC_ST_LOSTDATA;
+ status &= (uint8_t)(~(FDC_ST_DRQ | FDC_ST_BUSY));
+ set_irq(true);
+ set_drq(false);
+ //}
read_io8(3);
}
status |= FDC_ST_LOSTDATA;
{
// type-1 restore
cmdtype = FDC_CMD_TYPE1;
- status = FDC_ST_HEADENG | FDC_ST_BUSY;
- trkreg = 0xff;
+ if(!check_drive()) {
+ return;
+ }
+ if((cmdreg & 0x08) != 0) { // Head engage
+ status = FDC_ST_HEADENG | FDC_ST_BUSY;
+ } else {
+ status = FDC_ST_BUSY;
+ }
+ set_irq(false);
+ set_drq(false);
+
+ if(fdc[drvreg].track < 0) {
+ fdc[drvreg].track = 0;
+ trkreg = 0;
+ } else if(fdc[drvreg].track >= 80) {
+ fdc[drvreg].track = 80;
+ trkreg = 80;
+ } else {
+ trkreg = fdc[drvreg].track;
+ }
datareg = 0;
seektrk = 0;
{
// type-1 seek
cmdtype = FDC_CMD_TYPE1;
- status = FDC_ST_HEADENG | FDC_ST_BUSY;
+ if(!check_drive()) {
+ return;
+ }
+ if((cmdreg & 0x08) != 0) { // Head engage
+ status = FDC_ST_HEADENG | FDC_ST_BUSY;
+ } else {
+ status = FDC_ST_BUSY;
+ }
// seektrk = (uint8_t)(fdc[drvreg].track + datareg - trkreg);
seektrk = datareg;
} else {
seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
}
-//#else
-// if(disk[drvreg]->media_type != MEDIA_TYPE_2D){
-//#endif
-// seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
-// } else {
-// seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
-// }
-// seekvct = !(datareg > trkreg);
seekvct = !(seektrk > fdc[drvreg].track);
if(cmdreg & 4) {
{
// type-1 step in
cmdtype = FDC_CMD_TYPE1;
- status = FDC_ST_HEADENG | FDC_ST_BUSY;
-
+ if(!check_drive()) {
+ return;
+ }
+ if((cmdreg & 0x08) != 0) { // Head engage
+ status = FDC_ST_HEADENG | FDC_ST_BUSY;
+ } else {
+ status = FDC_ST_BUSY;
+ }
seektrk = fdc[drvreg].track + 1;
-//#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV20) || defined(_FM77AV20EX)
-// if(disk[drvreg]->drive_type != DRIVE_TYPE_2D) {
-//#else
-// if(disk[drvreg]->media_type != MEDIA_TYPE_2D){
-//#endif
-// seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
-// } else {
-// seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
-// }
if(type_fm77av_2dd) {
if(disk[drvreg]->drive_type != DRIVE_TYPE_2D) {
seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
{
// type-1 step out
cmdtype = FDC_CMD_TYPE1;
- status = FDC_ST_HEADENG | FDC_ST_BUSY;
+ if(!check_drive()) {
+ return;
+ }
+ if((cmdreg & 0x08) != 0) { // Head engage
+ status = FDC_ST_HEADENG | FDC_ST_BUSY;
+ } else {
+ status = FDC_ST_BUSY;
+ }
seektrk = fdc[drvreg].track - 1;
if(type_fm77av_2dd) {
} else {
seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
}
-//#if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV20) || defined(_FM77AV20EX)
-// if(disk[drvreg]->drive_type != DRIVE_TYPE_2D) {
-//#else
-// if(disk[drvreg]->media_type != MEDIA_TYPE_2D){
-//#endif
-// seektrk = (seektrk > 83) ? 83 : (seektrk < 0) ? 0 : seektrk;
-// } else {
-// seektrk = (seektrk > 41) ? 41 : (seektrk < 0) ? 0 : seektrk;
-// }
seekvct = true;
if(cmdreg & 4) {
{
// type-2 read data
cmdtype = (cmdreg & 0x10) ? FDC_CMD_RD_MSEC : FDC_CMD_RD_SEC;
+ if(!check_drive2()) {
+ return;
+ }
status = FDC_ST_BUSY;
status_tmp = search_sector();
now_search = true;
{
// type-2 write data
cmdtype = (cmdreg & 0x10) ? FDC_CMD_WR_MSEC : FDC_CMD_WR_SEC;
+ if(!check_drive2()) {
+ return;
+ }
status = FDC_ST_BUSY;
status_tmp = search_sector() & ~FDC_ST_RECTYPE;
now_search = true;
{
// type-3 read address
cmdtype = FDC_CMD_RD_ADDR;
+ if(!check_drive2()) {
+ return;
+ }
status = FDC_ST_BUSY;
status_tmp = search_addr();
now_search = true;
{
// type-3 read track
cmdtype = FDC_CMD_RD_TRK;
+ if(!check_drive2()) {
+ return;
+ }
status = FDC_ST_BUSY;
status_tmp = 0;
{
// type-3 write track
cmdtype = FDC_CMD_WR_TRK;
+ if(!check_drive2()) {
+ return;
+ }
status = FDC_ST_BUSY;
status_tmp = 0;
//#endif
if(cmdtype == 0 || !(status & FDC_ST_BUSY)) {
cmdtype = FDC_CMD_TYPE1;
- status = FDC_ST_HEADENG;
+ if(!type_fm7) status = FDC_ST_HEADENG; // Hack for FUKUALL.d77 .
}
status &= ~FDC_ST_BUSY;
//#endif
cancel_my_event(EVENT_SEEK);
- cancel_my_event(EVENT_SEEKEND);
+ cancel_my_event(EVENT_SEEKEND_VERIFY);
cancel_my_event(EVENT_SEARCH);
cancel_my_event(EVENT_DRQ);
cancel_my_event(EVENT_MULTI1);
(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
(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
(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(drv < _max_drive) {
disk[drv]->open(file_path, bank);
+#if defined(_USE_QT)
+ if((disk[drv]->is_special_disk == SPECIAL_DISK_FM7_FLEX) || (config.disk_count_immediate[drv])) {
+#else
+ if(disk[drv]->is_special_disk == SPECIAL_DISK_FM7_FLEX) {
+#endif
+ fdc[drv].count_immediate = true;
+ } else {
+ fdc[drv].count_immediate = false;
+ }
}
}
disk[drv]->close();
cmdtype = 0;
update_head_flag(drvreg, false);
+ fdc[drv].count_immediate = false;
}
}
}
}
-#define STATE_VERSION 5
+#define STATE_VERSION 6
void MB8877::save_state(FILEIO* state_fio)
{