Skip to content

Commit b3ca1a0

Browse files
committed
support heroic verse and bistrover
1 parent 2c6da66 commit b3ca1a0

File tree

12 files changed

+4534
-113
lines changed

12 files changed

+4534
-113
lines changed

bemani/backend/iidx/base.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ class IIDXBase(CoreHandler, CardManagerHandler, PASELIHandler, Base):
4141
CHART_TYPE_A14: Final[int] = 5
4242
# Beginner charts only save status
4343
CHART_TYPE_B7: Final[int] = 6
44+
# Some new chart ids added because of HV. No B14 charts
45+
# yet but the should be ready "just in case"
46+
CHART_TYPE_L7: Final[int] = 7
47+
CHART_TYPE_B14: Final[int] = 8
48+
CHART_TYPE_L14: Final[int] = 9
4449

4550
DAN_RANK_7_KYU: Final[int] = DBConstants.IIDX_DAN_RANK_7_KYU
4651
DAN_RANK_6_KYU: Final[int] = DBConstants.IIDX_DAN_RANK_6_KYU

bemani/backend/iidx/bistrover.py

Lines changed: 2035 additions & 3 deletions
Large diffs are not rendered by default.

bemani/backend/iidx/heroicverse.py

Lines changed: 2015 additions & 3 deletions
Large diffs are not rendered by default.

