1 /*
2  *        BIN to NEWBRAIN .BAS file
3  *
4  *        Stefano Bodrato 4/2007
5  *
6  *        $Id: newbrain.c,v 1.8 2016-06-26 00:46:55 aralbrec Exp $
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              ascii        = 0;
17 static char              help         = 0;
18 
19 /* Options that are available for this module */
20 option_t newbrain_options[] = {
21     { 'h', "help",     "Display this help",          OPT_BOOL,  &help},
22     { 'b', "binfile",  "Linked binary file",         OPT_STR,   &binname },
23     { 'c', "crt0file", "crt0 file used in linking",  OPT_STR,   &crtfile },
24     { 'o', "output",   "Name of output file",        OPT_STR,   &outfile },
25     { 'a', "ascii",     "Generate a BASIC loader in plain text", OPT_BOOL, &outfile },
26     {  0 , "blockname", "Name of the binary block in tape",      OPT_STR,  &blockname},
27     {  0 , "org",      "Origin of the binary",       OPT_INT,   &origin },
28     {  0,  NULL,       NULL,                         OPT_NONE,  NULL }
29 };
30 
31 
32 int newbrain_exec()
33 {
34     char    filename[FILENAME_MAX+1];
35     FILE    *fpin, *fpout, *fpout2;
36     int    pos;
37 
38     int        c;
39     int        i,p,l,b;
40     int        len;
41     int        lnum;
42 
43     unsigned long       checksum;
44 
45 
46     if ( help || binname == NULL || ( crtfile == NULL && origin == -1 ) ) {
mtx_bit(FILE * fpout,unsigned char bit)47         return -1;
48     }
49 
50     if ( blockname == NULL ) blockname = zbasename(binname);
51 
52     if ( outfile == NULL ) {
53         strcpy(filename,binname);
54         suffix_change(filename,".txt");
55     } else {
56         strcpy(filename,outfile);
57     }
58 
59 
60     if ( origin != -1 ) {
61         pos = origin;
62     } else {
63 		if ( (pos = get_org_addr(crtfile)) == -1 ) {
64             exit_log(1,"Could not find parameter ZORG (not z88dk compiled?)\n");
65         }
66     }
67 
68 
69 	if ( (fpin=fopen_bin(binname, crtfile) ) == NULL ) {
70         exit_log(1,"Can't open input file %s\n",binname);
71     }
72 
73 
mtx_rawout(FILE * fpout,unsigned char b)74 /*
75  *        Now we try to determine the size of the file
76  *        to be converted
77  */
78     if  (fseek(fpin,0,SEEK_END)) {
79         fclose(fpin);
80         exit_log(1,"Couldn't determine size of file\n");
81     }
82 
83     len=ftell(fpin);
84 
mtx_leader(FILE * fpout)85 
86     fseek(fpin,0L,SEEK_SET);
87 
88 
89     if ( ascii ) {
90 
91             /* All in a BASIC program */
92 
93             if ( (fpout=fopen(filename,"w") ) == NULL ) {
94                 exit_log(1,"Can't open output text format file %s\n",filename);
95             }
96 
97             fprintf(fpout,"10 IF TOP>%i THEN RESERVE TOP-%i\n",pos-1,pos-1);
98             fprintf(fpout,"20 FOR i=0TO%i:READa:POKE%i+i,a:NEXT i\n",len-1,pos);
99             fprintf(fpout,"30 CALL%i\n",pos);
100             fprintf(fpout,"40 END\n");
101             lnum=100;
102             /* ... M/C ...*/
103             for (i=0; i<len;i++) {
mtx_exec(char * target)104                 if ((i % 60) == 0) {
105                     fprintf(fpout,"\n");
106                     fprintf(fpout,"%i DATA ",lnum);
107                     lnum=lnum+2;
108                 }
109                 else
110                     fputc(',',fpout);
111                 c=getc(fpin);
112                 fprintf(fpout,"%i",c);
113             }
114             fprintf(fpout,"\n");
115 
116             fclose(fpin);
117             fclose(fpout);
118 
119     }
120     else    /*  Much more efficient LOADER  */
121     {
122 
123             /* binary block */
124 
125             suffix_change(filename,".dat");
126 
127             if ( (fpout2=fopen(filename,"wb") ) == NULL ) {
128                 exit_log(1,"Can't open output dat Binary file %s\n",filename);
129             }
130 
131             checksum=0x3b;                 /* Init checksum */
132                 fputc (0,fpout2);
133             writeword_cksum(strlen(blockname), fpout2, &checksum);
134             for (i=0; i<strlen(blockname); i++) {
135                 fputc (blockname[i],fpout2);
136                 checksum += blockname[i];
137             }
138             writebyte_cksum(0x81, fpout2, &checksum);
139             writeword((checksum%65536),fpout2);   /* name checksum */
140 
141             /* Block */
142             for (b=0; b<=(len/1024); b++) {
143 
144               for (i=0; i<10;i++)          /* block leading zeroes */
145                 fputc (0,fpout2);
146 
147               checksum=0x3b;               /* Init checksum */
148 
149               p = (b * 1024) + 1024 -1;    /* set the pointer at the end of the block */
150               l = 1024;
151 
152               if ( p > (len - 1) ) {       /* is last block smaller ? */
153                  p = len - 1;
154                  l = len - (b * 1024);
155               }
156 
157               /* Block length*/
158               writeword_cksum(l, fpout2, &checksum);
159 
160               for (i=p; i>(p-l); i--) {
161                   fseek(fpin, i, SEEK_SET);
162                   c = getc(fpin);
163                   writebyte_cksum(c, fpout2, &checksum);
164               }
165 
166               writebyte_cksum(b+1, fpout2, &checksum);
167               writeword((checksum%65536), fpout2);
168             }
169 
170             for (i=0; i<9;i++)        /* tail */
171               fputc (0,fpout2);
172 
173             fclose(fpin);
174             fclose(fpout2);
175 
176 
177 
178             /* TEMP BASIC loader */
179 
180             suffix_change(filename,".tmp");
181 
182             if ( (fpout=fopen(filename,"wb") ) == NULL ) {
183                 exit_log(1,"Can't open temp output file %s\n",filename);
184             }
185 
186             fputc(0x0d,fpout);
187 
188             fprintf(fpout,"10 ");
189             fputc(0xAC,fpout);        /* RESERVE */
190             fputc(0xA8,fpout);        /* TOP */
191             fputc(0x82,fpout);        /* - */
192             fprintf(fpout,"%i",pos);  /* memory location */
193             fputc(0x0d,fpout);
194 
195             fprintf(fpout,"20 ");
196             fputc('b',fpout);
197             fputc(0x8c,fpout);        /* = */
198             fprintf(fpout,"121:");  /* 121 */
199             fputc(0x89,fpout);        /* IF */
200             fputc(0xa4,fpout);        /* PEEK */
201             fprintf(fpout,"(51)");
202             fputc(0x8d,fpout);        /* > */
203             fprintf(fpout,"127");
204             fputc(0xb4,fpout);        /* THEN */
205             fprintf(fpout,"b");
206             fputc(0x8c,fpout);        /* = */
207             fputc(0xa4,fpout);        /* PEEK */
208             fprintf(fpout,"(168)");
209             fputc(0x81,fpout);        /* + */
210             fprintf(fpout,"256");
211             fputc(0x83,fpout);        /* * */
212             fputc(0xa4,fpout);        /* PEEK */
213             fprintf(fpout,"(169):");
214             fputc(0x9e,fpout);        /* POKE */
215             fprintf(fpout,"169,");
216             fputc(0x96,fpout);        /* INT */
217             fprintf(fpout,"((b");
218             fputc(0x81,fpout);        /* + */
219             fprintf(fpout,"23)");
220             fputc(0x84,fpout);        /* / */
221             fprintf(fpout,"256):");
222             fputc(0x9e,fpout);        /* POKE */
223             fprintf(fpout,"168,b");
224             fputc(0x81,fpout);        /* + */
225             fprintf(fpout,"23");
226             fputc(0x82,fpout);        /* - */
227             fprintf(fpout,"256");
228             fputc(0x83,fpout);        /* * */
229             fputc(0xa4,fpout);        /* PEEK */
230             fprintf(fpout,"(169)");
231             fputc(0x0d,fpout);
232 
233             fprintf(fpout,"30 ");
234             fputc(0x8b,fpout);        /* FOR */
235             fprintf(fpout," i ");
236             fputc(0x8c,fpout);        /* = */
237             fprintf(fpout," 0 ");
238             fputc(0xb6,fpout);        /* TO */
239             fprintf(fpout," 22:");
240             fputc(0x9c,fpout);        /* READ */
241             fprintf(fpout," c:");
242             fputc(0x9e,fpout);        /* POKE */
243             fprintf(fpout," b");
244             fputc(0x81,fpout);        /* + */
245             fprintf(fpout,"i,c:");
246             fputc(0x8c,fpout);        /* NEXT */
247             fprintf(fpout," i:");
248             fputc(0x9d,fpout);        /* DATA */
249             fprintf(fpout," 253,110,32,253,102,33,22,0,30,1,1,");
250             fprintf(fpout,"%i",len%256);  /* LSB for Length */
251             fputc(',',fpout);
252             fprintf(fpout,"%i",len/256);  /* MSB for Length */
253             fprintf(fpout,",231,49,119,35,11,120,177,200,24,246");
254             fputc(0x0d,fpout);
255 
256             fprintf(fpout,"40 ");
257             fputc(0x97,fpout);        /* OPEN */
258             /* fputc(' ',fpout); */
259             fputc(0xb3,fpout);        /* # */
260             fprintf(fpout,"1,");
261             fputc('"',fpout);
262             fprintf(fpout,"%s",blockname);
263             fputc('"',fpout);
264             fputc(0x0d,fpout);
265 
266             fprintf(fpout,"50 ");
267             fputc(0x9f,fpout);        /* CALL */
268             fprintf(fpout," b : ");
269             fputc(0x9f,fpout);        /* CALL */
270             fprintf(fpout," %i",pos);
271             fputc(0x0d,fpout);
272 
273             fputc(0x04,fpout);
274             fputc(0x0d,fpout);
275             fclose(fpout);
276 
277 
278 
279             /* Now convert in tape format */
280 
281             if ( (fpin=fopen(filename,"rb") ) == NULL ) {
282                 exit_log(1,"Can't read temp file%s\n",binname);
283             }
284 
285             if  (fseek(fpin,0,SEEK_END)) {
286                 fclose(fpin);
287                 exit_log(1,"Couldn't determine size of temp file\n");
288             }
289 
290             len=ftell(fpin);
291 
292             suffix_change(filename,".bas");
293 
294             if ( (fpout2=fopen(filename,"wb") ) == NULL ) {
295                 exit_log(1,"Can't open output BASIC Binary file %s\n",filename);
296             }
297 
298             /* header for binary block */
299 
300             checksum=0x3b;              /* Init checksum */
301 
302             fputc (0,fpout2);
303             writeword_cksum(strlen(filename), fpout2, &checksum);
304             for (i=0; i<strlen(filename); i++) {
305                 fputc (filename[i],fpout2);             /* +1 ?? */
306                 checksum += filename[i];
307             }
308             writebyte_cksum(0x81, fpout2, &checksum);
309             writeword((checksum%65536),fpout2); /* name checksum */
310 
311             for (i=0; i<10;i++)         /* zero filling the next part */
312                 fputc (0,fpout2);
313 
314             checksum=0x3b;              /* Init checksum */
315 
316             /* Block length*/
317             writeword_cksum(len, fpout2, &checksum);
318 
319             /* Block */
320             for (i=len-1; i>=0; i--) {
321                   fseek(fpin, i, SEEK_SET);
322                   c=getc(fpin);
323                   writebyte_cksum(c, fpout2, &checksum);
324             }
325 
326             writebyte_cksum(0x41, fpout2, &checksum);
327 
328             writeword((checksum%65536),fpout2);  /* block checksum */
329             for (i=0; i<9;i++)                   /* tail  */
330                 fputc (0,fpout2);
331 
332             fclose(fpin);
333             fclose(fpout2);
334 
335 
336             /* TAPE directory */
337 
338             if ( (fpout=fopen("_dir.txt","w") ) == NULL ) {
339                 exit_log(1,"Can't open output text format file %s\n",filename);
340             }
341             fprintf(fpout,"%s\n",filename);
342             suffix_change(filename,".dat");
343             fprintf(fpout,"%s\n",filename);
344             fclose(fpout);
345 
346             suffix_change(filename,".tmp");
347             remove(filename);
348 
349     }
350     return 0;
351 }
352