/[projet1]/public/pc/tools/osdk/main/tap2dsk/sources/tap2dsk.c
Defence Force logotype

Contents of /public/pc/tools/osdk/main/tap2dsk/sources/tap2dsk.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1509 - (show annotations)
Sat Apr 13 12:04:39 2019 UTC (5 months ago) by dbug
File MIME type: text/plain
File size: 12061 byte(s)
Tap2Dsk 2.1.1
- Added a fix to avoid the tool to stay stuck on tapes with incorrect size specified in their headers
1 /* tap2dsk : converts an Oric tape image to a sedoric/stratsed dsk image */
2 /* (c) F.Frances 2004 */
3
4 /* Limitations :
5 * - only 1 bitmap sector, thus limits the capacity to ~2048 sectors
6 * - only 1 side with 80 tracks max.
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #define DIRTRACK 20
13 #define NBTRACKS 21
14 #define NBSECT 17
15
16 typedef unsigned char byte;
17 typedef byte sector[256];
18
19 struct {
20 char signature[8];
21 int sides;
22 int tracks;
23 int sect;
24 char pad[256-20];
25 } imageheader = { "ORICDISK", 1, NBTRACKS, NBSECT };
26
27 sector disk[80][NBSECT];
28 sector directory,descriptor;
29 sector system_sect={ // some system parameters
30 0xD0,0xD0,0xD0,0xD0, // drive table
31 0, // keyboard type
32 100,0,10,0, // RENUM parameters
33 'T','A','P','2','D','S','K',' ','S','A','M','P','L','E',' ','D','I','S','C',' ',' ', // disk name
34 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
35 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
36 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' // inist
37 };
38 sector bitmap={
39 0xFF, // signature
40 0,
41 0,0, // number of free sectors
42 0,0, // number of files
43 NBTRACKS, // number of tracks/side
44 NBSECT, // number of sectors/track
45 1, // number of directory sectors
46 NBTRACKS, // number of tracks + 128 if double sided
47 0 // master/slave/gameinit indicator
48 };
49
50 byte sedoric[]=
51 {
52 #include "sedoric3.h"
53 };
54
55 int track,sect=1;
56 unsigned int dir_offset=0x10;
57 int used_sectors;
58
59
60
61 void allocate_sector(int track, int sect, byte *contents)
62 {
63 int linear_sector=track*NBSECT+sect-1;
64 bitmap[0x10+linear_sector/8] &= ~(1<<linear_sector%8);
65 memcpy(disk[track][sect-1],contents,sizeof(sector));
66 used_sectors++;
67 }
68
69 void find_free_sector(byte *contents)
70 {
71 int linear_sector=0;
72 while ((bitmap[0x10+linear_sector/8] & (1<<linear_sector%8)) == 0)
73 linear_sector++;
74
75 track=linear_sector/NBSECT;
76 sect=linear_sector%NBSECT+1;
77 if (track==80) {
78 fprintf(stderr,"Not enough space on sample disc");
79 exit(1);
80 }
81 allocate_sector(track,sect,contents);
82 }
83
84 void update_sector(int track, int sect, byte *contents)
85 {
86 memcpy(disk[track][sect-1],contents,sizeof(sector));
87 }
88
89 void convert_basename(char *dest, char *name)
90 {
91 static int filenumber=0;
92 int dest_offset=0, src_offset=0;
93 printf("Storing ");
94 while (dest_offset<9 && src_offset<17 && name[src_offset])
95 {
96 if (name[src_offset]>='a' && name[src_offset]<='z')
97 name[src_offset]-=0x20;
98
99 if ((name[src_offset]>='0' && name[src_offset]<='9')
100 || (name[src_offset]>='A' && name[src_offset]<='Z'))
101 {
102 putchar(name[src_offset]);
103 dest[dest_offset++]=name[src_offset];
104 }
105 src_offset++;
106 }
107 if (dest_offset)
108 {
109 while (dest_offset<9)
110 dest[dest_offset++]=' ';
111 }
112 else
113 {
114 printf("NONAME%03d",filenumber);
115 sprintf(dest,"NONAME%03d",filenumber++);
116 }
117 }
118
119 void store_file(byte *buf, char *name, byte *header)
120 {
121 int start=(header[6]<<8)+header[7];
122 int end=(header[4]<<8)+header[5];
123 int exec=header[3];
124 int block=header[2];
125 int sectors=(end-start)/sizeof(sector)+1;
126 int desc_sect,desc_track;
127 int desc_off=0x0C;
128
129 memset(descriptor,0,sizeof(sector));
130 find_free_sector(descriptor);
131 desc_track=track; desc_sect=sect;
132 descriptor[2]=0xFF;
133 descriptor[3]=(block?0x40:0x80)+(exec?1:0);
134 descriptor[4]=header[7];
135 descriptor[5]=header[6];
136 descriptor[6]=header[5];
137 descriptor[7]=header[4];
138 if (exec)
139 {
140 descriptor[8]=descriptor[4];
141 descriptor[9]=descriptor[5];
142 }
143 else
144 {
145 descriptor[8]=descriptor[9]=0;
146 }
147 descriptor[10]=sectors&0xFF;
148 descriptor[11]=sectors>>8;
149
150 convert_basename((char*)(directory+dir_offset),name);
151 if (exec)
152 {
153 sprintf((char*)(directory+dir_offset+9),"COM");
154 printf(".COM");
155 }
156 else
157 {
158 sprintf((char*)(directory+dir_offset+9),"%s",block?"BIN":"BAS");
159 printf(".%s",block?"BIN":"BAS");
160 }
161 printf("\n");
162 directory[dir_offset+12]=desc_track;
163 directory[dir_offset+13]=desc_sect;
164 directory[dir_offset+14]=sectors+1+(sectors>=(256-12)/2?1:0); // Sedoric bug work-around : allocate a second descriptor when exactly 122 sectors of data
165 directory[dir_offset+15]=0x40; // UNPROT
166
167 while (sectors--)
168 {
169 find_free_sector(buf);
170 buf+=sizeof(sector);
171 descriptor[desc_off++]=track;
172 descriptor[desc_off++]=sect;
173 if (desc_off==0x100)
174 { // Sedoric bug work-around : allocate a second descriptor when the first is full, even if not needed
175 find_free_sector(descriptor);
176 descriptor[0]=track;
177 descriptor[1]=sect;
178 update_sector(desc_track,desc_sect,descriptor);
179 memset(descriptor,0,sizeof(sector));
180 desc_track=track;
181 desc_sect=sect;
182 desc_off=2;
183 }
184 }
185 update_sector(desc_track,desc_sect,descriptor);
186 }
187
188 char generateEscapeCode(int color)
189 {
190 return (char) 64 + color;
191 }
192
193 int main(int argc, char *argv[])
194 {
195 byte header[9];
196 char name[17];
197 byte file_buffer[48*1024];
198 FILE *tape, *dsk;
199 int dir_track= DIRTRACK, dir_sect=4;
200 int tracks= DIRTRACK+1; // minimum track number
201 int total_sectors,free_sectors;
202 int tape_num,i;
203 int tape_name_index = -1;
204 int paper_color = -1;
205 int ink_color = -1;
206
207 printf("Tap2dsk V2.1.1\n");
208
209 if (argc<2)
210 {
211 fprintf(stderr,"Usage: tap2dsk [-c<paper_color>:<ink_color>] [-n<disk_label>] [-i<init_string>] <tape_image1> ...<tape_imageN> <old_disk_image>\n");
212 exit(1);
213 }
214
215 for (i=1; i<argc; i++)
216 {
217 if (argv[i][0]=='-')
218 {
219 switch (argv[i][1])
220 {
221 case 'c':
222 case 'C':
223 if (sscanf(argv[i], "-c%d:%d", &paper_color, &ink_color) != 2)
224 {
225 fprintf(stderr, "Malformed color option. It should be -c<paper_color>:<ink_color>\n");
226 exit(3);
227 }
228 if (paper_color <16 || paper_color >23 || ink_color < 0 || ink_color > 7)
229 {
230 fprintf(stderr, "Wrong colors. Paper color should be between 16 and 23 and ink color between 0 and 7\n");
231 exit(3);
232 }
233 // if the name was before
234 if (tape_name_index > 0)
235 {
236 memset(system_sect + 9, ' ', 21);
237 *(system_sect + 9) = (char)27;
238 *(system_sect + 10) = generateEscapeCode(paper_color);
239 *(system_sect + 11) = (char)27;
240 *(system_sect + 12) = generateEscapeCode(ink_color);
241 if (strlen(argv[tape_name_index]) - 2 > 17)
242 {
243 fprintf(stderr, "Disk label too long (if you use colors you loose four characters)\n");
244 exit(3);
245 }
246 memcpy(system_sect + 13, argv[tape_name_index] + 2, strlen(argv[tape_name_index]) - 2);
247 }
248 break;
249 case 'i':
250 case 'I':
251 if (strlen(argv[i]) - 2 > 60)
252 {
253 fprintf(stderr,"Init string too long\n");
254 exit(3);
255 }
256 memcpy(system_sect+0x1E,argv[i]+2,strlen(argv[i])-2);
257 // remember where it was
258 tape_name_index = i;
259 break;
260 case 'n':
261 case 'N':
262 memset(system_sect+9,' ',21);
263 // if the colors were before
264 if (paper_color > 0 && ink_color >= 0)
265 {
266 *(system_sect + 9) = (char)27;
267 *(system_sect + 10) = generateEscapeCode(paper_color);
268 *(system_sect + 11) = (char)27;
269 *(system_sect + 12) = generateEscapeCode(ink_color);
270 if (strlen(argv[i]) - 2 > 17)
271 {
272 fprintf(stderr, "Disk label too long (if you use colors you loose four characters)\n");
273 exit(3);
274 }
275 memcpy(system_sect + 13, argv[i] + 2, strlen(argv[i]) - 2);
276 }
277 else
278 {
279 // if there are no colors do like before
280 // if the colors are after we will overwrite the label
281 if (strlen(argv[i]) - 2 > 21)
282 {
283 fprintf(stderr, "Disk label too long\n");
284 exit(3);
285 }
286 memcpy(system_sect + 9, argv[i] + 2, strlen(argv[i]) - 2);
287 }
288 tape_name_index = i;
289 break;
290
291 default:
292 fprintf(stderr,"Bad option : %c\n",argv[i][1]);
293 exit(2);
294 }
295 }
296 }
297
298 dsk=fopen(argv[argc-1],"wb");
299 if (dsk==NULL)
300 {
301 fprintf(stderr,"Cannot open %s for writing\n",argv[2]);
302 exit(1);
303 }
304
305 memset(bitmap+0x10,0xFF,sizeof(sector)-0x10);
306 for (i=0; i<99; i++)
307 { // 99 secteurs pour sedoric
308 int track= i/NBSECT;
309 int sector = i%NBSECT + 1;
310 allocate_sector(track,sector,sedoric+i*256);
311 }
312 allocate_sector(DIRTRACK,1,system_sect);
313 allocate_sector(DIRTRACK,2,bitmap);
314 allocate_sector(DIRTRACK,4,directory);
315
316 for (tape_num=1; tape_num<argc-1; tape_num++)
317 {
318 if (argv[tape_num][0]=='-') continue;
319 tape=fopen(argv[tape_num],"rb");
320 if (tape==NULL)
321 {
322 fprintf(stderr,"Cannot read tape image %s\n",argv[tape_num]);
323 exit(1);
324 }
325 printf("Reading %s\n",argv[tape_num]);
326
327
328 while (fgetc(tape)!=EOF)
329 {
330 int start,end,i;
331 int readByte;
332 while ( (readByte = fgetc(tape)) != 0x24)
333 {
334 if (readByte < 0)
335 {
336 break;
337 }
338 };
339 if (readByte < 0)
340 {
341 // Case where we miss an EOF because of some invalidl tape file
342 break;
343 }
344
345 for (i=0;i<9;i++) header[i]=fgetc(tape);
346 for (i=0;i<17;i++) {
347 name[i]=fgetc(tape);
348 if (name[i]==0) break;
349 }
350
351 // if the name is null then copy the file name instead
352 if (name[0] == 0)
353 {
354 // only take the file name from the path
355 char *lastdot;
356 char *fileName = argv[tape_num];
357 // try to find '\\'
358 char *lastsep = strrchr(fileName, '\\');
359 if (lastsep != NULL)
360 {
361 // if there is something after the separator
362 if (lastsep+1 != 0)
363 fileName = lastsep + 1;
364 }
365 else
366 {
367 // try to find /
368 lastsep = strrchr(fileName, '/');
369 if (lastsep != NULL)
370 {
371 // if there is something after the separator
372 if (lastsep + 1 != 0)
373 fileName = lastsep + 1;
374 }
375 }
376
377 // remove the extension if there is one
378 lastdot = strrchr(fileName, '.');
379 if (lastdot != NULL)
380 *lastdot = 0;
381 for (i = 0; i<17; i++)
382 {
383 name[i] = fileName[i];
384 if (name[i] == 0) break;
385 }
386 }
387
388 start=(header[6]<<8)+header[7];
389 end =(header[4]<<8)+header[5];
390 for (i=0; i<end+1-start; i++)
391 file_buffer[i]=fgetc(tape);
392 printf("Found %s\n",name);
393 store_file(file_buffer,name,header);
394 bitmap[4]++; // number of files
395 dir_offset+=16;
396 if (dir_offset==0x100)
397 {
398 find_free_sector(directory);
399 directory[0]=track;
400 directory[1]=sect;
401 update_sector(dir_track,dir_sect,directory);
402 memset(directory,0,sizeof(sector));
403 dir_track=track;
404 dir_sect=sect;
405 dir_offset=0x10;
406 update_sector(dir_track,dir_sect,directory);
407 }
408 }
409 fclose(tape);
410 tape=NULL;
411 }
412 directory[2]=dir_offset;
413 update_sector(dir_track,dir_sect,directory);
414
415 if (track>=tracks) tracks=track+1;
416 total_sectors=tracks*NBSECT;
417 free_sectors=total_sectors-used_sectors;
418 bitmap[2]=free_sectors & 0xFF;
419 bitmap[3]=free_sectors >> 8;
420 bitmap[6]=tracks;
421 bitmap[9]=tracks;
422 update_sector(DIRTRACK,2,bitmap);
423
424 imageheader.tracks=tracks;
425 fwrite(&imageheader,sizeof(imageheader),1,dsk);
426 for (track=0;track<tracks;track++)
427 for (sect=1;sect<=NBSECT;sect++)
428 fwrite(disk[track][sect-1],sizeof(sector),1,dsk);
429
430 return 0;
431 }
432
433

  ViewVC Help
Powered by ViewVC 1.1.26