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
20 #include "../fileio.h"
22 int PC6031::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 PC6031::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 PC6031::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;
92 SEND_RESULT_STATUS = 0x06,
93 SEND_DRIVE_STATUS = 0x07,
98 WAIT = 0xff, // waiting state
102 // data input (port D0H)
103 unsigned char PC6031::FddIn60()
107 if (mdisk.DAV) { // if data is valid
108 if (mdisk.step == 6) {
109 mdisk.retdat = Getc88(mdisk.drv);
110 if(--mdisk.size == 0) mdisk.step = 0;
114 } else { // if data is not valid
120 // data/command output (port D1H)
121 void PC6031::FddOut60(unsigned char dat)
123 if (mdisk.command == WAIT) { // when command
125 switch (mdisk.command) {
126 case INIT: // 00h init
128 case WRITE_DATA: // 01h write data
131 case READ_DATA: // 02h read data
134 case SEND_DATA: // 03h send data
137 case COPY: // 04h copy
139 case FORMAT: // 05h format
141 case SEND_RESULT_STATUS: // 06h send result status
144 case SEND_DRIVE_STATUS: // 07h send drive status
145 mdisk.retdat |= 0x0a;
147 case TRANSMIT: // 11h transnmit
149 case RECEIVE: // 12h receive
151 case LOAD: // 14h load
153 case SAVE: // 15h save
156 } else { // when data
157 switch (mdisk.command) {
158 case WRITE_DATA: // 01h write data
159 switch (mdisk.step) {
160 case 1: // 01h:block number
162 mdisk.size = mdisk.blk*256;
165 case 2: // 02h:drive number - 1
169 case 3: // 03h:track number
173 case 4: // 04h:sector number
175 // double track number(1D->2D)
176 Seek88(mdisk.drv, mdisk.trk*2, mdisk.sct);
179 case 5: // 05h:write data
180 Putc88(mdisk.drv, dat);
181 if( --mdisk.size == 0 ){
187 case READ_DATA: // 02h read data
188 switch (mdisk.step) {
189 case 1: // 01h:block number
191 mdisk.size = mdisk.blk*256;
194 case 2: // 02h:drive number-1
198 case 3: // 03h:track number
202 case 4: // 04h:sector number
204 // double track number(1D->2D)
205 Seek88(mdisk.drv, mdisk.trk*2, mdisk.sct);
213 // control input from disk unit (port D2H)
214 unsigned char PC6031::FddCntIn60(void)
216 if (((old_D2H & 0x01) ^ mdisk.DAV) || mdisk.RFD && mdisk.DAV) {
217 mdisk.DAC = mdisk.DAV;
218 } else if (mdisk.ATN) {
220 mdisk.command = WAIT;
221 } else if (mdisk.DAC) {
223 } else if (mdisk.RFD) {
227 io_D2H = 0xf0 | 0x08 /* (mdisk.ATN<<3) */ | (mdisk.DAC<<2) | (mdisk.RFD<<1) | mdisk.DAV;
231 // control output to disk unit (port D3H)
232 void PC6031::FddCntOut60(unsigned char dat)
234 // 8255 basic behavior
235 if (!(dat&0x80)) { // check msb
237 switch ((dat>>1)&0x07) {
251 io_D2H = 0xf0 | 0x08 /* (mdisk.ATN<<3) */ | (mdisk.DAC<<2) | (mdisk.RFD<<1) | mdisk.DAV;
255 // I/O access functions
256 void PC6031::OutD1H_60(unsigned char data) { io_D1H = data; FddOut60(io_D1H); }
257 void PC6031::OutD2H_60(unsigned char data) {
258 mdisk.ATN = (data & 0x80) >> 7;
259 mdisk.DAC = (data & 0x40) >> 6;
260 mdisk.RFD = (data & 0x20) >> 5;
261 mdisk.DAV = (data & 0x10) >> 4;
262 io_D2H = 0xf0 | 0x08 /* (mdisk.ATN<<3) */ | (mdisk.DAC<<2) | (mdisk.RFD<<1) | mdisk.DAV;
264 void PC6031::OutD3H_60(unsigned char data) { io_D3H = data; FddCntOut60(io_D3H); }
266 unsigned char PC6031::InD0H_60() { return FddIn60(); }
267 unsigned char PC6031::InD1H_60() { return io_D1H; }
268 unsigned char PC6031::InD2H_60() { io_D2H = FddCntIn60(); return io_D2H; }
269 unsigned char PC6031::InD3H_60() { return io_D3H; }
271 void PC6031::initialize()
273 for(int i = 0; i < 2; i++) {
274 disk[i] = new DISK(emu);
277 memset(&mdisk, 0, sizeof(DISK60));
278 mdisk.command = WAIT; // received command
279 mdisk.retdat = 0xff; // data from port D0H
281 io_D2H = 0xf0 | 0x08 /* (mdisk.ATN<<3) */ | (mdisk.DAC<<2) | (mdisk.RFD<<1) | mdisk.DAV;
286 void PC6031::release()
288 for(int i = 0; i < 2; i++) {
296 void PC6031::write_io8(uint32 addr, uint32 data)
311 uint32 PC6031::read_io8(uint32 addr)
315 return InD0H_60(); break;
317 return InD1H_60(); break;
319 return InD2H_60(); break;
321 return InD3H_60(); break;
326 uint32 PC6031::read_signal(int ch)
330 for(int drv = 0; drv < 2; drv++) {
339 // ----------------------------------------------------------------------------
341 // ----------------------------------------------------------------------------
343 void PC6031::open_disk(int drv, _TCHAR path[], int offset)
346 disk[drv]->open(path, offset);
351 void PC6031::close_disk(int drv)
353 if(drv < 2 && disk[drv]->inserted) {
358 bool PC6031::disk_inserted(int drv)
361 return disk[drv]->inserted;
366 bool PC6031::disk_ejected(int drv)
369 return disk[drv]->ejected;
374 #define STATE_VERSION 1
376 void PC6031::save_state(FILEIO* state_fio)
378 state_fio->FputUint32(STATE_VERSION);
379 state_fio->FputInt32(this_device_id);
381 for(int i = 0; i < 2; i++) {
382 disk[i]->save_state(state_fio);
384 state_fio->Fwrite(cur_trk, sizeof(cur_trk), 1);
385 state_fio->Fwrite(cur_sct, sizeof(cur_sct), 1);
386 state_fio->Fwrite(cur_pos, sizeof(cur_pos), 1);
387 state_fio->Fwrite(access, sizeof(access), 1);
388 state_fio->Fwrite(&mdisk, sizeof(DISK60), 1);
389 state_fio->FputUint8(io_D1H);
390 state_fio->FputUint8(io_D2H);
391 state_fio->FputUint8(old_D2H);
392 state_fio->FputUint8(io_D3H);
393 state_fio->FputInt32(DrvNum);
396 bool PC6031::load_state(FILEIO* state_fio)
398 if(state_fio->FgetUint32() != STATE_VERSION) {
401 if(state_fio->FgetInt32() != this_device_id) {
404 for(int i = 0; i < 2; i++) {
405 if(!disk[i]->load_state(state_fio)) {
409 state_fio->Fread(cur_trk, sizeof(cur_trk), 1);
410 state_fio->Fread(cur_sct, sizeof(cur_sct), 1);
411 state_fio->Fread(cur_pos, sizeof(cur_pos), 1);
412 state_fio->Fread(access, sizeof(access), 1);
413 state_fio->Fread(&mdisk, sizeof(DISK60), 1);
414 io_D1H = state_fio->FgetUint8();
415 io_D2H = state_fio->FgetUint8();
416 old_D2H = state_fio->FgetUint8();
417 io_D3H = state_fio->FgetUint8();
418 DrvNum = state_fio->FgetInt32();