1 /*
2  *        Galaksija tape file
3  *
4  *        Based on the original "bin2gtp" program by Tomaz Solc
5  *
test_namespace()6  *        $Id: galaksija.c $
7  */
8 
9 #include "appmake.h"
10 
11 static char             *binname      = NULL;
12 static char             *crtfile      = NULL;
13 static char             *outfile      = NULL;
14 static char             *blockname    = NULL;
15 static int               origin       = -1;
16 static char              audio        = 0;
17 static char              fast         = 0;
18 static char              khz_22       = 0;
19 static char              dumb         = 0;
20 static char              loud         = 0;
21 static char              help         = 0;
22 
23 static char              bit_state    = 0;
24 static uint8_t           h_lvl;
25 static uint8_t           l_lvl;
26 static uint8_t           gal_h_lvl;
27 static uint8_t           gal_l_lvl;
28 
29 
30 
31 /* Options that are available for this module */
32 option_t gal_options[] = {
33     { 'h', "help",     "Display this help",          OPT_BOOL,  &help},
34     { 'b', "binfile",  "Linked binary file",         OPT_STR,   &binname },
35     { 'c', "crt0file", "crt0 file used in linking",  OPT_STR,   &crtfile },
36     { 'o', "output",   "Name of output file",        OPT_STR,   &outfile },
37     {  0,  "audio",    "Create also a WAV file",     OPT_BOOL,  &audio },
38     {  0,  "fast",     "Tweak the audio tones to run a bit faster",  OPT_BOOL,  &fast },
39     {  0,  "22",       "22050hz bitrate option",     OPT_BOOL,  &khz_22 },
40     {  0,  "dumb",     "Just convert to WAV a tape file",  OPT_BOOL,  &dumb },
41     {  0,  "loud",     "Louder audio volume",        OPT_BOOL,  &loud },
42     {  0 , "org",      "Origin of the binary",       OPT_INT,   &origin },
43     {  0 , "blockname", "Name of the code block in tap file", OPT_STR, &blockname},
44     {  0,  NULL,       NULL,                         OPT_NONE,  NULL }
45 };
46 
47 
48 
49 /* two fast cycles for '0', two slow cycles for '1' */
50 
51 void gal_bit(FILE* fpout, unsigned char bit)
52 {
53     int i, period0, period1, pulse_width;
54 
55     if (fast) {
56         period1 = 58;
57         period0 = 145;
58         pulse_width = 22;
59     } else {
60         period1 = 75;
61         period0 = 150;
62         pulse_width = 30;
63     }
64 
65     if (bit_state) {
66         h_lvl = gal_h_lvl;
67         l_lvl = gal_l_lvl;
68     } else {
69         h_lvl = gal_l_lvl;
70         l_lvl = gal_h_lvl;
71     }
72 
73     if (bit) {
74 
75         /* '1' */
76         for (i = 0; i < pulse_width; i++)
77             fputc(l_lvl, fpout);
78         for (i = 0; i < pulse_width; i++)
79             fputc(h_lvl, fpout);
80 
81         for (i = 0; i < period1 - 2 * pulse_width; i++)
82             fputc(0x80, fpout);
83 
84         for (i = 0; i < pulse_width; i++)
85             fputc(l_lvl, fpout);
86         for (i = 0; i < pulse_width; i++)
87             fputc(h_lvl, fpout);
88 
89         for (i = 0; i < period1 - 2 * pulse_width; i++)
90             fputc(0x80, fpout);
91 
92     } else {
93 
94         /* '0' */
95         for (i = 0; i < pulse_width; i++)
96             fputc(l_lvl, fpout);
97         for (i = 0; i < pulse_width; i++)
98             fputc(h_lvl, fpout);
99 
100         for (i = 0; i < period0 - 2 * pulse_width; i++)
101             fputc(0x80, fpout);
102     }
103 }
104 
105 void gal_rawout(FILE* fpout, unsigned char b)
106 {
107     /* bit order is reversed ! */
108     static unsigned char c[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
109     int i, interbyte_pause;
110 
111     if (fast)
112         interbyte_pause = 200;
113     else
114         interbyte_pause = 225;
115 
116     /* interbyte pause */
117     for (i = 0; i < interbyte_pause; i++)
118         fputc(0x80, fpout);
119 
120     /* byte */
121     for (i = 0; i < 8; i++)
122         gal_bit(fpout, (b & c[i]));
123 }
124 
125 #define GTP_BLOCK_STANDARD 0x00
126 #define GTP_BLOCK_TURBO 0x01
127 #define GTP_BLOCK_NAME 0x10
128 
129 int gal_exec(char* target)
130 {
131     char filename[FILENAME_MAX + 1];
132     char wavfile[FILENAME_MAX + 1];
133     int c, i;
134     int len;
135 
136     unsigned long checksum;
137     FILE *fpin, *fpout;
138 
139     char basicdef[] = "\001\000A=USR(&2C3A)\015";
140     int basicdeflen = 15;
141     int datalen;
142 
143     if (help)
144         return -1;
145 
146     if (binname == NULL || (!dumb && (crtfile == NULL && origin == -1))) {
147         return -1;
148     }
149 
150     if (loud) {
151         gal_h_lvl = 0xFF;
152         gal_l_lvl = 0;
153     } else {
154         gal_h_lvl = 0xe0;
155         gal_l_lvl = 0x20;
156     }
157 
158     if (dumb) {
159         strcpy(filename, binname);
160 
161     } else {
162 
163         if (outfile == NULL) {
164             strcpy(filename, binname);
165             suffix_change(filename, ".gtp");
166         } else {
167             strcpy(filename, outfile);
168         }
169 
170         if (blockname == NULL)
171             blockname = zbasename(binname);
172 
173 /* Tomaz's code insertion starts here */
174 
175 #if 0
176 		/* basic start addr */
177 		h2le_short(0x2c3a+len, &data[0]);
178 		/* basic end addr */
179 		h2le_short(0x2c3a+len+basiclen, &data[2]);
180 #endif
181 
182         if ((fpin = fopen_bin(binname, crtfile)) == NULL) {
183             exit_log(1,"File open error\n");
184         }
185 
186         if (fseek(fpin, 0, SEEK_END)) {
187             fclose(fpin);
188             exit_log(1,"Couldn't determine size of file\n");
189         }
190         len = ftell(fpin);
191         fseek(fpin, 0L, SEEK_SET);
192 
193         datalen = 4 + len + basicdeflen;
194 
195         if ((fpout = fopen(filename, "wb")) == NULL) {
196             exit_log(1,"Can't open output file %s\n", filename);
197         }
198 
199         /* **** GTP Header **** */
200 
201         /* *** Name block *** */
202 
203         fputc(GTP_BLOCK_NAME, fpout); /* Block ID: NAME    */
204         writeword(strlen(blockname) + 1, fpout); /* NAME block size   */
205         fputc(0, fpout);
206         fputc(0, fpout);
207         for (i = 0; i <= strlen(blockname); i++) { /* block name string */
208             fputc(blockname[i], fpout);
209         }
210 
211         /* *** Data block *** */
212 
213         fputc(GTP_BLOCK_STANDARD, fpout); /* Block ID: STD SPEED DATA */
214         writeword(datalen + 6, fpout); /* block size               */
215         fputc(0, fpout);
216         fputc(0, fpout);
217 
218         checksum = 0; /* Init checksum */
219 
220         writebyte_cksum(0xa5, fpout, &checksum);
221         writeword_cksum(0x2c36, fpout, &checksum); /* ORG address              */
222         writeword_cksum(0x2c36 + datalen, fpout, &checksum); /* block end location       */
223         writeword_cksum(0x2c36 + 4 + len, fpout, &checksum); /* BASIC start address      */
224         writeword_cksum(0x2c36 + datalen, fpout, &checksum); /* block end location       */
225 
226         /* binary file */
227 
228         for (i = 0; i < len; i++) {
229             c = getc(fpin);
230             writebyte_cksum(c, fpout, &checksum);
231             /* fputc(c,fpout);*/
232         }
233 
234         /* basic */
235         for (i = 0; i < basicdeflen; i++) { /* block name string */
236             writebyte_cksum(basicdef[i], fpout, &checksum);
237             /*fputc(basicdef[i],fpout);*/
238         }
239 
240         writebyte(255 - (checksum % 256), fpout); /* data checksum */
241 
242         fclose(fpin);
243         fclose(fpout);
244     }
245 
246     /* ***************************************** */
247     /*  Now, if requested, create the audio file */
248     /* ***************************************** */
249     if ((audio) || (fast) || (loud) || (khz_22)) {
250         if ((fpin = fopen(filename, "rb")) == NULL) {
251             exit_log(1, "Can't open file %s for wave conversion\n", filename);
252         }
253 
254         if (fseek(fpin, 0, SEEK_END)) {
255             fclose(fpin);
256             exit_log(1,"Couldn't determine size of file\n");
257         }
258         len = ftell(fpin);
259         fseek(fpin, 0, SEEK_SET);
260 
261         strcpy(wavfile, filename);
262 
263         suffix_change(wavfile, ".RAW");
264 
265         if ((fpout = fopen(wavfile, "wb")) == NULL) {
266             exit_log(1,"Can't open output raw audio file %s\n", wavfile);
267         }
268 
269         /* leading silence and tone*/
270         for (i = 0; i < 0x5000; i++)
271             fputc(0x80, fpout);
272 
273         /* sync */
274         gal_rawout(fpout, 0);
275 
276         /* program block */
277         if (len > 0) {
278             for (i = 0; i < len; i++) {
279                 c = getc(fpin);
280                 gal_rawout(fpout, c);
281             }
282         }
283 
284         /* trailing tone and silence (probably not necessary) */
285         /*
286 		gal_bit(fpout,0);
287 		gal_tone(fpout);
288 		for (i=0; i < 0x10000; i++)
289 			fputc(0x80, fpout);
290 */
291         fclose(fpin);
292         fclose(fpout);
293 
294         /* Now complete with the WAV header */
295 		if (khz_22)
296 			raw2wav_22k(wavfile,2);
297 		else
298 			raw2wav(wavfile);
299 
300     } /* END of WAV CONVERSION BLOCK */
301 
302     exit(0);
303 }
304