2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
7 [ EPSON TF-20 (pseudo) ]
14 This is based on vfloppy 1.4 by:
16 Justin Mitchell (madmitch@discordia.org.uk) and friends.
17 Fred Jan Kraan (fjkraan@xs4all.nl)
21 #define PHASE_SELECT 1
26 #define PHASE_RESULT 6
29 #define DID_FIRST 0x31
30 #define DID_SECOND 0x32
43 #define FNC_RESET_P 0x0d
44 #define FNC_RESET_M 0x0e
46 #define FNC_WRITE 0x78
47 #define FNC_WRITEHST 0x79
49 #define FNC_FORMAT 0x7c
51 #define ERR_SUCCESS 0x00
53 #define ERR_WRITE 0xfb
54 #define ERR_DRIVE 0xfc
55 #define ERR_PROTECTED 0xfd
56 #define ERR_UNKNOWN 0xfe
58 void PTF20::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;
74 for(int i = 0; i < __MAX_DRIVE; i++) {
84 for(int i = 0; i < __MAX_DRIVE; i++) {
91 #define REPLY(val) write_signals(&outputs_sio, val)
93 void PTF20::write_signal(int id, uint32_t data, uint32_t mask)
104 if(data != DID_FIRST) {
108 phase = PHASE_SELECT;
113 bufr[buflen++] = data;
117 if(bufr[0] != DID_FIRST && bufr[0] != DID_SECOND) {
121 if(bufr[2] != DS_SEL) {
149 bufr[buflen++] = data;
158 bufr[buflen++] = data;
159 if(buflen < (6 + bufr[4] + 4)) {
182 for(int i = 0; i < 7; i++) {
185 phase = PHASE_RESULT;
198 for(int i = 7; i < buflen; i++) {
207 } else if(data == ACK) {
215 uint32_t PTF20::read_signal(int ch)
219 for(int i = 0; i < __MAX_DRIVE; i++) {
228 #define SET_HEAD(size) { \
236 for(int s = 0; s < 6; s++) \
238 bufs[6] = 256 - sum; \
242 #define SET_DATA(v) bufs[buflen++] = (v)
243 #define SET_CODE(v) { \
244 bufs[buflen++] = (v); \
245 bufs[buflen++] = 3; \
247 for(int s = 7; s < buflen; s++) \
249 bufs[buflen++] = 256 - sum; \
252 bool PTF20::process_cmd()
254 int drv, trk, side, sec, dst;
255 uint8_t *sctr, *sctw;
261 SET_CODE(ERR_SUCCESS);
265 drv = (bufr[1] == DID_FIRST) ? 0 : (bufr[1] == DID_SECOND) ? 2 : 4;
269 if(!is_disk_inserted(drv)) {
272 for(int i = 0; i < 128; i++) {
278 if((sctr = get_sector(drv, trk, sec)) == NULL) {
281 for(int i = 0; i < 128; i++) {
288 for(int i = 0; i < 128; i++) {
291 SET_CODE(ERR_SUCCESS);
295 drv = (bufr[1] == DID_FIRST) ? 0 : (bufr[1] == DID_SECOND) ? 2 : 4;
299 if(!is_disk_inserted(drv)) {
305 if(disk_protected(drv)) {
308 SET_CODE(ERR_PROTECTED);
311 if((sctw = get_sector(drv, trk, sec)) == NULL) {
317 // dont care write type
318 for(int i = 0; i < 128; i++) {
319 sctw[i] = bufr[11 + i];
322 SET_CODE(ERR_SUCCESS);
327 SET_CODE(ERR_SUCCESS);
331 drv = (bufr[1] == DID_FIRST) ? 0 : (bufr[1] == DID_SECOND) ? 2 : 4;
333 dst = (drv & ~1) | (~drv & 1);
334 if(!is_disk_inserted(drv)) {
340 if(!is_disk_inserted(dst)) {
346 if(disk_protected(dst)) {
349 SET_CODE(ERR_PROTECTED);
352 for(trk = 0; trk < 40; trk++) {
353 for(sec = 1; sec <= 64; sec++) {
354 if((sctr = get_sector(drv, trk, sec)) == NULL) {
360 if((sctw = get_sector(dst, trk, sec)) == NULL) {
366 memcpy(sctw, sctr, 128);
369 SET_DATA(trk == 39 ? 0xff : 0); // high-order
370 SET_DATA(trk == 39 ? 0xff : trk); // low-order
371 SET_CODE(ERR_SUCCESS);
376 drv = (bufr[1] == DID_FIRST) ? 0 : (bufr[1] == DID_SECOND) ? 2 : 4;
378 if(!is_disk_inserted(drv)) {
384 if(disk_protected(drv)) {
387 SET_CODE(ERR_PROTECTED);
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);
399 SET_DATA(trk == 39 ? 0xff : 0); // high-order
400 SET_DATA(trk == 39 ? 0xff : trk); // low-order
401 SET_CODE(ERR_SUCCESS);
404 for(trk = 0; trk < 40; trk++) {
405 for(sec = 1; sec <= 64; sec++) {
406 if((sctw = get_sector(drv, trk, sec)) == NULL) {
412 memset(sctw, 0xe5, 128);
415 SET_DATA(trk == 39 ? 0xff : 0); // high-order
416 SET_DATA(trk == 39 ? 0xff : trk); // low-order
417 SET_CODE(ERR_SUCCESS);
426 bool PTF20::disk_protected(int drv)
428 if(drv < __MAX_DRIVE) {
429 return disk[drv]->write_protected;
434 uint8_t* PTF20::get_sector(int drv, int trk, int sec)
436 // logical : trk = 0-39, sec = 1-64, secsize = 128bytes
437 int total = trk * 64 + sec - 1;
438 int half = total & 1;
440 int phys_sec = total & 15;
442 int phys_side = total & 1;
443 int phys_trk = total >> 1;
445 if(!is_disk_inserted(drv)) {
450 if(!disk[drv]->get_sector(phys_trk, phys_side, phys_sec)) {
453 return disk[drv]->sector + (half ? 128 : 0);
456 // ----------------------------------------------------------------------------
458 // ----------------------------------------------------------------------------
460 void PTF20::open_disk(int drv, const _TCHAR* file_path, int bank)
462 if(drv < __MAX_DRIVE) {
463 disk[drv]->open(file_path, bank);
467 void PTF20::close_disk(int drv)
469 if(drv < __MAX_DRIVE) {
474 bool PTF20::is_disk_inserted(int drv)
476 if(drv < __MAX_DRIVE) {
477 return disk[drv]->inserted;
482 void PTF20::is_disk_protected(int drv, bool value)
484 if(drv < __MAX_DRIVE) {
485 disk[drv]->write_protected = value;
489 bool PTF20::is_disk_protected(int drv)
491 if(drv < __MAX_DRIVE) {
492 return disk[drv]->write_protected;
497 #define STATE_VERSION 1
499 bool PTF20::process_state(FILEIO* state_fio, bool loading)
501 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
504 if(!state_fio->StateCheckInt32(this_device_id)) {
507 for(int i = 0; i < __MAX_DRIVE; i++) {
508 if(!disk[i]->process_state(state_fio, loading)) {
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);