upse_unpack_psf.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /*
  2. * UPSE: the unix playstation sound emulator.
  3. *
  4. * Filename: upse_unpack_psf.c
  5. * Purpose: libupse: PSF/MiniPSF/PSF2/MiniPSF2 unpacker
  6. *
  7. * Copyright (c) 2007 William Pitcock <nenolod@sacredspiral.co.uk>
  8. *
  9. * UPSE is free software, released under the GNU General Public License,
  10. * version 2.
  11. *
  12. * A copy of the GNU General Public License, version 2, is included in
  13. * the UPSE source kit as COPYING.
  14. *
  15. * UPSE is offered without any warranty of any kind, explicit or implicit.
  16. */
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <stdarg.h>
  21. #include "upse-internal.h"
  22. #include "upse.h"
  23. #include "upse-string.h"
  24. // LOAD STUFF
  25. typedef struct
  26. {
  27. unsigned char id[8];
  28. u32 text;
  29. u32 data;
  30. u32 pc0;
  31. u32 gp0;
  32. u32 t_addr;
  33. u32 t_size;
  34. u32 d_addr;
  35. u32 d_size;
  36. u32 b_addr;
  37. u32 b_size;
  38. u32 s_addr;
  39. u32 s_size;
  40. u32 SavedSP;
  41. u32 SavedFP;
  42. u32 SavedGP;
  43. u32 SavedRA;
  44. u32 SavedS0;
  45. } upse_packed_t upse_exe_header_t;
  46. static long _upse_time_to_ms(const char *str)
  47. {
  48. int x, c = 0;
  49. int acc = 0;
  50. char s[100];
  51. strncpy(s, str, 100);
  52. s[99] = 0;
  53. for (x = strlen(s); x >= 0; x--)
  54. if (s[x] == '.' || s[x] == ',')
  55. {
  56. acc = atoi(s + x + 1);
  57. s[x] = 0;
  58. }
  59. else if (s[x] == ':')
  60. {
  61. if (c == 0)
  62. acc += atoi(s + x + 1) * 10;
  63. else if (c == 1)
  64. acc += atoi(s + x + (x ? 1 : 0)) * 10 * 60;
  65. c++;
  66. s[x] = 0;
  67. }
  68. else if (x == 0)
  69. {
  70. if (c == 0)
  71. acc += atoi(s + x) * 10;
  72. else if (c == 1)
  73. acc += atoi(s + x) * 10 * 60;
  74. else if (c == 2)
  75. acc += atoi(s + x) * 10 * 60 * 60;
  76. }
  77. acc *= 100; // To milliseconds.
  78. return (acc);
  79. }
  80. static char *_upse_resolve_path(char *f, char *newfile)
  81. {
  82. static char *ret;
  83. char *tp1;
  84. #if PSS_STYLE==1
  85. tp1 = ((char *) strrchr(f, '/'));
  86. #else
  87. tp1 = ((char *) strrchr(f, '\\'));
  88. #if PSS_STYLE!=3
  89. {
  90. char *tp3;
  91. tp3 = ((char *) strrchr(f, '/'));
  92. if (tp1 < tp3)
  93. tp1 = tp3;
  94. }
  95. #endif
  96. #endif
  97. if (!tp1)
  98. {
  99. ret = malloc(strlen(newfile) + 1);
  100. strcpy(ret, newfile);
  101. }
  102. else
  103. {
  104. ret = malloc(tp1 - f + 2 + strlen(newfile)); // 1(NULL), 1(/).
  105. memcpy(ret, f, tp1 - f);
  106. ret[tp1 - f] = '/';
  107. ret[tp1 - f + 1] = 0;
  108. strcat(ret, newfile);
  109. }
  110. return (ret);
  111. }
  112. static int _upse_psf_get_tag(char *buf, char **key, char **val)
  113. {
  114. char *tmp;
  115. tmp = buf;
  116. /* First, convert any weirdo ASCII characters to spaces. */
  117. while (*tmp++)
  118. if (*tmp > 0 && *tmp < 0x20)
  119. *tmp = 0x20;
  120. /* Strip off white space off end of string(which should be the "value"). */
  121. for (tmp = buf + strlen(buf) - 1; tmp >= buf; tmp--)
  122. {
  123. if (*tmp != 0x20)
  124. break;
  125. *tmp = 0;
  126. }
  127. /* Now, search for the first non-whitespace character. */
  128. while (*buf == 0x20)
  129. buf++;
  130. tmp = buf;
  131. while ((*buf != 0x20) && (*buf != '='))
  132. {
  133. if (!*buf)
  134. return (0); /* Null character. */
  135. buf++;
  136. }
  137. /* Allocate memory, copy string, and terminate string. */
  138. if (!(*key = malloc(buf - tmp + 1)))
  139. return (0);
  140. strncpy(*key, tmp, buf - tmp);
  141. (*key)[(buf - tmp)] = 0;
  142. /* Search for "=" character. */
  143. while (*buf != '=')
  144. {
  145. if (!*buf)
  146. return (0); /* Null character. */
  147. buf++;
  148. }
  149. buf++; /* Skip over equals character. */
  150. /* Remove leading whitespace on value. */
  151. while (*buf == 0x20)
  152. {
  153. if (!*buf)
  154. return (0); /* Null character. */
  155. buf++;
  156. }
  157. /* Allocate memory, and copy string over. Trailing whitespace was eliminated
  158. earlier.
  159. */
  160. if (!(*val = malloc(strlen(buf) + 1)))
  161. return (0);
  162. strcpy(*val, buf);
  163. //puts(*key);
  164. //puts(*val);
  165. return (1);
  166. }
  167. static void _upse_psf_free_tags(upse_psftag_t * tags)
  168. {
  169. while (tags)
  170. {
  171. upse_psftag_t *tmp = tags->next;
  172. free(tags->key);
  173. free(tags->value);
  174. free(tags);
  175. tags = tmp;
  176. }
  177. }
  178. static void _upse_psf_add_tag(upse_psftag_t ** tag, const char *key, const char *val)
  179. {
  180. upse_psftag_t *tmp;
  181. tmp = malloc(sizeof(upse_psftag_t));
  182. memset(tmp, 0, sizeof(upse_psftag_t));
  183. tmp->key = strdup(key);
  184. tmp->value = strdup(val);
  185. tmp->next = NULL;
  186. if (!*tag)
  187. *tag = tmp;
  188. else
  189. {
  190. upse_psftag_t *rec;
  191. rec = *tag;
  192. while (rec->next)
  193. rec = rec->next;
  194. rec->next = tmp;
  195. }
  196. }
  197. typedef struct
  198. {
  199. int num;
  200. char *value;
  201. } upse_libcache_slot_t;
  202. static int ccomp(const void *v1, const void *v2)
  203. {
  204. const upse_libcache_slot_t *a1, *a2;
  205. a1 = v1;
  206. a2 = v2;
  207. return (a1->num - a2->num);
  208. }
  209. static upse_psf_t *_upse_load(char *path, int level, int type, upse_iofuncs_t *_upse_iofuncs) // Type==1 for just info load.
  210. {
  211. void *fp;
  212. upse_exe_header_t tmpHead;
  213. tmpHead.t_addr = 0;
  214. tmpHead.t_size = 0;
  215. unsigned char *in, *out = 0;
  216. u8 head[4];
  217. u32 reserved;
  218. u32 complen;
  219. u32 crc32;
  220. uLongf outlen;
  221. upse_psf_t *psfi;
  222. upse_psf_t *tmpi;
  223. _ENTER;
  224. if (!(fp = _upse_iofuncs->open_impl(path, "rb")))
  225. {
  226. _ERROR("path %s failed to load\n", path);
  227. return NULL;
  228. }
  229. _upse_iofuncs->read_impl(head, 1, 4, fp);
  230. if (memcmp(head, "PSF\x01", 4))
  231. return NULL;
  232. psfi = calloc(sizeof(upse_psf_t), 1);
  233. psfi->stop = ~0;
  234. psfi->fade = 0;
  235. _upse_iofuncs->read_impl(&reserved, 1, 4, fp);
  236. _upse_iofuncs->read_impl(&complen, 1, 4, fp);
  237. complen = BFLIP32(complen);
  238. _upse_iofuncs->read_impl(&crc32, 1, 4, fp);
  239. crc32 = BFLIP32(crc32);
  240. _upse_iofuncs->seek_impl(fp, reserved, SEEK_CUR);
  241. if (type)
  242. _upse_iofuncs->seek_impl(fp, complen, SEEK_CUR);
  243. else
  244. {
  245. in = malloc(complen);
  246. out = malloc(1024 * 1024 * 2 + 0x800);
  247. _upse_iofuncs->read_impl(in, 1, complen, fp);
  248. outlen = 1024 * 1024 * 2;
  249. uncompress(out, &outlen, in, complen);
  250. free(in);
  251. memcpy(&tmpHead, out, sizeof(upse_exe_header_t));
  252. upse_r3000_cpu_regs.pc = BFLIP32(tmpHead.pc0);
  253. upse_r3000_cpu_regs.GPR.n.gp = BFLIP32(tmpHead.gp0);
  254. upse_r3000_cpu_regs.GPR.n.sp = BFLIP32(tmpHead.s_addr);
  255. if (upse_r3000_cpu_regs.GPR.n.sp == 0)
  256. upse_r3000_cpu_regs.GPR.n.sp = 0x801fff00;
  257. if (level)
  258. {
  259. LoadPSXMem(BFLIP32(tmpHead.t_addr), BFLIP32(tmpHead.t_size), out + 0x800);
  260. free(out);
  261. }
  262. }
  263. {
  264. u8 tagdata[5];
  265. if (_upse_iofuncs->read_impl(tagdata, 1, 5, fp) == 5)
  266. {
  267. if (!memcmp(tagdata, "[TAG]", 5))
  268. {
  269. char linebuf[1024];
  270. while (upse_io_fgets(linebuf, 1024, fp, _upse_iofuncs))
  271. {
  272. int x;
  273. char *key = NULL, *value = NULL;
  274. if (!_upse_psf_get_tag(linebuf, &key, &value))
  275. {
  276. if (key)
  277. free(key);
  278. if (value)
  279. free(value);
  280. continue;
  281. }
  282. _upse_psf_add_tag(&psfi->taglist, key, value);
  283. if (!level)
  284. {
  285. static char *yoinks[8] = { "title", "artist", "game", "year", "genre",
  286. "copyright", "psfby", "comment"
  287. };
  288. char **yoinks2[8] = { &psfi->title, &psfi->artist, &psfi->game, &psfi->year, &psfi->genre,
  289. &psfi->copyright, &psfi->psfby, &psfi->comment
  290. };
  291. for (x = 0; x < 8; x++)
  292. if (!strcasecmp(key, yoinks[x]))
  293. *yoinks2[x] = value;
  294. if (!strcasecmp(key, "length"))
  295. psfi->stop = _upse_time_to_ms(value);
  296. else if (!strcasecmp(key, "fade"))
  297. psfi->fade = _upse_time_to_ms(value);
  298. }
  299. if (!strcasecmp(key, "_lib") && !type)
  300. {
  301. char *tmpfn;
  302. /* Load file name "value" from the directory specified in
  303. the full path(directory + file name) "path"
  304. */
  305. tmpfn = _upse_resolve_path(path, value);
  306. if (!(tmpi = _upse_load(tmpfn, level + 1, 0, _upse_iofuncs)))
  307. {
  308. free(key);
  309. free(value);
  310. free(tmpfn);
  311. if (!level)
  312. free(out);
  313. _upse_iofuncs->close_impl(fp);
  314. _upse_psf_free_tags(psfi->taglist);
  315. free(psfi);
  316. return NULL;
  317. }
  318. _upse_psf_free_tags(tmpi->taglist);
  319. free(tmpi);
  320. free(tmpfn);
  321. }
  322. if (key)
  323. free(key);
  324. }
  325. }
  326. }
  327. }
  328. _upse_iofuncs->close_impl(fp);
  329. /* Now, if we're at level 0(main PSF), load the main executable, and any libN stuff */
  330. if (!level && !type)
  331. {
  332. LoadPSXMem(BFLIP32(tmpHead.t_addr), BFLIP32(tmpHead.t_size), out + 0x800);
  333. free(out);
  334. }
  335. if (!type) /* Load libN */
  336. {
  337. upse_libcache_slot_t *cache;
  338. upse_psftag_t *tag;
  339. unsigned int libncount = 0;
  340. unsigned int cur = 0;
  341. tag = psfi->taglist;
  342. while (tag)
  343. {
  344. if (!strncasecmp(tag->key, "_lib", 4) && tag->key[4])
  345. libncount++;
  346. tag = tag->next;
  347. }
  348. if (libncount)
  349. {
  350. cache = malloc(sizeof(upse_libcache_slot_t) * libncount);
  351. tag = psfi->taglist;
  352. while (tag)
  353. {
  354. if (!strncasecmp(tag->key, "_lib", 4) && tag->key[4])
  355. {
  356. cache[cur].num = atoi(&tag->key[4]);
  357. cache[cur].value = tag->value;
  358. cur++;
  359. }
  360. tag = tag->next;
  361. }
  362. qsort(cache, libncount, sizeof(upse_libcache_slot_t), ccomp);
  363. for (cur = 0; cur < libncount; cur++)
  364. {
  365. u32 ba[3];
  366. char *tmpfn;
  367. if (cache[cur].num < 2)
  368. continue;
  369. ba[0] = upse_r3000_cpu_regs.pc;
  370. ba[1] = upse_r3000_cpu_regs.GPR.n.gp;
  371. ba[2] = upse_r3000_cpu_regs.GPR.n.sp;
  372. /* Load file name "value" from the directory specified in
  373. the full path(directory + file name) "path"
  374. */
  375. tmpfn = _upse_resolve_path(path, cache[cur].value);
  376. if (!(tmpi = _upse_load(tmpfn, level + 1, 0, _upse_iofuncs)))
  377. {
  378. //free(key);
  379. //free(value);
  380. //free(tmpfn);
  381. //_upse_iofuncs->close_impl(fp);
  382. //return(0);
  383. }
  384. free(tmpfn);
  385. _upse_psf_free_tags(tmpi->taglist);
  386. free(tmpi);
  387. upse_r3000_cpu_regs.pc = ba[0];
  388. upse_r3000_cpu_regs.GPR.n.gp = ba[1];
  389. upse_r3000_cpu_regs.GPR.n.sp = ba[2];
  390. }
  391. free(cache);
  392. } // if(libncount)
  393. } // if(!type)
  394. _LEAVE;
  395. return psfi;
  396. }
  397. void upse_free_psf_metadata(upse_psf_t * info)
  398. {
  399. _upse_psf_free_tags(info->taglist);
  400. free(info);
  401. }
  402. upse_psf_t *upse_get_psf_metadata(char *path, upse_iofuncs_t * iofuncs)
  403. {
  404. upse_psf_t *ret;
  405. _ENTER;
  406. if (!(ret = _upse_load(path, 0, 1, iofuncs)))
  407. return NULL;
  408. if (ret->stop == (u32) ~ 0)
  409. ret->fade = 0;
  410. ret->length = ret->stop + ret->fade;
  411. _LEAVE;
  412. return ret;
  413. }
  414. upse_psf_t *upse_load(char *path, upse_iofuncs_t * iofuncs)
  415. {
  416. upse_psf_t *ret;
  417. _ENTER;
  418. psxInit();
  419. psxReset();
  420. SPUinit();
  421. SPUopen();
  422. if (!(ret = _upse_load(path, 0, 0, iofuncs)))
  423. {
  424. psxShutdown();
  425. return NULL;
  426. }
  427. if (ret->stop == (u32) ~ 0)
  428. ret->fade = 0;
  429. SPUsetlength(ret->stop, ret->fade);
  430. ret->length = ret->stop + ret->fade;
  431. _LEAVE;
  432. return ret;
  433. }