2 // PC-6001/6601 disk I/O
\r
3 // This file is based on a disk I/O program in C++
\r
4 // by Mr. Yumitaro and translated into C for Cocoa iP6
\r
5 // by Koichi NISHIDA 2006
\r
9 Skelton for retropc emulator
\r
11 Author : Takeda.Toshiya
\r
21 int PC6031::Seek88(int drvno, int trackno, int sectno)
\r
24 cur_trk[drvno] = trackno;
\r
25 cur_sct[drvno] = sectno;
\r
28 if(disk[drvno]->get_track(trackno >> 1, trackno & 1)) {
\r
29 for(int i = 0; i < disk[drvno]->sector_num; i++) {
\r
30 if(disk[drvno]->get_sector(trackno >> 1, 0/*trackno & 1*/, i)) {
\r
31 if(disk[drvno]->id[2] == sectno) {
\r
41 unsigned char PC6031::Getc88(int drvno)
\r
43 if(drvno < 2 && disk[drvno]->sector != NULL) {
\r
44 if(cur_pos[drvno] >= disk[drvno]->sector_size) {
\r
46 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
\r
47 // cur_trk[drvno]++;
\r
48 cur_trk[drvno] += 2;
\r
50 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
\r
55 access[drvno] = true;
\r
56 return disk[drvno]->sector[cur_pos[drvno]++];
\r
61 int PC6031::Putc88(int drvno, unsigned char dat)
\r
63 if(drvno < 2 && disk[drvno]->sector != NULL) {
\r
64 if(cur_pos[drvno] >= disk[drvno]->sector_size) {
\r
66 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
\r
67 // cur_trk[drvno]++;
\r
68 cur_trk[drvno] += 2;
\r
70 if(!Seek88(drvno, cur_trk[drvno], cur_sct[drvno])) {
\r
75 access[drvno] = true;
\r
76 disk[drvno]->sector[cur_pos[drvno]++] = dat;
\r
91 SEND_RESULT_STATUS = 0x06,
\r
92 SEND_DRIVE_STATUS = 0x07,
\r
97 WAIT = 0xff, // waiting state
\r
101 // data input (port D0H)
\r
102 unsigned char PC6031::FddIn60()
\r
106 if (mdisk.DAV) { // if data is valid
\r
107 if (mdisk.step == 6) {
\r
108 mdisk.retdat = Getc88(mdisk.drv);
\r
109 if(--mdisk.size == 0) mdisk.step = 0;
\r
112 ret = mdisk.retdat;
\r
113 } else { // if data is not valid
\r
119 // data/command output (port D1H)
\r
120 void PC6031::FddOut60(unsigned char dat)
\r
122 if (mdisk.command == WAIT) { // when command
\r
123 mdisk.command = dat;
\r
124 switch (mdisk.command) {
\r
125 case INIT: // 00h init
\r
127 case WRITE_DATA: // 01h write data
\r
130 case READ_DATA: // 02h read data
\r
133 case SEND_DATA: // 03h send data
\r
136 case COPY: // 04h copy
\r
138 case FORMAT: // 05h format
\r
140 case SEND_RESULT_STATUS: // 06h send result status
\r
141 mdisk.retdat = 0x40;
\r
143 case SEND_DRIVE_STATUS: // 07h send drive status
\r
144 mdisk.retdat |= 0x0a;
\r
146 case TRANSMIT: // 11h transnmit
\r
148 case RECEIVE: // 12h receive
\r
150 case LOAD: // 14h load
\r
152 case SAVE: // 15h save
\r
155 } else { // when data
\r
156 switch (mdisk.command) {
\r
157 case WRITE_DATA: // 01h write data
\r
158 switch (mdisk.step) {
\r
159 case 1: // 01h:block number
\r
161 mdisk.size = mdisk.blk*256;
\r
164 case 2: // 02h:drive number - 1
\r
168 case 3: // 03h:track number
\r
172 case 4: // 04h:sector number
\r
174 // double track number(1D->2D)
\r
175 Seek88(mdisk.drv, mdisk.trk*2, mdisk.sct);
\r
178 case 5: // 05h:write data
\r
179 Putc88(mdisk.drv, dat);
\r
180 if( --mdisk.size == 0 ){
\r
186 case READ_DATA: // 02h read data
\r
187 switch (mdisk.step) {
\r
188 case 1: // 01h:block number
\r
190 mdisk.size = mdisk.blk*256;
\r
193 case 2: // 02h:drive number-1
\r
197 case 3: // 03h:track number
\r
201 case 4: // 04h:sector number
\r
203 // double track number(1D->2D)
\r
204 Seek88(mdisk.drv, mdisk.trk*2, mdisk.sct);
\r
212 // control input from disk unit (port D2H)
\r
213 unsigned char PC6031::FddCntIn60(void)
\r
215 if (((old_D2H & 0x01) ^ mdisk.DAV) || mdisk.RFD && mdisk.DAV) {
\r
216 mdisk.DAC = mdisk.DAV;
\r
217 } else if (mdisk.ATN) {
\r
219 mdisk.command = WAIT;
\r
220 } else if (mdisk.DAC) {
\r
222 } else if (mdisk.RFD) {
\r
226 io_D2H = 0xf0 | 0x08 /* (mdisk.ATN<<3) */ | (mdisk.DAC<<2) | (mdisk.RFD<<1) | mdisk.DAV;
\r
230 // control output to disk unit (port D3H)
\r
231 void PC6031::FddCntOut60(unsigned char dat)
\r
233 // 8255 basic behavior
\r
234 if (!(dat&0x80)) { // check msb
\r
236 switch ((dat>>1)&0x07) {
\r
237 case 7: // bit7 ATN
\r
240 case 6: // bit6 DAC
\r
243 case 5: // bit5 RFD
\r
246 case 4: // bit4 DAV
\r
250 io_D2H = 0xf0 | 0x08 /* (mdisk.ATN<<3) */ | (mdisk.DAC<<2) | (mdisk.RFD<<1) | mdisk.DAV;
\r
254 // I/O access functions
\r
255 void PC6031::OutD1H_60(unsigned char data) { io_D1H = data; FddOut60(io_D1H); }
\r
256 void PC6031::OutD2H_60(unsigned char data) {
\r
257 mdisk.ATN = (data & 0x80) >> 7;
\r
258 mdisk.DAC = (data & 0x40) >> 6;
\r
259 mdisk.RFD = (data & 0x20) >> 5;
\r
260 mdisk.DAV = (data & 0x10) >> 4;
\r
261 io_D2H = 0xf0 | 0x08 /* (mdisk.ATN<<3) */ | (mdisk.DAC<<2) | (mdisk.RFD<<1) | mdisk.DAV;
\r
263 void PC6031::OutD3H_60(unsigned char data) { io_D3H = data; FddCntOut60(io_D3H); }
\r
265 unsigned char PC6031::InD0H_60() { return FddIn60(); }
\r
266 unsigned char PC6031::InD1H_60() { return io_D1H; }
\r
267 unsigned char PC6031::InD2H_60() { io_D2H = FddCntIn60(); return io_D2H; }
\r
268 unsigned char PC6031::InD3H_60() { return io_D3H; }
\r
270 void PC6031::initialize()
\r
272 for(int i = 0; i < 2; i++) {
\r
273 disk[i] = new DISK();
\r
276 memset(&mdisk, 0, sizeof(DISK60));
\r
277 mdisk.command = WAIT; // received command
\r
278 mdisk.retdat = 0xff; // data from port D0H
\r
280 io_D2H = 0xf0 | 0x08 /* (mdisk.ATN<<3) */ | (mdisk.DAC<<2) | (mdisk.RFD<<1) | mdisk.DAV;
\r
285 void PC6031::release()
\r
287 for(int i = 0; i < 2; i++) {
\r
295 void PC6031::write_io8(uint32 addr, uint32 data)
\r
310 uint32 PC6031::read_io8(uint32 addr)
\r
314 return InD0H_60(); break;
\r
316 return InD1H_60(); break;
\r
318 return InD2H_60(); break;
\r
320 return InD3H_60(); break;
\r
325 uint32 PC6031::read_signal(int ch)
\r
327 // get access status
\r
329 for(int drv = 0; drv < 2; drv++) {
\r
333 access[drv] = false;
\r
338 // ----------------------------------------------------------------------------
\r
340 // ----------------------------------------------------------------------------
\r
342 void PC6031::open_disk(int drv, _TCHAR path[], int offset)
\r
345 disk[drv]->open(path, offset);
\r
350 void PC6031::close_disk(int drv)
\r
352 if(drv < 2 && disk[drv]->inserted) {
\r
353 disk[drv]->close();
\r
357 bool PC6031::disk_inserted(int drv)
\r
360 return disk[drv]->inserted;
\r
365 bool PC6031::disk_ejected(int drv)
\r
368 return disk[drv]->ejected;
\r