|
@@ -1,5 +1,6 @@
|
|
|
#include <stdio.h>
|
|
|
#include <stdlib.h>
|
|
|
+#include <strings.h>
|
|
|
|
|
|
#include <usb.h>
|
|
|
|
|
@@ -7,32 +8,118 @@
|
|
|
|
|
|
#include "qdinc.h"
|
|
|
|
|
|
+static const char * default_tempfile = "/tmp/quickdev";
|
|
|
+
|
|
|
+
|
|
|
+void usage(void)
|
|
|
+{
|
|
|
+ fprintf(stderr, "usage: qdinc [-hsi] <romfile>\n");
|
|
|
+ exit(1);
|
|
|
+}
|
|
|
|
|
|
int main(int argc, char * argv[])
|
|
|
{
|
|
|
- if(argc != 4 && argc != 3)
|
|
|
+ char * filename = 0;
|
|
|
+
|
|
|
+ int hirom = 0;
|
|
|
+ int header = 0;
|
|
|
+ int init = 0;
|
|
|
+ int i,j,j2;
|
|
|
+ for(i = 1; i < argc; i++)
|
|
|
{
|
|
|
- fprintf(stderr, "usage: qdinc [hl] <update> [reference]\n");
|
|
|
- exit(1);
|
|
|
+ if(argv[i][0] == '-')
|
|
|
+ {
|
|
|
+ if(strcmp(argv[i], "--") == 0)
|
|
|
+ {
|
|
|
+ if(i != argc - 2 || filename)
|
|
|
+ usage();
|
|
|
+ else
|
|
|
+ {
|
|
|
+ filename = argv[i+1];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ unsigned int len = strlen(argv[i]);
|
|
|
+ if(len == 1)
|
|
|
+ usage();
|
|
|
+ for(j = 1; j < len; j++)
|
|
|
+ {
|
|
|
+ switch(argv[i][j])
|
|
|
+ {
|
|
|
+ case 'h':
|
|
|
+ hirom = 1;
|
|
|
+ break;
|
|
|
+ case 's':
|
|
|
+ header = 1;
|
|
|
+ break;
|
|
|
+ case 'i':
|
|
|
+ init = 1;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ usage();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if(filename != 0)
|
|
|
+ usage();
|
|
|
+ filename = argv[i];
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- int hirom = (argv[1][0] == 'h' || argv[1][0] == 'H');
|
|
|
-
|
|
|
-
|
|
|
unsigned int pos = 0;
|
|
|
int ref_complete, upd_complete = 0;
|
|
|
|
|
|
- FILE * upd = fopen(argv[2], "rb");
|
|
|
+ const char * tempfile = getenv("QDINC_FILE");
|
|
|
+
|
|
|
+ if(tempfile == 0)
|
|
|
+ tempfile = default_tempfile;
|
|
|
+
|
|
|
+ char * outfile = malloc(strlen(tempfile) + sizeof(".out"));
|
|
|
+ char * ext = stpcpy(outfile, tempfile);
|
|
|
+ strcpy(ext, ".out");
|
|
|
+
|
|
|
+ FILE * out = fopen(outfile, "wb");
|
|
|
+
|
|
|
+ if(out == 0)
|
|
|
+ {
|
|
|
+ fprintf(stderr, "Could not open file %s for writing\n", outfile);
|
|
|
+ exit(1);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ FILE * upd = fopen(filename, "rb");
|
|
|
|
|
|
if(upd == 0)
|
|
|
{
|
|
|
- fprintf(stderr, "couldn't open file %s\n", argv[3]);
|
|
|
+ fprintf(stderr, "Could not open file %s\n", argv[3]);
|
|
|
+ exit(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ fseek(upd, 0, SEEK_END);
|
|
|
+ unsigned int size = ftell(upd);
|
|
|
+
|
|
|
+ if(header)
|
|
|
+ {
|
|
|
+ if(size < 512)
|
|
|
+ size = 0;
|
|
|
+ else
|
|
|
+ size -= 512;
|
|
|
+ fseek(upd, 512, SEEK_SET);
|
|
|
}
|
|
|
+ else
|
|
|
+ rewind(upd);
|
|
|
|
|
|
+ if(size > 0x200000)
|
|
|
+ {
|
|
|
+ fprintf(stderr, "Input file is larger than supported by Quickdev16\n");
|
|
|
+ exit(1);
|
|
|
+ }
|
|
|
|
|
|
FILE * ref = 0;
|
|
|
- if(argc == 4)
|
|
|
- ref = fopen(argv[3], "rb");
|
|
|
+ if(!init)
|
|
|
+ ref = fopen(tempfile, "rb");
|
|
|
|
|
|
ref_complete = (ref == 0);
|
|
|
|
|
@@ -65,6 +152,8 @@ int main(int argc, char * argv[])
|
|
|
#ifdef QDINC_OLD_FIRMWARE
|
|
|
/* wait for the loader to depack */
|
|
|
usleep(500000);
|
|
|
+#else
|
|
|
+ usleep(50000);
|
|
|
#endif
|
|
|
|
|
|
cnt = usb_control_msg(handle,
|
|
@@ -79,14 +168,29 @@ int main(int argc, char * argv[])
|
|
|
|
|
|
unsigned char lastchar;
|
|
|
unsigned int transmitted = 0;
|
|
|
+
|
|
|
+
|
|
|
+ char progress[21];
|
|
|
+
|
|
|
+ for(i = 0; i < 20; i++)
|
|
|
+ progress[i] = ' ';
|
|
|
+ progress[20] = 0;
|
|
|
+ j = 0;
|
|
|
+ j2 = 0;
|
|
|
|
|
|
while(!upd_complete)
|
|
|
{
|
|
|
+ int msg = 0;
|
|
|
unsigned char updchar = fgetc(upd);
|
|
|
unsigned char refchar;
|
|
|
if(feof(upd))
|
|
|
+ {
|
|
|
+ msg = 1;
|
|
|
upd_complete = 1;
|
|
|
- if(!ref_complete)
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fputc(updchar, out);
|
|
|
+ if(!ref_complete && !upd_complete)
|
|
|
{
|
|
|
refchar = fgetc(ref);
|
|
|
if(feof(ref))
|
|
@@ -125,9 +229,6 @@ int main(int argc, char * argv[])
|
|
|
int consecutive = (last_position == position - blocklen);
|
|
|
unsigned int begin = position - blocklen;
|
|
|
|
|
|
- printf("updating %sblock from 0x%06x to 0x%06x of size 0x%03x\n", (consecutive ? "consecutive " : ""), begin, begin + reallen - 1, reallen);
|
|
|
-
|
|
|
-
|
|
|
cnt = usb_control_msg(handle,
|
|
|
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
|
|
USB_ENDPOINT_OUT, consecutive ? USB_BULK_UPLOAD_NEXT : USB_BULK_UPLOAD_ADDR, begin >> 16,
|
|
@@ -138,11 +239,47 @@ int main(int argc, char * argv[])
|
|
|
transmitted += reallen;
|
|
|
blocklen = 0;
|
|
|
reallen = 0;
|
|
|
+
|
|
|
+ msg = 1;
|
|
|
+
|
|
|
+ }
|
|
|
+ if(msg)
|
|
|
+ {
|
|
|
+ for(; j < (position - 1) * 20 / size; j++)
|
|
|
+ progress[j] = '=';
|
|
|
+ for(; j2 < transmitted * 20 / size; j2++)
|
|
|
+ progress[j2] = '#';
|
|
|
+ printf("At 0x%06x/0x%06x %6.2f%% [%10s] Tx 0x%06x/0x%06x %6.2f%%\r",
|
|
|
+ position - 1, size, (position - 1) * 100.0 / size,
|
|
|
+ progress,
|
|
|
+ transmitted, size, transmitted * 100.0 / size);
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
|
-
|
|
|
lastchar = updchar;
|
|
|
}
|
|
|
position--;
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ while(!ref_complete)
|
|
|
+ {
|
|
|
+ unsigned char refchar = fgetc(ref);
|
|
|
+ if(feof(ref))
|
|
|
+ ref_complete = 1;
|
|
|
+ else
|
|
|
+ fputc(refchar, out);
|
|
|
+ }
|
|
|
+
|
|
|
+ fclose(out);
|
|
|
+ fclose(upd);
|
|
|
+ fclose(ref);
|
|
|
+
|
|
|
+ if(rename(outfile, tempfile))
|
|
|
+ {
|
|
|
+ fprintf(stderr, "Could not replace tempfile %s\n", tempfile);
|
|
|
+ exit(1);
|
|
|
+ }
|
|
|
+
|
|
|
cnt = usb_control_msg(handle,
|
|
|
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
|
|
USB_ENDPOINT_OUT, USB_BULK_UPLOAD_END, 0, 0, NULL,
|
|
@@ -155,11 +292,11 @@ int main(int argc, char * argv[])
|
|
|
0, 5000);
|
|
|
#endif
|
|
|
|
|
|
- printf("Transmitted %i of %i bytes (%3.2f)\n", transmitted, position, transmitted * 100.0 / position);
|
|
|
cnt = usb_control_msg(handle,
|
|
|
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
|
|
USB_ENDPOINT_OUT, USB_MODE_SNES, 0, 0, NULL,
|
|
|
0, 5000);
|
|
|
return 0;
|
|
|
|
|
|
+ printf("Done");
|
|
|
}
|