Beispiel #1
0
        private void save_SPCR(Stream stream, ZXST_Header header)
        {
            StreamHelper.Write(stream, Encoding.ASCII.GetBytes("SPCR"));
            int size = 8;

            StreamHelper.Write(stream, size);

            var ula    = _spec.BusManager.FindDevice <IUlaDevice>();
            var memory = _spec.BusManager.FindDevice <IMemoryDevice>();

            byte cmr0 = memory.CMR0;
            byte cmr1 = memory.CMR1;

            switch (header.MachineId)
            {
            case SzxModelId.ZXSTMID_16K:
            case SzxModelId.ZXSTMID_48K:
                cmr0 = 0x30;
                cmr1 = 0x00;
                break;
            }
            StreamHelper.Write(stream, (byte)(ula.PortFE & 7));                     // chBorder
            StreamHelper.Write(stream, (byte)(cmr0));                               // ch7ffd
            StreamHelper.Write(stream, (byte)(cmr1));                               // ch1ffd  TODO: port 1ffd/effd
            StreamHelper.Write(stream, (byte)(ula.PortFE & 0xF8));                  // chFe
            StreamHelper.Write(stream, new byte[4]);                                // chReserved[4]
        }
Beispiel #2
0
        /// <summary>
        /// ZXSTSPECREGS - The Spectrum's ULA state specifying the current border colour, memory paging status etc.
        /// </summary>
        #endregion
        private void apply_SPCR(byte[] data, ZXST_Header header)
        {
            int  offset   = 0;
            byte chBorder = data[offset]; offset += 1;
            byte ch7ffd   = data[offset]; offset += 1;
            byte ch1ffd   = data[offset]; offset += 1;             // #1ffd/#effd
            byte chFe     = data[offset]; offset += 1;             // Only bits 3 and 4 (the MIC and EAR bits) are guaranteed to be valid.
            //byte[] chReserved = new byte[4];
            //for (int i = 0; i < 4; i++)
            //    chReserved[i] = data[i + offset];

            byte pFE = (byte)((chFe & 0xF8) | (chBorder & 7));

            var ula    = _spec.BusManager.FindDevice <IUlaDevice>();
            var memory = _spec.BusManager.FindDevice <IMemoryDevice>();

            ula.PortFE = pFE;
            switch (header.MachineId)
            {
            case SzxModelId.ZXSTMID_16K:
            case SzxModelId.ZXSTMID_48K:
                memory.CMR0 = 0x30;
                memory.CMR1 = 0;
                break;

            default:
                memory.CMR0 = ch7ffd;
                memory.CMR1 = ch1ffd;
                break;
            }
        }
Beispiel #3
0
        private void saveToStream(Stream stream)
        {
            var header = new ZXST_Header();

            // very ugly, because there is no option for custom configuration machine
            var memory = _spec.BusManager.FindDevice <IMemoryDevice>();

            header.MachineId = GetModelId(_spec.BusManager.ModelId);
            if (header.MachineId == SzxModelId.ZXSTMID_CUSTOM)
            {
                if (memory.RamPages.Length == 8)
                {
                    header.MachineId = SzxModelId.ZXSTMID_PENTAGON128;
                }
                else if (memory.IsMap48)
                {
                    header.MachineId = SzxModelId.ZXSTMID_48K;
                }
            }

            var ula = _spec.BusManager.FindDevice <IUlaDevice>();

            if (ula.IsEarlyTimings)
            {
                header.Flags = (byte)(header.Flags & ~ZXSTMF_ALTERNATETIMINGS);
            }
            header.Serialize(stream);

            save_CRTR(stream);
            save_Z80R(stream);
            save_SPCR(stream, header);
            switch (header.MachineId)
            {
            case SzxModelId.ZXSTMID_16K:
                save_RAMP(stream, 5, memory.RamPages[memory.Map48[1]]);
                break;

            case SzxModelId.ZXSTMID_48K:
                save_RAMP(stream, 5, memory.RamPages[memory.Map48[1]]);
                save_RAMP(stream, 2, memory.RamPages[memory.Map48[2]]);
                save_RAMP(stream, 0, memory.RamPages[memory.Map48[3]]);
                break;

            default:
                for (int i = 0; i < memory.RamPages.Length; i++)
                {
                    save_RAMP(stream, (byte)i, memory.RamPages[i]);
                }
                break;
            }
            save_AY(stream);
            save_B128(stream);
        }
