Merge branch 'master' of git://github.com/gilligan/quickdev16
This commit is contained in:
commit
f10da9afed
@ -50,7 +50,7 @@
|
||||
|
||||
#define DO_CRC_CHECK_LOADER 0
|
||||
#define DO_CRC_CHECK 0
|
||||
#define DO_SHM_SCRATCHPAD 1
|
||||
#define DO_SHM_SCRATCHPAD 0
|
||||
#define DO_SHM 0
|
||||
#define DO_TIMER 0
|
||||
#define DO_SHELL 1
|
||||
|
||||
@ -305,7 +305,7 @@ int main(void)
|
||||
system_set_bus_avr();
|
||||
system_send_snes_reset();
|
||||
}
|
||||
globals_init();
|
||||
/*globals_init();*/
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
23
tools/qdips/Makefile
Normal file
23
tools/qdips/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
USBFLAGS = `libusb-config --cflags`
|
||||
USBLIBS = `libusb-config --libs`
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = $(CPPFLAGS) $(USBFLAGS) -O -g -Wall -D_GNU_SOURCE --std=c99
|
||||
LIBS = $(USBLIBS)
|
||||
|
||||
NAME = qdips
|
||||
OBJECTS = opendevice.o $(NAME).o
|
||||
|
||||
|
||||
PROGRAM = $(NAME)$(EXE_SUFFIX)
|
||||
|
||||
|
||||
all: $(PROGRAM)
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
$(PROGRAM): $(OBJECTS)
|
||||
$(CC) -o $(PROGRAM) $(OBJECTS) $(LIBS)
|
||||
clean:
|
||||
rm -f *.o $(PROGRAM)
|
||||
286
tools/qdips/opendevice.c
Normal file
286
tools/qdips/opendevice.c
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Name: opendevice.c Project: V-USB host-side library Author: Christian
|
||||
* Starkjohann Creation Date: 2008-04-10 Tabsize: 4 Copyright: (c) 2008 by
|
||||
* OBJECTIVE DEVELOPMENT Software GmbH License: GNU GPL v2 (see License.txt),
|
||||
* GNU GPL v3 or proprietary (CommercialLicense.txt) This Revision: $Id:
|
||||
* opendevice.c 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
* General Description: The functions in this module can be used to find and
|
||||
* open a device based on libusb or libusb-win32.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "opendevice.h"
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define MATCH_SUCCESS 1
|
||||
#define MATCH_FAILED 0
|
||||
#define MATCH_ABORT -1
|
||||
|
||||
/*
|
||||
* private interface: match text and p, return MATCH_SUCCESS, MATCH_FAILED, or
|
||||
* MATCH_ABORT.
|
||||
*/
|
||||
static int _shellStyleMatch(char *text, char *p)
|
||||
{
|
||||
int last,
|
||||
matched,
|
||||
reverse;
|
||||
|
||||
for (; *p; text++, p++) {
|
||||
if (*text == 0 && *p != '*')
|
||||
return MATCH_ABORT;
|
||||
switch (*p) {
|
||||
case '\\':
|
||||
/*
|
||||
* Literal match with following character.
|
||||
*/
|
||||
p++;
|
||||
/*
|
||||
* FALLTHROUGH
|
||||
*/
|
||||
default:
|
||||
if (*text != *p)
|
||||
return MATCH_FAILED;
|
||||
continue;
|
||||
case '?':
|
||||
/*
|
||||
* Match anything.
|
||||
*/
|
||||
continue;
|
||||
case '*':
|
||||
while (*++p == '*')
|
||||
/*
|
||||
* Consecutive stars act just like one.
|
||||
*/
|
||||
continue;
|
||||
if (*p == 0)
|
||||
/*
|
||||
* Trailing star matches everything.
|
||||
*/
|
||||
return MATCH_SUCCESS;
|
||||
while (*text)
|
||||
if ((matched = _shellStyleMatch(text++, p)) != MATCH_FAILED)
|
||||
return matched;
|
||||
return MATCH_ABORT;
|
||||
case '[':
|
||||
reverse = p[1] == '^';
|
||||
if (reverse) /* Inverted character class. */
|
||||
p++;
|
||||
matched = MATCH_FAILED;
|
||||
if (p[1] == ']' || p[1] == '-')
|
||||
if (*++p == *text)
|
||||
matched = MATCH_SUCCESS;
|
||||
for (last = *p; *++p && *p != ']'; last = *p)
|
||||
if (*p == '-' && p[1] != ']' ? *text <= *++p
|
||||
&& *text >= last : *text == *p)
|
||||
matched = MATCH_SUCCESS;
|
||||
if (matched == reverse)
|
||||
return MATCH_FAILED;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return *text == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* public interface for shell style matching: returns 0 if fails, 1 if matches
|
||||
*/
|
||||
static int shellStyleMatch(char *text, char *pattern)
|
||||
{
|
||||
if (pattern == NULL) /* NULL pattern is synonymous to "*" */
|
||||
return 1;
|
||||
return _shellStyleMatch(text, pattern) == MATCH_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int usbGetStringAscii(usb_dev_handle * dev, int index, char *buf, int buflen)
|
||||
{
|
||||
char buffer[256];
|
||||
int rval,
|
||||
i;
|
||||
|
||||
if ((rval = usb_get_string_simple(dev, index, buf, buflen)) >= 0) /* use
|
||||
* libusb
|
||||
* version
|
||||
* if
|
||||
* it
|
||||
* works
|
||||
*/
|
||||
return rval;
|
||||
if ((rval =
|
||||
usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
|
||||
(USB_DT_STRING << 8) + index, 0x0409, buffer,
|
||||
sizeof(buffer), 5000)) < 0)
|
||||
return rval;
|
||||
if (buffer[1] != USB_DT_STRING) {
|
||||
*buf = 0;
|
||||
return 0;
|
||||
}
|
||||
if ((unsigned char) buffer[0] < rval)
|
||||
rval = (unsigned char) buffer[0];
|
||||
rval /= 2;
|
||||
/*
|
||||
* lossy conversion to ISO Latin1:
|
||||
*/
|
||||
for (i = 1; i < rval; i++) {
|
||||
if (i > buflen) /* destination buffer overflow */
|
||||
break;
|
||||
buf[i - 1] = buffer[2 * i];
|
||||
if (buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
|
||||
buf[i - 1] = '?';
|
||||
}
|
||||
buf[i - 1] = 0;
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int usbOpenDevice(usb_dev_handle ** device, int vendorID,
|
||||
char *vendorNamePattern, int productID,
|
||||
char *productNamePattern, char *serialNamePattern,
|
||||
FILE * printMatchingDevicesFp, FILE * warningsFp)
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
usb_dev_handle *handle = NULL;
|
||||
int errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
for (bus = usb_get_busses(); bus; bus = bus->next) {
|
||||
for (dev = bus->devices; dev; dev = dev->next) { /* iterate over
|
||||
* all devices
|
||||
* on all
|
||||
* busses */
|
||||
if ((vendorID == 0 || dev->descriptor.idVendor == vendorID)
|
||||
&& (productID == 0 || dev->descriptor.idProduct == productID)) {
|
||||
char vendor[256],
|
||||
product[256],
|
||||
serial[256];
|
||||
int len;
|
||||
handle = usb_open(dev); /* we need to open the device in order
|
||||
* to query strings */
|
||||
if (!handle) {
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
if (warningsFp != NULL)
|
||||
fprintf(warningsFp,
|
||||
"Warning: cannot open VID=0x%04x PID=0x%04x: %s\n",
|
||||
dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct, usb_strerror());
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* now check whether the names match:
|
||||
*/
|
||||
len = vendor[0] = 0;
|
||||
if (dev->descriptor.iManufacturer > 0) {
|
||||
len =
|
||||
usbGetStringAscii(handle, dev->descriptor.iManufacturer,
|
||||
vendor, sizeof(vendor));
|
||||
}
|
||||
if (len < 0) {
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
if (warningsFp != NULL)
|
||||
fprintf(warningsFp,
|
||||
"Warning: cannot query manufacturer for VID=0x%04x PID=0x%04x: %s\n",
|
||||
dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct, usb_strerror());
|
||||
} else {
|
||||
errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
/*
|
||||
* printf("seen device from vendor ->%s<-\n", vendor);
|
||||
*/
|
||||
if (shellStyleMatch(vendor, vendorNamePattern)) {
|
||||
len = product[0] = 0;
|
||||
if (dev->descriptor.iProduct > 0) {
|
||||
len =
|
||||
usbGetStringAscii(handle,
|
||||
dev->descriptor.iProduct,
|
||||
product, sizeof(product));
|
||||
}
|
||||
if (len < 0) {
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
if (warningsFp != NULL)
|
||||
fprintf(warningsFp,
|
||||
"Warning: cannot query product for VID=0x%04x PID=0x%04x: %s\n",
|
||||
dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct,
|
||||
usb_strerror());
|
||||
} else {
|
||||
errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
/*
|
||||
* printf("seen product ->%s<-\n", product);
|
||||
*/
|
||||
if (shellStyleMatch(product, productNamePattern)) {
|
||||
len = serial[0] = 0;
|
||||
if (dev->descriptor.iSerialNumber > 0) {
|
||||
len =
|
||||
usbGetStringAscii(handle,
|
||||
dev->descriptor.
|
||||
iSerialNumber, serial,
|
||||
sizeof(serial));
|
||||
}
|
||||
if (len < 0) {
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
if (warningsFp != NULL)
|
||||
fprintf(warningsFp,
|
||||
"Warning: cannot query serial for VID=0x%04x PID=0x%04x: %s\n",
|
||||
dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct,
|
||||
usb_strerror());
|
||||
}
|
||||
if (shellStyleMatch(serial, serialNamePattern)) {
|
||||
if (printMatchingDevicesFp != NULL) {
|
||||
if (serial[0] == 0) {
|
||||
fprintf(printMatchingDevicesFp,
|
||||
"VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\"\n",
|
||||
dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct,
|
||||
vendor, product);
|
||||
} else {
|
||||
fprintf(printMatchingDevicesFp,
|
||||
"VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\" serial=\"%s\"\n",
|
||||
dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct,
|
||||
vendor, product, serial);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
usb_close(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
}
|
||||
if (handle) /* we have found a deice */
|
||||
break;
|
||||
}
|
||||
if (handle != NULL) {
|
||||
errorCode = 0;
|
||||
*device = handle;
|
||||
}
|
||||
if (printMatchingDevicesFp != NULL) /* never return an error for listing
|
||||
* only */
|
||||
errorCode = 0;
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
77
tools/qdips/opendevice.h
Normal file
77
tools/qdips/opendevice.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* Name: opendevice.h
|
||||
* Project: V-USB host-side library
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-04-10
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: opendevice.h 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
General Description:
|
||||
This module offers additional functionality for host side drivers based on
|
||||
libusb or libusb-win32. It includes a function to find and open a device
|
||||
based on numeric IDs and textual description. It also includes a function to
|
||||
obtain textual descriptions from a device.
|
||||
|
||||
To use this functionality, simply copy opendevice.c and opendevice.h into your
|
||||
project and add them to your Makefile. You may modify and redistribute these
|
||||
files according to the GNU General Public License (GPL) version 2 or 3.
|
||||
*/
|
||||
|
||||
#ifndef __OPENDEVICE_H_INCLUDED__
|
||||
#define __OPENDEVICE_H_INCLUDED__
|
||||
|
||||
#include <usb.h> /* this is libusb, see http://libusb.sourceforge.net/ */
|
||||
#include <stdio.h>
|
||||
|
||||
int usbGetStringAscii(usb_dev_handle *dev, int index, char *buf, int buflen);
|
||||
/* This function gets a string descriptor from the device. 'index' is the
|
||||
* string descriptor index. The string is returned in ISO Latin 1 encoding in
|
||||
* 'buf' and it is terminated with a 0-character. The buffer size must be
|
||||
* passed in 'buflen' to prevent buffer overflows. A libusb device handle
|
||||
* must be given in 'dev'.
|
||||
* Returns: The length of the string (excluding the terminating 0) or
|
||||
* a negative number in case of an error. If there was an error, use
|
||||
* usb_strerror() to obtain the error message.
|
||||
*/
|
||||
|
||||
int usbOpenDevice(usb_dev_handle **device, int vendorID, char *vendorNamePattern, int productID, char *productNamePattern, char *serialNamePattern, FILE *printMatchingDevicesFp, FILE *warningsFp);
|
||||
/* This function iterates over all devices on all USB busses and searches for
|
||||
* a device. Matching is done first by means of Vendor- and Product-ID (passed
|
||||
* in 'vendorID' and 'productID'. An ID of 0 matches any numeric ID (wildcard).
|
||||
* When a device matches by its IDs, matching by names is performed. Name
|
||||
* matching can be done on textual vendor name ('vendorNamePattern'), product
|
||||
* name ('productNamePattern') and serial number ('serialNamePattern'). A
|
||||
* device matches only if all non-null pattern match. If you don't care about
|
||||
* a string, pass NULL for the pattern. Patterns are Unix shell style pattern:
|
||||
* '*' stands for 0 or more characters, '?' for one single character, a list
|
||||
* of characters in square brackets for a single character from the list
|
||||
* (dashes are allowed to specify a range) and if the lis of characters begins
|
||||
* with a caret ('^'), it matches one character which is NOT in the list.
|
||||
* Other parameters to the function: If 'warningsFp' is not NULL, warning
|
||||
* messages are printed to this file descriptor with fprintf(). If
|
||||
* 'printMatchingDevicesFp' is not NULL, no device is opened but matching
|
||||
* devices are printed to the given file descriptor with fprintf().
|
||||
* If a device is opened, the resulting USB handle is stored in '*device'. A
|
||||
* pointer to a "usb_dev_handle *" type variable must be passed here.
|
||||
* Returns: 0 on success, an error code (see defines below) on failure.
|
||||
*/
|
||||
|
||||
/* usbOpenDevice() error codes: */
|
||||
#define USBOPEN_SUCCESS 0 /* no error */
|
||||
#define USBOPEN_ERR_ACCESS 1 /* not enough permissions to open device */
|
||||
#define USBOPEN_ERR_IO 2 /* I/O error */
|
||||
#define USBOPEN_ERR_NOTFOUND 3 /* device not found */
|
||||
|
||||
|
||||
/* Obdev's free USB IDs, see USBID-License.txt for details */
|
||||
|
||||
#define USB_VID_OBDEV_SHARED 5824 /* obdev's shared vendor ID */
|
||||
#define USB_PID_OBDEV_SHARED_CUSTOM 1500 /* shared PID for custom class devices */
|
||||
#define USB_PID_OBDEV_SHARED_HID 1503 /* shared PID for HIDs except mice & keyboards */
|
||||
#define USB_PID_OBDEV_SHARED_CDCACM 1505 /* shared PID for CDC Modem devices */
|
||||
#define USB_PID_OBDEV_SHARED_MIDI 1508 /* shared PID for MIDI class devices */
|
||||
|
||||
#endif /* __OPENDEVICE_H_INCLUDED__ */
|
||||
353
tools/qdips/qdips.c
Normal file
353
tools/qdips/qdips.c
Normal file
@ -0,0 +1,353 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <usb.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "opendevice.h"
|
||||
#include "qdips.h"
|
||||
|
||||
|
||||
#define _16MBIT 0x200000
|
||||
|
||||
#define HIROM_BANK_SIZE_SHIFT 16
|
||||
#define LOROM_BANK_SIZE_SHIFT 15
|
||||
#define HIROM_BANK_COUNT_SHIFT 32
|
||||
#define LOROM_BANK_COUNT_SHIFT 64
|
||||
|
||||
#define IPS_MAGIC "PATCH"
|
||||
#define EOF_TAG 0x454f46
|
||||
#define PATCH_END 1
|
||||
#define PATCH_ERR 2
|
||||
#define PATCH_CHUNKS_MAX 2048
|
||||
|
||||
#define RLE_LEN 0
|
||||
#define RLE_VAL 1
|
||||
|
||||
#define QD16_MAX_TX_LEN 128
|
||||
#define QD16_CMD_TIMEOUT 5000
|
||||
|
||||
|
||||
|
||||
#define QD16_SEND_DATA(__addr_hi,__addr_lo,__src,__len)\
|
||||
usb_control_msg(handle,\
|
||||
USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_ENDPOINT_OUT,\
|
||||
USB_BULK_UPLOAD_NEXT,\
|
||||
__addr_hi, __addr_lo,\
|
||||
(char*)__src, __len,\
|
||||
QD16_CMD_TIMEOUT);
|
||||
|
||||
#define QD16_SEND_ADDR(__addr_hi,__addr_lo,__src,__len)\
|
||||
usb_control_msg(handle,\
|
||||
USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_ENDPOINT_OUT,\
|
||||
USB_BULK_UPLOAD_ADDR,\
|
||||
__addr_hi,__addr_lo,\
|
||||
(char*)__src,__len,\
|
||||
QD16_CMD_TIMEOUT);
|
||||
|
||||
|
||||
typedef struct _ips_tag {
|
||||
uint32_t ofs; /* offset in file to patch (3 bytes (24bit address) in file!) */
|
||||
uint16_t len; /* number of bytes in this chunk (if len==0 : data[0] = counter / data[1] = fill byte*/
|
||||
uint8_t* data; /* chunk data */
|
||||
} ips_tag_t;
|
||||
|
||||
int qd16_transfer_data(int addr_hi, int addr_lo, uint8_t* data, int len);
|
||||
int qd16_apply_ips_chunk(ips_tag_t* ips_tag);
|
||||
int ips_read_next_tag(FILE* patch_file, ips_tag_t* tag);
|
||||
int qd16_init(void);
|
||||
void qd16_finish(void);
|
||||
void usage(void);
|
||||
|
||||
usb_dev_handle *handle = NULL;
|
||||
const unsigned char rawVid[2] = { USB_CFG_VENDOR_ID }, rawPid[2] = { USB_CFG_DEVICE_ID};
|
||||
char vendor[] = { USB_CFG_VENDOR_NAME, 0 }, product[] = { USB_CFG_DEVICE_NAME, 0};
|
||||
int cnt, vid, pid;
|
||||
|
||||
int hirom = 0;
|
||||
int quiet = 0;
|
||||
|
||||
uint8_t dummy[128];
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: qdips [option] <patchfile>\n\n\
|
||||
Options:\n\
|
||||
-q\tBe quiet\n\
|
||||
-h\tForce HiROM mode\n\n");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
FILE* patch_file;
|
||||
char * fname = 0;
|
||||
int opt = 0;
|
||||
|
||||
char magic[6];
|
||||
ips_tag_t ips_tags[PATCH_CHUNKS_MAX];
|
||||
int chunk_index = 0;
|
||||
|
||||
if (argc==1)
|
||||
usage();
|
||||
|
||||
while ((opt = getopt(argc,argv,"qh")) != -1){
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
hirom = 1;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (optind >= argc) {
|
||||
usage();
|
||||
}
|
||||
|
||||
int ret = qd16_init();
|
||||
if (ret != 0){
|
||||
fprintf(stderr,"Error during init. Exiting!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fname = argv[optind];
|
||||
patch_file = fopen(fname,"rb");
|
||||
if (patch_file == 0) {
|
||||
fprintf(stderr,"Failed to open file '%s'!\n",fname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (fgets(magic,strlen(IPS_MAGIC)+1,patch_file) == NULL) {
|
||||
fprintf(stderr,"Error reading from file %s\n",fname);
|
||||
fclose(patch_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp(magic,IPS_MAGIC) != 0){
|
||||
fprintf(stderr,"Patch is not in ips format!\n");
|
||||
}
|
||||
|
||||
int patch_error = 0;
|
||||
|
||||
while (!feof(patch_file) && chunk_index < PATCH_CHUNKS_MAX) {
|
||||
|
||||
int ret = ips_read_next_tag(patch_file,&ips_tags[chunk_index]);
|
||||
|
||||
if (ret == PATCH_END)
|
||||
break;
|
||||
else if (ret == PATCH_ERR) {
|
||||
patch_error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
chunk_index++;
|
||||
}
|
||||
|
||||
fclose(patch_file);
|
||||
|
||||
if (patch_error){
|
||||
printf("error at patch chunk #%d!\n",chunk_index);
|
||||
}
|
||||
|
||||
int errors=0;
|
||||
|
||||
for (int i=0; i<chunk_index; i++){
|
||||
|
||||
if (!quiet)
|
||||
printf("uploading chunk %d ..\r",i+1);
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
int ret = qd16_apply_ips_chunk(&ips_tags[i]);
|
||||
if (ret!=0){
|
||||
printf("\nfailed applying chunk %d !\n",i);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!quiet)
|
||||
printf("\nsuccessfully applied %d chunks\n",chunk_index-errors);
|
||||
|
||||
qd16_finish();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qd16_transfer_data(int addr_hi, int addr_lo, uint8_t* data, int len)
|
||||
{
|
||||
|
||||
int addr = (addr_hi<<16) | (addr_lo&0xffff);
|
||||
int pos = 0;
|
||||
int ret;
|
||||
|
||||
|
||||
int bytes_left = len;
|
||||
int txlen;
|
||||
|
||||
while (bytes_left>0) {
|
||||
|
||||
txlen = (bytes_left>QD16_MAX_TX_LEN?QD16_MAX_TX_LEN:bytes_left);
|
||||
ret = QD16_SEND_ADDR( ((addr>>16)&0xff), (addr&0xffff), data+pos, txlen);
|
||||
if (ret<0)
|
||||
break;
|
||||
|
||||
addr += txlen;
|
||||
pos += txlen;
|
||||
bytes_left -= txlen;
|
||||
}
|
||||
|
||||
if (bytes_left){
|
||||
printf("%s\n",usb_strerror());
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
int qd16_apply_ips_chunk(ips_tag_t* ips_tag)
|
||||
{
|
||||
int addr_hi = (ips_tag->ofs)>>16;
|
||||
int addr_lo = (ips_tag->ofs)&0xffff;
|
||||
|
||||
|
||||
if (ips_tag->len > 0){
|
||||
|
||||
int ret = qd16_transfer_data(addr_hi,addr_lo,ips_tag->data,ips_tag->len);
|
||||
if (ret!=0)
|
||||
printf("error transfering data to qd16\n");
|
||||
|
||||
} else {
|
||||
|
||||
uint16_t len = (uint16_t)ips_tag->data[RLE_LEN];
|
||||
uint8_t val = ips_tag->data[RLE_VAL];
|
||||
|
||||
// prepare patch buffer
|
||||
uint8_t *buff = malloc(len);
|
||||
memset(buff,val,len);
|
||||
|
||||
// transfer
|
||||
int ret = QD16_SEND_ADDR(addr_hi,addr_lo,buff,len);
|
||||
if (ret<0)
|
||||
printf("error executing command: %s\n",usb_strerror());
|
||||
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qd16_finish(void)
|
||||
{
|
||||
cnt = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_BULK_UPLOAD_END, 0, 0, NULL,
|
||||
0, 5000);
|
||||
|
||||
if (cnt<0) {
|
||||
printf("USB_BULK_UPLOAD_END failed: %s\n",usb_strerror());
|
||||
}
|
||||
|
||||
cnt = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_SET_LOADER, 1, 1, NULL,
|
||||
0, 5000);
|
||||
|
||||
cnt = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_MODE_SNES, 0, 0, NULL,
|
||||
0, 5000);
|
||||
if (cnt<0) {
|
||||
printf("USB_MODE_SNES failed: %s\n",usb_strerror());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int qd16_init(void)
|
||||
{
|
||||
usb_init();
|
||||
|
||||
vid = rawVid[1] * 256 + rawVid[0];
|
||||
pid = rawPid[1] * 256 + rawPid[0];
|
||||
|
||||
if (usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) != 0) {
|
||||
fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
cnt = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_SET_LOADER, 0, 0, NULL,
|
||||
0, 5000);
|
||||
|
||||
if (cnt<0) {
|
||||
printf("USB_SET_LOADER failed: %s\n",usb_strerror());
|
||||
}
|
||||
|
||||
cnt = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_MODE_AVR, 0, 0, NULL,
|
||||
0, 5000);
|
||||
|
||||
if (cnt<0) {
|
||||
printf("USB_MODE_AVR failed: %s\n",usb_strerror());
|
||||
}
|
||||
|
||||
usleep(500000);
|
||||
|
||||
cnt = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
|
||||
USB_BULK_UPLOAD_INIT,
|
||||
(hirom ? HIROM_BANK_SIZE_SHIFT : LOROM_BANK_SIZE_SHIFT) ,
|
||||
/*(hirom ? HIROM_BANK_COUNT_SHIFT : LOROM_BANK_COUNT_SHIFT), */ // ???
|
||||
5,
|
||||
NULL, 0, 5000);
|
||||
|
||||
if (cnt<0) {
|
||||
printf("USB_BULK_UPLOAD_INIT failed: %s\n",usb_strerror());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ips_read_next_tag(FILE* patch_file, ips_tag_t* tag)
|
||||
{
|
||||
|
||||
tag->ofs = getc(patch_file)<<16 | getc(patch_file)<<8 | getc(patch_file);
|
||||
|
||||
if (tag->ofs == EOF_TAG)
|
||||
return PATCH_END;
|
||||
if (tag->ofs > _16MBIT)
|
||||
return PATCH_ERR;
|
||||
|
||||
tag->len = getc(patch_file)<<8 | getc(patch_file);
|
||||
|
||||
// if the length field is > 0 then it is
|
||||
// a standard replacement tag
|
||||
//
|
||||
if (tag->len>0) {
|
||||
tag->data = malloc(tag->len);
|
||||
|
||||
size_t ret = fread(tag->data,1,tag->len,patch_file);
|
||||
if (ret != tag->len)
|
||||
return PATCH_ERR;
|
||||
|
||||
} else {
|
||||
// if the length tag is 0 then it is
|
||||
// a RLE tag: read 3 bytes from patch: 2bytes: count / 1 byte: value
|
||||
tag->data = malloc(sizeof(3));
|
||||
tag->data[RLE_LEN] = (uint16_t)(getc(patch_file)<<8 | getc(patch_file));
|
||||
tag->data[RLE_VAL] = getc(patch_file);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
59
tools/qdips/qdips.h
Normal file
59
tools/qdips/qdips.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef __QDINC_H__
|
||||
#define __QDINC_H__
|
||||
|
||||
#define QDINC_RANGE 96
|
||||
#define QDINC_SIZE 254
|
||||
|
||||
/* quickdev protocol defines */
|
||||
|
||||
#define USB_UPLOAD_INIT 0
|
||||
#define USB_UPLOAD_ADDR 1
|
||||
|
||||
#define USB_DOWNLOAD_INIT 2
|
||||
#define USB_DOWNLOAD_ADDR 3
|
||||
|
||||
#define USB_CRC 4
|
||||
#define USB_CRC_ADDR 5
|
||||
|
||||
#define USB_BULK_UPLOAD_INIT 6
|
||||
#define USB_BULK_UPLOAD_ADDR 7
|
||||
#define USB_BULK_UPLOAD_NEXT 8
|
||||
#define USB_BULK_UPLOAD_END 9
|
||||
#define USB_MODE_SNES 10
|
||||
#define USB_MODE_AVR 11
|
||||
#define USB_AVR_RESET 12
|
||||
#define USB_SET_LOADER 13
|
||||
|
||||
/* -------------------------- Device Description --------------------------- */
|
||||
|
||||
#define USB_CFG_VENDOR_ID 0xc0, 0x16
|
||||
/* USB vendor ID for the device, low byte first. If you have registered your
|
||||
* own Vendor ID, define it here. Otherwise you use one of obdev's free shared
|
||||
* VID/PID pairs. Be sure to read USBID-License.txt for rules!
|
||||
*/
|
||||
#define USB_CFG_DEVICE_ID 0xdd, 0x05
|
||||
/* This is the ID of the product, low byte first. It is interpreted in the
|
||||
* scope of the vendor ID. If you have registered your own VID with usb.org
|
||||
* or if you have licensed a PID from somebody else, define it here. Otherwise
|
||||
* you use obdev's free shared VID/PID pair. Be sure to read the rules in
|
||||
* USBID-License.txt!
|
||||
*/
|
||||
#define USB_CFG_DEVICE_VERSION 0x00, 0x01
|
||||
/* Version number of the device: Minor number first, then major number.
|
||||
*/
|
||||
#define USB_CFG_VENDOR_NAME 'o', 'p', 't', 'i', 'x', 'x', '.', 'o', 'r', 'g'
|
||||
#define USB_CFG_VENDOR_NAME_LEN 10
|
||||
/* These two values define the vendor name returned by the USB device. The name
|
||||
* must be given as a list of characters under single quotes. The characters
|
||||
* are interpreted as Unicode (UTF-16) entities.
|
||||
* If you don't want a vendor name string, undefine these macros.
|
||||
* ALWAYS define a vendor name containing your Internet domain name if you use
|
||||
* obdev's free shared VID/PID pair. See the file USBID-License.txt for
|
||||
* details.
|
||||
*/
|
||||
#define USB_CFG_DEVICE_NAME 'Q', 'U', 'I', 'C', 'K', 'D', 'E', 'V', '1', '6'
|
||||
#define USB_CFG_DEVICE_NAME_LEN 10
|
||||
|
||||
/* end of quickdev protocol defines */
|
||||
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user