1 /*
2  *      Short program to create a Robotron KC85/2..KC85/4 type header
3  *
4  *
5  *      $Id: kc.c,v 1.1 2016-10-03 06:14:49 stefano Exp $
6  */
7 
8 #include "appmake.h"
9 #include <string.h>
10 #include <ctype.h>
11 
12 
13 
14 static char             *binname      = NULL;
15 static char             *crtfile      = NULL;
16 static char             *outfile      = NULL;
17 static char             *blockname    = NULL;
18 static int               origin       = -1;
19 static char              help         = 0;
20 
21 
22 /* Options that are available for this module */
23 option_t kc_options[] = {
24     { 'h', "help",     "Display this help",          OPT_BOOL,  &help},
25     { 'b', "binfile",  "Linked binary file",         OPT_STR,   &binname },
26     { 'c', "crt0file", "crt0 file used in linking",  OPT_STR,   &crtfile },
27     { 'o', "output",   "Name of output file",        OPT_STR,   &outfile },
28     {  0 , "org",      "Origin of the binary",       OPT_INT,   &origin },
29     {  0 , "blockname", "Name of the code block in tap file", OPT_STR, &blockname},
30     {  0,  NULL,       NULL,                         OPT_NONE,  NULL }
31 };
32 
33 
34 
35 /*
36  * Execution starts here
37  */
38 
kc_exec(char * target)39 int kc_exec(char* target)
40 {
41     char filename[FILENAME_MAX + 1];
42     FILE* fpin;
43     FILE* fpout;
44     long pos;
45     int len;
46     int c, i;
47     int nflag;
48 
49     if (help)
50         return -1;
51 
52     if (binname == NULL) {
53         return -1;
54     }
55 
56     if (outfile == NULL) {
57         strcpy(filename, binname);
58     } else {
59         strcpy(filename, outfile);
60     }
61 
62     // strupr(filename);
63     // not available on all platforms
64 
65     for (i = strlen(filename) - 1; i >= 0 && filename[i] != '/' && filename[i] != '\\'; i--)
66         filename[i] = toupper(filename[i]);
67 
68     //
69 
70     suffix_change(filename, ".KCC");
71 
72     if (strcmp(binname, filename) == 0) {
73         exit_log(1,"Input and output file names must be different\n");
74     }
75 
76     if (blockname == NULL)
77         blockname = zbasename(binname);
78 
79     if (origin != -1) {
80         pos = origin;
81     } else {
82         if ((pos = get_org_addr(crtfile)) == -1) {
83             exit_log(1,"Could not find parameter ZORG (not z88dk compiled?)\n");
84         }
85     }
86 
87     if ((fpin = fopen_bin(binname, crtfile)) == NULL) {
88         exit_log(1, "Can't open input file %s\n", binname);
89     }
90 
91     if (fseek(fpin, 0, SEEK_END)) {
92         fclose(fpin);
93         exit_log(1, "Couldn't determine size of file\n");
94         fclose(fpin);
95     }
96 
97     len = ftell(fpin);
98 
99     fseek(fpin, 0L, SEEK_SET);
100 
101     if ((fpout = fopen(filename, "wb")) == NULL) {
102         fclose(fpin);
103         exit_log(1,"Can't open output file\n");
104     }
105 
106     /* deal with the filename */
107     nflag = 0;
108     for (i = 0; i < 8; i++) {
109         if (nflag)
110             writebyte(0, fpout);
111         else {
112             if (!isalnum(blockname[i])) {
113                 writebyte(0, fpout);
114                 nflag++;
115             } else {
116                 writebyte(toupper(blockname[i]), fpout);
117             }
118         }
119     }
120 
121     writebyte('K', fpout);
122     writebyte('C', fpout);
123     writebyte('C', fpout);
124 
125     for (i = 0; i < 5; i++)
126         writebyte(0, fpout);
127 
128     writebyte(3, fpout); /* 0x02 = load, 0x03 = autostart */
129 
130     writeword(pos, fpout);
131     writeword(pos + len, fpout);
132     writeword(pos, fpout); /* start address */
133 
134     for (i = 0; i < 105; i++)
135         writebyte(0, fpout);
136 
137     for (i = 0; i < len; i++) {
138         c = getc(fpin);
139         writebyte(c, fpout);
140     }
141 
142     // Pad the block out to 128 bytes
143     while( (i % 128) > 0) {
144         writebyte(0, fpout);
145         i++;
146     }
147 
148     fclose(fpin);
149     fclose(fpout);
150 
151     return 0;
152 }
153