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 ]
21 int FLOPPY::Seek88(int drvno, int trackno, int sectno)
24 cur_trk[drvno] = trackno;
25 cur_sct[drvno] = sectno;
28 if(disk[drvno]->get_track(trackno >> 1, trackno & 1)) {
29 for(int i = 0; i < disk[drvno]->sector_num; i++) {
30 if(disk[drvno]->get_sector(trackno >> 1, 0/*trackno & 1*/, i)) {
31 if(disk[drvno]->id[2] == sectno) {
41 unsigned char FLOPPY::Getc88(int drvno)
43 if(drvno < 2 && disk[drvno]->sector != NULL) {
44 if(cur_pos[drvno] >= disk[drvno]->sector_size) {
46 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
50 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
56 return disk[drvno]->sector[cur_pos[drvno]++];
61 int FLOPPY::Putc88(int drvno, unsigned char dat)
63 if(drvno < 2 && disk[drvno]->sector != NULL) {
64 if(cur_pos[drvno] >= disk[drvno]->sector_size) {
66 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
70 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
76 disk[drvno]->sector[cur_pos[drvno]++] = dat;
82 // push data to data buffer
83 void FLOPPY::Push(int part, unsigned char data)
87 if(Index[part] < 256) Data[part][Index[part]++] = data;
90 // pop data from data buffer
91 unsigned char FLOPPY::Pop(int part)
93 if(part > 3) return 0xff;
95 if(Index[part] > 0) return Data[part][--Index[part]];
100 void FLOPPY::Clear(int i)
106 #define FDC_BUSY (0x10)
107 #define FDC_READY (0x00)
108 #define FDC_NON_DMA (0x20)
109 #define FDC_FD2PC (0x40)
110 #define FDC_PC2FD (0x00)
111 #define FDC_DATA_READY (0x80)
114 #define ST0_NOT_READY (0x08)
115 #define ST0_EQUIP_CHK (0x10)
116 #define ST0_SEEK_END (0x20)
117 #define ST0_IC_NT (0x00)
118 #define ST0_IC_AT (0x40)
119 #define ST0_IC_IC (0x80)
120 #define ST0_IC_AI (0xc0)
123 #define ST1_NOT_WRITABLE (0x02)
128 #define ST3_TRACK0 (0x10)
129 #define ST3_READY (0x20)
130 #define ST3_WRITE_PROTECT (0x40)
131 #define ST3_FAULT (0x80)
134 int FLOPPY::DiskInit66(void)
136 memset( &CmdIn, 0, sizeof( CmdBuffer ) );
137 memset( &CmdOut, 0, sizeof( CmdBuffer ) );
142 Status = FDC_DATA_READY | FDC_READY | FDC_PC2FD;
146 // push data to status buffer
147 void FLOPPY::PushStatus(int data)
149 CmdOut.Data[CmdOut.Index++] = data;
152 // pop data from status buffer
153 unsigned char FLOPPY::PopStatus()
155 return CmdOut.Data[--CmdOut.Index];
159 void FLOPPY::OutFDC(unsigned char data)
161 const int CmdLength[] = { 0,0,0,3,2,9,9,2,1,0,0,0,0,6,0,3 };
163 CmdIn.Data[CmdIn.Index++] = data;
164 if (CmdLength[CmdIn.Data[0]&0xf] == CmdIn.Index) Exec();
168 unsigned char FLOPPY::InFDC()
170 if (CmdOut.Index == 1) Status = FDC_DATA_READY | FDC_PC2FD;
180 Drv = CmdIn.Data[1]&3; // drive number No.(0-3)
181 C = CmdIn.Data[2]; // cylinder
182 H = CmdIn.Data[3]; // head address
183 R = CmdIn.Data[4]; // sector No.
184 N = CmdIn.Data[5] ? CmdIn.Data[5]*256 : 256; // sector size
186 if (disk[Drv]->inserted) {
188 // double track number(1D->2D)
189 Seek88(Drv, C*2+H, R);
190 for (i = 0; i < SendSectors; i++) {
193 Push(i, Getc88(Drv));
200 PushStatus(0); // st2
201 PushStatus(0); // st1
202 PushStatus(disk[Drv]->inserted ? 0 : ST0_NOT_READY); // st0 bit3 : media not ready
203 Status = FDC_DATA_READY | FDC_FD2PC;
207 void FLOPPY::Write(void)
212 Drv = CmdIn.Data[1]&3; // drive No.(0-3)
213 C = CmdIn.Data[2]; // cylinder
214 H = CmdIn.Data[3]; // head address
215 R = CmdIn.Data[4]; // sector No.
216 N = CmdIn.Data[5] ? CmdIn.Data[5]*256 : 256; // sector size
218 if (disk[Drv]->inserted) {
220 // double track number(1D->2D)
221 Seek88(Drv, C*2+H, R);
222 for (i=0; i<SendSectors; i++) {
223 for(j=0; j<0x100; j++)
224 Putc88(Drv, Pop(i)); // write data
232 PushStatus(0); // st2
233 PushStatus(0); // st1
235 PushStatus(disk[Drv]->inserted ? 0 : ST0_NOT_READY); // st0 bit3 : media not ready
237 Status = FDC_DATA_READY | FDC_FD2PC;
241 void FLOPPY::Seek(void)
245 Drv = CmdIn.Data[1]&3; // drive No.(0-3)
246 C = CmdIn.Data[2]; // cylinder
247 H = CmdIn.Data[3]; // head address
249 if (!disk[Drv]->inserted) { // disk unmounted ?
250 SeekST0 = ST0_IC_AT | ST0_SEEK_END | ST0_NOT_READY | Drv;
254 // double number(1D->2D)
255 Seek88(Drv, C*2+H, 1);
256 SeekST0 = ST0_IC_NT | ST0_SEEK_END | Drv;
262 // sense interrupt status
263 void FLOPPY::SenseInterruptStatus(void)
267 PushStatus(LastCylinder);
271 PushStatus(ST0_IC_IC);
274 Status = FDC_DATA_READY | FDC_FD2PC;
277 // execute FDC command
281 switch (CmdIn.Data[0] & 0xf) {
282 case 0x03: // Specify
284 case 0x05: // Write Data
287 case 0x06: // Read Data
290 case 0x08: // Sense Interrupt Status
291 SenseInterruptStatus();
293 case 0x0d: // Write ID
294 // Format is Not Implimented
296 case 0x07: // Recalibrate
297 CmdIn.Data[2] = 0; // Seek to TRACK0
301 default: ; // Invalid
306 // I/O access functions
307 void FLOPPY::OutB1H_66(unsigned char data) { DIO = data&2 ? 1 : 0; } // FD mode
308 void FLOPPY::OutB2H_66(unsigned char data) {} // FDC INT?
309 void FLOPPY::OutB3H_66(unsigned char data) {} // in out of PortB2h
310 void FLOPPY::OutD0H_66(unsigned char data) { Push(0, data); } // Buffer
311 void FLOPPY::OutD1H_66(unsigned char data) { Push(1, data); } // Buffer
312 void FLOPPY::OutD2H_66(unsigned char data) { Push(2, data); } // Buffer
313 void FLOPPY::OutD3H_66(unsigned char data) { Push(3, data); } // Buffer
314 void FLOPPY::OutD6H_66(unsigned char data) {} // select drive
315 void FLOPPY::OutD8H_66(unsigned char data) {} //
316 void FLOPPY::OutDAH_66(unsigned char data) { SendSectors = ~(data - 0x10); } // set transfer amount
317 void FLOPPY::OutDDH_66(unsigned char data) { OutFDC(data); } // FDC data register
318 void FLOPPY::OutDEH_66(unsigned char data) {} // ?
320 unsigned char FLOPPY::InB2H_66() { return 3; } // FDC INT
321 unsigned char FLOPPY::InD0H_66() { return Pop(0); } // Buffer
322 unsigned char FLOPPY::InD1H_66() { return Pop(1); } // Buffer
323 unsigned char FLOPPY::InD2H_66() { return Pop(2); } // Buffer
324 unsigned char FLOPPY::InD3H_66() { return Pop(3); } // Buffer
325 unsigned char FLOPPY::InD4H_66() { return 0; } // Mortor(on 0/off 1)
326 unsigned char FLOPPY::InDCH_66() { return Status; } // FDC status register
327 unsigned char FLOPPY::InDDH_66() { return InFDC(); } // FDC data register
329 void FLOPPY::initialize()
331 for(int i = 0; i < 2; i++) {
332 disk[i] = new DISK(emu);
337 void FLOPPY::release()
339 for(int i = 0; i < 2; i++) {
350 memset(Index, 0, sizeof(Index));
353 void FLOPPY::write_io8(uint32 addr, uint32 data)
356 uint16 port=(addr & 0x00ff);
357 byte Value=(data & 0xff);
376 d_ext->write_io8(0, data);
383 d_ext->write_io8(1, data);
390 d_ext->write_io8(2, data);
397 d_ext->write_io8(3, data);
404 d_ext->write_io8(0, data);
409 d_ext->write_io8(1, data);
414 d_ext->write_io8(2, data);
421 d_ext->write_io8(3, data);
440 uint32 FLOPPY::read_io8(uint32 addr)
443 uint16 port=(addr & 0x00ff);
446 switch(addr & 0xff) {
453 Value=d_ext->read_io8(0);
460 Value=d_ext->read_io8(1);
467 Value=d_ext->read_io8(2);
474 Value=d_ext->read_io8(3);
481 Value=d_ext->read_io8(0);
488 Value=d_ext->read_io8(1);
493 Value=d_ext->read_io8(2);
498 Value=d_ext->read_io8(3);
511 uint32 FLOPPY::read_signal(int ch)
515 for(int drv = 0; drv < 2; drv++) {
524 void FLOPPY::open_disk(int drv, _TCHAR path[], int offset)
527 disk[drv]->open(path, offset);
532 void FLOPPY::close_disk(int drv)
534 if(drv < 2 && disk[drv]->inserted) {
539 bool FLOPPY::disk_inserted(int drv)
542 return disk[drv]->inserted;