+++ /dev/null
-/*\r
-** makeobj.c\r
-**\r
-**---------------------------------------------------------------------------\r
-** Copyright 2014 Braden Obrzut\r
-** All rights reserved.\r
-**\r
-** Redistribution and use in source and binary forms, with or without\r
-** modification, are permitted provided that the following conditions\r
-** are met:\r
-**\r
-** 1. Redistributions of source code must retain the above copyright\r
-** notice, this list of conditions and the following disclaimer.\r
-** 2. Redistributions in binary form must reproduce the above copyright\r
-** notice, this list of conditions and the following disclaimer in the\r
-** documentation and/or other materials provided with the distribution.\r
-** 3. The name of the author may not be used to endorse or promote products\r
-** derived from this software without specific prior written permission.\r
-**\r
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
-** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
-** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
-** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
-** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
-** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
-** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-**---------------------------------------------------------------------------\r
-**\r
-** This is a throwaway program to create OMF object files for DOS. It also\r
-** extracts the object files. It should be compatible with MakeOBJ by John\r
-** Romero except where we calculate the checksum correctly.\r
-**\r
-*/\r
-\r
-#include <stdio.h>\r
-#include <malloc.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <stdlib.h>\r
-\r
-#pragma pack(1)\r
-typedef struct\r
-{\r
- unsigned char type;\r
- unsigned short len;\r
-} SegHeader;\r
-\r
-typedef struct\r
-{\r
- unsigned short len;\r
- unsigned char name;\r
- unsigned char classname;\r
- unsigned char overlayname;\r
-} SegDef;\r
-#pragma pack()\r
-\r
-const char* ReadFile(const char* fn, int *size)\r
-{\r
- char* out;\r
-\r
- FILE* f = fopen(fn, "rb");\r
- fseek(f, 0, SEEK_END);\r
- *size = ftell(f);\r
- out = (char*)malloc(*size);\r
- fseek(f, 0, SEEK_SET);\r
-\r
- fread(out, *size, 1, f);\r
-\r
- fclose(f);\r
-\r
- return out;\r
-}\r
-\r
-void WriteFile(const char* fn, const char *data, int size)\r
-{\r
- FILE* f = fopen(fn, "wb");\r
- fwrite(data, size, 1, f);\r
- fclose(f);\r
-}\r
-\r
-void Extract(const char* infn)\r
-{\r
- const char* in;\r
- const char* start;\r
- const char* p;\r
- char outfn[16];\r
- char str[256];\r
- char *outdata;\r
- int outsize;\r
- int insize;\r
- SegHeader head;\r
-\r
- outdata = NULL;\r
-\r
- start = in = ReadFile(infn, &insize);\r
-\r
- while(in < start + insize)\r
- {\r
- head = *(SegHeader*)in;\r
-\r
- switch(head.type)\r
- {\r
- case 0x80: /* THEADR */\r
- memcpy(outfn, in+4, in[3]);\r
- outfn[in[3]] = 0;\r
- printf("Output: %s\n", outfn);\r
- {\r
- int i;\r
- for(i = 0;i < 16;++i)\r
- {\r
- if(outfn[i] == ' ')\r
- outfn[i] = 0;\r
- }\r
- }\r
- break;\r
- case 0x88: /* COMENT */\r
- switch(in[3])\r
- {\r
- case 0:\r
- memcpy(str, in+5, head.len-2);\r
- str[head.len-3] = 0;\r
- printf("Comment: %s\n", str);\r
- break;\r
- default:\r
- printf("Unknown comment type %X @ %x ignored.\n", (unsigned char)in[3], (unsigned int)(in - start));\r
- break;\r
- }\r
- break;\r
- case 0x96: /* LNAMES */\r
- p = in+3;\r
- while(p < in+head.len+2)\r
- {\r
- memcpy(str, p+1, (unsigned char)*p);\r
- str[(unsigned char)*p] = 0;\r
- printf("Name: %s\n", str);\r
-\r
- p += (unsigned char)*p+1;\r
- }\r
- break;\r
- case 0x98: /* SEGDEF */\r
- {\r
- SegDef *sd;\r
-\r
- sd = *(in+3) ? (SegDef*)(in+4) : (SegDef*)(in+7);\r
- printf("Segment Length: %d\n", sd->len);\r
-\r
- outdata = (char*)malloc(sd->len);\r
- outsize = sd->len;\r
- break;\r
- }\r
- case 0x90: /* PUBDEF */\r
- p = in+5;\r
- if(in[5] == 0)\r
- p += 2;\r
- while(p < in+head.len+2)\r
- {\r
- memcpy(str, p+1, (unsigned char)*p);\r
- str[(unsigned char)*p] = 0;\r
- printf("Public Name: %s\n", str);\r
-\r
- p += (unsigned char)*p+4;\r
- }\r
- break;\r
- case 0xA0: /* LEDATA */\r
- printf("Writing data at %d (%d)\n", *(unsigned short*)(in+4), head.len-4);\r
- memcpy(outdata+*(unsigned short*)(in+4), in+6, head.len-4);\r
- break;\r
- case 0x8A: /* MODEND */\r
- /* Ignore */\r
- break;\r
- default:\r
- printf("Unknown header type %X @ %x ignored.\n", head.type, (unsigned int)(in - start));\r
- break;\r
- }\r
-\r
- in += 3 + head.len;\r
- }\r
-\r
- WriteFile(outfn, outdata, outsize);\r
-\r
- free((char*)start);\r
- free(outdata);\r
-}\r
-\r
-void CheckSum(char *s, unsigned short len)\r
-{\r
- int sum;\r
-\r
- len += 3;\r
-\r
- sum = 0;\r
- while(len > 1)\r
- {\r
- sum += *(unsigned char*)s;\r
- ++s;\r
- --len;\r
- }\r
- *s = (unsigned char)(0x100-(sum&0xFF));\r
-}\r
-\r
-void MakeDataObj(const char* infn, const char* outfn, const char* segname, const char* symname, int altmode)\r
-{\r
-#define Flush() fwrite(d.buf, d.head.len+3, 1, f)\r
- union\r
- {\r
- char buf[4096];\r
- SegHeader head;\r
- } d;\r
- int i;\r
- FILE *f;\r
- int insize;\r
- const char *in;\r
- const char *infn_stripped = strrchr(infn, '/');\r
- if(strrchr(infn, '\\') > infn_stripped)\r
- infn_stripped = strrchr(infn, '\\');\r
- if(infn_stripped == NULL)\r
- infn_stripped = infn;\r
- else\r
- ++infn_stripped;\r
-\r
- f = fopen(outfn, "wb");\r
-\r
- in = ReadFile(infn, &insize);\r
-\r
- d.head.type = 0x80;\r
- d.head.len = 14;\r
- d.buf[3] = 12;\r
- if(d.buf[3] > 12)\r
- d.buf[3] = 12;\r
- sprintf(&d.buf[4], "%-12s", infn_stripped);\r
- for(i = 0;i < strlen(infn_stripped) && i < 12;++i)\r
- d.buf[4+i] = toupper(d.buf[4+i]);\r
- /* CheckSum(d.buf, d.head.len); */\r
- d.buf[17] = 0; /* For some reason this one isn't checksummed by MakeOBJ */\r
- Flush();\r
-\r
- d.head.type = 0x88;\r
- d.head.len = 15;\r
- d.buf[3] = 0;\r
- d.buf[4] = 0;\r
- /* We're not really MakeOBJ v1.1, but to allow us to verify with md5sums */\r
- memcpy(&d.buf[5], "MakeOBJ v1.1", 12);\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
-\r
- d.head.type = 0x96;\r
- d.head.len = strlen(infn_stripped)+40;\r
- d.buf[3] = 6;\r
- memcpy(&d.buf[4], "DGROUP", 6);\r
- d.buf[10] = 5;\r
- memcpy(&d.buf[11], "_DATA", 5);\r
- d.buf[16] = 4;\r
- memcpy(&d.buf[17], "DATA", 4);\r
- d.buf[21] = 0;\r
- d.buf[22] = 5;\r
- memcpy(&d.buf[23], "_TEXT", 5);\r
- d.buf[28] = 4;\r
- memcpy(&d.buf[29], "CODE", 4);\r
- d.buf[33] = 8;\r
- memcpy(&d.buf[34], "FAR_DATA", 8);\r
- if(!segname)\r
- {\r
- if(!altmode)\r
- {\r
- d.buf[42] = strlen(infn_stripped)-1;\r
- for(i = 0;i < strlen(infn_stripped)-4;++i)\r
- {\r
- if(i == 0)\r
- d.buf[43] = toupper(infn_stripped[0]);\r
- else\r
- d.buf[43+i] = tolower(infn_stripped[i]);\r
- }\r
- memcpy(&d.buf[43+i], "Seg", 3);\r
- }\r
- else\r
- {\r
- d.head.len = 40;\r
- }\r
- }\r
- else\r
- {\r
- d.head.len = strlen(segname)+41;\r
- d.buf[42] = strlen(segname);\r
- strcpy(&d.buf[43], segname);\r
- }\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
-\r
- d.head.type = 0x98;\r
- d.head.len = 7;\r
- *(unsigned short*)(d.buf+4) = insize;\r
- if(altmode == 0)\r
- {\r
- d.buf[3] = (char)((unsigned char)0x60);\r
- d.buf[6] = 8;\r
- d.buf[7] = 7;\r
- d.buf[8] = 4;\r
- }\r
- else\r
- {\r
- d.buf[3] = (char)((unsigned char)0x48);\r
- d.buf[6] = 2;\r
- d.buf[7] = 3;\r
- d.buf[8] = 4;\r
- }\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
-\r
- if(altmode)\r
- {\r
- d.head.type = 0x9A;\r
- d.head.len = 4;\r
- d.buf[3] = 1;\r
- d.buf[4] = (char)((unsigned char)0xFF);\r
- d.buf[5] = 1;\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
- }\r
-\r
- d.head.type = 0x90;\r
- d.head.len = strlen(infn_stripped)+4;\r
- d.buf[3] = 1;\r
- d.buf[4] = 1;\r
- if(!symname)\r
- {\r
- d.buf[5] = strlen(infn_stripped)-3;\r
- d.buf[6] = '_';\r
- for(i = 0;i < strlen(infn_stripped)-4;++i)\r
- d.buf[7+i] = tolower(infn_stripped[i]);\r
- }\r
- else\r
- {\r
- d.head.len = strlen(symname)+7;\r
- d.buf[5] = strlen(symname);\r
- strcpy(&d.buf[6], symname);\r
- i = strlen(symname)-1;\r
- }\r
- d.buf[7+i] = 0;\r
- d.buf[8+i] = 0;\r
- d.buf[9+i] = 0;\r
- /* This checksum is calculated wrong in MakeOBJ, although I don't know in what way. */\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
-\r
-#define LEDATA_LEN 1024\r
- for(i = 0;i < insize;i += LEDATA_LEN)\r
- {\r
- d.head.type = 0xA0;\r
- d.head.len = insize - i > LEDATA_LEN ? LEDATA_LEN+4 : insize - i + 4;\r
- d.buf[3] = 1;\r
- *(unsigned short*)(d.buf+4) = i;\r
- memcpy(&d.buf[6], &in[i], d.head.len-4);\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
- }\r
-\r
- d.head.type = 0x8A;\r
- d.head.len = 2;\r
- d.buf[3] = 0;\r
- d.buf[4] = 0;\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
-\r
- fclose(f);\r
- free((char*)in);\r
-}\r
-\r
-void DumpData(const char* infn, const char* outfn, int skip)\r
-{\r
- FILE *f;\r
- int i;\r
- int insize;\r
- char symname[9];\r
- const char *in;\r
- const char *infn_stripped = strrchr(infn, '/');\r
- if(strrchr(infn, '\\') > infn_stripped)\r
- infn_stripped = strrchr(infn, '\\');\r
- if(infn_stripped == NULL)\r
- infn_stripped = infn;\r
- else\r
- ++infn_stripped;\r
-\r
- f = fopen(outfn, "wb");\r
-\r
- memset(symname, 0, 9);\r
- memcpy(symname, infn_stripped, strlen(infn_stripped)-4);\r
- fprintf(f, "char far %s[] ={\r\n", symname);\r
-\r
- in = ReadFile(infn, &insize);\r
-\r
- for(i = skip;i < insize;++i)\r
- {\r
- fprintf(f, "%d", (unsigned char)in[i]);\r
- if(i != insize-1)\r
- fprintf(f, ",\r\n");\r
- }\r
- fprintf(f, " };\r\n");\r
-\r
- fclose(f);\r
- free((char*)in);\r
-}\r
-\r
-int main(int argc, char* argv[])\r
-{\r
- if(argc < 3)\r
- {\r
- printf("Converts file to OMF.\nUseage:\n ./makeobj [fx] <input> ...\n");\r
- return 0;\r
- }\r
-\r
- switch(argv[1][0])\r
- {\r
- case 'c':\r
- if(argc < 4)\r
- {\r
- printf("Need an output location. (Extra parms: <output> [<symbol>])\n");\r
- return 0;\r
- }\r
- else\r
- {\r
- const char *symname = NULL;\r
- if(argc >= 5)\r
- symname = argv[4];\r
- MakeDataObj(argv[2], argv[3], NULL, symname, 1);\r
- }\r
- break;\r
- default:\r
- case 'f':\r
- if(argc < 4)\r
- {\r
- printf("Need an output location. (Extra parms: <output> [<segname> <symbol>])\n");\r
- return 0;\r
- }\r
- else\r
- {\r
- const char *segname = NULL, *symname = NULL;\r
- if(argc >= 6)\r
- {\r
- segname = argv[4];\r
- symname = argv[5];\r
- }\r
- MakeDataObj(argv[2], argv[3], segname, symname, 0);\r
- }\r
- break;\r
- case 'x':\r
- Extract(argv[2]);\r
- break;\r
- case 's':\r
- if(argc < 4)\r
- {\r
- printf("Need an output location. (Extra parms: <output> [<skip>])\n");\r
- return 0;\r
- }\r
- else\r
- {\r
- int skip = 0;\r
- if(argc >= 5)\r
- {\r
- skip = atoi(argv[4]);\r
- }\r
- DumpData(argv[2], argv[3], skip);\r
- }\r
- break;\r
- break;\r
- }\r
- return 0;\r
-}\r