Some better resources to look at would be:
Send 84 bytes:
If the Data Len is greater than 0 then the next TCP packet(s) will be that data.
No args used.
No args, but there will be a DataLen so expect that data in the next TCP packets. You don't actually need to send this more than once, but you may want to send Connect and this again to get a list of process names/IDs.
An easy/dumb way to get started with viewing the video frames is to loop until the packet size is smaller than usual, then you can do the same from then on knowing you probably have the entire frames.
If the joined packets decompress successfully you can then look at the length. 288000 bytes is a top screen frame, otherwise it's the bottom screen.
Example of buttons only:
NTRPacket ntrIR = NTRPacket.NewWriteMemory(1000, 16, 1105696, 12, 12); //Seq=1000 doesn't matter, pid=0x10 or 16, address=0x10DF20 or 1105696, payload 12 bytes Network.tcpClientStream.Write(ntrIR.GetBytes(), 0, 84); byte[] inputredirection = new byte[] { b0, b1, 0x00, 0x00, //Buttons 0x00, 0x00, 0x00, 0x02, //Touch 0x00, 0x08, 0x80, 0x00 //Circle Pad }; Network.tcpClientStream.Write(inputredirection, 0, inputredirection.Length);
A no-input payload would like like: ff0f0000 | 00000002 | 00088000 (buttons | touch | circlepad)
Wireshark filter to not see that: data.len == 12 && !(data.data == ff:0f:00:00:00:00:00:02:00:08:80:00)
Bits “b0”: DULR SEBA 0000 YXLR = Down, Up, Left, Right, Start, Select (E), B, A
Bits “b1”: 4×0, Y, X, L, R
The 0's are always 0, and every normal button is 0 when pressed.
The best way to use the touchscreen is probably to use the same code as other Input Redirection clients.
X = (int)Math.Round(((double)X / 319) * 4095); Y = (int)Math.Round(((double)Y / 239) * 4095); uint touch = (uint)(X | (Y << 12) | (0x01 << 24)); if (touch != oldtouch) { byte[] bValue = BitConverter.GetBytes(touch); bValue.CopyTo(inputredirection, 4);
Again you probably should use the same code as other clients. I didn't for the Circle Pad I went for something I could understand later.
The Xbox 360/One controller uses 16 bits for each stick axis but the Circle Pad only uses 12 bits. Shaving off 4 bits removes some jitter anyway so you don't need to add your own deadzone code. It doesn't seem to matter if you leave the 4th byte set to 0x01 all the time.
uint leftX = (uint)(((report.Data[1] << 8) + (report.Data[0])) & 0xFFF0) >> 0x4; uint leftY = (uint)(((report.Data[3] << 8) + (report.Data[2])) & 0xFFF0) >> 0x4; uint circle = ((0xFFF - leftY) << 12) + leftX; if (oldcircle != circle) { byte[] bCircle = BitConverter.GetBytes(circle); bCircle[3] = 0x01; bCircle.CopyTo(inputredirection, 8);
Oh boy this just dropped for Luma and it supports ZL/ZR/C-Stick input redirection. The inputs are the same as NTR input redirection.
UDP Port: 4950
20 bytes = ff0f0000 | 00000002 | fff77f00 | 81008080 | 00000000 (buttons | touch | circle | c-stick | special)
Just continuously send it.
C-stick includes ZL/ZR. Replace that 0x00 with either ZL = 0x02 and/or ZR = 0x04;
int rightX = (((report.Data[5] << 8) + (report.Data[4])) & 0xFFF0) >> 0x08; int rightY = 0xFF - ((((report.Data[7] << 8) + (report.Data[6])) & 0xFFF0) >> 0x08); //Includes flip // The C-Stick needs to be rotated 45 degrees... // Read: https://stackoverflow.com/questions/2259476/rotating-a-point-about-another-point-2d double pX = rightX - 127; double pY = rightY - 127; byte rotatedCX = (byte)((pX * c - pY * s) + 127); byte rotatedCY = (byte)((pX * s + pY * c) + 127); uint cstick = (uint)(rotatedCX << 8) + (rotatedCY); if (oldz != z || oldcstick != cstick) { inputredirection[13] = z; inputredirection[14] = (byte)rotatedCX; inputredirection[15] = (byte)rotatedCY;
Just testing on the home menu it seems this is good enough to fix the rotation issue.
You might notice that the X and Y of the C-Stick are 8 bits each, but I reused the Xbox controller code taking 16 bytes of each to 12 bits. Ideally I should try to add deadzone or check that the highest bits are the ones being used.
The left most byte of Special includes:
So send the button you want then send 0x00 straight after to release it.