mirror of
https://github.com/raphnet/gc_n64_usb-v3
synced 2024-12-21 23:08:53 -05:00
Add gc2n64 mapping read/write
This commit is contained in:
parent
ead823947a
commit
e3c5feaf15
@ -8,6 +8,10 @@
|
||||
#include "ihex.h"
|
||||
#include "delay.h"
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
int gc2n64_adapter_echotest(gcn64_hdl_t hdl, int channel, int verbose)
|
||||
{
|
||||
unsigned char cmd[30];
|
||||
@ -37,61 +41,359 @@ int gc2n64_adapter_echotest(gcn64_hdl_t hdl, int channel, int verbose)
|
||||
return (n!= sizeof(buf)) || memcmp(cmd, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
int gc2n64_adapter_getMapping(gcn64_hdl_t hdl, int channel, int id)
|
||||
int gc2n64_adapter_storeCurrentMapping(gcn64_hdl_t hdl, int channel, int dst_slot)
|
||||
{
|
||||
int n;
|
||||
unsigned char cmd[3];
|
||||
|
||||
cmd[0] = 'R';
|
||||
cmd[1] = 0x04; // Save current mapping
|
||||
cmd[2] = dst_slot;
|
||||
|
||||
n = gcn64lib_rawSiCommand(hdl, channel, cmd, sizeof(cmd), cmd, 1);
|
||||
if (n<0) {
|
||||
return n;
|
||||
}
|
||||
if (n != 1) {
|
||||
fprintf(stderr, "Communication error while storing mapping\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cmd[0] == 0x00) {
|
||||
return gc2n64_adapter_waitNotBusy(hdl, channel, 0);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "storeCurrentMapping: Command NACKed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int gc2n64_adapter_setMapping(gcn64_hdl_t hdl, int channel, struct gc2n64_adapter_mapping *mapping)
|
||||
{
|
||||
unsigned char buf[64];
|
||||
unsigned char mapdata[64];
|
||||
int i, n;
|
||||
int maplen, togo, done, chunk;
|
||||
|
||||
|
||||
maplen = mapping->n_pairs * 2;
|
||||
|
||||
if (maplen > sizeof(mapdata)) {
|
||||
fprintf(stderr, "Mapping too large\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=0; i<mapping->n_pairs; i++) {
|
||||
mapdata[i*2] = mapping->pairs[i].gc;
|
||||
mapdata[i*2 + 1] = mapping->pairs[i].n64;
|
||||
}
|
||||
|
||||
printf("Map data : ");
|
||||
printHexBuf(mapdata, maplen);
|
||||
|
||||
togo = maplen;
|
||||
done = 0;
|
||||
chunk = 0;
|
||||
while (togo) {
|
||||
int len;
|
||||
|
||||
if (togo > 32) {
|
||||
len = 32;
|
||||
} else {
|
||||
len = togo;
|
||||
}
|
||||
|
||||
buf[0] = 'R';
|
||||
buf[1] = 0x03; // set mapping
|
||||
buf[2] = chunk;
|
||||
memcpy(buf + 3, mapdata + done, len);
|
||||
done+= len;
|
||||
|
||||
// printf("Mapping chunk : ");
|
||||
// printHexBuf(buf, len + 2);
|
||||
|
||||
n = gcn64lib_rawSiCommand(hdl, channel, buf, len + 3, buf, 1);
|
||||
if (n<0) {
|
||||
return n;
|
||||
}
|
||||
if (n != 1) {
|
||||
fprintf(stderr, "Communication error setting mapping\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
togo -= len;
|
||||
chunk++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gc2n64_adapter_getMapping(gcn64_hdl_t hdl, int channel, int mapping_id, struct gc2n64_adapter_mapping *dst_mapping)
|
||||
{
|
||||
unsigned char buf[64];
|
||||
unsigned char cmd[4];
|
||||
int n;
|
||||
int mapping_size;
|
||||
int togo;
|
||||
|
||||
cmd[0] = 'R';
|
||||
cmd[1] = 0x02; // Get mapping
|
||||
cmd[2] = id;
|
||||
cmd[2] = mapping_id;
|
||||
cmd[3] = 0; // chunk 0 (size)
|
||||
|
||||
n = gcn64lib_rawSiCommand(hdl, channel, cmd, 4, buf, 4);
|
||||
n = gcn64lib_rawSiCommand(hdl, channel, cmd, 4, buf, 1);
|
||||
if (n<0)
|
||||
return n;
|
||||
|
||||
if (n == 1) {
|
||||
int i, pos;
|
||||
mapping_size = buf[0];
|
||||
printf("Mapping %d size: %d\n", id, mapping_size);
|
||||
// printf("Mapping %d size: %d\n", mapping_id, mapping_size);
|
||||
|
||||
togo = mapping_size;
|
||||
for (pos=0, i=0; pos<mapping_size; i++) {
|
||||
cmd[0] = 'R';
|
||||
cmd[1] = 0x02; // Get mapping
|
||||
cmd[2] = id;
|
||||
cmd[2] = mapping_id;
|
||||
cmd[3] = i+1; // chunk 1 is first 32 byte block, 2nd is next 32 bytes, etc
|
||||
printf("Getting block %d\n", i+1);
|
||||
n = gcn64lib_rawSiCommand(hdl, channel, cmd, 4, buf + pos, 32);
|
||||
// printf("Getting block %d\n", i+1);
|
||||
n = gcn64lib_rawSiCommand(hdl, channel, cmd, 4, buf + pos, togo > 32 ? 32 : togo);
|
||||
if (n<0) {
|
||||
return n;
|
||||
}
|
||||
printf("ret: %d\n", n);
|
||||
// printf("ret: %d\n", n);
|
||||
if (n==0)
|
||||
break;
|
||||
pos += n;
|
||||
togo -= n;
|
||||
}
|
||||
|
||||
printf("Received %d bytes\n", pos);
|
||||
printHexBuf(buf, pos);
|
||||
//printf("Received %d bytes\n", pos);
|
||||
if (n%2) {
|
||||
fprintf(stderr, "Error: Odd length mapping received\n");
|
||||
printHexBuf(buf, pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO : Decode this to dst_mapping
|
||||
dst_mapping->n_pairs = pos/2;
|
||||
for (i=0; i<dst_mapping->n_pairs; i++) {
|
||||
dst_mapping->pairs[i].gc = buf[i*2];
|
||||
dst_mapping->pairs[i].n64 = buf[i*2+1];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *gc2n64_adapter_getMappingSlotName(unsigned char id, int default_context)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case MAPPING_SLOT_BUILTIN_CURRENT:
|
||||
if (default_context) {
|
||||
return "[Built-in default]";
|
||||
} else {
|
||||
return "[Current mapping]";
|
||||
}
|
||||
case MAPPING_SLOT_DPAD_UP: return "[D-Pad UP]";
|
||||
case MAPPING_SLOT_DPAD_DOWN: return "[D-Pad DOWN]";
|
||||
case MAPPING_SLOT_DPAD_LEFT: return "[D-Pad LEFT]";
|
||||
case MAPPING_SLOT_DPAD_RIGHT: return "[D-Pad RIGHT]";
|
||||
}
|
||||
return "Invalid ID";
|
||||
}
|
||||
|
||||
const char *gc2n64_adapter_getGCname(unsigned char id)
|
||||
{
|
||||
const char *names[] = {
|
||||
"A","B","Z","Start",
|
||||
"L","R",
|
||||
"C-stick up (50% threshold)",
|
||||
"C-stick down (50% threshold)",
|
||||
"C-stick left (50% threshold)",
|
||||
"C-stick right (50% threshold)",
|
||||
"Dpad-up","Dpad-down","Dpad-left","Dpad-right",
|
||||
"Joystick left-right axis","Joystick up-down axis",
|
||||
// Extras
|
||||
"X","Y",
|
||||
"Joystick up (50% threshold)", "Joystick down (50% threshold)",
|
||||
"Joystick left (50% threshold)", "Joystick right (50% threshold)",
|
||||
"Analogic L slider (50% threshold)",
|
||||
"Analogic R slider (50% threshold)",
|
||||
"C-stick left-right axis","C-stick up-down axis",
|
||||
};
|
||||
|
||||
if (id == 0xff)
|
||||
return "None";
|
||||
|
||||
if (id < 0 || id >= ARRAY_SIZE(names)) {
|
||||
return "Error";
|
||||
}
|
||||
return names[id];
|
||||
}
|
||||
|
||||
const char *gc2n64_adapter_getN64name(unsigned char id)
|
||||
{
|
||||
const char *names[] = {
|
||||
"A","B","Z","Start","L","R",
|
||||
"C-up","C-down","C-left","C-right",
|
||||
"Dpad-up","Dpad-down","Dpad-left","Dpad-right",
|
||||
"Joystick left-right axis","Joystick up-down axis",
|
||||
"Joystick up", "Joystick down",
|
||||
"Joystick left", "Joystick right",
|
||||
"None"
|
||||
};
|
||||
|
||||
if (id == 0xff)
|
||||
return "None";
|
||||
|
||||
if (id < 0 || id >= ARRAY_SIZE(names)) {
|
||||
return "Error";
|
||||
}
|
||||
return names[id];
|
||||
}
|
||||
|
||||
struct gc2n64_adapter_mapping *gc2n64_adapter_loadMapping(const char *srcfile)
|
||||
{
|
||||
FILE *fptr;
|
||||
struct gc2n64_adapter_mapping *map = NULL;;
|
||||
char linebuf[64];
|
||||
int line = 0, pair = 0;
|
||||
|
||||
fptr = fopen(srcfile, "r");
|
||||
if (!fptr) {
|
||||
perror("fopen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
map = malloc(sizeof(struct gc2n64_adapter_mapping));
|
||||
if (!map) {
|
||||
perror("malloc");
|
||||
goto err;
|
||||
}
|
||||
|
||||
do {
|
||||
if (fgets(linebuf, sizeof(linebuf), fptr)) {
|
||||
int gc, n64, n;
|
||||
line++;
|
||||
|
||||
if (line == 1) {
|
||||
const char *magic = "# gc2n64 mapping";
|
||||
if (strncmp(magic, linebuf, strlen(magic))) {
|
||||
fprintf(stderr, "Does not appear to be a valid mapping file\n");
|
||||
goto err;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
n = sscanf(linebuf, "%03d;%03d", &gc, &n64);
|
||||
if (n != 2) {
|
||||
// printf("Ignoring line %d\n", line);
|
||||
} else {
|
||||
// printf("%d -> %d\n", gc, n64);
|
||||
map->pairs[pair].gc = gc;
|
||||
map->pairs[pair].n64 = n64;
|
||||
|
||||
pair++;
|
||||
if (pair >= GC2N64_MAX_MAPPING_PAIRS) {
|
||||
fprintf(stderr, "too many pairs, cannot load mapping.\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!feof(fptr));
|
||||
|
||||
map->n_pairs = pair;
|
||||
|
||||
fclose(fptr);
|
||||
return map;
|
||||
|
||||
err:
|
||||
if (map) {
|
||||
free(map);
|
||||
}
|
||||
fclose(fptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int gc2n64_adapter_saveMapping(struct gc2n64_adapter_mapping *map, const char *dstfile)
|
||||
{
|
||||
FILE *fptr;
|
||||
int i;
|
||||
|
||||
fptr = fopen(dstfile, "w");
|
||||
if (!fptr) {
|
||||
perror("fopen");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(fptr, "# gc2n64 mapping\n");
|
||||
for (i=0; i<map->n_pairs; i++) {
|
||||
fprintf(fptr, "%03d;%03d # %s -> %s\n",
|
||||
map->pairs[i].gc, map->pairs[i].n64,
|
||||
gc2n64_adapter_getGCname(map->pairs[i].gc),
|
||||
gc2n64_adapter_getN64name(map->pairs[i].n64));
|
||||
}
|
||||
fflush(fptr);
|
||||
fclose(fptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gc2n64_adapter_printMapping(struct gc2n64_adapter_mapping *map)
|
||||
{
|
||||
int i;
|
||||
int is_default;
|
||||
|
||||
for (i=0; i<map->n_pairs; i++) {
|
||||
// Do not display the terminator
|
||||
if (map->pairs[i].gc == 0xff || map->pairs[i].n64 == 0xff) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* 0 .. 15 is a 1:1 (same button name) mapping by default */
|
||||
if (map->pairs[i].gc < 16) {
|
||||
if (map->pairs[i].gc == map->pairs[i].n64) {
|
||||
is_default = 1;
|
||||
}
|
||||
else {
|
||||
is_default = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 16 and above maps to NONE by default
|
||||
if (map->pairs[i].n64 == 20) {
|
||||
is_default = 1;
|
||||
} else {
|
||||
is_default = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_default) {
|
||||
printf("%s -> %s, ", gc2n64_adapter_getGCname(map->pairs[i].gc),
|
||||
gc2n64_adapter_getN64name(map->pairs[i].n64));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gc2n64_adapter_printInfo(struct gc2n64_adapter_info *inf)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!inf->in_bootloader) {
|
||||
printf("gc_to_n64 adapter info: {\n");
|
||||
|
||||
printf("\tDefault mapping id: %d\n", inf->app.default_mapping_id);
|
||||
printf("\tDefault mapping id: %d (%s)\n", inf->app.default_mapping_id, gc2n64_adapter_getMappingSlotName(inf->app.default_mapping_id, 1) );
|
||||
printf("\tDeadzone enabled: %d\n", inf->app.deadzone_enabled);
|
||||
printf("\tOld v1.5 conversion: %d\n", inf->app.old_v1_5_conversion);
|
||||
printf("\tFirmware version: %s\n", inf->app.version);
|
||||
printf("\tUpgradable: %s\n", inf->app.upgradeable ? "Yes":"No (Atmega8)");
|
||||
for (i=0; i<GC2N64_NUM_MAPPINGS; i++) {
|
||||
printf("\tMapping %d (%-13s): { ", i, gc2n64_adapter_getMappingSlotName(i, 0));
|
||||
gc2n64_adapter_printMapping(&inf->app.mappings[i]);
|
||||
printf(" }\n");
|
||||
}
|
||||
} else {
|
||||
printf("gc_to_n64 adapter in bootloader mode: {\n");
|
||||
|
||||
@ -139,6 +441,10 @@ int gc2n64_adapter_getInfo(gcn64_hdl_t hdl, int channel, struct gc2n64_adapter_i
|
||||
strncpy(inf->bootldr.version, (char*)buf+10, sizeof(inf->bootldr.version)-1);
|
||||
}
|
||||
|
||||
for (n=0; n<GC2N64_NUM_MAPPINGS; n++) {
|
||||
gc2n64_adapter_getMapping(hdl, channel, n, &inf->app.mappings[n]);
|
||||
}
|
||||
|
||||
} else {
|
||||
printf("No answer (old version?)\n");
|
||||
return -1;
|
||||
@ -147,7 +453,7 @@ int gc2n64_adapter_getInfo(gcn64_hdl_t hdl, int channel, struct gc2n64_adapter_i
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gc2n64_adapter_boot_isBusy(gcn64_hdl_t hdl, int channel)
|
||||
int gc2n64_adapter_isBusy(gcn64_hdl_t hdl, int channel)
|
||||
{
|
||||
unsigned char buf[64];
|
||||
int n;
|
||||
@ -170,13 +476,13 @@ int gc2n64_adapter_boot_isBusy(gcn64_hdl_t hdl, int channel)
|
||||
return 0; // Idle
|
||||
}
|
||||
|
||||
int gc2n64_adapter_boot_waitNotBusy(gcn64_hdl_t hdl, int channel, int verbose)
|
||||
int gc2n64_adapter_waitNotBusy(gcn64_hdl_t hdl, int channel, int verbose)
|
||||
{
|
||||
char spinner[4] = { '|','/','-','\\' };
|
||||
int busy, no_reply_count=0;
|
||||
int c=0;
|
||||
|
||||
while ((busy = gc2n64_adapter_boot_isBusy(hdl, channel)))
|
||||
while ((busy = gc2n64_adapter_isBusy(hdl, channel)))
|
||||
{
|
||||
if (busy < 0) {
|
||||
return -1;
|
||||
@ -376,7 +682,7 @@ int gc2n64_adapter_sendFirmwareBlocks(gcn64_hdl_t hdl, int channel, unsigned cha
|
||||
}
|
||||
|
||||
if (buf[1]) {
|
||||
if (gc2n64_adapter_boot_waitNotBusy(hdl, channel, 1)) {
|
||||
if (gc2n64_adapter_waitNotBusy(hdl, channel, 1)) {
|
||||
fprintf(stderr, "Error waiting not busy\n");
|
||||
return -1;
|
||||
}
|
||||
@ -506,7 +812,7 @@ int gc2n64_adapter_updateFirmware(gcn64_hdl_t hdl, int channel, const char *hexf
|
||||
printf("step [4/7] : Erase current firmware... "); fflush(stdout);
|
||||
gc2n64_adapter_boot_eraseAll(hdl, channel);
|
||||
|
||||
if (gc2n64_adapter_boot_waitNotBusy(hdl, channel, 1)) {
|
||||
if (gc2n64_adapter_waitNotBusy(hdl, channel, 1)) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
@ -3,12 +3,25 @@
|
||||
|
||||
#include "gcn64.h"
|
||||
|
||||
#define GC2N64_MAX_MAPPING_PAIRS 32
|
||||
#define GC2N64_NUM_MAPPINGS 5
|
||||
|
||||
struct gc2n64_adapter_mapping_pair {
|
||||
int gc, n64;
|
||||
};
|
||||
|
||||
struct gc2n64_adapter_mapping {
|
||||
int n_pairs;
|
||||
struct gc2n64_adapter_mapping_pair pairs[GC2N64_MAX_MAPPING_PAIRS];
|
||||
};
|
||||
|
||||
struct gc2n64_adapter_info_app {
|
||||
unsigned char default_mapping_id;
|
||||
unsigned char deadzone_enabled;
|
||||
unsigned char old_v1_5_conversion;
|
||||
unsigned char upgradeable;
|
||||
char version[16];
|
||||
struct gc2n64_adapter_mapping mappings[GC2N64_NUM_MAPPINGS];
|
||||
};
|
||||
|
||||
struct gc2n64_adapter_info_bootloader {
|
||||
@ -28,6 +41,24 @@ struct gc2n64_adapter_info {
|
||||
int gc2n64_adapter_echotest(gcn64_hdl_t hdl, int channel, int verbosee);
|
||||
int gc2n64_adapter_getInfo(gcn64_hdl_t hdl, int channel, struct gc2n64_adapter_info *inf);
|
||||
void gc2n64_adapter_printInfo(struct gc2n64_adapter_info *inf);
|
||||
void gc2n64_adapter_printMapping(struct gc2n64_adapter_mapping *map);
|
||||
|
||||
#define MAPPING_SLOT_BUILTIN_CURRENT 0
|
||||
#define MAPPING_SLOT_DPAD_UP 1
|
||||
#define MAPPING_SLOT_DPAD_DOWN 2
|
||||
#define MAPPING_SLOT_DPAD_LEFT 3
|
||||
#define MAPPING_SLOT_DPAD_RIGHT 4
|
||||
const char *gc2n64_adapter_getMappingSlotName(unsigned char id, int default_context);
|
||||
|
||||
int gc2n64_adapter_getMapping(gcn64_hdl_t hdl, int channel, int mapping_id, struct gc2n64_adapter_mapping *dst_mapping);
|
||||
int gc2n64_adapter_setMapping(gcn64_hdl_t hdl, int channel, struct gc2n64_adapter_mapping *mapping);
|
||||
int gc2n64_adapter_storeCurrentMapping(gcn64_hdl_t hdl, int channel, int dst_slot);
|
||||
|
||||
int gc2n64_adapter_saveMapping(struct gc2n64_adapter_mapping *map, const char *dstfile);
|
||||
struct gc2n64_adapter_mapping *gc2n64_adapter_loadMapping(const char *srcfile);
|
||||
|
||||
int gc2n64_adapter_waitNotBusy(gcn64_hdl_t hdl, int channel, int verbose);
|
||||
int gc2n64_adapter_boot_isBusy(gcn64_hdl_t hdl, int channel);
|
||||
|
||||
int gc2n64_adapter_boot_eraseAll(gcn64_hdl_t hdl, int channel);
|
||||
int gc2n64_adapter_boot_readBlock(gcn64_hdl_t hdl, int channel, unsigned int block_id, unsigned char dst[32]);
|
||||
|
79
tool/main.c
79
tool/main.c
@ -44,6 +44,7 @@ static void printUsage(void)
|
||||
printf(" -s serial Operate on specified device (required unless -f is specified)\n");
|
||||
printf(" -f, --force If no serial is specified, use first device detected.\n");
|
||||
printf(" -o, --outfile file Output file for read operations (eg: --n64-mempak-dump)\n");
|
||||
//printf(" -i, --infile file Input file for write operations (eg: --gc_to_n64_update)\n");
|
||||
printf(" --nonstop Continue testing forever or until an error occurs.\n");
|
||||
printf("\n");
|
||||
printf("Configuration commands:\n");
|
||||
@ -68,6 +69,9 @@ static void printUsage(void)
|
||||
printf("GC to N64 adapter commands: (For GC to N64 adapter connected to GC/N64 to USB adapter)\n");
|
||||
printf(" --gc_to_n64_info Display info on adapter (version, config, etc)\n");
|
||||
printf(" --gc_to_n64_update file.hex Update GC to N64 adapter firmware\n");
|
||||
printf(" --gc_to_n64_read_mapping id Dump a mapping (Use with --outfile to write to file)\n");
|
||||
printf(" --gc_to_n64_load_mapping file Load a mapping from a file and send it to the adapter\n");
|
||||
printf(" --gc_to_n64_store_current_mapping slot Store the current mapping to one of the D-Pad slots.\n");
|
||||
printf("\n");
|
||||
printf("GC to N64 adapter, development/debug commands:\n");
|
||||
printf(" --gc_to_n64_echotest Perform a communication test (usable with --nonstop)\n");
|
||||
@ -82,6 +86,7 @@ static void printUsage(void)
|
||||
|
||||
|
||||
#define OPT_OUTFILE 'o'
|
||||
#define OPT_INFILE 'i'
|
||||
#define OPT_SET_SERIAL 257
|
||||
#define OPT_GET_SERIAL 258
|
||||
#define OPT_BOOTLOADER 300
|
||||
@ -104,6 +109,9 @@ static void printUsage(void)
|
||||
#define OPT_GC_TO_N64_ENTER_BOOTLOADER 317
|
||||
#define OPT_GC_TO_N64_BOOT_APPLICATION 318
|
||||
#define OPT_NONSTOP 319
|
||||
#define OPT_GC_TO_N64_READ_MAPPING 320
|
||||
#define OPT_GC_TO_N64_LOAD_MAPPING 321
|
||||
#define OPT_GC_TO_N64_STORE_CURRENT_MAPPING 322
|
||||
|
||||
struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
@ -120,6 +128,7 @@ struct option longopts[] = {
|
||||
{ "suspend_polling", 0, NULL, OPT_SUSPEND_POLLING },
|
||||
{ "resume_polling", 0, NULL, OPT_RESUME_POLLING },
|
||||
{ "outfile", 1, NULL, OPT_OUTFILE },
|
||||
{ "infile", 1, NULL, OPT_INFILE },
|
||||
{ "set_poll_rate", 1, NULL, OPT_SET_POLL_INTERVAL },
|
||||
{ "get_poll_rate", 0, NULL, OPT_GET_POLL_INTERVAL },
|
||||
{ "n64_mempak_write", 1, NULL, OPT_N64_MEMPAK_WRITE },
|
||||
@ -131,6 +140,9 @@ struct option longopts[] = {
|
||||
{ "gc_to_n64_dump", 0, NULL, OPT_GC_TO_N64_DUMP },
|
||||
{ "gc_to_n64_enter_bootloader", 0, NULL, OPT_GC_TO_N64_ENTER_BOOTLOADER },
|
||||
{ "gc_to_n64_boot_application", 0, NULL, OPT_GC_TO_N64_BOOT_APPLICATION },
|
||||
{ "gc_to_n64_read_mapping", 1, NULL, OPT_GC_TO_N64_READ_MAPPING },
|
||||
{ "gc_to_n64_load_mapping", 1, NULL, OPT_GC_TO_N64_LOAD_MAPPING },
|
||||
{ "gc_to_n64_store_current_mapping", 1, NULL, OPT_GC_TO_N64_STORE_CURRENT_MAPPING },
|
||||
{ "nonstop", 0, NULL, OPT_NONSTOP },
|
||||
{ },
|
||||
};
|
||||
@ -171,6 +183,7 @@ int main(int argc, char **argv)
|
||||
wchar_t target_serial[TARGET_SERIAL_CHARS];
|
||||
const char *short_optstr = "hls:vfo:";
|
||||
const char *outfile = NULL;
|
||||
const char *infile = NULL;
|
||||
int gc2n64_channel = 0;
|
||||
|
||||
while((opt = getopt_long(argc, argv, short_optstr, longopts, NULL)) != -1) {
|
||||
@ -203,6 +216,10 @@ int main(int argc, char **argv)
|
||||
outfile = optarg;
|
||||
printf("Output file: %s\n", outfile);
|
||||
break;
|
||||
case 'i':
|
||||
infile = optarg;
|
||||
printf("Input file: %s\n", infile);
|
||||
break;
|
||||
case OPT_NONSTOP:
|
||||
nonstop = 1;
|
||||
break;
|
||||
@ -408,6 +425,68 @@ int main(int argc, char **argv)
|
||||
case OPT_GC_TO_N64_BOOT_APPLICATION:
|
||||
gc2n64_adapter_bootApplication(hdl, gc2n64_channel);
|
||||
break;
|
||||
|
||||
case OPT_GC_TO_N64_READ_MAPPING:
|
||||
{
|
||||
struct gc2n64_adapter_info inf;
|
||||
int map_id;
|
||||
|
||||
map_id = atoi(optarg);
|
||||
if ((map_id <= 0) || (map_id > GC2N64_NUM_MAPPINGS)) {
|
||||
fprintf(stderr, "Invalid mapping id (1 to 4)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gc2n64_adapter_getInfo(hdl, gc2n64_channel, &inf);
|
||||
printf("Mapping %d : { ", map_id);
|
||||
gc2n64_adapter_printMapping(&inf.app.mappings[map_id-1]);
|
||||
printf(" }\n");
|
||||
if (outfile) {
|
||||
printf("Writing mapping to file '%s'\n", outfile);
|
||||
gc2n64_adapter_saveMapping(&inf.app.mappings[map_id-1], outfile);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_GC_TO_N64_LOAD_MAPPING:
|
||||
{
|
||||
struct gc2n64_adapter_mapping *mapping;
|
||||
|
||||
printf("Reading mapping from file '%s'\n", optarg);
|
||||
mapping = gc2n64_adapter_loadMapping(optarg);
|
||||
if (!mapping) {
|
||||
fprintf(stderr, "Failed to load mapping\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Mapping : { ");
|
||||
gc2n64_adapter_printMapping(mapping);
|
||||
printf(" }\n");
|
||||
|
||||
gc2n64_adapter_setMapping(hdl, gc2n64_channel, mapping);
|
||||
|
||||
free(mapping);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_GC_TO_N64_STORE_CURRENT_MAPPING:
|
||||
{
|
||||
int slot;
|
||||
|
||||
slot = atoi(optarg);
|
||||
|
||||
if (slot < 1 || slot > 4) {
|
||||
fprintf(stderr, "Mapping out of range (1-4)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 == gc2n64_adapter_storeCurrentMapping(hdl, gc2n64_channel, slot)) {
|
||||
printf("Stored mapping to slot %d (%s)\n", slot, gc2n64_adapter_getMappingSlotName(slot, 0));
|
||||
} else {
|
||||
printf("Error storing mapping\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (do_exchange) {
|
||||
|
Loading…
Reference in New Issue
Block a user