From c5e4a2c2daba0efb2029d2ebba1c9d4353484fcf Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 5 Nov 2020 01:53:35 +0200 Subject: [PATCH] support LoROM --- flashkit.c | 157 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 133 insertions(+), 24 deletions(-) diff --git a/flashkit.c b/flashkit.c index e6d5785..75f348e 100644 --- a/flashkit.c +++ b/flashkit.c @@ -135,6 +135,16 @@ static void set_addr16(int fd, uint32_t addr) set_addr8(fd, addr >> 1); } +static uint32_t lorom_addr(uint32_t a) +{ + return ((a & 0x7f8000) << 1) | 0x8000 | (a & 0x7fff); +} + +static void set_addr8l(int fd, uint32_t addr) +{ + set_addr8(fd, lorom_addr(addr)); +} + static uint16_t read_bus8(int fd, uint32_t addr) { uint8_t cmd[7] = { @@ -165,6 +175,11 @@ static uint16_t read_bus16(int fd, uint32_t addr) return ntohs(r); } +static uint16_t read_bus8l(int fd, uint32_t addr) +{ + return read_bus8(fd, lorom_addr(addr)); +} + static void write_bus8(int fd, uint32_t addr, uint16_t d) { uint8_t cmd[8] = { @@ -191,6 +206,11 @@ static void write_bus16(int fd, uint32_t addr, uint16_t d) write_serial(fd, cmd, sizeof(cmd)); } +static void write_bus8l(int fd, uint32_t addr, uint16_t d) +{ + write_bus8(fd, lorom_addr(addr), d); +} + static void read_block8(int fd, void *dst, uint32_t size) { // PAR_MODE8 does not work, so read as 16bit and throw away MSB @@ -283,8 +303,43 @@ static void flash_seq_write16(int fd, uint32_t addr, const uint8_t *d) write_serial(fd, cmd, sizeof(cmd)); } +static void flash_seq_write8l(int fd, uint32_t addr, const uint8_t *d) +{ + addr = lorom_addr(addr); + uint8_t cmd[] = { + // unlock + CMD_ADDR, 0, + CMD_ADDR, 0x8a, + CMD_ADDR, 0xaa, + CMD_WR | PAR_SINGE | PAR_MODE8, 0xaa, + CMD_ADDR, 0, + CMD_ADDR, 0x85, + CMD_ADDR, 0x55, + CMD_WR | PAR_SINGE | PAR_MODE8, 0x55, + // program setup + CMD_ADDR, 0, + CMD_ADDR, 0x8a, + CMD_ADDR, 0xaa, + CMD_WR | PAR_SINGE | PAR_MODE8, 0xa0, + // program data + CMD_ADDR, addr >> 16, + CMD_ADDR, addr >> 8, + CMD_ADDR, addr >> 0, + CMD_WR | PAR_SINGE | PAR_MODE8, *d, + CMD_RY + }; + + write_serial(fd, cmd, sizeof(cmd)); +} + +#define N0 "" +#define N1 "8bit" +#define N2 "8bit+LoROM" +#define N3 "8bit+LoROM+adapter" static const struct iof { + const char *name; + int addrs_remapped; void (*set_addr)(int fd, uint32_t addr); uint16_t (*read_bus)(int fd, uint32_t addr); void (*write_bus)(int fd, uint32_t addr, uint16_t d); @@ -293,11 +348,12 @@ static const struct iof } io_ops[] = { - { set_addr8, read_bus8, write_bus8, read_block8, flash_seq_write8 }, - { set_addr16, read_bus16, write_bus16, read_block16, flash_seq_write16 }, + { N0, 0, set_addr16, read_bus16, write_bus16, read_block16, flash_seq_write16 }, + { N1, 0, set_addr8, read_bus8, write_bus8, read_block8, flash_seq_write8 }, + { N2, 1, set_addr8l, read_bus8l, write_bus8l, read_block8, flash_seq_write8l }, }; -static const struct iof *io = &io_ops[1]; +static const struct iof *io = &io_ops[0]; static uint16_t flash_seq_r(int fd, uint8_t cmd, uint32_t addr) { @@ -309,7 +365,7 @@ static uint16_t flash_seq_r(int fd, uint8_t cmd, uint32_t addr) return io->read_bus(fd, addr); } -static void flash_seq_erase(int fd, uint32_t addr) +static void flash_seq_erase_d(int fd, uint32_t addr, uint8_t d) { // printf("erase %06x\n", addr); io->write_bus(fd, 0xaaa, 0xaa); @@ -318,7 +374,17 @@ static void flash_seq_erase(int fd, uint32_t addr) io->write_bus(fd, 0xaaa, 0xaa); io->write_bus(fd, 0x555, 0x55); - io->write_bus(fd, addr, 0x30); + io->write_bus(fd, addr, d); +} + +static void flash_seq_erase(int fd, uint32_t addr) +{ + flash_seq_erase_d(fd, addr, 0x30); +} + +static void flash_seq_erase_full(int fd) +{ + flash_seq_erase_d(fd, 0xaaa, 0x10); } // status wait + dummy read to cause a wait? @@ -475,18 +541,23 @@ static const char *portname = static void usage(const char *argv0) { + size_t i; + printf("usage:\n" "%s [options]\n" " -d (default %s)\n" " -r [size] dump the cart (default 4MB)\n" " -w [size] program the flash (def. file size)\n" " -s [size] simple write (SRAM, etc, def. file size)\n" - " -e erase (rounds to block size)\n" + " -e erase (rounds to block size); can specify 'full'\n" " -a read/write start address (default 0)\n" - " -8 8bit flash\n" - " -v verify written data\n" - " -i get info about the flash chip\n" + " -m use an address mapper n, one of:\n" , argv0, portname); + for (i = 1; i < sizeof(io_ops) / sizeof(io_ops[0]); i++) + printf( + " %zd: %s\n", i, io_ops[i].name); + printf( " -v verify written data\n" + " -i get info about the flash chip\n"); exit(1); } @@ -506,8 +577,22 @@ static void *getarg(int argc, char *argv[], int arg) return argv[arg]; } -static uint8_t g_block[0x10000]; -static uint8_t g_block2[0x10000]; +static long getarg_l(int argc, char *argv[], int arg) +{ + char *endp = NULL; + long r; + + if (arg >= argc) + invarg(argc, argv, arg); + r = strtol(argv[arg], &endp, 0); + if (endp == NULL || *endp != 0) + invarg(argc, argv, arg); + return r; +} + +// 32K to easily handle SNES LoROM +static uint8_t g_block[0x8000]; +static uint8_t g_block2[sizeof(g_block)]; int main(int argc, char *argv[]) { @@ -544,7 +629,7 @@ int main(int argc, char *argv[]) if (!strcmp(argv[arg], "-r")) { fname_r = getarg(argc, argv, ++arg); if (arg + 1 < argc && argv[arg + 1][0] != '-') { - size_r = strtol(argv[++arg], NULL, 0); + size_r = getarg_l(argc, argv, ++arg); if (size_r <= 0) invarg(argc, argv, arg); } @@ -553,7 +638,7 @@ int main(int argc, char *argv[]) if (!strcmp(argv[arg], "-w")) { fname_w = getarg(argc, argv, ++arg); if (arg + 1 < argc && argv[arg + 1][0] != '-') { - size_w = strtol(argv[++arg], NULL, 0); + size_w = getarg_l(argc, argv, ++arg); if (size_w <= 0) invarg(argc, argv, arg); } @@ -562,27 +647,36 @@ int main(int argc, char *argv[]) if (!strcmp(argv[arg], "-s")) { fname_ws = getarg(argc, argv, ++arg); if (arg + 1 < argc && argv[arg + 1][0] != '-') { - size_ws = strtol(argv[++arg], NULL, 0); + size_ws = getarg_l(argc, argv, ++arg); if (size_ws <= 0) invarg(argc, argv, arg); } continue; } if (!strcmp(argv[arg], "-a")) { - address_in = strtol(getarg(argc, argv, ++arg), NULL, 0); - if (address_in < 0 || (address_in & 1)) + address_in = getarg_l(argc, argv, ++arg); + if (address_in < 0) invarg(argc, argv, arg); continue; } if (!strcmp(argv[arg], "-e")) { - size_e = strtol(getarg(argc, argv, ++arg), NULL, 0); - if (size_e <= 0) - invarg(argc, argv, arg); + arg++; + if (!strcmp(getarg(argc, argv, arg), "full")) + size_e = -1; + else { + size_e = getarg_l(argc, argv, arg); + if (size_e <= 0) + invarg(argc, argv, arg); + } continue; } - if (!strcmp(argv[arg], "-8")) { - io = &io_ops[0]; - write_step = 1; + if (!strcmp(argv[arg], "-m")) { + long v = getarg_l(argc, argv, ++arg); + if ((size_t)v >= sizeof(io_ops) / sizeof(io_ops[0])) + invarg(argc, argv, arg); + io = &io_ops[v]; + if (v != 0) + write_step = 1; continue; } if (!strcmp(argv[arg], "-v")) { @@ -601,7 +695,9 @@ int main(int argc, char *argv[]) if (fname_w) { f_w = open_prep_read(fname_w, &size_w); - if (size_e < size_w) + if (size_e == 0 && io->addrs_remapped) + size_e = -1; + if (size_e != -1 && size_e < size_w) size_e = size_w; if (do_verify) size_v = size_w; @@ -634,7 +730,17 @@ int main(int argc, char *argv[]) if (do_info || size_e) read_info(fd); - if (size_e) { + if (size_e == -1) { + printf("performing full erase..."); fflush(stdout); + flash_seq_erase_full(fd); + rv = ry_read(fd); + if (rv != 0xffff) { + fprintf(stderr, "\nerase error: %04x\n", rv); + return 1; + } + printf(" done.\n"); + } + else if (size_e) { // set_delay(fd, 0); // ? a_blk = get_block_addr(address_in, 0); end = address_in + size_e; @@ -647,6 +753,7 @@ int main(int argc, char *argv[]) if (rv != 0xffff) { fprintf(stderr, "\nerase error: %lx %04x\n", a_blk, rv); + return 1; } a_blk = get_block_addr(a_blk, 1); @@ -722,6 +829,8 @@ int main(int argc, char *argv[]) print_progress(0, blks * sizeof(g_block)); io->set_addr(fd, address_in); for (done = 0; done < size_r || done < size_v; ) { + if (io->addrs_remapped) + io->set_addr(fd, address_in + done); io->read_block(fd, g_block, sizeof(g_block)); if (f_r && done < size_r) { len = min(size_r - done, sizeof(g_block)); -- 2.39.2