mirror of
https://github.com/raphnet/gc_n64_usb-v3
synced 2024-12-21 06:48:52 -05:00
Channels for raw SI commands
Configurable poll interval
This commit is contained in:
parent
fd83e0ae7d
commit
0627841025
41
config.c
41
config.c
@ -10,10 +10,15 @@ struct eeprom_data_struct g_eeprom_data;
|
||||
* values. */
|
||||
void eeprom_app_write_defaults(void)
|
||||
{
|
||||
int i;
|
||||
const char default_serial[SERIAL_NUM_LEN] = { '0','0','0','0','0','1' };
|
||||
|
||||
memcpy(g_eeprom_data.cfg.serial, default_serial, SERIAL_NUM_LEN);
|
||||
g_eeprom_data.cfg.mode = CFG_MODE_STANDARD;
|
||||
|
||||
for (i=0; i<NUM_CHANNELS; i++) {
|
||||
g_eeprom_data.cfg.poll_interval[i] = 5; // 5ms default
|
||||
}
|
||||
}
|
||||
|
||||
static void config_set_serial(char serial[SERIAL_NUM_LEN])
|
||||
@ -32,6 +37,24 @@ unsigned char config_getParam(unsigned char param, unsigned char *value, unsigne
|
||||
case CFG_PARAM_SERIAL:
|
||||
memcpy(value, g_eeprom_data.cfg.serial, SERIAL_NUM_LEN);
|
||||
return SERIAL_NUM_LEN;
|
||||
case CFG_PARAM_POLL_INTERVAL0:
|
||||
*value = g_eeprom_data.cfg.poll_interval[0];
|
||||
return 1;
|
||||
#if NUM_CHANNELS > 1
|
||||
case CFG_PARAM_POLL_INTERVAL1:
|
||||
*value = g_eeprom_data.cfg.poll_interval[1];
|
||||
return 1;
|
||||
#endif
|
||||
#if NUM_CHANNELS > 2
|
||||
case CFG_PARAM_POLL_INTERVAL2:
|
||||
*value = g_eeprom_data.cfg.poll_interval[2];
|
||||
return 1;
|
||||
#endif
|
||||
#if NUM_CHANNELS > 3
|
||||
case CFG_PARAM_POLL_INTERVAL3:
|
||||
*value = g_eeprom_data.cfg.poll_interval[3];
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -50,6 +73,24 @@ unsigned char config_setParam(unsigned char param, const unsigned char *value)
|
||||
case CFG_PARAM_SERIAL:
|
||||
config_set_serial((char*)value);
|
||||
return 1;
|
||||
case CFG_PARAM_POLL_INTERVAL0:
|
||||
g_eeprom_data.cfg.poll_interval[0] = value[0];
|
||||
return 1;
|
||||
#if NUM_CHANNELS > 1
|
||||
case CFG_PARAM_POLL_INTERVAL1:
|
||||
g_eeprom_data.cfg.poll_interval[1] = value[0];
|
||||
return 1;
|
||||
#endif
|
||||
#if NUM_CHANNELS > 2
|
||||
case CFG_PARAM_POLL_INTERVAL2:
|
||||
g_eeprom_data.cfg.poll_interval[2] = value[0];
|
||||
return 1;
|
||||
#endif
|
||||
#if NUM_CHANNELS > 3
|
||||
case CFG_PARAM_POLL_INTERVAL3:
|
||||
g_eeprom_data.cfg.poll_interval[3] = value[0];
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
2
config.h
2
config.h
@ -1,10 +1,12 @@
|
||||
#ifndef _config_h__
|
||||
#define _config_h__
|
||||
|
||||
#define NUM_CHANNELS 4
|
||||
#define SERIAL_NUM_LEN 6
|
||||
struct eeprom_cfg {
|
||||
uint8_t serial[SERIAL_NUM_LEN];
|
||||
uint8_t mode;
|
||||
uint8_t poll_interval[NUM_CHANNELS];
|
||||
};
|
||||
|
||||
void eeprom_app_write_defaults(void);
|
||||
|
18
hiddata.c
18
hiddata.c
@ -38,9 +38,8 @@ uint16_t hiddata_get_report(struct usb_request *rq, const uint8_t **dat)
|
||||
/*** Get/Set report called from interrupt context! */
|
||||
uint8_t hiddata_set_report(const struct usb_request *rq, const uint8_t *dat, uint16_t len)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
int i;
|
||||
printf("Set data %d\n", len);
|
||||
for (i=0; i<len; i++) {
|
||||
printf("0x%02x ", dat[i]);
|
||||
@ -57,8 +56,8 @@ uint8_t hiddata_set_report(const struct usb_request *rq, const uint8_t *dat, uin
|
||||
|
||||
static void hiddata_processCommandBuffer(void)
|
||||
{
|
||||
int i;
|
||||
int bits;
|
||||
unsigned char channel;
|
||||
|
||||
if (cmdbuf_len < 1) {
|
||||
state = STATE_IDLE;
|
||||
@ -73,11 +72,13 @@ static void hiddata_processCommandBuffer(void)
|
||||
break;
|
||||
case RQ_GCN64_RAW_SI_COMMAND:
|
||||
// TODO : Range checking
|
||||
// cmd : RQ, LEN, data[]
|
||||
bits = gcn64_transaction(cmdbuf+2, cmdbuf[1]);
|
||||
// cmdbuf[] : RQ, CHN, LEN, data[]
|
||||
channel = cmdbuf[1];
|
||||
bits = gcn64_transaction(cmdbuf+3, cmdbuf[2]);
|
||||
cmdbuf_len = bits / 8; // The above return a number of bits
|
||||
gcn64_protocol_getBytes(0, cmdbuf_len, cmdbuf + 2);
|
||||
cmdbuf_len += 2; // Answer: RQ, LEN, data[]
|
||||
gcn64_protocol_getBytes(0, cmdbuf_len, cmdbuf + 3);
|
||||
cmdbuf[2] = cmdbuf_len;
|
||||
cmdbuf_len += 3; // Answer: RQ, CHN, LEN, data[]
|
||||
break;
|
||||
case RQ_GCN64_GET_CONFIG_PARAM:
|
||||
// Cmd : RQ, PARAM
|
||||
@ -92,7 +93,8 @@ static void hiddata_processCommandBuffer(void)
|
||||
cmdbuf_len = 2;
|
||||
break;
|
||||
case RQ_GCN64_SUSPEND_POLLING:
|
||||
g_polling_suspended = 1;
|
||||
// CMD: RQ, PARAM
|
||||
g_polling_suspended = cmdbuf[1];
|
||||
break;
|
||||
}
|
||||
|
||||
|
13
main.c
13
main.c
@ -480,6 +480,14 @@ void eeprom_app_ready(void)
|
||||
|
||||
char g_polling_suspended = 0;
|
||||
|
||||
void pollDelay(void)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<g_eeprom_data.cfg.poll_interval[0]; i++) {
|
||||
_delay_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Gamepad *pad = NULL;
|
||||
@ -512,7 +520,10 @@ int main(void)
|
||||
// for polling the controller...
|
||||
hiddata_doTask();
|
||||
|
||||
_delay_ms(5);
|
||||
if (!g_polling_suspended) {
|
||||
pollDelay();
|
||||
}
|
||||
|
||||
decideVibration();
|
||||
|
||||
if (last_v != gamepad_vibrate) {
|
||||
|
@ -14,5 +14,10 @@
|
||||
|
||||
#define CFG_PARAM_SERIAL 0x01
|
||||
|
||||
#define CFG_PARAM_POLL_INTERVAL0 0x10
|
||||
#define CFG_PARAM_POLL_INTERVAL1 0x11
|
||||
#define CFG_PARAM_POLL_INTERVAL2 0x12
|
||||
#define CFG_PARAM_POLL_INTERVAL3 0x13
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@ PREFIX=/usr/local
|
||||
|
||||
PROG=gcn64ctl
|
||||
|
||||
OBJS=main.o gcn64.o mempak.o
|
||||
OBJS=main.o gcn64.o mempak.o gcn64lib.o
|
||||
|
||||
.PHONY : clean install
|
||||
|
||||
|
@ -35,6 +35,5 @@ int gcn64_poll_result(gcn64_hdl_t hdl, unsigned char *cmd, int cmdlen);
|
||||
|
||||
int gcn64_exchange(gcn64_hdl_t hdl, unsigned char *outcmd, int outlen, unsigned char *result, int result_max);
|
||||
|
||||
|
||||
#endif // _gcn64_h__
|
||||
|
||||
|
BIN
tool/gcn64ctl
Executable file
BIN
tool/gcn64ctl
Executable file
Binary file not shown.
77
tool/gcn64lib.c
Normal file
77
tool/gcn64lib.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include <string.h>
|
||||
#include "gcn64lib.h"
|
||||
#include "../requests.h"
|
||||
|
||||
int gcn64lib_getConfig(gcn64_hdl_t hdl, unsigned char param, unsigned char *rx, unsigned char rx_max)
|
||||
{
|
||||
unsigned char cmd[2];
|
||||
int n;
|
||||
|
||||
cmd[0] = RQ_GCN64_GET_CONFIG_PARAM;
|
||||
cmd[1] = param;
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, 2, rx, rx_max);
|
||||
if (n<2)
|
||||
return n;
|
||||
|
||||
n -= 2;
|
||||
|
||||
// Drop the leading CMD and PARAM
|
||||
if (n) {
|
||||
memmove(rx, rx+2, n);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
int gcn64lib_setConfig(gcn64_hdl_t hdl, unsigned char param, unsigned char *data, unsigned char len)
|
||||
{
|
||||
unsigned char cmd[2 + len];
|
||||
int n;
|
||||
|
||||
cmd[0] = RQ_GCN64_SET_CONFIG_PARAM;
|
||||
cmd[1] = param;
|
||||
memcpy(cmd + 2, data, len);
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, 2 + len, cmd, sizeof(cmd));
|
||||
if (n<0)
|
||||
return n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcn64lib_suspendPolling(gcn64_hdl_t hdl, unsigned char suspend)
|
||||
{
|
||||
unsigned char cmd[2];
|
||||
int n;
|
||||
|
||||
cmd[0] = RQ_GCN64_SUSPEND_POLLING;
|
||||
cmd[1] = suspend;
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, 2, cmd, sizeof(cmd));
|
||||
if (n<0)
|
||||
return n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcn64lib_rawSiCommand(gcn64_hdl_t hdl, unsigned char channel, unsigned char *tx, unsigned char tx_len, unsigned char *rx, unsigned char max_rx)
|
||||
{
|
||||
unsigned char cmd[3 + tx_len];
|
||||
int cmdlen, rx_len, n;
|
||||
|
||||
cmd[0] = RQ_GCN64_RAW_SI_COMMAND;
|
||||
cmd[1] = channel;
|
||||
cmd[2] = tx_len;
|
||||
memcpy(cmd+3, tx, tx_len);
|
||||
cmdlen = 3 + tx_len;
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, cmdlen, rx, max_rx);
|
||||
if (n<0)
|
||||
return n;
|
||||
|
||||
rx_len = rx[2];
|
||||
|
||||
memmove(rx, rx + 3, rx_len);
|
||||
|
||||
return rx_len;
|
||||
}
|
11
tool/gcn64lib.h
Normal file
11
tool/gcn64lib.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef _gcn64_lib_h__
|
||||
#define _gcn64_lib_h__
|
||||
|
||||
#include "gcn64.h"
|
||||
|
||||
int gcn64lib_suspendPolling(gcn64_hdl_t hdl, unsigned char suspend);
|
||||
int gcn64lib_setConfig(gcn64_hdl_t hdl, unsigned char param, unsigned char *data, unsigned char len);
|
||||
int gcn64lib_getConfig(gcn64_hdl_t hdl, unsigned char param, unsigned char *rx, unsigned char rx_max);
|
||||
int gcn64lib_rawSiCommand(gcn64_hdl_t hdl, unsigned char channel, unsigned char *tx, unsigned char tx_len, unsigned char *rx, unsigned char max_rx);
|
||||
|
||||
#endif // _gcn64_lib_h__
|
5
tool/gcn64utils.h
Normal file
5
tool/gcn64utils.h
Normal file
@ -0,0 +1,5 @@
|
||||
#ifndef _gcn64_utils_h__
|
||||
#define _gcn64_utils_h__
|
||||
|
||||
#endif // _gcn64_utils_h__
|
||||
|
114
tool/main.c
114
tool/main.c
@ -26,6 +26,7 @@
|
||||
|
||||
#include "version.h"
|
||||
#include "gcn64.h"
|
||||
#include "gcn64lib.h"
|
||||
#include "mempak.h"
|
||||
#include "../requests.h"
|
||||
#include "../gcn64_protocol.h"
|
||||
@ -36,19 +37,22 @@ static void printUsage(void)
|
||||
printf("Control tool for WUSBmote adapter. Version %s\n", VERSION_STR);
|
||||
printf("\n");
|
||||
printf("Options:\n");
|
||||
printf(" -h, --help Print help\n");
|
||||
printf(" -l, --list List devices\n");
|
||||
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 Output file for read operations (eg: --n64-mempak-dump)\n");
|
||||
printf(" -h, --help Print help\n");
|
||||
printf(" -l, --list List devices\n");
|
||||
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("\n");
|
||||
printf("Configuration commands:\n");
|
||||
printf(" --set_serial serial Assign a new device serial number\n");
|
||||
printf(" --get_serial Read serial from eeprom\n");
|
||||
printf(" --set_poll_rate ms Set time between controller polls in milliseconds\n");
|
||||
printf(" --get_poll_rate Read configured poll rate\n");
|
||||
printf("\n");
|
||||
printf("Advanced commands:\n");
|
||||
printf(" --bootloader Re-enumerate in bootloader mode\n");
|
||||
printf(" --suspend_polling Stop polling controller\n");
|
||||
printf(" --suspend_polling Stop polling the controller\n");
|
||||
printf(" --resume_polling Re-start polling the controller\n");
|
||||
printf("\n");
|
||||
printf("Raw controller commands:\n");
|
||||
printf(" --n64_getstatus Read N64 controller status now\n");
|
||||
@ -58,6 +62,17 @@ static void printUsage(void)
|
||||
printf(" --n64_mempak_dump Dump N64 mempak contents (Use with --outfile to write to file)\n");
|
||||
}
|
||||
|
||||
static void printHexBuf(unsigned char *buf, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<n; i++) {
|
||||
printf("%02x ", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
#define OPT_OUTFILE 'o'
|
||||
#define OPT_SET_SERIAL 257
|
||||
#define OPT_GET_SERIAL 258
|
||||
@ -68,6 +83,9 @@ static void printUsage(void)
|
||||
#define OPT_N64_MEMPAK_DUMP 304
|
||||
#define OPT_N64_GETCAPS 305
|
||||
#define OPT_SUSPEND_POLLING 306
|
||||
#define OPT_RESUME_POLLING 307
|
||||
#define OPT_SET_POLL_INTERVAL 308
|
||||
#define OPT_GET_POLL_INTERVAL 309
|
||||
|
||||
struct option longopts[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
@ -82,7 +100,10 @@ struct option longopts[] = {
|
||||
{ "n64_getcaps", 0, NULL, OPT_N64_GETCAPS },
|
||||
{ "n64_mempak_dump", 0, NULL, OPT_N64_MEMPAK_DUMP },
|
||||
{ "suspend_polling", 0, NULL, OPT_SUSPEND_POLLING },
|
||||
{ "resume_polling", 0, NULL, OPT_RESUME_POLLING },
|
||||
{ "outfile", 1, NULL, OPT_OUTFILE },
|
||||
{ "set_poll_rate", 1, NULL, OPT_SET_POLL_INTERVAL },
|
||||
{ "get_poll_rate", 0, NULL, OPT_GET_POLL_INTERVAL },
|
||||
{ },
|
||||
};
|
||||
|
||||
@ -209,68 +230,83 @@ int main(int argc, char **argv)
|
||||
unsigned char cmd[64] = { };
|
||||
int n;
|
||||
int cmdlen = 0;
|
||||
int do_exchange = 0;
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case OPT_SET_POLL_INTERVAL:
|
||||
cmd[0] = atoi(optarg);
|
||||
printf("Setting poll interval to %d ms\n", cmd[0]);
|
||||
gcn64lib_setConfig(hdl, CFG_PARAM_POLL_INTERVAL0, cmd, 1);
|
||||
break;
|
||||
|
||||
case OPT_GET_POLL_INTERVAL:
|
||||
n = gcn64lib_getConfig(hdl, CFG_PARAM_POLL_INTERVAL0, cmd, sizeof(cmd));
|
||||
if (n == 1) {
|
||||
printf("Poll interval: %d ms\n", cmd[0]);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_SET_SERIAL:
|
||||
printf("Setting serial...");
|
||||
if (strlen(optarg) != 6) {
|
||||
fprintf(stderr, "Serial number must be 6 characters\n");
|
||||
return -1;
|
||||
}
|
||||
cmd[0] = RQ_GCN64_SET_CONFIG_PARAM;
|
||||
cmd[1] = CFG_PARAM_SERIAL;
|
||||
memcpy(cmd + 2, optarg, 6);
|
||||
cmdlen = 8;
|
||||
gcn64lib_setConfig(hdl, CFG_PARAM_SERIAL, (void*)optarg, 6);
|
||||
break;
|
||||
|
||||
case OPT_GET_SERIAL:
|
||||
cmd[0] = RQ_GCN64_GET_CONFIG_PARAM;
|
||||
cmd[1] = CFG_PARAM_SERIAL;
|
||||
cmdlen = 2;
|
||||
n = gcn64lib_getConfig(hdl, CFG_PARAM_SERIAL, cmd, sizeof(cmd));
|
||||
if (n==6) {
|
||||
cmd[6] = 0;
|
||||
printf("Serial: %s\n", cmd);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_BOOTLOADER:
|
||||
printf("Sending 'jump to bootloader' command...");
|
||||
cmd[0] = RQ_GCN64_JUMP_TO_BOOTLOADER;
|
||||
cmdlen = 1;
|
||||
do_exchange = 1;
|
||||
break;
|
||||
|
||||
case OPT_SUSPEND_POLLING:
|
||||
cmd[0] = RQ_GCN64_SUSPEND_POLLING;
|
||||
cmdlen = 1;
|
||||
gcn64lib_suspendPolling(hdl, 1);
|
||||
break;
|
||||
|
||||
case OPT_RESUME_POLLING:
|
||||
gcn64lib_suspendPolling(hdl, 0);
|
||||
break;
|
||||
|
||||
case OPT_N64_GETSTATUS:
|
||||
cmd[0] = RQ_GCN64_RAW_SI_COMMAND;
|
||||
cmd[1] = 0x01; // Length of SI command
|
||||
cmd[2] = N64_GET_STATUS; // N64 GET status
|
||||
cmdlen = 3;
|
||||
break;
|
||||
|
||||
case OPT_GC_GETSTATUS:
|
||||
cmd[0] = RQ_GCN64_RAW_SI_COMMAND;
|
||||
cmd[1] = 0x03; // Length of SI command
|
||||
cmd[2] = GC_GETSTATUS1;
|
||||
cmd[3] = GC_GETSTATUS2;
|
||||
cmd[4] = GC_GETSTATUS3(0);
|
||||
cmdlen = 5;
|
||||
cmd[0] = N64_GET_STATUS;
|
||||
n = gcn64lib_rawSiCommand(hdl, 0, cmd, 1, cmd, sizeof(cmd));
|
||||
if (n >= 0) {
|
||||
printf("N64 Get status[%d]: ", n);
|
||||
printHexBuf(cmd, n);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_GC_GETSTATUS_RUMBLE:
|
||||
cmd[0] = RQ_GCN64_RAW_SI_COMMAND;
|
||||
cmd[1] = 0x03; // Length of SI command
|
||||
cmd[2] = GC_GETSTATUS1;
|
||||
cmd[3] = GC_GETSTATUS2;
|
||||
cmd[4] = GC_GETSTATUS3(0);
|
||||
cmdlen = 5;
|
||||
case OPT_GC_GETSTATUS:
|
||||
cmd[0] = GC_GETSTATUS1;
|
||||
cmd[1] = GC_GETSTATUS2;
|
||||
cmd[2] = GC_GETSTATUS3(opt == OPT_GC_GETSTATUS_RUMBLE);
|
||||
n = gcn64lib_rawSiCommand(hdl, 0, cmd, 3, cmd, sizeof(cmd));
|
||||
if (n >= 0) {
|
||||
printf("GC Get status[%d]: ", n);
|
||||
printHexBuf(cmd, n);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_N64_GETCAPS:
|
||||
cmd[0] = RQ_GCN64_RAW_SI_COMMAND;
|
||||
cmd[1] = 0x01; // Length of SI command
|
||||
cmd[2] = N64_GET_CAPABILITIES; // N64 GET status
|
||||
cmdlen = 3;
|
||||
cmd[0] = N64_GET_CAPABILITIES;
|
||||
n = gcn64lib_rawSiCommand(hdl, 0, cmd, 1, cmd, sizeof(cmd));
|
||||
if (n >= 0) {
|
||||
printf("N64 Get caps[%d]: ", n);
|
||||
printHexBuf(cmd, n);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_N64_MEMPAK_DUMP:
|
||||
@ -282,7 +318,7 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd[0]) {
|
||||
if (do_exchange) {
|
||||
int i;
|
||||
n = gcn64_exchange(hdl, cmd, cmdlen, cmd, sizeof(cmd));
|
||||
if (n<0)
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include "gcn64.h"
|
||||
#include "gcn64lib.h"
|
||||
#include "mempak.h"
|
||||
#include "../gcn64_protocol.h"
|
||||
#include "../requests.h"
|
||||
@ -122,30 +123,42 @@ int mempak_writeBlock(gcn64_hdl_t hdl, unsigned short addr, unsigned char data[3
|
||||
int mempak_readBlock(gcn64_hdl_t hdl, unsigned short addr, unsigned char dst[32])
|
||||
{
|
||||
unsigned char cmd[64];
|
||||
int cmdlen;
|
||||
//int cmdlen;
|
||||
int n;
|
||||
uint16_t addr_crc;
|
||||
unsigned char crc;
|
||||
|
||||
addr_crc = __calc_address_crc(addr);
|
||||
|
||||
cmd[0] = N64_EXPANSION_READ;
|
||||
cmd[1] = addr_crc>>8; // Address high byte
|
||||
cmd[2] = addr_crc&0xff; // Address low byte
|
||||
|
||||
/*
|
||||
cmd[0] = RQ_GCN64_RAW_SI_COMMAND;
|
||||
cmd[1] = 3;
|
||||
cmd[2] = N64_EXPANSION_READ;
|
||||
cmd[3] = addr_crc>>8; // Address high byte
|
||||
cmd[4] = addr_crc&0xff; // Address low byte
|
||||
cmdlen = 5;
|
||||
|
||||
*/
|
||||
//printf("Addr 0x%04x with crc -> 0x%04x\n", addr, addr_crc);
|
||||
|
||||
n = gcn64_exchange(hdl, cmd, cmdlen, cmd, sizeof(cmd));
|
||||
if (n != 35)
|
||||
n = gcn64lib_rawSiCommand(hdl, 0, cmd, 3, cmd, sizeof(cmd));
|
||||
if (n != 33) {
|
||||
printf("Hey! %d\n", n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(dst, cmd + 2, 0x20);
|
||||
// n = gcn64_exchange(hdl, cmd, cmdlen, cmd, sizeof(cmd));
|
||||
// if (n != 35)
|
||||
// return -1;
|
||||
|
||||
//memcpy(dst, cmd + 2, 0x20);
|
||||
memcpy(dst, cmd, 0x20);
|
||||
|
||||
crc = __calc_data_crc(dst);
|
||||
if (crc != cmd[34]) {
|
||||
if (crc != cmd[32]) {
|
||||
fprintf(stderr, "Bad CRC reading address 0x%04x\n", addr);
|
||||
return -1;
|
||||
}
|
||||
@ -184,7 +197,7 @@ int mempak_readAll(gcn64_hdl_t hdl, unsigned char dstbuf[0x8000])
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mempak_dump(gcn64_hdl_t hdl)
|
||||
int mempak_dump(gcn64_hdl_t hdl)
|
||||
{
|
||||
unsigned char cardbuf[0x8000];
|
||||
int i,j;
|
||||
@ -193,7 +206,10 @@ void mempak_dump(gcn64_hdl_t hdl)
|
||||
mempak_init(hdl);
|
||||
|
||||
printf("Reading card...\n");
|
||||
mempak_readAll(hdl, cardbuf);
|
||||
i = mempak_readAll(hdl, cardbuf);
|
||||
if (i<0) {
|
||||
return i;
|
||||
}
|
||||
|
||||
for (i=0; i<DUMP_SIZE; i+=0x20) {
|
||||
printf("%04x: ", i);
|
||||
@ -207,6 +223,8 @@ void mempak_dump(gcn64_hdl_t hdl)
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define NUM_COPIES 4
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
void mempak_dump(gcn64_hdl_t hdl);
|
||||
int mempak_dump(gcn64_hdl_t hdl);
|
||||
int mempak_readBlock(gcn64_hdl_t hdl, unsigned short addr, unsigned char dst[32]);
|
||||
int mempak_dumpToFile(gcn64_hdl_t hdl, const char *out_filename);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user