Browse Source

Refactoring

pull/1/head
MickGyver 3 years ago
parent
commit
c098ddc905
  1. 163
      CD32ControllerUSB/CD32ControllerUSB.ino
  2. 145
      CD32ControllerUSB/Gamepad.cpp
  3. 80
      CD32ControllerUSB/Gamepad.h
  4. 28
      README.md
  5. 85
      SegaControllerUSB/Gamepad.cpp
  6. 27
      SegaControllerUSB/Gamepad.h
  7. 32
      SegaControllerUSB/README.md
  8. 3
      SegaControllerUSB/SegaControllerUSB.ino
  9. 0
      SegaControllerUSB/images/sega-usb-adapter-1.png
  10. BIN
      SegaControllerUSB/images/sega-usb-adapter-2.png
  11. 0
      SegaControllerUSB/images/sega-usb-adapter-3.png
  12. BIN
      SegaControllerUSB/images/sega-usb-adapter-4.png
  13. BIN
      SegaControllerUSB/images/sega-usb-adapter-parts.png
  14. BIN
      SegaControllerUSB/images/sega-usb-adapter-wiring.png
  15. BIN
      images/sega-usb-adapter-2.png
  16. BIN
      images/sega-usb-adapter-4.png
  17. BIN
      images/sega-usb-adapter-parts.png
  18. BIN
      images/sega-usb-adapter-wiring.png

163
CD32ControllerUSB/CD32ControllerUSB.ino

