Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // TODO: Allow direct reads/writes to GEC
- // TODO: Allow to specify serial port and speed to use
- // TODO: Support other mappers
- // TODO: Allow using multiple in length arguments (such as 1024KiB, 2MiB...)
- // Also print lengths using these multiples
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <getopt.h>
- #include "fsm.h"
- #define MAX_FILELEN 255
- #define VERSION_MAJOR 0x00
- #define VERSION_MINOR 0x01
- #ifndef TRUE
- #define TRUE 1
- #endif
- #ifndef FALSE
- #define FALSE 0
- #endif
- #ifndef NULL
- #define NULL ((void*)0)
- #endif
- /// Structure containing a memory image (file, address and length)
- typedef struct {
- char *file;
- uint32_t addr;
- uint32_t len;
- } MemImage;
- /// printf-like macro that writes on stderr instead of stdout
- #define PrintErr(...) do{fprintf(stderr, __VA_ARGS__);}while(0)
- const struct option opt[] = {
- {"flash", required_argument, NULL, 'f'},
- {"read", required_argument, NULL, 'r'},
- {"erase", no_argument, NULL, 'e'},
- {"verify", no_argument, NULL, 'V'},
- {"write-save", required_argument, NULL, 'w'},
- {"back-save", required_argument, NULL, 'b'},
- {"cart-info", no_argument, NULL, 'c'},
- {"flash-id", no_argument, NULL, 'i'},
- {"version", no_argument, NULL, 'R'},
- {"verbose", no_argument, NULL, 'v'},
- {"help", no_argument, NULL, 'h'},
- {NULL, 0, NULL, 0 }
- };
- const char *description[] = {
- "Flash rom file",
- "Read ROM/Flash to file",
- "Erase Flash",
- "Verify flash after writing file",
- "Write file to SRAM",
- "Backup SRAM to file",
- "Show cartridge information",
- "Show flash chip identification",
- "Print version and exit",
- "Show more information during execution",
- "Print help screen and exit"
- };
- void PrintVersion(char *prgName) {
- printf("%s version %d.%d, doragasu 2015.\n", prgName,
- VERSION_MAJOR, VERSION_MINOR);
- }
- void PrintHelp(char *prgName) {
- int i;
- PrintVersion(prgName);
- printf("Usage: %s [OPTIONS [OPTION_ARG]]\nSupported options:\n\n", prgName);
- for (i = 0; opt[i].name; i++) {
- printf(" -%c, --%s%s: %s.\n", opt[i].val, opt[i].name,
- opt[i].has_arg == required_argument?" <arg>":"",
- description[i]);
- }
- // Print additional info
- printf("For file arguments, it is possible to specify start address and "
- "file length to read/write in bytes, with the following format:\n"
- " file_name:memory_address:file_length\n\n"
- "Examples:\n"
- " - Erase Flash and write entire ROM to cartridge: %s -ef rom_file\n"
- " - Flash and verify 32 KiB to 0x700000: "
- "%s -Vf rom_file:0x700000:32768\n"
- " - Dump 1 MiB of the cartridge: %s -r rom_file::1048576\n"
- " - Backup cartridge SRAM: %s --back-save saver_file\n\n"
- "SRAM reads/writes must fall within the hex range 0~7FFF\n"
- "ROM/Flash reads/writes must fall within the hex range 0~7FFFFF\n",
- prgName, prgName, prgName, prgName);
- }
- /// Receives a MemImage pointer with full info in file name (e.g.
- /// m->file = "rom.bin:6000:1"). Removes from m->file information other
- /// than the file name, and fills the remaining structure fields if info
- /// is provided (e.g. info in previous example would cause m = {"rom.bin",
- /// 0x6000, 1}).
- int ParseMemArgument(MemImage *m) {
- int i;
- char *addr = NULL;
- char *len = NULL;
- char *endPtr;
- // Set address and length to default values
- m->len = m->addr = 0;
- // First argument is name. Find where it ends
- for (i = 0; i < (MAX_FILELEN + 1) && m->file[i] != '\0' &&
- m->file[i] != ':'; i++);
- // Check if end reached without finding end of string
- if (i == MAX_FILELEN + 1) return 1;
- if (m->file[i] == '\0') return 0;
- // End of token marker, search address
- m->file[i++] = '\0';
- addr = m->file + i;
- for (; i < (MAX_FILELEN + 1) && m->file[i] != '\0' && m->file[i] != ':';
- i++);
- // Check if end reached without finding end of string
- if (i == MAX_FILELEN + 1) return 1;
- // If end of token marker, search length
- if (m->file[i] == ':') {
- m->file[i++] = '\0';
- len = m->file + i;
- // Verify there's an end of string
- for (; i < (MAX_FILELEN + 1) && m->file[i] != '\0'; i++);
- if (m->file[i] != '\0') return 1;
- }
- // Convert strings to numbers and return
- if (addr && *addr) m->addr = strtol(addr, &endPtr, 0);
- if (m->addr == 0 && addr == endPtr) return 2;
- if (len && *len) m->len = strtol(len, &endPtr, 0);
- if (m->len == 0 && len == endPtr) return 3;
- return 0;
- }
- void PrintMemImage(MemImage *m) {
- printf("%s", m->file);
- if (m->addr) printf(" at address 0x%06X", m->addr);
- if (m->len ) printf(" (%d bytes)", m->len);
- }
- void PrintMemError(int code) {
- switch (code) {
- case 0: printf("Memory range OK.\n"); break;
- case 1: PrintErr("Invalid memory range string.\n"); break;
- case 2: PrintErr("Invalid memory address.\n"); break;
- case 3: PrintErr("Invalid memory length.\n"); break;
- default: PrintErr("Unknown memory specification error.\n");
- }
- }
- int main(int argc, char **argv) {
- /// Option index, for command line options parsing
- int opIdx = 0;
- /// Character returned by getopt_long()
- int c;
- /// Erase flash if TRUE
- int erase = FALSE;
- /// Verify flash write if TRUE
- int verify = FALSE;
- /// Print extra information on screen
- int verbose = FALSE;
- /// Show cartridge information
- int cartInfo = FALSE;
- /// Show flash chip id
- int flashId = FALSE;
- /// Rom file to write to flash
- MemImage fWr = {NULL, 0, 0};
- /// Rom file to read from flash (default read length: 1 MiB)
- MemImage fRd = {NULL, 0, 1024*1024};
- /// Ram file to write
- MemImage rWr = {NULL, 0, 0};
- /// Ram file to read (default read length: 32 KiB)
- MemImage rRd = {NULL, 0, 32*1024};
- /// Error code for function calls
- int errCode;
- /// Parse command line switches
- if (1 == argc) {
- printf("Nothing to do!\n");
- PrintHelp(argv[0]);
- return 0;
- }
- while ((c = getopt_long(argc, argv, "f:r:eVw:b:ciRvh", opt,
- &opIdx)) != -1) {
- // Parse command-line options
- switch (c) {
- case 'f': // Write flash
- fWr.file = optarg;
- if ((errCode = ParseMemArgument(&fWr))) {
- PrintErr("Error: On Flash file argument: ");
- PrintMemError(errCode);
- return 1;
- }
- break;
- case 'r': // Read flash
- fRd.file = optarg;
- if ((errCode = ParseMemArgument(&fRd))) {
- PrintErr("Error: On ROM/Flash read argument: ");
- PrintMemError(errCode);
- return 1;
- }
- break;
- case 'e': // Erase flash
- erase = TRUE;
- break;
- case 'V': // Verify flash write
- verify = TRUE;
- break;
- case 'w': // Write RAM
- rWr.file = optarg;
- if ((errCode = ParseMemArgument(&rWr))) {
- PrintErr("Error: On RAM write argument: ");
- PrintMemError(errCode);
- return 1;
- }
- break;
- case 'b': // Read RAM
- rRd.file = optarg;
- if ((errCode = ParseMemArgument(&rRd))) {
- PrintErr("Error: On RAM read argument: ");
- PrintMemError(errCode);
- return 1;
- }
- break;
- case 'c': // Cart info
- cartInfo = TRUE;
- break;
- case 'i': // Flash chip id
- flashId = TRUE;
- break;
- case 'R': // Print program version
- PrintVersion(argv[0]);
- return 0;
- case 'v': // Verbose
- verbose = TRUE;
- break;
- case 'h': // Print help
- PrintHelp(argv[0]);
- return 0;
- case '?': // Unknown switch
- PrintHelp(argv[0]);
- return 1;
- }
- }
- // If verbose, print config
- if (verbose) {
- printf("The following actions will be performed (in order):\n");
- printf("==================================================\n\n");
- if (cartInfo) printf(" - Show cartridge header information.\n");
- if (flashId) printf(" - Show Flash chip identification.\n");
- if (erase) printf(" - Erase Flash.\n");
- if (fWr.file) {
- printf(" - Flash %s", verify?"and verify ":"");
- PrintMemImage(&fWr); putchar('\n');
- }
- if (fRd.file) {
- printf(" - Read ROM/Flash to ");
- PrintMemImage(&fRd); putchar('\n');
- }
- if (rWr.file) {
- printf(" - Write to SRAM ");
- PrintMemImage(&rWr); putchar('\n');
- }
- if (rRd.file) {
- printf(" - Read SRAM to ");
- PrintMemImage(&rRd); putchar('\n');
- }
- printf("\n");
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement