4 **---------------------------------------------------------------------------
\r
5 ** Copyright 2014 Braden Obrzut
\r
6 ** All rights reserved.
\r
8 ** Redistribution and use in source and binary forms, with or without
\r
9 ** modification, are permitted provided that the following conditions
\r
12 ** 1. Redistributions of source code must retain the above copyright
\r
13 ** notice, this list of conditions and the following disclaimer.
\r
14 ** 2. Redistributions in binary form must reproduce the above copyright
\r
15 ** notice, this list of conditions and the following disclaimer in the
\r
16 ** documentation and/or other materials provided with the distribution.
\r
17 ** 3. The name of the author may not be used to endorse or promote products
\r
18 ** derived from this software without specific prior written permission.
\r
20 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
\r
21 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
\r
22 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
\r
23 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
24 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
\r
25 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
\r
26 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
\r
27 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
\r
28 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
\r
29 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
30 **---------------------------------------------------------------------------
\r
32 ** This is a throwaway program to create OMF object files for DOS. It also
\r
33 ** extracts the object files. It should be compatible with MakeOBJ by John
\r
34 ** Romero except where we calculate the checksum correctly.
\r
55 unsigned char classname;
\r
56 unsigned char overlayname;
\r
60 const char* ReadFile(const char* fn, int *size)
\r
64 FILE* f = fopen(fn, "rb");
\r
65 fseek(f, 0, SEEK_END);
\r
67 out = (char*)malloc(*size);
\r
68 fseek(f, 0, SEEK_SET);
\r
70 fread(out, *size, 1, f);
\r
77 void WriteFile(const char* fn, const char *data, int size)
\r
79 FILE* f = fopen(fn, "wb");
\r
80 fwrite(data, size, 1, f);
\r
84 void Extract(const char* infn)
\r
98 start = in = ReadFile(infn, &insize);
\r
100 while(in < start + insize)
\r
102 head = *(SegHeader*)in;
\r
106 case 0x80: /* THEADR */
\r
107 memcpy(outfn, in+4, in[3]);
\r
109 printf("Output: %s\n", outfn);
\r
112 for(i = 0;i < 16;++i)
\r
114 if(outfn[i] == ' ')
\r
119 case 0x88: /* COMENT */
\r
123 memcpy(str, in+5, head.len-2);
\r
124 str[head.len-3] = 0;
\r
125 printf("Comment: %s\n", str);
\r
128 printf("Unknown comment type %X @ %x ignored.\n", (unsigned char)in[3], (unsigned int)(in - start));
\r
132 case 0x96: /* LNAMES */
\r
134 while(p < in+head.len+2)
\r
136 memcpy(str, p+1, (unsigned char)*p);
\r
137 str[(unsigned char)*p] = 0;
\r
138 printf("Name: %s\n", str);
\r
140 p += (unsigned char)*p+1;
\r
143 case 0x98: /* SEGDEF */
\r
147 sd = *(in+3) ? (SegDef*)(in+4) : (SegDef*)(in+7);
\r
148 printf("Segment Length: %d\n", sd->len);
\r
150 outdata = (char*)malloc(sd->len);
\r
154 case 0x90: /* PUBDEF */
\r
158 while(p < in+head.len+2)
\r
160 memcpy(str, p+1, (unsigned char)*p);
\r
161 str[(unsigned char)*p] = 0;
\r
162 printf("Public Name: %s\n", str);
\r
164 p += (unsigned char)*p+4;
\r
167 case 0xA0: /* LEDATA */
\r
168 printf("Writing data at %d (%d)\n", *(unsigned short*)(in+4), head.len-4);
\r
169 memcpy(outdata+*(unsigned short*)(in+4), in+6, head.len-4);
\r
171 case 0x8A: /* MODEND */
\r
175 printf("Unknown header type %X @ %x ignored.\n", head.type, (unsigned int)(in - start));
\r
179 in += 3 + head.len;
\r
182 WriteFile(outfn, outdata, outsize);
\r
184 free((char*)start);
\r
188 void CheckSum(char *s, unsigned short len)
\r
197 sum += *(unsigned char*)s;
\r
201 *s = (unsigned char)(0x100-(sum&0xFF));
\r
204 void MakeDataObj(const char* infn, const char* outfn, const char* segname, const char* symname, int altmode)
\r
206 #define Flush() fwrite(d.buf, d.head.len+3, 1, f)
\r
216 const char *infn_stripped = strrchr(infn, '/');
\r
217 if(strrchr(infn, '\\') > infn_stripped)
\r
218 infn_stripped = strrchr(infn, '\\');
\r
219 if(infn_stripped == NULL)
\r
220 infn_stripped = infn;
\r
224 f = fopen(outfn, "wb");
\r
226 in = ReadFile(infn, &insize);
\r
228 d.head.type = 0x80;
\r
233 sprintf(&d.buf[4], "%-12s", infn_stripped);
\r
234 for(i = 0;i < strlen(infn_stripped) && i < 12;++i)
\r
235 d.buf[4+i] = toupper(d.buf[4+i]);
\r
236 /* CheckSum(d.buf, d.head.len); */
\r
237 d.buf[17] = 0; /* For some reason this one isn't checksummed by MakeOBJ */
\r
240 d.head.type = 0x88;
\r
244 /* We're not really MakeOBJ v1.1, but to allow us to verify with md5sums */
\r
245 memcpy(&d.buf[5], "MakeOBJ v1.1", 12);
\r
246 CheckSum(d.buf, d.head.len);
\r
249 d.head.type = 0x96;
\r
250 d.head.len = strlen(infn_stripped)+40;
\r
252 memcpy(&d.buf[4], "DGROUP", 6);
\r
254 memcpy(&d.buf[11], "_DATA", 5);
\r
256 memcpy(&d.buf[17], "DATA", 4);
\r
259 memcpy(&d.buf[23], "_TEXT", 5);
\r
261 memcpy(&d.buf[29], "CODE", 4);
\r
263 memcpy(&d.buf[34], "FAR_DATA", 8);
\r
268 d.buf[42] = strlen(infn_stripped)-1;
\r
269 for(i = 0;i < strlen(infn_stripped)-4;++i)
\r
272 d.buf[43] = toupper(infn_stripped[0]);
\r
274 d.buf[43+i] = tolower(infn_stripped[i]);
\r
276 memcpy(&d.buf[43+i], "Seg", 3);
\r
285 d.head.len = strlen(segname)+41;
\r
286 d.buf[42] = strlen(segname);
\r
287 strcpy(&d.buf[43], segname);
\r
289 CheckSum(d.buf, d.head.len);
\r
292 d.head.type = 0x98;
\r
294 *(unsigned short*)(d.buf+4) = insize;
\r
297 d.buf[3] = (char)((unsigned char)0x60);
\r
304 d.buf[3] = (char)((unsigned char)0x48);
\r
309 CheckSum(d.buf, d.head.len);
\r
314 d.head.type = 0x9A;
\r
317 d.buf[4] = (char)((unsigned char)0xFF);
\r
319 CheckSum(d.buf, d.head.len);
\r
323 d.head.type = 0x90;
\r
324 d.head.len = strlen(infn_stripped)+4;
\r
329 d.buf[5] = strlen(infn_stripped)-3;
\r
331 for(i = 0;i < strlen(infn_stripped)-4;++i)
\r
332 d.buf[7+i] = tolower(infn_stripped[i]);
\r
336 d.head.len = strlen(symname)+7;
\r
337 d.buf[5] = strlen(symname);
\r
338 strcpy(&d.buf[6], symname);
\r
339 i = strlen(symname)-1;
\r
344 /* This checksum is calculated wrong in MakeOBJ, although I don't know in what way. */
\r
345 CheckSum(d.buf, d.head.len);
\r
348 #define LEDATA_LEN 1024
\r
349 for(i = 0;i < insize;i += LEDATA_LEN)
\r
351 d.head.type = 0xA0;
\r
352 d.head.len = insize - i > LEDATA_LEN ? LEDATA_LEN+4 : insize - i + 4;
\r
354 *(unsigned short*)(d.buf+4) = i;
\r
355 memcpy(&d.buf[6], &in[i], d.head.len-4);
\r
356 CheckSum(d.buf, d.head.len);
\r
360 d.head.type = 0x8A;
\r
364 CheckSum(d.buf, d.head.len);
\r
371 void DumpData(const char* infn, const char* outfn, int skip)
\r
378 const char *infn_stripped = strrchr(infn, '/');
\r
379 if(strrchr(infn, '\\') > infn_stripped)
\r
380 infn_stripped = strrchr(infn, '\\');
\r
381 if(infn_stripped == NULL)
\r
382 infn_stripped = infn;
\r
386 f = fopen(outfn, "wb");
\r
388 memset(symname, 0, 9);
\r
389 memcpy(symname, infn_stripped, strlen(infn_stripped)-4);
\r
390 fprintf(f, "char far %s[] ={\r\n", symname);
\r
392 in = ReadFile(infn, &insize);
\r
394 for(i = skip;i < insize;++i)
\r
396 fprintf(f, "%d", (unsigned char)in[i]);
\r
398 fprintf(f, ",\r\n");
\r
400 fprintf(f, " };\r\n");
\r
406 int main(int argc, char* argv[])
\r
410 printf("Converts file to OMF.\nUseage:\n ./makeobj [fx] <input> ...\n");
\r
419 printf("Need an output location. (Extra parms: <output> [<symbol>])\n");
\r
424 const char *symname = NULL;
\r
427 MakeDataObj(argv[2], argv[3], NULL, symname, 1);
\r
434 printf("Need an output location. (Extra parms: <output> [<segname> <symbol>])\n");
\r
439 const char *segname = NULL, *symname = NULL;
\r
445 MakeDataObj(argv[2], argv[3], segname, symname, 0);
\r
454 printf("Need an output location. (Extra parms: <output> [<skip>])\n");
\r
462 skip = atoi(argv[4]);
\r
464 DumpData(argv[2], argv[3], skip);
\r