Beispiel #4
0
        public bool LoadSZX(Stream fs)
        {
            for (int f = 0; f < 16; f++)
            {
                RAM_BANK[f] = new byte[8192];
            }

            using (BinaryReader r = new BinaryReader(fs)) {
                int bytesToRead = (int)fs.Length;

                byte[] buffer    = new byte[bytesToRead];
                int    bytesRead = r.Read(buffer, 0, bytesToRead);

                if (bytesRead == 0)
                {
                    return(false); //something bad happened!
                }
                GCHandle pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);

                //Read in the szx header to begin proceedings
                header = (ZXST_Header)Marshal.PtrToStructure(pinnedBuffer.AddrOfPinnedObject(),
                                                             typeof(ZXST_Header));

                if (header.MajorVersion != 1)
                {
                    pinnedBuffer.Free();
                    return(false);
                }

                string formatName    = GetID(header.Magic);
                int    bufferCounter = Marshal.SizeOf(header);

                while (bufferCounter < bytesRead)
                {
                    //Read the block info
                    ZXST_Block block = (ZXST_Block)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter),
                                                                          typeof(ZXST_Block));

                    bufferCounter += Marshal.SizeOf(block);
                    string blockID = GetID(block.Id);
                    switch (blockID)
                    {
                    case "SPCR":
                        //Read the ZXST_SpecRegs structure
                        specRegs = (ZXST_SpecRegs)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter),
                                                                         typeof(ZXST_SpecRegs));
                        break;

                    case "Z80R":
                        //Read the ZXST_SpecRegs structure
                        z80Regs = (ZXST_Z80Regs)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter),
                                                                       typeof(ZXST_Z80Regs));
                        break;

                    case "KEYB":
                        //Read the ZXST_SpecRegs structure
                        keyboard = (ZXST_Keyboard)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter),
                                                                         typeof(ZXST_Keyboard));
                        break;

                    case "AY\0\0":
                        ayState = (ZXST_AYState)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter),
                                                                       typeof(ZXST_AYState));
                        break;

                    case "+3\0\0":
                        plus3Disk = (ZXST_Plus3Disk)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter),
                                                                           typeof(ZXST_Plus3Disk));

                        numDrivesPresent = plus3Disk.numDrives;
                        plus3DiskFile    = new ZXST_DiskFile[plus3Disk.numDrives];
                        externalDisk     = new String[plus3Disk.numDrives];
                        InsertDisk       = new bool[plus3Disk.numDrives];
                        break;

                    case "DSK\0":
                        ZXST_DiskFile df = (ZXST_DiskFile)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter),
                                                                                 typeof(ZXST_DiskFile));

                        plus3DiskFile[df.driveNum] = df;
                        InsertDisk[df.driveNum]    = true;

                        int    offset2 = bufferCounter + Marshal.SizeOf(df);
                        char[] file    = new char[df.uncompressedSize];
                        Array.Copy(buffer, offset2, file, 0, df.uncompressedSize);     //leave out the \0 terminator
                        externalDisk[df.driveNum] = new String(file);
                        break;

                    case "TAPE":
                        tape = (ZXST_Tape)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter),
                                                                 typeof(ZXST_Tape));
                        InsertTape = true;

                        //Embedded tape file
                        if ((tape.flags & 1) != 0)
                        {
                            int offset = bufferCounter + Marshal.SizeOf(tape);
                            //Compressed?
                            if ((tape.flags & 2) != 0)
                            {
                                MemoryStream compressedData   = new MemoryStream(buffer, offset, tape.compressedSize);
                                MemoryStream uncompressedData = new MemoryStream();
                                using (ZInputStream zipStream = new ZInputStream(compressedData)) {
                                    byte[] tempBuffer    = new byte[2048];
                                    int    bytesUnzipped = 0;
                                    while ((bytesUnzipped = zipStream.read(tempBuffer, 0, 2048)) > 0)
                                    {
                                        uncompressedData.Write(tempBuffer, 0, bytesUnzipped);
                                    }
                                    embeddedTapeData = uncompressedData.ToArray();
                                    compressedData.Close();
                                    uncompressedData.Close();
                                }
                            }
                            else
                            {
                                embeddedTapeData = new byte[tape.compressedSize];
                                Array.Copy(buffer, offset, embeddedTapeData, 0, tape.compressedSize);
                            }
                        }
                        else       //external tape file
                        {
                            int    offset = bufferCounter + Marshal.SizeOf(tape);
                            char[] file2  = new char[tape.compressedSize - 1];
                            Array.Copy(buffer, offset, file2, 0, tape.compressedSize - 1);     //leave out the \0 terminator
                            externalTapeFile = new String(file2);
                        }
                        break;

                    case "RAMP":
                        //Read the ZXST_SpecRegs structure
                        ZXST_RAMPage ramPages = (ZXST_RAMPage)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter),
                                                                                     typeof(ZXST_RAMPage));
                        if (ramPages.wFlags == ZXSTRF_COMPRESSED)
                        {
                            int          offset           = bufferCounter + Marshal.SizeOf(ramPages);
                            int          compressedSize   = ((int)block.Size - (Marshal.SizeOf(ramPages)));//  - Marshal.SizeOf(block) - 1 ));
                            MemoryStream compressedData   = new MemoryStream(buffer, offset, compressedSize);
                            MemoryStream uncompressedData = new MemoryStream();
                            using (ZInputStream zipStream = new ZInputStream(compressedData)) {
                                byte[] tempBuffer    = new byte[2048];
                                int    bytesUnzipped = 0;
                                while ((bytesUnzipped = zipStream.read(tempBuffer, 0, 2048)) > 0)
                                {
                                    uncompressedData.Write(tempBuffer, 0, bytesUnzipped);
                                }
                                byte[] pageData = uncompressedData.ToArray();
                                {
                                    Array.Copy(pageData, 0, RAM_BANK[ramPages.chPageNo * 2], 0, 8192);
                                    Array.Copy(pageData, 0 + 8192, RAM_BANK[ramPages.chPageNo * 2 + 1], 0, 8192);
                                }
                                compressedData.Close();
                                uncompressedData.Close();
                            }
                        }
                        else
                        {
                            int bufferOffset = bufferCounter + Marshal.SizeOf(ramPages);
                            {
                                Array.Copy(buffer, bufferOffset, RAM_BANK[ramPages.chPageNo * 2], 0, 8192);
                                Array.Copy(buffer, bufferOffset + 8192, RAM_BANK[ramPages.chPageNo * 2 + 1], 0, 8192);
                            }
                        }
                        break;

                    case "PLTT":
                        palette = (ZXST_PaletteBlock)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter),
                                                                            typeof(ZXST_PaletteBlock));

                        paletteLoaded = true;
                        break;

                    default:     //unrecognised block, so skip to next
                        break;
                    }

                    bufferCounter += (int)block.Size; //Move to next block
                }
                pinnedBuffer.Free();
                return(true);
            }
        }
