internal override int ReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP) { ValidateBufferOffsets(buffer, offset, size); if (socketFlags != SocketFlags.None) { // Invalid flags for this operation throw new SocketException(SocketErrors.WSAEINVAL); } UdpConnectionContract /*.Imp*/ conn = (UdpConnectionContract)m_Conn.Acquire(); try { if (conn.InState(UdpConnectionContract.State.Closed /*.Value*/)) { throw new SocketException(BAD_SOCKET_STATE_ERR); } Bytes rdata = conn.Read(); uint addr = 0; ushort port = 0; remoteEP = new IPEndPoint(new IPAddress(addr), port); int amount = Math.Min(rdata.Length, size); Bitter.ToByteArray(rdata, 0, amount, buffer, offset); return(amount); } finally { m_Conn.Release(conn); } }
public IList <TwinkleBeatmaniaChartEvent> Decode(ReadOnlySpan <byte> data, int length) { var result = new List <TwinkleBeatmaniaChartEvent>(); var noteCountMode = true; for (var i = 0; i < length; i += 4) { if (noteCountMode) { if (data[i + 0x03] == 0 || data[i + 0x03] == 1) { continue; } noteCountMode = false; } var offset = Bitter.ToInt16S(data, i); if (offset == 0x7FFF) { break; } var value = data[i + 0x02]; var command = data[i + 0x03]; result.Add(new TwinkleBeatmaniaChartEvent { Offset = (ushort)offset, Param = command, Value = value }); } return(result); }
private static DdrDatabaseEntry GetOldRecord(DdrPs2MetadataTableEntry item) { var record = item.Data.AsSpan(); var id = Encodings.CP437.GetStringWithoutNulls(record.Slice(0x00, 5)); if (id == string.Empty) { return(null); } return(new DdrDatabaseEntry { Index = item.Index, Id = id, Type = record[0x06], CdTitle = record[0x07], InternalId = Bitter.ToInt16(record, 0x08), MaxBpm = Bitter.ToInt16(record, 0x10), MinBpm = Bitter.ToInt16(record, 0x12), Unknown014 = Bitter.ToInt16(record, 0x14), SonglistOrder = Bitter.ToInt16(record, 0x16), UnlockNumber = Bitter.ToInt16(record, 0x18), Difficulties = new int[0], Flags = Bitter.ToInt32(record, 0x1C), // Radar0 = Bitter.ToInt16Array(record, 0x20, 6), // Radar1 = Bitter.ToInt16Array(record, 0x2C, 6), // Radar2 = Bitter.ToInt16Array(record, 0x38, 6), // Radar3 = Bitter.ToInt16Array(record, 0x44, 6), // Radar4 = Bitter.ToInt16Array(record, 0x50, 6) }); }
//way too many copies. But for now we'll live with it. private StatusCode AskDnsServer(IPv4 dnsServer, byte[] outData, out byte[] rcvData) { UDP udp = new UDP(); udp.Bind(IPv4.Any, 0); udp.Connect(dnsServer, Dns.Format.ServerPort); Bytes packet = Bitter.FromByteArray(outData); udp.WriteData(packet); Bytes buffer; buffer = udp.PollReadData(TimeSpan.FromTicks(timeout.Ticks)); //This is silly..I'll come back and clean this up. udp.Close(); if (buffer == null) { rcvData = null; return(StatusCode.Timeout); } rcvData = new byte[buffer.Length]; Bitter.ToByteArray(buffer, 0, buffer.Length, rcvData, 0); //delete buffer; return(StatusCode.Success); }
//process incoming packet public static bool ProcessIncomingPacket(Bytes packet, IpHeader ipHeader) { int offset = EthernetHeader.Size + IpHeader.Size; //14 byte ethernet header + 20 byte IP header VTable.Assert(offset == 34); UDPHeader udpHeader = new UDPHeader(packet, offset); DebugPrint("ProcessIncomingPacket: Received packet from address {0} port {1}\n", ipHeader.srcAddress.ToString(), udpHeader.srcPort); UDP udp = GetUDPSession(udpHeader.dstPort); //now we check to see whether the udp session wants to packet //XXX review this logic... //todo: check if udp is bound to local IP that dest IP matches. //UDP header? if ((udp != null) && ((udp.LocalAddress == IPv4.Any) || (udp.RemoteAddress == ipHeader.srcAddress && udp.RemotePort == udpHeader.srcPort) || (udp.RemotePort == 0))) { offset += UDPHeader.Size; Bytes data = Bitter.SplitOff(ref packet, offset); //delete packet; udp.PushPacket(data); udp.udpWaitEvent.Set(); return(true); } DebugPrint("Received packe destined for inactive UDP port {0}" + " source address {1} source port {2}\n", udpHeader.dstPort, ipHeader.srcAddress.ToString(), udpHeader.srcPort); //delete packet; return(false); }
public Bytes PopAllPackets() { Bytes packet; int sizeOfData; Bytes buffer; if (byteCount <= 0) { DebugStub.WriteLine("UDP PopAllPackets: no data???\n"); DebugStub.Break(); return(null); } using (thisLock.Lock()) { DebugPrint("Popping {0} bytes of data to client\n", byteCount); buffer = new Bytes(new byte[byteCount]); VectorQueueByte incomingPacketQueue = packetContainer.Acquire(); int offset = 0; while ((packet = incomingPacketQueue.ExtractHead()) != null) { VTable.Assert(packet != null); Bitter.Copy(buffer, offset, packet.Length, packet, 0); offset += packet.Length; byteCount -= packet.Length; //delete packet; } packetContainer.Release(incomingPacketQueue); DebugStub.Assert(byteCount == 0); } return(buffer); }
internal override int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags) { if (buffer == null) { throw new ArgumentNullException("buffer"); } if (offset < 0 || offset > buffer.Length) { throw new ArgumentOutOfRangeException("offset"); } if (size < 0 || size > buffer.Length - offset) { throw new ArgumentOutOfRangeException("size"); } // Copy the data into the shared heap Bytes dataToWrite = Bitter.FromByteArray(buffer, offset, size); return(Send(dataToWrite, socketFlags)); }
public IsoVolume Decode(ReadOnlySpan <byte> data) { return(new IsoVolume { SystemIdentifier = Encodings.CP437.GetString(data.Slice(8, 32)), VolumeIdentifier = Encodings.CP437.GetString(data.Slice(40, 32)), SpaceSize = Bitter.ToInt32(data.Slice(80, 8)), SetSize = Bitter.ToInt32(data.Slice(120, 4)), SequenceNumber = Bitter.ToInt32(data.Slice(124, 4)), LogicalBlockSize = Bitter.ToInt32(data.Slice(128, 4)), PathTableSize = Bitter.ToInt32(data.Slice(132, 8)), TypeLPathTableLocation = Bitter.ToInt32(data.Slice(140, 4)), OptionalTypeLPathTableLocation = Bitter.ToInt32(data.Slice(144, 4)), TypeMPathTableLocation = Bitter.ToInt32(data.Slice(148, 4)), OptionalTypeMPathTableLocation = Bitter.ToInt32(data.Slice(152, 4)), RootDirectoryRecord = _isoDirectoryRecordDecoder.Decode(new MemoryStream(data.Slice(156, 34).ToArray()), true), VolumeSetIdentifier = Encodings.CP437.GetString(data.Slice(190, 128)), PublisherIdentifier = Encodings.CP437.GetString(data.Slice(318, 128)), DataPreparerIdentifier = Encodings.CP437.GetString(data.Slice(446, 128)), ApplicationIdentifier = Encodings.CP437.GetString(data.Slice(574, 128)), CopyrightFileIdentifier = Encodings.CP437.GetString(data.Slice(702, 38)), AbstractFileIdentifier = Encodings.CP437.GetString(data.Slice(740, 36)), BibliographicFileIdentifier = Encodings.CP437.GetString(data.Slice(776, 37)), ApplicationData = data.Slice(883, 512).ToArray() }); }
public XboxIsoInfo Decode(byte[] sector) { return(new XboxIsoInfo { DirectorySectorNumber = Bitter.ToInt32(sector, 0x14), DirectorySize = Bitter.ToInt32(sector, 0x18) }); }
internal override int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags) { ValidateBufferOffsets(buffer, offset, size); Bytes dataToWrite = Bitter.FromByteArray(buffer, offset, size); return(Send(dataToWrite, socketFlags)); }
public MicrosoftAdpcmFormat(byte[] data) { SamplesPerBlock = Bitter.ToInt16(data, 2); var coefficientCount = Bitter.ToInt16(data, 4); Coefficients = new int[coefficientCount * 2]; for (var i = 0; i < Coefficients.Length; i++) { Coefficients[i] = Bitter.ToInt16(data, 6 + i * 2); } }
public HeuristicResult Match(IHeuristicReader reader) { var data = reader.Read(0x10); if (data.Length < 0x10) { return(null); } var length = Bitter.ToInt32S(data); if (length == 0) { return(null); } if ((length & 0x7FF) != 0) { return(null); } if (data[0x05] == 0) { return(null); } var sampleRate = Bitter.ToInt16S(data, 6); if (sampleRate == 0) { return(null); } if (data[0x08] == 0) { return(null); } if (data[0x08] > 2) { return(null); } return(new VagHeuristicResult(this) { Start = 0x800, Interleave = 0x800, Channels = data[0x08], SampleRate = sampleRate, Length = length }); }
public void Set(byte[] buffer, int bufferStart, int bufferBytes) { { if (this.data == null || this.data.Length < bufferBytes) { this.data = new Bytes(new byte[bufferBytes]); } this.start = 0; this.length = bufferBytes; Bitter.FromByteArray(this.data, 0, bufferBytes, buffer, bufferStart); } }
internal static int AppMain(Parameters !config) { IPContract.Imp ipConn = ((!)config.ipRef).Acquire(); if (ipConn == null) { Console.WriteLine("Could not initialize IP endpoint."); return(1); } ipConn.RecvReady(); try { if (config.name == null) { char[] !in ExHeap repHost, repDomain; ipConn.SendGetHostName(); ipConn.RecvHostName(out repHost); ipConn.SendGetDomainName(); ipConn.RecvDomainName(out repDomain); Console.WriteLine("{0}.{1}", Bitter.ToString(repHost), Bitter.ToString(repDomain)); delete repHost; delete repDomain; return(0); // success } else { ipConn.SendSetHostName(Bitter.FromString2(config.name)); switch receive { case ipConn.Err(): Console.WriteLine("Failure setting host name \"{0}\"", config.name); return(1); // failure; case ipConn.OK(): Console.WriteLine("Success setting host name"); break; case ipConn.ChannelClosed(): Console.WriteLine("Failure setting host name \"{0}\" (channel closed)", config.name); return(1); // failure; } } } finally { delete ipConn; } return(0); // success }
public WaveFmtChunk Decode(IRiffChunk chunk) { var data = chunk.Data; return(new WaveFmtChunk { Format = Bitter.ToInt16(data, 0), Channels = Bitter.ToInt16(data, 2), SampleRate = Bitter.ToInt32(data, 4), ByteRate = Bitter.ToInt32(data, 8), BlockAlign = Bitter.ToInt16(data, 12), BitsPerSample = Bitter.ToInt16(data, 14), ExtraData = data.Length > 16 ? data.AsSpan(16).ToArray() : new byte[0] }); }
/* * public void GetFragmentRange(out UIntPtr virtualAddr, * out int lengthBytes) * { * { * if (this.data != null) { * virtualAddr = Bitter.ToAddress(this.data, this.start); * lengthBytes = this.length; * } * else { * virtualAddr = UIntPtr.Zero; * lengthBytes = 0; * } * } * } */ public int Copy(byte[] destination, int offset) { { if (this.data != null) { Bitter.ToByteArray(this.data, this.start, this.length, destination, offset); return(this.length); } else { return(0); } } }
// Must be balanced with a call to ReleaseDnsConnection()! internal static DNSContract.Imp !GetDnsConnection() { LocalDataStoreSlot slot = SafeSlotFetchOrInitialize(ref DnsSlot, DnsSlotLock); if (Thread.GetData(slot) == null) { // We haven't created a channel for this thread yet. Create one. DNSContract.Imp !dnsImp; DNSContract.Exp !dnsExp; DirectoryServiceContract.Imp epNS = DirectoryService.NewClientEndpoint(); DNSContract.NewChannel(out dnsImp, out dnsExp); try { epNS.SendBind(Bitter.FromString2(DNSContract.ModuleName), dnsExp); switch receive { case epNS.NakBind(ServiceContract.Exp: Start rejectedEP, error) : if (rejectedEP != null) { delete rejectedEP; } delete dnsImp; // Do nothing; we will return null below. break; case epNS.AckBind(): // Success; put our remaining end of the channel // into thread-local storage. dnsImp.RecvReady(); TRef <DNSContract.Imp : ReadyState> dnsConnHolder = new TRef <DNSContract.Imp : ReadyState>(dnsImp); Thread.SetData(slot, dnsConnHolder); break; } } finally { delete epNS; } } // By now there should definitely be a channel in our thread-local storage. TRef <DNSContract.Imp : ReadyState> !connHolder = (TRef <DNSContract.Imp : ReadyState> !)Thread.GetData(slot); return(connHolder.Acquire()); }
public HeuristicResult Match(IHeuristicReader reader) { if (reader.Length < 0x804) { return(null); } var data = reader.Read(0x2C); if (Bitter.ToInt32(data.Slice(0x00)) != 0x08640001) { return(null); } if (Bitter.ToInt32(data.Slice(0x04)) != 0) { return(null); } var startOffset = Bitter.ToInt32(data.Slice(0x08)); if (startOffset < 0x00000030) { return(null); } var result = new VagHeuristicResult(this) { Start = startOffset, Length = Bitter.ToInt32(data.Slice(0x0C)), LoopStart = Bitter.ToInt32(data.Slice(0x10)), LoopEnd = Bitter.ToInt32(data.Slice(0x14)), SampleRate = Bitter.ToInt32(data.Slice(0x18)), Channels = Bitter.ToInt32(data.Slice(0x1C)), Interleave = Bitter.ToInt32(data.Slice(0x24)), Volume = new BigRational(Bitter.ToInt32(data.Slice(0x28)), 100), }; if (data[0x20] != 0x00 || data[0x21] != 0x00 || data[0x22] != 0x00 || data[0x23] != 0x00) { result.Key = data.Slice(0x20, 4).ToArray(); } return(result); }
internal static int DefaultMain(DefaultConfig !config) { IPContract.Imp ipConn = ((!)config.ipRef).Acquire(); if (ipConn == null) { throw new Exception("Unable to acquire handle to the IP network"); } ipConn.RecvReady(); char[][] !in ExHeap ifNames; ipConn.SendGetInterfaces(); ipConn.RecvInterfaceList(out ifNames); for (int i = 0; i < ifNames.Length; ++i) { CustomVector.Expose(ifNames, i); char[] in ExHeap ifName = ifNames[i]; if (ifName == null) { throw new Exception("ifName is null"); } string !deviceName = Bitter.ToString2(ifName); CustomVector.UnExpose(ifNames, i); ipConn.SendGetInterfaceState(Bitter.FromString2(deviceName)); switch receive { case ipConn.InterfaceNotFound(): Console.WriteLine("Unexpected error"); break; case ipConn.InterfaceState(InterfaceInfo ifInfo): WriteInterfaceLine(ifInfo, deviceName); break; case ipConn.ChannelClosed(): throw new Exception("ipConn channel closed"); } } delete ifNames; delete ipConn; return(0); }
internal override int SendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP) { ValidateBufferOffsets(buffer, offset, size); if (socketFlags != SocketFlags.None) { // Invalid flags for this operation throw new SocketException(SocketErrors.WSAEINVAL); } IPEndPoint ep = remoteEP as IPEndPoint; if (ep == null) { throw new SocketException(SocketErrors.WSAEINVAL); } UdpConnectionContract /*.Imp*/ conn = (UdpConnectionContract)m_Conn.Acquire(); try { if (conn.InState(UdpConnectionContract.State.Closed /*.Value*/)) { throw new SocketException(BAD_SOCKET_STATE_ERR); } // Copy the data to write into an ExHeap vector and send it Bytes dataToWrite = Bitter.FromByteArray(buffer, offset, size); conn.WriteTo((uint)ep.Address.m_addr, unchecked ((ushort)ep.Port), dataToWrite); // no longer own dataToWrite! return(size); } finally { m_Conn.Release(conn); } }
public static KeyboardDeviceContract.Imp OpenKeyboard(string! devName) { KeyboardDeviceContract.Exp! exp; KeyboardDeviceContract.Imp! imp; KeyboardDeviceContract.NewChannel(out imp, out exp); // get NS endpoint DirectoryServiceContract.Imp ns = DirectoryService.NewClientEndpoint(); bool success = false; ns.SendBind(Bitter.FromString2(devName),exp); switch receive { case ns.AckBind(): success = true; break; case ns.NakBind(exp): delete exp; break; case ns.ChannelClosed(): break; } if (!success) { DebugStub.Print("OpenKeyboard lookup of {0} failed.\n", __arglist(devName); delete imp; delete ns; return null; } switch receive { case imp.Success(): break; case unsatisfiable: throw new Exception("Didn't imp.RecvAckConnect"); break; } delete ns; return imp; }
public HeuristicResult Match(IHeuristicReader reader) { var data = reader.Read(0x10); if (data.Length < 0x10) { return(null); } var a = Bitter.ToInt32(data); var b = Bitter.ToInt32(data, 4); var c = Bitter.ToInt32(data, 8); var d = Bitter.ToInt32(data, 12); if (a <= 0) { return(null); } if (b <= 0) { return(null); } if (c < 0) { return(null); } if (d != 0) { return(null); } if (a - b - c != 16384) { return(null); } return(new HeuristicResult(this)); }
public TwinkleBeatmaniaSoundDefinition Decode(ReadOnlySpan <byte> data) { if (data.Length < 0x12) { return(null); } var invalid = true; for (var i = 1; i < 0x12; i++) { if (data[i] != data[0]) { invalid = false; break; } } if (invalid) { return(null); } return(new TwinkleBeatmaniaSoundDefinition { Channel = data[0x00], Flags01 = data[0x01], Frequency = Bitter.ToInt16S(data, 0x02) & 0xFFFF, Volume = data[0x04], Panning = data[0x05], SampleStart = Bitter.ToInt24S(data, 0x06) & 0xFFFFFF, SampleEnd = Bitter.ToInt24S(data, 0x09) & 0xFFFFFF, Value0C = Bitter.ToInt16S(data, 0x0C) & 0xFFFF, Flags0E = data[0x0E], Flags0F = data[0x0F], SizeInBlocks = Bitter.ToInt16S(data, 0x10) & 0xFFFF }); }
public static SortedList Parse(Bytes buffer) { // This is an unnecessary copy byte [] data = Bitter.ToByteArray(buffer); return(Parse(data, 0, data.Length)); }
// Original note from Yaron: // ARP logic: see RFC 826 http://www.faqs.org/rfcs/rfc826.html // public void ProcessIncomingPacket(Bytes packet, IAdapter adapter) { //Get the ARP packet info located after the ethernet header ArpHeader arpHeader = new ArpHeader(packet, 14); DebugPrint("ARP: ProcessIncomingPacket\n"); //do some checks to make sure the packet is copacetic if (arpHeader.htype != 0x1) { DebugPrint("ARP: ProcessIncomingPacket got wrong hardware type? 0x{0,8:x}\n", arpHeader.htype); //delete packet; return; } if (arpHeader.ptype != 0x0800) { DebugPrint("ARP: ProcessIncomingPacket got wrong protocol? 0x{0,8:x}\n", arpHeader.ptype); //delete packet; return; } //ethernet address should be 6 bytes if (arpHeader.hlen != 6) { DebugPrint("ARP: ProcessIncomingPacket got wrong hw length? 0x{0,8:x}\n", arpHeader.hlen); //delete packet; return; } if (arpHeader.plen != 4) { DebugPrint("ARP: ProcessIncomingPacket got wrong protocol address length? 0x{0,8:x}\n", arpHeader.plen); //delete packet; return; } DebugPrint("Incoming packet\n"); bool merged = false; bool updated = false; ArpEntry target = arpTable.Lookup(arpHeader.senderIPAddr); if (target != null && target.Dynamic == true) { DebugPrint("ARP UPDATE\n"); // we have it already - just update the details... target.MacAddress = arpHeader.senderEthernetAddr; target.EntryAge = arpTable.Age; merged = true; updated = true; } if (merged == false) { DebugPrint("ARP ADDITION\n"); arpTable.AddEntry(new ArpEntry(arpHeader.senderIPAddr, arpHeader.senderEthernetAddr, true)); merged = true; UpdatePendingRequests(arpHeader.senderIPAddr, arpHeader.senderEthernetAddr); } //Is this a local address bool forSelf = IP.IsLocalAddress(arpHeader.destIPAddr); if (forSelf == false) { //delete packet; return; } // now figure out the opcode if (arpHeader.op == ARP_REQUEST) { DebugPrint("Handling request ({0},{1}) ---> ({2},{3} \npkt dest {4} {5})\n", arpHeader.senderIPAddr, arpHeader.senderEthernetAddr, arpHeader.destIPAddr, adapter.HardwareAddress, arpHeader.destIPAddr, arpHeader.destEthernetAddr ); int dataLength = EthernetHeader.Size + ArpHeader.Size; VTable.Assert(packet.Length >= dataLength); Bytes data = Bitter.SplitOff(ref packet, EthernetHeader.Size); EthernetHeader.Write(packet, adapter.HardwareAddress, arpHeader.senderEthernetAddr, EthernetHeader.PROTOCOL_ARP); //use arp header to format reply ArpHeader.Write(data, adapter.HardwareAddress, arpHeader.destIPAddr, ArpHeader.ARP_REPLY, arpHeader.senderEthernetAddr, arpHeader.senderIPAddr); adapter.PopulateTxRing(packet, data); } else { // otherwise we are done DebugPrint( "Handling reply ({2},{3}) <--- ({0},{1})\n", arpHeader.senderIPAddr, arpHeader.senderEthernetAddr, arpHeader.destIPAddr, arpHeader.destEthernetAddr ); //delete packet; } if (merged && !updated) { DebugPrint(arpTable.ToString()); } }
public HeuristicResult Match(IHeuristicReader reader) { // Must have at least 4 bytes if (reader.Length == null || reader.Length < 4) { return(null); } // Put a hard cap of 64k as a sanity check if (reader.Length > 65536) { return(null); } // Must be divisible by 4 if ((reader.Length & 0x3) != 0) { return(null); } var data = reader.Read((int)reader.Length); // Make sure each chunk length makes sense var thisOffset = 0; while (thisOffset < reader.Length) { var thisChunkLength = Bitter.ToInt32(data, thisOffset); if (thisChunkLength == 0) { break; } if (thisChunkLength < 0) { return(null); } if (thisOffset + thisChunkLength >= reader.Length) { return(null); } if ((thisOffset & 0x3) != 0) { return(null); } thisOffset += thisChunkLength; } // Try to make sense of the timing chunk length var timingChunkLength = Bitter.ToInt32(data); if (timingChunkLength < 20) { return(null); } if (timingChunkLength >= reader.Length) { return(null); } if ((timingChunkLength & 0x3) != 0) { return(null); } // Check both the measure and the second offset, make sure they are increasing var timingMeasure = int.MinValue; var timingSector = int.MinValue; for (var i = 1; i < timingChunkLength >> 2; i += 2) { var thisTimingMeasure = Bitter.ToInt32(data, i << 2); var thisTimingSector = Bitter.ToInt32(data, 0x4 + (i << 2)); if (thisTimingMeasure < timingMeasure) { return(null); } if (thisTimingSector < timingSector) { return(null); } timingMeasure = thisTimingMeasure; timingSector = thisTimingSector; } // No reason to believe this isn't a step1 at this point return(new HeuristicResult(this)); }
public IList <DdrDatabaseEntry> Decode(ReadOnlySpan <byte> database) { var offset = 0; var length = database.Length; var result = new List <DdrDatabaseEntry>(); var shortNameOffsets = new Dictionary <int, int>(); var longNameOffsets = new Dictionary <int, int>(); var index = 0; // Read database entries while (offset < length) { var raw = database.Slice(offset, 0x80); var id = Encodings.CP437.GetStringWithoutNulls(raw.Slice(0x00, 5)); if (id == string.Empty) { break; } var entry = new DdrDatabaseEntry { Index = index, Id = id, Type = raw[0x06], CdTitle = raw[0x07], InternalId = Bitter.ToInt16(raw, 0x08), MaxBpm = Bitter.ToInt16(raw, 0x10), MinBpm = Bitter.ToInt16(raw, 0x12), Unknown014 = Bitter.ToInt16(raw, 0x14), SonglistOrder = Bitter.ToInt16(raw, 0x16), UnlockNumber = Bitter.ToInt16(raw, 0x18), Difficulties = new[] { raw[0x1C] & 0xF, raw[0x1C] >> 4, raw[0x1D] & 0xF, raw[0x1D] >> 4, raw[0x20] & 0xF, raw[0x20] >> 4, raw[0x21] & 0xF, raw[0x21] >> 4, }, Unknown01E = Bitter.ToInt16(raw, 0x1E), Unknown022 = Bitter.ToInt16(raw, 0x22), Flags = Bitter.ToInt32(raw, 0x24), Radar0 = Bitter.ToInt16Array(raw, 0x28, 8), Radar1 = Bitter.ToInt16Array(raw, 0x38, 8), Radar2 = Bitter.ToInt16Array(raw, 0x48, 8), Radar3 = Bitter.ToInt16Array(raw, 0x58, 8), Radar4 = Bitter.ToInt16Array(raw, 0x68, 8) }; longNameOffsets[index] = Bitter.ToInt32(raw, 0x78); shortNameOffsets[index] = Bitter.ToInt32(raw, 0x7C); result.Add(entry); offset += 0x80; index++; } offset += 0x80; // Read string table var strings = database.Slice(offset); foreach (var kv in longNameOffsets) { result[kv.Key].LongName = Encodings.CP437.GetStringWithoutNulls(strings.Slice(kv.Value)); } foreach (var kv in shortNameOffsets) { result[kv.Key].ShortName = Encodings.CP437.GetStringWithoutNulls(strings.Slice(kv.Value)); } return(result); }
private static DdrDatabaseEntry GetNewRecord(DdrPs2MetadataTableEntry records) { var record = records.Data.AsSpan(); var id = Encodings.CP437.GetStringWithoutNulls(record.Slice(0x00, 5)); var mdbIndex = 0; var difficultyOffset = 0; int[] difficulties; if (id == string.Empty) { return(null); } var bpmOffset = 0; var isXDifficulties = Bitter.ToInt16(record, 0x06) == Bitter.ToInt16(record, 0x08) && record.Slice(0x25, 10).ToArray().All(x => x <= 20) && record.Slice(0x25, 10).ToArray().Any(x => x != 0x00); if (isXDifficulties) { mdbIndex = Bitter.ToInt16(record, 0x08); bpmOffset += 0x0C; } else { if (Bitter.ToInt16(record, 0x10) != 0 && Bitter.ToInt16(record, 0x12) == 0) { if (record[0x06] == 0x05 && Bitter.ToInt16(record, 0x08) == Bitter.ToInt16(record, 0x0A)) { // SN JP, SN US, SN2 US mdbIndex = Bitter.ToInt16(record, 0x0C); bpmOffset += 0x10; difficultyOffset += 0x10; } else { // SN2 JP mdbIndex = Bitter.ToInt16(record, 0x08); bpmOffset += 0x0C; } } if (Bitter.ToInt32(record, 0x14 + bpmOffset) != -1) { // SN, SN2 while (Bitter.ToInt32(record, 0x10 + bpmOffset) == 0) { bpmOffset += 4; difficultyOffset += 4; } } if (bpmOffset > 0) { while (Bitter.ToInt32(record, 0x24 + difficultyOffset) == 0) { difficultyOffset += 4; } } } if (isXDifficulties) { difficulties = new[] { record[0x26], record[0x27], record[0x28], record[0x29], record[0x25], 0, 0, 0, record[0x2B], record[0x2C], record[0x2D], record[0x2E], record[0x2A], 0, 0, 0, }; } else { difficulties = new[] { record[0x24 + difficultyOffset] & 0xF, record[0x24 + difficultyOffset] >> 4, record[0x25 + difficultyOffset] & 0xF, record[0x25 + difficultyOffset] >> 4, record[0x26 + difficultyOffset] & 0xF, record[0x26 + difficultyOffset] >> 4, record[0x27 + difficultyOffset] & 0xF, record[0x27 + difficultyOffset] >> 4, record[0x28 + difficultyOffset] & 0xF, record[0x28 + difficultyOffset] >> 4, record[0x29 + difficultyOffset] & 0xF, record[0x29 + difficultyOffset] >> 4, record[0x2A + difficultyOffset] & 0xF, record[0x2A + difficultyOffset] >> 4, record[0x2B + difficultyOffset] & 0xF, record[0x2B + difficultyOffset] >> 4 }; } return(new DdrDatabaseEntry { Index = records.Index, Id = id, Type = record[0x06], CdTitle = record[0x07], InternalId = Bitter.ToInt16(record, 0x08), MaxBpm = Bitter.ToInt16(record, 0x10 + bpmOffset), MinBpm = Bitter.ToInt16(record, 0x12 + bpmOffset), Unknown014 = Bitter.ToInt16(record, 0x14 + bpmOffset), SonglistOrder = Bitter.ToInt16(record, 0x16 + bpmOffset), UnlockNumber = Bitter.ToInt16(record, 0x18 + bpmOffset), Difficulties = difficulties, Flags = Bitter.ToInt32(record, 0x2C + difficultyOffset), AudioTrack = mdbIndex // Radar0 = Bitter.ToInt16Array(record, 0x30, 6), // Radar1 = Bitter.ToInt16Array(record, 0x3C, 6), // Radar2 = Bitter.ToInt16Array(record, 0x48, 6), // Radar3 = Bitter.ToInt16Array(record, 0x54, 6), // Radar4 = Bitter.ToInt16Array(record, 0x60, 6) }); }
private IEnumerable <IChart> DecodeInternal(IEnumerable <Step1Chunk> data) { var chunks = data.AsList(); if (!chunks.Any()) { throw new RhythmCodexException("No chunks to decode."); } var timings = _timingChunkDecoder.Convert(chunks[0].Data); foreach (var chunk in chunks.Skip(1)) { var timingEvents = _timingEventDecoder.Decode(timings); // Decode the raw steps. var steps = _stepChunkDecoder.Convert(chunk.Data); // Old charts store singles charts twice, as if it was a couples chart. So, check for that. int?panelCount = null; var steps1 = steps.Select(s => s.Panels & 0xF).ToArray(); var steps2 = steps.Select(s => s.Panels >> 4).ToArray(); var isSingle = steps1.SequenceEqual(steps2); int?playerCount; if (isSingle) { playerCount = 1; panelCount = 4; foreach (var step in steps) { step.Panels &= 0xF; } } else { // Bit of a hack to make solo charts work. playerCount = steps.Any(s => (s.Panels & 0xA0) != 0) ? 2 : 1; panelCount = _stepPanelSplitter.Split(steps.Aggregate(0, (i, s) => i | s.Panels)).Count() / playerCount; } // Determine what kind of chart this is based on the panels used. var mapper = _panelMapperSelector.Select(steps, new ChartInfo { PanelCount = panelCount, PlayerCount = playerCount }); // Convert the steps. var stepEvents = _stepEventDecoder.Decode(steps, mapper); var events = timingEvents.Concat(stepEvents).ToList(); var info = _chartInfoDecoder.Decode(Bitter.ToInt32(chunk.Data.AsSpan(0)), mapper.PlayerCount, mapper.PanelCount); // Output metadata. var difficulty = info.Difficulty; var type = $"{SmGameTypes.Dance}-{info.Type}"; var description = $"step1 - {events.Count(ev => ev[FlagData.Note] == true)} panels - {steps.Count(s => s.Panels != 0)} steps"; var chart = new Chart { Events = events, [StringData.Difficulty] = difficulty, [StringData.Type] = type, [StringData.Description] = description }; var firstTiming = timings.Timings.OrderBy(t => t.LinearOffset).First(); chart[NumericData.LinearOffset] = chart.GetZeroLinearReference( (BigRational)firstTiming.LinearOffset / timings.Rate, (BigRational)firstTiming.MetricOffset / SsqConstants.MeasureLength); // Have a chart. :3 yield return(chart); } }
public HeuristicResult Match(IHeuristicReader reader) { var noteCountMode = true; var hasBpm = false; var hasEnd = false; var hasTerminator = false; var evData = new byte[4]; while (true) { if (reader.Read(evData, 0, 4) < 4) { break; } var eventOffset = Bitter.ToInt16S(evData); var eventValue = evData[2]; var eventCommand = evData[3]; var eventParameter = eventCommand >> 4; var eventType = eventCommand & 0xF; // empty event = invalid if (Bitter.ToInt32(evData) == 0) { return(null); } // positive event offsets only if (eventOffset < 0) { return(null); } // offsets can't be present during note count if (noteCountMode && eventOffset != 0) { return(null); } // disable note count info if another event type shows up if (eventCommand != 0x00 && eventCommand != 0x01) { noteCountMode = false; } // skip the rest of processing if in note count mode if (noteCountMode) { continue; } // terminator bytes if (eventOffset == 0x7FFF) { hasTerminator = true; break; } // make sure we have the bare minimums if (eventType == 6) { hasEnd = true; } else if (eventType == 4 && eventValue + (eventParameter << 8) != 0) { hasBpm = true; } } if (!(hasBpm && hasEnd && hasTerminator)) { return(null); } return(new HeuristicResult(this)); }