1 /*
2  *        Laser 200/300 VZ to CAS file converter
3  *        and WAV generator (dumb mode is not necessary)
4  *
5  *        $Id: vz.c $
6  */
7 
8 #include "appmake.h"
9 
10 static char* binname = NULL;
11 static char* crtfile = NULL;
12 static char* outfile = NULL;
13 static char* blockname = NULL;
14 static char help = 0;
15 static char audio = 0;
16 static char fast = 0;
17 static char vz_22 = 0;
18 
19 static int create_file(const char* target, int laser500);
20 
21 /* Options that are available for this module */
22 option_t vz_options[] = {
23     { 'h', "help", "Display this help", OPT_BOOL, &help },
24     { 'b', "binfile", "Linked binary file", OPT_STR, &binname },
25     { 'c', "crt0file", "crt0 file used in linking", OPT_STR, &crtfile },
26     { 'o', "output", "Name of output file", OPT_STR, &outfile },
27     { 0, "audio", "Create also a WAV file", OPT_BOOL, &audio },
28     { 0, "fast", "Create a fast loading WAV", OPT_BOOL, &fast },
29     { 0, "22", "22050hz bitrate option", OPT_BOOL, &vz_22 },
30     { 0, "blockname", "Name of the code block", OPT_STR, &blockname },
31     { 0, NULL, NULL, OPT_NONE, NULL }
32 };
33 
34 option_t laser500_options[] = {
35     { 'h', "help", "Display this help", OPT_BOOL, &help },
36     { 'b', "binfile", "Linked binary file", OPT_STR, &binname },
37     { 'c', "crt0file", "crt0 file used in linking", OPT_STR, &crtfile },
38     { 'o', "output", "Name of output file", OPT_STR, &outfile },
39     { 0, "fast", "Create a fast loading WAV", OPT_BOOL, &fast },
40     { 0, "22", "22050hz bitrate option", OPT_BOOL, &vz_22 },
41     { 0, "audio", "Create also a WAV file", OPT_BOOL, &audio },
42     { 0, NULL, NULL, OPT_NONE, NULL }
43 };
44 
vz_click(FILE * fpout,int click)45 void vz_click(FILE* fpout, int click)
46 {
47     int i;
48 
49     for (i = 0; i < (click); i++)
50         fputc(0xe0, fpout);
51     for (i = 0; i < (click); i++)
52         fputc(0x20, fpout);
53 }
54 
vz_bit(FILE * fpout,unsigned char bit)55 void vz_bit(FILE* fpout, unsigned char bit)
56 {
57     int bip, bop;
58 
59     if (fast) {
60         bip = 11;
61         bop = 23;
62     } else {
63         bip = 12;
64         bop = 25;
65     }
66 
67     if (bit) {
68         /* '1' */
69         vz_click(fpout, bip);
70         vz_click(fpout, bip);
71         vz_click(fpout, bip);
72     } else {
73         /* '0' */
74         vz_click(fpout, bip);
75         vz_click(fpout, bop);
76     }
77 }
78 
vz_rawout(FILE * fpout,unsigned char b)79 void vz_rawout(FILE* fpout, unsigned char b)
80 {
81     static unsigned char c[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
82     int i;
83 
84     /* byte */
85     for (i = 0; i < 8; i++)
86         vz_bit(fpout, b & c[i]);
87 }
88 
vz_exec(char * target)89 int vz_exec(char* target)
90 {
91     return create_file(target, 0);
92 }
93 
laser500_exec(char * target)94 int laser500_exec(char* target)
95 {
96     return create_file(target, 1);
97 }
98 
create_file(const char * target,int laser500)99 static int create_file(const char* target, int laser500)
100 {
101     char filename[FILENAME_MAX + 1];
102     char wavfile[FILENAME_MAX + 1];
103     char name[18];
104     FILE *fpin, *fpout;
105     int c;
106     int i;
107     int len, hdlen;
108     unsigned long checksum;
109     unsigned short startaddr;
110     unsigned short endaddr;
111 
112     if (help)
113         return -1;
114 
115     if (binname == NULL) {
116         return -1;
117     }
118 
119     if (outfile == NULL) {
120         strcpy(filename, binname);
121         suffix_change(filename, ".cas");
122     } else {
123         strcpy(filename, outfile);
124     }
125 
126     if (blockname == NULL)
127         blockname = zbasename(binname);
128 
129     if ((fpin = fopen_bin(binname, crtfile)) == NULL) {
130         exit_log(1, "Can't open input file %s\n", binname);
131     }
132 
133     /*
134  *        Now we try to determine the size of the file
135  *        to be converted
136  */
137     if (fseek(fpin, 0, SEEK_END)) {
138         fclose(fpin);
139         exit_log(1,"Couldn't determine size of file\n");
140     }
141 
142     /*len=ftell(fpin) - sizeof(struct vz);*/
143     len = ftell(fpin);
144     if (!laser500) {
145         len -= 24;
146 
147         /* Get rid of VZ magic (4 bytes) and filename (17 chars) */
148         fseek(fpin, 21L, SEEK_SET);
149     } else {
150         fseek(fpin, 0L, SEEK_SET);
151     }
152 
153     if ((fpout = fopen(filename, "wb")) == NULL) {
154         fclose(fpin);
155         exit_log(1,"Can't open output file\n");
156     }
157 
158     for (i = 0; i < 128; i++)
159         fputc(0x80, fpout); /* preamble */
160     for (i = 0; i < 5; i++)
161         fputc(0xFE, fpout); /* leadin */
162 
163     if (laser500) {
164         fputc(0xf1, fpout); // Binary (same as VZ200?)
165     } else {
166         c = fgetc(fpin); /* File Type */
167         fputc(c, fpout);
168     }
169 
170     /* Deal with the filename */
171     if (strlen(blockname) >= 17) {
172         strncpy(name, blockname, 17);
173         name[17] = 0;
174     } else {
175         strcpy(name, blockname);
176         strncat(name, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 17 - strlen(blockname));
177     }
178     for (i = 0; i <= strlen(name); i++)
179         writebyte(toupper(name[i]), fpout);
180 
181     if (laser500) {
182         // Header2
183         fputc(0x00, fpout);
184         for (i = 0; i < 10; i++) {
185             fputc(0x80, fpout);
186         }
187         fputc(0xff, fpout);
188         startaddr = 0x89a3 - 14;
189     } else {
190         startaddr = fgetc(fpin) + 256 * fgetc(fpin);
191     }
192     endaddr = startaddr + len;
193 
194     checksum = 0;
195     writeword_cksum(startaddr, fpout, &checksum);
196     writeword_cksum(endaddr, fpout, &checksum);
197 
198     for (i = 0; i < len; i++) {
199         c = getc(fpin);
200         writebyte_cksum(c, fpout, &checksum);
201     }
202 
203     writeword((checksum % 65536), fpout); /* name checksum */
204 
205     fclose(fpin);
206     fclose(fpout);
207 
208     /* ***************************************** */
209     /*  Now, if requested, create the audio file */
210     /* ***************************************** */
211     if ((audio) || (fast) || (vz_22)) {
212         if ((fpin = fopen(filename, "rb")) == NULL) {
213             exit_log(1, "Can't open file %s for wave conversion\n", filename);
214         }
215 
216         if (fseek(fpin, 0, SEEK_END)) {
217             fclose(fpin);
218             exit_log(1,"Couldn't determine size of file\n");
219         }
220         len = ftell(fpin);
221         fseek(fpin, 0L, SEEK_SET);
222 
223         strcpy(wavfile, filename);
224         suffix_change(wavfile, ".RAW");
225         if ((fpout = fopen(wavfile, "wb")) == NULL) {
226             exit_log(1, "Can't open output raw audio file %s\n", wavfile);
227         }
228 
229         /* preamble + leadin + type + name + string termination */
230         hdlen = 128 + 5 + 1 + strlen(name) + 1;
231 
232         /* leading silence */
233         for (i = 0; i < 0x20000; i++)
234             fputc(0x20, fpout);
235 
236         /* header+filename */
237         for (i = 0; (i < hdlen); i++) {
238             c = getc(fpin);
239             vz_rawout(fpout, c);
240         }
241 
242         /* short gap between filename and data block */
243 
244         /*
245 		 * useless code to simulate the original 'click'
246 		 * (a totally silent gap must be better)
247 		 *
248 		fputc(0x60, fpout);
249 		fputc(0x60, fpout);
250 	    for (i=0x20; i < 0x70; i++) {
251 			fputc(i, fpout);
252 			fputc(i, fpout);
253 		}
254 	    for (i=0; i < 25; i++)
255 			fputc(0, fpout);
256 		*/
257 
258         for (i = 0; i < 159; i++) {
259             fputc(0x20, fpout);
260         }
261 
262         /* start addr + end addr + program block */
263         for (i = 0; (i < (len - hdlen)); i++) {
264             c = getc(fpin);
265             vz_rawout(fpout, c);
266         }
267 
268         for (i = 0; (i <= 10); i++) {
269             vz_rawout(fpout, 0);
270         }
271 
272         /* trailing silence */
273         for (i = 0; i < 0x1500; i++)
274             fputc(0x20, fpout);
275 
276         fclose(fpin);
277         fclose(fpout);
278 
279         /* Now let's think at the WAV format */
280 		if (vz_22)
281 			raw2wav_22k(wavfile,2);
282 		else
283 			raw2wav(wavfile);
284     }
285 
286     return 0;
287 }
288