Beispiel #5
0
        private void save_SPCR(Stream stream, ZXST_Header header)
        {
            StreamHelper.Write(stream, Encoding.ASCII.GetBytes("SPCR"));
            int size = 8;
            StreamHelper.Write(stream, size);

            var ula = _spec.BusManager.FindDevice<IUlaDevice>();
            var memory = _spec.BusManager.FindDevice<IMemoryDevice>();

            byte cmr0 = memory.CMR0;
            byte cmr1 = memory.CMR1;
            switch (header.MachineId)
            {
                case MachineId.ZXSTMID_16K:
                case MachineId.ZXSTMID_48K:
                    cmr0 = 0x30;
                    cmr1 = 0x00;
                    break;
            }
            StreamHelper.Write(stream, (byte)(ula.PortFE&7));				// chBorder
            StreamHelper.Write(stream, (byte)(cmr0));			            // ch7ffd
            StreamHelper.Write(stream, (byte)(cmr1));				        // ch1ffd  TODO: port 1ffd/effd
            StreamHelper.Write(stream, (byte)(ula.PortFE & 0xF8));			// chFe
            StreamHelper.Write(stream, new byte[4]);						// chReserved[4]
        }
Beispiel #6
0
        private void saveToStream(Stream stream)
        {
            var header = new ZXST_Header();

            // very ugly, because there is no option for custom configuration machine
            var memory = _spec.BusManager.FindDevice<IMemoryDevice>();
            header.MachineId = MachineId.ZXSTMID_128K;
            if (memory is ZXMAK2.Hardware.Spectrum.MemoryPlus3)
            {
                header.MachineId = MachineId.ZXSTMID_PLUS3;
            }
            else if (memory.RamPages.Length != 8)
            {
                header.MachineId = MachineId.ZXSTMID_PENTAGON1024;
                if (memory is ZXMAK2.Hardware.Pentagon.MemoryPentagon512)
                    header.MachineId = MachineId.ZXSTMID_PENTAGON512;
                else if (memory is ZXMAK2.Hardware.Pentagon.MemoryPentagon1024)
                    header.MachineId = MachineId.ZXSTMID_PENTAGON1024;
                else if (memory is ZXMAK2.Hardware.Scorpion.MemoryScorpion1024)
                    header.MachineId = MachineId.ZXSTMID_PENTAGON1024;
                else if (memory is ZXMAK2.Hardware.Scorpion.MemoryScorpion256)
                    header.MachineId = MachineId.ZXSTMID_SCORPION;
            }
            else if (memory.IsMap48)
            {
                header.MachineId = MachineId.ZXSTMID_48K;
            }
            var ula = _spec.BusManager.FindDevice<IUlaDevice>();
            if (ula.GetType() == typeof(ZXMAK2.Hardware.Spectrum.UlaSpectrum48_Early) ||
                ula.GetType() == typeof(ZXMAK2.Hardware.Spectrum.UlaSpectrum128_Early))
            {
                header.Flags = (byte)(header.Flags & ~ZXSTMF_ALTERNATETIMINGS);
            }
            header.Serialize(stream);

            save_CRTR(stream);
            save_Z80R(stream);
            save_SPCR(stream, header);
            switch (header.MachineId)
            {
                case MachineId.ZXSTMID_16K:
                    save_RAMP(stream, 5, memory.RamPages[memory.Map48[1]]);
                    break;
                case MachineId.ZXSTMID_48K:
                    save_RAMP(stream, 5, memory.RamPages[memory.Map48[1]]);
                    save_RAMP(stream, 2, memory.RamPages[memory.Map48[2]]);
                    save_RAMP(stream, 0, memory.RamPages[memory.Map48[3]]);
                    break;
                default:
                    for (int i = 0; i < memory.RamPages.Length; i++)
                        save_RAMP(stream, (byte)i, memory.RamPages[i]);
                    break;
            }
            save_AY(stream);
            save_B128(stream);
        }
