00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifdef SAVE_RCSID
00011 static char *rcsid =
00012 "@(#) $Id: t64.c,v 1.4 2006/02/24 12:01:01 trikalio Exp $";
00013 #endif
00014
00015 #include <stdlib.h>
00016 #include <string.h>
00017
00018 #include "opencbm.h"
00019 #include "inputfiles.h"
00020
00021 static int probe(FILE *file, const char *fname, cbmcopy_message_cb msg_cb)
00022 {
00023
00024 const char signatures[][32] =
00025 {
00026 "C64 tape image file\0\0\0\0\0\0\0\0\0\0\0\0\0",
00027 "C64S tape file\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
00028 "C64S tape image file\0\0\0\0\0\0\0\0\0\0\0\0"
00029 };
00030 struct
00031 {
00032 char sig[32];
00033 unsigned char major;
00034 unsigned char minor;
00035 unsigned char max_entries_l;
00036 unsigned char max_entries_h;
00037 unsigned char used_entries_l;
00038 unsigned char used_entries_h;
00039 char pad[2];
00040 char name[24];
00041 } t64header;
00042
00043 size_t i;
00044 int used_entries;
00045
00046 msg_cb( sev_debug, "checking for t64" );
00047
00048 if(fread( &t64header, sizeof(t64header), 1, file) == 1)
00049 {
00050 for(i = 0; i < sizeof(signatures) / 32; i++)
00051 {
00052 if(memcmp(signatures[i], t64header.sig, 32) == 0)
00053 {
00054 used_entries =
00055 t64header.used_entries_l +
00056 t64header.used_entries_h * 256;
00057 msg_cb( sev_debug, "found t64 signature `%sī", signatures[i] );
00058 msg_cb( sev_debug, "tape version %u.%u",
00059 t64header.major, t64header.minor );
00060 msg_cb( sev_debug, "tape contains %d file%c",
00061 used_entries, used_entries > 1 ? 's' : '\0' );
00062 return used_entries;
00063 }
00064 }
00065 }
00066 rewind( file );
00067 return 0;
00068 }
00069
00070
00071 static int read(FILE *file, const char *fname, int entry,
00072 char *cbmname, char *type,
00073 unsigned char **data, size_t *size,
00074 cbmcopy_message_cb msg_cb)
00075 {
00076 struct
00077 {
00078 unsigned char c64s_type;
00079 unsigned char c1541_type;
00080 unsigned char start_l;
00081 unsigned char start_h;
00082 unsigned char end_l;
00083 unsigned char end_h;
00084 unsigned char unused1[2];
00085 unsigned char offset[4];
00086 unsigned char unused2[4];
00087 unsigned char name[16];
00088 } t64entry;
00089 long offset;
00090 int i;
00091 int start;
00092 int end;
00093
00094 if(fseek( file, 0x40 + 32 * entry, SEEK_SET ) == 0 &&
00095 fread( &t64entry, sizeof(t64entry), 1, file ) == 1)
00096 {
00097 memcpy( cbmname, t64entry.name, 16 );
00098 for( i = 15; i >= 0 && cbmname[i] == 0x20; i-- )
00099 {
00100 cbmname[i] = (char) 0xa0;
00101 }
00102 switch(t64entry.c1541_type)
00103 {
00104 case 0x01:
00105 case 0x80:
00106 case 'D' :
00107 *type = 'D';
00108 break;
00109 case 0x81:
00110 case 'S' :
00111 *type = 'S';
00112 break;
00113 case 0x82:
00114 case 'P' :
00115 *type = 'P';
00116 break;
00117 case 0x83:
00118 case 'U' :
00119 *type = 'U';
00120 break;
00121 default:
00122 msg_cb( sev_info, "unknown 1541 file type, using default" );
00123 *type = 'P';
00124 break;
00125 }
00126 for(offset = 0, i = 3; i >= 0; i--)
00127 {
00128 offset = offset * 0x100 + t64entry.offset[i];
00129 }
00130 msg_cb( sev_debug, "data offset = %08lx", offset );
00131 start = t64entry.start_l + 0x100 * t64entry.start_h;
00132 end = t64entry.end_l + 0x100 * t64entry.end_h;
00133
00134 if(fseek(file, offset, SEEK_SET) == 0)
00135 {
00136 *size = 2 + (end - start);
00137 *data = malloc(*size);
00138 if(*data)
00139 {
00140 (*data)[0] = t64entry.start_l;
00141 (*data)[1] = t64entry.start_h;
00142 if(fread(&(*data)[2], (*size)-2, 1, file) == 1)
00143 {
00144 return 0;
00145 }
00146 else
00147 {
00148 msg_cb( sev_warning, "could not read file data" );
00149 }
00150 free(*data);
00151 }
00152 else
00153 {
00154 msg_cb( sev_warning, "no memory" );
00155 }
00156 }
00157 else
00158 {
00159 msg_cb( sev_warning, "could not seek to file data" );
00160 }
00161 }
00162 else
00163 {
00164 msg_cb( sev_warning, "could not seek to directory entry" );
00165 }
00166 return 1;
00167 }
00168
00169 DECLARE_INPUT_READER(t64);