makeip.c (3964B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 6 #define NUM_FIELDS 11 7 8 struct field; 9 10 int check_areasym(char *, struct field *); 11 12 struct field { 13 char *name; 14 int pos; 15 int len; 16 int (*extra_check)(char *, struct field *); 17 } fields[NUM_FIELDS] = { 18 { "Hardware ID", 0x0, 0x10, NULL }, 19 { "Maker ID", 0x10, 0x10, NULL }, 20 { "Device Info", 0x20, 0x10, NULL }, 21 { "Area Symbols", 0x30, 0x8, check_areasym }, 22 { "Peripherals", 0x38, 0x8, NULL }, 23 { "Product No", 0x40, 0xa, NULL }, 24 { "Version", 0x4a, 0x6, NULL }, 25 { "Release Date", 0x50, 0x10, NULL }, 26 { "Boot Filename", 0x60, 0x10, NULL }, 27 { "SW Maker Name", 0x70, 0x10, NULL }, 28 { "Game Title", 0x80, 0x80, NULL }, 29 }; 30 31 int filled_in[NUM_FIELDS]; 32 33 int check_areasym(char *ptr, struct field *f) 34 { 35 int i, a = 0; 36 for(i=0; i<f->len; i++) 37 switch(ptr[i]) { 38 case 'J': 39 a |= (1<<0); 40 break; 41 case 'U': 42 a |= (1<<1); 43 break; 44 case 'E': 45 a |= (1<<2); 46 break; 47 case ' ': 48 break; 49 default: 50 fprintf(stderr, "Unknown area symbol '%c'.\n", ptr[i]); 51 return 0; 52 } 53 for(i=0; i<f->len; i++) 54 if((a & (1<<i)) == 0) 55 ptr[i] = ' '; 56 else 57 ptr[i] = "JUE"[i]; 58 return 1; 59 } 60 61 void trim(char *str) 62 { 63 int l = strlen(str); 64 while(l>0 && (str[l-1] == '\r' || str[l-1] == '\n' || 65 str[l-1] == ' ' || str[l-1] == '\t')) 66 str[--l]='\0'; 67 } 68 69 int parse_input(FILE *fh, char *ip) 70 { 71 static char buf[80]; 72 int i; 73 memset(filled_in, 0, sizeof(filled_in)); 74 while(fgets(buf, sizeof(buf), fh)) { 75 char *p; 76 trim(buf); 77 if(*buf) 78 if((p = strchr(buf, ':'))) { 79 *p++ = '\0'; 80 trim(buf); 81 for(i=0; i<NUM_FIELDS; i++) 82 if(!strcmp(buf, fields[i].name)) 83 break; 84 if(i>=NUM_FIELDS) { 85 fprintf(stderr, "Unknown field \"%s\".\n", buf); 86 return 0; 87 } 88 memset(ip+fields[i].pos, ' ', fields[i].len); 89 while(*p == ' ' || *p == '\t') 90 p++; 91 if(strlen(p)>fields[i].len) { 92 fprintf(stderr, "Data for field \"%s\" is too long.\n", fields[i]); 93 return 0; 94 } 95 memcpy(ip+fields[i].pos, p, strlen(p)); 96 if(fields[i].extra_check!=NULL && 97 !(*fields[i].extra_check)(ip+fields[i].pos, &fields[i])) 98 return 0; 99 filled_in[i] = 1; 100 } else { 101 fprintf(stderr, "Missing : on line.\n"); 102 return 0; 103 } 104 } 105 106 for(i=0; i<NUM_FIELDS; i++) 107 if(!filled_in[i]) { 108 fprintf(stderr, "Missing value for \"%s\".\n", fields[i]); 109 return 0; 110 } 111 112 return 1; 113 } 114 115 int calcCRC(const unsigned char *buf, int size) 116 { 117 int i, c, n = 0xffff; 118 for (i = 0; i < size; i++) 119 { 120 n ^= (buf[i]<<8); 121 for (c = 0; c < 8; c++) 122 if (n & 0x8000) 123 n = (n << 1) ^ 4129; 124 else 125 n = (n << 1); 126 } 127 return n & 0xffff; 128 } 129 130 void update_crc(char *ip) 131 { 132 int n = calcCRC((unsigned char *)(ip+0x40), 16); 133 char buf[5]; 134 sprintf(buf, "%04X", n); 135 if(memcmp(buf, ip+0x20, 4)) { 136 printf("Setting CRC to %s (was %.4s)\n", buf, ip+0x20); 137 memcpy(ip+0x20, buf, 4); 138 } 139 } 140 141 void makeip(char *ip_tmpl, char *in, char *out) 142 { 143 static char ip[0x8000]; 144 FILE *fh = fopen(ip_tmpl, "rb"); 145 if(fh == NULL) { 146 fprintf(stderr, "Can't open \"%s\".\n", ip_tmpl); 147 exit(1); 148 } 149 if(fread(ip, 1, 0x8000, fh) != 0x8000) { 150 fprintf(stderr, "Read error.\n"); 151 exit(1); 152 } 153 fclose(fh); 154 fh = fopen(in, "r"); 155 if(fh == NULL) { 156 fprintf(stderr, "Can't open \"%s\".\n", in); 157 exit(1); 158 } 159 if(!parse_input(fh, ip)) 160 exit(1); 161 fclose(fh); 162 update_crc(ip); 163 fh = fopen(out, "wb"); 164 if(fh == NULL) { 165 fprintf(stderr, "Can't open \"%s\".\n", out); 166 exit(1); 167 } 168 if(fwrite(ip, 1, 0x8000, fh) != 0x8000) { 169 fprintf(stderr, "Write error.\n"); 170 exit(1); 171 } 172 fclose(fh); 173 } 174 175 int main(int argc, char *argv[]) 176 { 177 char *ip_tmpl; 178 179 if(argc != 3) { 180 fprintf(stderr, "Usage: %s ip.txt IP.BIN\n", argv[0]); 181 exit(1); 182 } 183 184 ip_tmpl = getenv("IP_TEMPLATE_FILE"); 185 if(ip_tmpl == NULL) 186 ip_tmpl = "IP.TMPL"; 187 188 makeip(ip_tmpl, argv[1], argv[2]); 189 190 return 0; 191 }