From 2444e7699bcb6a8bd62c6998d607ed04aa4ba45f Mon Sep 17 00:00:00 2001 From: Raphael Assenat Date: Fri, 21 Aug 2015 00:16:34 -0400 Subject: [PATCH] Add gamecube support (and rework makefiles) --- Makefile | 2 +- Makefile.inc | 1 + Makefile.stk525 | 10 +-- gamecube.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++ gamecube.h | 7 ++ 5 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 Makefile.inc create mode 100644 gamecube.c create mode 100644 gamecube.h diff --git a/Makefile b/Makefile index ee487cc..4c9fd9f 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=16000000L -Os -DUART1_STDOUT LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map HEXFILE=$(PROGNAME).hex -OBJS=main.o usbpad.o n64.o gcn64_protocol.o usart1.o usb.o bootloader.o +include Makefile.inc all: $(HEXFILE) diff --git a/Makefile.inc b/Makefile.inc new file mode 100644 index 0000000..f0d1dcc --- /dev/null +++ b/Makefile.inc @@ -0,0 +1 @@ +OBJS=main.o usb.o usbpad.o gcn64_protocol.o n64.o gamecube.o usart1.o bootloader.o diff --git a/Makefile.stk525 b/Makefile.stk525 index f1ed842..22ed794 100644 --- a/Makefile.stk525 +++ b/Makefile.stk525 @@ -9,13 +9,10 @@ CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=16000000L -Os -DUART1_STDOUT -DSTK525 LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map HEXFILE=$(PROGNAME).hex -OBJS=main.o usbpad.o n64.o gcn64_protocol.o usart1.o usb.o bootloader.o +include Makefile.inc all: $(HEXFILE) -clean: - rm -f $(PROGNAME).elf $(PROGNAME).hex $(PROGNAME).map $(OBJS) - main.o: main.c reportdesc.c dataHidReport.c $(CC) $(CFLAGS) -c $< -o $@ @@ -31,10 +28,13 @@ main.o: main.c reportdesc.c dataHidReport.c $(PROGNAME).elf: $(OBJS) $(LD) $(OBJS) $(LDFLAGS) -o $(PROGNAME).elf -$(PROGNAME).hex: $(PROGNAME).elf +$(HEXFILE): $(PROGNAME).elf avr-objcopy -j .data -j .text -O ihex $(PROGNAME).elf $(PROGNAME).hex avr-size $(PROGNAME).elf +clean: + rm -f $(PROGNAME).elf $(PROGNAME).hex $(PROGNAME).map $(OBJS) + fuse: flash: $(HEXFILE) diff --git a/gamecube.c b/gamecube.c new file mode 100644 index 0000000..c0a99f5 --- /dev/null +++ b/gamecube.c @@ -0,0 +1,200 @@ +/* Extenmote : NES, SNES, N64 and Gamecube to Wii remote adapter firmware + * Copyright (C) 2012 Raphael Assenat + * + * Based on: + * + * GC to N64 : Gamecube controller to N64 adapter firmware + * Copyright (C) 2011 Raphael Assenat + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include +#include +#include "gamepads.h" +#include "gamecube.h" +#include "gcn64_protocol.h" + +/*********** prototypes *************/ +static void gamecubeInit(void); +static char gamecubeUpdate(void); +static char gamecubeChanged(void); + +/* What was most recently read from the controller */ +static gamepad_data last_built_report; + +/* What was most recently sent to the host */ +static gamepad_data last_sent_report; + +static char origins_set = 0; +static unsigned char orig_x, orig_y, orig_cx, orig_cy; + +static void gamecubeInit(void) +{ + gamecubeUpdate(); +} + +void gc_decodeAnswer() +{ + unsigned char x,y,cx,cy; + + // Note: Checking seems a good idea, adds protection + // against corruption (if the "constant" bits are invalid, + // maybe others are : Drop the packet). + // + // However, I have seen bit 2 in a high state. To be as compatible + // as possible, I decided NOT to look at these bits since instead + // of being "constant" bits they might have a meaning I don't know. + + // Check the always 0 and always 1 bits +#if 0 + if (gcn64_workbuf[0] || gcn64_workbuf[1] || gcn64_workbuf[2]) + return 1; + + if (!gcn64_workbuf[8]) + return 1; +#endif + +/* + (Source: Nintendo Gamecube Controller Protocol + updated 8th March 2004, by James.) + + Bit Function + 0-2 Always 0 << RAPH: Not true, I see 001! + 3 Start + 4 Y + 5 X + 6 B + 7 A + 8 Always 1 + 9 L + 10 R + 11 Z + 12-15 Up,Down,Right,Left + 16-23 Joy X + 24-31 Joy Y + 32-39 C Joystick X + 40-47 C Joystick Y + 48-55 Left Btn Val + 56-63 Right Btn Val + */ + + last_built_report.pad_type = PAD_TYPE_GAMECUBE; + last_built_report.gc.buttons = gcn64_protocol_getByte(0) | gcn64_protocol_getByte(8); + x = gcn64_protocol_getByte(16); + y = gcn64_protocol_getByte(24); + cx = gcn64_protocol_getByte(32); + cy = gcn64_protocol_getByte(40); + last_built_report.gc.lt = gcn64_protocol_getByte(48); + last_built_report.gc.rt = gcn64_protocol_getByte(56); + gcn64_protocol_getBytes(0, 8, last_built_report.gc.raw_data); + + if (origins_set) { + last_built_report.gc.x = ((int)x-(int)orig_x); + last_built_report.gc.y = ((int)y-(int)orig_y); + last_built_report.gc.cx = ((int)cx-(int)orig_cx); + last_built_report.gc.cy = ((int)cy-(int)orig_cy); + } else { + orig_x = x; + orig_y = y; + orig_cx = cx; + orig_cy = cy; + last_built_report.gc.x = 0; + last_built_report.gc.y = 0; + last_built_report.gc.cx = 0; + last_built_report.gc.cy = 0; + origins_set = 1; + } +} + + +static char gamecubeUpdate() +{ + //unsigned char tmp=0; + unsigned char tmpdata[8]; + unsigned char count; + +#if 0 + /* The GetID command. This is required for the Nintendo Wavebird to work... */ + tmp = GC_GETID; + count = gcn64_transaction(&tmp, 1); + if (count != GC_GETID_REPLY_LENGTH) { + return 1; + } + + /* + * The wavebird needs time. It does not answer the + * folowwing get status command if we don't wait here. + * + * A good 2:1 safety margin has been chosen. + * + */ + // 10 : does not work + // 20 : does not work + // 25 : works + // 30 : works + _delay_us(50); +#endif + + tmpdata[0] = GC_GETSTATUS1; + tmpdata[1] = GC_GETSTATUS2; + tmpdata[2] = GC_GETSTATUS3(0); + + count = gcn64_transaction(tmpdata, 3); + if (count != GC_GETSTATUS_REPLY_LENGTH) { + return 1; + } + + gc_decodeAnswer(); + + return 0; +} + + +static char gamecubeProbe(void) +{ + origins_set = 0; + + if (gamecubeUpdate()) { + return 0; + } + + return 1; +} + +static char gamecubeChanged(void) +{ + return memcmp(&last_built_report, &last_sent_report, sizeof(gamepad_data)); +} + +static void gamecubeGetReport(gamepad_data *dst) +{ + if (dst) + memcpy(dst, &last_built_report, sizeof(gamepad_data)); +} + +Gamepad GamecubeGamepad = { + .init = gamecubeInit, + .update = gamecubeUpdate, + .changed = gamecubeChanged, + .getReport = gamecubeGetReport, + .probe = gamecubeProbe, +}; + +Gamepad *gamecubeGetGamepad(void) +{ + return &GamecubeGamepad; +} + diff --git a/gamecube.h b/gamecube.h new file mode 100644 index 0000000..d699288 --- /dev/null +++ b/gamecube.h @@ -0,0 +1,7 @@ +#include "gamepads.h" + +#define GAMECUBE_UPDATE_NORMAL 0 +#define GAMECUBE_UPDATE_ORIGIN 1 + +Gamepad *gamecubeGetGamepad(void); +