src/mess/formats/spec_snqk.c
| r7460 | r7461 | |
| 6 | 6 | |
| 7 | 7 | - Implement the following snapshot formats |
| 8 | 8 | .89C (Tezxas) |
| 9 | | .FRZ (CBSpeccy) |
| 10 | | .PLUSD (DISCiPLE/+D) |
| 11 | 9 | .SLT (Various emulators) |
| 12 | 10 | .SZX (Spectaculator) |
| 13 | 11 | .ZLS (ZX-Live!) |
| r7460 | r7461 | |
| 129 | 127 | } |
| 130 | 128 | spectrum_setup_prg(image->machine, snapshot_data, snapshot_size); |
| 131 | 129 | } |
| 130 | else if (!mame_stricmp(file_type, "plusd")) |
| 131 | { |
| 132 | if ((snapshot_size != PLUSD48_SIZE) || (snapshot_size != PLUSD128_SIZE)) |
| 133 | { |
| 134 | logerror("Invalid .PLUSD file size.\n"); |
| 135 | goto error; |
| 136 | } |
| 137 | spectrum_setup_plusd(image->machine, snapshot_data, snapshot_size); |
| 138 | } |
| 132 | 139 | else if (!mame_stricmp(file_type, "sem")) |
| 133 | 140 | { |
| 134 | 141 | if (snapshot_data[0] != 0x05 && snapshot_data[1] != 'S' && \ |
| r7460 | r7461 | |
| 175 | 182 | if (snapshot_data[0] != 'X' && snapshot_data[1] != 'S' && \ |
| 176 | 183 | snapshot_data[2] != 'N' && snapshot_data[3] != 'A') |
| 177 | 184 | { |
| 178 | | logerror("Invalid .SEM file size.\n"); |
| 185 | logerror("Invalid .SNX file size.\n"); |
| 179 | 186 | goto error; |
| 180 | 187 | } |
| 181 | 188 | spectrum_setup_snx(image->machine, snapshot_data, snapshot_size); |
| 182 | 189 | } |
| 190 | else if (!mame_stricmp(file_type, "frz")) |
| 191 | { |
| 192 | if (snapshot_size != FRZ_SIZE) |
| 193 | { |
| 194 | logerror("Invalid .FRZ file size.\n"); |
| 195 | goto error; |
| 196 | } |
| 197 | spectrum_setup_frz(image->machine, snapshot_data, snapshot_size); |
| 198 | } |
| 183 | 199 | else |
| 184 | 200 | { |
| 185 | 201 | spectrum_setup_z80(image->machine, snapshot_data, snapshot_size); |
| r7460 | r7461 | |
| 235 | 251 | * 21 27 1 I |
| 236 | 252 | * 22 28 2 SP |
| 237 | 253 | * 24 30 2 PC |
| 238 | | * 26 32 2 0 (reserved for future use) |
| 254 | * 26 32 2 0x00 (reserved for future use) |
| 239 | 255 | * 28 34 1 Border color |
| 240 | | * 29 35 1 0 (reserved for future use) |
| 256 | * 29 35 1 0x00 (reserved for future use) |
| 241 | 257 | * 30 36 2 Status word |
| 242 | 258 | * 32 38 16384/ RAM dump |
| 243 | 259 | * 49152 |
| r7460 | r7461 | |
| 380 | 396 | * Load a .SNA file. |
| 381 | 397 | * |
| 382 | 398 | * This format was used by Arnt Gulbrandsen for its JPP |
| 383 | | * emulator, and it's based on the format developed for the Mirage |
| 399 | * emulator, and it's based on the format used by the Mirage |
| 384 | 400 | * Microdriver, a Microdrive backup accessory. |
| 385 | 401 | * |
| 386 | 402 | * http://www.worldofspectrum.org/infoseekid.cgi?id=1000266 |
| r7460 | r7461 | |
| 393 | 409 | * It's been reported that snapshots saved at critical moments would |
| 394 | 410 | * subsequently crash on restore due to the fact that the stack was full |
| 395 | 411 | * or pointed to a ROM address. A workaround for this situation is to |
| 396 | | * store 0x0000 into the word that stored the PC. |
| 412 | * store 0x0000 into the word where the PC was located. |
| 397 | 413 | * |
| 398 | | * For sake of fidelity, the code that clears the top of the stack has |
| 414 | * For sake of fidelity, the code that zeroes the top of the stack has |
| 399 | 415 | * been written but commented out. |
| 400 | 416 | * |
| 401 | 417 | * Later, the format has been extended to store the whole Spectrum 128 status. |
| r7460 | r7461 | |
| 448 | 464 | * 16411 16384 RAM bank 2 (0x8000-0xbfff) |
| 449 | 465 | * 32795 16384 RAM bank n (0xc000-0xffff - currently paged bank) |
| 450 | 466 | * 49179 2 PC |
| 451 | | * 49181 1 Port 7FFD data |
| 467 | * 49181 1 Port 0x7FFD data |
| 452 | 468 | * 49182 1 TR-DOS rom paged (0=no/1=yes) |
| 453 | 469 | * 49183 81920/ Remaining RAM banks in ascending order |
| 454 | 470 | * 98304 |
| r7460 | r7461 | |
| 540 | 556 | { |
| 541 | 557 | /* 128K Snapshot */ |
| 542 | 558 | state->port_7ffd_data = snapdata[SNA128_OFFSET + 2]; |
| 559 | logerror ("Port 7FFD:%02X\n", state->port_7ffd_data); |
| 543 | 560 | if (snapdata[SNA128_OFFSET + 3]) |
| 544 | 561 | { |
| 545 | 562 | /* TODO: page TR-DOS ROM when supported */ |
| r7460 | r7461 | |
| 557 | 574 | /* Get PC from stack */ |
| 558 | 575 | addr = cpu_get_reg(cpu, Z80_SP); |
| 559 | 576 | |
| 560 | | if (addr < BASE_RAM) |
| 561 | | logerror("Corrupted SP points to ROM at:%04X", addr); |
| 577 | if (addr < BASE_RAM || addr > 4*SPECTRUM_BANK - 2) |
| 578 | logerror("Corrupted SP out of range:%04X", addr); |
| 562 | 579 | else |
| 563 | 580 | logerror("Fetching PC from the stack at SP:%04X\n", addr); |
| 564 | 581 | |
| r7460 | r7461 | |
| 587 | 604 | else |
| 588 | 605 | { |
| 589 | 606 | /* Set up other RAM banks */ |
| 590 | | bank_offset = SNA48_SIZE + SNA128_OFFSET; |
| 591 | 607 | for (i = 0; i < 8; i++) |
| 592 | 608 | usedbanks[i] = 0; |
| 593 | 609 | |
| r7460 | r7461 | |
| 602 | 618 | for (i = 0; i < 3*SPECTRUM_BANK; i++) |
| 603 | 619 | memory_write_byte(space, BASE_RAM + i, snapdata[SNA48_HDR + i]); |
| 604 | 620 | |
| 621 | bank_offset = SNA48_SIZE + SNA128_HDR; |
| 605 | 622 | for (i = 0; i < 8; i++) |
| 606 | 623 | { |
| 607 | 624 | if (!usedbanks[i]) |
| r7460 | r7461 | |
| 611 | 628 | state->port_7ffd_data += i; |
| 612 | 629 | spectrum_update_paging(machine); |
| 613 | 630 | for (j = 0; j < SPECTRUM_BANK; j++) |
| 614 | | memory_write_byte(space,j + 3*SPECTRUM_BANK, snapdata[bank_offset + j]); |
| 631 | memory_write_byte(space, j + 3*SPECTRUM_BANK, snapdata[bank_offset + j]); |
| 615 | 632 | bank_offset += SPECTRUM_BANK; |
| 616 | 633 | } |
| 617 | 634 | } |
| r7460 | r7461 | |
| 633 | 650 | state->port_7ffd_data = snapdata[SNA128_OFFSET + 2]; |
| 634 | 651 | spectrum_update_paging(machine); |
| 635 | 652 | |
| 636 | | logerror("Snapshot loaded.\nExecution resuming at Bank:%d %s\n", data, cpu_get_reg_string(cpu, Z80_PC)); |
| 653 | logerror("Snapshot loaded.\nExecution resuming at bank:%d %s\n", data, cpu_get_reg_string(cpu, Z80_PC)); |
| 637 | 654 | } |
| 638 | 655 | } |
| 639 | 656 | |
| r7460 | r7461 | |
| 660 | 677 | * 24 4 H |
| 661 | 678 | * 28 4 L |
| 662 | 679 | * 32 4 PC |
| 663 | | * 36 4 0 (reserved for future use) |
| 680 | * 36 4 0x00 (reserved for future use) |
| 664 | 681 | * 40 4 SP |
| 665 | | * 44 104 0 (reserved for future use) |
| 682 | * 44 104 0x00 (reserved for future use) |
| 666 | 683 | * 148 4 R |
| 667 | | * 152 4 0 (reserved for future use) |
| 684 | * 152 4 0x00 (reserved for future use) |
| 668 | 685 | * 156 4 Border color |
| 669 | | * 160 4 0 (reserved for future use) |
| 686 | * 160 4 0x00 (reserved for future use) |
| 670 | 687 | * 164 2 Interrupt mode (0=IM0/1=IM1/2=IM2) |
| 671 | | * 166 24 0 (reserved for future use) |
| 688 | * 166 24 0x00 (reserved for future use) |
| 672 | 689 | * 190 1 I |
| 673 | 690 | * 191 1 IFF1/2: (0=DI/1=EI) |
| 674 | | * 192 44 0 (reserved for future use) |
| 691 | * 192 44 0x00 (reserved for future use) |
| 675 | 692 | * 236 4 AF' *BE* |
| 676 | 693 | * 240 4 BC' *BE* |
| 677 | 694 | * 244 2 DE' *BE* |
| r7460 | r7461 | |
| 793 | 810 | * 13 1 Track number of the first sector of the file |
| 794 | 811 | * 14 1 Sector number of the first sector of the file |
| 795 | 812 | * 15 195 Sector allocation bitmap |
| 796 | | * 210 10 0 (reserved for future use) |
| 813 | * 210 10 0x00 (reserved for future use) |
| 797 | 814 | * 220 2 IY |
| 798 | 815 | * 222 2 IX |
| 799 | 816 | * 224 2 DE' |
| r7460 | r7461 | |
| 803 | 820 | * 232 2 DE |
| 804 | 821 | * 234 2 BC |
| 805 | 822 | * 236 2 HL |
| 806 | | * 238 1 IFF1/2: (bit 2, 0=DI/1=EI) |
| 823 | * 238 1 Junk created when saving I via LD A,I/PUSH AF |
| 807 | 824 | * 239 1 I |
| 808 | 825 | * 240 2 SP |
| 809 | | * 242 14 0 (reserved for future use) |
| 826 | * 242 14 0x00 (reserved for future use) |
| 810 | 827 | * 256 49152 RAM dump |
| 811 | 828 | * |
| 812 | | * R,AF and PC are stored on the stack. Due to a bug in the |
| 813 | | * BIOS, the snapshots created with the +D have the AF' register |
| 829 | * IFF1/2, R, AF and PC are stored on the stack. Due to a bug in the |
| 830 | * BIOS, the snapshots created with the DISCiPLE have the AF' register |
| 814 | 831 | * replaced with the AF register. |
| 815 | 832 | * |
| 816 | 833 | * It's unknown (but likely possible) that the snapshots could |
| r7460 | r7461 | |
| 864 | 881 | |
| 865 | 882 | LOAD_REG(cpu, Z80_IM, (data == 0x00 || data == 0x3f) ? 1 : 2); |
| 866 | 883 | |
| 867 | | data = snapdata[PRG_OFFSET + 238]; |
| 868 | | LOAD_REG(cpu, Z80_IFF1, BIT(data, 2)); |
| 869 | | LOAD_REG(cpu, Z80_IFF2, BIT(data, 2)); |
| 870 | | |
| 871 | | intr = BIT(data, 2) ? CLEAR_LINE : ASSERT_LINE; |
| 872 | | cputag_set_input_line(machine, "maincpu", INPUT_LINE_IRQ0, intr); |
| 873 | | cputag_set_input_line(machine, "maincpu", INPUT_LINE_HALT, CLEAR_LINE); |
| 874 | | |
| 875 | 884 | /* Memory dump */ |
| 876 | 885 | logerror("Loading %04X bytes of RAM at %04X\n", 3*SPECTRUM_BANK, BASE_RAM); |
| 877 | 886 | for (i = 0; i < 3*SPECTRUM_BANK; i++) |
| 878 | 887 | memory_write_byte(space, BASE_RAM + i, snapdata[PRG_HDR + i]); |
| 879 | 888 | |
| 880 | 889 | addr = (snapdata[PRG_OFFSET + 241] << 8) | snapdata[PRG_OFFSET + 240]; |
| 881 | | if (addr < BASE_RAM) |
| 882 | | logerror("Corrupted SP points to ROM at:%04X", addr); |
| 890 | if (addr < BASE_RAM || addr > 4*SPECTRUM_BANK - 6) |
| 891 | logerror("Corrupted SP out of range:%04X", addr); |
| 883 | 892 | else |
| 884 | | logerror("Fetching registers R, AF and PC from the stack at SP:%04X\n", addr); |
| 893 | logerror("Fetching registers IFF1/2, R, AF and PC from the stack at SP:%04X\n", addr); |
| 885 | 894 | |
| 886 | | data = memory_read_byte(space, addr + 0); // Junk created when pushing R on the stack via LD A,R/PUSH AF |
| 895 | data = memory_read_byte(space, addr + 0); // IFF1/2: (bit 2, 0=DI/1=EI) |
| 896 | LOAD_REG(cpu, Z80_IFF1, BIT(data, 2)); |
| 897 | LOAD_REG(cpu, Z80_IFF2, BIT(data, 2)); |
| 887 | 898 | |
| 899 | intr = BIT(data, 2) ? CLEAR_LINE : ASSERT_LINE; |
| 900 | cputag_set_input_line(machine, "maincpu", INPUT_LINE_IRQ0, intr); |
| 901 | cputag_set_input_line(machine, "maincpu", INPUT_LINE_HALT, CLEAR_LINE); |
| 902 | |
| 888 | 903 | data = memory_read_byte(space, addr + 1); |
| 889 | 904 | LOAD_REG(cpu, Z80_R, data); |
| 890 | 905 | |
| r7460 | r7461 | |
| 894 | 909 | data = (memory_read_byte(space, addr + 5) << 8) | memory_read_byte(space, addr + 4); |
| 895 | 910 | LOAD_REG(cpu, Z80_PC, data); |
| 896 | 911 | |
| 912 | #if 0 |
| 913 | memory_write_byte(space, addr + 0, 0); // It's been reported that zeroing these locations fixes the loading |
| 914 | memory_write_byte(space, addr + 1, 0); // of a few images that were snapshot at a "wrong" instant |
| 915 | memory_write_byte(space, addr + 2, 0); |
| 916 | memory_write_byte(space, addr + 3, 0); |
| 917 | memory_write_byte(space, addr + 4, 0); |
| 918 | memory_write_byte(space, addr + 5, 0); |
| 919 | #endif |
| 920 | |
| 897 | 921 | addr += 6; |
| 898 | 922 | logerror("Fixing SP:%04X\n", addr); |
| 899 | 923 | cpu_set_reg(cpu, Z80_SP, addr); |
| r7460 | r7461 | |
| 913 | 937 | |
| 914 | 938 | /******************************************************************* |
| 915 | 939 | * |
| 940 | * Load a .PLUSD file. |
| 941 | * |
| 942 | * .PLUSD files are the snapshots produced by the DISCiPLE or |
| 943 | * the +D disk interface, thus share the same internal organization |
| 944 | * of the .PRG files, with a couple of notable exceptions: |
| 945 | * |
| 946 | * 1) The filesystem metadata is missing |
| 947 | * 2) Spectrum 128 snapshots (file type 9) are allowed |
| 948 | * |
| 949 | * A commented disassembly of both BIOSes is avilable at: |
| 950 | * |
| 951 | * http://www.biehold.nl/rudy/ |
| 952 | * |
| 953 | * 48K snapshots are 49174 bytes long, 128K snapshots are 131095 |
| 954 | * bytes long. |
| 955 | * |
| 956 | * Philip Kendall's FUSE emulator at http://fuse-emulator.sourceforge.net |
| 957 | * supports this format, but no extension is officially provided. |
| 958 | * Therefore I have used .PLUSD - corrections are welcome! |
| 959 | * |
| 960 | * 48K snapshot format |
| 961 | * ------------------- |
| 962 | * |
| 963 | * Offset Size Description (all registers stored with LSB first |
| 964 | * ------- ------- ------------------------------------------------- |
| 965 | * 0 2 IY |
| 966 | * 2 2 IX |
| 967 | * 4 2 DE' |
| 968 | * 6 2 BC' |
| 969 | * 8 2 HL' |
| 970 | * 10 2 AF' |
| 971 | * 12 2 DE |
| 972 | * 14 2 BC |
| 973 | * 16 2 HL |
| 974 | * 18 1 Junk created when saving I via LD A,I/PUSH AF |
| 975 | * 19 1 I |
| 976 | * 20 2 SP |
| 977 | * 22 49152 RAM dump |
| 978 | * |
| 979 | * 128K snapshot format |
| 980 | * -------------------- |
| 981 | * |
| 982 | * Offset Size Description (all registers stored with LSB first |
| 983 | * ------- ------- ------------------------------------------------- |
| 984 | * 0 2 IY |
| 985 | * 2 2 IX |
| 986 | * 4 2 DE' |
| 987 | * 6 2 BC' |
| 988 | * 8 2 HL' |
| 989 | * 10 2 AF' |
| 990 | * 12 2 DE |
| 991 | * 14 2 BC |
| 992 | * 16 2 HL |
| 993 | * 18 1 Junk created when saving I via LD A,I/PUSH AF |
| 994 | * 19 1 I |
| 995 | * 20 2 SP |
| 996 | * 22 1 Port 0x7FFD data |
| 997 | * 23 131072 RAM dump |
| 998 | * |
| 999 | * The 8 RAM banks are stored in the order 0-7. |
| 1000 | * |
| 1001 | * IFF1/2, R, AF and PC are stored on the stack. Due to a bug in the |
| 1002 | * BIOS, the snapshots created with the DISCiPLE have the AF' register |
| 1003 | * replaced with the AF register. |
| 1004 | * |
| 1005 | * It's unknown (but likely possible) that the snapshots could |
| 1006 | * suffer from the same "top of the stack" bug as well as .SNA images. |
| 1007 | * |
| 1008 | *******************************************************************/ |
| 1009 | void spectrum_setup_plusd(running_machine *machine, UINT8 *snapdata, UINT32 snapsize) |
| 1010 | { |
| 1011 | int i, j; |
| 1012 | UINT8 intr; |
| 1013 | UINT16 addr, data; |
| 1014 | spectrum_state *state = (spectrum_state *)machine->driver_data; |
| 1015 | running_device *cpu = devtag_get_device(machine, "maincpu"); |
| 1016 | const address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); |
| 1017 | |
| 1018 | data = (snapdata[PLUSD_OFFSET + 15] << 8) | snapdata[PLUSD_OFFSET + 14]; |
| 1019 | LOAD_REG(cpu, Z80_BC, data); |
| 1020 | |
| 1021 | data = (snapdata[PLUSD_OFFSET + 13] << 8) | snapdata[PLUSD_OFFSET + 12]; |
| 1022 | LOAD_REG(cpu, Z80_DE, data); |
| 1023 | |
| 1024 | data = (snapdata[PLUSD_OFFSET + 17] << 8) | snapdata[PLUSD_OFFSET + 16]; |
| 1025 | LOAD_REG(cpu, Z80_HL, data); |
| 1026 | |
| 1027 | |
| 1028 | data = (snapdata[PLUSD_OFFSET + 11] << 8) | snapdata[PLUSD_OFFSET + 10]; |
| 1029 | LOAD_REG(cpu, Z80_AF2, data); |
| 1030 | |
| 1031 | data = (snapdata[PLUSD_OFFSET + 7] << 8) | snapdata[PLUSD_OFFSET + 6]; |
| 1032 | LOAD_REG(cpu, Z80_BC2, data); |
| 1033 | |
| 1034 | data = (snapdata[PLUSD_OFFSET + 5] << 8) | snapdata[PLUSD_OFFSET + 4]; |
| 1035 | LOAD_REG(cpu, Z80_DE2, data); |
| 1036 | |
| 1037 | data = (snapdata[PLUSD_OFFSET + 9] << 8) | snapdata[PLUSD_OFFSET + 8]; |
| 1038 | LOAD_REG(cpu, Z80_HL2, data); |
| 1039 | |
| 1040 | |
| 1041 | data = (snapdata[PLUSD_OFFSET + 3] << 8) | snapdata[PLUSD_OFFSET + 2]; |
| 1042 | LOAD_REG(cpu, Z80_IX, data); |
| 1043 | |
| 1044 | data = (snapdata[PLUSD_OFFSET + 1] << 8) | snapdata[PLUSD_OFFSET + 0]; |
| 1045 | LOAD_REG(cpu, Z80_IY, data); |
| 1046 | |
| 1047 | data = snapdata[PLUSD_OFFSET + 19]; |
| 1048 | LOAD_REG(cpu, Z80_I, data); |
| 1049 | |
| 1050 | LOAD_REG(cpu, Z80_IM, (data == 0x00 || data == 0x3f) ? 1 : 2); |
| 1051 | |
| 1052 | if (snapsize == PLUSD48_SIZE) |
| 1053 | { |
| 1054 | spectrum_page_basicrom(machine); |
| 1055 | |
| 1056 | /* Memory dump */ |
| 1057 | logerror("Loading %04X bytes of RAM at %04X\n", 3*SPECTRUM_BANK, BASE_RAM); |
| 1058 | for (i = 0; i < 3*SPECTRUM_BANK; i++) |
| 1059 | memory_write_byte(space, BASE_RAM + i, snapdata[PLUSD48_HDR + i]); |
| 1060 | } |
| 1061 | else |
| 1062 | { |
| 1063 | logerror("Loading %05X bytes of RAM at %04X\n", 8*SPECTRUM_BANK, BASE_RAM); |
| 1064 | for (i = 0; i < 8; i++) |
| 1065 | { |
| 1066 | switch (i) |
| 1067 | { |
| 1068 | case 5: addr = SPECTRUM_BANK; |
| 1069 | break; |
| 1070 | case 2: addr = 2*SPECTRUM_BANK; |
| 1071 | break; |
| 1072 | case 0: |
| 1073 | case 1: |
| 1074 | case 3: |
| 1075 | case 4: |
| 1076 | case 6: |
| 1077 | case 7: addr = 3*SPECTRUM_BANK; |
| 1078 | state->port_7ffd_data &= 0xf8; |
| 1079 | state->port_7ffd_data += i; |
| 1080 | spectrum_update_paging(machine); |
| 1081 | break; |
| 1082 | }; |
| 1083 | logerror("Loading bank %d from offset:%05X\n", i, PLUSD128_HDR + i*SPECTRUM_BANK); |
| 1084 | for (j = 0; j < SPECTRUM_BANK; j++) |
| 1085 | memory_write_byte(space, j + addr, snapdata[j + PLUSD128_HDR + i*SPECTRUM_BANK]); |
| 1086 | } |
| 1087 | state->port_7ffd_data = snapdata[PLUSD_OFFSET + 22]; |
| 1088 | logerror ("Port 7FFD:%02X\n", state->port_7ffd_data); |
| 1089 | logerror ("Paging bank:%d\n", state->port_7ffd_data & 0x07); |
| 1090 | spectrum_update_paging(machine); |
| 1091 | } |
| 1092 | |
| 1093 | addr = (snapdata[PLUSD_OFFSET + 21] << 8) | snapdata[PLUSD_OFFSET + 20]; |
| 1094 | if (addr < BASE_RAM || addr > 4*SPECTRUM_BANK - 6) |
| 1095 | logerror("Corrupted SP out of range:%04X", addr); |
| 1096 | else |
| 1097 | logerror("Fetching registers IFF1/2, R, AF and PC from the stack at SP:%04X\n", addr); |
| 1098 | |
| 1099 | data = memory_read_byte(space, addr + 0); // IFF1/2: (bit 2, 0=DI/1=EI) |
| 1100 | LOAD_REG(cpu, Z80_IFF1, BIT(data, 2)); |
| 1101 | LOAD_REG(cpu, Z80_IFF2, BIT(data, 2)); |
| 1102 | |
| 1103 | intr = BIT(data, 2) ? CLEAR_LINE : ASSERT_LINE; |
| 1104 | cputag_set_input_line(machine, "maincpu", INPUT_LINE_IRQ0, intr); |
| 1105 | cputag_set_input_line(machine, "maincpu", INPUT_LINE_HALT, CLEAR_LINE); |
| 1106 | |
| 1107 | data = memory_read_byte(space, addr + 1); |
| 1108 | LOAD_REG(cpu, Z80_R, data); |
| 1109 | |
| 1110 | data = (memory_read_byte(space, addr + 3) << 8) | memory_read_byte(space, addr + 2); |
| 1111 | LOAD_REG(cpu, Z80_AF, data); |
| 1112 | |
| 1113 | data = (memory_read_byte(space, addr + 5) << 8) | memory_read_byte(space, addr + 4); |
| 1114 | LOAD_REG(cpu, Z80_PC, data); |
| 1115 | |
| 1116 | #if 0 |
| 1117 | memory_write_byte(space, addr + 0, 0); // It's been reported that zeroing these locations fixes the loading |
| 1118 | memory_write_byte(space, addr + 1, 0); // of a few images that were snapshot at a "wrong" instant |
| 1119 | memory_write_byte(space, addr + 2, 0); |
| 1120 | memory_write_byte(space, addr + 3, 0); |
| 1121 | memory_write_byte(space, addr + 4, 0); |
| 1122 | memory_write_byte(space, addr + 5, 0); |
| 1123 | #endif |
| 1124 | |
| 1125 | addr += 6; |
| 1126 | logerror("Fixing SP:%04X\n", addr); |
| 1127 | cpu_set_reg(cpu, Z80_SP, addr); |
| 1128 | |
| 1129 | /* Set border color */ |
| 1130 | data = (memory_read_byte(space, 0x5c48) >> 3) & 0x07; // Get the current border color from BORDCR system variable. |
| 1131 | state->port_fe_data = (state->port_fe_data & 0xf8) | data; |
| 1132 | EventList_Reset(); |
| 1133 | border_set_last_color(data); |
| 1134 | border_force_redraw(); |
| 1135 | logerror("Border color:%02X\n", data); |
| 1136 | |
| 1137 | if (snapsize == PLUSD48_SIZE) |
| 1138 | logerror("Snapshot loaded.\nExecution resuming at %s\n", cpu_get_reg_string(cpu, Z80_PC)); |
| 1139 | else |
| 1140 | logerror("Snapshot loaded.\nExecution resuming at bank:%d %s\n", state->port_7ffd_data & 0x07, cpu_get_reg_string(cpu, Z80_PC)); |
| 1141 | } |
| 1142 | |
| 1143 | /******************************************************************* |
| 1144 | * |
| 916 | 1145 | * Load a .SEM file. |
| 917 | 1146 | * |
| 918 | 1147 | * .SEM files were produced by a german emulator called SpecEmu |
| r7460 | r7461 | |
| 1166 | 1395 | * ------- ------- ------------------------------------------------- |
| 1167 | 1396 | * 0 132 Last 132 bytes of ROM dump |
| 1168 | 1397 | * 132 49152 RAM dump |
| 1169 | | * 49284 132 0 (reserved for future use) |
| 1398 | * 49284 132 0x00 (reserved for future use) |
| 1170 | 1399 | * 49416 10 Various KGB settings |
| 1171 | 1400 | * 49426 1 IFF1/2: (0=DI/1=EI) |
| 1172 | 1401 | * 49427 2 Reserved (must be 0x0003) |
| 1173 | 1402 | * 49429 1 KGB ColorMode (0=BW/1=Color) |
| 1174 | | * 49430 4 0 (reserved for future use) |
| 1403 | * 49430 4 0x00 (reserved for future use) |
| 1175 | 1404 | * 49434 2 BC |
| 1176 | 1405 | * 49436 2 BC' |
| 1177 | 1406 | * 49438 2 DE |
| r7460 | r7461 | |
| 1182 | 1411 | * 49448 2 IY |
| 1183 | 1412 | * 49450 1 I |
| 1184 | 1413 | * 49451 1 R |
| 1185 | | * 49452 3 0 (reserved for future use) |
| 1414 | * 49452 3 0x00 (reserved for future use) |
| 1186 | 1415 | * 49455 1 A' |
| 1187 | | * 49456 1 0 (reserved for future use) |
| 1416 | * 49456 1 0x00 (reserved for future use) |
| 1188 | 1417 | * 49457 1 A |
| 1189 | | * 49458 1 0 (reserved for future use) |
| 1418 | * 49458 1 0x00 (reserved for future use) |
| 1190 | 1419 | * 49459 1 F' |
| 1191 | | * 49460 1 0 (reserved for future use) |
| 1420 | * 49460 1 0x00 (reserved for future use) |
| 1192 | 1421 | * 49461 1 F |
| 1193 | | * 49462 2 0 (reserved for future use) |
| 1422 | * 49462 2 0x00 (reserved for future use) |
| 1194 | 1423 | * 49464 2 PC |
| 1195 | | * 49466 2 0 (reserved for future use) |
| 1424 | * 49466 2 0x00 (reserved for future use) |
| 1196 | 1425 | * 49468 2 SP |
| 1197 | 1426 | * 49470 2 KGB Soundmode (0=Simple/1=Pitch/2=RomOnly) |
| 1198 | 1427 | * 49472 2 KGB HaltMode (0=NoHalt/1=Halt) |
| 1199 | 1428 | * 49474 2 Interrupt mode (-1=IM0/0=IM1/1=IM2) |
| 1200 | | * 49476 10 0 (reserved for future use) |
| 1429 | * 49476 10 0x00 (reserved for future use) |
| 1201 | 1430 | * |
| 1202 | 1431 | *******************************************************************/ |
| 1203 | 1432 | void spectrum_setup_zx(running_machine *machine, UINT8 *snapdata, UINT32 snapsize) |
| r7460 | r7461 | |
| 1315 | 1544 | * 0 49152 RAM dump |
| 1316 | 1545 | * 49152 2 AF |
| 1317 | 1546 | * 49154 1 Border color |
| 1318 | | * 49155 1 0 (reserved for future use) |
| 1547 | * 49155 1 0x00 (reserved for future use) |
| 1319 | 1548 | * 49156 2 BC |
| 1320 | 1549 | * 49158 2 DE |
| 1321 | 1550 | * 49160 2 HL |
| r7460 | r7461 | |
| 1323 | 1552 | * 49164 2 SP |
| 1324 | 1553 | * 49166 2 IX |
| 1325 | 1554 | * 49168 2 IY |
| 1326 | | * 49170 1 0 (reserved for IFF2 but not implemented) |
| 1555 | * 49170 1 0x00 (reserved for IFF2 but not implemented) |
| 1327 | 1556 | * 49171 1 IFF1 (0=DI/other=EI) |
| 1328 | 1557 | * 49172 1 Interrupt mode (0=IM0/1=IM1/2=IM2) |
| 1329 | 1558 | * 49173 1 R |
| r7460 | r7461 | |
| 1463 | 1692 | * 10 = IF2 Right |
| 1464 | 1693 | * 11 = Cursor/AGF/Protek |
| 1465 | 1694 | * 37 1 Specci settings: R register emulation (0=no/1=yes) |
| 1466 | | * Bit 7 - value of the EAR bit |
| 1695 | * Bit 7 - EAR bit (0=Issue 3/1=Issue 2) |
| 1467 | 1696 | * 38 1 Specci settings: Interrupt frequency (0=50 Hz/1=100 Hz) |
| 1468 | 1697 | * 39 1 Specci settings: RS232 redirection (0=RS232/1=Centronics) |
| 1469 | 1698 | * 40 1 Specci settings: Sound emulation |
| r7460 | r7461 | |
| 1548 | 1777 | if (compress == SNX_COMPRESSED) |
| 1549 | 1778 | { |
| 1550 | 1779 | fill = source[++i]; |
| 1551 | | logerror("Dest:%04X Filler:%02X\n", SPECTRUM_BANK + numbytes, fill); |
| 1780 | logerror("Dest:%04X Filler:%02X\n", BASE_RAM + numbytes, fill); |
| 1552 | 1781 | for(j = 0; j < count; j++) |
| 1553 | | memory_write_byte(space, SPECTRUM_BANK + numbytes + j, fill); |
| 1782 | memory_write_byte(space, BASE_RAM + numbytes + j, fill); |
| 1554 | 1783 | numbytes += count; |
| 1555 | 1784 | } |
| 1556 | 1785 | else |
| 1557 | 1786 | { |
| 1558 | | logerror("Dest:%04X\n", SPECTRUM_BANK + numbytes); |
| 1787 | logerror("Dest:%04X\n", BASE_RAM + numbytes); |
| 1559 | 1788 | j = 0; |
| 1560 | 1789 | while (j < count) |
| 1561 | | memory_write_byte(space, SPECTRUM_BANK + numbytes + j++, source[++i]); |
| 1790 | memory_write_byte(space, BASE_RAM + numbytes + j++, source[++i]); |
| 1562 | 1791 | numbytes += count; |
| 1563 | 1792 | } |
| 1564 | 1793 | } |
| r7460 | r7461 | |
| 1640 | 1869 | /* get pc from stack */ |
| 1641 | 1870 | addr = cpu_get_reg(cpu, Z80_SP); |
| 1642 | 1871 | |
| 1643 | | if (addr < BASE_RAM) |
| 1644 | | logerror("Corrupted SP points to ROM at:%04X", addr); |
| 1872 | if (addr < BASE_RAM || addr > 4*SPECTRUM_BANK - 2) |
| 1873 | logerror("Corrupted SP out of range:%04X", addr); |
| 1645 | 1874 | else |
| 1646 | 1875 | logerror("Fetching PC from the stack at SP:%04X\n", addr); |
| 1647 | 1876 | |
| r7460 | r7461 | |
| 1670 | 1899 | |
| 1671 | 1900 | /* TODO: Enable/disable joysticks as per snapdata[SNX_OFFSET + 36] */ |
| 1672 | 1901 | |
| 1902 | /* TODO: Enable selection of Issue 2/3 config switch as per snapdata[SNX_OFFSET + 37] */ |
| 1903 | |
| 1673 | 1904 | logerror("Snapshot loaded.\nExecution resuming at %s\n", cpu_get_reg_string(cpu, Z80_PC)); |
| 1674 | 1905 | } |
| 1675 | 1906 | |
| 1676 | | static void spectrum_z80_decompress_block(running_machine *machine,UINT8 *pSource, int Dest, int size) |
| 1907 | /******************************************************************* |
| 1908 | * |
| 1909 | * Load a .FRZ file. |
| 1910 | * |
| 1911 | * .FRZ files were produced by the czech Amiga emulator CBSpeccy |
| 1912 | * written by the CodeBusters. Kudos to Dmitriy Zhivilov and |
| 1913 | * Ian Greenway for having reverse-engineered and shared the |
| 1914 | * description of this format. |
| 1915 | * |
| 1916 | * The original specs of this format were published on a |
| 1917 | * russian electronics magazine. |
| 1918 | * |
| 1919 | * The format is always 131114 bytes long and supports only |
| 1920 | * Spectrum 128K images. |
| 1921 | * |
| 1922 | * Offset Size Description (all registers stored with MSB first) |
| 1923 | * ------- ------- ------------------------------------------------- |
| 1924 | * 0 1 0x00 (reserved for future use) |
| 1925 | * 1 1 Port 0x7FFD data |
| 1926 | * 2 2 HL' |
| 1927 | * 4 2 HL |
| 1928 | * 6 2 DE' |
| 1929 | * 8 2 DE |
| 1930 | * 10 2 BC' |
| 1931 | * 12 2 BC |
| 1932 | * 14 2 AF' |
| 1933 | * 16 2 AF |
| 1934 | * 18 7 Emulation disk registers and T-states |
| 1935 | * 25 1 R |
| 1936 | * 26 2 PC |
| 1937 | * 28 2 SP |
| 1938 | * 30 1 I |
| 1939 | * 31 1 0xFF (reserved for future use) |
| 1940 | * 32 1 0x00 (reserved for future use) |
| 1941 | * 33 1 Interrupt mode (0=IM0/1=IM1/2=IM2) |
| 1942 | * 34 3 0x00 (reserved for future use) |
| 1943 | * 37 1 IFF1: bit 2 contains IFF1 (0=DI/1=EI) |
| 1944 | * 38 2 IY |
| 1945 | * 40 2 IX |
| 1946 | * 42 131072 RAM dump |
| 1947 | * |
| 1948 | * The 8 16K banks are stored in the order 5, 2, 0, 1, 3, 4, 6, 7 |
| 1949 | * |
| 1950 | *******************************************************************/ |
| 1951 | void spectrum_setup_frz(running_machine *machine, UINT8 *snapdata, UINT32 snapsize) |
| 1677 | 1952 | { |
| 1953 | int i, j; |
| 1954 | UINT8 intr; |
| 1955 | UINT16 addr, data; |
| 1956 | spectrum_state *state = (spectrum_state *)machine->driver_data; |
| 1957 | running_device *cpu = devtag_get_device(machine, "maincpu"); |
| 1958 | const address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); |
| 1959 | |
| 1960 | if (state->port_7ffd_data == -1) |
| 1961 | { |
| 1962 | logerror("Can't load 128K .FRZ file into 48K machine\n"); |
| 1963 | return; |
| 1964 | } |
| 1965 | |
| 1966 | data = (snapdata[FRZ_OFFSET + 16] << 8) | snapdata[FRZ_OFFSET + 17]; |
| 1967 | LOAD_REG(cpu, Z80_AF, data); |
| 1968 | |
| 1969 | data = (snapdata[FRZ_OFFSET + 12] << 8) | snapdata[FRZ_OFFSET + 13]; |
| 1970 | LOAD_REG(cpu, Z80_BC, data); |
| 1971 | |
| 1972 | data = (snapdata[FRZ_OFFSET + 8] << 8) | snapdata[FRZ_OFFSET + 9]; |
| 1973 | LOAD_REG(cpu, Z80_DE, data); |
| 1974 | |
| 1975 | data = (snapdata[FRZ_OFFSET + 4] << 8) | snapdata[FRZ_OFFSET + 5]; |
| 1976 | LOAD_REG(cpu, Z80_HL, data); |
| 1977 | |
| 1978 | |
| 1979 | data = (snapdata[FRZ_OFFSET + 14] << 8) | snapdata[FRZ_OFFSET + 15]; |
| 1980 | LOAD_REG(cpu, Z80_AF2, data); |
| 1981 | |
| 1982 | data = (snapdata[FRZ_OFFSET + 10] << 8) | snapdata[FRZ_OFFSET + 11]; |
| 1983 | LOAD_REG(cpu, Z80_BC2, data); |
| 1984 | |
| 1985 | data = (snapdata[FRZ_OFFSET + 6] << 8) | snapdata[FRZ_OFFSET + 7]; |
| 1986 | LOAD_REG(cpu, Z80_DE2, data); |
| 1987 | |
| 1988 | data = (snapdata[FRZ_OFFSET + 2] << 8) | snapdata[FRZ_OFFSET + 3]; |
| 1989 | LOAD_REG(cpu, Z80_HL2, data); |
| 1990 | |
| 1991 | |
| 1992 | data = (snapdata[FRZ_OFFSET + 40] << 8) | snapdata[FRZ_OFFSET + 41]; |
| 1993 | LOAD_REG(cpu, Z80_IX, data); |
| 1994 | |
| 1995 | data = (snapdata[FRZ_OFFSET + 38] << 8) | snapdata[FRZ_OFFSET + 39]; |
| 1996 | LOAD_REG(cpu, Z80_IY, data); |
| 1997 | |
| 1998 | |
| 1999 | data = snapdata[FRZ_OFFSET + 25]; |
| 2000 | LOAD_REG(cpu, Z80_R, data); |
| 2001 | |
| 2002 | data = snapdata[FRZ_OFFSET + 30]; |
| 2003 | LOAD_REG(cpu, Z80_I, data); |
| 2004 | |
| 2005 | |
| 2006 | data = (snapdata[FRZ_OFFSET + 28] << 8) | snapdata[FRZ_OFFSET + 29]; |
| 2007 | LOAD_REG(cpu, Z80_SP, data); |
| 2008 | |
| 2009 | data = (snapdata[FRZ_OFFSET + 26] << 8) | snapdata[FRZ_OFFSET + 27]; |
| 2010 | LOAD_REG(cpu, Z80_PC, data); |
| 2011 | |
| 2012 | |
| 2013 | data = snapdata[FRZ_OFFSET + 33]; |
| 2014 | LOAD_REG(cpu, Z80_IM, data); |
| 2015 | |
| 2016 | data = snapdata[FRZ_OFFSET + 37]; |
| 2017 | LOAD_REG(cpu, Z80_IFF1, BIT(data, 2)); |
| 2018 | LOAD_REG(cpu, Z80_IFF2, BIT(data, 2)); |
| 2019 | |
| 2020 | intr = BIT(data, 2) ? CLEAR_LINE : ASSERT_LINE; |
| 2021 | cputag_set_input_line(machine, "maincpu", INPUT_LINE_IRQ0, intr); |
| 2022 | cputag_set_input_line(machine, "maincpu", INPUT_LINE_HALT, CLEAR_LINE); |
| 2023 | |
| 2024 | /* Memory dump */ |
| 2025 | addr = 0; |
| 2026 | const UINT8 banks[] = { 5, 2, 0, 1, 3, 4, 6, 7 }; |
| 2027 | logerror("Loading %05X bytes of RAM at %04X\n", 8*SPECTRUM_BANK, BASE_RAM); |
| 2028 | for (i = 0; i < 8; i++) |
| 2029 | { |
| 2030 | switch (banks[i]) |
| 2031 | { |
| 2032 | case 5: addr = SPECTRUM_BANK; |
| 2033 | break; |
| 2034 | case 2: addr = 2*SPECTRUM_BANK; |
| 2035 | break; |
| 2036 | case 0: |
| 2037 | case 1: |
| 2038 | case 3: |
| 2039 | case 4: |
| 2040 | case 6: |
| 2041 | case 7: addr = 3*SPECTRUM_BANK; |
| 2042 | state->port_7ffd_data &= 0xf8; |
| 2043 | state->port_7ffd_data += banks[i]; |
| 2044 | spectrum_update_paging(machine); |
| 2045 | break; |
| 2046 | }; |
| 2047 | logerror("Loading bank %d from offset:%05X\n", banks[i], FRZ_HDR + i*SPECTRUM_BANK); |
| 2048 | for (j = 0; j < SPECTRUM_BANK; j++) |
| 2049 | memory_write_byte(space, j + addr, snapdata[j + FRZ_HDR + i*SPECTRUM_BANK]); |
| 2050 | } |
| 2051 | state->port_7ffd_data = snapdata[FRZ_OFFSET + 1]; |
| 2052 | logerror ("Port 7FFD:%02X\n", state->port_7ffd_data); |
| 2053 | logerror ("Paging bank:%d\n", state->port_7ffd_data & 0x07); |
| 2054 | spectrum_update_paging(machine); |
| 2055 | |
| 2056 | /* Set border color */ |
| 2057 | data = (memory_read_byte(space, 0x5c48) >> 3) & 0x07; // Get the current border color from BORDCR system variable. |
| 2058 | state->port_fe_data = (state->port_fe_data & 0xf8) | data; |
| 2059 | EventList_Reset(); |
| 2060 | border_set_last_color(data); |
| 2061 | border_force_redraw(); |
| 2062 | logerror("Border color:%02X\n", data); |
| 2063 | |
| 2064 | logerror("Snapshot loaded.\nExecution resuming at bank:%d %s\n", state->port_7ffd_data & 0x07, cpu_get_reg_string(cpu, Z80_PC)); |
| 2065 | } |
| 2066 | |
| 2067 | static void spectrum_z80_decompress_block(running_machine *machine,UINT8 *source, UINT16 dest, UINT16 size) |
| 2068 | { |
| 1678 | 2069 | UINT8 ch; |
| 1679 | 2070 | int i; |
| 1680 | 2071 | const address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); |
| r7460 | r7461 | |
| 1682 | 2073 | do |
| 1683 | 2074 | { |
| 1684 | 2075 | /* get byte */ |
| 1685 | | ch = pSource[0]; |
| 2076 | ch = source[0]; |
| 1686 | 2077 | |
| 1687 | | /* either start 0f 0x0ed, 0x0ed, xx yy or |
| 1688 | | * single 0x0ed */ |
| 1689 | | if (ch == (UINT8) 0x0ed) |
| 2078 | /* either start 0f 0x0ed, 0x0ed, xx yy or single 0x0ed */ |
| 2079 | if (ch == 0x0ed) |
| 1690 | 2080 | { |
| 1691 | | if (pSource[1] == (UINT8) 0x0ed) |
| 2081 | if (source[1] == 0x0ed) |
| 1692 | 2082 | { |
| 2083 | /* 0x0ed, 0x0ed, xx yy - repetition */ |
| 2084 | UINT8 count; |
| 2085 | UINT8 data; |
| 1693 | 2086 | |
| 1694 | | /* 0x0ed, 0x0ed, xx yy */ |
| 1695 | | /* repetition */ |
| 2087 | count = source[2]; |
| 1696 | 2088 | |
| 1697 | | int count; |
| 1698 | | int data; |
| 1699 | | |
| 1700 | | count = (pSource[2] & 0x0ff); |
| 1701 | | |
| 1702 | 2089 | if (count == 0) |
| 1703 | 2090 | return; |
| 1704 | 2091 | |
| 1705 | | data = (pSource[3] & 0x0ff); |
| 2092 | data = source[3]; |
| 1706 | 2093 | |
| 1707 | | pSource += 4; |
| 2094 | source += 4; |
| 1708 | 2095 | |
| 1709 | 2096 | if (count > size) |
| 1710 | 2097 | count = size; |
| r7460 | r7461 | |
| 1713 | 2100 | |
| 1714 | 2101 | for (i = 0; i < count; i++) |
| 1715 | 2102 | { |
| 1716 | | memory_write_byte(space,Dest, data); |
| 1717 | | Dest++; |
| 2103 | memory_write_byte(space, dest, data); |
| 2104 | dest++; |
| 1718 | 2105 | } |
| 1719 | 2106 | } |
| 1720 | 2107 | else |
| 1721 | 2108 | { |
| 1722 | 2109 | /* single 0x0ed */ |
| 1723 | | memory_write_byte(space,Dest, ch); |
| 1724 | | Dest++; |
| 1725 | | pSource++; |
| 2110 | memory_write_byte(space, dest, ch); |
| 2111 | dest++; |
| 2112 | source++; |
| 1726 | 2113 | size--; |
| 1727 | | |
| 1728 | 2114 | } |
| 1729 | 2115 | } |
| 1730 | 2116 | else |
| 1731 | 2117 | { |
| 1732 | 2118 | /* not 0x0ed */ |
| 1733 | | memory_write_byte(space,Dest, ch); |
| 1734 | | Dest++; |
| 1735 | | pSource++; |
| 2119 | memory_write_byte(space, dest, ch); |
| 2120 | dest++; |
| 2121 | source++; |
| 1736 | 2122 | size--; |
| 1737 | 2123 | } |
| 1738 | | |
| 1739 | 2124 | } |
| 1740 | 2125 | while (size > 0); |
| 1741 | 2126 | } |
| r7460 | r7461 | |
| 1933 | 2318 | { |
| 1934 | 2319 | logerror("Not compressed\n"); /* not compressed */ |
| 1935 | 2320 | for (i = 0; i < 49152; i++) |
| 1936 | | memory_write_byte(space,i + 16384, snapdata[30 + i]); |
| 2321 | memory_write_byte(space, i + 16384, snapdata[30 + i]); |
| 1937 | 2322 | } |
| 1938 | 2323 | else |
| 1939 | 2324 | { |
| r7460 | r7461 | |
| 2014 | 2399 | |
| 2015 | 2400 | /* not compressed */ |
| 2016 | 2401 | for (i = 0; i < 16384; i++) |
| 2017 | | memory_write_byte(space,i + Dest, pSource[i]); |
| 2402 | memory_write_byte(space, i + Dest, pSource[i]); |
| 2018 | 2403 | } |
| 2019 | 2404 | else |
| 2020 | 2405 | { |
| r7460 | r7461 | |
| 2070 | 2455 | return INIT_FAIL; |
| 2071 | 2456 | |
| 2072 | 2457 | for (i = 0; i < quick_length; i++) |
| 2073 | | memory_write_byte(space,i + quick_addr, quick_data[i]); |
| 2458 | memory_write_byte(space, i + quick_addr, quick_data[i]); |
| 2074 | 2459 | |
| 2075 | 2460 | logerror("quick loading at %.4x size:%.4x\n", quick_addr, quick_length); |
| 2076 | 2461 | return INIT_PASS; |