2 // PC-6001/6601 disk I/O
3 // This file is based on a disk I/O program in C++
4 // by Mr. Yumitaro and translated into C for Cocoa iP6
5 // by Koichi NISHIDA 2006
9 Skelton for retropc emulator
11 Author : Takeda.Toshiya
22 int PC6031::Seek88(int drvno, int trackno, int sectno)
25 if(cur_trk[drvno] != trackno) {
26 if(d_noise_seek != NULL) d_noise_seek->play();
28 cur_trk[drvno] = trackno;
29 cur_sct[drvno] = sectno;
32 if(disk[drvno]->get_track(trackno >> 1, trackno & 1)) {
33 for(int i = 0; i < disk[drvno]->sector_num.sd; i++) {
34 if(disk[drvno]->get_sector(trackno >> 1, 0/*trackno & 1*/, i)) {
35 if(disk[drvno]->id[2] == sectno) {
45 unsigned char PC6031::Getc88(int drvno)
47 if(drvno < 2 && disk[drvno]->sector != NULL) {
48 if(cur_pos[drvno] >= disk[drvno]->sector_size.sd) {
50 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
54 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
60 return disk[drvno]->sector[cur_pos[drvno]++];
65 int PC6031::Putc88(int drvno, unsigned char dat)
67 if(drvno < 2 && disk[drvno]->sector != NULL) {
68 if(cur_pos[drvno] >= disk[drvno]->sector_size.sd) {
70 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
74 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
80 disk[drvno]->sector[cur_pos[drvno]++] = dat;
95 SEND_RESULT_STATUS = 0x06,
96 SEND_DRIVE_STATUS = 0x07,
101 WAIT = 0xff, // waiting state
105 // data input (port D0H)
106 unsigned char PC6031::FddIn60()
110 if (mdisk.DAV) { // if data is valid
111 if (mdisk.step == 6) {
112 mdisk.retdat = Getc88(mdisk.drv);
113 if(--mdisk.size == 0) mdisk.step = 0;
117 } else { // if data is not valid
123 // data/command output (port D1H)
124 void PC6031::FddOut60(unsigned char dat)
126 if (mdisk.command == WAIT) { // when command
128 switch (mdisk.command) {
129 case INIT: // 00h init
131 case WRITE_DATA: // 01h write data
134 case READ_DATA: // 02h read data
137 case SEND_DATA: // 03h send data
140 case COPY: // 04h copy
142 case FORMAT: // 05h format
144 case SEND_RESULT_STATUS: // 06h send result status
147 case SEND_DRIVE_STATUS: // 07h send drive status
148 mdisk.retdat |= 0x0a;
150 case TRANSMIT: // 11h transnmit
152 case RECEIVE: // 12h receive
154 case LOAD: // 14h load
156 case SAVE: // 15h save
159 } else { // when data
160 switch (mdisk.command) {
161 case WRITE_DATA: // 01h write data
162 switch (mdisk.step) {
163 case 1: // 01h:block number
165 mdisk.size = mdisk.blk*256;
168 case 2: // 02h:drive number - 1
172 case 3: // 03h:track number
176 case 4: // 04h:sector number
178 // double track number(1D->2D)
179 Seek88(mdisk.drv, mdisk.trk*2, mdisk.sct);
182 case 5: // 05h:write data
183 Putc88(mdisk.drv, dat);
184 if( --mdisk.size == 0 ){
190 case READ_DATA: // 02h read data
191 switch (mdisk.step) {
192 case 1: // 01h:block number
194 mdisk.size = mdisk.blk*256;
197 case 2: // 02h:drive number-1
201 case 3: // 03h:track number
205 case 4: // 04h:sector number
207 // double track number(1D->2D)
208 Seek88(mdisk.drv, mdisk.trk*2, mdisk.sct);
216 // control input from disk unit (port D2H)
217 unsigned char PC6031::FddCntIn60(void)
219 if ((((old_D2H & 0x01) ^ mdisk.DAV) != 0) || (mdisk.RFD != 0) && (mdisk.DAV != 0)) { // ToDo: Check Logic 20180614 K.O
220 mdisk.DAC = mdisk.DAV;
221 } else if (mdisk.ATN != 0) {
223 mdisk.command = WAIT;
224 } else if (mdisk.DAC != 0) {
226 } else if (mdisk.RFD != 0) {
230 io_D2H = 0xf0 | 0x08 /* (mdisk.ATN<<3) */ | (mdisk.DAC<<2) | (mdisk.RFD<<1) | mdisk.DAV;
234 // control output to disk unit (port D3H)
235 void PC6031::FddCntOut60(unsigned char dat)
237 // 8255 basic behavior
238 if (!(dat&0x80)) { // check msb
240 switch ((dat>>1)&0x07) {
254 io_D2H = 0xf0 | 0x08 /* (mdisk.ATN<<3) */ | (mdisk.DAC<<2) | (mdisk.RFD<<1) | mdisk.DAV;
258 // I/O access functions
259 void PC6031::OutD1H_60(unsigned char data) { io_D1H = data; FddOut60(io_D1H); }
260 void PC6031::OutD2H_60(unsigned char data) {
261 mdisk.ATN = (data & 0x80) >> 7;
262 mdisk.DAC = (data & 0x40) >> 6;
263 mdisk.RFD = (data & 0x20) >> 5;
264 mdisk.DAV = (data & 0x10) >> 4;
265 io_D2H = 0xf0 | 0x08 /* (mdisk.ATN<<3) */ | (mdisk.DAC<<2) | (mdisk.RFD<<1) | mdisk.DAV;
267 void PC6031::OutD3H_60(unsigned char data) { io_D3H = data; FddCntOut60(io_D3H); }
269 unsigned char PC6031::InD0H_60() { return FddIn60(); }
270 unsigned char PC6031::InD1H_60() { return io_D1H; }
271 unsigned char PC6031::InD2H_60() { io_D2H = FddCntIn60(); return io_D2H; }
272 unsigned char PC6031::InD3H_60() { return io_D3H; }
274 void PC6031::initialize()
276 for(int i = 0; i < 2; i++) {
277 disk[i] = new DISK(emu);
278 disk[i]->set_device_name(_T("%s/Disk #%d"), this_device_name, i + 1);
279 disk[i]->drive_type = DRIVE_TYPE_2D;
281 if(d_noise_seek != NULL) {
282 d_noise_seek->set_device_name(_T("Noise Player (FDD Seek)"));
283 if(!d_noise_seek->load_wav_file(_T("FDDSEEK.WAV"))) {
284 if(!d_noise_seek->load_wav_file(_T("FDDSEEK1.WAV"))) {
285 d_noise_seek->load_wav_file(_T("SEEK.WAV"));
288 d_noise_seek->set_mute(!config.sound_noise_fdd);
290 // if(d_noise_head_down != NULL) {
291 // d_noise_head_down->set_device_name(_T("Noise Player (FDD Head Load)"));
292 // d_noise_head_down->load_wav_file(_T("HEADDOWN.WAV"));
293 // d_noise_head_down->set_mute(!config.sound_noise_fdd);
295 // if(d_noise_head_up != NULL) {
296 // d_noise_head_up->set_device_name(_T("Noise Player (FDD Head Unload)"));
297 // d_noise_head_up->load_wav_file(_T("HEADUP.WAV"));
298 // d_noise_head_up->set_mute(!config.sound_noise_fdd);
301 memset(&mdisk, 0, sizeof(DISK60));
302 mdisk.command = WAIT; // received command
303 mdisk.retdat = 0xff; // data from port D0H
305 io_D2H = 0xf0 | 0x08 /* (mdisk.ATN<<3) */ | (mdisk.DAC<<2) | (mdisk.RFD<<1) | mdisk.DAV;
310 void PC6031::release()
312 for(int i = 0; i < 2; i++) {
320 void PC6031::write_io8(uint32_t addr, uint32_t data)
335 uint32_t PC6031::read_io8(uint32_t addr)
339 return InD0H_60(); break;
341 return InD1H_60(); break;
343 return InD2H_60(); break;
345 return InD3H_60(); break;
350 uint32_t PC6031::read_signal(int ch)
354 for(int drv = 0; drv < 2; drv++) {
363 // ----------------------------------------------------------------------------
365 // ----------------------------------------------------------------------------
367 void PC6031::open_disk(int drv, const _TCHAR* file_path, int bank)
370 disk[drv]->open(file_path, bank);
375 void PC6031::close_disk(int drv)
377 if(drv < 2 && disk[drv]->inserted) {
382 bool PC6031::is_disk_inserted(int drv)
385 return disk[drv]->inserted;
390 bool PC6031::disk_ejected(int drv)
393 return disk[drv]->ejected;
398 void PC6031::is_disk_protected(int drv, bool value)
401 disk[drv]->write_protected = value;
405 bool PC6031::is_disk_protected(int drv)
408 return disk[drv]->write_protected;
413 void PC6031::update_config()
415 if(d_noise_seek != NULL) {
416 d_noise_seek->set_mute(!config.sound_noise_fdd);
418 // if(d_noise_head_down != NULL) {
419 // d_noise_head_down->set_mute(!config.sound_noise_fdd);
421 // if(d_noise_head_up != NULL) {
422 // d_noise_head_up->set_mute(!config.sound_noise_fdd);
426 #define STATE_VERSION 1
428 bool PC6031::process_state(FILEIO* state_fio, bool loading)
430 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
433 if(!state_fio->StateCheckInt32(this_device_id)) {
436 for(int i = 0; i < 2; i++) {
437 if(!disk[i]->process_state(state_fio, loading)) {
441 // state_fio->StateBuffer(cur_trk, sizeof(cur_trk), 1);
442 // state_fio->StateBuffer(cur_sct, sizeof(cur_sct), 1);
443 // state_fio->StateBuffer(cur_pos, sizeof(cur_pos), 1);
444 // state_fio->StateBuffer(access, sizeof(access), 1);
445 // state_fio->StateBuffer(&mdisk, sizeof(DISK60), 1);
446 for(int i = 0; i < (sizeof(cur_trk) / sizeof(int)); i++) {
447 state_fio->StateInt32(cur_trk[i]);
449 for(int i = 0; i < (sizeof(cur_sct) / sizeof(int)); i++) {
450 state_fio->StateInt32(cur_sct[i]);
452 for(int i = 0; i < (sizeof(cur_pos) / sizeof(int)); i++) {
453 state_fio->StateInt32(cur_pos[i]);
455 for(int i = 0; i < (sizeof(access) / sizeof(bool)); i++) {
456 state_fio->StateBool(access[i]);
460 state_fio->StateInt32(mdisk.ATN);
461 state_fio->StateInt32(mdisk.DAC);
462 state_fio->StateInt32(mdisk.RFD);
463 state_fio->StateInt32(mdisk.DAV);
465 state_fio->StateInt32(mdisk.command);
466 state_fio->StateInt32(mdisk.step);
467 state_fio->StateInt32(mdisk.blk);
469 state_fio->StateInt32(mdisk.drv);
470 state_fio->StateInt32(mdisk.trk);
471 state_fio->StateInt32(mdisk.sct);
472 state_fio->StateInt32(mdisk.size);
474 state_fio->StateUint8(mdisk.retdat);
476 state_fio->StateUint8(io_D1H);
477 state_fio->StateUint8(io_D2H);
478 state_fio->StateUint8(old_D2H);
479 state_fio->StateUint8(io_D3H);
480 state_fio->StateInt32(DrvNum);