@ -0,0 +1,163 @@ @@ -0,0 +1,163 @@
/* DaemonBite CD32 to USB Adapter
* Author: Mikael Norrgård <mick@daemonbite.com>
*
* Copyright (c) 2020 Mikael Norrgård <http://daemonbite.com>
*
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#include "Gamepad.h"
enum Mode
{
TwoButton,
CD32
};
// Controller DB9 pins (looking face-on to the end of the plug):
//
// 5 4 3 2 1
// 9 8 7 6
//
// Wire it up according to the following table:
//
// DB9 Arduino Pro Micro
// --------------------------------------
// 1 TXO PD3
// 2 RXI PD2
// 3 3 PD0
// 4 4 PD4
// 5 A0 PF7
// 6 6 PD7
// 7 VCC
// 8 GND
// 9 A1 PF6
//
// Connect a slide switch to pins GND,GND and 2 (PD1)
// Set up USB HID gamepad
Gamepad_ Gamepad;
bool usbUpdate = false; // Should gamepad data be sent to USB?
// Controller
uint8_t axes = 0;
uint8_t axesPrev = 0;
uint8_t buttons = 0;
uint8_t buttonsPrev = 0;
Mode mode = CD32;
Mode modePrev = mode;
void setup()
{
// Setup switch pin (2, PD1)
DDRD &= ~B00000010; // input
PORTD |= B00000010; // high to enable internal pull-up
// Setup controller pins
DDRD &= ~B10011101; // inputs
PORTD |= B10011101; // high to enable internal pull-up
DDRF &= ~B11000000; // input
PORTF |= B11000000; // high to enable internal pull-up
}
void loop()
{
// Set mode from switch
(PIND & B00000010) ? mode = CD32 : mode = TwoButton;
// Read X and Y axes
axes = ~(PIND & B00011101);
switch(mode)
{
// Two button mode
case TwoButton:
buttons = ~( ((PIND & B10000000) >> 7) | ((PINF & B01000000) >> 5) | B11111100 );
break;
// CD32 button mode
case CD32:
// Set pin 6 (clock, PD7) and pin 5 (latch, PF7) as output low
PORTD &= ~B10000000; // low to disable internal pull-up (will become low when set as output)
DDRD |= B10000000; // output
PORTF &= ~B10000000; // low to disable internal pull-up (will become low when set as output)
DDRF |= B10000000; // output
delayMicroseconds(40);
// Clear buttons
buttons = 0;
// Read buttons
(PINF & B01000000) ? buttons &= ~B00000010 : buttons |= B00000010; // Blue (2)
sendClock();
(PINF & B01000000) ? buttons &= ~B00000001 : buttons |= B00000001; // Red (1)
sendClock();
(PINF & B01000000) ? buttons &= ~B00001000 : buttons |= B00001000; // Yellow (4)
sendClock();
(PINF & B01000000) ? buttons &= ~B00000100 : buttons |= B00000100; // Green (3)
sendClock();
(PINF & B01000000) ? buttons &= ~B00100000 : buttons |= B00100000; // RTrig (6)
sendClock();
(PINF & B01000000) ? buttons &= ~B00010000 : buttons |= B00010000; // LTrig (5)
sendClock();
(PINF & B01000000) ? buttons &= ~B01000000 : buttons |= B01000000; // Play (7)
// Set pin 5 (latch, PF7) and pin 6 (clock, PD7) as input with pull-ups
DDRF &= ~B10000000; // input
PORTF |= B10000000; // high to enable internal pull-up
DDRD &= ~B10000000; // input
PORTD |= B10000000; // high to enable internal pull-up
delayMicroseconds(40);
break;
}
// Has any buttons changed state?
if (buttons != buttonsPrev)
{
Gamepad._GamepadReport.buttons = buttons;
buttonsPrev = buttons;
usbUpdate = true;
}
// Has any axes changed state?
if (axes != axesPrev)
{
Gamepad._GamepadReport.Y = ((axes & B00000100) >> 2) - ((axes & B00001000) >> 3);
Gamepad._GamepadReport.X = ((axes & B00010000) >> 4) - (axes & B00000001);
axesPrev = axes;
usbUpdate = true;
}
if(usbUpdate)
{
Gamepad.send();
usbUpdate = false;
}
}
void sendClock()
{
// Send a clock pulse to pin 6 and wait
PORTD |= B10000000;
delayMicroseconds(10);
PORTD &= ~B10000000;
delayMicroseconds(40);
}

145
CD32ControllerUSB/Gamepad.cpp

@ -0,0 +1,145 @@ @@ -0,0 +1,145 @@
/* Gamepad.cpp
*
* Based on the advanced HID library for Arduino:
* https://github.com/NicoHood/HID
* Copyright (c) 2014-2015 NicoHood
*
* Copyright (c) 2020 Mikael Norrgård <http://daemonbite.com>
*
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "Gamepad.h"
static const uint8_t _hidReportDescriptor[] PROGMEM = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x04, // USAGE (Joystick) (Maybe change to gamepad? I don't think so but...)
0xa1, 0x01, // COLLECTION (Application)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x08, // USAGE_MAXIMUM (Button 8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x08, // REPORT_COUNT (8)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0xff, // LOGICAL_MINIMUM (-1)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x02, // REPORT_COUNT (2)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
};
Gamepad_::Gamepad_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1)
{
epType[0] = EP_TYPE_INTERRUPT_IN;
PluggableUSB().plug(this);
}
int Gamepad_::getInterface(uint8_t* interfaceCount)
{
*interfaceCount += 1; // uses 1
HIDDescriptor hidInterface = {
D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE),
D_HIDREPORT(sizeof(_hidReportDescriptor)),
D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01)
};
return USB_SendControl(0, &hidInterface, sizeof(hidInterface));
}
int Gamepad_::getDescriptor(USBSetup& setup)
{
// Check if this is a HID Class Descriptor request
if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; }
if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; }
// In a HID Class Descriptor wIndex cointains the interface number
if (setup.wIndex != pluggedInterface) { return 0; }
// Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol
// due to the USB specs, but Windows and Linux just assumes its in report mode.
protocol = HID_REPORT_PROTOCOL;
return USB_SendControl(TRANSFER_PGM, _hidReportDescriptor, sizeof(_hidReportDescriptor));
}
bool Gamepad_::setup(USBSetup& setup)
{
if (pluggedInterface != setup.wIndex) {
return false;
}
uint8_t request = setup.bRequest;
uint8_t requestType = setup.bmRequestType;
if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
{
if (request == HID_GET_REPORT) {
// TODO: HID_GetReport();
return true;
}
if (request == HID_GET_PROTOCOL) {
// TODO: Send8(protocol);
return true;
}
}
if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
{
if (request == HID_SET_PROTOCOL) {
protocol = setup.wValueL;
return true;
}
if (request == HID_SET_IDLE) {
idle = setup.wValueL;
return true;
}
if (request == HID_SET_REPORT)
{
}
}
return false;
}
void Gamepad_::reset()
{
_GamepadReport.X = 0;
_GamepadReport.Y = 0;
_GamepadReport.buttons = 0;
this->send();
}
void Gamepad_::send()
{
USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_GamepadReport, sizeof(GamepadReport));
}

80
CD32ControllerUSB/Gamepad.h

@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
/* Gamepad.h
*
* Based on the advanced HID library for Arduino:
* https://github.com/NicoHood/HID
* Copyright (c) 2014-2015 NicoHood
*
* Copyright (c) 2020 Mikael Norrgård <http://daemonbite.com>
*
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <Arduino.h>
#include "HID.h"
// NOTE: To make this work on the MiSTer (or possibly other Linux distros),
// you need to edit USBDesc.h like follows. Change:
// #define ISERIAL 3
// to
// #define ISERIAL 0
// The numbers after colon are bit fields, meaning how many bits the field uses.
// Remove those if there are problems
typedef struct {
union
{
struct {
bool b0: 1 ;
bool b1: 1 ;
bool b2: 1 ;
bool b3: 1 ;
bool b4: 1 ;
bool b5: 1 ;
bool b6: 1 ;
bool b7: 1 ;
};
uint8_t buttons;
};
int8_t X ;
int8_t Y ;
} GamepadReport;
class Gamepad_ : public PluggableUSBModule
{
private:
uint8_t reportId;
protected:
int getInterface(uint8_t* interfaceCount);
int getDescriptor(USBSetup& setup);
bool setup(USBSetup& setup);
uint8_t epType[1];
uint8_t protocol;
uint8_t idle;
public:
GamepadReport _GamepadReport;
Gamepad_(void);
void reset(void);
void send();
};

28
README.md

@ -1,31 +1,19 @@ @@ -1,31 +1,19 @@
# DaemonBite Sega Controller To USB Adapter
# DaemonBite Retro Controllers To USB Adapters
## Introduction
This is a simple to build adapter for connecting Mega Drive (Genesis), Master System (+ Atari and C= controllers) to USB. It supports 3 and 6-button Mega Drive controllers and 1 and 2-button SMS/Atari/C= controllers.
This is a collection of easy to build adapters for connecting Mega Drive/Genesis (3/6-button), Master System, Atari, Commodore, Amiga (incl. CD32) controllers to USB. Support for more controllers is on the way (NES, SNES, NeoGeo etc.).
The input lag for this adapter is minimal. Here is the result from a test with a 1ms polling rate on a MiSTer:
The input lag for these adapters is minimal. Here is the result of the Sega controller adapter from a test with a 1ms polling rate on a MiSTer:
| Controller | Samples | Average | Max | Min | Std Dev |
| ------ | ------ | ------ | ------ | ------ | ------ |
| Original 3-Button Mega Drive Controller | 2342 | 0.75ms | 1.28ms | 0.24ms | 0.29ms |
| 8bitdo M30 Wireless 2.4G | 2348 | 4.54ms | 8.05ms | 2.22ms | 1.31ms |
The Mega Drive gamepad interface is based on this repository : https://github.com/jonthysell/SegaController but almost entirely rewritten and a lot of optimisations have been made.
## Parts you need
- Arduino Pro Micro (ATMega32U4)
- Male end of Mega Drive controller extension (or DSUB 9Pin Male connector and some wires)
- Heat shrink tube (Ø ~20mm)
- Micro USB cable
## Wiring
![Assemble1](images/sega-usb-adapter-wiring.png)
## How to assemble (please ignore the switch)
![Assemble1](images/sega-usb-adapter-1.png)
![Assemble1](images/sega-usb-adapter-2.png)
(The switch goes to pins GND-GND-2 even if the picture above shows it connected to GND-2-3)
![Assemble1](images/sega-usb-adapter-3.png)
![Assemble1](images/sega-usb-adapter-4.png)
## How to build
See the README files in the subfolders for build instructions. All the adapters are build around the Arduino Pro Micro.
## License
This project is licensed under the GNU General Public License v3.0.
## Credits
The Mega Drive gamepad interface is based on this repository : https://github.com/jonthysell/SegaController but almost entirely rewritten and a lot of optimisations have been made.

85
SegaControllerUSB/Gamepad.cpp

@ -1,4 +1,8 @@ @@ -1,4 +1,8 @@
/* Gamepad.cpp
*
* Based on the advanced HID library for Arduino:
* https://github.com/NicoHood/HID
* Copyright (c) 2014-2015 NicoHood
*
* Copyright (c) 2020 Mikael Norrgård <http://daemonbite.com>
*
@ -20,13 +24,14 @@ @@ -20,13 +24,14 @@
*
*/
#pragma once
#include "Gamepad.h"
static const uint8_t _hidReportDescriptor[] PROGMEM = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x04, // USAGE (Joystick) (Maybe change to gamepad? I don't think so but...)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1) // change to 3 if using mouse and keyboard on 1&2
0x09, 0x04, // USAGE (Joystick) (Maybe change to gamepad? I don't think so but...)
0xa1, 0x01, // COLLECTION (Application)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
@ -54,22 +59,76 @@ static const uint8_t _hidReportDescriptor[] PROGMEM = { @@ -54,22 +59,76 @@ static const uint8_t _hidReportDescriptor[] PROGMEM = {
0xc0, // END_COLLECTION
};
Gamepad_::Gamepad_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1)
{
epType[0] = EP_TYPE_INTERRUPT_IN;
PluggableUSB().plug(this);
}
Gamepad_::Gamepad_(void)
{
reportId=1;
static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
HID().AppendDescriptor(&node);
int Gamepad_::getInterface(uint8_t* interfaceCount)
{
*interfaceCount += 1; // uses 1
HIDDescriptor hidInterface = {
D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE),
D_HIDREPORT(sizeof(_hidReportDescriptor)),
D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01)
};
return USB_SendControl(0, &hidInterface, sizeof(hidInterface));
}
void Gamepad_::begin(uint8_t id)
int Gamepad_::getDescriptor(USBSetup& setup)
{
reportId=id;
// Check if this is a HID Class Descriptor request
if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; }
if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; }
// In a HID Class Descriptor wIndex cointains the interface number
if (setup.wIndex != pluggedInterface) { return 0; }
// Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol
// due to the USB specs, but Windows and Linux just assumes its in report mode.
protocol = HID_REPORT_PROTOCOL;
return USB_SendControl(TRANSFER_PGM, _hidReportDescriptor, sizeof(_hidReportDescriptor));
}
void Gamepad_::end(void)
bool Gamepad_::setup(USBSetup& setup)
{
this->reset();
if (pluggedInterface != setup.wIndex) {
return false;
}
uint8_t request = setup.bRequest;
uint8_t requestType = setup.bmRequestType;
if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
{
if (request == HID_GET_REPORT) {
// TODO: HID_GetReport();
return true;
}
if (request == HID_GET_PROTOCOL) {
// TODO: Send8(protocol);
return true;
}
}
if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
{
if (request == HID_SET_PROTOCOL) {
protocol = setup.wValueL;
return true;
}
if (request == HID_SET_IDLE) {
idle = setup.wValueL;
return true;
}
if (request == HID_SET_REPORT)
{
}
}
return false;
}
void Gamepad_::reset()
@ -82,5 +141,5 @@ void Gamepad_::reset() @@ -82,5 +141,5 @@ void Gamepad_::reset()
void Gamepad_::send()
{
HID().SendReport(reportId,&_GamepadReport,sizeof(GamepadReport));
USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_GamepadReport, sizeof(GamepadReport));
}

