From: notaz <notasas@gmail.com>
Date: Wed, 4 Nov 2020 23:53:35 +0000 (+0200)
Subject: support LoROM
X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c5e4a2c2daba0efb2029d2ebba1c9d4353484fcf;p=flashkit-mdc.git

support LoROM
---

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 <ttydevice>      (default %s)\n"
 		"  -r <file> [size]    dump the cart (default 4MB)\n"
 		"  -w <file> [size]    program the flash (def. file size)\n"
 		"  -s <file> [size]    simple write (SRAM, etc, def. file size)\n"
-		"  -e <size>           erase (rounds to block size)\n"
+		"  -e <size>           erase (rounds to block size); can specify 'full'\n"
 		"  -a <start_address>  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 <n>              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));