private static int ReadGeneralizedDataBlock(byte[] buf, int index, ref TapeBlock tb) { tb.Description = "CSW Recording"; int size = getInt32(buf, index); index += 4; int pause = getUInt16(buf, index); index += 2; int totp = getInt32(buf, index); index += 4; int npp = buf[index]; index += 1; int asp = buf[index]; index += 1; int totd = getInt32(buf, index); index += 4; int npd = buf[index]; index += 1; int asd = buf[index]; index += 1; return(size); }
public override void Deserialize(Stream stream) { byte[] array = new byte[2]; while (stream.Position < stream.Length) { stream.Read(array, 0, 2); int num = (int)BitConverter.ToUInt16(array, 0); if (num == 0) { return; } byte[] array2 = new byte[num]; stream.Read(array2, 0, num); TapeBlock tapeBlock = new TapeBlock(); tapeBlock.Description = TapSerializer.getBlockDescription(array2, 0, array2.Length); tapeBlock.Periods = TapSerializer.getBlockPeriods(array2, 0, array2.Length, 2168, 667, 735, 855, 1710, (array2[0] < 4) ? 8064 : 3220, 1000, 8); this._tape.Blocks.Add(tapeBlock); } }
private static IEnumerable <ITapeBlock> Load(Stream stream, int tactsPerSecond) { var reader = new WavStreamReader(stream); var ratio = tactsPerSecond / (double)reader.Header.FmtSampleRate; // usually 3.5mhz / 44khz var rleData = LoadRleData(reader); var list = new List <TapeBlock>(); var pulses = new List <int>(); var blockTime = 0; var blockCounter = 0; foreach (var rle in rleData) { var len = (int)Math.Round(rle * ratio, MidpointRounding.AwayFromZero); pulses.Add(len); blockTime += len; if (blockTime >= tactsPerSecond * 2) { var tb = new TapeBlock(); tb.Description = string.Format("WAV-{0:D3}", blockCounter++); tb.Periods = new List <int>(pulses); list.Add(tb); blockTime = 0; pulses.Clear(); } } if (pulses.Count > 0) { var tb = new TapeBlock(); tb.Description = string.Format("WAV-{0:D3}", blockCounter++); tb.Periods = new List <int>(pulses); list.Add(tb); } return(list); }
private static IEnumerable <ITapeBlock> Load(Stream stream) { var list = new List <TapeBlock>(); byte[] bsize = new byte[2]; while (stream.Position < stream.Length) { stream.Read(bsize, 0, 2); int size = BitConverter.ToUInt16(bsize, 0); if (size == 0) { break; } byte[] block = new byte[size]; stream.Read(block, 0, size); var tb = new TapeBlock(); tb.Description = getBlockDescription(block, 0, block.Length); tb.Periods = getBlockPeriods(block, 0, block.Length, 2168, 667, 735, 855, 1710, (block[0] < 4) ? 8064 : 3220, 1000, 8); tb.TapData = block; list.Add(tb); } return(list); }
private static IEnumerable <ITapeBlock> Load(Stream stream, int tactsPerSecond) { try { var hdr = new byte[0x34]; stream.Read(hdr, 0, 0x20); var txtInfo = string.Empty; if (Encoding.ASCII.GetString(hdr, 0, 22) != "Compressed Square Wave") { Locator.Resolve <IUserMessage>() .Error("CSW loader\n\nInvalid CSW file, identifier not found!"); return(null); } var version = hdr[0x17]; if (version > 2) { Locator.Resolve <IUserMessage>() .Error("CSW loader\n\nFormat CSW V{0}.{1} not supported!", hdr[0x17], hdr[0x18]); return(null); } if (version == 2) // CSW V2 { stream.Read(hdr, 0x20, 0x14); var binDesc = new List <byte>(); for (var i = 0; i < 16 && hdr[0x24 + i] != 0; i++) { binDesc.Add(hdr[0x24 + i]); } txtInfo = Encoding.ASCII.GetString(binDesc.ToArray()); var extHdr = new byte[hdr[0x23]]; stream.Read(extHdr, 0, extHdr.Length); } var cswSampleRate = version == 2 ? BitConverter.ToInt32(hdr, 0x19) : BitConverter.ToUInt16(hdr, 0x19); var cswCompressionType = version == 2 ? hdr[0x21] : hdr[0x1B]; // Flags b0: initial polarity; if set, the signal starts at logical high var cswFlags = version == 2 ? hdr[0x22] : hdr[0x1C]; var cswPulseCount = version == 2 ? BitConverter.ToInt32(hdr, 0x1D) : (int)stream.Length - 0x20; var rleData = LoadRleData( stream, cswCompressionType, cswPulseCount); var ratio = tactsPerSecond / (double)cswSampleRate; // usually 3.5mhz / 44khz var list = new List <TapeBlock>(); var pulses = new List <int>(); var blockTime = 0; var blockCounter = 0; foreach (var rle in rleData) { var len = (int)Math.Round(rle * ratio, MidpointRounding.AwayFromZero); pulses.Add(len); blockTime += len; if (blockTime >= tactsPerSecond * 2) { var tb = new TapeBlock(); tb.Description = string.Format("CSW-{0:D3}", blockCounter++); tb.Periods = new List <int>(pulses); list.Add(tb); blockTime = 0; pulses.Clear(); } } if (pulses.Count > 0) { var tb = new TapeBlock(); tb.Description = string.Format("CSW-{0:D3}", blockCounter++); tb.Periods = new List <int>(pulses); list.Add(tb); } if (txtInfo != string.Empty) { var desc = new TapeBlock(); desc.Periods = new List <int>(); desc.Description = string.Format("[{0}]", txtInfo); list.Insert(0, desc); } return(list); } catch (Exception ex) { Logger.Error(ex); Locator.Resolve <IUserMessage>() .Error("CSW loader\n\n{0}", ex.Message); return(null); } }
private static IEnumerable <ITapeBlock> Load(Stream stream, int frequency) { byte[] snbuf = new byte[stream.Length]; stream.Read(snbuf, 0, snbuf.Length); if (Encoding.ASCII.GetString(snbuf, 0, 7) != "ZXTape!" || snbuf[7] != 0x1A) { Locator.Resolve <IUserMessage>() .Error("TZX loader\n\nInvalid TZX file, identifier not found!"); return(null); } //int verMajor = snbuf[0x08]; //int verMinor = snbuf[0x09]; int ptr = 0; int size, pause, i, n, t, t0, j; int pl, p, last;//, *end; char *p; //int loop_n = 0, loop_p = 0; //byte[] nm = new byte[512]; //TapeBlock tb = null; //bool grouping = false; //int newOffset; List <TapeBlock> tzxBlocks = new List <TapeBlock>(); Stack <KeyValuePair <int, int> > loopStack = new Stack <KeyValuePair <int, int> >(); while (ptr < snbuf.Length) { int blockId = snbuf[ptr++]; TapeBlock tb = new TapeBlock(); tb.TzxId = blockId; switch (blockId) { #region ID 10 - Standard Speed Data Block case 0x10: // Standard Speed Data Block size = getUInt16(snbuf, ptr + 2); pause = getUInt16(snbuf, ptr); ptr += 4; tb.Description = TapSerializer.getBlockDescription(snbuf, ptr, size); tb.Periods = TapSerializer.getBlockPeriods(snbuf, ptr, size, 2168, 667, 735, 855, 1710, (snbuf[ptr] < 4) ? 8064 : 3220, pause, 8); tb.TapData = TapSerializer.getBlockTapData(snbuf, ptr, size); ptr += size; break; #endregion #region ID 11 - Turbo Speed Data Block case 0x11: // Turbo Speed Data Block size = 0xFFFFFF & getInt32(snbuf, ptr + 0x0F); tb.Description = TapSerializer.getBlockDescription(snbuf, ptr + 0x12, size); tb.Periods = TapSerializer.getBlockPeriods(snbuf, ptr + 0x12, size, getUInt16(snbuf, ptr), getUInt16(snbuf, ptr + 2), getUInt16(snbuf, ptr + 4), getUInt16(snbuf, ptr + 6), getUInt16(snbuf, ptr + 8), getUInt16(snbuf, ptr + 10), getUInt16(snbuf, ptr + 13), snbuf[ptr + 12]); //tb.TapData = TapSerializer.getBlockTapData(snbuf, ptr+0x12, size); // todo: test used bits - ptr+12 ptr += size + 0x12; break; #endregion #region ID 12 - Pure Tone case 0x12: // Pure Tone tb.Description = "Pure Tone"; pl = getUInt16(snbuf, ptr); n = getUInt16(snbuf, ptr + 2); tb.Periods = new List <int>(n); for (i = 0; i < n; i++) { tb.Periods.Add(pl); } ptr += 4; break; #endregion #region ID 13 - Pulse sequence case 0x13: // Pulse sequence tb.Description = "Pulse sequence"; n = snbuf[ptr++]; tb.Periods = new List <int>(n); for (i = 0; i < n; i++, ptr += 2) { tb.Periods.Add(getUInt16(snbuf, ptr)); } break; #endregion #region ID 14 - Pure Data Block case 0x14: // Pure Data Block tb.Description = "Pure Data Block"; size = 0xFFFFFF & getInt32(snbuf, ptr + 7); tb.Periods = TapSerializer.getBlockPeriods(snbuf, ptr + 0x0A, size, 0, 0, 0, getUInt16(snbuf, ptr), getUInt16(snbuf, ptr + 2), -1, getUInt16(snbuf, ptr + 5), snbuf[ptr + 4]); tb.TapData = TapSerializer.getBlockTapData(snbuf, ptr + 0x0A, size); ptr += size + 0x0A; break; #endregion #region ID 15 - Direct Recording case 0x15: // Direct Recording tb.Description = "Direct Recording"; size = 0xFFFFFF & getInt32(snbuf, ptr + 5); t0 = getUInt16(snbuf, ptr); pause = getUInt16(snbuf, ptr + 2); last = snbuf[ptr + 4]; ptr += 8; pl = 0; n = 0; for (i = 0; i < size; i++) // count number of pulses { for (j = 0x80; j != 0; j >>= 1) { if (((snbuf[ptr + i] ^ pl) & j) != 0) { n++; pl ^= -1; } } } t = 0; pl = 0; tb.Periods = new List <int>(n + 2); for (i = 1; i < size; i++, ptr++) // find pulses { for (j = 0x80; j != 0; j >>= 1) { t += t0; if (((snbuf[ptr] ^ pl) & j) != 0) { tb.Periods.Add(t); pl ^= -1; t = 0; } } } // find pulses - last byte for (j = 0x80; j != (byte)(0x80 >> last); j >>= 1) { t += t0; if (((snbuf[ptr] ^ pl) & j) != 0) { tb.Periods.Add(t); pl ^= -1; t = 0; } } ptr++; tb.Periods.Add(t); // last pulse ??? if (pause != 0) { tb.Periods.Add(pause * 3500); } break; #endregion //#region ID 18 //case 0x18: // tb.Description = "CSW Recording"; // break; //#endregion #region ID 19 - Generalized Data Block case 0x19: ptr += ReadGeneralizedDataBlock(snbuf, ptr, ref tb); break; #endregion #region ID 20 - Pause (silence) or 'Stop the Tape' command case 0x20: // Pause (silence) or 'Stop the Tape' command pause = getUInt16(snbuf, ptr); tb.Description = (pause != 0 ? "[Pause " + pause + " ms]" : "[Stop the Tape]"); tb.Periods = new List <int>(2); ptr += 2; if (pause == 0) // at least 1ms pulse as specified in TZX 1.13 { tb.Command = TapeCommand.STOP_THE_TAPE; tb.Periods.Add(3500); pause = -1; } else { pause *= 3500; } tb.Periods.Add(pause); break; #endregion #region ID 21 - Group start case 0x21: // Group start n = snbuf[ptr++]; tb.Description = "[GROUP: " + Encoding.ASCII.GetString(snbuf, ptr, n) + "]"; tb.Command = TapeCommand.BEGIN_GROUP; ptr += n; tb.Periods = new List <int>(); //grouping = true; break; #endregion #region ID 22 - Group end case 0x22: // Group end tb.Description = "[END GROUP]"; tb.Command = TapeCommand.END_GROUP; tb.Periods = new List <int>(); //grouping = false; break; #endregion #region ID 23 - Jump to block case 0x23: // Jump to block tb.Description = "[JUMP TO BLOCK " + getUInt16(snbuf, ptr) + "]"; // 1=next block, 2=skip 1 block, -1=prev block tb.Periods = new List <int>(); ptr += 2; break; #endregion #region ID 24 - Loop start case 0x24: // Loop start { int loop_p = tzxBlocks.Count + 1; // from next int loop_n = getUInt16(snbuf, ptr); // TODO: as Command loopStack.Push(new KeyValuePair <int, int>(loop_p, loop_n)); ptr += 2; tb.Description = string.Format("[LOOP {0}]", loop_n); tb.Periods = new List <int>(); break; } #endregion #region ID 25 - Loop end case 0x25: // Loop end { tb.Description = string.Format("[END LOOP]"); tb.Periods = new List <int>(); KeyValuePair <int, int> loopInfo = loopStack.Pop(); int loop_p = loopInfo.Key; int loop_n = loopInfo.Value; if (loop_n == 0) { break; // loop_n is repeat count, =1 for mem economy } size = tzxBlocks.Count - loop_p; for (i = 0; i < loop_n; i++) { TapeBlock repeatBlock = new TapeBlock(); repeatBlock.Description = string.Format("[LOOP REPEAT {0}]", i + 1); repeatBlock.Periods = new List <int>(); tzxBlocks.Add(repeatBlock); for (int z = 0; z < size; z++) { tzxBlocks.Add(tzxBlocks[loop_p + z]); } } break; } #endregion #region ID 26 - Call sequence case 0x26: // Call sequence tb.Description = "[CALL SEQUENCE]"; tb.Periods = new List <int>(); ptr += 2 + 2 * getUInt16(snbuf, ptr); break; #endregion #region ID 27 - Return from sequence case 0x27: // Return from sequence tb.Description = "[RETURN SEQUENCE]"; tb.Periods = new List <int>(); break; #endregion #region ID 28 - Select block case 0x28: // Select block tb.Description = "[SELECT BLOCK]"; tb.Periods = new List <int>(); ptr += 2 + getUInt16(snbuf, ptr); break; #endregion #region ID 2A - Stop tape if in 48K mode case 0x2A: // Stop tape if in 48K mode tb.Description = "[Stop tape if in 48K mode]"; tb.Command = TapeCommand.STOP_THE_TAPE_48K; tb.Periods = new List <int>(); ptr += 4 + getUInt16(snbuf, ptr); break; #endregion #region ID 30 - Text description case 0x30: // Text description n = snbuf[ptr++]; tb.Description = "[" + Encoding.ASCII.GetString(snbuf, ptr, n) + "]"; tb.Periods = new List <int>(); ptr += n; break; #endregion #region ID 31 - Message block case 0x31: // Message block ptr++; //n = snbuf[ptr++]; // msg display time n = snbuf[ptr++]; tb.Description = "[Message: " + Encoding.ASCII.GetString(snbuf, ptr, n) + "]"; tb.Command = TapeCommand.SHOW_MESSAGE; tb.Periods = new List <int>(); ptr += n; break; #endregion #region ID 32 - Archive info+ case 0x32: // Archive info { tb.Description = "Archive info"; tb.Periods = new List <int>(); p = ptr + 3; StringBuilder builderInfo = new StringBuilder(); for (i = 0; i < snbuf[ptr + 2]; i++) { string info; int infoType = snbuf[p++]; switch (infoType) { case 0: info = "Full title"; break; case 1: info = "Publisher"; break; case 2: info = "Author"; break; case 3: info = "Year"; break; case 4: info = "Language"; break; case 5: info = "Type"; break; case 6: info = "Price"; break; case 7: info = "Protection"; break; case 8: info = "Origin"; break; case 0xFF: info = "Comment"; break; default: info = "info"; break; } size = snbuf[p++]; string infoValue = Encoding.ASCII.GetString(snbuf, p, size); p += size; if (infoType == 0 || infoType == 7 || infoType == 0xFF) { if (builderInfo.Length > 0 && infoValue.Length > 0) // insert separator { builderInfo.Append("; "); } builderInfo.Append(string.Format("{0}: {1}", info, infoValue)); } } tb.Description = builderInfo.ToString(); ptr += 2 + getUInt16(snbuf, ptr); break; } #endregion #region ID 33 - Hardware type case 0x33: // Hardware type n = snbuf[ptr++]; // hwinfo count tb.Description = "[HARDWARE TYPE]"; tb.Periods = new List <int>(); ptr += 3 * n; break; #endregion #region ID 34 - Emulation info case 0x34: // Emulation info tb.Description = "[EMULATION INFO]"; tb.Periods = new List <int>(); ptr += 8; break; #endregion #region ID 35 - Custom info block+ case 0x35: // Custom info block { string infoValue = Encoding.ASCII.GetString(snbuf, ptr, 0x10); tb.Description = string.Format("[CUSTOM INFO - {0}]", infoValue); ptr += 0x10; tb.Periods = new List <int>(); int customLength = BitConverter.ToInt32(snbuf, ptr); ptr += 4 + customLength; break; } #endregion #region ID 40 - Snapshot block case 0x40: // Snapshot block tb.Description = "[SNAPSHOT - "; if (snbuf[ptr] == 0) { tb.Description += ".Z80]"; } else if (snbuf[ptr] == 1) { tb.Description += ".SNA]"; } else { tb.Description += "???]"; } ptr++; size = snbuf[ptr] | snbuf[ptr + 1] << 8 | snbuf[ptr + 2] << 16; ptr += 3; tb.Periods = new List <int>(); ptr += size; break; #endregion #region ID 5A - "Glue" block+ case 0x5A: // "Glue" block tb.Description = string.Format("[GLUE]"); tb.Periods = new List <int>(); ptr += 9; break; #endregion default: tb.Description = string.Format( "[NOT SUPPORTED BLOCK 0x{0:X2}]", snbuf[ptr - 1]); tb.Periods = new List <int>(); ptr += getInt32(snbuf, ptr) & 0xFFFFFF; ptr += 4; break; } tzxBlocks.Add(tb); } var ltb = tzxBlocks.Count > 0 ? tzxBlocks[tzxBlocks.Count - 1] : null; if (ltb != null) { ltb.Periods.Add(frequency / 220); ltb.Periods.Add(frequency / 220); } return(tzxBlocks); }
public override void Deserialize(Stream stream) { List <int> list = new List <int>(); byte[] array = new byte[52]; stream.Read(array, 0, 32); if (Encoding.ASCII.GetString(array, 0, 22) != "Compressed Square Wave") { PlatformFactory.Platform.ShowWarning("Invalid CSW file, identifier not found! ", "CSW loader"); return; } if (array[23] > 2) { PlatformFactory.Platform.ShowWarning(string.Concat(new string[] { "Format CSW V", array[23].ToString(), ".", array[24].ToString(), " not supported!" }), "CSW loader"); return; } if (array[23] == 2) { stream.Read(array, 32, 20); byte[] array2 = new byte[(int)array[35]]; stream.Read(array2, 0, array2.Length); } int num = (array[23] == 2) ? BitConverter.ToInt32(array, 25) : ((int)BitConverter.ToUInt16(array, 25)); int num2 = (int)((array[23] == 2) ? array[33] : array[27]); byte[] array3; if (array[23] == 2) { array3 = new byte[BitConverter.ToInt32(array, 29)]; } else { array3 = new byte[stream.Length - 32L]; } if (num2 == 1) { stream.Read(array3, 0, array3.Length); } else { if (num2 != 2) { PlatformFactory.Platform.ShowWarning("Unknown compression type!", "CSW loader"); return; } this.csw2_uncompress(stream, array3); } int num3 = (int)(this._tape.Z80FQ / (ulong)((long)num)); int i = 0; while (i < array3.Length) { int num4 = (int)array3[i++] * num3; if (num4 == 0) { num4 = BitConverter.ToInt32(array3, i) / num3; i += 4; } list.Add(num4); } list.Add((int)(this._tape.Z80FQ / 10UL)); TapeBlock tapeBlock = new TapeBlock(); tapeBlock.Description = "CSW tape image"; tapeBlock.Periods = list; this._tape.Blocks.Add(tapeBlock); }
public override void Deserialize(Stream stream) { byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); if (Encoding.ASCII.GetString(array, 0, 7) != "ZXTape!" || array[7] != 26) { PlatformFactory.Platform.ShowWarning("Invalid TZX file, identifier not found! ", "TZX loader"); return; } int i = 0; int num = 0; int num2 = 0; while (i < array.Length) { byte b = array[i++]; TapeBlock tapeBlock; switch (b) { case 16: { tapeBlock = new TapeBlock(); int num3 = (int)FormatSerializer.getUInt16(array, i + 2); int num4 = (int)FormatSerializer.getUInt16(array, i); i += 4; tapeBlock.Description = TapSerializer.getBlockDescription(array, i, num3); tapeBlock.Periods = TapSerializer.getBlockPeriods(array, i, num3, 2168, 667, 735, 855, 1710, (array[i] < 4) ? 8064 : 3220, num4, 8); i += num3; this._tape.Blocks.Add(tapeBlock); continue; } case 17: { tapeBlock = new TapeBlock(); int num3 = 16777215 & FormatSerializer.getInt32(array, i + 15); tapeBlock.Description = TapSerializer.getBlockDescription(array, i + 18, num3); tapeBlock.Periods = TapSerializer.getBlockPeriods(array, i + 18, num3, (int)FormatSerializer.getUInt16(array, i), (int)FormatSerializer.getUInt16(array, i + 2), (int)FormatSerializer.getUInt16(array, i + 4), (int)FormatSerializer.getUInt16(array, i + 6), (int)FormatSerializer.getUInt16(array, i + 8), (int)FormatSerializer.getUInt16(array, i + 10), (int)FormatSerializer.getUInt16(array, i + 13), (int)array[i + 12]); i += num3 + 18; this._tape.Blocks.Add(tapeBlock); continue; } case 18: { tapeBlock = new TapeBlock(); tapeBlock.Description = "Pure Tone"; int num5 = (int)FormatSerializer.getUInt16(array, i); int num6 = (int)FormatSerializer.getUInt16(array, i + 2); tapeBlock.Periods = new List <int>(num6); for (int j = 0; j < num6; j++) { tapeBlock.Periods.Add(num5); } i += 4; this._tape.Blocks.Add(tapeBlock); continue; } case 19: { tapeBlock = new TapeBlock(); tapeBlock.Description = "Pulse sequence"; int num6 = (int)array[i++]; tapeBlock.Periods = new List <int>(num6); int j = 0; while (j < num6) { tapeBlock.Periods.Add((int)FormatSerializer.getUInt16(array, i)); j++; i += 2; } this._tape.Blocks.Add(tapeBlock); continue; } case 20: { tapeBlock = new TapeBlock(); tapeBlock.Description = "Pure Data Block"; int num3 = 16777215 & FormatSerializer.getInt32(array, i + 7); tapeBlock.Periods = TapSerializer.getBlockPeriods(array, i + 10, num3, 0, 0, 0, (int)FormatSerializer.getUInt16(array, i), (int)FormatSerializer.getUInt16(array, i + 2), -1, (int)FormatSerializer.getUInt16(array, i + 5), (int)array[i + 4]); i += num3 + 10; this._tape.Blocks.Add(tapeBlock); continue; } case 21: { tapeBlock = new TapeBlock(); tapeBlock.Description = "Direct Recording"; int num3 = 16777215 & FormatSerializer.getInt32(array, i + 5); int @uint = (int)FormatSerializer.getUInt16(array, i); int num4 = (int)FormatSerializer.getUInt16(array, i + 2); int num7 = (int)array[i + 4]; i += 8; int num5 = 0; int num6 = 0; int j; for (j = 0; j < num3; j++) { for (int num8 = 128; num8 != 0; num8 >>= 1) { if ((((int)array[i + j] ^ num5) & num8) != 0) { num6++; num5 ^= -1; } } } int num9 = 0; num5 = 0; tapeBlock.Periods = new List <int>(num6 + 2); j = 1; while (j < num3) { for (int num8 = 128; num8 != 0; num8 >>= 1) { num9 += @uint; if ((((int)array[i] ^ num5) & num8) != 0) { tapeBlock.Periods.Add(num9); num5 ^= -1; num9 = 0; } } j++; i++; } for (int num8 = 128; num8 != (int)((byte)(128 >> num7)); num8 >>= 1) { num9 += @uint; if ((((int)array[i] ^ num5) & num8) != 0) { tapeBlock.Periods.Add(num9); num5 ^= -1; num9 = 0; } } i++; tapeBlock.Periods.Add(num9); if (num4 != 0) { tapeBlock.Periods.Add(num4 * 3500); } this._tape.Blocks.Add(tapeBlock); continue; } case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: case 41: case 43: case 44: case 45: case 46: case 47: break; case 32: { tapeBlock = new TapeBlock(); int num4 = (int)FormatSerializer.getUInt16(array, i); tapeBlock.Description = ((num4 != 0) ? ("[Pause " + num4 + " ms]") : "[Stop the Tape]"); tapeBlock.Periods = new List <int>(2); i += 2; if (num4 == 0) { tapeBlock.Command = TapeCommand.STOP_THE_TAPE; tapeBlock.Periods.Add(3500); num4 = -1; } else { num4 *= 3500; } tapeBlock.Periods.Add(num4); this._tape.Blocks.Add(tapeBlock); continue; } case 33: { tapeBlock = new TapeBlock(); int num6 = (int)array[i++]; tapeBlock.Description = "[GROUP: " + Encoding.ASCII.GetString(array, i, num6) + "]"; tapeBlock.Command = TapeCommand.BEGIN_GROUP; i += num6; tapeBlock.Periods = new List <int>(); this._tape.Blocks.Add(tapeBlock); continue; } case 34: tapeBlock = new TapeBlock(); tapeBlock.Description = "[END GROUP]"; tapeBlock.Command = TapeCommand.END_GROUP; tapeBlock.Periods = new List <int>(); this._tape.Blocks.Add(tapeBlock); continue; case 35: tapeBlock = new TapeBlock(); tapeBlock.Description = "[JUMP TO BLOCK " + FormatSerializer.getUInt16(array, i) + "]"; tapeBlock.Periods = new List <int>(); i += 2; this._tape.Blocks.Add(tapeBlock); continue; case 36: num = (int)FormatSerializer.getUInt16(array, i); num2 = this._tape.Blocks.Count; i += 2; continue; case 37: if (num != 0) { int num3 = this._tape.Blocks.Count - num2; for (int k = 0; k < num3; k++) { this._tape.Blocks.Add(this._tape.Blocks[num + k]); } num = 0; continue; } continue; case 38: tapeBlock = new TapeBlock(); tapeBlock.Description = "[CALL SEQUENCE]"; tapeBlock.Periods = new List <int>(); i += (int)(2 + 2 * FormatSerializer.getUInt16(array, i)); this._tape.Blocks.Add(tapeBlock); continue; case 39: tapeBlock = new TapeBlock(); tapeBlock.Description = "[RETURN SEQUENCE]"; tapeBlock.Periods = new List <int>(); this._tape.Blocks.Add(tapeBlock); continue; case 40: tapeBlock = new TapeBlock(); tapeBlock.Description = "[SELECT BLOCK]"; tapeBlock.Periods = new List <int>(); i += (int)(2 + FormatSerializer.getUInt16(array, i)); this._tape.Blocks.Add(tapeBlock); continue; case 42: tapeBlock = new TapeBlock(); tapeBlock.Description = "[Stop tape if in 48K mode]"; tapeBlock.Command = TapeCommand.STOP_THE_TAPE_48K; tapeBlock.Periods = new List <int>(); i += (int)(4 + FormatSerializer.getUInt16(array, i)); this._tape.Blocks.Add(tapeBlock); continue; case 48: { tapeBlock = new TapeBlock(); int num6 = (int)array[i++]; tapeBlock.Description = "[" + Encoding.ASCII.GetString(array, i, num6) + "]"; tapeBlock.Periods = new List <int>(); i += num6; this._tape.Blocks.Add(tapeBlock); continue; } case 49: { tapeBlock = new TapeBlock(); i++; int num6 = (int)array[i++]; tapeBlock.Description = "[Message: " + Encoding.ASCII.GetString(array, i, num6) + "]"; tapeBlock.Command = TapeCommand.SHOW_MESSAGE; tapeBlock.Periods = new List <int>(); i += num6; this._tape.Blocks.Add(tapeBlock); continue; } case 50: { tapeBlock = new TapeBlock(); tapeBlock.Description = "Archive info"; tapeBlock.Periods = new List <int>(); int num10 = i + 3; for (int j = 0; j < (int)array[i + 2]; j++) { byte b2 = array[num10++]; string arg; switch (b2) { case 0: arg = "Full title"; break; case 1: arg = "Publisher"; break; case 2: arg = "Author"; break; case 3: arg = "Year"; break; case 4: arg = "Language"; break; case 5: arg = "Type"; break; case 6: arg = "Price"; break; case 7: arg = "Protection"; break; case 8: arg = "Origin"; break; default: if (b2 != 255) { arg = "info"; } else { arg = "Comment"; } break; } int num3 = (int)array[num10++]; tapeBlock.Description = string.Format("{0}: {1}", arg, Encoding.ASCII.GetString(array, num10, num3)); num10 += num3; } i += (int)(2 + FormatSerializer.getUInt16(array, i)); this._tape.Blocks.Add(tapeBlock); continue; } case 51: { tapeBlock = new TapeBlock(); int num6 = (int)array[i++]; tapeBlock.Description = "[HARDWARE TYPE]"; tapeBlock.Periods = new List <int>(); i += 3 * num6; this._tape.Blocks.Add(tapeBlock); continue; } case 52: tapeBlock = new TapeBlock(); tapeBlock.Description = "[EMULATION INFO]"; tapeBlock.Periods = new List <int>(); i += 8; this._tape.Blocks.Add(tapeBlock); continue; case 53: tapeBlock = new TapeBlock(); tapeBlock.Description = "[CUSTOM INFO - " + Encoding.ASCII.GetString(array, i, 10) + "]"; i += 10; tapeBlock.Periods = new List <int>(); i += (int)(2 + FormatSerializer.getUInt16(array, i)); this._tape.Blocks.Add(tapeBlock); continue; default: if (b == 64) { tapeBlock = new TapeBlock(); tapeBlock.Description = "[SNAPSHOT - "; if (array[i] == 0) { TapeBlock tapeBlock2 = tapeBlock; tapeBlock2.Description += ".Z80]"; } else if (array[i] == 1) { TapeBlock tapeBlock3 = tapeBlock; tapeBlock3.Description += ".SNA]"; } else { TapeBlock tapeBlock4 = tapeBlock; tapeBlock4.Description += "???]"; } i++; int num3 = (int)array[i] | (int)array[i + 1] << 8 | (int)array[i + 2] << 16; i += 3; tapeBlock.Periods = new List <int>(); i += num3; this._tape.Blocks.Add(tapeBlock); continue; } if (b == 90) { i += 9; continue; } break; } tapeBlock = new TapeBlock(); tapeBlock.Description = "[UNKNOWN BLOCK 0x" + array[i - 1].ToString("X2") + "]"; tapeBlock.Periods = new List <int>(); i += (FormatSerializer.getInt32(array, i) & 16777215); i += 4; this._tape.Blocks.Add(tapeBlock); } }
/// <summary> /// Стирает все символы, присутствующие на ленте. /// </summary> public void Clear() { _firstBlock = null; _lastBlock = null; _currentBlock = null; }
/// <summary> /// Удаляет блок из ленты. /// </summary> /// <param name="block">Удаляемый блок.</param> private void RemoveBlock(TapeBlock block) { if (block == null) throw new ArgumentNullException("Удаляемый блок не может быть неопределенным"); if(block.Prev == null) // блок стоит первым в списке либо он единственный. { _firstBlock = block.Next; if(_firstBlock != null) _firstBlock.Prev = null; else _lastBlock = null; _currentBlock = _firstBlock; } else if(block.Next == null) // блок стоит последним в списке. { _lastBlock = block.Prev; _lastBlock.Next = null; _currentBlock = _lastBlock; } else // блок стоит в центре списка. { block.Prev.Next = block.Next; block.Next.Prev = block.Prev; _currentBlock = block.Prev; } }
/// <summary> /// Добавляет блок ячеек на свое место в списке. /// </summary> /// <param name="block">Добавляемый блок.</param> private void AddBlock(TapeBlock block) { if(_currentBlock == null) { _currentBlock = block; _firstBlock = block; _lastBlock = block; return; } TapeBlock current = _firstBlock; while(block.CompareTo(current) == 1) { current = current.Next; if (current == null) break; } if(current == null) { _lastBlock.Next = block; block.Prev = _lastBlock; _lastBlock = block; } else { if (current.Prev != null) { current.Prev.Next = block; block.Prev = current.Prev; } else _firstBlock = block; current.Prev = block; block.Next = current; } _currentBlock = block; }
/// <summary> /// Возвращает значение указанной ячейки. /// </summary> /// <param name="cell">Индекс указанной ячейки.</param> /// <returns>Значение указанной ячейки.</returns> public int GetValue(BigInteger cell) { if (_currentBlock == null) return 0; if (cell < _firstBlock.FirstCell) return 0; if (cell > _lastBlock.LastCell) return 0; if (cell < _currentBlock.FirstCell) { TapeBlock initialValue = _currentBlock; _currentBlock = _currentBlock.Prev; BigInteger blockCell; while (_currentBlock != null) { if (cell >= _currentBlock.FirstCell) { blockCell = cell - _currentBlock.FirstCell; if (blockCell >= 0) { if (blockCell < BLOCK_SIZE) return _currentBlock.GetValue((int)blockCell); } } _currentBlock = _currentBlock.Prev; } _currentBlock = initialValue; return 0; } else if (cell > _currentBlock.LastCell) { TapeBlock initialValue = _currentBlock; _currentBlock = _currentBlock.Next; BigInteger blockCell; while (_currentBlock != null) { if (cell <= _currentBlock.LastCell) { blockCell = cell - _currentBlock.FirstCell; if (blockCell >= 0) { if (blockCell < BLOCK_SIZE) return _currentBlock.GetValue((int)blockCell); } } _currentBlock = _currentBlock.Next; } _currentBlock = initialValue; return 0; } else { return _currentBlock.GetValue((int)(cell - _currentBlock.FirstCell)); } }