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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1184 - (show annotations)
Wed Sep 17 20:18:26 2014 UTC (5 years, 2 months ago) by Jylam
File MIME type: text/plain
File size: 11079 byte(s)
Fix gcc warnings on tap2cd

1 /* tap2cd : converts .TAP images to 22050 baud WAV files */
2 /* F.Frances 1999-2012 */
3
4 /* Modified by Chema June 2012 to include a special loader */
5 /* which sets HIRES and loads the screen area first. */
6 /* Also changes a bit the timing of the loading routine to */
7 /* avoid loading errors on some machines */
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12
13 #define FALSE 0
14 #define TRUE 1
15
16 FILE *in,*out;
17 int file_size=0;
18 unsigned char header[9];
19 unsigned char Mem[48*1024];
20 char name[18];
21 int check_crc=0;
22 int df_loader=0;
23
24 struct {
25 char sig[4];
26 int riff_size;
27 char typesig[4];
28 char fmtsig[4];
29 int fmtsize;
30 short tag;
31 short channels;
32 int freq;
33 int bytes_per_sec;
34 short byte_per_sample;
35 short bits_per_sample;
36 char samplesig[4];
37 int datalength;
38 } sample_riff= { "RIFF",0,"WAVE","fmt ",16,1,1,22050,22050,1,8,"data",0 };
39
40
41 // These files are created by 'CreateLoader.bat'
42 #include "loader_df.h"
43 #include "loader_crc.h"
44 #include "loader_nocrc.h"
45
46
47 static int current_level=0x20;
48 void inverse_level() { current_level=255-current_level; }
49
50 void usage()
51 {
52 printf("Usage: tap2cd [-c|-h] <.TAP file> <WAV file>\n");
53 printf("(-c check CRC, -h load HIRES screen first)\n");
54 exit(1);
55 }
56
57 void check_args(int argc,char *argv[])
58 {
59 int opts=0;
60 if (argc==1) usage();
61 if (argv[1][0]=='-') {
62 opts=1;
63 if (argv[1][1]=='c' || argv[1][1]=='C') {
64 check_crc=1; printf("CRC check activated\n");
65 }else
66 if (argv[1][1]=='h' || argv[1][1]=='H') {
67 df_loader=1;printf("CRC check activated. Loading of HIRES screen first activated\n");
68 } else usage();
69 }
70 if (argc!=1+opts+2) usage();
71 in=fopen(argv[1+opts],"rb");
72 if (in==NULL) {
73 printf("Cannot open %s file\n",argv[1+opts]);
74 usage();
75 }
76 out=fopen(argv[2+opts],"wb");
77 if (out==NULL) {
78 printf("Cannot create %s file\n",argv[2+opts]);
79 usage();
80 }
81 fwrite(&sample_riff,1,sizeof(sample_riff),out);
82 }
83
84 void emit_level(int size)
85 {
86 int i;
87 inverse_level();
88 for (i=0;i<size;i++) fputc(current_level,out);
89 file_size+=size;
90 }
91
92 void emit_two_fast_bits(int bits)
93 {
94 switch (bits) {
95 case 0: emit_level(5); break;
96 case 1: emit_level(3); break;
97 case 2: emit_level(4); break;
98 case 3: emit_level(2); break;
99 }
100 }
101
102 void emit_standard_short_level() { emit_level(4); }
103 void emit_standard_long_level() { emit_level(10); }
104
105 void emit_standard_bit(int bit)
106 {
107 emit_standard_short_level();
108 if (bit==0) emit_standard_long_level();
109 else emit_standard_short_level();
110 }
111
112 /*
113 Standard durations are 210 µs for a short level and 418 µs for a long level,
114 hence 420 µs for a full period of two short levels (i.e a '1' bit),
115 and 628 µs for a full period of a short level followed by a long level (a '0' bit).
116 The threshold when reading with the Oric rom is set at 512 µs.
117 Here we use a number of 22050 Hz samples, so the values are a bit changed:
118 4 samples for a short level (i.e. 181 µs), and 10 samples for a long level (454 µs).
119 So a '1' bit is 362 µs long, and a '0' bit is 635 µs long.
120
121 The '0' bit waveform is asymetric, since it consists in a short level followed by
122 a long level. This is a good thing for the Oric reading routines because a bug in the
123 write routine adds half a bit (half a period) to every byte written... As a result, in
124 one byte out of two, the second half of the period (the one that differentiates 0 and 1)
125 is written as the high level instead of the low level. When reading, the high level is
126 always considered as the first part of the period, so in one byte out of two, the part
127 of the period that was written in second place becomes the first part when reading
128 (it is associated with the first part of next bit). So, thanks to a scheme where
129 the first part written is always the same duration, the bits read are the same than
130 the ones written, except that a variable number of stop bits are read between two
131 consecutives bytes (3 and half stop bits are written between two consecutive bytes,
132 but the read routines detects alternately 3 and 4 stop bits between two bytes).
133
134 This inversing "feature" is corrected here (there's no additional half period),
135 but it seems that the waveform emitted by a number of player devices is reversed
136 (all the high levels become low levels, and low levels become high levels),
137 so it's good to keep this asymetric coding for the standard format.
138 */
139
140 void emit_standard_byte_with_no_stop_bit(int val)
141 {
142 int i,parity=1;
143 emit_standard_bit(0);
144 for (i=0; i<8; i++,val>>=1) {
145 parity+=val&1;
146 emit_standard_bit(val&1);
147 }
148 emit_standard_bit(parity&1);
149 }
150
151 void emit_standard_byte(int val)
152 {
153 emit_standard_byte_with_no_stop_bit(val);
154 emit_standard_bit(1);
155 emit_standard_bit(1);
156 emit_standard_bit(1);
157 }
158
159 void emit_fast_byte(int val)
160 {
161 emit_two_fast_bits((val>>6)&3);
162 emit_two_fast_bits((val>>4)&3);
163 emit_two_fast_bits((val>>2)&3);
164 emit_two_fast_bits(val&3);
165 }
166
167 void emit_fast_synchro()
168 {
169 /*
170 The turbo fast format is not affected by the waveform inversion because each high or
171 low level is measured independently. However when the standard bytes are read,
172 we don't know if the waveform is inversed or not, and thus we don't know if the first turbo
173 fast level will be a high or a low level... So, an additional 1/2 bit is used here to be sure the
174 last bit (parity bit) is complete in standard format: if the waveform is reversed, the last
175 part of the parity bit will be associated to the first part of the bit that follows.
176 A standard short level is thus written to complete last bit in case the waveform will be
177 inversed, and then a small synchro is written, consisting in a sequence of very short levels
178 (2 samples each) followed by a longer level (5 samples long).
179 */
180 emit_standard_short_level();
181 emit_two_fast_bits(3); /* two '1' bits */
182 emit_two_fast_bits(3); /* two '1' bits */
183 emit_two_fast_bits(3); /* two '1' bits */
184 emit_two_fast_bits(3); /* two '1' bits */
185 emit_two_fast_bits(2); /* a '1' bit and a '0' bit */
186
187 /* two bits at once are shifted in the shifter.
188 But when the first bit enters the shifter, another bit is shifted out :
189 this bit must be a 'one' for the second shift to work correctly (space
190 and time constraints of the loader).
191 When the second bit enters the shifter, another bit is shifted out too.
192 If it is a 'zero', it means a byte is complete.
193 This is why the shifter is initialized to 11111110 between two bytes.
194 However the shifter is initialized to 11111111 before loading a page,
195 so a byte will never appear complete until a first zero bit exits the
196 shifter. This allows to implement a synchro : a sequence of ones followed
197 by a single 0 (beware that one bit out of two must always be a one).
198 */
199 }
200
201 void emit_standard_gap(int size)
202 {
203 int i;
204 for (i=0;i<size;i++) emit_standard_bit(1); /* stop bits to skip */
205 }
206
207 int compute_crc8(int start, int size)
208 {
209 int crc=0;
210 int i;
211 for (i=start;i<start+size;i++) {
212 int bits;
213 int shifter=Mem[i];
214 for (bits=0; bits<8; bits++) {
215 shifter<<=1;
216 crc<<=1;
217 if ((shifter&0x100)!=0) crc|=1;
218 if ((crc&0x100)!=0)
219 crc^=0x1D5; /* x^8+x^7+x^6+x^4+x^2+1 polynomial */
220 }
221 }
222 return crc;
223 }
224
225 void emit_fast_page(int adr,int size)
226 {
227 int i;
228 int offset=256-size;
229 int page=adr-offset;
230 int crc = compute_crc8(adr,size);
231 emit_standard_gap(10);
232 emit_standard_byte(page>>8);
233 emit_standard_byte(page&0xFF);
234 if (check_crc||df_loader)
235 emit_standard_byte(crc);
236 emit_standard_byte_with_no_stop_bit(offset);
237 emit_fast_synchro();
238 for (i=0;i<size;i++)
239 emit_fast_byte(Mem[adr+i]);
240 if (check_crc||df_loader) /* give enough time to compute the crc */
241 emit_standard_gap(10+115*size/256);
242 }
243
244 void emit_standard_header(char header[])
245 {
246 int i;
247 for (i=0;i<300;i++) emit_standard_byte(0x16);
248 emit_standard_byte(0x24);
249 for (i=0;i<9;i++) emit_standard_byte(header[i]);
250 for (i=0;name[i];i++) emit_standard_byte(name[i]);
251 emit_standard_byte(0);
252 }
253
254 void emit_loader()
255 {
256 int i;
257 char loader_header[9]={
258 0, /* not an array of integers */
259 0, /* not an array of strings */
260 0x80, /* memory block */
261 0xC7, /* AUTO-exec */
262 0x01,0xFF, /* end address (will be adjusted) */
263 0x01,0x00, /* start address (0x100) */
264 0 /* not used */
265 };
266
267
268 if (check_crc){
269 loader_header[5]=(sizeof(loader_check_crc)-1) & 0xFF;
270 emit_standard_header(loader_header);
271 emit_standard_gap(30);
272 for (i=0;i<sizeof(loader_check_crc);i++) emit_standard_byte(loader_check_crc[i]);
273 }else{
274 if (df_loader){
275 loader_header[5]=(sizeof(loader_df)-1) & 0xFF;
276 emit_standard_header(loader_header);
277 emit_standard_gap(30);
278 for (i=0;i<sizeof(loader_df);i++) emit_standard_byte(loader_df[i]);
279 }else{
280 loader_header[5]=(sizeof(loader_no_check)-1) & 0xFF;
281 emit_standard_header(loader_header);
282 emit_standard_gap(30);
283 for (i=0;i<sizeof(loader_no_check);i++) emit_standard_byte(loader_no_check[i]);
284 }
285 }
286
287
288 }
289
290 void emit_fast_prog(int start,int end)
291 {
292 int i;
293 emit_loader();
294 if (df_loader)
295 emit_standard_gap(2000);
296 else
297 emit_standard_gap(100);
298
299 emit_fast_page(0x2A8,9); /* header is emitted as a small 9-bytes page */
300
301 if (df_loader){
302 end=0xbf3f;
303 for(i=0xa000;i<=end;i+=256)
304 if (i+255<end)
305 emit_fast_page(i,256);
306 else
307 emit_fast_page(i,end-i+1);
308 end =0x9fff;
309 for (i=start;i<=end;i+=256)
310 if (i+255<end) emit_fast_page(i,256);
311 else emit_fast_page(i,end-i+1);
312 }else{
313 for (i=start;i<=end;i+=256)
314 if (i+255<end) emit_fast_page(i,256);
315 else emit_fast_page(i,end-i+1);
316 }
317
318 emit_standard_gap(10); /* small synchro gap */
319 emit_standard_byte(0); /* marker for last page */
320 }
321
322 void ask_name(char *name)
323 {
324 char reply[80];
325 do {
326 if (name[0])
327 printf("Stored name is %s, enter new name (or RETURN to keep): ",name);
328 else
329 printf("Program has no stored name, enter a name: ");
330 gets(reply);
331 if (reply[0]) strcpy(name,reply);
332 } while (name[0]==0);
333 }
334
335 int main(int argc,char *argv[])
336 {
337 int start,end;
338 int firstprog=TRUE;
339 int i;
340
341 check_args(argc,argv);
342
343 while (!feof(in)) {
344 while (fgetc(in)==0x16) ; /* read synchro (0x24 included) */
345 if (feof(in)) break;
346 for (i=8;i>=0;i--) Mem[0x2A8+i]=header[8-i]=fgetc(in); /* header */
347 start=header[6]*256+header[7]; end=header[4]*256+header[5];
348 i=0; while ((name[i++]=fgetc(in))!=0); /* name */
349 for (i=start;i<=end;i++) Mem[i]=fgetc(in);
350 if (firstprog) ask_name(name);
351 emit_fast_prog(start,end);
352 firstprog=FALSE;
353 }
354 emit_standard_gap(1500); /* 0.5s protection at the end */
355 fclose(in);
356 fseek(out,40,SEEK_SET); fwrite(&file_size,1,4,out);
357 file_size+=36;
358 fseek(out,4,SEEK_SET); fwrite(&file_size,1,4,out);
359 fclose(out);
360 return 0;
361 }
362

  ViewVC Help
Powered by ViewVC 1.1.26