27
SegaControllerUSB/Gamepad.h

@ -1,4 +1,8 @@ @@ -1,4 +1,8 @@
/* Gamepad.h
*
* Based on the advanced HID library for Arduino:
* https://github.com/NicoHood/HID
* Copyright (c) 2014-2015 NicoHood
*
* Copyright (c) 2020 Mikael Norrgård <http://daemonbite.com>
*
@ -20,8 +24,17 @@ @@ -20,8 +24,17 @@
*
*/
#pragma once
#include <Arduino.h>
#include "HID.h"
// NOTE: To make this work on the MiSTer (or possibly other Linux distros),
// you need to edit USBDesc.h like follows. Change:
// #define ISERIAL 3
// to
// #define ISERIAL 0
// The numbers after colon are bit fields, meaning how many bits the field uses.
// Remove those if there are problems
typedef struct {
@ -45,17 +58,23 @@ typedef struct { @@ -45,17 +58,23 @@ typedef struct {
} GamepadReport;
class Gamepad_
class Gamepad_ : public PluggableUSBModule
{
private:
uint8_t reportId;
protected:
int getInterface(uint8_t* interfaceCount);
int getDescriptor(USBSetup& setup);
bool setup(USBSetup& setup);
uint8_t epType[1];
uint8_t protocol;
uint8_t idle;
public:
GamepadReport _GamepadReport;
Gamepad_(void);
void begin(uint8_t id);
void end(void);
void reset(void);
void send();
};
extern Gamepad_ Gamepad;

32
SegaControllerUSB/README.md

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
# DaemonBite Sega Controller To USB Adapter
## Introduction
This is a simple to build adapter for connecting Mega Drive (Genesis), Master System (+ Atari and C= controllers) to USB. It supports 3 and 6-button Mega Drive controllers and 1 and 2-button SMS/Atari/C= controllers.
The input lag for this adapter is minimal. Here is the result from a test with a 1ms polling rate on a MiSTer:
| Controller | Samples | Average | Max | Min | Std Dev |
| ------ | ------ | ------ | ------ | ------ | ------ |
| Original 3-Button Mega Drive Controller | 2342 | 0.75ms | 1.28ms | 0.24ms | 0.29ms |
| 8bitdo M30 Wireless 2.4G | 2348 | 4.54ms | 8.05ms | 2.22ms | 1.31ms |
## Parts you need
- Arduino Pro Micro (ATMega32U4)
- Male end of Mega Drive controller extension (or DSUB 9Pin Male connector and some wires)
- Heat shrink tube (Ø ~20mm)
- Micro USB cable
## Wiring
![Assemble1](images/sega-usb-adapter-wiring.png)
## How to assemble (please ignore the switch)
![Assemble1](images/sega-usb-adapter-1.png)
![Assemble1](images/sega-usb-adapter-2.png)
(The switch goes to pins GND-GND-2 even if the picture above shows it connected to GND-2-3)
![Assemble1](images/sega-usb-adapter-3.png)
![Assemble1](images/sega-usb-adapter-4.png)
## License
This project is licensed under the GNU General Public License v3.0.
## Credits
The Mega Drive gamepad interface is based on this repository : https://github.com/jonthysell/SegaController but almost entirely rewritten and a lot of optimisations have been made.

3
SegaControllerUSB/SegaControllerUSB.ino

@ -52,8 +52,7 @@ word currentState = 0; @@ -52,8 +52,7 @@ word currentState = 0;
word lastState = 1;
void setup()
{
Gamepad.begin(1);
{
}
void loop()

0
images/sega-usb-adapter-1.png → SegaControllerUSB/images/sega-usb-adapter-1.png

Before

Width:  |  Height:  |  Size: 409 KiB

After

Width:  |  Height:  |  Size: 409 KiB

BIN
SegaControllerUSB/images/sega-usb-adapter-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 KiB

0
images/sega-usb-adapter-3.png → SegaControllerUSB/images/sega-usb-adapter-3.png

Before

Width:  |  Height:  |  Size: 357 KiB

After

Width:  |  Height:  |  Size: 357 KiB

BIN
SegaControllerUSB/images/sega-usb-adapter-4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

BIN
SegaControllerUSB/images/sega-usb-adapter-parts.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 KiB

BIN
SegaControllerUSB/images/sega-usb-adapter-wiring.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

BIN
images/sega-usb-adapter-2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 KiB

BIN
images/sega-usb-adapter-4.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 364 KiB

BIN
images/sega-usb-adapter-parts.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 447 KiB

BIN
images/sega-usb-adapter-wiring.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 KiB

Loading…
Cancel
Save