Repository navigation
v0.0.194
rePIU v0.0.194
이전 릴리스 v0.0.193 이후의 변경입니다(Tasks 751–754). Linux x64에서 디스크 이미지가 있는 16개 롬셋이
모두 실행되고, pumpit8의 노트가 음악과 어긋나 뒤로 돌아가던 증상이 사라졌습니다. 엔진이 게스트의 cli를
지키고, WSL에서 GPU로 그리며, 입력 기록을 핸들러의 복귀에서 끝내고, 타이머 tick이 오디오와 같은 시계를
따릅니다. 노트 증상은 사용자가 WSLg(wayland)에서 플레이로 확인했습니다.
숫자로 (WSL Linux x64 Release)
| v0.0.193 | v0.0.194 | |
|---|---|---|
| 60초를 완주하는 롬셋(디스크 이미지가 있는 16개 중) | 15 (pumpitpc가 5초에 죽음) | 16 |
| 시작 직후 tick 폭주(초당 18,000 tick, 프레임 0장) | 6회 중 2회 | 32회 중 0회 |
| pumpit8 선택 화면 fps | 36~42 | 60 |
| pumpit8·pumpitp2 마지막 20초 fps 중앙값 | 39 | 60 |
| pumpit8에서 게스트가 읽은 누름(입력 스크립트는 139회) | 1,389~2,406 | 139 |
| pumpit8 플레이의 tick 속도(오디오의 시계로, 240이어야 함) | 241~264 | 239.5~240.7 |
고친 것
게스트의 cli를 지킵니다 (Task 751) — user mode에서는 IF를 내릴 수 없어, 게임이 cli…sti로 감싼
구간 한가운데에도 타이머 tick이 주입됐습니다. pumpitpc는 보안 칩(CAT702) 통신 도중 핸들러가 보드의
레지스터를 바꿔 부팅 검사가 실패했습니다. 이제 cli가 세운 hold가 sti나 주입 프레임의 iret까지 주입을
미룹니다(100 ms 밸브). 주입의 규칙도 정리했습니다: 핸들러 반환 직후의 연쇄는 3개·주기 1 ms 이상, 중첩은 한
단계, 직전 핸들러가 쓴 시간만큼 인터럽트된 코드에 차례를 줍니다. 시작 직후의 tick 폭주가 이 규칙으로
사라졌습니다.
aam·aad 에뮬레이션 (Task 751) — long mode에 없는 명령입니다. pumpitpc가 첫 점수 표시에서 죽던
원인이었습니다.
페이서가 늦은 프레임을 한 주기 더 붙잡지 않습니다 (Task 752) — 재동기 조건이 이 프레임 자신의 마감과
비교하고 있어, 1 ms 늦은 프레임이 33 ms 프레임이 됐습니다. 이제 한 주기 넘게 늦었을 때만 재동기하고 늦은
프레임은 자지 않고 지나갑니다.
WSL에서 GPU로 그립니다 (Task 752) — WSL은 GPU를 Mesa의 D3D12 드라이버로만 내주는데 Mesa는 스스로
llvmpipe를 고릅니다. /dev/dxg와 d3d12_dri.so가 있고 사용자가 드라이버를 직접 고르지 않았으면 엔진이
GALLIUM_DRIVER=d3d12를 설정합니다.
입력 기록을 핸들러의 복귀에서 끝냅니다 (Task 753) — tick을 주입할 때 쌓는 입력 replay 프레임이 스택
비교로만 회수돼, 게스트가 다시 올라오지 않는 스택 높이에서 주입된 tick의 프레임이 끝까지 남았습니다. 그
뒤로 핸들러 밖의 읽기는 옛 시각의 키로 답을 받았습니다(SERVICE 누름을 초당 60회 읽음). 이제 핸들러의
iret에서 끝내고, 복귀를 볼 수 없는 Win32는 이후 64회 넘는 주입으로 회수합니다.
타이머 tick이 오디오의 시계를 따릅니다 (Task 754) — tick 스케줄만 SDL의 시계(Linux의
CLOCK_MONOTONIC_RAW)를 쓰고 오디오와 나머지는 CLOCK_MONOTONIC을 썼습니다. WSL2가 CLOCK_MONOTONIC을
1~7% 늦추는 동안 게스트의 시간이 음악보다 최대 9% 빨리 가서, 노트가 앞서 나갔다가 뒤로 돌아왔습니다. 이제
tick 스케줄과 입력 타임라인이 steady_clock을 따르고, 두 시계가 어긋나면 엔진이 알립니다.
새 스위치와 진단 (설정하지 않으면 기본 동작)
| 변수 / 출력 | 내용 |
|---|---|
REPIU_GUEST_CLI_HOLD=0 |
게스트 cli hold를 끔 |
guest cli hold cli/sti/blocked/expired/max-hold-us/held-at-end (최종 보고) |
hold의 횟수와 가장 긴 hold |
timer IRQ0 after-return …, timer IRQ0 nesting …, timer IRQ0 turn … (최종 보고) |
주입 규칙별로 미룬 횟수 |
REPIU_PIU10_CAT702_TRACE=1 |
CAT702 통신마다 [repiu-cat702] #N bits= in= out= |
[repiu-linexe] get-proc miss name=… |
Glide 이름 조회 실패 |
REPIU_WSL_D3D12=0 |
WSL에서 Mesa의 선택을 그대로 둠 |
[repiu-glide] GL renderer: …, Glide GL renderer/wsl-d3d12-chosen (최종 보고) |
무엇이 그리는지 |
REPIU_GLIDE_LONG_FRAME_LOG=2 |
모든 프레임을 sleep/guest/present로 찍음 |
REPIU_JAMMA_REPLAY_FRAME_END=0 |
입력 프레임을 복귀로 끝내지 않음(스택 비교와 나이만) |
REPIU_JAMMA_TIMELINE_TRACE=1 |
나이로 회수되는 입력 프레임마다 ESP와 주입 당시 EIP |
JAMMA timeline frames ended-by-return/retired-stale/latest-state-reads (최종 보고) |
입력 프레임이 회수된 경로 |
REPIU_EVENT_CLOCK=sdl |
tick 스케줄이 이전처럼 SDL의 시계를 따름 |
[repiu-clock] …, host clock raw-against-steady … (최종 보고) |
두 시계의 어긋남(1초 창, 0.5% 기준) |
scripts/survey_romsets.sh <binary> <tag> [seconds] [profile…] |
롬셋별 60초 실행 요약(build/survey/<tag>/summary.txt) |
scripts/input_scripts/pumpit8_play.txt, survey_generic.txt |
pumpit8을 곡까지 모는 입력, 조사용 공통 입력 |
알려진 것
- WSL에서 음악이 느려졌다 돌아옵니다. 이 머신의 WSL은
CLOCK_MONOTONIC을 실제 시간보다 1~7% 늦추고
있고(Windows 성능 카운터와 대조, 누가 늦추는지는 미확인), 오디오는 그 시계를 따라 소비됩니다. WSL을 다시
시작해도 남았습니다. 엔진 밖의 일로 보고 있으며 실기(실제 Linux 머신)에서의 확인이 후속 작업입니다.
노트와 음악은 서로 맞습니다. - WSL에서 잰 fps와 tick 속도는
CLOCK_MONOTONIC으로 잰 값이라, 시계가 늦춰진 동안에는 1~9% 높게 나옵니다.
최종 보고의host clock …줄을 먼저 보십시오. - Win32의 pumpitp3·pumpipx3가 간헐적으로
Fatal error: unable to find entry point in DLL.로 죽습니다.
CAT702 통신은 정상이고 원인은 미확정입니다. - 6개 프로필(pumpit2, pumpit3, pumpite, pumpitp3a, pumpipx3a, pumpipx3b)은 디스크 이미지(CHD)가 없어 실행할
수 없습니다. - INT 21h AH=08h(
getch)가 없습니다. 게임의 오류 화면 뒤에서만 닿습니다. - Win32는 게스트의
iret을 볼 수 없어 중첩·차례 규칙이 꺼져 있고, 입력 프레임은 나이로 회수됩니다(약
0.27초까지 옛 시각의 읽기가 남을 수 있음). Tasks 752~754는 Win32에서 빌드와 probe만 확인했습니다. - 예산 만료 뒤 teardown segfault는 그대로입니다. pumpit8 곡 선택에서 미리듣기 로드마다 게스트가 0.5초
멈춥니다. 플레이 중 present가 23~43 ms인 프레임이 가끔 있습니다(호스트 표시 쪽, 미조사). - Tasks 748~752의 입력 스크립트 실행은 Task 753의 결함 아래에서 돌았습니다(게스트가 받은 입력이 스크립트보다
많았음).
rePIU v0.0.194
Changes since the previous release, v0.0.193 (Tasks 751–754). On Linux x64 all 16 ROM sets that
have a disc image run, and pumpit8's arrows no longer part from the music and go back. The engine keeps
the guest's cli, draws with the GPU on WSL, ends an input record at its handler's return, and runs the
timer ticks on the clock the audio follows. The arrows were confirmed by the user in play on WSLg
(wayland).
In numbers (WSL Linux x64 Release)
| v0.0.193 | v0.0.194 | |
|---|---|---|
| ROM sets running their 60 s (of the 16 with a disc image) | 15 (pumpitpc died at 5 s) | 16 |
| Tick storms right after start (18,000 ticks a second, no frames) | 2 of 6 starts | 0 of 32 |
| pumpit8's selection screens, fps | 36–42 | 60 |
| Median fps over the last 20 s, pumpit8 and pumpitp2 | 39 | 60 |
| Presses the guest read in pumpit8 (the input script holds 139) | 1,389–2,406 | 139 |
| Tick rate in pumpit8's play (on the audio's clock; 240 expected) | 241–264 | 239.5–240.7 |
Fixed
The guest's cli is kept (Task 751) — user mode cannot clear IF, so timer ticks were injected even
in the middle of a section the game wrapped in cli…sti. In pumpitpc the handler changed a board
register in the middle of a transaction with the security chip (CAT702) and the boot check failed. A hold
raised by cli now defers injection until sti or the iret of an injected frame (with a 100 ms
valve). The rules of injection were set in order too: a chain right after a handler's return is at most
3 and at periods of 1 ms or more, nesting is one level deep, and the interrupted code gets a turn as long
as the last handler took. The tick storm right after start is gone with these rules.
aam and aad are emulated (Task 751) — long mode does not have them. They were why pumpitpc died
at its first score display.
The pacer no longer holds a late frame one period longer (Task 752) — its resynchronisation test
compared against the frame's own deadline, so a frame 1 ms late became a 33 ms frame. Only a frame more
than a period late resynchronises now, and a late frame passes without a sleep.
The GPU draws on WSL (Task 752) — WSL offers the GPU only through Mesa's D3D12 driver, and Mesa picks
llvmpipe by itself. With /dev/dxg and d3d12_dri.so present and no driver chosen by the user, the
engine sets GALLIUM_DRIVER=d3d12.
An input record ends at its handler's return (Task 753) — the input replay frame pushed when a tick
is injected was retired by a stack test alone, so the frame of a tick injected at a stack level the guest
does not come back to stayed to the end, and reads outside a handler were answered with the keys of an
old time (a SERVICE press read 60 times a second). A frame now ends at the handler's iret, and Win32,
which cannot see the return, retires it after more than 64 later injections.
Timer ticks follow the audio's clock (Task 754) — the tick schedule alone used SDL's clock
(CLOCK_MONOTONIC_RAW on Linux) while the audio and the rest used CLOCK_MONOTONIC. While WSL2 slowed
CLOCK_MONOTONIC by 1–7%, the guest's time ran up to 9% ahead of the music, so the arrows ran ahead and
came back. The tick schedule and the input timeline now follow steady_clock, and the engine says so
when the two clocks part.
New switches and diagnostics (default behaviour when unset)
| Variable / output | What it is |
|---|---|
REPIU_GUEST_CLI_HOLD=0 |
turns the guest cli hold off |
guest cli hold cli/sti/blocked/expired/max-hold-us/held-at-end (final report) |
the hold's counts and its longest |
timer IRQ0 after-return …, timer IRQ0 nesting …, timer IRQ0 turn … (final report) |
deferrals by injection rule |
REPIU_PIU10_CAT702_TRACE=1 |
[repiu-cat702] #N bits= in= out= per CAT702 transaction |
[repiu-linexe] get-proc miss name=… |
a Glide name lookup that failed |
REPIU_WSL_D3D12=0 |
leaves Mesa's choice alone on WSL |
[repiu-glide] GL renderer: …, Glide GL renderer/wsl-d3d12-chosen (final report) |
what draws |
REPIU_GLIDE_LONG_FRAME_LOG=2 |
every frame as sleep, guest and present |
REPIU_JAMMA_REPLAY_FRAME_END=0 |
input frames are not ended by return (stack test and age only) |
REPIU_JAMMA_TIMELINE_TRACE=1 |
the ESP and interrupted EIP of each input frame retired by age |
JAMMA timeline frames ended-by-return/retired-stale/latest-state-reads (final report) |
how input frames were retired |
REPIU_EVENT_CLOCK=sdl |
the tick schedule follows SDL's clock as before |
[repiu-clock] …, host clock raw-against-steady … (final report) |
the two clocks' divergence (windows of 1 s, 0.5% limit) |
scripts/survey_romsets.sh <binary> <tag> [seconds] [profile…] |
a 60 s run per ROM set, summarised in build/survey/<tag>/summary.txt |
scripts/input_scripts/pumpit8_play.txt, survey_generic.txt |
input that drives pumpit8 into a song; the survey's common input |
Known
- On WSL the music slows and comes back. This machine's WSL slows
CLOCK_MONOTONICby 1–7% against
real time (measured against the Windows performance counter; what slows it is not established), and
audio is consumed by that clock. It remained after WSL was restarted. It is taken to be outside the
engine, and checking on real hardware (an actual Linux machine) is the follow-up. Arrows and music
agree with each other. - Fps and tick rates measured on WSL are measured with
CLOCK_MONOTONICand read 1–9% high while that
clock is being slowed. Read the final report'shost clock …line first. - pumpitp3 and pumpipx3 on Win32 die intermittently with
Fatal error: unable to find entry point in DLL.Their CAT702 transactions are correct and the cause is not established. - Six profiles (pumpit2, pumpit3, pumpite, pumpitp3a, pumpipx3a, pumpipx3b) have no disc image (CHD) and
cannot be run. - INT 21h AH=08h (
getch) is absent. It is reached only behind a game's error screen. - Win32 cannot see the guest's
iret, so the nesting and turn rules are off there and input frames are
retired by age (reads at an old time can remain for about 0.27 s). Tasks 752–754 were checked on Win32
by build and probes only. - The teardown segfault after the budget remains. In pumpit8's song selection the guest stalls half a
second per preview load. Some frames in play present in 23–43 ms (the host's display side, not
investigated). - The scripted runs of Tasks 748–752 ran under Task 753's defect (the guest received more input than the
script held).