OSDN Git Service

[VM][STATE] Apply new framework to some VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / ptf20.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2008.02.28 -
6
7         [ EPSON TF-20 (pseudo) ]
8 */
9
10 #include "ptf20.h"
11 #include "disk.h"
12
13 /*
14         This is based on vfloppy 1.4 by:
15
16         Justin Mitchell (madmitch@discordia.org.uk) and friends.
17         Fred Jan Kraan (fjkraan@xs4all.nl)
18 */
19
20 #define PHASE_IDLE      0
21 #define PHASE_SELECT    1
22 #define PHASE_FUNC      2
23 #define PHASE_HEAD      3
24 #define PHASE_DATA      4
25 #define PHASE_EXEC      5
26 #define PHASE_RESULT    6
27 #define PHASE_END       7
28
29 #define DID_FIRST       0x31
30 #define DID_SECOND      0x32
31 #define DS_SEL          0x05
32
33 #define NUL             0x00
34 #define SOH             0x01
35 #define STX             0x02
36 #define ETX             0x03
37 #define EOT             0x04
38 #define ENQ             0x05
39 #define ACK             0x06
40 #define NAK             0x15
41 #define US              0x31
42
43 #define FNC_RESET_P     0x0d
44 #define FNC_RESET_M     0x0e
45 #define FNC_READ        0x77
46 #define FNC_WRITE       0x78
47 #define FNC_WRITEHST    0x79
48 #define FNC_COPY        0x7a
49 #define FNC_FORMAT      0x7c
50
51 #define ERR_SUCCESS     0x00
52 #define ERR_READ        0xfa
53 #define ERR_WRITE       0xfb
54 #define ERR_DRIVE       0xfc
55 #define ERR_PROTECTED   0xfd
56 #define ERR_UNKNOWN     0xfe
57
58 void PTF20::initialize()
59 {
60         DEVICE::initialize();
61         // initialize d88 handler
62         __MAX_DRIVE = osd->get_feature_int_value(_T("MAX_DRIVE"));
63         if(__MAX_DRIVE <= 0) __MAX_DRIVE = 1;
64         if(__MAX_DRIVE > 8) __MAX_DRIVE = 8;
65         for(int i = 0; i < __MAX_DRIVE; i++) {
66                 disk[i] = new DISK(emu);
67                 disk[i]->set_device_name(_T("%s/Disk #%d"), this_device_name, i + 1);
68                 disk[i]->drive_type = DRIVE_TYPE_2D;
69         }
70 }
71
72 void PTF20::release()
73 {
74         for(int i = 0; i < __MAX_DRIVE; i++) {
75                 if(disk[i]) {
76                         disk[i]->close();
77                         delete disk[i];
78                 }
79         }
80 }
81
82 void PTF20::reset()
83 {
84         for(int i = 0; i < __MAX_DRIVE; i++) {
85                 access[i] = false;
86         }
87         phase = PHASE_IDLE;
88         buflen = 0;
89 }
90
91 #define REPLY(val) write_signals(&outputs_sio, val)
92
93 void PTF20::write_signal(int id, uint32_t data, uint32_t mask)
94 {
95         switch(phase) {
96         case PHASE_IDLE:
97                 if(data == EOT) {
98                         break;
99                 }
100                 if(data == ENQ) {
101                         REPLY(ACK);
102                         break;
103                 }
104                 if(data != DID_FIRST) {
105                         REPLY(NAK);
106                         break;
107                 }
108                 phase = PHASE_SELECT;
109                 buflen = 0;
110                 break;
111                 
112         case PHASE_SELECT:
113                 bufr[buflen++] = data;
114                 if(buflen < 3) {
115                         break;
116                 }
117                 if(bufr[0] != DID_FIRST && bufr[0] != DID_SECOND) {
118                         phase = PHASE_IDLE;
119                         break;
120                 }
121                 if(bufr[2] != DS_SEL) {
122                         REPLY(NAK);
123                         phase = PHASE_IDLE;
124                         break;
125                 }
126                 REPLY(ACK);
127                 phase = PHASE_FUNC;
128                 break;
129                 
130         case PHASE_FUNC:
131                 if(data == EOT) {
132                         phase = PHASE_IDLE;
133                         break;
134                 }
135                 if(data == ENQ) {
136                         REPLY(ACK);
137                         break;
138                 }
139                 if(data != SOH) {
140                         REPLY(NAK);
141                         phase = PHASE_IDLE;
142                         break;
143                 }
144                 phase = PHASE_HEAD;
145                 buflen = 0;
146                 break;
147                 
148         case PHASE_HEAD:
149                 bufr[buflen++] = data;
150                 if(buflen < 6) {
151                         break;
152                 }
153                 REPLY(ACK);
154                 phase = PHASE_DATA;
155                 break;
156                 
157         case PHASE_DATA:
158                 bufr[buflen++] = data;
159                 if(buflen < (6 + bufr[4] + 4)) {
160                         break;
161                 }
162                 if(bufr[6] != STX) {
163                         REPLY(NAK);
164                         phase = PHASE_IDLE;
165                         break;
166                 }
167                 REPLY(ACK);
168                 phase = PHASE_EXEC;
169                 break;
170                 
171         case PHASE_EXEC:
172                 if(data != EOT) {
173                         REPLY(NAK);
174                         phase = PHASE_IDLE;
175                         break;
176                 }
177                 if(!process_cmd()) {
178                         REPLY(NAK);
179                         phase = PHASE_IDLE;
180                         break;
181                 }
182                 for(int i = 0; i < 7; i++) {
183                         REPLY(bufs[i]);
184                 }
185                 phase = PHASE_RESULT;
186                 break;
187                 
188         case PHASE_RESULT:
189                 if(data == ENQ) {
190                         REPLY(ACK);
191                         phase = PHASE_FUNC;
192                         break;
193                 }
194                 if(data != ACK) {
195                         phase = PHASE_FUNC;
196                         break;
197                 }
198                 for(int i = 7; i < buflen; i++) {
199                         REPLY(bufs[i]);
200                 }
201                 phase = PHASE_END;
202                 break;
203                 
204         case PHASE_END:
205                 if(data == ENQ) {
206                         REPLY(ACK);
207                 } else if(data == ACK) {
208                         REPLY(EOT);
209                 }
210                 phase = PHASE_FUNC;
211                 break;
212         }
213 }
214
215 uint32_t PTF20::read_signal(int ch)
216 {
217         // get access status
218         uint32_t stat = 0;
219         for(int i = 0; i < __MAX_DRIVE; i++) {
220                 if(access[i]) {
221                         stat |= 1 << i;
222                 }
223                 access[i] = false;
224         }
225         return stat;
226 }
227
228 #define SET_HEAD(size) { \
229         bufs[0] = 1; \
230         bufs[1] = 1; \
231         bufs[2] = bufr[2]; \
232         bufs[3] = bufr[1]; \
233         bufs[4] = bufr[3]; \
234         bufs[5] = size; \
235         uint8_t sum = 0; \
236         for(int s = 0; s < 6; s++) \
237                 sum += bufs[s]; \
238         bufs[6] = 256 - sum; \
239         bufs[7] = 2; \
240         buflen = 8; \
241 }
242 #define SET_DATA(v) bufs[buflen++] = (v)
243 #define SET_CODE(v) { \
244         bufs[buflen++] = (v); \
245         bufs[buflen++] = 3; \
246         uint8_t sum = 0; \
247         for(int s = 7; s < buflen; s++) \
248                 sum += bufs[s]; \
249         bufs[buflen++] = 256 - sum; \
250 }
251
252 bool PTF20::process_cmd()
253 {
254         int drv, trk, side, sec, dst;
255         uint8_t *sctr, *sctw;
256         
257         switch(bufr[3]) {
258         case FNC_RESET_P:
259         case FNC_RESET_M:
260                 SET_HEAD(0);
261                 SET_CODE(ERR_SUCCESS);
262                 return true;
263                 
264         case FNC_READ:
265                 drv = (bufr[1] == DID_FIRST) ? 0 : (bufr[1] == DID_SECOND) ? 2 : 4;
266                 drv += bufr[7] - 1;
267                 trk = bufr[8];
268                 sec = bufr[9];
269                 if(!is_disk_inserted(drv)) {
270                         // drive error
271                         SET_HEAD(0x80);
272                         for(int i = 0; i < 128; i++) {
273                                 SET_DATA(0xff);
274                         }
275                         SET_CODE(ERR_DRIVE);
276                         return true;
277                 }
278                 if((sctr = get_sector(drv, trk, sec)) == NULL) {
279                         // read error
280                         SET_HEAD(0x80);
281                         for(int i = 0; i < 128; i++) {
282                                 SET_DATA(0xff);
283                         }
284                         SET_CODE(ERR_READ);
285                         return true;
286                 }
287                 SET_HEAD(0x80);
288                 for(int i = 0; i < 128; i++) {
289                         SET_DATA(sctr[i]);
290                 }
291                 SET_CODE(ERR_SUCCESS);
292                 return true;
293                 
294         case FNC_WRITE:
295                 drv = (bufr[1] == DID_FIRST) ? 0 : (bufr[1] == DID_SECOND) ? 2 : 4;
296                 drv += bufr[7] - 1;
297                 trk = bufr[8];
298                 sec = bufr[9];
299                 if(!is_disk_inserted(drv)) {
300                         // drive error
301                         SET_HEAD(0);
302                         SET_CODE(ERR_DRIVE);
303                         return true;
304                 }
305                 if(disk_protected(drv)) {
306                         // write protect
307                         SET_HEAD(0);
308                         SET_CODE(ERR_PROTECTED);
309                         return true;
310                 }
311                 if((sctw = get_sector(drv, trk, sec)) == NULL) {
312                         // write error
313                         SET_HEAD(0);
314                         SET_CODE(ERR_WRITE);
315                         return true;
316                 }
317                 // dont care write type
318                 for(int i = 0; i < 128; i++) {
319                         sctw[i] = bufr[11 + i];
320                 }
321                 SET_HEAD(0);
322                 SET_CODE(ERR_SUCCESS);
323                 return true;
324                 
325         case FNC_WRITEHST:
326                 SET_HEAD(0);
327                 SET_CODE(ERR_SUCCESS);
328                 return true;
329                 
330         case FNC_COPY:
331                 drv = (bufr[1] == DID_FIRST) ? 0 : (bufr[1] == DID_SECOND) ? 2 : 4;
332                 drv += bufr[7] - 1;
333                 dst = (drv & ~1) | (~drv & 1);
334                 if(!is_disk_inserted(drv)) {
335                         // drive error
336                         SET_HEAD(0);
337                         SET_CODE(ERR_DRIVE);
338                         return true;
339                 }
340                 if(!is_disk_inserted(dst)) {
341                         // drive error
342                         SET_HEAD(0);
343                         SET_CODE(ERR_DRIVE);
344                         return true;
345                 }
346                 if(disk_protected(dst)) {
347                         // write protect
348                         SET_HEAD(0);
349                         SET_CODE(ERR_PROTECTED);
350                         return true;
351                 }
352                 for(trk = 0; trk < 40; trk++) {
353                         for(sec = 1; sec <= 64; sec++) {
354                                 if((sctr = get_sector(drv, trk, sec)) == NULL) {
355                                         // read error
356                                         SET_HEAD(0);
357                                         SET_CODE(ERR_READ);
358                                         return true;
359                                 }
360                                 if((sctw = get_sector(dst, trk, sec)) == NULL) {
361                                         // write error
362                                         SET_HEAD(0);
363                                         SET_CODE(ERR_WRITE);
364                                         return true;
365                                 }
366                                 memcpy(sctw, sctr, 128);
367                         }
368                         SET_HEAD(2);
369                         SET_DATA(trk == 39 ? 0xff : 0);         // high-order
370                         SET_DATA(trk == 39 ? 0xff : trk);       // low-order
371                         SET_CODE(ERR_SUCCESS);
372                 }
373                 return true;
374                 
375         case FNC_FORMAT:
376                 drv = (bufr[1] == DID_FIRST) ? 0 : (bufr[1] == DID_SECOND) ? 2 : 4;
377                 drv += bufr[7] - 1;
378                 if(!is_disk_inserted(drv)) {
379                         // drive error
380                         SET_HEAD(0);
381                         SET_CODE(ERR_DRIVE);
382                         return true;
383                 }
384                 if(disk_protected(drv)) {
385                         // write protect
386                         SET_HEAD(0);
387                         SET_CODE(ERR_PROTECTED);
388                         return true;
389                 }
390 #if 1
391                 for(trk = 0; trk < 40; trk++) {
392                         for(side = 0; side < 2; side++) {
393                                 disk[drv]->format_track(trk, side);
394                                 for(sec = 1; sec <= 16; sec++) {
395                                         disk[drv]->insert_sector(trk, side, sec, 1, false, false, 0xe5, 256);
396                                 }
397                         }
398                         SET_HEAD(2);
399                         SET_DATA(trk == 39 ? 0xff : 0);         // high-order
400                         SET_DATA(trk == 39 ? 0xff : trk);       // low-order
401                         SET_CODE(ERR_SUCCESS);
402                 }
403 #else
404                 for(trk = 0; trk < 40; trk++) {
405                         for(sec = 1; sec <= 64; sec++) {
406                                 if((sctw = get_sector(drv, trk, sec)) == NULL) {
407                                         // write error
408                                         SET_HEAD(0);
409                                         SET_CODE(ERR_WRITE);
410                                         return true;
411                                 }
412                                 memset(sctw, 0xe5, 128);
413                         }
414                         SET_HEAD(2);
415                         SET_DATA(trk == 39 ? 0xff : 0);         // high-order
416                         SET_DATA(trk == 39 ? 0xff : trk);       // low-order
417                         SET_CODE(ERR_SUCCESS);
418                 }
419 #endif
420                 return true;
421         }
422         // unknown command
423         return false;
424 }
425
426 bool PTF20::disk_protected(int drv)
427 {
428         if(drv < __MAX_DRIVE) {
429                 return disk[drv]->write_protected;
430         }
431         return false;
432 }
433
434 uint8_t* PTF20::get_sector(int drv, int trk, int sec)
435 {
436         // logical : trk = 0-39, sec = 1-64, secsize = 128bytes
437         int total = trk * 64 + sec - 1;
438         int half = total & 1;
439         total >>= 1;
440         int phys_sec = total & 15;
441         total >>= 4;
442         int phys_side = total & 1;
443         int phys_trk = total >> 1;
444         
445         if(!is_disk_inserted(drv)) {
446                 return NULL;
447         }
448         access[drv] = true;
449         
450         if(!disk[drv]->get_sector(phys_trk, phys_side, phys_sec)) {
451                 return NULL;
452         }
453         return disk[drv]->sector + (half ? 128 : 0);
454 }
455
456 // ----------------------------------------------------------------------------
457 // user interface
458 // ----------------------------------------------------------------------------
459
460 void PTF20::open_disk(int drv, const _TCHAR* file_path, int bank)
461 {
462         if(drv < __MAX_DRIVE) {
463                 disk[drv]->open(file_path, bank);
464         }
465 }
466
467 void PTF20::close_disk(int drv)
468 {
469         if(drv < __MAX_DRIVE) {
470                 disk[drv]->close();
471         }
472 }
473
474 bool PTF20::is_disk_inserted(int drv)
475 {
476         if(drv < __MAX_DRIVE) {
477                 return disk[drv]->inserted;
478         }
479         return false;
480 }
481
482 void PTF20::is_disk_protected(int drv, bool value)
483 {
484         if(drv < __MAX_DRIVE) {
485                 disk[drv]->write_protected = value;
486         }
487 }
488
489 bool PTF20::is_disk_protected(int drv)
490 {
491         if(drv < __MAX_DRIVE) {
492                 return disk[drv]->write_protected;
493         }
494         return false;
495 }
496
497 #define STATE_VERSION   1
498
499 bool PTF20::process_state(FILEIO* state_fio, bool loading)
500 {
501         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
502                 return false;
503         }
504         if(!state_fio->StateCheckInt32(this_device_id)) {
505                 return false;
506         }
507         for(int i = 0; i < __MAX_DRIVE; i++) {
508                 if(!disk[i]->process_state(state_fio, loading)) {
509                         return false;
510                 }
511         }
512         state_fio->StateBuffer(bufr, sizeof(bufr), 1);
513         state_fio->StateBuffer(bufs, sizeof(bufs), 1);
514         state_fio->StateInt32(buflen);
515         state_fio->StateInt32(phase);
516         return true;
517 }
518