// Find offsets where a byte changes from one specific value to another // int main(int argc, char *argv[]) { int retVal; uint8 *beforeFile = NULL; uint8 *afterFile = NULL; uint8 byteBefore; uint8 byteAfter; size_t beforeLength; size_t afterLength; uint32 i; if ( argc != 5 ) { fprintf(stderr, "Synopsis: %s <before.bin> <after.bin> <byteBefore> <byteAfter>\n", argv[0]); FAIL(1, cleanup); } beforeFile = flLoadFile(argv[1], &beforeLength); if ( !beforeFile ) { fprintf(stderr, "File %s cannot be loaded\n", argv[1]); FAIL(2, cleanup); } afterFile = flLoadFile(argv[2], &afterLength); if ( !afterFile ) { fprintf(stderr, "File %s cannot be loaded\n", argv[2]); FAIL(2, cleanup); } if ( beforeLength != afterLength ) { fprintf(stderr, "Files are of different lengths\n"); FAIL(3, cleanup); } byteBefore = (uint8)strtoul(argv[3], NULL, 0); byteAfter = (uint8)strtoul(argv[4], NULL, 0); for ( i = 0; i < beforeLength; i++ ) { if ( beforeFile[i] == byteBefore && afterFile[i] == byteAfter ) { printf("Candidate: 0x%08X\n", i); } } retVal = 0; cleanup: flFreeFile(afterFile); flFreeFile(beforeFile); return retVal; }
// Direct-write a binary file to the specified address. The area of memory to be written must reside // entirely within one of the two direct-writable memory areas (0x000000-0x07FFFF and // 0x400000-0x47FFFF, mapped to SDRAM pages 0 and 31 respectively) and must have an even start // address and length. The MegaDrive need not be suspended at the monitor. // int umdkDirectWriteFile( struct FLContext *handle, uint32 address, const char *fileName, const char **error) { int retVal = 0; FLStatus status; uint8 command[8]; uint32 wordAddr; size_t byteCount; size_t wordCount; uint8 *const fileData = flLoadFile(fileName, &byteCount); CHECK_STATUS(!fileData, 1, cleanup, "umdkDirectWriteFile(): Cannot read from %s!", fileName); // Verify the write is in a legal range if ( isInside(MONITOR, 0x80000, address, byteCount) ) { // Write is to the UMDKv2-reserved 512KiB of address-space at 0x400000. The mapping for this // is fixed to the top 512KiB of SDRAM, so we need to transpose the MD virtual address to // get the correct SDRAM physical address. address += 0xb80000; } else if ( !isInside(0, 0x80000, address, byteCount) ) { // The only other region of the address-space which is directly host-addressable is the // bottom 512KiB of address-space, which has a logical-physical mapping that is guaranteed // by SEGA to be 1:1 (i.e no transpose necessary). So any attempt to directly access memory // anywhere else is an error. CHECK_STATUS( true, 1, cleanup, "umdkDirectWriteFile(): Illegal direct-write to 0x%06X-0x%06X range!", address, address+byteCount-1 ); } // Next verify that the write is to an even address, and has even length CHECK_STATUS(address&1, 2, cleanup, "umdkDirectWriteFile(): Address must be even!"); CHECK_STATUS(byteCount&1, 3, cleanup, "umdkDirectWriteFile(): File must have even length!"); // Get word-count and word-address wordAddr = address / 2; wordCount = byteCount / 2; // Prepare the write command prepMemCtrlCmd(0x00, wordAddr, command); prepMemCtrlCmd(0x80, wordCount, command+4); // Do the write status = flWriteChannelAsync(handle, 0x00, 8, command, error); CHECK_STATUS(status, 4, cleanup); status = flWriteChannelAsync(handle, 0x00, byteCount, fileData, error); CHECK_STATUS(status, 5, cleanup); cleanup: flFreeFile(fileData); return retVal; }
int main(int argc, const char *argv[]) { int returnCode; struct FLContext *handle = NULL; FLStatus status; const char *error = NULL; uint8 byte = 0x10; uint8 buf[256]; bool flag; bool isNeroCapable, isCommCapable; uint32 fileLen; uint8 *buffer = NULL; uint32 numDevices, scanChain[16], i; const char *vp = NULL, *ivp = NULL, *queryPort = NULL, *portConfig = NULL, *progConfig = NULL, *dataFile = NULL; const char *const prog = argv[0]; printf("FPGALink \"C\" Example Copyright (C) 2011-2013 Chris McClelland\n\n"); argv++; argc--; while ( argc ) { if ( argv[0][0] != '-' ) { unexpected(prog, *argv); FAIL(1); } switch ( argv[0][1] ) { case 'h': usage(prog); FAIL(0); break; case 'q': GET_ARG("q", queryPort, 2); break; case 'd': GET_ARG("d", portConfig, 3); break; case 'v': GET_ARG("v", vp, 4); break; case 'i': GET_ARG("i", ivp, 5); break; case 'p': GET_ARG("p", progConfig, 6); break; case 'f': GET_ARG("f", dataFile, 7); break; default: invalid(prog, argv[0][1]); FAIL(8); } argv++; argc--; } if ( !vp ) { missing(prog, "v <VID:PID>"); FAIL(9); } status = flInitialise(0, &error); CHECK(10); printf("Attempting to open connection to FPGALink device %s...\n", vp); status = flOpen(vp, &handle, NULL); if ( status ) { if ( ivp ) { int count = 60; printf("Loading firmware into %s...\n", ivp); status = flLoadStandardFirmware(ivp, vp, &error); CHECK(11); printf("Awaiting renumeration"); flSleep(1000); do { printf("."); fflush(stdout); flSleep(100); status = flIsDeviceAvailable(vp, &flag, &error); CHECK(12); count--; } while ( !flag && count ); printf("\n"); if ( !flag ) { fprintf(stderr, "FPGALink device did not renumerate properly as %s\n", vp); FAIL(13); } printf("Attempting to open connection to FPGLink device %s again...\n", vp); status = flOpen(vp, &handle, &error); CHECK(14); } else { fprintf(stderr, "Could not open FPGALink device at %s and no initial VID:PID was supplied\n", vp); FAIL(15); } } if ( portConfig ) { printf("Configuring ports...\n"); status = flPortConfig(handle, portConfig, &error); CHECK(16); flSleep(100); } isNeroCapable = flIsNeroCapable(handle); isCommCapable = flIsCommCapable(handle); if ( queryPort ) { if ( isNeroCapable ) { status = jtagScanChain(handle, queryPort, &numDevices, scanChain, 16, &error); CHECK(17); if ( numDevices ) { printf("The FPGALink device at %s scanned its JTAG chain, yielding:\n", vp); for ( i = 0; i < numDevices; i++ ) { printf(" 0x%08X\n", scanChain[i]); } } else { printf("The FPGALink device at %s scanned its JTAG chain but did not find any attached devices\n", vp); } } else { fprintf(stderr, "JTAG chain scan requested but FPGALink device at %s does not support NeroJTAG\n", vp); FAIL(18); } } if ( progConfig ) { printf("Executing programming configuration \"%s\" on FPGALink device %s...\n", progConfig, vp); if ( isNeroCapable ) { status = flProgram(handle, progConfig, NULL, &error); CHECK(19); } else { fprintf(stderr, "Program operation requested but device at %s does not support NeroProg\n", vp); FAIL(20); } } if ( dataFile ) { if ( isCommCapable ) { printf("Enabling FIFO mode...\n"); status = flFifoMode(handle, true, &error); CHECK(21); printf("Zeroing registers 1 & 2...\n"); byte = 0x00; status = flWriteChannel(handle, 1000, 0x01, 1, &byte, &error); CHECK(22); status = flWriteChannel(handle, 1000, 0x02, 1, &byte, &error); CHECK(23); buffer = flLoadFile(dataFile, &fileLen); if ( buffer ) { uint16 checksum = 0x0000; uint32 i; for ( i = 0; i < fileLen; i++ ) { checksum += buffer[i]; } printf( "Writing %0.2f MiB (checksum 0x%04X) from %s to FPGALink device %s...\n", (double)fileLen/(1024*1024), checksum, dataFile, vp); status = flWriteChannel(handle, 30000, 0x00, fileLen, buffer, &error); CHECK(24); } else { fprintf(stderr, "Unable to load file %s!\n", dataFile); FAIL(25); } printf("Reading channel 0..."); status = flReadChannel(handle, 1000, 0x00, 1, buf, &error); CHECK(26); printf("got 0x%02X\n", buf[0]); printf("Reading channel 1..."); status = flReadChannel(handle, 1000, 0x01, 1, buf, &error); CHECK(27); printf("got 0x%02X\n", buf[0]); printf("Reading channel 2..."); status = flReadChannel(handle, 1000, 0x02, 1, buf, &error); CHECK(28); printf("got 0x%02X\n", buf[0]); } else { fprintf(stderr, "Data file load requested but device at %s does not support CommFPGA\n", vp); FAIL(29); } } returnCode = 0; cleanup: if ( error ) { fprintf(stderr, "%s\n", error); flFreeError(error); } flFreeFile(buffer); flClose(handle); return returnCode; }