Mechanic · structure & scoring · rhythm
Rank meter
A running grade of the player's performance in a rhythm game, moved by each judged line.
On this page
A rank meter grades the player as a song goes. In PaRappa the Rapper 2 each judged line moves the rank one level against a target set by the teacher’s own line, and an in-between level beside each rank means it takes 2 lines in a row1 to change the rank shown1. At Cool the target’s teacher part becomes a flat coolup + 1502, and the checks for following the teacher stop scoring2.
- Stepped levelsPaRappa the Rapper 2 (2001). Each line steps the rank one level against the teacher's line plus the line's `coolup`, with an in-between level beside Cool, Good, Bad, and Awful; at Cool any key counts and following the teacher isn't checked.1,2
Games
| Game | Year | How | Note |
|---|---|---|---|
| PaRappa the Rapper 2 | 2001 | Stepped levels | each line steps the rank one level against the teacher's line plus the line's `coolup`, with an in-between level beside Cool, Good, Bad, and Awful; at Cool any key counts and following the teacher isn't checked |
Every claim about this mechanic, by game (2)
References
- ^ abcIn the July 12th NTSC-J prototype of PaRappa the Rapper 2, the rank is one of 14 levels (
RANK_LEVEL,RLVL_COOL0 toRLVL_END213), andRANK_LEVEL2DISP_LEVELshows levels 0 and 1 as Cool, 2 to 4 as Good, 5 to 7 as Bad, 8 to 10 as Awful, and 11 to 13 as none (DLVL_MAX). The stage's score data sets each exam's type (SCRRJ_EXAM). At an exam other than hook, VS, cancel, and bonus, the player's line score (now_score) is set against a target (exam_coolP): the line'scoolupfrom the stage data plus what the teacher's own presses score when run through the same checks (ExamScoreCheckSame, which scores a copy and returns its unhalved sum, so in one-button play or the easy table mode a halved line score meets a target whose teacher part isn't halved), a part that is a flat 150 while the rank is at level 0 or 1, and 11111 when there is no line. Under a Cool exam a score below the target steps the rank down (levelDownRank) and any other steps it up (levelUpRank). Under a Good exam a score at or above the target steps up, a score of 0 or less steps down, and a score between them moves level 2 (RLVL_GOOD_COOL) down to Good, leaves Good alone, and steps any other level up. Under a Bad or Awful exam a score above 0 steps up and any other steps down. A step moves to the next level along the tables, which put an in-between level beside each rank: up from Good (3) is level 2, still shown Good, then Cool (0); down from Good is level 4, then Bad (6); down from Awful (9) is level 10 and thenRLVL_END1(12). So a shown rank changes after two steps the same way, and a step back from an in-between level returns to the plain rank (computed from the tables). In one-button play (PLAY_TYPE_ONE) or the easy table mode (PLAY_TABLE_EASY), a Good exam that would leave the rank at level 0, 1, or 2 sets it to Good (3), so the rank can't reach Cool there.Codeparappadev/parappa2revisedHow we know
246 RLVL_COOL = 0, 247 RLVL_COOL_GOOD = 1, 248 RLVL_GOOD_COOL = 2, 249 RLVL_GOOD = 3, 250 RLVL_GOOD_BAD = 4, 251 RLVL_BAD_GOOD = 5, 252 RLVL_BAD = 6, 253 RLVL_BAD_AWFUL = 7, 254 RLVL_AWFUL_BAD = 8, 255 RLVL_AWFUL = 9, 256 RLVL_AWFUL_END = 10, 257 RLVL_END0 = 11, ⋮
include/main/etc.h lines 246–259 at 45694de · upstream ↗ 453DISP_LEVEL RANK_LEVEL2DISP_LEVEL(RANK_LEVEL lvl) { 454 DISP_LEVEL lvl_tbl[17] = { 455 DLVL_COOL, DLVL_COOL, 456 DLVL_GOOD, DLVL_GOOD, DLVL_GOOD, 457 DLVL_BAD, DLVL_BAD, DLVL_BAD, 458 DLVL_AWFUL, DLVL_AWFUL, DLVL_AWFUL, 459 DLVL_MAX, DLVL_MAX, DLVL_MAX, 460 DLVL_MAX, DLVL_MAX, DLVL_MAX,
src/main/scrctrl.c lines 453–464 at 45694de · upstream ↗ 1352 case SCRRJ_EXAM: 1353 sindv_pp->scr_exam_str.exam_enum = Rsub;
src/main/scrctrl.c lines 1352–1353 at 45694de · upstream ↗ 3067 if (scex_pp->exam_enum == EXAM_CANCEL) { ⋮ 3070 if (scex_pp->exam_enum == EXAM_BONUS) { ⋮ 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 3067–3087 at 45694de · upstream ↗ 2873 global_ply_tmp = *sindv_pp->global_ply; ⋮ 2875 sindv_tmp = *sindv_pp; 2876 sindv_tmp.global_ply = &global_ply_tmp; ⋮ 2907 ExamScoreCheck(&sindv_tmp); 2908 return global_ply_tmp.now_score;
src/main/scrctrl.c lines 2873–2908 at 45694de · upstream ↗ 2859static int ExamScoreCheckSame(SCORE_INDV_STR *sindv_pp) { ⋮ 2868 if (sindv_pp->global_ply->rank_level == RLVL_COOL || 2869 sindv_pp->global_ply->rank_level == RLVL_COOL_GOOD) { 2870 return 150;
src/main/scrctrl.c lines 2859–2871 at 45694de · upstream ↗ 3204 scex_pp->exam_point = sindv_pp->global_ply->now_score; ⋮ 3206 if (tapset_pp == NULL) { 3207 scex_pp->exam_coolP = 11111; 3208 } else { 3209 exp = ExamScoreCheckSame(sindv_pp); 3210 if (global_data.play_step != PSTEP_VS) { 3211 scex_pp->exam_coolP = tapset_pp->coolup + exp; 3212 } else { ⋮ 3225 case EXAM_COOL: 3226 if (scex_pp->exam_point < scex_pp->exam_coolP) { 3227 rank_saki = levelDownRank(rank_moto); 3228 } else { ⋮
src/main/scrctrl.c lines 3201–3259 at 45694de · upstream ↗ 2922static int levelUpRank(RANK_LEVEL lvl) { 2923 RANK_LEVEL up_tbl[17] = { 2924 /* COOL -> COOL */ RLVL_COOL, 2925 /* COOL/GOOD -> COOL */ RLVL_COOL, 2926 /* GOOD/COOL -> COOL */ RLVL_COOL, 2927 /* GOOD -> GOOD/COOL */ RLVL_GOOD_COOL, 2928 /* GOOD/BAD -> GOOD */ RLVL_GOOD, 2929 /* BAD/GOOD -> GOOD */ RLVL_GOOD, 2930 /* BAD -> BAD/GOOD */ RLVL_BAD_GOOD, 2931 /* BAD/AWFUL -> BAD */ RLVL_BAD, 2932 /* AWFUL/BAD -> BAD */ RLVL_BAD, 2933 /* AWFUL -> AWFUL/BAD */ RLVL_AWFUL_BAD, ⋮
src/main/scrctrl.c lines 2922–2968 at 45694de · upstream ↗ 3487 if (scex_pp->exam_enum != EXAM_HOOK && scex_pp->exam_enum != EXAM_VS) { 3488 if (rank_saki != rank_moto) { 3489 int line_change; ⋮ 3491 sindv_pp->global_ply->rank_level = rank_saki;
src/main/scrctrl.c lines 3487–3491 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.
- ^ abcIn the July 12th NTSC-J prototype of PaRappa the Rapper 2, while the rank is at level 0 or 1 (
RLVL_COOL,RLVL_COOL_GOOD, both shown as Cool), a line is scored three ways differently. Every key the game maps (KcAll: triangle, circle, cross, square, L1, and R1 byGetIndex2KeyCode) counts as one the teacher's line uses (otehon_all), where otherwise only the keys in the teacher's line count, so on-grid presses of any of them score andexh_nombar_sub, which takes points for keys outside the teacher's, finds none (computed); in one-button play (PLAY_TYPE_ONE) the set is triangle alone either way. Five checks score 0: the all-keys test (EXH_ALLKEY_OUT), the imitation test (EXH_MANE), and three that compare the presses with the teacher's notes (EXH_MBAR_KEY_OUTandEXH_MBAR_TIME_OUT, the first press's key and slot run against the first note's, andEXH_MBAR_NUM_OUT, the count of presses against the count of notes). And the teacher's part of the target is a flat 150 (ExamScoreCheckSame), not the teacher's notes scored. The atlas reads this as Cool's freestyle: following the teacher is no longer checked, and off-grid presses and mashing (exh_renda_out) still cost. Under a Good exam the rank gets to Cool after two lines in a row that each score at least the target, the line'scoolupplus the teacher's notes scored (computed: Good to level 2, then 0), except in one-button play or the easy table mode, which hold it at Good; under a Cool exam a line belowcoolup+ 150 steps it down, and two in a row put it back at Good (computed).Codeparappadev/parappa2How we know
2773 if (sindv_pp->global_ply->rank_level == RLVL_COOL || sindv_pp->global_ply->rank_level == RLVL_COOL_GOOD) { 2774 exam_check[i].otehon_all = KcAll; 2775 } else { 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 2773–2787 at 45694de · upstream ↗ 81typedef enum { 82 KcTR = 16, 83 KcCI = 32, 84 KcXX = 64, 85 KcSQ = 128, 86 KcL1 = 4, 87 KcR1 = 8, 88 KcAll = 252,
include/main/scrctrl.h lines 81–88 at 45694de · upstream ↗ 500int GetIndex2KeyCode(int index) { 501 static int KeyCode[7] = { 502 0, KcTR, KcCI, KcXX, KcSQ, KcL1, KcR1,
src/main/etc.c lines 500–503 at 45694de · upstream ↗ 2345static int exh_nombar_sub(EXAM_CHECK *ec_pp) { ⋮ 2353 int keycode = GetIndex2KeyCode(ec_pp->ted[i].key); 2354 if ((keycode & ec_pp->otehon_all) == 0) { 2355 ret -= 1;
src/main/scrctrl.c lines 2345–2357 at 45694de · upstream ↗ 2383static int exh_mbar_key_out(EXAM_CHECK *ec_pp) { ⋮ 2394 } else if (ec_pp->oth[0].key == ec_pp->ted[0].key) { ⋮ 2402static int exh_mbar_time_out(EXAM_CHECK *ec_pp) { ⋮ 2409 } else if (ec_pp->oth[0].th_num == ec_pp->ted[0].th_num) { ⋮ 2417static int exh_mbar_num_out(EXAM_CHECK *ec_pp) { 2418 int ret = ec_pp->ted_num - ec_pp->oth_num;
src/main/scrctrl.c lines 2383–2420 at 45694de · upstream ↗ 2832 ret = scrprgstr_pp->exh_str_pp[j].score_prg(exam_check_pp); ⋮ 2834 if (sindv_pp->global_ply->rank_level == RLVL_COOL || sindv_pp->global_ply->rank_level == RLVL_COOL_GOOD) { 2835 if (scrprgstr_pp->exh_str_pp[j].save_p == EXH_ALLKEY_OUT || 2836 scrprgstr_pp->exh_str_pp[j].save_p == EXH_MBAR_NUM_OUT || 2837 scrprgstr_pp->exh_str_pp[j].save_p == EXH_MBAR_KEY_OUT || 2838 scrprgstr_pp->exh_str_pp[j].save_p == EXH_MANE || 2839 scrprgstr_pp->exh_str_pp[j].save_p == EXH_MBAR_TIME_OUT) { 2840 ret = 0;
src/main/scrctrl.c lines 2831–2844 at 45694de · upstream ↗ 2868 if (sindv_pp->global_ply->rank_level == RLVL_COOL || 2869 sindv_pp->global_ply->rank_level == RLVL_COOL_GOOD) { 2870 return 150;
src/main/scrctrl.c lines 2868–2871 at 45694de · upstream ↗ 3209 exp = ExamScoreCheckSame(sindv_pp); 3210 if (global_data.play_step != PSTEP_VS) { 3211 scex_pp->exam_coolP = tapset_pp->coolup + exp; ⋮ 3225 case EXAM_COOL: 3226 if (scex_pp->exam_point < scex_pp->exam_coolP) { 3227 rank_saki = levelDownRank(rank_moto); ⋮ 3229 rank_saki = levelUpRank(rank_moto); ⋮ 3232 case EXAM_GOOD: 3233 if (scex_pp->exam_point >= scex_pp->exam_coolP) { 3234 rank_saki = levelUpRank(rank_moto); ⋮ 3236 rank_saki = levelDownRank(rank_moto); ⋮ 3239 rank_saki = levelDownRank(rank_moto); ⋮
src/main/scrctrl.c lines 3209–3247 at 45694de · upstream ↗ 2923 RANK_LEVEL up_tbl[17] = { 2924 /* COOL -> COOL */ RLVL_COOL, 2925 /* COOL/GOOD -> COOL */ RLVL_COOL, 2926 /* GOOD/COOL -> COOL */ RLVL_COOL, 2927 /* GOOD -> GOOD/COOL */ RLVL_GOOD_COOL, ⋮ 2947 RANK_LEVEL down_tbl[17] = { 2948 /* COOL -> COOL/GOOD */ RLVL_COOL_GOOD, 2949 /* COOL/GOOD -> GOOD */ RLVL_GOOD,
src/main/scrctrl.c lines 2922–2951 at 45694de · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked 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