# game471 test mode This note describes the operator/test mode in the arcade `game471.exe` (4.74.00ENG). The structural and layout observations below come from the executable and its shipped resources, not from screenshots. ## Live entry The game exposes twenty logical cabinet inputs through `FUN_00634060` (`0x00634060`). Logical input 0 is the TEST switch. During normal operation, the main task at `FUN_006396f0` samples input 0 on every update. Holding it for at least three updates starts the test-mode transition. The game then: 1. stops the normal game/audio/render tasks; 2. waits 45 updates; 3. constructs the test-mode text renderer, sprite renderer, input adapter, SE adapter, and BGM adapter; 4. initializes the test-mode form system and opens the main form. The already generated `game471_bootskip.exe` can reach the original menu under Wine. Once the `GameWare` window is active, press and briefly hold Caps Lock. Caps Lock is the executable's built-in DirectInput fallback for the TEST switch; no test-mode-specific patch is needed. The original executable's keyboard fallback table starts at `0x007840f0`: | Logical input | Cabinet control | FAST I/O mask | DirectInput fallback | | --- | --- | ---: | --- | | 0 | Test switch | `0x00000040` | `DIK_CAPITAL` (Caps Lock) | | 1 | Service switch | `0x00000001` | `DIK_F1` | | 2 | Coin switch | `0x00000004` | `DIK_F2` | | 3 | Select switch | `0x00000010` | `DIK_F3` | | 4 | Enter switch | `0x00000020` | `DIK_RBRACKET` (`]`) | | 5 | Left booster up | `0x00000100` | `DIK_Q` | | 6 | Left booster down | `0x00000200` | `DIK_A` | | 7 | Left booster left | `0x00000400` | `DIK_LCONTROL` | | 8 | Left booster right | `0x00000800` | `DIK_S` | | 9 | Left booster button | `0x00100000` | `DIK_LMENU` (left Alt) | | 10..14 | Right booster controls | `0x00010000` through `0x00200000` | raw scan codes `78,7d,7a,7b,6a` | `FUN_00633d00` obtains the FAST I/O bitfield and masks it with the first table above. `FUN_00633de0` applies the per-input active-high/active-low table. `FUN_00634060` ORs that result with the DirectInput fallback. ## Test-mode input adapter `GWTestModeInput_GW` is constructed by `FUN_00569d00`. Its update method, `FUN_00569d20`, translates cabinet inputs to the generic test-mode flags: - Test switch -> `0x20` (back/exit) - Select switch -> `0x02` - Enter switch -> `0x58` - left booster up/down/left/right/button -> `0x01`, `0x02`, `0x84`, `0x48`, `0x10` The language table describes the intended behavior: - booster up/down or Select moves the cursor; - booster buttons or Enter confirms; - booster left/right or Enter changes a setting; - Test returns/backtracks. Short synthetic X11 key taps may be sampled for several game updates because the original runs uncapped. For automated navigation, inject an explicit cabinet state for one update instead of relying on `xdotool key`. ## Resources Test mode does not use the normal RVB/MTX menu assets. Its strings come from: - `data/TestModeLaungage/Laungage_eng_sjis.csv` - `data/TestModeLaungage/Laungage_jpn_sjis.csv` Both are CP932/Shift-JIS. `Laungage` is the spelling used by the shipped game. The glyphs themselves come from `data/font/Font.mtf` and the `data/font/FontXXXXXXXX.mfi` atlas pages. `GWTestModeRenderText_GW` constructs a pool of 256 regular GameWare text objects backed by that font. It does not use a test-mode-specific bitmap font or GDI text. `Font.mtf` starts with a 16-way Unicode radix table. A resolved entry stores the MFI page in its low 24 bits and the high nibble of the atlas cell in bits 28..31; the low cell nibble comes from the Unicode codepoint. Each MFI contains a 512x512 DXT5 atlas split into 16x16 cells. This is confirmed by `FUN_00485f90`, which creates GameWare image format 3, and by `GWPCImage2D::Create`, whose format table maps index 3 to `D3DFMT_DXT5`. The font shader uses the DXT5 alpha channel as glyph coverage. The English ASCII glyphs use page 0 and occupy the left half of each cell, producing 8x16 glyphs. The selection marker is U+2192 (`→`), resolved by the MTF to page 27, cell `0xb2`, and is 16x16. The renderer is a separate, mostly text-based framework represented by the following RTTI classes: - `GWTestModeWindowText`, `GWTestModeWindow`, `GWTestModeWindowList` - `GWTestModeForm`, `GWTestModeSelectForm` - `GWTestModeForm_YesNo`, `GWTestModeForm_ProcYesNo` - `GWTestModeInput_GW` - `GWTestModeRenderText_GW`, `GWTestModeRenderSprite_GW` - `GWTestModeBGM_GW`, `GWTestModeSE_GW` The framework screen is 720x1280 on black. `FUN_00577940` installs a logical text size of 16x16, pure red `(1,0,0,1)` for the selected/help color, and pure cyan `(0,1,1,1)` for normal selectable entries. The three centered common title windows use normalized y coordinates `-0.95`, `-0.925`, and `-0.9`, which map to pixel y positions 32, 48, and 64. The main list is anchored at normalized y `-0.725` (176 px). Its default row gap is `0.01` of the 640-pixel half-height, so rows advance by `16 + 6.4 = 22.4` pixels. The selected row is red and has a separately drawn `→`; unselected rows are cyan. The help form is centered at normalized y `0.2` (768 px), while the main five-line build/machine/time information list is centered at y `0.4` (896 px). ## Main menu in 4.74.00ENG The live build displays: 1. Monitor Test 2. Input/Output Test 3. LED Test 4. Card Test 5. Audio Settings 6. Game Settings 7. Network Info 8. Bookkeeping 9. System Info 10. Restore factory settings 11. Exit Test Mode The CSV also contains `Check Input Count`, `System Settings`, `Delete High Scores`, and `Machine Connection Test`, but prefixes those entries with `#`. It contains `Update Online` without `#`, although that item is still filtered out by this build's runtime conditions. ## Forms and data exposed - Monitor Test: color bars, white, red, green, blue, and cross-hatch patterns. - Input/Output Test: all cabinet switches, both five-input boosters, headphone volume/jack state, and Groove Stage connection. Booster buttons drive their lamps; the coin switch changes lockout. - LED Test: all lights and individual title, side, and booster light groups. - Card Test: card-reader status and card ID. - Audio Settings: test BGM, master/headphone/demo levels, five speaker channels, Groove Stage status, and normal/demo vibration intensity. - Game Settings: coin/song price, per-day operating hours, and score-attack mode. - Network Info: location identity/address/IP, cabinet IP/MAC, NESYS versions, and relay server. - Bookkeeping: uptime/play totals, free plays, service-switch count, player statistics, 30-week and hourly histograms, play logs, the last twenty errors, and service-switch history. - System Info: program/system configuration values. - Factory Settings: confirmation form followed by persistent-data reset. Persistent test-mode data has separate RTTI classes for system settings, high scores, play/weekly/daily/error/service-switch logs, and game-unique data. Log paths embedded in the executable live under `TestModeFile\...\Log`. ### Coin/song presets `CTestModeForm_GameSetting` chooses its coin/song table from the Type X `HKLM\SOFTWARE\taito\typex\Country` registry value. `Country == 0` uses eight entries, in this exact order: 1. 1 coin, 2 songs 2. 1 coin, 3 songs 3. 2 coins, 2 songs 4. 2 coins, 3 songs 5. Free play, 1 song 6. Free play, 2 songs 7. Free play, 3 songs 8. 1 coin, 1 song For a non-zero country value it instead exposes 39 entries: every combination of 1 through 12 coins with 1 through 3 songs, followed by the three free-play variants. `FUN_00570a70` and `FUN_00570810` wrap the selected index forward and backward respectively. OpenRoller mirrors the registry value with `Country` in `openroller.cfg` beside the executable. CMake creates the file on the first build but leaves an existing copy untouched. The value is reread whenever test mode is entered, so the application does not need to be rebuilt after changing it. ## Useful code addresses | Address | Role | | ---: | --- | | `0x006396f0` | top-level boot/game/test-mode state machine | | `0x00634060` | logical cabinet input + DirectInput fallback | | `0x00633d00` | mask current FAST I/O input bitfield | | `0x00633de0` | apply active-level table | | `0x00569d00` | construct `GWTestModeInput_GW` | | `0x00569d20` | translate game inputs to generic test-mode input flags | | `0x00569610` | construct `GWTestModeRenderText_GW` | | `0x00569ad0` | construct `GWTestModeRenderSprite_GW` | | `0x00569440` | construct `GWTestModeSE_GW` | | `0x005693f0` | construct `GWTestModeBGM_GW` | | `0x00577940` | initialize test-mode form/render state | | `0x00634fd0` | credit/service-credit handling and `SERVICE-SW LOCKED` | `SERVICE-SW LOCKED` is unrelated to entering test mode. It is emitted by the credit controller after repeated Service-switch credit pulses and holds the service-credit lock for 180 updates. ## LED output pipeline The LED test form's main methods are: | Address | Role | | ---: | --- | | `0x0056e160` | construct `CTestModeForm_LEDTest` | | `0x0056e390` | update the selected LED test pattern | | `0x0056e6c0` | handle the seven LED-test menu items | | `0x0062b0e0` | set logical LED `index` to `R,G,B,alpha` | | `0x0062d4d0` | construct all logical LED objects and their hardware mapping | | `0x0062a4d0` | update one `CLedDevice` and place its value in the cabinet output buffers | | `0x004b3b40` | write one RGB pixel into the shared board buffer | | `0x004b4c50` | pack shared LED buffers into the FIO transfer blocks | | `0x004b55f0` | exchange registers and transfer blocks with `iDmacDrv32` | | `0x004b6700` | wrapper for `iDmacDrvRegisterBufferWrite` | ### Logical groups There are 118 logical LED objects: | Logical indices | Test-mode group | Hardware coordinates | | ---: | --- | --- | | `0` | left booster button | simple output 4 | | `1..8` | left booster RGB group 8 | board 0, group 8, positions 0..7 | | `9..40` | left booster RGB groups 0..7 | board 0, groups 0..7, positions 0..3 | | `41` | right booster button | simple output 5 | | `42..49` | right booster RGB group 8 | board 1, group 8, positions 0..7 | | `50..81` | right booster RGB groups 0..7 | board 1, groups 0..7, positions 0..3 | | `82..93` | title | board 2, strips 0..1, pixels 0..5 | | `94..105` | left side | board 2, strips 2..3, pixels 0..5 | | `106..117` | right side | board 2, strips 4..5, pixels 0..5 | The menu implements the groups directly: - item 0 cycles all 118 LEDs through off, white, red, green, and blue; - items 1, 2, and 3 fill the twelve title/left/right-side LEDs white one address at a time, then clear them in the same order; - items 4 and 5 perform the same fill/clear sequence across 41 LEDs on the corresponding booster; - item 6 starts the form-exit sequence. The LED screen itself is only the generic seven-row `GWTestModeWindowList`, anchored at y `-0.725` with an explicit row gap of `0.05` (48 px row advance). It does not draw a schematic of the cabinet or booster rings. The all-light loop special-cases logical LEDs 0 and 41 because the booster button lamps are single-channel. For those two, it ORs `R|G|B` and writes the same intensity as a simple lamp. The executable establishes 40 independently controlled RGB positions plus one simple button lamp per booster. The `group/position` coordinates above describe the software/FIO mapping only; they do not establish the physical arrangement of those RGB positions inside the arcade booster's plastic assembly. ### Color representation `FUN_004b3b40(board, strip, pixel, R, G, B)` stores each full-color LED as three bytes in this order: ```text B, R, G ``` Each board reserves `9 * 8 * 3 = 0xd8` bytes even where fewer than eight pixels are connected. Before placing a value in the hardware buffer, `CLedDevice` applies the executable's integer gamma curve independently to each channel: ```text wire_channel = min(channel * channel / 255, 255) ``` The alpha/intensity field is applied by the LED object before this final conversion. Test mode always passes alpha `0xff`. ### iDmac/FIO transfers for board type 0x825c The current shim reports FIO type `0x825c`; the game selects its `0x25c` packing branch. Each hardware update eventually makes these calls: | Register-buffer address | Bytes | LED content | | ---: | ---: | --- | | `0x5000` | `0x1b0` | general FIO block; title bytes at offset `0x168`, button lamps at offsets 4 and 5 | | `0x5200` | `0x1e0` | general FIO block; left/right-side bytes at offset `0x168` | | `0x5400` | `0x0d8` | raw board-0 buffer: left booster | | `0x5600` | `0x0d8` | raw board-1 buffer: right booster | The board-2 source buffer is split as follows: - its first `0x30` bytes (two 8-pixel strip slots) go to `0x5000 + 0x168`; - its following `0x60` bytes (four 8-pixel strip slots) go to `0x5200 + 0x168`. The unused bytes in those strip slots remain zero. This was confirmed both in the decompiled `GWInputDeviceXioFio_BOOST` update path and in the live `idmac_shim.log`: normal steady-state writes have sizes `1b0`, `1e0`, `d8`, and `d8` respectively. Initial device negotiation first sends four `0x200` byte blocks, then switches to the exact steady-state lengths above. The game also contains a `0x23c` packing branch and generic transfer banks through `0x5e00`, but those are not selected by the current emulated hardware ID.