diff --git a/requests.h b/requests.h
index a5c51d5..a5cf59a 100644
--- a/requests.h
+++ b/requests.h
@@ -19,5 +19,11 @@
#define CFG_PARAM_POLL_INTERVAL2 0x12
#define CFG_PARAM_POLL_INTERVAL3 0x13
+#define CFG_PARAM_N64_SQUARE 0x20
+#define CFG_PARAM_GC_MAIN_SQUARE 0x21
+#define CFG_PARAM_GC_CSTICK_SQUARE 0x22
+#define CFG_PARAM_FULL_SLIDERS 0x23
+#define CFG_PARAM_INVERT_TRIG 0x24
+
#endif
diff --git a/tool/Makefile b/tool/Makefile
index d230887..aa18b2f 100644
--- a/tool/Makefile
+++ b/tool/Makefile
@@ -8,7 +8,7 @@ PREFIX=/usr/local
PROG=gcn64ctl
-OBJS=main.o gcn64.o mempak.o gcn64lib.o
+OBJS=main.o gcn64.o mempak.o gcn64lib.o hexdump.o
.PHONY : clean install
diff --git a/tool/gcn64ctl b/tool/gcn64ctl
index a0507a3..057c93a 100755
Binary files a/tool/gcn64ctl and b/tool/gcn64ctl differ
diff --git a/tool/gtk/gcn64cfg.glade b/tool/gtk/gcn64cfg.glade
index 67c2d84..6671d35 100644
--- a/tool/gtk/gcn64cfg.glade
+++ b/tool/gtk/gcn64cfg.glade
@@ -358,7 +358,7 @@
False
vertical
-
-
+
GC Square main stick
True
True
@@ -390,7 +390,7 @@
-
+
GC Square C-stick
True
True
@@ -406,7 +406,7 @@
-
+
GC Full range sliders
(non-centered)
True
@@ -423,7 +423,7 @@
-
+
GC Inverted triggers
True
True
diff --git a/tool/gtk/gcn64ctl_gui b/tool/gtk/gcn64ctl_gui
index ae57a93..5e17d76 100755
Binary files a/tool/gtk/gcn64ctl_gui and b/tool/gtk/gcn64ctl_gui differ
diff --git a/tool/gtk/main.c b/tool/gtk/main.c
index 347f1c8..ec9668a 100644
--- a/tool/gtk/main.c
+++ b/tool/gtk/main.c
@@ -42,6 +42,30 @@ G_MODULE_EXPORT void pollIntervalChanged(GtkWidget *win, gpointer data)
n = gcn64lib_setConfig(app->current_adapter_handle, CFG_PARAM_POLL_INTERVAL0, &buf, 1);
}
+
+G_MODULE_EXPORT void config_checkbox_changed(GtkWidget *win, gpointer data)
+{
+ struct application *app = data;
+ struct {
+ unsigned char cfg_param;
+ GtkCheckButton *chkbtn;
+ } configurable_bits[] = {
+ { CFG_PARAM_N64_SQUARE, GET_UI_ELEMENT(GtkCheckButton, chkbtn_n64_square) },
+ { CFG_PARAM_GC_MAIN_SQUARE, GET_UI_ELEMENT(GtkCheckButton, chkbtn_gc_main_square) },
+ { CFG_PARAM_GC_CSTICK_SQUARE, GET_UI_ELEMENT(GtkCheckButton, chkbtn_gc_cstick_square) },
+ { CFG_PARAM_FULL_SLIDERS, GET_UI_ELEMENT(GtkCheckButton, chkbtn_gc_full_sliders) },
+ { CFG_PARAM_INVERT_TRIG, GET_UI_ELEMENT(GtkCheckButton, chkbtn_gc_invert_trig) },
+ { },
+ };
+ int i;
+ unsigned char buf;
+
+ for (i=0; configurable_bits[i].chkbtn; i++) {
+ buf = gtk_toggle_button_get_active(configurable_bits[i].chkbtn);
+ gcn64lib_setConfig(app->current_adapter_handle, configurable_bits[i], &buf, 1);
+ }
+}
+
G_MODULE_EXPORT void onMainWindowShow(GtkWidget *win, gpointer data)
{
int res;
@@ -133,6 +157,8 @@ G_MODULE_EXPORT void resume_polling(GtkButton *button, gpointer data)
gcn64lib_suspendPolling(app->current_adapter_handle, 0);
}
+
+
int
main( int argc,
char **argv )
diff --git a/tool/hexdump.c b/tool/hexdump.c
new file mode 100644
index 0000000..1d1a14d
--- /dev/null
+++ b/tool/hexdump.c
@@ -0,0 +1,13 @@
+#include
+
+void printHexBuf(unsigned char *buf, int n)
+{
+ int i;
+
+ for (i=0; i
#include
+#include "hexdump.h"
#include "version.h"
#include "gcn64.h"
#include "gcn64lib.h"
@@ -60,16 +61,7 @@ static void printUsage(void)
printf(" --gc_getstatus_rumble Read GC controller status now (turns rumble ON)\n");
printf(" --n64_getcaps Get N64 controller capabilities (or status such as pak present)\n");
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
#include
#include
+#include "hexdump.h"
#include "gcn64.h"
#include "gcn64lib.h"
#include "mempak.h"
@@ -104,20 +105,19 @@ int mempak_writeBlock(gcn64_hdl_t hdl, unsigned short addr, unsigned char data[3
addr_crc = __calc_address_crc(addr);
- 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
- memcpy(cmd + 5, data, 0x20);
+ cmd[0] = N64_EXPANSION_WRITE;
+ cmd[1] = addr_crc>>8; // Address high byte
+ cmd[2] = addr_crc&0xff; // Address low byte
+ memcpy(cmd + 3, data, 0x20);
+ cmdlen = 3 + 0x20;
- cmdlen = 5 + 0x20;
-
- n = gcn64_exchange(hdl, cmd, cmdlen, cmd, sizeof(cmd));
- if (n != 35)
+ n = gcn64lib_rawSiCommand(hdl, 0, cmd, cmdlen, cmd, sizeof(cmd));
+ if (n != 1) {
+ printf("write block returned != 1 (%d)\n", n);
return -1;
+ }
- return 0x20;
+ return cmd[0];
}
int mempak_readBlock(gcn64_hdl_t hdl, unsigned short addr, unsigned char dst[32])
@@ -134,16 +134,6 @@ int mempak_readBlock(gcn64_hdl_t hdl, unsigned short addr, unsigned char dst[32]
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 = gcn64lib_rawSiCommand(hdl, 0, cmd, 3, cmd, sizeof(cmd));
if (n != 33) {
printf("Hey! %d\n", n);
@@ -169,16 +159,57 @@ int mempak_readBlock(gcn64_hdl_t hdl, unsigned short addr, unsigned char dst[32]
int mempak_init(gcn64_hdl_t hdl)
{
unsigned char buf[0x20];
+ int res;
memset(buf, 0xfe, 32);
- mempak_writeBlock(hdl, 0x8000, buf);
- memset(buf, 0x80, 32);
- mempak_writeBlock(hdl, 0x8000, buf);
+ res = mempak_writeBlock(hdl, 0x8001, buf);
+
+ if (res == 0xe1) {
+ return 0;
+ }
+
+ return -1;
+}
+
+#define DUMP_SIZE 0x8000
+
+int mempak_writeAll(gcn64_hdl_t hdl, unsigned char srcbuf[0x8000])
+{
+ unsigned short addr;
+ unsigned char readback[0x20];
+ int res;
+
+ for (addr = 0x0000; addr < DUMP_SIZE; addr+= 0x20)
+ {
+ printf("Writing address 0x%04x / 0x8000\r", addr); fflush(stdout);
+ res = mempak_writeBlock(hdl, addr, &srcbuf[addr]);
+ if (res < 0) {
+ fprintf(stderr, "Write error\n");
+ return -1;
+ }
+
+ printf("\nwrite returned:0x %02x\n", res);
+ printHexBuf(&srcbuf[addr], res);
+
+
+ if (0x20 != mempak_readBlock(hdl, addr, readback)) {
+ fprintf(stderr, "readback failed\n");
+ return -2;
+ }
+
+ printf("Wrote: ");
+ printHexBuf(&srcbuf[addr], 0x20);
+
+ printf("Read: ");
+ printHexBuf(readback, 0x20);
+
+ break;
+ }
+ printf("\nDone!\n");
return 0;
}
-#define DUMP_SIZE 0x8000
int mempak_readAll(gcn64_hdl_t hdl, unsigned char dstbuf[0x8000])
{
@@ -236,7 +267,7 @@ int mempak_dumpToFile(gcn64_hdl_t hdl, const char *out_filename)
int copies;
printf("Init pak\n");
- mempak_init(hdl);
+// mempak_init(hdl);
printf("Reading card...\n");
mempak_readAll(hdl, cardbuf);
@@ -261,3 +292,59 @@ int mempak_dumpToFile(gcn64_hdl_t hdl, const char *out_filename)
return 0;
}
+int mempak_writeFromFile(gcn64_hdl_t hdl, const char *in_filename)
+{
+ unsigned char cardbuf[0x8000];
+ FILE *fptr;
+ long file_size;
+ int i;
+ int num_images = -1;
+ long offset = 0;
+
+ fptr = fopen(in_filename, "rb");
+ if (!fptr) {
+ perror("fopen");
+ return -1;
+ }
+
+ fseek(fptr, 0, SEEK_END);
+ file_size = ftell(fptr);
+ fseek(fptr, 0, SEEK_SET);
+
+ printf("File size: %ld bytes\n", file_size);
+
+ /* Raw binary images. Those can contain more than one card's data. For
+ * instance, Mupen64 seems to contain four saves. */
+ for (i=0; i<4; i++) {
+ if (file_size == 0x8000*i) {
+ num_images = i+1;
+ printf("MPK file Contains %d image(s)\n", num_images);
+ }
+ }
+
+ if (num_images < 0) {
+ char header[11];
+ char *magic = "123-456-STD";
+ /* If the size is not a fixed multiple, it could be a .N64 file */
+ fread(header, 11, 1, fptr);
+ if (0 == memcmp(header, magic, sizeof(header))) {
+ printf(".N64 file detected\n");
+ // TODO : Extract comments and other info. from the header
+ offset = 0x1040; // Thanks to N-Rage`s Dinput8 Plugin sources
+ }
+ }
+
+ fseek(fptr, offset, SEEK_SET);
+ fread(cardbuf, sizeof(cardbuf), 1, fptr);
+ fclose(fptr);
+
+
+ printf("Init pak\n");
+ mempak_init(hdl);
+ printf("Writing card...\n");
+ mempak_writeAll(hdl, cardbuf);
+
+ return 0;
+}
+
+
diff --git a/tool/mempak.h b/tool/mempak.h
index 93cd5ff..d311a1f 100644
--- a/tool/mempak.h
+++ b/tool/mempak.h
@@ -2,5 +2,5 @@
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);
-
+int mempak_writeFromFile(gcn64_hdl_t hdl, const char *in_filename);