MakeExtCfg.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. /*
  2. * MakeExtCfg.c
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <ctype.h>
  8. typedef unsigned char u8_t;
  9. typedef unsigned short u16_t;
  10. typedef unsigned int u32_t;
  11. typedef unsigned int uint_t;
  12. #define CFG_ID_MAX_NUM 0x20
  13. #pragma pack(1)
  14. typedef struct
  15. {
  16. u8_t format[4];
  17. u8_t magic [4];
  18. u16_t user_version;
  19. u8_t minor_version;
  20. u8_t major_version;
  21. u16_t total_size;
  22. u16_t num_cfgs;
  23. } extcfg_file_header_t;
  24. /*
  25. typedef struct
  26. {
  27. u8_t cfg_id;
  28. u8_t sub_pos;
  29. u8_t cfg_len;
  30. } extcfg_item_info_t;
  31. */
  32. typedef struct
  33. {
  34. u32_t cfg_id:8;
  35. u32_t sub_pos:12;
  36. u32_t cfg_len:12;
  37. } extcfg_item_info_t;
  38. typedef struct
  39. {
  40. u32_t id;
  41. u32_t len;
  42. u8_t data[0];
  43. } src_data_info_t;
  44. #pragma pack()
  45. typedef struct
  46. {
  47. char *xml_file_name;
  48. char *src_file_name;
  49. char *extcfg_file_name;
  50. u8_t *xml_data;
  51. int xml_data_size;
  52. u8_t *src_data;
  53. int src_data_size;
  54. u8_t *extcfg_data;
  55. int extcfg_data_size;
  56. extcfg_item_info_t *extcfg_item;
  57. int extcfg_item_nums;
  58. int dae_cfg_id;
  59. int cfg_id_num;
  60. int cfg_id[CFG_ID_MAX_NUM];
  61. int last_check_id;
  62. u32_t cfg_version;
  63. u32_t id_item_size;
  64. } make_extcfg_context_t;
  65. static make_extcfg_context_t make_extcfg_context;
  66. static int get_args(int argc, char* argv[])
  67. {
  68. make_extcfg_context_t* ptr = &make_extcfg_context;
  69. if (argc != 4)
  70. goto err;
  71. memset(ptr, 0, sizeof(make_extcfg_context_t));
  72. ptr->xml_file_name = argv[1];
  73. ptr->src_file_name = argv[2];
  74. ptr->extcfg_file_name = argv[3];
  75. return 0;
  76. err:
  77. printf("usage: MakeExtCfg.exe xml_file src.bin extcfg.bin\n");
  78. return -1;
  79. }
  80. static u8_t* read_file(char* file_name, int* file_size)
  81. {
  82. FILE* file = NULL;
  83. u8_t* data = NULL;
  84. int size;
  85. if ((file = fopen(file_name, "rb")) == NULL)
  86. goto err;
  87. fseek(file, 0, SEEK_END);
  88. size = (int)ftell(file);
  89. if ((data = malloc(size)) == NULL)
  90. goto err;
  91. fseek(file, 0, SEEK_SET);
  92. if (fread(data, 1, size, file) != size)
  93. goto err;
  94. fclose(file);
  95. if (file_size != NULL)
  96. *file_size = size;
  97. return data;
  98. err:
  99. if (data != NULL)
  100. free(data);
  101. if (file != NULL)
  102. fclose(file);
  103. return NULL;
  104. }
  105. static int read_file_head(char *file_name, extcfg_file_header_t *head_data, int head_size)
  106. {
  107. FILE* file = NULL;
  108. int file_size = 0;
  109. file = fopen(file_name, "rb");
  110. if (file == NULL)
  111. goto err;
  112. fseek(file, 0, SEEK_END);
  113. file_size = (int)ftell(file);
  114. if (file_size < head_size)
  115. goto err;
  116. memset(head_data, 0, head_size);
  117. fseek(file, 0, SEEK_SET);
  118. if (fread(head_data, 1, head_size, file) != head_size)
  119. goto err;
  120. if ((memcmp(head_data->format, "CFG", 4) != 0) || memcmp(head_data->magic, "VER", 4) != 0)
  121. goto err;
  122. fclose(file);
  123. file = NULL;
  124. return 0;
  125. err:
  126. if (file)
  127. fclose(file);
  128. return -1;
  129. }
  130. static inline int count_space(char *text)
  131. {
  132. int j = 0;
  133. while(text[j] == ' ')
  134. j++;
  135. return j;
  136. }
  137. static inline int count_to_end(char *text, char c)
  138. {
  139. int j = 0;
  140. while(text[j] != c)
  141. j++;
  142. return j;
  143. }
  144. static int get_symbol_value(char *text, int len, char *symbol, char *name)
  145. {
  146. int i = 0, j = 0;
  147. if (strncmp(text, symbol, strlen(symbol)) != 0)
  148. return 0;
  149. i = strlen(symbol);
  150. i += count_space(&text[i]);
  151. if (text[i] != '=')
  152. return 0;
  153. i += 1;
  154. i += count_space(&text[i]);
  155. if (text[i] != '\"')
  156. return 0;
  157. i += 1;
  158. j = count_to_end(&text[i], '\"');
  159. memcpy(name, &text[i], j);
  160. name[j] = '\0';
  161. return i;
  162. }
  163. static int get_config_info(char *text, int len, char *name, int *id)
  164. {
  165. int i, j;
  166. char temp_id[5];
  167. if (strncmp(text, "<config", 7) != 0)
  168. return 0;
  169. i = 7;
  170. // there is at least 1 space
  171. if ((j = count_space(&text[i])) == 0)
  172. return 0;
  173. i += j;
  174. // get config name to check if it is Multi Dae ID
  175. i += get_symbol_value(&text[i], len - i, "name", name);
  176. while(i < len)
  177. {
  178. if ((j = get_symbol_value(&text[i], len - i, "cfg_id", temp_id)) > 0)
  179. {
  180. *id = strtol(temp_id, NULL, 16);
  181. i += j;
  182. continue;
  183. }
  184. if (text[i] == '>')
  185. {
  186. i += 1;
  187. break;
  188. }
  189. i++;
  190. }
  191. return i;
  192. }
  193. static int get_cfg_id(void)
  194. {
  195. make_extcfg_context_t* ptr = &make_extcfg_context;
  196. int i, j;
  197. char temp_name[64];
  198. int temp_id;
  199. ptr->xml_data = read_file(ptr->xml_file_name, &ptr->xml_data_size);
  200. if (ptr->xml_data == NULL)
  201. return -1;
  202. i = 0;
  203. ptr->cfg_id_num = 0;
  204. ptr->dae_cfg_id = 0;
  205. memset(ptr->cfg_id, 0, sizeof(ptr->cfg_id));
  206. while(i < ptr->xml_data_size)
  207. {
  208. memset(temp_name, 0, sizeof(temp_name));
  209. temp_id = 0;
  210. if ((j = get_config_info((char *)&ptr->xml_data[i], ptr->xml_data_size - i, temp_name, &temp_id)) > 0)
  211. {
  212. if (strstr(temp_name, "Multi_Dae"))
  213. {
  214. ptr->dae_cfg_id = temp_id;
  215. }
  216. else
  217. {
  218. if (ptr->cfg_id_num >= CFG_ID_MAX_NUM)
  219. goto err;
  220. ptr->cfg_id[ptr->cfg_id_num] = temp_id;
  221. ptr->cfg_id_num += 1;
  222. }
  223. i += j;
  224. continue;
  225. }
  226. i++;
  227. }
  228. if (ptr->cfg_id_num == 0 && ptr->dae_cfg_id == 0)
  229. goto err;
  230. return 0;
  231. err:
  232. if (ptr->xml_data != NULL)
  233. free(ptr->xml_data);
  234. ptr->xml_data = NULL;
  235. return -1;
  236. }
  237. static int check_id_valid(u8_t id)
  238. {
  239. make_extcfg_context_t* ptr = &make_extcfg_context;
  240. int i;
  241. // max custom dae id nums is 10
  242. if ((id >= ptr->dae_cfg_id) && (id <= ptr->dae_cfg_id + 10 - 1))
  243. return 1;
  244. if (ptr->last_check_id == 0)
  245. {
  246. // old frimware before transparency mode
  247. if (ptr->cfg_id_num == 0)
  248. {
  249. ptr->last_check_id = id;
  250. return 1;
  251. }
  252. for(i = 0; i < ptr->cfg_id_num; i++)
  253. {
  254. if (id == ptr->cfg_id[i])
  255. return 1;
  256. }
  257. // not find the id in config_ext.xml
  258. ptr->last_check_id = ptr->cfg_id[i-1];
  259. }
  260. // is a continuous ID from config_ext.xml
  261. if (id == (ptr->last_check_id + 1))
  262. {
  263. ptr->last_check_id = id;
  264. return 1;
  265. }
  266. return 0;
  267. }
  268. static void extcfg_add(extcfg_item_info_t *item_info, u8_t *data)
  269. {
  270. make_extcfg_context_t* ptr = &make_extcfg_context;
  271. extcfg_item_info_t *item;
  272. /* write item info */
  273. ptr->extcfg_item = realloc(ptr->extcfg_item, (ptr->extcfg_item_nums + 1) * ptr->id_item_size);
  274. item = &ptr->extcfg_item[ptr->extcfg_item_nums];
  275. item->cfg_id = item_info->cfg_id;
  276. item->sub_pos = item_info->sub_pos;
  277. item->cfg_len = item_info->cfg_len;
  278. ptr->extcfg_item_nums += 1;
  279. /* write item data */
  280. ptr->extcfg_data = realloc(ptr->extcfg_data, ptr->extcfg_data_size + item->cfg_len);
  281. memcpy(&ptr->extcfg_data[ptr->extcfg_data_size], data, item->cfg_len);
  282. ptr->extcfg_data_size += item->cfg_len;
  283. }
  284. static int src_data_convert(void)
  285. {
  286. make_extcfg_context_t *ptr = &make_extcfg_context;
  287. u8_t *src_data = ptr->src_data;
  288. src_data_info_t *src_info;
  289. extcfg_item_info_t item_info;
  290. int offs = 0;
  291. while (offs < ptr->src_data_size - 8)
  292. {
  293. src_info = (src_data_info_t*)&src_data[offs];
  294. if (check_id_valid(src_info->id))
  295. {
  296. item_info.cfg_id = src_info->id;
  297. item_info.cfg_len = src_info->len;
  298. item_info.sub_pos = 0;
  299. extcfg_add(&item_info, src_info->data);
  300. /* 8bytes of cfg_id and cfg_len */
  301. offs += (src_info->len + 8);
  302. // offset of next data item align with word
  303. offs = (offs + 3) / 4 * 4;
  304. }
  305. else
  306. {
  307. /* abort if id wrong */
  308. return -1;
  309. }
  310. }
  311. return 0;
  312. }
  313. static int convert_extcfg(void)
  314. {
  315. /* 读取版本头信息,从输入的extcfg.bin文件
  316. 逐项转写[ID len data ... ] -> [ID 00 len ... ] [data ...]
  317. 自定义音效的ID是xml中的ID递增,至多10个
  318. 拓展的ID数量只有CFG_ID_MAX_NUM(不包括自定义音效)
  319. */
  320. make_extcfg_context_t *ptr = &make_extcfg_context;
  321. FILE *output_file = NULL;
  322. extcfg_file_header_t cfg_head;
  323. ptr->src_data = read_file(ptr->src_file_name, &ptr->src_data_size);
  324. if (ptr->src_data == NULL)
  325. goto err;
  326. // "CFG VER xxxx'size''num'" = 16bytes
  327. // version number in file_head would change, so we must do copy
  328. if (read_file_head(ptr->extcfg_file_name, &cfg_head, 0x10) < 0)
  329. goto err;
  330. ptr->cfg_version = (u32_t)cfg_head.major_version;
  331. if (ptr->cfg_version >= 0x20)
  332. {
  333. // ptr->id_item_size = sizeof(extcfg_item_info_new_t);
  334. ptr->id_item_size = sizeof(extcfg_item_info_t);
  335. }
  336. else
  337. {
  338. ptr->id_item_size = sizeof(extcfg_item_info_t);
  339. }
  340. /* convert data */
  341. if (src_data_convert() < 0)
  342. goto err;
  343. cfg_head.num_cfgs = ptr->extcfg_item_nums;
  344. cfg_head.total_size =
  345. ( sizeof(extcfg_file_header_t) +
  346. ptr->id_item_size * ptr->extcfg_item_nums +
  347. ptr->extcfg_data_size
  348. );
  349. /* write data into file */
  350. output_file = fopen(ptr->extcfg_file_name, "wb");
  351. if (output_file == NULL)
  352. goto err;
  353. fwrite(&cfg_head, 1, sizeof(extcfg_file_header_t), output_file);
  354. if (ptr->extcfg_item_nums > 0)
  355. {
  356. fwrite(ptr->extcfg_item, ptr->id_item_size, ptr->extcfg_item_nums, output_file);
  357. fwrite(ptr->extcfg_data, 1, ptr->extcfg_data_size, output_file);
  358. }
  359. fclose(output_file);
  360. free(ptr->src_data);
  361. output_file = NULL;
  362. ptr->src_data = NULL;
  363. return 0;
  364. err:
  365. if (ptr->src_data != NULL)
  366. free(ptr->src_data);
  367. if (output_file != NULL)
  368. fclose(output_file);
  369. ptr->src_data = NULL;
  370. output_file = NULL;
  371. return -1;
  372. }
  373. int main(int argc, char *argv[])
  374. {
  375. if (get_args(argc, argv) < 0)
  376. goto err;
  377. if (get_cfg_id() < 0)
  378. goto err;
  379. if (convert_extcfg() < 0)
  380. goto err;
  381. return 0;
  382. err:
  383. printf("fail\n");
  384. return -1;
  385. }