Mechanic · input & timing · rhythm
Timing window
The span of time around a note in which a rhythm game takes a press as on time, and how it grades presses inside and outside it.
On this page
A timing window is how far from the beat a press can land and still count. PaRappa the Rapper 2 doesn’t measure the distance to a note. It sorts each press into a slot of a grid fixed to the beat: a press in a scoring run counts, and one in the gap between runs costs, so 16 of every 24 ticks1 take a press1.
- Beat gridPaRappa the Rapper 2 (2001). Each press falls in a 4-tick slot of a 96-tick cycle, a beat at the computed tempo scale; runs from 4 ticks before to 11 after each quarter beat score, and the 8-tick gaps between them cost.1
Games
| Game | Year | How | Note |
|---|---|---|---|
| PaRappa the Rapper 2 | 2001 | Beat grid | each press falls in a 4-tick slot of a 96-tick cycle, a beat at the computed tempo scale; runs from 4 ticks before to 11 after each quarter beat score, and the 8-tick gaps between them cost |
Every claim about this mechanic, by game (1)
References
- ^ abcIn the July 12th NTSC-J prototype of PaRappa the Rapper 2, a press is judged by which slot of a fixed grid it lands in, not by its distance from the teacher's note. The line clock converts a vsync count to ticks as count × 96 ×
tempo/ 3600, so with 60 vsyncs a second andtempoin beats per minute a beat is 96 ticks (computed). Each press is stored with its time less the line's start time (ofs_frame);on_th_makeadds that start modulo 96, plus 96, and divides by 4, which puts the press in the 4-tick slot of its own time modulo 96 (computed).thnum_getreads the slot in a 24-bit pattern that repeats every beat and numbers its runs of equal bits, so a press in a run of 1s gets an eventh_numand a press in a run of 0s an odd one. For the main grid (CK_TH_NORMAL, 0x00e79e79) the 1s cover ticks 92 to 11, 20 to 35, 44 to 59, and 68 to 83 of each beat, that is from 4 ticks before to 11 ticks after each multiple of 24 (a quarter of the beat), and the 0s cover the 8 ticks from 12 to 19 after it (computed). In the first of a line's three checks,exh_normal_addcounts each press in a 1-run whose key the teacher's line uses (otehon_all; while the rank is Cool, any key, and in one-button play, triangle) andexh_normal_subtakes one off for each such press in a 0-run, each weighted 48/16, that is ±3 (computed); a press anywhere in a run scores the same. The same check's imitation test (exh_mane, weight 8/16) runs over every pair of a teacher's note and a press and counts each pair with the sameth_numand, outside one-button play, the same key, so one press can count once for each note in its run; it scores 2 × that count − presses; it runs again on a late grid (CK_TH_LATE, 0x00f3cf3c, with the teacher's notes moved 2 slots later) and keeps the better result. The third check uses a swing grid (CK_TH_HANE, 0x00c1cc1c). A line's score (now_score) is the sum of the three checks' totals, and in the game play step (PSTEP_GAME) it is then halved as (now_score+ 1) / 2 in one-button play (PLAY_TYPE_ONE) and halved that way again in the easy table mode (PLAY_TABLE_EASY), so twice when both apply; a check's total is 0 when its all-keys test fails and −100 when the presses reach the line's length in 24-tick steps, rounded up, plus 3 (exh_renda_out). In the hook play step (PSTEP_HOOK) a line is scored by an imitation test alone (manemane_check), on the main grid.Codeparappadev/parappa2revisedHow we know
3990 if (scr_main_pp->scr_ctrl_pp[i].gtime_type == GTIME_VSYNC) { 3991 scr_main_pp->scr_ctrl_pp[i].lineTime = ((TimeCallbackTimeGetChan(i) * 96.0f * GetLineTempo(i) + 1800.0f) / 3600.0f);
src/main/scrctrl.c lines 3990–3991 at 45694de · upstream ↗ 2141 SCR_TAP_MEMORY *mkey_pp = &sindv_pp->scr_tap_memory[sindv_pp->scr_tap_memory_cnt]; ⋮ 2145 mkey_pp->ofs_frame = onKeyTime - tapset_pp->taptimeStart - sindv_pp->current_time;
src/main/scrctrl.c lines 2141–2145 at 45694de · upstream ↗ 2765 exam_check[i].tapset_pp = IndvGetTapSetAdrs(sindv_pp); ⋮ 2770 exam_check[i].ofs_tick = exam_check[i].tapset_pp->taptimeStart + sindv_pp->current_time; ⋮ 2776 exam_check[i].otehon_all = otehon_all_make(&exam_check[i]); ⋮ 2785 if (global_data.play_typeL == PLAY_TYPE_ONE) { 2786 exam_check[i].otehon_all = KcTR;
src/main/scrctrl.c lines 2765–2787 at 45694de · upstream ↗ 136static u_int thnum_tbl[] = { 0x00e79e79, 0x00f3cf3c, 0x00c1cc1c, 0x00000000 };src/main/scrctrl.c line 136 at 45694de · upstream ↗ 2222static int thnum_get(int p96_num, CK_TH_ENUM ckth) { ⋮ 2230 thnum_data = thnum_tbl[ckth]; ⋮ 2232 for (i = 0; i <= p96_num; i++) { 2233 ck_dat = (thnum_data >> (23 - (i % 24))) & 1; ⋮ 2235 if (ck_bit < 0) { 2236 if (ck_dat == 0) { 2237 ret_cnt = 1; ⋮ 2239 } else if (ck_dat != ck_bit) { 2240 ret_cnt++;
src/main/scrctrl.c lines 2222–2247 at 45694de · upstream ↗ 2253static void on_th_make(EXAM_CHECK *ec_pp, CK_TH_ENUM ckth) { ⋮ 2267 ofsT = ec_pp->ofs_tick % 96; 2268 ofsT += 96; ⋮ 2273 frame = ec_pp->stm_pp[i].ofs_frame; 2274 p96_num = (frame + ofsT) / 4; ⋮ 2277 ec_pp->ted[i].th_num = thnum_get(p96_num, ckth); ⋮ 2304 p96_num = (frame + ofsT) / 4; ⋮ 2306 if (ckth == CK_TH_LATE) { 2307 p96_num += 2; ⋮ 2311 ec_pp->oth[i].th_num = thnum_get(p96_num, ckth);
src/main/scrctrl.c lines 2253–2312 at 45694de · upstream ↗ 2317static int exh_normal_add(EXAM_CHECK *ec_pp) { ⋮ 2322 if (!(ec_pp->ted[i].th_num & 1)) { 2323 if (GetIndex2KeyCode(ec_pp->ted[i].key) & ec_pp->otehon_all) { 2324 ret++; ⋮ 2332static int exh_normal_sub(EXAM_CHECK *ec_pp) { ⋮ 2337 if (GetIndex2KeyCode(ec_pp->ted[i].key) & ec_pp->otehon_all) { 2338 ret -= ec_pp->ted[i].th_num & 1;
src/main/scrctrl.c lines 2317–2343 at 45694de · upstream ↗ 99static EXH_STR exh_str_normal[] = { 100 { .score_prg = exh_normal_add, .save_p = EXH_NORMAL_ADD, .bairitu = 48 }, 101 { .score_prg = exh_normal_sub, .save_p = EXH_NORMAL_SUB, .bairitu = 48 }, ⋮ 108 { .score_prg = exh_mane, .save_p = EXH_MANE, .bairitu = 8 }, 109 { .score_prg = exh_all_add, .save_p = EXH_TOTAL, .bairitu = 16 },
src/main/scrctrl.c lines 99–110 at 45694de · upstream ↗ 2583static int exh_renda_out(EXAM_CHECK *ec_pp) { ⋮ 2586 renda_ck = ec_pp->tapset_pp->taptimeEnd - ec_pp->tapset_pp->taptimeStart; 2587 renda_ck = ((renda_ck + 23) / 24); 2588 renda_ck += 3; ⋮ 2590 if (ec_pp->ted_num >= renda_ck) { 2591 return -1; ⋮ 2597static int manemane_check_sub(EXAM_CHECK *ec_pp) { ⋮ 2605 if (global_data.play_typeL == PLAY_TYPE_ONE) { 2606 if (ec_pp->oth[i].th_num == ec_pp->ted[j].th_num) { 2607 mane_cnt++; ⋮ 2610 if (ec_pp->oth[i].th_num == ec_pp->ted[j].th_num) { 2611 if (ec_pp->oth[i].key == ec_pp->ted[j].key) { ⋮
src/main/scrctrl.c lines 2583–2684 at 45694de · upstream ↗ 2790 if (global_data.play_step == PSTEP_HOOK) { ⋮ 2796 scrprgstr_pp = scrprgstr_hook; ⋮ 2813 exam_check_pp->each_point[scrprgstr_pp->exh_str_pp[j].save_p] = (ret * scrprgstr_pp->exh_str_pp[j].bairitu) / 16; ⋮ 2816 CK_TH_ENUM ck_th_enum_tbl[3] = { 2817 CK_TH_NORMAL, 2818 CK_TH_NORMAL, 2819 CK_TH_HANE ⋮ 2829 on_th_make(exam_check_pp, ck_th_enum_tbl[i]); ⋮ 2844 exam_check_pp->each_point[scrprgstr_pp->exh_str_pp[j].save_p] = (ret * scrprgstr_pp->exh_str_pp[j].bairitu) / 16; ⋮ 2853 sum += exam_check[i].each_point[EXH_TOTAL]; ⋮ 2856 sindv_pp->global_ply->now_score = sum;
src/main/scrctrl.c lines 2790–2856 at 45694de · upstream ↗ 3077 if (scex_pp->exam_do == EXAM_DO_NON) { 3078 ExamScoreCheck(sindv_pp); ⋮ 3080 if (global_data.play_step == PSTEP_GAME) { 3081 if (global_data.play_typeL == PLAY_TYPE_ONE) { 3082 sindv_pp->global_ply->now_score = (sindv_pp->global_ply->now_score + 1) / 2; ⋮ 3084 if (global_data.play_table_modeL == PLAY_TABLE_EASY) { 3085 sindv_pp->global_ply->now_score = (sindv_pp->global_ply->now_score + 1) / 2;
src/main/scrctrl.c lines 3077–3087 at 45694de · upstream ↗ 131static EXH_STR exh_str_hook[] = { 132 { .score_prg = manemane_check, .save_p = EXH_MANE, .bairitu = 16 }, 133 { .score_prg = exh_all_add, .save_p = EXH_TOTAL, .bairitu = 16 },
src/main/scrctrl.c lines 131–134 at 45694de · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
Sources
Code
- parappadev and parappa2 contributors. 2026. “parappa2: a decompilation of PaRappa the Rapper 2 (parappadev/parappa2).” Commit 45694de. parappadev/parappa2 @ 45694de · licence, all uses