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 NEC PC-6601 Emulator 'yaPC-6601'
10 NEC PC-6601SR Emulator 'yaPC-6801'
15 [ internal floppy drive ]
20 #include "../../fileio.h"
22 int FLOPPY::Seek88(int drvno, int trackno, int sectno)
25 cur_trk[drvno] = trackno;
26 cur_sct[drvno] = sectno;
29 if(disk[drvno]->get_track(trackno >> 1, trackno & 1)) {
30 for(int i = 0; i < disk[drvno]->sector_num; i++) {
31 if(disk[drvno]->get_sector(trackno >> 1, 0/*trackno & 1*/, i)) {
32 if(disk[drvno]->id[2] == sectno) {
42 unsigned char FLOPPY::Getc88(int drvno)
44 if(drvno < 2 && disk[drvno]->sector != NULL) {
45 if(cur_pos[drvno] >= disk[drvno]->sector_size) {
47 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
51 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
57 return disk[drvno]->sector[cur_pos[drvno]++];
62 int FLOPPY::Putc88(int drvno, unsigned char dat)
64 if(drvno < 2 && disk[drvno]->sector != NULL) {
65 if(cur_pos[drvno] >= disk[drvno]->sector_size) {
67 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
71 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
77 disk[drvno]->sector[cur_pos[drvno]++] = dat;
83 // push data to data buffer
84 void FLOPPY::Push(int part, unsigned char data)
88 if(Index[part] < 256) Data[part][Index[part]++] = data;
91 // pop data from data buffer
92 unsigned char FLOPPY::Pop(int part)
94 if(part > 3) return 0xff;
96 if(Index[part] > 0) return Data[part][--Index[part]];
101 void FLOPPY::Clear(int i)
107 #define FDC_BUSY (0x10)
108 #define FDC_READY (0x00)
109 #define FDC_NON_DMA (0x20)
110 #define FDC_FD2PC (0x40)
111 #define FDC_PC2FD (0x00)
112 #define FDC_DATA_READY (0x80)
115 #define ST0_NOT_READY (0x08)
116 #define ST0_EQUIP_CHK (0x10)
117 #define ST0_SEEK_END (0x20)
118 #define ST0_IC_NT (0x00)
119 #define ST0_IC_AT (0x40)
120 #define ST0_IC_IC (0x80)
121 #define ST0_IC_AI (0xc0)
124 #define ST1_NOT_WRITABLE (0x02)
129 #define ST3_TRACK0 (0x10)
130 #define ST3_READY (0x20)
131 #define ST3_WRITE_PROTECT (0x40)
132 #define ST3_FAULT (0x80)
135 int FLOPPY::DiskInit66(void)
137 memset( &CmdIn, 0, sizeof( CmdBuffer ) );
138 memset( &CmdOut, 0, sizeof( CmdBuffer ) );
143 Status = FDC_DATA_READY | FDC_READY | FDC_PC2FD;
147 // push data to status buffer
148 void FLOPPY::PushStatus(int data)
150 CmdOut.Data[CmdOut.Index++] = data;
153 // pop data from status buffer
154 unsigned char FLOPPY::PopStatus()
156 return CmdOut.Data[--CmdOut.Index];
160 void FLOPPY::OutFDC(unsigned char data)
162 const int CmdLength[] = { 0,0,0,3,2,9,9,2,1,0,0,0,0,6,0,3 };
164 CmdIn.Data[CmdIn.Index++] = data;
165 if (CmdLength[CmdIn.Data[0]&0xf] == CmdIn.Index) Exec();
169 unsigned char FLOPPY::InFDC()
171 if (CmdOut.Index == 1) Status = FDC_DATA_READY | FDC_PC2FD;
181 Drv = CmdIn.Data[1]&3; // drive number No.(0-3)
182 C = CmdIn.Data[2]; // cylinder
183 H = CmdIn.Data[3]; // head address
184 R = CmdIn.Data[4]; // sector No.
185 N = CmdIn.Data[5] ? CmdIn.Data[5]*256 : 256; // sector size
187 if (disk[Drv]->inserted) {
189 // double track number(1D->2D)
190 Seek88(Drv, C*2+H, R);
191 for (i = 0; i < SendSectors; i++) {
194 Push(i, Getc88(Drv));
201 PushStatus(0); // st2
202 PushStatus(0); // st1
203 PushStatus(disk[Drv]->inserted ? 0 : ST0_NOT_READY); // st0 bit3 : media not ready
204 Status = FDC_DATA_READY | FDC_FD2PC;
208 void FLOPPY::Write(void)
213 Drv = CmdIn.Data[1]&3; // drive No.(0-3)
214 C = CmdIn.Data[2]; // cylinder
215 H = CmdIn.Data[3]; // head address
216 R = CmdIn.Data[4]; // sector No.
217 N = CmdIn.Data[5] ? CmdIn.Data[5]*256 : 256; // sector size
219 if (disk[Drv]->inserted) {
221 // double track number(1D->2D)
222 Seek88(Drv, C*2+H, R);
223 for (i=0; i<SendSectors; i++) {
224 for(j=0; j<0x100; j++)
225 Putc88(Drv, Pop(i)); // write data
233 PushStatus(0); // st2
234 PushStatus(0); // st1
236 PushStatus(disk[Drv]->inserted ? 0 : ST0_NOT_READY); // st0 bit3 : media not ready
238 Status = FDC_DATA_READY | FDC_FD2PC;
242 void FLOPPY::Seek(void)
246 Drv = CmdIn.Data[1]&3; // drive No.(0-3)
247 C = CmdIn.Data[2]; // cylinder
248 H = CmdIn.Data[3]; // head address
250 if (!disk[Drv]->inserted) { // disk unmounted ?
251 SeekST0 = ST0_IC_AT | ST0_SEEK_END | ST0_NOT_READY | Drv;
255 // double number(1D->2D)
256 Seek88(Drv, C*2+H, 1);
257 SeekST0 = ST0_IC_NT | ST0_SEEK_END | Drv;
263 // sense interrupt status
264 void FLOPPY::SenseInterruptStatus(void)
268 PushStatus(LastCylinder);
272 PushStatus(ST0_IC_IC);
275 Status = FDC_DATA_READY | FDC_FD2PC;
278 // execute FDC command
282 switch (CmdIn.Data[0] & 0xf) {
283 case 0x03: // Specify
285 case 0x05: // Write Data
288 case 0x06: // Read Data
291 case 0x08: // Sense Interrupt Status
292 SenseInterruptStatus();
294 case 0x0d: // Write ID
295 // Format is Not Implimented
297 case 0x07: // Recalibrate
298 CmdIn.Data[2] = 0; // Seek to TRACK0
302 default: ; // Invalid
307 // I/O access functions
308 void FLOPPY::OutB1H_66(unsigned char data) { DIO = data&2 ? 1 : 0; } // FD mode
309 void FLOPPY::OutB2H_66(unsigned char data) {} // FDC INT?
310 void FLOPPY::OutB3H_66(unsigned char data) {} // in out of PortB2h
311 void FLOPPY::OutD0H_66(unsigned char data) { Push(0, data); } // Buffer
312 void FLOPPY::OutD1H_66(unsigned char data) { Push(1, data); } // Buffer
313 void FLOPPY::OutD2H_66(unsigned char data) { Push(2, data); } // Buffer
314 void FLOPPY::OutD3H_66(unsigned char data) { Push(3, data); } // Buffer
315 void FLOPPY::OutD6H_66(unsigned char data) {} // select drive
316 void FLOPPY::OutD8H_66(unsigned char data) {} //
317 void FLOPPY::OutDAH_66(unsigned char data) { SendSectors = ~(data - 0x10); } // set transfer amount
318 void FLOPPY::OutDDH_66(unsigned char data) { OutFDC(data); } // FDC data register
319 void FLOPPY::OutDEH_66(unsigned char data) {} // ?
321 unsigned char FLOPPY::InB2H_66() { return 3; } // FDC INT
322 unsigned char FLOPPY::InD0H_66() { return Pop(0); } // Buffer
323 unsigned char FLOPPY::InD1H_66() { return Pop(1); } // Buffer
324 unsigned char FLOPPY::InD2H_66() { return Pop(2); } // Buffer
325 unsigned char FLOPPY::InD3H_66() { return Pop(3); } // Buffer
326 unsigned char FLOPPY::InD4H_66() { return 0; } // Mortor(on 0/off 1)
327 unsigned char FLOPPY::InDCH_66() { return Status; } // FDC status register
328 unsigned char FLOPPY::InDDH_66() { return InFDC(); } // FDC data register
330 void FLOPPY::initialize()
332 for(int i = 0; i < 2; i++) {
333 disk[i] = new DISK(emu);
338 void FLOPPY::release()
340 for(int i = 0; i < 2; i++) {
351 memset(Index, 0, sizeof(Index));
354 void FLOPPY::write_io8(uint32 addr, uint32 data)
357 uint16 port=(addr & 0x00ff);
358 byte Value=(data & 0xff);
377 d_ext->write_io8(0, data);
384 d_ext->write_io8(1, data);
391 d_ext->write_io8(2, data);
398 d_ext->write_io8(3, data);
405 d_ext->write_io8(0, data);
410 d_ext->write_io8(1, data);
415 d_ext->write_io8(2, data);
422 d_ext->write_io8(3, data);
441 uint32 FLOPPY::read_io8(uint32 addr)
444 uint16 port=(addr & 0x00ff);
447 switch(addr & 0xff) {
454 Value=d_ext->read_io8(0);
461 Value=d_ext->read_io8(1);
468 Value=d_ext->read_io8(2);
475 Value=d_ext->read_io8(3);
482 Value=d_ext->read_io8(0);
489 Value=d_ext->read_io8(1);
494 Value=d_ext->read_io8(2);
499 Value=d_ext->read_io8(3);
512 uint32 FLOPPY::read_signal(int ch)
516 for(int drv = 0; drv < 2; drv++) {
525 void FLOPPY::open_disk(int drv, _TCHAR path[], int offset)
528 disk[drv]->open(path, offset);
533 void FLOPPY::close_disk(int drv)
535 if(drv < 2 && disk[drv]->inserted) {
540 bool FLOPPY::disk_inserted(int drv)
543 return disk[drv]->inserted;
548 #define STATE_VERSION 1
550 void FLOPPY::save_state(FILEIO* state_fio)
552 state_fio->FputUint32(STATE_VERSION);
553 state_fio->FputInt32(this_device_id);
555 state_fio->FputUint8(io_B1H);
556 for(int i = 0; i < 2; i++) {
557 disk[i]->save_state(state_fio);
559 state_fio->Fwrite(cur_trk, sizeof(cur_trk), 1);
560 state_fio->Fwrite(cur_sct, sizeof(cur_sct), 1);
561 state_fio->Fwrite(cur_pos, sizeof(cur_pos), 1);
562 state_fio->Fwrite(access, sizeof(access), 1);
563 state_fio->Fwrite(Data, sizeof(Data), 1);
564 state_fio->Fwrite(Index, sizeof(Index), 1);
565 state_fio->Fwrite(&CmdIn, sizeof(CmdBuffer), 1);
566 state_fio->Fwrite(&CmdOut, sizeof(CmdBuffer), 1);
568 state_fio->FputUint8(SeekST0);
569 state_fio->FputUint8(LastCylinder);
570 state_fio->FputInt32(SeekEnd);
571 state_fio->FputUint8(SendSectors);
572 state_fio->FputInt32(DIO);
573 state_fio->FputUint8(Status);
576 bool FLOPPY::load_state(FILEIO* state_fio)
578 if(state_fio->FgetUint32() != STATE_VERSION) {
581 if(state_fio->FgetInt32() != this_device_id) {
584 io_B1H = state_fio->FgetUint8();
585 for(int i = 0; i < 2; i++) {
586 if(!disk[i]->load_state(state_fio)) {
590 state_fio->Fread(cur_trk, sizeof(cur_trk), 1);
591 state_fio->Fread(cur_sct, sizeof(cur_sct), 1);
592 state_fio->Fread(cur_pos, sizeof(cur_pos), 1);
593 state_fio->Fread(access, sizeof(access), 1);
594 state_fio->Fread(Data, sizeof(Data), 1);
595 state_fio->Fread(Index, sizeof(Index), 1);
596 state_fio->Fread(&CmdIn, sizeof(CmdBuffer), 1);
597 state_fio->Fread(&CmdOut, sizeof(CmdBuffer), 1);
598 SeekST0 = state_fio->FgetUint8();
599 LastCylinder = state_fio->FgetUint8();
600 SeekEnd = state_fio->FgetInt32();
601 SendSectors = state_fio->FgetUint8();
602 DIO = state_fio->FgetInt32();
603 Status = state_fio->FgetUint8();