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