bemani/format/iidxchart.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ class IIDXChart:
1212
clear ranks for IIDX.
1313
"""
1414

15-
CHART_POSITIONS: Final[List[int]] = [1, 0, 2, 7, 6, 8]
15+
CHART_POSITIONS: Final[List[int]] = [1, 0, 2, 7, 6, 8, 3, 4, 9, 10]
1616

1717
def __init__(self, data: bytes) -> None:
1818
self.__bpm_min: Optional[int] = None
1919
self.__bpm_max: Optional[int] = None
20-
self.__note_counts = [0, 0, 0, 0, 0, 0]
20+
self.__note_counts = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2121
self.__parse_charts(data)
2222

2323
def __parse_header(self, data: bytes) -> List[Tuple[int, int]]:
@@ -30,7 +30,7 @@ def __parse_header(self, data: bytes) -> List[Tuple[int, int]]:
3030
def __parse_charts(self, data: bytes) -> None:
3131
header = self.__parse_header(data)
3232

33-
for chart in [0, 1, 2, 3, 4, 5]:
33+
for chart in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
3434
offset, length = header[self.CHART_POSITIONS[chart]]
3535
chartdata = data[offset:(offset + length)]
3636
position = 0

bemani/format/iidxmusicdb.py

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ def __parse_db(self, data: bytes) -> None:
8686
elif data[4] == 0x1A:
8787
offset = 0xD300
8888
leap = 0x344
89+
elif data[4] == 0x1B:
90+
offset = 0xDAD0
91+
leap = 0x52C
92+
elif data[4] == 0x1C:
93+
offset = 0xE2A0
94+
leap = 0x52C
8995

9096
if sig[0] != b'IIDX':
9197
raise Exception(f'Invalid signature \'{sig[0]}\' found!')
@@ -101,29 +107,51 @@ def parse_string(string: bytes) -> str:
101107
# Load songs
102108
while True:
103109
try:
104-
songdata = struct.unpack_from(
105-
"<64s64s64s64s24xB7xBBBBBB162xH",
106-
data,
107-
offset,
108-
)
110+
if data[4] < 0x1B:
111+
songdata = struct.unpack_from(
112+
"<64s64s64s64s24xB7x6B162xH",
113+
data,
114+
offset,
115+
)
116+
else:
117+
# Heroic Verse and above have a completely different structure for song entries
118+
songdata = struct.unpack_from(
119+
"<64s64s64s64s24xB7x10B646xH",
120+
data,
121+
offset,
122+
)
109123
except struct.error:
110124
# Out of input!
111125
break
112126

113127
songoffset = offset
114128
offset = offset + leap
115-
song = IIDXSong(
116-
songdata[11],
117-
parse_string(songdata[0]),
118-
parse_string(songdata[1]),
119-
parse_string(songdata[2]),
120-
parse_string(songdata[3]),
121-
[songdata[5], songdata[6], songdata[7], songdata[8], songdata[9], songdata[10]],
122-
songdata[4],
123-
)
129+
if data[4] < 0x1B:
130+
song = IIDXSong(
131+
songdata[11],
132+
parse_string(songdata[0]),
133+
parse_string(songdata[1]),
134+
parse_string(songdata[2]),
135+
parse_string(songdata[3]),
136+
[songdata[5], songdata[6], songdata[7], songdata[8], songdata[9], songdata[10]],
137+
songdata[4],
138+
)
139+
else:
140+
song = IIDXSong(
141+
songdata[15],
142+
parse_string(songdata[0]),
143+
parse_string(songdata[1]),
144+
parse_string(songdata[2]),
145+
parse_string(songdata[3]),
146+
[songdata[6], songdata[7], songdata[8], songdata[11], songdata[12], songdata[13], songdata[5], songdata[9], songdata[10], songdata[14]],
147+
songdata[4],
148+
)
124149
if song.artist == 'event_data' and song.genre == 'event_data':
125150
continue
126-
self.__songs[songdata[11]] = (song, songoffset)
151+
if data[4] < 0x1B:
152+
self.__songs[songdata[11]] = (song, songoffset)
153+
else:
154+
self.__songs[songdata[15]] = (song, songoffset)
127155

128156
@property
129157
def songs(self) -> List[IIDXSong]:

bemani/frontend/iidx/endpoints.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,12 @@ def viewtopscores(musicid: int) -> Response:
183183
name = None
184184
artist = None
185185
genre = None
186-
difficulties = [0, 0, 0, 0, 0, 0]
187-
notecounts = [0, 0, 0, 0, 0, 0]
186+
difficulties = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
187+
notecounts = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
188188

189189
for version in versions:
190190
for omniadd in [0, 10000]:
191-
for chart in [0, 1, 2, 3, 4, 5]:
191+
for chart in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
192192
details = g.data.local.music.get_song(GameConstants.IIDX, version + omniadd, musicid, chart)
193193
if details is not None:
194194
name = details.name

bemani/frontend/iidx/iidx.py

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ class IIDXFrontend(FrontendBase):
2020
IIDXBase.CHART_TYPE_N14,
2121
IIDXBase.CHART_TYPE_H14,
2222
IIDXBase.CHART_TYPE_A14,
23+
IIDXBase.CHART_TYPE_B7,
24+
IIDXBase.CHART_TYPE_L7,
25+
IIDXBase.CHART_TYPE_B14,
26+
IIDXBase.CHART_TYPE_L14,
2327
]
2428

2529
valid_rival_types: List[str] = [
@@ -72,6 +76,111 @@ def get_duplicate_id(self, musicid: int, chart: int) -> Optional[Tuple[int, int]
7276
16102: 21258,
7377
16101: 21262,
7478
14100: 21220,
79+
28100: 27115,
80+
# Tons of leggendarias here...
81+
1017: 1100,
82+
4005: 4100,
83+
4001: 4101,
84+
5014: 5100,
85+
11032: 11100,
86+
11012: 11101,
87+
12002: 12100,
88+
12016: 12101,
89+
13010: 13100,
90+
13038: 13101,
91+
14009: 14100,
92+
14046: 14101,
93+
14022: 14102,
94+
15023: 15101,
95+
15007: 15102,
96+
15061: 15103,
97+
15004: 15104,
98+
15045: 15105,
99+
16050: 16101,
100+
16045: 16102,
101+
16031: 16103,
102+
16015: 16104,
103+
16002: 16105,
104+
17060: 17101,
105+
17028: 17102,
106+
18025: 18100,
107+
18011: 18103,
108+
19063: 19100,
109+
20100: 20103,
110+
20039: 20104,
111+
20068: 20105,
112+
20024: 20106,
113+
20019: 20107,
114+
21012: 21100,
115+
21059: 21101,
116+
21069: 21102,
117+
21073: 21103,
118+
21052: 21104,
119+
21048: 21105,
120+
21050: 21106,
121+
21029: 21107,
122+
21089: 21108,
123+
1005: 21204,
124+
4020: 21205,
125+
5007: 21206,
126+
6013: 21207,
127+
7038: 21208,
128+
8023: 21209,
129+
8024: 21210,
130+
9001: 21211,
131+
9051: 21212,
132+
9033: 21213,
133+
11028: 21215,
134+
12010: 21216,
135+
12052: 21217,
136+
12053: 21218,
137+
12054: 21219,
138+
23054: 23100,
139+
14053: 21222,
140+
15000: 21223,
141+
15001: 21224,
142+
23031: 23101,
143+
15014: 21227,
144+
24041: 24100,
145+
15015: 21228,
146+
15016: 21229,
147+
15020: 21230,
148+
23070: 23102,
149+
15025: 21232,
150+
15026: 21233,
151+
15032: 21234,
152+
15041: 21235,
153+
15054: 21236,
154+
24011: 24101,
155+
16000: 21238,
156+
16001: 21239,
157+
16011: 21241,
158+
16016: 21243,
159+
16017: 21244,
160+
16018: 21245,
161+
16020: 21246,
162+
16021: 21247,
163+
16022: 21248,
164+
16024: 21249,
165+
16025: 21250,
166+
16028: 21251,
167+
16030: 21252,
168+
14012: 21264,
169+
16034: 21254,
170+
16038: 21255,
171+
16040: 21256,
172+
16042: 21257,
173+
16047: 21259,
174+
16049: 21260,
175+
15005: 21261,
176+
15008: 21263,
177+
22008: 22101,
178+
22013: 22102,
179+
22024: 22103,
180+
22027: 22104,
181+
22031: 22105,
182+
22089: 22106,
183+
22006: 22107,
75184
}
76185
# Some charts were changed, and others kept the same on these
77186
if chart in [0, 1, 2]:
@@ -263,8 +372,8 @@ def format_attempt(self, userid: UserID, attempt: Attempt) -> Dict[str, Any]:
263372
return formatted_attempt
264373

265374
def format_song(self, song: Song) -> Dict[str, Any]:
266-
difficulties = [0, 0, 0, 0, 0, 0]
267-
notecounts = [0, 0, 0, 0, 0, 0]
375+
difficulties = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
376+
notecounts = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
268377
difficulties[song.chart] = song.data.get_int('difficulty', 13)
269378
notecounts[song.chart] = song.data.get_int('notecount', 5730)
270379

0 commit comments

Comments
 (0)