comparison blastem.c @ 424:7e8e179116af

Add support for loading GST format savestates
author Mike Pavone <pavone@retrodev.com>
date Sat, 29 Jun 2013 17:15:08 -0700
parents 642b2f8aee32
children 8b3ae850d1c4
comparison
equal deleted inserted replaced
423:8e136187c0e0 424:7e8e179116af
1461 } 1461 }
1462 } 1462 }
1463 return context; 1463 return context;
1464 } 1464 }
1465 1465
1466 #define GST_68K_REGS 0x80
1467 #define GST_68K_REG_SIZE (0xDA-GST_68K_REGS)
1468 #define GST_68K_PC_OFFSET (0xC8-GST_68K_REGS)
1469 #define GST_68K_SR_OFFSET (0xD0-GST_68K_REGS)
1470 #define GST_68K_USP_OFFSET (0xD2-GST_68K_REGS)
1471 #define GST_68K_SSP_OFFSET (0xD6-GST_68K_REGS)
1472 #define GST_68K_RAM 0x2478
1473 #define GST_Z80_REGS 0x404
1474 #define GST_Z80_REG_SIZE (0x440-GST_Z80_REGS)
1475 #define GST_Z80_RAM 0x474
1476
1477 uint32_t read_le_32(uint8_t * data)
1478 {
1479 return data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0];
1480 }
1481
1482 uint16_t read_le_16(uint8_t * data)
1483 {
1484 return data[1] << 8 | data[0];
1485 }
1486
1487 uint16_t read_be_16(uint8_t * data)
1488 {
1489 return data[0] << 8 | data[1];
1490 }
1491
1492 uint32_t m68k_load_gst(m68k_context * context, FILE * gstfile)
1493 {
1494 uint8_t buffer[4096];
1495 fseek(gstfile, GST_68K_REGS, SEEK_SET);
1496 if (fread(buffer, 1, GST_68K_REG_SIZE, gstfile) != GST_68K_REG_SIZE) {
1497 fputs("Failed to read 68K registers from savestate\n", stderr);
1498 return 0;
1499 }
1500 uint8_t * curpos = buffer;
1501 for (int i = 0; i < 8; i++) {
1502 context->dregs[i] = read_le_32(curpos);
1503 curpos += sizeof(uint32_t);
1504 }
1505 for (int i = 0; i < 8; i++) {
1506 context->aregs[i] = read_le_32(curpos);
1507 curpos += sizeof(uint32_t);
1508 }
1509 uint32_t pc = read_le_32(buffer + GST_68K_PC_OFFSET);
1510 uint16_t sr = read_le_16(buffer + GST_68K_SR_OFFSET);
1511 context->status = sr >> 8;
1512 for (int flag = 4; flag >= 0; flag--) {
1513 context->flags[flag] = sr & 1;
1514 sr >>= 1;
1515 }
1516 if (context->status & (1 << 5)) {
1517 context->aregs[8] = read_le_32(buffer + GST_68K_USP_OFFSET);
1518 } else {
1519 context->aregs[8] = read_le_32(buffer + GST_68K_SSP_OFFSET);
1520 }
1521 fseek(gstfile, GST_68K_RAM, SEEK_SET);
1522 for (int i = 0; i < (32*1024);) {
1523 if (fread(buffer, 1, sizeof(buffer), gstfile) != sizeof(buffer)) {
1524 fputs("Failed to read 68K RAM from savestate\n", stderr);
1525 return 0;
1526 }
1527 for(curpos = buffer; curpos < (buffer + sizeof(buffer)); curpos += sizeof(uint16_t)) {
1528 context->mem_pointers[1][i++] = read_be_16(curpos);
1529 }
1530 }
1531 return pc;
1532 }
1533
1534 uint8_t z80_load_gst(z80_context * context, FILE * gstfile)
1535 {
1536 uint8_t regdata[GST_Z80_REG_SIZE];
1537 fseek(gstfile, GST_Z80_REGS, SEEK_SET);
1538 if (fread(regdata, 1, sizeof(regdata), gstfile) != sizeof(regdata)) {
1539 fputs("Failed to read Z80 registers from savestate\n", stderr);
1540 return 0;
1541 }
1542 uint8_t * curpos = regdata;
1543 uint8_t f = *(curpos++);
1544 context->flags[ZF_C] = f & 1;
1545 f >>= 1;
1546 context->flags[ZF_N] = f & 1;
1547 f >>= 1;
1548 context->flags[ZF_PV] = f & 1;
1549 f >>= 2;
1550 context->flags[ZF_H] = f & 1;
1551 f >>= 2;
1552 context->flags[ZF_Z] = f & 1;
1553 f >>= 1;
1554 context->flags[ZF_S] = f;
1555
1556 context->regs[Z80_A] = *curpos;
1557 curpos += 3;
1558 for (int reg = Z80_C; reg <= Z80_IYH; reg++) {
1559 context->regs[reg++] = *(curpos++);
1560 context->regs[reg] = *curpos;
1561 curpos += 3;
1562 }
1563 uint16_t pc = read_le_16(curpos);
1564 curpos += 4;
1565 context->sp = read_le_16(curpos);
1566 curpos += 4;
1567 f = *(curpos++);
1568 context->alt_flags[ZF_C] = f & 1;
1569 f >>= 1;
1570 context->alt_flags[ZF_N] = f & 1;
1571 f >>= 1;
1572 context->alt_flags[ZF_PV] = f & 1;
1573 f >>= 2;
1574 context->alt_flags[ZF_H] = f & 1;
1575 f >>= 2;
1576 context->alt_flags[ZF_Z] = f & 1;
1577 f >>= 1;
1578 context->alt_flags[ZF_S] = f;
1579 context->alt_regs[Z80_A] = *curpos;
1580 curpos += 3;
1581 for (int reg = Z80_C; reg <= Z80_H; reg++) {
1582 context->alt_regs[reg++] = *(curpos++);
1583 context->alt_regs[reg] = *curpos;
1584 curpos += 3;
1585 }
1586 context->regs[Z80_I] = *curpos;
1587 curpos += 2;
1588 context->iff1 = context->iff2 = *curpos;
1589 curpos += 2;
1590 reset = !*(curpos++);
1591 busreq = *curpos;
1592 curpos += 3;
1593 uint32_t bank = read_le_32(curpos);
1594 if (bank < 0x400000) {
1595 context->mem_pointers[1] = context->mem_pointers[2] + bank;
1596 } else {
1597 context->mem_pointers[1] = NULL;
1598 }
1599 context->bank_reg = bank >> 15;
1600 fseek(gstfile, GST_Z80_RAM, SEEK_SET);
1601 if(fread(context->mem_pointers[0], 1, 8*1024, gstfile) != (8*1024)) {
1602 fputs("Failed to read Z80 RAM from savestate\n", stderr);
1603 return 0;
1604 }
1605 context->native_pc = z80_get_native_address_trans(context, pc);
1606 return 1;
1607 }
1608
1609 uint32_t load_gst(genesis_context * gen, char * fname)
1610 {
1611 FILE * gstfile = fopen(fname, "rb");
1612 if (!gstfile) {
1613 fprintf(stderr, "Could not open file %s for reading\n", fname);
1614 goto error;
1615 }
1616 char ident[5];
1617 if (fread(ident, 1, sizeof(ident), gstfile) != sizeof(ident)) {
1618 fprintf(stderr, "Could not read ident code from %s\n", fname);
1619 goto error_close;
1620 }
1621 if (memcmp(ident, "GST\xE0\x40", 3) != 0) {
1622 fprintf(stderr, "%s doesn't appear to be a GST savestate. The ident code is %c%c%c\\x%X\\x%X instead of GST\\xE0\\x40.\n", fname, ident[0], ident[1], ident[2], ident[3], ident[4]);
1623 goto error_close;
1624 }
1625 uint32_t pc = m68k_load_gst(gen->m68k, gstfile);
1626 if (!pc) {
1627 goto error_close;
1628 }
1629 if (!vdp_load_gst(gen->vdp, gstfile)) {
1630 goto error_close;
1631 }
1632 if (!ym_load_gst(gen->ym, gstfile)) {
1633 goto error_close;
1634 }
1635 if (!z80_load_gst(gen->z80, gstfile)) {
1636 goto error_close;
1637 }
1638 gen->ports[0].control = 0x40;
1639 gen->ports[1].control = 0x40;
1640 adjust_int_cycle(gen->m68k, gen->vdp);
1641 fclose(gstfile);
1642 return pc;
1643
1644 error_close:
1645 fclose(gstfile);
1646 error:
1647 return 0;
1648 }
1649
1466 #define ROM_END 0x1A4 1650 #define ROM_END 0x1A4
1467 #define RAM_ID 0x1B0 1651 #define RAM_ID 0x1B0
1468 #define RAM_FLAGS 0x1B2 1652 #define RAM_FLAGS 0x1B2
1469 #define RAM_START 0x1B4 1653 #define RAM_START 0x1B4
1470 #define RAM_END 0x1B8 1654 #define RAM_END 0x1B8
1500 fwrite(genesis->save_ram, 1, size, f); 1684 fwrite(genesis->save_ram, 1, size, f);
1501 fclose(f); 1685 fclose(f);
1502 printf("Saved SRAM to %s\n", sram_filename); 1686 printf("Saved SRAM to %s\n", sram_filename);
1503 } 1687 }
1504 1688
1505 void init_run_cpu(genesis_context * gen, int debug, FILE * address_log) 1689 void init_run_cpu(genesis_context * gen, int debug, FILE * address_log, char * statefile)
1506 { 1690 {
1507 m68k_context context; 1691 m68k_context context;
1508 x86_68k_options opts; 1692 x86_68k_options opts;
1509 gen->m68k = &context; 1693 gen->m68k = &context;
1510 memmap_chunk memmap[MAX_MAP_CHUNKS]; 1694 memmap_chunk memmap[MAX_MAP_CHUNKS];
1614 context.mem_pointers[2] = initial_mapped; 1798 context.mem_pointers[2] = initial_mapped;
1615 context.mem_pointers[3] = (uint16_t *)gen->save_ram; 1799 context.mem_pointers[3] = (uint16_t *)gen->save_ram;
1616 uint32_t address; 1800 uint32_t address;
1617 address = cart[2] << 16 | cart[3]; 1801 address = cart[2] << 16 | cart[3];
1618 translate_m68k_stream(address, &context); 1802 translate_m68k_stream(address, &context);
1619 if (debug) { 1803 if (statefile) {
1620 insert_breakpoint(&context, address, (uint8_t *)debugger); 1804 uint32_t pc = load_gst(gen, statefile);
1621 } 1805 if (!pc) {
1622 m68k_reset(&context); 1806 exit(1);
1807 }
1808 if (debug) {
1809 insert_breakpoint(&context, pc, (uint8_t *)debugger);
1810 }
1811 start_68k_context(&context, pc);
1812 } else {
1813 if (debug) {
1814 insert_breakpoint(&context, address, (uint8_t *)debugger);
1815 }
1816 m68k_reset(&context);
1817 }
1623 } 1818 }
1624 1819
1625 char title[64]; 1820 char title[64];
1626 1821
1627 #define TITLE_START 0x150 1822 #define TITLE_START 0x150
1687 int width = -1; 1882 int width = -1;
1688 int height = -1; 1883 int height = -1;
1689 int debug = 0; 1884 int debug = 0;
1690 int ym_log = 0; 1885 int ym_log = 0;
1691 FILE *address_log = NULL; 1886 FILE *address_log = NULL;
1887 char * statefile;
1692 for (int i = 2; i < argc; i++) { 1888 for (int i = 2; i < argc; i++) {
1693 if (argv[i][0] == '-') { 1889 if (argv[i][0] == '-') {
1694 switch(argv[i][1]) { 1890 switch(argv[i][1]) {
1695 case 'd': 1891 case 'd':
1696 debug = 1; 1892 debug = 1;
1729 break; 1925 break;
1730 default: 1926 default:
1731 fprintf(stderr, "'%c' is not a valid region character for the -r option\n", argv[i][0]); 1927 fprintf(stderr, "'%c' is not a valid region character for the -r option\n", argv[i][0]);
1732 return 1; 1928 return 1;
1733 } 1929 }
1930 break;
1931 case 's':
1932 i++;
1933 if (i >= argc) {
1934 fputs("-s must be followed by a savestate filename\n", stderr);
1935 return 1;
1936 }
1937 statefile = argv[i];
1734 break; 1938 break;
1735 case 'y': 1939 case 'y':
1736 ym_log = 1; 1940 ym_log = 1;
1737 break; 1941 break;
1738 default: 1942 default:
1799 if (i < 0) { 2003 if (i < 0) {
1800 strcpy(sram_filename + fname_size, ".sram"); 2004 strcpy(sram_filename + fname_size, ".sram");
1801 } 2005 }
1802 set_keybindings(); 2006 set_keybindings();
1803 2007
1804 init_run_cpu(&gen, debug, address_log); 2008 init_run_cpu(&gen, debug, address_log, statefile);
1805 return 0; 2009 return 0;
1806 } 2010 }