Identity and evidence precedence
This is the Williams System 11B physical product released 1990. It covers the five-driver whirl_* clone tree: whirl_l3 (parent, US/Canadian production LA-3), whirl_l2 (LU-2 firmware revision), and whirl_g1/whirl_g2/whirl_g3 (German-localized LG-1/LG-2/LG-3 firmware revisions). All five share one static whirlGameData/init_whirl pair (input_ports_whirl aliases the shared input_ports_s11 table), so every driver is physically identical.
Evidence precedence for this definition: the retained known-working VPX script is runtime and mechanism-causality ground truth; the Williams operations manual controls physical construction, part numbers, wiring, and device presence; pinned PinMAME controls controller generation, public address topology, and per-game GI/bulb-type metadata; the retained VPX geometry supplies normalized coordinates. Unlike several prior games in this project, this manual carries a genuine OCR text layer, but every multi-column table used here was still read from 300 dpi rendered pages and transcribed by hand into external:pinmame-review-artifacts/whirlwind/manual-transcription.md -- the text layer interleaves columns badly and is never treated as authoritative for tabular data.
This is the first System 11 machine curated in this project, and it introduces controllers/pinmame/system-11.json, derived entirely from pinned PinMAME source (src/wpc/s11.c, s11.h, s11games.c, core.h) rather than by analogy with any WPC profile. Four structural facts do not carry over from WPC and must be re-learned for every future System 11 game:
- Switches and lamps share one sequential, column-major 1-64 address space with no dedicated-switch namespace. The base PinMAME driver registers
core_swSeq2m/core_m2swSeq (n+7, so column=((n-1)/8)+1, row=((n-1)%8)+1) for every generation that does not override it, and s11.c never overrides it (unlike wpc.c's wpc_sw2m, the familiar column-times-ten scheme). s11.c documents this in its own source comment: "S11 is 1-64, convert to 0-64 (+8), i.e. 1=8, 2=9...". Column 1 (public 1-8) is not a separate WPC-style dedicated/coin-door namespace -- it is ordinary matrix column 1, loaded from the shared S11_COMINPORT/S11_COMPORTS keyboard ports, and it reads through the identical core_getSw/core_setSw path as every other address.
- General illumination is not a separate channel. System 11 has no
coreGlobals.gi[] string abstraction at all (that field is WPC/Whitestar/SAM-only per core.h's own comment, and s11.c never touches it). GI is simply two ordinary solenoid addresses (11, 16 for Whirlwind) whose per-game bulb-type metadata (CORE_MODOUT_BULB_44_6_3V_AC_REV) happens to be continuous AC GI bulbs; the addresses are resolved from pinned PinMAME's own MACHINE_INIT(s11) per-game strncasecmp(gn,...) block, not from any fixed platform range. Two other System 11 games in the same driver file (Earthshaker, Big Guns) use three and two GI addresses respectively at entirely different numbers -- there is no fixed GI count or address range across the platform.
- No printed-flipper-address translation, because these flippers are not CPU-controlled at all. Whirlwind declares
FLIP_SWNO(58,57) with no FLIP_SOL bit. On real hardware the cabinet flipper button fires its coil directly through a relay/fuse circuit with zero CPU involvement -- the manual's own Switches parts list confirms this by listing the flipper buttons (SW-10A-48 left, SW-1010A-13 right) as unnumbered entries with no matrix address at all. PinMAME's public addresses 45-48 are purely synthetic: core_updateSw fabricates them from live switch 57/58 state for ball-physics purposes only, and no physical driver-board output exists behind them.
- The 8-solenoid A/C-relay multiplex is real hardware, not an emulator artifact. Solenoid 12 (A/C Select Relay) switches the solenoid B+ power bus between two circuits: de-energized, addresses 1-8 ("A"-side) fire their nominal devices (Outhole Kicker, Shooter Lane Feeder, etc.); energized, the same eight driver transistors fire a second bank of devices at addresses 25-32 ("C"-side, address = A-side + 24) -- for Whirlwind, eight backglass flasher circuits. This is documented explicitly in the manual's own Figure 4 and page-95 schematic as a deliberate "multiplexing" technique, one driver transistor controlling two separate solenoid circuits.
Addresses 17-22 are "special" solenoids, each fired from one PIA CA2/CB2 line; the PIA-to-public-address map is scrambled by silkscreen order (setSSSol's ssSolNo[0]={5,4,1,2,0,3} table) but resolves to a clean sequential 17-22 once un-scrambled, matching the manual's own numbering exactly. Addresses 37-41 are the Sound Overlay Solenoid Board, routed over a ribbon cable to a separate board; the manual's own board-local item numbers (23-27, "Snd O/L 1-5") are not the public address -- the offset (public = manual item + 14) is resolved by cross-referencing pinned PinMAME's own doc comment ("37-41 Sound overlay board") against the retained script's own SolCallback registrations, which directly confirm two of the five points (SolBackwallFan at 38 = manual item 24 "Blower Motor"; SolSpinWheelsMotor at 41 = manual item 27 "Spin Wheels Motor").
Address 23 (CORE_SSFLIPENSOL/S11_GAMEONSOL) is an emulator/ROM-internal "flipper and switched-solenoid enable" pulse with no physical driver-board output -- it is easy to confuse with the manual's own item 23 (a real device, "BP Lightning (L) Flashers", at the different public address 37) and the two must not be conflated.
Pinned PinMAME source disagreement, noted but not blocking
Pinned s11.c's per-game bulb-type declarations for Whirlwind (core_set_pwm_output_type calls naming PWM indices 40-42 as "Sound Overlay Board #1"/"#3&4") do not cleanly agree with core_getSol's own generic GEN_ALLS11 bit-formula for public 37-44, nor with the raw pia5cb2_w write path (which targets PWM indices 40-47). Rather than trust either of these secondary, mutually-inconsistent source comments, the address assignments above are resolved from the retained known-working script's own direct SolCallback registrations (decisive, since two of the five addresses are independently confirmed by name-matched physical function) plus the doc-comment's address count ("37-41", five addresses, matching the manual's own five Sound Overlay items exactly). This is a real internal inconsistency in the pinned driver worth flagging for any future contributor cross-referencing s11.c directly, but it does not affect this definition's own conclusions.
Ball paths: trough/outhole, cellar subway, and the three-position lock
A ball draining from the playfield lands in the outhole (switch 10) and is kicked into the trough proper by solenoid 1 (Outhole Kicker); up to three balls queue at trough positions 1-3 (switches 11-13), and solenoid 2 (Shooter Lane Feeder) ejects the lead ball through the BallRelease kicker into the shooter lane. None of these four switches has an individual VPX trigger object in the retained table -- the script's cvpmBallStack helper (bsTrough.InitSw 10,11,12,13) manages them abstractly against the single BallRelease exit kicker -- so they are documented projections onto the two real anchor objects that bound the mechanism (Kicker.Drain for the outhole, Kicker.BallRelease for the three trough positions) rather than invented coordinates.
A ball entering either cellar opening (switch 19 right, switch 20 left) travels a below-playfield subway and is returned to the playfield through the left cellar exit by solenoid 14 (Cellar Kickback, printed "Under P'fld Kickback" on the Solenoid Table and "Cellar Kickback" on the page-95 schematic -- the same device, confirmed by cross-reference).
The left ball lock (assembly B-13269) holds up to three balls sensed by switches 22 (lower), 23 (middle), and 24 (upper); solenoid 4 (Left Locking Kickback) releases the chain by firing Kicker3, then Kicker2 on its own hit event, then Kicker1, walking a ball down from the top position to the exit one kicker at a time.
The headline mechanism: three motorized spinning discs, no sensor
A single motor (Wheels Drive Assembly, p/n D-13199, solenoid 41 "Spin Wheels Motor") drives a shaft/pinion/gear train (72T/84T/115T gears) turning three playfield discs simultaneously. The retained script spins the middle disc opposite sense (+50) from the two outer discs (-50) and coasts the assembly down (SpinnerStep decays by 0.05/tick) rather than stopping instantly when the solenoid de-energizes. Two independent primary sources agree there is no position or ball-pass sensor of any kind: the manual's own Wheels Drive Assembly parts list names only mechanical parts (bracket, shaft, gears, motor, bearings) with no switch or opto part anywhere; and no Controller.Switch call anywhere in the retained script is associated with any of the three disc primitives or their cvpmTurntable collision-helper objects. This is a pure motorized obstacle, not a scored or sensed feature in itself.
The cabinet fan: sound and glow only, no geometry
Solenoid 38 ("Blower Motor", manual item 24, driven via the Sound Overlay board and a Triac board) is a fan mounted atop the backbox with no associated switch. The retained script's SolBackwallFan handler only toggles a backglass glow cue (FlSol38) and starts/stops a "Topper_Fan" sound effect; no fan mesh or primitive exists anywhere in the retained table's extraction. Cabinet-mounted, no playfield coordinate -- matching the expectation set before curation began.
Unresolved: backglass-vs-playfield flasher mounting (conflict.flasher-backglass-vs-playfield-mounting)
Eleven flasher solenoid addresses (the eight A/C-mux "C"-side flashers 25-32, plus three of the five Sound Overlay flashers, 37/39/40) are named by the manual after playfield features they light -- "R Ramp Top/Upr Jets Flashers", "BP Lightning (L) Flashers", and so on -- implying bulbs mounted on or near those features. The retained script implements every one of them purely as a backglass effect: each handler toggles the visibility of an FlSolNN Flasher object, and all eleven are confirmed members of the script's BGArr backglass-repositioning array with raw pos_y values far outside the playfield's 0-2162 bounds (e.g. FlSol25.pos_y = -902.14825). No playfield coordinate can be derived from this table for any of the eleven, and the definition does not guess either way -- their spatial keys are omitted, and the disagreement is recorded as a first-class, unresolved conflict rather than silently resolved in either source's favor.
General illumination
Solenoid 11 (Upper Playfield GI) and solenoid 16 (Lower Playfield / Backbox GI) are the machine's only two GI addresses, both confirmed by pinned PinMAME's own MACHINE_INIT block naming them exactly this way. The manual's GI relay-board page (printed 53) shows solenoid 16 energizing two physically separate relays simultaneously -- one on the playfield-side C-11902-1 board (lower playfield GI) and a second, separate C-11998-1 board in the backbox (backbox/backglass GI) -- while solenoid 11 drives only the single upper-playfield relay on the same C-11902-1 board. The retained script's SolLowerGI handler matches this exactly, driving both the LowerGI light collection (one member, Light1) and a near-full-table Flasher4 overlay together. Solenoid 11's own UpperGI light collection is empty in this retained table -- a completeness gap in this specific VPX author's work, not evidence the physical upper-playfield GI bank does not exist -- so its spatial key is omitted rather than invented, matching the precedent Star Trek: The Next Generation's unresolved lamps established.
Jet bumpers, slingshots, and the manual's duplicate "Top Lower Jet Bumper" label
Six jet bumpers split into two triangular clusters: an upper cluster near the top of the playfield (switches 49-51, solenoids 17/19/21) and a lower cluster nearer the cellar (switches 52-54, solenoids 9/15/10). The Solenoid Table prints an identical label, verbatim, "Top Lower Jet Bumper", for both solenoid 10 and solenoid 21 -- almost certainly a proofing duplication, since the two solenoids sit in different wiring banks (9/10/15 are "Controlled"; 17/19/21 are "Special #1/#3/#5") that mirror the Left/Right/third-position naming pattern the matching switch labels use ("Top Jets left/right/bot" for the upper cluster, "Btm Jets left/right/top" for the lower). By that structure, solenoid 10 is the "top" position of the lower cluster (matching switch 54/Bumper6), and solenoid 21 is resolved as the "bottom" position of the upper cluster (matching switch 51/Bumper3) -- the same physical bumper switch 51 senses, not a fourth, undocumented device. This is recorded as a resolved labeling anomaly, not an unresolved conflict, since the wiring-bank and switch-naming structure independently triangulate a single answer; the manual's verbatim duplicate text is preserved in the retained excerpt for anyone who wants to re-derive it.
Two slingshot kickers (BL/BR Kicker, switches 55/56, solenoids 18/20) use the standard paired kicker-actuating switch construction the switch-locations page's *** footnote describes.
Flippers: three physical, one repurposed opto pair, no CPU control
Three physical flipper assemblies exist: lower-left, lower-right, and upper-right (C-11626-L-3/C-11626-R-3 x2 per the Playfield Parts list) -- there is no upper-left flipper. The retained script's SolRFlipper handler rotates both RightFlipper (lower) and RightFlipper1 (upper) together from the single right-flipper coil/button, confirming the upper-right flipper is mechanically/scripted-slaved to the lower-right button rather than having an independent coil or button of its own.
Matrix addresses 57 (right) and 58 (left) are a genuinely separate circuit from the physical flipper buttons: an optotransistor pair on the Backbox Interconnect board that watches the same button mechanism purely so the ROM can read button state in software, used for the "Flipper Lane Change" feature the Switches parts list names them after. Pinned PinMAME's own FLIP_SWNO(58,57) declaration independently confirms this exact pair (left=58, right=57) is what the emulator treats as "the flipper button, as read by the CPU" -- consistent with, not contradicting, the parts list's more precise "R/L Flipper Lane Change" label. Both addresses are opto-constructed but pinned PinMAME declares no inverted-switch mask at all for whirl_l3, so their rest-state polarity is unconfirmed (see below).
Switch 2: A/C relay feedback, not "ball tilt"
Pinned PinMAME sets hw.gameSpecific1's S11_MUXSW2 flag for Whirlwind, which makes SWITCH_UPDATE(s11) unconditionally overwrite public switch 2 with the live state of the A/C Select Relay (solenoid 12) rather than whatever nominal meaning the shared S11_COMPORTS keyboard convention might otherwise suggest for that bit position. The manual's own label for switch 2, "C Power-A/C Relay", independently confirms this identity -- there is no conflict here, just a platform mechanism worth knowing before assuming a generic dedicated-switch label applies.
Unconfirmed opto polarity (coverage.missing: polarity)
Four drop-target switches (26-29, opto-sensed via the 1-Bank and 3-Bank Opto Boards) and the flipper-lane-change opto pair (57, 58) have confirmed opto construction from the switch-locations parts list (blank switch part number paired with an opto-board part number, or the explicit "Optotransistor" footnote), but this manual states no shading legend or "typically closed" wording anywhere the way several WPC-era manuals in this project have. Separately, pinned PinMAME declares no inverted-switch mask at all for whirl_l3 (wpc.invSw is entirely unset in whirlGameData's positional initializer), so the public state is never emulator-normalized for any switch on this driver. Resolving the true rest-state polarity of these six addresses needs either a LibPinMAME gameplay-harness trace against a legal whirl_l3 ROM, or a clearer copy/edition of the manual that does carry a shading legend.