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