1 /* ISOLINK
2  *
3  * This program appends the IPL.BIN file together with
4  * a list of binary segments which may be overlays or
5  * data, and produces an ISO output file
6  *
7  * An array of segment information is also produced and
8  * stored (I'm not sure where yet)
9  *
10  */
11 
12 
13 /*************/
14 /* INCLUDES  */
15 /*************/
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include "main.h"
21 #include "../../include/overlay.h"
22 
23 
24 /*************/
25 /* DEFINES   */
26 /*************/
27 
28 #define	OVERLAY_SUFFIX	"ovl"
29 
30 
31 /*************/
32 /* GLOBALS   */
33 /*************/
34 
35 int sector_array[200][2];
36 int array_count;
37 int cderr_flag = 0;
38 int cderr_ovl = 0;
39 static char incpath[10][256];
40 static int debug;
41 
42 
43 /*************/
44 /* CODE      */
45 /*************/
46 
47 void
init_path(void)48 init_path(void)
49 {
50    char *p, *pl;
51    int  i, l;
52 
53    strcpy(incpath[0], ".");
54    strcat(incpath[0], PATH_SEPARATOR_STRING);
55 
56    p = getenv("PCE_INCLUDE");
57 
58    if (p == NULL)
59       return;
60 
61    for (i = 1; i < 10; i++)
62    {
63       pl = strchr(p, ';');
64 
65       if (pl == NULL)
66          l = strlen(p);
67       else
68          l = pl - p;
69 
70       if (l) {
71          strncpy(incpath[i], p, l);
72          p += l;
73          while (*p == ';')
74             p++;
75       }
76       incpath[i][l] = '\0';
77 
78       if (l) {
79          if (incpath[i][l - 1] != PATH_SEPARATOR)
80             strcat(incpath[i], PATH_SEPARATOR_STRING);
81       }
82    }
83 }
84 
85 
86 FILE *
file_open(char * name,char * mode)87 file_open(char * name, char * mode)
88 {
89    FILE * fp = NULL;
90    char testname[256];
91    int i;
92 
93 /* search current directory, then PCE_INCLUDE path */
94 
95    for (i = 0; i < 10; i++) {
96       if (strlen(incpath[i])) {
97          strcpy(testname, incpath[i]);
98          strcat(testname, name);
99          fp = fopen(testname, mode);
100          if (fp != NULL) {
101             if (debug) {
102                printf("filename      = %s\n", testname);
103             }
104             break;
105          }
106       }
107    }
108 
109    return(fp);
110 }
111 
112 
113 void
file_write(FILE * outfile,FILE * infile,char * filename,int curr_filenum)114 file_write(FILE *outfile, FILE *infile, char * filename, int curr_filenum)
115 {
116    char buffer[2048];
117    long size;
118    int  sectors;
119    int bytes_read, bytes_written;
120    int i, j;
121    int code;
122 
123 
124    code = 0;
125    if (strcmp(OVERLAY_SUFFIX, &filename[strlen(filename)-3]) == 0) {
126       code = 1;
127    }
128 
129    /* check size of file */
130 
131    fseek(infile, 0L, SEEK_END);
132    size = ftell(infile);
133    rewind(infile);
134 
135 
136    /* get proper number of sectors if not an exact size multiple */
137 
138    sectors = size/2048;
139    if ((sectors * 2048) != size) {
140       sectors++;
141    }
142 
143    for (i = 0; i < sectors; i++)
144    {
145       bytes_read = fread((void *)buffer, 1, 2048, infile);
146 
147       if (bytes_read != 2048)
148       {
149          /* wrong place to get an incomplete read */
150 
151          if ( ((sectors*2048) == size) || ((i+1) != sectors) )
152          {
153              printf("Error while reading file %s\n", filename);
154              exit(1);
155          }
156          else
157          {
158             /* fill buffer with zeroes */
159 
160             for (j = bytes_read; j < 2048; j++)
161             {
162                buffer[j] = 0;
163             }
164          }
165       }
166 
167       if (code == 1)
168       {
169          if (i == 0)	/* ie. boot segment */
170          {
171             /* This byte is the place where the overlay entry point */
172             /* declares "I am overlay number <n>", and now running  */
173 
174             buffer[1] = curr_filenum;
175 
176             if ((cderr_flag == 1) && (curr_filenum == 1))
177             {
178                buffer[(CDERR_OVERRIDE & 0x07FF)] = 1;
179                buffer[(CDERR_OVERLAY_NUM & 0x07FF)] = cderr_ovl;
180             }
181          }
182          else if (i == DATA_SECTOR)
183          {
184             for (j = 0; j < array_count; j++)
185             {
186 
187                /* sector_array[0] is ipl.bin which is a segment    */
188                /* but not an addressable one - still, it is stored */
189                /* Encode this array into DATA_SEGMENT of all code  */
190                /* overlays on disk, in Hu6280 addressable order    */
191 
192                buffer[j*4]   = (sector_array[j][0]) & 255;
193                buffer[j*4+1] = (sector_array[j][0]) >> 8;
194                buffer[j*4+2] = (sector_array[j][1]) & 255;
195                buffer[j*4+3] = (sector_array[j][1]) >> 8;
196             }
197          }
198       }
199 
200       bytes_written = fwrite((void *)buffer, 1, 2048, outfile);
201 
202       if (bytes_written != 2048)
203       {
204           printf("Error writing output file while processing %s\n", filename);
205           exit(1);
206       }
207    }
208 }
209 
210 
211 void
ipl_write(FILE * outfile,FILE * infile,char * name)212 ipl_write(FILE *outfile, FILE *infile, char * name)
213 {
214    char ipl_buffer[4096];
215    long size;
216 
217    /* check size of file */
218 
219    fseek(infile, 0L, SEEK_END);
220    size = ftell(infile);
221    rewind(infile);
222 
223    if (size > 4096) {
224       printf("ipl.bin file is wrong size - %ld, should be 4096\n", size);
225       exit(1);
226    }
227 
228    fread(ipl_buffer, 1, 4096, infile);
229 
230    memset(&ipl_buffer[0x800], 0, 32);
231 
232    /* prg sector base */
233    ipl_buffer[0x802] = 2;
234 
235    /* nb_sectors */
236    ipl_buffer[0x803] = 16;	/* Get boot segments first; up to and including */
237 				/* overlay array.  The boot segments will load */
238 				/* the remaining segments and relocate code if */
239 				/* necessary           */
240 
241    /* loading address */
242    ipl_buffer[0x804] = 0x00;
243    ipl_buffer[0x805] = 0x40;
244 
245    /* starting address */
246    ipl_buffer[0x806] = (BOOT_ENTRY_POINT & 0xff);	/* boot entry point */
247    ipl_buffer[0x807] = (BOOT_ENTRY_POINT >> 8) & 0xff;
248 
249    /* mpr registers */
250    ipl_buffer[0x808] = 0x00;
251    ipl_buffer[0x809] = 0x01;
252    ipl_buffer[0x80A] = 0x02;
253    ipl_buffer[0x80B] = 0x03;
254    ipl_buffer[0x80C] = 0x00;	/* boot loader also @ $C000 */
255 
256    /*load mode */
257    ipl_buffer[0x80D] = 0x60;
258 
259    fwrite(ipl_buffer, 1, 4096, outfile);
260 }
261 
262 
263 void
zero_write(FILE * outfile,int sectors)264 zero_write(FILE *outfile, int sectors)
265 {
266    char zero_buf[2048];
267    int i;
268 
269    memset(zero_buf, 0, 2048);
270    for (i = 0; i < sectors; i++)
271    {
272       fwrite(zero_buf, 1, 2048, outfile);
273    }
274 }
275 
276 
277 void
usage(void)278 usage(void)
279 {
280    printf("Usage: ISOLINK <outfile> <infile_1> <infile_2> -cderr <infile_n>. . .\n");
281    printf("\n\n");
282    printf("-cderr :  Indicates that the following overlay is to be used \n");
283    printf("          instead of the default text message when SCD programs\n");
284    printf("          are executed on plain CD systems\n\n");
285    printf("          Note: this overlay must be compiled as '-cd', not '-scd'\n\n");
286 }
287 
288 
289 int
main(int argc,char * argv[])290 main(int argc, char *argv[])
291 {
292    int i, j;
293    int curr_sector, sectors, zero_fill;
294    long file_len;
295    FILE * infile;
296    FILE * outfile;
297 
298    debug = 0;
299    array_count = 0;
300    curr_sector = 0;
301    j = 0;
302 
303    init_path();
304 
305    /********************************************************/
306    /* parse command-line                                   */
307    /* if any sort of command-line options are found, abort */
308    /*                                                      */
309    /* otherwise, step through filenames testing them       */
310    /* for existence, and creating an array which holds     */
311    /* size and number of sectors                           */
312    /********************************************************/
313 
314    for (i = 1; i < argc; i++)
315    {
316       if (argv[i][0] == '-')
317       {
318          if ((strcmp(argv[i], "-cderr") == 0) &&
319              (i != 1) &&		/* not valid for first arg */
320              (i < (argc-1)) &&		/* must have filename after */
321              (cderr_flag == 0))		/* only valid once on line */
322          {
323             cderr_flag = 1;
324             cderr_ovl = j;
325             continue;
326          }
327          else
328          {
329             usage();
330             exit(1);
331          }
332       }
333 
334       if (i == 1) {
335          infile = file_open("ipl.bin", "rb");
336       } else {
337          infile = file_open(argv[i], "rb");
338       }
339 
340       if (infile == NULL)
341       {
342          printf("Could not open file: %s\n", (i == 1 ? "ipl.bin" : argv[i]));
343          printf("Operation aborted\n\n");
344          exit(1);
345       }
346 
347       fseek(infile, 0L, SEEK_END);
348       file_len = ftell(infile);
349       rewind(infile);
350 
351       sectors = (file_len/2048);
352       if ((sectors * 2048) != file_len) {
353          sectors++;
354       }
355 
356       if (debug) {
357          printf("length = %ld\n", file_len);
358          printf("start sector  = %d\n", curr_sector);
359          printf("len (sectors) = %d\n", sectors);
360       }
361 
362       sector_array[j][0] = curr_sector;
363       sector_array[j][1] = sectors;
364       curr_sector += sectors;
365       j++;
366 
367       fclose(infile);
368    }
369 
370    array_count = j;
371 
372    /* OK, let's open them for real now   */
373    /* and copy them from input to output */
374 
375    outfile = fopen(argv[1], "wb");
376 
377    infile = file_open("ipl.bin", "rb");
378    ipl_write(outfile, infile, "ipl.bin");
379    fclose(infile);
380 
381    j = 0;
382    for (i = 2; i < argc; i++)
383    {
384       if (argv[i][0] != '-')
385       {
386          j++;
387          infile = file_open(argv[i], "rb");
388          file_write(outfile, infile, argv[i], j);
389          fclose(infile);
390       }
391    }
392 
393    /* pad it out to 6 seconds to comply */
394    /* with CDROM specification */
395 
396    zero_fill = (6*75)-curr_sector;
397 
398    /* pad at least 2 seconds of trailing zeroes */
399 
400    if (zero_fill < (2*75))
401 	zero_fill = 2*75;
402 
403    zero_write(outfile, zero_fill);
404 
405    fclose(outfile);
406 
407    return(0);
408 }
409