Site Tools


documentation:hardware:opera:pbus

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.

Pinout

Taken from the FZ-1 Technical Guide

Patent

Protocol

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.

Control Pad / Joypad

Bits (MSB → LSB)Description
1bitset, the high order bit from the ID (0x80)
2bitunused, unset, part of the joypad mask
1bitset if DPAD DOWN pressed
1bitset if DPAD UP pressed
1bitset if DPAD RIGHT pressed
1bitset if DPAD LEFT pressed
1bitset if A pressed
1bitset if B pressed
1bitset if C pressed
1bitset if P pressed
1bitset if X pressed
1bitset if RIGHT TRIGGER pressed
1bitset if LEFT RIGGER pressed
2bitunused? unset with normal joypad

Flightstick / Analog Controller

Bits (MSB → LSB)Description
8bitidentifier 0 (0x01)
8bitidentifier 1 (0x7B)
8bitlength? (0x08)
8bithorizontal position
2bitunused? / unset
8bitvertical position
2bitunused? / unset
8bitdepth position
4bit0x2 (unsure meaning)
1bitset if TRIGGER / FIRE pressed
1bitset if A pressed
1bitset if B pressed
1bitset if C pressed
1bitset if DPAD UP pressed
1bitset if DPAD DOWN pressed
1bitset if DPAD RIGHT pressed
1bitset if DPAD LEFT pressed
1bitset if P pressed
1bitset if X pressed
1bitset if LEFT TRIGGER pressed
1bitset if RIGHT TRIGGER pressed
4bitunused? / unset

Mouse

Bits (MSB → LSB)Description
8bitidentifier (0x49)
1bitset if LEFT BUTTON pressed
1bitset if MIDDLE BUTTON pressed
1bitset if RIGHT BUTTON pressed
1bitset if SHIFT BUTTON pressed
10bitx delta (signed)
10bity delta (signed)

Lightgun

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
8bitidentifier (0x4D)
1bitset if TRIGGER pressed
1bitset if SERVICE pressed (arcade)
1bitset if COIN pressed (arcade)
1bitset if START pressed (arcade)
1bitset if HOLSTER (arcade) or OPTION (retail) pressed
1bitunused? / unset
1bitunused? / unset
20bitCounter: counter at top-center of hit
5bitLinePulseCount: number of scanlines which were hit

Orbatak Trackball

Orbatak has two device types. The trackballs are the same as the regular mouse as described above.

Orbatak Coin / Start / Service

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
8bitidentifier (0xC0)
8bit0x00 / unset
3bitunused / unset
1bitset if COIN (P1) pressed
1bitset if COIN (P2) pressed
1bitset if START (P2) pressed
1bitset if START (P1) pressed
1bitset if SERVICE pressed
8bit0x00 / unset

Portfolio Drivers

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:

  • event.h : The header provided in the SDK for developers of the platform
  • portfolio_os/src/input : The core operating system code that manages the high level POD abstraction

Here is a list of known drivers:

DeviceDevice IDDriverNotes
DefaultnoneDefaultDriver.c
control padembedded into first byteControlPadDriver.c
analog stick0x01StickDriver.c and cport1.romUnsure about there being apparently a builtin and dynamically loaded driver. Unsure what the difference is between 0x01 device ID version and the 0x4C version.
keyboard0x02 or 0x4BKeyboardDriver.cKeyboardDriver.c appears incomplete and non-functional.
mouse0x49MouseDriver.c and cport49.romROM can be found in numerous SDKs.
stereoscopic glasses0x41cport41.romROM can be found in numerous SDKs.
lightgun0x4DLightGunRom.c and cport4D.romROM can be found in numerous SDKs.
splitter0x56SplitterDriver.c
splitter 20x57?? SplitterDriver.cA different kind of splitter? Or a second splitter in the same device chain?
ir receiver0x03cport3.romROM only found in the "3DO Dev Tools" archive under “3DO_OS/net1p0d8/remote/System/Drivers/“
documentation/hardware/opera/pbus.txt · Last modified: 2022/10/02 19:41 (external edit)