From cf8e5a7bc0db616adf3c3327218559066aace799 Mon Sep 17 00:00:00 2001 From: Akeraiotitasoft Date: Fri, 24 Mar 2023 22:10:29 -0700 Subject: [PATCH 1/2] compiler options --- .gitignore | 1 + Makefile.atmega168 | 3 ++- Makefile.atmega328p | 63 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 Makefile.atmega328p diff --git a/.gitignore b/.gitignore index 5249613..7f27c27 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.vs *.elf *.o *.map diff --git a/Makefile.atmega168 b/Makefile.atmega168 index af7cd3b..ef2b2e9 100644 --- a/Makefile.atmega168 +++ b/Makefile.atmega168 @@ -4,8 +4,9 @@ LD=$(CC) PROGNAME=atmega168_extenmote OBJDIR=objs-$(PROGNAME) -CPU=atmega168a +CPU=atmega168 CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=12000000L -Os -DWITH_SNES -DWITH_N64 -DWITH_GAMECUBE -DWITH_EEPROM -DWITH_DB9 +#CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=12000000L -Os -DWITH_SNES -DWITH_EEPROM LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map HEXFILE=$(PROGNAME).hex AVRDUDE=avrdude -p m168 -P usb -c avrispmkII diff --git a/Makefile.atmega328p b/Makefile.atmega328p new file mode 100644 index 0000000..e1fc545 --- /dev/null +++ b/Makefile.atmega328p @@ -0,0 +1,63 @@ +CC=avr-gcc +AS=$(CC) +LD=$(CC) + +PROGNAME=atmega328p_extenmote +OBJDIR=objs-$(PROGNAME) +CPU=atmega328p +CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=16000000L -Os -DWITH_SNES -DWITH_N64 -DWITH_GAMECUBE -DWITH_EEPROM -DWITH_DB9 +LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map +HEXFILE=$(PROGNAME).hex +AVRDUDE=avrdude -p m328p -P com5 -c avrisp -b 19200 + +# - - - - - BOOTSZ1 BOOTSZ0 BOOTRST +# 0 0 0 0 0 0 0 1 +# 1 1 1 1 1 0 0 1 +#EFUSE=0x01 +EFUSE=0xF9 + +# RSTDISBL DWEN SPIEN WDTON EESAVE BODLEVEL2 BODLEVEL1 BODLEVEL0 +# 1 1 0 1 1 1 1 1 +HFUSE=0xdf +# +# CKDIV8 CKOUT SUT1 SUT0 CKSEL3 CKSEL2 CKSEL1 CKSEL0 +# 1 1 0 1 1 1 1 1 +# +# 8mhz internal RC oscillator (Ok for NES/SNES only mode) +LFUSE=0xDF + +OBJS=$(addprefix $(OBJDIR)/, main.o wiimote.o snes.o rlut.o n64.o gcn64_protocol.o gamecube.o eeprom.o classic.o analog.o tripleclick.o db9.o) + +all: $(HEXFILE) + +clean: + rm -f $(PROGNAME).elf $(PROGNAME).hex $(PROGNAME).map $(OBJS) + +$(OBJDIR)/%.o: %.S + $(CC) $(CFLAGS) -c $< -o $@ + +$(OBJDIR)/%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(OBJDIR)/%.o: %.c %.h + $(CC) $(CFLAGS) -c $< -o $@ + +$(PROGNAME).elf: $(OBJS) + $(LD) $(OBJS) $(LDFLAGS) -o $(PROGNAME).elf + +$(PROGNAME).hex: $(PROGNAME).elf + avr-objcopy -j .data -j .text -O ihex $(PROGNAME).elf $(PROGNAME).hex + avr-size $(PROGNAME).elf + +fuse: + $(AVRDUDE) -e -Uefuse:w:$(EFUSE):m -Uhfuse:w:$(HFUSE):m -Ulfuse:w:$(LFUSE):m -B 20.0 -v + +flash: $(HEXFILE) + $(AVRDUDE) -Uflash:w:$(HEXFILE) -B 1.0 -F + +chip_erase: + $(AVRDUDE) -e -B 1.0 -F + +reset: + $(AVRDUDE) -B 1.0 -F + From 2c02649529a24cb5f2b375c56121e044c0195359 Mon Sep 17 00:00:00 2001 From: Akeraiotitasoft Date: Mon, 8 May 2023 12:40:44 -0700 Subject: [PATCH 2/2] Mouse and Gun support - experimental --- classic.c | 27 ++++++++++++ gamepads.h | 36 +++++++++++++++ main.c | 28 ++++++++++-- snes.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 208 insertions(+), 8 deletions(-) diff --git a/classic.c b/classic.c index 3e8c23a..6abdbe9 100644 --- a/classic.c +++ b/classic.c @@ -13,6 +13,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * Changes pertaining to SNES Mouse and NES lightgun Copyright (C) 2023 Akerasoft + * The author may be contacted at robert.kolski@akerasoft.com */ #include @@ -55,6 +58,10 @@ * 'G' | 'C' Gamecube controller * 'S' | 'F' SNES * 'F' | 'C' NES + * (C) Akerasoft 2023 -- BEGIN -- + * 'G' | 'N' NES Lightgun / Zapper + * 'M' | 'S' SNES Mouse + * (C) Akerasoft 2023 -- END -- * * Writing at byte 6 might one day control the rumble motor. Rumbles on when non-zero. */ @@ -289,6 +296,26 @@ void dataToClassic(const gamepad_data *src, classic_pad_data *dst, char first_re } break; +// (C) Akerasoft 2023 -- BEGIN -- + case PAD_TYPE_MOUSE: + dst->controller_id[0] = 'M'; + dst->controller_id[1] = 'S'; + memcpy(dst->controller_raw_data, src->snes.raw_data, MOUSE_RAW_SIZE); + + if (src->snes.buttons & MOUSE_BTN_L) { dst->buttons |= CPAD_BTN_X; } + if (src->snes.buttons & MOUSE_BTN_R) { dst->buttons |= CPAD_BTN_A; } + break; + + case PAD_TYPE_GUN: + dst->controller_id[0] = 'G'; + dst->controller_id[1] = 'N'; + memcpy(dst->controller_raw_data, src->gun.raw_data, GUN_RAW_SIZE); + + if (src->snes.buttons & GUN_BTN_TRIGGER) { dst->buttons |= CPAD_BTN_B; } + if (src->snes.buttons & GUN_BTN_SENSOR) { dst->buttons |= CPAD_BTN_A; } + break; +// (C) Akerasoft 2023 -- END -- + case PAD_TYPE_NES: // if (first_read && src->nes.buttons & NES_BTN_START) { // disable_config = 1; diff --git a/gamepads.h b/gamepads.h index bbf3b93..3b49f3e 100644 --- a/gamepads.h +++ b/gamepads.h @@ -13,6 +13,10 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * Changes pertaining to SNES Mouse and NES lightgun Copyright (C) 2023 Akerasoft + * The author may be contacted at robert.kolski@akerasoft.com + * */ #ifndef _gamepad_h__ #define _gamepad_h__ @@ -25,9 +29,17 @@ #define PAD_TYPE_GAMECUBE 5 #define PAD_TYPE_MD 6 #define PAD_TYPE_SMS 7 +// (C) Akerasoft 2023 -- BEGIN -- +#define PAD_TYPE_GUN 8 +#define PAD_TYPE_MOUSE 9 +// (C) Akerasoft 2023 -- END -- #define NES_RAW_SIZE 1 #define SNES_RAW_SIZE 2 +// (C) Akerasoft 2023 -- BEGIN -- +#define MOUSE_RAW_SIZE 4 +#define GUN_RAW_SIZE 1 +// (C) Akerasoft 2023 -- END -- #define N64_RAW_SIZE 4 #define GC_RAW_SIZE 8 #define DB9_RAW_SIZE 2 @@ -90,6 +102,26 @@ typedef struct _snes_pad_data { #define SNES_BTN_L 0x2000 #define SNES_BTN_R 0x1000 +// (C) Akerasoft 2023 -- BEGIN -- +typedef struct _mouse_pad_data { + unsigned char pad_type; // PAD_TYPE_MOUSE + unsigned short buttons; + unsigned char raw_data[MOUSE_RAW_SIZE]; +} mouse_pad_data; + +#define MOUSE_BTN_R 0x8000 +#define MOUSE_BTN_L 0x4000 +#define MOUSE_SENSITIVITY 0x3000 + +typedef struct _gun_pad_data { + unsigned char pad_type; // PAD_TYPE_GUN + unsigned short buttons; + unsigned char raw_data[GUN_RAW_SIZE]; +} gun_pad_data; + +#define GUN_BTN_TRIGGER 0x0080 +#define GUN_BTN_SENSOR 0x0040 +// (C) Akerasoft 2023 -- END -- typedef struct _nes_pad_data { unsigned char pad_type; // PAD_TYPE_NES @@ -190,6 +222,10 @@ typedef struct _gamepad_data { unsigned char pad_type; // PAD_TYPE_* classic_pad_data classic; snes_pad_data snes; +// (C) Akerasoft 2023 -- BEGIN -- + mouse_pad_data mouse; + gun_pad_data gun; +// (C) Akerasoft 2023 -- END -- nes_pad_data nes; n64_pad_data n64; gc_pad_data gc; diff --git a/main.c b/main.c index bc4c86c..56e4e73 100644 --- a/main.c +++ b/main.c @@ -13,6 +13,10 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * Changes pertaining to SNES Mouse and NES lightgun Copyright (C) 2023 Akerasoft + * The author may be contacted at robert.kolski@akerasoft.com + * */ #include @@ -66,14 +70,20 @@ static void hwInit(void) /* PORTD * 0: out0 * 1: out0 - * 2: out0 - * 3: out0 +// (C) Akerasoft 2023 - proposal PORT D2 and D3 are for NES Zapper. When no other controller found +// use NES Zapper / lightgun in the SNES.c file. + * 2: in + * 3: in +// (C) Akerasoft 2023 - END * 4: out1 // Tied to VCC on Multiuse PCB2 for routing reasons * 5: out0 * 6: in-pu // Pulled to GND on mutluse db9 v3. Wired to VCC on multiuse PCB2. * 7: out0 */ - PORTD = 0x60; +// (C) Akerasoft 2023 - proposal PORT D2 and D3 are for NES Zapper. + PORTD = 0x6C; +// (C) Akerasoft 2023 - END + DDRD = 0xbf; _delay_ms(1); @@ -393,6 +403,18 @@ int main(void) memcpy(raw, lastReadData.nes.raw_data, sizeof(lastReadData.nes.raw_data)); wm_newaction(raw, sizeof(lastReadData.nes.raw_data)); break; + +// (C) Akerasoft 2023 - BEGIN + case PAD_TYPE_GUN: + memcpy(raw, lastReadData.gun.raw_data, sizeof(lastReadData.gun.raw_data)); + wm_newaction(raw, sizeof(lastReadData.gun.raw_data)); + break; + + case PAD_TYPE_MOUSE: + memcpy(raw, lastReadData.mouse.raw_data, sizeof(lastReadData.mouse.raw_data)); + wm_newaction(raw, sizeof(lastReadData.mouse.raw_data)); + break; +// (C) Akerasoft 2023 - END } // TODO : Controller specific report format diff --git a/snes.c b/snes.c index 2b3000e..d20ff4c 100644 --- a/snes.c +++ b/snes.c @@ -21,6 +21,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * The author may be contacted at raph@raphnet.net + * + * Changes pertaining to SNES Mouse and NES lightgun Copyright (C) 2023 Akerasoft + * The author may be contacted at robert.kolski@akerasoft.com */ #include #include @@ -30,7 +33,14 @@ #include "gamepads.h" #include "snes.h" -#define GAMEPAD_BYTES 2 +// (C) Akerasoft 2023 -- BEGIN -- +// to support the mouse it has to be 4 bytes +// 1 byte for NES +// 1 byte for GUN +// 2 bytes for SNES +// 4 bytes for Mouse +#define GAMEPAD_BYTES 4 +// (C) Akerasoft 2023 -- END -- /******** IO port definitions **************/ #define SNES_LATCH_DDR DDRC @@ -65,6 +75,10 @@ static unsigned char last_read_controller_bytes[GAMEPAD_BYTES]; static unsigned char last_reported_controller_bytes[GAMEPAD_BYTES]; static char nes_mode = 0; +// (C) Akerasoft 2023 -- BEGIN -- +static char gun_mode = 0; +static char mouse_mode = 0; +// (C) Akerasoft 2023 -- END -- static char snesInit(void) { @@ -115,7 +129,35 @@ static char snesInit(void) 13 none (always high) 14 none (always high) 15 none (always high) - 16 none (always high) + + +// (C) Akerasoft 2023 -- BEGIN -- +// Though this information came from: +// https://www.repairfaq.org/REPAIR/F_SNES.html +// So Rafael Assenat is the copyright holder anyway for this section + + 16 none (always high) (SNES controller present) + + 16 low - mouse present + 17 Y direction (0=up, 1=down) + 18 Y motion bit 6 + 19 Y motion bit 5 + 20 Y motion bit 4 + 21 Y motion bit 3 + 22 Y motion bit 2 + 23 Y motion bit 1 + 24 Y motion bit 0 + 25 X direction (0=left, 1=right) + 26 X motion bit 6 + 27 X motion bit 5 + 28 X motion bit 4 + 29 X motion bit 3 + 30 X motion bit 2 + 31 X motion bit 1 + 32 X motion bit 0 + +// (C) Akerasoft 2023 -- END -- + * */ @@ -124,6 +166,15 @@ static char snesUpdate(void) int i; unsigned char tmp=0; +// (C) Akerasoft 2023 -- BEGIN -- + if (gun_mode) + { + tmp = (PIND & 0x0C) << 4; + last_read_controller_bytes[0] = tmp; + return 0; + } +// (C) Akerasoft 2023 -- END -- + SNES_LATCH_HIGH(); _delay_us(12); SNES_LATCH_LOW(); @@ -154,6 +205,34 @@ static char snesUpdate(void) SNES_CLOCK_HIGH(); } last_read_controller_bytes[1] = tmp; +// (C) Akerasoft 2023 -- BEGIN -- + for (i=0; i<8; i++) + { + _delay_us(6); + + SNES_CLOCK_LOW(); + + tmp <<= 1; + if (!SNES_GET_DATA()) { tmp |= 0x01; } + + _delay_us(6); + SNES_CLOCK_HIGH(); + } + last_read_controller_bytes[2] = tmp; + for (i=0; i<8; i++) + { + _delay_us(6); + + SNES_CLOCK_LOW(); + + tmp <<= 1; + if (!SNES_GET_DATA()) { tmp |= 0x01; } + + _delay_us(6); + SNES_CLOCK_HIGH(); + } + last_read_controller_bytes[3] = tmp; +// (C) Akerasoft 2023 -- END -- return 0; } @@ -166,23 +245,45 @@ static char snesChanged(void) static void snesGetReport(gamepad_data *dst) { - unsigned char h, l; + unsigned char h, l, d2, d3; if (dst != NULL) { l = last_read_controller_bytes[0]; h = last_read_controller_bytes[1]; - +// (C) Akerasoft 2023 -- BEGIN -- + d2 = last_read_controller_bytes[2]; + d3 = last_read_controller_bytes[3]; +// (C) Akerasoft 2023 -- END -- // The 4 last bits are always high if an SNES controller // is connected. With a NES controller, they are low. // (High on the wire is a 0 here due to the snesUpdate() implementation) // - if ((h & 0x0f) == 0x0f) { + +// (C) Akerasoft 2023 -- BEGIN -- + // The 3 just before last bits are high for the SNES mouse + // but the very last bit in byte 2 is low. So 0x1 is the expected value here + if (l == 0x00 && h == 0x00 && d2 == 0x00 && d3 == 0x00) + { + gun_mode = 1; + nes_mode = 0; + mouse_mode = 0; + } else if ((h & 0x0f) == 0x0f) { nes_mode = 1; + gun_mode = 0; + mouse_mode = 0; + } else if ((h & 0x0f) == 0x01) { + mouse_mode = 1; + gun_mode = 0; + nes_mode = 0; } else { + // SNES Controller nes_mode = 0; + mouse_mode = 0; + gun_mode = 0; } +// (C) Akerasoft 2023 -- END -- if (nes_mode) { // Nes controllers send the data in this order: @@ -190,6 +291,20 @@ static void snesGetReport(gamepad_data *dst) dst->nes.pad_type = PAD_TYPE_NES; dst->nes.buttons = l; dst->nes.raw_data[0] = l; +// (C) Akerasoft 2023 -- BEGIN -- + } else if (mouse_mode) { + dst->mouse.pad_type = PAD_TYPE_MOUSE; + dst->mouse.buttons = l; + dst->mouse.buttons |= h<<8; + dst->mouse.raw_data[0] = l; + dst->mouse.raw_data[1] = h; + dst->mouse.raw_data[2] = d2; + dst->mouse.raw_data[3] = d3; + } else if (gun_mode) { + dst->gun.pad_type = PAD_TYPE_GUN; + dst->gun.buttons = l; + dst->gun.raw_data[0] = l; +// (C) Akerasoft 2023 -- END -- } else { dst->nes.pad_type = PAD_TYPE_SNES; dst->snes.buttons = l;