Details on the 3DO PBUS / Player Bus. This is the bus used to communicate with control pads, flight sticks, light guns, mice, and other peripherals.
Taken from the FZ-1 Technical Guide
From the patent: pages 21-23
Since the above described arrangement permits 448 bits to be
transferred per field and the minimum bit transfer per device is
8bits, a maximum of approximately 56 devices can be on the bus at
one time.Each of the player devices has an ID code embedded in its response
data. An ID code is mapped by software in the system to the number
of input and output bits for the device identified. Since the ID
code is embedded, it is received by the system 100 both at
initialization and when data is being read in under normal
operation. In this manner, it is possible to reconfigure the
system (add or delete devices) without re-initializing and without
adversely affecting those device already on the line.During an initialization sequence, a string of zeros is shifted
out from the system 100. A requirement for all of the player
devices is that they see a string of zeros either as an
initialization or don't cares.The first 4 bits of data stream received by the system 100 from
each device is that device's basic identification code (ID
code). The embedding of an ID code in the data stream functions as
follows for a joystick 15. The basic joystick 15 will have 8 bits
of data that are (inverted): down, up, right, left, switch-2,
switch-1, fire-2 and fire-1. Using the inability of the joystick
to indicate both up and down at the same time, the ID codes for a
basic joystick are 01QQ, 10QQ and 11QQ, where QQ is 01, 10 or
11. All other devices start with 00QQ. All joysticks are incapable
of generating 00 for their first 2 bits. With regard to the escape
function, the 1100 sequence indicates escape for the joystick. In
all other devices, the escape function is indicated by the bit
immediately following the 4 bit identification code. A string of
zeros indicate the end of input data into the system 100 device.
Bits (MSB → LSB) | Description |
---|---|
1bit | set, the high order bit from the ID (0x80) |
2bit | unused, unset, part of the joypad mask |
1bit | set if DPAD DOWN pressed |
1bit | set if DPAD UP pressed |
1bit | set if DPAD RIGHT pressed |
1bit | set if DPAD LEFT pressed |
1bit | set if A pressed |
1bit | set if B pressed |
1bit | set if C pressed |
1bit | set if P pressed |
1bit | set if X pressed |
1bit | set if RIGHT TRIGGER pressed |
1bit | set if LEFT RIGGER pressed |
2bit | unused? unset with normal joypad |
Bits (MSB → LSB) | Description |
---|---|
8bit | identifier 0 (0x01) |
8bit | identifier 1 (0x7B) |
8bit | length? (0x08) |
8bit | horizontal position |
2bit | unused? / unset |
8bit | vertical position |
2bit | unused? / unset |
8bit | depth position |
4bit | 0x2 (unsure meaning) |
1bit | set if TRIGGER / FIRE pressed |
1bit | set if A pressed |
1bit | set if B pressed |
1bit | set if C pressed |
1bit | set if DPAD UP pressed |
1bit | set if DPAD DOWN pressed |
1bit | set if DPAD RIGHT pressed |
1bit | set if DPAD LEFT pressed |
1bit | set if P pressed |
1bit | set if X pressed |
1bit | set if LEFT TRIGGER pressed |
1bit | set if RIGHT TRIGGER pressed |
4bit | unused? / unset |
Bits (MSB → LSB) | Description |
---|---|
8bit | identifier (0x49) |
1bit | set if LEFT BUTTON pressed |
1bit | set if MIDDLE BUTTON pressed |
1bit | set if RIGHT BUTTON pressed |
1bit | set if SHIFT BUTTON pressed |
10bit | x delta (signed) |
10bit | y delta (signed) |
According to the 3DO SDK's Examples/EventBroker/LightGun/lightgun.c:
DESCRIPTION OF LIGHTGUN HARDWARE -------------------------------- The lightgun is not capable of returning an (X, Y) position value when reporting events. It does report a counter value that returns the time it took between the beginning of a field (vertical blank) and when the scan-beam passes into the field of view of the light sensor in the lightgun. The X and Y value can be calculated from the timer value returned from the lightgun based on how long it takes to draw from the start of one scan line to the start of the scan line immediately below it (YSCANTIME) and how long it takes to draw from the first pixel to the last pixel on the same scan line (XSCANTIME). A third required value, is a time offset value that takes into consideration the time between the beginning of a field and when scan-beam begings drawing to the first pixel on the first scan line (TIMEOFFSET). #define NTSC_DEFAULT_XSCANTIME 1030 #define NTSC_DEFAULT_YSCANTIME 12707 #define NTSC_DEFAULT_TIMEOFFSET -12835 #define PAL_DEFAULT_XSCANTIME 1051 #define PAL_DEFAULT_YSCANTIME 12796 #define PAL_DEFAULT_TIMEOFFSET -58995 #define PAL_WIDTH 388 #define NTSC_WIDTH 320 x = ((((10 * counter) % NTSC_DEFAULT_YSCANTIME) * NTSC_WIDTH) / (NTSC_DEFAULT_XSCANTIME * 10)); y = ((10 * counter) / NTSC_DEFAULT_YSCANTIME);
From the 3DO SDK's Interfaces/2p5/includes/event.h:
- The "Lightgun" generic class and event structures are for the use of pods/devices which can't report X and Y positions, but only a time (counter value) between the beginning of field, and the time that the scan-beam passed into the field-of-view of the lightgun sensor. Some lightguns can also send in a "signal quality" pulse counter, this being the number of successive horizontal scan lines during which the beam was seen at roughly the same horizontal posotion. A line pulse count of 0 means "no hit". typedef struct LightGunEventData { uint32 lged_ButtonBits; /* left justified, zero fill */ uint32 lged_Counter; /* counter at top-center of hit */ uint32 lged_LinePulseCount; /* # of scan lines which were hit */ } LightGunEventData; #define LightGunTrigger 0x80000000
Bits (MSB → LSB) | Description |
---|---|
8bit | identifier (0x4D) |
1bit | set if TRIGGER pressed |
1bit | set if SERVICE pressed (arcade) |
1bit | set if COIN pressed (arcade) |
1bit | set if START pressed (arcade) |
1bit | set if HOLSTER (arcade) or OPTION (retail) pressed |
1bit | unused? / unset |
1bit | unused? / unset |
20bit | Counter: counter at top-center of hit |
5bit | LinePulseCount: number of scanlines which were hit |
Orbatak has two device types. The trackballs are the same as the regular mouse as described above.
The extra buttons needed for the coin slots, start buttons, and service button are provided by the “SILLY_CONTROL_PAD” as it's defined in the 3DO SDK (event.h).
Bits (MSB → LSB) | Description |
---|---|
8bit | identifier (0xC0) |
8bit | 0x00 / unset |
3bit | unused / unset |
1bit | set if COIN (P1) pressed |
1bit | set if COIN (P2) pressed |
1bit | set if START (P2) pressed |
1bit | set if START (P1) pressed |
1bit | set if SERVICE pressed |
8bit | 0x00 / unset |
The 3DO's Portfolio operating system has the ability to dynamically load drivers for peripherals. These “ROM” files, which appear to be AIF files of dynamically loadable code, can live on the filesystem or be sent over the PBUS by the device.
Details about PBUS devices can primarily be found in two locations:
Here is a list of known drivers:
Device | Device ID | Driver | Notes |
---|---|---|---|
Default | none | DefaultDriver.c | |
control pad | embedded into first byte | ControlPadDriver.c | |
analog stick | 0x01 | StickDriver.c and cport1.rom | Unsure about there being apparently a builtin and dynamically loaded driver. Unsure what the difference is between 0x01 device ID version and the 0x4C version. |
keyboard | 0x02 or 0x4B | KeyboardDriver.c | KeyboardDriver.c appears incomplete and non-functional. |
mouse | 0x49 | MouseDriver.c and cport49.rom | ROM can be found in numerous SDKs. |
stereoscopic glasses | 0x41 | cport41.rom | ROM can be found in numerous SDKs. |
lightgun | 0x4D | LightGunRom.c and cport4D.rom | ROM can be found in numerous SDKs. |
splitter | 0x56 | SplitterDriver.c | |
splitter 2 | 0x57 | ?? SplitterDriver.c | A different kind of splitter? Or a second splitter in the same device chain? |
ir receiver | 0x03 | cport3.rom | ROM only found in the "3DO Dev Tools" archive under “3DO_OS/net1p0d8/remote/System/Drivers/“ |