]> 4ch.mooo.com Git - 16.git/blob - 16/keen456/KEEN4-6/static/makeobj.c
extrcted keen code remake
[16.git] / 16 / keen456 / KEEN4-6 / static / makeobj.c
1 /*\r
2 ** makeobj.c\r
3 **\r
4 **---------------------------------------------------------------------------\r
5 ** Copyright 2014 Braden Obrzut\r
6 ** All rights reserved.\r
7 **\r
8 ** Redistribution and use in source and binary forms, with or without\r
9 ** modification, are permitted provided that the following conditions\r
10 ** are met:\r
11 **\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
19 **\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
31 **\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
35 **\r
36 */\r
37 \r
38 #include <stdio.h>\r
39 #include <malloc.h>\r
40 #include <string.h>\r
41 #include <ctype.h>\r
42 #include <stdlib.h>\r
43 \r
44 #pragma pack(1)\r
45 typedef struct\r
46 {\r
47         unsigned char type;\r
48         unsigned short len;\r
49 } SegHeader;\r
50 \r
51 typedef struct\r
52 {\r
53         unsigned short len;\r
54         unsigned char name;\r
55         unsigned char classname;\r
56         unsigned char overlayname;\r
57 } SegDef;\r
58 #pragma pack()\r
59 \r
60 const char* ReadFile(const char* fn, int *size)\r
61 {\r
62         char* out;\r
63 \r
64         FILE* f = fopen(fn, "rb");\r
65         fseek(f, 0, SEEK_END);\r
66         *size = ftell(f);\r
67         out = (char*)malloc(*size);\r
68         fseek(f, 0, SEEK_SET);\r
69 \r
70         fread(out, *size, 1, f);\r
71 \r
72         fclose(f);\r
73 \r
74         return out;\r
75 }\r
76 \r
77 void WriteFile(const char* fn, const char *data, int size)\r
78 {\r
79         FILE* f = fopen(fn, "wb");\r
80         fwrite(data, size, 1, f);\r
81         fclose(f);\r
82 }\r
83 \r
84 void Extract(const char* infn)\r
85 {\r
86         const char* in;\r
87         const char* start;\r
88         const char* p;\r
89         char outfn[16];\r
90         char str[256];\r
91         char *outdata;\r
92         int outsize;\r
93         int insize;\r
94         SegHeader head;\r
95 \r
96         outdata = NULL;\r
97 \r
98         start = in = ReadFile(infn, &insize);\r
99 \r
100         while(in < start + insize)\r
101         {\r
102                 head = *(SegHeader*)in;\r
103 \r
104                 switch(head.type)\r
105                 {\r
106                         case 0x80: /* THEADR */\r
107                                 memcpy(outfn, in+4, in[3]);\r
108                                 outfn[in[3]] = 0;\r
109                                 printf("Output: %s\n", outfn);\r
110                                 {\r
111                                         int i;\r
112                                         for(i = 0;i < 16;++i)\r
113                                         {\r
114                                                 if(outfn[i] == ' ')\r
115                                                         outfn[i] = 0;\r
116                                         }\r
117                                 }\r
118                                 break;\r
119                         case 0x88: /* COMENT */\r
120                                 switch(in[3])\r
121                                 {\r
122                                         case 0:\r
123                                                 memcpy(str, in+5, head.len-2);\r
124                                                 str[head.len-3] = 0;\r
125                                                 printf("Comment: %s\n", str);\r
126                                                 break;\r
127                                         default:\r
128                                                 printf("Unknown comment type %X @ %x ignored.\n", (unsigned char)in[3], (unsigned int)(in - start));\r
129                                                 break;\r
130                                 }\r
131                                 break;\r
132                         case 0x96: /* LNAMES */\r
133                                 p = in+3;\r
134                                 while(p < in+head.len+2)\r
135                                 {\r
136                                         memcpy(str, p+1, (unsigned char)*p);\r
137                                         str[(unsigned char)*p] = 0;\r
138                                         printf("Name: %s\n", str);\r
139 \r
140                                         p += (unsigned char)*p+1;\r
141                                 }\r
142                                 break;\r
143                         case 0x98: /* SEGDEF */\r
144                         {\r
145                                 SegDef *sd;\r
146 \r
147                                 sd = *(in+3) ? (SegDef*)(in+4) : (SegDef*)(in+7);\r
148                                 printf("Segment Length: %d\n", sd->len);\r
149 \r
150                                 outdata = (char*)malloc(sd->len);\r
151                                 outsize = sd->len;\r
152                                 break;\r
153                         }\r
154                         case 0x90: /* PUBDEF */\r
155                                 p = in+5;\r
156                                 if(in[5] == 0)\r
157                                         p += 2;\r
158                                 while(p < in+head.len+2)\r
159                                 {\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
163 \r
164                                         p += (unsigned char)*p+4;\r
165                                 }\r
166                                 break;\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
170                                 break;\r
171                         case 0x8A: /* MODEND */\r
172                                 /* Ignore */\r
173                                 break;\r
174                         default:\r
175                                 printf("Unknown header type %X @ %x ignored.\n", head.type, (unsigned int)(in - start));\r
176                                 break;\r
177                 }\r
178 \r
179                 in += 3 + head.len;\r
180         }\r
181 \r
182         WriteFile(outfn, outdata, outsize);\r
183 \r
184         free((char*)start);\r
185         free(outdata);\r
186 }\r
187 \r
188 void CheckSum(char *s, unsigned short len)\r
189 {\r
190         int sum;\r
191 \r
192         len += 3;\r
193 \r
194         sum = 0;\r
195         while(len > 1)\r
196         {\r
197                 sum += *(unsigned char*)s;\r
198                 ++s;\r
199                 --len;\r
200         }\r
201         *s = (unsigned char)(0x100-(sum&0xFF));\r
202 }\r
203 \r
204 void MakeDataObj(const char* infn, const char* outfn, const char* segname, const char* symname, int altmode)\r
205 {\r
206 #define Flush() fwrite(d.buf, d.head.len+3, 1, f)\r
207         union\r
208         {\r
209                 char buf[4096];\r
210                 SegHeader head;\r
211         } d;\r
212         int i;\r
213         FILE *f;\r
214         int insize;\r
215         const char *in;\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
221         else\r
222                 ++infn_stripped;\r
223 \r
224         f = fopen(outfn, "wb");\r
225 \r
226         in = ReadFile(infn, &insize);\r
227 \r
228         d.head.type = 0x80;\r
229         d.head.len = 14;\r
230         d.buf[3] = 12;\r
231         if(d.buf[3] > 12)\r
232                 d.buf[3] = 12;\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
238         Flush();\r
239 \r
240         d.head.type = 0x88;\r
241         d.head.len = 15;\r
242         d.buf[3] = 0;\r
243         d.buf[4] = 0;\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
247         Flush();\r
248 \r
249         d.head.type = 0x96;\r
250         d.head.len = strlen(infn_stripped)+40;\r
251         d.buf[3] = 6;\r
252         memcpy(&d.buf[4], "DGROUP", 6);\r
253         d.buf[10] = 5;\r
254         memcpy(&d.buf[11], "_DATA", 5);\r
255         d.buf[16] = 4;\r
256         memcpy(&d.buf[17], "DATA", 4);\r
257         d.buf[21] = 0;\r
258         d.buf[22] = 5;\r
259         memcpy(&d.buf[23], "_TEXT", 5);\r
260         d.buf[28] = 4;\r
261         memcpy(&d.buf[29], "CODE", 4);\r
262         d.buf[33] = 8;\r
263         memcpy(&d.buf[34], "FAR_DATA", 8);\r
264         if(!segname)\r
265         {\r
266                 if(!altmode)\r
267                 {\r
268                         d.buf[42] = strlen(infn_stripped)-1;\r
269                         for(i = 0;i < strlen(infn_stripped)-4;++i)\r
270                         {\r
271                                 if(i == 0)\r
272                                         d.buf[43] = toupper(infn_stripped[0]);\r
273                                 else\r
274                                         d.buf[43+i] = tolower(infn_stripped[i]);\r
275                         }\r
276                         memcpy(&d.buf[43+i], "Seg", 3);\r
277                 }\r
278                 else\r
279                 {\r
280                         d.head.len = 40;\r
281                 }\r
282         }\r
283         else\r
284         {\r
285                 d.head.len = strlen(segname)+41;\r
286                 d.buf[42] = strlen(segname);\r
287                 strcpy(&d.buf[43], segname);\r
288         }\r
289         CheckSum(d.buf, d.head.len);\r
290         Flush();\r
291 \r
292         d.head.type = 0x98;\r
293         d.head.len = 7;\r
294         *(unsigned short*)(d.buf+4) = insize;\r
295         if(altmode == 0)\r
296         {\r
297                 d.buf[3] = (char)((unsigned char)0x60);\r
298                 d.buf[6] = 8;\r
299                 d.buf[7] = 7;\r
300                 d.buf[8] = 4;\r
301         }\r
302         else\r
303         {\r
304                 d.buf[3] = (char)((unsigned char)0x48);\r
305                 d.buf[6] = 2;\r
306                 d.buf[7] = 3;\r
307                 d.buf[8] = 4;\r
308         }\r
309         CheckSum(d.buf, d.head.len);\r
310         Flush();\r
311 \r
312         if(altmode)\r
313         {\r
314                 d.head.type = 0x9A;\r
315                 d.head.len = 4;\r
316                 d.buf[3] = 1;\r
317                 d.buf[4] = (char)((unsigned char)0xFF);\r
318                 d.buf[5] = 1;\r
319                 CheckSum(d.buf, d.head.len);\r
320                 Flush();\r
321         }\r
322 \r
323         d.head.type = 0x90;\r
324         d.head.len = strlen(infn_stripped)+4;\r
325         d.buf[3] = 1;\r
326         d.buf[4] = 1;\r
327         if(!symname)\r
328         {\r
329                 d.buf[5] = strlen(infn_stripped)-3;\r
330                 d.buf[6] = '_';\r
331                 for(i = 0;i < strlen(infn_stripped)-4;++i)\r
332                         d.buf[7+i] = tolower(infn_stripped[i]);\r
333         }\r
334         else\r
335         {\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
340         }\r
341         d.buf[7+i] = 0;\r
342         d.buf[8+i] = 0;\r
343         d.buf[9+i] = 0;\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
346         Flush();\r
347 \r
348 #define LEDATA_LEN 1024\r
349         for(i = 0;i < insize;i += LEDATA_LEN)\r
350         {\r
351                 d.head.type = 0xA0;\r
352                 d.head.len = insize - i > LEDATA_LEN ? LEDATA_LEN+4 : insize - i + 4;\r
353                 d.buf[3] = 1;\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
357                 Flush();\r
358         }\r
359 \r
360         d.head.type = 0x8A;\r
361         d.head.len = 2;\r
362         d.buf[3] = 0;\r
363         d.buf[4] = 0;\r
364         CheckSum(d.buf, d.head.len);\r
365         Flush();\r
366 \r
367         fclose(f);\r
368         free((char*)in);\r
369 }\r
370 \r
371 void DumpData(const char* infn, const char* outfn, int skip)\r
372 {\r
373         FILE *f;\r
374         int i;\r
375         int insize;\r
376         char symname[9];\r
377         const char *in;\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
383         else\r
384                 ++infn_stripped;\r
385 \r
386         f = fopen(outfn, "wb");\r
387 \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
391 \r
392         in = ReadFile(infn, &insize);\r
393 \r
394         for(i = skip;i < insize;++i)\r
395         {\r
396                 fprintf(f, "%d", (unsigned char)in[i]);\r
397                 if(i != insize-1)\r
398                         fprintf(f, ",\r\n");\r
399         }\r
400         fprintf(f, " };\r\n");\r
401 \r
402         fclose(f);\r
403         free((char*)in);\r
404 }\r
405 \r
406 int main(int argc, char* argv[])\r
407 {\r
408         if(argc < 3)\r
409         {\r
410                 printf("Converts file to OMF.\nUseage:\n  ./makeobj [fx] <input> ...\n");\r
411                 return 0;\r
412         }\r
413 \r
414         switch(argv[1][0])\r
415         {\r
416                 case 'c':\r
417                         if(argc < 4)\r
418                         {\r
419                                 printf("Need an output location. (Extra parms: <output> [<symbol>])\n");\r
420                                 return 0;\r
421                         }\r
422                         else\r
423                         {\r
424                                 const char *symname = NULL;\r
425                                 if(argc >= 5)\r
426                                         symname = argv[4];\r
427                                 MakeDataObj(argv[2], argv[3], NULL, symname, 1);\r
428                         }\r
429                         break;\r
430                 default:\r
431                 case 'f':\r
432                         if(argc < 4)\r
433                         {\r
434                                 printf("Need an output location. (Extra parms: <output> [<segname> <symbol>])\n");\r
435                                 return 0;\r
436                         }\r
437                         else\r
438                         {\r
439                                 const char *segname = NULL, *symname = NULL;\r
440                                 if(argc >= 6)\r
441                                 {\r
442                                         segname = argv[4];\r
443                                         symname = argv[5];\r
444                                 }\r
445                                 MakeDataObj(argv[2], argv[3], segname, symname, 0);\r
446                         }\r
447                         break;\r
448                 case 'x':\r
449                         Extract(argv[2]);\r
450                         break;\r
451                 case 's':\r
452                         if(argc < 4)\r
453                         {\r
454                                 printf("Need an output location. (Extra parms: <output> [<skip>])\n");\r
455                                 return 0;\r
456                         }\r
457                         else\r
458                         {\r
459                                 int skip = 0;\r
460                                 if(argc >= 5)\r
461                                 {\r
462                                         skip = atoi(argv[4]);\r
463                                 }\r
464                                 DumpData(argv[2], argv[3], skip);\r
465                         }\r
466                         break;\r
467                         break;\r
468         }\r
469         return 0;\r
470 }\r