PinMAME reports logical active state on this platform. A consumer must not invert again. Whether a real switch is normally closed stays recorded per device as a physical fact, so a recreation can build the right hardware without changing what the emulator reports.
Address groups
Diagnostic buttons, switch matrix, and synthetic flipper-button positions
Public switches are sequential matrix positions, not column-times-ten notation: address = (column - 1) * 8 + row, so column 1 is 1-8 and column 6 is 41-48. by35.c strobes five columns from PIA0:A bits 0-4 and a sixth from PIA1:B, giving at most 48 matrix positions; a game that wires only five columns uses 1-40. Which PIA1:B bit supplies the sixth column is game-dependent: the default path reads bit 7, but drivers flagged BY35GD_SWVECTOR read bit 4 instead. Either way that bit is also one of the four continuous solenoid outputs published at 17-20, so on a six-column game one public solenoid address carries a switch strobe rather than a coil. Treat a continuously asserted address in that range as a candidate strobe and resolve it per game rather than assuming it is an unused coil. Self test, CPU diagnostic, and sound diagnostic are the direct addresses -7, -6, and -5, which live in switch column 0 and are not matrix positions. Games declaring FLIP_SW keep their real flipper buttons in the matrix, and PinMAME also maintains a generic flipper column at internal column 11 which VPinMAME publishes at 81-88; unless the driver supplies FLIP_SWNO, FLIP_SWL and FLIP_SWR are zero and core_updateSw never copies that column into the game matrix, so the ROM never reads 81-88. A definition declares only the columns and positions its own machine wires.
MPU option-switch banks S1-S32
pinmame.input.dip
DIP switch
Legal addresses
1 … 3232 slots
Transports
libpinmamechannel=dip
The MPU carries four eight-position option banks, S1-S8, S9-S16, S17-S24, and S25-S32; the fourth bank exists only on hardware variants flagged BY35HW_DIP4. Individual drivers may declare a larger MDRV_DIPS count than 32 to reserve room for emulator-side options, which does not add physical option switches.
Decoded momentary outputs, continuous outputs, and synthetic flipper outputs
The CPU writes a four-bit selector to PIA1:B bits 0-3 and by35.c sets bit (value) of the solenoid word, so public momentary address = selector + 1 and the public range is 1-15. Selector 15 is the idle state and is masked off, which is why there is no public address 16. PIA1:B bits 4-7 are the four continuous outputs, inverted in hardware and published at 17-20; src/lisy/lisy35.c, which drives real Bally hardware from this driver, identifies continuous bit 1 as the coin lockout and bit 2 as the flipper-enable relay, that is public 18 and 19. Not every continuous address is a coil: on six-column games one of them carries the sixth switch-column strobe, and lisy35.c masks that bit out of the coil data per game. Flipper coils are switched by the flipper-enable relay rather than by a driver-board output, so they have no momentary address; VPinMAME's generic flipper callbacks expose lower-right at 46 and lower-left at 48. A machine's printed Self Test number is the order in which the ROM's solenoid test pulses each coil and is not the public address; the two are unrelated and must be reconciled per game. The self test publishes the mapping directly because it flashes each coil's identification number on the player displays as it fires it, so a harness run resolves it without guessing.
Lamp driver module outputs and optional auxiliary lamp driver outputs
by35_lampStrobe ignores the decoder selector value 0x0f and advances two matrix columns per data bit. The skipped value is a selector, not a public address - public lamp 15 is perfectly addressable - and its effect is that each board contributes four runs of fifteen usable outputs, leaving public addresses 16, 32, 48, and 64 on the main board, and 80, 96, 112, and 128 on the auxiliary board, unreachable decoder slots rather than unused lamps. The AS-2518-23 lamp driver module therefore has sixty outputs at 1-15, 17-31, 33-47, and 49-63. A game whose core_tGameData declares a non-zero lampCol also strobes an auxiliary lamp driver board; PinMAME sizes the public lamp count as (8 + lampCol) * 8, so the auxiliary range grows with lampCol and only a game declaring lampCol = 8 reaches 127. The auxiliary rules below therefore bound the widest case; a definition for a lower-lampCol game must not declare addresses beyond its own (8 + lampCol) * 8 limit, and declaring auxiliary columns never asserts that a machine populates them. The public address a given strobe produces is exactly public = 16 * d + lampadr + 1 on the main board, where d is the lamp-data line index 0-3 and lampadr is the 0-14 decoder selector; the auxiliary board adds 64. That is the algebraic collapse of by35_lampStrobe's two branches and it is why the four data lines map onto the four fifteen-address runs.
Evidence
Reference
src/wpc/by35.c pia1b_w solenoid selector and continuous nibble, by35_lampStrobe column stride and skipped address, pia0b_r column strobe assembly; src/wpc/by35.h BY35_SWSELFTEST/BY35_SWCPUDIAG/BY35_SWSOUNDDIAG and BY35HW_DIP4; src/wpc/core.h CORE_SOLBIT, CORE_FLIPPERSWCOL, CORE_STDLAMPCOLS/CORE_CUSTLAMPCOL; src/wpc/core.c CORE_CUSTLAMPCOL lamp-column assertion and src/wpc/vpintf.c public lamp-count sizing; src/lisy/lisy35.c lisy35_solenoid_handler momentary and continuous coil identification
src/wpc/by35.c pia1b_w solenoid selector and continuous nibble, by35_lampStrobe column stride and skipped address, pia0b_r column strobe assembly; src/wpc/by35.h BY35_SWSELFTEST/BY35_SWCPUDIAG/BY35_SWSOUNDDIAG and BY35HW_DIP4; src/wpc/core.h CORE_SOLBIT, CORE_FLIPPERSWCOL, CORE_STDLAMPCOLS/CORE_CUSTLAMPCOL; src/wpc/core.c CORE_CUSTLAMPCOL lamp-column assertion and src/wpc/vpintf.c public lamp-count sizing; src/lisy/lisy35.c lisy35_solenoid_handler momentary and continuous coil identification
Address ranges, transports and normalisation rules live in one profile file. If PinMAME exposes a group this profile does not describe — or describes wrongly — the fix belongs there.
Cite a source for anything you change — a manual page, a line in a working VPX script, PinMAME source, or a reading from the machine's own service menu. Claims without provenance cannot be validated.