Advertisement
AndrewHaxalot

USBGecko.cs

Jan 29th, 2014
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 64.53 KB | None | 0 0
  1. #define DIRECT
  2.  
  3. using System;
  4. using System.IO;
  5. using System.Drawing;
  6. using System.Drawing.Imaging;
  7. using System.Runtime.InteropServices;
  8. using System.Runtime.Serialization.Formatters.Binary;
  9. using Ionic.Zip;
  10.  
  11. #if DIRECT
  12.     #if MONO
  13.         using libftdi;
  14.     #else
  15.         using D2XXDirect;
  16.     #endif
  17. #else
  18.     using FTD2XX_NET;
  19.     using FT_STATUS = FTD2XX_NET.FTDI.FT_STATUS;
  20. #endif
  21.  
  22. namespace FTDIUSBGecko
  23. {
  24.     public class ByteSwap
  25.     {
  26.         public static UInt16 Swap(UInt16 input)
  27.         {
  28.             if (BitConverter.IsLittleEndian)
  29.                 return ((UInt16)(
  30.                     ((0xFF00 & input) >> 8) |
  31.                     ((0x00FF & input) << 8)));
  32.             else
  33.                 return input;
  34.         }
  35.  
  36.         public static UInt32 Swap(UInt32 input)
  37.         {
  38.             if (BitConverter.IsLittleEndian)
  39.                 return ((UInt32)(
  40.                     ((0xFF000000 & input) >> 24) |
  41.                     ((0x00FF0000 & input) >> 8) |
  42.                     ((0x0000FF00 & input) << 8) |
  43.                     ((0x000000FF & input) << 24)));
  44.             else
  45.                 return input;
  46.         }
  47.  
  48.         public static UInt64 Swap(UInt64 input)
  49.         {
  50.             if (BitConverter.IsLittleEndian)
  51.                 return ((UInt64)(
  52.                     ((0xFF00000000000000 & input) >> 56) |
  53.                     ((0x00FF000000000000 & input) >> 40) |
  54.                     ((0x0000FF0000000000 & input) >> 24) |
  55.                     ((0x000000FF00000000 & input) >> 8) |
  56.                     ((0x00000000FF000000 & input) << 8) |
  57.                     ((0x0000000000FF0000 & input) << 24) |
  58.                     ((0x000000000000FF00 & input) << 40) |
  59.                     ((0x00000000000000FF & input) << 56)));
  60.             else
  61.                 return input;
  62.         }
  63.     }
  64.  
  65.     public class Dump
  66.     {
  67.         public Dump(UInt32 theStartAddress, UInt32 theEndAddress)
  68.         {
  69.             Construct(theStartAddress, theEndAddress, 0);
  70.         }
  71.  
  72.         public Dump(UInt32 theStartAddress, UInt32 theEndAddress, int theFileNumber)
  73.         {
  74.             Construct(theStartAddress, theEndAddress, theFileNumber);
  75.         }
  76.  
  77.         private void Construct(UInt32 theStartAddress, UInt32 theEndAddress, int theFileNumber)
  78.         {
  79.             startAddress = theStartAddress;
  80.             endAddress = theEndAddress;
  81.             readCompletedAddress = theStartAddress;
  82.             mem = new Byte[endAddress - startAddress];
  83.             fileNumber = theFileNumber;            
  84.         }
  85.    
  86.  
  87.         public UInt32 ReadAddress32(UInt32 addressToRead)
  88.         {
  89.             //dumpStream.Seek(addressToRead - startAddress, SeekOrigin.Begin);
  90.             //byte [] buffer = new byte[4];
  91.  
  92.             //dumpStream.Read(buffer, 0, 4);
  93.             if (addressToRead < startAddress) return 0;
  94.             if (addressToRead > endAddress - 4) return 0;
  95.             Byte[] buffer = new Byte[4];
  96.             Buffer.BlockCopy(mem, index(addressToRead), buffer, 0, 4);
  97.             //GeckoApp.SubArray<byte> buffer = new GeckoApp.SubArray<byte>(mem, (int)(addressToRead - startAddress), 4);
  98.  
  99.             //Read buffer
  100.             UInt32 result = BitConverter.ToUInt32(buffer, 0);
  101.  
  102.             //Swap to machine endianness and return
  103.             return ByteSwap.Swap(result);
  104.         }
  105.  
  106.         private int index(UInt32 addressToRead)
  107.         {
  108.             return (int)(addressToRead - startAddress);
  109.         }
  110.  
  111.         public UInt32 ReadAddress(UInt32 addressToRead, int numBytes)
  112.         {
  113.             if (addressToRead < startAddress) return 0;
  114.             if (addressToRead > endAddress - numBytes) return 0;
  115.            
  116.             Byte[] buffer = new Byte[4];
  117.             Buffer.BlockCopy(mem, index(addressToRead), buffer, 0, numBytes);
  118.  
  119.             //Read buffer
  120.             switch (numBytes)
  121.             {
  122.                 case 4:
  123.                     UInt32 result = BitConverter.ToUInt32(buffer, 0);
  124.  
  125.                     //Swap to machine endianness and return
  126.                     return ByteSwap.Swap(result);
  127.  
  128.                 case 2:
  129.                     UInt16 result16 = BitConverter.ToUInt16(buffer, 0);
  130.  
  131.                     //Swap to machine endianness and return
  132.                     return ByteSwap.Swap(result16);
  133.  
  134.                 default:
  135.                     return buffer[0];
  136.             }
  137.         }
  138.  
  139.         public void WriteStreamToDisk()
  140.         {
  141.             string myDirectory = Environment.CurrentDirectory + @"\searchdumps\";
  142.             if (!Directory.Exists(myDirectory))
  143.             {
  144.                 Directory.CreateDirectory(myDirectory);
  145.             }
  146.             string myFile = myDirectory + "dump" + fileNumber.ToString() + ".dmp";
  147.  
  148.             WriteStreamToDisk(myFile);
  149.         }
  150.  
  151.         public void WriteStreamToDisk(string filepath)
  152.         {
  153.             FileStream foo = new FileStream(filepath, FileMode.Create);
  154.             foo.Write(mem, 0, (int)(endAddress-startAddress));
  155.             foo.Close();
  156.             foo.Dispose();
  157.         }
  158.  
  159.         public void WriteCompressedStreamToDisk(string filepath)
  160.         {
  161.             ZipFile foo = new ZipFile(filepath);
  162.             foo.AddEntry("mem", mem);
  163.             foo.Dispose();
  164.         }
  165.  
  166.         public Byte[] mem;
  167.         private UInt32 startAddress;
  168.         public UInt32 StartAddress
  169.         {
  170.             get { return startAddress; }
  171.         }
  172.         private UInt32 endAddress;
  173.         public UInt32 EndAddress
  174.         {
  175.             get { return endAddress; }
  176.         }
  177.         private UInt32 readCompletedAddress;
  178.         public UInt32 ReadCompletedAddress
  179.         {
  180.             get { return readCompletedAddress; }
  181.             set { readCompletedAddress = value; }
  182.         }
  183.         private int fileNumber;
  184.     }
  185.  
  186.     public enum EUSBErrorCode {
  187.         FTDIQueryError,
  188.         noFTDIDevicesFound,
  189.         noUSBGeckoFound,
  190.         FTDIResetError,
  191.         FTDIPurgeRxError,
  192.         FTDIPurgeTxError,
  193.         FTDITimeoutSetError,
  194.         FTDITransferSetError,
  195.         FTDICommandSendError,
  196.         FTDIReadDataError,
  197.         FTDIInvalidReply,
  198.         TooManyRetries,
  199.         REGStreamSizeInvalid,
  200.         CheatStreamSizeInvalid
  201.     }
  202.  
  203.     public enum FTDICommand {
  204.         CMD_ResultError,
  205.         CMD_FatalError,
  206.         CMD_OK
  207.     }
  208.  
  209.     public enum WiiStatus {
  210.         Running,
  211.         Paused,
  212.         Breakpoint,
  213.         Loader,
  214.         Unknown
  215.     }
  216.  
  217.     public enum WiiLanguage {
  218.         NoOverride,
  219.         Japanese,
  220.         English,
  221.         German,
  222.         French,
  223.         Spanish,
  224.         Italian,
  225.         Dutch,
  226.         ChineseSimplified,
  227.         ChineseTraditional,
  228.         Korean
  229.     }
  230.     public enum WiiPatches {
  231.         NoPatches,
  232.         PAL60,
  233.         VIDTV,
  234.         PAL60VIDTV,
  235.         NTSC,
  236.         NTSCVIDTV,
  237.         PAL50,
  238.         PAL50VIDTV
  239.     }
  240.     public enum WiiHookType {
  241.         VI,
  242.         WiiRemote,
  243.         GamecubePad
  244.     }
  245.  
  246.     public delegate void GeckoProgress(UInt32 currentchunk, UInt32 allchunks, UInt32 transferred, UInt32 length, bool okay, bool dump);
  247.  
  248.     public class EUSBGeckoException : Exception
  249.     {
  250.         private EUSBErrorCode PErrorCode;
  251.         public EUSBErrorCode ErrorCode
  252.         {
  253.             get
  254.             {
  255.                 return PErrorCode;
  256.             }
  257.         }
  258.  
  259.         public EUSBGeckoException(EUSBErrorCode code)
  260.             : base()            
  261.         {
  262.             PErrorCode = code;
  263.         }
  264.         public EUSBGeckoException(EUSBErrorCode code, string message)
  265.             : base(message)
  266.         {
  267.             PErrorCode = code;
  268.         }
  269.         public EUSBGeckoException(EUSBErrorCode code, string message, Exception inner)
  270.             : base(message, inner)
  271.         {
  272.             PErrorCode = code;
  273.         }
  274.     }
  275.  
  276.     public class USBGecko
  277.     {
  278.         #if DIRECT
  279.             #if MONO
  280.                 private LFTDI PFTDI;
  281.             #else  
  282.                 private D2XXWrapper PFTDI;
  283.             #endif
  284.         #else  
  285.             private FTDI PFTDI;
  286.         #endif
  287.  
  288.         #region base constants
  289.         private const UInt32    packetsize = 0xF800;
  290.         private const UInt32 uplpacketsize = 0xF80;
  291.  
  292.         private const Byte      cmd_poke08 = 0x01;
  293.         private const Byte      cmd_poke16 = 0x02;
  294.         private const Byte     cmd_pokemem = 0x03;
  295.         private const Byte     cmd_readmem = 0x04;
  296.         private const Byte       cmd_pause = 0x06;
  297.         private const Byte    cmd_unfreeze = 0x07;
  298.         private const Byte  cmd_breakpoint = 0x09;
  299.         private const Byte cmd_breakpointx = 0x10;
  300.         private const Byte    cmd_sendregs = 0x2F;
  301.         private const Byte     cmd_getregs = 0x30;
  302.         private const Byte    cmd_cancelbp = 0x38;
  303.         private const Byte  cmd_sendcheats = 0x40;
  304.         private const Byte      cmd_upload = 0x41;
  305.         private const Byte        cmd_hook = 0x42;
  306.         private const Byte   cmd_hookpause = 0x43;
  307.         private const Byte        cmd_step = 0x44;
  308.         private const Byte      cmd_status = 0x50;
  309.         private const Byte   cmd_cheatexec = 0x60;
  310.         private const Byte cmd_nbreakpoint = 0x89;
  311.         private const Byte     cmd_version = 0x99;
  312.  
  313.         private const Byte         GCBPHit = 0x11;
  314.         private const Byte           GCACK = 0xAA;
  315.         private const Byte         GCRETRY = 0xBB;
  316.         private const Byte          GCFAIL = 0xCC;
  317.         private const Byte          GCDONE = 0xFF;
  318.  
  319.         private const Byte        GCNewVer = 0x80;
  320.  
  321.         private static readonly Byte[] GCAllowedVersions = new Byte[] { GCNewVer };
  322.  
  323.         private const Byte       BPExecute = 0x03;
  324.         private const Byte          BPRead = 0x05;
  325.         private const Byte         BPWrite = 0x06;
  326.         private const Byte     BPReadWrite = 0x07;
  327.         #endregion
  328.  
  329.         private event GeckoProgress PChunkUpdate;
  330.  
  331.         public event GeckoProgress chunkUpdate
  332.         {
  333.             add
  334.             {
  335.                 PChunkUpdate += value;
  336.             }
  337.             remove
  338.             {
  339.                 PChunkUpdate -= value;
  340.             }
  341.         }
  342.  
  343.         private bool PConnected;
  344.  
  345.         public bool connected
  346.         {
  347.             get
  348.             {
  349.                 return PConnected;
  350.             }
  351.         }
  352.  
  353.         private bool PCancelDump;
  354.  
  355.         public bool CancelDump
  356.         {
  357.             get
  358.             {
  359.                 return PCancelDump;
  360.             }
  361.             set
  362.             {
  363.                 PCancelDump = value;
  364.             }
  365.         }
  366.  
  367.         public USBGecko()
  368.         {
  369.             #if DIRECT
  370.                 #if MONO
  371.                     PFTDI = new LFTDI();
  372.                 #else
  373.                     PFTDI = new D2XXWrapper();
  374.                 #endif
  375.             #else  
  376.                 PFTDI = new FTDI();
  377.             #endif
  378.             PConnected = false;
  379.             PChunkUpdate = null;
  380.         }
  381.  
  382.         ~ USBGecko()
  383.         {
  384.             if (PConnected)
  385.                 Disconnect();
  386.         }
  387.  
  388.         protected bool InitGecko()
  389.         {
  390.           UInt32 FT_PURGE_RX = 1;
  391.             UInt32 FT_PURGE_TX = 2;
  392.  
  393.             FT_STATUS ftStatus = FT_STATUS.FT_OK;
  394.             //Reset device
  395.             ftStatus = PFTDI.ResetDevice();
  396.          if (ftStatus != FT_STATUS.FT_OK)
  397.             {
  398.                 Disconnect();
  399.                 throw new EUSBGeckoException(EUSBErrorCode.FTDIResetError);
  400.             }
  401.             //Purge RX buffers
  402.             ftStatus = PFTDI.Purge(FT_PURGE_RX);
  403.         if (ftStatus != FT_STATUS.FT_OK)
  404.             {
  405.                 Disconnect();
  406.                 throw new EUSBGeckoException(EUSBErrorCode.FTDIPurgeRxError);
  407.             }
  408.             //Purge TX buffers
  409.             ftStatus = PFTDI.Purge(FT_PURGE_TX);
  410.        if (ftStatus != FT_STATUS.FT_OK)
  411.             {
  412.                 Disconnect();
  413.                 throw new EUSBGeckoException(EUSBErrorCode.FTDIPurgeTxError);
  414.             }
  415.  
  416.             return true;
  417.         }
  418.  
  419.         public bool Connect()
  420.         {
  421.             if(PConnected)
  422.                 Disconnect();
  423.  
  424.             PConnected = false;
  425.  
  426.             UInt32 ftdiDeviceCount = 0;
  427.             FT_STATUS ftStatus = FT_STATUS.FT_OK;
  428.  
  429.           ftStatus = PFTDI.GetNumberOfDevices(ref ftdiDeviceCount);
  430.            //Check if device query works
  431.             if (ftStatus != FT_STATUS.FT_OK)
  432.             {
  433.                 Disconnect();
  434.                 throw new EUSBGeckoException(EUSBErrorCode.FTDIQueryError);
  435.             }
  436.             //Check if devices availible
  437.            if (ftdiDeviceCount == 0)
  438.             {
  439.                 Disconnect();
  440.                 throw new EUSBGeckoException(EUSBErrorCode.noFTDIDevicesFound);
  441.             }
  442.             //Open USB Gecko
  443.            ftStatus = PFTDI.OpenBySerialNumber("GECKUSB0");
  444.            if (ftStatus != FT_STATUS.FT_OK)
  445.             {
  446.                 // Don't disconnect if there's nothing connected
  447. #if !MONO
  448.                 Disconnect();
  449. #endif
  450.                 throw new EUSBGeckoException(EUSBErrorCode.noUSBGeckoFound);
  451.             }
  452.  
  453.             //Set Timeouts to 2 seconds
  454.             ftStatus = PFTDI.SetTimeouts(2000,2000);
  455.            if (ftStatus != FT_STATUS.FT_OK)
  456.             {
  457.                 Disconnect();
  458.                 throw new EUSBGeckoException(EUSBErrorCode.FTDITimeoutSetError);
  459.             }
  460. #if !MONO
  461.            byte LatencyTimer = 2;
  462.  
  463.            ftStatus = PFTDI.SetLatencyTimer(LatencyTimer);
  464.            if (ftStatus != FT_STATUS.FT_OK)
  465.            {
  466.                Disconnect();
  467.                throw new EUSBGeckoException(EUSBErrorCode.FTDITimeoutSetError);
  468.            }
  469. #endif
  470.  
  471.             //Set Transfer rate
  472.             ftStatus = PFTDI.InTransferSize(0x10000);
  473.            if (ftStatus != FT_STATUS.FT_OK)
  474.             {
  475.                 Disconnect();
  476.                 throw new EUSBGeckoException(EUSBErrorCode.FTDITimeoutSetError);
  477.             }
  478.  
  479.             //Initialise USB Gecko
  480.            if (InitGecko())
  481.             {
  482.                System.Threading.Thread.Sleep(150);
  483.                 PConnected = true;
  484.                 return true;
  485.             }
  486.             else
  487.                 return false;
  488.         }
  489.  
  490.         public void Disconnect()
  491.         {
  492.             PConnected = false;
  493.             PFTDI.Close();
  494.         }
  495.  
  496.         protected FTDICommand GeckoRead(Byte[] recbyte, UInt32 nobytes)
  497.         {
  498.             UInt32 bytes_read = 0;
  499.  
  500.             FT_STATUS ftStatus = PFTDI.Read(recbyte, nobytes, ref bytes_read);
  501.             if (ftStatus == FT_STATUS.FT_OK)
  502.             {
  503.                 if (bytes_read != nobytes)
  504.                 {
  505.                     return FTDICommand.CMD_ResultError;   // lost bytes in transmission
  506.                 }
  507.             }
  508.             else
  509.             {
  510.                 return FTDICommand.CMD_FatalError;       // fatal error
  511.             }
  512.  
  513.             return FTDICommand.CMD_OK;
  514.         }
  515.  
  516.         protected FTDICommand GeckoWrite(Byte[] sendbyte, Int32 nobytes)
  517.         {
  518.             UInt32 bytes_written = 0;
  519.  
  520.             FT_STATUS ftStatus = PFTDI.Write(sendbyte, nobytes, ref bytes_written);
  521.          if (ftStatus == FT_STATUS.FT_OK)
  522.             {
  523.                 if (bytes_written != nobytes)
  524.                 {
  525.                     return FTDICommand.CMD_ResultError;   // lost bytes in transmission
  526.                 }
  527.             }
  528.             else
  529.             {
  530.                 return FTDICommand.CMD_FatalError;       // fatal error
  531.             }
  532.  
  533.             return FTDICommand.CMD_OK;
  534.         }
  535.  
  536.         //Send update on a running process to the parent class
  537.         protected void SendUpdate(UInt32 currentchunk, UInt32 allchunks, UInt32 transferred, UInt32 length, bool okay, bool dump)
  538.         {
  539.             if (PChunkUpdate != null)
  540.                 PChunkUpdate(currentchunk, allchunks, transferred, length, okay, dump);
  541.         }
  542.  
  543.         public void Dump(Dump dump)
  544.         {
  545.             //Stream[] tempStream = { dump.dumpStream, dump.getOutputStream() };
  546.             //Stream[] tempStream = { dump.dumpStream };
  547.             //Dump(dump.startAddress, dump.endAddress, tempStream);
  548.             //dump.getOutputStream().Dispose();
  549.             //dump.WriteStreamToDisk();
  550.             Dump(dump.StartAddress, dump.EndAddress, dump);
  551.         }
  552.  
  553.         public void Dump(UInt32 startdump, UInt32 enddump, Stream saveStream)
  554.         {
  555.             Stream [] tempStream = { saveStream };
  556.             Dump(startdump, enddump, tempStream);
  557.         }
  558.  
  559.         public void Dump(UInt32 startdump, UInt32 enddump, Stream[] saveStream)
  560.         {
  561.             //Reset connection
  562.             InitGecko();
  563.  
  564.             if (GeckoApp.ValidMemory.rangeCheckId(startdump) != GeckoApp.ValidMemory.rangeCheckId(enddump))
  565.             {
  566.                 enddump = GeckoApp.ValidMemory.ValidAreas[GeckoApp.ValidMemory.rangeCheckId(startdump)].high;
  567.             }
  568.  
  569.             if (!GeckoApp.ValidMemory.validAddress(startdump)) return;
  570.  
  571.             //How many bytes of data have to be transferred
  572.             UInt32 memlength = enddump - startdump;
  573.  
  574.             //How many chunks do I need to split this data into
  575.             //How big ist the last chunk
  576.             UInt32 fullchunks = memlength / packetsize;
  577.             UInt32 lastchunk = memlength % packetsize;
  578.  
  579.             //How many chunks do I need to transfer
  580.             UInt32 allchunks = fullchunks;
  581.             if (lastchunk > 0)
  582.                 allchunks++;
  583.  
  584.             UInt64 GeckoMemRange = ByteSwap.Swap((UInt64)(((UInt64)startdump << 32) + ((UInt64)enddump)));
  585.             if (GeckoWrite(BitConverter.GetBytes(cmd_readmem), 1) != FTDICommand.CMD_OK)
  586.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  587.  
  588.             //Read reply - expcecting GCACK
  589.             Byte retry = 0;
  590.             while (retry < 10)
  591.             {
  592.                 Byte[] response = new Byte[1];
  593.                 if (GeckoRead(response, 1) != FTDICommand.CMD_OK)
  594.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  595.                 Byte reply = response[0];
  596.                 if (reply == GCACK)
  597.                     break;
  598.                 if (retry == 9)
  599.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIInvalidReply);
  600.             }
  601.  
  602.             //Now let's send the dump information
  603.             if (GeckoWrite(BitConverter.GetBytes(GeckoMemRange), 8) != FTDICommand.CMD_OK)
  604.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  605.  
  606.             //We start with chunk 0
  607.             UInt32 chunk = 0;
  608.             retry = 0;
  609.  
  610.             // Reset cancel flag
  611.             bool done = false;
  612.             CancelDump = false;
  613.  
  614.             Byte[] buffer = new Byte[packetsize]; //read buffer
  615.             while (chunk < fullchunks && !done)
  616.             {
  617.                 //No output yet availible
  618.                 SendUpdate(chunk, allchunks, chunk * packetsize, memlength, retry == 0, true);
  619.                 //Set buffer
  620.                 FTDICommand returnvalue = GeckoRead(buffer, packetsize);
  621.                 if (returnvalue == FTDICommand.CMD_ResultError)
  622.                 {
  623.                     retry++;
  624.                     if (retry >= 3)
  625.                     {
  626.                         //Give up, too many retries
  627.                         GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  628.                         throw new EUSBGeckoException(EUSBErrorCode.TooManyRetries);
  629.                     }
  630.                     GeckoWrite(BitConverter.GetBytes(GCRETRY), 1);
  631.                     continue;
  632.                 }
  633.                 else if (returnvalue == FTDICommand.CMD_FatalError)
  634.                 {
  635.                     //Major fail, give it up
  636.                     GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  637.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  638.                 }
  639.                 //write received package to output stream
  640.                 foreach (Stream stream in saveStream)
  641.                 {
  642.                     stream.Write(buffer, 0, ((Int32)packetsize));
  643.                 }
  644.  
  645.                 //reset retry counter
  646.                 retry = 0;
  647.                 //next chunk
  648.                 chunk++;
  649.  
  650.                 if (!CancelDump)
  651.                 {
  652.                     //ackowledge package
  653.                     GeckoWrite(BitConverter.GetBytes(GCACK), 1);
  654.                 }
  655.                 else
  656.                 {
  657.                     // User requested a cancel
  658.                     GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  659.                     done = true;
  660.                 }
  661.             }
  662.  
  663.             //Final package?
  664.             while (!done)
  665.             {
  666.                 //No output yet availible
  667.                 SendUpdate(chunk, allchunks, chunk * packetsize, memlength, retry == 0, true);
  668.                 //Set buffer
  669.                 // buffer = new Byte[lastchunk];
  670.                 FTDICommand returnvalue = GeckoRead(buffer, lastchunk);
  671.                 if (returnvalue == FTDICommand.CMD_ResultError)
  672.                 {
  673.                     retry++;
  674.                     if (retry >= 3)
  675.                     {
  676.                         //Give up, too many retries
  677.                         GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  678.                         throw new EUSBGeckoException(EUSBErrorCode.TooManyRetries);
  679.                     }
  680.                     GeckoWrite(BitConverter.GetBytes(GCRETRY), 1);
  681.                     continue;
  682.                 }
  683.                 else if (returnvalue == FTDICommand.CMD_FatalError)
  684.                 {
  685.                     //Major fail, give it up
  686.                     GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  687.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  688.                 }
  689.                 //write received package to output stream
  690.                 foreach (Stream stream in saveStream)
  691.                 {
  692.                     stream.Write(buffer, 0, ((Int32)lastchunk));
  693.                 }
  694.                 //reset retry counter
  695.                 retry = 0;
  696.                 //cancel while loop
  697.                 done = true;
  698.                 //ackowledge package
  699.                 GeckoWrite(BitConverter.GetBytes(GCACK), 1);
  700.             }
  701.             SendUpdate(allchunks, allchunks, memlength, memlength, true, true);
  702.         }
  703.  
  704.  
  705.         public void Dump(UInt32 startdump, UInt32 enddump, Dump memdump)
  706.         {
  707.             //Reset connection
  708.             InitGecko();
  709.  
  710.             //How many bytes of data have to be transferred
  711.             UInt32 memlength = enddump - startdump;
  712.  
  713.             //How many chunks do I need to split this data into
  714.             //How big ist the last chunk
  715.             UInt32 fullchunks = memlength / packetsize;
  716.             UInt32 lastchunk = memlength % packetsize;
  717.  
  718.             //How many chunks do I need to transfer
  719.             UInt32 allchunks = fullchunks;
  720.             if (lastchunk > 0)
  721.                 allchunks++;
  722.  
  723.             UInt64 GeckoMemRange = ByteSwap.Swap((UInt64)(((UInt64)startdump << 32) + ((UInt64)enddump)));
  724.             if (GeckoWrite(BitConverter.GetBytes(cmd_readmem), 1) != FTDICommand.CMD_OK)
  725.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  726.  
  727.             //Read reply - expcecting GCACK
  728.             Byte retry = 0;
  729.             while (retry < 10)
  730.             {
  731.                 Byte[] response = new Byte[1];
  732.                 if (GeckoRead(response, 1) != FTDICommand.CMD_OK)
  733.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  734.                 Byte reply = response[0];
  735.                 if (reply == GCACK)
  736.                     break;
  737.                 if (retry == 9)
  738.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIInvalidReply);
  739.             }
  740.  
  741.             //Now let's send the dump information
  742.             if (GeckoWrite(BitConverter.GetBytes(GeckoMemRange), 8) != FTDICommand.CMD_OK)
  743.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  744.  
  745.             //We start with chunk 0
  746.             UInt32 chunk = 0;
  747.             retry = 0;
  748.  
  749.             // Reset cancel flag
  750.             bool done = false;
  751.             CancelDump = false;
  752.  
  753.             Byte[] buffer = new Byte[packetsize]; //read buffer
  754.             //GeckoApp.SubArray<Byte> buffer;
  755.             while (chunk < fullchunks && !done)
  756.             {
  757.                 //buffer = new SubArray<byte>(mem, chunk*packetsize, packetsize);
  758.                 //No output yet availible
  759.                 SendUpdate(chunk, allchunks, chunk * packetsize, memlength, retry == 0, true);
  760.                 //Set buffer
  761.                 FTDICommand returnvalue = GeckoRead(buffer, packetsize);
  762.                 if (returnvalue == FTDICommand.CMD_ResultError)
  763.                 {
  764.                     retry++;
  765.                     if (retry >= 3)
  766.                     {
  767.                         //Give up, too many retries
  768.                         GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  769.                         throw new EUSBGeckoException(EUSBErrorCode.TooManyRetries);
  770.                     }
  771.                     GeckoWrite(BitConverter.GetBytes(GCRETRY), 1);
  772.                     continue;
  773.                 }
  774.                 else if (returnvalue == FTDICommand.CMD_FatalError)
  775.                 {
  776.                     //Major fail, give it up
  777.                     GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  778.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  779.                 }
  780.                 //write received package to output stream
  781.                 //foreach (Stream stream in saveStream)
  782.                 //{
  783.                 //    stream.Write(buffer, 0, ((Int32)packetsize));
  784.                 //}
  785.  
  786.                 Buffer.BlockCopy(buffer, 0, memdump.mem, (int)(chunk * packetsize + (startdump - memdump.StartAddress)), (int)packetsize);
  787.  
  788.                 memdump.ReadCompletedAddress = (UInt32)((chunk + 1) * packetsize + startdump);
  789.  
  790.                 //reset retry counter
  791.                 retry = 0;
  792.                 //next chunk
  793.                 chunk++;
  794.  
  795.                 if (!CancelDump)
  796.                 {
  797.                     //ackowledge package
  798.                     GeckoWrite(BitConverter.GetBytes(GCACK), 1);
  799.                 }
  800.                 else
  801.                 {
  802.                     // User requested a cancel
  803.                     GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  804.                     done = true;
  805.                 }
  806.             }
  807.  
  808.             //Final package?
  809.             while (!done)
  810.             {
  811.                 //buffer = new SubArray<byte>(mem, chunk * packetsize, lastchunk);
  812.                 //No output yet availible
  813.                 SendUpdate(chunk, allchunks, chunk * packetsize, memlength, retry == 0, true);
  814.                 //Set buffer
  815.                 // buffer = new Byte[lastchunk];
  816.                 FTDICommand returnvalue = GeckoRead(buffer, lastchunk);
  817.                 if (returnvalue == FTDICommand.CMD_ResultError)
  818.                 {
  819.                     retry++;
  820.                     if (retry >= 3)
  821.                     {
  822.                         //Give up, too many retries
  823.                         GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  824.                         throw new EUSBGeckoException(EUSBErrorCode.TooManyRetries);
  825.                     }
  826.                     GeckoWrite(BitConverter.GetBytes(GCRETRY), 1);
  827.                     continue;
  828.                 }
  829.                 else if (returnvalue == FTDICommand.CMD_FatalError)
  830.                 {
  831.                     //Major fail, give it up
  832.                     GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  833.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  834.                 }
  835.                 //write received package to output stream
  836.                 //foreach (Stream stream in saveStream)
  837.                 //{
  838.                 //    stream.Write(buffer, 0, ((Int32)lastchunk));
  839.                 //}
  840.  
  841.                 Buffer.BlockCopy(buffer, 0, memdump.mem, (int)(chunk * packetsize + (startdump - memdump.StartAddress)), (int)lastchunk);
  842.                
  843.  
  844.                 //reset retry counter
  845.                 retry = 0;
  846.                 //cancel while loop
  847.                 done = true;
  848.                 //ackowledge package
  849.                 GeckoWrite(BitConverter.GetBytes(GCACK), 1);
  850.             }
  851.             SendUpdate(allchunks, allchunks, memlength, memlength, true, true);
  852.         }
  853.  
  854.         public void Upload(UInt32 startupload, UInt32 endupload, Stream sendStream)
  855.         {
  856.             //Reset connection
  857.             InitGecko();
  858.  
  859.             //How many bytes of data have to be transferred
  860.             UInt32 memlength = endupload - startupload;
  861.  
  862.             //How many chunks do I need to split this data into
  863.             //How big ist the last chunk
  864.             UInt32 fullchunks = memlength / uplpacketsize;
  865.             UInt32 lastchunk = memlength % uplpacketsize;
  866.  
  867.             //How many chunks do I need to transfer
  868.             UInt32 allchunks = fullchunks;
  869.             if (lastchunk > 0)
  870.                 allchunks++;
  871.  
  872.             UInt64 GeckoMemRange = ByteSwap.Swap((UInt64)(((UInt64)startupload << 32) + ((UInt64)endupload)));
  873.             if (GeckoWrite(BitConverter.GetBytes(cmd_upload), 1) != FTDICommand.CMD_OK)
  874.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  875.  
  876.             //Read reply - expcecting GCACK
  877.             Byte retry = 0;
  878.             while (retry < 10)
  879.             {
  880.                 Byte[] response = new Byte[1];
  881.                 if (GeckoRead(response, 1) != FTDICommand.CMD_OK)
  882.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  883.                 Byte reply = response[0];
  884.                 if (reply == GCACK)
  885.                     break;
  886.                 if (retry == 9)
  887.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIInvalidReply);
  888.             }
  889.  
  890.             //Now let's send the upload information
  891.             if (GeckoWrite(BitConverter.GetBytes(GeckoMemRange), 8) != FTDICommand.CMD_OK)
  892.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  893.  
  894.             //We start with chunk 0
  895.             UInt32 chunk = 0;
  896.             retry = 0;
  897.  
  898.             Byte[] buffer; //read buffer
  899.             while (chunk < fullchunks)
  900.             {
  901.                 //No output yet availible
  902.                 SendUpdate(chunk, allchunks, chunk * packetsize, memlength, retry == 0, false);
  903.                 //Set buffer
  904.                 buffer = new Byte[uplpacketsize];
  905.                 //Read buffer from stream
  906.                 sendStream.Read(buffer, 0, (int)uplpacketsize);
  907.                 FTDICommand returnvalue = GeckoWrite(buffer, (int)uplpacketsize);
  908.                 if (returnvalue == FTDICommand.CMD_ResultError)
  909.                 {
  910.                     retry++;
  911.                     if (retry >= 3)
  912.                     {
  913.                         //Give up, too many retries
  914.                         GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  915.                         throw new EUSBGeckoException(EUSBErrorCode.TooManyRetries);
  916.                     }
  917.                     //Reset stream
  918.                     sendStream.Seek((-1)*((int)uplpacketsize), SeekOrigin.Current);
  919.                     GeckoWrite(BitConverter.GetBytes(GCRETRY), 1);
  920.                     continue;
  921.                 }
  922.                 else if (returnvalue == FTDICommand.CMD_FatalError)
  923.                 {
  924.                     //Major fail, give it up
  925.                     GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  926.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  927.                 }
  928.                 //reset retry counter
  929.                 retry = 0;
  930.                 //next chunk
  931.                 chunk++;
  932.                 //ackowledge package
  933.                 GeckoWrite(BitConverter.GetBytes(GCACK), 1);
  934.             }
  935.  
  936.             //Final package?
  937.             while (lastchunk > 0)
  938.             {
  939.                 //No output yet availible
  940.                 SendUpdate(chunk, allchunks, chunk * packetsize, memlength, retry == 0, false);
  941.                 //Set buffer
  942.                 buffer = new Byte[lastchunk];
  943.                 //Read buffer from stream
  944.                 sendStream.Read(buffer, 0, (int)lastchunk);
  945.                 FTDICommand returnvalue = GeckoRead(buffer, lastchunk);
  946.                 if (returnvalue == FTDICommand.CMD_ResultError)
  947.                 {
  948.                     retry++;
  949.                     if (retry >= 3)
  950.                     {
  951.                         //Give up, too many retries
  952.                         GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  953.                         throw new EUSBGeckoException(EUSBErrorCode.TooManyRetries);
  954.                     }
  955.                     //Reset stream
  956.                     sendStream.Seek((-1) * ((int)lastchunk), SeekOrigin.Current);
  957.                     GeckoWrite(BitConverter.GetBytes(GCRETRY), 1);
  958.                     continue;
  959.                 }
  960.                 else if (returnvalue == FTDICommand.CMD_FatalError)
  961.                 {
  962.                     //Major fail, give it up
  963.                     GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  964.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  965.                 }
  966.                 //reset retry counter
  967.                 retry = 0;
  968.                 //cancel while loop
  969.                 lastchunk = 0;
  970.                 //ackowledge package
  971.                 GeckoWrite(BitConverter.GetBytes(GCACK), 1);
  972.             }
  973.             SendUpdate(allchunks, allchunks, memlength, memlength, true, false);
  974.         }
  975.  
  976.         public bool Reconnect()
  977.         {
  978.             Disconnect();
  979.             try
  980.             {
  981.                 return Connect();
  982.             }
  983.             catch
  984.             {
  985.                 return false;
  986.             }
  987.         }
  988.  
  989.         //Allows sending a basic one byte command to the Wii
  990.         public FTDICommand RawCommand(Byte id)
  991.         {
  992.             return GeckoWrite(BitConverter.GetBytes(id), 1);
  993.         }
  994.  
  995.         //Pauses the game
  996.         public void Pause()
  997.         {
  998.             //Only needs to send a cmd_pause to Wii
  999.             if (RawCommand(cmd_pause) != FTDICommand.CMD_OK)
  1000.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1001.         }
  1002.  
  1003.         // Tries to repeatedly pause the game until it succeeds
  1004.         public void SafePause()
  1005.         {
  1006.             bool WasRunning = (status() == WiiStatus.Running);
  1007.             while (WasRunning)
  1008.             {
  1009.                 Pause();
  1010.                 System.Threading.Thread.Sleep(100);
  1011.                 // Sometimes, the game doesn't actually pause...
  1012.                 // So loop repeatedly until it does!
  1013.                 WasRunning = (status() == WiiStatus.Running);
  1014.             }
  1015.         }
  1016.  
  1017.         //Unpauses the game
  1018.         public void Resume()
  1019.         {
  1020.             //Only needs to send a cmd_unfreeze to Wii
  1021.             if (RawCommand(cmd_unfreeze) != FTDICommand.CMD_OK)
  1022.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1023.         }
  1024.  
  1025.         // Tries repeatedly to resume the game until it succeeds
  1026.         public void SafeResume()
  1027.         {
  1028.             bool NotRunning = (status() != WiiStatus.Running);
  1029.             int failCounter = 0;
  1030.             while (NotRunning && failCounter < 10)
  1031.             {
  1032.                 Resume();
  1033.                 System.Threading.Thread.Sleep(100);
  1034.                 // Sometimes, the game doesn't actually resume...
  1035.                 // So loop repeatedly until it does!
  1036.                 try
  1037.                 {
  1038.                     NotRunning = (status() != WiiStatus.Running);
  1039.                 }
  1040.                 catch (FTDIUSBGecko.EUSBGeckoException ex)
  1041.                 {
  1042.                     NotRunning = true;
  1043.                     failCounter++;
  1044.                 }
  1045.             }
  1046.         }
  1047.  
  1048.         //Sends a GCFAIL to the game.. in case the Gecko handler hangs.. sendfail might solve it!
  1049.         public void sendfail()
  1050.         {
  1051.             //Only needs to send a cmd_unfreeze to Wii
  1052.             //Ignores the reply, send this command multiple times!
  1053.             RawCommand(GCFAIL);
  1054.         }
  1055.  
  1056.         #region poke commands
  1057.         //Poke a 32 bit value - note: address and value must be all in endianness of sending platform
  1058.         public void poke(UInt32 address, UInt32 value)
  1059.         {
  1060.             //Lower address
  1061.             address &= 0xFFFFFFFC;
  1062.  
  1063.             //value = send [address in big endian] [value in big endian]
  1064.             UInt64 PokeVal = ( ((UInt64)address) << 32) | ((UInt64) value);
  1065.  
  1066.             PokeVal = ByteSwap.Swap(PokeVal);
  1067.  
  1068.             //Send poke
  1069.             if (RawCommand(cmd_pokemem)!=FTDICommand.CMD_OK)
  1070.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1071.  
  1072.             //write value
  1073.             if (GeckoWrite(BitConverter.GetBytes(PokeVal), 8)!=FTDICommand.CMD_OK)
  1074.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1075.         }
  1076.  
  1077.         //Copy of poke, just poke32 to make clear it is a 32-bit poke
  1078.         public void poke32(UInt32 address, UInt32 value)
  1079.         {
  1080.             poke(address, value);
  1081.         }
  1082.        
  1083.         //Poke a 16 bit value - note: address and value must be all in endianness of sending platform
  1084.         public void poke16(UInt32 address, UInt16 value)
  1085.         {
  1086.             //Lower address
  1087.             address &= 0xFFFFFFFE;
  1088.  
  1089.             //value = send [address in big endian] [value in big endian]
  1090.             UInt64 PokeVal = (((UInt64)address) << 32) | ((UInt64)value);
  1091.  
  1092.             PokeVal = ByteSwap.Swap(PokeVal);
  1093.  
  1094.             //Send poke16
  1095.             if (RawCommand(cmd_poke16) != FTDICommand.CMD_OK)
  1096.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1097.  
  1098.             //write value
  1099.             if (GeckoWrite(BitConverter.GetBytes(PokeVal), 8) != FTDICommand.CMD_OK)
  1100.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1101.         }
  1102.  
  1103.         //Poke a 08 bit value - note: address and value must be all in endianness of sending platform
  1104.         public void poke08(UInt32 address, Byte value)
  1105.         {
  1106.             //value = send [address in big endian] [value in big endian]
  1107.             UInt64 PokeVal = (((UInt64)address) << 32) | ((UInt64)value);
  1108.  
  1109.             PokeVal = ByteSwap.Swap(PokeVal);
  1110.  
  1111.             //Send poke08
  1112.             if (RawCommand(cmd_poke08) != FTDICommand.CMD_OK)
  1113.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1114.  
  1115.             //write value
  1116.             if (GeckoWrite(BitConverter.GetBytes(PokeVal), 8) != FTDICommand.CMD_OK)
  1117.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1118.         }
  1119.         #endregion
  1120.  
  1121.         //Returns the console status
  1122.         public WiiStatus status()
  1123.         {
  1124.             System.Threading.Thread.Sleep(100);
  1125.             //Initialise Gecko
  1126.             if (!InitGecko())
  1127.                 throw new EUSBGeckoException(EUSBErrorCode.FTDIResetError);
  1128.  
  1129.             //Send status command
  1130.             if (RawCommand(cmd_status) != FTDICommand.CMD_OK)
  1131.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1132.  
  1133. //          System.Threading.Thread.Sleep(10);
  1134.            
  1135.             //Read status
  1136.             Byte[] buffer=new Byte[1];
  1137.             if (GeckoRead(buffer, 1) != FTDICommand.CMD_OK)
  1138.                 throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  1139.  
  1140.             //analyse reply
  1141.             switch (buffer[0])
  1142.             {
  1143.                  case 0: return WiiStatus.Running;
  1144.                  case 1: return WiiStatus.Paused;
  1145.                  case 2: return WiiStatus.Breakpoint;
  1146.                  case 3: return WiiStatus.Loader;
  1147.                 default: return WiiStatus.Unknown;
  1148.             }
  1149.         }
  1150.  
  1151.         //Step to the next frame
  1152.         public void Step()
  1153.         {
  1154.             //Reset buffers
  1155.             if (!InitGecko())
  1156.                 throw new EUSBGeckoException(EUSBErrorCode.FTDIResetError);
  1157.  
  1158.             //Send step command
  1159.             if (RawCommand(cmd_step) != FTDICommand.CMD_OK)
  1160.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1161.         }
  1162.  
  1163.         #region breakpoint crap
  1164.         //Initialise a basic data breakpoint
  1165.         //address = Which address should the breakpoint be added on
  1166.         //bptype = how many bytes need to be added to the 8 byte aligned address - 5 for read, 6 for write, 7 for rw
  1167.         //exact = only break if the exact address is being accessed
  1168.         protected void Breakpoint(UInt32 address, Byte bptype, bool exact)
  1169.         {
  1170.             InitGecko();
  1171.  
  1172.             UInt32 lowaddr = (address & 0xFFFFFFF8) | bptype;
  1173.               //Actual address to put the breakpoint - the identity adder is applied to it
  1174.  
  1175.             bool useGeckoBP = false;
  1176.             if (exact)
  1177.                 useGeckoBP = (VersionRequest() >= GCNewVer);
  1178.  
  1179.             if (!useGeckoBP) //classic PPC breakpoint
  1180.             {
  1181.                 if (RawCommand(cmd_breakpoint) != FTDICommand.CMD_OK)
  1182.                     throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1183.  
  1184.                 //Convert lowaddr to BigEndian
  1185.                 UInt32 breakpaddr = ByteSwap.Swap(lowaddr);
  1186.  
  1187.                 if (GeckoWrite(BitConverter.GetBytes(breakpaddr),4)!=FTDICommand.CMD_OK)
  1188.                     throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1189.             }
  1190.             else //advanced exact Gecko breakpoint
  1191.             {
  1192.                 if (RawCommand(cmd_nbreakpoint) != FTDICommand.CMD_OK)
  1193.                     throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1194.  
  1195.                 UInt64 breakpaddr = ((UInt64)lowaddr) << 32 | ((UInt64)address);
  1196.                 breakpaddr = ByteSwap.Swap(breakpaddr);
  1197.  
  1198.                 if (GeckoWrite(BitConverter.GetBytes(breakpaddr), 8) != FTDICommand.CMD_OK)
  1199.                     throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1200.             }
  1201.         }
  1202.  
  1203.         //Read breakpoint
  1204.         public void BreakpointR(UInt32 address, bool exact)
  1205.         {
  1206.             Breakpoint(address, BPRead, exact);
  1207.         }
  1208.         public void BreakpointR(UInt32 address)
  1209.         {
  1210.             Breakpoint(address, BPRead, true);
  1211.         }
  1212.  
  1213.         //Write breakpoint
  1214.         public void BreakpointW(UInt32 address, bool exact)
  1215.         {
  1216.             Breakpoint(address, BPWrite, exact);
  1217.         }
  1218.         public void BreakpointW(UInt32 address)
  1219.         {
  1220.             Breakpoint(address, BPWrite, true);
  1221.         }
  1222.  
  1223.         //Read/Write breakpoint
  1224.         public void BreakpointRW(UInt32 address, bool exact)
  1225.         {
  1226.             Breakpoint(address, BPReadWrite, exact);
  1227.         }
  1228.         public void BreakpointRW(UInt32 address)
  1229.         {
  1230.             Breakpoint(address, BPReadWrite, true);
  1231.         }
  1232.  
  1233.        
  1234.         //Execute breakpoints require a different command and different parameters
  1235.         //address = address to put the breakpoint on
  1236.         public void BreakpointX(UInt32 address)
  1237.         {
  1238.             InitGecko();
  1239.  
  1240.             //Unlike Data breakpoints Execute breakpoints are exact to 4 bytes
  1241.             UInt32 baddress = ByteSwap.Swap(((UInt32)(address & 0xFFFFFFFC) | BPExecute));
  1242.  
  1243.             //Send breakpoint execute command
  1244.             if (RawCommand(cmd_breakpointx) != FTDICommand.CMD_OK)
  1245.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1246.  
  1247.             //Send address to handler
  1248.             if(GeckoWrite(BitConverter.GetBytes(baddress),4) != FTDICommand.CMD_OK)
  1249.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1250.         }
  1251.  
  1252.         //Returns true once a Breakpoint has hit
  1253.         //Function is depricated use status function instead - only for backwards compatibility with Delphi ports!
  1254.         public bool BreakpointHit()
  1255.         {
  1256.             Byte[] buffer = new Byte[1];
  1257.            
  1258.             if (GeckoRead(buffer, 1) != FTDICommand.CMD_OK)
  1259.                 return false;
  1260.  
  1261.             //did we receive a bphit signal?
  1262.             return (buffer[0] == GCBPHit);
  1263.         }
  1264.  
  1265.         //Cancels running breakpoints
  1266.         //doesn't work thanks to a malfunction of current gecko handlers!
  1267.         public void CancelBreakpoint()
  1268.         {
  1269.             if (RawCommand(cmd_cancelbp) != FTDICommand.CMD_OK)
  1270.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1271.         }
  1272. #endregion
  1273.  
  1274.         //Is this version code a correct Gecko version?
  1275.         protected bool AllowedVersion(Byte version)
  1276.         {
  1277.             for (int i = 0; i < GCAllowedVersions.Length; i++)
  1278.                 if (GCAllowedVersions[i] == version)
  1279.                     return true;
  1280.             return false;
  1281.         }
  1282.  
  1283.         public Byte VersionRequest()
  1284.         {
  1285.             InitGecko();
  1286.  
  1287.             if (RawCommand(cmd_version) != FTDICommand.CMD_OK)
  1288.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1289.  
  1290.             Byte retries = 0;
  1291.             Byte result = 0;
  1292.             Byte[] buffer = new Byte[1];
  1293.  
  1294.             //try to receive a version 3 times.. if it really does not return anything useful give up!
  1295.             do
  1296.             {
  1297.                 if (GeckoRead(buffer, 1) == FTDICommand.CMD_OK)
  1298.                 {
  1299.                     if (AllowedVersion(buffer[0]))
  1300.                     {
  1301.                         result = buffer[0];
  1302.                         break;
  1303.                     }
  1304.                 }
  1305.                 retries++;
  1306.             } while (retries < 3);
  1307.  
  1308.             return result;
  1309.         }
  1310.  
  1311.         public UInt32 peek(UInt32 address)
  1312.         {
  1313.             if (!GeckoApp.ValidMemory.validAddress(address))
  1314.             {
  1315.                 return 0;
  1316.             }
  1317.  
  1318.             //address will be alligned to 4
  1319.             UInt32 paddress=address & 0xFFFFFFFC;
  1320.  
  1321.             //Create a memory stream for the actual dump
  1322.             MemoryStream stream = new MemoryStream();
  1323.  
  1324.             //make sure to not send data to the output
  1325.             GeckoProgress oldUpdate = PChunkUpdate;
  1326.             PChunkUpdate = null;
  1327.  
  1328.             try
  1329.             {
  1330.  
  1331.                 //dump data
  1332.                 Dump(paddress, paddress + 4, stream);
  1333.  
  1334.                 //go to beginning
  1335.                 stream.Seek(0, SeekOrigin.Begin);
  1336.                 Byte[] buffer = new Byte[4];
  1337.                 stream.Read(buffer, 0, 4);
  1338.  
  1339.                 //Read buffer
  1340.                 UInt32 result = BitConverter.ToUInt32(buffer, 0);
  1341.  
  1342.                 //Swap to machine endianness and return
  1343.                 result = ByteSwap.Swap(result);
  1344.  
  1345.                 return result;
  1346.             }
  1347.             finally
  1348.             {
  1349.                 PChunkUpdate = oldUpdate;
  1350.                
  1351.                 //make sure the Stream is properly closed
  1352.                 stream.Close();
  1353.             }
  1354.         }
  1355.  
  1356.         #region register operations
  1357.         //Read registers in breakpoint cases
  1358.         public void GetRegisters(Stream stream)
  1359.         {
  1360.             //Check Gecko version
  1361.             bool includeFloatRegisters = (VersionRequest() >= GCNewVer);
  1362.  
  1363.             //In case we use a new Gecko we receive more data from the console:
  1364.             UInt32 bytesExpected;
  1365.             if (includeFloatRegisters)
  1366.                 bytesExpected = 0x120;
  1367.             else
  1368.                 bytesExpected = 0x0A0;
  1369.  
  1370.             //Send command
  1371.             if (RawCommand(cmd_getregs) != FTDICommand.CMD_OK)
  1372.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1373.  
  1374.             //Read registers
  1375.             Byte[] buffer = new Byte[bytesExpected];
  1376.             if (GeckoRead(buffer, bytesExpected) != FTDICommand.CMD_OK)
  1377.                 throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  1378.  
  1379.             //Store registers to output stream!
  1380.             stream.Write(buffer, 0, ((Int32)bytesExpected));
  1381.         }
  1382.  
  1383.         //Send registers
  1384.         public void SendRegisters(Stream sendStream)
  1385.         {
  1386.             InitGecko();
  1387.  
  1388.             //FP registers cannot be sent!
  1389.             const Int32 bytesExpected = 0xA0;
  1390.  
  1391.             if (sendStream.Length != bytesExpected)
  1392.                 throw new EUSBGeckoException(EUSBErrorCode.REGStreamSizeInvalid);
  1393.  
  1394.             //Fill buffer
  1395.             Byte[] buffer = new Byte[bytesExpected];
  1396.             sendStream.Seek(0, SeekOrigin.Begin);
  1397.             sendStream.Read(buffer, 0, bytesExpected);
  1398.  
  1399.             //Initialize send command
  1400.             if (RawCommand(cmd_sendregs) != FTDICommand.CMD_OK)
  1401.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1402.  
  1403.             //Check GCACK reply with 3 retries!
  1404.             Byte retries = 0;
  1405.             while (retries < 3)
  1406.             {
  1407.                 Byte[] rpbuffer = new Byte[1];
  1408.                 if (GeckoRead(rpbuffer, 1) != FTDICommand.CMD_OK)
  1409.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  1410.  
  1411.                 if (rpbuffer[0] == GCACK)
  1412.                     break;
  1413.  
  1414.                 retries++;
  1415.                 if (retries == 3)
  1416.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  1417.             }
  1418.  
  1419.             retries = 0;
  1420.             while (retries < 3)
  1421.             {
  1422.                 //Try to send data
  1423.                 FTDICommand answer = GeckoWrite(buffer, bytesExpected);
  1424.                 //Check answer
  1425.                 if (answer == FTDICommand.CMD_ResultError)
  1426.                 {
  1427.                     retries++;
  1428.                     if (retries >= 3)
  1429.                     {
  1430.                         //Too many retries, give up
  1431.                         RawCommand(GCFAIL);
  1432.                         throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1433.                     }
  1434.                     RawCommand(GCRETRY);
  1435.                     continue;
  1436.                 }
  1437.                 else if (answer == FTDICommand.CMD_FatalError)
  1438.                 {
  1439.                     //Major fail, give up!
  1440.                     RawCommand(GCFAIL);
  1441.                     throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1442.                 }
  1443.                 break;
  1444.             }
  1445.         }
  1446.         #endregion
  1447.  
  1448.         #region Cheat related stuff
  1449.         private UInt64 readInt64(Stream inputstream)
  1450.         {
  1451.             Byte[] buffer = new Byte[8];
  1452.             inputstream.Read(buffer, 0, 8);
  1453.             UInt64 result = BitConverter.ToUInt64(buffer,0);
  1454.             result = ByteSwap.Swap(result);
  1455.             return result;
  1456.         }
  1457.  
  1458.         private void writeInt64(Stream outputstream, UInt64 value)
  1459.         {
  1460.             UInt64 bvalue = ByteSwap.Swap(value);
  1461.             Byte[] buffer = BitConverter.GetBytes(bvalue);
  1462.             outputstream.Write(buffer, 0, 8);
  1463.         }
  1464.  
  1465.         private void insertInto(Stream insertStream, UInt64 value)
  1466.         {
  1467.             MemoryStream tempstream = new MemoryStream();
  1468.             writeInt64(tempstream, value);
  1469.             insertStream.Seek(0, SeekOrigin.Begin);
  1470.            
  1471.             Byte[] streambuffer=new Byte[insertStream.Length];
  1472.             insertStream.Read(streambuffer,0, (Int32)insertStream.Length);
  1473.             tempstream.Write(streambuffer, 0, (Int32)insertStream.Length);
  1474.  
  1475.             insertStream.Seek(0, SeekOrigin.Begin);
  1476.             tempstream.Seek(0, SeekOrigin.Begin);
  1477.  
  1478.             streambuffer = new Byte[tempstream.Length];
  1479.             tempstream.Read(streambuffer, 0, (Int32)tempstream.Length);
  1480.             insertStream.Write(streambuffer, 0, (Int32)tempstream.Length);
  1481.  
  1482.             tempstream.Close();
  1483.         }
  1484.  
  1485.         public void sendCheats(Stream inputStream)
  1486.         {
  1487.             MemoryStream cheatStream = new MemoryStream();
  1488.             Byte[] orgData = new Byte[inputStream.Length];
  1489.             inputStream.Seek(0,SeekOrigin.Begin);
  1490.             inputStream.Read(orgData, 0, (Int32)inputStream.Length);
  1491.             cheatStream.Write(orgData, 0, (Int32)inputStream.Length);
  1492.            
  1493.             UInt32 length = (UInt32)cheatStream.Length;
  1494.             //Cheat stream length must be multiple of 8
  1495.             if (length % 8 != 0)
  1496.             {
  1497.                 cheatStream.Close();
  1498.                 throw new EUSBGeckoException(EUSBErrorCode.CheatStreamSizeInvalid);
  1499.             }
  1500.  
  1501.             //Reset buffers
  1502.             InitGecko();
  1503.  
  1504.             //Make sure the stream ends with F0/F1
  1505.             cheatStream.Seek(-8,SeekOrigin.End);
  1506.             UInt64 data = readInt64(cheatStream);
  1507.             data = data & 0xFE00000000000000;
  1508.             if ( (data != 0xF000000000000000) &&
  1509.                  (data != 0xFE00000000000000))
  1510.             {
  1511.                 cheatStream.Seek(0, SeekOrigin.End);
  1512.                 writeInt64(cheatStream, 0xF000000000000000);
  1513.             }
  1514.  
  1515.             //Make sure it starts with 00D0C0...
  1516.             cheatStream.Seek(0, SeekOrigin.Begin);
  1517.             data = readInt64(cheatStream);
  1518.             if (data != 0x00D0C0DE00D0C0DE)
  1519.             {
  1520.                 insertInto(cheatStream, 0x00D0C0DE00D0C0DE);
  1521.             }
  1522.  
  1523.             cheatStream.Seek(0, SeekOrigin.Begin);
  1524.  
  1525.             length = (UInt32)cheatStream.Length;
  1526.  
  1527.             if (GeckoWrite(BitConverter.GetBytes(cmd_sendcheats), 1) != FTDICommand.CMD_OK)
  1528.             {
  1529.                 cheatStream.Close();
  1530.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1531.             }
  1532.            
  1533.             //How many chunks do I need to split this data into
  1534.             //How big ist the last chunk
  1535.             UInt32 fullchunks = length / uplpacketsize;
  1536.             UInt32 lastchunk = length % uplpacketsize;
  1537.  
  1538.             //How many chunks do I need to transfer
  1539.             UInt32 allchunks = fullchunks;
  1540.             if (lastchunk > 0)
  1541.                 allchunks++;
  1542.  
  1543.             //Read reply - expcecting GCACK
  1544.             Byte retry = 0;
  1545.             while (retry < 10)
  1546.             {
  1547.                 Byte[] response = new Byte[1];
  1548.                 if (GeckoRead(response, 1) != FTDICommand.CMD_OK)
  1549.                 {
  1550.                     cheatStream.Close();
  1551.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  1552.                 }
  1553.                 Byte reply = response[0];
  1554.                 if (reply == GCACK)
  1555.                     break;
  1556.                 if (retry == 9)
  1557.                 {
  1558.                     cheatStream.Close();
  1559.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIInvalidReply);
  1560.                 }
  1561.             }
  1562.  
  1563.             UInt32 blength = ByteSwap.Swap(length);
  1564.             if (GeckoWrite(BitConverter.GetBytes(blength), 4) != FTDICommand.CMD_OK)
  1565.             {
  1566.                 cheatStream.Close();
  1567.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1568.             }
  1569.  
  1570.             //We start with chunk 0
  1571.             UInt32 chunk = 0;
  1572.             retry = 0;
  1573.  
  1574.             Byte[] buffer; //read buffer
  1575.             while (chunk < fullchunks)
  1576.             {
  1577.                 //No output yet availible
  1578.                 SendUpdate(chunk, allchunks, chunk * packetsize, length, retry == 0,false);
  1579.                 //Set buffer
  1580.                 buffer = new Byte[uplpacketsize];
  1581.                 //Read buffer from stream
  1582.                 cheatStream.Read(buffer, 0, (int)uplpacketsize);
  1583.                 FTDICommand returnvalue = GeckoWrite(buffer, (int)uplpacketsize);
  1584.                 if (returnvalue == FTDICommand.CMD_ResultError)
  1585.                 {
  1586.                     retry++;
  1587.                     if (retry >= 3)
  1588.                     {
  1589.                         //Give up, too many retries
  1590.                         GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  1591.                         cheatStream.Close();
  1592.                         throw new EUSBGeckoException(EUSBErrorCode.TooManyRetries);
  1593.                     }
  1594.                     //Reset stream
  1595.                     cheatStream.Seek((-1) * ((int)uplpacketsize), SeekOrigin.Current);
  1596.                     GeckoWrite(BitConverter.GetBytes(GCRETRY), 1);
  1597.                     continue;
  1598.                 }
  1599.                 else if (returnvalue == FTDICommand.CMD_FatalError)
  1600.                 {
  1601.                     //Major fail, give it up
  1602.                     GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  1603.                     cheatStream.Close();
  1604.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  1605.                 }
  1606.  
  1607.                 Byte[] response = new Byte[1];
  1608.                 returnvalue = GeckoRead(response, 1);
  1609.                 if ((returnvalue == FTDICommand.CMD_ResultError) || (response[0] != GCACK))
  1610.                 {
  1611.                     retry++;
  1612.                     if (retry >= 3)
  1613.                     {
  1614.                         //Give up, too many retries
  1615.                         GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  1616.                         cheatStream.Close();
  1617.                         throw new EUSBGeckoException(EUSBErrorCode.TooManyRetries);
  1618.                     }
  1619.                     //Reset stream
  1620.                     cheatStream.Seek((-1) * ((int)uplpacketsize), SeekOrigin.Current);
  1621.                     GeckoWrite(BitConverter.GetBytes(GCRETRY), 1);
  1622.                     continue;
  1623.                 }
  1624.                 else if (returnvalue == FTDICommand.CMD_FatalError)
  1625.                 {
  1626.                     //Major fail, give it up
  1627.                     GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  1628.                     cheatStream.Close();
  1629.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  1630.                 }
  1631.                
  1632.                 //reset retry counter
  1633.                 retry = 0;
  1634.                 //next chunk
  1635.                 chunk++;
  1636.                 //ackowledge package
  1637.             }
  1638.  
  1639.             //Final package?
  1640.             while (lastchunk > 0)
  1641.             {
  1642.                 //No output yet availible
  1643.                 SendUpdate(chunk, allchunks, chunk * packetsize, length, retry == 0,false);
  1644.                 //Set buffer
  1645.                 buffer = new Byte[lastchunk];
  1646.                 //Read buffer from stream
  1647.                 cheatStream.Read(buffer, 0, (int)lastchunk);
  1648.                 FTDICommand returnvalue = GeckoWrite(buffer, (Int32)lastchunk);
  1649.                 if (returnvalue == FTDICommand.CMD_ResultError)
  1650.                 {
  1651.                     retry++;
  1652.                     if (retry >= 3)
  1653.                     {
  1654.                         //Give up, too many retries
  1655.                         GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  1656.                         cheatStream.Close();
  1657.                         throw new EUSBGeckoException(EUSBErrorCode.TooManyRetries);
  1658.                     }
  1659.                     //Reset stream
  1660.                     cheatStream.Seek((-1) * ((int)lastchunk), SeekOrigin.Current);
  1661.                     GeckoWrite(BitConverter.GetBytes(GCRETRY), 1);
  1662.                     continue;
  1663.                 }
  1664.                 else if (returnvalue == FTDICommand.CMD_FatalError)
  1665.                 {
  1666.                     //Major fail, give it up
  1667.                     GeckoWrite(BitConverter.GetBytes(GCFAIL), 1);
  1668.                     cheatStream.Close();
  1669.                     throw new EUSBGeckoException(EUSBErrorCode.FTDIReadDataError);
  1670.                 }
  1671.                 //reset retry counter
  1672.                 retry = 0;
  1673.                 //cancel while loop
  1674.                 lastchunk = 0;
  1675.                 //ackowledge package
  1676.                 //GeckoWrite(BitConverter.GetBytes(GCACK), 1);
  1677.             }
  1678.             SendUpdate(allchunks, allchunks, length, length, true,false);
  1679.             cheatStream.Close();
  1680.         }
  1681.  
  1682.         //Execute cheats
  1683.         public void ExecuteCheats()
  1684.         {
  1685.             if (RawCommand(cmd_cheatexec) != FTDICommand.CMD_OK)
  1686.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1687.         }
  1688.         #endregion
  1689.  
  1690.         #region hooking crap
  1691.         //Hook command:
  1692.         public void Hook(bool pause, WiiLanguage language, WiiPatches patches, WiiHookType hookType)
  1693.         {
  1694.             InitGecko();
  1695.  
  1696.             //Hookpause command or regular hook?
  1697.             Byte command;
  1698.             if (pause)
  1699.                 command = cmd_hookpause;
  1700.             else
  1701.                 command = cmd_hook;
  1702.  
  1703.             //Perform hook command
  1704.             command += (Byte)hookType;
  1705.             if (RawCommand(command) != FTDICommand.CMD_OK)
  1706.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1707.  
  1708.             //Send language
  1709.             if (language != WiiLanguage.NoOverride)
  1710.                 command = (Byte)(language - 1);
  1711.             else
  1712.                 command = 0xCD;
  1713.  
  1714.             if (RawCommand(command) != FTDICommand.CMD_OK)
  1715.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1716.  
  1717.             //Send patches
  1718.             command = (Byte)patches;
  1719.             if (RawCommand(command) != FTDICommand.CMD_OK)
  1720.                 throw new EUSBGeckoException(EUSBErrorCode.FTDICommandSendError);
  1721.         }
  1722.  
  1723.         public void Hook()
  1724.         {
  1725.             Hook(false, WiiLanguage.NoOverride, WiiPatches.NoPatches, WiiHookType.VI);
  1726.         }
  1727.         #endregion
  1728.  
  1729.         #region Screenshot processing
  1730.         private static Byte ConvertSafely(double floatValue)
  1731.         {
  1732.             return (Byte)Math.Round(Math.Max(0, Math.Min(floatValue, 255)));
  1733.         }
  1734.  
  1735.         private static Bitmap ProcessImage(UInt32 width, UInt32 height, Stream analyze)
  1736.         {
  1737.  
  1738.             Bitmap BitmapRGB = new Bitmap((int)width, (int)height, PixelFormat.Format24bppRgb);
  1739.             BitmapData bData = BitmapRGB.LockBits(new Rectangle(0, 0, (int)width, (int)height),
  1740.                                 ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
  1741.  
  1742.             int size = bData.Stride * bData.Height;
  1743.  
  1744.             Byte[] data = new Byte[size];
  1745.  
  1746.             System.Runtime.InteropServices.Marshal.Copy(bData.Scan0, data, 0, size);
  1747.  
  1748.             Byte[] bufferBytes= new Byte[width * height * 2];
  1749.  
  1750.             int y = 0;
  1751.             int u = 0;
  1752.             int v = 0;
  1753.             int yvpos = 0;
  1754.             int rgbpos = 0;
  1755.  
  1756.             analyze.Read(bufferBytes, 0, (int)(width * height * 2));
  1757.             for (int i = 0; i < width*height; i++)
  1758.             {
  1759.                 yvpos = i * 2;
  1760.                 //YV encoding is a bit awkward!
  1761.                 if (i % 2 == 0) //Even
  1762.                 {
  1763.                     y = bufferBytes[yvpos];
  1764.                     u = bufferBytes[yvpos + 1]; //U value is taken from current V block
  1765.                     v = bufferBytes[yvpos + 3]; //Take V from next data YV block
  1766.                 }
  1767.                 else //Odd
  1768.                     y = bufferBytes[yvpos];
  1769.                     //u is taken from last pixel
  1770.                     //v too!
  1771.  
  1772.                 rgbpos = (i * 3);
  1773.                     data[rgbpos] = ConvertSafely(1.164 * (y - 16) + 2.017 * (u - 128));                     //Blue pixel value
  1774.                 data[rgbpos + 1] = ConvertSafely(1.164 * (y - 16) - 0.392 * (u - 128) - 0.813 * (v - 128)); //Greeen pixel value
  1775.                 data[rgbpos + 2] = ConvertSafely(1.164 * (y - 16) + 1.596 * (v - 128));                     //Red pixel value
  1776.             }
  1777.  
  1778.             System.Runtime.InteropServices.Marshal.Copy(data, 0, bData.Scan0, data.Length);
  1779.  
  1780.             BitmapRGB.UnlockBits(bData);
  1781.  
  1782.             return BitmapRGB;
  1783.         }
  1784.  
  1785.         public Image Screenshot()
  1786.         {
  1787.             MemoryStream analyze;
  1788.  
  1789.             //Dump video registers
  1790.             analyze = new MemoryStream();
  1791.             Dump(0xCC002000, 0xCC002080, analyze);
  1792.             analyze.Seek(0, SeekOrigin.Begin);
  1793.             Byte[] viregs = new Byte[128];
  1794.             analyze.Read(viregs, 0, 128);
  1795.             analyze.Close();
  1796.  
  1797.             //Extract width, height and offset in memory
  1798.             UInt32  swidth = (UInt32)(viregs[0x49] << 3);
  1799.             UInt32 sheight = (UInt32)(((viregs[0] << 5) | (viregs[1] >> 3)) & 0x07FE);
  1800.             UInt32 soffset = (UInt32)((viregs[0x1D] << 16) | (viregs[0x1E] << 8) | viregs[0x1F]);
  1801.             if ( (viregs[0x1C] & 0x10) == 0x10)
  1802.                 soffset <<= 5;
  1803.             soffset += 0x80000000;
  1804.             soffset -= (UInt32)((viregs[0x1C] & 0xF) << 3);
  1805.  
  1806.             //Dump video data
  1807.             analyze = new MemoryStream();
  1808.             Dump(soffset, soffset + sheight * swidth * 2, analyze);
  1809.             analyze.Seek(0, SeekOrigin.Begin);
  1810.  
  1811.             if (sheight > 600) //Progressive mode!
  1812.             {
  1813.                 sheight = sheight / 2;
  1814.                 swidth = swidth * 2;
  1815.             }
  1816.  
  1817.             Bitmap b = ProcessImage(swidth, sheight, analyze);
  1818.             analyze.Close();
  1819.  
  1820.             return b;
  1821.         }
  1822.         #endregion
  1823.     }
  1824. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement