cart.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098
  1. /*
  2. * PicoDrive
  3. * (c) Copyright Dave, 2004
  4. * (C) notaz, 2006-2010
  5. *
  6. * This work is licensed under the terms of MAME license.
  7. * See COPYING file in the top-level directory.
  8. */
  9. #include "pico_int.h"
  10. #include "../cpu/debug.h"
  11. #include "../unzip/unzip.h"
  12. #include <zlib.h>
  13. static int rom_alloc_size;
  14. static const char *rom_exts[] = { "bin", "gen", "smd", "iso", "sms", "gg", "sg" };
  15. void (*PicoCartUnloadHook)(void);
  16. void (*PicoCartMemSetup)(void);
  17. void (*PicoCartLoadProgressCB)(int percent) = NULL;
  18. void (*PicoCDLoadProgressCB)(const char *fname, int percent) = NULL; // handled in Pico/cd/cd_file.c
  19. int PicoGameLoaded;
  20. static void PicoCartDetect(const char *carthw_cfg);
  21. /* cso struct */
  22. typedef struct _cso_struct
  23. {
  24. unsigned char in_buff[2*2048];
  25. unsigned char out_buff[2048];
  26. struct {
  27. char magic[4];
  28. unsigned int unused;
  29. unsigned int total_bytes;
  30. unsigned int total_bytes_high; // ignored here
  31. unsigned int block_size; // 10h
  32. unsigned char ver;
  33. unsigned char align;
  34. unsigned char reserved[2];
  35. } header;
  36. unsigned int fpos_in; // input file read pointer
  37. unsigned int fpos_out; // pos in virtual decompressed file
  38. int block_in_buff; // block which we have read in in_buff
  39. int pad;
  40. int index[0];
  41. }
  42. cso_struct;
  43. static int uncompress2(void *dest, int destLen, void *source, int sourceLen)
  44. {
  45. z_stream stream;
  46. int err;
  47. stream.next_in = (Bytef*)source;
  48. stream.avail_in = (uInt)sourceLen;
  49. stream.next_out = dest;
  50. stream.avail_out = (uInt)destLen;
  51. stream.zalloc = NULL;
  52. stream.zfree = NULL;
  53. err = inflateInit2(&stream, -15);
  54. if (err != Z_OK) return err;
  55. err = inflate(&stream, Z_FINISH);
  56. if (err != Z_STREAM_END) {
  57. inflateEnd(&stream);
  58. return err;
  59. }
  60. //*destLen = stream.total_out;
  61. return inflateEnd(&stream);
  62. }
  63. static const char *get_ext(const char *path)
  64. {
  65. const char *ext;
  66. if (strlen(path) < 4)
  67. return ""; // no ext
  68. // allow 2 or 3 char extensions for now
  69. ext = path + strlen(path) - 2;
  70. if (ext[-1] != '.') ext--;
  71. if (ext[-1] != '.')
  72. return "";
  73. return ext;
  74. }
  75. struct zip_file {
  76. pm_file file;
  77. ZIP *zip;
  78. struct zipent *entry;
  79. z_stream stream;
  80. unsigned char inbuf[16384];
  81. long start;
  82. unsigned int pos;
  83. };
  84. pm_file *pm_open(const char *path)
  85. {
  86. pm_file *file = NULL;
  87. const char *ext;
  88. FILE *f;
  89. if (path == NULL)
  90. return NULL;
  91. ext = get_ext(path);
  92. if (strcasecmp(ext, "zip") == 0)
  93. {
  94. struct zip_file *zfile = NULL;
  95. struct zipent *zipentry;
  96. ZIP *zipfile;
  97. int i, ret;
  98. zipfile = openzip(path);
  99. if (zipfile != NULL)
  100. {
  101. /* search for suitable file (right extension or large enough file) */
  102. while ((zipentry = readzip(zipfile)) != NULL)
  103. {
  104. ext = get_ext(zipentry->name);
  105. if (zipentry->uncompressed_size >= 32*1024)
  106. goto found_rom_zip;
  107. for (i = 0; i < sizeof(rom_exts)/sizeof(rom_exts[0]); i++)
  108. if (strcasecmp(ext, rom_exts[i]) == 0)
  109. goto found_rom_zip;
  110. }
  111. /* zipfile given, but nothing found suitable for us inside */
  112. goto zip_failed;
  113. found_rom_zip:
  114. zfile = calloc(1, sizeof(*zfile));
  115. if (zfile == NULL)
  116. goto zip_failed;
  117. ret = seekcompresszip(zipfile, zipentry);
  118. if (ret != 0)
  119. goto zip_failed;
  120. ret = inflateInit2(&zfile->stream, -15);
  121. if (ret != Z_OK) {
  122. elprintf(EL_STATUS, "zip: inflateInit2 %d", ret);
  123. goto zip_failed;
  124. }
  125. zfile->zip = zipfile;
  126. zfile->entry = zipentry;
  127. zfile->start = ftell(zipfile->fp);
  128. zfile->file.file = zfile;
  129. zfile->file.size = zipentry->uncompressed_size;
  130. zfile->file.type = PMT_ZIP;
  131. strncpy(zfile->file.ext, ext, sizeof(zfile->file.ext) - 1);
  132. return &zfile->file;
  133. zip_failed:
  134. closezip(zipfile);
  135. free(zfile);
  136. return NULL;
  137. }
  138. }
  139. else if (strcasecmp(ext, "cso") == 0)
  140. {
  141. cso_struct *cso = NULL, *tmp = NULL;
  142. int size;
  143. f = fopen(path, "rb");
  144. if (f == NULL)
  145. goto cso_failed;
  146. #ifdef __GP2X__
  147. /* we use our own buffering */
  148. setvbuf(f, NULL, _IONBF, 0);
  149. #endif
  150. cso = malloc(sizeof(*cso));
  151. if (cso == NULL)
  152. goto cso_failed;
  153. if (fread(&cso->header, 1, sizeof(cso->header), f) != sizeof(cso->header))
  154. goto cso_failed;
  155. if (strncmp(cso->header.magic, "CISO", 4) != 0) {
  156. elprintf(EL_STATUS, "cso: bad header");
  157. goto cso_failed;
  158. }
  159. if (cso->header.block_size != 2048) {
  160. elprintf(EL_STATUS, "cso: bad block size (%u)", cso->header.block_size);
  161. goto cso_failed;
  162. }
  163. size = ((cso->header.total_bytes >> 11) + 1)*4 + sizeof(*cso);
  164. tmp = realloc(cso, size);
  165. if (tmp == NULL)
  166. goto cso_failed;
  167. cso = tmp;
  168. elprintf(EL_STATUS, "allocated %i bytes for CSO struct", size);
  169. size -= sizeof(*cso); // index size
  170. if (fread(cso->index, 1, size, f) != size) {
  171. elprintf(EL_STATUS, "cso: premature EOF");
  172. goto cso_failed;
  173. }
  174. // all ok
  175. cso->fpos_in = ftell(f);
  176. cso->fpos_out = 0;
  177. cso->block_in_buff = -1;
  178. file = calloc(1, sizeof(*file));
  179. if (file == NULL) goto cso_failed;
  180. file->file = f;
  181. file->param = cso;
  182. file->size = cso->header.total_bytes;
  183. file->type = PMT_CSO;
  184. return file;
  185. cso_failed:
  186. if (cso != NULL) free(cso);
  187. if (f != NULL) fclose(f);
  188. return NULL;
  189. }
  190. /* not a zip, treat as uncompressed file */
  191. f = fopen(path, "rb");
  192. if (f == NULL) return NULL;
  193. file = calloc(1, sizeof(*file));
  194. if (file == NULL) {
  195. fclose(f);
  196. return NULL;
  197. }
  198. fseek(f, 0, SEEK_END);
  199. file->file = f;
  200. file->param = NULL;
  201. file->size = ftell(f);
  202. file->type = PMT_UNCOMPRESSED;
  203. strncpy(file->ext, ext, sizeof(file->ext) - 1);
  204. fseek(f, 0, SEEK_SET);
  205. #ifdef __GP2X__
  206. if (file->size > 0x400000)
  207. /* we use our own buffering */
  208. setvbuf(f, NULL, _IONBF, 0);
  209. #endif
  210. return file;
  211. }
  212. size_t pm_read(void *ptr, size_t bytes, pm_file *stream)
  213. {
  214. int ret;
  215. if (stream->type == PMT_UNCOMPRESSED)
  216. {
  217. ret = fread(ptr, 1, bytes, stream->file);
  218. }
  219. else if (stream->type == PMT_ZIP)
  220. {
  221. struct zip_file *z = stream->file;
  222. if (z->entry->compression_method == 0) {
  223. int ret = fread(ptr, 1, bytes, z->zip->fp);
  224. z->pos += ret;
  225. return ret;
  226. }
  227. z->stream.next_out = ptr;
  228. z->stream.avail_out = bytes;
  229. while (z->stream.avail_out != 0) {
  230. if (z->stream.avail_in == 0) {
  231. z->stream.avail_in = fread(z->inbuf, 1, sizeof(z->inbuf), z->zip->fp);
  232. if (z->stream.avail_in == 0)
  233. break;
  234. z->stream.next_in = z->inbuf;
  235. }
  236. ret = inflate(&z->stream, Z_NO_FLUSH);
  237. if (ret == Z_STREAM_END)
  238. break;
  239. if (ret != Z_OK) {
  240. elprintf(EL_STATUS, "zip: inflate: %d", ret);
  241. return 0;
  242. }
  243. }
  244. z->pos += bytes - z->stream.avail_out;
  245. return bytes - z->stream.avail_out;
  246. }
  247. else if (stream->type == PMT_CSO)
  248. {
  249. cso_struct *cso = stream->param;
  250. int read_pos, read_len, out_offs, rret;
  251. int block = cso->fpos_out >> 11;
  252. int index = cso->index[block];
  253. int index_end = cso->index[block+1];
  254. unsigned char *out = ptr, *tmp_dst;
  255. ret = 0;
  256. while (bytes != 0)
  257. {
  258. out_offs = cso->fpos_out&0x7ff;
  259. if (out_offs == 0 && bytes >= 2048)
  260. tmp_dst = out;
  261. else tmp_dst = cso->out_buff;
  262. read_pos = (index&0x7fffffff) << cso->header.align;
  263. if (index < 0) {
  264. if (read_pos != cso->fpos_in)
  265. fseek(stream->file, read_pos, SEEK_SET);
  266. rret = fread(tmp_dst, 1, 2048, stream->file);
  267. cso->fpos_in = read_pos + rret;
  268. if (rret != 2048) break;
  269. } else {
  270. read_len = (((index_end&0x7fffffff) << cso->header.align) - read_pos) & 0xfff;
  271. if (block != cso->block_in_buff)
  272. {
  273. if (read_pos != cso->fpos_in)
  274. fseek(stream->file, read_pos, SEEK_SET);
  275. rret = fread(cso->in_buff, 1, read_len, stream->file);
  276. cso->fpos_in = read_pos + rret;
  277. if (rret != read_len) {
  278. elprintf(EL_STATUS, "cso: read failed @ %08x", read_pos);
  279. break;
  280. }
  281. cso->block_in_buff = block;
  282. }
  283. rret = uncompress2(tmp_dst, 2048, cso->in_buff, read_len);
  284. if (rret != 0) {
  285. elprintf(EL_STATUS, "cso: uncompress failed @ %08x with %i", read_pos, rret);
  286. break;
  287. }
  288. }
  289. rret = 2048;
  290. if (out_offs != 0 || bytes < 2048) {
  291. //elprintf(EL_STATUS, "cso: unaligned/nonfull @ %08x, offs=%i, len=%u", cso->fpos_out, out_offs, bytes);
  292. if (bytes < rret) rret = bytes;
  293. if (2048 - out_offs < rret) rret = 2048 - out_offs;
  294. memcpy(out, tmp_dst + out_offs, rret);
  295. }
  296. ret += rret;
  297. out += rret;
  298. cso->fpos_out += rret;
  299. bytes -= rret;
  300. block++;
  301. index = index_end;
  302. index_end = cso->index[block+1];
  303. }
  304. }
  305. else
  306. ret = 0;
  307. return ret;
  308. }
  309. int pm_seek(pm_file *stream, long offset, int whence)
  310. {
  311. if (stream->type == PMT_UNCOMPRESSED)
  312. {
  313. fseek(stream->file, offset, whence);
  314. return ftell(stream->file);
  315. }
  316. else if (stream->type == PMT_ZIP)
  317. {
  318. struct zip_file *z = stream->file;
  319. unsigned int pos = z->pos;
  320. int ret;
  321. switch (whence)
  322. {
  323. case SEEK_CUR: pos += offset; break;
  324. case SEEK_SET: pos = offset; break;
  325. case SEEK_END: pos = stream->size - offset; break;
  326. }
  327. if (z->entry->compression_method == 0) {
  328. ret = fseek(z->zip->fp, z->start + pos, SEEK_SET);
  329. if (ret == 0)
  330. return (z->pos = pos);
  331. return -1;
  332. }
  333. offset = pos - z->pos;
  334. if (pos < z->pos) {
  335. // full decompress from the start
  336. fseek(z->zip->fp, z->start, SEEK_SET);
  337. z->stream.avail_in = 0;
  338. z->stream.next_in = z->inbuf;
  339. inflateReset(&z->stream);
  340. z->pos = 0;
  341. offset = pos;
  342. }
  343. if (PicoMessage != NULL && offset > 4 * 1024 * 1024)
  344. PicoMessage("Decompressing data...");
  345. while (offset > 0) {
  346. char buf[16 * 1024];
  347. size_t l = offset > sizeof(buf) ? sizeof(buf) : offset;
  348. ret = pm_read(buf, l, stream);
  349. if (ret != l)
  350. break;
  351. offset -= l;
  352. }
  353. return z->pos;
  354. }
  355. else if (stream->type == PMT_CSO)
  356. {
  357. cso_struct *cso = stream->param;
  358. switch (whence)
  359. {
  360. case SEEK_CUR: cso->fpos_out += offset; break;
  361. case SEEK_SET: cso->fpos_out = offset; break;
  362. case SEEK_END: cso->fpos_out = cso->header.total_bytes - offset; break;
  363. }
  364. return cso->fpos_out;
  365. }
  366. else
  367. return -1;
  368. }
  369. int pm_close(pm_file *fp)
  370. {
  371. int ret = 0;
  372. if (fp == NULL) return EOF;
  373. if (fp->type == PMT_UNCOMPRESSED)
  374. {
  375. fclose(fp->file);
  376. }
  377. else if (fp->type == PMT_ZIP)
  378. {
  379. struct zip_file *z = fp->file;
  380. inflateEnd(&z->stream);
  381. closezip(z->zip);
  382. }
  383. else if (fp->type == PMT_CSO)
  384. {
  385. free(fp->param);
  386. fclose(fp->file);
  387. }
  388. else
  389. ret = EOF;
  390. free(fp);
  391. return ret;
  392. }
  393. // byteswap, data needs to be int aligned, src can match dst
  394. void Byteswap(void *dst, const void *src, int len)
  395. {
  396. const unsigned int *ps = src;
  397. unsigned int *pd = dst;
  398. int i, m;
  399. if (len < 2)
  400. return;
  401. m = 0x00ff00ff;
  402. for (i = 0; i < len / 4; i++) {
  403. unsigned int t = ps[i];
  404. pd[i] = ((t & m) << 8) | ((t & ~m) >> 8);
  405. }
  406. }
  407. // Interleve a 16k block and byteswap
  408. static int InterleveBlock(unsigned char *dest,unsigned char *src)
  409. {
  410. int i=0;
  411. for (i=0;i<0x2000;i++) dest[(i<<1) ]=src[ i]; // Odd
  412. for (i=0;i<0x2000;i++) dest[(i<<1)+1]=src[0x2000+i]; // Even
  413. return 0;
  414. }
  415. // Decode a SMD file
  416. static int DecodeSmd(unsigned char *data,int len)
  417. {
  418. unsigned char *temp=NULL;
  419. int i=0;
  420. temp=(unsigned char *)malloc(0x4000);
  421. if (temp==NULL) return 1;
  422. memset(temp,0,0x4000);
  423. // Interleve each 16k block and shift down by 0x200:
  424. for (i=0; i+0x4200<=len; i+=0x4000)
  425. {
  426. InterleveBlock(temp,data+0x200+i); // Interleve 16k to temporary buffer
  427. memcpy(data+i,temp,0x4000); // Copy back in
  428. }
  429. free(temp);
  430. return 0;
  431. }
  432. static unsigned char *PicoCartAlloc(int filesize, int is_sms)
  433. {
  434. unsigned char *rom;
  435. if (is_sms) {
  436. // make size power of 2 for easier banking handling
  437. int s = 0, tmp = filesize;
  438. while ((tmp >>= 1) != 0)
  439. s++;
  440. if (filesize > (1 << s))
  441. s++;
  442. rom_alloc_size = 1 << s;
  443. // be sure we can cover all address space
  444. if (rom_alloc_size < 0x10000)
  445. rom_alloc_size = 0x10000;
  446. }
  447. else {
  448. // make alloc size at least sizeof(mcd_state),
  449. // in case we want to switch to CD mode
  450. if (filesize < sizeof(mcd_state))
  451. filesize = sizeof(mcd_state);
  452. // align to 512K for memhandlers
  453. rom_alloc_size = (filesize + 0x7ffff) & ~0x7ffff;
  454. }
  455. if (rom_alloc_size - filesize < 4)
  456. rom_alloc_size += 4; // padding for out-of-bound exec protection
  457. // Allocate space for the rom plus padding
  458. // use special address for 32x dynarec
  459. rom = plat_mmap(0x02000000, rom_alloc_size, 0, 0);
  460. return rom;
  461. }
  462. int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms)
  463. {
  464. unsigned char *rom;
  465. int size, bytes_read;
  466. if (f == NULL)
  467. return 1;
  468. size = f->size;
  469. if (size <= 0) return 1;
  470. size = (size+3)&~3; // Round up to a multiple of 4
  471. // Allocate space for the rom plus padding
  472. rom = PicoCartAlloc(size, is_sms);
  473. if (rom == NULL) {
  474. elprintf(EL_STATUS, "out of memory (wanted %i)", size);
  475. return 2;
  476. }
  477. if (PicoCartLoadProgressCB != NULL)
  478. {
  479. // read ROM in blocks, just for fun
  480. int ret;
  481. unsigned char *p = rom;
  482. bytes_read=0;
  483. do
  484. {
  485. int todo = size - bytes_read;
  486. if (todo > 256*1024) todo = 256*1024;
  487. ret = pm_read(p,todo,f);
  488. bytes_read += ret;
  489. p += ret;
  490. PicoCartLoadProgressCB(bytes_read * 100 / size);
  491. }
  492. while (ret > 0);
  493. }
  494. else
  495. bytes_read = pm_read(rom,size,f); // Load up the rom
  496. if (bytes_read <= 0) {
  497. elprintf(EL_STATUS, "read failed");
  498. free(rom);
  499. return 3;
  500. }
  501. if (!is_sms)
  502. {
  503. // maybe we are loading MegaCD BIOS?
  504. if (!(PicoAHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom+0x124, "BOOT", 4) ||
  505. !strncmp((char *)rom+0x128, "BOOT", 4))) {
  506. PicoAHW |= PAHW_MCD;
  507. }
  508. // Check for SMD:
  509. if (size >= 0x4200 && (size&0x3fff) == 0x200 &&
  510. ((rom[0x2280] == 'S' && rom[0x280] == 'E') || (rom[0x280] == 'S' && rom[0x2281] == 'E'))) {
  511. elprintf(EL_STATUS, "SMD format detected.");
  512. DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD
  513. }
  514. else Byteswap(rom, rom, size); // Just byteswap
  515. }
  516. else
  517. {
  518. if (size >= 0x4200 && (size&0x3fff) == 0x200) {
  519. elprintf(EL_STATUS, "SMD format detected.");
  520. // at least here it's not interleaved
  521. size -= 0x200;
  522. memmove(rom, rom + 0x200, size);
  523. }
  524. }
  525. if (prom) *prom = rom;
  526. if (psize) *psize = size;
  527. return 0;
  528. }
  529. // Insert a cartridge:
  530. int PicoCartInsert(unsigned char *rom, unsigned int romsize, const char *carthw_cfg)
  531. {
  532. // notaz: add a 68k "jump one op back" opcode to the end of ROM.
  533. // This will hang the emu, but will prevent nasty crashes.
  534. // note: 4 bytes are padded to every ROM
  535. if (rom != NULL)
  536. *(unsigned long *)(rom+romsize) = 0xFFFE4EFA; // 4EFA FFFE byteswapped
  537. Pico.rom=rom;
  538. Pico.romsize=romsize;
  539. if (SRam.data) {
  540. free(SRam.data);
  541. SRam.data = NULL;
  542. }
  543. if (PicoCartUnloadHook != NULL) {
  544. PicoCartUnloadHook();
  545. PicoCartUnloadHook = NULL;
  546. }
  547. pdb_cleanup();
  548. PicoAHW &= PAHW_MCD|PAHW_SMS;
  549. PicoCartMemSetup = NULL;
  550. PicoDmaHook = NULL;
  551. PicoResetHook = NULL;
  552. PicoLineHook = NULL;
  553. PicoLoadStateHook = NULL;
  554. carthw_chunks = NULL;
  555. if (!(PicoAHW & (PAHW_MCD|PAHW_SMS)))
  556. PicoCartDetect(carthw_cfg);
  557. // setup correct memory map for loaded ROM
  558. switch (PicoAHW) {
  559. default:
  560. elprintf(EL_STATUS|EL_ANOMALY, "starting in unknown hw configuration: %x", PicoAHW);
  561. case 0:
  562. case PAHW_SVP: PicoMemSetup(); break;
  563. case PAHW_MCD: PicoMemSetupCD(); break;
  564. case PAHW_PICO: PicoMemSetupPico(); break;
  565. case PAHW_SMS: PicoMemSetupMS(); break;
  566. }
  567. if (PicoCartMemSetup != NULL)
  568. PicoCartMemSetup();
  569. if (PicoAHW & PAHW_SMS)
  570. PicoPowerMS();
  571. else
  572. PicoPower();
  573. PicoGameLoaded = 1;
  574. return 0;
  575. }
  576. int PicoCartResize(int newsize)
  577. {
  578. void *tmp = plat_mremap(Pico.rom, rom_alloc_size, newsize);
  579. if (tmp == NULL)
  580. return -1;
  581. Pico.rom = tmp;
  582. rom_alloc_size = newsize;
  583. return 0;
  584. }
  585. void PicoCartUnload(void)
  586. {
  587. if (PicoCartUnloadHook != NULL) {
  588. PicoCartUnloadHook();
  589. PicoCartUnloadHook = NULL;
  590. }
  591. if (PicoAHW & PAHW_32X)
  592. PicoUnload32x();
  593. if (Pico.rom != NULL) {
  594. SekFinishIdleDet();
  595. plat_munmap(Pico.rom, rom_alloc_size);
  596. Pico.rom = NULL;
  597. }
  598. PicoGameLoaded = 0;
  599. }
  600. static unsigned int rom_crc32(void)
  601. {
  602. unsigned int crc;
  603. elprintf(EL_STATUS, "caclulating CRC32..");
  604. // have to unbyteswap for calculation..
  605. Byteswap(Pico.rom, Pico.rom, Pico.romsize);
  606. crc = crc32(0, Pico.rom, Pico.romsize);
  607. Byteswap(Pico.rom, Pico.rom, Pico.romsize);
  608. return crc;
  609. }
  610. static int rom_strcmp(int rom_offset, const char *s1)
  611. {
  612. int i, len = strlen(s1);
  613. const char *s_rom = (const char *)Pico.rom;
  614. if (rom_offset + len > Pico.romsize)
  615. return 0;
  616. for (i = 0; i < len; i++)
  617. if (s1[i] != s_rom[(i + rom_offset) ^ 1])
  618. return 1;
  619. return 0;
  620. }
  621. static unsigned int rom_read32(int addr)
  622. {
  623. unsigned short *m = (unsigned short *)(Pico.rom + addr);
  624. return (m[0] << 16) | m[1];
  625. }
  626. static char *sskip(char *s)
  627. {
  628. while (*s && isspace_(*s))
  629. s++;
  630. return s;
  631. }
  632. static void rstrip(char *s)
  633. {
  634. char *p;
  635. for (p = s + strlen(s) - 1; p >= s; p--)
  636. if (isspace_(*p))
  637. *p = 0;
  638. }
  639. static int parse_3_vals(char *p, int *val0, int *val1, int *val2)
  640. {
  641. char *r;
  642. *val0 = strtoul(p, &r, 0);
  643. if (r == p)
  644. goto bad;
  645. p = sskip(r);
  646. if (*p++ != ',')
  647. goto bad;
  648. *val1 = strtoul(p, &r, 0);
  649. if (r == p)
  650. goto bad;
  651. p = sskip(r);
  652. if (*p++ != ',')
  653. goto bad;
  654. *val2 = strtoul(p, &r, 0);
  655. if (r == p)
  656. goto bad;
  657. return 1;
  658. bad:
  659. return 0;
  660. }
  661. static int is_expr(const char *expr, char **pr)
  662. {
  663. int len = strlen(expr);
  664. char *p = *pr;
  665. if (strncmp(expr, p, len) != 0)
  666. return 0;
  667. p = sskip(p + len);
  668. if (*p != '=')
  669. return 0; // wrong or malformed
  670. *pr = sskip(p + 1);
  671. return 1;
  672. }
  673. #include "carthw_cfg.c"
  674. static void parse_carthw(const char *carthw_cfg, int *fill_sram)
  675. {
  676. int line = 0, any_checks_passed = 0, skip_sect = 0;
  677. const char *s, *builtin = builtin_carthw_cfg;
  678. int tmp, rom_crc = 0;
  679. char buff[256], *p, *r;
  680. FILE *f;
  681. f = fopen(carthw_cfg, "r");
  682. if (f == NULL)
  683. f = fopen("pico/carthw.cfg", "r");
  684. if (f == NULL)
  685. elprintf(EL_STATUS, "couldn't open carthw.cfg!");
  686. for (;;)
  687. {
  688. if (f != NULL) {
  689. p = fgets(buff, sizeof(buff), f);
  690. if (p == NULL)
  691. break;
  692. }
  693. else {
  694. if (*builtin == 0)
  695. break;
  696. for (s = builtin; *s != 0 && *s != '\n'; s++)
  697. ;
  698. while (*s == '\n')
  699. s++;
  700. tmp = s - builtin;
  701. if (tmp > sizeof(buff) - 1)
  702. tmp = sizeof(buff) - 1;
  703. memcpy(buff, builtin, tmp);
  704. buff[tmp] = 0;
  705. p = buff;
  706. builtin = s;
  707. }
  708. line++;
  709. p = sskip(p);
  710. if (*p == 0 || *p == '#')
  711. continue;
  712. if (*p == '[') {
  713. any_checks_passed = 0;
  714. skip_sect = 0;
  715. continue;
  716. }
  717. if (skip_sect)
  718. continue;
  719. /* look for checks */
  720. if (is_expr("check_str", &p))
  721. {
  722. int offs;
  723. offs = strtoul(p, &r, 0);
  724. if (offs < 0 || offs > Pico.romsize) {
  725. elprintf(EL_STATUS, "carthw:%d: check_str offs out of range: %d\n", line, offs);
  726. goto bad;
  727. }
  728. p = sskip(r);
  729. if (*p != ',')
  730. goto bad;
  731. p = sskip(p + 1);
  732. if (*p != '"')
  733. goto bad;
  734. p++;
  735. r = strchr(p, '"');
  736. if (r == NULL)
  737. goto bad;
  738. *r = 0;
  739. if (rom_strcmp(offs, p) == 0)
  740. any_checks_passed = 1;
  741. else
  742. skip_sect = 1;
  743. continue;
  744. }
  745. else if (is_expr("check_size_gt", &p))
  746. {
  747. int size;
  748. size = strtoul(p, &r, 0);
  749. if (r == p || size < 0)
  750. goto bad;
  751. if (Pico.romsize > size)
  752. any_checks_passed = 1;
  753. else
  754. skip_sect = 1;
  755. continue;
  756. }
  757. else if (is_expr("check_csum", &p))
  758. {
  759. int csum;
  760. csum = strtoul(p, &r, 0);
  761. if (r == p || (csum & 0xffff0000))
  762. goto bad;
  763. if (csum == (rom_read32(0x18c) & 0xffff))
  764. any_checks_passed = 1;
  765. else
  766. skip_sect = 1;
  767. continue;
  768. }
  769. else if (is_expr("check_crc32", &p))
  770. {
  771. unsigned int crc;
  772. crc = strtoul(p, &r, 0);
  773. if (r == p)
  774. goto bad;
  775. if (rom_crc == 0)
  776. rom_crc = rom_crc32();
  777. if (crc == rom_crc)
  778. any_checks_passed = 1;
  779. else
  780. skip_sect = 1;
  781. continue;
  782. }
  783. /* now time for actions */
  784. if (is_expr("hw", &p)) {
  785. if (!any_checks_passed)
  786. goto no_checks;
  787. rstrip(p);
  788. if (strcmp(p, "svp") == 0)
  789. PicoSVPStartup();
  790. else if (strcmp(p, "pico") == 0)
  791. PicoInitPico();
  792. else if (strcmp(p, "prot") == 0)
  793. carthw_sprot_startup();
  794. else if (strcmp(p, "ssf2_mapper") == 0)
  795. carthw_ssf2_startup();
  796. else if (strcmp(p, "x_in_1_mapper") == 0)
  797. carthw_Xin1_startup();
  798. else if (strcmp(p, "realtec_mapper") == 0)
  799. carthw_realtec_startup();
  800. else if (strcmp(p, "radica_mapper") == 0)
  801. carthw_radica_startup();
  802. else if (strcmp(p, "piersolar_mapper") == 0)
  803. carthw_pier_startup();
  804. else if (strcmp(p, "prot_lk3") == 0)
  805. carthw_prot_lk3_startup();
  806. else {
  807. elprintf(EL_STATUS, "carthw:%d: unsupported mapper: %s", line, p);
  808. skip_sect = 1;
  809. }
  810. continue;
  811. }
  812. if (is_expr("sram_range", &p)) {
  813. int start, end;
  814. if (!any_checks_passed)
  815. goto no_checks;
  816. rstrip(p);
  817. start = strtoul(p, &r, 0);
  818. if (r == p)
  819. goto bad;
  820. p = sskip(r);
  821. if (*p != ',')
  822. goto bad;
  823. p = sskip(p + 1);
  824. end = strtoul(p, &r, 0);
  825. if (r == p)
  826. goto bad;
  827. if (((start | end) & 0xff000000) || start > end) {
  828. elprintf(EL_STATUS, "carthw:%d: bad sram_range: %08x - %08x", line, start, end);
  829. goto bad_nomsg;
  830. }
  831. SRam.start = start;
  832. SRam.end = end;
  833. continue;
  834. }
  835. else if (is_expr("prop", &p)) {
  836. if (!any_checks_passed)
  837. goto no_checks;
  838. rstrip(p);
  839. if (strcmp(p, "no_sram") == 0)
  840. SRam.flags &= ~SRF_ENABLED;
  841. else if (strcmp(p, "no_eeprom") == 0)
  842. SRam.flags &= ~SRF_EEPROM;
  843. else if (strcmp(p, "filled_sram") == 0)
  844. *fill_sram = 1;
  845. else if (strcmp(p, "force_6btn") == 0)
  846. PicoQuirks |= PQUIRK_FORCE_6BTN;
  847. else {
  848. elprintf(EL_STATUS, "carthw:%d: unsupported prop: %s", line, p);
  849. goto bad_nomsg;
  850. }
  851. elprintf(EL_STATUS, "game prop: %s", p);
  852. continue;
  853. }
  854. else if (is_expr("eeprom_type", &p)) {
  855. int type;
  856. if (!any_checks_passed)
  857. goto no_checks;
  858. rstrip(p);
  859. type = strtoul(p, &r, 0);
  860. if (r == p || type < 0)
  861. goto bad;
  862. SRam.eeprom_type = type;
  863. SRam.flags |= SRF_EEPROM;
  864. continue;
  865. }
  866. else if (is_expr("eeprom_lines", &p)) {
  867. int scl, sda_in, sda_out;
  868. if (!any_checks_passed)
  869. goto no_checks;
  870. rstrip(p);
  871. if (!parse_3_vals(p, &scl, &sda_in, &sda_out))
  872. goto bad;
  873. if (scl < 0 || scl > 15 || sda_in < 0 || sda_in > 15 ||
  874. sda_out < 0 || sda_out > 15)
  875. goto bad;
  876. SRam.eeprom_bit_cl = scl;
  877. SRam.eeprom_bit_in = sda_in;
  878. SRam.eeprom_bit_out= sda_out;
  879. continue;
  880. }
  881. else if ((tmp = is_expr("prot_ro_value16", &p)) || is_expr("prot_rw_value16", &p)) {
  882. int addr, mask, val;
  883. if (!any_checks_passed)
  884. goto no_checks;
  885. rstrip(p);
  886. if (!parse_3_vals(p, &addr, &mask, &val))
  887. goto bad;
  888. carthw_sprot_new_location(addr, mask, val, tmp ? 1 : 0);
  889. continue;
  890. }
  891. bad:
  892. elprintf(EL_STATUS, "carthw:%d: unrecognized expression: %s", line, buff);
  893. bad_nomsg:
  894. skip_sect = 1;
  895. continue;
  896. no_checks:
  897. elprintf(EL_STATUS, "carthw:%d: command without any checks before it: %s", line, buff);
  898. skip_sect = 1;
  899. continue;
  900. }
  901. if (f != NULL)
  902. fclose(f);
  903. }
  904. /*
  905. * various cart-specific things, which can't be handled by generic code
  906. */
  907. static void PicoCartDetect(const char *carthw_cfg)
  908. {
  909. int fill_sram = 0;
  910. memset(&SRam, 0, sizeof(SRam));
  911. if (Pico.rom[0x1B1] == 'R' && Pico.rom[0x1B0] == 'A')
  912. {
  913. SRam.start = rom_read32(0x1B4) & ~0xff000001; // align
  914. SRam.end = (rom_read32(0x1B8) & ~0xff000000) | 1;
  915. if (Pico.rom[0x1B2] & 0x40)
  916. // EEPROM
  917. SRam.flags |= SRF_EEPROM;
  918. SRam.flags |= SRF_ENABLED;
  919. }
  920. if (SRam.end == 0 || SRam.start > SRam.end)
  921. {
  922. // some games may have bad headers, like S&K and Sonic3
  923. // note: majority games use 0x200000 as starting address, but there are some which
  924. // use something else (0x300000 by HardBall '95). Luckily they have good headers.
  925. SRam.start = 0x200000;
  926. SRam.end = 0x203FFF;
  927. SRam.flags |= SRF_ENABLED;
  928. }
  929. // set EEPROM defaults, in case it gets detected
  930. SRam.eeprom_type = 0; // 7bit (24C01)
  931. SRam.eeprom_bit_cl = 1;
  932. SRam.eeprom_bit_in = 0;
  933. SRam.eeprom_bit_out= 0;
  934. if (carthw_cfg != NULL)
  935. parse_carthw(carthw_cfg, &fill_sram);
  936. if (SRam.flags & SRF_ENABLED)
  937. {
  938. if (SRam.flags & SRF_EEPROM)
  939. SRam.size = 0x2000;
  940. else
  941. SRam.size = SRam.end - SRam.start + 1;
  942. SRam.data = calloc(SRam.size, 1);
  943. if (SRam.data == NULL)
  944. SRam.flags &= ~SRF_ENABLED;
  945. if (SRam.eeprom_type == 1) // 1 == 0 in PD EEPROM code
  946. SRam.eeprom_type = 0;
  947. }
  948. if ((SRam.flags & SRF_ENABLED) && fill_sram)
  949. {
  950. elprintf(EL_STATUS, "SRAM fill");
  951. memset(SRam.data, 0xff, SRam.size);
  952. }
  953. // Unusual region 'code'
  954. if (rom_strcmp(0x1f0, "EUROPE") == 0 || rom_strcmp(0x1f0, "Europe") == 0)
  955. *(int *) (Pico.rom + 0x1f0) = 0x20204520;
  956. }
  957. // vim:shiftwidth=2:expandtab