Beispiel #7
0
        private void loadFromStream(Stream stream)
        {
            ZXST_Header header = new ZXST_Header();
            header.Deserialize(stream);

            if (header.MajorVersion != 1)
                throw new NotSupportedException(string.Format("Sorry, but MajorVersion={0} is not supported", header.MajorVersion));

            //int num = 0;

            InitStd128K();
            bool eof = false;
            do
            {
                byte[] data = new byte[8];
                eof |= stream.Read(data, 0, data.Length) != data.Length;

                UInt32 id = BitConverter.ToUInt32(data, 0);
                UInt32 size = BitConverter.ToUInt32(data, 4);
                data = new byte[size];
                eof |= stream.Read(data, 0, data.Length) != data.Length;

                if (!eof)
                {
                    string strId = Encoding.ASCII.GetString(BitConverter.GetBytes(id));
                    //using (FileStream fs = new FileStream((num++).ToString("D2")+"_" + strId.Replace('\0', '_') + ".block", FileMode.Create, FileAccess.Write, FileShare.Read))
                    //    fs.Write(data, 0, data.Length);

                    switch (strId)
                    {
                        case "Z80R":
                            apply_Z80R(data);
                            break;
                        case "SPCR":
                            apply_SPCR(data, header);
                            break;
                        case "AY\0\0":
                            apply_AY(data);
                            break;
                        case "RAMP":
                            apply_RAMP(data);
                            break;
                        case "B128":
                            applyB128(data);
                            break;
                        //case "KEYB":
                        //    break;
                        default:
                            //LogAgent.Info("SzxSerializer: skip block '{0}' (unsupported)", strId);
                            break;
                    }
                }
            }
            while (!eof);
        }
