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 - + N64 Square joystick True True @@ -374,7 +374,7 @@ - + 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);