Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- PokeFlash.cpp : Defines the entry point for the console application.
- vim: set ai ts=2 sw=2 sts=2 et:
- g++ -o PokeFlash PokeFlash.cpp -lftd2xx && ./PokeFlash -f menu.min
- */
- #include <iostream>
- using namespace std;
- #ifdef _WIN32
- #include <windows.h>
- #include <tchar.h>
- #pragma comment(lib, "ftd2xx.lib")
- #else
- #include <unistd.h>
- #include <sys/time.h>
- #define sscanf_s sscanf
- static inline int fopen_s(FILE **f, const char *fn, const char *m)
- {
- *f = fopen(fn,m);
- return 0;
- }
- static inline void Sleep(unsigned int ms)
- {
- usleep(ms*1000);
- }
- static inline unsigned int GetTickCount()
- {
- timeval tv1; gettimeofday(&tv1, NULL);
- return (tv1.tv_sec * 1000) + (tv1.tv_usec / 1000);
- }
- #endif
- #include <stdio.h>
- #include "ftd2xx.h"
- typedef unsigned char BYTE;
- #define DEV_DESC "Dual RS232-HS B" //"FT2232H MiniModule A"
- #define BUFSIZE (4*1024*1024) // 4MB - huge buffer to hold all the commands that are sent down the USB to the FT2232H
- #define BLOCKSIZE (8*1024) // We read/write chunks of 8kb to the cart
- #define NBLOCKS ((512*1024) / BLOCKSIZE)
- #define N_WAIT_CYCLES 24 //96 // How many wait cycles for byte programming?
- #define FLASH_RESET 0
- #define FLASH_MANUFACTURER 1
- #define FLASH_DEVICECODE 2
- #define FLASH_WRITEBYTE 3
- #define FLASH_CHIPERASE 4
- #define FLASH_SECERASE 5
- #define FLASH_DEVICECODEEX 6
- #define FLASH_UNLOCKBYP 7
- #define FLASH_RESETBYP 8
- // Command buffer
- BYTE cmdBuffer[BUFSIZE];
- int PosCmdBuf=0;
- // Data buffers
- BYTE datBuffer[BLOCKSIZE*4+1024];
- BYTE verBuffer[BLOCKSIZE*4+1024];
- FT_HANDLE ftHandle;
- FT_STATUS ftStatus;
- // clock divider
- DWORD clock_divider=1;
- // Flash infos
- BYTE manuf, devc, devcex;
- void CS_Low(void);
- void CS_High(void);
- void Power_Off(void);
- int Sync_To_MPSSE(void);
- int OpenDevice(void);
- void WriteCart(DWORD addr, BYTE dat, BYTE waitcycles);
- BYTE ReadCart(DWORD addr, DWORD nBytes);
- void FlushInBuffer(void);
- void FlushOutBuffer(void);
- void SetSpeed(BYTE speed);
- BYTE FlashProcess(int command, DWORD addr, BYTE data);
- BYTE ConvByt(BYTE byt);
- BYTE ConvBytBack(BYTE byt);
- int main(int argc, char* argv[])
- {
- FILE* fileOut, * fileIn;
- int bCtr, i, t, j;
- int fileErrors;
- int bytesRead;
- bool hasMenu=FALSE;
- const char* inFileName=NULL;
- const char* inFileNames[64];
- char* outFileName=NULL;
- DWORD time2;
- DWORD tErase,tProg,tRead;
- DWORD fSize;
- printf("PokeFlash V1.0 by Lupin\n\r");
- printf("http://lupin.shizzle.it\n\r");
- printf("-----------------------\n\r\n\r");
- if(argc<2) {
- printf("Usage: PokeFlash [-f infile1 [infile2] [more...]] [-d outfile] [-c divider]\n\r---------------------------------------------------------------------------\n\r");
- printf("-f infile Program binary file(s) to flash\n\r");
- printf(" Specify more than one file for menu ROM (menu.min needed)\n\r");
- printf("-d outfile Dump the cart contents to file\n\r");
- printf("-c divider Set clock divider (higher=slower); Values from 01 to 40 (hex)\n\r");
- getchar();
- return 0;
- }
- for(i=1;i<argc;i++) {
- if(strcmp(argv[i],"-f")==0) {
- t=0; j=i;
- inFileNames[t] = "menu.min";
- while(argv[++j] != NULL) {
- if(argv[j][0] == '-') break;
- inFileName=inFileNames[++t]=argv[j];
- }
- if(argv[j]==NULL) break;
- i=j;
- }
- if(strcmp(argv[i],"-c")==0) sscanf_s(argv[++i], "%02X", &clock_divider);
- if(strcmp(argv[i],"-d")==0) outFileName=argv[++i];
- }
- // Build menu ROM if more than one ROM
- if(t>1) {
- printf("Building menu ROM...\n\r");
- // Create output file
- fopen_s(&fileOut, "menu_out.min", "wb");
- if(!fileOut) {
- printf("File menu_out.min could not be created!\n\r");
- getchar();
- return 0;
- }
- for(i=0;i<=t;i++) {
- fopen_s(&fileIn, inFileNames[i],"rb");
- if(!fileIn) {
- printf("Input file %s could not be opened!\n\r", inFileNames[i]);
- getchar();
- return 0;
- }
- if(i>0) fseek(fileIn,8192,SEEK_SET); // Skip bios
- while((bytesRead = fread(&datBuffer, 1, BLOCKSIZE,fileIn)) !=0) {
- fwrite(&datBuffer, 1, bytesRead, fileOut);
- }
- fclose(fileIn);
- // Align position in output file to 8kb boundary
- fSize = ftell(fileOut);
- if(fSize & 0x1FFF) fseek(fileOut, (fSize & (~0x1FFF)) + 0x2000, SEEK_SET);
- }
- fSize = ftell(fileOut);
- fclose(fileOut);
- inFileName="menu_out.min";
- if(fSize > (512*1024)) {
- printf("Menu ROM is too big!\n\rMenu ROM size: %d kb\n\r", fSize>>10);
- getchar();
- return 0;
- }
- printf("Menu ROM created!\n\rMenu ROM size: %d kb\n\r\n\r", fSize>>10);
- hasMenu=TRUE;
- }
- // Connect to device
- if(!OpenDevice()) return 0;
- Sleep(50);
- // Check the flash type
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- WriteCart(0x555, ConvByt(0x90), 0);
- FlushOutBuffer();
- manuf = ConvBytBack(ReadCart(0x0, 1));
- devc = ConvBytBack(ReadCart(0x1, 1));
- devcex = ConvBytBack(ReadCart(0x3, 1));
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- WriteCart(0x555, ConvByt(0xF0), 0);
- FlushOutBuffer();
- if((manuf==0x1F) && (devc==0x13) && (devcex=0x0F)) {
- printf("Atmel AT49BV040A 512kb memory detected!\n\r\n\r");
- } else if((manuf==0x01) && (devc==0x4F)) {
- printf("AMD AM29LV040B 512kb memory detected!\n\r\n\r");
- } else {
- printf("Device not supported:\n\r");
- printf("Manufacturer code: %02X\n\r", manuf);
- printf("Device code: %02X\n\r", devc);
- printf("Extended code: %02X\n\r", devcex);
- getchar();
- return 0;
- }
- // Programming
- if(inFileName) {
- // Open file for programming
- fopen_s(&fileIn, inFileName, "rb");
- if(!fileIn) {
- printf("Input file %s could not be opened!\n\r", inFileName);
- getchar();
- return 0;
- }
- // Get file size
- fseek(fileIn, 0, SEEK_END);
- fSize = ftell(fileIn);
- fseek(fileIn, 0, SEEK_SET);
- if(fSize > (512*1024)) {
- printf("The input file is too large! Max. size is 512kb!\n\r");
- getchar();
- return 0;
- }
- // Chip erase or sector erase
- //CS_Low();
- if((fSize>0x40000)||hasMenu) {
- // File is >256kb - do chip erase
- printf("Chip Erase...\n\r");
- time2 = GetTickCount();
- FlashProcess(FLASH_CHIPERASE, 0, 0);
- while( (ReadCart(0, 1) != 0xFF) && ((GetTickCount()-time2) < 20000) ) continue;
- tErase=GetTickCount()-time2;
- printf("Chip erase done! Time: %dms\n\r\n\r", tErase);
- } else {
- // File is <256kb - erase each sector to save time
- // Erase lower 16kb - boot block
- time2 = GetTickCount();
- FlashProcess(FLASH_SECERASE, 0x00000, 0);
- while( (ReadCart(0x00000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
- tErase=GetTickCount()-time2;
- printf("Boot block erase done! Time: %dms\n\r", tErase);
- if(fSize > 0x04000) {
- // Erase parameter block 1
- time2 = GetTickCount();
- FlashProcess(FLASH_SECERASE, 0x04000, 0);
- while( (ReadCart(0x04000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
- tErase=GetTickCount()-time2;
- printf("Parameter block 1 erase done! Time: %dms\n\r", tErase);
- }
- if(fSize > 0x06000) {
- // Erase parameter block 2
- time2 = GetTickCount();
- FlashProcess(FLASH_SECERASE, 0x06000, 0);
- while( (ReadCart(0x06000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
- tErase=GetTickCount()-time2;
- printf("Parameter block 2 erase done! Time: %dms\n\r", tErase);
- }
- if(fSize > 0x08000) {
- // Erase memory block 1
- time2 = GetTickCount();
- FlashProcess(FLASH_SECERASE, 0x08000, 0);
- while( (ReadCart(0x08000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
- tErase=GetTickCount()-time2;
- printf("Memory block 1 erase done! Time: %dms\n\r", tErase);
- }
- if(fSize > 0x10000) {
- // Erase memory block 2
- time2 = GetTickCount();
- FlashProcess(FLASH_SECERASE, 0x10000, 0);
- while( (ReadCart(0x10000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
- tErase=GetTickCount()-time2;
- printf("Memory block 2 erase done! Time: %dms\n\r", tErase);
- }
- if(fSize > 0x20000) {
- // Erase memory block 3
- time2 = GetTickCount();
- FlashProcess(FLASH_SECERASE, 0x20000, 0);
- while( (ReadCart(0x20000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
- tErase=GetTickCount()-time2;
- printf("Memory block 3 erase done! Time: %dms\n\r", tErase);
- }
- if(fSize > 0x30000) {
- // Erase memory block 4
- time2 = GetTickCount();
- FlashProcess(FLASH_SECERASE, 0x30000, 0);
- while( (ReadCart(0x30000, 1) != 0xFF) && ((GetTickCount()-time2) < 5000) ) continue;
- tErase=GetTickCount()-time2;
- printf("Memory block 4 erase done! Time: %dms\n\r", tErase);
- }
- printf("\n\r");
- }
- // Programming
- printf("Programming flash...\n\r");
- time2 = GetTickCount();
- // Unlock bypass mode if flash supports it
- FlashProcess(FLASH_UNLOCKBYP, 0, 0);
- bytesRead=BLOCKSIZE;
- for(bCtr=0;(bCtr<NBLOCKS)&&(bytesRead==BLOCKSIZE);bCtr++) {
- bytesRead = fread(&datBuffer, 1, BLOCKSIZE, fileIn);
- // Write block
- for(i=0;i<bytesRead;i++) {
- FlashProcess(FLASH_WRITEBYTE, bCtr*BLOCKSIZE+i, datBuffer[i]);
- }
- FlushOutBuffer();
- printf("Block %d done!\n\r", bCtr);
- }
- FlashProcess(FLASH_RESETBYP, 0, 0);
- tProg = GetTickCount()-time2;
- printf("Programming done! Time: %dms\n\r\n\r", tProg);
- } else {
- // No programming was done, just doing a read operation
- //CS_Low();
- }
- // Read & verify
- // In this step we either do verify, dump to file or both
- if(outFileName) {
- fopen_s(&fileOut, outFileName, "wb");
- if(!fileOut) {
- printf("Output file does not exist!\n\r");
- getchar();
- return 0;
- }
- }
- printf("Read");
- if(inFileName) printf(" & verify");
- if(outFileName) printf(" & dump");
- printf("...\n\r");
- time2 = GetTickCount();
- if(inFileName) fseek(fileIn, 0, SEEK_SET);
- fileErrors=0;
- bytesRead=BLOCKSIZE;
- for(bCtr=0;(bCtr<NBLOCKS)&&(bytesRead==BLOCKSIZE);bCtr++) {
- ReadCart(bCtr*BLOCKSIZE, bytesRead);
- if(inFileName) {
- // Read from input file and do verify
- bytesRead=fread(&verBuffer, 1, BLOCKSIZE, fileIn);
- for(i=0;i<bytesRead;i++) {
- if(datBuffer[i] != verBuffer[i]) {
- if(fileErrors < 64) printf("Verify FAIL - Addr:%08X Orig:%02X Cart:%02X\n\r", bCtr*BLOCKSIZE+i, verBuffer[i], datBuffer[i]);
- fileErrors++;
- }
- }
- }
- if(outFileName) fwrite (&datBuffer, 1, bytesRead, fileOut);
- }
- if(inFileName) printf("Verify errors: %d\n\r", fileErrors);
- tRead = GetTickCount()-time2;
- printf("Reading done! Time: %dms\n\r\n\r", tRead);
- printf("Total time: %dms\n\r", inFileName?tErase+tProg+tRead:tRead);
- // Cleanup & End
- Power_Off();
- if(outFileName) fclose (fileOut);
- if(inFileName) fclose (fileIn);
- FT_Close(ftHandle);
- //getchar();
- return 0;
- }
- int OpenDevice(void)
- {
- int iDevCount,i;
- char buf[64];
- DWORD dwNumBytes, dwBytesRead;
- // How many devices?
- FT_ListDevices(&iDevCount, NULL, FT_LIST_NUMBER_ONLY);
- if (iDevCount == 0) {
- printf("No FTDI devices found. Please connect device and re-try.\n\r");
- getchar();
- return 0;
- }
- // Loop all devices and look for our device
- for(i=0;i<iDevCount;i++) {
- if(FT_ListDevices((void*)i, &buf, (FT_OPEN_BY_DESCRIPTION | FT_LIST_BY_INDEX)) != FT_OK) {
- printf("Failed reading device description!\n\r");
- getchar();
- return 0;
- }
- if(strcmp(buf, DEV_DESC)==0) {
- if(FT_OpenEx(&buf, FT_OPEN_BY_DESCRIPTION, &ftHandle) != FT_OK) {
- printf("Failed opening the device!\n\r");
- getchar();
- return 0;
- }
- break;
- }
- }
- // Step5: Setup latency
- if(FT_SetLatencyTimer(ftHandle, 16) != FT_OK) {
- printf("Set USB Device Latency Timer failed!\n\r");
- getchar();
- return 0;
- }
- // Step6: Reset controller
- if(FT_SetBitMode(ftHandle, 0x0, 0x0) != FT_OK) {
- printf("Device reset failed!\n\r");
- getchar();
- return 0;
- }
- // Step7: Set the port to MPSSE mode
- if(FT_SetBitMode(ftHandle, 0x0, 0x2) != FT_OK) {
- printf("Set to MPSSE mode failed!\n\r");
- getchar();
- return 0;
- }
- // Check sync...
- if (!Sync_To_MPSSE()) {
- printf("Unable to synchronise the MPSSE write/read cycle!\n\r");
- getchar();
- return 0;
- }
- // Config stuff
- //Bit0=CLK
- //Bit1=DO
- //Bit2=DI
- //Bit3=CS
- //Bit5=PWR
- //Bit7=PWR read
- // initialise the port
- PosCmdBuf = 0;
- // set the low byte
- cmdBuffer[PosCmdBuf++] = 0x80; // Set data bits low byte command
- cmdBuffer[PosCmdBuf++] = 0x20; // set CS=low, DI=low, DO=low, SK=low, PWR=high
- cmdBuffer[PosCmdBuf++] = 0x2B; // CS=input, DI=input, DO=output, SK=output, PWR=output,
- // set the clock divider
- cmdBuffer[PosCmdBuf++] = 0x86;
- cmdBuffer[PosCmdBuf++] = (BYTE)clock_divider;
- cmdBuffer[PosCmdBuf++] = 0x00;
- cmdBuffer[PosCmdBuf++] = 0x85; // turn off loopback
- cmdBuffer[PosCmdBuf++] = 0x8A; // turn off divider by 5
- FT_Write(ftHandle, &cmdBuffer, PosCmdBuf, &dwBytesRead);
- // now check if the cart is already powered (inside PM)
- PosCmdBuf=0;
- cmdBuffer[PosCmdBuf++] = 0x81;
- FT_Write(ftHandle, &cmdBuffer, PosCmdBuf, &dwBytesRead);
- PosCmdBuf=0;
- // wait for data to become available
- do
- FT_GetQueueStatus(ftHandle, &dwNumBytes);
- while (dwNumBytes != 1);
- // read the input queue
- FT_Read(ftHandle, &datBuffer, dwNumBytes, &dwBytesRead);
- if(datBuffer[0] & 0x80) {
- printf("Cart seems to be powered (VCC is on) - please turn off your PM!\n\r");
- getchar();
- return 0;
- }
- // Set CS high and power on cart
- CS_High();
- Sleep(10);
- // Set CS to low, start programming operation
- CS_Low();
- return 1;
- }
- void SetSpeed(BYTE speed)
- {
- DWORD dwBytesRead;
- cmdBuffer[PosCmdBuf++] = 0x86; // set clock divider command to 1MHz
- cmdBuffer[PosCmdBuf++] = speed; // low byte 60MHz / ((value+1)*2)
- cmdBuffer[PosCmdBuf++] = 0x00; // high byte
- FT_Write(ftHandle, &cmdBuffer, PosCmdBuf, &dwBytesRead);
- PosCmdBuf = 0;
- }
- void CS_Low(void)
- {
- DWORD dwBytesRead;
- cmdBuffer[PosCmdBuf++] = 0x80;
- cmdBuffer[PosCmdBuf++] = 0x00;
- cmdBuffer[PosCmdBuf++] = 0x2B;
- FT_Write(ftHandle, &cmdBuffer, PosCmdBuf, &dwBytesRead);
- PosCmdBuf = 0;
- }
- void CS_High(void)
- {
- DWORD dwBytesRead;
- cmdBuffer[PosCmdBuf++] = 0x80;
- cmdBuffer[PosCmdBuf++] = 0x08;
- cmdBuffer[PosCmdBuf++] = 0x2B;
- FT_Write(ftHandle, &cmdBuffer, PosCmdBuf, &dwBytesRead);
- PosCmdBuf = 0;
- }
- void Power_Off(void)
- {
- DWORD dwBytesRead;
- cmdBuffer[PosCmdBuf++] = 0x80;
- cmdBuffer[PosCmdBuf++] = 0x20;
- cmdBuffer[PosCmdBuf++] = 0x00;
- FT_Write(ftHandle, &cmdBuffer, PosCmdBuf, &dwBytesRead);
- PosCmdBuf = 0;
- }
- int Sync_To_MPSSE(void)
- {
- DWORD dwNumBytes, dwBytesRead;
- // uses &HAA and &HAB commands which are invalid so that the MPSSE processor should
- // echo these back to use preceded with &HFA
- // clear anything in the input buffer
- FT_GetQueueStatus(ftHandle, &dwNumBytes);
- if (dwNumBytes > 0) {
- // read chunks of 'input buffer size'
- while (dwNumBytes > BLOCKSIZE)
- {
- FT_Read(ftHandle, &datBuffer, BLOCKSIZE, &dwBytesRead);
- dwNumBytes -= dwBytesRead;
- }
- FT_Read(ftHandle, &datBuffer, dwNumBytes, &dwBytesRead); // read the final bytes
- }
- // put a bad command to the command processor
- // Send 0xAA
- cmdBuffer[0] = 0xAA;
- FT_Write(ftHandle, &cmdBuffer, 1, &dwBytesRead);
- // wait for a response
- do
- FT_GetQueueStatus(ftHandle, &dwNumBytes);
- while (dwNumBytes != 2);
- // read the input queue
- FT_Read(ftHandle, &datBuffer, dwNumBytes, &dwBytesRead);
- if((datBuffer[0] == 0xFA) && (datBuffer[1] == 0xAA))
- {
- return 1;
- }
- return 0;
- }
- BYTE FlashProcess(int command, DWORD addr, BYTE data)
- {
- BYTE tmp;
- switch(command) {
- case FLASH_UNLOCKBYP:
- if((manuf==0x01) && (devc==0x4F)) {
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- WriteCart(0x555, ConvByt(0x20), 0);
- }
- return 1;
- case FLASH_RESETBYP:
- if((manuf==0x01) && (devc==0x4F)) {
- WriteCart(0, ConvByt(0x90), 0);
- WriteCart(0, 0, 0);
- }
- return 1;
- case FLASH_RESET:
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- WriteCart(0x555, ConvByt(0xF0), 0);
- FlushOutBuffer();
- return 1;
- case FLASH_MANUFACTURER:
- WriteCart(0x555, ConvByt(0xAA), 10);
- WriteCart(0xAAA, ConvByt(0x55), 10);
- WriteCart(0x555, ConvByt(0x90), 10);
- tmp = ConvByt(ReadCart(0x0, 1));
- WriteCart(0x555, ConvByt(0xAA), 10);
- WriteCart(0xAAA, ConvByt(0x55), 10);
- WriteCart(0x555, ConvByt(0xF0), 10);
- FlushOutBuffer();
- return tmp;
- case FLASH_DEVICECODE:
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- WriteCart(0x555, ConvByt(0x90), 0);
- tmp = ConvByt(ReadCart(0x1, 1));
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- WriteCart(0x555, ConvByt(0xF0), 0);
- FlushOutBuffer();
- return tmp;
- case FLASH_DEVICECODEEX:
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- WriteCart(0x555, ConvByt(0x90), 0);
- tmp = ConvByt(ReadCart(0x3, 1));
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- WriteCart(0x555, ConvByt(0xF0), 0);
- FlushOutBuffer();
- return tmp;
- case FLASH_WRITEBYTE:
- if (data==0xFF) return 1;
- // Full sequence only needed for devices without bypass
- if(!((manuf==0x01) && (devc==0x4F))) {
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- }
- WriteCart(0x555, ConvByt(0xA0), 0);
- WriteCart(addr, data, (BYTE)(N_WAIT_CYCLES / (clock_divider + 1)));
- return 1;
- case FLASH_CHIPERASE:
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- WriteCart(0x555, ConvByt(0x80), 0);
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- WriteCart(0x555, ConvByt(0x10), 0);
- FlushOutBuffer();
- return 1;
- case FLASH_SECERASE:
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- WriteCart(0x555, ConvByt(0x80), 0);
- WriteCart(0x555, ConvByt(0xAA), 0);
- WriteCart(0xAAA, ConvByt(0x55), 0);
- WriteCart(addr, ConvByt(0x30), 0);
- FlushOutBuffer();
- return 1;
- }
- return 0;
- }
- void FlushInBuffer(void)
- {
- DWORD dwNumBytes, dwBytesRead;
- FT_GetQueueStatus(ftHandle, &dwNumBytes);
- FT_Read(ftHandle, &datBuffer, dwNumBytes, &dwBytesRead);
- }
- void FlushOutBuffer(void)
- {
- DWORD dwBytesWritten;
- cmdBuffer[PosCmdBuf++] = 0x87;
- FT_Write(ftHandle, cmdBuffer, PosCmdBuf, &dwBytesWritten);
- PosCmdBuf = 0;
- }
- BYTE ConvByt(BYTE byt)
- {
- BYTE bret=0;
- if (byt & (1<<0)) bret |= 1<<7;
- if (byt & (1<<1)) bret |= 1<<5;
- if (byt & (1<<2)) bret |= 1<<3;
- if (byt & (1<<3)) bret |= 1<<1;
- if (byt & (1<<4)) bret |= 1<<0;
- if (byt & (1<<5)) bret |= 1<<2;
- if (byt & (1<<6)) bret |= 1<<4;
- if (byt & (1<<7)) bret |= 1<<6;
- return bret;
- }
- BYTE ConvBytBack(BYTE byt)
- {
- BYTE bret=0;
- if (byt & (1<<7)) bret |= 1<<0;
- if (byt & (1<<5)) bret |= 1<<1;
- if (byt & (1<<3)) bret |= 1<<2;
- if (byt & (1<<1)) bret |= 1<<3;
- if (byt & (1<<0)) bret |= 1<<4;
- if (byt & (1<<2)) bret |= 1<<5;
- if (byt & (1<<4)) bret |= 1<<6;
- if (byt & (1<<6)) bret |= 1<<7;
- return bret;
- }
- void WriteCart(DWORD addr, BYTE dat, BYTE waitcycles)
- {
- // Send 4 Bytes
- cmdBuffer[PosCmdBuf++] = 0x11;
- cmdBuffer[PosCmdBuf++] = 0x03;
- cmdBuffer[PosCmdBuf++] = 0x00;
- // Layout:
- // xAAA AAAA AAAA AAAA AAAA xCxD DDDD DDDx
- cmdBuffer[PosCmdBuf++] = (addr >> 12) & 0xFF;
- cmdBuffer[PosCmdBuf++] = (addr >> 4) & 0xFF;
- cmdBuffer[PosCmdBuf++] = ((addr << 4) & 0xF0) | 0x4 | (dat>>7);
- cmdBuffer[PosCmdBuf++] = (dat<<1) & 0xFE;
- if(waitcycles>0) {
- // Make sure CS and other lines are low (dont leave programming mode)
- cmdBuffer[PosCmdBuf++] = 0x80;
- cmdBuffer[PosCmdBuf++] = 0x00;
- cmdBuffer[PosCmdBuf++] = 0x2B;
- cmdBuffer[PosCmdBuf++] = 0x8F;
- cmdBuffer[PosCmdBuf++] = 4*waitcycles-1;
- cmdBuffer[PosCmdBuf++] = 0x00;
- }
- }
- BYTE ReadCart(DWORD addr, DWORD nBytes)
- {
- DWORD i;
- DWORD dwNumBytes, dwBytesRead;
- // Read bytes from the cart
- if(nBytes == 0) return 0;
- for(i=0;i<nBytes;i++) {
- cmdBuffer[PosCmdBuf++] = 0x35; // Command
- cmdBuffer[PosCmdBuf++] = 3; // Anz. Bytes
- cmdBuffer[PosCmdBuf++] = 0;
- // Layout:
- // xAAA AAAA AAAA AAAA AAAA xCxD DDDD DDDx
- cmdBuffer[PosCmdBuf++] = (addr >> 12) & 0xFF;
- cmdBuffer[PosCmdBuf++] = (addr >> 4) & 0xFF;
- cmdBuffer[PosCmdBuf++] = ((addr << 4) & 0xF0);
- cmdBuffer[PosCmdBuf++] = 0;
- addr++;
- }
- // Send all bytes
- FlushOutBuffer();
- // wait for data to become available
- do
- FT_GetQueueStatus(ftHandle, &dwNumBytes);
- while (dwNumBytes != nBytes*4);
- // read the input queue
- FT_Read(ftHandle, datBuffer, dwNumBytes, &dwBytesRead);
- // Post processing of data
- for(i=0;i<nBytes;i++) {
- datBuffer[i] = ((datBuffer[i*4+2] & 1) << 7) | (datBuffer[i*4+3]>>1);
- }
- return datBuffer[0];
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement