From b86d30a960b04652317416b7e3f14189ba569e74 Mon Sep 17 00:00:00 2001 From: tyam Date: Thu, 18 Sep 2025 13:01:48 -0500 Subject: [PATCH 1/7] Update unilab.py Adjust max deco id to final value and actually handle the decopa fake "force unlock" that somehow got lost in the shuffle of the older commits --- bemani/backend/popn/unilab.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/bemani/backend/popn/unilab.py b/bemani/backend/popn/unilab.py index 0874dba..9aea100 100644 --- a/bemani/backend/popn/unilab.py +++ b/bemani/backend/popn/unilab.py @@ -20,7 +20,7 @@ class PopnMusicUnilab(PopnMusicModernBase): GAME_MAX_MUSIC_ID: int = 2188 # Biggest deco part ID in the game - GAME_MAX_DECO_ID: int = 81 + GAME_MAX_DECO_ID: int = 109 def previous_version(self) -> PopnMusicBase: return PopnMusicKaimei(self.data, self.config, self.model) @@ -570,6 +570,17 @@ class PopnMusicUnilab(PopnMusicModernBase): battery.add_child(Node.u32("energy", energy)) battery.add_child(Node.bool("is_cleared", is_cleared)) + # Fake unlock all deco items if enabled + if game_config.get_bool("force_unlock_deco"): + for deco_id in range(1, self.GAME_MAX_DECO_ID + 1): + item = Node.void("item") + item.add_child(Node.u8("type", 7)) + item.add_child(Node.u16("id", deco_id)) + item.add_child(Node.u16("param", 0)) + item.add_child(Node.bool("is_new", False)) + item.add_child(Node.u64("get_time", 0)) + root.add_child(item) + return root def unformat_profile(self, userid: UserID, request: Node, oldprofile: Profile) -> Profile: From 9f6a855266093c00a427978031c60560ec6933c7 Mon Sep 17 00:00:00 2001 From: tyam Date: Sat, 27 Sep 2025 21:57:34 -0500 Subject: [PATCH 2/7] Event ID documentation Properly handle the permanent unlocks for event id 1, relocate lively quest to the right value, document attract mode ad flags. This leaves one event unaccounted for. I'll circle back around to this later to see if I can figure out the final event id at some point in the future. --- bemani/backend/popn/unilab.py | 81 ++++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/bemani/backend/popn/unilab.py b/bemani/backend/popn/unilab.py index 9aea100..5b7be10 100644 --- a/bemani/backend/popn/unilab.py +++ b/bemani/backend/popn/unilab.py @@ -50,9 +50,9 @@ class PopnMusicUnilab(PopnMusicModernBase): }, }, { - # Shutchou! pop'n quest Lively II event - "name": "Shutchou! pop'n quest Lively II phase", - "tip": "Shutchou! pop'n quest Lively II phase for all players.", + # Shutchou! pop'n quest Lively II ~nostalgia~ event + "name": "Shutchou! pop'n quest Lively II 〜nostalgia〜 phase", + "tip": "Shutchou! pop'n quest Lively II 〜nostalgia〜 phase for all players.", "category": "game_config", "setting": "popn_quest_lively_2", "values": { @@ -291,23 +291,24 @@ class PopnMusicUnilab(PopnMusicModernBase): # 5 - 2172 - レイドバックジャーニー # 6 - 2188 - Super Heroine 0: music_phase, - # Shutchou! pop'n quest Lively II (0-6) - # When active, the following songs are available for unlock - # 1 - 1989 - Ketter - # 1990 - Petit Queen - # 1991 - 波と凪の挟間で - # 2 - 1984 - コルドバの女 - # 1985 - say...but in vain - # 1992 - Northern Cross - # 3 - 1982 - Surf on the Light - # 1983 - バッドエンド・シンドローム - # 1988 - Danza Pantera - # 4 - 1986 - virkatoの主題によるperson09風超絶技巧変奏曲 - # 1987 - 水晶塔のオルカ - # 1993 - Un Happy Heart - # 5 - 2017 - virkatoの主題によるperson09風超絶技巧変奏曲 upper - # 6 - Event Ended - 1: popn_quest_lively_2, + # Permanent song unlocks (0-6) + # This setting PERMANENTLY unlocks 86 songs by granting them in the database. + # Reverting this to a lower number will not remove these songs from the profile. + # 1 - Unlock 45 songs from 解明!MN探偵社: + # 195, 267, 323, 521, 575, 1894, 1896, 1908, 1914, 1915, 1916, 1924, 1925, 1926, 1927, 1928, + # 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, + # 1946, 1947, 1955, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1965, 1968, 1969, 1970 + # 2 - Unlock all 6 songs from BEMANI 2021真夏の歌合戦5番勝負: + # 1948, 1949, 1950, 1951, 1952, 1953 + # 3 - Unlock all 11 songs from 冬のポップン!スペシャルコンボ! + # 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1971, 1972, 1973, 1974 + # 4 - Unlock 12 songs from 解明!MN探偵社: + # 1976, 1977, 1978, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + # 5 - Unlock the final 10 songs from 解明!MN探偵社: + # 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016, 2018 + # 6 - Unlock 2 songs from BPL応援 楽曲解禁スタンプラリー: + # 1954, 1956 + 1: 6, # KAC 2023 (0-4) - Please see the site below for what songs are in set A and set B # https://bemaniwiki.com/?%B8%F8%BC%B0%C2%E7%B2%F1/KONAMI+Arcade+Championship%282023%29/%CD%BD%C1%AA%A5%E9%A5%A6%A5%F3%A5%C9#popn # 0 - Disabled @@ -321,7 +322,16 @@ class PopnMusicUnilab(PopnMusicModernBase): # 1 - Net taisen # 2 - Net taisen + Local mode 3: 1 if enable_net_taisen else 0, - # Unknown event (0-7) + # Paseli Festival Attract mode ads (0-7) + # As updates to datecodes happen the older ones are are completely locked out + # 0 - Paseli Festival 2022 - 5000 yen gift for 400 winners! - 2022-09-11 through 2022-09-25 + # 1 - Disabled + # 2 - Paseli Festival 2022-2023 - 10,000 yen gift for 1,210 winners! - 2022-12-15 through 2023-01-15 + # 3 - Appears identical to 2 + # 4 - Paseli Festival 2023 - 10,000 yen gift for 5,000 winners! - 2023-06-01 through 2023-06-30 + # 5 - Disabled + # 6 - Paseli Festival 2023 - 10,000 yen gift for 5,000 winners! - 2023-11-22 through 2023-12-24 + # 7 - Disabled 4: 7, # Narunaru♪ UniLab jikkenshitsu! (0-48) # 6500 clear points are needed unless otherwise specified @@ -391,9 +401,27 @@ class PopnMusicUnilab(PopnMusicModernBase): # Super Unilab BOOST! (0-2) # Boost should be 120, 150, or 200, bemaniwiki has the explanation and it's based on the unlocks left to do 6: super_unilab_boost, - # Unknown event (0-6) - 7: 6, - # Unknown event (0-2) + # Shutchou! pop'n quest Lively II ~nostalgia~ (0-6) + # When active, the following songs are available for unlock + # 1 - 1990 - Petit Queen + # 1991 - 波と凪の挟間で + # 1989 - Ketter + # 2 - 1984 - コルドバの女 + # 1985 - say...but in vain + # 1992 - Northern Cross + # 3 - 1982 - Surf on the Light + # 1988 - Danza Pantera + # 1983 - バッドエンド・シンドローム + # 4 - 1993 - Un Happy Heart + # 1987 - 水晶塔のオルカ + # 1986 - virkatoの主題によるperson09風超絶技巧変奏曲 + # 5 - 2017 - virkatoの主題によるperson09風超絶技巧変奏曲 upper + # 6 - Event Ended + 7: popn_quest_lively_2, + # Attract mode ad campaign (0-2) + # 0 - Off + # 1 - pop'n PIICA / clear file campaign + # 2 - Ended 8: 2, # Kakusei no Elem - Awakening Elem (0-44) # Songs are unlocked as a percentage of 280 points unless otherwise specified @@ -458,7 +486,10 @@ class PopnMusicUnilab(PopnMusicModernBase): 10: 1 if (kakusei_phase > 0) else 0, # CanCan's Super Awakening Boost (0-2) 11: cancan_boost, - # Unknown event (0-2) + # BEMANI Pro League 3 ad in attract mode (0-2) + # 0 - Off + # 1 - Streaming on Youtube every Wednesday + # 2 - Ended 12: 2, # Unknown event (0-2) 13: 2, From ca2e6d0d5c0676ac8a678c8824d243dfcc5e4ed1 Mon Sep 17 00:00:00 2001 From: tyam Date: Tue, 14 Oct 2025 09:54:37 -0500 Subject: [PATCH 3/7] Update bootstrap Add popn 27 to bootstrap list --- bootstrap | 1 + 1 file changed, 1 insertion(+) diff --git a/bootstrap b/bootstrap index e731f61..1328e0a 100755 --- a/bootstrap +++ b/bootstrap @@ -14,6 +14,7 @@ set -e ./read --series pnm --version 24 "$@" ./read --series pnm --version 25 "$@" ./read --series pnm --version 26 "$@" +./read --series pnm --version 27 "$@" # Init Jubeat ./read --series jubeat --version saucer "$@" From b087fe9239c182c2b8107d7989db36499937186b Mon Sep 17 00:00:00 2001 From: tyam Date: Tue, 14 Oct 2025 09:58:36 -0500 Subject: [PATCH 4/7] Update README.md Add peace, kaimei riddles, and unilab to api readme --- bemani/api/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bemani/api/README.md b/bemani/api/README.md index f1c5619..e61a3be 100644 --- a/bemani/api/README.md +++ b/bemani/api/README.md @@ -185,6 +185,9 @@ Valid game series and their versions are as follows. Clients and servers should * ``22`` - Pop'n Music Lapistoria * ``23`` - Pop'n Music Eclale * ``24`` - Pop'n Music うさぎと猫と少年の夢 + * ``25`` - Pop'n Music peace + * ``26`` - Pop'n Music 解明リドルズ + * ``27`` - Pop'n Music Unilab * ``reflecbeat`` * ``1`` - REFLEC BEAT * ``2`` - REFLEC BEAT limelight From 24265ea66d9589a730b0790f8ead751da2d551d7 Mon Sep 17 00:00:00 2001 From: tyam Date: Tue, 14 Oct 2025 10:21:56 -0500 Subject: [PATCH 5/7] Update endpoints.py Aligned comments for unicode values with the correct lines --- bemani/frontend/popn/endpoints.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bemani/frontend/popn/endpoints.py b/bemani/frontend/popn/endpoints.py index ad5d82f..4219b78 100644 --- a/bemani/frontend/popn/endpoints.py +++ b/bemani/frontend/popn/endpoints.py @@ -335,13 +335,13 @@ def updatename() -> Dict[str, Any]: if ( re.match( "^[" - + "\uff20-\uff3a" - + "\uff41-\uff5a" # widetext A-Z and @ - + "\uff10-\uff19" # widetext a-z - + "\uff0c\uff0e\uff3f" # widetext 0-9 - + "\u3041-\u308d\u308f\u3092\u3093" # widetext ,._ - + "\u30a1-\u30ed\u30ef\u30f2\u30f3\u30fc" # hiragana - + "]*$", # katakana + + "\uff20-\uff3a" # widetext A-Z and @ + + "\uff41-\uff5a" # widetext a-z + + "\uff10-\uff19" # widetext 0-9 + + "\uff0c\uff0e\uff3f" # widetext ,._ + + "\u3041-\u308d\u308f\u3092\u3093" # hiragana + + "\u30a1-\u30ed\u30ef\u30f2\u30f3\u30fc" # katakana + + "]*$", name, ) is None From 59191e5789644aa2389a1e52c42ea409242ce157 Mon Sep 17 00:00:00 2001 From: tyam Date: Mon, 1 Dec 2025 09:12:37 -0600 Subject: [PATCH 6/7] Update unilab.py Add some missing client test stuff --- bemani/client/popn/unilab.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/bemani/client/popn/unilab.py b/bemani/client/popn/unilab.py index cbc0286..bddcfc2 100644 --- a/bemani/client/popn/unilab.py +++ b/bemani/client/popn/unilab.py @@ -135,6 +135,20 @@ class PopnMusicUnilabClient(BaseClient): self.assert_path(resp, "response/player24/customize") self.assert_path(resp, "response/player24/stamp/stamp_id") self.assert_path(resp, "response/player24/stamp/cnt") + # Kaimei Riddles + self.assert_path(resp, "response/player24/event2021/point") + self.assert_path(resp, "response/player24/event2021/step") + self.assert_path(resp, "response/player24/event2021/quest_point") + self.assert_path(resp, "response/player24/event2021/step_nos") + self.assert_path(resp, "response/player24/event2021/quest_point_nos") + self.assert_path(resp, "response/player24/account/sp_riddles_id") + self.assert_path(resp, "response/player24/riddles_data/sh_riddles/sh_riddles_id") + # Unilab + self.assert_path(resp, "response/player24/event_p27/team_id") + self.assert_path(resp, "response/player24/event_p27/first_play") + self.assert_path(resp, "response/player24/event_p27/select_battery_id") + self.assert_path(resp, "response/player24/event_p27/elem_first_play") + self.assert_path(resp, "response/player24/event_p27/today_first_play") def verify_player24_read(self, ref_id: str, msg_type: str) -> Dict[str, Dict[int, Dict[str, int]]]: call = self.call_node() From 49472a6956f7db2a5ae6c4577ea43adcb392a01b Mon Sep 17 00:00:00 2001 From: tyam Date: Tue, 14 Apr 2026 16:14:19 -0500 Subject: [PATCH 7/7] Update read.py Last datecode missing for unilab (not counting 2024091700 which is identical to 2024073100). This should be the last unicode change. --- bemani/utils/read.py | 72 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/bemani/utils/read.py b/bemani/utils/read.py index cd56df2..b737d85 100644 --- a/bemani/utils/read.py +++ b/bemani/utils/read.py @@ -2718,6 +2718,78 @@ class ImportPopn(ImportBase): available_charts=available_charts, ) ) + # Based on M39:J:A:A:2023112800 + configurations.append( + PopnScrapeConfiguration( + version="M39:J:A:A:2023112800", + # Normal offset for music DB, size + offset=0x2C14C8, + step=172, + length=2139, + # Offset and step of file DB + file_offset=0x2Af6C0, + file_step=32, + # Standard lookups + genre_offset=0, + title_offset=1, + artist_offset=2, + comment_offset=3, + english_title_offset=4, + english_artist_offset=5, + extended_genre_offset=None, + charts_offset=8, + folder_offset=9, + # Offsets for normal chart difficulties + easy_offset=12, + normal_offset=13, + hyper_offset=14, + ex_offset=15, + # Offsets for battle chart difficulties + battle_normal_offset=16, + battle_hyper_offset=17, + # Offsets into which offset to seek to for file lookups + easy_file_offset=18, + normal_file_offset=19, + hyper_file_offset=20, + ex_file_offset=21, + battle_normal_file_offset=22, + battle_hyper_file_offset=23, + packedfmt=( + "<" + "I" # Genre + "I" # Title + "I" # Artist + "I" # Comment + "I" # English Title + "I" # English Artist + "H" # ?? + "H" # ?? + "I" # Available charts mask + "I" # Folder + "I" # Event unlocks? + "I" # Event unlocks? + "B" # Easy difficulty + "B" # Normal difficulty + "B" # Hyper difficulty + "B" # EX difficulty + "B" # Battle normal difficulty + "B" # Battle hyper difficulty + "xx" # Unknown pointer + "H" # Easy chart pointer + "H" # Normal chart pointer + "H" # Hyper chart pointer + "H" # EX chart pointer + "H" # Battle normal pointer + "H" # Battle hyper pointer + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + ), + # Offsets into file DB for finding file and folder. + file_folder_offset=0, + file_name_offset=1, + filefmt="<" "I" "I" "I" "I" "I" "I" "I" "I", # Folder # Filename + available_charts=available_charts, + ) + ) # Based on M39:J:A:A:2023121800 configurations.append( PopnScrapeConfiguration(