Previous 15994 Revisions Next

r7461 Wednesday 24th February, 2010 at 23:24:19 UTC by Stefano Priore
[SPECTRUM] Added support for .PLUSD and .FRZ snapshots. Fixed remaining issues with .PRG snaps.
[docs]messnew.txt
[src/mess/drivers]spectrum.c
[src/mess/formats]spec_snqk.c spec_snqk.h

src/mess/formats/spec_snqk.c
r7460r7461
66
77    - Implement the following snapshot formats
88      .89C (Tezxas)
9      .FRZ (CBSpeccy)
10      .PLUSD (DISCiPLE/+D)
119      .SLT (Various emulators)
1210      .SZX (Spectaculator)
1311      .ZLS (ZX-Live!)
r7460r7461
129127        }
130128        spectrum_setup_prg(image->machine, snapshot_data, snapshot_size);
131129    }
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    }
132139    else if (!mame_stricmp(file_type, "sem"))
133140    {
134141        if (snapshot_data[0] != 0x05 && snapshot_data[1] != 'S' && \
r7460r7461
175182        if (snapshot_data[0] != 'X' && snapshot_data[1] != 'S' && \
176183            snapshot_data[2] != 'N' && snapshot_data[3] != 'A')
177184        {
178          logerror("Invalid .SEM file size.\n");
185          logerror("Invalid .SNX file size.\n");
179186          goto error;
180187        }
181188        spectrum_setup_snx(image->machine, snapshot_data, snapshot_size);
182189    }
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    }
183199    else
184200    {
185201        spectrum_setup_z80(image->machine, snapshot_data, snapshot_size);
r7460r7461
235251 *      21      27          1       I
236252 *      22      28          2       SP
237253 *      24      30          2       PC
238 *      26      32          2       0 (reserved for future use)
254 *      26      32          2       0x00 (reserved for future use)
239255 *      28      34          1       Border color
240 *      29      35          1       0 (reserved for future use)
256 *      29      35          1       0x00 (reserved for future use)
241257 *      30      36          2       Status word
242258 *      32      38          16384/  RAM dump
243259 *                          49152
r7460r7461
380396 *      Load a .SNA file.
381397 *
382398 *      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
384400 *      Microdriver, a Microdrive backup accessory.
385401 *
386402 *      http://www.worldofspectrum.org/infoseekid.cgi?id=1000266
r7460r7461
393409 *      It's been reported that snapshots saved at critical moments would
394410 *      subsequently crash on restore due to the fact that the stack was full
395411 *      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.
397413 *
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
399415 *      been written but commented out.
400416 *
401417 *      Later, the format has been extended to store the whole Spectrum 128 status.
r7460r7461
448464 *      16411   16384   RAM bank 2 (0x8000-0xbfff)
449465 *      32795   16384   RAM bank n (0xc000-0xffff - currently paged bank)
450466 *      49179   2       PC
451 *      49181   1       Port 7FFD data
467 *      49181   1       Port 0x7FFD data
452468 *      49182   1       TR-DOS rom paged (0=no/1=yes)
453469 *      49183   81920/  Remaining RAM banks in ascending order
454470 *              98304
r7460r7461
540556    {
541557        /* 128K Snapshot */
542558        state->port_7ffd_data = snapdata[SNA128_OFFSET + 2];
559        logerror ("Port 7FFD:%02X\n", state->port_7ffd_data);
543560        if (snapdata[SNA128_OFFSET + 3])
544561        {
545562          /* TODO: page TR-DOS ROM when supported */
r7460r7461
557574        /* Get PC from stack */
558575        addr = cpu_get_reg(cpu, Z80_SP);
559576
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);
562579        else
563580          logerror("Fetching PC from the stack at SP:%04X\n", addr);
564581
r7460r7461
587604    else
588605    {
589606        /* Set up other RAM banks */
590        bank_offset = SNA48_SIZE + SNA128_OFFSET;
591607        for (i = 0; i < 8; i++)
592608            usedbanks[i] = 0;
593609
r7460r7461
602618        for (i = 0; i < 3*SPECTRUM_BANK; i++)
603619          memory_write_byte(space, BASE_RAM + i, snapdata[SNA48_HDR + i]);
604620
621        bank_offset = SNA48_SIZE + SNA128_HDR;
605622        for (i = 0; i < 8; i++)
606623        {
607624            if (!usedbanks[i])
r7460r7461
611628                state->port_7ffd_data += i;
612629                spectrum_update_paging(machine);
613630                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]);
615632                bank_offset += SPECTRUM_BANK;
616633            }
617634        }
r7460r7461
633650        state->port_7ffd_data = snapdata[SNA128_OFFSET + 2];
634651        spectrum_update_paging(machine);
635652
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));
637654    }
638655}
639656
r7460r7461
660677 *      24      4       H
661678 *      28      4       L
662679 *      32      4       PC
663 *      36      4       0 (reserved for future use)
680 *      36      4       0x00 (reserved for future use)
664681 *      40      4       SP
665 *      44      104     0 (reserved for future use)
682 *      44      104     0x00 (reserved for future use)
666683 *      148     4       R
667 *      152     4       0 (reserved for future use)
684 *      152     4       0x00 (reserved for future use)
668685 *      156     4       Border color
669 *      160     4       0 (reserved for future use)
686 *      160     4       0x00 (reserved for future use)
670687 *      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)
672689 *      190     1       I
673690 *      191     1       IFF1/2: (0=DI/1=EI)
674 *      192     44      0 (reserved for future use)
691 *      192     44      0x00 (reserved for future use)
675692 *      236     4       AF' *BE*
676693 *      240     4       BC' *BE*
677694 *      244     2       DE' *BE*
r7460r7461
793810 *      13      1       Track number of the first sector of the file
794811 *      14      1       Sector number of the first sector of the file
795812 *      15      195     Sector allocation bitmap
796 *      210     10      0 (reserved for future use)
813 *      210     10      0x00 (reserved for future use)
797814 *      220     2       IY
798815 *      222     2       IX
799816 *      224     2       DE'
r7460r7461
803820 *      232     2       DE
804821 *      234     2       BC
805822 *      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
807824 *      239     1       I
808825 *      240     2       SP
809 *      242     14      0 (reserved for future use)
826 *      242     14      0x00 (reserved for future use)
810827 *      256     49152   RAM dump
811828 *
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
814831 *      replaced with the AF register.
815832 *
816833 *      It's unknown (but likely possible) that the snapshots could
r7460r7461
864881
865882    LOAD_REG(cpu, Z80_IM, (data == 0x00 || data == 0x3f) ? 1 : 2);
866883
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
875884    /* Memory dump */
876885    logerror("Loading %04X bytes of RAM at %04X\n", 3*SPECTRUM_BANK, BASE_RAM);
877886    for (i = 0; i < 3*SPECTRUM_BANK; i++)
878887        memory_write_byte(space, BASE_RAM + i, snapdata[PRG_HDR + i]);
879888
880889    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);
883892    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);
885894
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));
887898
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
888903    data = memory_read_byte(space, addr + 1);
889904    LOAD_REG(cpu, Z80_R, data);
890905
r7460r7461
894909    data = (memory_read_byte(space, addr + 5) << 8) | memory_read_byte(space, addr + 4);
895910    LOAD_REG(cpu, Z80_PC, data);
896911
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
897921    addr += 6;
898922    logerror("Fixing SP:%04X\n", addr);
899923    cpu_set_reg(cpu, Z80_SP, addr);
r7460r7461
913937
914938/*******************************************************************
915939 *
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 *******************************************************************/
1009void 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 *
9161145 *      Load a .SEM file.
9171146 *
9181147 *      .SEM files were produced by a german emulator called SpecEmu
r7460r7461
11661395 *      ------- ------- -------------------------------------------------
11671396 *      0       132     Last 132 bytes of ROM dump
11681397 *      132     49152   RAM dump
1169 *      49284   132     0 (reserved for future use)
1398 *      49284   132     0x00 (reserved for future use)
11701399 *      49416   10      Various KGB settings
11711400 *      49426   1       IFF1/2: (0=DI/1=EI)
11721401 *      49427   2       Reserved (must be 0x0003)
11731402 *      49429   1       KGB ColorMode (0=BW/1=Color)
1174 *      49430   4       0 (reserved for future use)
1403 *      49430   4       0x00 (reserved for future use)
11751404 *      49434   2       BC
11761405 *      49436   2       BC'
11771406 *      49438   2       DE
r7460r7461
11821411 *      49448   2       IY
11831412 *      49450   1       I
11841413 *      49451   1       R
1185 *      49452   3       0 (reserved for future use)
1414 *      49452   3       0x00 (reserved for future use)
11861415 *      49455   1       A'
1187 *      49456   1       0 (reserved for future use)
1416 *      49456   1       0x00 (reserved for future use)
11881417 *      49457   1       A
1189 *      49458   1       0 (reserved for future use)
1418 *      49458   1       0x00 (reserved for future use)
11901419 *      49459   1       F'
1191 *      49460   1       0 (reserved for future use)
1420 *      49460   1       0x00 (reserved for future use)
11921421 *      49461   1       F
1193 *      49462   2       0 (reserved for future use)
1422 *      49462   2       0x00 (reserved for future use)
11941423 *      49464   2       PC
1195 *      49466   2       0 (reserved for future use)
1424 *      49466   2       0x00 (reserved for future use)
11961425 *      49468   2       SP
11971426 *      49470   2       KGB Soundmode (0=Simple/1=Pitch/2=RomOnly)
11981427 *      49472   2       KGB HaltMode (0=NoHalt/1=Halt)
11991428 *      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)
12011430 *
12021431 *******************************************************************/
12031432void spectrum_setup_zx(running_machine *machine, UINT8 *snapdata, UINT32 snapsize)
r7460r7461
13151544 *      0       49152   RAM dump
13161545 *      49152   2       AF
13171546 *      49154   1       Border color
1318 *      49155   1       0 (reserved for future use)
1547 *      49155   1       0x00 (reserved for future use)
13191548 *      49156   2       BC
13201549 *      49158   2       DE
13211550 *      49160   2       HL
r7460r7461
13231552 *      49164   2       SP
13241553 *      49166   2       IX
13251554 *      49168   2       IY
1326 *      49170   1       0 (reserved for IFF2 but not implemented)
1555 *      49170   1       0x00 (reserved for IFF2 but not implemented)
13271556 *      49171   1       IFF1 (0=DI/other=EI)
13281557 *      49172   1       Interrupt mode (0=IM0/1=IM1/2=IM2)
13291558 *      49173   1       R
r7460r7461
14631692 *                                            10 = IF2 Right
14641693 *                                            11 = Cursor/AGF/Protek
14651694 *      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)
14671696 *      38      1       Specci settings: Interrupt frequency (0=50 Hz/1=100 Hz)
14681697 *      39      1       Specci settings: RS232 redirection (0=RS232/1=Centronics)
14691698 *      40      1       Specci settings: Sound emulation
r7460r7461
15481777        if (compress == SNX_COMPRESSED)
15491778        {
15501779            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);
15521781            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);
15541783            numbytes += count;
15551784        }
15561785        else
15571786        {
1558            logerror("Dest:%04X\n", SPECTRUM_BANK + numbytes);
1787            logerror("Dest:%04X\n", BASE_RAM + numbytes);
15591788            j = 0;
15601789            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]);
15621791            numbytes += count;
15631792        }
15641793    }
r7460r7461
16401869    /* get pc from stack */
16411870    addr = cpu_get_reg(cpu, Z80_SP);
16421871
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);
16451874    else
16461875      logerror("Fetching PC from the stack at SP:%04X\n", addr);
16471876
r7460r7461
16701899
16711900/* TODO: Enable/disable joysticks as per snapdata[SNX_OFFSET + 36] */
16721901
1902/* TODO: Enable selection of Issue 2/3 config switch as per snapdata[SNX_OFFSET + 37] */
1903
16731904    logerror("Snapshot loaded.\nExecution resuming at %s\n", cpu_get_reg_string(cpu, Z80_PC));
16741905}
16751906
1676static 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 *******************************************************************/
1951void spectrum_setup_frz(running_machine *machine, UINT8 *snapdata, UINT32 snapsize)
16771952{
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
2067static void spectrum_z80_decompress_block(running_machine *machine,UINT8 *source, UINT16 dest, UINT16 size)
2068{
16782069    UINT8 ch;
16792070    int i;
16802071    const address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM);
r7460r7461
16822073    do
16832074    {
16842075        /* get byte */
1685        ch = pSource[0];
2076        ch = source[0];
16862077
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)
16902080        {
1691            if (pSource[1] == (UINT8) 0x0ed)
2081            if (source[1] == 0x0ed)
16922082            {
2083                /* 0x0ed, 0x0ed, xx yy - repetition */
2084                UINT8 count;
2085                UINT8 data;
16932086
1694                /* 0x0ed, 0x0ed, xx yy */
1695                /* repetition */
2087                count = source[2];
16962088
1697                int count;
1698                int data;
1699
1700                count = (pSource[2] & 0x0ff);
1701
17022089                if (count == 0)
17032090                    return;
17042091
1705                data = (pSource[3] & 0x0ff);
2092                data = source[3];
17062093
1707                pSource += 4;
2094                source += 4;
17082095
17092096                if (count > size)
17102097                    count = size;
r7460r7461
17132100
17142101                for (i = 0; i < count; i++)
17152102                {
1716                    memory_write_byte(space,Dest, data);
1717                    Dest++;
2103                    memory_write_byte(space, dest, data);
2104                    dest++;
17182105                }
17192106            }
17202107            else
17212108            {
17222109                /* single 0x0ed */
1723                memory_write_byte(space,Dest, ch);
1724                Dest++;
1725                pSource++;
2110                memory_write_byte(space, dest, ch);
2111                dest++;
2112                source++;
17262113                size--;
1727
17282114            }
17292115        }
17302116        else
17312117        {
17322118            /* not 0x0ed */
1733            memory_write_byte(space,Dest, ch);
1734            Dest++;
1735            pSource++;
2119            memory_write_byte(space, dest, ch);
2120            dest++;
2121            source++;
17362122            size--;
17372123        }
1738
17392124    }
17402125    while (size > 0);
17412126}
r7460r7461
19332318        {
19342319            logerror("Not compressed\n");   /* not compressed */
19352320            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]);
19372322        }
19382323        else
19392324        {
r7460r7461
20142399
20152400                    /* not compressed */
20162401                    for (i = 0; i < 16384; i++)
2017                        memory_write_byte(space,i + Dest, pSource[i]);
2402                        memory_write_byte(space, i + Dest, pSource[i]);
20182403                }
20192404                else
20202405                {
r7460r7461
20702455        return INIT_FAIL;
20712456
20722457    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]);
20742459
20752460    logerror("quick loading at %.4x size:%.4x\n", quick_addr, quick_length);
20762461    return INIT_PASS;
src/mess/formats/spec_snqk.h
r7460r7461
1515void spectrum_setup_sp(running_machine *machine, UINT8 *snapdata, UINT32 snapsize);
1616void spectrum_setup_ach(running_machine *machine, UINT8 *snapdata, UINT32 snapsize);
1717void spectrum_setup_prg(running_machine *machine, UINT8 *snapdata, UINT32 snapsize);
18void spectrum_setup_plusd(running_machine *machine, UINT8 *snapdata, UINT32 snapsize);
1819void spectrum_setup_sem(running_machine *machine, UINT8 *snapdata, UINT32 snapsize);
1920void spectrum_setup_sit(running_machine *machine, UINT8 *snapdata, UINT32 snapsize);
2021void spectrum_setup_zx(running_machine *machine, UINT8 *snapdata, UINT32 snapsize);
2122void spectrum_setup_snp(running_machine *machine, UINT8 *snapdata, UINT32 snapsize);
2223void spectrum_setup_snx(running_machine *machine, UINT8 *snapdata, UINT32 snapsize);
24void spectrum_setup_frz(running_machine *machine, UINT8 *snapdata, UINT32 snapsize);
2325
2426#define BASE_RAM      0x4000
2527#define SPECTRUM_BANK 0x4000
r7460r7461
6971
7072/*****************************************************************************
7173 *
74 * .PLUSD format (used by FUSE)
75 *
76 ****************************************************************************/
77#define PLUSD_OFFSET 0
78#define PLUSD48_HDR  22
79#define PLUSD48_SIZE (PLUSD48_HDR + 3*SPECTRUM_BANK)
80
81#define PLUSD128_HDR  23
82#define PLUSD128_SIZE (PLUSD128_HDR + 8*SPECTRUM_BANK)
83
84/*****************************************************************************
85 *
7286 * .SEM format (used by SpecEmu)
7387 *
7488 ****************************************************************************/
r7460r7461
115129#define SNX_COMPRESSED   0xff
116130#define SNX_UNCOMPRESSED 0x00
117131
132/*****************************************************************************
133 *
134 * .FRZ format (used by CBSpeccy, ZX-Live and ASp)
135 *
136 ****************************************************************************/
137#define FRZ_OFFSET 0
138#define FRZ_HDR    42
139#define FRZ_SIZE   (FRZ_HDR + 8*SPECTRUM_BANK)
140
118141typedef enum
119142{
120143    SPECTRUM_SNAPSHOT_NONE,
src/mess/drivers/spectrum.c
r7460r7461
564564   MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
565565
566566   /* devices */
567   MDRV_SNAPSHOT_ADD("snapshot", spectrum, "ach,prg,sem,sit,sna,snp,snx,sp,z80,zx", 0)
567   MDRV_SNAPSHOT_ADD("snapshot", spectrum, "ach,frz,plusd,prg,sem,sit,sna,snp,snx,sp,z80,zx", 0)
568568   MDRV_QUICKLOAD_ADD("quickload", spectrum, "scr", 0)
569569   MDRV_CASSETTE_ADD( "cassette", spectrum_cassette_config )
570570
docs/messnew.txt
r7460r7461
7474- [SMS] Fixed PGA Tour Golf freeze based on Flubba's & RetroRalph's
7575  research (bug #1911). [Enik Land]
7676
77- [SPECTRUM] Added support for .ach, .prg, .sem, .sit, .snp, .snx and .zx
78  snapshot formats. Hopefully fixed existing issues with .sna and .sp
79  formats (both VGASpec-style and Spanish Spectrum-style formats are
80  supported now).
77- [SPECTRUM] Added support for .ach, .frz, .plusd, .prg, .sem, .sit,
78  .snp, .snx and .zx snapshot formats. Hopefully fixed existing issues
79  with .sna and .spformats (both VGASpec-style and Spanish Spectrum-style
80  formats are supported now).
8181
8282- [TX0] Fixed disassembly in the debugger. [Robbbert]
8383
r7460r7461
108108
109109- Implemented floppy drive write protect signal toggling on floppy
110110  disk insert/eject. [Curt Coder]
111 
111
112112- Implemented 'disk double sided' (TWOSID) floppy drive signal. [Curt Coder]
113113
114114- Emulated the following Commodore floppy disk drives at hardware level:

Previous 15994 Revisions Next


© 1998-2018 The MESS Team