1 /*
2  *      PC-8801 application packager
3  *
4  *      $Id: pc88.c - Stefano $
5  */
6 
7 
8 #include "appmake.h"
9 #include "fcntl.h"
10 
11 /* Binding to functions in nec.c */
12 extern void nec_rawout (FILE *fpout, unsigned char b);
13 extern void nec_bit (FILE *fpout, unsigned char bit);
14 extern char nec_fast;
15 extern char nec_22;
16 
17 static char             *binname      = NULL;
18 static char             *crtfile      = NULL;
19 static char             *outfile      = NULL;
20 static int               origin       = -1;
21 static char              audio        = 0;
22 static char              dumb         = 0;
23 static char              help         = 0;
24 
25 static long              elapsed;
26 
27 
28 /* Options that are available for this module */
29 option_t pc88_options[] = {
30     { 'h', "help",     "Display this help",          OPT_BOOL,  &help},
31     { 'b', "binfile",  "Linked binary file",         OPT_STR,   &binname },
newbrain_exec()32     { 'c', "crt0file", "crt0 file used in linking",  OPT_STR,   &crtfile },
33     { 'o', "output",   "Name of output file",        OPT_STR,   &outfile },
34     {  0,  "audio",    "Create also a WAV file",     OPT_BOOL,  &audio },
35     {  0,  "fast",     "Create a fast loading WAV",  OPT_BOOL,  &nec_fast },
36     {  0,  "22",       "22050hz bitrate option",     OPT_BOOL,  &nec_22 },
37     {  0,  "dumb",     "Just convert to WAV a tape file",  OPT_BOOL,  &dumb },
38     {  0 , "org",      "Origin of the binary",       OPT_INT,   &origin },
39     {  0,  NULL,       NULL,                         OPT_NONE,  NULL }
40 };
41 
42 
43 
44 
45 void pc88_write_tick(long tick, FILE* fpout)
46 {
47 	writelong(elapsed, fpout);
48 	writelong(tick, fpout);
49 
50 	elapsed += tick;
51 }
52 
53 
54 void pc88_write_data_tag(int datlen, FILE* fpout)
55 {
56 	writeword(0x101, fpout);		/* Data block TAG ID */
57 	writeword(12 + datlen, fpout);	/* Whole TAG len */
58 	/* 1200 baud: actual data number of bytes × 44
59 	    600 baud: actual data number of bytes × 88 */
60 	pc88_write_tick(44 * datlen, fpout);
61 	writeword(datlen, fpout);
62 
63 	writeword(0x01cc, fpout);		/*  00CCH (600baud) or 01CCH (1200baud). */
64 }
65 
66 
67 
68 long getlong (FILE *fpin)
69 {
70 	return (fgetc(fpin)+256*fgetc(fpin)+65536*fgetc(fpin)+16777216*fgetc(fpin));
71 }
72 
73 
74 /*
75  * Execution starts here
76  */
77 
78 int pc88_exec(char* target)
79 {
80     char filename[FILENAME_MAX + 1];
81     char wavfile[FILENAME_MAX+1];
82     char name[10];
83     char buf[25];
84     FILE* fpin;
85     FILE* fpout;
86     int len, len2;
87     long pos;
88     unsigned long checksum, ticks;
89     int i, j;
90 
91     if (help)
92         return -1;
93 
94     if (binname == NULL || (!dumb && (crtfile == NULL && origin == -1))) {
95         return -1;
96     }
97 
98 
99 	/* Creating the ".T88" file */
100 
101     if (dumb)
102         strcpy(filename, binname);
103 
104 	else {
105 
106         if (outfile == NULL) {
107             strcpy(filename, binname);
108                 suffix_change(filename, ".t88");
109         } else {
110             strcpy(filename, outfile);
111         }
112 
113         if (strcmp(binname, filename) == 0) {
114             exit_log(1,"Input and output file names must be different\n");
115         }
116 
117         if (origin != -1) {
118             pos = origin;
119         } else {
120             if ((pos = get_org_addr(crtfile)) == -1) {
121                 exit_log(1,"Could not find parameter ZORG (not z88dk compiled?)\n");
122             }
123         }
124 
125         if ((fpin = fopen_bin(binname, crtfile)) == NULL) {
126             exit_log(1, "Can't open input file %s\n", binname);
127         }
128 
129         if (fseek(fpin, 0, SEEK_END)) {
130             fclose(fpin);
131             exit_log(1, "Couldn't determine size of file\n");
132         }
133 
134         len = ftell(fpin);
135 
136         fseek(fpin, 0L, SEEK_SET);
137 
138         if ((fpout = fopen(filename, "wb")) == NULL) {
139             fclose(fpin);
140             exit_log(1,"Can't open output file\n");
141         }
142 
143 
144 		elapsed=0;
145 
146         /* T88 FILE HEADER */
147         writestring("PC-8801 Tape Image(T88)", fpout);
148 		writebyte(0, fpout);		/* String termination */
149 
150         /* Version TAG */
151 		writeword(1, fpout);		/* TAG ID for version */
152 		writeword(2, fpout);		/* TAG len */
153 		writeword(0x100, fpout);	/* V.0100 */
154 
155         /* Blank space */
156 		//writeword(0x100, fpout);	/* TAG ID for blank */
157 		//writeword(8, fpout);		/* TAG len */
158 		//pc88_write_tick(10000, fpout);
159 
160         /* LEADER */
161 		writeword(0x102, fpout);	/* TAG ID for space */
162 		writeword(8, fpout);		/* TAG len */
163 		pc88_write_tick(7928, fpout);
164 
165 		/* Filename block leading tone */
166 		writeword(0x103, fpout);	/* TAG ID for mark */
167 		writeword(8, fpout);		/* TAG len */
168 		pc88_write_tick(1320, fpout);
169 
170 		/* Deal with the filename */
171 		strcpy(name, "$$$      ");
172 		for (i = 0; (i < 6) && (isalnum(filename[i])); i++)
173 			name[i+3] = toupper(filename[i]);
174 
175 		pc88_write_data_tag(9, fpout);
176 		for (i = 0; i < 9; i++)
177 			writebyte(name[i], fpout);
178 
179 		/* Data block leading tone */
180 		writeword(0x103, fpout);	/* TAG ID for mark */
181 		writeword(8, fpout);		/* TAG len */
182 		pc88_write_tick(330, fpout);
183 
184 
185 		/* Binary block */
186 		pc88_write_data_tag(len + 7 + 3 * ((len+127)/128), fpout);		/* Total length */
187 
188 		/* Data block with ORG position */
189 		checksum = 0;
190 		writebyte(0x3a, fpout);
191 		writebyte_cksum((unsigned char)(pos >> 8), fpout, &checksum);    // MSB
192 		writebyte_cksum((unsigned char)(pos & 0xff), fpout, &checksum);  // LSB
193 		writebyte(0x100 - (checksum & 0xff), fpout);
194 
195 		len2=128;
196 		for (i=0; i<len; i+=len2) {
197 			if ((len-i)<128) len2=len-i;
198 			writebyte(0x3a, fpout);
199 			checksum = 0;
200 			writebyte_cksum(len2, fpout, &checksum);
201 			for (j = 0; j < len2; j++) {
202 				writebyte_cksum(getc(fpin),fpout, &checksum);
203 			}
204 			writebyte(0x100 - (checksum & 0xff), fpout);
205 		}
206 
207 		writebyte(0x3a, fpout);
208 		writebyte(0x00, fpout);
209 		writebyte(0x3a, fpout);	// end
210 
211 		/* Tail */
212 		writeword(0x103, fpout);	/* TAG ID for mark */
213 		writeword(8, fpout);		/* TAG len */
214 		pc88_write_tick(3966, fpout);
215 
216 		writeword(0x102, fpout);	/* TAG ID for space */
217 		writeword(8, fpout);		/* TAG len */
218 		pc88_write_tick(9252, fpout);
219 
220 		/* End TAG */
221 		writeword(0, fpout);		/* TAG ID for END */
222 		writeword(0, fpout);		/* TAG body (no content) */
223 
224 
225         fclose(fpin);
226         fclose(fpout);
227 	}
228 
229 	/* ***************************************** */
230 	/*  Now, if requested, create the audio file */
231 	/* ***************************************** */
232     if ((audio) || (nec_fast) || (nec_22)) {
233 		if ( (fpin=fopen(filename,"rb") ) == NULL ) {
234 			exit_log(1,"Can't open file %s for wave conversion\n",filename);
235 		}
236 
237 		for (i=0; i<23; i++)
238 			buf[i]=fgetc(fpin);
239 		if (strncmp(buf,"PC-8801 Tape Image(T88)",23)) {
240             fclose(fpin);
241             exit_log(1,"The file to be converted is not in T88 format.\n");
242 		}
243 		fgetc(fpin);
244 
245         strcpy(wavfile,filename);
246 
247 			suffix_change(wavfile,".RAW");
248 
249 		if ( (fpout=fopen(wavfile,"wb") ) == NULL ) {
250 			exit_log(1,"Can't open output raw audio file %s\n",wavfile);
251 		}
252 
253 		while (i!=0) {
254 			i=fgetc(fpin)+256*fgetc(fpin);
255 			switch (i)
256 			{
257 				case 1:
258 					fgetc(fpin); fgetc(fpin);
259 					if (dumb) {
260 						printf ("T88 file version: ");
261 						printf ("%X\n",fgetc(fpin)+256*fgetc(fpin));
262 					} else {
263 						fgetc(fpin); fgetc(fpin);
264 					}
265 					break;
266 				case 0x100:
267 					if (dumb)
268 						printf ("  -Blank- : ");
269 					fgetc(fpin); fgetc(fpin);	/* TAG length */
270 					ticks=getlong(fpin);
271 					if (dumb)
272 						printf (" elapsed=%0.2f sec., ",(float) ticks / 4800);
273 					ticks=getlong(fpin);
274 					if (dumb)
275 						printf (" ticks=%0.2f sec.\n",(float) ticks / 4800);
276 
277 					for (i = 0; (i < ticks); i++)	/* duration approximated */
278 						fputc(0x80, fpout);
279 
280 					break;
281 				case 0x102:
282 					if (dumb)
283 						printf ("  SPACE tone : ");  /* 1200 */
284 					fgetc(fpin); fgetc(fpin);	/* TAG length */
285 					ticks=getlong(fpin);
286 					if (dumb)
287 						printf (" elapsed=%0.2f sec., ",(float) ticks / 4800);
288 					ticks=getlong(fpin);
289 					if (dumb)
290 						printf (" ticks=%0.2f sec.\n",(float) ticks / 4800);
291 
292 					for (i = 0; (i < (ticks/4)); i++)	/* duration approximated */
293 						nec_bit(fpout, 0);
294 
295 					break;
296 				case 0x103:
297 					if (dumb)
298 						printf ("  MARK tone : ");	/* 2400 */
299 					fgetc(fpin); fgetc(fpin);	/* TAG length */
300 					ticks=getlong(fpin);
301 					if (dumb)
302 						printf (" elapsed=%0.2f sec., ",(float) ticks / 4800);
303 					ticks=getlong(fpin);
304 					if (dumb)
305 						printf (" ticks=%0.2f sec.\n",(float) ticks / 4800);
306 
307 					for (i = 0; (i < (ticks/4)); i++)	/* duration approximated */
308 						nec_bit(fpout, 1);
309 
310 					break;
311 				case 0x101:
312 					if (dumb)
313 						printf ("    Data block : ");
314 					i=fgetc(fpin)+256*fgetc(fpin);
315 					if (dumb)
316 						printf ("TAG length: %d\n",i);
317 					for (j=1; j<=10; j++) fgetc(fpin);
318 					j=fgetc(fpin)+256*fgetc(fpin);
319 					switch (j) {
320 					case 0x00cc:
321 						printf ("      600 baud.   WARNING: data will be saved at 1200 bps\n");
322 						break;
323 					case 0x01cc:
324 						if (dumb)
325 							printf ("      1200 baud\n");
326 						break;
327 					default:
328 						printf ("   WARNING: unexpected value for 'baud rate': 0x%X\n",j);
329 						break;
330 					}
331 					i-=12;
332 					for (j=1; j<=i; j++)
333 						nec_rawout(fpout,fgetc(fpin));
334 					break;
335 				default:
336 					if (dumb)
337 						printf ("TAG type: %X\n",i);
338 					i=fgetc(fpin)+256*fgetc(fpin);
339 					if (dumb)
340 						printf ("TAG len: %X\n",i);
341 					for (j=1; j<=i; j++) fgetc(fpin);
342 					break;
343 			}
344 		}
345         fclose(fpin);
346         fclose(fpout);
347 
348 		/* Now complete with the WAV header */
349 		if (nec_22)
350 			raw2wav_22k(wavfile,2);
351 		else
352 			raw2wav(wavfile);
353 	}
354 
355     return 0;
356 }
357