Guest User

PokeFlash non-windows fix

a guest
Jun 3rd, 2011
130
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. PokeFlash.cpp : Defines the entry point for the console application.
  3. vim: set ai ts=2 sw=2 sts=2 et:
  4. g++ -o PokeFlash PokeFlash.cpp -lftd2xx && ./PokeFlash -f menu.min
  5. */
  6.  
  7. #include <iostream>
  8. using namespace std;
  9.  
  10. #ifdef _WIN32
  11.   #include <windows.h>
  12.   #include <tchar.h>
  13.   #pragma comment(lib, "ftd2xx.lib")
  14. #else
  15.   #include <unistd.h>
  16.   #include <sys/time.h>
  17.   #define sscanf_s    sscanf
  18.   static inline int fopen_s(FILE **f, const char *fn, const char *m)
  19.   {
  20.     *f = fopen(fn,m);
  21.     return 0;
  22.   }
  23.   static inline void Sleep(unsigned int ms)
  24.   {
  25.     usleep(ms*1000);
  26.   }
  27.   static inline unsigned int GetTickCount()
  28.   {
  29.     timeval tv1; gettimeofday(&tv1, NULL);
  30.     return (tv1.tv_sec * 1000) + (tv1.tv_usec / 1000);
  31.   }
  32. #endif
  33. #include <stdio.h>
  34. #include "ftd2xx.h"
  35.  
  36. typedef unsigned char BYTE;
  37.  
  38. #define DEV_DESC "Dual RS232-HS B"  //"FT2232H MiniModule A"
  39.  
  40. #define BUFSIZE (4*1024*1024) // 4MB - huge buffer to hold all the commands that are sent down the USB to the FT2232H
  41. #define BLOCKSIZE (8*1024)    // We read/write chunks of 8kb to the cart
  42. #define NBLOCKS ((512*1024) / BLOCKSIZE)
  43. #define N_WAIT_CYCLES   24   //96 // How many wait cycles for byte programming?
  44.  
  45. #define FLASH_RESET     0
  46. #define FLASH_MANUFACTURER  1
  47. #define FLASH_DEVICECODE  2
  48. #define FLASH_WRITEBYTE   3
  49. #define FLASH_CHIPERASE   4
  50. #define FLASH_SECERASE    5
  51. #define FLASH_DEVICECODEEX  6
  52. #define FLASH_UNLOCKBYP   7
  53. #define FLASH_RESETBYP    8
  54.  
  55. // Command buffer
  56. BYTE cmdBuffer[BUFSIZE];
  57. int PosCmdBuf=0;
  58.  
  59. // Data buffers
  60. BYTE datBuffer[BLOCKSIZE*4+1024];
  61. BYTE verBuffer[BLOCKSIZE*4+1024];
  62.  
  63. FT_HANDLE ftHandle;
  64. FT_STATUS ftStatus;
  65.  
  66. // clock divider
  67. DWORD clock_divider=1;
  68.  
  69. // Flash infos
  70. BYTE manuf, devc, devcex;
  71.  
  72.  
  73. void CS_Low(void);
  74. void CS_High(void);
  75. void Power_Off(void);
  76. int Sync_To_MPSSE(void);
  77. int OpenDevice(void);
  78. void WriteCart(DWORD addr, BYTE dat, BYTE waitcycles);
  79. BYTE ReadCart(DWORD addr, DWORD nBytes);
  80. void FlushInBuffer(void);
  81. void FlushOutBuffer(void);
  82. void SetSpeed(BYTE speed);
  83. BYTE FlashProcess(int command, DWORD addr, BYTE data);
  84. BYTE ConvByt(BYTE byt);
  85. BYTE ConvBytBack(BYTE byt);
  86.  
  87.  
  88. int main(int argc, char* argv[])
  89. {
  90.   FILE* fileOut, * fileIn;
  91.   int bCtr, i, t, j;
  92.   int fileErrors;
  93.   int bytesRead;
  94.   bool hasMenu=FALSE;
  95.   const char* inFileName=NULL;
  96.   const char* inFileNames[64];
  97.   char* outFileName=NULL;
  98.   DWORD time2;
  99.   DWORD tErase,tProg,tRead;
  100.   DWORD fSize;
  101.  
  102.   printf("PokeFlash V1.0 by Lupin\n\r");
  103.   printf("http://lupin.shizzle.it\n\r");
  104.   printf("-----------------------\n\r\n\r");
  105.  
  106.  
  107.   if(argc<2) {
  108.     printf("Usage: PokeFlash [-f infile1 [infile2] [more...]] [-d outfile] [-c divider]\n\r---------------------------------------------------------------------------\n\r");
  109.     printf("-f infile     Program binary file(s) to flash\n\r");
  110.     printf("              Specify more than one file for menu ROM (menu.min needed)\n\r");
  111.     printf("-d outfile    Dump the cart contents to file\n\r");
  112.     printf("-c divider    Set clock divider (higher=slower); Values from 01 to 40 (hex)\n\r");
  113.     getchar();
  114.     return 0;
  115.   }
  116.  
  117.   for(i=1;i<argc;i++) {
  118.     if(strcmp(argv[i],"-f")==0) {
  119.       t=0; j=i;
  120.       inFileNames[t] = "menu.min";
  121.       while(argv[++j] != NULL) {
  122.         if(argv[j][0] == '-') break;
  123.         inFileName=inFileNames[++t]=argv[j];
  124.       }
  125.       if(argv[j]==NULL) break;
  126.       i=j;
  127.     }
  128.     if(strcmp(argv[i],"-c")==0) sscanf_s(argv[++i], "%02X", &clock_divider);
  129.     if(strcmp(argv[i],"-d")==0) outFileName=argv[++i];
  130.   }
  131.  
  132.   // Build menu ROM if more than one ROM
  133.   if(t>1) {
  134.     printf("Building menu ROM...\n\r");
  135.    
  136.     // Create output file
  137.     fopen_s(&fileOut, "menu_out.min", "wb");
  138.     if(!fileOut) {
  139.       printf("File menu_out.min could not be created!\n\r");
  140.       getchar();
  141.       return 0;
  142.     }
  143.  
  144.     for(i=0;i<=t;i++) {
  145.       fopen_s(&fileIn, inFileNames[i],"rb");
  146.       if(!fileIn) {
  147.         printf("Input file %s could not be opened!\n\r", inFileNames[i]);
  148.         getchar();
  149.         return 0;
  150.       }
  151.       if(i>0) fseek(fileIn,8192,SEEK_SET); // Skip bios
  152.       while((bytesRead = fread(&datBuffer, 1, BLOCKSIZE,fileIn)) !=0) {
  153.         fwrite(&datBuffer, 1, bytesRead, fileOut);
  154.       }
  155.       fclose(fileIn);
  156.       // Align position in output file to 8kb boundary
  157.       fSize = ftell(fileOut);
  158.       if(fSize & 0x1FFF) fseek(fileOut, (fSize & (~0x1FFF)) + 0x2000, SEEK_SET);
  159.     }
  160.     fSize = ftell(fileOut);
  161.     fclose(fileOut);
  162.     inFileName="menu_out.min";
  163.     if(fSize > (512*1024)) {
  164.       printf("Menu ROM is too big!\n\rMenu ROM size: %d kb\n\r", fSize>>10);
  165.       getchar();
  166.       return 0;
  167.     }
  168.     printf("Menu ROM created!\n\rMenu ROM size: %d kb\n\r\n\r", fSize>>10);
  169.     hasMenu=TRUE;
  170.   }
  171.  
  172.  
  173.   // Connect to device
  174.   if(!OpenDevice()) return 0;
  175.  
  176.   Sleep(50);
  177.  
  178.   // Check the flash type
  179.   WriteCart(0x555, ConvByt(0xAA), 0);
  180.   WriteCart(0xAAA, ConvByt(0x55), 0);
  181.   WriteCart(0x555, ConvByt(0x90), 0);
  182.   FlushOutBuffer();
  183.   manuf = ConvBytBack(ReadCart(0x0, 1));
  184.   devc = ConvBytBack(ReadCart(0x1, 1));
  185.   devcex = ConvBytBack(ReadCart(0x3, 1));
  186.   WriteCart(0x555, ConvByt(0xAA), 0);
  187.   WriteCart(0xAAA, ConvByt(0x55), 0);
  188.   WriteCart(0x555, ConvByt(0xF0), 0);
  189.   FlushOutBuffer();
  190.  
  191.   if((manuf==0x1F) && (devc==0x13) && (devcex=0x0F)) {
  192.     printf("Atmel AT49BV040A 512kb memory detected!\n\r\n\r");
  193.   } else if((manuf==0x01) && (devc==0x4F)) {
  194.     printf("AMD AM29LV040B 512kb memory detected!\n\r\n\r");
  195.   } else {
  196.     printf("Device not supported:\n\r");
  197.     printf("Manufacturer code: %02X\n\r", manuf);
  198.     printf("Device code: %02X\n\r", devc);
  199.     printf("Extended code: %02X\n\r", devcex);
  200.     getchar();
  201.     return 0;
  202.   }
  203.  
  204.  
  205.   // Programming
  206.   if(inFileName) {
  207.     // Open file for programming
  208.     fopen_s(&fileIn, inFileName, "rb");
  209.     if(!fileIn) {
  210.       printf("Input file %s could not be opened!\n\r", inFileName);
  211.       getchar();
  212.       return 0;
  213.     }
  214.     // Get file size
  215.     fseek(fileIn, 0, SEEK_END);
  216.     fSize = ftell(fileIn);
  217.     fseek(fileIn, 0, SEEK_SET);
  218.     if(fSize > (512*1024)) {
  219.       printf("The input file is too large! Max. size is 512kb!\n\r");
  220.       getchar();
  221.       return 0;
  222.     }
  223.  
  224.     // Chip erase or sector erase
  225.     //CS_Low();
  226.     if((fSize>0x40000)||hasMenu) {
  227.       // File is >256kb - do chip erase
  228.       printf("Chip Erase...\n\r");
  229.       time2 = GetTickCount();
  230.       FlashProcess(FLASH_CHIPERASE, 0, 0);
  231.       while( (ReadCart(0, 1) != 0xFF) && ((GetTickCount()-time2) < 20000) ) continue;
  232.       tErase=GetTickCount()-time2;
  233.       printf("Chip erase done! Time: %dms\n\r\n\r", tErase);
  234.     } else {
  235.       // File is <256kb - erase each sector to save time
  236.  
  237.       // Erase lower 16kb - boot block
  238.       time2 = GetTickCount();
  239.       FlashProcess(FLASH_SECERASE, 0x00000, 0);
  240.       while( (ReadCart(0x00000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
  241.       tErase=GetTickCount()-time2;
  242.       printf("Boot block erase done! Time: %dms\n\r", tErase);
  243.  
  244.  
  245.       if(fSize > 0x04000) {
  246.         // Erase parameter block 1
  247.         time2 = GetTickCount();
  248.         FlashProcess(FLASH_SECERASE, 0x04000, 0);
  249.         while( (ReadCart(0x04000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
  250.         tErase=GetTickCount()-time2;
  251.         printf("Parameter block 1 erase done! Time: %dms\n\r", tErase);
  252.       }
  253.  
  254.       if(fSize > 0x06000) {
  255.         // Erase parameter block 2
  256.         time2 = GetTickCount();
  257.         FlashProcess(FLASH_SECERASE, 0x06000, 0);
  258.         while( (ReadCart(0x06000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
  259.         tErase=GetTickCount()-time2;
  260.         printf("Parameter block 2 erase done! Time: %dms\n\r", tErase);
  261.       }
  262.  
  263.       if(fSize > 0x08000) {
  264.         // Erase memory block 1
  265.         time2 = GetTickCount();
  266.         FlashProcess(FLASH_SECERASE, 0x08000, 0);
  267.         while( (ReadCart(0x08000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
  268.         tErase=GetTickCount()-time2;
  269.         printf("Memory block 1 erase done! Time: %dms\n\r", tErase);
  270.       }
  271.  
  272.       if(fSize > 0x10000) {
  273.         // Erase memory block 2
  274.         time2 = GetTickCount();
  275.         FlashProcess(FLASH_SECERASE, 0x10000, 0);
  276.         while( (ReadCart(0x10000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
  277.         tErase=GetTickCount()-time2;
  278.         printf("Memory block 2 erase done! Time: %dms\n\r", tErase);
  279.       }
  280.  
  281.       if(fSize > 0x20000) {
  282.         // Erase memory block 3
  283.         time2 = GetTickCount();
  284.         FlashProcess(FLASH_SECERASE, 0x20000, 0);
  285.         while( (ReadCart(0x20000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
  286.         tErase=GetTickCount()-time2;
  287.         printf("Memory block 3 erase done! Time: %dms\n\r", tErase);
  288.       }
  289.  
  290.       if(fSize > 0x30000) {
  291.         // Erase memory block 4
  292.         time2 = GetTickCount();
  293.         FlashProcess(FLASH_SECERASE, 0x30000, 0);
  294.         while( (ReadCart(0x30000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
  295.         tErase=GetTickCount()-time2;
  296.         printf("Memory block 4 erase done! Time: %dms\n\r", tErase);
  297.       }
  298.       printf("\n\r");
  299.     }
  300.  
  301.  
  302.     // Programming
  303.     printf("Programming flash...\n\r");
  304.     time2 = GetTickCount();
  305.     // Unlock bypass mode if flash supports it
  306.     FlashProcess(FLASH_UNLOCKBYP, 0, 0);
  307.     bytesRead=BLOCKSIZE;
  308.     for(bCtr=0;(bCtr<NBLOCKS)&&(bytesRead==BLOCKSIZE);bCtr++) {
  309.       bytesRead = fread(&datBuffer, 1, BLOCKSIZE, fileIn);
  310.       // Write block
  311.       for(i=0;i<bytesRead;i++) {
  312.         FlashProcess(FLASH_WRITEBYTE, bCtr*BLOCKSIZE+i, datBuffer[i]);
  313.       }
  314.       FlushOutBuffer();
  315.       printf("Block %d done!\n\r", bCtr);
  316.     }
  317.     FlashProcess(FLASH_RESETBYP, 0, 0);
  318.     tProg = GetTickCount()-time2;
  319.     printf("Programming done! Time: %dms\n\r\n\r", tProg);
  320.   } else {
  321.  
  322.     // No programming was done, just doing a read operation
  323.  
  324.     //CS_Low();
  325.  
  326.   }
  327.  
  328.   // Read & verify
  329.   // In this step we either do verify, dump to file or both
  330.   if(outFileName) {
  331.     fopen_s(&fileOut, outFileName, "wb");
  332.     if(!fileOut) {
  333.       printf("Output file does not exist!\n\r");
  334.       getchar();
  335.       return 0;
  336.     }
  337.   }
  338.  
  339.   printf("Read");
  340.   if(inFileName) printf(" & verify");
  341.   if(outFileName) printf(" & dump");
  342.   printf("...\n\r");
  343.   time2 = GetTickCount();
  344.   if(inFileName) fseek(fileIn, 0, SEEK_SET);
  345.   fileErrors=0;
  346.   bytesRead=BLOCKSIZE;
  347.   for(bCtr=0;(bCtr<NBLOCKS)&&(bytesRead==BLOCKSIZE);bCtr++) {
  348.     ReadCart(bCtr*BLOCKSIZE, bytesRead);
  349.     if(inFileName) {
  350.       // Read from input file and do verify
  351.       bytesRead=fread(&verBuffer, 1, BLOCKSIZE, fileIn);
  352.       for(i=0;i<bytesRead;i++) {
  353.         if(datBuffer[i] != verBuffer[i]) {
  354.           if(fileErrors < 64) printf("Verify FAIL - Addr:%08X Orig:%02X Cart:%02X\n\r", bCtr*BLOCKSIZE+i, verBuffer[i], datBuffer[i]);
  355.           fileErrors++;
  356.         }
  357.       }
  358.     }
  359.     if(outFileName) fwrite (&datBuffer, 1, bytesRead, fileOut);
  360.   }
  361.   if(inFileName) printf("Verify errors: %d\n\r", fileErrors);
  362.   tRead = GetTickCount()-time2;
  363.   printf("Reading done! Time: %dms\n\r\n\r", tRead);
  364.   printf("Total time: %dms\n\r", inFileName?tErase+tProg+tRead:tRead);
  365.  
  366.  
  367.   // Cleanup & End
  368.   Power_Off();
  369.   if(outFileName) fclose (fileOut);
  370.   if(inFileName) fclose (fileIn);
  371.   FT_Close(ftHandle);
  372.   //getchar();
  373.   return 0;
  374. }
  375.  
  376.  
  377.  
  378.  
  379. int OpenDevice(void)
  380. {
  381.   int iDevCount,i;
  382.   char buf[64];
  383.   DWORD dwNumBytes, dwBytesRead;
  384.  
  385.   // How many devices?
  386.   FT_ListDevices(&iDevCount, NULL, FT_LIST_NUMBER_ONLY);
  387.   if (iDevCount == 0) {
  388.     printf("No FTDI devices found. Please connect device and re-try.\n\r");
  389.     getchar();
  390.     return 0;
  391.   }
  392.  
  393.   // Loop all devices and look for our device
  394.   for(i=0;i<iDevCount;i++) {
  395.     if(FT_ListDevices((void*)i, &buf, (FT_OPEN_BY_DESCRIPTION | FT_LIST_BY_INDEX)) != FT_OK) {
  396.       printf("Failed reading device description!\n\r");
  397.       getchar();
  398.       return 0;
  399.     }
  400.     if(strcmp(buf, DEV_DESC)==0) {
  401.       if(FT_OpenEx(&buf, FT_OPEN_BY_DESCRIPTION, &ftHandle) != FT_OK) {
  402.         printf("Failed opening the device!\n\r");
  403.         getchar();
  404.         return 0;
  405.       }
  406.       break;
  407.     }
  408.   }
  409.  
  410.  
  411.   // Step5: Setup latency
  412.   if(FT_SetLatencyTimer(ftHandle, 16) != FT_OK) {
  413.     printf("Set USB Device Latency Timer failed!\n\r");
  414.     getchar();
  415.     return 0;
  416.   }
  417.  
  418.   // Step6: Reset controller
  419.   if(FT_SetBitMode(ftHandle, 0x0, 0x0) != FT_OK) {
  420.     printf("Device reset failed!\n\r");
  421.     getchar();
  422.     return 0;
  423.   }
  424.  
  425.   // Step7: Set the port to MPSSE mode
  426.   if(FT_SetBitMode(ftHandle, 0x0, 0x2) != FT_OK) {
  427.     printf("Set to MPSSE mode failed!\n\r");
  428.     getchar();
  429.     return 0;
  430.   }
  431.    
  432.     // Check sync...
  433.     if (!Sync_To_MPSSE()) {
  434.     printf("Unable to synchronise the MPSSE write/read cycle!\n\r");
  435.         getchar();
  436.     return 0;
  437.     }
  438.  
  439.  
  440.   // Config stuff
  441.     //Bit0=CLK
  442.     //Bit1=DO
  443.     //Bit2=DI
  444.     //Bit3=CS
  445.   //Bit5=PWR
  446.   //Bit7=PWR read
  447.    
  448.     // initialise the port
  449.   PosCmdBuf = 0;
  450.     // set the low byte
  451.     cmdBuffer[PosCmdBuf++] = 0x80;              // Set data bits low byte command
  452.     cmdBuffer[PosCmdBuf++] = 0x20;              // set CS=low, DI=low, DO=low, SK=low, PWR=high
  453.     cmdBuffer[PosCmdBuf++] = 0x2B;              // CS=input, DI=input, DO=output, SK=output, PWR=output,
  454.     // set the clock divider
  455.     cmdBuffer[PosCmdBuf++] = 0x86;              
  456.     cmdBuffer[PosCmdBuf++] = (BYTE)clock_divider;
  457.     cmdBuffer[PosCmdBuf++] = 0x00;
  458.     cmdBuffer[PosCmdBuf++] = 0x85;              // turn off loopback
  459.     cmdBuffer[PosCmdBuf++] = 0x8A;              // turn off divider by 5
  460.   FT_Write(ftHandle, &cmdBuffer, PosCmdBuf, &dwBytesRead);
  461.  
  462.  
  463.   // now check if the cart is already powered (inside PM)
  464.   PosCmdBuf=0;
  465.   cmdBuffer[PosCmdBuf++] = 0x81;
  466.   FT_Write(ftHandle, &cmdBuffer, PosCmdBuf, &dwBytesRead);
  467.   PosCmdBuf=0;
  468.  
  469.   // wait for data to become available
  470.     do
  471.     FT_GetQueueStatus(ftHandle, &dwNumBytes);
  472.     while (dwNumBytes != 1);
  473.  
  474.   // read the input queue
  475.   FT_Read(ftHandle, &datBuffer, dwNumBytes, &dwBytesRead);
  476.  
  477.   if(datBuffer[0] & 0x80) {
  478.     printf("Cart seems to be powered (VCC is on) - please turn off your PM!\n\r");
  479.     getchar();
  480.     return 0;
  481.   }
  482.  
  483.   // Set CS high and power on cart
  484.     CS_High();
  485.   Sleep(10);
  486.   // Set CS to low, start programming operation
  487.   CS_Low();
  488.  
  489.   return 1;
  490. }
  491.  
  492.  
  493. void SetSpeed(BYTE speed)
  494. {
  495.   DWORD dwBytesRead;
  496.     cmdBuffer[PosCmdBuf++] = 0x86;  // set clock divider command to 1MHz
  497.     cmdBuffer[PosCmdBuf++] = speed; // low byte    60MHz / ((value+1)*2)
  498.     cmdBuffer[PosCmdBuf++] = 0x00;  // high byte
  499.   FT_Write(ftHandle, &cmdBuffer, PosCmdBuf, &dwBytesRead);
  500.   PosCmdBuf = 0;
  501. }
  502.  
  503. void CS_Low(void)
  504. {
  505.   DWORD dwBytesRead;
  506.     cmdBuffer[PosCmdBuf++] = 0x80;
  507.     cmdBuffer[PosCmdBuf++] = 0x00;
  508.     cmdBuffer[PosCmdBuf++] = 0x2B;
  509.   FT_Write(ftHandle, &cmdBuffer, PosCmdBuf, &dwBytesRead);
  510.   PosCmdBuf = 0;
  511. }
  512.  
  513. void CS_High(void)
  514. {
  515.   DWORD dwBytesRead;
  516.     cmdBuffer[PosCmdBuf++] = 0x80;
  517.     cmdBuffer[PosCmdBuf++] = 0x08;
  518.     cmdBuffer[PosCmdBuf++] = 0x2B;
  519.   FT_Write(ftHandle, &cmdBuffer, PosCmdBuf, &dwBytesRead);
  520.   PosCmdBuf = 0;
  521. }
  522.  
  523.  
  524. void Power_Off(void)
  525. {
  526.   DWORD dwBytesRead;
  527.     cmdBuffer[PosCmdBuf++] = 0x80;
  528.     cmdBuffer[PosCmdBuf++] = 0x20;
  529.     cmdBuffer[PosCmdBuf++] = 0x00;
  530.   FT_Write(ftHandle, &cmdBuffer, PosCmdBuf, &dwBytesRead);
  531.   PosCmdBuf = 0;
  532. }
  533.  
  534.  
  535. int Sync_To_MPSSE(void)
  536. {
  537.   DWORD dwNumBytes, dwBytesRead;
  538.  
  539.   // uses &HAA and &HAB commands which are invalid so that the MPSSE processor should
  540.   // echo these back to use preceded with &HFA
  541.  
  542.    
  543.     // clear anything in the input buffer
  544.   FT_GetQueueStatus(ftHandle, &dwNumBytes);
  545.     if (dwNumBytes > 0) {
  546.         // read chunks of 'input buffer size'
  547.         while (dwNumBytes > BLOCKSIZE)
  548.     {
  549.       FT_Read(ftHandle, &datBuffer, BLOCKSIZE, &dwBytesRead);
  550.       dwNumBytes -= dwBytesRead;
  551.         }
  552.         FT_Read(ftHandle, &datBuffer, dwNumBytes, &dwBytesRead); // read the final bytes
  553.     }
  554.    
  555.  
  556.     // put a bad command to the command processor
  557.   // Send 0xAA
  558.   cmdBuffer[0] = 0xAA;
  559.   FT_Write(ftHandle, &cmdBuffer, 1, &dwBytesRead);
  560.  
  561.     // wait for a response
  562.     do
  563.     FT_GetQueueStatus(ftHandle, &dwNumBytes);
  564.     while (dwNumBytes != 2);
  565.  
  566.   // read the input queue
  567.   FT_Read(ftHandle, &datBuffer, dwNumBytes, &dwBytesRead);
  568.    
  569.   if((datBuffer[0] == 0xFA) && (datBuffer[1] == 0xAA))
  570.   {
  571.     return 1;
  572.   }
  573.  
  574.   return 0;
  575. }
  576.  
  577.  
  578. BYTE FlashProcess(int command, DWORD addr, BYTE data)
  579. {
  580.   BYTE tmp;
  581.   switch(command) {
  582.     case FLASH_UNLOCKBYP:
  583.       if((manuf==0x01) && (devc==0x4F)) {
  584.         WriteCart(0x555, ConvByt(0xAA), 0);
  585.         WriteCart(0xAAA, ConvByt(0x55), 0);
  586.         WriteCart(0x555, ConvByt(0x20), 0);
  587.       }
  588.       return 1;
  589.     case FLASH_RESETBYP:
  590.       if((manuf==0x01) && (devc==0x4F)) {
  591.         WriteCart(0, ConvByt(0x90), 0);
  592.         WriteCart(0, 0, 0);
  593.       }
  594.       return 1;
  595.     case FLASH_RESET:
  596.       WriteCart(0x555, ConvByt(0xAA), 0);
  597.       WriteCart(0xAAA, ConvByt(0x55), 0);
  598.       WriteCart(0x555, ConvByt(0xF0), 0);
  599.       FlushOutBuffer();
  600.       return 1;
  601.     case FLASH_MANUFACTURER:
  602.       WriteCart(0x555, ConvByt(0xAA), 10);
  603.       WriteCart(0xAAA, ConvByt(0x55), 10);
  604.       WriteCart(0x555, ConvByt(0x90), 10);
  605.       tmp = ConvByt(ReadCart(0x0, 1));
  606.       WriteCart(0x555, ConvByt(0xAA), 10);
  607.       WriteCart(0xAAA, ConvByt(0x55), 10);
  608.       WriteCart(0x555, ConvByt(0xF0), 10);
  609.       FlushOutBuffer();
  610.       return tmp;
  611.     case FLASH_DEVICECODE:
  612.       WriteCart(0x555, ConvByt(0xAA), 0);
  613.       WriteCart(0xAAA, ConvByt(0x55), 0);
  614.       WriteCart(0x555, ConvByt(0x90), 0);
  615.       tmp = ConvByt(ReadCart(0x1, 1));
  616.       WriteCart(0x555, ConvByt(0xAA), 0);
  617.       WriteCart(0xAAA, ConvByt(0x55), 0);
  618.       WriteCart(0x555, ConvByt(0xF0), 0);
  619.       FlushOutBuffer();
  620.       return tmp;
  621.     case FLASH_DEVICECODEEX:
  622.       WriteCart(0x555, ConvByt(0xAA), 0);
  623.       WriteCart(0xAAA, ConvByt(0x55), 0);
  624.       WriteCart(0x555, ConvByt(0x90), 0);
  625.       tmp = ConvByt(ReadCart(0x3, 1));
  626.       WriteCart(0x555, ConvByt(0xAA), 0);
  627.       WriteCart(0xAAA, ConvByt(0x55), 0);
  628.       WriteCart(0x555, ConvByt(0xF0), 0);
  629.       FlushOutBuffer();
  630.       return tmp;
  631.     case FLASH_WRITEBYTE:
  632.       if (data==0xFF) return 1;
  633.       // Full sequence only needed for devices without bypass
  634.       if(!((manuf==0x01) && (devc==0x4F))) {
  635.         WriteCart(0x555, ConvByt(0xAA), 0);
  636.         WriteCart(0xAAA, ConvByt(0x55), 0);
  637.       }
  638.       WriteCart(0x555, ConvByt(0xA0), 0);
  639.       WriteCart(addr, data, (BYTE)(N_WAIT_CYCLES / (clock_divider + 1)));  
  640.       return 1;
  641.     case FLASH_CHIPERASE:
  642.       WriteCart(0x555, ConvByt(0xAA), 0);
  643.       WriteCart(0xAAA, ConvByt(0x55), 0);
  644.       WriteCart(0x555, ConvByt(0x80), 0);
  645.       WriteCart(0x555, ConvByt(0xAA), 0);
  646.       WriteCart(0xAAA, ConvByt(0x55), 0);
  647.       WriteCart(0x555, ConvByt(0x10), 0);
  648.       FlushOutBuffer();
  649.       return 1;
  650.     case FLASH_SECERASE:
  651.       WriteCart(0x555, ConvByt(0xAA), 0);
  652.       WriteCart(0xAAA, ConvByt(0x55), 0);
  653.       WriteCart(0x555, ConvByt(0x80), 0);
  654.       WriteCart(0x555, ConvByt(0xAA), 0);
  655.       WriteCart(0xAAA, ConvByt(0x55), 0);
  656.       WriteCart(addr, ConvByt(0x30), 0);
  657.       FlushOutBuffer();
  658.       return 1;
  659.   }
  660.   return 0;
  661. }
  662.  
  663.  
  664.  
  665. void FlushInBuffer(void)
  666. {
  667.   DWORD dwNumBytes, dwBytesRead;
  668.   FT_GetQueueStatus(ftHandle, &dwNumBytes);
  669.   FT_Read(ftHandle, &datBuffer, dwNumBytes, &dwBytesRead);
  670.  
  671. }
  672.  
  673.  
  674. void FlushOutBuffer(void)
  675. {
  676.   DWORD dwBytesWritten;
  677.   cmdBuffer[PosCmdBuf++] = 0x87;
  678.   FT_Write(ftHandle, cmdBuffer, PosCmdBuf, &dwBytesWritten);
  679.   PosCmdBuf = 0;
  680. }
  681.  
  682. BYTE ConvByt(BYTE byt)
  683. {
  684.   BYTE bret=0;
  685.     if (byt & (1<<0)) bret |= 1<<7;
  686.     if (byt & (1<<1)) bret |= 1<<5;
  687.   if (byt & (1<<2)) bret |= 1<<3;
  688.   if (byt & (1<<3)) bret |= 1<<1;
  689.   if (byt & (1<<4)) bret |= 1<<0;
  690.   if (byt & (1<<5)) bret |= 1<<2;
  691.   if (byt & (1<<6)) bret |= 1<<4;
  692.   if (byt & (1<<7)) bret |= 1<<6;
  693.   return bret;
  694. }
  695.  
  696.  
  697. BYTE ConvBytBack(BYTE byt)
  698. {
  699.   BYTE bret=0;
  700.     if (byt & (1<<7)) bret |= 1<<0;
  701.     if (byt & (1<<5)) bret |= 1<<1;
  702.   if (byt & (1<<3)) bret |= 1<<2;
  703.   if (byt & (1<<1)) bret |= 1<<3;
  704.   if (byt & (1<<0)) bret |= 1<<4;
  705.   if (byt & (1<<2)) bret |= 1<<5;
  706.   if (byt & (1<<4)) bret |= 1<<6;
  707.   if (byt & (1<<6)) bret |= 1<<7;
  708.   return bret;
  709. }
  710.  
  711. void WriteCart(DWORD addr, BYTE dat, BYTE waitcycles)
  712. {  
  713.   // Send 4 Bytes
  714.   cmdBuffer[PosCmdBuf++] = 0x11;
  715.   cmdBuffer[PosCmdBuf++] = 0x03;
  716.   cmdBuffer[PosCmdBuf++] = 0x00;
  717.    
  718.   // Layout:
  719.   // xAAA AAAA AAAA AAAA AAAA xCxD DDDD DDDx
  720.     cmdBuffer[PosCmdBuf++] = (addr >> 12) & 0xFF;
  721.     cmdBuffer[PosCmdBuf++] = (addr >> 4) & 0xFF;
  722.     cmdBuffer[PosCmdBuf++] = ((addr << 4) & 0xF0) | 0x4 | (dat>>7);
  723.   cmdBuffer[PosCmdBuf++] = (dat<<1) & 0xFE;
  724.  
  725.  
  726.  
  727.  
  728.   if(waitcycles>0) {
  729.     // Make sure CS and other lines are low (dont leave programming mode)
  730.     cmdBuffer[PosCmdBuf++] = 0x80;
  731.     cmdBuffer[PosCmdBuf++] = 0x00;
  732.     cmdBuffer[PosCmdBuf++] = 0x2B;
  733.  
  734.     cmdBuffer[PosCmdBuf++] = 0x8F;
  735.     cmdBuffer[PosCmdBuf++] = 4*waitcycles-1;
  736.     cmdBuffer[PosCmdBuf++] = 0x00;
  737.   }
  738. }
  739.  
  740. BYTE ReadCart(DWORD addr, DWORD nBytes)
  741. {
  742.   DWORD i;
  743.   DWORD dwNumBytes, dwBytesRead;
  744.  
  745.   // Read bytes from the cart
  746.   if(nBytes == 0) return 0;
  747.   for(i=0;i<nBytes;i++) {
  748.     cmdBuffer[PosCmdBuf++] = 0x35;  // Command
  749.     cmdBuffer[PosCmdBuf++] = 3; // Anz. Bytes
  750.     cmdBuffer[PosCmdBuf++] = 0;
  751.     // Layout:
  752.     // xAAA AAAA AAAA AAAA AAAA xCxD DDDD DDDx
  753.     cmdBuffer[PosCmdBuf++] = (addr >> 12) & 0xFF;
  754.     cmdBuffer[PosCmdBuf++] = (addr >> 4) & 0xFF;
  755.     cmdBuffer[PosCmdBuf++] = ((addr << 4) & 0xF0);
  756.     cmdBuffer[PosCmdBuf++] = 0;
  757.     addr++;
  758.   }
  759.  
  760.   // Send all bytes
  761.   FlushOutBuffer();
  762.  
  763.   // wait for data to become available
  764.     do
  765.     FT_GetQueueStatus(ftHandle, &dwNumBytes);
  766.     while (dwNumBytes != nBytes*4);
  767.  
  768.   // read the input queue
  769.   FT_Read(ftHandle, datBuffer, dwNumBytes, &dwBytesRead);
  770.  
  771.   // Post processing of data
  772.   for(i=0;i<nBytes;i++) {
  773.     datBuffer[i] = ((datBuffer[i*4+2] & 1) << 7) | (datBuffer[i*4+3]>>1);
  774.   }
  775.  
  776.   return datBuffer[0];
  777. }
RAW Paste Data