]> 4ch.mooo.com Git - 16.git/blobdiff - 16/keen456/KEEN4-6/static/makeobj.c
extrcted keen code remake
[16.git] / 16 / keen456 / KEEN4-6 / static / makeobj.c
diff --git a/16/keen456/KEEN4-6/static/makeobj.c b/16/keen456/KEEN4-6/static/makeobj.c
new file mode 100755 (executable)
index 0000000..fe85a9d
--- /dev/null
@@ -0,0 +1,470 @@
+/*\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