/* CPCREAD v1.0 */ /* Marco Vieth, 17.5.1993 */ /* CPCREAD copies CPC-disks to a special image-file, which is used by CPCEMU. Now also in C. */ /* translated from pascal by TPTC */ #include /* for printf */ #include /* for exit */ #include /* for REGPACK */ #include /* for memset */ #include /* for strcpy */ typedef unsigned char byte; typedef unsigned short int word; /* Reads CPC-Disks to a file (only side A) */ /* 40 Track, Data/System-format */ #define LAST_HEAD 0 /* last head (only 0 !) */ #define LAST_TRK 39 /* last track-number (0..) */ #define LAST_SEC 9 /* last sector-number (without offset) (1..) */ struct media { byte drive; byte head; byte track; byte sector; byte sec_count; /* number of sectors */ }; struct format { byte FSC; /* first sector */ byte PST; /* physical sectors per track */ byte LTRK; /* last track */ word BSEC; /* bytes per sector */ }; typedef byte secdat[0x1FF+1]; typedef secdat trkdat[10]; struct format qfor; struct media qdrv; trkdat datbu; byte disk_info[0xff+1]; /* disk-info-array */ byte track_info[0xff+1]; /* track-info-array */ char upcase(char ch) { if ((ch>='a') && (ch<='z')) ch-=0x20; return ch; } /* for another formats : */ #define OFF_MAX 8 byte s_offs[OFF_MAX] = { 0xc0, 0x40, 0x00, 0x70, 0x80, 0xa0, 0xb0, 0xf0 }; byte off_pos = 0; void read_sector(struct media *drv, struct format *form, byte *buffer) { word retry; struct REGPACK reg; retry = 0; do { /* printf("drive = %02X\n",drv->drive); printf("head = %02X\n",drv->head); printf("track = %02X\n",drv->track); printf("sector = %02X\n",drv->sector); */ reg.r_ax = 0x0200 + drv->sec_count; /* number of sectors */ reg.r_cx = (drv->track << 8) + (drv->sector | (form->FSC - 1)); reg.r_dx = (drv->head << 8) + drv->drive; /* head and drive */ reg.r_es = FP_SEG(buffer); /* DMA-segment */ reg.r_bx = FP_OFF(buffer); /* DMA-offset */ intr(0x13 , ®); if ((reg.r_ax & 0xFF00) != 0) /* error occured */ { retry = retry + 1; if (retry > 3) { retry = 0; off_pos++; if (off_pos < OFF_MAX) { form->FSC = s_offs[off_pos]+1; /* set new first-sector */ printf("trying sector-offset 0x%02X ... \n",s_offs[off_pos]); printf("Loading track %d ... ",drv->track); } else { printf("Error Disk-access drive %c\n",(char)(drv->drive + 65)); exit(1); } } } } while (!((reg.r_ax & 0xFF00) == 0)); } void setformat(struct format *form) { form->FSC = s_offs[off_pos]+1;/* first sector */ form->PST = LAST_SEC; /* sectors per track */ form->LTRK = LAST_TRK; /* last track */ form->BSEC = 0x200; /* bytes per sector */ } void initdrv(struct media *drv, byte drive_num) { drv->drive = drive_num; drv->head = 0; drv->track = 0; drv->sector = 0; drv->sec_count = 1; } void create_disk_info(void) { char ident[] = "MV - CPCEMU Disk-File\r\nDisk-Info\r\n"; word i; memset(disk_info, 0, 0x100); strcpy(disk_info, ident); i = 34 + 14; disk_info[i] = LAST_TRK+1; /* # tracks */ i = i + 1; disk_info[i] = LAST_HEAD+1; /* # heads */ i = i + 1; disk_info[i] = 0; /* lo-byte track-size */ i = i + 1; disk_info[i] = LAST_SEC*0x02 + 0x01; /* hi-byte track-size */ /* BPS = 0x200, track-info always 0x100-bytes */ } void create_track_info(byte track, byte head, byte sectoff) { char ident[] = "Track-Info\r\n"; word i, j; memset(track_info, 0, 0x100); strcpy(track_info, ident); i = 12 + 4; track_info[i] = track; /* track-number */ i = i + 1; track_info[i] = head; /* head-number */ i = i + 1; i = i + 2; /* 2 bytes not used */ /* format-track-parameter */ track_info[i] = 2; /* BPS */ i = i + 1; track_info[i] = LAST_SEC; /* # sectors */ i = i + 1; track_info[i] = 0x4e; /* GAP #3 format */ i = i + 1; track_info[i] = 0xe5; /* fill-byte */ i = i + 1; /* sector-data */ for (j = 1; j <= LAST_SEC; j++) { /* sector-ID */ track_info[i] = track; /* track-number */ i = i + 1; track_info[i] = head; /* head-number */ i = i + 1; track_info[i] = j | sectoff; /* sector or sector-offset */ i = i + 1; track_info[i] = 2; /* BPS */ i = i + 1; /* errors in sector */ track_info[i] = 0; /* state 1 errors */ i = i + 1; track_info[i] = 0; /* state 2 errors */ i = i + 1; track_info[i] = 0; /* not used */ i = i + 1; track_info[i] = 0; /* not used */ i = i + 1; } } void blockwrite(FILE *f, byte *buf, word lg) { word i; for (i=0; i= 'A') && (inp_line[0] <= 'E')) source_drv = ((byte)inp_line[0] - 65); } break; case '3': { printf("New destination-file : "); scanf("%s",inp_line); strcpy(destination_file,inp_line); } break; case '4': ; break; default: printf("What was that ??\n"); } } while (!(ch == '4')); } main( /* int argc,char *argv[] */ ) { /* main */ menue(); return 0; } /* end of cpcread.c */