Beispiel #8
0
        private void apply_SPCR(byte[] data, ZXST_Header header)
        {
            int offset = 0;
            byte chBorder = data[offset]; offset += 1;
            byte ch7ffd = data[offset]; offset += 1;
            byte ch1ffd = data[offset]; offset += 1;		   // #1ffd/#effd
            byte chFe = data[offset]; offset += 1;			   // Only bits 3 and 4 (the MIC and EAR bits) are guaranteed to be valid.
            //byte[] chReserved = new byte[4];
            //for (int i = 0; i < 4; i++)
            //    chReserved[i] = data[i + offset];

            byte pFE = (byte)((chFe & 0xF8) | (chBorder & 7));

            var ula = _spec.BusManager.FindDevice<IUlaDevice>();
            var memory = _spec.BusManager.FindDevice<IMemoryDevice>();
            ula.PortFE = pFE;
            switch(header.MachineId)
            {
                case MachineId.ZXSTMID_16K:
                case MachineId.ZXSTMID_48K:
                    memory.CMR0 = 0x30;
                    memory.CMR1 = 0;
                    break;
                default:
                    memory.CMR0 =   ch7ffd;
                    memory.CMR1 = ch1ffd;
                    break;
            }
        }
Beispiel #9
0
        private void loadFromStream(Stream stream)
        {
            ZXST_Header header = new ZXST_Header();

            header.Deserialize(stream);

            if (header.MajorVersion != 1)
            {
                throw new NotSupportedException(string.Format("Sorry, but MajorVersion={0} is not supported", header.MajorVersion));
            }

            //int num = 0;

            InitStd128K();
            bool eof = false;

            do
            {
                byte[] data = new byte[8];
                eof |= stream.Read(data, 0, data.Length) != data.Length;

                UInt32 id   = BitConverter.ToUInt32(data, 0);
                UInt32 size = BitConverter.ToUInt32(data, 4);
                data = new byte[size];
                eof |= stream.Read(data, 0, data.Length) != data.Length;

                if (!eof)
                {
                    string strId = Encoding.ASCII.GetString(BitConverter.GetBytes(id));
                    //using (FileStream fs = new FileStream((num++).ToString("D2")+"_" + strId.Replace('\0', '_') + ".block", FileMode.Create, FileAccess.Write, FileShare.Read))
                    //    fs.Write(data, 0, data.Length);

                    switch (strId)
                    {
                    case "Z80R":
                        apply_Z80R(data);
                        break;

                    case "SPCR":
                        apply_SPCR(data, header);
                        break;

                    case "AY\0\0":
                        apply_AY(data);
                        break;

                    case "RAMP":
                        apply_RAMP(data);
                        break;

                    case "B128":
                        applyB128(data);
                        break;

                    //case "KEYB":
                    //    break;
                    default:
                        //LogAgent.Info("SzxSerializer: skip block '{0}' (unsupported)", strId);
                        break;
                    }
                }
            }while (!eof);
        }